mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
bootstrap-table: Add "extensions"
This commit is contained in:
parent
316dfe5e38
commit
37baec2db6
@ -0,0 +1,170 @@
|
|||||||
|
/**
|
||||||
|
* @author: Dennis Hernández
|
||||||
|
* @webSite: http://djhvscf.github.io/Blog
|
||||||
|
* @update: zhixin wen <wenzhixin2010@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
!($ => {
|
||||||
|
const diacriticsMap = {}
|
||||||
|
const defaultAccentsDiacritics = [
|
||||||
|
{base: 'A', letters: '\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F'},
|
||||||
|
{base: 'AA',letters: '\uA732'},
|
||||||
|
{base: 'AE',letters: '\u00C6\u01FC\u01E2'},
|
||||||
|
{base: 'AO',letters: '\uA734'},
|
||||||
|
{base: 'AU',letters: '\uA736'},
|
||||||
|
{base: 'AV',letters: '\uA738\uA73A'},
|
||||||
|
{base: 'AY',letters: '\uA73C'},
|
||||||
|
{base: 'B', letters: '\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181'},
|
||||||
|
{base: 'C', letters: '\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E'},
|
||||||
|
{base: 'D', letters: '\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779'},
|
||||||
|
{base: 'DZ',letters: '\u01F1\u01C4'},
|
||||||
|
{base: 'Dz',letters: '\u01F2\u01C5'},
|
||||||
|
{base: 'E', letters: '\u0045\u24BA\uFF25\u00C8\u00C9\u00CA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\u00CB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E'},
|
||||||
|
{base: 'F', letters: '\u0046\u24BB\uFF26\u1E1E\u0191\uA77B'},
|
||||||
|
{base: 'G', letters: '\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E'},
|
||||||
|
{base: 'H', letters: '\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D'},
|
||||||
|
{base: 'I', letters: '\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197'},
|
||||||
|
{base: 'J', letters: '\u004A\u24BF\uFF2A\u0134\u0248'},
|
||||||
|
{base: 'K', letters: '\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2'},
|
||||||
|
{base: 'L', letters: '\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780'},
|
||||||
|
{base: 'LJ',letters: '\u01C7'},
|
||||||
|
{base: 'Lj',letters: '\u01C8'},
|
||||||
|
{base: 'M', letters: '\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C'},
|
||||||
|
{base: 'N', letters: '\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4'},
|
||||||
|
{base: 'NJ',letters: '\u01CA'},
|
||||||
|
{base: 'Nj',letters: '\u01CB'},
|
||||||
|
{base: 'O', letters: '\u004F\u24C4\uFF2F\u00D2\u00D3\u00D4\u1ED2\u1ED0\u1ED6\u1ED4\u00D5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\u00D6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\u00D8\u01FE\u0186\u019F\uA74A\uA74C'},
|
||||||
|
{base: 'OI',letters: '\u01A2'},
|
||||||
|
{base: 'OO',letters: '\uA74E'},
|
||||||
|
{base: 'OU',letters: '\u0222'},
|
||||||
|
{base: 'OE',letters: '\u008C\u0152'},
|
||||||
|
{base: 'oe',letters: '\u009C\u0153'},
|
||||||
|
{base: 'P', letters: '\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754'},
|
||||||
|
{base: 'Q', letters: '\u0051\u24C6\uFF31\uA756\uA758\u024A'},
|
||||||
|
{base: 'R', letters: '\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782'},
|
||||||
|
{base: 'S', letters: '\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784'},
|
||||||
|
{base: 'T', letters: '\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786'},
|
||||||
|
{base: 'TZ',letters: '\uA728'},
|
||||||
|
{base: 'U', letters: '\u0055\u24CA\uFF35\u00D9\u00DA\u00DB\u0168\u1E78\u016A\u1E7A\u016C\u00DC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244'},
|
||||||
|
{base: 'V', letters: '\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245'},
|
||||||
|
{base: 'VY',letters: '\uA760'},
|
||||||
|
{base: 'W', letters: '\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72'},
|
||||||
|
{base: 'X', letters: '\u0058\u24CD\uFF38\u1E8A\u1E8C'},
|
||||||
|
{base: 'Y', letters: '\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE'},
|
||||||
|
{base: 'Z', letters: '\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762'},
|
||||||
|
{base: 'a', letters: '\u0061\u24D0\uFF41\u1E9A\u00E0\u00E1\u00E2\u1EA7\u1EA5\u1EAB\u1EA9\u00E3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\u00E4\u01DF\u1EA3\u00E5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250'},
|
||||||
|
{base: 'aa',letters: '\uA733'},
|
||||||
|
{base: 'ae',letters: '\u00E6\u01FD\u01E3'},
|
||||||
|
{base: 'ao',letters: '\uA735'},
|
||||||
|
{base: 'au',letters: '\uA737'},
|
||||||
|
{base: 'av',letters: '\uA739\uA73B'},
|
||||||
|
{base: 'ay',letters: '\uA73D'},
|
||||||
|
{base: 'b', letters: '\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253'},
|
||||||
|
{base: 'c', letters: '\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184'},
|
||||||
|
{base: 'd', letters: '\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A'},
|
||||||
|
{base: 'dz',letters: '\u01F3\u01C6'},
|
||||||
|
{base: 'e', letters: '\u0065\u24D4\uFF45\u00E8\u00E9\u00EA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\u00EB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u025B\u01DD'},
|
||||||
|
{base: 'f', letters: '\u0066\u24D5\uFF46\u1E1F\u0192\uA77C'},
|
||||||
|
{base: 'g', letters: '\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F'},
|
||||||
|
{base: 'h', letters: '\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265'},
|
||||||
|
{base: 'hv',letters: '\u0195'},
|
||||||
|
{base: 'i', letters: '\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131'},
|
||||||
|
{base: 'j', letters: '\u006A\u24D9\uFF4A\u0135\u01F0\u0249'},
|
||||||
|
{base: 'k', letters: '\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3'},
|
||||||
|
{base: 'l', letters: '\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747'},
|
||||||
|
{base: 'lj',letters: '\u01C9'},
|
||||||
|
{base: 'm', letters: '\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F'},
|
||||||
|
{base: 'n', letters: '\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5'},
|
||||||
|
{base: 'nj',letters: '\u01CC'},
|
||||||
|
{base: 'o', letters: '\u006F\u24DE\uFF4F\u00F2\u00F3\u00F4\u1ED3\u1ED1\u1ED7\u1ED5\u00F5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\u00F6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\u00F8\u01FF\u0254\uA74B\uA74D\u0275'},
|
||||||
|
{base: 'oi',letters: '\u01A3'},
|
||||||
|
{base: 'ou',letters: '\u0223'},
|
||||||
|
{base: 'oo',letters: '\uA74F'},
|
||||||
|
{base: 'p',letters: '\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755'},
|
||||||
|
{base: 'q',letters: '\u0071\u24E0\uFF51\u024B\uA757\uA759'},
|
||||||
|
{base: 'r',letters: '\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783'},
|
||||||
|
{base: 's',letters: '\u0073\u24E2\uFF53\u00DF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B'},
|
||||||
|
{base: 't',letters: '\u0074\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787'},
|
||||||
|
{base: 'tz',letters: '\uA729'},
|
||||||
|
{base: 'u',letters: '\u0075\u24E4\uFF55\u00F9\u00FA\u00FB\u0169\u1E79\u016B\u1E7B\u016D\u00FC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289'},
|
||||||
|
{base: 'v',letters: '\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C'},
|
||||||
|
{base: 'vy',letters: '\uA761'},
|
||||||
|
{base: 'w',letters: '\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73'},
|
||||||
|
{base: 'x',letters: '\u0078\u24E7\uFF58\u1E8B\u1E8D'},
|
||||||
|
{base: 'y',letters: '\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF'},
|
||||||
|
{base: 'z',letters: '\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763'}
|
||||||
|
]
|
||||||
|
|
||||||
|
const initNeutraliser = () => {
|
||||||
|
for (const diacritic of defaultAccentsDiacritics) {
|
||||||
|
const letters = diacritic.letters
|
||||||
|
for (let i = 0; i < letters.length; i++) {
|
||||||
|
diacriticsMap[letters[i]] = diacritic.base
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* eslint-disable no-control-regex */
|
||||||
|
const removeDiacritics = str => str.replace(/[^\u0000-\u007E]/g, a => diacriticsMap[a] || a)
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, {
|
||||||
|
searchAccentNeutralise: false
|
||||||
|
})
|
||||||
|
|
||||||
|
$.BootstrapTable = class extends $.BootstrapTable {
|
||||||
|
init () {
|
||||||
|
if (this.options.searchAccentNeutralise) {
|
||||||
|
initNeutraliser()
|
||||||
|
}
|
||||||
|
super.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
initSearch () {
|
||||||
|
if (this.options.sidePagination !== 'server') {
|
||||||
|
let s = this.searchText && this.searchText.toLowerCase()
|
||||||
|
const f = $.isEmptyObject(this.filterColumns) ? null : this.filterColumns
|
||||||
|
|
||||||
|
// Check filter
|
||||||
|
this.data = f ? this.options.data.filter((item, i) => {
|
||||||
|
for (const key in f) {
|
||||||
|
if (item[key] !== f[key]) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}) : this.options.data
|
||||||
|
|
||||||
|
this.data = s ? this.options.data.filter((item, i) => {
|
||||||
|
for (let [key, value] of Object.entries(item)) {
|
||||||
|
key = $.isNumeric(key) ? parseInt(key, 10) : key
|
||||||
|
const column = this.columns[this.fieldsColumnsIndex[key]]
|
||||||
|
const j = this.header.fields.indexOf(key)
|
||||||
|
|
||||||
|
if (column && column.searchFormatter) {
|
||||||
|
value = $.fn.bootstrapTable.utils.calculateObjectValue(column,
|
||||||
|
this.header.formatters[j], [value, item, i], value)
|
||||||
|
}
|
||||||
|
|
||||||
|
const index = this.header.fields.indexOf(key)
|
||||||
|
if (index !== -1 && this.header.searchables[index] && typeof value === 'string') {
|
||||||
|
if (this.options.searchAccentNeutralise) {
|
||||||
|
value = removeDiacritics(value)
|
||||||
|
s = removeDiacritics(s)
|
||||||
|
}
|
||||||
|
if (this.options.strictSearch) {
|
||||||
|
if ((`${value}`).toLowerCase() === s) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ((`${value}`).toLowerCase().includes(s)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}) : this.data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})(jQuery)
|
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "Accent Neutralise",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Plugin to neutralise the words.",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/accent-neutralise",
|
||||||
|
"example": "#",
|
||||||
|
|
||||||
|
"plugins": [{
|
||||||
|
"name": "bootstrap-table-accent-neutralise",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/accent-neutralise"
|
||||||
|
}],
|
||||||
|
|
||||||
|
"author": {
|
||||||
|
"name": "djhvscf",
|
||||||
|
"image": "https://avatars1.githubusercontent.com/u/4496763"
|
||||||
|
}
|
||||||
|
}
|
116
InvenTree/InvenTree/static/bootstrap-table/extensions/addrbar/bootstrap-table-addrbar.js
vendored
Normal file
116
InvenTree/InvenTree/static/bootstrap-table/extensions/addrbar/bootstrap-table-addrbar.js
vendored
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
/**
|
||||||
|
* @author: general
|
||||||
|
* @website: note.generals.space
|
||||||
|
* @email: generals.space@gmail.com
|
||||||
|
* @github: https://github.com/generals-space/bootstrap-table-addrbar
|
||||||
|
* @update: zhixin wen <wenzhixin2010@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
($ => {
|
||||||
|
/*
|
||||||
|
* function: 获取浏览器地址栏中的指定参数.
|
||||||
|
* key: 参数名
|
||||||
|
* url: 默认为当前地址栏
|
||||||
|
*/
|
||||||
|
function _GET (key, url = window.location.search) {
|
||||||
|
/*
|
||||||
|
* 注意这里正则表达式的书写方法
|
||||||
|
* (^|&)key匹配: 直接以key开始或以&key开始的字符串
|
||||||
|
* 同理(&|$)表示以&结束或是直接结束的字符串
|
||||||
|
* ...当然, 我并不知道这种用法.
|
||||||
|
*/
|
||||||
|
const reg = new RegExp(`(^|&)${key}=([^&]*)(&|$)`)
|
||||||
|
const result = url.substr(1).match(reg)
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
return decodeURIComponent(result[2])
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* function: 根据给定参数生成url地址
|
||||||
|
* var dic = {name: 'genreal', age: 24}
|
||||||
|
* var url = 'https://www.baidu.com?age=22';
|
||||||
|
* _buildUrl(dic, url);
|
||||||
|
* 将得到"https://www.baidu.com?age=24&name=genreal"
|
||||||
|
* 哦, 忽略先后顺序吧...
|
||||||
|
*
|
||||||
|
* 补充: 可以参考浏览器URLSearchParams对象, 更加方便和强大.
|
||||||
|
* 考虑到兼容性, 暂时不使用这个工具.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function _buildUrl (dict, url = window.location.search) {
|
||||||
|
for (const [key, val] of Object.entries(dict)) {
|
||||||
|
// 搜索name=general这种形式的字符串(&是分隔符)
|
||||||
|
const pattern = `${key}=([^&]*)`
|
||||||
|
const targetStr = `${key}=${val}`
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 如果目标url中包含了key键, 我们需要将它替换成我们自己的val
|
||||||
|
* 不然就直接添加好了.
|
||||||
|
*/
|
||||||
|
if (url.match(pattern)) {
|
||||||
|
const tmp = new RegExp(`(${key}=)([^&]*)`, 'gi')
|
||||||
|
url = url.replace(tmp, targetStr)
|
||||||
|
} else {
|
||||||
|
const seperator = url.match('[?]') ? '&' : '?'
|
||||||
|
url = url + seperator + targetStr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (location.hash) {
|
||||||
|
url += location.hash
|
||||||
|
}
|
||||||
|
return url
|
||||||
|
}
|
||||||
|
|
||||||
|
$.BootstrapTable = class extends $.BootstrapTable {
|
||||||
|
init () {
|
||||||
|
// 拥有addrbar选项并且其值为true的才会继续执行
|
||||||
|
if (this.options.addrbar) {
|
||||||
|
// 标志位, 初始加载后关闭
|
||||||
|
this.addrbarInit = true
|
||||||
|
const _prefix = this.options.addrPrefix || ''
|
||||||
|
|
||||||
|
// 优先级排序: 用户指定值最优先, 未指定时从地址栏获取, 未获取到时采用默认值
|
||||||
|
this.options.pageSize = this.options.pageSize || (
|
||||||
|
_GET(`${_prefix}limit`) ? parseInt(_GET(`${_prefix}limit`)) : $.BootstrapTable.DEFAULTS.pageSize
|
||||||
|
)
|
||||||
|
this.options.pageNumber = this.options.pageNumber || (
|
||||||
|
_GET(`${_prefix}page`) ? parseInt(_GET(`${_prefix}page`)) : $.BootstrapTable.DEFAULTS.pageNumber
|
||||||
|
)
|
||||||
|
this.options.sortOrder = this.options.sortOrder || (
|
||||||
|
_GET(`${_prefix}order`) ? _GET(`${_prefix}order`) : $.BootstrapTable.DEFAULTS.sortOrder
|
||||||
|
)
|
||||||
|
this.options.sortName = this.options.sortName || (
|
||||||
|
_GET(`${_prefix}sort`) ? _GET(`${_prefix}sort`) : 'id'
|
||||||
|
)
|
||||||
|
this.options.searchText = this.options.searchText || (
|
||||||
|
_GET(`${_prefix}search`) ? _GET(`${_prefix}search`) : $.BootstrapTable.DEFAULTS.searchText
|
||||||
|
)
|
||||||
|
|
||||||
|
const _onLoadSuccess = this.options.onLoadSuccess
|
||||||
|
|
||||||
|
this.options.onLoadSuccess = data => {
|
||||||
|
if (this.addrbarInit) {
|
||||||
|
this.addrbarInit = false
|
||||||
|
} else {
|
||||||
|
const params = {}
|
||||||
|
params[`${_prefix}page`] = this.options.pageNumber,
|
||||||
|
params[`${_prefix}limit`] = this.options.pageSize,
|
||||||
|
params[`${_prefix}order`] = this.options.sortOrder,
|
||||||
|
params[`${_prefix}sort`] = this.options.sortName,
|
||||||
|
params[`${_prefix}search`] = this.options.searchText
|
||||||
|
// h5提供的修改浏览器地址栏的方法
|
||||||
|
window.history.pushState({}, '', _buildUrl(params))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_onLoadSuccess) {
|
||||||
|
_onLoadSuccess.call(this, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.init()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})(jQuery)
|
@ -0,0 +1,78 @@
|
|||||||
|
/**
|
||||||
|
* @author: Alec Fenichel
|
||||||
|
* @webSite: https://fenichelar.com
|
||||||
|
* @update: zhixin wen <wenzhixin2010@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
($ => {
|
||||||
|
const Utils = $.fn.bootstrapTable.utils
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, {
|
||||||
|
autoRefresh: false,
|
||||||
|
autoRefreshInterval: 60,
|
||||||
|
autoRefreshSilent: true,
|
||||||
|
autoRefreshStatus: true,
|
||||||
|
autoRefreshFunction: null
|
||||||
|
})
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults.icons, {
|
||||||
|
autoRefresh: Utils.bootstrapVersion === 4 ? 'fa-clock' : 'glyphicon-time icon-time'
|
||||||
|
})
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.locales, {
|
||||||
|
formatAutoRefresh () {
|
||||||
|
return 'Auto Refresh'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales)
|
||||||
|
|
||||||
|
$.BootstrapTable = class extends $.BootstrapTable {
|
||||||
|
init (...args) {
|
||||||
|
super.init(...args)
|
||||||
|
|
||||||
|
if (this.options.autoRefresh && this.options.autoRefreshStatus) {
|
||||||
|
this.options.autoRefreshFunction = setInterval(() => {
|
||||||
|
this.refresh({silent: this.options.autoRefreshSilent})
|
||||||
|
}, this.options.autoRefreshInterval * 1000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
initToolbar (...args) {
|
||||||
|
super.initToolbar(...args)
|
||||||
|
|
||||||
|
if (this.options.autoRefresh) {
|
||||||
|
const $btnGroup = this.$toolbar.find('>.btn-group')
|
||||||
|
let $btnAutoRefresh = $btnGroup.find('.auto-refresh')
|
||||||
|
|
||||||
|
if (!$btnAutoRefresh.length) {
|
||||||
|
$btnAutoRefresh = $(`
|
||||||
|
<button class="auto-refresh btn${Utils.sprintf(' btn-%s', this.options.buttonsClass)}
|
||||||
|
${Utils.sprintf(' btn-%s', this.options.iconSize)}
|
||||||
|
${this.options.autoRefreshStatus ? 'active' : ''}"
|
||||||
|
type="button" title="${this.options.formatAutoRefresh()}">
|
||||||
|
<i class="${this.options.iconsPrefix} ${this.options.icons.autoRefresh}"></i>
|
||||||
|
</button>
|
||||||
|
`).appendTo($btnGroup)
|
||||||
|
|
||||||
|
$btnAutoRefresh.on('click', $.proxy(this.toggleAutoRefresh, this))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleAutoRefresh () {
|
||||||
|
if (this.options.autoRefresh) {
|
||||||
|
if (this.options.autoRefreshStatus) {
|
||||||
|
clearInterval(this.options.autoRefreshFunction)
|
||||||
|
this.$toolbar.find('>.btn-group').find('.auto-refresh').removeClass('active')
|
||||||
|
} else {
|
||||||
|
this.options.autoRefreshFunction = setInterval(() => {
|
||||||
|
this.refresh({silent: this.options.autoRefreshSilent})
|
||||||
|
}, this.options.autoRefreshInterval * 1000)
|
||||||
|
this.$toolbar.find('>.btn-group').find('.auto-refresh').addClass('active')
|
||||||
|
}
|
||||||
|
this.options.autoRefreshStatus = !this.options.autoRefreshStatus
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})(jQuery)
|
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "Auto Refresh",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Plugin to automatically refresh the table on an interval.",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/auto-refresh",
|
||||||
|
"example": "#",
|
||||||
|
|
||||||
|
"plugins": [{
|
||||||
|
"name": "bootstrap-table-auto-refresh",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/auto-refresh"
|
||||||
|
}],
|
||||||
|
|
||||||
|
"author": {
|
||||||
|
"name": "fenichaler",
|
||||||
|
"image": "https://avatars.githubusercontent.com/u/3437075"
|
||||||
|
}
|
||||||
|
}
|
401
InvenTree/InvenTree/static/bootstrap-table/extensions/cookie/bootstrap-table-cookie.js
vendored
Normal file
401
InvenTree/InvenTree/static/bootstrap-table/extensions/cookie/bootstrap-table-cookie.js
vendored
Normal file
@ -0,0 +1,401 @@
|
|||||||
|
/**
|
||||||
|
* @author: Dennis Hernández
|
||||||
|
* @webSite: http://djhvscf.github.io/Blog
|
||||||
|
* @update zhixin wen <wenzhixin2010@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
($ => {
|
||||||
|
const UtilsCookie = {
|
||||||
|
cookieIds: {
|
||||||
|
sortOrder: 'bs.table.sortOrder',
|
||||||
|
sortName: 'bs.table.sortName',
|
||||||
|
pageNumber: 'bs.table.pageNumber',
|
||||||
|
pageList: 'bs.table.pageList',
|
||||||
|
columns: 'bs.table.columns',
|
||||||
|
searchText: 'bs.table.searchText',
|
||||||
|
filterControl: 'bs.table.filterControl',
|
||||||
|
filterBy: 'bs.table.filterBy'
|
||||||
|
},
|
||||||
|
getCurrentHeader (that) {
|
||||||
|
let header = that.$header
|
||||||
|
if (that.options.height) {
|
||||||
|
header = that.$tableHeader
|
||||||
|
}
|
||||||
|
|
||||||
|
return header
|
||||||
|
},
|
||||||
|
getCurrentSearchControls (that) {
|
||||||
|
let searchControls = 'select, input'
|
||||||
|
if (that.options.height) {
|
||||||
|
searchControls = 'table select, table input'
|
||||||
|
}
|
||||||
|
|
||||||
|
return searchControls
|
||||||
|
},
|
||||||
|
cookieEnabled () {
|
||||||
|
return !!(navigator.cookieEnabled)
|
||||||
|
},
|
||||||
|
inArrayCookiesEnabled (cookieName, cookiesEnabled) {
|
||||||
|
let index = -1
|
||||||
|
|
||||||
|
for (let i = 0; i < cookiesEnabled.length; i++) {
|
||||||
|
if (cookieName.toLowerCase() === cookiesEnabled[i].toLowerCase()) {
|
||||||
|
index = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return index
|
||||||
|
},
|
||||||
|
setCookie (that, cookieName, cookieValue) {
|
||||||
|
if ((!that.options.cookie) || (!UtilsCookie.cookieEnabled()) || (that.options.cookieIdTable === '')) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UtilsCookie.inArrayCookiesEnabled(cookieName, that.options.cookiesEnabled) === -1) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cookieName = `${that.options.cookieIdTable}.${cookieName}`
|
||||||
|
|
||||||
|
switch (that.options.cookieStorage) {
|
||||||
|
case 'cookieStorage':
|
||||||
|
document.cookie = [
|
||||||
|
cookieName, '=', encodeURIComponent(cookieValue),
|
||||||
|
`; expires=${UtilsCookie.calculateExpiration(that.options.cookieExpire)}`,
|
||||||
|
that.options.cookiePath ? `; path=${that.options.cookiePath}` : '',
|
||||||
|
that.options.cookieDomain ? `; domain=${that.options.cookieDomain}` : '',
|
||||||
|
that.options.cookieSecure ? '; secure' : ''
|
||||||
|
].join('')
|
||||||
|
break
|
||||||
|
case 'localStorage':
|
||||||
|
localStorage.setItem(cookieName, cookieValue)
|
||||||
|
break
|
||||||
|
case 'sessionStorage':
|
||||||
|
sessionStorage.setItem(cookieName, cookieValue)
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
getCookie (that, tableName, cookieName) {
|
||||||
|
if (!cookieName) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UtilsCookie.inArrayCookiesEnabled(cookieName, that.options.cookiesEnabled) === -1) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
cookieName = `${tableName}.${cookieName}`
|
||||||
|
|
||||||
|
switch (that.options.cookieStorage) {
|
||||||
|
case 'cookieStorage':
|
||||||
|
const value = `; ${document.cookie}`
|
||||||
|
const parts = value.split(`; ${cookieName}=`)
|
||||||
|
return parts.length === 2 ? decodeURIComponent(parts.pop().split(';').shift()) : null
|
||||||
|
case 'localStorage':
|
||||||
|
return localStorage.getItem(cookieName)
|
||||||
|
case 'sessionStorage':
|
||||||
|
return sessionStorage.getItem(cookieName)
|
||||||
|
default:
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deleteCookie (that, tableName, cookieName) {
|
||||||
|
cookieName = `${tableName}.${cookieName}`
|
||||||
|
|
||||||
|
switch (that.options.cookieStorage) {
|
||||||
|
case 'cookieStorage':
|
||||||
|
document.cookie = [
|
||||||
|
encodeURIComponent(cookieName), '=',
|
||||||
|
'; expires=Thu, 01 Jan 1970 00:00:00 GMT',
|
||||||
|
that.options.cookiePath ? `; path=${that.options.cookiePath}` : '',
|
||||||
|
that.options.cookieDomain ? `; domain=${that.options.cookieDomain}` : ''
|
||||||
|
].join('')
|
||||||
|
break
|
||||||
|
case 'localStorage':
|
||||||
|
localStorage.removeItem(cookieName)
|
||||||
|
break
|
||||||
|
case 'sessionStorage':
|
||||||
|
sessionStorage.removeItem(cookieName)
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
calculateExpiration (cookieExpire) {
|
||||||
|
const time = cookieExpire.replace(/[0-9]*/, '') // s,mi,h,d,m,y
|
||||||
|
cookieExpire = cookieExpire.replace(/[A-Za-z]{1,2}/, '') // number
|
||||||
|
|
||||||
|
switch (time.toLowerCase()) {
|
||||||
|
case 's':
|
||||||
|
cookieExpire = +cookieExpire
|
||||||
|
break
|
||||||
|
case 'mi':
|
||||||
|
cookieExpire *= 60
|
||||||
|
break
|
||||||
|
case 'h':
|
||||||
|
cookieExpire = cookieExpire * 60 * 60
|
||||||
|
break
|
||||||
|
case 'd':
|
||||||
|
cookieExpire = cookieExpire * 24 * 60 * 60
|
||||||
|
break
|
||||||
|
case 'm':
|
||||||
|
cookieExpire = cookieExpire * 30 * 24 * 60 * 60
|
||||||
|
break
|
||||||
|
case 'y':
|
||||||
|
cookieExpire = cookieExpire * 365 * 24 * 60 * 60
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
cookieExpire = undefined
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if (!cookieExpire) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
const d = new Date()
|
||||||
|
d.setTime(d.getTime() + cookieExpire * 1000)
|
||||||
|
return d.toGMTString()
|
||||||
|
},
|
||||||
|
initCookieFilters (bootstrapTable) {
|
||||||
|
setTimeout(() => {
|
||||||
|
const parsedCookieFilters = JSON.parse(UtilsCookie.getCookie(bootstrapTable, bootstrapTable.options.cookieIdTable, UtilsCookie.cookieIds.filterControl))
|
||||||
|
|
||||||
|
if (!bootstrapTable.options.filterControlValuesLoaded && parsedCookieFilters) {
|
||||||
|
|
||||||
|
const cachedFilters = {}
|
||||||
|
const header = UtilsCookie.getCurrentHeader(bootstrapTable)
|
||||||
|
const searchControls = UtilsCookie.getCurrentSearchControls(bootstrapTable)
|
||||||
|
|
||||||
|
const applyCookieFilters = (element, filteredCookies) => {
|
||||||
|
$(filteredCookies).each((i, cookie) => {
|
||||||
|
if (cookie.text !== '') {
|
||||||
|
$(element).val(cookie.text)
|
||||||
|
cachedFilters[cookie.field] = cookie.text
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
header.find(searchControls).each(function () {
|
||||||
|
const field = $(this).closest('[data-field]').data('field')
|
||||||
|
const filteredCookies = parsedCookieFilters.filter(cookie => cookie.field === field)
|
||||||
|
|
||||||
|
applyCookieFilters(this, filteredCookies)
|
||||||
|
})
|
||||||
|
|
||||||
|
bootstrapTable.initColumnSearch(cachedFilters)
|
||||||
|
bootstrapTable.options.filterControlValuesLoaded = true
|
||||||
|
bootstrapTable.initServer()
|
||||||
|
}
|
||||||
|
}, 250)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, {
|
||||||
|
cookie: false,
|
||||||
|
cookieExpire: '2h',
|
||||||
|
cookiePath: null,
|
||||||
|
cookieDomain: null,
|
||||||
|
cookieSecure: null,
|
||||||
|
cookieIdTable: '',
|
||||||
|
cookiesEnabled: [
|
||||||
|
'bs.table.sortOrder', 'bs.table.sortName',
|
||||||
|
'bs.table.pageNumber', 'bs.table.pageList',
|
||||||
|
'bs.table.columns', 'bs.table.searchText',
|
||||||
|
'bs.table.filterControl', 'bs.table.filterBy'
|
||||||
|
],
|
||||||
|
cookieStorage: 'cookieStorage', // localStorage, sessionStorage
|
||||||
|
// internal variable
|
||||||
|
filterControls: [],
|
||||||
|
filterControlValuesLoaded: false
|
||||||
|
})
|
||||||
|
|
||||||
|
$.fn.bootstrapTable.methods.push('getCookies')
|
||||||
|
$.fn.bootstrapTable.methods.push('deleteCookie')
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.utils, {
|
||||||
|
setCookie: UtilsCookie.setCookie,
|
||||||
|
getCookie: UtilsCookie.getCookie
|
||||||
|
})
|
||||||
|
|
||||||
|
$.BootstrapTable = class extends $.BootstrapTable {
|
||||||
|
init () {
|
||||||
|
// FilterBy logic
|
||||||
|
const filterByCookie = JSON.parse(UtilsCookie.getCookie(this, this.options.cookieIdTable, UtilsCookie.cookieIds.filterBy))
|
||||||
|
this.filterColumns = filterByCookie ? filterByCookie : {}
|
||||||
|
|
||||||
|
// FilterControl logic
|
||||||
|
this.options.filterControls = []
|
||||||
|
this.options.filterControlValuesLoaded = false
|
||||||
|
|
||||||
|
this.options.cookiesEnabled = typeof this.options.cookiesEnabled === 'string' ?
|
||||||
|
this.options.cookiesEnabled.replace('[', '').replace(']', '')
|
||||||
|
.replace(/ /g, '').toLowerCase().split(',') :
|
||||||
|
this.options.cookiesEnabled
|
||||||
|
|
||||||
|
if (this.options.filterControl) {
|
||||||
|
const that = this
|
||||||
|
this.$el.on('column-search.bs.table', (e, field, text) => {
|
||||||
|
let isNewField = true
|
||||||
|
|
||||||
|
for (let i = 0; i < that.options.filterControls.length; i++) {
|
||||||
|
if (that.options.filterControls[i].field === field) {
|
||||||
|
that.options.filterControls[i].text = text
|
||||||
|
isNewField = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isNewField) {
|
||||||
|
that.options.filterControls.push({
|
||||||
|
field,
|
||||||
|
text
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
UtilsCookie.setCookie(that, UtilsCookie.cookieIds.filterControl, JSON.stringify(that.options.filterControls))
|
||||||
|
}).on('created-controls.bs.table', UtilsCookie.initCookieFilters(that))
|
||||||
|
}
|
||||||
|
super.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
initServer (...args) {
|
||||||
|
if (
|
||||||
|
this.options.cookie &&
|
||||||
|
this.options.filterControl &&
|
||||||
|
!this.options.filterControlValuesLoaded
|
||||||
|
) {
|
||||||
|
const cookie = JSON.parse(UtilsCookie.getCookie(this, this.options.cookieIdTable, UtilsCookie.cookieIds.filterControl))
|
||||||
|
if (cookie) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.initServer(...args)
|
||||||
|
}
|
||||||
|
|
||||||
|
initTable (...args) {
|
||||||
|
super.initTable(...args)
|
||||||
|
this.initCookie()
|
||||||
|
}
|
||||||
|
|
||||||
|
onSort (...args) {
|
||||||
|
super.onSort(...args)
|
||||||
|
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.sortOrder, this.options.sortOrder)
|
||||||
|
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.sortName, this.options.sortName)
|
||||||
|
}
|
||||||
|
|
||||||
|
onPageNumber (...args) {
|
||||||
|
super.onPageNumber(...args)
|
||||||
|
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber)
|
||||||
|
}
|
||||||
|
|
||||||
|
onPageListChange (...args) {
|
||||||
|
super.onPageListChange(...args)
|
||||||
|
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageList, this.options.pageSize)
|
||||||
|
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber)
|
||||||
|
}
|
||||||
|
|
||||||
|
onPagePre (...args) {
|
||||||
|
super.onPagePre(...args)
|
||||||
|
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber)
|
||||||
|
}
|
||||||
|
|
||||||
|
onPageNext (...args) {
|
||||||
|
super.onPageNext(...args)
|
||||||
|
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber)
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleColumn (...args) {
|
||||||
|
super.toggleColumn(...args)
|
||||||
|
|
||||||
|
const visibleColumns = []
|
||||||
|
|
||||||
|
$.each(this.columns, (i, column) => {
|
||||||
|
if (column.visible) {
|
||||||
|
visibleColumns.push(column.field)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.columns, JSON.stringify(visibleColumns))
|
||||||
|
}
|
||||||
|
|
||||||
|
selectPage (page) {
|
||||||
|
super.selectPage(page)
|
||||||
|
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, page)
|
||||||
|
}
|
||||||
|
|
||||||
|
onSearch (event) {
|
||||||
|
super.onSearch(event)
|
||||||
|
|
||||||
|
if ($(event.currentTarget).parent().hasClass('search')) {
|
||||||
|
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.searchText, this.searchText)
|
||||||
|
}
|
||||||
|
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber)
|
||||||
|
}
|
||||||
|
|
||||||
|
filterBy (...args) {
|
||||||
|
super.filterBy(...args)
|
||||||
|
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.filterBy, JSON.stringify(this.filterColumns))
|
||||||
|
}
|
||||||
|
|
||||||
|
initCookie () {
|
||||||
|
if (!this.options.cookie) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((this.options.cookieIdTable === '') || (this.options.cookieExpire === '') || (!UtilsCookie.cookieEnabled())) {
|
||||||
|
console.error('Configuration error. Please review the cookieIdTable and the cookieExpire property. If the properties are correct, then this browser does not support cookies.')
|
||||||
|
this.options.cookie = false // Make sure that the cookie extension is disabled
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const sortOrderCookie = UtilsCookie.getCookie(this, this.options.cookieIdTable, UtilsCookie.cookieIds.sortOrder)
|
||||||
|
const sortOrderNameCookie = UtilsCookie.getCookie(this, this.options.cookieIdTable, UtilsCookie.cookieIds.sortName)
|
||||||
|
const pageNumberCookie = UtilsCookie.getCookie(this, this.options.cookieIdTable, UtilsCookie.cookieIds.pageNumber)
|
||||||
|
const pageListCookie = UtilsCookie.getCookie(this, this.options.cookieIdTable, UtilsCookie.cookieIds.pageList)
|
||||||
|
const columnsCookie = JSON.parse(UtilsCookie.getCookie(this, this.options.cookieIdTable, UtilsCookie.cookieIds.columns))
|
||||||
|
const searchTextCookie = UtilsCookie.getCookie(this, this.options.cookieIdTable, UtilsCookie.cookieIds.searchText)
|
||||||
|
|
||||||
|
// sortOrder
|
||||||
|
this.options.sortOrder = sortOrderCookie ? sortOrderCookie : this.options.sortOrder
|
||||||
|
// sortName
|
||||||
|
this.options.sortName = sortOrderNameCookie ? sortOrderNameCookie : this.options.sortName
|
||||||
|
// pageNumber
|
||||||
|
this.options.pageNumber = pageNumberCookie ? +pageNumberCookie : this.options.pageNumber
|
||||||
|
// pageSize
|
||||||
|
this.options.pageSize = pageListCookie ? pageListCookie === this.options.formatAllRows() ? pageListCookie : +pageListCookie : this.options.pageSize
|
||||||
|
// searchText
|
||||||
|
this.options.searchText = searchTextCookie ? searchTextCookie : ''
|
||||||
|
|
||||||
|
if (columnsCookie) {
|
||||||
|
$.each(this.columns, (i, column) => {
|
||||||
|
column.visible = $.inArray(column.field, columnsCookie) !== -1
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getCookies () {
|
||||||
|
const bootstrapTable = this
|
||||||
|
const cookies = {}
|
||||||
|
$.each(UtilsCookie.cookieIds, (key, value) => {
|
||||||
|
cookies[key] = UtilsCookie.getCookie(bootstrapTable, bootstrapTable.options.cookieIdTable, value)
|
||||||
|
if (key === 'columns') {
|
||||||
|
cookies[key] = JSON.parse(cookies[key])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return cookies
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteCookie (cookieName) {
|
||||||
|
if ((cookieName === '') || (!UtilsCookie.cookieEnabled())) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
UtilsCookie.deleteCookie(this, this.options.cookieIdTable, UtilsCookie.cookieIds[cookieName])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
})(jQuery)
|
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "Cookie",
|
||||||
|
"version": "1.2.1",
|
||||||
|
"description": "Plugin to use the cookie of the browser.",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/cookie",
|
||||||
|
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/cookie.html",
|
||||||
|
|
||||||
|
"plugins": [{
|
||||||
|
"name": "bootstrap-table-cookie",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/cookie"
|
||||||
|
}],
|
||||||
|
|
||||||
|
"author": {
|
||||||
|
"name": "djhvscf",
|
||||||
|
"image": "https://avatars1.githubusercontent.com/u/4496763"
|
||||||
|
}
|
||||||
|
}
|
102
InvenTree/InvenTree/static/bootstrap-table/extensions/copy-rows/bootstrap-table-copy-rows.js
vendored
Normal file
102
InvenTree/InvenTree/static/bootstrap-table/extensions/copy-rows/bootstrap-table-copy-rows.js
vendored
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
/**
|
||||||
|
* @author Homer Glascock <HopGlascock@gmail.com>
|
||||||
|
* @version: v1.0.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
!function ($) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var calculateObjectValue = $.fn.bootstrapTable.utils.calculateObjectValue,
|
||||||
|
sprintf = $.fn.bootstrapTable.utils.sprintf;
|
||||||
|
|
||||||
|
var copytext = function (text) {
|
||||||
|
var textField = document.createElement('textarea');
|
||||||
|
$(textField).html(text);
|
||||||
|
document.body.appendChild(textField);
|
||||||
|
textField.select();
|
||||||
|
|
||||||
|
try {
|
||||||
|
document.execCommand('copy');
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
console.log("Oops, unable to copy");
|
||||||
|
}
|
||||||
|
$(textField).remove();
|
||||||
|
};
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, {
|
||||||
|
copyBtn: false,
|
||||||
|
copyWHiddenBtn: false,
|
||||||
|
copyDelemeter: ", "
|
||||||
|
});
|
||||||
|
|
||||||
|
$.fn.bootstrapTable.methods.push('copyColumnsToClipboard', 'copyColumnsToClipboardWithHidden');
|
||||||
|
|
||||||
|
var BootstrapTable = $.fn.bootstrapTable.Constructor,
|
||||||
|
_initToolbar = BootstrapTable.prototype.initToolbar;
|
||||||
|
|
||||||
|
BootstrapTable.prototype.initToolbar = function () {
|
||||||
|
|
||||||
|
_initToolbar.apply(this, Array.prototype.slice.apply(arguments));
|
||||||
|
|
||||||
|
var that = this,
|
||||||
|
$btnGroup = this.$toolbar.find('>.btn-group');
|
||||||
|
|
||||||
|
if (this.options.clickToSelect || this.options.singleSelect) {
|
||||||
|
|
||||||
|
if (this.options.copyBtn) {
|
||||||
|
var copybtn = "<button class='btn btn-default' id='copyBtn'><span class='glyphicon glyphicon-copy icon-pencil'></span></button>";
|
||||||
|
$btnGroup.append(copybtn);
|
||||||
|
$btnGroup.find('#copyBtn').click(function () { that.copyColumnsToClipboard(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.options.copyWHiddenBtn) {
|
||||||
|
var copyhiddenbtn = "<button class='btn btn-default' id='copyWHiddenBtn'><span class='badge'><span class='glyphicon glyphicon-copy icon-pencil'></span></span></button>";
|
||||||
|
$btnGroup.append(copyhiddenbtn);
|
||||||
|
$btnGroup.find('#copyWHiddenBtn').click(function () { that.copyColumnsToClipboardWithHidden(); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.copyColumnsToClipboard = function () {
|
||||||
|
var that = this,
|
||||||
|
ret = "",
|
||||||
|
delimet = this.options.copyDelemeter;
|
||||||
|
|
||||||
|
$.each(that.getSelections(), function (index, row) {
|
||||||
|
$.each(that.options.columns[0], function (indy, column) {
|
||||||
|
if (column.field !== "state" && column.field !== "RowNumber" && column.visible) {
|
||||||
|
if (row[column.field] !== null) {
|
||||||
|
ret += calculateObjectValue(column, that.header.formatters[indy], [row[column.field], row, index], row[column.field]);
|
||||||
|
}
|
||||||
|
ret += delimet;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ret += "\r\n";
|
||||||
|
});
|
||||||
|
|
||||||
|
copytext(ret);
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.copyColumnsToClipboardWithHidden = function () {
|
||||||
|
var that = this,
|
||||||
|
ret = "",
|
||||||
|
delimet = this.options.copyDelemeter;
|
||||||
|
|
||||||
|
$.each(that.getSelections(), function (index, row) {
|
||||||
|
$.each(that.options.columns[0], function (indy, column) {
|
||||||
|
if (column.field != "state" && column.field !== "RowNumber") {
|
||||||
|
if (row[column.field] !== null) {
|
||||||
|
ret += calculateObjectValue(column, that.header.formatters[indy], [row[column.field], row, index], row[column.field]);
|
||||||
|
}
|
||||||
|
ret += delimet;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ret += "\r\n";
|
||||||
|
});
|
||||||
|
|
||||||
|
copytext(ret);
|
||||||
|
};
|
||||||
|
}(jQuery);
|
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "Copy Rows",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Allows pushing of selected column data to the clipboard.",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/copy-rows",
|
||||||
|
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/copy-rows.html",
|
||||||
|
|
||||||
|
"plugins": [{
|
||||||
|
"name": "copy-rows",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/copy-rows"
|
||||||
|
}],
|
||||||
|
|
||||||
|
"author": {
|
||||||
|
"name": "Homer Glascock",
|
||||||
|
"image": "https://avatars1.githubusercontent.com/u/5546710"
|
||||||
|
}
|
||||||
|
}
|
32
InvenTree/InvenTree/static/bootstrap-table/extensions/defer-url/bootstrap-table-defer-url.js
vendored
Normal file
32
InvenTree/InvenTree/static/bootstrap-table/extensions/defer-url/bootstrap-table-defer-url.js
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* When using server-side processing, the default mode of operation for
|
||||||
|
* bootstrap-table is to simply throw away any data that currently exists in the
|
||||||
|
* table and make a request to the server to get the first page of data to
|
||||||
|
* display. This is fine for an empty table, but if you already have the first
|
||||||
|
* page of data displayed in the plain HTML, it is a waste of resources. As
|
||||||
|
* such, you can use data-defer-url instead of data-url to allow you to instruct
|
||||||
|
* bootstrap-table to not make that initial request, rather it will use the data
|
||||||
|
* already on the page.
|
||||||
|
*
|
||||||
|
* @author: Ruben Suarez
|
||||||
|
* @webSite: http://rubensa.eu.org
|
||||||
|
* @version: v1.0.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function($) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, {
|
||||||
|
deferUrl : undefined
|
||||||
|
});
|
||||||
|
|
||||||
|
var BootstrapTable = $.fn.bootstrapTable.Constructor, _init = BootstrapTable.prototype.init;
|
||||||
|
|
||||||
|
BootstrapTable.prototype.init = function() {
|
||||||
|
_init.apply(this, Array.prototype.slice.apply(arguments));
|
||||||
|
|
||||||
|
if (this.options.deferUrl) {
|
||||||
|
this.options.url = this.options.deferUrl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})(jQuery);
|
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "DeferURL",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Plugin to defer server side processing.",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/defer-url",
|
||||||
|
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/defer-url.html",
|
||||||
|
|
||||||
|
"plugins": [{
|
||||||
|
"name": "bootstrap-table-defer-url",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/defer-url"
|
||||||
|
}],
|
||||||
|
|
||||||
|
"author": {
|
||||||
|
"name": "rubensa",
|
||||||
|
"image": "https://avatars1.githubusercontent.com/u/1469340"
|
||||||
|
}
|
||||||
|
}
|
149
InvenTree/InvenTree/static/bootstrap-table/extensions/editable/bootstrap-table-editable.js
vendored
Normal file
149
InvenTree/InvenTree/static/bootstrap-table/extensions/editable/bootstrap-table-editable.js
vendored
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
/**
|
||||||
|
* @author zhixin wen <wenzhixin2010@gmail.com>
|
||||||
|
* extensions: https://github.com/vitalets/x-editable
|
||||||
|
*/
|
||||||
|
|
||||||
|
($ => {
|
||||||
|
const Utils = $.fn.bootstrapTable.utils
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, {
|
||||||
|
editable: true,
|
||||||
|
onEditableInit () {
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
onEditableSave (field, row, oldValue, $el) {
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
onEditableShown (field, row, $el, editable) {
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
onEditableHidden (field, row, $el, reason) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.Constructor.EVENTS, {
|
||||||
|
'editable-init.bs.table': 'onEditableInit',
|
||||||
|
'editable-save.bs.table': 'onEditableSave',
|
||||||
|
'editable-shown.bs.table': 'onEditableShown',
|
||||||
|
'editable-hidden.bs.table': 'onEditableHidden'
|
||||||
|
})
|
||||||
|
|
||||||
|
$.BootstrapTable = class extends $.BootstrapTable {
|
||||||
|
initTable () {
|
||||||
|
super.initTable()
|
||||||
|
|
||||||
|
if (!this.options.editable) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
$.each(this.columns, (i, column) => {
|
||||||
|
if (!column.editable) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const editableOptions = {}
|
||||||
|
const editableDataMarkup = []
|
||||||
|
const editableDataPrefix = 'editable-'
|
||||||
|
const processDataOptions = (key, value) => {
|
||||||
|
// Replace camel case with dashes.
|
||||||
|
const dashKey = key.replace(/([A-Z])/g, $1 => `-${$1.toLowerCase()}`)
|
||||||
|
if (dashKey.indexOf(editableDataPrefix) === 0) {
|
||||||
|
editableOptions[dashKey.replace(editableDataPrefix, 'data-')] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$.each(this.options, processDataOptions)
|
||||||
|
|
||||||
|
column.formatter = column.formatter || (value => value)
|
||||||
|
column._formatter = column._formatter ? column._formatter : column.formatter
|
||||||
|
column.formatter = (value, row, index) => {
|
||||||
|
const result = Utils.calculateObjectValue(column,
|
||||||
|
column._formatter, [value, row, index], value)
|
||||||
|
|
||||||
|
$.each(column, processDataOptions)
|
||||||
|
|
||||||
|
$.each(editableOptions, (key, value) => {
|
||||||
|
editableDataMarkup.push(` ${key}="${value}"`)
|
||||||
|
})
|
||||||
|
|
||||||
|
let _dont_edit_formatter = false
|
||||||
|
if (column.editable.hasOwnProperty('noeditFormatter')) {
|
||||||
|
_dont_edit_formatter = column.editable.noeditFormatter(value, row, index)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_dont_edit_formatter === false) {
|
||||||
|
return `<a href="javascript:void(0)"
|
||||||
|
data-name="${column.field}"
|
||||||
|
data-pk="${row[this.options.idField]}"
|
||||||
|
data-value="${result}"
|
||||||
|
${editableDataMarkup.join('')}></a>`
|
||||||
|
}
|
||||||
|
return _dont_edit_formatter
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
initBody (fixedScroll) {
|
||||||
|
super.initBody(fixedScroll)
|
||||||
|
|
||||||
|
if (!this.options.editable) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
$.each(this.columns, (i, column) => {
|
||||||
|
if (!column.editable) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = this.getData()
|
||||||
|
const $field = this.$body.find(`a[data-name="${column.field}"]`)
|
||||||
|
|
||||||
|
$field.each((i, element) => {
|
||||||
|
const $element = $(element)
|
||||||
|
const $tr = $element.closest('tr')
|
||||||
|
const index = $tr.data('index')
|
||||||
|
const row = data[index]
|
||||||
|
|
||||||
|
const editableOpts = Utils.calculateObjectValue(column,
|
||||||
|
column.editable, [index, row, $element], {})
|
||||||
|
|
||||||
|
$element.editable(editableOpts)
|
||||||
|
})
|
||||||
|
|
||||||
|
$field.off('save').on('save', ({currentTarget}, {submitValue}) => {
|
||||||
|
const $this = $(currentTarget)
|
||||||
|
const data = this.getData()
|
||||||
|
const index = $this.parents('tr[data-index]').data('index')
|
||||||
|
const row = data[index]
|
||||||
|
const oldValue = row[column.field]
|
||||||
|
|
||||||
|
$this.data('value', submitValue)
|
||||||
|
row[column.field] = submitValue
|
||||||
|
this.trigger('editable-save', column.field, row, oldValue, $this)
|
||||||
|
this.resetFooter()
|
||||||
|
})
|
||||||
|
|
||||||
|
$field.off('shown').on('shown', ({currentTarget}, editable) => {
|
||||||
|
const $this = $(currentTarget)
|
||||||
|
const data = this.getData()
|
||||||
|
const index = $this.parents('tr[data-index]').data('index')
|
||||||
|
const row = data[index]
|
||||||
|
|
||||||
|
this.trigger('editable-shown', column.field, row, $this, editable)
|
||||||
|
})
|
||||||
|
|
||||||
|
$field.off('hidden').on('hidden', ({currentTarget}, reason) => {
|
||||||
|
const $this = $(currentTarget)
|
||||||
|
const data = this.getData()
|
||||||
|
const index = $this.parents('tr[data-index]').data('index')
|
||||||
|
const row = data[index]
|
||||||
|
|
||||||
|
this.trigger('editable-hidden', column.field, row, $this, reason)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
this.trigger('editable-init')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
})(jQuery)
|
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "Table Editable",
|
||||||
|
"version": "1.1.0",
|
||||||
|
"description": "Use the x-editable to in-place editing your table.",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/editable",
|
||||||
|
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/editable.html",
|
||||||
|
|
||||||
|
"plugins": [{
|
||||||
|
"name": "x-editable",
|
||||||
|
"url": "https://github.com/vitalets/x-editable"
|
||||||
|
}],
|
||||||
|
|
||||||
|
"author": {
|
||||||
|
"name": "wenzhixin",
|
||||||
|
"image": "https://avatars1.githubusercontent.com/u/2117018"
|
||||||
|
}
|
||||||
|
}
|
225
InvenTree/InvenTree/static/bootstrap-table/extensions/export/bootstrap-table-export.js
vendored
Normal file
225
InvenTree/InvenTree/static/bootstrap-table/extensions/export/bootstrap-table-export.js
vendored
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
/**
|
||||||
|
* @author zhixin wen <wenzhixin2010@gmail.com>
|
||||||
|
* extensions: https://github.com/hhurz/tableExport.jquery.plugin
|
||||||
|
*/
|
||||||
|
|
||||||
|
($ => {
|
||||||
|
const Utils = $.fn.bootstrapTable.utils
|
||||||
|
|
||||||
|
const bootstrap = {
|
||||||
|
3: {
|
||||||
|
icons: {
|
||||||
|
export: 'glyphicon-export icon-share'
|
||||||
|
},
|
||||||
|
html: {
|
||||||
|
dropmenu: '<ul class="dropdown-menu" role="menu"></ul>',
|
||||||
|
dropitem: '<li role="menuitem" data-type="%s"><a href="javascript:">%s</a></li>'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
4: {
|
||||||
|
icons: {
|
||||||
|
export: 'fa-download'
|
||||||
|
},
|
||||||
|
html: {
|
||||||
|
dropmenu: '<div class="dropdown-menu dropdown-menu-right"></div>',
|
||||||
|
dropitem: '<a class="dropdown-item" data-type="%s" href="javascript:">%s</a>'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}[Utils.bootstrapVersion]
|
||||||
|
|
||||||
|
const TYPE_NAME = {
|
||||||
|
json: 'JSON',
|
||||||
|
xml: 'XML',
|
||||||
|
png: 'PNG',
|
||||||
|
csv: 'CSV',
|
||||||
|
txt: 'TXT',
|
||||||
|
sql: 'SQL',
|
||||||
|
doc: 'MS-Word',
|
||||||
|
excel: 'MS-Excel',
|
||||||
|
xlsx: 'MS-Excel (OpenXML)',
|
||||||
|
powerpoint: 'MS-Powerpoint',
|
||||||
|
pdf: 'PDF'
|
||||||
|
}
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, {
|
||||||
|
showExport: false,
|
||||||
|
exportDataType: 'basic', // basic, all, selected
|
||||||
|
exportTypes: ['json', 'xml', 'csv', 'txt', 'sql', 'excel'],
|
||||||
|
exportOptions: {},
|
||||||
|
exportFooter: false
|
||||||
|
})
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults.icons, {
|
||||||
|
export: bootstrap.icons.export
|
||||||
|
})
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.locales, {
|
||||||
|
formatExport () {
|
||||||
|
return 'Export data'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales)
|
||||||
|
|
||||||
|
$.fn.bootstrapTable.methods.push('exportTable')
|
||||||
|
|
||||||
|
$.BootstrapTable = class extends $.BootstrapTable {
|
||||||
|
initToolbar () {
|
||||||
|
const o = this.options
|
||||||
|
|
||||||
|
this.showToolbar = this.showToolbar || o.showExport
|
||||||
|
|
||||||
|
super.initToolbar()
|
||||||
|
|
||||||
|
if (!this.options.showExport) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const $btnGroup = this.$toolbar.find('>.btn-group')
|
||||||
|
this.$export = $btnGroup.find('div.export')
|
||||||
|
|
||||||
|
if (this.$export.length) {
|
||||||
|
this.updateExportButton()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.$export = $(`
|
||||||
|
<div class="export btn-group">
|
||||||
|
<button class="btn btn-${o.buttonsClass} btn-${o.iconSize} dropdown-toggle"
|
||||||
|
aria-label="export type"
|
||||||
|
title="${o.formatExport()}"
|
||||||
|
data-toggle="dropdown"
|
||||||
|
type="button">
|
||||||
|
<i class="${o.iconsPrefix} ${o.icons.export}"></i>
|
||||||
|
<span class="caret"></span>
|
||||||
|
</button>
|
||||||
|
${bootstrap.html.dropmenu}
|
||||||
|
</div>
|
||||||
|
`).appendTo($btnGroup)
|
||||||
|
|
||||||
|
this.updateExportButton()
|
||||||
|
|
||||||
|
const $menu = this.$export.find('.dropdown-menu')
|
||||||
|
let exportTypes = o.exportTypes
|
||||||
|
|
||||||
|
if (typeof exportTypes === 'string') {
|
||||||
|
const types = exportTypes.slice(1, -1).replace(/ /g, '').split(',')
|
||||||
|
exportTypes = types.map(t => t.slice(1, -1))
|
||||||
|
}
|
||||||
|
for (const type of exportTypes) {
|
||||||
|
if (TYPE_NAME.hasOwnProperty(type)) {
|
||||||
|
$menu.append(Utils.sprintf(bootstrap.html.dropitem, type, TYPE_NAME[type]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$menu.find('>li, >a').click(({currentTarget}) => {
|
||||||
|
const type = $(currentTarget).data('type')
|
||||||
|
const exportOptions = {
|
||||||
|
type,
|
||||||
|
escape: false
|
||||||
|
}
|
||||||
|
|
||||||
|
this.exportTable(exportOptions)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
exportTable (options) {
|
||||||
|
const o = this.options
|
||||||
|
const stateField = this.header.stateField
|
||||||
|
const isCardView = o.cardView
|
||||||
|
|
||||||
|
const doExport = callback => {
|
||||||
|
if (stateField) {
|
||||||
|
this.hideColumn(stateField)
|
||||||
|
}
|
||||||
|
if (isCardView) {
|
||||||
|
this.toggleView()
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = this.getData()
|
||||||
|
if (o.exportFooter) {
|
||||||
|
const $footerRow = this.$tableFooter.find('tr').first()
|
||||||
|
const footerData = {}
|
||||||
|
const footerHtml = []
|
||||||
|
|
||||||
|
$.each($footerRow.children(), (index, footerCell) => {
|
||||||
|
const footerCellHtml = $(footerCell).children('.th-inner').first().html()
|
||||||
|
footerData[this.columns[index].field] = footerCellHtml === ' ' ? null : footerCellHtml
|
||||||
|
|
||||||
|
// grab footer cell text into cell index-based array
|
||||||
|
footerHtml.push(footerCellHtml)
|
||||||
|
})
|
||||||
|
|
||||||
|
this.append(footerData)
|
||||||
|
|
||||||
|
const $lastTableRow = this.$body.children().last()
|
||||||
|
|
||||||
|
$.each($lastTableRow.children(), (index, lastTableRowCell) => {
|
||||||
|
$(lastTableRowCell).html(footerHtml[index])
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$el.tableExport($.extend({
|
||||||
|
onAfterSaveToFile: () => {
|
||||||
|
if (o.exportFooter) {
|
||||||
|
this.load(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stateField) {
|
||||||
|
this.showColumn(stateField)
|
||||||
|
}
|
||||||
|
if (isCardView) {
|
||||||
|
this.toggleView()
|
||||||
|
}
|
||||||
|
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}, o.exportOptions, options))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (o.exportDataType === 'all' && o.pagination) {
|
||||||
|
const eventName = o.sidePagination === 'server'
|
||||||
|
? 'post-body.bs.table' : 'page-change.bs.table'
|
||||||
|
this.$el.one(eventName, () => {
|
||||||
|
doExport(() => {
|
||||||
|
this.togglePagination()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
this.togglePagination()
|
||||||
|
} else if (o.exportDataType === 'selected') {
|
||||||
|
let data = this.getData()
|
||||||
|
let selectedData = this.getSelections()
|
||||||
|
if (!selectedData.length) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (o.sidePagination === 'server') {
|
||||||
|
data = {
|
||||||
|
total: o.totalRows,
|
||||||
|
[this.options.dataField]: data
|
||||||
|
}
|
||||||
|
selectedData = {
|
||||||
|
total: selectedData.length,
|
||||||
|
[this.options.dataField]: selectedData
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.load(selectedData)
|
||||||
|
doExport(() => {
|
||||||
|
this.load(data)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
doExport()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateSelected () {
|
||||||
|
super.updateSelected()
|
||||||
|
this.updateExportButton()
|
||||||
|
}
|
||||||
|
|
||||||
|
updateExportButton () {
|
||||||
|
if (this.options.exportDataType === 'selected') {
|
||||||
|
this.$export.find('> button')
|
||||||
|
.prop('disabled', !this.getSelections().length)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})(jQuery)
|
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "Table Export",
|
||||||
|
"version": "1.1.0",
|
||||||
|
"description": "Export your table data to JSON, XML, CSV, TXT, SQL, Word, Excel, PNG, PDF.",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/export",
|
||||||
|
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/export.html",
|
||||||
|
|
||||||
|
"plugins": [{
|
||||||
|
"name": "tableExport.jquery.plugin",
|
||||||
|
"url": "https://github.com/hhurz/tableExport.jquery.plugin"
|
||||||
|
}],
|
||||||
|
|
||||||
|
"author": {
|
||||||
|
"name": "wenzhixin",
|
||||||
|
"image": "https://avatars1.githubusercontent.com/u/2117018"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* @author: Dennis Hernández
|
||||||
|
* @webSite: http://djhvscf.github.io/Blog
|
||||||
|
* @version: v2.1.1
|
||||||
|
*/
|
||||||
|
|
||||||
|
.no-filter-control {
|
||||||
|
height: 34px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-control {
|
||||||
|
margin: 0 2px 2px 2px;
|
||||||
|
}
|
@ -0,0 +1,917 @@
|
|||||||
|
/**
|
||||||
|
* @author: Dennis Hernández
|
||||||
|
* @webSite: http://djhvscf.github.io/Blog
|
||||||
|
* @version: v2.2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
($ => {
|
||||||
|
const Utils = $.fn.bootstrapTable.utils
|
||||||
|
const UtilsFilterControl = {
|
||||||
|
getOptionsFromSelectControl (selectControl) {
|
||||||
|
return selectControl.get(selectControl.length - 1).options
|
||||||
|
},
|
||||||
|
|
||||||
|
hideUnusedSelectOptions (selectControl, uniqueValues) {
|
||||||
|
const options = UtilsFilterControl.getOptionsFromSelectControl(
|
||||||
|
selectControl
|
||||||
|
)
|
||||||
|
|
||||||
|
for (let i = 0; i < options.length; i++) {
|
||||||
|
if (options[i].value !== '') {
|
||||||
|
if (!uniqueValues.hasOwnProperty(options[i].value)) {
|
||||||
|
selectControl
|
||||||
|
.find(Utils.sprintf('option[value=\'%s\']', options[i].value))
|
||||||
|
.hide()
|
||||||
|
} else {
|
||||||
|
selectControl
|
||||||
|
.find(Utils.sprintf('option[value=\'%s\']', options[i].value))
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
addOptionToSelectControl (selectControl, _value, text) {
|
||||||
|
const value = $.trim(_value)
|
||||||
|
const $selectControl = $(selectControl.get(selectControl.length - 1))
|
||||||
|
if (
|
||||||
|
!UtilsFilterControl.existOptionInSelectControl(selectControl, value)
|
||||||
|
) {
|
||||||
|
$selectControl.append(
|
||||||
|
$('<option></option>')
|
||||||
|
.attr('value', value)
|
||||||
|
.text(
|
||||||
|
$('<div />')
|
||||||
|
.html(text)
|
||||||
|
.text()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
sortSelectControl (selectControl) {
|
||||||
|
const $selectControl = $(selectControl.get(selectControl.length - 1))
|
||||||
|
const $opts = $selectControl.find('option:gt(0)')
|
||||||
|
|
||||||
|
$opts.sort((a, b) => {
|
||||||
|
let aa = $(a).text().toLowerCase()
|
||||||
|
let bb = $(b).text().toLowerCase()
|
||||||
|
if ($.isNumeric(a) && $.isNumeric(b)) {
|
||||||
|
// Convert numerical values from string to float.
|
||||||
|
aa = parseFloat(aa)
|
||||||
|
bb = parseFloat(bb)
|
||||||
|
}
|
||||||
|
return aa > bb ? 1 : aa < bb ? -1 : 0
|
||||||
|
})
|
||||||
|
|
||||||
|
$selectControl.find('option:gt(0)').remove()
|
||||||
|
$selectControl.append($opts)
|
||||||
|
},
|
||||||
|
existOptionInSelectControl (selectControl, value) {
|
||||||
|
const options = UtilsFilterControl.getOptionsFromSelectControl(
|
||||||
|
selectControl
|
||||||
|
)
|
||||||
|
for (let i = 0; i < options.length; i++) {
|
||||||
|
if (options[i].value === value.toString()) {
|
||||||
|
// The value is not valid to add
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we get here, the value is valid to add
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
fixHeaderCSS ({ $tableHeader }) {
|
||||||
|
$tableHeader.css('height', '77px')
|
||||||
|
},
|
||||||
|
getCurrentHeader ({ $header, options, $tableHeader }) {
|
||||||
|
let header = $header
|
||||||
|
if (options.height) {
|
||||||
|
header = $tableHeader
|
||||||
|
}
|
||||||
|
|
||||||
|
return header
|
||||||
|
},
|
||||||
|
getCurrentSearchControls ({ options }) {
|
||||||
|
let searchControls = 'select, input'
|
||||||
|
if (options.height) {
|
||||||
|
searchControls = 'table select, table input'
|
||||||
|
}
|
||||||
|
|
||||||
|
return searchControls
|
||||||
|
},
|
||||||
|
getCursorPosition (el) {
|
||||||
|
if (Utils.isIEBrowser()) {
|
||||||
|
if ($(el).is('input[type=text]')) {
|
||||||
|
let pos = 0
|
||||||
|
if ('selectionStart' in el) {
|
||||||
|
pos = el.selectionStart
|
||||||
|
} else if ('selection' in document) {
|
||||||
|
el.focus()
|
||||||
|
const Sel = document.selection.createRange()
|
||||||
|
const SelLength = document.selection.createRange().text.length
|
||||||
|
Sel.moveStart('character', -el.value.length)
|
||||||
|
pos = Sel.text.length - SelLength
|
||||||
|
}
|
||||||
|
return pos
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
},
|
||||||
|
setCursorPosition (el) {
|
||||||
|
$(el).val(el.value)
|
||||||
|
},
|
||||||
|
copyValues (that) {
|
||||||
|
const header = UtilsFilterControl.getCurrentHeader(that)
|
||||||
|
const searchControls = UtilsFilterControl.getCurrentSearchControls(that)
|
||||||
|
|
||||||
|
that.options.valuesFilterControl = []
|
||||||
|
|
||||||
|
header.find(searchControls).each(function () {
|
||||||
|
that.options.valuesFilterControl.push({
|
||||||
|
field: $(this)
|
||||||
|
.closest('[data-field]')
|
||||||
|
.data('field'),
|
||||||
|
value: $(this).val(),
|
||||||
|
position: UtilsFilterControl.getCursorPosition($(this).get(0)),
|
||||||
|
hasFocus: $(this).is(':focus')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
setValues (that) {
|
||||||
|
let field = null
|
||||||
|
let result = []
|
||||||
|
const header = UtilsFilterControl.getCurrentHeader(that)
|
||||||
|
const searchControls = UtilsFilterControl.getCurrentSearchControls(that)
|
||||||
|
|
||||||
|
if (that.options.valuesFilterControl.length > 0) {
|
||||||
|
// Callback to apply after settings fields values
|
||||||
|
let fieldToFocusCallback = null
|
||||||
|
header.find(searchControls).each(function (index, ele) {
|
||||||
|
field = $(this)
|
||||||
|
.closest('[data-field]')
|
||||||
|
.data('field')
|
||||||
|
result = that.options.valuesFilterControl.filter(valueObj => valueObj.field === field)
|
||||||
|
|
||||||
|
if (result.length > 0) {
|
||||||
|
$(this).val(result[0].value)
|
||||||
|
if (result[0].hasFocus) {
|
||||||
|
// set callback if the field had the focus.
|
||||||
|
fieldToFocusCallback = ((fieldToFocus, carretPosition) => {
|
||||||
|
// Closure here to capture the field and cursor position
|
||||||
|
const closedCallback = () => {
|
||||||
|
fieldToFocus.focus()
|
||||||
|
UtilsFilterControl.setCursorPosition(fieldToFocus, carretPosition)
|
||||||
|
}
|
||||||
|
return closedCallback
|
||||||
|
})($(this).get(0), result[0].position)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Callback call.
|
||||||
|
if (fieldToFocusCallback !== null) {
|
||||||
|
fieldToFocusCallback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
collectBootstrapCookies () {
|
||||||
|
const cookies = []
|
||||||
|
const foundCookies = document.cookie.match(/(?:bs.table.)(\w*)/g)
|
||||||
|
|
||||||
|
if (foundCookies) {
|
||||||
|
$.each(foundCookies, (i, _cookie) => {
|
||||||
|
let cookie = _cookie
|
||||||
|
if (/./.test(cookie)) {
|
||||||
|
cookie = cookie.split('.').pop()
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($.inArray(cookie, cookies) === -1) {
|
||||||
|
cookies.push(cookie)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return cookies
|
||||||
|
}
|
||||||
|
},
|
||||||
|
escapeID (id) {
|
||||||
|
return String(id).replace(/(:|\.|\[|\]|,)/g, '\\$1')
|
||||||
|
},
|
||||||
|
isColumnSearchableViaSelect ({ filterControl, searchable }) {
|
||||||
|
return filterControl &&
|
||||||
|
filterControl.toLowerCase() === 'select' &&
|
||||||
|
searchable
|
||||||
|
},
|
||||||
|
isFilterDataNotGiven ({ filterData }) {
|
||||||
|
return filterData === undefined ||
|
||||||
|
filterData.toLowerCase() === 'column'
|
||||||
|
},
|
||||||
|
hasSelectControlElement (selectControl) {
|
||||||
|
return selectControl && selectControl.length > 0
|
||||||
|
},
|
||||||
|
initFilterSelectControls (that) {
|
||||||
|
const data = that.data
|
||||||
|
const itemsPerPage = that.pageTo < that.options.data.length ? that.options.data.length : that.pageTo
|
||||||
|
const z = that.options.pagination
|
||||||
|
? that.options.sidePagination === 'server'
|
||||||
|
? that.pageTo
|
||||||
|
: that.options.totalRows
|
||||||
|
: that.pageTo
|
||||||
|
|
||||||
|
$.each(that.header.fields, (j, field) => {
|
||||||
|
const column = that.columns[that.fieldsColumnsIndex[field]]
|
||||||
|
const selectControl = $(`.bootstrap-table-filter-control-${UtilsFilterControl.escapeID(column.field)}`)
|
||||||
|
|
||||||
|
if (
|
||||||
|
UtilsFilterControl.isColumnSearchableViaSelect(column) &&
|
||||||
|
UtilsFilterControl.isFilterDataNotGiven(column) &&
|
||||||
|
UtilsFilterControl.hasSelectControlElement(selectControl)
|
||||||
|
) {
|
||||||
|
if (selectControl.get(selectControl.length - 1).options.length === 0) {
|
||||||
|
// Added the default option
|
||||||
|
UtilsFilterControl.addOptionToSelectControl(selectControl, '', column.filterControlPlaceholder)
|
||||||
|
}
|
||||||
|
|
||||||
|
const uniqueValues = {}
|
||||||
|
for (let i = 0; i < z; i++) {
|
||||||
|
// Added a new value
|
||||||
|
const fieldValue = data[i][field]
|
||||||
|
const formattedValue = Utils.calculateObjectValue(that.header, that.header.formatters[j], [fieldValue, data[i], i], fieldValue)
|
||||||
|
|
||||||
|
uniqueValues[formattedValue] = fieldValue
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line guard-for-in
|
||||||
|
for (const key in uniqueValues) {
|
||||||
|
UtilsFilterControl.addOptionToSelectControl(selectControl, uniqueValues[key], key)
|
||||||
|
}
|
||||||
|
|
||||||
|
UtilsFilterControl.sortSelectControl(selectControl)
|
||||||
|
|
||||||
|
if (that.options.hideUnusedSelectOptions) {
|
||||||
|
UtilsFilterControl.hideUnusedSelectOptions(selectControl, uniqueValues)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
that.trigger('created-controls')
|
||||||
|
},
|
||||||
|
getFilterDataMethod (objFilterDataMethod, searchTerm) {
|
||||||
|
const keys = Object.keys(objFilterDataMethod)
|
||||||
|
for (let i = 0; i < keys.length; i++) {
|
||||||
|
if (keys[i] === searchTerm) {
|
||||||
|
return objFilterDataMethod[searchTerm]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
},
|
||||||
|
createControls (that, header) {
|
||||||
|
let addedFilterControl = false
|
||||||
|
let isVisible
|
||||||
|
let html
|
||||||
|
|
||||||
|
$.each(that.columns, (i, column) => {
|
||||||
|
isVisible = 'hidden'
|
||||||
|
html = []
|
||||||
|
|
||||||
|
if (!column.visible) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!column.filterControl) {
|
||||||
|
html.push('<div class="no-filter-control"></div>')
|
||||||
|
} else {
|
||||||
|
html.push('<div class="filter-control">')
|
||||||
|
|
||||||
|
const nameControl = column.filterControl.toLowerCase()
|
||||||
|
if (column.searchable && that.options.filterTemplate[nameControl]) {
|
||||||
|
addedFilterControl = true
|
||||||
|
isVisible = 'visible'
|
||||||
|
html.push(
|
||||||
|
that.options.filterTemplate[nameControl](
|
||||||
|
that,
|
||||||
|
column.field,
|
||||||
|
isVisible,
|
||||||
|
column.filterControlPlaceholder
|
||||||
|
? column.filterControlPlaceholder
|
||||||
|
: '',
|
||||||
|
`filter-control-${i}`
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$.each(header.children().children(), (i, tr) => {
|
||||||
|
const $tr = $(tr)
|
||||||
|
if ($tr.data('field') === column.field) {
|
||||||
|
$tr.find('.fht-cell').append(html.join(''))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (
|
||||||
|
column.filterData !== undefined &&
|
||||||
|
column.filterData.toLowerCase() !== 'column'
|
||||||
|
) {
|
||||||
|
const filterDataType = UtilsFilterControl.getFilterDataMethod(
|
||||||
|
/* eslint-disable no-use-before-define */
|
||||||
|
filterDataMethods,
|
||||||
|
column.filterData.substring(0, column.filterData.indexOf(':'))
|
||||||
|
)
|
||||||
|
let filterDataSource
|
||||||
|
let selectControl
|
||||||
|
|
||||||
|
if (filterDataType !== null) {
|
||||||
|
filterDataSource = column.filterData.substring(
|
||||||
|
column.filterData.indexOf(':') + 1,
|
||||||
|
column.filterData.length
|
||||||
|
)
|
||||||
|
selectControl = $(
|
||||||
|
`.bootstrap-table-filter-control-${UtilsFilterControl.escapeID(column.field)}`
|
||||||
|
)
|
||||||
|
|
||||||
|
UtilsFilterControl.addOptionToSelectControl(selectControl, '', column.filterControlPlaceholder)
|
||||||
|
filterDataType(filterDataSource, selectControl)
|
||||||
|
} else {
|
||||||
|
throw new SyntaxError(
|
||||||
|
'Error. You should use any of these allowed filter data methods: var, json, url.' +
|
||||||
|
' Use like this: var: {key: "value"}'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
let variableValues
|
||||||
|
let key
|
||||||
|
// eslint-disable-next-line default-case
|
||||||
|
switch (filterDataType) {
|
||||||
|
case 'url':
|
||||||
|
$.ajax({
|
||||||
|
url: filterDataSource,
|
||||||
|
dataType: 'json',
|
||||||
|
success (data) {
|
||||||
|
// eslint-disable-next-line guard-for-in
|
||||||
|
for (const key in data) {
|
||||||
|
UtilsFilterControl.addOptionToSelectControl(selectControl, key, data[key])
|
||||||
|
}
|
||||||
|
UtilsFilterControl.sortSelectControl(selectControl)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
break
|
||||||
|
case 'var':
|
||||||
|
variableValues = window[filterDataSource]
|
||||||
|
// eslint-disable-next-line guard-for-in
|
||||||
|
for (key in variableValues) {
|
||||||
|
UtilsFilterControl.addOptionToSelectControl(selectControl, key, variableValues[key])
|
||||||
|
}
|
||||||
|
UtilsFilterControl.sortSelectControl(selectControl)
|
||||||
|
break
|
||||||
|
case 'jso':
|
||||||
|
variableValues = JSON.parse(filterDataSource)
|
||||||
|
// eslint-disable-next-line guard-for-in
|
||||||
|
for (key in variableValues) {
|
||||||
|
UtilsFilterControl.addOptionToSelectControl(selectControl, key, variableValues[key])
|
||||||
|
}
|
||||||
|
UtilsFilterControl.sortSelectControl(selectControl)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (addedFilterControl) {
|
||||||
|
header.off('keyup', 'input').on('keyup', 'input', (event, obj) => {
|
||||||
|
// Simulate enter key action from clear button
|
||||||
|
event.keyCode = obj ? obj.keyCode : event.keyCode
|
||||||
|
|
||||||
|
if (that.options.searchOnEnterKey && event.keyCode !== 13) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($.inArray(event.keyCode, [37, 38, 39, 40]) > -1) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const $currentTarget = $(event.currentTarget)
|
||||||
|
|
||||||
|
if ($currentTarget.is(':checkbox') || $currentTarget.is(':radio')) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
clearTimeout(event.currentTarget.timeoutId || 0)
|
||||||
|
event.currentTarget.timeoutId = setTimeout(() => {
|
||||||
|
that.onColumnSearch(event)
|
||||||
|
}, that.options.searchTimeOut)
|
||||||
|
})
|
||||||
|
|
||||||
|
header.off('change', 'select').on('change', 'select', event => {
|
||||||
|
if (that.options.searchOnEnterKey && event.keyCode !== 13) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($.inArray(event.keyCode, [37, 38, 39, 40]) > -1) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
clearTimeout(event.currentTarget.timeoutId || 0)
|
||||||
|
event.currentTarget.timeoutId = setTimeout(() => {
|
||||||
|
that.onColumnSearch(event)
|
||||||
|
}, that.options.searchTimeOut)
|
||||||
|
})
|
||||||
|
|
||||||
|
header.off('mouseup', 'input').on('mouseup', 'input', function (event) {
|
||||||
|
const $input = $(this)
|
||||||
|
const oldValue = $input.val()
|
||||||
|
|
||||||
|
if (oldValue === '') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
const newValue = $input.val()
|
||||||
|
|
||||||
|
if (newValue === '') {
|
||||||
|
clearTimeout(event.currentTarget.timeoutId || 0)
|
||||||
|
event.currentTarget.timeoutId = setTimeout(() => {
|
||||||
|
that.onColumnSearch(event)
|
||||||
|
}, that.options.searchTimeOut)
|
||||||
|
}
|
||||||
|
}, 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
if (header.find('.date-filter-control').length > 0) {
|
||||||
|
$.each(that.columns, (i, { filterControl, field, filterDatepickerOptions }) => {
|
||||||
|
if (
|
||||||
|
filterControl !== undefined &&
|
||||||
|
filterControl.toLowerCase() === 'datepicker'
|
||||||
|
) {
|
||||||
|
header
|
||||||
|
.find(
|
||||||
|
`.date-filter-control.bootstrap-table-filter-control-${field}`
|
||||||
|
)
|
||||||
|
.datepicker(filterDatepickerOptions)
|
||||||
|
.on('changeDate', ({ currentTarget }) => {
|
||||||
|
$(currentTarget).val(
|
||||||
|
currentTarget.value
|
||||||
|
)
|
||||||
|
// Fired the keyup event
|
||||||
|
$(currentTarget).keyup()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
header.find('.filterControl').hide()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getDirectionOfSelectOptions (_alignment) {
|
||||||
|
const alignment = _alignment === undefined ? 'left' : _alignment.toLowerCase()
|
||||||
|
|
||||||
|
switch (alignment) {
|
||||||
|
case 'left':
|
||||||
|
return 'ltr'
|
||||||
|
case 'right':
|
||||||
|
return 'rtl'
|
||||||
|
case 'auto':
|
||||||
|
return 'auto'
|
||||||
|
default:
|
||||||
|
return 'ltr'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const filterDataMethods = {
|
||||||
|
var (filterDataSource, selectControl) {
|
||||||
|
const variableValues = window[filterDataSource]
|
||||||
|
// eslint-disable-next-line guard-for-in
|
||||||
|
for (const key in variableValues) {
|
||||||
|
UtilsFilterControl.addOptionToSelectControl(selectControl, key, variableValues[key])
|
||||||
|
}
|
||||||
|
UtilsFilterControl.sortSelectControl(selectControl)
|
||||||
|
},
|
||||||
|
url (filterDataSource, selectControl) {
|
||||||
|
$.ajax({
|
||||||
|
url: filterDataSource,
|
||||||
|
dataType: 'json',
|
||||||
|
success (data) {
|
||||||
|
// eslint-disable-next-line guard-for-in
|
||||||
|
for (const key in data) {
|
||||||
|
UtilsFilterControl.addOptionToSelectControl(selectControl, key, data[key])
|
||||||
|
}
|
||||||
|
UtilsFilterControl.sortSelectControl(selectControl)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
json (filterDataSource, selectControl) {
|
||||||
|
const variableValues = JSON.parse(filterDataSource)
|
||||||
|
// eslint-disable-next-line guard-for-in
|
||||||
|
for (const key in variableValues) {
|
||||||
|
UtilsFilterControl.addOptionToSelectControl(selectControl, key, variableValues[key])
|
||||||
|
}
|
||||||
|
UtilsFilterControl.sortSelectControl(selectControl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const bootstrap = {
|
||||||
|
3: {
|
||||||
|
icons: {
|
||||||
|
clear: 'glyphicon-trash icon-clear'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
4: {
|
||||||
|
icons: {
|
||||||
|
clear: 'fa-trash icon-clear'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}[Utils.bootstrapVersion]
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, {
|
||||||
|
filterControl: false,
|
||||||
|
onColumnSearch (field, text) {
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
onCreatedControls () {
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
filterShowClear: false,
|
||||||
|
alignmentSelectControlOptions: undefined,
|
||||||
|
filterTemplate: {
|
||||||
|
input (that, field, isVisible, placeholder) {
|
||||||
|
return Utils.sprintf(
|
||||||
|
'<input type="text" class="form-control bootstrap-table-filter-control-%s" style="width: 100%; visibility: %s" placeholder="%s">',
|
||||||
|
field,
|
||||||
|
isVisible,
|
||||||
|
placeholder
|
||||||
|
)
|
||||||
|
},
|
||||||
|
select ({ options }, field, isVisible) {
|
||||||
|
return Utils.sprintf(
|
||||||
|
'<select class="form-control bootstrap-table-filter-control-%s" style="width: 100%; visibility: %s" dir="%s"></select>',
|
||||||
|
field,
|
||||||
|
isVisible,
|
||||||
|
UtilsFilterControl.getDirectionOfSelectOptions(
|
||||||
|
options.alignmentSelectControlOptions
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
datepicker (that, field, isVisible) {
|
||||||
|
return Utils.sprintf(
|
||||||
|
'<input type="text" class="form-control date-filter-control bootstrap-table-filter-control-%s" style="width: 100%; visibility: %s">',
|
||||||
|
field,
|
||||||
|
isVisible
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
disableControlWhenSearch: false,
|
||||||
|
searchOnEnterKey: false,
|
||||||
|
// internal variables
|
||||||
|
valuesFilterControl: []
|
||||||
|
})
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.columnDefaults, {
|
||||||
|
filterControl: undefined,
|
||||||
|
filterData: undefined,
|
||||||
|
filterDatepickerOptions: undefined,
|
||||||
|
filterStrictSearch: false,
|
||||||
|
filterStartsWithSearch: false,
|
||||||
|
filterControlPlaceholder: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.Constructor.EVENTS, {
|
||||||
|
'column-search.bs.table': 'onColumnSearch',
|
||||||
|
'created-controls.bs.table': 'onCreatedControls'
|
||||||
|
})
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults.icons, {
|
||||||
|
clear: bootstrap.icons.clear
|
||||||
|
})
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.locales, {
|
||||||
|
formatClearFilters () {
|
||||||
|
return 'Clear Filters'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales)
|
||||||
|
|
||||||
|
$.fn.bootstrapTable.methods.push('triggerSearch')
|
||||||
|
$.fn.bootstrapTable.methods.push('clearFilterControl')
|
||||||
|
|
||||||
|
$.BootstrapTable = class extends $.BootstrapTable {
|
||||||
|
init () {
|
||||||
|
// Make sure that the filterControl option is set
|
||||||
|
if (this.options.filterControl) {
|
||||||
|
const that = this
|
||||||
|
|
||||||
|
// Make sure that the internal variables are set correctly
|
||||||
|
this.options.valuesFilterControl = []
|
||||||
|
|
||||||
|
this.$el
|
||||||
|
.on('reset-view.bs.table', () => {
|
||||||
|
// Create controls on $tableHeader if the height is set
|
||||||
|
if (!that.options.height) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Avoid recreate the controls
|
||||||
|
if (
|
||||||
|
that.$tableHeader.find('select').length > 0 ||
|
||||||
|
that.$tableHeader.find('input').length > 0
|
||||||
|
) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
UtilsFilterControl.createControls(that, that.$tableHeader)
|
||||||
|
})
|
||||||
|
.on('post-header.bs.table', () => {
|
||||||
|
UtilsFilterControl.setValues(that)
|
||||||
|
})
|
||||||
|
.on('post-body.bs.table', () => {
|
||||||
|
if (that.options.height) {
|
||||||
|
UtilsFilterControl.fixHeaderCSS(that)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.on('column-switch.bs.table', () => {
|
||||||
|
UtilsFilterControl.setValues(that)
|
||||||
|
})
|
||||||
|
.on('load-success.bs.table', () => {
|
||||||
|
that.EnableControls(true)
|
||||||
|
})
|
||||||
|
.on('load-error.bs.table', () => {
|
||||||
|
that.EnableControls(true)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
super.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
initToolbar () {
|
||||||
|
this.showToolbar =
|
||||||
|
this.showToolbar ||
|
||||||
|
(this.options.filterControl && this.options.filterShowClear)
|
||||||
|
|
||||||
|
super.initToolbar()
|
||||||
|
|
||||||
|
if (this.options.filterControl && this.options.filterShowClear) {
|
||||||
|
const $btnGroup = this.$toolbar.find('>.btn-group')
|
||||||
|
let $btnClear = $btnGroup.find('.filter-show-clear')
|
||||||
|
|
||||||
|
if (!$btnClear.length) {
|
||||||
|
$btnClear = $(
|
||||||
|
[
|
||||||
|
Utils.sprintf(
|
||||||
|
'<button class="btn btn-%s filter-show-clear" ',
|
||||||
|
this.options.buttonsClass
|
||||||
|
),
|
||||||
|
Utils.sprintf(
|
||||||
|
'type="button" title="%s">',
|
||||||
|
this.options.formatClearFilters()
|
||||||
|
),
|
||||||
|
Utils.sprintf(
|
||||||
|
'<i class="%s %s"></i> ',
|
||||||
|
this.options.iconsPrefix,
|
||||||
|
this.options.icons.clear
|
||||||
|
),
|
||||||
|
'</button>'
|
||||||
|
].join('')
|
||||||
|
).appendTo($btnGroup)
|
||||||
|
|
||||||
|
$btnClear
|
||||||
|
.off('click')
|
||||||
|
.on('click', $.proxy(this.clearFilterControl, this))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
initHeader () {
|
||||||
|
super.initHeader()
|
||||||
|
|
||||||
|
if (!this.options.filterControl) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
UtilsFilterControl.createControls(this, this.$header)
|
||||||
|
}
|
||||||
|
initBody () {
|
||||||
|
super.initBody()
|
||||||
|
|
||||||
|
UtilsFilterControl.initFilterSelectControls(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
initSearch () {
|
||||||
|
const that = this
|
||||||
|
const fp = $.isEmptyObject(that.filterColumnsPartial)
|
||||||
|
? null
|
||||||
|
: that.filterColumnsPartial
|
||||||
|
|
||||||
|
if (fp === null || Object.keys(fp).length <= 1) {
|
||||||
|
super.initSearch()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.options.sidePagination === 'server') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fp === null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check partial column filter
|
||||||
|
that.data = fp
|
||||||
|
? that.options.data.filter((item, i) => {
|
||||||
|
const itemIsExpected = []
|
||||||
|
Object.keys(item).forEach((key, index) => {
|
||||||
|
const thisColumn = that.columns[that.fieldsColumnsIndex[key]]
|
||||||
|
const fval = (fp[key] || '').toLowerCase()
|
||||||
|
let value = item[key]
|
||||||
|
|
||||||
|
if (fval === '') {
|
||||||
|
itemIsExpected.push(true)
|
||||||
|
} else {
|
||||||
|
// Fix #142: search use formated data
|
||||||
|
if (thisColumn && thisColumn.searchFormatter) {
|
||||||
|
value = $.fn.bootstrapTable.utils.calculateObjectValue(
|
||||||
|
that.header,
|
||||||
|
that.header.formatters[$.inArray(key, that.header.fields)],
|
||||||
|
[value, item, i],
|
||||||
|
value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($.inArray(key, that.header.fields) !== -1) {
|
||||||
|
if (typeof value === 'string' || typeof value === 'number') {
|
||||||
|
if (thisColumn.filterStrictSearch) {
|
||||||
|
if (value.toString().toLowerCase() === fval.toString().toLowerCase()) {
|
||||||
|
itemIsExpected.push(true)
|
||||||
|
} else {
|
||||||
|
itemIsExpected.push(false)
|
||||||
|
}
|
||||||
|
} else if (thisColumn.filterStartsWithSearch) {
|
||||||
|
if ((`${value}`).toLowerCase().indexOf(fval) === 0) {
|
||||||
|
itemIsExpected.push(true)
|
||||||
|
} else {
|
||||||
|
itemIsExpected.push(false)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ((`${value}`).toLowerCase().includes(fval)) {
|
||||||
|
itemIsExpected.push(true)
|
||||||
|
} else {
|
||||||
|
itemIsExpected.push(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return !itemIsExpected.includes(false)
|
||||||
|
})
|
||||||
|
: that.data
|
||||||
|
}
|
||||||
|
|
||||||
|
initColumnSearch (filterColumnsDefaults) {
|
||||||
|
UtilsFilterControl.copyValues(this)
|
||||||
|
|
||||||
|
if (filterColumnsDefaults) {
|
||||||
|
this.filterColumnsPartial = filterColumnsDefaults
|
||||||
|
this.updatePagination()
|
||||||
|
|
||||||
|
// eslint-disable-next-line guard-for-in
|
||||||
|
for (const filter in filterColumnsDefaults) {
|
||||||
|
this.trigger('column-search', filter, filterColumnsDefaults[filter])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onColumnSearch (event) {
|
||||||
|
if ($.inArray(event.keyCode, [37, 38, 39, 40]) > -1) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
UtilsFilterControl.copyValues(this)
|
||||||
|
const text = $.trim($(event.currentTarget).val())
|
||||||
|
const $field = $(event.currentTarget)
|
||||||
|
.closest('[data-field]')
|
||||||
|
.data('field')
|
||||||
|
|
||||||
|
if ($.isEmptyObject(this.filterColumnsPartial)) {
|
||||||
|
this.filterColumnsPartial = {}
|
||||||
|
}
|
||||||
|
if (text) {
|
||||||
|
this.filterColumnsPartial[$field] = text
|
||||||
|
} else {
|
||||||
|
delete this.filterColumnsPartial[$field]
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the searchText is the same as the previously selected column value,
|
||||||
|
// bootstrapTable will not try searching again (even though the selected column
|
||||||
|
// may be different from the previous search). As a work around
|
||||||
|
// we're manually appending some text to bootrap's searchText field
|
||||||
|
// to guarantee that it will perform a search again when we call this.onSearch(event)
|
||||||
|
this.searchText += 'randomText'
|
||||||
|
|
||||||
|
this.options.pageNumber = 1
|
||||||
|
this.EnableControls(false)
|
||||||
|
this.onSearch(event)
|
||||||
|
this.trigger('column-search', $field, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
clearFilterControl () {
|
||||||
|
if (this.options.filterControl && this.options.filterShowClear) {
|
||||||
|
const that = this
|
||||||
|
const cookies = UtilsFilterControl.collectBootstrapCookies()
|
||||||
|
const header = UtilsFilterControl.getCurrentHeader(that)
|
||||||
|
const table = header.closest('table')
|
||||||
|
const controls = header.find(UtilsFilterControl.getCurrentSearchControls(that))
|
||||||
|
const search = that.$toolbar.find('.search input')
|
||||||
|
let hasValues = false
|
||||||
|
let timeoutId = 0
|
||||||
|
|
||||||
|
$.each(that.options.valuesFilterControl, (i, item) => {
|
||||||
|
hasValues = hasValues ? true : item.value !== ''
|
||||||
|
item.value = ''
|
||||||
|
})
|
||||||
|
|
||||||
|
UtilsFilterControl.setValues(that)
|
||||||
|
|
||||||
|
// clear cookies once the filters are clean
|
||||||
|
clearTimeout(timeoutId)
|
||||||
|
timeoutId = setTimeout(() => {
|
||||||
|
if (cookies && cookies.length > 0) {
|
||||||
|
$.each(cookies, (i, item) => {
|
||||||
|
if (that.deleteCookie !== undefined) {
|
||||||
|
that.deleteCookie(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, that.options.searchTimeOut)
|
||||||
|
|
||||||
|
// If there is not any value in the controls exit this method
|
||||||
|
if (!hasValues) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear each type of filter if it exists.
|
||||||
|
// Requires the body to reload each time a type of filter is found because we never know
|
||||||
|
// which ones are going to be present.
|
||||||
|
if (controls.length > 0) {
|
||||||
|
this.filterColumnsPartial = {}
|
||||||
|
$(controls[0]).trigger(
|
||||||
|
controls[0].tagName === 'INPUT' ? 'keyup' : 'change', { keyCode: 13 }
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (search.length > 0) {
|
||||||
|
that.resetSearch()
|
||||||
|
}
|
||||||
|
|
||||||
|
// use the default sort order if it exists. do nothing if it does not
|
||||||
|
if (
|
||||||
|
that.options.sortName !== table.data('sortName') ||
|
||||||
|
that.options.sortOrder !== table.data('sortOrder')
|
||||||
|
) {
|
||||||
|
const sorter = header.find(
|
||||||
|
Utils.sprintf(
|
||||||
|
'[data-field="%s"]',
|
||||||
|
$(controls[0])
|
||||||
|
.closest('table')
|
||||||
|
.data('sortName')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if (sorter.length > 0) {
|
||||||
|
that.onSort({ type: 'keypress', currentTarget: sorter })
|
||||||
|
$(sorter)
|
||||||
|
.find('.sortable')
|
||||||
|
.trigger('click')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
triggerSearch () {
|
||||||
|
const header = UtilsFilterControl.getCurrentHeader(this)
|
||||||
|
const searchControls = UtilsFilterControl.getCurrentSearchControls(this)
|
||||||
|
|
||||||
|
header.find(searchControls).each(function () {
|
||||||
|
const el = $(this)
|
||||||
|
if (el.is('select')) {
|
||||||
|
el.change()
|
||||||
|
} else {
|
||||||
|
el.keyup()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
EnableControls (enable) {
|
||||||
|
if (
|
||||||
|
this.options.disableControlWhenSearch &&
|
||||||
|
this.options.sidePagination === 'server'
|
||||||
|
) {
|
||||||
|
const header = UtilsFilterControl.getCurrentHeader(this)
|
||||||
|
const searchControls = UtilsFilterControl.getCurrentSearchControls(this)
|
||||||
|
|
||||||
|
if (!enable) {
|
||||||
|
header.find(searchControls).prop('disabled', 'disabled')
|
||||||
|
} else {
|
||||||
|
header.find(searchControls).removeProp('disabled')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})(jQuery)
|
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "Filter Control",
|
||||||
|
"version": "2.1.0",
|
||||||
|
"description": "Plugin to add input/select element on the top of the columns in order to filter the data.",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/filter-control",
|
||||||
|
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/filter-control.html",
|
||||||
|
|
||||||
|
"plugins": [{
|
||||||
|
"name": "bootstrap-table-filter-control",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/filter-control"
|
||||||
|
}],
|
||||||
|
|
||||||
|
"author": {
|
||||||
|
"name": "djhvscf",
|
||||||
|
"image": "https://avatars1.githubusercontent.com/u/4496763"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
.fixed-table-header-columns,
|
||||||
|
.fixed-table-body-columns {
|
||||||
|
position: absolute;
|
||||||
|
background-color: #fff;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: hidden;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fixed-table-header-columns {
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fixed-table-header-columns .table,
|
||||||
|
.fixed-table-body-columns .table {
|
||||||
|
border-right: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fixed-table-header-columns .table.table-no-bordered,
|
||||||
|
.fixed-table-body-columns .table.table-no-bordered {
|
||||||
|
border-right: 1px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fixed-table-body-columns table {
|
||||||
|
position: absolute;
|
||||||
|
animation: none;
|
||||||
|
}
|
115
InvenTree/InvenTree/static/bootstrap-table/extensions/fixed-columns/bootstrap-table-fixed-columns.js
vendored
Normal file
115
InvenTree/InvenTree/static/bootstrap-table/extensions/fixed-columns/bootstrap-table-fixed-columns.js
vendored
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/**
|
||||||
|
* @author zhixin wen <wenzhixin2010@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
($ => {
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, {
|
||||||
|
fixedColumns: false,
|
||||||
|
fixedNumber: 1
|
||||||
|
})
|
||||||
|
|
||||||
|
$.BootstrapTable = class extends $.BootstrapTable {
|
||||||
|
|
||||||
|
fitHeader (...args) {
|
||||||
|
super.fitHeader(...args)
|
||||||
|
|
||||||
|
if (!this.options.fixedColumns) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.$el.is(':hidden')) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$container.find('.fixed-table-header-columns').remove()
|
||||||
|
this.$fixedHeader = $('<div class="fixed-table-header-columns"></div>')
|
||||||
|
this.$fixedHeader.append(this.$tableHeader.find('>table').clone(true))
|
||||||
|
this.$tableHeader.after(this.$fixedHeader)
|
||||||
|
|
||||||
|
const width = this.getFixedColumnsWidth()
|
||||||
|
|
||||||
|
this.$fixedHeader.css({
|
||||||
|
top: 0,
|
||||||
|
width,
|
||||||
|
height: this.$tableHeader.outerHeight(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
this.initFixedColumnsBody()
|
||||||
|
|
||||||
|
this.$fixedBody.css({
|
||||||
|
top: this.$tableHeader.outerHeight(true),
|
||||||
|
width,
|
||||||
|
height: this.$tableBody.outerHeight(true) - 1
|
||||||
|
})
|
||||||
|
|
||||||
|
this.initFixedColumnsEvents()
|
||||||
|
}
|
||||||
|
|
||||||
|
initBody (...args) {
|
||||||
|
super.initBody(...args)
|
||||||
|
|
||||||
|
if (!this.options.fixedColumns) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.options.showHeader && this.options.height) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.initFixedColumnsBody()
|
||||||
|
|
||||||
|
this.$fixedBody.css({
|
||||||
|
top: 0,
|
||||||
|
width: this.getFixedColumnsWidth(),
|
||||||
|
height: this.$tableHeader.outerHeight(true) + this.$tableBody.outerHeight(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
this.initFixedColumnsEvents()
|
||||||
|
}
|
||||||
|
|
||||||
|
initFixedColumnsBody () {
|
||||||
|
this.$container.find('.fixed-table-body-columns').remove()
|
||||||
|
this.$fixedBody = $('<div class="fixed-table-body-columns"></div>')
|
||||||
|
this.$fixedBody.append(this.$tableBody.find('>table').clone(true))
|
||||||
|
this.$tableBody.after(this.$fixedBody)
|
||||||
|
}
|
||||||
|
|
||||||
|
getFixedColumnsWidth () {
|
||||||
|
const visibleFields = this.getVisibleFields()
|
||||||
|
let width = 0
|
||||||
|
|
||||||
|
for (let i = 0; i < this.options.fixedNumber; i++) {
|
||||||
|
width += this.$header.find(`th[data-field="${visibleFields[i]}"]`).outerWidth(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
return width + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
initFixedColumnsEvents () {
|
||||||
|
// events
|
||||||
|
this.$tableBody.off('scroll.fixed-columns').on('scroll.fixed-columns', e => {
|
||||||
|
this.$fixedBody.find('table').css('top', -$(e.currentTarget).scrollTop())
|
||||||
|
})
|
||||||
|
|
||||||
|
this.$body.find('> tr[data-index]').off('hover').hover(e => {
|
||||||
|
const index = $(e.currentTarget).data('index')
|
||||||
|
this.$fixedBody.find(`tr[data-index="${index}"]`)
|
||||||
|
.css('background-color', $(e.currentTarget).css('background-color'))
|
||||||
|
}, e => {
|
||||||
|
const index = $(e.currentTarget).data('index')
|
||||||
|
const $tr = this.$fixedBody.find(`tr[data-index="${index}"]`)
|
||||||
|
$tr.attr('style', $tr.attr('style').replace(/background-color:.*;/, ''))
|
||||||
|
})
|
||||||
|
|
||||||
|
this.$fixedBody.find('tr[data-index]').off('hover').hover(e => {
|
||||||
|
const index = $(e.currentTarget).data('index')
|
||||||
|
this.$body.find(`tr[data-index="${index}"]`)
|
||||||
|
.css('background-color', $(e.currentTarget).css('background-color'))
|
||||||
|
}, e => {
|
||||||
|
const index = $(e.currentTarget).data('index')
|
||||||
|
const $tr = this.$body.find(`> tr[data-index="${index}"]`)
|
||||||
|
$tr.attr('style', $tr.attr('style').replace(/background-color:.*;/, ''))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})(jQuery)
|
11
InvenTree/InvenTree/static/bootstrap-table/extensions/group-by-v2/bootstrap-table-group-by.css
vendored
Normal file
11
InvenTree/InvenTree/static/bootstrap-table/extensions/group-by-v2/bootstrap-table-group-by.css
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
.bootstrap-table .table > tbody > tr.groupBy {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bootstrap-table .table > tbody > tr.groupBy.expanded {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.bootstrap-table .table > tbody > tr.hidden + tr.detail-view {
|
||||||
|
display: none;
|
||||||
|
}
|
230
InvenTree/InvenTree/static/bootstrap-table/extensions/group-by-v2/bootstrap-table-group-by.js
vendored
Normal file
230
InvenTree/InvenTree/static/bootstrap-table/extensions/group-by-v2/bootstrap-table-group-by.js
vendored
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
/**
|
||||||
|
* @author: Yura Knoxville
|
||||||
|
* @version: v1.1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function ($) {
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var initBodyCaller,
|
||||||
|
tableGroups;
|
||||||
|
|
||||||
|
// it only does '%s', and return '' when arguments are undefined
|
||||||
|
var sprintf = function (str) {
|
||||||
|
var args = arguments,
|
||||||
|
flag = true,
|
||||||
|
i = 1;
|
||||||
|
|
||||||
|
str = str.replace(/%s/g, function () {
|
||||||
|
var arg = args[i++];
|
||||||
|
|
||||||
|
if (typeof arg === 'undefined') {
|
||||||
|
flag = false;
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return arg;
|
||||||
|
});
|
||||||
|
return flag ? str : '';
|
||||||
|
};
|
||||||
|
|
||||||
|
var groupBy = function (array , f) {
|
||||||
|
var groups = {};
|
||||||
|
array.forEach(function(o) {
|
||||||
|
var group = f(o);
|
||||||
|
groups[group] = groups[group] || [];
|
||||||
|
groups[group].push(o);
|
||||||
|
});
|
||||||
|
|
||||||
|
return groups;
|
||||||
|
};
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, {
|
||||||
|
groupBy: false,
|
||||||
|
groupByField: '',
|
||||||
|
groupByFormatter: undefined
|
||||||
|
});
|
||||||
|
|
||||||
|
var BootstrapTable = $.fn.bootstrapTable.Constructor,
|
||||||
|
_initSort = BootstrapTable.prototype.initSort,
|
||||||
|
_initBody = BootstrapTable.prototype.initBody,
|
||||||
|
_updateSelected = BootstrapTable.prototype.updateSelected;
|
||||||
|
|
||||||
|
BootstrapTable.prototype.initSort = function () {
|
||||||
|
_initSort.apply(this, Array.prototype.slice.apply(arguments));
|
||||||
|
|
||||||
|
var that = this;
|
||||||
|
tableGroups = [];
|
||||||
|
|
||||||
|
if ((this.options.groupBy) && (this.options.groupByField !== '')) {
|
||||||
|
|
||||||
|
if ((this.options.sortName != this.options.groupByField)) {
|
||||||
|
this.data.sort(function(a, b) {
|
||||||
|
return a[that.options.groupByField].localeCompare(b[that.options.groupByField]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var that = this;
|
||||||
|
var groups = groupBy(that.data, function (item) {
|
||||||
|
return [item[that.options.groupByField]];
|
||||||
|
});
|
||||||
|
|
||||||
|
var index = 0;
|
||||||
|
$.each(groups, function(key, value) {
|
||||||
|
tableGroups.push({
|
||||||
|
id: index,
|
||||||
|
name: key,
|
||||||
|
data: value
|
||||||
|
});
|
||||||
|
|
||||||
|
value.forEach(function(item) {
|
||||||
|
if (!item._data) {
|
||||||
|
item._data = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
item._data['parent-index'] = index;
|
||||||
|
});
|
||||||
|
|
||||||
|
index++;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BootstrapTable.prototype.initBody = function () {
|
||||||
|
initBodyCaller = true;
|
||||||
|
|
||||||
|
_initBody.apply(this, Array.prototype.slice.apply(arguments));
|
||||||
|
|
||||||
|
if ((this.options.groupBy) && (this.options.groupByField !== '')) {
|
||||||
|
var that = this,
|
||||||
|
checkBox = false,
|
||||||
|
visibleColumns = 0;
|
||||||
|
|
||||||
|
this.columns.forEach(function(column) {
|
||||||
|
if (column.checkbox) {
|
||||||
|
checkBox = true;
|
||||||
|
} else {
|
||||||
|
if (column.visible) {
|
||||||
|
visibleColumns += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (this.options.detailView && !this.options.cardView) {
|
||||||
|
visibleColumns += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
tableGroups.forEach(function(item){
|
||||||
|
var html = [];
|
||||||
|
|
||||||
|
html.push(sprintf('<tr class="info groupBy expanded" data-group-index="%s">', item.id));
|
||||||
|
|
||||||
|
if (that.options.detailView && !that.options.cardView) {
|
||||||
|
html.push('<td class="detail"></td>');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checkBox) {
|
||||||
|
html.push('<td class="bs-checkbox">',
|
||||||
|
'<input name="btSelectGroup" type="checkbox" />',
|
||||||
|
'</td>'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
var formattedValue = item.name;
|
||||||
|
if (typeof(that.options.groupByFormatter) == "function") {
|
||||||
|
formattedValue = that.options.groupByFormatter(item.name, item.id, item.data);
|
||||||
|
}
|
||||||
|
html.push('<td',
|
||||||
|
sprintf(' colspan="%s"', visibleColumns),
|
||||||
|
'>', formattedValue, '</td>'
|
||||||
|
);
|
||||||
|
|
||||||
|
html.push('</tr>');
|
||||||
|
|
||||||
|
that.$body.find('tr[data-parent-index='+item.id+']:first').before($(html.join('')));
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$selectGroup = [];
|
||||||
|
this.$body.find('[name="btSelectGroup"]').each(function() {
|
||||||
|
var self = $(this);
|
||||||
|
|
||||||
|
that.$selectGroup.push({
|
||||||
|
group: self,
|
||||||
|
item: that.$selectItem.filter(function () {
|
||||||
|
return ($(this).closest('tr').data('parent-index') ===
|
||||||
|
self.closest('tr').data('group-index'));
|
||||||
|
})
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$container.off('click', '.groupBy')
|
||||||
|
.on('click', '.groupBy', function() {
|
||||||
|
$(this).toggleClass('expanded');
|
||||||
|
that.$body.find('tr[data-parent-index='+$(this).closest('tr').data('group-index')+']').toggleClass('hidden');
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$container.off('click', '[name="btSelectGroup"]')
|
||||||
|
.on('click', '[name="btSelectGroup"]', function (event) {
|
||||||
|
event.stopImmediatePropagation();
|
||||||
|
|
||||||
|
var self = $(this);
|
||||||
|
var checked = self.prop('checked');
|
||||||
|
that[checked ? 'checkGroup' : 'uncheckGroup']($(this).closest('tr').data('group-index'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
initBodyCaller = false;
|
||||||
|
this.updateSelected();
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.updateSelected = function () {
|
||||||
|
if (!initBodyCaller) {
|
||||||
|
_updateSelected.apply(this, Array.prototype.slice.apply(arguments));
|
||||||
|
|
||||||
|
if ((this.options.groupBy) && (this.options.groupByField !== '')) {
|
||||||
|
this.$selectGroup.forEach(function (item) {
|
||||||
|
var checkGroup = item.item.filter(':enabled').length ===
|
||||||
|
item.item.filter(':enabled').filter(':checked').length;
|
||||||
|
|
||||||
|
item.group.prop('checked', checkGroup);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.getGroupSelections = function (index) {
|
||||||
|
var that = this;
|
||||||
|
|
||||||
|
return $.grep(this.data, function (row) {
|
||||||
|
return (row[that.header.stateField] && (row._data['parent-index'] === index));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.checkGroup = function (index) {
|
||||||
|
this.checkGroup_(index, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.uncheckGroup = function (index) {
|
||||||
|
this.checkGroup_(index, false);
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.checkGroup_ = function (index, checked) {
|
||||||
|
var rows;
|
||||||
|
var filter = function() {
|
||||||
|
return ($(this).closest('tr').data('parent-index') === index);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!checked) {
|
||||||
|
rows = this.getGroupSelections(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$selectItem.filter(filter).prop('checked', checked);
|
||||||
|
|
||||||
|
this.updateRows();
|
||||||
|
this.updateSelected();
|
||||||
|
if (checked) {
|
||||||
|
rows = this.getGroupSelections(index);
|
||||||
|
}
|
||||||
|
this.trigger(checked ? 'check-all' : 'uncheck-all', rows);
|
||||||
|
};
|
||||||
|
|
||||||
|
})(jQuery);
|
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"name": "Group By V2",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Group the data by field",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/group-by-v2",
|
||||||
|
"example": "",
|
||||||
|
"plugins": [],
|
||||||
|
"author": {
|
||||||
|
"name": "Knoxvillekm",
|
||||||
|
"image": "https://avatars3.githubusercontent.com/u/11072464"
|
||||||
|
}
|
||||||
|
}
|
53
InvenTree/InvenTree/static/bootstrap-table/extensions/group-by/bootstrap-table-group-by.css
vendored
Normal file
53
InvenTree/InvenTree/static/bootstrap-table/extensions/group-by/bootstrap-table-group-by.css
vendored
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
table.treetable tbody tr td {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.treetable span {
|
||||||
|
background-position: center left;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
padding: .2em 0 .2em 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.treetable tr.collapsed span.indenter a {
|
||||||
|
background-image: url(data:image/png;base64,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);
|
||||||
|
padding-right: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.treetable tr.expanded span.indenter a {
|
||||||
|
background-image: url(data:image/png;base64,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);
|
||||||
|
padding-right: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.treetable tr.branch {
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.treetable tr.selected {
|
||||||
|
background-color: #3875d7;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.treetable tr span.indenter a {
|
||||||
|
outline: none; /* Expander shows outline after upgrading to 3.0 (#141) */
|
||||||
|
}
|
||||||
|
|
||||||
|
table.treetable tr.collapsed.selected span.indenter a {
|
||||||
|
background-image: url(data:image/png;base64,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);
|
||||||
|
}
|
||||||
|
|
||||||
|
table.treetable tr.expanded.selected span.indenter a {
|
||||||
|
background-image: url(data:image/png;base64,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);
|
||||||
|
}
|
||||||
|
|
||||||
|
table.treetable tr.accept {
|
||||||
|
background-color: #a3bce4;
|
||||||
|
color: #fff
|
||||||
|
}
|
||||||
|
|
||||||
|
table.treetable tr.collapsed.accept td span.indenter a {
|
||||||
|
background-image: url(data:image/x-png;base64,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);
|
||||||
|
}
|
||||||
|
|
||||||
|
table.treetable tr.expanded.accept td span.indenter a {
|
||||||
|
background-image: url(data:image/x-png;base64,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);
|
||||||
|
}
|
243
InvenTree/InvenTree/static/bootstrap-table/extensions/group-by/bootstrap-table-group-by.js
vendored
Normal file
243
InvenTree/InvenTree/static/bootstrap-table/extensions/group-by/bootstrap-table-group-by.js
vendored
Normal file
@ -0,0 +1,243 @@
|
|||||||
|
/**
|
||||||
|
* @author: Dennis Hernández
|
||||||
|
* @webSite: http://djhvscf.github.io/Blog
|
||||||
|
* @version: v1.1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
!function ($) {
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var originalRowAttr,
|
||||||
|
dataTTId = 'data-tt-id',
|
||||||
|
dataTTParentId = 'data-tt-parent-id',
|
||||||
|
obj = {},
|
||||||
|
parentId = undefined;
|
||||||
|
|
||||||
|
var getParentRowId = function (that, id) {
|
||||||
|
var parentRows = that.$body.find('tr').not('[' + 'data-tt-parent-id]');
|
||||||
|
|
||||||
|
for (var i = 0; i < parentRows.length; i++) {
|
||||||
|
if (i === id) {
|
||||||
|
return $(parentRows[i]).attr('data-tt-id');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
var sumData = function (that, data) {
|
||||||
|
var sumRow = {};
|
||||||
|
$.each(data, function (i, row) {
|
||||||
|
if (!row.IsParent) {
|
||||||
|
for (var prop in row) {
|
||||||
|
if (!isNaN(parseFloat(row[prop]))) {
|
||||||
|
if (that.columns[that.fieldsColumnsIndex[prop]].groupBySumGroup) {
|
||||||
|
if (sumRow[prop] === undefined) {
|
||||||
|
sumRow[prop] = 0;
|
||||||
|
}
|
||||||
|
sumRow[prop] += +row[prop];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return sumRow;
|
||||||
|
};
|
||||||
|
|
||||||
|
var rowAttr = function (row, index) {
|
||||||
|
//Call the User Defined Function
|
||||||
|
originalRowAttr.apply([row, index]);
|
||||||
|
|
||||||
|
obj[dataTTId.toString()] = index;
|
||||||
|
|
||||||
|
if (!row.IsParent) {
|
||||||
|
obj[dataTTParentId.toString()] = parentId === undefined ? index : parentId;
|
||||||
|
} else {
|
||||||
|
parentId = index;
|
||||||
|
delete obj[dataTTParentId.toString()];
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
};
|
||||||
|
|
||||||
|
var setObjectKeys = function () {
|
||||||
|
// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
|
||||||
|
Object.keys = function (o) {
|
||||||
|
if (o !== Object(o)) {
|
||||||
|
throw new TypeError('Object.keys called on a non-object');
|
||||||
|
}
|
||||||
|
var k = [],
|
||||||
|
p;
|
||||||
|
for (p in o) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(o, p)) {
|
||||||
|
k.push(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return k;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var getDataArrayFromItem = function (that, item) {
|
||||||
|
var itemDataArray = [];
|
||||||
|
for (var i = 0; i < that.options.groupByField.length; i++) {
|
||||||
|
itemDataArray.push(item[that.options.groupByField[i]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return itemDataArray;
|
||||||
|
};
|
||||||
|
|
||||||
|
var getNewRow = function (that, result, index) {
|
||||||
|
var newRow = {};
|
||||||
|
for (var i = 0; i < that.options.groupByField.length; i++) {
|
||||||
|
newRow[that.options.groupByField[i].toString()] = result[index][0][that.options.groupByField[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
newRow.IsParent = true;
|
||||||
|
|
||||||
|
return newRow;
|
||||||
|
};
|
||||||
|
|
||||||
|
var groupBy = function (array, f) {
|
||||||
|
var groups = {};
|
||||||
|
$.each(array, function (i, o) {
|
||||||
|
var group = JSON.stringify(f(o));
|
||||||
|
groups[group] = groups[group] || [];
|
||||||
|
groups[group].push(o);
|
||||||
|
});
|
||||||
|
return Object.keys(groups).map(function (group) {
|
||||||
|
return groups[group];
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var makeGrouped = function (that, data) {
|
||||||
|
var newData = [],
|
||||||
|
sumRow = {};
|
||||||
|
|
||||||
|
var result = groupBy(data, function (item) {
|
||||||
|
return getDataArrayFromItem(that, item);
|
||||||
|
});
|
||||||
|
|
||||||
|
for (var i = 0; i < result.length; i++) {
|
||||||
|
result[i].unshift(getNewRow(that, result, i));
|
||||||
|
if (that.options.groupBySumGroup) {
|
||||||
|
sumRow = sumData(that, result[i]);
|
||||||
|
if (!$.isEmptyObject(sumRow)) {
|
||||||
|
result[i].push(sumRow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newData = newData.concat.apply(newData, result);
|
||||||
|
|
||||||
|
if (!that.options.loaded && newData.length > 0) {
|
||||||
|
that.options.loaded = true;
|
||||||
|
that.options.originalData = that.options.data;
|
||||||
|
that.options.data = newData;
|
||||||
|
}
|
||||||
|
|
||||||
|
return newData;
|
||||||
|
};
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, {
|
||||||
|
groupBy: false,
|
||||||
|
groupByField: [],
|
||||||
|
groupBySumGroup: false,
|
||||||
|
groupByInitExpanded: undefined, //node, 'all'
|
||||||
|
//internal variables
|
||||||
|
loaded: false,
|
||||||
|
originalData: undefined
|
||||||
|
});
|
||||||
|
|
||||||
|
$.fn.bootstrapTable.methods.push('collapseAll', 'expandAll', 'refreshGroupByField');
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.COLUMN_DEFAULTS, {
|
||||||
|
groupBySumGroup: false
|
||||||
|
});
|
||||||
|
|
||||||
|
var BootstrapTable = $.fn.bootstrapTable.Constructor,
|
||||||
|
_init = BootstrapTable.prototype.init,
|
||||||
|
_initData = BootstrapTable.prototype.initData;
|
||||||
|
|
||||||
|
BootstrapTable.prototype.init = function () {
|
||||||
|
//Temporal validation
|
||||||
|
if (!this.options.sortName) {
|
||||||
|
if ((this.options.groupBy) && (this.options.groupByField.length > 0)) {
|
||||||
|
var that = this;
|
||||||
|
|
||||||
|
// Compatibility: IE < 9 and old browsers
|
||||||
|
if (!Object.keys) {
|
||||||
|
$.fn.bootstrapTable.utils.objectKeys();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Make sure that the internal variables are set correctly
|
||||||
|
this.options.loaded = false;
|
||||||
|
this.options.originalData = undefined;
|
||||||
|
|
||||||
|
originalRowAttr = this.options.rowAttributes;
|
||||||
|
this.options.rowAttributes = rowAttr;
|
||||||
|
this.$el.off('post-body.bs.table').on('post-body.bs.table', function () {
|
||||||
|
that.$el.treetable({
|
||||||
|
expandable: true,
|
||||||
|
onNodeExpand: function () {
|
||||||
|
if (that.options.height) {
|
||||||
|
that.resetHeader();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onNodeCollapse: function () {
|
||||||
|
if (that.options.height) {
|
||||||
|
that.resetHeader();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
if (that.options.groupByInitExpanded !== undefined) {
|
||||||
|
if (typeof that.options.groupByInitExpanded === 'number') {
|
||||||
|
that.expandNode(that.options.groupByInitExpanded);
|
||||||
|
} else if (that.options.groupByInitExpanded.toLowerCase() === 'all') {
|
||||||
|
that.expandAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_init.apply(this, Array.prototype.slice.apply(arguments));
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.initData = function (data, type) {
|
||||||
|
//Temporal validation
|
||||||
|
if (!this.options.sortName) {
|
||||||
|
if ((this.options.groupBy) && (this.options.groupByField.length > 0)) {
|
||||||
|
|
||||||
|
this.options.groupByField = typeof this.options.groupByField === 'string' ?
|
||||||
|
this.options.groupByField.replace('[', '').replace(']', '')
|
||||||
|
.replace(/ /g, '').toLowerCase().split(',') : this.options.groupByField;
|
||||||
|
|
||||||
|
data = makeGrouped(this, data ? data : this.options.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_initData.apply(this, [data, type]);
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.expandAll = function () {
|
||||||
|
this.$el.treetable('expandAll');
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.collapseAll = function () {
|
||||||
|
this.$el.treetable('collapseAll');
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.expandNode = function (id) {
|
||||||
|
id = getParentRowId(this, id);
|
||||||
|
if (id !== undefined) {
|
||||||
|
this.$el.treetable('expandNode', id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.refreshGroupByField = function (groupByFields) {
|
||||||
|
if (!$.fn.bootstrapTable.utils.compareObjects(this.options.groupByField, groupByFields)) {
|
||||||
|
this.options.groupByField = groupByFields;
|
||||||
|
this.load(this.options.originalData);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}(jQuery);
|
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "Group By",
|
||||||
|
"version": "1.1.0",
|
||||||
|
"description": "Plugin to group the data by fields.",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/group-by",
|
||||||
|
"example": "#",
|
||||||
|
|
||||||
|
"plugins": [{
|
||||||
|
"name": "bootstrap-table-group-by",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/group-by"
|
||||||
|
}],
|
||||||
|
|
||||||
|
"author": {
|
||||||
|
"name": "djhvscf",
|
||||||
|
"image": "https://avatars1.githubusercontent.com/u/4496763"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* @author: Jewway
|
||||||
|
* @version: v1.0.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
!function ($) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var BootstrapTable = $.fn.bootstrapTable.Constructor;
|
||||||
|
|
||||||
|
BootstrapTable.prototype.changeTitle = function (locale) {
|
||||||
|
$.each(this.options.columns, function (idx, columnList) {
|
||||||
|
$.each(columnList, function (idx, column) {
|
||||||
|
if (column.field) {
|
||||||
|
column.title = locale[column.field];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
this.initHeader();
|
||||||
|
this.initBody();
|
||||||
|
this.initToolbar();
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.changeLocale = function (localeId) {
|
||||||
|
this.options.locale = localeId;
|
||||||
|
this.initLocale();
|
||||||
|
this.initPagination();
|
||||||
|
this.initBody();
|
||||||
|
this.initToolbar();
|
||||||
|
};
|
||||||
|
|
||||||
|
$.fn.bootstrapTable.methods.push('changeTitle');
|
||||||
|
$.fn.bootstrapTable.methods.push('changeLocale');
|
||||||
|
|
||||||
|
}(jQuery);
|
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "i18n Enhance",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Plugin to add i18n API in order to change column's title and table locale.",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/i18n-enhance",
|
||||||
|
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/i18n-enhance.html",
|
||||||
|
|
||||||
|
"plugins": [{
|
||||||
|
"name": "bootstrap-table-i18n-enhance",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/i18n-enhance"
|
||||||
|
}],
|
||||||
|
|
||||||
|
"author": {
|
||||||
|
"name": "Jewway",
|
||||||
|
"image": "https://avatars0.githubusercontent.com/u/3501899"
|
||||||
|
}
|
||||||
|
}
|
80
InvenTree/InvenTree/static/bootstrap-table/extensions/key-events/bootstrap-table-key-events.js
vendored
Normal file
80
InvenTree/InvenTree/static/bootstrap-table/extensions/key-events/bootstrap-table-key-events.js
vendored
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
/**
|
||||||
|
* @author: Dennis Hernández
|
||||||
|
* @webSite: http://djhvscf.github.io/Blog
|
||||||
|
* @version: v1.0.0
|
||||||
|
*
|
||||||
|
* @update zhixin wen <wenzhixin2010@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
!function ($) {
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, {
|
||||||
|
keyEvents: false
|
||||||
|
});
|
||||||
|
|
||||||
|
var BootstrapTable = $.fn.bootstrapTable.Constructor,
|
||||||
|
_init = BootstrapTable.prototype.init;
|
||||||
|
|
||||||
|
BootstrapTable.prototype.init = function () {
|
||||||
|
_init.apply(this, Array.prototype.slice.apply(arguments));
|
||||||
|
this.initKeyEvents();
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.initKeyEvents = function () {
|
||||||
|
if (this.options.keyEvents) {
|
||||||
|
var that = this;
|
||||||
|
|
||||||
|
$(document).off('keydown').on('keydown', function (e) {
|
||||||
|
var $search = that.$toolbar.find('.search input'),
|
||||||
|
$refresh = that.$toolbar.find('button[name="refresh"]'),
|
||||||
|
$toggle = that.$toolbar.find('button[name="toggle"]'),
|
||||||
|
$paginationSwitch = that.$toolbar.find('button[name="paginationSwitch"]');
|
||||||
|
|
||||||
|
if (document.activeElement === $search.get(0) || !$.contains(document.activeElement ,that.$toolbar.get(0))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (e.keyCode) {
|
||||||
|
case 83: //s
|
||||||
|
if (!that.options.search) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$search.focus();
|
||||||
|
return false;
|
||||||
|
case 82: //r
|
||||||
|
if (!that.options.showRefresh) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$refresh.click();
|
||||||
|
return false;
|
||||||
|
case 84: //t
|
||||||
|
if (!that.options.showToggle) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$toggle.click();
|
||||||
|
return false;
|
||||||
|
case 80: //p
|
||||||
|
if (!that.options.showPaginationSwitch) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$paginationSwitch.click();
|
||||||
|
return false;
|
||||||
|
case 37: // left
|
||||||
|
if (!that.options.pagination) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
that.prevPage();
|
||||||
|
return false;
|
||||||
|
case 39: // right
|
||||||
|
if (!that.options.pagination) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
that.nextPage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}(jQuery);
|
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "Key Events",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Plugin to support the key events in the bootstrap table.",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/key-events",
|
||||||
|
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/key-events.html",
|
||||||
|
|
||||||
|
"plugins": [{
|
||||||
|
"name": "bootstrap-table-key-events",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/key-events"
|
||||||
|
}],
|
||||||
|
|
||||||
|
"author": {
|
||||||
|
"name": "djhvscf",
|
||||||
|
"image": "https://avatars1.githubusercontent.com/u/4496763"
|
||||||
|
}
|
||||||
|
}
|
136
InvenTree/InvenTree/static/bootstrap-table/extensions/mobile/bootstrap-table-mobile.js
vendored
Normal file
136
InvenTree/InvenTree/static/bootstrap-table/extensions/mobile/bootstrap-table-mobile.js
vendored
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
/**
|
||||||
|
* @author: Dennis Hernández
|
||||||
|
* @webSite: http://djhvscf.github.io/Blog
|
||||||
|
* @version: v1.1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
!function ($) {
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var showHideColumns = function (that, checked) {
|
||||||
|
if (that.options.columnsHidden.length > 0 ) {
|
||||||
|
$.each(that.columns, function (i, column) {
|
||||||
|
if (that.options.columnsHidden.indexOf(column.field) !== -1) {
|
||||||
|
if (column.visible !== checked) {
|
||||||
|
that.toggleColumn(that.fieldsColumnsIndex[column.field], checked, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var resetView = function (that) {
|
||||||
|
if (that.options.height || that.options.showFooter) {
|
||||||
|
setTimeout(function(){
|
||||||
|
that.resetView.call(that);
|
||||||
|
}, 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var changeView = function (that, width, height) {
|
||||||
|
if (that.options.minHeight) {
|
||||||
|
if ((width <= that.options.minWidth) && (height <= that.options.minHeight)) {
|
||||||
|
conditionCardView(that);
|
||||||
|
} else if ((width > that.options.minWidth) && (height > that.options.minHeight)) {
|
||||||
|
conditionFullView(that);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (width <= that.options.minWidth) {
|
||||||
|
conditionCardView(that);
|
||||||
|
} else if (width > that.options.minWidth) {
|
||||||
|
conditionFullView(that);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resetView(that);
|
||||||
|
};
|
||||||
|
|
||||||
|
var conditionCardView = function (that) {
|
||||||
|
changeTableView(that, false);
|
||||||
|
showHideColumns(that, false);
|
||||||
|
};
|
||||||
|
|
||||||
|
var conditionFullView = function (that) {
|
||||||
|
changeTableView(that, true);
|
||||||
|
showHideColumns(that, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
var changeTableView = function (that, cardViewState) {
|
||||||
|
that.options.cardView = cardViewState;
|
||||||
|
that.toggleView();
|
||||||
|
};
|
||||||
|
|
||||||
|
var debounce = function(func,wait) {
|
||||||
|
var timeout;
|
||||||
|
return function() {
|
||||||
|
var context = this,
|
||||||
|
args = arguments;
|
||||||
|
var later = function() {
|
||||||
|
timeout = null;
|
||||||
|
func.apply(context,args);
|
||||||
|
};
|
||||||
|
clearTimeout(timeout);
|
||||||
|
timeout = setTimeout(later, wait);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, {
|
||||||
|
mobileResponsive: false,
|
||||||
|
minWidth: 562,
|
||||||
|
minHeight: undefined,
|
||||||
|
heightThreshold: 100, // just slightly larger than mobile chrome's auto-hiding toolbar
|
||||||
|
checkOnInit: true,
|
||||||
|
columnsHidden: []
|
||||||
|
});
|
||||||
|
|
||||||
|
var BootstrapTable = $.fn.bootstrapTable.Constructor,
|
||||||
|
_init = BootstrapTable.prototype.init;
|
||||||
|
|
||||||
|
BootstrapTable.prototype.init = function () {
|
||||||
|
_init.apply(this, Array.prototype.slice.apply(arguments));
|
||||||
|
|
||||||
|
if (!this.options.mobileResponsive) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.options.minWidth) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.options.minWidth < 100 && this.options.resizable) {
|
||||||
|
console.log("The minWidth when the resizable extension is active should be greater or equal than 100");
|
||||||
|
this.options.minWidth = 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
var that = this,
|
||||||
|
old = {
|
||||||
|
width: $(window).width(),
|
||||||
|
height: $(window).height()
|
||||||
|
};
|
||||||
|
|
||||||
|
$(window).on('resize orientationchange',debounce(function (evt) {
|
||||||
|
// reset view if height has only changed by at least the threshold.
|
||||||
|
var height = $(this).height(),
|
||||||
|
width = $(this).width();
|
||||||
|
|
||||||
|
if (Math.abs(old.height - height) > that.options.heightThreshold || old.width != width) {
|
||||||
|
changeView(that, width, height);
|
||||||
|
old = {
|
||||||
|
width: width,
|
||||||
|
height: height
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},200));
|
||||||
|
|
||||||
|
if (this.options.checkOnInit) {
|
||||||
|
var height = $(window).height(),
|
||||||
|
width = $(window).width();
|
||||||
|
changeView(this, width, height);
|
||||||
|
old = {
|
||||||
|
width: width,
|
||||||
|
height: height
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}(jQuery);
|
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "Mobile",
|
||||||
|
"version": "1.1.0",
|
||||||
|
"description": "Plugin to support the responsive feature.",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/mobile",
|
||||||
|
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/mobile.html",
|
||||||
|
|
||||||
|
"plugins": [{
|
||||||
|
"name": "bootstrap-table-mobile",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/mobile"
|
||||||
|
}],
|
||||||
|
|
||||||
|
"author": {
|
||||||
|
"name": "djhvscf",
|
||||||
|
"image": "https://avatars1.githubusercontent.com/u/4496763"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,88 @@
|
|||||||
|
/**
|
||||||
|
* @author Homer Glascock <HopGlascock@gmail.com>
|
||||||
|
* @version: v1.0.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
!function ($) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var sprintf = $.fn.bootstrapTable.utils.sprintf;
|
||||||
|
|
||||||
|
var reInit = function (self) {
|
||||||
|
self.initHeader();
|
||||||
|
self.initSearch();
|
||||||
|
self.initPagination();
|
||||||
|
self.initBody();
|
||||||
|
};
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, {
|
||||||
|
showToggleBtn: false,
|
||||||
|
multiToggleDefaults: [], //column names go here
|
||||||
|
});
|
||||||
|
|
||||||
|
$.fn.bootstrapTable.methods.push('hideAllColumns', 'showAllColumns');
|
||||||
|
|
||||||
|
var BootstrapTable = $.fn.bootstrapTable.Constructor,
|
||||||
|
_initToolbar = BootstrapTable.prototype.initToolbar;
|
||||||
|
|
||||||
|
BootstrapTable.prototype.initToolbar = function () {
|
||||||
|
|
||||||
|
_initToolbar.apply(this, Array.prototype.slice.apply(arguments));
|
||||||
|
|
||||||
|
var that = this,
|
||||||
|
$btnGroup = this.$toolbar.find('>.btn-group');
|
||||||
|
|
||||||
|
if (typeof this.options.multiToggleDefaults === 'string') {
|
||||||
|
this.options.multiToggleDefaults = JSON.parse(this.options.multiToggleDefaults);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.options.showToggleBtn && this.options.showColumns) {
|
||||||
|
var showbtn = "<button class='btn btn-default hidden' id='showAllBtn'><span class='glyphicon glyphicon-resize-full icon-zoom-in'></span></button>",
|
||||||
|
hidebtn = "<button class='btn btn-default' id='hideAllBtn'><span class='glyphicon glyphicon-resize-small icon-zoom-out'></span></button>";
|
||||||
|
|
||||||
|
$btnGroup.append(showbtn + hidebtn);
|
||||||
|
|
||||||
|
$btnGroup.find('#showAllBtn').click(function () { that.showAllColumns();
|
||||||
|
$btnGroup.find('#hideAllBtn').toggleClass('hidden');
|
||||||
|
$btnGroup.find('#showAllBtn').toggleClass('hidden');
|
||||||
|
});
|
||||||
|
$btnGroup.find('#hideAllBtn').click(function () { that.hideAllColumns();
|
||||||
|
$btnGroup.find('#hideAllBtn').toggleClass('hidden');
|
||||||
|
$btnGroup.find('#showAllBtn').toggleClass('hidden');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.hideAllColumns = function () {
|
||||||
|
var that = this,
|
||||||
|
defaults = that.options.multiToggleDefaults;
|
||||||
|
|
||||||
|
$.each(this.columns, function (index, column) {
|
||||||
|
//if its one of the defaults dont touch it
|
||||||
|
if (defaults.indexOf(column.field) == -1 && column.switchable) {
|
||||||
|
column.visible = false;
|
||||||
|
var $items = that.$toolbar.find('.keep-open input').prop('disabled', false);
|
||||||
|
$items.filter(sprintf('[value="%s"]', index)).prop('checked', false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
reInit(that);
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.showAllColumns = function () {
|
||||||
|
var that = this;
|
||||||
|
$.each(this.columns, function (index, column) {
|
||||||
|
if (column.switchable) {
|
||||||
|
column.visible = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var $items = that.$toolbar.find('.keep-open input').prop('disabled', false);
|
||||||
|
$items.filter(sprintf('[value="%s"]', index)).prop('checked', true);
|
||||||
|
});
|
||||||
|
|
||||||
|
reInit(that);
|
||||||
|
|
||||||
|
that.toggleColumn(0, that.columns[0].visible, false);
|
||||||
|
};
|
||||||
|
|
||||||
|
}(jQuery);
|
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "Multi Column Toggle",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Allows hiding and showing of multiple columns at once.",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/multi-column-toggle",
|
||||||
|
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/multi-column-toggle.html",
|
||||||
|
|
||||||
|
"plugins": [{
|
||||||
|
"name": "multi-column-toggle",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/multi-column-toggle"
|
||||||
|
}],
|
||||||
|
|
||||||
|
"author": {
|
||||||
|
"name": "Homer Glascock",
|
||||||
|
"image": "https://avatars1.githubusercontent.com/u/5546710"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,71 @@
|
|||||||
|
/**
|
||||||
|
* @author: Dennis Hernández
|
||||||
|
* @webSite: http://djhvscf.github.io/Blog
|
||||||
|
* @version: v1.0.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
!function ($) {
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, {
|
||||||
|
multipleSearch: false,
|
||||||
|
delimeter: " "
|
||||||
|
});
|
||||||
|
|
||||||
|
var BootstrapTable = $.fn.bootstrapTable.Constructor,
|
||||||
|
_initSearch = BootstrapTable.prototype.initSearch;
|
||||||
|
|
||||||
|
BootstrapTable.prototype.initSearch = function () {
|
||||||
|
if (this.options.multipleSearch) {
|
||||||
|
if (this.searchText === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var strArray = this.searchText.split(this.options.delimeter),
|
||||||
|
that = this,
|
||||||
|
f = $.isEmptyObject(this.filterColumns) ? null : this.filterColumns,
|
||||||
|
dataFiltered = [];
|
||||||
|
|
||||||
|
if (strArray.length === 1) {
|
||||||
|
_initSearch.apply(this, Array.prototype.slice.apply(arguments));
|
||||||
|
} else {
|
||||||
|
for (var i = 0; i < strArray.length; i++) {
|
||||||
|
var str = strArray[i].trim();
|
||||||
|
dataFiltered = str ? $.grep(dataFiltered.length === 0 ? this.options.data : dataFiltered, function (item, i) {
|
||||||
|
for (var key in item) {
|
||||||
|
key = $.isNumeric(key) ? parseInt(key, 10) : key;
|
||||||
|
var value = item[key],
|
||||||
|
column = that.columns[that.fieldsColumnsIndex[key]],
|
||||||
|
j = $.inArray(key, that.header.fields);
|
||||||
|
|
||||||
|
// Fix #142: search use formated data
|
||||||
|
if (column && column.searchFormatter) {
|
||||||
|
value = $.fn.bootstrapTable.utils.calculateObjectValue(column,
|
||||||
|
that.header.formatters[j], [value, item, i], value);
|
||||||
|
}
|
||||||
|
|
||||||
|
var index = $.inArray(key, that.header.fields);
|
||||||
|
if (index !== -1 && that.header.searchables[index] && (typeof value === 'string' || typeof value === 'number')) {
|
||||||
|
if (that.options.strictSearch) {
|
||||||
|
if ((value + '').toLowerCase() === str) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ((value + '').toLowerCase().indexOf(str) !== -1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}) : this.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.data = dataFiltered;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_initSearch.apply(this, Array.prototype.slice.apply(arguments));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}(jQuery);
|
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "Multiple Search",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Plugin to support the multiple search.",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/multiple-search",
|
||||||
|
"example": "#",
|
||||||
|
|
||||||
|
"plugins": [{
|
||||||
|
"name": "bootstrap-table-multiple-search",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/multiple-search"
|
||||||
|
}],
|
||||||
|
|
||||||
|
"author": {
|
||||||
|
"name": "djhvscf",
|
||||||
|
"image": "https://avatars1.githubusercontent.com/u/4496763"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
.multiple-select-row-selected {
|
||||||
|
background: lightBlue
|
||||||
|
}
|
||||||
|
|
||||||
|
.table tbody tr:hover td,
|
||||||
|
.table tbody tr:hover th {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.table-striped tbody tr:nth-child(odd):hover td {
|
||||||
|
background-color: #F9F9F9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fixed-table-container tbody .selected td {
|
||||||
|
background: lightBlue;
|
||||||
|
}
|
@ -0,0 +1,127 @@
|
|||||||
|
/**
|
||||||
|
* @author: Dennis Hernández
|
||||||
|
* @webSite: http://djhvscf.github.io/Blog
|
||||||
|
* @version: v1.0.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
!function ($) {
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
document.onselectstart = function() {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
var getTableObjectFromCurrentTarget = function (currentTarget) {
|
||||||
|
currentTarget = $(currentTarget);
|
||||||
|
return currentTarget.is("table") ? currentTarget : currentTarget.parents().find(".table");
|
||||||
|
};
|
||||||
|
|
||||||
|
var getRow = function (target) {
|
||||||
|
target = $(target);
|
||||||
|
return target.parent().parent();
|
||||||
|
};
|
||||||
|
|
||||||
|
var onRowClick = function (e) {
|
||||||
|
var that = getTableObjectFromCurrentTarget(e.currentTarget);
|
||||||
|
|
||||||
|
if (window.event.ctrlKey) {
|
||||||
|
toggleRow(e.currentTarget, that, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window.event.button === 0) {
|
||||||
|
if (!window.event.ctrlKey && !window.event.shiftKey) {
|
||||||
|
clearAll(that);
|
||||||
|
toggleRow(e.currentTarget, that, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window.event.shiftKey) {
|
||||||
|
selectRowsBetweenIndexes([that.bootstrapTable("getOptions").multipleSelectRowLastSelectedRow.rowIndex, e.currentTarget.rowIndex], that)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var onCheckboxChange = function (e) {
|
||||||
|
var that = getTableObjectFromCurrentTarget(e.currentTarget);
|
||||||
|
clearAll(that);
|
||||||
|
toggleRow(getRow(e.currentTarget), that, false, false);
|
||||||
|
};
|
||||||
|
|
||||||
|
var toggleRow = function (row, that, clearAll, useShift) {
|
||||||
|
if (clearAll) {
|
||||||
|
row = $(row);
|
||||||
|
that.bootstrapTable("getOptions").multipleSelectRowLastSelectedRow = undefined;
|
||||||
|
row.removeClass(that.bootstrapTable("getOptions").multipleSelectRowCssClass);
|
||||||
|
that.bootstrapTable("uncheck", row.data("index"));
|
||||||
|
} else {
|
||||||
|
that.bootstrapTable("getOptions").multipleSelectRowLastSelectedRow = row;
|
||||||
|
row = $(row);
|
||||||
|
if (useShift) {
|
||||||
|
row.addClass(that.bootstrapTable("getOptions").multipleSelectRowCssClass);
|
||||||
|
that.bootstrapTable("check", row.data("index"));
|
||||||
|
} else {
|
||||||
|
if(row.hasClass(that.bootstrapTable("getOptions").multipleSelectRowCssClass)) {
|
||||||
|
row.removeClass(that.bootstrapTable("getOptions").multipleSelectRowCssClass)
|
||||||
|
that.bootstrapTable("uncheck", row.data("index"));
|
||||||
|
} else {
|
||||||
|
row.addClass(that.bootstrapTable("getOptions").multipleSelectRowCssClass);
|
||||||
|
that.bootstrapTable("check", row.data("index"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var selectRowsBetweenIndexes = function (indexes, that) {
|
||||||
|
indexes.sort(function(a, b) {
|
||||||
|
return a - b;
|
||||||
|
});
|
||||||
|
|
||||||
|
for (var i = indexes[0]; i <= indexes[1]; i++) {
|
||||||
|
toggleRow(that.bootstrapTable("getOptions").multipleSelectRowRows[i-1], that, false, true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var clearAll = function (that) {
|
||||||
|
for (var i = 0; i < that.bootstrapTable("getOptions").multipleSelectRowRows.length; i++) {
|
||||||
|
toggleRow(that.bootstrapTable("getOptions").multipleSelectRowRows[i], that, true, false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, {
|
||||||
|
multipleSelectRow: false,
|
||||||
|
multipleSelectRowCssClass: 'multiple-select-row-selected',
|
||||||
|
//internal variables used by the extension
|
||||||
|
multipleSelectRowLastSelectedRow: undefined,
|
||||||
|
multipleSelectRowRows: []
|
||||||
|
});
|
||||||
|
|
||||||
|
var BootstrapTable = $.fn.bootstrapTable.Constructor,
|
||||||
|
_init = BootstrapTable.prototype.init,
|
||||||
|
_initBody = BootstrapTable.prototype.initBody;
|
||||||
|
|
||||||
|
BootstrapTable.prototype.init = function () {
|
||||||
|
if (this.options.multipleSelectRow) {
|
||||||
|
var that = this;
|
||||||
|
|
||||||
|
//Make sure that the internal variables have the correct value
|
||||||
|
this.options.multipleSelectRowLastSelectedRow = undefined;
|
||||||
|
this.options.multipleSelectRowRows = [];
|
||||||
|
|
||||||
|
this.$el.on("post-body.bs.table", function (e) {
|
||||||
|
setTimeout(function () {
|
||||||
|
that.options.multipleSelectRowRows = that.$body.children();
|
||||||
|
that.options.multipleSelectRowRows.click(onRowClick);
|
||||||
|
that.options.multipleSelectRowRows.find("input[type=checkbox]").change(onCheckboxChange);
|
||||||
|
}, 1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_init.apply(this, Array.prototype.slice.apply(arguments));
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.clearAllMultipleSelectionRow = function () {
|
||||||
|
clearAll(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
$.fn.bootstrapTable.methods.push('clearAllMultipleSelectionRow');
|
||||||
|
}(jQuery);
|
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "Multiple Selection Row",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Plugin to enable the multiple selection row. You can use the ctrl+click to select one row or use ctrl+shift+click to select a range of rows.",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/multiple-selection-row",
|
||||||
|
"example": "",
|
||||||
|
|
||||||
|
"plugins": [{
|
||||||
|
"name": "bootstrap-table-multiple-selection-row",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/multiple-selection-row"
|
||||||
|
}],
|
||||||
|
|
||||||
|
"author": {
|
||||||
|
"name": "djhvscf",
|
||||||
|
"image": "https://avatars1.githubusercontent.com/u/4496763"
|
||||||
|
}
|
||||||
|
}
|
412
InvenTree/InvenTree/static/bootstrap-table/extensions/multiple-sort/bootstrap-table-multiple-sort.js
vendored
Normal file
412
InvenTree/InvenTree/static/bootstrap-table/extensions/multiple-sort/bootstrap-table-multiple-sort.js
vendored
Normal file
@ -0,0 +1,412 @@
|
|||||||
|
/**
|
||||||
|
* @author Nadim Basalamah <dimbslmh@gmail.com>
|
||||||
|
* @version: v1.1.0
|
||||||
|
* https://github.com/dimbslmh/bootstrap-table/tree/master/src/extensions/multiple-sort/bootstrap-table-multiple-sort.js
|
||||||
|
* Modification: ErwannNevou <https://github.com/ErwannNevou>
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function($) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var isSingleSort = false;
|
||||||
|
|
||||||
|
var showSortModal = function(that) {
|
||||||
|
var _selector = that.sortModalSelector,
|
||||||
|
_id = '#' + _selector;
|
||||||
|
|
||||||
|
if (!$(_id).hasClass("modal")) {
|
||||||
|
var sModal = ' <div class="modal fade" id="' + _selector + '" tabindex="-1" role="dialog" aria-labelledby="' + _selector + 'Label" aria-hidden="true">';
|
||||||
|
sModal += ' <div class="modal-dialog">';
|
||||||
|
sModal += ' <div class="modal-content">';
|
||||||
|
sModal += ' <div class="modal-header">';
|
||||||
|
sModal += ' <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>';
|
||||||
|
sModal += ' <h4 class="modal-title" id="' + _selector + 'Label">' + that.options.formatMultipleSort() + '</h4>';
|
||||||
|
sModal += ' </div>';
|
||||||
|
sModal += ' <div class="modal-body">';
|
||||||
|
sModal += ' <div class="bootstrap-table">';
|
||||||
|
sModal += ' <div class="fixed-table-toolbar">';
|
||||||
|
sModal += ' <div class="bars">';
|
||||||
|
sModal += ' <div id="toolbar">';
|
||||||
|
sModal += ' <button id="add" type="button" class="btn btn-default"><i class="' + that.options.iconsPrefix + ' ' + that.options.icons.plus + '"></i> ' + that.options.formatAddLevel() + '</button>';
|
||||||
|
sModal += ' <button id="delete" type="button" class="btn btn-default" disabled><i class="' + that.options.iconsPrefix + ' ' + that.options.icons.minus + '"></i> ' + that.options.formatDeleteLevel() + '</button>';
|
||||||
|
sModal += ' </div>';
|
||||||
|
sModal += ' </div>';
|
||||||
|
sModal += ' </div>';
|
||||||
|
sModal += ' <div class="fixed-table-container">';
|
||||||
|
sModal += ' <table id="multi-sort" class="table">';
|
||||||
|
sModal += ' <thead>';
|
||||||
|
sModal += ' <tr>';
|
||||||
|
sModal += ' <th></th>';
|
||||||
|
sModal += ' <th><div class="th-inner">' + that.options.formatColumn() + '</div></th>';
|
||||||
|
sModal += ' <th><div class="th-inner">' + that.options.formatOrder() + '</div></th>';
|
||||||
|
sModal += ' </tr>';
|
||||||
|
sModal += ' </thead>';
|
||||||
|
sModal += ' <tbody></tbody>';
|
||||||
|
sModal += ' </table>';
|
||||||
|
sModal += ' </div>';
|
||||||
|
sModal += ' </div>';
|
||||||
|
sModal += ' </div>';
|
||||||
|
sModal += ' <div class="modal-footer">';
|
||||||
|
sModal += ' <button type="button" class="btn btn-default" data-dismiss="modal">' + that.options.formatCancel() + '</button>';
|
||||||
|
sModal += ' <button type="button" class="btn btn-primary">' + that.options.formatSort() + '</button>';
|
||||||
|
sModal += ' </div>';
|
||||||
|
sModal += ' </div>';
|
||||||
|
sModal += ' </div>';
|
||||||
|
sModal += ' </div>';
|
||||||
|
|
||||||
|
$('body').append($(sModal));
|
||||||
|
|
||||||
|
that.$sortModal = $(_id);
|
||||||
|
var $rows = that.$sortModal.find('tbody > tr');
|
||||||
|
|
||||||
|
that.$sortModal.off('click', '#add').on('click', '#add', function() {
|
||||||
|
var total = that.$sortModal.find('.multi-sort-name:first option').length,
|
||||||
|
current = that.$sortModal.find('tbody tr').length;
|
||||||
|
|
||||||
|
if (current < total) {
|
||||||
|
current++;
|
||||||
|
that.addLevel();
|
||||||
|
that.setButtonStates();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
that.$sortModal.off('click', '#delete').on('click', '#delete', function() {
|
||||||
|
var total = that.$sortModal.find('.multi-sort-name:first option').length,
|
||||||
|
current = that.$sortModal.find('tbody tr').length;
|
||||||
|
|
||||||
|
if (current > 1 && current <= total) {
|
||||||
|
current--;
|
||||||
|
that.$sortModal.find('tbody tr:last').remove();
|
||||||
|
that.setButtonStates();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
that.$sortModal.off('click', '.btn-primary').on('click', '.btn-primary', function() {
|
||||||
|
var $rows = that.$sortModal.find('tbody > tr'),
|
||||||
|
$alert = that.$sortModal.find('div.alert'),
|
||||||
|
fields = [],
|
||||||
|
results = [];
|
||||||
|
|
||||||
|
|
||||||
|
that.options.sortPriority = $.map($rows, function(row) {
|
||||||
|
var $row = $(row),
|
||||||
|
name = $row.find('.multi-sort-name').val(),
|
||||||
|
order = $row.find('.multi-sort-order').val();
|
||||||
|
|
||||||
|
fields.push(name);
|
||||||
|
|
||||||
|
return {
|
||||||
|
sortName: name,
|
||||||
|
sortOrder: order
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
var sorted_fields = fields.sort();
|
||||||
|
|
||||||
|
for (var i = 0; i < fields.length - 1; i++) {
|
||||||
|
if (sorted_fields[i + 1] == sorted_fields[i]) {
|
||||||
|
results.push(sorted_fields[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (results.length > 0) {
|
||||||
|
if ($alert.length === 0) {
|
||||||
|
$alert = '<div class="alert alert-danger" role="alert"><strong>' + that.options.formatDuplicateAlertTitle() + '</strong> ' + that.options.formatDuplicateAlertDescription() + '</div>';
|
||||||
|
$($alert).insertBefore(that.$sortModal.find('.bars'));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ($alert.length === 1) {
|
||||||
|
$($alert).remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
that.$sortModal.modal('hide');
|
||||||
|
that.options.sortName = '';
|
||||||
|
|
||||||
|
if (that.options.sidePagination === 'server') {
|
||||||
|
var t = that.options.queryParams;
|
||||||
|
that.options.queryParams = function(params) {
|
||||||
|
params.multiSort = that.options.sortPriority;
|
||||||
|
return t(params);
|
||||||
|
};
|
||||||
|
isSingleSort=false;
|
||||||
|
that.initServer(that.options.silentSort);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
that.onMultipleSort();
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (that.options.sortPriority === null || that.options.sortPriority.length === 0) {
|
||||||
|
if (that.options.sortName) {
|
||||||
|
that.options.sortPriority = [{
|
||||||
|
sortName: that.options.sortName,
|
||||||
|
sortOrder: that.options.sortOrder
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (that.options.sortPriority !== null && that.options.sortPriority.length > 0) {
|
||||||
|
if ($rows.length < that.options.sortPriority.length && typeof that.options.sortPriority === 'object') {
|
||||||
|
for (var i = 0; i < that.options.sortPriority.length; i++) {
|
||||||
|
that.addLevel(i, that.options.sortPriority[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
that.addLevel(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
that.setButtonStates();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$.fn.bootstrapTable.methods.push('multipleSort');
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, {
|
||||||
|
showMultiSort: false,
|
||||||
|
showMultiSortButton: true,
|
||||||
|
sortPriority: null,
|
||||||
|
onMultipleSort: function() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults.icons, {
|
||||||
|
sort: 'glyphicon-sort',
|
||||||
|
plus: 'glyphicon-plus',
|
||||||
|
minus: 'glyphicon-minus'
|
||||||
|
});
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.Constructor.EVENTS, {
|
||||||
|
'multiple-sort.bs.table': 'onMultipleSort'
|
||||||
|
});
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.locales, {
|
||||||
|
formatMultipleSort: function() {
|
||||||
|
return 'Multiple Sort';
|
||||||
|
},
|
||||||
|
formatAddLevel: function() {
|
||||||
|
return 'Add Level';
|
||||||
|
},
|
||||||
|
formatDeleteLevel: function() {
|
||||||
|
return 'Delete Level';
|
||||||
|
},
|
||||||
|
formatColumn: function() {
|
||||||
|
return 'Column';
|
||||||
|
},
|
||||||
|
formatOrder: function() {
|
||||||
|
return 'Order';
|
||||||
|
},
|
||||||
|
formatSortBy: function() {
|
||||||
|
return 'Sort by';
|
||||||
|
},
|
||||||
|
formatThenBy: function() {
|
||||||
|
return 'Then by';
|
||||||
|
},
|
||||||
|
formatSort: function() {
|
||||||
|
return 'Sort';
|
||||||
|
},
|
||||||
|
formatCancel: function() {
|
||||||
|
return 'Cancel';
|
||||||
|
},
|
||||||
|
formatDuplicateAlertTitle: function() {
|
||||||
|
return 'Duplicate(s) detected!';
|
||||||
|
},
|
||||||
|
formatDuplicateAlertDescription: function() {
|
||||||
|
return 'Please remove or change any duplicate column.';
|
||||||
|
},
|
||||||
|
formatSortOrders: function() {
|
||||||
|
return {
|
||||||
|
asc: 'Ascending',
|
||||||
|
desc: 'Descending'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales);
|
||||||
|
|
||||||
|
var BootstrapTable = $.fn.bootstrapTable.Constructor,
|
||||||
|
_initToolbar = BootstrapTable.prototype.initToolbar;
|
||||||
|
|
||||||
|
BootstrapTable.prototype.initToolbar = function() {
|
||||||
|
this.showToolbar = this.showToolbar || this.options.showMultiSort;
|
||||||
|
var that = this,
|
||||||
|
sortModalSelector = 'sortModal_' + this.$el.attr('id'),
|
||||||
|
sortModalId = '#' + sortModalSelector;
|
||||||
|
this.$sortModal = $(sortModalId);
|
||||||
|
this.sortModalSelector = sortModalSelector;
|
||||||
|
|
||||||
|
_initToolbar.apply(this, Array.prototype.slice.apply(arguments));
|
||||||
|
|
||||||
|
if (that.options.sidePagination === 'server' && !isSingleSort && that.options.sortPriority !== null){
|
||||||
|
var t = that.options.queryParams;
|
||||||
|
that.options.queryParams = function(params) {
|
||||||
|
params.multiSort = that.options.sortPriority;
|
||||||
|
return t(params);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.options.showMultiSort) {
|
||||||
|
var $btnGroup = this.$toolbar.find('>.btn-group').first(),
|
||||||
|
$multiSortBtn = this.$toolbar.find('div.multi-sort');
|
||||||
|
|
||||||
|
if (!$multiSortBtn.length && this.options.showMultiSortButton) {
|
||||||
|
$multiSortBtn = ' <button class="multi-sort btn btn-default' + (this.options.iconSize === undefined ? '' : ' btn-' + this.options.iconSize) + '" type="button" data-toggle="modal" data-target="' + sortModalId + '" title="' + this.options.formatMultipleSort() + '">';
|
||||||
|
$multiSortBtn += ' <i class="' + this.options.iconsPrefix + ' ' + this.options.icons.sort + '"></i>';
|
||||||
|
$multiSortBtn += '</button>';
|
||||||
|
|
||||||
|
$btnGroup.append($multiSortBtn);
|
||||||
|
|
||||||
|
showSortModal(that);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$el.on('sort.bs.table', function() {
|
||||||
|
isSingleSort = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$el.on('multiple-sort.bs.table', function() {
|
||||||
|
isSingleSort = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$el.on('load-success.bs.table', function() {
|
||||||
|
if (!isSingleSort && that.options.sortPriority !== null && typeof that.options.sortPriority === 'object' && that.options.sidePagination !== 'server') {
|
||||||
|
that.onMultipleSort();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$el.on('column-switch.bs.table', function(field, checked) {
|
||||||
|
for (var i = 0; i < that.options.sortPriority.length; i++) {
|
||||||
|
if (that.options.sortPriority[i].sortName === checked) {
|
||||||
|
that.options.sortPriority.splice(i, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
that.assignSortableArrows();
|
||||||
|
that.$sortModal.remove();
|
||||||
|
showSortModal(that);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$el.on('reset-view.bs.table', function() {
|
||||||
|
if (!isSingleSort && that.options.sortPriority !== null && typeof that.options.sortPriority === 'object') {
|
||||||
|
that.assignSortableArrows();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.multipleSort = function() {
|
||||||
|
var that = this;
|
||||||
|
if (!isSingleSort && that.options.sortPriority !== null && typeof that.options.sortPriority === 'object' && that.options.sidePagination !== 'server') {
|
||||||
|
that.onMultipleSort();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.onMultipleSort = function() {
|
||||||
|
var that = this;
|
||||||
|
|
||||||
|
var cmp = function(x, y) {
|
||||||
|
return x > y ? 1 : x < y ? -1 : 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
var arrayCmp = function(a, b) {
|
||||||
|
var arr1 = [],
|
||||||
|
arr2 = [];
|
||||||
|
|
||||||
|
for (var i = 0; i < that.options.sortPriority.length; i++) {
|
||||||
|
var order = that.options.sortPriority[i].sortOrder === 'desc' ? -1 : 1,
|
||||||
|
aa = a[that.options.sortPriority[i].sortName],
|
||||||
|
bb = b[that.options.sortPriority[i].sortName];
|
||||||
|
|
||||||
|
if (aa === undefined || aa === null) {
|
||||||
|
aa = '';
|
||||||
|
}
|
||||||
|
if (bb === undefined || bb === null) {
|
||||||
|
bb = '';
|
||||||
|
}
|
||||||
|
if ($.isNumeric(aa) && $.isNumeric(bb)) {
|
||||||
|
aa = parseFloat(aa);
|
||||||
|
bb = parseFloat(bb);
|
||||||
|
}
|
||||||
|
if (typeof aa !== 'string') {
|
||||||
|
aa = aa.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
arr1.push(
|
||||||
|
order * cmp(aa, bb));
|
||||||
|
arr2.push(
|
||||||
|
order * cmp(bb, aa));
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmp(arr1, arr2);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.data.sort(function(a, b) {
|
||||||
|
return arrayCmp(a, b);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.initBody();
|
||||||
|
this.assignSortableArrows();
|
||||||
|
this.trigger('multiple-sort');
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.addLevel = function(index, sortPriority) {
|
||||||
|
var text = index === 0 ? this.options.formatSortBy() : this.options.formatThenBy();
|
||||||
|
|
||||||
|
this.$sortModal.find('tbody')
|
||||||
|
.append($('<tr>')
|
||||||
|
.append($('<td>').text(text))
|
||||||
|
.append($('<td>').append($('<select class="form-control multi-sort-name">')))
|
||||||
|
.append($('<td>').append($('<select class="form-control multi-sort-order">')))
|
||||||
|
);
|
||||||
|
|
||||||
|
var $multiSortName = this.$sortModal.find('.multi-sort-name').last(),
|
||||||
|
$multiSortOrder = this.$sortModal.find('.multi-sort-order').last();
|
||||||
|
|
||||||
|
$.each(this.columns, function(i, column) {
|
||||||
|
if (column.sortable === false || column.visible === false) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
$multiSortName.append('<option value="' + column.field + '">' + column.title + '</option>');
|
||||||
|
});
|
||||||
|
|
||||||
|
$.each(this.options.formatSortOrders(), function(value, order) {
|
||||||
|
$multiSortOrder.append('<option value="' + value + '">' + order + '</option>');
|
||||||
|
});
|
||||||
|
|
||||||
|
if (sortPriority !== undefined) {
|
||||||
|
$multiSortName.find('option[value="' + sortPriority.sortName + '"]').attr("selected", true);
|
||||||
|
$multiSortOrder.find('option[value="' + sortPriority.sortOrder + '"]').attr("selected", true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.assignSortableArrows = function() {
|
||||||
|
var that = this,
|
||||||
|
headers = that.$header.find('th');
|
||||||
|
|
||||||
|
for (var i = 0; i < headers.length; i++) {
|
||||||
|
for (var c = 0; c < that.options.sortPriority.length; c++) {
|
||||||
|
if ($(headers[i]).data('field') === that.options.sortPriority[c].sortName) {
|
||||||
|
$(headers[i]).find('.sortable').removeClass('desc asc').addClass(that.options.sortPriority[c].sortOrder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.setButtonStates = function() {
|
||||||
|
var total = this.$sortModal.find('.multi-sort-name:first option').length,
|
||||||
|
current = this.$sortModal.find('tbody tr').length;
|
||||||
|
|
||||||
|
if (current == total) {
|
||||||
|
this.$sortModal.find('#add').attr('disabled', 'disabled');
|
||||||
|
}
|
||||||
|
if (current > 1) {
|
||||||
|
this.$sortModal.find('#delete').removeAttr('disabled');
|
||||||
|
}
|
||||||
|
if (current < total) {
|
||||||
|
this.$sortModal.find('#add').removeAttr('disabled');
|
||||||
|
}
|
||||||
|
if (current == 1) {
|
||||||
|
this.$sortModal.find('#delete').attr('disabled', 'disabled');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})(jQuery);
|
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "Multiple Sort",
|
||||||
|
"version": "1.1.0",
|
||||||
|
"description": "Plugin to support the multiple sort.",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/multiple-sort",
|
||||||
|
"example": "#",
|
||||||
|
|
||||||
|
"plugins": [{
|
||||||
|
"name": "bootstrap-table-multiple-sort",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/multiple-sort"
|
||||||
|
}],
|
||||||
|
|
||||||
|
"author": {
|
||||||
|
"name": "dimbslmh",
|
||||||
|
"image": "https://avatars1.githubusercontent.com/u/745635"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
/**
|
||||||
|
* @author: Brian Huisman
|
||||||
|
* @webSite: http://www.greywyvern.com
|
||||||
|
* @version: v1.0.0
|
||||||
|
* JS functions to allow natural sorting on bootstrap-table columns
|
||||||
|
* add data-sorter="alphanum" or data-sorter="numericOnly" to any th
|
||||||
|
*
|
||||||
|
* @update Dennis Hernández <http://djhvscf.github.io/Blog>
|
||||||
|
* @update Duane May
|
||||||
|
*/
|
||||||
|
|
||||||
|
function alphanum(a, b) {
|
||||||
|
function chunkify(t) {
|
||||||
|
var tz = [],
|
||||||
|
x = 0,
|
||||||
|
y = -1,
|
||||||
|
n = 0,
|
||||||
|
i,
|
||||||
|
j;
|
||||||
|
|
||||||
|
while (i = (j = t.charAt(x++)).charCodeAt(0)) {
|
||||||
|
var m = (i === 46 || (i >= 48 && i <= 57));
|
||||||
|
if (m !== n) {
|
||||||
|
tz[++y] = "";
|
||||||
|
n = m;
|
||||||
|
}
|
||||||
|
tz[y] += j;
|
||||||
|
}
|
||||||
|
return tz;
|
||||||
|
}
|
||||||
|
|
||||||
|
function stringfy(v) {
|
||||||
|
if (typeof(v) === "number") {
|
||||||
|
v = "" + v;
|
||||||
|
}
|
||||||
|
if (!v) {
|
||||||
|
v = "";
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
var aa = chunkify(stringfy(a));
|
||||||
|
var bb = chunkify(stringfy(b));
|
||||||
|
|
||||||
|
for (x = 0; aa[x] && bb[x]; x++) {
|
||||||
|
if (aa[x] !== bb[x]) {
|
||||||
|
var c = Number(aa[x]),
|
||||||
|
d = Number(bb[x]);
|
||||||
|
|
||||||
|
if (c == aa[x] && d == bb[x]) {
|
||||||
|
return c - d;
|
||||||
|
} else {
|
||||||
|
return (aa[x] > bb[x]) ? 1 : -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return aa.length - bb.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
function numericOnly(a, b) {
|
||||||
|
function stripNonNumber(s) {
|
||||||
|
s = s.replace(new RegExp(/[^0-9]/g), "");
|
||||||
|
return parseInt(s, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
return stripNonNumber(a) - stripNonNumber(b);
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "Natural Sorting",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Plugin to support the natural sorting.",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/natural-sorting",
|
||||||
|
"example": "#",
|
||||||
|
|
||||||
|
"plugins": [{
|
||||||
|
"name": "bootstrap-table-natural-sorting",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/natural-sorting"
|
||||||
|
}],
|
||||||
|
|
||||||
|
"author": {
|
||||||
|
"name": "GreyWyvern",
|
||||||
|
"image": "https://avatars1.githubusercontent.com/u/137631"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
.jumpto input {
|
||||||
|
height: 31px;
|
||||||
|
width: 50px;
|
||||||
|
margin-left: 5px;
|
||||||
|
margin-right: 5px;
|
||||||
|
text-align: center;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
/**
|
||||||
|
* @author Jay <jwang@dizsoft.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function ($) {
|
||||||
|
'use strict';
|
||||||
|
var sprintf = $.fn.bootstrapTable.utils.sprintf;
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, {
|
||||||
|
showJumpto: false,
|
||||||
|
exportOptions: {}
|
||||||
|
});
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.locales, {
|
||||||
|
formatJumpto: function () {
|
||||||
|
return 'GO';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales);
|
||||||
|
|
||||||
|
var BootstrapTable = $.fn.bootstrapTable.Constructor,
|
||||||
|
_initPagination = BootstrapTable.prototype.initPagination;
|
||||||
|
|
||||||
|
BootstrapTable.prototype.initPagination = function () {
|
||||||
|
_initPagination.apply(this, Array.prototype.slice.apply(arguments));
|
||||||
|
|
||||||
|
if (this.options.showJumpto) {
|
||||||
|
var that = this,
|
||||||
|
$pageGroup = this.$pagination.find('ul.pagination'),
|
||||||
|
$jumpto = $pageGroup.find('li.jumpto');
|
||||||
|
|
||||||
|
if (!$jumpto.length) {
|
||||||
|
$jumpto = $([
|
||||||
|
'<li class="jumpto">',
|
||||||
|
'<input type="text" class="form-control">',
|
||||||
|
'<button class="btn' +
|
||||||
|
sprintf(' btn-%s', this.options.buttonsClass) +
|
||||||
|
sprintf(' btn-%s', this.options.iconSize) +
|
||||||
|
'" title="' + this.options.formatJumpto() + '" ' +
|
||||||
|
' type="button">'+this.options.formatJumpto(),
|
||||||
|
'</button>',
|
||||||
|
'</li>'].join('')).appendTo($pageGroup);
|
||||||
|
|
||||||
|
$jumpto.find('button').click(function () {
|
||||||
|
that.selectPage(parseInt($jumpto.find('input').val()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})(jQuery);
|
@ -0,0 +1,21 @@
|
|||||||
|
(The MIT License)
|
||||||
|
|
||||||
|
Copyright (c) 2019 doug-the-guy <badlydrawnsun@yahoo.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
@ -0,0 +1,92 @@
|
|||||||
|
# Bootstrap Table Pipelining
|
||||||
|
|
||||||
|
Use Plugin: [bootstrap-table-pipeline]
|
||||||
|
|
||||||
|
This plugin enables client side data caching for server side requests which will
|
||||||
|
eliminate the need to issue a new request every page change. This will allow
|
||||||
|
for a performance balance for a large data set between returning all data at once
|
||||||
|
(client side paging) and a new server side request (server side paging).
|
||||||
|
|
||||||
|
There are two new options:
|
||||||
|
- usePipeline: enables this feature
|
||||||
|
- pipelineSize: the size of each cache window
|
||||||
|
|
||||||
|
The size of the pipeline must be evenly divisible by the current page size. This is
|
||||||
|
assured by rounding up to the nearest evenly divisible value. For example, if
|
||||||
|
the pipeline size is 4990 and the current page size is 25, then pipeline size will
|
||||||
|
be dynamically set to 5000.
|
||||||
|
|
||||||
|
The cache windows are computed based on the pipeline size and the total number of rows
|
||||||
|
returned by the server side query. For example, with pipeline size 500 and total rows
|
||||||
|
1300, the cache windows will be:
|
||||||
|
|
||||||
|
[{'lower': 0, 'upper': 499}, {'lower': 500, 'upper': 999}, {'lower': 1000, 'upper': 1499}]
|
||||||
|
|
||||||
|
Using the limit (i.e. the pipelineSize) and offset parameters, the server side request
|
||||||
|
**MUST** return only the data in the requested cache window **AND** the total number of rows.
|
||||||
|
To wit, the server side code must use the offset and limit parameters to prepare the response
|
||||||
|
data.
|
||||||
|
|
||||||
|
On a page change, the new offset is checked if it is within the current cache window. If so,
|
||||||
|
the requested page data is returned from the cached data set. Otherwise, a new server side
|
||||||
|
request will be issued for the new cache window.
|
||||||
|
|
||||||
|
The current cached data is only invalidated on these events:
|
||||||
|
- sorting
|
||||||
|
- searching
|
||||||
|
- page size change
|
||||||
|
- page change moves into a new cache window
|
||||||
|
|
||||||
|
There are two new events:
|
||||||
|
- cached-data-hit.bs.table: issued when cached data is used on a page change
|
||||||
|
- cached-data-reset.bs.table: issued when the cached data is invalidated and new server side request is issued
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
* Created with Bootstrap 4
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```
|
||||||
|
# assumed import of bootstrap and bootstrap-table assets
|
||||||
|
<script src="/path/to/bootstrap-table-pipeline.js"></script>
|
||||||
|
...
|
||||||
|
<table id="pipeline_table"
|
||||||
|
class="table table-striped"
|
||||||
|
data-method='post'
|
||||||
|
data-use-pipeline="true"
|
||||||
|
data-pipeline-size="5000"
|
||||||
|
data-pagination="true"
|
||||||
|
data-side-pagination="server"
|
||||||
|
data-page-size="50">
|
||||||
|
<thead><tr>
|
||||||
|
<th data-field="type" data-sortable="true">Type</th>
|
||||||
|
<th data-field="value" data-sortable="true">Value</th>
|
||||||
|
<th data-field="date" data-sortable="true">Date</th>
|
||||||
|
</tr></thead>
|
||||||
|
</table>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
### usePipeline
|
||||||
|
|
||||||
|
* type: Boolean
|
||||||
|
* description: Set true to enable pipelining
|
||||||
|
* default: `false`
|
||||||
|
|
||||||
|
## pipelineSize
|
||||||
|
|
||||||
|
* type: Integer
|
||||||
|
* description: Size of each cache window. Must be greater than 0
|
||||||
|
* default: `1000`
|
||||||
|
|
||||||
|
## Events
|
||||||
|
|
||||||
|
### onCachedDataHit(cached-data-hit.bs.table)
|
||||||
|
|
||||||
|
* Fires when paging was able to use the locally cached data.
|
||||||
|
|
||||||
|
### onCachedDataReset(cached-data-reset.bs.table)
|
||||||
|
|
||||||
|
* Fires when the locally cached data needed to be reset (i.e. on sorting, searching, page size change or paged out of current cache window)
|
330
InvenTree/InvenTree/static/bootstrap-table/extensions/pipeline/bootstrap-table-pipeline.js
vendored
Normal file
330
InvenTree/InvenTree/static/bootstrap-table/extensions/pipeline/bootstrap-table-pipeline.js
vendored
Normal file
@ -0,0 +1,330 @@
|
|||||||
|
/**
|
||||||
|
* @author doug-the-guy
|
||||||
|
* @version v1.0.0
|
||||||
|
*
|
||||||
|
* Boostrap Table Pipeline
|
||||||
|
* -----------------------
|
||||||
|
*
|
||||||
|
* This plugin enables client side data caching for server side requests which will
|
||||||
|
* eliminate the need to issue a new request every page change. This will allow
|
||||||
|
* for a performance balance for a large data set between returning all data at once
|
||||||
|
* (client side paging) and a new server side request (server side paging).
|
||||||
|
*
|
||||||
|
* There are two new options:
|
||||||
|
* - usePipeline: enables this feature
|
||||||
|
* - pipelineSize: the size of each cache window
|
||||||
|
*
|
||||||
|
* The size of the pipeline must be evenly divisible by the current page size. This is
|
||||||
|
* assured by rounding up to the nearest evenly divisible value. For example, if
|
||||||
|
* the pipeline size is 4990 and the current page size is 25, then pipeline size will
|
||||||
|
* be dynamically set to 5000.
|
||||||
|
*
|
||||||
|
* The cache windows are computed based on the pipeline size and the total number of rows
|
||||||
|
* returned by the server side query. For example, with pipeline size 500 and total rows
|
||||||
|
* 1300, the cache windows will be:
|
||||||
|
*
|
||||||
|
* [{'lower': 0, 'upper': 499}, {'lower': 500, 'upper': 999}, {'lower': 1000, 'upper': 1499}]
|
||||||
|
*
|
||||||
|
* Using the limit (i.e. the pipelineSize) and offset parameters, the server side request
|
||||||
|
* **MUST** return only the data in the requested cache window **AND** the total number of rows.
|
||||||
|
* To wit, the server side code must use the offset and limit parameters to prepare the response
|
||||||
|
* data.
|
||||||
|
*
|
||||||
|
* On a page change, the new offset is checked if it is within the current cache window. If so,
|
||||||
|
* the requested page data is returned from the cached data set. Otherwise, a new server side
|
||||||
|
* request will be issued for the new cache window.
|
||||||
|
*
|
||||||
|
* The current cached data is only invalidated on these events:
|
||||||
|
* * sorting
|
||||||
|
* * searching
|
||||||
|
* * page size change
|
||||||
|
* * page change moves into a new cache window
|
||||||
|
*
|
||||||
|
* There are two new events:
|
||||||
|
* - cached-data-hit.bs.table: issued when cached data is used on a page change
|
||||||
|
* - cached-data-reset.bs.table: issued when the cached data is invalidated and a
|
||||||
|
* new server side request is issued
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
(function ($) {
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Utils = $.fn.bootstrapTable.utils;
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, {
|
||||||
|
usePipeline: false,
|
||||||
|
pipelineSize: 1000,
|
||||||
|
onCachedDataHit: function(data) {
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
onCachedDataReset: function(data){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.Constructor.EVENTS, {
|
||||||
|
'cached-data-hit.bs.table': 'onCachedDataHit',
|
||||||
|
'cached-data-reset.bs.table': 'onCachedDataReset'
|
||||||
|
});
|
||||||
|
|
||||||
|
var BootstrapTable = $.fn.bootstrapTable.Constructor,
|
||||||
|
_init = BootstrapTable.prototype.init,
|
||||||
|
_initServer = BootstrapTable.prototype.initServer,
|
||||||
|
_onSearch = BootstrapTable.prototype.onSearch,
|
||||||
|
_onSort = BootstrapTable.prototype.onSort,
|
||||||
|
_onPageListChange = BootstrapTable.prototype.onPageListChange;
|
||||||
|
|
||||||
|
BootstrapTable.prototype.init = function () {
|
||||||
|
// needs to be called before initServer()
|
||||||
|
this.initPipeline();
|
||||||
|
_init.apply(this, Array.prototype.slice.apply(arguments));
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.initPipeline = function() {
|
||||||
|
this.cacheRequestJSON = {};
|
||||||
|
this.cacheWindows = [];
|
||||||
|
this.currWindow = 0;
|
||||||
|
this.resetCache = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.onSearch = function(event) {
|
||||||
|
/* force a cache reset on search */
|
||||||
|
if (this.options.usePipeline) {
|
||||||
|
this.resetCache = true;
|
||||||
|
}
|
||||||
|
_onSearch.apply(this, Array.prototype.slice.apply(arguments));
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.onSort = function(event) {
|
||||||
|
/* force a cache reset on sort */
|
||||||
|
if (this.options.usePipeline) {
|
||||||
|
this.resetCache = true;
|
||||||
|
}
|
||||||
|
_onSort.apply(this, Array.prototype.slice.apply(arguments));
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.onPageListChange = function (event) {
|
||||||
|
/* rebuild cache window on page size change */
|
||||||
|
var target = $(event.currentTarget);
|
||||||
|
var newPageSize = parseInt(target.text());
|
||||||
|
this.options.pipelineSize = this.calculatePipelineSize(this.options.pipelineSize, newPageSize);
|
||||||
|
this.resetCache = true;
|
||||||
|
_onPageListChange.apply(this, Array.prototype.slice.apply(arguments));
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.calculatePipelineSize = function(pipelineSize, pageSize) {
|
||||||
|
/* calculate pipeline size by rounding up to the nearest value evenly divisible
|
||||||
|
* by the pageSize */
|
||||||
|
if(pageSize == 0) return 0;
|
||||||
|
return Math.ceil(pipelineSize/pageSize) * pageSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.setCacheWindows = function() {
|
||||||
|
/* set cache windows based on the total number of rows returned by server side
|
||||||
|
* request and the pipelineSize */
|
||||||
|
this.cacheWindows = [];
|
||||||
|
var numWindows = this.options.totalRows / this.options.pipelineSize;
|
||||||
|
for(var i = 0; i <= numWindows; i++){
|
||||||
|
var b = i * this.options.pipelineSize;
|
||||||
|
this.cacheWindows[i] = {'lower': b, 'upper': b + this.options.pipelineSize - 1};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.setCurrWindow = function(offset) {
|
||||||
|
/* set the current cache window index, based on where the current offset falls */
|
||||||
|
this.currWindow = 0;
|
||||||
|
for(var i = 0; i < this.cacheWindows.length; i++){
|
||||||
|
if(this.cacheWindows[i].lower <= offset && offset <= this.cacheWindows[i].upper){
|
||||||
|
this.currWindow = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.drawFromCache = function(offset, limit) {
|
||||||
|
/* draw rows from the cache using offset and limit */
|
||||||
|
var res = $.extend(true, {}, this.cacheRequestJSON);
|
||||||
|
var drawStart = offset - this.cacheWindows[this.currWindow].lower;
|
||||||
|
var drawEnd = drawStart + limit;
|
||||||
|
res.rows = res.rows.slice(drawStart, drawEnd);
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.initServer = function(silent, query, url){
|
||||||
|
/* determine if requested data is in cache (on paging) or if
|
||||||
|
* a new ajax request needs to be issued (sorting, searching, paging
|
||||||
|
* moving outside of cached data, page size change)
|
||||||
|
* initial version of this extension will entirely override base initServer
|
||||||
|
**/
|
||||||
|
|
||||||
|
var data = {};
|
||||||
|
var index = this.header.fields.indexOf(this.options.sortName);
|
||||||
|
|
||||||
|
var params = {
|
||||||
|
searchText: this.searchText,
|
||||||
|
sortName: this.options.sortName,
|
||||||
|
sortOrder: this.options.sortOrder
|
||||||
|
};
|
||||||
|
|
||||||
|
var request = null;
|
||||||
|
|
||||||
|
if (this.header.sortNames[index]) {
|
||||||
|
params.sortName = this.header.sortNames[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.options.pagination && this.options.sidePagination === 'server') {
|
||||||
|
params.pageSize = this.options.pageSize === this.options.formatAllRows()
|
||||||
|
? this.options.totalRows : this.options.pageSize
|
||||||
|
params.pageNumber = this.options.pageNumber
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(url || this.options.url) && !this.options.ajax) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var useAjax = true;
|
||||||
|
if (this.options.queryParamsType === 'limit') {
|
||||||
|
params = {
|
||||||
|
searchText: params.searchText,
|
||||||
|
sortName: params.sortName,
|
||||||
|
sortOrder: params.sortOrder
|
||||||
|
}
|
||||||
|
if (this.options.pagination && this.options.sidePagination === 'server') {
|
||||||
|
params.limit = this.options.pageSize === this.options.formatAllRows() ? this.options.totalRows : this.options.pageSize;
|
||||||
|
params.offset = (this.options.pageSize === this.options.formatAllRows() ? this.options.totalRows : this.options.pageSize) * (this.options.pageNumber - 1);
|
||||||
|
if (this.options.usePipeline) {
|
||||||
|
// if cacheWindows is empty, this is the initial request
|
||||||
|
if(!this.cacheWindows.length){
|
||||||
|
useAjax = true;
|
||||||
|
params.drawOffset = params.offset;
|
||||||
|
// cache exists: determine if the page request is entirely within the current cached window
|
||||||
|
} else {
|
||||||
|
var w = this.cacheWindows[this.currWindow];
|
||||||
|
// case 1: reset cache but stay within current window (e.g. column sort)
|
||||||
|
// case 2: move outside of the current window (e.g. search or paging)
|
||||||
|
// since each cache window is aligned with the current page size
|
||||||
|
// checking if params.offset is outside the current window is sufficient.
|
||||||
|
// need to requery for preceding or succeeding cache window
|
||||||
|
// also handle case
|
||||||
|
if(this.resetCache || (params.offset < w.lower || params.offset > w.upper)){
|
||||||
|
useAjax = true;
|
||||||
|
this.setCurrWindow(params.offset);
|
||||||
|
// store the relative offset for drawing the page data afterwards
|
||||||
|
params.drawOffset = params.offset;
|
||||||
|
// now set params.offset to the lower bound of the new cache window
|
||||||
|
// the server will return that whole cache window
|
||||||
|
params.offset = this.cacheWindows[this.currWindow].lower;
|
||||||
|
// within current cache window
|
||||||
|
} else {
|
||||||
|
useAjax = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (params.limit === 0) {
|
||||||
|
delete params.limit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// force an ajax call - this is on search, sort or page size change
|
||||||
|
if (this.resetCache) {
|
||||||
|
useAjax = true;
|
||||||
|
this.resetCache = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.options.usePipeline && useAjax) {
|
||||||
|
/* in this scenario limit is used on the server to get the cache window
|
||||||
|
* and drawLimit is used to get the page data afterwards */
|
||||||
|
params.drawLimit = params.limit;
|
||||||
|
params.limit = this.options.pipelineSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// cached results can be used
|
||||||
|
if(!useAjax) {
|
||||||
|
var res = this.drawFromCache(params.offset, params.limit);
|
||||||
|
this.load(res);
|
||||||
|
this.trigger('load-success', res);
|
||||||
|
this.trigger('cached-data-hit', res);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// cached results can't be used
|
||||||
|
// continue base initServer code
|
||||||
|
if (!($.isEmptyObject(this.filterColumnsPartial))) {
|
||||||
|
params.filter = JSON.stringify(this.filterColumnsPartial, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
data = Utils.calculateObjectValue(this.options, this.options.queryParams, [params], data);
|
||||||
|
|
||||||
|
$.extend(data, query || {});
|
||||||
|
|
||||||
|
// false to stop request
|
||||||
|
if (data === false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!silent) {
|
||||||
|
this.$tableLoading.show();
|
||||||
|
}
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
request = $.extend({}, Utils.calculateObjectValue(null, this.options.ajaxOptions), {
|
||||||
|
type: this.options.method,
|
||||||
|
url: url || this.options.url,
|
||||||
|
data: this.options.contentType === 'application/json' && this.options.method === 'post'
|
||||||
|
? JSON.stringify(data) : data,
|
||||||
|
cache: this.options.cache,
|
||||||
|
contentType: this.options.contentType,
|
||||||
|
dataType: this.options.dataType,
|
||||||
|
success: function(res){
|
||||||
|
res = Utils.calculateObjectValue(self.options, self.options.responseHandler, [res], res);
|
||||||
|
// cache results if using pipelining
|
||||||
|
if(self.options.usePipeline){
|
||||||
|
// store entire request in cache
|
||||||
|
self.cacheRequestJSON = $.extend(true, {}, res);
|
||||||
|
// this gets set in load() also but needs to be set before
|
||||||
|
// setting cacheWindows
|
||||||
|
self.options.totalRows = res[self.options.totalField];
|
||||||
|
// if this is a search, potentially less results will be returned
|
||||||
|
// so cache windows need to be rebuilt. Otherwise it
|
||||||
|
// will come out the same
|
||||||
|
self.setCacheWindows();
|
||||||
|
self.setCurrWindow(params.drawOffset);
|
||||||
|
// just load data for the page
|
||||||
|
res = self.drawFromCache(params.drawOffset, params.drawLimit);
|
||||||
|
self.trigger('cached-data-reset', res);
|
||||||
|
}
|
||||||
|
self.load(res);
|
||||||
|
self.trigger('load-success', res);
|
||||||
|
if (!silent) self.$tableLoading.hide();
|
||||||
|
},
|
||||||
|
error: function(res){
|
||||||
|
var data = [];
|
||||||
|
if (self.options.sidePagination === 'server') {
|
||||||
|
data = {};
|
||||||
|
data[self.options.totalField] = 0;
|
||||||
|
data[self.options.dataField] = [];
|
||||||
|
}
|
||||||
|
self.load(data);
|
||||||
|
self.trigger('load-error', res.status, res);
|
||||||
|
if (!silent) self.$tableLoading.hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (this.options.ajax) {
|
||||||
|
Utils.calculateObjectValue(this, this.options.ajax, [request], null);
|
||||||
|
} else {
|
||||||
|
if (this._xhr && this._xhr.readyState !== 4) {
|
||||||
|
this._xhr.abort();
|
||||||
|
}
|
||||||
|
this._xhr = $.ajax(request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$.fn.bootstrapTable.methods.push();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
})(jQuery);
|
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"name": "Pipeline",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Plugin to support a hybrid approach to server/client side paging.",
|
||||||
|
"url": "",
|
||||||
|
"example": "#",
|
||||||
|
|
||||||
|
"plugins": [{
|
||||||
|
"name": "bootstrap-table-pipeline",
|
||||||
|
"url": ""
|
||||||
|
}],
|
||||||
|
|
||||||
|
"author": {
|
||||||
|
"name": "doug-the-guy",
|
||||||
|
"image": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
149
InvenTree/InvenTree/static/bootstrap-table/extensions/print/bootstrap-table-print.js
vendored
Normal file
149
InvenTree/InvenTree/static/bootstrap-table/extensions/print/bootstrap-table-print.js
vendored
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
(function ($) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var sprintf = $.fn.bootstrapTable.utils.sprintf;
|
||||||
|
|
||||||
|
function printPageBuilderDefault(table) {
|
||||||
|
return '<html><head>' +
|
||||||
|
'<style type="text/css" media="print">' +
|
||||||
|
' @page { size: auto; margin: 25px 0 25px 0; }' +
|
||||||
|
'</style>' +
|
||||||
|
'<style type="text/css" media="all">' +
|
||||||
|
'table{border-collapse: collapse; font-size: 12px; }\n' +
|
||||||
|
'table, th, td {border: 1px solid grey}\n' +
|
||||||
|
'th, td {text-align: center; vertical-align: middle;}\n' +
|
||||||
|
'p {font-weight: bold; margin-left:20px }\n' +
|
||||||
|
'table { width:94%; margin-left:3%; margin-right:3%}\n' +
|
||||||
|
'div.bs-table-print { text-align:center;}\n' +
|
||||||
|
'</style></head><title>Print Table</title><body>' +
|
||||||
|
'<p>Printed on: ' + new Date + ' </p>' +
|
||||||
|
'<div class="bs-table-print">' + table + "</div></body></html>";
|
||||||
|
}
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, {
|
||||||
|
showPrint: false,
|
||||||
|
printAsFilteredAndSortedOnUI: true, //boolean, when true - print table as sorted and filtered on UI.
|
||||||
|
//Please note that if true is set, along with explicit predefined print options for filtering and sorting (printFilter, printSortOrder, printSortColumn)- then they will be applied on data already filtered and sorted by UI controls.
|
||||||
|
//For printing data as filtered and sorted on UI - do not set these 3 options:printFilter, printSortOrder, printSortColumn
|
||||||
|
|
||||||
|
printSortColumn: undefined , //String, set column field name to be sorted by
|
||||||
|
printSortOrder: 'asc', //String: 'asc' , 'desc' - relevant only if printSortColumn is set
|
||||||
|
printPageBuilder: function(table){return printPageBuilderDefault(table)} // function, receive html <table> element as string, returns html string for printing. by default delegates to function printPageBuilderDefault(table). used for styling and adding header or footer
|
||||||
|
});
|
||||||
|
$.extend($.fn.bootstrapTable.COLUMN_DEFAULTS, {
|
||||||
|
printFilter: undefined, //set value to filter by in print page
|
||||||
|
printIgnore: false, //boolean, set true to ignore this column in the print page
|
||||||
|
printFormatter:undefined //function(value, row, index), formats the cell value for this column in the printed table. Function behaviour is similar to the 'formatter' column option
|
||||||
|
|
||||||
|
});
|
||||||
|
$.extend($.fn.bootstrapTable.defaults.icons, {
|
||||||
|
print: 'glyphicon-print icon-share'
|
||||||
|
});
|
||||||
|
|
||||||
|
var BootstrapTable = $.fn.bootstrapTable.Constructor,
|
||||||
|
_initToolbar = BootstrapTable.prototype.initToolbar;
|
||||||
|
|
||||||
|
BootstrapTable.prototype.initToolbar = function () {
|
||||||
|
this.showToolbar = this.showToolbar || this.options.showPrint;
|
||||||
|
|
||||||
|
_initToolbar.apply(this, Array.prototype.slice.apply(arguments));
|
||||||
|
|
||||||
|
if (this.options.showPrint) {
|
||||||
|
var that = this,
|
||||||
|
$btnGroup = this.$toolbar.find('>.btn-group'),
|
||||||
|
$print = $btnGroup.find('button.bs-print');
|
||||||
|
|
||||||
|
if (!$print.length) {
|
||||||
|
$print = $([
|
||||||
|
'<button class="bs-print btn btn-default' + sprintf(' btn-%s"', this.options.iconSize) + ' name="print" title="print" type="button">',
|
||||||
|
sprintf('<i class="%s %s"></i> ', this.options.iconsPrefix, this.options.icons.print),
|
||||||
|
'</button>'].join('')).appendTo($btnGroup);
|
||||||
|
|
||||||
|
$print.click(function () {
|
||||||
|
function formatValue(row, i, column ) {
|
||||||
|
var value = row[column.field];
|
||||||
|
if (typeof column.printFormatter === 'function') {
|
||||||
|
return column.printFormatter.apply(column, [value, row, i]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return typeof value === 'undefined' ? "-" : value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildTable(data, columnsArray) {
|
||||||
|
var html = ['<table><thead>'];
|
||||||
|
for (var k = 0; k < columnsArray.length; k++) {
|
||||||
|
var columns = columnsArray[k];
|
||||||
|
html.push('<tr>');
|
||||||
|
for (var h = 0; h < columns.length; h++) {
|
||||||
|
if (!columns[h].printIgnore) {
|
||||||
|
html.push(
|
||||||
|
'<th',
|
||||||
|
sprintf(' rowspan="%s"', columns[h].rowspan),
|
||||||
|
sprintf(' colspan="%s"', columns[h].colspan),
|
||||||
|
sprintf('>%s</th>', columns[h].title)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
html.push('</tr>');
|
||||||
|
}
|
||||||
|
html.push('</thead><tbody>');
|
||||||
|
for (var i = 0; i < data.length; i++) {
|
||||||
|
html.push('<tr>');
|
||||||
|
for(var l = 0; l < columnsArray.length; l++) {
|
||||||
|
var columns = columnsArray[l];
|
||||||
|
for(var j = 0; j < columns.length; j++) {
|
||||||
|
if (!columns[j].printIgnore && columns[j].field) {
|
||||||
|
html.push('<td>', formatValue(data[i], i, columns[j]), '</td>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
html.push('</tr>');
|
||||||
|
}
|
||||||
|
html.push('</tbody></table>');
|
||||||
|
return html.join('');
|
||||||
|
}
|
||||||
|
function sortRows(data,colName,sortOrder) {
|
||||||
|
if(!colName){
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
var reverse = sortOrder != 'asc';
|
||||||
|
reverse = -((+reverse) || -1);
|
||||||
|
return data.sort(function (a, b) {
|
||||||
|
return reverse * (a[colName].localeCompare(b[colName]));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function filterRow(row,filters) {
|
||||||
|
for (var index = 0; index < filters.length; ++index) {
|
||||||
|
if(row[filters[index].colName]!=filters[index].value) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
function filterRows(data,filters) {
|
||||||
|
return data.filter(function (row) {
|
||||||
|
return filterRow(row,filters)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function getColumnFilters(columns) {
|
||||||
|
return !columns || !columns[0] ? [] : columns[0].filter(function (col) {
|
||||||
|
return col.printFilter;
|
||||||
|
}).map(function (col) {
|
||||||
|
return {colName:col.field, value:col.printFilter};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
var doPrint = function (data) {
|
||||||
|
data=filterRows(data,getColumnFilters(that.options.columns));
|
||||||
|
data=sortRows(data,that.options.printSortColumn,that.options.printSortOrder);
|
||||||
|
var table=buildTable(data,that.options.columns);
|
||||||
|
var newWin = window.open("");
|
||||||
|
newWin.document.write(that.options.printPageBuilder.call(this, table));
|
||||||
|
newWin.print();
|
||||||
|
newWin.close();
|
||||||
|
};
|
||||||
|
doPrint(that.options.printAsFilteredAndSortedOnUI? that.getData() : that.options.data.slice(0));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})(jQuery);
|
@ -0,0 +1,181 @@
|
|||||||
|
/**
|
||||||
|
* @author: Dennis Hernández
|
||||||
|
* @webSite: http://djhvscf.github.io/Blog
|
||||||
|
* @version: v1.1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
!function ($) {
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
//From MDN site, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
|
||||||
|
var filterFn = function () {
|
||||||
|
if (!Array.prototype.filter) {
|
||||||
|
Array.prototype.filter = function(fun/*, thisArg*/) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
if (this === void 0 || this === null) {
|
||||||
|
throw new TypeError();
|
||||||
|
}
|
||||||
|
|
||||||
|
var t = Object(this);
|
||||||
|
var len = t.length >>> 0;
|
||||||
|
if (typeof fun !== 'function') {
|
||||||
|
throw new TypeError();
|
||||||
|
}
|
||||||
|
|
||||||
|
var res = [];
|
||||||
|
var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
|
||||||
|
for (var i = 0; i < len; i++) {
|
||||||
|
if (i in t) {
|
||||||
|
var val = t[i];
|
||||||
|
|
||||||
|
// NOTE: Technically this should Object.defineProperty at
|
||||||
|
// the next index, as push can be affected by
|
||||||
|
// properties on Object.prototype and Array.prototype.
|
||||||
|
// But that method's new, and collisions should be
|
||||||
|
// rare, so use the more-compatible alternative.
|
||||||
|
if (fun.call(thisArg, val, i, t)) {
|
||||||
|
res.push(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, {
|
||||||
|
reorderableColumns: false,
|
||||||
|
maxMovingRows: 10,
|
||||||
|
onReorderColumn: function (headerFields) {
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
dragaccept: null
|
||||||
|
});
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.Constructor.EVENTS, {
|
||||||
|
'reorder-column.bs.table': 'onReorderColumn'
|
||||||
|
});
|
||||||
|
|
||||||
|
var BootstrapTable = $.fn.bootstrapTable.Constructor,
|
||||||
|
_initHeader = BootstrapTable.prototype.initHeader,
|
||||||
|
_toggleColumn = BootstrapTable.prototype.toggleColumn,
|
||||||
|
_toggleView = BootstrapTable.prototype.toggleView,
|
||||||
|
_resetView = BootstrapTable.prototype.resetView;
|
||||||
|
|
||||||
|
BootstrapTable.prototype.initHeader = function () {
|
||||||
|
_initHeader.apply(this, Array.prototype.slice.apply(arguments));
|
||||||
|
|
||||||
|
if (!this.options.reorderableColumns) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.makeRowsReorderable();
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.toggleColumn = function () {
|
||||||
|
_toggleColumn.apply(this, Array.prototype.slice.apply(arguments));
|
||||||
|
|
||||||
|
if (!this.options.reorderableColumns) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.makeRowsReorderable();
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.toggleView = function () {
|
||||||
|
_toggleView.apply(this, Array.prototype.slice.apply(arguments));
|
||||||
|
|
||||||
|
if (!this.options.reorderableColumns) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.options.cardView) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.makeRowsReorderable();
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.resetView = function () {
|
||||||
|
_resetView.apply(this, Array.prototype.slice.apply(arguments));
|
||||||
|
|
||||||
|
if (!this.options.reorderableColumns) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.makeRowsReorderable();
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.makeRowsReorderable = function () {
|
||||||
|
var that = this;
|
||||||
|
try {
|
||||||
|
$(this.$el).dragtable('destroy');
|
||||||
|
} catch (e) {}
|
||||||
|
$(this.$el).dragtable({
|
||||||
|
maxMovingRows: that.options.maxMovingRows,
|
||||||
|
dragaccept: that.options.dragaccept,
|
||||||
|
clickDelay:200,
|
||||||
|
beforeStop: function() {
|
||||||
|
var ths = [],
|
||||||
|
formatters = [],
|
||||||
|
columns = [],
|
||||||
|
columnsHidden = [],
|
||||||
|
columnIndex = -1,
|
||||||
|
optionsColumns = [];
|
||||||
|
that.$header.find('th').each(function (i) {
|
||||||
|
ths.push($(this).data('field'));
|
||||||
|
formatters.push($(this).data('formatter'));
|
||||||
|
});
|
||||||
|
|
||||||
|
//Exist columns not shown
|
||||||
|
if (ths.length < that.columns.length) {
|
||||||
|
columnsHidden = $.grep(that.columns, function (column) {
|
||||||
|
return !column.visible;
|
||||||
|
});
|
||||||
|
for (var i = 0; i < columnsHidden.length; i++) {
|
||||||
|
ths.push(columnsHidden[i].field);
|
||||||
|
formatters.push(columnsHidden[i].formatter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < this.length; i++ ) {
|
||||||
|
columnIndex = that.fieldsColumnsIndex[ths[i]];
|
||||||
|
if (columnIndex !== -1) {
|
||||||
|
that.columns[columnIndex].fieldIndex = i;
|
||||||
|
columns.push(that.columns[columnIndex]);
|
||||||
|
that.columns.splice(columnIndex, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
that.columns = that.columns.concat(columns);
|
||||||
|
|
||||||
|
filterFn(); //Support <IE9
|
||||||
|
$.each(that.columns, function(i, column) {
|
||||||
|
var found = false,
|
||||||
|
field = column.field;
|
||||||
|
that.options.columns[0].filter(function(item) {
|
||||||
|
if(!found && item["field"] == field) {
|
||||||
|
optionsColumns.push(item);
|
||||||
|
found = true;
|
||||||
|
return false;
|
||||||
|
} else
|
||||||
|
return true;
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
that.options.columns[0] = optionsColumns;
|
||||||
|
|
||||||
|
that.header.fields = ths;
|
||||||
|
that.header.formatters = formatters;
|
||||||
|
that.initHeader();
|
||||||
|
that.initToolbar();
|
||||||
|
that.initBody();
|
||||||
|
that.resetView();
|
||||||
|
that.trigger('reorder-column', ths);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}(jQuery);
|
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "Reorder Columns",
|
||||||
|
"version": "1.1.0",
|
||||||
|
"description": "Plugin to support the reordering columns feature.",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/reorder-columns",
|
||||||
|
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/reorder-columns.html",
|
||||||
|
|
||||||
|
"plugins": [{
|
||||||
|
"name": "bootstrap-table-reorder-columns",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/reorder-columns"
|
||||||
|
}],
|
||||||
|
|
||||||
|
"author": {
|
||||||
|
"name": "djhvscf",
|
||||||
|
"image": "https://avatars1.githubusercontent.com/u/4496763"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
.reorder_rows_onDragClass td {
|
||||||
|
background-color: #eee;
|
||||||
|
-webkit-box-shadow: 11px 5px 12px 2px #333, 0 1px 0 #ccc inset, 0 -1px 0 #ccc inset;
|
||||||
|
-webkit-box-shadow: 6px 3px 5px #555, 0 1px 0 #ccc inset, 0 -1px 0 #ccc inset;
|
||||||
|
-moz-box-shadow: 6px 4px 5px 1px #555, 0 1px 0 #ccc inset, 0 -1px 0 #ccc inset;
|
||||||
|
-box-shadow: 6px 4px 5px 1px #555, 0 1px 0 #ccc inset, 0 -1px 0 #ccc inset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reorder_rows_onDragClass td:last-child {
|
||||||
|
-webkit-box-shadow: 8px 7px 12px 0 #333, 0 1px 0 #ccc inset, 0 -1px 0 #ccc inset;
|
||||||
|
-webkit-box-shadow: 1px 8px 6px -4px #555, 0 1px 0 #ccc inset, 0 -1px 0 #ccc inset;
|
||||||
|
-moz-box-shadow: 0 9px 4px -4px #555, 0 1px 0 #ccc inset, 0 -1px 0 #ccc inset, -1px 0 0 #ccc inset;
|
||||||
|
-box-shadow: 0 9px 4px -4px #555, 0 1px 0 #ccc inset, 0 -1px 0 #ccc inset, -1px 0 0 #ccc inset;
|
||||||
|
}
|
118
InvenTree/InvenTree/static/bootstrap-table/extensions/reorder-rows/bootstrap-table-reorder-rows.js
vendored
Normal file
118
InvenTree/InvenTree/static/bootstrap-table/extensions/reorder-rows/bootstrap-table-reorder-rows.js
vendored
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
/**
|
||||||
|
* @author: Dennis Hernández
|
||||||
|
* @webSite: http://djhvscf.github.io/Blog
|
||||||
|
* @version: v1.0.1
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function ($) {
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var isSearch = false;
|
||||||
|
|
||||||
|
var rowAttr = function (row, index) {
|
||||||
|
return {
|
||||||
|
id: 'customId_' + index
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, {
|
||||||
|
reorderableRows: false,
|
||||||
|
onDragStyle: null,
|
||||||
|
onDropStyle: null,
|
||||||
|
onDragClass: "reorder_rows_onDragClass",
|
||||||
|
dragHandle: null,
|
||||||
|
useRowAttrFunc: false,
|
||||||
|
onReorderRowsDrag: function (table, row) {
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
onReorderRowsDrop: function (table, row) {
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
onReorderRow: function (newData) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.Constructor.EVENTS, {
|
||||||
|
'reorder-row.bs.table': 'onReorderRow'
|
||||||
|
});
|
||||||
|
|
||||||
|
var BootstrapTable = $.fn.bootstrapTable.Constructor,
|
||||||
|
_init = BootstrapTable.prototype.init,
|
||||||
|
_initSearch = BootstrapTable.prototype.initSearch;
|
||||||
|
|
||||||
|
BootstrapTable.prototype.init = function () {
|
||||||
|
|
||||||
|
if (!this.options.reorderableRows) {
|
||||||
|
_init.apply(this, Array.prototype.slice.apply(arguments));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var that = this;
|
||||||
|
if (this.options.useRowAttrFunc) {
|
||||||
|
this.options.rowAttributes = rowAttr;
|
||||||
|
}
|
||||||
|
|
||||||
|
var onPostBody = this.options.onPostBody;
|
||||||
|
this.options.onPostBody = function () {
|
||||||
|
setTimeout(function () {
|
||||||
|
that.makeRowsReorderable();
|
||||||
|
onPostBody.apply();
|
||||||
|
}, 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
_init.apply(this, Array.prototype.slice.apply(arguments));
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.initSearch = function () {
|
||||||
|
_initSearch.apply(this, Array.prototype.slice.apply(arguments));
|
||||||
|
|
||||||
|
if (!this.options.reorderableRows) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Known issue after search if you reorder the rows the data is not display properly
|
||||||
|
//isSearch = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.makeRowsReorderable = function () {
|
||||||
|
if (this.options.cardView) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var that = this;
|
||||||
|
this.$el.tableDnD({
|
||||||
|
onDragStyle: that.options.onDragStyle,
|
||||||
|
onDropStyle: that.options.onDropStyle,
|
||||||
|
onDragClass: that.options.onDragClass,
|
||||||
|
onDrop: that.onDrop,
|
||||||
|
onDragStart: that.options.onReorderRowsDrag,
|
||||||
|
dragHandle: that.options.dragHandle
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.onDrop = function (table, droppedRow) {
|
||||||
|
var tableBs = $(table),
|
||||||
|
tableBsData = tableBs.data('bootstrap.table'),
|
||||||
|
tableBsOptions = tableBs.data('bootstrap.table').options,
|
||||||
|
row = null,
|
||||||
|
newData = [];
|
||||||
|
|
||||||
|
for (var i = 0; i < table.tBodies[0].rows.length; i++) {
|
||||||
|
row = $(table.tBodies[0].rows[i]);
|
||||||
|
newData.push(tableBsOptions.data[row.data('index')]);
|
||||||
|
row.data('index', i).attr('data-index', i);
|
||||||
|
}
|
||||||
|
|
||||||
|
tableBsOptions.data = tableBsOptions.data.slice(0, tableBsData.pageFrom - 1)
|
||||||
|
.concat(newData)
|
||||||
|
.concat(tableBsOptions.data.slice(tableBsData.pageTo));
|
||||||
|
|
||||||
|
//Call the user defined function
|
||||||
|
tableBsOptions.onReorderRowsDrop.apply(table, [table, droppedRow]);
|
||||||
|
|
||||||
|
//Call the event reorder-row
|
||||||
|
tableBsData.trigger('reorder-row', newData);
|
||||||
|
};
|
||||||
|
})(jQuery);
|
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "Reorder Rows",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Plugin to support the reordering rows feature.",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/reorder-rows",
|
||||||
|
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/reorder-rows.html",
|
||||||
|
|
||||||
|
"plugins": [{
|
||||||
|
"name": "bootstrap-table-reorder-rows",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/reorder-rows"
|
||||||
|
}],
|
||||||
|
|
||||||
|
"author": {
|
||||||
|
"name": "djhvscf",
|
||||||
|
"image": "https://avatars1.githubusercontent.com/u/4496763"
|
||||||
|
}
|
||||||
|
}
|
72
InvenTree/InvenTree/static/bootstrap-table/extensions/resizable/bootstrap-table-resizable.js
vendored
Normal file
72
InvenTree/InvenTree/static/bootstrap-table/extensions/resizable/bootstrap-table-resizable.js
vendored
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/**
|
||||||
|
* @author: Dennis Hernández
|
||||||
|
* @webSite: http://djhvscf.github.io/Blog
|
||||||
|
* @version: v2.0.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function($) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var initResizable = function(that) {
|
||||||
|
if (that.options.resizable && !that.options.cardView && !isInit(that)) {
|
||||||
|
that.$el.resizableColumns();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var reInitResizable = function(that) {
|
||||||
|
destroy(that);
|
||||||
|
initResizable(that);
|
||||||
|
};
|
||||||
|
|
||||||
|
var destroy = function(that) {
|
||||||
|
if (isInit(that)) {
|
||||||
|
that.$el.data("resizableColumns").destroy();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var isInit = function(that) {
|
||||||
|
return that.$el.data("resizableColumns") !== undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, {
|
||||||
|
resizable: false
|
||||||
|
});
|
||||||
|
|
||||||
|
var BootstrapTable = $.fn.bootstrapTable.Constructor,
|
||||||
|
_initBody = BootstrapTable.prototype.initBody,
|
||||||
|
_toggleView = BootstrapTable.prototype.toggleView,
|
||||||
|
_resetView = BootstrapTable.prototype.resetView;
|
||||||
|
|
||||||
|
BootstrapTable.prototype.initBody = function() {
|
||||||
|
var that = this;
|
||||||
|
_initBody.apply(this, Array.prototype.slice.apply(arguments));
|
||||||
|
|
||||||
|
that.$el
|
||||||
|
.off("column-switch.bs.table, page-change.bs.table")
|
||||||
|
.on("column-switch.bs.table, page-change.bs.table", function() {
|
||||||
|
reInitResizable(that);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.toggleView = function() {
|
||||||
|
_toggleView.apply(this, Array.prototype.slice.apply(arguments));
|
||||||
|
|
||||||
|
if (this.options.resizable && this.options.cardView) {
|
||||||
|
//Destroy the plugin
|
||||||
|
destroy(this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.resetView = function() {
|
||||||
|
var that = this;
|
||||||
|
|
||||||
|
_resetView.apply(this, Array.prototype.slice.apply(arguments));
|
||||||
|
|
||||||
|
if (this.options.resizable) {
|
||||||
|
// because in fitHeader function, we use setTimeout(func, 100);
|
||||||
|
setTimeout(function() {
|
||||||
|
initResizable(that);
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})(jQuery);
|
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "Resizable",
|
||||||
|
"version": "1.1.0",
|
||||||
|
"description": "Plugin to support the resizable feature.",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/resizable",
|
||||||
|
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/resizable.html",
|
||||||
|
|
||||||
|
"plugins": [{
|
||||||
|
"name": "bootstrap-table-resizable",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/resizable"
|
||||||
|
}],
|
||||||
|
|
||||||
|
"author": {
|
||||||
|
"name": "djhvscf",
|
||||||
|
"image": "https://avatars1.githubusercontent.com/u/4496763"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,332 @@
|
|||||||
|
/**
|
||||||
|
* @author: Jewway
|
||||||
|
* @version: v1.1.1
|
||||||
|
*/
|
||||||
|
|
||||||
|
! function ($) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
function getCurrentHeader(that) {
|
||||||
|
var header = that.$header;
|
||||||
|
if (that.options.height) {
|
||||||
|
header = that.$tableHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
function initFilterValues(that) {
|
||||||
|
if (!$.isEmptyObject(that.filterColumnsPartial)) {
|
||||||
|
var $header = getCurrentHeader(that);
|
||||||
|
|
||||||
|
$.each(that.columns, function (idx, column) {
|
||||||
|
var value = that.filterColumnsPartial[column.field];
|
||||||
|
|
||||||
|
if (column.filter) {
|
||||||
|
if (column.filter.setFilterValue) {
|
||||||
|
var $filter = $header.find('[data-field=' + column.field + '] .filter');
|
||||||
|
column.filter.setFilterValue($filter, column.field, value);
|
||||||
|
} else {
|
||||||
|
var $ele = $header.find('[data-filter-field=' + column.field + ']');
|
||||||
|
switch (column.filter.type) {
|
||||||
|
case 'input':
|
||||||
|
$ele.val(value);
|
||||||
|
case 'select':
|
||||||
|
$ele.val(value).trigger('change');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createFilter(that, header) {
|
||||||
|
var enableFilter = false,
|
||||||
|
isVisible,
|
||||||
|
html,
|
||||||
|
timeoutId = 0;
|
||||||
|
|
||||||
|
$.each(that.columns, function (i, column) {
|
||||||
|
isVisible = 'hidden';
|
||||||
|
html = null;
|
||||||
|
|
||||||
|
if (!column.visible) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!column.filter) {
|
||||||
|
html = $('<div class="no-filter"></div>');
|
||||||
|
} else {
|
||||||
|
var filterClass = column.filter.class ? ' ' + column.filter.class : '';
|
||||||
|
html = $('<div style="margin: 0px 2px 2px 2px;" class="filter' + filterClass + '">');
|
||||||
|
|
||||||
|
if (column.searchable) {
|
||||||
|
enableFilter = true;
|
||||||
|
isVisible = 'visible'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (column.filter.template) {
|
||||||
|
html.append(column.filter.template(that, column, isVisible));
|
||||||
|
} else {
|
||||||
|
var $filter = $(that.options.filterTemplate[column.filter.type.toLowerCase()](that, column, isVisible));
|
||||||
|
|
||||||
|
switch (column.filter.type) {
|
||||||
|
case 'input':
|
||||||
|
var cpLock = true;
|
||||||
|
$filter.off('compositionstart').on('compositionstart', function (event) {
|
||||||
|
cpLock = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
$filter.off('compositionend').on('compositionend', function (event) {
|
||||||
|
cpLock = true;
|
||||||
|
var $input = $(this);
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
timeoutId = setTimeout(function () {
|
||||||
|
that.onColumnSearch(event, column.field, $input.val());
|
||||||
|
}, that.options.searchTimeOut);
|
||||||
|
});
|
||||||
|
|
||||||
|
$filter.off('keyup').on('keyup', function (event) {
|
||||||
|
if (cpLock) {
|
||||||
|
var $input = $(this);
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
timeoutId = setTimeout(function () {
|
||||||
|
that.onColumnSearch(event, column.field, $input.val());
|
||||||
|
}, that.options.searchTimeOut);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$filter.off('mouseup').on('mouseup', function (event) {
|
||||||
|
var $input = $(this),
|
||||||
|
oldValue = $input.val();
|
||||||
|
|
||||||
|
if (oldValue === "") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(function () {
|
||||||
|
var newValue = $input.val();
|
||||||
|
|
||||||
|
if (newValue === "") {
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
timeoutId = setTimeout(function () {
|
||||||
|
that.onColumnSearch(event, column.field, newValue);
|
||||||
|
}, that.options.searchTimeOut);
|
||||||
|
}
|
||||||
|
}, 1);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'select':
|
||||||
|
$filter.on('select2:select', function (event) {
|
||||||
|
that.onColumnSearch(event, column.field, $(this).val());
|
||||||
|
});
|
||||||
|
|
||||||
|
$filter.on("select2:unselecting", function (event) {
|
||||||
|
var $select2 = $(this);
|
||||||
|
event.preventDefault();
|
||||||
|
$select2.val(null).trigger('change');
|
||||||
|
that.searchText = undefined;
|
||||||
|
that.onColumnSearch(event, column.field, $select2.val());
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.append($filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$.each(header.children().children(), function (i, tr) {
|
||||||
|
tr = $(tr);
|
||||||
|
if (tr.data('field') === column.field) {
|
||||||
|
tr.find('.fht-cell').append(html);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!enableFilter) {
|
||||||
|
header.find('.filter').hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function initSelect2(that) {
|
||||||
|
var $header = getCurrentHeader(that);
|
||||||
|
|
||||||
|
$.each(that.columns, function (idx, column) {
|
||||||
|
if (column.filter && column.filter.type === 'select') {
|
||||||
|
var $selectEle = $header.find('select[data-filter-field="' + column.field + '"]');
|
||||||
|
|
||||||
|
if ($selectEle.length > 0 && !$selectEle.data().select2) {
|
||||||
|
var select2Opts = {
|
||||||
|
placeholder: "",
|
||||||
|
allowClear: true,
|
||||||
|
data: column.filter.data,
|
||||||
|
dropdownParent: that.$el.closest(".bootstrap-table")
|
||||||
|
};
|
||||||
|
|
||||||
|
$selectEle.select2(select2Opts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, {
|
||||||
|
filter: false,
|
||||||
|
filterValues: {},
|
||||||
|
filterTemplate: {
|
||||||
|
input: function (instance, column, isVisible) {
|
||||||
|
return '<input type="text" class="form-control" data-filter-field="' + column.field + '" style="width: 100%; visibility:' + isVisible + '">';
|
||||||
|
},
|
||||||
|
select: function (instance, column, isVisible) {
|
||||||
|
return '<select data-filter-field="' + column.field + '" style="width: 100%; visibility:' + isVisible + '"></select>';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onColumnSearch: function (field, text) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.COLUMN_DEFAULTS, {
|
||||||
|
filter: undefined
|
||||||
|
});
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.Constructor.EVENTS, {
|
||||||
|
'column-search.bs.table': 'onColumnSearch'
|
||||||
|
});
|
||||||
|
|
||||||
|
var BootstrapTable = $.fn.bootstrapTable.Constructor,
|
||||||
|
_init = BootstrapTable.prototype.init,
|
||||||
|
_initHeader = BootstrapTable.prototype.initHeader,
|
||||||
|
_initSearch = BootstrapTable.prototype.initSearch;
|
||||||
|
|
||||||
|
BootstrapTable.prototype.init = function () {
|
||||||
|
//Make sure that the filtercontrol option is set
|
||||||
|
if (this.options.filter) {
|
||||||
|
var that = this;
|
||||||
|
|
||||||
|
if (that.options.filterTemplate) {
|
||||||
|
that.options.filterTemplate = $.extend({}, $.fn.bootstrapTable.defaults.filterTemplate, that.options.filterTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$.isEmptyObject(that.options.filterValues)) {
|
||||||
|
that.filterColumnsPartial = that.options.filterValues;
|
||||||
|
that.options.filterValues = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$el.on('reset-view.bs.table', function () {
|
||||||
|
//Create controls on $tableHeader if the height is set
|
||||||
|
if (!that.options.height) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Avoid recreate the controls
|
||||||
|
if (that.$tableHeader.find('select').length > 0 || that.$tableHeader.find('input').length > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
createFilter(that, that.$tableHeader);
|
||||||
|
}).on('post-header.bs.table', function () {
|
||||||
|
var timeoutId = 0;
|
||||||
|
|
||||||
|
initSelect2(that);
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
timeoutId = setTimeout(function () {
|
||||||
|
initFilterValues(that);
|
||||||
|
}, that.options.searchTimeOut - 1000);
|
||||||
|
}).on('column-switch.bs.table', function (field, checked) {
|
||||||
|
initFilterValues(that);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_init.apply(this, Array.prototype.slice.apply(arguments));
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.initHeader = function () {
|
||||||
|
_initHeader.apply(this, Array.prototype.slice.apply(arguments));
|
||||||
|
if (this.options.filter) {
|
||||||
|
createFilter(this, this.$header);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.initSearch = function () {
|
||||||
|
var that = this,
|
||||||
|
filterValues = that.filterColumnsPartial;
|
||||||
|
|
||||||
|
// Filter for client
|
||||||
|
if (that.options.sidePagination === 'client') {
|
||||||
|
this.data = $.grep(this.data, function (row, idx) {
|
||||||
|
for (var field in filterValues) {
|
||||||
|
var column = that.columns[that.fieldsColumnsIndex[field]],
|
||||||
|
filterValue = filterValues[field].toLowerCase(),
|
||||||
|
rowValue = row[field];
|
||||||
|
|
||||||
|
rowValue = $.fn.bootstrapTable.utils.calculateObjectValue(
|
||||||
|
that.header,
|
||||||
|
that.header.formatters[$.inArray(field, that.header.fields)], [rowValue, row, idx], rowValue);
|
||||||
|
|
||||||
|
if (column.filterStrictSearch) {
|
||||||
|
if (!($.inArray(field, that.header.fields) !== -1 &&
|
||||||
|
(typeof rowValue === 'string' || typeof rowValue === 'number') &&
|
||||||
|
rowValue.toString().toLowerCase() === filterValue.toString().toLowerCase())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!($.inArray(field, that.header.fields) !== -1 &&
|
||||||
|
(typeof rowValue === 'string' || typeof rowValue === 'number') &&
|
||||||
|
(rowValue + '').toLowerCase().indexOf(filterValue) !== -1)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_initSearch.apply(this, Array.prototype.slice.apply(arguments));
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.onColumnSearch = function (event, field, value) {
|
||||||
|
if ($.isEmptyObject(this.filterColumnsPartial)) {
|
||||||
|
this.filterColumnsPartial = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
this.filterColumnsPartial[field] = value;
|
||||||
|
} else {
|
||||||
|
delete this.filterColumnsPartial[field];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.options.pageNumber = 1;
|
||||||
|
this.onSearch(event);
|
||||||
|
this.trigger('column-search', field, value);
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.setSelect2Data = function (field, data) {
|
||||||
|
var that = this,
|
||||||
|
$header = getCurrentHeader(that),
|
||||||
|
$selectEle = $header.find('select[data-filter-field=\"' + field + '\"]');
|
||||||
|
$selectEle.empty();
|
||||||
|
$selectEle.select2({
|
||||||
|
data: data,
|
||||||
|
placeholder: "",
|
||||||
|
allowClear: true,
|
||||||
|
dropdownParent: that.$el.closest(".bootstrap-table")
|
||||||
|
});
|
||||||
|
|
||||||
|
$.each(this.columns, function (idx, column) {
|
||||||
|
if (column.field === field) {
|
||||||
|
column.filter.data = data;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
BootstrapTable.prototype.setFilterValues = function (values) {
|
||||||
|
this.filterColumnsPartial = values;
|
||||||
|
};
|
||||||
|
|
||||||
|
$.fn.bootstrapTable.methods.push('setSelect2Data');
|
||||||
|
$.fn.bootstrapTable.methods.push('setFilterValues');
|
||||||
|
|
||||||
|
}(jQuery);
|
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "Select2 Filter",
|
||||||
|
"version": "1.1.0",
|
||||||
|
"description": "Plugin to add select2 filter on the top of the columns in order to filter the data.",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/select2-filter",
|
||||||
|
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/select2-filter.html",
|
||||||
|
|
||||||
|
"plugins": [{
|
||||||
|
"name": "bootstrap-table-select2-filter",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/select2-filter"
|
||||||
|
}],
|
||||||
|
|
||||||
|
"author": {
|
||||||
|
"name": "Jewway",
|
||||||
|
"image": "https://avatars0.githubusercontent.com/u/3501899"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
/**
|
||||||
|
* @author vincent loh <vincent.ml@gmail.com>
|
||||||
|
* @update zhixin wen <wenzhixin2010@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
.fix-sticky {
|
||||||
|
position: fixed !important;
|
||||||
|
overflow: hidden;
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fix-sticky table thead {
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fix-sticky table thead.thead-light {
|
||||||
|
background: #e9ecef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fix-sticky table thead.thead-light {
|
||||||
|
background: #212529;
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
/**
|
||||||
|
* @author vincent loh <vincent.ml@gmail.com>
|
||||||
|
* @update J Manuel Corona <jmcg92@gmail.com>
|
||||||
|
* @update zhixin wen <wenzhixin2010@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
($ => {
|
||||||
|
const Utils = $.fn.bootstrapTable.utils
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, {
|
||||||
|
stickyHeader: false,
|
||||||
|
stickyHeaderOffsetY: 0
|
||||||
|
})
|
||||||
|
|
||||||
|
const hiddenClass = Utils.bootstrapVersion === 4 ? 'd-none' : 'hidden'
|
||||||
|
|
||||||
|
$.BootstrapTable = class extends $.BootstrapTable {
|
||||||
|
initHeader (...args) {
|
||||||
|
super.initHeader(...args)
|
||||||
|
|
||||||
|
if (!this.options.stickyHeader) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$el.before('<div class="sticky-header-container"></div>')
|
||||||
|
this.$el.before('<div class="sticky_anchor_begin"></div>')
|
||||||
|
this.$el.after('<div class="sticky_anchor_end"></div>')
|
||||||
|
this.$header.addClass('sticky-header')
|
||||||
|
|
||||||
|
// clone header just once, to be used as sticky header
|
||||||
|
// deep clone header, using source header affects tbody>td width
|
||||||
|
this.$stickyContainer = this.$tableBody.find('.sticky-header-container')
|
||||||
|
this.$stickyBegin = this.$tableBody.find('.sticky_anchor_begin')
|
||||||
|
this.$stickyEnd = this.$tableBody.find('.sticky_anchor_end')
|
||||||
|
this.$stickyHeader = this.$header.clone(true, true)
|
||||||
|
|
||||||
|
// render sticky on window scroll or resize
|
||||||
|
$(window).on('resize.sticky-header-table', () => this.renderStickyHeader())
|
||||||
|
$(window).on('scroll.sticky-header-table', () => this.renderStickyHeader())
|
||||||
|
this.$tableBody.off('scroll').on('scroll', () => this.matchPositionX())
|
||||||
|
}
|
||||||
|
|
||||||
|
renderStickyHeader () {
|
||||||
|
const top = $(window).scrollTop()
|
||||||
|
// top anchor scroll position, minus header height
|
||||||
|
const start = this.$stickyBegin.offset().top - this.options.stickyHeaderOffsetY
|
||||||
|
// bottom anchor scroll position, minus header height, minus sticky height
|
||||||
|
const end = this.$stickyEnd.offset().top - this.options.stickyHeaderOffsetY - this.$header.height()
|
||||||
|
// show sticky when top anchor touches header, and when bottom anchor not exceeded
|
||||||
|
if (top > start && top <= end) {
|
||||||
|
// ensure clone and source column widths are the same
|
||||||
|
this.$stickyHeader.find('tr:eq(0)').find('th').each((index, el) => {
|
||||||
|
$(el).css('min-width', this.$header.find('tr:eq(0)').find('th').eq(index).css('width'))
|
||||||
|
})
|
||||||
|
// match bootstrap table style
|
||||||
|
this.$stickyContainer.removeClass(hiddenClass).addClass('fix-sticky fixed-table-container')
|
||||||
|
// stick it in position
|
||||||
|
this.$stickyContainer.css('top', `${this.options.stickyHeaderOffsetY}px`)
|
||||||
|
// create scrollable container for header
|
||||||
|
this.$stickyTable = $('<table/>')
|
||||||
|
this.$stickyTable.addClass(this.options.classes)
|
||||||
|
// append cloned header to dom
|
||||||
|
this.$stickyContainer.html(this.$stickyTable.append(this.$stickyHeader))
|
||||||
|
// match clone and source header positions when left-right scroll
|
||||||
|
this.matchPositionX()
|
||||||
|
} else {
|
||||||
|
this.$stickyContainer.removeClass('fix-sticky').addClass(hiddenClass)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
matchPositionX () {
|
||||||
|
this.$stickyContainer.scrollLeft(this.$tableBody.scrollLeft())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
})(jQuery)
|
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "Sticky Header",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "An extension which provides a sticky header for table columns when scrolling on a long page and / or table. Works for tables with many columns and narrow width with horizontal scrollbars too.",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/sticky-header",
|
||||||
|
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/sticky-header.html",
|
||||||
|
|
||||||
|
"plugins": [{
|
||||||
|
"name": "bootstrap-table-sticky-header",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/sticky-header"
|
||||||
|
}],
|
||||||
|
|
||||||
|
"author": {
|
||||||
|
"name": "vinzloh",
|
||||||
|
"image": "https://avatars0.githubusercontent.com/u/5501845"
|
||||||
|
}
|
||||||
|
}
|
228
InvenTree/InvenTree/static/bootstrap-table/extensions/toolbar/bootstrap-table-toolbar.js
vendored
Normal file
228
InvenTree/InvenTree/static/bootstrap-table/extensions/toolbar/bootstrap-table-toolbar.js
vendored
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
/**
|
||||||
|
* @author: aperez <aperez@datadec.es>
|
||||||
|
* @version: v2.0.0
|
||||||
|
*
|
||||||
|
* @update Dennis Hernández <http://djhvscf.github.io/Blog>
|
||||||
|
* @update zhixin wen <wenzhixin2010@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
($ => {
|
||||||
|
const Utils = $.fn.bootstrapTable.utils
|
||||||
|
|
||||||
|
const bootstrap = {
|
||||||
|
3: {
|
||||||
|
icons: {
|
||||||
|
advancedSearchIcon: 'glyphicon-chevron-down'
|
||||||
|
},
|
||||||
|
html: {
|
||||||
|
modalHeader: `
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
<h4 class="modal-title">%s</h4>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
4: {
|
||||||
|
icons: {
|
||||||
|
advancedSearchIcon: 'fa-chevron-down'
|
||||||
|
},
|
||||||
|
html: {
|
||||||
|
modalHeader: `
|
||||||
|
<div class="modal-header">
|
||||||
|
<h4 class="modal-title">%s</h4>
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}[Utils.bootstrapVersion]
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, {
|
||||||
|
advancedSearch: false,
|
||||||
|
idForm: 'advancedSearch',
|
||||||
|
actionForm: '',
|
||||||
|
idTable: undefined,
|
||||||
|
onColumnAdvancedSearch (field, text) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults.icons, {
|
||||||
|
advancedSearchIcon: bootstrap.icons.advancedSearchIcon
|
||||||
|
})
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.Constructor.EVENTS, {
|
||||||
|
'column-advanced-search.bs.table': 'onColumnAdvancedSearch'
|
||||||
|
})
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.locales, {
|
||||||
|
formatAdvancedSearch () {
|
||||||
|
return 'Advanced search'
|
||||||
|
},
|
||||||
|
formatAdvancedCloseButton () {
|
||||||
|
return 'Close'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales)
|
||||||
|
|
||||||
|
$.BootstrapTable = class extends $.BootstrapTable {
|
||||||
|
initToolbar () {
|
||||||
|
const o = this.options
|
||||||
|
|
||||||
|
this.showToolbar = this.showToolbar ||
|
||||||
|
(o.search &&
|
||||||
|
o.advancedSearch &&
|
||||||
|
o.idTable)
|
||||||
|
|
||||||
|
super.initToolbar()
|
||||||
|
|
||||||
|
if (!o.search || !o.advancedSearch || !o.idTable) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$toolbar.find('>.btn-group').append(`
|
||||||
|
<button class="btn btn-default${Utils.sprintf(' btn-%s', o.buttonsClass)}${Utils.sprintf(' btn-%s', o.iconSize)}"
|
||||||
|
type="button"
|
||||||
|
name="advancedSearch"
|
||||||
|
aria-label="advanced search"
|
||||||
|
title="${o.formatAdvancedSearch()}">
|
||||||
|
<i class="${o.iconsPrefix} ${o.icons.advancedSearchIcon}"></i>
|
||||||
|
</button>
|
||||||
|
`)
|
||||||
|
|
||||||
|
this.$toolbar.find('button[name="advancedSearch"]').off('click').on('click', () => this.showAvdSearch())
|
||||||
|
}
|
||||||
|
|
||||||
|
showAvdSearch () {
|
||||||
|
const o = this.options
|
||||||
|
|
||||||
|
if (!$(`#avdSearchModal_${o.idTable}`).hasClass('modal')) {
|
||||||
|
$('body').append(`
|
||||||
|
<div id="avdSearchModal_${o.idTable}" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-xs">
|
||||||
|
<div class="modal-content">
|
||||||
|
${Utils.sprintf(bootstrap.html.modalHeader, o.formatAdvancedSearch())}
|
||||||
|
<div class="modal-body modal-body-custom">
|
||||||
|
<div class="container-fluid" id="avdSearchModalContent_${o.idTable}"
|
||||||
|
style="padding-right: 0px; padding-left: 0px;" >
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" id="btnCloseAvd_${o.idTable}" class="btn btn-${o.buttonsClass}">
|
||||||
|
${o.formatAdvancedCloseButton()}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`)
|
||||||
|
|
||||||
|
let timeoutId = 0
|
||||||
|
|
||||||
|
$(`#avdSearchModalContent_${o.idTable}`).append(this.createFormAvd().join(''))
|
||||||
|
|
||||||
|
$(`#${o.idForm}`).off('keyup blur', 'input').on('keyup blur', 'input', e => {
|
||||||
|
if (o.sidePagination === 'server') {
|
||||||
|
this.onColumnAdvancedSearch(e)
|
||||||
|
} else {
|
||||||
|
clearTimeout(timeoutId)
|
||||||
|
timeoutId = setTimeout(() => {
|
||||||
|
this.onColumnAdvancedSearch(e)
|
||||||
|
}, o.searchTimeOut)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
$(`#btnCloseAvd_${o.idTable}`).click(() => {
|
||||||
|
$(`#avdSearchModal_${o.idTable}`).modal('hide')
|
||||||
|
if (o.sidePagination === 'server') {
|
||||||
|
this.options.pageNumber = 1
|
||||||
|
this.updatePagination()
|
||||||
|
this.trigger('column-advanced-search', this.filterColumnsPartial)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
$(`#avdSearchModal_${o.idTable}`).modal()
|
||||||
|
} else {
|
||||||
|
$(`#avdSearchModal_${o.idTable}`).modal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
createFormAvd () {
|
||||||
|
const o = this.options
|
||||||
|
const html = [`<form class="form-horizontal" id="${o.idForm}" action="${o.actionForm}">`]
|
||||||
|
|
||||||
|
for (const column of this.columns) {
|
||||||
|
if (!column.checkbox && column.visible && column.searchable) {
|
||||||
|
html.push(`
|
||||||
|
<div class="form-group row">
|
||||||
|
<label class="col-sm-4 control-label">${column.title}</label>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<input type="text" class="form-control input-md" name="${column.field}" placeholder="${column.title}" id="${column.field}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
html.push('</form>')
|
||||||
|
|
||||||
|
return html
|
||||||
|
}
|
||||||
|
|
||||||
|
initSearch () {
|
||||||
|
super.initSearch()
|
||||||
|
|
||||||
|
if (!this.options.advancedSearch || this.options.sidePagination === 'server') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const fp = $.isEmptyObject(this.filterColumnsPartial) ? null : this.filterColumnsPartial
|
||||||
|
|
||||||
|
this.data = fp ? $.grep(this.data, (item, i) => {
|
||||||
|
for (const [key, v] of Object.entries(fp)) {
|
||||||
|
const fval = v.toLowerCase()
|
||||||
|
let value = item[key]
|
||||||
|
const index = this.header.fields.indexOf(key)
|
||||||
|
value = Utils.calculateObjectValue(this.header,
|
||||||
|
this.header.formatters[index], [value, item, i], value)
|
||||||
|
|
||||||
|
if (
|
||||||
|
!(index !== -1 &&
|
||||||
|
(typeof value === 'string' || typeof value === 'number') &&
|
||||||
|
(`${value}`).toLowerCase().includes(fval))
|
||||||
|
) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}) : this.data
|
||||||
|
}
|
||||||
|
|
||||||
|
onColumnAdvancedSearch (e) {
|
||||||
|
const text = $.trim($(e.currentTarget).val())
|
||||||
|
const $field = $(e.currentTarget)[0].id
|
||||||
|
|
||||||
|
if ($.isEmptyObject(this.filterColumnsPartial)) {
|
||||||
|
this.filterColumnsPartial = {}
|
||||||
|
}
|
||||||
|
if (text) {
|
||||||
|
this.filterColumnsPartial[$field] = text
|
||||||
|
} else {
|
||||||
|
delete this.filterColumnsPartial[$field]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.options.sidePagination !== 'server') {
|
||||||
|
this.options.pageNumber = 1
|
||||||
|
this.onSearch(e)
|
||||||
|
this.updatePagination()
|
||||||
|
this.trigger('column-advanced-search', $field, text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})(jQuery)
|
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "Toolbar",
|
||||||
|
"version": "2.0.0",
|
||||||
|
"description": "Plugin to support the advanced search.",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/toolbar",
|
||||||
|
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/toolbar.html",
|
||||||
|
|
||||||
|
"plugins": [{
|
||||||
|
"name": "bootstrap-table-toolbar",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/toolbar"
|
||||||
|
}],
|
||||||
|
|
||||||
|
"author": {
|
||||||
|
"name": "djhvscf",
|
||||||
|
"image": "https://avatars1.githubusercontent.com/u/4496763"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
.table:not(.table-condensed)>tbody>tr>td.treenode{padding-top:0;padding-bottom:0;border-bottom:solid #fff 1px}.table:not(.table-condensed)>tbody>tr:last-child>td.treenode{border-bottom:none}.treenode .text{float:left;display:block;padding-top:6px;padding-bottom:6px}.treenode .vertical,.treenode .vertical.last{float:left;display:block;width:1px;border-left:dashed silver 1px;height:38px;margin-left:8px}.treenode .vertical.last{height:15px}.treenode .space,.treenode .node{float:left;display:block;width:15px;height:5px;margin-top:15px}.treenode .node{border-top:dashed silver 1px}
|
130
InvenTree/InvenTree/static/bootstrap-table/extensions/tree-column/bootstrap-table-tree-column.js
vendored
Normal file
130
InvenTree/InvenTree/static/bootstrap-table/extensions/tree-column/bootstrap-table-tree-column.js
vendored
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
/**
|
||||||
|
* @author: KingYang
|
||||||
|
* @webSite: https://github.com/kingyang
|
||||||
|
* @version: v1.0.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
! function ($) {
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, {
|
||||||
|
treeShowField: null,
|
||||||
|
idField: 'id',
|
||||||
|
parentIdField: 'pid',
|
||||||
|
treeVerticalcls: 'vertical',
|
||||||
|
treeVerticalLastcls: 'vertical last',
|
||||||
|
treeSpacecls: 'space',
|
||||||
|
treeNodecls: 'node',
|
||||||
|
treeCellcls: 'treenode',
|
||||||
|
treeTextcls: 'text',
|
||||||
|
onTreeFormatter: function (row) {
|
||||||
|
var that = this,
|
||||||
|
options = that.options,
|
||||||
|
level = row._level || 0,
|
||||||
|
plevel = row._parent && row._parent._level || 0,
|
||||||
|
paddings = [];
|
||||||
|
for (var i = 0; i < plevel; i++) {
|
||||||
|
paddings.push('<i class="' + options.treeVerticalcls + '"></i>');
|
||||||
|
paddings.push('<i class="' + options.treeSpacecls + '"></i>');
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = plevel; i < level; i++) {
|
||||||
|
if (row._last && i === (level - 1)) {
|
||||||
|
paddings.push('<i class="' + options.treeVerticalLastcls + '"></i>');
|
||||||
|
} else {
|
||||||
|
paddings.push('<i class="' + options.treeVerticalcls + '"></i>');
|
||||||
|
}
|
||||||
|
paddings.push('<i class="' + options.treeNodecls + '"></i>');
|
||||||
|
}
|
||||||
|
return paddings.join('');
|
||||||
|
}, onGetNodes: function (row, data) {
|
||||||
|
var that = this;
|
||||||
|
var nodes = [];
|
||||||
|
$.each(data, function (i, item) {
|
||||||
|
if (row[that.options.idField] === item[that.options.parentIdField]) {
|
||||||
|
nodes.push(item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return nodes;
|
||||||
|
},
|
||||||
|
onCheckLeaf: function (row, data) {
|
||||||
|
if (row.isLeaf !== undefined) {
|
||||||
|
return row.isLeaf;
|
||||||
|
}
|
||||||
|
return !row._nodes || !row._nodes.length;
|
||||||
|
}, onCheckRoot: function (row, data) {
|
||||||
|
var that = this;
|
||||||
|
return !row[that.options.parentIdField];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var BootstrapTable = $.fn.bootstrapTable.Constructor,
|
||||||
|
_initRow = BootstrapTable.prototype.initRow,
|
||||||
|
_initHeader = BootstrapTable.prototype.initHeader;
|
||||||
|
|
||||||
|
BootstrapTable.prototype.initHeader = function () {
|
||||||
|
var that = this;
|
||||||
|
_initHeader.apply(that, Array.prototype.slice.apply(arguments));
|
||||||
|
var treeShowField = that.options.treeShowField;
|
||||||
|
if (treeShowField) {
|
||||||
|
$.each(this.header.fields, function (i, field) {
|
||||||
|
if (treeShowField === field) {
|
||||||
|
that.treeEnable = true;
|
||||||
|
var _formatter = that.header.formatters[i];
|
||||||
|
var _class = [that.options.treeCellcls];
|
||||||
|
if (that.header.classes[i]) {
|
||||||
|
_class.push(that.header.classes[i].split('"')[1] || '');
|
||||||
|
}
|
||||||
|
that.header.classes[i] = ' class="' + _class.join(' ') + '"';
|
||||||
|
that.header.formatters[i] = function (value, row, index) {
|
||||||
|
var colTree = [that.options.onTreeFormatter.apply(that, [row])];
|
||||||
|
colTree.push('<span class="' + that.options.treeTextcls + '">');
|
||||||
|
if (_formatter) {
|
||||||
|
colTree.push(_formatter.apply(this, Array.prototype.slice.apply(arguments)));
|
||||||
|
} else {
|
||||||
|
colTree.push(value);
|
||||||
|
}
|
||||||
|
colTree.push('</span>');
|
||||||
|
return colTree.join('');
|
||||||
|
};
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var initNode = function (item, idx, data, parentDom) {
|
||||||
|
var that = this;
|
||||||
|
var nodes = that.options.onGetNodes.apply(that, [item, data]);
|
||||||
|
item._nodes = nodes;
|
||||||
|
parentDom.append(_initRow.apply(that, [item, idx, data, parentDom]));
|
||||||
|
var len = nodes.length - 1;
|
||||||
|
for (var i = 0; i <= len; i++) {
|
||||||
|
var node = nodes[i];
|
||||||
|
node._level = item._level + 1;
|
||||||
|
node._parent = item;
|
||||||
|
if (i === len)
|
||||||
|
node._last = 1;
|
||||||
|
initNode.apply(that, [node, $.inArray(node, data), data, parentDom]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
BootstrapTable.prototype.initRow = function (item, idx, data, parentDom) {
|
||||||
|
var that = this;
|
||||||
|
if (that.treeEnable) {
|
||||||
|
if (that.options.onCheckRoot.apply(that, [item, data])) {
|
||||||
|
if (item._level === undefined) {
|
||||||
|
item._level = 0;
|
||||||
|
}
|
||||||
|
initNode.apply(that, [item, idx, data, parentDom]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
return _initRow.apply(that, Array.prototype.slice.apply(arguments));
|
||||||
|
};
|
||||||
|
|
||||||
|
} (jQuery);
|
@ -0,0 +1,43 @@
|
|||||||
|
.table:not(.table-condensed) > tbody > tr > td.treenode {
|
||||||
|
padding-top: 0;
|
||||||
|
padding-bottom: 0;
|
||||||
|
border-bottom: solid #fff 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table:not(.table-condensed) > tbody > tr:last-child > td.treenode {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.treenode {
|
||||||
|
.text {
|
||||||
|
float: left;
|
||||||
|
display: block;
|
||||||
|
padding-top: 6px;
|
||||||
|
padding-bottom: 6px;
|
||||||
|
}
|
||||||
|
.vertical,
|
||||||
|
.vertical.last {
|
||||||
|
float: left;
|
||||||
|
display: block;
|
||||||
|
width: 1px;
|
||||||
|
border-left: dashed silver 1px;
|
||||||
|
height: 38px;
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
.vertical.last {
|
||||||
|
height: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.space,
|
||||||
|
.node {
|
||||||
|
float: left;
|
||||||
|
display: block;
|
||||||
|
width: 15px;
|
||||||
|
height: 5px;
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.node {
|
||||||
|
border-top: dashed silver 1px;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "Tree column",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Plugin to support display tree data column.",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/tree-column",
|
||||||
|
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/tree-column.html",
|
||||||
|
|
||||||
|
"plugins": [{
|
||||||
|
"name": "bootstrap-table-reorder-rows",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/tree-column"
|
||||||
|
}],
|
||||||
|
|
||||||
|
"author": {
|
||||||
|
"name": "KingYang",
|
||||||
|
"image": "https://avatars3.githubusercontent.com/u/1540211"
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 346 B |
111
InvenTree/InvenTree/static/bootstrap-table/extensions/treegrid/bootstrap-table-treegrid.js
vendored
Normal file
111
InvenTree/InvenTree/static/bootstrap-table/extensions/treegrid/bootstrap-table-treegrid.js
vendored
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
/**
|
||||||
|
* @author: YL
|
||||||
|
* @version: v1.0.0
|
||||||
|
*/
|
||||||
|
!function ($) {
|
||||||
|
'use strict';
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, {
|
||||||
|
treeShowField: null,
|
||||||
|
idField: 'id',
|
||||||
|
parentIdField: 'pid',
|
||||||
|
rootParentId: null,
|
||||||
|
onGetNodes: function (row, data) {
|
||||||
|
var that = this;
|
||||||
|
var nodes = [];
|
||||||
|
$.each(data, function (i, item) {
|
||||||
|
if (row[that.options.idField] === item[that.options.parentIdField]) {
|
||||||
|
nodes.push(item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return nodes;
|
||||||
|
},
|
||||||
|
onCheckRoot: function (row, data) {
|
||||||
|
var that = this;
|
||||||
|
return that.options.rootParentId === row[that.options.parentIdField] ||
|
||||||
|
!row[that.options.parentIdField];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var BootstrapTable = $.fn.bootstrapTable.Constructor,
|
||||||
|
_init = BootstrapTable.prototype.init,
|
||||||
|
_initRow = BootstrapTable.prototype.initRow,
|
||||||
|
_initHeader = BootstrapTable.prototype.initHeader,
|
||||||
|
_rowStyle = null;
|
||||||
|
|
||||||
|
BootstrapTable.prototype.init = function () {
|
||||||
|
_rowStyle = this.options.rowStyle;
|
||||||
|
_init.apply(this, Array.prototype.slice.apply(arguments));
|
||||||
|
};
|
||||||
|
|
||||||
|
// td
|
||||||
|
BootstrapTable.prototype.initHeader = function () {
|
||||||
|
var that = this;
|
||||||
|
_initHeader.apply(that, Array.prototype.slice.apply(arguments));
|
||||||
|
var treeShowField = that.options.treeShowField;
|
||||||
|
if (treeShowField) {
|
||||||
|
$.each(this.header.fields, function (i, field) {
|
||||||
|
if (treeShowField === field) {
|
||||||
|
that.treeEnable = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var initTr = function (item, idx, data, parentDom) {
|
||||||
|
var that = this;
|
||||||
|
var nodes = that.options.onGetNodes.apply(that, [item, data]);
|
||||||
|
item._nodes = nodes;
|
||||||
|
parentDom.append(_initRow.apply(that, [item, idx, data, parentDom]));
|
||||||
|
|
||||||
|
// init sub node
|
||||||
|
var len = nodes.length - 1;
|
||||||
|
for (var i = 0; i <= len; i++) {
|
||||||
|
var node = nodes[i];
|
||||||
|
node._level = item._level + 1;
|
||||||
|
node._parent = item;
|
||||||
|
if (i === len)
|
||||||
|
node._last = 1;
|
||||||
|
// jquery.treegrid.js
|
||||||
|
that.options.rowStyle = function (item, idx) {
|
||||||
|
var res = _rowStyle.apply(that, Array.prototype.slice.apply(arguments));
|
||||||
|
var id = item[that.options.idField] ? item[that.options.idField] : 0;
|
||||||
|
var pid = item[that.options.parentIdField] ? item[that.options.parentIdField] : 0;
|
||||||
|
res.classes = [
|
||||||
|
res.classes || '',
|
||||||
|
'treegrid-' + id,
|
||||||
|
'treegrid-parent-' + pid
|
||||||
|
].join(' ');
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
initTr.apply(that, [node, $.inArray(node, data), data, parentDom]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// tr
|
||||||
|
BootstrapTable.prototype.initRow = function (item, idx, data, parentDom) {
|
||||||
|
var that = this;
|
||||||
|
if (that.treeEnable) {
|
||||||
|
// init root node
|
||||||
|
if (that.options.onCheckRoot.apply(that, [item, data])) {
|
||||||
|
if (item._level === undefined) {
|
||||||
|
item._level = 0;
|
||||||
|
}
|
||||||
|
// jquery.treegrid.js
|
||||||
|
that.options.rowStyle = function (item, idx) {
|
||||||
|
var res = _rowStyle.apply(that, Array.prototype.slice.apply(arguments));
|
||||||
|
var x = item[that.options.idField] ? item[that.options.idField] : 0;
|
||||||
|
res.classes = [
|
||||||
|
res.classes || '',
|
||||||
|
'treegrid-' + x
|
||||||
|
].join(' ');
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
initTr.apply(that, [item, idx, data, parentDom]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return _initRow.apply(that, Array.prototype.slice.apply(arguments));
|
||||||
|
};
|
||||||
|
}(jQuery);
|
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "treegrid",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Plugin to support the jquery treegrid.",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/treegrid",
|
||||||
|
"example": "https://github.com/wenzhixin/bootstrap-table-examples/blob/master/extensions/treegrid.html",
|
||||||
|
|
||||||
|
"plugins": [{
|
||||||
|
"name": "bootstrap-table-treegrid",
|
||||||
|
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/treegrid"
|
||||||
|
}],
|
||||||
|
|
||||||
|
"author": {
|
||||||
|
"name": "foreveryang321",
|
||||||
|
"image": "https://avatars0.githubusercontent.com/u/5868190"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user