index.js 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. export default {
  2. getSearchInput (that) {
  3. if (typeof that.options.searchSelector === 'string') {
  4. return $(that.options.searchSelector)
  5. }
  6. return that.$toolbar.find('.search input')
  7. },
  8. // it only does '%s', and return '' when arguments are undefined
  9. sprintf (_str, ...args) {
  10. let flag = true
  11. let i = 0
  12. const str = _str.replace(/%s/g, () => {
  13. const arg = args[i++]
  14. if (typeof arg === 'undefined') {
  15. flag = false
  16. return ''
  17. }
  18. return arg
  19. })
  20. return flag ? str : ''
  21. },
  22. isObject (val) {
  23. return val instanceof Object && !Array.isArray(val)
  24. },
  25. isEmptyObject (obj = {}) {
  26. return Object.entries(obj).length === 0 && obj.constructor === Object
  27. },
  28. isNumeric (n) {
  29. return !isNaN(parseFloat(n)) && isFinite(n)
  30. },
  31. getFieldTitle (list, value) {
  32. for (const item of list) {
  33. if (item.field === value) {
  34. return item.title
  35. }
  36. }
  37. return ''
  38. },
  39. setFieldIndex (columns) {
  40. let totalCol = 0
  41. const flag = []
  42. for (const column of columns[0]) {
  43. totalCol += column.colspan || 1
  44. }
  45. for (let i = 0; i < columns.length; i++) {
  46. flag[i] = []
  47. for (let j = 0; j < totalCol; j++) {
  48. flag[i][j] = false
  49. }
  50. }
  51. for (let i = 0; i < columns.length; i++) {
  52. for (const r of columns[i]) {
  53. const rowspan = r.rowspan || 1
  54. const colspan = r.colspan || 1
  55. const index = flag[i].indexOf(false)
  56. r.colspanIndex = index
  57. if (colspan === 1) {
  58. r.fieldIndex = index
  59. // when field is undefined, use index instead
  60. if (typeof r.field === 'undefined') {
  61. r.field = index
  62. }
  63. } else {
  64. r.colspanGroup = r.colspan
  65. }
  66. for (let j = 0; j < rowspan; j++) {
  67. for (let k = 0; k < colspan; k++) {
  68. flag[i + j][index + k] = true
  69. }
  70. }
  71. }
  72. }
  73. },
  74. normalizeAccent (value) {
  75. if (typeof value !== 'string') {
  76. return value
  77. }
  78. return value.normalize('NFD').replace(/[\u0300-\u036f]/g, '')
  79. },
  80. updateFieldGroup (columns) {
  81. const allColumns = [].concat(...columns)
  82. for (const c of columns) {
  83. for (const r of c) {
  84. if (r.colspanGroup > 1) {
  85. let colspan = 0
  86. for (let i = r.colspanIndex; i < r.colspanIndex + r.colspanGroup; i++) {
  87. const column = allColumns.find(col => col.fieldIndex === i)
  88. if (column.visible) {
  89. colspan++
  90. }
  91. }
  92. r.colspan = colspan
  93. r.visible = colspan > 0
  94. }
  95. }
  96. }
  97. },
  98. getScrollBarWidth () {
  99. if (this.cachedWidth === undefined) {
  100. const $inner = $('<div/>').addClass('fixed-table-scroll-inner')
  101. const $outer = $('<div/>').addClass('fixed-table-scroll-outer')
  102. $outer.append($inner)
  103. $('body').append($outer)
  104. const w1 = $inner[0].offsetWidth
  105. $outer.css('overflow', 'scroll')
  106. let w2 = $inner[0].offsetWidth
  107. if (w1 === w2) {
  108. w2 = $outer[0].clientWidth
  109. }
  110. $outer.remove()
  111. this.cachedWidth = w1 - w2
  112. }
  113. return this.cachedWidth
  114. },
  115. calculateObjectValue (self, name, args, defaultValue) {
  116. let func = name
  117. if (typeof name === 'string') {
  118. // support obj.func1.func2
  119. const names = name.split('.')
  120. if (names.length > 1) {
  121. func = window
  122. for (const f of names) {
  123. func = func[f]
  124. }
  125. } else {
  126. func = window[name]
  127. }
  128. }
  129. if (func !== null && typeof func === 'object') {
  130. return func
  131. }
  132. if (typeof func === 'function') {
  133. return func.apply(self, args || [])
  134. }
  135. if (
  136. !func &&
  137. typeof name === 'string' &&
  138. this.sprintf(name, ...args)
  139. ) {
  140. return this.sprintf(name, ...args)
  141. }
  142. return defaultValue
  143. },
  144. compareObjects (objectA, objectB, compareLength) {
  145. const aKeys = Object.keys(objectA)
  146. const bKeys = Object.keys(objectB)
  147. if (compareLength && aKeys.length !== bKeys.length) {
  148. return false
  149. }
  150. for (const key of aKeys) {
  151. if (bKeys.includes(key) && objectA[key] !== objectB[key]) {
  152. return false
  153. }
  154. }
  155. return true
  156. },
  157. escapeHTML (text) {
  158. if (typeof text === 'string') {
  159. return text
  160. .replace(/&/g, '&amp;')
  161. .replace(/</g, '&lt;')
  162. .replace(/>/g, '&gt;')
  163. .replace(/"/g, '&quot;')
  164. .replace(/'/g, '&#039;')
  165. .replace(/`/g, '&#x60;')
  166. }
  167. return text
  168. },
  169. unescapeHTML (text) {
  170. if (typeof text === 'string') {
  171. return text
  172. .replace(/&amp;/g, '&')
  173. .replace(/&lt;/g, '<')
  174. .replace(/&gt;/g, '>')
  175. .replace(/&quot;/g, '"')
  176. .replace(/&#039;/g, '\'')
  177. .replace(/&#x60;/g, '`')
  178. }
  179. return text
  180. },
  181. getRealDataAttr (dataAttr) {
  182. for (const [attr, value] of Object.entries(dataAttr)) {
  183. const auxAttr = attr.split(/(?=[A-Z])/).join('-').toLowerCase()
  184. if (auxAttr !== attr) {
  185. dataAttr[auxAttr] = value
  186. delete dataAttr[attr]
  187. }
  188. }
  189. return dataAttr
  190. },
  191. getItemField (item, field, escape) {
  192. let value = item
  193. if (typeof field !== 'string' || item.hasOwnProperty(field)) {
  194. return escape ? this.escapeHTML(item[field]) : item[field]
  195. }
  196. const props = field.split('.')
  197. for (const p of props) {
  198. value = value && value[p]
  199. }
  200. return escape ? this.escapeHTML(value) : value
  201. },
  202. isIEBrowser () {
  203. return navigator.userAgent.includes('MSIE ') ||
  204. /Trident.*rv:11\./.test(navigator.userAgent)
  205. },
  206. findIndex (items, item) {
  207. for (const it of items) {
  208. if (JSON.stringify(it) === JSON.stringify(item)) {
  209. return items.indexOf(it)
  210. }
  211. }
  212. return -1
  213. },
  214. trToData (columns, $els) {
  215. const data = []
  216. const m = []
  217. $els.each((y, el) => {
  218. const $el = $(el)
  219. const row = {}
  220. // save tr's id, class and data-* attributes
  221. row._id = $el.attr('id')
  222. row._class = $el.attr('class')
  223. row._data = this.getRealDataAttr($el.data())
  224. row._style = $el.attr('style')
  225. $el.find('>td,>th').each((_x, el) => {
  226. const $el = $(el)
  227. const cspan = +$el.attr('colspan') || 1
  228. const rspan = +$el.attr('rowspan') || 1
  229. let x = _x
  230. // skip already occupied cells in current row
  231. for (; m[y] && m[y][x]; x++) {
  232. // ignore
  233. }
  234. // mark matrix elements occupied by current cell with true
  235. for (let tx = x; tx < x + cspan; tx++) {
  236. for (let ty = y; ty < y + rspan; ty++) {
  237. if (!m[ty]) { // fill missing rows
  238. m[ty] = []
  239. }
  240. m[ty][tx] = true
  241. }
  242. }
  243. const field = columns[x].field
  244. row[field] = $el.html().trim()
  245. // save td's id, class and data-* attributes
  246. row[`_${field}_id`] = $el.attr('id')
  247. row[`_${field}_class`] = $el.attr('class')
  248. row[`_${field}_rowspan`] = $el.attr('rowspan')
  249. row[`_${field}_colspan`] = $el.attr('colspan')
  250. row[`_${field}_title`] = $el.attr('title')
  251. row[`_${field}_data`] = this.getRealDataAttr($el.data())
  252. row[`_${field}_style`] = $el.attr('style')
  253. })
  254. data.push(row)
  255. })
  256. return data
  257. },
  258. sort (a, b, order, sortStable, aPosition, bPosition) {
  259. if (a === undefined || a === null) {
  260. a = ''
  261. }
  262. if (b === undefined || b === null) {
  263. b = ''
  264. }
  265. if (sortStable && a === b) {
  266. a = aPosition
  267. b = bPosition
  268. }
  269. // If both values are numeric, do a numeric comparison
  270. if (this.isNumeric(a) && this.isNumeric(b)) {
  271. // Convert numerical values form string to float.
  272. a = parseFloat(a)
  273. b = parseFloat(b)
  274. if (a < b) {
  275. return order * -1
  276. }
  277. if (a > b) {
  278. return order
  279. }
  280. return 0
  281. }
  282. if (a === b) {
  283. return 0
  284. }
  285. // If value is not a string, convert to string
  286. if (typeof a !== 'string') {
  287. a = a.toString()
  288. }
  289. if (a.localeCompare(b) === -1) {
  290. return order * -1
  291. }
  292. return order
  293. },
  294. getEventName (eventPrefix, id = '') {
  295. id = id || `${+new Date()}${~~(Math.random() * 1000000)}`
  296. return `${eventPrefix}-${id}`
  297. },
  298. hasDetailViewIcon (options) {
  299. return options.detailView && options.detailViewIcon && !options.cardView
  300. },
  301. getDetailViewIndexOffset (options) {
  302. return this.hasDetailViewIcon(options) && options.detailViewAlign !== 'right' ? 1 : 0
  303. },
  304. checkAutoMergeCells (data) {
  305. for (const row of data) {
  306. for (const key of Object.keys(row)) {
  307. if (key.startsWith('_') && (key.endsWith('_rowspan') || key.endsWith('_colspan'))) {
  308. return true
  309. }
  310. }
  311. }
  312. return false
  313. },
  314. deepCopy (arg) {
  315. if (arg === undefined) {
  316. return arg
  317. }
  318. return $.extend(true, Array.isArray(arg) ? [] : {}, arg)
  319. }
  320. }