Merge pull request #910 from SchrodingersGat/multi-level-bom
Multi level bom
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAFtJREFUeNpi/P//PwMlgImBQsA44C6giQENDAwM//HgBmLCAF/AMBLjBUeixf///48L7/+PCvZjU4fPAAc0AxywqcMXCwegGJ1NckL6jx5wpKYDxqGXEkkCgAEAmrqBIejdgngAAAAASUVORK5CYII=);
|
||||
}
|
||||
|
||||
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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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"
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 346 B |
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"
|
||||
}
|
||||
}
|
3
InvenTree/InvenTree/static/treegrid/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
/nbproject
|
||||
/node_modules
|
||||
/bower_modules
|
43
InvenTree/InvenTree/static/treegrid/CHANGELOG.txt
Normal file
@ -0,0 +1,43 @@
|
||||
== 0.3.0 - 03 February 2015
|
||||
* Perfomance optimization
|
||||
* Bootstrap 3 update
|
||||
* Add minifiyed js
|
||||
* Add npm installation
|
||||
* Add borew installation
|
||||
|
||||
== 0.2.1 - 21 January 2014
|
||||
* Add events support
|
||||
|
||||
== 0.1.9 - 18 December 2013
|
||||
* Fix table in table bug (thanks liuspcn)
|
||||
|
||||
== 0.1.8 - 16 December 2013
|
||||
* Fix support alphanumeric id (you can use "-" symbol in id)
|
||||
|
||||
== 0.1.7 - 15 November 2013
|
||||
* Fix isLast method. https://github.com/maxazan/jquery-treegrid/issues/4
|
||||
* Add isFirst method
|
||||
|
||||
== 0.1.6 - 14 November 2013
|
||||
* Add isNode method
|
||||
* Add getAllNodes method
|
||||
* Fix isLast method. Throw error if method is not node of tree.
|
||||
|
||||
== 0.1.5
|
||||
* Add support alphanumeric id
|
||||
|
||||
== 0.1.4
|
||||
* Add treeRow parameter
|
||||
|
||||
== 0.1.3 - 28 August 2013
|
||||
* Added bootstrap examples
|
||||
* Changed expander functionality
|
||||
* Fixed $.data set and get
|
||||
* Fixed $.extends settings
|
||||
* Adding new test
|
||||
|
||||
== 0.1.2 - 26 August 2013
|
||||
* Added save state
|
||||
|
||||
== 0.1.0 - 15 August 2013
|
||||
* Public release
|
23
InvenTree/InvenTree/static/treegrid/Gruntfile.js
Normal file
@ -0,0 +1,23 @@
|
||||
module.exports = function(grunt) {
|
||||
|
||||
// Project configuration.
|
||||
grunt.initConfig({
|
||||
pkg: grunt.file.readJSON('package.json'),
|
||||
uglify: {
|
||||
options: {
|
||||
banner: '/*! <%= pkg.name %> <%= pkg.version %> */\n'
|
||||
},
|
||||
build: {
|
||||
src: 'js/jquery.treegrid.js',
|
||||
dest: 'js/jquery.treegrid.min.js'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Load the plugin that provides the "uglify" task.
|
||||
grunt.loadNpmTasks('grunt-contrib-uglify');
|
||||
|
||||
// Default task(s).
|
||||
grunt.registerTask('default', ['uglify']);
|
||||
|
||||
};
|
20
InvenTree/InvenTree/static/treegrid/LICENSE
Normal file
@ -0,0 +1,20 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013
|
||||
|
||||
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.
|
21
InvenTree/InvenTree/static/treegrid/README.md
Normal file
@ -0,0 +1,21 @@
|
||||
TreeGrid plugin for jQuery
|
||||
==========
|
||||
|
||||
See more information at http://maxazan.github.io/jquery-treegrid
|
||||
|
||||
## Installation
|
||||
|
||||
|
||||
### Using npm
|
||||
```
|
||||
npm install jquery-treegrid
|
||||
```
|
||||
|
||||
### Using bower
|
||||
```
|
||||
bower install jquery-treegrid
|
||||
```
|
||||
|
||||
### From source
|
||||
|
||||
Download [source](https://github.com/maxazan/jquery-treegrid/archive/master.zip) from github.com
|
33
InvenTree/InvenTree/static/treegrid/bower.json
Normal file
@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": "jquery-treegrid",
|
||||
"description": "TreeGrid plugin for jQuery.",
|
||||
"version": "0.3.0",
|
||||
"homepage": "http://maxazan.github.io/jquery-treegrid",
|
||||
"license": "MIT",
|
||||
"ignore": [
|
||||
"examples",
|
||||
"tests",
|
||||
"**/.*",
|
||||
"composer.json",
|
||||
"index.html",
|
||||
"params.json",
|
||||
"style.css",
|
||||
"test.html",
|
||||
"treegrid.jquery.json"
|
||||
],
|
||||
"keywords": [
|
||||
"jquery",
|
||||
"javascript",
|
||||
"plugin",
|
||||
"bootstrap",
|
||||
"treegrid",
|
||||
"treeview"
|
||||
],
|
||||
"dependencies": {
|
||||
"jquery": ">= 1.9.1",
|
||||
"jquery.cookie": ">= 1.4.1"
|
||||
},
|
||||
"authors": [
|
||||
"Maksym Pomazan"
|
||||
]
|
||||
}
|
12
InvenTree/InvenTree/static/treegrid/composer.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "maxazan/jquery-treegrid",
|
||||
"description": "jquery treegrid plugin",
|
||||
"keywords": ["jquery", "grid", "treegrid", "tree"],
|
||||
"homepage": "http://maxazan.github.io/jquery-treegrid",
|
||||
"type": "library",
|
||||
"license": "MIT",
|
||||
"support": {
|
||||
"issues": "https://github.com/maxazan/jquery-treegrid/issues",
|
||||
"source": "https://github.com/maxazan/jquery-treegrid"
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
.treegrid-indent {width:16px; height: 16px; display: inline-block; position: relative;}
|
||||
|
||||
.treegrid-expander {width:16px; height: 16px; display: inline-block; position: relative; cursor: pointer;}
|
||||
|
||||
.treegrid-expander-expanded{background-image: url(../img/collapse.png); }
|
||||
.treegrid-expander-collapsed{background-image: url(../img/expand.png);}
|
1109
InvenTree/InvenTree/static/treegrid/examples/bootstrap-2.3.2/css/bootstrap-responsive.css
vendored
Normal file
6167
InvenTree/InvenTree/static/treegrid/examples/bootstrap-2.3.2/css/bootstrap.css
vendored
Normal file
9
InvenTree/InvenTree/static/treegrid/examples/bootstrap-2.3.2/css/bootstrap.min.css
vendored
Normal file
After Width: | Height: | Size: 8.6 KiB |
After Width: | Height: | Size: 12 KiB |
2280
InvenTree/InvenTree/static/treegrid/examples/bootstrap-2.3.2/js/bootstrap.js
vendored
Normal file
6
InvenTree/InvenTree/static/treegrid/examples/bootstrap-2.3.2/js/bootstrap.min.js
vendored
Normal file
131
InvenTree/InvenTree/static/treegrid/examples/example-basic.html
Normal file
@ -0,0 +1,131 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="chrome=1">
|
||||
<title>Jquery-treegrid basic example</title>
|
||||
|
||||
<link rel="stylesheet" href="../styles.css">
|
||||
<link rel="stylesheet" href="http://yandex.st/highlightjs/7.3/styles/default.min.css">
|
||||
<link rel="stylesheet" href="../css/jquery.treegrid.css">
|
||||
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="../js/jquery.treegrid.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$('.tree').treegrid();
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<script src="http://yandex.st/highlightjs/7.3/highlight.min.js"></script>
|
||||
<script>hljs.initHighlightingOnLoad();</script>
|
||||
<script>
|
||||
(function(i, s, o, g, r, a, m) {
|
||||
i['GoogleAnalyticsObject'] = r;
|
||||
i[r] = i[r] || function() {
|
||||
(i[r].q = i[r].q || []).push(arguments)
|
||||
}, i[r].l = 1 * new Date();
|
||||
a = s.createElement(o),
|
||||
m = s.getElementsByTagName(o)[0];
|
||||
a.async = 1;
|
||||
a.src = g;
|
||||
m.parentNode.insertBefore(a, m)
|
||||
})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');
|
||||
|
||||
ga('create', 'UA-43342702-1', 'maxazan.github.io');
|
||||
ga('send', 'pageview');
|
||||
|
||||
</script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrapper">
|
||||
|
||||
|
||||
<h1><a href="http://maxazan.github.io/jquery-treegrid/">TreeGrid</a> Basic example</h1>
|
||||
|
||||
<table class="tree">
|
||||
<tr class="treegrid-1">
|
||||
<td>Root node</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-2 treegrid-parent-1">
|
||||
<td>Node 1-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-3 treegrid-parent-1">
|
||||
<td>Node 1-2</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-4 treegrid-parent-3">
|
||||
<td>Node 1-2-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h2>Code</h2>
|
||||
|
||||
<pre>
|
||||
<code class='html'>
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="chrome=1">
|
||||
<title>Jquery-treegrid basic example</title>
|
||||
|
||||
<link rel="stylesheet" href="../css/jquery.treegrid.css">
|
||||
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="../js/jquery.treegrid.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$('.tree').treegrid();
|
||||
});
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<table class="tree">
|
||||
<tr class="treegrid-1">
|
||||
<td>Root node</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-2 treegrid-parent-1">
|
||||
<td>Node 1-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-3 treegrid-parent-1">
|
||||
<td>Node 1-2</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-4 treegrid-parent-3">
|
||||
<td>Node 1-2-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
</code>
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
var metas = document.getElementsByTagName('meta');
|
||||
var i;
|
||||
if (navigator.userAgent.match(/iPhone/i)) {
|
||||
for (i = 0; i < metas.length; i++) {
|
||||
if (metas[i].name == "viewport") {
|
||||
metas[i].content = "width=device-width, minimum-scale=1.0, maximum-scale=1.0";
|
||||
}
|
||||
}
|
||||
document.addEventListener("gesturestart", gestureStart, false);
|
||||
}
|
||||
function gestureStart() {
|
||||
for (i = 0; i < metas.length; i++) {
|
||||
if (metas[i].name == "viewport") {
|
||||
metas[i].content = "width=device-width, minimum-scale=0.25, maximum-scale=1.6";
|
||||
}
|
||||
}
|
||||
}</script>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,144 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
<link rel="shortcut icon" href="../../assets/ico/favicon.png">
|
||||
|
||||
<title>TreeGrid for Bootstrap 2.3.x</title>
|
||||
|
||||
<!-- Bootstrap core CSS -->
|
||||
<link href="bootstrap-2.3.2/css/bootstrap.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="../css/jquery.treegrid.css">
|
||||
<link rel="stylesheet" href="http://yandex.st/highlightjs/7.3/styles/default.min.css">
|
||||
<script src="http://yandex.st/highlightjs/7.3/highlight.min.js"></script>
|
||||
<script>hljs.initHighlightingOnLoad();</script>
|
||||
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="../js/jquery.treegrid.js"></script>
|
||||
<script type="text/javascript" src="../js/jquery.treegrid.bootstrap2.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$('.tree').treegrid();
|
||||
$('.tree2').treegrid({
|
||||
expanderExpandedClass: 'icon-minus-sign',
|
||||
expanderCollapsedClass: 'icon-plus-sign'
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<script>
|
||||
(function(i, s, o, g, r, a, m) {
|
||||
i['GoogleAnalyticsObject'] = r;
|
||||
i[r] = i[r] || function() {
|
||||
(i[r].q = i[r].q || []).push(arguments)
|
||||
}, i[r].l = 1 * new Date();
|
||||
a = s.createElement(o),
|
||||
m = s.getElementsByTagName(o)[0];
|
||||
a.async = 1;
|
||||
a.src = g;
|
||||
m.parentNode.insertBefore(a, m)
|
||||
})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');
|
||||
|
||||
ga('create', 'UA-43342702-1', 'maxazan.github.io');
|
||||
ga('send', 'pageview');
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
|
||||
<h1><a href="http://maxazan.github.io/jquery-treegrid/">TreeGrid</a> Bootstrap 2.3.2 examples</h1>
|
||||
|
||||
<table class="table tree">
|
||||
<tr class="treegrid-1">
|
||||
<td>Root node 1</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-2 treegrid-parent-1">
|
||||
<td>Node 1-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-3 treegrid-parent-1">
|
||||
<td>Node 1-2</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-4 treegrid-parent-3">
|
||||
<td>Node 1-2-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-5">
|
||||
<td>Root node 2</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-6 treegrid-parent-5">
|
||||
<td>Node 2-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-7 treegrid-parent-5">
|
||||
<td>Node 2-2</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-8 treegrid-parent-7">
|
||||
<td>Node 2-2-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h3>Source</h3>
|
||||
|
||||
<pre><code class="html"><link href="bootstrap-2.3.2/css/bootstrap.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="../css/jquery.treegrid.css">
|
||||
|
||||
<script type="text/javascript" src="../js/jquery.treegrid.js"></script>
|
||||
<script type="text/javascript" src="../js/jquery.treegrid.bootstrap2.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$('.tree').treegrid();
|
||||
});
|
||||
</script></code></pre>
|
||||
<h2>Bootstrap grid example<br>
|
||||
table-bordered table-striped table-condensed<br>
|
||||
with custom expander</h2>
|
||||
<table class="table tree2 table-bordered table-striped table-condensed">
|
||||
<tr class="treegrid-1">
|
||||
<td>Root node 1</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-2 treegrid-parent-1">
|
||||
<td>Node 1-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-3 treegrid-parent-1">
|
||||
<td>Node 1-2</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-4 treegrid-parent-3">
|
||||
<td>Node 1-2-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-5">
|
||||
<td>Root node 2</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-6 treegrid-parent-5">
|
||||
<td>Node 2-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-7 treegrid-parent-5">
|
||||
<td>Node 2-2</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-8 treegrid-parent-7">
|
||||
<td>Node 2-2-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h3>Source</h3>
|
||||
|
||||
<pre><code class="html"><link href="bootstrap-2.3.2/css/bootstrap.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="../css/jquery.treegrid.css">
|
||||
|
||||
<script type="text/javascript" src="../js/jquery.treegrid.js"></script>
|
||||
<script type="text/javascript" src="../js/jquery.treegrid.bootstrap2.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$('.tree').treegrid({
|
||||
expanderExpandedClass: 'icon-minus-sign',
|
||||
expanderCollapsedClass: 'icon-plus-sign'
|
||||
});
|
||||
});
|
||||
</script></code></pre>
|
||||
</div> <!-- /container -->
|
||||
|
||||
|
||||
<!-- Bootstrap core JavaScript
|
||||
================================================== -->
|
||||
<!-- Placed at the end of the document so the pages load faster -->
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,146 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
<link rel="shortcut icon" href="../../assets/ico/favicon.png">
|
||||
|
||||
<title>TreeGrid for Bootstrap 3.0.x</title>
|
||||
|
||||
<!-- Bootstrap core CSS -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="../css/jquery.treegrid.css">
|
||||
<link rel="stylesheet" href="http://yandex.st/highlightjs/7.3/styles/default.min.css">
|
||||
<script src="http://yandex.st/highlightjs/7.3/highlight.min.js"></script>
|
||||
<script>hljs.initHighlightingOnLoad();</script>
|
||||
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="../js/jquery.treegrid.js"></script>
|
||||
<script type="text/javascript" src="../js/jquery.treegrid.bootstrap3.js"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
$(document).ready(function() {
|
||||
$('.tree').treegrid();
|
||||
$('.tree-2').treegrid({
|
||||
expanderExpandedClass: 'glyphicon glyphicon-minus',
|
||||
expanderCollapsedClass: 'glyphicon glyphicon-plus'
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
<script>
|
||||
(function(i, s, o, g, r, a, m) {
|
||||
i['GoogleAnalyticsObject'] = r;
|
||||
i[r] = i[r] || function() {
|
||||
(i[r].q = i[r].q || []).push(arguments)
|
||||
}, i[r].l = 1 * new Date();
|
||||
a = s.createElement(o),
|
||||
m = s.getElementsByTagName(o)[0];
|
||||
a.async = 1;
|
||||
a.src = g;
|
||||
m.parentNode.insertBefore(a, m)
|
||||
})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');
|
||||
|
||||
ga('create', 'UA-43342702-1', 'maxazan.github.io');
|
||||
ga('send', 'pageview');
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
|
||||
<h1><a href="http://maxazan.github.io/jquery-treegrid/">TreeGrid</a> Bootstrap 3 examples</h1>
|
||||
|
||||
<table class="table tree">
|
||||
<tr class="treegrid-1">
|
||||
<td>Root node 1</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-2 treegrid-parent-1">
|
||||
<td>Node 1-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-3 treegrid-parent-1">
|
||||
<td>Node 1-2</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-4 treegrid-parent-3">
|
||||
<td>Node 1-2-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-5">
|
||||
<td>Root node 2</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-6 treegrid-parent-5">
|
||||
<td>Node 2-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-7 treegrid-parent-5">
|
||||
<td>Node 2-2</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-8 treegrid-parent-7">
|
||||
<td>Node 2-2-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h3>Code</h3>
|
||||
|
||||
<pre><code class="html"><link href="bootstrap-3.0.0/css/bootstrap.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="../css/jquery.treegrid.css">
|
||||
|
||||
<script type="text/javascript" src="../js/jquery.treegrid.js"></script>
|
||||
<script type="text/javascript" src="../js/jquery.treegrid.bootstrap3.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$('.tree').treegrid();
|
||||
});
|
||||
</script></code></pre>
|
||||
<h2>Bootstrap TreeGrid example<br>
|
||||
table-bordered table-striped table-condensed<br>
|
||||
custom expander</h2>
|
||||
<table class="table tree-2 table-bordered table-striped table-condensed">
|
||||
<tr class="treegrid-1">
|
||||
<td>Root node 1</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-2 treegrid-parent-1">
|
||||
<td>Node 1-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-3 treegrid-parent-1">
|
||||
<td>Node 1-2</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-4 treegrid-parent-3">
|
||||
<td>Node 1-2-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-5">
|
||||
<td>Root node 2</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-6 treegrid-parent-5">
|
||||
<td>Node 2-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-7 treegrid-parent-5">
|
||||
<td>Node 2-2</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-8 treegrid-parent-7">
|
||||
<td>Node 2-2-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3>Code</h3>
|
||||
<pre><code class="html"><link href="bootstrap-3.0.0/css/bootstrap.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="../css/jquery.treegrid.css">
|
||||
|
||||
<script type="text/javascript" src="../js/jquery.treegrid.js"></script>
|
||||
<script type="text/javascript" src="../js/jquery.treegrid.bootstrap3.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$('.tree').treegrid({
|
||||
expanderExpandedClass: 'glyphicon glyphicon-minus',
|
||||
expanderCollapsedClass: 'glyphicon glyphicon-plus'
|
||||
});
|
||||
});
|
||||
</script></code></pre>
|
||||
</div> <!-- /container -->
|
||||
|
||||
|
||||
<!-- Bootstrap core JavaScript
|
||||
================================================== -->
|
||||
<!-- Placed at the end of the document so the pages load faster -->
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,146 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
<link rel="shortcut icon" href="../../assets/ico/favicon.png">
|
||||
|
||||
<title>TreeGrid for Bootstrap 3.0.x</title>
|
||||
|
||||
<!-- Bootstrap core CSS -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="../css/jquery.treegrid.css">
|
||||
<link rel="stylesheet" href="http://yandex.st/highlightjs/7.3/styles/default.min.css">
|
||||
<script src="http://yandex.st/highlightjs/7.3/highlight.min.js"></script>
|
||||
<script>hljs.initHighlightingOnLoad();</script>
|
||||
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="../js/jquery.treegrid.js"></script>
|
||||
<script type="text/javascript" src="../js/jquery.treegrid.bootstrap3.js"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
$(document).ready(function() {
|
||||
$('.tree').treegrid();
|
||||
$('.tree-2').treegrid({
|
||||
expanderExpandedClass: 'glyphicon glyphicon-minus',
|
||||
expanderCollapsedClass: 'glyphicon glyphicon-plus'
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
<script>
|
||||
(function(i, s, o, g, r, a, m) {
|
||||
i['GoogleAnalyticsObject'] = r;
|
||||
i[r] = i[r] || function() {
|
||||
(i[r].q = i[r].q || []).push(arguments)
|
||||
}, i[r].l = 1 * new Date();
|
||||
a = s.createElement(o),
|
||||
m = s.getElementsByTagName(o)[0];
|
||||
a.async = 1;
|
||||
a.src = g;
|
||||
m.parentNode.insertBefore(a, m)
|
||||
})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');
|
||||
|
||||
ga('create', 'UA-43342702-1', 'maxazan.github.io');
|
||||
ga('send', 'pageview');
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
|
||||
<h1><a href="http://maxazan.github.io/jquery-treegrid/">TreeGrid</a> Bootstrap 3 resize examples</h1>
|
||||
|
||||
<table class="table tree">
|
||||
<tr class="treegrid-1">
|
||||
<td>Root node 1</td><td class="hidden-xs">Additional info</td><td class="hidden-xs hidden-sm">Additional info2</td><td class="hidden-xs hidden-sm hidden-md">Additional info3</td>
|
||||
</tr>
|
||||
<tr class="treegrid-2 treegrid-parent-1">
|
||||
<td>Node 1-1</td><td class="hidden-xs">Additional info</td><td class="hidden-xs hidden-sm">Additional info2</td><td class="hidden-xs hidden-sm hidden-md">Additional info3</td>
|
||||
</tr>
|
||||
<tr class="treegrid-3 treegrid-parent-1">
|
||||
<td>Node 1-2</td><td class="hidden-xs">Additional info</td><td class="hidden-xs hidden-sm">Additional info2</td><td class="hidden-xs hidden-sm hidden-md">Additional info3</td>
|
||||
</tr>
|
||||
<tr class="treegrid-4 treegrid-parent-3">
|
||||
<td>Node 1-2-1</td><td class="hidden-xs">Additional info</td><td class="hidden-xs hidden-sm">Additional info2</td><td class="hidden-xs hidden-sm hidden-md">Additional info3</td>
|
||||
</tr>
|
||||
<tr class="treegrid-5">
|
||||
<td>Root node 2</td><td class="hidden-xs">Additional info</td><td class="hidden-xs hidden-sm">Additional info2</td><td class="hidden-xs hidden-sm hidden-md">Additional info3</td>
|
||||
</tr>
|
||||
<tr class="treegrid-6 treegrid-parent-5">
|
||||
<td>Node 2-1</td><td class="hidden-xs">Additional info</td><td class="hidden-xs hidden-sm">Additional info2</td><td class="hidden-xs hidden-sm hidden-md">Additional info3</td>
|
||||
</tr>
|
||||
<tr class="treegrid-7 treegrid-parent-5">
|
||||
<td>Node 2-2</td><td class="hidden-xs">Additional info</td><td class="hidden-xs hidden-sm">Additional info2</td><td class="hidden-xs hidden-sm hidden-md">Additional info3</td>
|
||||
</tr>
|
||||
<tr class="treegrid-8 treegrid-parent-7">
|
||||
<td>Node 2-2-1</td><td class="hidden-xs">Additional info</td><td class="hidden-xs hidden-sm">Additional info2</td><td class="hidden-xs hidden-sm hidden-md">Additional info3</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h3>Code</h3>
|
||||
|
||||
<pre><code class="html"><link href="bootstrap-3.0.0/css/bootstrap.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="../css/jquery.treegrid.css">
|
||||
|
||||
<script type="text/javascript" src="../js/jquery.treegrid.js"></script>
|
||||
<script type="text/javascript" src="../js/jquery.treegrid.bootstrap3.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$('.tree').treegrid();
|
||||
});
|
||||
</script></code></pre>
|
||||
<h2>Bootstrap TreeGrid example<br>
|
||||
table-bordered table-striped table-condensed<br>
|
||||
custom expander</h2>
|
||||
<table class="table tree-2 table-bordered table-striped table-condensed">
|
||||
<tr class="treegrid-1">
|
||||
<td>Root node 1</td><td class="hidden-xs">Additional info</td><td class="hidden-xs hidden-sm">Additional info2</td><td class="hidden-xs hidden-sm hidden-md">Additional info3</td>
|
||||
</tr>
|
||||
<tr class="treegrid-2 treegrid-parent-1">
|
||||
<td>Node 1-1</td><td class="hidden-xs">Additional info</td><td class="hidden-xs hidden-sm">Additional info2</td><td class="hidden-xs hidden-sm hidden-md">Additional info3</td>
|
||||
</tr>
|
||||
<tr class="treegrid-3 treegrid-parent-1">
|
||||
<td>Node 1-2</td><td class="hidden-xs">Additional info</td><td class="hidden-xs hidden-sm">Additional info2</td><td class="hidden-xs hidden-sm hidden-md">Additional info3</td>
|
||||
</tr>
|
||||
<tr class="treegrid-4 treegrid-parent-3">
|
||||
<td>Node 1-2-1</td><td class="hidden-xs">Additional info</td><td class="hidden-xs hidden-sm">Additional info2</td><td class="hidden-xs hidden-sm hidden-md">Additional info3</td>
|
||||
</tr>
|
||||
<tr class="treegrid-5">
|
||||
<td>Root node 2</td><td class="hidden-xs">Additional info</td><td class="hidden-xs hidden-sm">Additional info2</td><td class="hidden-xs hidden-sm hidden-md">Additional info3</td>
|
||||
</tr>
|
||||
<tr class="treegrid-6 treegrid-parent-5">
|
||||
<td>Node 2-1</td><td class="hidden-xs">Additional info</td><td class="hidden-xs hidden-sm">Additional info2</td><td class="hidden-xs hidden-sm hidden-md">Additional info3</td>
|
||||
</tr>
|
||||
<tr class="treegrid-7 treegrid-parent-5">
|
||||
<td>Node 2-2</td><td class="hidden-xs">Additional info</td><td class="hidden-xs hidden-sm">Additional info2</td><td class="hidden-xs hidden-sm hidden-md">Additional info3</td>
|
||||
</tr>
|
||||
<tr class="treegrid-8 treegrid-parent-7">
|
||||
<td>Node 2-2-1</td><td class="hidden-xs">Additional info</td><td class="hidden-xs hidden-sm">Additional info2</td><td class="hidden-xs hidden-sm hidden-md">Additional info3</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3>Code</h3>
|
||||
<pre><code class="html"><link href="bootstrap-3.0.0/css/bootstrap.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="../css/jquery.treegrid.css">
|
||||
|
||||
<script type="text/javascript" src="../js/jquery.treegrid.js"></script>
|
||||
<script type="text/javascript" src="../js/jquery.treegrid.bootstrap3.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$('.tree').treegrid({
|
||||
expanderExpandedClass: 'glyphicon glyphicon-minus',
|
||||
expanderCollapsedClass: 'glyphicon glyphicon-plus'
|
||||
});
|
||||
});
|
||||
</script></code></pre>
|
||||
</div> <!-- /container -->
|
||||
|
||||
|
||||
<!-- Bootstrap core JavaScript
|
||||
================================================== -->
|
||||
<!-- Placed at the end of the document so the pages load faster -->
|
||||
</body>
|
||||
</html>
|
135
InvenTree/InvenTree/static/treegrid/examples/example-column.html
Normal file
@ -0,0 +1,135 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="chrome=1">
|
||||
<title>TreeGrid example with tree in 2nd column</title>
|
||||
|
||||
<link rel="stylesheet" href="../styles.css">
|
||||
<link rel="stylesheet" href="http://yandex.st/highlightjs/7.3/styles/default.min.css">
|
||||
<link rel="stylesheet" href="../css/jquery.treegrid.css">
|
||||
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="../js/jquery.treegrid.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$('.tree').treegrid({
|
||||
treeColumn: 1
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<script src="http://yandex.st/highlightjs/7.3/highlight.min.js"></script>
|
||||
<script>hljs.initHighlightingOnLoad();</script>
|
||||
<script>
|
||||
(function(i, s, o, g, r, a, m) {
|
||||
i['GoogleAnalyticsObject'] = r;
|
||||
i[r] = i[r] || function() {
|
||||
(i[r].q = i[r].q || []).push(arguments)
|
||||
}, i[r].l = 1 * new Date();
|
||||
a = s.createElement(o),
|
||||
m = s.getElementsByTagName(o)[0];
|
||||
a.async = 1;
|
||||
a.src = g;
|
||||
m.parentNode.insertBefore(a, m)
|
||||
})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');
|
||||
|
||||
ga('create', 'UA-43342702-1', 'maxazan.github.io');
|
||||
ga('send', 'pageview');
|
||||
|
||||
</script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrapper">
|
||||
|
||||
|
||||
<h1><a href="http://maxazan.github.io/jquery-treegrid/">TreeGrid</a> example with tree in 2nd column</h1>
|
||||
|
||||
<table class="tree">
|
||||
<tr class="treegrid-1">
|
||||
<td>Root node</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-2 treegrid-parent-1">
|
||||
<td>Node 1-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-3 treegrid-parent-1">
|
||||
<td>Node 1-2</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-4 treegrid-parent-3">
|
||||
<td>Node 1-2-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h2>Code</h2>
|
||||
|
||||
<pre>
|
||||
<code class='html'>
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="chrome=1">
|
||||
<title>Jquery-treegrid basic example</title>
|
||||
|
||||
<link rel="stylesheet" href="../css/jquery.treegrid.css">
|
||||
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="../js/jquery.treegrid.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$('.tree').treegrid({
|
||||
treeColumn: 1
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<table class="tree">
|
||||
<tr class="treegrid-1">
|
||||
<td>Root node</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-2 treegrid-parent-1">
|
||||
<td>Node 1-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-3 treegrid-parent-1">
|
||||
<td>Node 1-2</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-4 treegrid-parent-3">
|
||||
<td>Node 1-2-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
</code>
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
var metas = document.getElementsByTagName('meta');
|
||||
var i;
|
||||
if (navigator.userAgent.match(/iPhone/i)) {
|
||||
for (i = 0; i < metas.length; i++) {
|
||||
if (metas[i].name == "viewport") {
|
||||
metas[i].content = "width=device-width, minimum-scale=1.0, maximum-scale=1.0";
|
||||
}
|
||||
}
|
||||
document.addEventListener("gesturestart", gestureStart, false);
|
||||
}
|
||||
function gestureStart() {
|
||||
for (i = 0; i < metas.length; i++) {
|
||||
if (metas[i].name == "viewport") {
|
||||
metas[i].content = "width=device-width, minimum-scale=0.25, maximum-scale=1.6";
|
||||
}
|
||||
}
|
||||
}</script>
|
||||
|
||||
</body>
|
||||
</html>
|
155
InvenTree/InvenTree/static/treegrid/examples/example-events.html
Normal file
@ -0,0 +1,155 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="chrome=1">
|
||||
<title>TreeGrid events example</title>
|
||||
|
||||
<link rel="stylesheet" href="../styles.css">
|
||||
<link rel="stylesheet" href="http://yandex.st/highlightjs/7.3/styles/default.min.css">
|
||||
<link rel="stylesheet" href="../css/jquery.treegrid.css">
|
||||
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="../js/jquery.treegrid.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$('.tree').treegrid({
|
||||
onChange: function() {
|
||||
alert("Changed: " + $(this).attr("id"));
|
||||
},
|
||||
onCollapse: function() {
|
||||
alert("Collapsed " + $(this).attr("id"));
|
||||
},
|
||||
onExpand: function() {
|
||||
alert("Expanded: " + $(this).attr("id"));
|
||||
}});
|
||||
$('#node-1').on("change", function() {
|
||||
alert("Event from " + $(this).attr("id"));
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<script src="http://yandex.st/highlightjs/7.3/highlight.min.js"></script>
|
||||
<script>hljs.initHighlightingOnLoad();</script>
|
||||
<script>
|
||||
(function(i, s, o, g, r, a, m) {
|
||||
i['GoogleAnalyticsObject'] = r;
|
||||
i[r] = i[r] || function() {
|
||||
(i[r].q = i[r].q || []).push(arguments)
|
||||
}, i[r].l = 1 * new Date();
|
||||
a = s.createElement(o),
|
||||
m = s.getElementsByTagName(o)[0];
|
||||
a.async = 1;
|
||||
a.src = g;
|
||||
m.parentNode.insertBefore(a, m)
|
||||
})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');
|
||||
|
||||
ga('create', 'UA-43342702-1', 'maxazan.github.io');
|
||||
ga('send', 'pageview');
|
||||
|
||||
</script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrapper">
|
||||
|
||||
|
||||
<h1><a href="http://maxazan.github.io/jquery-treegrid/">TreeGrid</a> events example</h1>
|
||||
|
||||
<table class="tree">
|
||||
<tr id="node-1" class="treegrid-1">
|
||||
<td>Root node</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr id="node-1-1" class="treegrid-2 treegrid-parent-1">
|
||||
<td>Node 1-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr id="node-1-2" class="treegrid-3 treegrid-parent-1">
|
||||
<td>Node 1-2</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr id="node-1-2-1" class="treegrid-4 treegrid-parent-3">
|
||||
<td>Node 1-2-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h2>Code</h2>
|
||||
|
||||
<pre>
|
||||
<code class='html'>
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="chrome=1">
|
||||
<title>Jquery-treegrid basic example</title>
|
||||
|
||||
<link rel="stylesheet" href="../css/jquery.treegrid.css">
|
||||
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="../js/jquery.treegrid.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$('.tree').treegrid({
|
||||
onChange: function() {
|
||||
alert("Changed: "+$(this).attr("id"));
|
||||
},
|
||||
onCollapse: function() {
|
||||
alert("Collapsed: "+$(this).attr("id"));
|
||||
},
|
||||
onExpand: function() {
|
||||
alert("Expanded "+$(this).attr("id"));
|
||||
}});
|
||||
$('#node-1').on("change", function() {
|
||||
alert("Event from " + $(this).attr("id"));
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<table class="tree">
|
||||
<tr class="treegrid-1">
|
||||
<td>Root node</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-2 treegrid-parent-1">
|
||||
<td>Node 1-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-3 treegrid-parent-1">
|
||||
<td>Node 1-2</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-4 treegrid-parent-3">
|
||||
<td>Node 1-2-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
</code>
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
var metas = document.getElementsByTagName('meta');
|
||||
var i;
|
||||
if (navigator.userAgent.match(/iPhone/i)) {
|
||||
for (i = 0; i < metas.length; i++) {
|
||||
if (metas[i].name == "viewport") {
|
||||
metas[i].content = "width=device-width, minimum-scale=1.0, maximum-scale=1.0";
|
||||
}
|
||||
}
|
||||
document.addEventListener("gesturestart", gestureStart, false);
|
||||
}
|
||||
function gestureStart() {
|
||||
for (i = 0; i < metas.length; i++) {
|
||||
if (metas[i].name == "viewport") {
|
||||
metas[i].content = "width=device-width, minimum-scale=0.25, maximum-scale=1.6";
|
||||
}
|
||||
}
|
||||
}</script>
|
||||
|
||||
</body>
|
||||
</html>
|
113
InvenTree/InvenTree/static/treegrid/examples/example-huge.html
Normal file
@ -0,0 +1,113 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="chrome=1">
|
||||
<title>Jquery-treegrid basic example</title>
|
||||
|
||||
<link rel="stylesheet" href="../styles.css">
|
||||
<link rel="stylesheet" href="../css/jquery.treegrid.css">
|
||||
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="../js/jquery.treegrid.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
//create huge treetable
|
||||
var count_root_elements=100;
|
||||
var count_deep=10;
|
||||
console.log('init');
|
||||
for(var i=0; i<count_root_elements; i++){
|
||||
console.log('add');
|
||||
var tr=$("<tr></tr>").addClass("treegrid-"+i+"-0").appendTo($('.tree')).html("<td>Root node "+i+"</td><td>Additional info</td>");
|
||||
|
||||
for(var j=1; j<count_deep; j++){
|
||||
$("<tr></tr>").addClass("treegrid-"+i+"-"+j).addClass("treegrid-parent-"+i+"-"+(j-1)).appendTo($('.tree')).html("<td>Child node "+i+"-"+j+"</td><td>Additional info</td>");
|
||||
}
|
||||
}
|
||||
|
||||
$('.tree').treegrid();
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrapper">
|
||||
|
||||
|
||||
<h1><a href="http://maxazan.github.io/jquery-treegrid/">TreeGrid</a> Big data example</h1>
|
||||
|
||||
<table class="tree"></table>
|
||||
|
||||
<h2>Code</h2>
|
||||
|
||||
<pre>
|
||||
<code class='html'>
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="chrome=1">
|
||||
<title>Jquery-treegrid basic example</title>
|
||||
|
||||
<link rel="stylesheet" href="../css/jquery.treegrid.css">
|
||||
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="../js/jquery.treegrid.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$('.tree').treegrid();
|
||||
});
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<table class="tree">
|
||||
<tr class="treegrid-1">
|
||||
<td>Root node</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-2 treegrid-parent-1">
|
||||
<td>Node 1-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-3 treegrid-parent-1">
|
||||
<td>Node 1-2</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-4 treegrid-parent-3">
|
||||
<td>Node 1-2-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
</code>
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
var metas = document.getElementsByTagName('meta');
|
||||
var i;
|
||||
if (navigator.userAgent.match(/iPhone/i)) {
|
||||
for (i = 0; i < metas.length; i++) {
|
||||
if (metas[i].name == "viewport") {
|
||||
metas[i].content = "width=device-width, minimum-scale=1.0, maximum-scale=1.0";
|
||||
}
|
||||
}
|
||||
document.addEventListener("gesturestart", gestureStart, false);
|
||||
}
|
||||
function gestureStart() {
|
||||
for (i = 0; i < metas.length; i++) {
|
||||
if (metas[i].name == "viewport") {
|
||||
metas[i].content = "width=device-width, minimum-scale=0.25, maximum-scale=1.6";
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,162 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="chrome=1">
|
||||
<title>Jquery-treegrid save state example</title>
|
||||
|
||||
<link rel="stylesheet" href="../styles.css">
|
||||
<link rel="stylesheet" href="http://yandex.st/highlightjs/7.3/styles/default.min.css">
|
||||
<link rel="stylesheet" href="../css/jquery.treegrid.css">
|
||||
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="../js/jquery.treegrid.js"></script>
|
||||
<script type="text/javascript" src="../js/jquery.cookie.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$('.tree').treegrid({
|
||||
'initialState': 'collapsed',
|
||||
'saveState': true,
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<script src="http://yandex.st/highlightjs/7.3/highlight.min.js"></script>
|
||||
<script>hljs.initHighlightingOnLoad();</script>
|
||||
<script>
|
||||
(function(i, s, o, g, r, a, m) {
|
||||
i['GoogleAnalyticsObject'] = r;
|
||||
i[r] = i[r] || function() {
|
||||
(i[r].q = i[r].q || []).push(arguments)
|
||||
}, i[r].l = 1 * new Date();
|
||||
a = s.createElement(o),
|
||||
m = s.getElementsByTagName(o)[0];
|
||||
a.async = 1;
|
||||
a.src = g;
|
||||
m.parentNode.insertBefore(a, m)
|
||||
})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');
|
||||
|
||||
ga('create', 'UA-43342702-1', 'maxazan.github.io');
|
||||
ga('send', 'pageview');
|
||||
|
||||
</script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrapper">
|
||||
|
||||
|
||||
<h1><a href="http://maxazan.github.io/jquery-treegrid/">TreeGrid</a> save state example</h1>
|
||||
<p>You can reload page. The tree state is saved.</p>
|
||||
<table class="tree">
|
||||
<tr class="treegrid-1">
|
||||
<td>Root node 1</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-2 treegrid-parent-1">
|
||||
<td>Node 1-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-3 treegrid-parent-1">
|
||||
<td>Node 1-2</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-4 treegrid-parent-3">
|
||||
<td>Node 1-2-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-5">
|
||||
<td>Root node 2</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-6 treegrid-parent-5">
|
||||
<td>Node 2-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-7 treegrid-parent-5">
|
||||
<td>Node 2-2</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-8 treegrid-parent-7">
|
||||
<td>Node 2-2-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h2>Code</h2>
|
||||
|
||||
<pre>
|
||||
<code class='html'>
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="chrome=1">
|
||||
<title>Jquery-treegrid basic example</title>
|
||||
|
||||
<link rel="stylesheet" href="../css/jquery.treegrid.css">
|
||||
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="../js/jquery.treegrid.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$('.tree').treegrid({
|
||||
'initialState': 'collapsed',
|
||||
'saveState': true,
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<table class="tree">
|
||||
<tr class="treegrid-1">
|
||||
<td>Root node 1</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-2 treegrid-parent-1">
|
||||
<td>Node 1-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-3 treegrid-parent-1">
|
||||
<td>Node 1-2</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-4 treegrid-parent-3">
|
||||
<td>Node 1-2-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-5">
|
||||
<td>Root node 2</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-6 treegrid-parent-5">
|
||||
<td>Node 2-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-7 treegrid-parent-5">
|
||||
<td>Node 2-2</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-8 treegrid-parent-7">
|
||||
<td>Node 2-2-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
</code>
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
var metas = document.getElementsByTagName('meta');
|
||||
var i;
|
||||
if (navigator.userAgent.match(/iPhone/i)) {
|
||||
for (i = 0; i < metas.length; i++) {
|
||||
if (metas[i].name == "viewport") {
|
||||
metas[i].content = "width=device-width, minimum-scale=1.0, maximum-scale=1.0";
|
||||
}
|
||||
}
|
||||
document.addEventListener("gesturestart", gestureStart, false);
|
||||
}
|
||||
function gestureStart() {
|
||||
for (i = 0; i < metas.length; i++) {
|
||||
if (metas[i].name == "viewport") {
|
||||
metas[i].content = "width=device-width, minimum-scale=0.25, maximum-scale=1.6";
|
||||
}
|
||||
}
|
||||
}</script>
|
||||
|
||||
</body>
|
||||
</html>
|
BIN
InvenTree/InvenTree/static/treegrid/img/collapse.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
InvenTree/InvenTree/static/treegrid/img/expand.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
InvenTree/InvenTree/static/treegrid/img/file.png
Normal file
After Width: | Height: | Size: 342 B |
BIN
InvenTree/InvenTree/static/treegrid/img/folder.png
Normal file
After Width: | Height: | Size: 537 B |
478
InvenTree/InvenTree/static/treegrid/index.html
Normal file
@ -0,0 +1,478 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="chrome=1">
|
||||
<meta name="google-site-verification" content="Qsvvve1CBtl2_PikToO7CdVGsY7bwLrjc_9AgZtt_bk" />
|
||||
<title>Treegrid jquery plugin</title>
|
||||
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
<link rel="stylesheet" href="http://yandex.st/highlightjs/7.3/styles/default.min.css">
|
||||
<link rel="stylesheet" href="css/jquery.treegrid.css">
|
||||
<script src="http://yandex.st/highlightjs/7.3/highlight.min.js"></script>
|
||||
<script>hljs.initHighlightingOnLoad();</script>
|
||||
<script>
|
||||
(function(i, s, o, g, r, a, m) {
|
||||
i['GoogleAnalyticsObject'] = r;
|
||||
i[r] = i[r] || function() {
|
||||
(i[r].q = i[r].q || []).push(arguments)
|
||||
}, i[r].l = 1 * new Date();
|
||||
a = s.createElement(o),
|
||||
m = s.getElementsByTagName(o)[0];
|
||||
a.async = 1;
|
||||
a.src = g;
|
||||
m.parentNode.insertBefore(a, m)
|
||||
})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');
|
||||
|
||||
ga('create', 'UA-43342702-1', 'maxazan.github.io');
|
||||
ga('send', 'pageview');
|
||||
|
||||
</script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrapper">
|
||||
|
||||
<ul class="download" style="float:right;">
|
||||
<li><a href="https://github.com/maxazan/jquery-treegrid/zipball/master">Download <br><strong>ZIP File</strong></a></li>
|
||||
<li><a href="https://github.com/maxazan/jquery-treegrid/tarball/master">Download <br><strong>TAR Ball</strong></a></li>
|
||||
<li><a href="https://github.com/maxazan/jquery-treegrid">View On <br><strong>GitHub</strong></a></li>
|
||||
</ul>
|
||||
|
||||
<h1>TreeGrid jQuery plugin</h1>
|
||||
<h2>Features</h2>
|
||||
<ul>
|
||||
<li>Create TreeGrid from HTML table</li>
|
||||
<li>Simple and flexible javascript</li>
|
||||
<li>Compatible with bootstrap</li>
|
||||
<li>Ability to save the state of the tree</li>
|
||||
<li>Events support</li>
|
||||
|
||||
</ul>
|
||||
<h2>Usage</h2>
|
||||
<p>Step 1. Initialize plugin</p>
|
||||
<pre><code>
|
||||
<script type="text/javascript" src="js/jquery.js"></script>
|
||||
<script type="text/javascript" src="js/jquery.treegrid.js"></script>
|
||||
<link rel="stylesheet" href="css/jquery.treegrid.css">
|
||||
|
||||
<script type="text/javascript">
|
||||
$('.tree').treegrid();
|
||||
</script></code></pre>
|
||||
<p>Step 2. Make table</p>
|
||||
<pre><code class="html">
|
||||
<table class="tree">
|
||||
<tr class="treegrid-1">
|
||||
<td>Root node</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-2 treegrid-parent-1">
|
||||
<td>Node 1-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-3 treegrid-parent-1">
|
||||
<td>Node 1-2</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-4 treegrid-parent-3">
|
||||
<td>Node 1-2-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</code></pre>
|
||||
<p>Step 3. See result</p>
|
||||
|
||||
<table class="tree">
|
||||
<tr class="treegrid-1">
|
||||
<td>Root node</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-2 treegrid-parent-1">
|
||||
<td>Node 1-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-3 treegrid-parent-1">
|
||||
<td>Node 1-2</td><td>Additional info</td>
|
||||
</tr>
|
||||
<tr class="treegrid-4 treegrid-parent-3">
|
||||
<td>Node 1-2-1</td><td>Additional info</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h2>Other examples</h2>
|
||||
<p><a href="examples/example-basic.html" target="_blank">Basic example</a></p>
|
||||
<p><a href="examples/example-column.html" target="_blank">Tree on 2nd column example</a></p>
|
||||
<p><a href="examples/example-save-state.html" target="_blank">Save state example</a></p>
|
||||
<p><a href="examples/example-bootstrap-2.html" target="_blank">TreeGrid for bootstrap 2.x</a></p>
|
||||
<p><a href="examples/example-bootstrap-3.html" target="_blank">TreeGrid for bootstrap 3.x</a></p>
|
||||
<p><a href="examples/example-bootstrap-resize.html" target="_blank">TreeGrid for bootstrap 3.x resize demo</a></p>
|
||||
<p><a href="examples/example-events.html" target="_blank">Events examples</a></p>
|
||||
<p><a href="examples/example-huge.html" target="_blank">Big data example</a></p>
|
||||
|
||||
|
||||
<h2>Configuration Settings</h2>
|
||||
<h3>Settings</h3>
|
||||
<table>
|
||||
<tr><th>Parameter</th><th>Type</th><th>Default value</th><th>Description</th></tr>
|
||||
<tr>
|
||||
<td>treeColumn</td>
|
||||
<td>Numeric</td>
|
||||
<td>0</td>
|
||||
<td>Number of column using for tree</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>initialState</td>
|
||||
<td>String</td>
|
||||
<td>expanded</td>
|
||||
<td>Initial state of tree<br>
|
||||
'expanded' - all nodes will be expanded<br>
|
||||
'collapsed' - all nodes will be collapsed<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>saveState</td>
|
||||
<td>Boolean</td>
|
||||
<td>false</td>
|
||||
<td>If true you can reload page and tree state was saved</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>saveStateMethod</td>
|
||||
<td>String</td>
|
||||
<td>cookie</td>
|
||||
<td>
|
||||
'cookie' - save state to cookie<br>
|
||||
'hash' - save state to hash<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>saveStateName</td>
|
||||
<td>String</td>
|
||||
<td>tree-grid-state</td>
|
||||
<td>
|
||||
Name of cookie or hash to save state.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>expanderTemplate</td>
|
||||
<td>String</td>
|
||||
<td><span class="treegrid-expander"></span></td>
|
||||
<td>HTML Element when you click on that will be collapse/expand branches</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>expanderExpandedClass</td>
|
||||
<td>String</td>
|
||||
<td>treegrid-expander-expanded</td>
|
||||
<td>Class using for expander element when it expanded</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>expanderCollapsedClass</td>
|
||||
<td>String</td>
|
||||
<td>treegrid-expander-collapsed</td>
|
||||
<td>Class using for expander element when it collapsed</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>indentTemplate</td>
|
||||
<td>String</td>
|
||||
<td><span class="treegrid-indent"></span></td>
|
||||
<td>HTML Element that will be placed as padding, depending on the depth of nesting node</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>onCollapse</td>
|
||||
<td>Function</td>
|
||||
<td>null</td>
|
||||
<td>Function, which will be executed when one of node will be collapsed</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>onExpand</td>
|
||||
<td>Function</td>
|
||||
<td>null</td>
|
||||
<td>Function, which will be executed when one of node will be expanded</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>onChange</td>
|
||||
<td>Function</td>
|
||||
<td>null</td>
|
||||
<td>Function, which will be executed when one of node will be expanded or collapsed</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3>Public methods</h3>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Method name</th>
|
||||
<th>Description</th>
|
||||
<th>Example</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>getRootNodes</td>
|
||||
<td>Returns the root branches</td>
|
||||
<td>
|
||||
<pre><code class="javascript">// Expand all root nodes
|
||||
$('.tree').treegrid('getRootNodes').treegrid('expand');</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>getNodeId</td>
|
||||
<td>Return the id of node</td>
|
||||
<td>
|
||||
<pre><code class="javascript">if($('#node-2').treegrid('getNodeId')===2){
|
||||
// Do something with node 2
|
||||
};</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>getParentNodeId</td>
|
||||
<td>Return the id of parent node or null if node is root</td>
|
||||
<td>
|
||||
<pre><code class="javascript">if($('#node-2').treegrid('getParentNodeId')===2){
|
||||
// Do something if parent node Id is 2
|
||||
};</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>getAllNodes</td>
|
||||
<td>Return the all nodes of tree</td>
|
||||
<td>
|
||||
<pre><code class="javascript">// Find all nodes
|
||||
$('#tree-1').treegrid('getAllNodes').each(function() {
|
||||
if ($(this).treegrid("isLast")) {
|
||||
//Do something with all last nodes
|
||||
}
|
||||
});
|
||||
</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>getParentNode</td>
|
||||
<td>Return the parent node or null if node is root</td>
|
||||
<td>
|
||||
<pre><code class="javascript">// Expand parent node
|
||||
$('#node-2').treegrid('getParentNode').treegrid('collapse');
|
||||
</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>getChildNodes</td>
|
||||
<td>Return the child nodes or null if node is leaf</td>
|
||||
<td>
|
||||
<pre><code class="javascript">// Expand child nodes
|
||||
$('#node-2').treegrid('getChildNodes').treegrid('expand');
|
||||
</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>getDepth</td>
|
||||
<td>Returns the depth of nested branch</td>
|
||||
<td>
|
||||
<pre><code class="javascript">// Expand all nodes 2nd nesting
|
||||
$('.tree').find('tr').each(function(){
|
||||
if ($(this).treegrid('getDepth')<2){
|
||||
$(this).treegrid('expand');
|
||||
}
|
||||
});</code></pre>
|
||||
</td>
|
||||
<tr>
|
||||
<td>isNode</td>
|
||||
<td>return true if element is node</td>
|
||||
<td>
|
||||
<pre><code class="javascript">
|
||||
$('#tree-1').find('tr').each(function() {
|
||||
if ($(this).treegrid("isNode")) {
|
||||
//Do something
|
||||
}
|
||||
});
|
||||
</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>isLeaf</td>
|
||||
<td>Is there a node leaf</td>
|
||||
<td>
|
||||
<pre><code class="javascript">// hide all files
|
||||
$('.tree').find('tr').each(function(){
|
||||
if ($(this).treegrid('isLeaf')){
|
||||
$(this).hide();
|
||||
}
|
||||
});</code></pre>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
<tr>
|
||||
<td>isLast</td>
|
||||
<td>Return true if node is last in branch</td>
|
||||
<td>
|
||||
<pre><code class="javascript">// hide all last elements
|
||||
$('.tree').find('tr').each(function(){
|
||||
if ($(this).treegrid('isLast')){
|
||||
$(this).hide();
|
||||
}
|
||||
});</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>isFirst</td>
|
||||
<td>Return true if node is first in branch</td>
|
||||
<td>
|
||||
<pre><code class="javascript">// hide all last elements
|
||||
$('.tree').find('tr').each(function(){
|
||||
if ($(this).treegrid('isFirst')){
|
||||
$(this).hide();
|
||||
}
|
||||
});</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>isExpanded</td>
|
||||
<td>Is node expanded</td>
|
||||
<td>
|
||||
<pre><code class="javascript">if($('#node-2').treegrid('isExpanded')){
|
||||
// Do something if node expanded
|
||||
};</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>isCollapsed</td>
|
||||
<td>Is node collapsed</td>
|
||||
<td>
|
||||
<pre><code class="javascript">if($('#node-2').treegrid('isCollapsed')){
|
||||
// Do something if node collapsed
|
||||
};</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>isOneOfParentsCollapsed</td>
|
||||
<td>Is at least one of the parent nodes is collapsed</td>
|
||||
<td>
|
||||
<pre><code class="javascript">if($('#node-2').treegrid('isOneOfParentCollapsed')){
|
||||
// Do something if one of parent collapsed
|
||||
};</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>expand</td>
|
||||
<td>Expand node</td>
|
||||
<td>
|
||||
<pre><code class="javascript">$('#node-2').treegrid('expand');</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>collapse</td>
|
||||
<td>Collapse node</td>
|
||||
<td>
|
||||
<pre><code class="javascript">$('#node-2').treegrid('collapse');</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>expandRecursive</td>
|
||||
<td>Expand nodes recursively</td>
|
||||
<td>
|
||||
<pre><code class="javascript">$('#node-2').treegrid('expandRecursive');</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>collapseRecursive</td>
|
||||
<td>Collapse nodes recursively</td>
|
||||
<td>
|
||||
<pre><code class="javascript">$('#node-2').treegrid('collapseRecursive');</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>expandAll</td>
|
||||
<td>Expand all nodes</td>
|
||||
<td>
|
||||
<pre><code class="javascript">$('#tree').treegrid('expandAll');</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>collapseAll</td>
|
||||
<td>Collapse all nodes</td>
|
||||
<td>
|
||||
<pre><code class="javascript">$('#tree').treegrid('collapseAll');</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>toggle</td>
|
||||
<td>Collapse node if it expanded and expand when collapsed</td>
|
||||
<td>
|
||||
<pre><code class="javascript">$('#node-2').treegrid('toggle');</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>render</td>
|
||||
<td>Redraw the node and all its children</td>
|
||||
<td>
|
||||
<pre><code class="javascript">$('#node-2').treegrid('render');</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
<h3>Events</h3>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Event name</th>
|
||||
<th>Description</th>
|
||||
<th>Example</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>collapse</td>
|
||||
<td>Will fire when node collapsed</td>
|
||||
<td>
|
||||
<pre><code class="javascript">//Alert when node in treegrid with class "tree" collapsed
|
||||
$('.tree').treegrid('getRootNodes').on('collapse', function(){
|
||||
alert(this);
|
||||
});</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>expand</td>
|
||||
<td>Will fire when node expanded</td>
|
||||
<td>
|
||||
<pre><code class="javascript">//Alert when node with id "node1" expanded
|
||||
$('#node1').on('expand', function(){
|
||||
alert(this);
|
||||
});</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>change</td>
|
||||
<td>Will fire when node changed. Expanded or collapsed</td>
|
||||
<td>
|
||||
<pre><code class="javascript">//Alert when node in treegrid with class "tree" changed.
|
||||
$('.tree').treegrid('getRootNodes').on('change', function(){
|
||||
alert(this);
|
||||
});</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h2><a href="test.html">Unit Tests</a></h2>
|
||||
|
||||
</div>
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="js/jquery.treegrid.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
$('.tree').treegrid();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
var metas = document.getElementsByTagName('meta');
|
||||
var i;
|
||||
if (navigator.userAgent.match(/iPhone/i)) {
|
||||
for (i = 0; i < metas.length; i++) {
|
||||
if (metas[i].name == "viewport") {
|
||||
metas[i].content = "width=device-width, minimum-scale=1.0, maximum-scale=1.0";
|
||||
}
|
||||
}
|
||||
document.addEventListener("gesturestart", gestureStart, false);
|
||||
}
|
||||
function gestureStart() {
|
||||
for (i = 0; i < metas.length; i++) {
|
||||
if (metas[i].name == "viewport") {
|
||||
metas[i].content = "width=device-width, minimum-scale=0.25, maximum-scale=1.6";
|
||||
}
|
||||
}
|
||||
}</script>
|
||||
|
||||
</body>
|
||||
</html>
|