| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828 |
- export default {
- getBootstrapVersion () {
- let bootstrapVersion = 5
- try {
- const rawVersion = $.fn.dropdown.Constructor.VERSION
- // Only try to parse VERSION if it is defined.
- // It is undefined in older versions of Bootstrap (tested with 3.1.1).
- if (rawVersion !== undefined) {
- bootstrapVersion = parseInt(rawVersion, 10)
- }
- } catch (e) {
- // ignore
- }
- try {
- // eslint-disable-next-line no-undef
- const rawVersion = bootstrap.Tooltip.VERSION
- if (rawVersion !== undefined) {
- bootstrapVersion = parseInt(rawVersion, 10)
- }
- } catch (e) {
- // ignore
- }
- return bootstrapVersion
- },
- getIconsPrefix (theme) {
- return {
- bootstrap3: 'glyphicon',
- bootstrap4: 'fa',
- bootstrap5: 'bi',
- 'bootstrap-table': 'icon',
- bulma: 'fa',
- foundation: 'fa',
- materialize: 'material-icons',
- semantic: 'fa'
- }[theme] || 'fa'
- },
- getIcons (prefix) {
- return {
- glyphicon: {
- clearSearch: 'glyphicon-trash',
- columns: 'glyphicon-th icon-th',
- detailClose: 'glyphicon-minus icon-minus',
- detailOpen: 'glyphicon-plus icon-plus',
- fullscreen: 'glyphicon-fullscreen',
- paginationSwitchDown: 'glyphicon-collapse-down icon-chevron-down',
- paginationSwitchUp: 'glyphicon-collapse-up icon-chevron-up',
- refresh: 'glyphicon-refresh icon-refresh',
- search: 'glyphicon-search',
- toggleOff: 'glyphicon-list-alt icon-list-alt',
- toggleOn: 'glyphicon-list-alt icon-list-alt'
- },
- fa: {
- clearSearch: 'fa-trash',
- columns: 'fa-th-list',
- detailClose: 'fa-minus',
- detailOpen: 'fa-plus',
- fullscreen: 'fa-arrows-alt',
- paginationSwitchDown: 'fa-caret-square-down',
- paginationSwitchUp: 'fa-caret-square-up',
- refresh: 'fa-sync',
- search: 'fa-search',
- toggleOff: 'fa-toggle-off',
- toggleOn: 'fa-toggle-on'
- },
- bi: {
- clearSearch: 'bi-trash',
- columns: 'bi-list-ul',
- detailClose: 'bi-dash',
- detailOpen: 'bi-plus',
- fullscreen: 'bi-arrows-move',
- paginationSwitchDown: 'bi-caret-down-square',
- paginationSwitchUp: 'bi-caret-up-square',
- refresh: 'bi-arrow-clockwise',
- search: 'bi-search',
- toggleOff: 'bi-toggle-off',
- toggleOn: 'bi-toggle-on'
- },
- icon: {
- clearSearch: 'icon-trash-2',
- columns: 'icon-list',
- detailClose: 'icon-minus',
- detailOpen: 'icon-plus',
- fullscreen: 'icon-maximize',
- paginationSwitchDown: 'icon-arrow-up-circle',
- paginationSwitchUp: 'icon-arrow-down-circle',
- refresh: 'icon-refresh-cw',
- search: 'icon-search',
- toggleOff: 'icon-toggle-right',
- toggleOn: 'icon-toggle-right'
- },
- 'material-icons': {
- clearSearch: 'delete',
- columns: 'view_list',
- detailClose: 'remove',
- detailOpen: 'add',
- fullscreen: 'fullscreen',
- paginationSwitchDown: 'grid_on',
- paginationSwitchUp: 'grid_off',
- refresh: 'refresh',
- search: 'search',
- sort: 'sort',
- toggleOff: 'tablet',
- toggleOn: 'tablet_android'
- }
- }[prefix] || {}
- },
- getSearchInput (that) {
- if (typeof that.options.searchSelector === 'string') {
- return $(that.options.searchSelector)
- }
- return that.$toolbar.find('.search input')
- },
- // $.extend: https://github.com/jquery/jquery/blob/3.6.2/src/core.js#L132
- extend (...args) {
- let target = args[0] || {}
- let i = 1
- let deep = false
- let clone
- // Handle a deep copy situation
- if (typeof target === 'boolean') {
- deep = target
- // Skip the boolean and the target
- target = args[i] || {}
- i++
- }
- // Handle case when target is a string or something (possible in deep copy)
- if (typeof target !== 'object' && typeof target !== 'function') {
- target = {}
- }
- for (; i < args.length; i++) {
- const options = args[i]
- // Ignore undefined/null values
- if (typeof options === 'undefined' || options === null) {
- continue
- }
- // Extend the base object
- // eslint-disable-next-line guard-for-in
- for (const name in options) {
- const copy = options[name]
- // Prevent Object.prototype pollution
- // Prevent never-ending loop
- if (name === '__proto__' || target === copy) {
- continue
- }
- const copyIsArray = Array.isArray(copy)
- // Recurse if we're merging plain objects or arrays
- if (deep && copy && (this.isObject(copy) || copyIsArray)) {
- const src = target[name]
- if (copyIsArray && Array.isArray(src)) {
- if (src.every(it => !this.isObject(it) && !Array.isArray(it))) {
- target[name] = copy
- continue
- }
- }
- if (copyIsArray && !Array.isArray(src)) {
- clone = []
- } else if (!copyIsArray && !this.isObject(src)) {
- clone = {}
- } else {
- clone = src
- }
- // Never move original objects, clone them
- target[name] = this.extend(deep, clone, copy)
- // Don't bring in undefined values
- } else if (copy !== undefined) {
- target[name] = copy
- }
- }
- }
- return target
- },
- // it only does '%s', and return '' when arguments are undefined
- sprintf (_str, ...args) {
- let flag = true
- let i = 0
- const str = _str.replace(/%s/g, () => {
- const arg = args[i++]
- if (typeof arg === 'undefined') {
- flag = false
- return ''
- }
- return arg
- })
- return flag ? str : ''
- },
- isObject (obj) {
- if (typeof obj !== 'object' || obj === null) {
- return false
- }
- let proto = obj
- while (Object.getPrototypeOf(proto) !== null) {
- proto = Object.getPrototypeOf(proto)
- }
- return Object.getPrototypeOf(obj) === proto
- },
- isEmptyObject (obj = {}) {
- return Object.entries(obj).length === 0 && obj.constructor === Object
- },
- isNumeric (n) {
- return !isNaN(parseFloat(n)) && isFinite(n)
- },
- getFieldTitle (list, value) {
- for (const item of list) {
- if (item.field === value) {
- return item.title
- }
- }
- return ''
- },
- setFieldIndex (columns) {
- let totalCol = 0
- const flag = []
- for (const column of columns[0]) {
- totalCol += column.colspan || 1
- }
- for (let i = 0; i < columns.length; i++) {
- flag[i] = []
- for (let j = 0; j < totalCol; j++) {
- flag[i][j] = false
- }
- }
- for (let i = 0; i < columns.length; i++) {
- for (const r of columns[i]) {
- const rowspan = r.rowspan || 1
- const colspan = r.colspan || 1
- const index = flag[i].indexOf(false)
- r.colspanIndex = index
- if (colspan === 1) {
- r.fieldIndex = index
- // when field is undefined, use index instead
- if (typeof r.field === 'undefined') {
- r.field = index
- }
- } else {
- r.colspanGroup = r.colspan
- }
- for (let j = 0; j < rowspan; j++) {
- for (let k = 0; k < colspan; k++) {
- flag[i + j][index + k] = true
- }
- }
- }
- }
- },
- normalizeAccent (value) {
- if (typeof value !== 'string') {
- return value
- }
- return value.normalize('NFD').replace(/[\u0300-\u036f]/g, '')
- },
- updateFieldGroup (columns, fieldColumns) {
- const allColumns = [].concat(...columns)
- for (const c of columns) {
- for (const r of c) {
- if (r.colspanGroup > 1) {
- let colspan = 0
- for (let i = r.colspanIndex; i < r.colspanIndex + r.colspanGroup; i++) {
- const underColumns = allColumns.filter(col => col.fieldIndex === i)
- const column = underColumns[underColumns.length - 1]
- if (underColumns.length > 1) {
- for (let j = 0; j < underColumns.length - 1; j++) {
- underColumns[j].visible = column.visible
- }
- }
- if (column.visible) {
- colspan++
- }
- }
- r.colspan = colspan
- r.visible = colspan > 0
- }
- }
- }
- if (columns.length < 2) {
- return
- }
- for (const column of fieldColumns) {
- const sameColumns = allColumns.filter(col => col.fieldIndex === column.fieldIndex)
- if (sameColumns.length > 1) {
- for (const c of sameColumns) {
- c.visible = column.visible
- }
- }
- }
- },
- getScrollBarWidth () {
- if (this.cachedWidth === undefined) {
- const $inner = $('<div/>').addClass('fixed-table-scroll-inner')
- const $outer = $('<div/>').addClass('fixed-table-scroll-outer')
- $outer.append($inner)
- $('body').append($outer)
- const w1 = $inner[0].offsetWidth
- $outer.css('overflow', 'scroll')
- let w2 = $inner[0].offsetWidth
- if (w1 === w2) {
- w2 = $outer[0].clientWidth
- }
- $outer.remove()
- this.cachedWidth = w1 - w2
- }
- return this.cachedWidth
- },
- calculateObjectValue (self, name, args, defaultValue) {
- let func = name
- if (typeof name === 'string') {
- // support obj.func1.func2
- const names = name.split('.')
- if (names.length > 1) {
- func = window
- for (const f of names) {
- func = func[f]
- }
- } else {
- func = window[name]
- }
- }
- if (func !== null && typeof func === 'object') {
- return func
- }
- if (typeof func === 'function') {
- return func.apply(self, args || [])
- }
- if (
- !func &&
- typeof name === 'string' &&
- args &&
- this.sprintf(name, ...args)
- ) {
- return this.sprintf(name, ...args)
- }
- return defaultValue
- },
- compareObjects (objectA, objectB, compareLength) {
- const aKeys = Object.keys(objectA)
- const bKeys = Object.keys(objectB)
- if (compareLength && aKeys.length !== bKeys.length) {
- return false
- }
- for (const key of aKeys) {
- if (bKeys.includes(key) && objectA[key] !== objectB[key]) {
- return false
- }
- }
- return true
- },
- regexCompare (value, search) {
- try {
- const regexpParts = search.match(/^\/(.*?)\/([gim]*)$/)
- if (value.toString().search(regexpParts ? new RegExp(regexpParts[1], regexpParts[2]) : new RegExp(search, 'gim')) !== -1) {
- return true
- }
- } catch (e) {
- return false
- }
- return false
- },
- escapeApostrophe (value) {
- return value.toString()
- .replace(/'/g, ''')
- },
- escapeHTML (text) {
- if (!text) {
- return text
- }
- return text.toString()
- .replace(/&/g, '&')
- .replace(/</g, '<')
- .replace(/>/g, '>')
- .replace(/"/g, '"')
- .replace(/'/g, ''')
- },
- unescapeHTML (text) {
- if (typeof text !== 'string' || !text) {
- return text
- }
- return text.toString()
- .replace(/&/g, '&')
- .replace(/</g, '<')
- .replace(/>/g, '>')
- .replace(/"/g, '"')
- .replace(/'/g, '\'')
- },
- removeHTML (text) {
- if (!text) {
- return text
- }
- return text.toString()
- .replace(/(<([^>]+)>)/ig, '')
- .replace(/&[#A-Za-z0-9]+;/gi, '')
- .trim()
- },
- getRealDataAttr (dataAttr) {
- for (const [attr, value] of Object.entries(dataAttr)) {
- const auxAttr = attr.split(/(?=[A-Z])/).join('-').toLowerCase()
- if (auxAttr !== attr) {
- dataAttr[auxAttr] = value
- delete dataAttr[attr]
- }
- }
- return dataAttr
- },
- getItemField (item, field, escape, columnEscape = undefined) {
- let value = item
- // use column escape if it is defined
- if (typeof columnEscape !== 'undefined') {
- escape = columnEscape
- }
- if (typeof field !== 'string' || item.hasOwnProperty(field)) {
- return escape ? this.escapeHTML(item[field]) : item[field]
- }
- const props = field.split('.')
- for (const p of props) {
- value = value && value[p]
- }
- return escape ? this.escapeHTML(value) : value
- },
- isIEBrowser () {
- return navigator.userAgent.includes('MSIE ') ||
- /Trident.*rv:11\./.test(navigator.userAgent)
- },
- findIndex (items, item) {
- for (const it of items) {
- if (JSON.stringify(it) === JSON.stringify(item)) {
- return items.indexOf(it)
- }
- }
- return -1
- },
- trToData (columns, $els) {
- const data = []
- const m = []
- $els.each((y, el) => {
- const $el = $(el)
- const row = {}
- // save tr's id, class and data-* attributes
- row._id = $el.attr('id')
- row._class = $el.attr('class')
- row._data = this.getRealDataAttr($el.data())
- row._style = $el.attr('style')
- $el.find('>td,>th').each((_x, el) => {
- const $el = $(el)
- const colspan = +$el.attr('colspan') || 1
- const rowspan = +$el.attr('rowspan') || 1
- let x = _x
- // skip already occupied cells in current row
- for (; m[y] && m[y][x]; x++) {
- // ignore
- }
- // mark matrix elements occupied by current cell with true
- for (let tx = x; tx < x + colspan; tx++) {
- for (let ty = y; ty < y + rowspan; ty++) {
- if (!m[ty]) { // fill missing rows
- m[ty] = []
- }
- m[ty][tx] = true
- }
- }
- const field = columns[x].field
- row[field] = this.escapeApostrophe($el.html().trim())
- // save td's id, class and data-* attributes
- row[`_${field}_id`] = $el.attr('id')
- row[`_${field}_class`] = $el.attr('class')
- row[`_${field}_rowspan`] = $el.attr('rowspan')
- row[`_${field}_colspan`] = $el.attr('colspan')
- row[`_${field}_title`] = $el.attr('title')
- row[`_${field}_data`] = this.getRealDataAttr($el.data())
- row[`_${field}_style`] = $el.attr('style')
- })
- data.push(row)
- })
- return data
- },
- sort (a, b, order, options, aPosition, bPosition) {
- if (a === undefined || a === null) {
- a = ''
- }
- if (b === undefined || b === null) {
- b = ''
- }
- if (options.sortStable && a === b) {
- a = aPosition
- b = bPosition
- }
- // If both values are numeric, do a numeric comparison
- if (this.isNumeric(a) && this.isNumeric(b)) {
- // Convert numerical values form string to float.
- a = parseFloat(a)
- b = parseFloat(b)
- if (a < b) {
- return order * -1
- }
- if (a > b) {
- return order
- }
- return 0
- }
- if (options.sortEmptyLast) {
- if (a === '') {
- return 1
- }
- if (b === '') {
- return -1
- }
- }
- if (a === b) {
- return 0
- }
- // If value is not a string, convert to string
- if (typeof a !== 'string') {
- a = a.toString()
- }
- if (a.localeCompare(b) === -1) {
- return order * -1
- }
- return order
- },
- getEventName (eventPrefix, id = '') {
- id = id || `${+new Date()}${~~(Math.random() * 1000000)}`
- return `${eventPrefix}-${id}`
- },
- hasDetailViewIcon (options) {
- return options.detailView && options.detailViewIcon && !options.cardView
- },
- getDetailViewIndexOffset (options) {
- return this.hasDetailViewIcon(options) && options.detailViewAlign !== 'right' ? 1 : 0
- },
- checkAutoMergeCells (data) {
- for (const row of data) {
- for (const key of Object.keys(row)) {
- if (key.startsWith('_') && (key.endsWith('_rowspan') || key.endsWith('_colspan'))) {
- return true
- }
- }
- }
- return false
- },
- deepCopy (arg) {
- if (arg === undefined) {
- return arg
- }
- return this.extend(true, Array.isArray(arg) ? [] : {}, arg)
- },
- debounce (func, wait, immediate) {
- let timeout
- return function executedFunction () {
- const context = this
- const args = arguments
- const later = function () {
- timeout = null
- if (!immediate) func.apply(context, args)
- }
- const callNow = immediate && !timeout
- clearTimeout(timeout)
- timeout = setTimeout(later, wait)
- if (callNow) func.apply(context, args)
- }
- },
- replaceSearchMark (html, searchText) {
- const isDom = html instanceof Element
- const node = isDom ? html : document.createElement('div')
- const regExp = new RegExp(searchText, 'gim')
- const replaceTextWithDom = (text, regExp) => {
- const result = []
- let match
- let lastIndex = 0
- while ((match = regExp.exec(text)) !== null) {
- if (lastIndex !== match.index) {
- result.push(document.createTextNode(text.substring(lastIndex, match.index)))
- }
- const mark = document.createElement('mark')
- mark.innerText = match[0]
- result.push(mark)
- lastIndex = match.index + match[0].length
- }
- if (!result.length) {
- // no match
- return
- }
- if (lastIndex !== text.length) {
- result.push(document.createTextNode(text.substring(lastIndex)))
- }
- return result
- }
- const replaceMark = node => {
- for (let i = 0; i < node.childNodes.length; i++) {
- const child = node.childNodes[i]
- if (child.nodeType === document.TEXT_NODE) {
- const elements = replaceTextWithDom(child.data, regExp)
- if (elements) {
- for (const el of elements) {
- node.insertBefore(el, child)
- }
- node.removeChild(child)
- i += elements.length - 1
- }
- }
- if (child.nodeType === document.ELEMENT_NODE) {
- replaceMark(child)
- }
- }
- }
- if (!isDom) {
- node.innerHTML = html
- }
- replaceMark(node)
- return isDom ? node : node.innerHTML
- },
- classToString (class_) {
- if (typeof class_ === 'string') {
- return class_
- }
- if (Array.isArray(class_)) {
- return class_.map(x => this.classToString(x)).filter(x => x).join(' ')
- }
- if (class_ && typeof class_ === 'object') {
- return Object.entries(class_).map(([k, v]) => v ? k : '').filter(x => x).join(' ')
- }
- return ''
- },
- parseStyle (dom, style) {
- if (!style) {
- return dom
- }
- if (typeof style === 'string') {
- style.split(';').forEach(i => {
- const index = i.indexOf(':')
- if (index > 0) {
- const k = i.substring(0, index).trim()
- const v = i.substring(index + 1).trim()
- dom.style.setProperty(k, v)
- }
- })
- } else if (Array.isArray(style)) {
- for (const item of style) {
- this.parseStyle(item)
- }
- } else if (typeof style === 'object') {
- for (const [k, v] of Object.entries(style)) {
- dom.style.setProperty(k, v)
- }
- }
- return dom
- },
- h (element, attrs, children) {
- const el = element instanceof HTMLElement ? element : document.createElement(element)
- const _attrs = attrs || {}
- const _children = children || []
- // default attributes
- if (el.tagName === 'A') {
- el.href = 'javascript:'
- }
- for (const [k, v] of Object.entries(_attrs)) {
- if (v === undefined) {
- continue
- }
- if (['text', 'innerText'].includes(k)) {
- el.innerText = v
- } else if (['html', 'innerHTML'].includes(k)) {
- el.innerHTML = v
- } else if (k === 'children') {
- _children.push(...v)
- } else if (k === 'class') {
- el.setAttribute('class', this.classToString(v))
- } else if (k === 'style') {
- if (typeof v === 'string') {
- el.setAttribute('style', v)
- } else {
- this.parseStyle(el, v)
- }
- } else if (k.startsWith('@') || k.startsWith('on')) {
- // event handlers
- const event = k.startsWith('@') ? k.substring(1) : k.substring(2).toLowerCase()
- const args = Array.isArray(v) ? v : [v]
- el.addEventListener(event, ...args)
- } else if (k.startsWith('.')) {
- // set property
- el[k.substring(1)] = v
- } else {
- el.setAttribute(k, v)
- }
- }
- if (_children.length) {
- el.append(..._children)
- }
- return el
- },
- htmlToNodes (html) {
- if (html instanceof $) {
- return html.get()
- }
- if (html instanceof Node) {
- return [html]
- }
- if (typeof html !== 'string') {
- html = new String(html).toString()
- }
- const d = document.createElement('div')
- d.innerHTML = html
- return d.childNodes
- }
- }
|