index.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. export default {
  2. // it only does '%s', and return '' when arguments are undefined
  3. sprintf (_str, ...args) {
  4. let flag = true
  5. let i = 0
  6. const str = _str.replace(/%s/g, () => {
  7. const arg = args[i++]
  8. if (typeof arg === 'undefined') {
  9. flag = false
  10. return ''
  11. }
  12. return arg
  13. })
  14. return flag ? str : ''
  15. },
  16. isEmptyObject (obj = {}) {
  17. return Object.entries(obj).length === 0 && obj.constructor === Object
  18. },
  19. isNumeric (n) {
  20. return !isNaN(parseFloat(n)) && isFinite(n)
  21. },
  22. getFieldTitle (list, value) {
  23. for (const item of list) {
  24. if (item.field === value) {
  25. return item.title
  26. }
  27. }
  28. return ''
  29. },
  30. setFieldIndex (columns) {
  31. let totalCol = 0
  32. const flag = []
  33. for (const column of columns[0]) {
  34. totalCol += column.colspan || 1
  35. }
  36. for (let i = 0; i < columns.length; i++) {
  37. flag[i] = []
  38. for (let j = 0; j < totalCol; j++) {
  39. flag[i][j] = false
  40. }
  41. }
  42. for (let i = 0; i < columns.length; i++) {
  43. for (const r of columns[i]) {
  44. const rowspan = r.rowspan || 1
  45. const colspan = r.colspan || 1
  46. const index = flag[i].indexOf(false)
  47. if (colspan === 1) {
  48. r.fieldIndex = index
  49. // when field is undefined, use index instead
  50. if (typeof r.field === 'undefined') {
  51. r.field = index
  52. }
  53. }
  54. for (let k = 0; k < rowspan; k++) {
  55. flag[i + k][index] = true
  56. }
  57. for (let k = 0; k < colspan; k++) {
  58. flag[i][index + k] = true
  59. }
  60. }
  61. }
  62. },
  63. getScrollBarWidth () {
  64. if (this.cachedWidth === undefined) {
  65. const $inner = $('<div/>').addClass('fixed-table-scroll-inner')
  66. const $outer = $('<div/>').addClass('fixed-table-scroll-outer')
  67. $outer.append($inner)
  68. $('body').append($outer)
  69. const w1 = $inner[0].offsetWidth
  70. $outer.css('overflow', 'scroll')
  71. let w2 = $inner[0].offsetWidth
  72. if (w1 === w2) {
  73. w2 = $outer[0].clientWidth
  74. }
  75. $outer.remove()
  76. this.cachedWidth = w1 - w2
  77. }
  78. return this.cachedWidth
  79. },
  80. calculateObjectValue (self, name, args, defaultValue) {
  81. let func = name
  82. if (typeof name === 'string') {
  83. // support obj.func1.func2
  84. const names = name.split('.')
  85. if (names.length > 1) {
  86. func = window
  87. for (const f of names) {
  88. func = func[f]
  89. }
  90. } else {
  91. func = window[name]
  92. }
  93. }
  94. if (func !== null && typeof func === 'object') {
  95. return func
  96. }
  97. if (typeof func === 'function') {
  98. return func.apply(self, args || [])
  99. }
  100. if (
  101. !func &&
  102. typeof name === 'string' &&
  103. this.sprintf(name, ...args)
  104. ) {
  105. return this.sprintf(name, ...args)
  106. }
  107. return defaultValue
  108. },
  109. compareObjects (objectA, objectB, compareLength) {
  110. const aKeys = Object.keys(objectA)
  111. const bKeys = Object.keys(objectB)
  112. if (compareLength && aKeys.length !== bKeys.length) {
  113. return false
  114. }
  115. for (const key of aKeys) {
  116. if (bKeys.includes(key) && objectA[key] !== objectB[key]) {
  117. return false
  118. }
  119. }
  120. return true
  121. },
  122. escapeHTML (text) {
  123. if (typeof text === 'string') {
  124. return text
  125. .replace(/&/g, '&amp;')
  126. .replace(/</g, '&lt;')
  127. .replace(/>/g, '&gt;')
  128. .replace(/"/g, '&quot;')
  129. .replace(/'/g, '&#039;')
  130. .replace(/`/g, '&#x60;')
  131. }
  132. return text
  133. },
  134. getRealDataAttr (dataAttr) {
  135. for (const [attr, value] of Object.entries(dataAttr)) {
  136. const auxAttr = attr.split(/(?=[A-Z])/).join('-').toLowerCase()
  137. if (auxAttr !== attr) {
  138. dataAttr[auxAttr] = value
  139. delete dataAttr[attr]
  140. }
  141. }
  142. return dataAttr
  143. },
  144. getItemField (item, field, escape) {
  145. let value = item
  146. if (typeof field !== 'string' || item.hasOwnProperty(field)) {
  147. return escape ? this.escapeHTML(item[field]) : item[field]
  148. }
  149. const props = field.split('.')
  150. for (const p of props) {
  151. value = value && value[p]
  152. }
  153. return escape ? this.escapeHTML(value) : value
  154. },
  155. isIEBrowser () {
  156. return navigator.userAgent.includes('MSIE ') ||
  157. /Trident.*rv:11\./.test(navigator.userAgent)
  158. },
  159. findIndex (items, item) {
  160. for (const it of items) {
  161. if (JSON.stringify(it) === JSON.stringify(item)) {
  162. return items.indexOf(it)
  163. }
  164. }
  165. return -1
  166. },
  167. trToData (columns, $els) {
  168. const data = []
  169. const m = []
  170. $els.each((y, el) => {
  171. const row = {}
  172. // save tr's id, class and data-* attributes
  173. row._id = $(el).attr('id')
  174. row._class = $(el).attr('class')
  175. row._data = this.getRealDataAttr($(el).data())
  176. $(el).find('>td,>th').each((_x, el) => {
  177. const cspan = +$(el).attr('colspan') || 1
  178. const rspan = +$(el).attr('rowspan') || 1
  179. let x = _x
  180. // skip already occupied cells in current row
  181. for (; m[y] && m[y][x]; x++) {
  182. // ignore
  183. }
  184. // mark matrix elements occupied by current cell with true
  185. for (let tx = x; tx < x + cspan; tx++) {
  186. for (let ty = y; ty < y + rspan; ty++) {
  187. if (!m[ty]) { // fill missing rows
  188. m[ty] = []
  189. }
  190. m[ty][tx] = true
  191. }
  192. }
  193. const field = columns[x].field
  194. row[field] = $(el).html().trim()
  195. // save td's id, class and data-* attributes
  196. row[`_${field}_id`] = $(el).attr('id')
  197. row[`_${field}_class`] = $(el).attr('class')
  198. row[`_${field}_rowspan`] = $(el).attr('rowspan')
  199. row[`_${field}_colspan`] = $(el).attr('colspan')
  200. row[`_${field}_title`] = $(el).attr('title')
  201. row[`_${field}_data`] = this.getRealDataAttr($(el).data())
  202. })
  203. data.push(row)
  204. })
  205. return data
  206. },
  207. sort (a, b, order, sortStable) {
  208. if (a === undefined || a === null) {
  209. a = ''
  210. }
  211. if (b === undefined || b === null) {
  212. b = ''
  213. }
  214. if (sortStable && a === b) {
  215. a = a._position
  216. b = b._position
  217. }
  218. // If both values are numeric, do a numeric comparison
  219. if (this.isNumeric(a) && this.isNumeric(b)) {
  220. // Convert numerical values form string to float.
  221. a = parseFloat(a)
  222. b = parseFloat(b)
  223. if (a < b) {
  224. return order * -1
  225. }
  226. if (a > b) {
  227. return order
  228. }
  229. return 0
  230. }
  231. if (a === b) {
  232. return 0
  233. }
  234. // If value is not a string, convert to string
  235. if (typeof a !== 'string') {
  236. a = a.toString()
  237. }
  238. if (a.localeCompare(b) === -1) {
  239. return order * -1
  240. }
  241. return order
  242. }
  243. }