diff --git a/CONTROL/control b/CONTROL/control
index 0ae377f..64d0b48 100644
--- a/CONTROL/control
+++ b/CONTROL/control
@@ -1,7 +1,7 @@
Package: webif
Priority: optional
Section: web
-Version: 1.4.0-6
+Version: 1.4.0-7
Architecture: mipsel
Maintainer: af123@hpkg.tv
Depends: tcpfix,webif-channelicons(>=1.1.25),lighttpd(>=1.4.39-1),jim(>=0.77),jim-oo(>=0.77),jim-sqlite3(>=0.76),jim-cgi(>=0.7-1),jim-binary(>=0.76),service-control(>=2.3),busybox(>=1.20.2-1),lsof(>=4.87),epg(>=1.2.5),hmt(>=2.0.10),ssmtp,cron-daemon(>=1.18.3-3),at(>=3.1.18),anacron,trm(>=1.1),openssl-command,nicesplice,id3v2,file,rsvsync(>=1.1.10),webif-charts(>=1.2-1),stripts(>=1.2.5-3),tmenu(>=1.21-2),ffmpeg,id3v2,multienv(>=1.6),tcpping(>=1.1),e2fsprogs,wireless-tools(>=29-1),dbupdate,recmon(>=2.0.7),hwctl,nugget(>=0.95),sqlite3(>=3.15.1)
diff --git a/webif/html/diag/queue/script.js b/webif/html/diag/queue/script.js
index c64447d..f871b23 100644
--- a/webif/html/diag/queue/script.js
+++ b/webif/html/diag/queue/script.js
@@ -16,6 +16,8 @@ function dirname(path)
function load()
{
$('span.isloading').show();
+ // Grey out the rows
+ $('#queuetab > tbody tr').disable();
$.getJSON('fetch.jim', function(data) {
$('#queuetab > tbody').empty();
@@ -26,27 +28,47 @@ function load()
$.each(data, function(k, v) {
- s = '
');
- $('#queuetab > tbody').append(s);
+ $('').append($(' ', {
+ 'type': 'checkbox',
+ 'class': 'qid',
+ status: v.status,
+ value: v.qid
+ })).append(v.qid).appendTo($row);
+ $(' ', { html: v.submitted }).appendTo($row);
+ $(' ').append($('', {
+ 'class': 'file',
+ href: '#',
+ html: v.file
+ })).appendTo($row);
+ $(' ', { html: v.action + ' ' + v.args })
+ .appendTo($row);
+
+ var s = v.status;
+ if (v.status == 'RUNNING')
+ s += ' ';
+ if ((v.status == 'DEFER' || v.status == 'PENDING')
+ && v.start != '0')
+ s += ' (' + v.start + 's)';
+
+ $(' ', {
+ 'class': 'status ' + v.status,
+ html: s
+ }).appendTo($row);
+
+ $(' ', {
+ html: v.runtime != 0 ? v.runtime : ""
+ }).appendTo($row);
+
+ $(' ', {
+ 'class': 'queuelog',
+ html: v.log
+ }).appendTo($row);
+
+ $(' ', { html: v.last }).appendTo($row);
+
+ $('#queuetab > tbody').append($row);
});
if (data.length > 0)
@@ -85,6 +107,7 @@ $('table')
sortList: [[0,1]],
theme: 'webif',
widthFixed: false,
+ dateFormat: "ddmmyyyy",
widgets: ['zebra', 'stickyHeaders']
});
diff --git a/webif/html/lib/jquery.plugin/tablesorter2/images/black-asc.gif b/webif/html/lib/jquery.plugin/tablesorter2/images/black-asc.gif
deleted file mode 100644
index 730533f..0000000
Binary files a/webif/html/lib/jquery.plugin/tablesorter2/images/black-asc.gif and /dev/null differ
diff --git a/webif/html/lib/jquery.plugin/tablesorter2/images/black-desc.gif b/webif/html/lib/jquery.plugin/tablesorter2/images/black-desc.gif
deleted file mode 100644
index 4c3b610..0000000
Binary files a/webif/html/lib/jquery.plugin/tablesorter2/images/black-desc.gif and /dev/null differ
diff --git a/webif/html/lib/jquery.plugin/tablesorter2/images/black-unsorted.gif b/webif/html/lib/jquery.plugin/tablesorter2/images/black-unsorted.gif
deleted file mode 100644
index 5647f65..0000000
Binary files a/webif/html/lib/jquery.plugin/tablesorter2/images/black-unsorted.gif and /dev/null differ
diff --git a/webif/html/lib/jquery.plugin/tablesorter2/images/bootstrap-black-unsorted.png b/webif/html/lib/jquery.plugin/tablesorter2/images/bootstrap-black-unsorted.png
deleted file mode 100644
index 4e161a6..0000000
Binary files a/webif/html/lib/jquery.plugin/tablesorter2/images/bootstrap-black-unsorted.png and /dev/null differ
diff --git a/webif/html/lib/jquery.plugin/tablesorter2/images/bootstrap-white-unsorted.png b/webif/html/lib/jquery.plugin/tablesorter2/images/bootstrap-white-unsorted.png
deleted file mode 100644
index fb227a1..0000000
Binary files a/webif/html/lib/jquery.plugin/tablesorter2/images/bootstrap-white-unsorted.png and /dev/null differ
diff --git a/webif/html/lib/jquery.plugin/tablesorter2/images/dropbox-asc-hovered.png b/webif/html/lib/jquery.plugin/tablesorter2/images/dropbox-asc-hovered.png
deleted file mode 100644
index bc45223..0000000
Binary files a/webif/html/lib/jquery.plugin/tablesorter2/images/dropbox-asc-hovered.png and /dev/null differ
diff --git a/webif/html/lib/jquery.plugin/tablesorter2/images/dropbox-asc.png b/webif/html/lib/jquery.plugin/tablesorter2/images/dropbox-asc.png
deleted file mode 100644
index 0d6ee15..0000000
Binary files a/webif/html/lib/jquery.plugin/tablesorter2/images/dropbox-asc.png and /dev/null differ
diff --git a/webif/html/lib/jquery.plugin/tablesorter2/images/dropbox-desc-hovered.png b/webif/html/lib/jquery.plugin/tablesorter2/images/dropbox-desc-hovered.png
deleted file mode 100644
index 4930942..0000000
Binary files a/webif/html/lib/jquery.plugin/tablesorter2/images/dropbox-desc-hovered.png and /dev/null differ
diff --git a/webif/html/lib/jquery.plugin/tablesorter2/images/dropbox-desc.png b/webif/html/lib/jquery.plugin/tablesorter2/images/dropbox-desc.png
deleted file mode 100644
index 0bce65a..0000000
Binary files a/webif/html/lib/jquery.plugin/tablesorter2/images/dropbox-desc.png and /dev/null differ
diff --git a/webif/html/lib/jquery.plugin/tablesorter2/images/green-asc.gif b/webif/html/lib/jquery.plugin/tablesorter2/images/green-asc.gif
deleted file mode 100644
index 4cfba09..0000000
Binary files a/webif/html/lib/jquery.plugin/tablesorter2/images/green-asc.gif and /dev/null differ
diff --git a/webif/html/lib/jquery.plugin/tablesorter2/images/green-desc.gif b/webif/html/lib/jquery.plugin/tablesorter2/images/green-desc.gif
deleted file mode 100644
index 4f88176..0000000
Binary files a/webif/html/lib/jquery.plugin/tablesorter2/images/green-desc.gif and /dev/null differ
diff --git a/webif/html/lib/jquery.plugin/tablesorter2/images/green-header.gif b/webif/html/lib/jquery.plugin/tablesorter2/images/green-header.gif
deleted file mode 100644
index cc746b7..0000000
Binary files a/webif/html/lib/jquery.plugin/tablesorter2/images/green-header.gif and /dev/null differ
diff --git a/webif/html/lib/jquery.plugin/tablesorter2/images/green-unsorted.gif b/webif/html/lib/jquery.plugin/tablesorter2/images/green-unsorted.gif
deleted file mode 100644
index 0afe2c0..0000000
Binary files a/webif/html/lib/jquery.plugin/tablesorter2/images/green-unsorted.gif and /dev/null differ
diff --git a/webif/html/lib/jquery.plugin/tablesorter2/images/ice-asc.gif b/webif/html/lib/jquery.plugin/tablesorter2/images/ice-asc.gif
deleted file mode 100644
index 0961d9a..0000000
Binary files a/webif/html/lib/jquery.plugin/tablesorter2/images/ice-asc.gif and /dev/null differ
diff --git a/webif/html/lib/jquery.plugin/tablesorter2/images/ice-desc.gif b/webif/html/lib/jquery.plugin/tablesorter2/images/ice-desc.gif
deleted file mode 100644
index 0330fcc..0000000
Binary files a/webif/html/lib/jquery.plugin/tablesorter2/images/ice-desc.gif and /dev/null differ
diff --git a/webif/html/lib/jquery.plugin/tablesorter2/images/ice-unsorted.gif b/webif/html/lib/jquery.plugin/tablesorter2/images/ice-unsorted.gif
deleted file mode 100644
index c1afde5..0000000
Binary files a/webif/html/lib/jquery.plugin/tablesorter2/images/ice-unsorted.gif and /dev/null differ
diff --git a/webif/html/lib/jquery.plugin/tablesorter2/images/metro-black-asc.png b/webif/html/lib/jquery.plugin/tablesorter2/images/metro-black-asc.png
deleted file mode 100644
index f7a781b..0000000
Binary files a/webif/html/lib/jquery.plugin/tablesorter2/images/metro-black-asc.png and /dev/null differ
diff --git a/webif/html/lib/jquery.plugin/tablesorter2/images/metro-black-desc.png b/webif/html/lib/jquery.plugin/tablesorter2/images/metro-black-desc.png
deleted file mode 100644
index ef5f48e..0000000
Binary files a/webif/html/lib/jquery.plugin/tablesorter2/images/metro-black-desc.png and /dev/null differ
diff --git a/webif/html/lib/jquery.plugin/tablesorter2/images/metro-loading.gif b/webif/html/lib/jquery.plugin/tablesorter2/images/metro-loading.gif
deleted file mode 100644
index ae274c6..0000000
Binary files a/webif/html/lib/jquery.plugin/tablesorter2/images/metro-loading.gif and /dev/null differ
diff --git a/webif/html/lib/jquery.plugin/tablesorter2/images/metro-unsorted.png b/webif/html/lib/jquery.plugin/tablesorter2/images/metro-unsorted.png
deleted file mode 100644
index 653b083..0000000
Binary files a/webif/html/lib/jquery.plugin/tablesorter2/images/metro-unsorted.png and /dev/null differ
diff --git a/webif/html/lib/jquery.plugin/tablesorter2/images/metro-white-asc.png b/webif/html/lib/jquery.plugin/tablesorter2/images/metro-white-asc.png
deleted file mode 100644
index 6332718..0000000
Binary files a/webif/html/lib/jquery.plugin/tablesorter2/images/metro-white-asc.png and /dev/null differ
diff --git a/webif/html/lib/jquery.plugin/tablesorter2/images/metro-white-desc.png b/webif/html/lib/jquery.plugin/tablesorter2/images/metro-white-desc.png
deleted file mode 100644
index ca7c363..0000000
Binary files a/webif/html/lib/jquery.plugin/tablesorter2/images/metro-white-desc.png and /dev/null differ
diff --git a/webif/html/lib/jquery.plugin/tablesorter2/images/white-asc.gif b/webif/html/lib/jquery.plugin/tablesorter2/images/white-asc.gif
deleted file mode 100644
index 2173b0a..0000000
Binary files a/webif/html/lib/jquery.plugin/tablesorter2/images/white-asc.gif and /dev/null differ
diff --git a/webif/html/lib/jquery.plugin/tablesorter2/images/white-desc.gif b/webif/html/lib/jquery.plugin/tablesorter2/images/white-desc.gif
deleted file mode 100644
index 7109c3e..0000000
Binary files a/webif/html/lib/jquery.plugin/tablesorter2/images/white-desc.gif and /dev/null differ
diff --git a/webif/html/lib/jquery.plugin/tablesorter2/images/white-unsorted.gif b/webif/html/lib/jquery.plugin/tablesorter2/images/white-unsorted.gif
deleted file mode 100644
index 9bfc345..0000000
Binary files a/webif/html/lib/jquery.plugin/tablesorter2/images/white-unsorted.gif and /dev/null differ
diff --git a/webif/html/lib/jquery.plugin/tablesorter2/jquery.tablesorter.min.js b/webif/html/lib/jquery.plugin/tablesorter2/jquery.tablesorter.min.js
index c50b8f9..2668f9f 100644
--- a/webif/html/lib/jquery.plugin/tablesorter2/jquery.tablesorter.min.js
+++ b/webif/html/lib/jquery.plugin/tablesorter2/jquery.tablesorter.min.js
@@ -1,2 +1,2 @@
-!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof module&&"object"==typeof module.exports?module.exports=a(require("jquery")):a(jQuery)}(function(a){return function(a){"use strict";var b=a.tablesorter={version:"2.26.2",parsers:[],widgets:[],defaults:{theme:"default",widthFixed:!1,showProcessing:!1,headerTemplate:"{content}",onRenderTemplate:null,onRenderHeader:null,cancelSelection:!0,tabIndex:!0,dateFormat:"mmddyyyy",sortMultiSortKey:"shiftKey",sortResetKey:"ctrlKey",usNumberFormat:!0,delayInit:!1,serverSideSorting:!1,resort:!0,headers:{},ignoreCase:!0,sortForce:null,sortList:[],sortAppend:null,sortStable:!1,sortInitialOrder:"asc",sortLocaleCompare:!1,sortReset:!1,sortRestart:!1,emptyTo:"bottom",stringTo:"max",duplicateSpan:!0,textExtraction:"basic",textAttribute:"data-text",textSorter:null,numberSorter:null,initWidgets:!0,widgetClass:"widget-{name}",widgets:[],widgetOptions:{zebra:["even","odd"]},initialized:null,tableClass:"",cssAsc:"",cssDesc:"",cssNone:"",cssHeader:"",cssHeaderRow:"",cssProcessing:"",cssChildRow:"tablesorter-childRow",cssInfoBlock:"tablesorter-infoOnly",cssNoSort:"tablesorter-noSort",cssIgnoreRow:"tablesorter-ignoreRow",cssIcon:"tablesorter-icon",cssIconNone:"",cssIconAsc:"",cssIconDesc:"",pointerClick:"click",pointerDown:"mousedown",pointerUp:"mouseup",selectorHeaders:"> thead th, > thead td",selectorSort:"th, td",selectorRemove:".remove-me",debug:!1,headerList:[],empties:{},strings:{},parsers:[]},css:{table:"tablesorter",cssHasChild:"tablesorter-hasChildRow",childRow:"tablesorter-childRow",colgroup:"tablesorter-colgroup",header:"tablesorter-header",headerRow:"tablesorter-headerRow",headerIn:"tablesorter-header-inner",icon:"tablesorter-icon",processing:"tablesorter-processing",sortAsc:"tablesorter-headerAsc",sortDesc:"tablesorter-headerDesc",sortNone:"tablesorter-headerUnSorted"},language:{sortAsc:"Ascending sort applied, ",sortDesc:"Descending sort applied, ",sortNone:"No sort applied, ",sortDisabled:"sorting is disabled",nextAsc:"activate to apply an ascending sort",nextDesc:"activate to apply a descending sort",nextNone:"activate to remove the sort"},regex:{templateContent:/\{content\}/g,templateIcon:/\{icon\}/g,templateName:/\{name\}/i,spaces:/\s+/g,nonWord:/\W/g,formElements:/(input|select|button|textarea)/i,chunk:/(^([+\-]?(?:\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)?$|^0x[0-9a-f]+$|\d+)/gi,chunks:/(^\\0|\\0$)/,hex:/^0x[0-9a-f]+$/i,comma:/,/g,digitNonUS:/[\s|\.]/g,digitNegativeTest:/^\s*\([.\d]+\)/,digitNegativeReplace:/^\s*\(([.\d]+)\)/,digitTest:/^[\-+(]?\d+[)]?$/,digitReplace:/[,.'"\s]/g},string:{max:1,min:-1,emptymin:1,emptymax:-1,zero:0,none:0,"null":0,top:!0,bottom:!1},keyCodes:{enter:13},dates:{},instanceMethods:{},setup:function(c,d){if(!c||!c.tHead||0===c.tBodies.length||c.hasInitialized===!0)return void(d.debug&&(c.hasInitialized?console.warn("Stopping initialization. Tablesorter has already been initialized"):console.error("Stopping initialization! No table, thead or tbody",c)));var e="",f=a(c),g=a.metadata;c.hasInitialized=!1,c.isProcessing=!0,c.config=d,a.data(c,"tablesorter",d),d.debug&&(console[console.group?"group":"log"]("Initializing tablesorter"),a.data(c,"startoveralltimer",new Date)),d.supportsDataObject=function(a){return a[0]=parseInt(a[0],10),a[0]>1||1===a[0]&&parseInt(a[1],10)>=4}(a.fn.jquery.split(".")),d.emptyTo=d.emptyTo.toLowerCase(),d.stringTo=d.stringTo.toLowerCase(),d.last={sortList:[],clickedIndex:-1},/tablesorter\-/.test(f.attr("class"))||(e=""!==d.theme?" tablesorter-"+d.theme:""),d.table=c,d.$table=f.addClass(b.css.table+" "+d.tableClass+e).attr("role","grid"),d.$headers=f.find(d.selectorHeaders),d.namespace?d.namespace="."+d.namespace.replace(b.regex.nonWord,""):d.namespace=".tablesorter"+Math.random().toString(16).slice(2),d.$table.children().children("tr").attr("role","row"),d.$tbodies=f.children("tbody:not(."+d.cssInfoBlock+")").attr({"aria-live":"polite","aria-relevant":"all"}),d.$table.children("caption").length&&(e=d.$table.children("caption")[0],e.id||(e.id=d.namespace.slice(1)+"caption"),d.$table.attr("aria-labelledby",e.id)),d.widgetInit={},d.textExtraction=d.$table.attr("data-text-extraction")||d.textExtraction||"basic",b.buildHeaders(d),b.fixColumnWidth(c),b.addWidgetFromClass(c),b.applyWidgetOptions(c),b.setupParsers(d),d.totalRows=0,d.delayInit||b.buildCache(d),b.bindEvents(c,d.$headers,!0),b.bindMethods(d),d.supportsDataObject&&"undefined"!=typeof f.data().sortlist?d.sortList=f.data().sortlist:g&&f.metadata()&&f.metadata().sortlist&&(d.sortList=f.metadata().sortlist),b.applyWidget(c,!0),d.sortList.length>0?b.sortOn(d,d.sortList,{},!d.initWidgets):(b.setHeadersCss(d),d.initWidgets&&b.applyWidget(c,!1)),d.showProcessing&&f.unbind("sortBegin"+d.namespace+" sortEnd"+d.namespace).bind("sortBegin"+d.namespace+" sortEnd"+d.namespace,function(a){clearTimeout(d.timerProcessing),b.isProcessing(c),"sortBegin"===a.type&&(d.timerProcessing=setTimeout(function(){b.isProcessing(c,!0)},500))}),c.hasInitialized=!0,c.isProcessing=!1,d.debug&&(console.log("Overall initialization time: "+b.benchmark(a.data(c,"startoveralltimer"))),d.debug&&console.groupEnd&&console.groupEnd()),f.triggerHandler("tablesorter-initialized",c),"function"==typeof d.initialized&&d.initialized(c)},bindMethods:function(c){var d=c.$table,e=c.namespace,f="sortReset update updateRows updateAll updateHeaders addRows updateCell updateComplete sorton appendCache updateCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave ".split(" ").join(e+" ");d.unbind(f.replace(b.regex.spaces," ")).bind("sortReset"+e,function(a,c){a.stopPropagation(),b.sortReset(this.config,c)}).bind("updateAll"+e,function(a,c,d){a.stopPropagation(),b.updateAll(this.config,c,d)}).bind("update"+e+" updateRows"+e,function(a,c,d){a.stopPropagation(),b.update(this.config,c,d)}).bind("updateHeaders"+e,function(a,c){a.stopPropagation(),b.updateHeaders(this.config,c)}).bind("updateCell"+e,function(a,c,d,e){a.stopPropagation(),b.updateCell(this.config,c,d,e)}).bind("addRows"+e,function(a,c,d,e){a.stopPropagation(),b.addRows(this.config,c,d,e)}).bind("updateComplete"+e,function(){this.isUpdating=!1}).bind("sorton"+e,function(a,c,d,e){a.stopPropagation(),b.sortOn(this.config,c,d,e)}).bind("appendCache"+e,function(c,d,e){c.stopPropagation(),b.appendCache(this.config,e),a.isFunction(d)&&d(this)}).bind("updateCache"+e,function(a,c,d){a.stopPropagation(),b.updateCache(this.config,c,d)}).bind("applyWidgetId"+e,function(a,c){a.stopPropagation(),b.applyWidgetId(this,c)}).bind("applyWidgets"+e,function(a,c){a.stopPropagation(),b.applyWidget(this,c)}).bind("refreshWidgets"+e,function(a,c,d){a.stopPropagation(),b.refreshWidgets(this,c,d)}).bind("removeWidget"+e,function(a,c,d){a.stopPropagation(),b.removeWidget(this,c,d)}).bind("destroy"+e,function(a,c,d){a.stopPropagation(),b.destroy(this,c,d)}).bind("resetToLoadState"+e,function(d){d.stopPropagation(),b.removeWidget(this,!0,!1),c=a.extend(!0,b.defaults,c.originalSettings),this.hasInitialized=!1,b.setup(this,c)})},bindEvents:function(c,d,e){c=a(c)[0];var f,g=c.config,h=g.namespace,i=null;e!==!0&&(d.addClass(h.slice(1)+"_extra_headers"),f=a.fn.closest?d.closest("table")[0]:d.parents("table")[0],f&&"TABLE"===f.nodeName&&f!==c&&a(f).addClass(h.slice(1)+"_extra_table")),f=(g.pointerDown+" "+g.pointerUp+" "+g.pointerClick+" sort keyup ").replace(b.regex.spaces," ").split(" ").join(h+" "),d.find(g.selectorSort).add(d.filter(g.selectorSort)).unbind(f).bind(f,function(c,e){var f,h,j,k=a(c.target),l=" "+c.type+" ";if(!(1!==(c.which||c.button)&&!l.match(" "+g.pointerClick+" | sort | keyup ")||" keyup "===l&&c.which!==b.keyCodes.enter||l.match(" "+g.pointerClick+" ")&&"undefined"!=typeof c.which||l.match(" "+g.pointerUp+" ")&&i!==c.target&&e!==!0)){if(l.match(" "+g.pointerDown+" "))return i=c.target,j=k.jquery.split("."),void("1"===j[0]&&j[1]<4&&c.preventDefault());if(i=null,b.regex.formElements.test(c.target.nodeName)||k.hasClass(g.cssNoSort)||k.parents("."+g.cssNoSort).length>0||k.parents("button").length>0)return!g.cancelSelection;g.delayInit&&b.isEmptyObject(g.cache)&&b.buildCache(g),f=a.fn.closest?a(this).closest("th, td"):/TH|TD/.test(this.nodeName)?a(this):a(this).parents("th, td"),j=d.index(f),g.last.clickedIndex=0>j?f.attr("data-column"):j,h=g.$headers[g.last.clickedIndex],h&&!h.sortDisabled&&b.initSort(g,h,c)}}),g.cancelSelection&&d.attr("unselectable","on").bind("selectstart",!1).css({"user-select":"none",MozUserSelect:"none"})},buildHeaders:function(c){var d,e,f,g;for(c.headerList=[],c.headerContent=[],c.sortVars=[],c.debug&&(f=new Date),c.columns=b.computeColumnIndex(c.$table.children("thead, tfoot").children("tr")),e=c.cssIcon?' ':"",c.$headers=a(a.map(c.$table.find(c.selectorHeaders),function(d,f){var g,h,i,j,k,l=a(d);if(!l.parent().hasClass(c.cssIgnoreRow))return g=b.getColumnData(c.table,c.headers,f,!0),c.headerContent[f]=l.html(),""===c.headerTemplate||l.find("."+b.css.headerIn).length||(j=c.headerTemplate.replace(b.regex.templateContent,l.html()).replace(b.regex.templateIcon,l.find("."+b.css.icon).length?"":e),c.onRenderTemplate&&(h=c.onRenderTemplate.apply(l,[f,j]),h&&"string"==typeof h&&(j=h)),l.html('")),c.onRenderHeader&&c.onRenderHeader.apply(l,[f,c,c.$table]),i=parseInt(l.attr("data-column"),10),d.column=i,k=b.getData(l,g,"sortInitialOrder")||c.sortInitialOrder,c.sortVars[i]={count:-1,order:b.getOrder(k)?[1,0,2]:[0,1,2],lockedOrder:!1},k=b.getData(l,g,"lockedOrder")||!1,"undefined"!=typeof k&&k!==!1&&(c.sortVars[i].lockedOrder=!0,c.sortVars[i].order=b.getOrder(k)?[1,1,1]:[0,0,0]),c.headerList[f]=d,l.addClass(b.css.header+" "+c.cssHeader).parent().addClass(b.css.headerRow+" "+c.cssHeaderRow).attr("role","row"),c.tabIndex&&l.attr("tabindex",0),d})),c.$headerIndexed=[],g=0;gs;){if(d=p[s].rows,d.length)for(h=0,g=a.columns,i=0;g>i;i++){if(j=a.$headerIndexed[h],j&&j.length&&(k=b.getColumnData(r,a.headers,h),n=b.getParserById(b.getData(j,k,"extractor")),m=b.getParserById(b.getData(j,k,"sorter")),l="false"===b.getData(j,k,"parser"),a.empties[h]=(b.getData(j,k,"empty")||a.emptyTo||(a.emptyToBottom?"bottom":"top")).toLowerCase(),a.strings[h]=(b.getData(j,k,"string")||a.stringTo||"max").toLowerCase(),l&&(m=b.getParserById("no-parser")),n||(n=!1),m||(m=b.detectParserForColumn(a,d,-1,h)),a.debug&&(t["("+h+") "+j.text()]={parser:m.id,extractor:n?n.id:"none",string:a.strings[h],empty:a.empties[h]}),e.parsers[h]=m,e.extractors[h]=n,f=j[0].colSpan-1,f>0))for(h+=f,g+=f;f+1>0;)e.parsers[h-f]=m,e.extractors[h-f]=n,f--;h++}s+=e.parsers.length?q:1}a.debug&&(b.isEmptyObject(t)?console.warn(" No parsers detected!"):console[console.table?"table":"log"](t),console.log("Completed detecting parsers"+b.benchmark(o)),console.groupEnd&&console.groupEnd()),a.parsers=e.parsers,a.extractors=e.extractors},addParser:function(a){var c,d=b.parsers.length,e=!0;for(c=0;d>c;c++)b.parsers[c].id.toLowerCase()===a.id.toLowerCase()&&(e=!1);e&&(b.parsers[b.parsers.length]=a)},getParserById:function(a){if("false"==a)return!1;var c,d=b.parsers.length;for(c=0;d>c;c++)if(b.parsers[c].id.toLowerCase()===a.toString().toLowerCase())return b.parsers[c];return!1},detectParserForColumn:function(c,d,e,f){for(var g,h,i,j=b.parsers.length,k=!1,l="",m=!0;""===l&&m;)e++,i=d[e],i&&50>e?i.className.indexOf(b.cssIgnoreRow)<0&&(k=d[e].cells[f],l=b.getElementText(c,k,f),h=a(k),c.debug&&console.log("Checking if value was empty on row "+e+", column: "+f+': "'+l+'"')):m=!1;for(;--j>=0;)if(g=b.parsers[j],g&&"text"!==g.id&&g.is&&g.is(l,c.table,k,h))return g;return b.getParserById("text")},getElementText:function(c,d,e){if(!d)return"";var f,g=c.textExtraction||"",h=d.jquery?d:a(d);return"string"==typeof g?"basic"===g&&"undefined"!=typeof(f=h.attr(c.textAttribute))?a.trim(f):a.trim(d.textContent||h.text()):"function"==typeof g?a.trim(g(h[0],c.table,e)):"function"==typeof(f=b.getColumnData(c.table,g,e))?a.trim(f(h[0],c.table,e)):a.trim(h[0].textContent||h.text())},getParsedText:function(a,c,d,e){"undefined"==typeof e&&(e=b.getElementText(a,c,d));var f=""+e,g=a.parsers[d],h=a.extractors[d];return g&&(h&&"function"==typeof h.format&&(e=h.format(e,a.table,c,d)),f="no-parser"===g.id?"":g.format(""+e,a.table,c,d),a.ignoreCase&&"string"==typeof f&&(f=f.toLowerCase())),f},buildCache:function(c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B=c.table,C=c.parsers;if(c.$tbodies=c.$table.children("tbody:not(."+c.cssInfoBlock+")"),l="undefined"==typeof e?c.$tbodies:e,c.cache={},c.totalRows=0,!C)return c.debug?console.warn("Warning: *Empty table!* Not building a cache"):"";for(c.debug&&(q=new Date),c.showProcessing&&b.isProcessing(B,!0),k=0;ki;++i)if(s={child:[],raw:[]},m=a(l[k].rows[i]),n=[],m.hasClass(c.cssChildRow)&&0!==i)for(z=f.normalized.length-1,t=f.normalized[z][c.columns],t.$row=t.$row.add(m),m.prev().hasClass(c.cssChildRow)||m.prev().addClass(b.css.cssHasChild),o=m.children("th, td"),z=t.child.length,t.child[z]=[],w=0,y=c.columns,j=0;y>j;j++)p=o[j],p&&(t.child[z][j]=b.getParsedText(c,p,j),v=o[j].colSpan-1,v>0&&(w+=v,y+=v)),w++;else{for(s.$row=m,s.order=i,w=0,y=c.columns,j=0;y>j;++j){if(p=m[0].cells[j],p&&w0)){for(A=0;v>=A;)h=c.duplicateSpan||0===A?g:"string"!=typeof c.textExtraction?b.getElementText(c,p,w+A)||"":"",s.raw[w+A]=h,n[w+A]=h,A++;w+=v,y+=v}w++}n[c.columns]=s,f.normalized[f.normalized.length]=n}f.colMax=u,c.totalRows+=f.normalized.length}if(c.showProcessing&&b.isProcessing(B),c.debug){for(z=Math.min(5,c.cache[0].normalized.length),console[console.group?"group":"log"]("Building cache for "+c.totalRows+" rows (showing "+z+" rows in log)"+b.benchmark(q)),g={},j=0;jw;w++)g["row: "+w]||(g["row: "+w]={}),g["row: "+w][c.$headerIndexed[j].text()]=c.cache[0].normalized[w][j];console[console.table?"table":"log"](g),console.groupEnd&&console.groupEnd()}a.isFunction(d)&&d(B)},getColumnText:function(c,d,e,f){c=a(c)[0];var g,h,i,j,k,l,m,n,o,p,q="function"==typeof e,r="all"===d,s={raw:[],parsed:[],$cell:[]},t=c.config;if(!b.isEmptyObject(t)){for(k=t.$tbodies.length,g=0;k>g;g++)for(i=t.cache[g].normalized,l=i.length,h=0;l>h;h++)j=i[h],f&&!j[t.columns].$row.is(f)||(p=!0,n=r?j.slice(0,t.columns):j[d],j=j[t.columns],m=r?j.raw:j.raw[d],o=r?j.$row.children():j.$row.children().eq(d),q&&(p=e({tbodyIndex:g,rowIndex:h,parsed:n,raw:m,$row:j.$row,$cell:o})),p!==!1&&(s.parsed[s.parsed.length]=n,s.raw[s.raw.length]=m,s.$cell[s.$cell.length]=o));return s}t.debug&&console.warn("No cache found - aborting getColumnText function!")},setHeadersCss:function(c){var d,e,f,g=c.sortList,h=g.length,i=b.css.sortNone+" "+c.cssNone,j=[b.css.sortAsc+" "+c.cssAsc,b.css.sortDesc+" "+c.cssDesc],k=[c.cssIconAsc,c.cssIconDesc,c.cssIconNone],l=["ascending","descending"],m=c.$table.find("tfoot tr").children("td, th").add(a(c.namespace+"_extra_headers")).removeClass(j.join(" "));for(c.$headers.removeClass(j.join(" ")).addClass(i).attr("aria-sort","none").find("."+b.css.icon).removeClass(k.join(" ")).addClass(k[2]),e=0;h>e;e++)if(2!==g[e][1]&&(d=c.$headers.filter(function(a){for(var d=!0,e=c.$headers.eq(a),f=parseInt(e.attr("data-column"),10),g=f+c.$headers[a].colSpan;g>f;f++)d=d?d||b.isValueInArray(f,c.sortList)>-1:!1;return d}),d=d.not(".sorter-false").filter('[data-column="'+g[e][0]+'"]'+(1===h?":last":"")),d.length)){for(f=0;fe;e++)b.setColumnAriaLabel(c,c.$headers.eq(e))},setColumnAriaLabel:function(c,d,e){if(d.length){var f=parseInt(d.attr("data-column"),10),g=d.hasClass(b.css.sortAsc)?"sortAsc":d.hasClass(b.css.sortDesc)?"sortDesc":"sortNone",h=a.trim(d.text())+": "+b.language[g];d.hasClass("sorter-false")||e===!1?h+=b.language.sortDisabled:(e=c.sortVars[f].order[(c.sortVars[f].count+1)%(c.sortReset?3:2)],h+=b.language[0===e?"nextAsc":1===e?"nextDesc":"nextNone"]),d.attr("aria-label",h)}},updateHeader:function(a){var c,d,e,f,g=a.table,h=a.$headers.length;for(c=0;h>c;c++)e=a.$headers.eq(c),f=b.getColumnData(g,a.headers,c,!0),d="false"===b.getData(e,f,"sorter")||"false"===b.getData(e,f,"parser"),b.setColumnSort(a,e,d)},setColumnSort:function(a,b,c){var d=a.table.id;b[0].sortDisabled=c,b[c?"addClass":"removeClass"]("sorter-false").attr("aria-disabled",""+c),a.tabIndex&&(c?b.removeAttr("tabindex"):b.attr("tabindex","0")),d&&(c?b.removeAttr("aria-controls"):b.attr("aria-controls",d))},updateHeaderSortCount:function(c,d){var e,f,g,h,i,j,k,l,m=d||c.sortList,n=m.length;for(c.sortList=[],h=0;n>h;h++)if(k=m[h],e=parseInt(k[0],10),e=0?f:g[1]%(c.sortReset?3:2)}},updateAll:function(a,c,d){var e=a.table;e.isUpdating=!0,b.refreshWidgets(e,!0,!0),b.buildHeaders(a),b.bindEvents(e,a.$headers,!0),b.bindMethods(a),b.commonUpdate(a,c,d)},update:function(a,c,d){var e=a.table;e.isUpdating=!0,b.updateHeader(a),b.commonUpdate(a,c,d)},updateHeaders:function(a,c){a.table.isUpdating=!0,b.buildHeaders(a),b.bindEvents(a.table,a.$headers,!0),b.resortComplete(a,c)},updateCell:function(c,d,e,f){if(b.isEmptyObject(c.cache))return b.updateHeader(c),void b.commonUpdate(c,e,f);c.table.isUpdating=!0,c.$table.find(c.selectorRemove).remove();var g,h,i,j,k,l,m=c.$tbodies,n=a(d),o=m.index(a.fn.closest?n.closest("tbody"):n.parents("tbody").filter(":first")),p=c.cache[o],q=a.fn.closest?n.closest("tr"):n.parents("tr").filter(":first");if(d=n[0],m.length&&o>=0){if(i=m.eq(o).find("tr").index(q),k=p.normalized[i],l=q[0].cells.length,l!==c.columns)for(j=0,g=!1,h=0;l>h;h++)g||q[0].cells[h]===d?g=!0:j+=q[0].cells[h].colSpan;else j=n.index();g=b.getElementText(c,d,j),k[c.columns].raw[j]=g,g=b.getParsedText(c,d,j,g),k[j]=g,k[c.columns].$row=q,"numeric"===(c.parsers[j].type||"").toLowerCase()&&(p.colMax[j]=Math.max(Math.abs(g)||0,p.colMax[j]||0)),g="undefined"!==e?e:c.resort,g!==!1?b.checkResort(c,g,f):b.resortComplete(c,f)}else c.debug&&console.error("updateCell aborted, tbody missing or not within the indicated table"),c.table.isUpdating=!1},addRows:function(c,d,e,f){var g,h,i,j,k,l,m,n,o,p,q,r,s,t="string"==typeof d&&1===c.$tbodies.length&&/j;j++){for(o=0,m=d[j].cells.length,n=c.cache[i].normalized.length,q=[],p={child:[],raw:[],$row:d.eq(j),order:n},l=0;m>l;l++)r=d[j].cells[l],g=b.getElementText(c,r,o),p.raw[o]=g,h=b.getParsedText(c,r,o,g),q[o]=h,"numeric"===(c.parsers[o].type||"").toLowerCase()&&(c.cache[i].colMax[o]=Math.max(Math.abs(h)||0,c.cache[i].colMax[o]||0)),s=r.colSpan-1,s>0&&(o+=s),o++;q[c.columns]=p,c.cache[i].normalized[n]=q}b.checkResort(c,e,f)}},updateCache:function(a,c,d){a.parsers&&a.parsers.length||b.setupParsers(a,d),b.buildCache(a,c,d)},appendCache:function(a,c){var d,e,f,g,h,i,j,k=a.table,l=a.widgetOptions,m=a.$tbodies,n=[],o=a.cache;if(b.isEmptyObject(o))return a.appender?a.appender(k,n):k.isUpdating?a.$table.triggerHandler("updateComplete",k):"";for(a.debug&&(j=new Date),i=0;ih;h++)n[n.length]=d[h][a.columns].$row,a.appender&&(!a.pager||a.pager.removeRows&&l.pager_removeRows||a.pager.ajax)||g.append(d[h][a.columns].$row);b.processTbody(k,g,!1)}a.appender&&a.appender(k,n),a.debug&&console.log("Rebuilt table"+b.benchmark(j)),c||a.appender||b.applyWidget(k),k.isUpdating&&a.$table.triggerHandler("updateComplete",k)},commonUpdate:function(a,c,d){a.$table.find(a.selectorRemove).remove(),b.setupParsers(a),b.buildCache(a),b.checkResort(a,c,d)},initSort:function(c,d,e){if(c.table.isUpdating)return setTimeout(function(){b.initSort(c,d,e)},50);var f,g,h,i,j,k,l,m=!e[c.sortMultiSortKey],n=c.table,o=c.$headers.length,p=parseInt(a(d).attr("data-column"),10),q=c.sortVars[p].order;if(c.$table.triggerHandler("sortStart",n),c.sortVars[p].count=e[c.sortResetKey]?2:(c.sortVars[p].count+1)%(c.sortReset?3:2),c.sortRestart)for(h=0;o>h;h++)l=c.$headers.eq(h),k=parseInt(l.attr("data-column"),10),p!==k&&(m||l.hasClass(b.css.sortNone))&&(c.sortVars[k].count=-1);if(m){if(c.sortList=[],c.last.sortList=[],null!==c.sortForce)for(f=c.sortForce,g=0;gi&&(c.sortList[c.sortList.length]=[p,i],d.colSpan>1))for(g=1;g=0)for(g=0;gi&&(c.sortList[c.sortList.length]=[p,i],d.colSpan>1))for(g=1;gc;c++)e=a.cache[c].colMax,f=a.cache[c].normalized,f.sort(function(c,d){var f,l,m,n,o,p,q;for(f=0;k>f;f++){if(m=j[f][0],n=j[f][1],h=0===n,a.sortStable&&c[m]===d[m]&&1===k)return c[a.columns].order-d[a.columns].order;if(l=/n/i.test(b.getSortType(a.parsers,m)),l&&a.strings[m]?(l="boolean"==typeof b.string[a.strings[m]]?(h?1:-1)*(b.string[a.strings[m]]?-1:1):a.strings[m]?b.string[a.strings[m]]||0:0,o=a.numberSorter?a.numberSorter(c[m],d[m],h,e[m],g):b["sortNumeric"+(h?"Asc":"Desc")](c[m],d[m],l,e[m],m,a)):(p=h?c:d,q=h?d:c,o="function"==typeof i?i(p[m],q[m],h,m,g):"object"==typeof i&&i.hasOwnProperty(m)?i[m](p[m],q[m],h,m,g):b["sortNatural"+(h?"Asc":"Desc")](c[m],d[m],m,a)),o)return o}return c[a.columns].order-d[a.columns].order});a.debug&&console.log("Applying sort "+j.toString()+b.benchmark(d))}},resortComplete:function(b,c){b.table.isUpdating&&b.$table.triggerHandler("updateComplete",b.table),a.isFunction(c)&&c(b.table)},checkResort:function(c,d,e){var f=a.isArray(d)?d:c.sortList,g="undefined"==typeof d?c.resort:d;g===!1||c.serverSideSorting||c.table.isProcessing?(b.resortComplete(c,e),b.applyWidget(c.table,!1)):f.length?b.sortOn(c,f,function(){b.resortComplete(c,e)},!0):b.sortReset(c,function(){b.resortComplete(c,e),b.applyWidget(c.table,!1)})},sortOn:function(c,d,e,f){var g=c.table;c.$table.triggerHandler("sortStart",g),b.updateHeaderSortCount(c,d),b.setHeadersCss(c),c.delayInit&&b.isEmptyObject(c.cache)&&b.buildCache(c),c.$table.triggerHandler("sortBegin",g),b.multisort(c),b.appendCache(c,f),c.$table.triggerHandler("sortBeforeEnd",g),c.$table.triggerHandler("sortEnd",g),b.applyWidget(g),a.isFunction(e)&&e(g)},sortReset:function(c,d){c.sortList=[],b.setHeadersCss(c),b.multisort(c),b.appendCache(c),a.isFunction(d)&&d(c.table)},getSortType:function(a,b){return a&&a[b]?a[b].type||"":""},getOrder:function(a){return/^d/i.test(a)||1===a},sortNatural:function(a,c){if(a===c)return 0;var d,e,f,g,h,i,j=b.regex;if(j.hex.test(c)){if(d=parseInt(a.match(j.hex),16),e=parseInt(c.match(j.hex),16),e>d)return-1;if(d>e)return 1}for(d=a.replace(j.chunk,"\\0$1\\0").replace(j.chunks,"").split("\\0"),e=c.replace(j.chunk,"\\0$1\\0").replace(j.chunks,"").split("\\0"),i=Math.max(d.length,e.length),h=0;i>h;h++){if(f=isNaN(d[h])?d[h]||0:parseFloat(d[h])||0,g=isNaN(e[h])?e[h]||0:parseFloat(e[h])||0,isNaN(f)!==isNaN(g))return isNaN(f)?1:-1;if(typeof f!=typeof g&&(f+="",g+=""),g>f)return-1;if(f>g)return 1}return 0},sortNaturalAsc:function(a,c,d,e){if(a===c)return 0;var f=b.string[e.empties[d]||e.emptyTo];return""===a&&0!==f?"boolean"==typeof f?f?-1:1:-f||-1:""===c&&0!==f?"boolean"==typeof f?f?1:-1:f||1:b.sortNatural(a,c)},sortNaturalDesc:function(a,c,d,e){if(a===c)return 0;var f=b.string[e.empties[d]||e.emptyTo];return""===a&&0!==f?"boolean"==typeof f?f?-1:1:f||1:""===c&&0!==f?"boolean"==typeof f?f?1:-1:-f||-1:b.sortNatural(c,a)},sortText:function(a,b){return a>b?1:b>a?-1:0},getTextValue:function(a,b,c){if(c){var d,e=a?a.length:0,f=c+b;for(d=0;e>d;d++)f+=a.charCodeAt(d);return b*f}return 0},sortNumericAsc:function(a,c,d,e,f,g){if(a===c)return 0;var h=b.string[g.empties[f]||g.emptyTo];return""===a&&0!==h?"boolean"==typeof h?h?-1:1:-h||-1:""===c&&0!==h?"boolean"==typeof h?h?1:-1:h||1:(isNaN(a)&&(a=b.getTextValue(a,d,e)),isNaN(c)&&(c=b.getTextValue(c,d,e)),a-c)},sortNumericDesc:function(a,c,d,e,f,g){if(a===c)return 0;var h=b.string[g.empties[f]||g.emptyTo];return""===a&&0!==h?"boolean"==typeof h?h?-1:1:h||1:""===c&&0!==h?"boolean"==typeof h?h?1:-1:-h||-1:(isNaN(a)&&(a=b.getTextValue(a,d,e)),isNaN(c)&&(c=b.getTextValue(c,d,e)),c-a)},sortNumeric:function(a,b){return a-b},addWidget:function(a){a.id&&!b.isEmptyObject(b.getWidgetById(a.id))&&console.warn('"'+a.id+'" widget was loaded more than once!'),b.widgets[b.widgets.length]=a},hasWidget:function(b,c){return b=a(b),b.length&&b[0].config&&b[0].config.widgetInit[c]||!1},getWidgetById:function(a){var c,d,e=b.widgets.length;for(c=0;e>c;c++)if(d=b.widgets[c],d&&d.id&&d.id.toLowerCase()===a.toLowerCase())return d},applyWidgetOptions:function(c){var d,e,f=c.config,g=f.widgets.length;if(g)for(d=0;g>d;d++)e=b.getWidgetById(f.widgets[d]),e&&e.options&&(f.widgetOptions=a.extend(!0,{},e.options,f.widgetOptions))},addWidgetFromClass:function(a){var c,d,e=a.config,f="^"+e.widgetClass.replace(b.regex.templateName,"(\\S+)+")+"$",g=new RegExp(f,"g"),h=(a.className||"").split(b.regex.spaces);if(h.length)for(c=h.length,d=0;c>d;d++)h[d].match(g)&&(e.widgets[e.widgets.length]=h[d].replace(g,"$1"))},applyWidgetId:function(c,d,e){c=a(c)[0];var f,g,h,i=c.config,j=i.widgetOptions,k=b.getWidgetById(d);k&&(h=k.id,f=!1,a.inArray(h,i.widgets)<0&&(i.widgets[i.widgets.length]=h),i.debug&&(g=new Date),!e&&i.widgetInit[h]||(i.widgetInit[h]=!0,c.hasInitialized&&b.applyWidgetOptions(c),"function"==typeof k.init&&(f=!0,i.debug&&console[console.group?"group":"log"]("Initializing "+h+" widget"),k.init(c,k,i,j))),e||"function"!=typeof k.format||(f=!0,i.debug&&console[console.group?"group":"log"]("Updating "+h+" widget"),k.format(c,i,j,!1)),i.debug&&f&&(console.log("Completed "+(e?"initializing ":"applying ")+h+" widget"+b.benchmark(g)),console.groupEnd&&console.groupEnd()))},applyWidget:function(c,d,e){c=a(c)[0];var f,g,h,i,j,k=c.config,l=[];if(d===!1||!c.hasInitialized||!c.isApplyingWidgets&&!c.isUpdating){if(k.debug&&(j=new Date),b.addWidgetFromClass(c),clearTimeout(k.timerReady),k.widgets.length){for(c.isApplyingWidgets=!0,k.widgets=a.grep(k.widgets,function(b,c){return a.inArray(b,k.widgets)===c}),h=k.widgets||[],g=h.length,f=0;g>f;f++)i=b.getWidgetById(h[f]),i&&i.id?(i.priority||(i.priority=10),l[f]=i):k.debug&&console.warn('"'+h[f]+'" widget code does not exist!');for(l.sort(function(a,b){return a.priorityf;f++)i=l[f],i&&i.id&&b.applyWidgetId(c,i.id,d);k.debug&&console.groupEnd&&console.groupEnd(),d||"function"!=typeof e||e(c)}k.timerReady=setTimeout(function(){c.isApplyingWidgets=!1,a.data(c,"lastWidgetApplication",new Date),k.$table.triggerHandler("tablesorter-ready")},10),k.debug&&(i=k.widgets.length,console.log("Completed "+(d===!0?"initializing ":"applying ")+i+" widget"+(1!==i?"s":"")+b.benchmark(j)))}},removeWidget:function(c,d,e){c=a(c)[0];var f,g,h,i,j=c.config;if(d===!0)for(d=[],i=b.widgets.length,h=0;i>h;h++)g=b.widgets[h],g&&g.id&&(d[d.length]=g.id);else d=(a.isArray(d)?d.join(","):d||"").toLowerCase().split(/[\s,]+/);for(i=d.length,f=0;i>f;f++)g=b.getWidgetById(d[f]),h=a.inArray(d[f],j.widgets),h>=0&&e!==!0&&j.widgets.splice(h,1),g&&g.remove&&(j.debug&&console.log((e?"Refreshing":"Removing")+' "'+d[f]+'" widget'),g.remove(c,j,j.widgetOptions,e),j.widgetInit[d[f]]=!1)},refreshWidgets:function(c,d,e){c=a(c)[0];var f,g,h=c.config,i=h.widgets,j=b.widgets,k=j.length,l=[],m=function(b){a(b).triggerHandler("refreshComplete")};for(f=0;k>f;f++)g=j[f],g&&g.id&&(d||a.inArray(g.id,i)<0)&&(l[l.length]=g.id);b.removeWidget(c,l.join(","),!0),e!==!0?(b.applyWidget(c,d||!1,m),d&&b.applyWidget(c,!1,m)):m(c)},benchmark:function(a){return" ( "+((new Date).getTime()-a.getTime())+"ms )"},log:function(){console.log(arguments)},isEmptyObject:function(a){for(var b in a)return!1;return!0},isValueInArray:function(a,b){var c,d=b&&b.length||0;for(c=0;d>c;c++)if(b[c][0]===a)return c;return-1},formatFloat:function(c,d){if("string"!=typeof c||""===c)return c;var e,f=d&&d.config?d.config.usNumberFormat!==!1:"undefined"!=typeof d?d:!0;return c=f?c.replace(b.regex.comma,""):c.replace(b.regex.digitNonUS,"").replace(b.regex.comma,"."),b.regex.digitNegativeTest.test(c)&&(c=c.replace(b.regex.digitNegativeReplace,"-$1")),e=parseFloat(c),isNaN(e)?a.trim(c):e},isDigit:function(a){return isNaN(a)?b.regex.digitTest.test(a.toString().replace(b.regex.digitReplace,"")):""!==a},computeColumnIndex:function(b,c){
-var d,e,f,g,h,i,j,k,l,m,n=c&&c.columns||0,o=[],p=new Array(n);for(d=0;df;f++)for("undefined"==typeof o[f]&&(o[f]=[]),p=o[f],g=m;m+l>g;g++)p[g]="x"}return p.length},fixColumnWidth:function(c){c=a(c)[0];var d,e,f,g,h,i=c.config,j=i.$table.children("colgroup");if(j.length&&j.hasClass(b.css.colgroup)&&j.remove(),i.widthFixed&&0===i.$table.children("colgroup").length){for(j=a(''),d=i.$table.width(),f=i.$tbodies.find("tr:first").children(":visible"),g=f.length,h=0;g>h;h++)e=parseInt(f.eq(h).width()/d*1e3,10)/10+"%",j.append(a(" ").css("width",e));i.$table.prepend(j)}},getData:function(b,c,d){var e,f,g="",h=a(b);return h.length?(e=a.metadata?h.metadata():!1,f=" "+(h.attr("class")||""),"undefined"!=typeof h.data(d)||"undefined"!=typeof h.data(d.toLowerCase())?g+=h.data(d)||h.data(d.toLowerCase()):e&&"undefined"!=typeof e[d]?g+=e[d]:c&&"undefined"!=typeof c[d]?g+=c[d]:" "!==f&&f.match(" "+d+"-")&&(g=f.match(new RegExp("\\s"+d+"-([\\w-]+)"))[1]||""),a.trim(g)):""},getColumnData:function(b,c,d,e,f){if("undefined"!=typeof c&&null!==c){b=a(b)[0];var g,h,i=b.config,j=f||i.$headers,k=i.$headerIndexed&&i.$headerIndexed[d]||j.filter('[data-column="'+d+'"]:last');if(c[d])return e?c[d]:c[j.index(k)];for(h in c)if("string"==typeof h&&(g=k.filter(h).add(k.find(h)),g.length))return c[h]}},isProcessing:function(c,d,e){c=a(c);var f=c[0].config,g=e||c.find("."+b.css.header);d?("undefined"!=typeof e&&f.sortList.length>0&&(g=g.filter(function(){return this.sortDisabled?!1:b.isValueInArray(parseFloat(a(this).attr("data-column")),f.sortList)>=0})),c.add(g).addClass(b.css.processing+" "+f.cssProcessing)):c.add(g).removeClass(b.css.processing+" "+f.cssProcessing)},processTbody:function(b,c,d){if(b=a(b)[0],d)return b.isProcessing=!0,c.before(' '),a.fn.detach?c.detach():c.remove();var e=a(b).find("colgroup.tablesorter-savemyplace");c.insertAfter(e),e.remove(),b.isProcessing=!1},clearTableBody:function(b){a(b)[0].config.$tbodies.children().detach()},characterEquivalents:{a:"áàâãäąå",A:"ÁÀÂÃÄĄÅ",c:"çćč",C:"ÇĆČ",e:"éèêëěę",E:"ÉÈÊËĚĘ",i:"íìİîïı",I:"ÍÌİÎÏ",o:"óòôõöō",O:"ÓÒÔÕÖŌ",ss:"ß",SS:"ẞ",u:"úùûüů",U:"ÚÙÛÜŮ"},replaceAccents:function(a){var c,d="[",e=b.characterEquivalents;if(!b.characterRegex){b.characterRegexArray={};for(c in e)"string"==typeof c&&(d+=e[c],b.characterRegexArray[c]=new RegExp("["+e[c]+"]","g"));b.characterRegex=new RegExp(d+"]")}if(b.characterRegex.test(a))for(c in e)"string"==typeof c&&(a=a.replace(b.characterRegexArray[c],c));return a},restoreHeaders:function(c){var d,e,f=a(c)[0].config,g=f.$table.find(f.selectorHeaders),h=g.length;for(d=0;h>d;d++)e=g.eq(d),e.find("."+b.css.headerIn).length&&e.html(f.headerContent[d])},destroy:function(c,d,e){if(c=a(c)[0],c.hasInitialized){b.removeWidget(c,!0,!1);var f,g=a(c),h=c.config,i=h.debug,j=g.find("thead:first"),k=j.find("tr."+b.css.headerRow).removeClass(b.css.headerRow+" "+h.cssHeaderRow),l=g.find("tfoot:first > tr").children("th, td");d===!1&&a.inArray("uitheme",h.widgets)>=0&&(g.triggerHandler("applyWidgetId",["uitheme"]),g.triggerHandler("applyWidgetId",["zebra"])),j.find("tr").not(k).remove(),f="sortReset update updateRows updateAll updateHeaders updateCell addRows updateComplete sorton appendCache updateCache applyWidgetId applyWidgets refreshWidgets removeWidget destroy mouseup mouseleave "+"keypress sortBegin sortEnd resetToLoadState ".split(" ").join(h.namespace+" "),g.removeData("tablesorter").unbind(f.replace(b.regex.spaces," ")),h.$headers.add(l).removeClass([b.css.header,h.cssHeader,h.cssAsc,h.cssDesc,b.css.sortAsc,b.css.sortDesc,b.css.sortNone].join(" ")).removeAttr("data-column").removeAttr("aria-label").attr("aria-disabled","true"),k.find(h.selectorSort).unbind("mousedown mouseup keypress ".split(" ").join(h.namespace+" ").replace(b.regex.spaces," ")),b.restoreHeaders(c),g.toggleClass(b.css.table+" "+h.tableClass+" tablesorter-"+h.theme,d===!1),c.hasInitialized=!1,delete c.config.cache,"function"==typeof e&&e(c),i&&console.log("tablesorter has been removed")}}};a.fn.tablesorter=function(c){return this.each(function(){var d=this,e=a.extend(!0,{},b.defaults,c,b.instanceMethods);e.originalSettings=c,!d.hasInitialized&&b.buildTable&&"TABLE"!==this.nodeName?b.buildTable(d,e):b.setup(d,e)})},window.console&&window.console.log||(b.logs=[],console={},console.log=console.warn=console.error=console.table=function(){var a=arguments.length>1?arguments:arguments[0];b.logs[b.logs.length]={date:Date.now(),log:a}}),b.addParser({id:"no-parser",is:function(){return!1},format:function(){return""},type:"text"}),b.addParser({id:"text",is:function(){return!0},format:function(c,d){var e=d.config;return c&&(c=a.trim(e.ignoreCase?c.toLocaleLowerCase():c),c=e.sortLocaleCompare?b.replaceAccents(c):c),c},type:"text"}),b.regex.nondigit=/[^\w,. \-()]/g,b.addParser({id:"digit",is:function(a){return b.isDigit(a)},format:function(c,d){var e=b.formatFloat((c||"").replace(b.regex.nondigit,""),d);return c&&"number"==typeof e?e:c?a.trim(c&&d.config.ignoreCase?c.toLocaleLowerCase():c):c},type:"numeric"}),b.regex.currencyReplace=/[+\-,. ]/g,b.regex.currencyTest=/^\(?\d+[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]|[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]\d+\)?$/,b.addParser({id:"currency",is:function(a){return a=(a||"").replace(b.regex.currencyReplace,""),b.regex.currencyTest.test(a)},format:function(c,d){var e=b.formatFloat((c||"").replace(b.regex.nondigit,""),d);return c&&"number"==typeof e?e:c?a.trim(c&&d.config.ignoreCase?c.toLocaleLowerCase():c):c},type:"numeric"}),b.regex.urlProtocolTest=/^(https?|ftp|file):\/\//,b.regex.urlProtocolReplace=/(https?|ftp|file):\/\//,b.addParser({id:"url",is:function(a){return b.regex.urlProtocolTest.test(a)},format:function(c){return c?a.trim(c.replace(b.regex.urlProtocolReplace,"")):c},parsed:!0,type:"text"}),b.regex.dash=/-/g,b.regex.isoDate=/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}/,b.addParser({id:"isoDate",is:function(a){return b.regex.isoDate.test(a)},format:function(a,c){var d=a?new Date(a.replace(b.regex.dash,"/")):a;return d instanceof Date&&isFinite(d)?d.getTime():a},type:"numeric"}),b.regex.percent=/%/g,b.regex.percentTest=/(\d\s*?%|%\s*?\d)/,b.addParser({id:"percent",is:function(a){return b.regex.percentTest.test(a)&&a.length<15},format:function(a,c){return a?b.formatFloat(a.replace(b.regex.percent,""),c):a},type:"numeric"}),b.addParser({id:"image",is:function(a,b,c,d){return d.find("img").length>0},format:function(b,c,d){return a(d).find("img").attr(c.config.imgAttr||"alt")||b},parsed:!0,type:"text"}),b.regex.dateReplace=/(\S)([AP]M)$/i,b.regex.usLongDateTest1=/^[A-Z]{3,10}\.?\s+\d{1,2},?\s+(\d{4})(\s+\d{1,2}:\d{2}(:\d{2})?(\s+[AP]M)?)?$/i,b.regex.usLongDateTest2=/^\d{1,2}\s+[A-Z]{3,10}\s+\d{4}/i,b.addParser({id:"usLongDate",is:function(a){return b.regex.usLongDateTest1.test(a)||b.regex.usLongDateTest2.test(a)},format:function(a,c){var d=a?new Date(a.replace(b.regex.dateReplace,"$1 $2")):a;return d instanceof Date&&isFinite(d)?d.getTime():a},type:"numeric"}),b.regex.shortDateTest=/(^\d{1,2}[\/\s]\d{1,2}[\/\s]\d{4})|(^\d{4}[\/\s]\d{1,2}[\/\s]\d{1,2})/,b.regex.shortDateReplace=/[\-.,]/g,b.regex.shortDateXXY=/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/,b.regex.shortDateYMD=/(\d{4})[\/\s](\d{1,2})[\/\s](\d{1,2})/,b.convertFormat=function(a,c){a=(a||"").replace(b.regex.spaces," ").replace(b.regex.shortDateReplace,"/"),"mmddyyyy"===c?a=a.replace(b.regex.shortDateXXY,"$3/$1/$2"):"ddmmyyyy"===c?a=a.replace(b.regex.shortDateXXY,"$3/$2/$1"):"yyyymmdd"===c&&(a=a.replace(b.regex.shortDateYMD,"$1/$2/$3"));var d=new Date(a);return d instanceof Date&&isFinite(d)?d.getTime():""},b.addParser({id:"shortDate",is:function(a){return a=(a||"").replace(b.regex.spaces," ").replace(b.regex.shortDateReplace,"/"),b.regex.shortDateTest.test(a)},format:function(a,c,d,e){if(a){var f=c.config,g=f.$headerIndexed[e],h=g.length&&g.data("dateFormat")||b.getData(g,b.getColumnData(c,f.headers,e),"dateFormat")||f.dateFormat;return g.length&&g.data("dateFormat",h),b.convertFormat(a,h)||a}return a},type:"numeric"}),b.regex.timeTest=/^([1-9]|1[0-2]):([0-5]\d)(\s[AP]M)$|^((?:[01]\d|[2][0-4]):[0-5]\d)$/i,b.regex.timeMatch=/([1-9]|1[0-2]):([0-5]\d)(\s[AP]M)|((?:[01]\d|[2][0-4]):[0-5]\d)/i,b.addParser({id:"time",is:function(a){return b.regex.timeTest.test(a)},format:function(a,c){var d,e=(a||"").match(b.regex.timeMatch),f=new Date(a),g=a&&(null!==e?e[0]:"00:00 AM"),h=g?new Date("2000/01/01 "+g.replace(b.regex.dateReplace,"$1 $2")):g;return h instanceof Date&&isFinite(h)?(d=f instanceof Date&&isFinite(f)?f.getTime():0,d?parseFloat(h.getTime()+"."+f.getTime()):h.getTime()):a},type:"numeric"}),b.addParser({id:"metadata",is:function(){return!1},format:function(b,c,d){var e=c.config,f=e.parserMetadataName?e.parserMetadataName:"sortValue";return a(d).metadata()[f]},type:"numeric"}),b.addWidget({id:"zebra",priority:90,format:function(b,c,d){var e,f,g,h,i,j,k,l=new RegExp(c.cssChildRow,"i"),m=c.$tbodies.add(a(c.namespace+"_extra_table").children("tbody:not(."+c.cssInfoBlock+")"));for(i=0;ij;j++)f=e.eq(j),l.test(f[0].className)||g++,h=g%2===0,f.removeClass(d.zebra[h?1:0]).addClass(d.zebra[h?0:1])},remove:function(a,c,d,e){if(!e){var f,g,h=c.$tbodies,i=(d.zebra||["even","odd"]).join(" ");for(f=0;f thead th, > thead td",selectorSort:"th, td",selectorRemove:".remove-me",debug:!1,headerList:[],empties:{},strings:{},parsers:[],globalize:0,imgAttr:0},css:{table:"tablesorter",cssHasChild:"tablesorter-hasChildRow",childRow:"tablesorter-childRow",colgroup:"tablesorter-colgroup",header:"tablesorter-header",headerRow:"tablesorter-headerRow",headerIn:"tablesorter-header-inner",icon:"tablesorter-icon",processing:"tablesorter-processing",sortAsc:"tablesorter-headerAsc",sortDesc:"tablesorter-headerDesc",sortNone:"tablesorter-headerUnSorted"},language:{sortAsc:"Ascending sort applied, ",sortDesc:"Descending sort applied, ",sortNone:"No sort applied, ",sortDisabled:"sorting is disabled",nextAsc:"activate to apply an ascending sort",nextDesc:"activate to apply a descending sort",nextNone:"activate to remove the sort"},regex:{templateContent:/\{content\}/g,templateIcon:/\{icon\}/g,templateName:/\{name\}/i,spaces:/\s+/g,nonWord:/\W/g,formElements:/(input|select|button|textarea)/i,chunk:/(^([+\-]?(?:\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)?$|^0x[0-9a-f]+$|\d+)/gi,chunks:/(^\\0|\\0$)/,hex:/^0x[0-9a-f]+$/i,comma:/,/g,digitNonUS:/[\s|\.]/g,digitNegativeTest:/^\s*\([.\d]+\)/,digitNegativeReplace:/^\s*\(([.\d]+)\)/,digitTest:/^[\-+(]?\d+[)]?$/,digitReplace:/[,.'"\s]/g},string:{max:1,min:-1,emptymin:1,emptymax:-1,zero:0,none:0,null:0,top:!0,bottom:!1},keyCodes:{enter:13},dates:{},instanceMethods:{},setup:function(a,d){if(!a||!a.tHead||0===a.tBodies.length||a.hasInitialized===!0)return void(d.debug&&(a.hasInitialized?console.warn("Stopping initialization. Tablesorter has already been initialized"):console.error("Stopping initialization! No table, thead or tbody",a)));var e="",f=b(a),g=b.metadata;a.hasInitialized=!1,a.isProcessing=!0,a.config=d,b.data(a,"tablesorter",d),d.debug&&(console[console.group?"group":"log"]("Initializing tablesorter v"+c.version),b.data(a,"startoveralltimer",new Date)),d.supportsDataObject=function(a){return a[0]=parseInt(a[0],10),a[0]>1||1===a[0]&&parseInt(a[1],10)>=4}(b.fn.jquery.split(".")),d.emptyTo=d.emptyTo.toLowerCase(),d.stringTo=d.stringTo.toLowerCase(),d.last={sortList:[],clickedIndex:-1},/tablesorter\-/.test(f.attr("class"))||(e=""!==d.theme?" tablesorter-"+d.theme:""),d.table=a,d.$table=f.addClass(c.css.table+" "+d.tableClass+e).attr("role","grid"),d.$headers=f.find(d.selectorHeaders),d.namespace?d.namespace="."+d.namespace.replace(c.regex.nonWord,""):d.namespace=".tablesorter"+Math.random().toString(16).slice(2),d.$table.children().children("tr").attr("role","row"),d.$tbodies=f.children("tbody:not(."+d.cssInfoBlock+")").attr({"aria-live":"polite","aria-relevant":"all"}),d.$table.children("caption").length&&(e=d.$table.children("caption")[0],e.id||(e.id=d.namespace.slice(1)+"caption"),d.$table.attr("aria-labelledby",e.id)),d.widgetInit={},d.textExtraction=d.$table.attr("data-text-extraction")||d.textExtraction||"basic",c.buildHeaders(d),c.fixColumnWidth(a),c.addWidgetFromClass(a),c.applyWidgetOptions(a),c.setupParsers(d),d.totalRows=0,c.validateOptions(d),d.delayInit||c.buildCache(d),c.bindEvents(a,d.$headers,!0),c.bindMethods(d),d.supportsDataObject&&"undefined"!=typeof f.data().sortlist?d.sortList=f.data().sortlist:g&&f.metadata()&&f.metadata().sortlist&&(d.sortList=f.metadata().sortlist),c.applyWidget(a,!0),d.sortList.length>0?c.sortOn(d,d.sortList,{},!d.initWidgets):(c.setHeadersCss(d),d.initWidgets&&c.applyWidget(a,!1)),d.showProcessing&&f.unbind("sortBegin"+d.namespace+" sortEnd"+d.namespace).bind("sortBegin"+d.namespace+" sortEnd"+d.namespace,function(b){clearTimeout(d.timerProcessing),c.isProcessing(a),"sortBegin"===b.type&&(d.timerProcessing=setTimeout(function(){c.isProcessing(a,!0)},500))}),a.hasInitialized=!0,a.isProcessing=!1,d.debug&&(console.log("Overall initialization time:"+c.benchmark(b.data(a,"startoveralltimer"))),d.debug&&console.groupEnd&&console.groupEnd()),f.triggerHandler("tablesorter-initialized",a),"function"==typeof d.initialized&&d.initialized(a)},bindMethods:function(a){var d=a.$table,e=a.namespace,f="sortReset update updateRows updateAll updateHeaders addRows updateCell updateComplete sorton appendCache updateCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave ".split(" ").join(e+" ");d.unbind(f.replace(c.regex.spaces," ")).bind("sortReset"+e,function(a,b){a.stopPropagation(),c.sortReset(this.config,b)}).bind("updateAll"+e,function(a,b,d){a.stopPropagation(),c.updateAll(this.config,b,d)}).bind("update"+e+" updateRows"+e,function(a,b,d){a.stopPropagation(),c.update(this.config,b,d)}).bind("updateHeaders"+e,function(a,b){a.stopPropagation(),c.updateHeaders(this.config,b)}).bind("updateCell"+e,function(a,b,d,e){a.stopPropagation(),c.updateCell(this.config,b,d,e)}).bind("addRows"+e,function(a,b,d,e){a.stopPropagation(),c.addRows(this.config,b,d,e)}).bind("updateComplete"+e,function(){this.isUpdating=!1}).bind("sorton"+e,function(a,b,d,e){a.stopPropagation(),c.sortOn(this.config,b,d,e)}).bind("appendCache"+e,function(a,d,e){a.stopPropagation(),c.appendCache(this.config,e),b.isFunction(d)&&d(this)}).bind("updateCache"+e,function(a,b,d){a.stopPropagation(),c.updateCache(this.config,b,d)}).bind("applyWidgetId"+e,function(a,b){a.stopPropagation(),c.applyWidgetId(this,b)}).bind("applyWidgets"+e,function(a,b){a.stopPropagation(),c.applyWidget(this,b)}).bind("refreshWidgets"+e,function(a,b,d){a.stopPropagation(),c.refreshWidgets(this,b,d)}).bind("removeWidget"+e,function(a,b,d){a.stopPropagation(),c.removeWidget(this,b,d)}).bind("destroy"+e,function(a,b,d){a.stopPropagation(),c.destroy(this,b,d)}).bind("resetToLoadState"+e,function(d){d.stopPropagation(),c.removeWidget(this,!0,!1);var e=b.extend(!0,{},a.originalSettings);a=b.extend(!0,c.defaults,e),a.originalSettings=e,this.hasInitialized=!1,c.setup(this,a)})},bindEvents:function(a,d,e){a=b(a)[0];var f,g=a.config,h=g.namespace,i=null;e!==!0&&(d.addClass(h.slice(1)+"_extra_headers"),f=b.fn.closest?d.closest("table")[0]:d.parents("table")[0],f&&"TABLE"===f.nodeName&&f!==a&&b(f).addClass(h.slice(1)+"_extra_table")),f=(g.pointerDown+" "+g.pointerUp+" "+g.pointerClick+" sort keyup ").replace(c.regex.spaces," ").split(" ").join(h+" "),d.find(g.selectorSort).add(d.filter(g.selectorSort)).unbind(f).bind(f,function(a,e){var f,h,j,k=b(a.target),l=" "+a.type+" ";if(!(1!==(a.which||a.button)&&!l.match(" "+g.pointerClick+" | sort | keyup ")||" keyup "===l&&a.which!==c.keyCodes.enter||l.match(" "+g.pointerClick+" ")&&"undefined"!=typeof a.which||l.match(" "+g.pointerUp+" ")&&i!==a.target&&e!==!0)){if(l.match(" "+g.pointerDown+" "))return i=a.target,j=k.jquery.split("."),void("1"===j[0]&&j[1]<4&&a.preventDefault());if(i=null,c.regex.formElements.test(a.target.nodeName)||k.hasClass(g.cssNoSort)||k.parents("."+g.cssNoSort).length>0||k.parents("button").length>0)return!g.cancelSelection;g.delayInit&&c.isEmptyObject(g.cache)&&c.buildCache(g),f=b.fn.closest?b(this).closest("th, td"):/TH|TD/.test(this.nodeName)?b(this):b(this).parents("th, td"),j=d.index(f),g.last.clickedIndex=j<0?f.attr("data-column"):j,h=g.$headers[g.last.clickedIndex],h&&!h.sortDisabled&&c.initSort(g,h,a)}}),g.cancelSelection&&d.attr("unselectable","on").bind("selectstart",!1).css({"user-select":"none",MozUserSelect:"none"})},buildHeaders:function(a){var d,e,f,g;for(a.headerList=[],a.headerContent=[],a.sortVars=[],a.debug&&(f=new Date),a.columns=c.computeColumnIndex(a.$table.children("thead, tfoot").children("tr")),e=a.cssIcon?' ':"",a.$headers=b(b.map(a.$table.find(a.selectorHeaders),function(d,f){var g,h,i,j,k,l=b(d);if(!l.parent().hasClass(a.cssIgnoreRow))return g=c.getColumnData(a.table,a.headers,f,!0),a.headerContent[f]=l.html(),""===a.headerTemplate||l.find("."+c.css.headerIn).length||(j=a.headerTemplate.replace(c.regex.templateContent,l.html()).replace(c.regex.templateIcon,l.find("."+c.css.icon).length?"":e),a.onRenderTemplate&&(h=a.onRenderTemplate.apply(l,[f,j]),h&&"string"==typeof h&&(j=h)),l.html('")),a.onRenderHeader&&a.onRenderHeader.apply(l,[f,a,a.$table]),i=parseInt(l.attr("data-column"),10),d.column=i,k=c.getOrder(c.getData(l,g,"sortInitialOrder")||a.sortInitialOrder),a.sortVars[i]={count:-1,order:k?a.sortReset?[1,0,2]:[1,0]:a.sortReset?[0,1,2]:[0,1],lockedOrder:!1},k=c.getData(l,g,"lockedOrder")||!1,"undefined"!=typeof k&&k!==!1&&(a.sortVars[i].lockedOrder=!0,a.sortVars[i].order=c.getOrder(k)?[1,1]:[0,0]),a.headerList[f]=d,l.addClass(c.css.header+" "+a.cssHeader).parent().addClass(c.css.headerRow+" "+a.cssHeaderRow).attr("role","row"),a.tabIndex&&l.attr("tabindex",0),d})),a.$headerIndexed=[],g=0;g0))for(h+=f,g+=f;f+1>0;)e.parsers[h-f]=m,e.extractors[h-f]=n,f--;h++}s+=e.parsers.length?q:1}a.debug&&(c.isEmptyObject(t)?console.warn(" No parsers detected!"):console[console.table?"table":"log"](t),console.log("Completed detecting parsers"+c.benchmark(o)),console.groupEnd&&console.groupEnd()),a.parsers=e.parsers,a.extractors=e.extractors},addParser:function(a){var b,d=c.parsers.length,e=!0;for(b=0;b=0;)if(g=c.parsers[j],g&&"text"!==g.id&&g.is&&g.is(l,a.table,k,h))return g;return c.getParserById("text")},getElementText:function(a,d,e){if(!d)return"";var f,g=a.textExtraction||"",h=d.jquery?d:b(d);return"string"==typeof g?"basic"===g&&"undefined"!=typeof(f=h.attr(a.textAttribute))?b.trim(f):b.trim(d.textContent||h.text()):"function"==typeof g?b.trim(g(h[0],a.table,e)):"function"==typeof(f=c.getColumnData(a.table,g,e))?b.trim(f(h[0],a.table,e)):b.trim(h[0].textContent||h.text())},getParsedText:function(a,b,d,e){"undefined"==typeof e&&(e=c.getElementText(a,b,d));var f=""+e,g=a.parsers[d],h=a.extractors[d];return g&&(h&&"function"==typeof h.format&&(e=h.format(e,a.table,b,d)),f="no-parser"===g.id?"":g.format(""+e,a.table,b,d),a.ignoreCase&&"string"==typeof f&&(f=f.toLowerCase())),f},buildCache:function(a,d,e){var f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B=a.table,C=a.parsers;if(a.$tbodies=a.$table.children("tbody:not(."+a.cssInfoBlock+")"),l="undefined"==typeof e?a.$tbodies:e,a.cache={},a.totalRows=0,!C)return a.debug?console.warn("Warning: *Empty table!* Not building a cache"):"";for(a.debug&&(q=new Date),a.showProcessing&&c.isProcessing(B,!0),k=0;k0&&(w+=v,y+=v)),w++;else{for(s.$row=m,s.order=i,w=0,y=a.columns,j=0;j0)){for(A=0;A<=v;)h=a.duplicateSpan||0===A?g:"string"!=typeof a.textExtraction?c.getElementText(a,p,w+A)||"":"",s.raw[w+A]=h,n[w+A]=h,A++;w+=v,y+=v}w++}n[a.columns]=s,f.normalized[f.normalized.length]=n}f.colMax=u,a.totalRows+=f.normalized.length}if(a.showProcessing&&c.isProcessing(B),a.debug){for(z=Math.min(5,a.cache[0].normalized.length),console[console.group?"group":"log"]("Building cache for "+a.totalRows+" rows (showing "+z+" rows in log) and "+a.columns+" columns"+c.benchmark(q)),g={},j=0;j-1);return d}),d=d.not(".sorter-false").filter('[data-column="'+g[e][0]+'"]'+(1===h?":last":"")),d.length)){for(f=0;f=0?f:g[1]%l.length}},updateAll:function(a,b,d){var e=a.table;e.isUpdating=!0,c.refreshWidgets(e,!0,!0),c.buildHeaders(a),c.bindEvents(e,a.$headers,!0),c.bindMethods(a),c.commonUpdate(a,b,d)},update:function(a,b,d){var e=a.table;e.isUpdating=!0,c.updateHeader(a),c.commonUpdate(a,b,d)},updateHeaders:function(a,b){a.table.isUpdating=!0,c.buildHeaders(a),c.bindEvents(a.table,a.$headers,!0),c.resortComplete(a,b)},updateCell:function(a,d,e,f){if(c.isEmptyObject(a.cache))return c.updateHeader(a),void c.commonUpdate(a,e,f);a.table.isUpdating=!0,a.$table.find(a.selectorRemove).remove();var g,h,i,j,k,l,m=a.$tbodies,n=b(d),o=m.index(b.fn.closest?n.closest("tbody"):n.parents("tbody").filter(":first")),p=a.cache[o],q=b.fn.closest?n.closest("tr"):n.parents("tr").filter(":first");if(d=n[0],m.length&&o>=0){if(i=m.eq(o).find("tr").index(q),k=p.normalized[i],l=q[0].cells.length,l!==a.columns)for(j=0,g=!1,h=0;h0&&(p+=t),p++;r[d.columns]=q,d.cache[j].normalized[o]=r}c.checkResort(d,f,g)}},updateCache:function(a,b,d){a.parsers&&a.parsers.length||c.setupParsers(a,d),c.buildCache(a,b,d)},appendCache:function(a,b){var d,e,f,g,h,i,j,k=a.table,l=a.widgetOptions,m=a.$tbodies,n=[],o=a.cache;if(c.isEmptyObject(o))return a.appender?a.appender(k,n):k.isUpdating?a.$table.triggerHandler("updateComplete",k):"";for(a.debug&&(j=new Date),i=0;i1))for(g=1;g=0)for(g=0;g1))for(g=1;ge)return 1}for(d=(a||"").replace(j.chunk,"\\0$1\\0").replace(j.chunks,"").split("\\0"),e=(b||"").replace(j.chunk,"\\0$1\\0").replace(j.chunks,"").split("\\0"),i=Math.max(d.length,e.length),h=0;hg)return 1}return 0},sortNaturalAsc:function(a,b,d,e){if(a===b)return 0;var f=c.string[e.empties[d]||e.emptyTo];return""===a&&0!==f?"boolean"==typeof f?f?-1:1:-f||-1:""===b&&0!==f?"boolean"==typeof f?f?1:-1:f||1:c.sortNatural(a,b)},sortNaturalDesc:function(a,b,d,e){if(a===b)return 0;var f=c.string[e.empties[d]||e.emptyTo];return""===a&&0!==f?"boolean"==typeof f?f?-1:1:f||1:""===b&&0!==f?"boolean"==typeof f?f?1:-1:-f||-1:c.sortNatural(b,a)},sortText:function(a,b){return a>b?1:a=0&&e!==!0&&j.widgets.splice(h,1),g&&g.remove&&(j.debug&&console.log((e?"Refreshing":"Removing")+' "'+d[f]+'" widget'),g.remove(a,j,j.widgetOptions,e),j.widgetInit[d[f]]=!1)},refreshWidgets:function(a,d,e){a=b(a)[0];var f,g,h=a.config,i=h.widgets,j=c.widgets,k=j.length,l=[],m=function(a){b(a).triggerHandler("refreshComplete")};for(f=0;f'),d=i.$table.width(),f=i.$tbodies.find("tr:first").children(":visible"),g=f.length,h=0;h").css("width",e));i.$table.prepend(j)}},getData:function(a,c,d){var e,f,g="",h=b(a);return h.length?(e=!!b.metadata&&h.metadata(),f=" "+(h.attr("class")||""),"undefined"!=typeof h.data(d)||"undefined"!=typeof h.data(d.toLowerCase())?g+=h.data(d)||h.data(d.toLowerCase()):e&&"undefined"!=typeof e[d]?g+=e[d]:c&&"undefined"!=typeof c[d]?g+=c[d]:" "!==f&&f.match(" "+d+"-")&&(g=f.match(new RegExp("\\s"+d+"-([\\w-]+)"))[1]||""),b.trim(g)):""},getColumnData:function(a,c,d,e,f){if("object"!=typeof c||null===c)return c;a=b(a)[0];var g,h,i=a.config,j=f||i.$headers,k=i.$headerIndexed&&i.$headerIndexed[d]||j.filter('[data-column="'+d+'"]:last');if("undefined"!=typeof c[d])return e?c[d]:c[j.index(k)];for(h in c)if("string"==typeof h&&(g=k.filter(h).add(k.find(h)),g.length))return c[h]},isProcessing:function(a,d,e){a=b(a);var f=a[0].config,g=e||a.find("."+c.css.header);d?("undefined"!=typeof e&&f.sortList.length>0&&(g=g.filter(function(){return!this.sortDisabled&&c.isValueInArray(parseFloat(b(this).attr("data-column")),f.sortList)>=0})),a.add(g).addClass(c.css.processing+" "+f.cssProcessing)):a.add(g).removeClass(c.css.processing+" "+f.cssProcessing)},processTbody:function(a,c,d){if(a=b(a)[0],d)return a.isProcessing=!0,c.before(' '),b.fn.detach?c.detach():c.remove();var e=b(a).find("colgroup.tablesorter-savemyplace");c.insertAfter(e),e.remove(),a.isProcessing=!1},clearTableBody:function(a){b(a)[0].config.$tbodies.children().detach()},characterEquivalents:{a:"áàâãäąå",A:"ÁÀÂÃÄĄÅ",c:"çćč",C:"ÇĆČ",e:"éèêëěę",E:"ÉÈÊËĚĘ",i:"íìİîïı",I:"ÍÌİÎÏ",o:"óòôõöō",O:"ÓÒÔÕÖŌ",ss:"ß",SS:"ẞ",u:"úùûüů",U:"ÚÙÛÜŮ"},replaceAccents:function(a){var b,d="[",e=c.characterEquivalents;if(!c.characterRegex){c.characterRegexArray={};for(b in e)"string"==typeof b&&(d+=e[b],c.characterRegexArray[b]=new RegExp("["+e[b]+"]","g"));c.characterRegex=new RegExp(d+"]")}if(c.characterRegex.test(a))for(b in e)"string"==typeof b&&(a=a.replace(c.characterRegexArray[b],b));return a},validateOptions:function(a){var d,e,f,g,h="headers sortForce sortList sortAppend widgets".split(" "),i=a.originalSettings;if(i){a.debug&&(g=new Date);for(d in i)if(f=typeof c.defaults[d],"undefined"===f)console.warn('Tablesorter Warning! "table.config.'+d+'" option not recognized');else if("object"===f)for(e in i[d])f=c.defaults[d]&&typeof c.defaults[d][e],b.inArray(d,h)<0&&"undefined"===f&&console.warn('Tablesorter Warning! "table.config.'+d+"."+e+'" option not recognized');a.debug&&console.log("validate options time:"+c.benchmark(g))}},restoreHeaders:function(a){var d,e,f=b(a)[0].config,g=f.$table.find(f.selectorHeaders),h=g.length;for(d=0;d tr").children("th, td");d===!1&&b.inArray("uitheme",h.widgets)>=0&&(g.triggerHandler("applyWidgetId",["uitheme"]),g.triggerHandler("applyWidgetId",["zebra"])),j.find("tr").not(k).remove(),f="sortReset update updateRows updateAll updateHeaders updateCell addRows updateComplete sorton appendCache updateCache applyWidgetId applyWidgets refreshWidgets removeWidget destroy mouseup mouseleave "+"keypress sortBegin sortEnd resetToLoadState ".split(" ").join(h.namespace+" "),g.removeData("tablesorter").unbind(f.replace(c.regex.spaces," ")),h.$headers.add(l).removeClass([c.css.header,h.cssHeader,h.cssAsc,h.cssDesc,c.css.sortAsc,c.css.sortDesc,c.css.sortNone].join(" ")).removeAttr("data-column").removeAttr("aria-label").attr("aria-disabled","true"),k.find(h.selectorSort).unbind("mousedown mouseup keypress ".split(" ").join(h.namespace+" ").replace(c.regex.spaces," ")),c.restoreHeaders(a),g.toggleClass(c.css.table+" "+h.tableClass+" tablesorter-"+h.theme,d===!1),a.hasInitialized=!1,delete a.config.cache,"function"==typeof e&&e(a),i&&console.log("tablesorter has been removed")}}};b.fn.tablesorter=function(a){return this.each(function(){var d=this,e=b.extend(!0,{},c.defaults,a,c.instanceMethods);e.originalSettings=a,!d.hasInitialized&&c.buildTable&&"TABLE"!==this.nodeName?c.buildTable(d,e):c.setup(d,e)})},window.console&&window.console.log||(c.logs=[],console={},console.log=console.warn=console.error=console.table=function(){var a=arguments.length>1?arguments:arguments[0];c.logs[c.logs.length]={date:Date.now(),log:a}}),c.addParser({id:"no-parser",is:function(){return!1},format:function(){return""},type:"text"}),c.addParser({id:"text",is:function(){return!0},format:function(a,d){var e=d.config;return a&&(a=b.trim(e.ignoreCase?a.toLocaleLowerCase():a),a=e.sortLocaleCompare?c.replaceAccents(a):a),a},type:"text"}),c.regex.nondigit=/[^\w,. \-()]/g,c.addParser({id:"digit",is:function(a){return c.isDigit(a)},format:function(a,d){var e=c.formatFloat((a||"").replace(c.regex.nondigit,""),d);return a&&"number"==typeof e?e:a?b.trim(a&&d.config.ignoreCase?a.toLocaleLowerCase():a):a},type:"numeric"}),c.regex.currencyReplace=/[+\-,. ]/g,c.regex.currencyTest=/^\(?\d+[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]|[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]\d+\)?$/,c.addParser({id:"currency",is:function(a){return a=(a||"").replace(c.regex.currencyReplace,""),c.regex.currencyTest.test(a)},format:function(a,d){var e=c.formatFloat((a||"").replace(c.regex.nondigit,""),d);return a&&"number"==typeof e?e:a?b.trim(a&&d.config.ignoreCase?a.toLocaleLowerCase():a):a},type:"numeric"}),c.regex.urlProtocolTest=/^(https?|ftp|file):\/\//,c.regex.urlProtocolReplace=/(https?|ftp|file):\/\/(www\.)?/,c.addParser({id:"url",is:function(a){return c.regex.urlProtocolTest.test(a)},format:function(a){return a?b.trim(a.replace(c.regex.urlProtocolReplace,"")):a},type:"text"}),c.regex.dash=/-/g,c.regex.isoDate=/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}/,c.addParser({id:"isoDate",is:function(a){return c.regex.isoDate.test(a)},format:function(a,b){var d=a?new Date(a.replace(c.regex.dash,"/")):a;return d instanceof Date&&isFinite(d)?d.getTime():a},type:"numeric"}),c.regex.percent=/%/g,c.regex.percentTest=/(\d\s*?%|%\s*?\d)/,c.addParser({id:"percent",is:function(a){return c.regex.percentTest.test(a)&&a.length<15},format:function(a,b){return a?c.formatFloat(a.replace(c.regex.percent,""),b):a},type:"numeric"}),c.addParser({id:"image",is:function(a,b,c,d){return d.find("img").length>0},format:function(a,c,d){return b(d).find("img").attr(c.config.imgAttr||"alt")||a},parsed:!0,type:"text"}),c.regex.dateReplace=/(\S)([AP]M)$/i,c.regex.usLongDateTest1=/^[A-Z]{3,10}\.?\s+\d{1,2},?\s+(\d{4})(\s+\d{1,2}:\d{2}(:\d{2})?(\s+[AP]M)?)?$/i,c.regex.usLongDateTest2=/^\d{1,2}\s+[A-Z]{3,10}\s+\d{4}/i,c.addParser({id:"usLongDate",is:function(a){return c.regex.usLongDateTest1.test(a)||c.regex.usLongDateTest2.test(a)},format:function(a,b){var d=a?new Date(a.replace(c.regex.dateReplace,"$1 $2")):a;return d instanceof Date&&isFinite(d)?d.getTime():a},type:"numeric"}),c.regex.shortDateTest=/(^\d{1,2}[\/\s]\d{1,2}[\/\s]\d{4})|(^\d{4}[\/\s]\d{1,2}[\/\s]\d{1,2})/,c.regex.shortDateReplace=/[\-.,]/g,c.regex.shortDateXXY=/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/,c.regex.shortDateYMD=/(\d{4})[\/\s](\d{1,2})[\/\s](\d{1,2})/,c.convertFormat=function(a,b){a=(a||"").replace(c.regex.spaces," ").replace(c.regex.shortDateReplace,"/"),"mmddyyyy"===b?a=a.replace(c.regex.shortDateXXY,"$3/$1/$2"):"ddmmyyyy"===b?a=a.replace(c.regex.shortDateXXY,"$3/$2/$1"):"yyyymmdd"===b&&(a=a.replace(c.regex.shortDateYMD,"$1/$2/$3"));var d=new Date(a);return d instanceof Date&&isFinite(d)?d.getTime():""},c.addParser({id:"shortDate",is:function(a){return a=(a||"").replace(c.regex.spaces," ").replace(c.regex.shortDateReplace,"/"),c.regex.shortDateTest.test(a)},format:function(a,b,d,e){if(a){var f=b.config,g=f.$headerIndexed[e],h=g.length&&g.data("dateFormat")||c.getData(g,c.getColumnData(b,f.headers,e),"dateFormat")||f.dateFormat;return g.length&&g.data("dateFormat",h),c.convertFormat(a,h)||a}return a},type:"numeric"}),c.regex.timeTest=/^(0?[1-9]|1[0-2]):([0-5]\d)(\s[AP]M)$|^((?:[01]\d|[2][0-4]):[0-5]\d)$/i,c.regex.timeMatch=/(0?[1-9]|1[0-2]):([0-5]\d)(\s[AP]M)|((?:[01]\d|[2][0-4]):[0-5]\d)/i,c.addParser({id:"time",is:function(a){return c.regex.timeTest.test(a)},format:function(a,b){var d,e=(a||"").match(c.regex.timeMatch),f=new Date(a),g=a&&(null!==e?e[0]:"00:00 AM"),h=g?new Date("2000/01/01 "+g.replace(c.regex.dateReplace,"$1 $2")):g;return h instanceof Date&&isFinite(h)?(d=f instanceof Date&&isFinite(f)?f.getTime():0,d?parseFloat(h.getTime()+"."+f.getTime()):h.getTime()):a},type:"numeric"}),c.addParser({id:"metadata",is:function(){return!1},format:function(a,c,d){var e=c.config,f=e.parserMetadataName?e.parserMetadataName:"sortValue";return b(d).metadata()[f]},type:"numeric"}),c.addWidget({id:"zebra",priority:90,format:function(a,c,d){var e,f,g,h,i,j,k,l=new RegExp(c.cssChildRow,"i"),m=c.$tbodies.add(b(c.namespace+"_extra_table").children("tbody:not(."+c.cssInfoBlock+")"));for(i=0;i= 0 ) {
- t = (sz * p.page > p.filteredRows) && completed;
- p.page = (t) ? p.pageReset || 0 : p.page;
- p.startRow = (t) ? sz * p.page + 1 : (p.filteredRows === 0 ? 0 : sz * p.page + 1);
- p.endRow = Math.min( p.filteredRows, p.totalRows, sz * ( p.page + 1 ) );
- $out = p.$container.find(p.cssPageDisplay);
- // form the output string (can now get a new output string from the server)
- s = ( p.ajaxData && p.ajaxData.output ? p.ajaxData.output || p.output : p.output )
- // {page} = one-based index; {page+#} = zero based index +/- value
- .replace(/\{page([\-+]\d+)?\}/gi, function(m, n){
- return p.totalPages ? p.page + (n ? parseInt(n, 10) : 1) : 0;
- })
- // {totalPages}, {extra}, {extra:0} (array) or {extra : key} (object)
- .replace(/\{\w+(\s*:\s*\w+)?\}/gi, function(m){
- var len, indx,
- str = m.replace(/[{}\s]/g, ''),
- extra = str.split(':'),
- data = p.ajaxData,
- // return zero for default page/row numbers
- deflt = /(rows?|pages?)$/i.test(str) ? 0 : '';
- if (/(startRow|page)/.test(extra[0]) && extra[1] === 'input') {
- len = ('' + (extra[0] === 'page' ? p.totalPages : p.totalRows)).length;
- indx = extra[0] === 'page' ? p.page + 1 : p.startRow;
- return '';
- }
- return extra.length > 1 && data && data[extra[0]] ? data[extra[0]][extra[1]] : p[str] || (data ? data[str] : deflt) || deflt;
- });
- if ( p.$goto.length ) {
- t = '';
- options = buildPageSelect( table, p );
- len = options.length;
- for (indx = 0; indx < len; indx++) {
- t += '' + options[indx] + ' ';
- }
- // innerHTML doesn't work in IE9 - http://support2.microsoft.com/kb/276228
- p.$goto.html(t).val( p.page + 1 );
- }
- if ($out.length) {
- $out[ ($out[0].nodeName === 'INPUT') ? 'val' : 'html' ](s);
- // rebind startRow/page inputs
- $out.find('.ts-startRow, .ts-page').unbind('change' + namespace).bind('change' + namespace, function(){
- var v = $(this).val(),
- pg = $(this).hasClass('ts-startRow') ? Math.floor( v / sz ) + 1 : v;
- c.$table.triggerHandler('pageSet' + namespace, [ pg ]);
- });
- }
- }
- pagerArrows( table, p );
- fixHeight(table, p);
- if (p.initialized && completed !== false) {
- if (c.debug) {
- console.log('Pager: Triggering pagerComplete');
- }
- c.$table.triggerHandler('pagerComplete', p);
- // save pager info to storage
- if (p.savePages && ts.storage) {
- ts.storage(table, p.storageKey, {
- page : p.page,
- size : sz === p.totalRows ? 'all' : sz
- });
- }
- }
- },
-
- buildPageSelect = function( table, p ) {
- // Filter the options page number link array if it's larger than 'maxOptionSize'
- // as large page set links will slow the browser on large dom inserts
- var i, central_focus_size, focus_option_pages, insert_index, option_length, focus_length,
- pg = getTotalPages( table, p ) || 1,
- // make skip set size multiples of 5
- skip_set_size = Math.ceil( ( pg / p.maxOptionSize ) / 5 ) * 5,
- large_collection = pg > p.maxOptionSize,
- current_page = p.page + 1,
- start_page = skip_set_size,
- end_page = pg - skip_set_size,
- option_pages = [ 1 ],
- // construct default options pages array
- option_pages_start_page = (large_collection) ? skip_set_size : 1;
-
- for ( i = option_pages_start_page; i <= pg; ) {
- option_pages[ option_pages.length ] = i;
- i = i + ( large_collection ? skip_set_size : 1 );
- }
- option_pages[ option_pages.length ] = pg;
- if (large_collection) {
- focus_option_pages = [];
- // don't allow central focus size to be > 5 on either side of current page
- central_focus_size = Math.max( Math.floor( p.maxOptionSize / skip_set_size ) - 1, 5 );
-
- start_page = current_page - central_focus_size;
- if (start_page < 1) { start_page = 1; }
- end_page = current_page + central_focus_size;
- if (end_page > pg) { end_page = pg; }
- // construct an array to get a focus set around the current page
- for (i = start_page; i <= end_page ; i++) {
- focus_option_pages[ focus_option_pages.length ] = i;
- }
-
- // keep unique values
- option_pages = $.grep(option_pages, function(value, indx) {
- return $.inArray(value, option_pages) === indx;
- });
-
- option_length = option_pages.length;
- focus_length = focus_option_pages.length;
-
- // make sure at all option_pages aren't replaced
- if (option_length - focus_length > skip_set_size / 2 && option_length + focus_length > p.maxOptionSize ) {
- insert_index = Math.floor(option_length / 2) - Math.floor(focus_length / 2);
- Array.prototype.splice.apply(option_pages, [ insert_index, focus_length ]);
- }
- option_pages = option_pages.concat(focus_option_pages);
-
- }
-
- // keep unique values again
- option_pages = $.grep(option_pages, function(value, indx) {
- return $.inArray(value, option_pages) === indx;
- })
- .sort(function(a, b) { return a - b; });
-
- return option_pages;
- },
-
- fixHeight = function(table, p) {
- var d, h,
- c = table.config,
- $b = c.$tbodies.eq(0);
- $b.find('tr.pagerSavedHeightSpacer').remove();
- if (p.fixedHeight && !p.isDisabled) {
- h = $.data(table, 'pagerSavedHeight');
- if (h) {
- d = h - $b.height();
- if ( d > 5 && $.data(table, 'pagerLastSize') === p.size &&
- $b.children('tr:visible').length < (p.size === 'all' ? p.totalRows : p.size) ) {
- $b.append('');
- }
- }
- }
- },
-
- changeHeight = function(table, p) {
- var h,
- c = table.config,
- $b = c.$tbodies.eq(0);
- $b.find('tr.pagerSavedHeightSpacer').remove();
- if (!$b.children('tr:visible').length) {
- $b.append('');
- }
- h = $b.children('tr').eq(0).height() * (p.size === 'all' ? p.totalRows : p.size);
- $.data(table, 'pagerSavedHeight', h);
- fixHeight(table, p);
- $.data(table, 'pagerLastSize', p.size);
- },
-
- hideRows = function(table, p){
- if (!p.ajaxUrl) {
- var i,
- lastIndex = 0,
- c = table.config,
- rows = c.$tbodies.eq(0).children('tr'),
- l = rows.length,
- sz = p.size === 'all' ? p.totalRows : p.size,
- s = ( p.page * sz ),
- e = s + sz,
- f = c.widgetOptions && c.widgetOptions.filter_filteredRow || 'filtered',
- last = 0, // for cache indexing
- j = 0; // size counter
- p.cacheIndex = [];
- for ( i = 0; i < l; i++ ){
- if ( !rows[i].className.match(f) ) {
- if (j === s && rows[i].className.match(c.cssChildRow)) {
- // hide child rows @ start of pager (if already visible)
- rows[i].style.display = 'none';
- } else {
- rows[i].style.display = ( j >= s && j < e ) ? '' : 'none';
- if (last !== j && j >= s && j < e) {
- p.cacheIndex[ p.cacheIndex.length ] = i;
- last = j;
- }
- // don't count child rows
- j += rows[i].className.match(c.cssChildRow + '|' + c.selectorRemove.slice(1)) && !p.countChildRows ? 0 : 1;
- if ( j === e && rows[i].style.display !== 'none' && rows[i].className.match(ts.css.cssHasChild) ) {
- lastIndex = i;
- }
- }
- }
- }
- // add any attached child rows to last row of pager. Fixes part of issue #396
- if ( lastIndex > 0 && rows[lastIndex].className.match(ts.css.cssHasChild) ) {
- while ( ++lastIndex < l && rows[lastIndex].className.match(c.cssChildRow) ) {
- rows[lastIndex].style.display = '';
- }
- }
- }
- },
-
- hideRowsSetup = function(table, p){
- p.size = parsePageSize( p, p.$size.val(), 'get' );
- p.$size.val( p.size );
- $.data(table, 'pagerLastSize', p.size);
- pagerArrows( table, p );
- if ( !p.removeRows ) {
- hideRows(table, p);
- $(table).bind('sortEnd filterEnd '.split(' ').join(table.config.namespace + 'pager '), function(){
- hideRows(table, p);
- });
- }
- },
-
- renderAjax = function(data, table, p, xhr, settings, exception){
- // process data
- if ( typeof p.ajaxProcessing === 'function' ) {
-
- // in case nothing is returned by ajax, empty out the table; see #1032
- // but do it before calling pager_ajaxProcessing because that function may add content
- // directly to the table
- table.config.$tbodies.eq(0).empty();
-
- // ajaxProcessing result: [ total, rows, headers ]
- var i, j, t, hsh, $f, $sh, $headers, $h, icon, th, d, l, rr_count, len, sz,
- c = table.config,
- $table = c.$table,
- tds = '',
- result = p.ajaxProcessing(data, table, xhr) || [ 0, [] ],
- hl = $table.find('thead th').length;
-
- // Clean up any previous error.
- ts.showError( table );
-
- if ( exception ) {
- if (c.debug) {
- console.error('Pager: >> Ajax Error', xhr, settings, exception);
- }
- ts.showError( table, xhr, settings, exception );
- c.$tbodies.eq(0).children('tr').detach();
- p.totalRows = 0;
- } else {
- // process ajax object
- if (!$.isArray(result)) {
- p.ajaxData = result;
- c.totalRows = p.totalRows = result.total;
- c.filteredRows = p.filteredRows = typeof result.filteredRows !== 'undefined' ? result.filteredRows : result.total;
- th = result.headers;
- d = result.rows || [];
- } else {
- // allow [ total, rows, headers ] or [ rows, total, headers ]
- t = isNaN(result[0]) && !isNaN(result[1]);
- // ensure a zero returned row count doesn't fail the logical ||
- rr_count = result[t ? 1 : 0];
- p.totalRows = isNaN(rr_count) ? p.totalRows || 0 : rr_count;
- // can't set filtered rows when returning an array
- c.totalRows = c.filteredRows = p.filteredRows = p.totalRows;
- // set row data to empty array if nothing found - see http://stackoverflow.com/q/30875583/145346
- d = p.totalRows === 0 ? [] : result[t ? 0 : 1] || []; // row data
- th = result[2]; // headers
- }
- l = d && d.length;
- if (d instanceof jQuery) {
- if (p.processAjaxOnInit) {
- // append jQuery object
- c.$tbodies.eq(0).empty();
- c.$tbodies.eq(0).append(d);
- }
- } else if (l) {
- // build table from array
- for ( i = 0; i < l; i++ ) {
- tds += '';
- for ( j = 0; j < d[i].length; j++ ) {
- // build tbody cells; watch for data containing HTML markup - see #434
- tds += /^\s*' + d[i][j] + ' ';
- }
- tds += ' ';
- }
- // add rows to first tbody
- if (p.processAjaxOnInit) {
- c.$tbodies.eq(0).html( tds );
- }
- }
- p.processAjaxOnInit = true;
- // only add new header text if the length matches
- if ( th && th.length === hl ) {
- hsh = $table.hasClass('hasStickyHeaders');
- $sh = hsh ? c.widgetOptions.$sticky.children('thead:first').children('tr').children() : '';
- $f = $table.find('tfoot tr:first').children();
- // don't change td headers (may contain pager)
- $headers = c.$headers.filter( 'th ' );
- len = $headers.length;
- for ( j = 0; j < len; j++ ) {
- $h = $headers.eq( j );
- // add new test within the first span it finds, or just in the header
- if ( $h.find('.' + ts.css.icon).length ) {
- icon = $h.find('.' + ts.css.icon).clone(true);
- $h.find('.tablesorter-header-inner').html( th[j] ).append(icon);
- if ( hsh && $sh.length ) {
- icon = $sh.eq(j).find('.' + ts.css.icon).clone(true);
- $sh.eq(j).find('.tablesorter-header-inner').html( th[j] ).append(icon);
- }
- } else {
- $h.find('.tablesorter-header-inner').html( th[j] );
- if (hsh && $sh.length) {
- $sh.eq(j).find('.tablesorter-header-inner').html( th[j] );
- }
- }
- $f.eq(j).html( th[j] );
- }
- }
- }
- if (c.showProcessing) {
- ts.isProcessing(table); // remove loading icon
- }
- sz = parsePageSize( p, p.size, 'get' );
- // make sure last pager settings are saved, prevents multiple server side calls with
- // the same parameters
- p.totalPages = sz === 'all' ? 1 : Math.ceil( p.totalRows / sz );
- p.last.totalRows = p.totalRows;
- p.last.currentFilters = p.currentFilters;
- p.last.sortList = (c.sortList || []).join(',');
- updatePageDisplay(table, p, false);
- // tablesorter core updateCache (not pager)
- ts.updateCache( c, function(){
- if (p.initialized) {
- // apply widgets after table has rendered & after a delay to prevent
- // multiple applyWidget blocking code from blocking this trigger
- setTimeout(function(){
- if (c.debug) {
- console.log('Pager: Triggering pagerChange');
- }
- $table.triggerHandler( 'pagerChange', p );
- ts.applyWidget( table );
- updatePageDisplay(table, p, true);
- }, 0);
- }
- });
-
- }
- if (!p.initialized) {
- pagerInitialized(table, p);
- }
- },
-
- getAjax = function(table, p) {
- var url = getAjaxUrl(table, p),
- $doc = $(document),
- counter,
- c = table.config,
- namespace = c.namespace + 'pager';
- if ( url !== '' ) {
- if (c.showProcessing) {
- ts.isProcessing(table, true); // show loading icon
- }
- $doc.bind('ajaxError' + namespace, function(e, xhr, settings, exception) {
- renderAjax(null, table, p, xhr, settings, exception);
- $doc.unbind('ajaxError' + namespace);
- });
-
- counter = ++p.ajaxCounter;
-
- p.last.ajaxUrl = url; // remember processed url
- p.ajaxObject.url = url; // from the ajaxUrl option and modified by customAjaxUrl
- p.ajaxObject.success = function(data, status, jqxhr) {
- // Refuse to process old ajax commands that were overwritten by new ones - see #443
- if (counter < p.ajaxCounter){
- return;
- }
- renderAjax(data, table, p, jqxhr);
- $doc.unbind('ajaxError' + namespace);
- if (typeof p.oldAjaxSuccess === 'function') {
- p.oldAjaxSuccess(data);
- }
- };
- if (c.debug) {
- console.log('Pager: Ajax initialized', p.ajaxObject);
- }
- $.ajax(p.ajaxObject);
- }
- },
-
- getAjaxUrl = function(table, p) {
- var indx, len,
- c = table.config,
- url = (p.ajaxUrl) ? p.ajaxUrl
- // allow using "{page+1}" in the url string to switch to a non-zero based index
- .replace(/\{page([\-+]\d+)?\}/, function(s, n){ return p.page + (n ? parseInt(n, 10) : 0); })
- // this will pass "all" to server when size is set to "all"
- .replace(/\{size\}/g, p.size) : '',
- sortList = c.sortList,
- filterList = p.currentFilters || $(table).data('lastSearch') || [],
- sortCol = url.match(/\{\s*sort(?:List)?\s*:\s*(\w*)\s*\}/),
- filterCol = url.match(/\{\s*filter(?:List)?\s*:\s*(\w*)\s*\}/),
- arry = [];
- if (sortCol) {
- sortCol = sortCol[1];
- len = sortList.length;
- for (indx = 0; indx < len; indx++) {
- arry[ arry.length ] = sortCol + '[' + sortList[indx][0] + ']=' + sortList[indx][1];
- }
- // if the arry is empty, just add the col parameter... "&{sortList:col}" becomes "&col"
- url = url.replace(/\{\s*sort(?:List)?\s*:\s*(\w*)\s*\}/g, arry.length ? arry.join('&') : sortCol );
- arry = [];
- }
- if (filterCol) {
- filterCol = filterCol[1];
- len = filterList.length;
- for (indx = 0; indx < len; indx++) {
- if (filterList[indx]) {
- arry[ arry.length ] = filterCol + '[' + indx + ']=' + encodeURIComponent( filterList[indx] );
- }
- }
- // if the arry is empty, just add the fcol parameter... "&{filterList:fcol}" becomes "&fcol"
- url = url.replace(/\{\s*filter(?:List)?\s*:\s*(\w*)\s*\}/g, arry.length ? arry.join('&') : filterCol );
- p.currentFilters = filterList;
- }
- if ( typeof p.customAjaxUrl === 'function' ) {
- url = p.customAjaxUrl(table, url);
- }
- if (c.debug) {
- console.log('Pager: Ajax url = ' + url);
- }
- return url;
- },
-
- renderTable = function(table, rows, p) {
- var $tb, index, count, added,
- $t = $(table),
- c = table.config,
- f = c.$table.hasClass('hasFilters'),
- l = rows && rows.length || 0, // rows may be undefined
- e = p.size === 'all' ? p.totalRows : p.size,
- s = ( p.page * e );
- if ( l < 1 ) {
- if (c.debug) {
- console.warn('Pager: >> No rows for pager to render');
- }
- // empty table, abort!
- return;
- }
- if ( p.page >= p.totalPages ) {
- // lets not render the table more than once
- moveToLastPage(table, p);
- }
- p.cacheIndex = [];
- p.isDisabled = false; // needed because sorting will change the page and re-enable the pager
- if (p.initialized) {
- if (c.debug) {
- console.log('Pager: Triggering pagerChange');
- }
- $t.triggerHandler( 'pagerChange', p );
- }
- if ( !p.removeRows ) {
- hideRows(table, p);
- } else {
- ts.clearTableBody(table);
- $tb = ts.processTbody(table, c.$tbodies.eq(0), true);
- // not filtered, start from the calculated starting point (s)
- // if filtered, start from zero
- index = f ? 0 : s;
- count = f ? 0 : s;
- added = 0;
- while (added < e && index < rows.length) {
- if (!f || !/filtered/.test(rows[index][0].className)){
- count++;
- if (count > s && added <= e) {
- added++;
- p.cacheIndex[ p.cacheIndex.length ] = index;
- $tb.append(rows[index]);
- }
- }
- index++;
- }
- ts.processTbody(table, $tb, false);
- }
- updatePageDisplay(table, p);
- if (table.isUpdating) {
- if (c.debug) {
- console.log('Pager: Triggering updateComplete');
- }
- $t.triggerHandler('updateComplete', [ table, true ]);
- }
- },
-
- showAllRows = function(table, p) {
- var index, $controls, len;
- if ( p.ajax ) {
- pagerArrows( table, p, true );
- } else {
- $.data(table, 'pagerLastPage', p.page);
- $.data(table, 'pagerLastSize', p.size);
- p.page = 0;
- p.size = 'all';
- p.totalPages = 1;
- $(table)
- .addClass('pagerDisabled')
- .removeAttr('aria-describedby')
- .find('tr.pagerSavedHeightSpacer').remove();
- renderTable(table, table.config.rowsCopy, p);
- p.isDisabled = true;
- ts.applyWidget( table );
- if (table.config.debug) {
- console.log('Pager: Disabled');
- }
- }
- // disable size selector
- $controls = p.$size
- .add( p.$goto )
- .add( p.$container.find( '.ts-startRow, .ts-page' ) );
- len = $controls.length;
- for ( index = 0; index < len; index++ ) {
- $controls.eq( index )
- .attr( 'aria-disabled', 'true' )
- .addClass( p.cssDisabled )[0].disabled = true;
- }
- },
-
- // updateCache if delayInit: true
- updateCache = function(table) {
- var c = table.config,
- p = c.pager;
- // tablesorter core updateCache (not pager)
- ts.updateCache( c, function(){
- var i,
- rows = [],
- n = table.config.cache[0].normalized;
- p.totalRows = n.length;
- for (i = 0; i < p.totalRows; i++) {
- rows[ rows.length ] = n[i][c.columns].$row;
- }
- c.rowsCopy = rows;
- moveToPage(table, p, true);
- });
- },
-
- moveToPage = function(table, p, pageMoved) {
- if ( p.isDisabled ) { return; }
- var tmp,
- c = table.config,
- $t = $(table),
- l = p.last;
- if ( pageMoved !== false && p.initialized && ts.isEmptyObject(c.cache)) {
- return updateCache(table);
- }
- // abort page move if the table has filters and has not been initialized
- if (p.ajax && ts.hasWidget(table, 'filter') && !c.widgetOptions.filter_initialized) { return; }
- parsePageNumber( table, p );
- calcFilters(table, p);
- // fixes issue where one currentFilter is [] and the other is ['','',''],
- // making the next if comparison think the filters are different (joined by commas). Fixes #202.
- l.currentFilters = (l.currentFilters || []).join('') === '' ? [] : l.currentFilters;
- p.currentFilters = (p.currentFilters || []).join('') === '' ? [] : p.currentFilters;
- // don't allow rendering multiple times on the same page/size/totalRows/filters/sorts
- if ( l.page === p.page && l.size === p.size && l.totalRows === p.totalRows &&
- (l.currentFilters || []).join(',') === (p.currentFilters || []).join(',') &&
- // check for ajax url changes see #730
- (l.ajaxUrl || '') === (p.ajaxObject.url || '') &&
- // & ajax url option changes (dynamically add/remove/rename sort & filter parameters)
- (l.optAjaxUrl || '') === (p.ajaxUrl || '') &&
- l.sortList === (c.sortList || []).join(',') ) { return; }
- if (c.debug) {
- console.log('Pager: Changing to page ' + p.page);
- }
- p.last = {
- page : p.page,
- size : p.size,
- // fixes #408; modify sortList otherwise it auto-updates
- sortList : (c.sortList || []).join(','),
- totalRows : p.totalRows,
- currentFilters : p.currentFilters || [],
- ajaxUrl : p.ajaxObject.url || '',
- optAjaxUrl : p.ajaxUrl || ''
- };
- if (p.ajax) {
- if ( !p.processAjaxOnInit && !ts.isEmptyObject(p.initialRows) ) {
- p.processAjaxOnInit = true;
- tmp = p.initialRows;
- p.totalRows = typeof tmp.total !== 'undefined' ? tmp.total :
- ( c.debug ? console.error('Pager: no initial total page set!') || 0 : 0 );
- p.filteredRows = typeof tmp.filtered !== 'undefined' ? tmp.filtered :
- ( c.debug ? console.error('Pager: no initial filtered page set!') || 0 : 0 );
- pagerInitialized( table, p );
- } else {
- getAjax(table, p);
- }
- } else if (!p.ajax) {
- renderTable(table, c.rowsCopy, p);
- }
- $.data(table, 'pagerLastPage', p.page);
- if (p.initialized && pageMoved !== false) {
- if (c.debug) {
- console.log('Pager: Triggering pageMoved');
- }
- $t.triggerHandler('pageMoved', p);
- ts.applyWidget( table );
- if (table.isUpdating) {
- if (c.debug) {
- console.log('Pager: Triggering updateComplete');
- }
- $t.triggerHandler('updateComplete', [ table, true ]);
- }
- }
- },
-
- getTotalPages = function( table, p ) {
- return ts.hasWidget( table, 'filter' ) ? Math.min( p.totalPages, p.filteredPages ) : p.totalPages;
- },
-
- // set to either set or get value
- parsePageSize = function( p, size, mode ) {
- var s = parseInt( size, 10 ) || p.size || p.settings.size || 10;
- return /all/i.test( size ) || s === p.totalRows ?
- // "get" to get `p.size` or "set" to set `p.$size.val()`
- 'all' : ( mode === 'get' ? s : p.size );
- },
-
- parsePageNumber = function( table, p ) {
- var min = getTotalPages( table, p ) - 1;
- p.page = parseInt( p.page, 10 );
- if ( p.page < 0 || isNaN( p.page ) ) { p.page = 0; }
- if ( p.page > min && min >= 0 ) { p.page = min; }
- return p.page;
- },
-
- setPageSize = function(table, size, p) {
- p.size = parsePageSize( p, size, 'get' );
- p.$size.val( parsePageSize( p, p.size, 'set' ) );
- $.data(table, 'pagerLastPage', parsePageNumber( table, p ) );
- $.data(table, 'pagerLastSize', p.size);
- p.totalPages = p.size === 'all' ? 1 : Math.ceil( p.totalRows / p.size );
- p.filteredPages = p.size === 'all' ? 1 : Math.ceil( p.filteredRows / p.size );
- moveToPage(table, p);
- },
-
- moveToFirstPage = function(table, p) {
- p.page = 0;
- moveToPage(table, p);
- },
-
- moveToLastPage = function(table, p) {
- p.page = getTotalPages( table, p ) - 1;
- moveToPage(table, p);
- },
-
- moveToNextPage = function(table, p) {
- p.page++;
- var last = getTotalPages( table, p ) - 1;
- if ( p.page >= last ) {
- p.page = last;
- }
- moveToPage(table, p);
- },
-
- moveToPrevPage = function(table, p) {
- p.page--;
- if ( p.page <= 0 ) {
- p.page = 0;
- }
- moveToPage(table, p);
- },
-
- pagerInitialized = function(table, p) {
- p.initialized = true;
- p.initializing = false;
- if (table.config.debug) {
- console.log('Pager: Triggering pagerInitialized');
- }
- $(table).triggerHandler( 'pagerInitialized', p );
- ts.applyWidget( table );
- updatePageDisplay(table, p);
- },
-
- destroyPager = function(table, p) {
- var c = table.config,
- namespace = c.namespace + 'pager',
- ctrls = [ p.cssFirst, p.cssPrev, p.cssNext, p.cssLast, p.cssGoto, p.cssPageSize ].join( ',' );
- showAllRows(table, p);
- p.$container
- // hide pager controls
- .hide()
- // unbind
- .find( ctrls )
- .unbind( namespace );
- c.appender = null; // remove pager appender function
- c.$table.unbind( namespace );
- if (ts.storage) {
- ts.storage(table, p.storageKey, '');
- }
- delete c.pager;
- delete c.rowsCopy;
- },
-
- enablePager = function(table, p, triggered) {
- var info, size,
- c = table.config;
- p.$size.add(p.$goto).add(p.$container.find('.ts-startRow, .ts-page'))
- .removeClass(p.cssDisabled)
- .removeAttr('disabled')
- .attr('aria-disabled', 'false');
- p.isDisabled = false;
- p.page = $.data(table, 'pagerLastPage') || p.page || 0;
- size = p.$size.find('option[selected]').val();
- p.size = $.data(table, 'pagerLastSize') || parsePageSize( p, size, 'get' );
- p.$size.val( p.size ); // set page size
- p.totalPages = p.size === 'all' ? 1 : Math.ceil( getTotalPages( table, p ) / p.size );
- // if table id exists, include page display with aria info
- if ( table.id ) {
- info = table.id + '_pager_info';
- p.$container.find(p.cssPageDisplay).attr('id', info);
- c.$table.attr('aria-describedby', info);
- }
- changeHeight(table, p);
- if ( triggered ) {
- // tablesorter core update table
- ts.update( c );
- setPageSize(table, p.size, p);
- hideRowsSetup(table, p);
- if (c.debug) {
- console.log('Pager: Enabled');
- }
- }
- };
-
- $this.appender = function(table, rows) {
- var c = table.config,
- p = c.pager;
- if ( !p.ajax ) {
- c.rowsCopy = rows;
- p.totalRows = p.countChildRows ? c.$tbodies.eq(0).children('tr').length : rows.length;
- p.size = $.data(table, 'pagerLastSize') || p.size || p.settings.size || 10;
- p.totalPages = p.size === 'all' ? 1 : Math.ceil( p.totalRows / p.size );
- renderTable(table, rows, p);
- // update display here in case all rows are removed
- updatePageDisplay(table, p, false);
- }
- };
-
- $this.construct = function(settings) {
- return this.each(function() {
- // check if tablesorter has initialized
- if (!(this.config && this.hasInitialized)) { return; }
- var t, ctrls, fxn, size,
- table = this,
- c = table.config,
- wo = c.widgetOptions,
- p = c.pager = $.extend( true, {}, $.tablesorterPager.defaults, settings ),
- $t = c.$table,
- namespace = c.namespace + 'pager',
- // added in case the pager is reinitialized after being destroyed.
- pager = p.$container = $(p.container).addClass('tablesorter-pager').show();
- // save a copy of the original settings
- p.settings = $.extend( true, {}, $.tablesorterPager.defaults, settings );
- if (c.debug) {
- console.log('Pager: Initializing');
- }
- p.oldAjaxSuccess = p.oldAjaxSuccess || p.ajaxObject.success;
- c.appender = $this.appender;
- p.initializing = true;
- if (p.savePages && ts.storage) {
- t = ts.storage(table, p.storageKey) || {}; // fixes #387
- p.page = isNaN(t.page) ? p.page : t.page;
- p.size = t.size === 'all' ? t.size : ( isNaN( t.size ) ? p.size : t.size ) || p.setSize || 10;
- $.data(table, 'pagerLastSize', p.size);
- pager.find(p.cssPageSize).val(p.size);
- }
- // skipped rows
- p.regexRows = new RegExp('(' + (wo.filter_filteredRow || 'filtered') + '|' + c.selectorRemove.slice(1) + '|' + c.cssChildRow + ')');
-
- $t
- // .unbind( namespace ) adding in jQuery 1.4.3 ( I think )
- .unbind( pagerEvents.split(' ').join(namespace + ' ').replace(/\s+/g, ' ') )
- .bind('filterInit filterStart '.split(' ').join(namespace + ' '), function(e, filters) {
- p.currentFilters = $.isArray(filters) ? filters : c.$table.data('lastSearch');
- // don't change page if filters are the same (pager updating, etc)
- if (e.type === 'filterStart' && p.pageReset !== false && (c.lastCombinedFilter || '') !== (p.currentFilters || []).join('')) {
- p.page = p.pageReset; // fixes #456 & #565
- }
- })
- // update pager after filter widget completes
- .bind('filterEnd sortEnd '.split(' ').join(namespace + ' '), function() {
- p.currentFilters = c.$table.data('lastSearch');
- if (p.initialized || p.initializing) {
- if (c.delayInit && c.rowsCopy && c.rowsCopy.length === 0) {
- // make sure we have a copy of all table rows once the cache has been built
- updateCache(table);
- }
- updatePageDisplay(table, p, false);
- moveToPage(table, p, false);
- ts.applyWidget( table );
- }
- })
- .bind('disablePager' + namespace, function(e){
- e.stopPropagation();
- showAllRows(table, p);
- })
- .bind('enablePager' + namespace, function(e){
- e.stopPropagation();
- enablePager(table, p, true);
- })
- .bind('destroyPager' + namespace, function(e){
- e.stopPropagation();
- destroyPager(table, p);
- })
- .bind('updateComplete' + namespace, function(e, table, triggered){
- e.stopPropagation();
- // table can be unintentionally undefined in tablesorter v2.17.7 and earlier
- // don't recalculate total rows/pages if using ajax
- if ( !table || triggered || p.ajax ) { return; }
- var $rows = c.$tbodies.eq(0).children('tr').not(c.selectorRemove);
- p.totalRows = $rows.length - ( p.countChildRows ? 0 : $rows.filter('.' + c.cssChildRow).length );
- p.totalPages = p.size === 'all' ? 1 : Math.ceil( p.totalRows / p.size );
- if ($rows.length && c.rowsCopy && c.rowsCopy.length === 0) {
- // make a copy of all table rows once the cache has been built
- updateCache(table);
- }
- if ( p.page >= p.totalPages ) {
- moveToLastPage(table, p);
- }
- hideRows(table, p);
- changeHeight(table, p);
- updatePageDisplay(table, p, true);
- })
- .bind('pageSize refreshComplete '.split(' ').join(namespace + ' '), function(e, size){
- e.stopPropagation();
- setPageSize(table, parsePageSize( p, size, 'get' ), p);
- hideRows(table, p);
- updatePageDisplay(table, p, false);
- })
- .bind('pageSet pagerUpdate '.split(' ').join(namespace + ' '), function(e, num){
- e.stopPropagation();
- // force pager refresh
- if (e.type === 'pagerUpdate') {
- num = typeof num === 'undefined' ? p.page + 1 : num;
- p.last.page = true;
- }
- p.page = (parseInt(num, 10) || 1) - 1;
- moveToPage(table, p, true);
- updatePageDisplay(table, p, false);
- })
- .bind('pageAndSize' + namespace, function(e, page, size){
- e.stopPropagation();
- p.page = (parseInt(page, 10) || 1) - 1;
- setPageSize(table, parsePageSize( p, size, 'get' ), p);
- moveToPage(table, p, true);
- hideRows(table, p);
- updatePageDisplay(table, p, false);
- });
-
- // clicked controls
- ctrls = [ p.cssFirst, p.cssPrev, p.cssNext, p.cssLast ];
- fxn = [ moveToFirstPage, moveToPrevPage, moveToNextPage, moveToLastPage ];
- if (c.debug && !pager.length) {
- console.warn('Pager: >> Container not found');
- }
- pager.find(ctrls.join(','))
- .attr('tabindex', 0)
- .unbind('click' + namespace)
- .bind('click' + namespace, function(e){
- e.stopPropagation();
- var i, $t = $(this), l = ctrls.length;
- if ( !$t.hasClass(p.cssDisabled) ) {
- for (i = 0; i < l; i++) {
- if ($t.is(ctrls[i])) {
- fxn[i](table, p);
- break;
- }
- }
- }
- });
-
- // goto selector
- p.$goto = pager.find(p.cssGoto);
- if ( p.$goto.length ) {
- p.$goto
- .unbind('change' + namespace)
- .bind('change' + namespace, function(){
- p.page = $(this).val() - 1;
- moveToPage(table, p, true);
- updatePageDisplay(table, p, false);
- });
- } else if (c.debug) {
- console.warn('Pager: >> Goto selector not found');
- }
- // page size selector
- p.$size = pager.find(p.cssPageSize);
- if ( p.$size.length ) {
- // setting an option as selected appears to cause issues with initial page size
- p.$size.find('option').removeAttr('selected');
- p.$size.unbind('change' + namespace).bind('change' + namespace, function() {
- if ( !$(this).hasClass(p.cssDisabled) ) {
- var size = $(this).val();
- p.$size.val( size ); // in case there are more than one pagers
- setPageSize(table, size, p);
- changeHeight(table, p);
- }
- return false;
- });
- } else if (c.debug) {
- console.warn('Pager: >> Size selector not found');
- }
-
- // clear initialized flag
- p.initialized = false;
- // before initialization event
- $t.triggerHandler('pagerBeforeInitialized', p);
-
- enablePager(table, p, false);
- if ( typeof p.ajaxUrl === 'string' ) {
- // ajax pager; interact with database
- p.ajax = true;
- // When filtering with ajax, allow only custom filtering function, disable default
- // filtering since it will be done server side.
- c.widgetOptions.filter_serversideFiltering = true;
- c.serverSideSorting = true;
- moveToPage(table, p);
- } else {
- p.ajax = false;
- // Regular pager; all rows stored in memory
- ts.appendCache( c, true ); // true = don't apply widgets
- hideRowsSetup(table, p);
- }
-
- // pager initialized
- if (!p.ajax && !p.initialized) {
- p.initializing = false;
- p.initialized = true;
- moveToPage(table, p);
- if (c.debug) {
- console.log('Pager: Triggering pagerInitialized');
- }
- c.$table.triggerHandler( 'pagerInitialized', p );
- if ( !( c.widgetOptions.filter_initialized && ts.hasWidget(table, 'filter') ) ) {
- updatePageDisplay(table, p, false);
- }
- }
-
- // make the hasWidget function think that the pager widget is being used
- c.widgetInit.pager = true;
- });
- };
-
- }() });
-
- // see #486
- ts.showError = function( table, xhr, settings, exception ) {
- var $row,
- $table = $( table ),
- c = $table[0].config,
- wo = c && c.widgetOptions,
- errorRow = c.pager && c.pager.cssErrorRow ||
- wo && wo.pager_css && wo.pager_css.errorRow ||
- 'tablesorter-errorRow',
- typ = typeof xhr,
- valid = true,
- message = '',
- removeRow = function(){
- c.$table.find( 'thead' ).find( '.' + errorRow ).remove();
- };
-
- if ( !$table.length ) {
- console.error('tablesorter showError: no table parameter passed');
- return;
- }
-
- // ajaxError callback for plugin or widget - see #992
- if ( typeof c.pager.ajaxError === 'function' ) {
- valid = c.pager.ajaxError( c, xhr, settings, exception );
- if ( valid === false ) {
- return removeRow();
- } else {
- message = valid;
- }
- } else if ( typeof wo.pager_ajaxError === 'function' ) {
- valid = wo.pager_ajaxError( c, xhr, settings, exception );
- if ( valid === false ) {
- return removeRow();
- } else {
- message = valid;
- }
- }
-
- if ( message === '' ) {
- if ( typ === 'object' ) {
- message =
- xhr.status === 0 ? 'Not connected, verify Network' :
- xhr.status === 404 ? 'Requested page not found [404]' :
- xhr.status === 500 ? 'Internal Server Error [500]' :
- exception === 'parsererror' ? 'Requested JSON parse failed' :
- exception === 'timeout' ? 'Time out error' :
- exception === 'abort' ? 'Ajax Request aborted' :
- 'Uncaught error: ' + xhr.statusText + ' [' + xhr.status + ']';
- } else if ( typ === 'string' ) {
- // keep backward compatibility (external usage just passes a message string)
- message = xhr;
- } else {
- // remove all error rows
- return removeRow();
- }
- }
-
- // allow message to include entire row HTML!
- $row = ( /tr\>/.test(message) ? $(message) : $('' + message + ' ') )
- .click( function() {
- $( this ).remove();
- })
- // add error row to thead instead of tbody, or clicking on the header will result in a parser error
- .appendTo( c.$table.find( 'thead:first' ) )
- .addClass( errorRow + ' ' + c.selectorRemove.slice(1) )
- .attr({
- role : 'alert',
- 'aria-live' : 'assertive'
- });
-
- };
-
- // extend plugin scope
- $.fn.extend({
- tablesorterPager: $.tablesorterPager.construct
- });
-
-})(jQuery);
diff --git a/webif/html/lib/jquery.plugin/tablesorter2/jquery.tablesorter.pager.min.js b/webif/html/lib/jquery.plugin/tablesorter2/jquery.tablesorter.pager.min.js
new file mode 100644
index 0000000..676810c
--- /dev/null
+++ b/webif/html/lib/jquery.plugin/tablesorter2/jquery.tablesorter.pager.min.js
@@ -0,0 +1,5 @@
+/*!
+* tablesorter (FORK) pager plugin
+* updated 1/6/2017 (v2.28.4)
+*/
+!function(a){"use strict";var b=a.tablesorter;a.extend({tablesorterPager:new function(){this.defaults={container:null,ajaxUrl:null,customAjaxUrl:function(a,b){return b},ajaxError:null,ajaxObject:{dataType:"json"},processAjaxOnInit:!0,ajaxProcessing:function(a){return[0,[],null]},output:"{startRow} to {endRow} of {totalRows} rows",updateArrows:!0,page:0,pageReset:0,size:10,maxOptionSize:20,savePages:!0,storageKey:"tablesorter-pager",fixedHeight:!1,countChildRows:!1,removeRows:!1,cssFirst:".first",cssPrev:".prev",cssNext:".next",cssLast:".last",cssGoto:".gotoPage",cssPageDisplay:".pagedisplay",cssPageSize:".pagesize",cssErrorRow:"tablesorter-errorRow",cssDisabled:"disabled",totalRows:0,totalPages:0,filteredRows:0,filteredPages:0,ajaxCounter:0,currentFilters:[],startRow:0,endRow:0,$size:null,last:{}};var c="filterInit filterStart filterEnd sortEnd disablePager enablePager destroyPager updateComplete pageSize pageSet pageAndSize pagerUpdate refreshComplete ",d=this,e=function(a,b,c){var d,e="addClass",f="removeClass",g=b.cssDisabled,h=!!c,i=h||0===b.page,j=t(a,b),k=h||b.page===j-1||0===j;b.updateArrows&&(d=b.$container.find(b.cssFirst+","+b.cssPrev),d[i?e:f](g),d.each(function(){this.ariaDisabled=i}),d=b.$container.find(b.cssNext+","+b.cssLast),d[k?e:f](g),d.each(function(){this.ariaDisabled=k}))},f=function(a,c){var d,e,f,g=a.config,h=g.$table.hasClass("hasFilters");if(h&&!c.ajax)if(b.isEmptyObject(g.cache))c.filteredRows=c.totalRows=g.$tbodies.eq(0).children("tr").not(c.countChildRows?"":"."+g.cssChildRow).length;else for(c.filteredRows=0,d=g.cache[0].normalized,f=d.length,e=0;e=0){if(k=w*d.page>d.filteredRows&&g,d.page=k?d.pageReset||0:d.page,d.startRow=k?w*d.page+1:0===d.filteredRows?0:w*d.page+1,d.endRow=Math.min(d.filteredRows,d.totalRows,w*(d.page+1)),l=d.$container.find(d.cssPageDisplay),"function"==typeof d.output?j=d.output(c,d):(q=l.attr("data-pager-output"+(d.filteredRows '):f.length>1&&g&&g[f[0]]?g[f[0]][f[1]]:d[e]||(g?g[e]:h)||h})),m=d.$container.find(d.cssGoto),m.length){for(k="",p=h(c,d),o=p.length,n=0;n'+p[n]+"";m.html(k).val(d.page+1)}l.length&&(l["INPUT"===l[0].nodeName?"val":"html"](j),l.find(".ts-startRow, .ts-page").unbind("change"+s).bind("change"+s,function(){var b=a(this).val(),c=a(this).hasClass("ts-startRow")?Math.floor(b/w)+1:b;r.$table.triggerHandler("pageSet"+s,[c])}))}e(c,d),i(c,d),d.initialized&&g!==!1&&(r.debug&&console.log("Pager: Triggering pagerComplete"),r.$table.triggerHandler("pagerComplete",d),d.savePages&&b.storage&&b.storage(c,d.storageKey,{page:d.page,size:w===d.totalRows?"all":w}))}},h=function(b,c){var d,e,f,g,h,i,j=t(b,c)||1,k=5*Math.ceil(j/c.maxOptionSize/5),l=j>c.maxOptionSize,m=c.page+1,n=k,o=j-k,p=[1],q=l?k:1;for(d=q;d<=j;)p[p.length]=d,d+=l?k:1;if(p[p.length]=j,l){for(f=[],e=Math.max(Math.floor(c.maxOptionSize/k)-1,5),n=m-e,n<1&&(n=1),o=m+e,o>j&&(o=j),d=n;d<=o;d++)f[f.length]=d;p=a.grep(p,function(b,c){return a.inArray(b,p)===c}),h=p.length,i=f.length,h-i>k/2&&h+i>c.maxOptionSize&&(g=Math.floor(h/2)-Math.floor(i/2),Array.prototype.splice.apply(p,[g,i])),p=p.concat(f)}return p=a.grep(p,function(b,c){return a.inArray(b,p)===c}).sort(function(a,b){return a-b})},i=function(b,c){var d,e,f=b.config,g=f.$tbodies.eq(0);g.find("tr.pagerSavedHeightSpacer").remove(),c.fixedHeight&&!c.isDisabled&&(e=a.data(b,"pagerSavedHeight"),e&&(d=e-g.height(),d>5&&a.data(b,"pagerLastSize")===c.size&&g.children("tr:visible").length<("all"===c.size?c.totalRows:c.size)&&g.append('')))},j=function(b,c){var d,e=b.config,f=e.$tbodies.eq(0);f.find("tr.pagerSavedHeightSpacer").remove(),f.children("tr:visible").length||f.append(''),d=f.children("tr").eq(0).height()*("all"===c.size?c.totalRows:c.size),a.data(b,"pagerSavedHeight",d),i(b,c),a.data(b,"pagerLastSize",c.size)},k=function(a,c){if(!c.ajaxUrl){var d,e=0,f=a.config,g=f.$tbodies.eq(0).children("tr"),h=g.length,i="all"===c.size?c.totalRows:c.size,j=c.page*i,k=j+i,l=0,m=0;for(c.cacheIndex=[],d=0;d=j&&m=j&&m0&&g[e].className.match(b.css.cssHasChild))for(;++e> Ajax Error",f,h,i),b.showError(d,f,h,i),z.$tbodies.eq(0).children("tr").detach(),e.totalRows=0;else{if(a.isArray(D)?(l=isNaN(D[0])&&!isNaN(D[1]),w=D[l?1:0],e.totalRows=isNaN(w)?e.totalRows||0:w,z.totalRows=z.filteredRows=e.filteredRows=e.totalRows,t=0===e.totalRows?[]:D[l?0:1]||[],s=D[2]):(e.ajaxData=D,z.totalRows=e.totalRows=D.total,z.filteredRows=e.filteredRows="undefined"!=typeof D.filteredRows?D.filteredRows:D.total,s=D.headers,t=D.rows||[]),v=t&&t.length,t instanceof jQuery)e.processAjaxOnInit&&(z.$tbodies.eq(0).empty(),z.$tbodies.eq(0).append(t));else if(v){for(j=0;j",k=0;k"+t[j][k]+"";C+=" "}e.processAjaxOnInit&&z.$tbodies.eq(0).html(C)}if(e.processAjaxOnInit=!0,s)for(m=A.hasClass("hasStickyHeaders"),o=m?z.widgetOptions.$sticky.children("thead:first").children("tr:not(."+z.cssIgnoreRow+")").children():"",n=A.find("tfoot tr:first").children(),p=z.$headers.filter("th "),x=p.length,k=0;k> No rows for pager to render"));if(e.page>=e.totalPages&&y(c,e),e.cacheIndex=[],e.isDisabled=!1,e.initialized&&(m.debug&&console.log("Pager: Triggering pagerChange"),l.triggerHandler("pagerChange",e)),e.removeRows){for(b.clearTableBody(c),f=b.processTbody(c,m.$tbodies.eq(0),!0),h=n?0:q,i=n?0:q,j=0;jq&&j<=p&&(j++,e.cacheIndex[e.cacheIndex.length]=h,f.append(d[h]))),h++;b.processTbody(c,f,!1)}else k(c,e);g(c,e),c.isUpdating&&(m.debug&&console.log("Pager: Triggering updateComplete"),l.triggerHandler("updateComplete",[c,!0]))},q=function(c,d){var f,g,h;for(d.ajax?e(c,d,!0):(a.data(c,"pagerLastPage",d.page),a.data(c,"pagerLastSize",d.size),d.page=0,d.size="all",d.totalPages=1,a(c).addClass("pagerDisabled").removeAttr("aria-describedby").find("tr.pagerSavedHeightSpacer").remove(),p(c,c.config.rowsCopy,d),d.isDisabled=!0,b.applyWidget(c),c.config.debug&&console.log("Pager: Disabled")),g=d.$container.find(d.cssGoto+","+d.cssPageSize+", .ts-startRow, .ts-page"),h=g.length,f=0;fc&&c>=0&&(b.page=c),b.page},w=function(b,c,d){d.size=u(d,c,"get"),d.$container.find(d.cssPageSize).val(u(d,d.size,"set")),a.data(b,"pagerLastPage",v(b,d)),a.data(b,"pagerLastSize",d.size),d.totalPages="all"===d.size?1:Math.ceil(d.totalRows/d.size),d.filteredPages="all"===d.size?1:Math.ceil(d.filteredRows/d.size),s(b,d)},x=function(a,b){b.page=0,s(a,b)},y=function(a,b){b.page=t(a,b)-1,s(a,b)},z=function(a,b){b.page++;var c=t(a,b)-1;b.page>=c&&(b.page=c),s(a,b)},A=function(a,b){b.page--,b.page<=0&&(b.page=0),s(a,b)},B=function(c,d){d.initialized=!0,d.initializing=!1,c.config.debug&&console.log("Pager: Triggering pagerInitialized"),a(c).triggerHandler("pagerInitialized",d),b.applyWidget(c),g(c,d)},C=function(b,c){var d=b.config;d.pager=a.extend(!0,{},a.tablesorterPager.defaults,c.settings),F(b,c.settings)},D=function(a,c){var d=a.config,e=d.namespace+"pager",f=[c.cssFirst,c.cssPrev,c.cssNext,c.cssLast,c.cssGoto,c.cssPageSize].join(",");q(a,c),c.$container.hide().find(f).unbind(e),d.appender=null,d.$table.unbind(e),b.storage&&b.storage(a,c.storageKey,""),delete d.pager,delete d.rowsCopy},E=function(c,d,e){var f,g,h,i=c.config;d.$container.find(d.cssGoto+","+d.cssPageSize+",.ts-startRow, .ts-page").removeClass(d.cssDisabled).removeAttr("disabled").each(function(){this.ariaDisabled=!1}),d.isDisabled=!1,d.page=a.data(c,"pagerLastPage")||d.page||0,h=d.$container.find(d.cssPageSize),g=h.find("option[selected]").val(),d.size=a.data(c,"pagerLastSize")||u(d,g,"get"),h.val(d.size),d.totalPages="all"===d.size?1:Math.ceil(t(c,d)/d.size),c.id&&!i.$table.attr("aria-describedby")&&(h=d.$container.find(d.cssPageDisplay),f=h.attr("id"),f||(f=c.id+"_pager_info",h.attr("id",f)),i.$table.attr("aria-describedby",f)),j(c,d),e&&(b.update(i),w(c,d.size,d),l(c,d),i.debug&&console.log("Pager: Enabled"))},F=function(e,f){var h,i,m,n,o=e.config,p=o.widgetOptions,t=o.pager=a.extend(!0,{},a.tablesorterPager.defaults,f),v=o.$table,B=o.namespace+"pager",F=t.$container=a(t.container).addClass("tablesorter-pager").show();t.settings=a.extend(!0,{},a.tablesorterPager.defaults,f),o.debug&&console.log("Pager: Initializing"),t.oldAjaxSuccess=t.oldAjaxSuccess||t.ajaxObject.success,o.appender=d.appender,t.initializing=!0,t.savePages&&b.storage&&(h=b.storage(e,t.storageKey)||{},t.page=isNaN(h.page)?t.page:h.page,t.size="all"===h.size?h.size:(isNaN(h.size)?t.size:h.size)||t.setSize||10,a.data(e,"pagerLastSize",t.size),F.find(t.cssPageSize).val(t.size)),t.regexRows=new RegExp("("+(p.filter_filteredRow||"filtered")+"|"+o.selectorRemove.slice(1)+"|"+o.cssChildRow+")"),t.regexFiltered=new RegExp(p.filter_filteredRow||"filtered"),v.unbind(c.split(" ").join(B+" ").replace(/\s+/g," ")).bind("filterInit filterStart ".split(" ").join(B+" "),function(b,c){t.currentFilters=a.isArray(c)?c:o.$table.data("lastSearch"),"filterStart"===b.type&&t.pageReset!==!1&&(o.lastCombinedFilter||"")!==(t.currentFilters||[]).join("")&&(t.page=t.pageReset)}).bind("filterEnd sortEnd ".split(" ").join(B+" "),function(){t.currentFilters=o.$table.data("lastSearch"),(t.initialized||t.initializing)&&(o.delayInit&&o.rowsCopy&&0===o.rowsCopy.length&&r(e),g(e,t,!1),s(e,t,!1),b.applyWidget(e))}).bind("disablePager"+B,function(a){a.stopPropagation(),q(e,t)}).bind("enablePager"+B,function(a){a.stopPropagation(),E(e,t,!0)}).bind("destroyPager"+B,function(a){a.stopPropagation(),D(e,t)}).bind("resetToLoadState"+B,function(a){a.stopPropagation(),C(e,t)}).bind("updateComplete"+B,function(a,b,c){if(a.stopPropagation(),b&&!c&&!t.ajax){var d=o.$tbodies.eq(0).children("tr").not(o.selectorRemove);t.totalRows=d.length-(t.countChildRows?0:d.filter("."+o.cssChildRow).length),t.totalPages="all"===t.size?1:Math.ceil(t.totalRows/t.size),d.length&&o.rowsCopy&&0===o.rowsCopy.length&&r(b),t.page>=t.totalPages&&y(b,t),k(b,t),j(b,t),g(b,t,!0)}}).bind("pageSize refreshComplete ".split(" ").join(B+" "),function(a,b){a.stopPropagation(),w(e,u(t,b,"get"),t),k(e,t),g(e,t,!1)}).bind("pageSet pagerUpdate ".split(" ").join(B+" "),function(a,b){a.stopPropagation(),"pagerUpdate"===a.type&&(b="undefined"==typeof b?t.page+1:b,t.last.page=!0),t.page=(parseInt(b,10)||1)-1,s(e,t,!0),g(e,t,!1)}).bind("pageAndSize"+B,function(a,b,c){a.stopPropagation(),t.page=(parseInt(b,10)||1)-1,w(e,u(t,c,"get"),t),s(e,t,!0),k(e,t),g(e,t,!1)}),i=[t.cssFirst,t.cssPrev,t.cssNext,t.cssLast],m=[x,A,z,y],o.debug&&!F.length&&console.warn("Pager: >> Container not found"),F.find(i.join(",")).attr("tabindex",0).unbind("click"+B).bind("click"+B,function(b){b.stopPropagation();var c,d=a(this),f=i.length;if(!d.hasClass(t.cssDisabled))for(c=0;c> Goto selector not found"),n=F.find(t.cssPageSize),n.length?(n.find("option").removeAttr("selected"),n.unbind("change"+B).bind("change"+B,function(){if(!a(this).hasClass(t.cssDisabled)){var b=a(this).val();t.$container.find(t.cssGoto).val(b),w(e,b,t),j(e,t)}return!1})):o.debug&&console.warn("Pager: >> Size selector not found"),t.initialized=!1,v.triggerHandler("pagerBeforeInitialized",t),E(e,t,!1),"string"==typeof t.ajaxUrl?(t.ajax=!0,o.widgetOptions.filter_serversideFiltering=!0,o.serverSideSorting=!0,s(e,t)):(t.ajax=!1,b.appendCache(o,!0),l(e,t)),t.ajax||t.initialized||(t.initializing=!1,t.initialized=!0,s(e,t),o.debug&&console.log("Pager: Triggering pagerInitialized"),o.$table.triggerHandler("pagerInitialized",t),o.widgetOptions.filter_initialized&&b.hasWidget(e,"filter")||g(e,t,!1)),o.widgetInit.pager=!0};d.appender=function(b,c){var d=b.config,e=d.pager;e.ajax||(d.rowsCopy=c,e.totalRows=e.countChildRows?d.$tbodies.eq(0).children("tr").length:c.length,e.size=a.data(b,"pagerLastSize")||e.size||e.settings.size||10,e.totalPages="all"===e.size?1:Math.ceil(e.totalRows/e.size),p(b,c,e),g(b,e,!1))},d.construct=function(a){return this.each(function(){this.config&&this.hasInitialized&&F(this,a)})}}}),b.showError=function(b,c,d,e){var f,g=a(b),h=g[0].config,i=h&&h.widgetOptions,j=h.pager&&h.pager.cssErrorRow||i&&i.pager_css&&i.pager_css.errorRow||"tablesorter-errorRow",k=typeof c,l=!0,m="",n=function(){h.$table.find("thead").find("."+j).remove()};if(!g.length)return void console.error("tablesorter showError: no table parameter passed");if("function"==typeof h.pager.ajaxError){if(l=h.pager.ajaxError(h,c,d,e),l===!1)return n();m=l}else if("function"==typeof i.pager_ajaxError){if(l=i.pager_ajaxError(h,c,d,e),l===!1)return n();m=l}if(""===m)if("object"===k)m=0===c.status?"Not connected, verify Network":404===c.status?"Requested page not found [404]":500===c.status?"Internal Server Error [500]":"parsererror"===e?"Requested JSON parse failed":"timeout"===e?"Time out error":"abort"===e?"Ajax Request aborted":"Uncaught error: "+c.statusText+" ["+c.status+"]";else{if("string"!==k)return n();m=c}f=a(/tr\>/.test(m)?m:''+m+" ").click(function(){a(this).remove()}).appendTo(h.$table.find("thead:first")).addClass(j+" "+h.selectorRemove.slice(1)).attr({role:"alert","aria-live":"assertive"})},a.fn.extend({tablesorterPager:a.tablesorterPager.construct})}(jQuery);
\ No newline at end of file
diff --git a/webif/html/lib/jquery.plugin/tablesorter2/jquery.tablesorter.widgets.js b/webif/html/lib/jquery.plugin/tablesorter2/jquery.tablesorter.widgets.js
deleted file mode 100644
index 90b0748..0000000
--- a/webif/html/lib/jquery.plugin/tablesorter2/jquery.tablesorter.widgets.js
+++ /dev/null
@@ -1,2968 +0,0 @@
-/*** This file is dynamically generated ***
-█████▄ ▄████▄ █████▄ ▄████▄ ██████ ███████▄ ▄████▄ █████▄ ██ ██████ ██ ██
-██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██▄▄ ██▄▄██
-██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██▀▀ ▀▀▀██
-█████▀ ▀████▀ ██ ██ ▀████▀ ██ ██ ██ ██ ▀████▀ █████▀ ██ ██ █████▀
-*/
-/*! tablesorter (FORK) - updated 05-28-2016 (v2.26.2)*/
-/* Includes widgets ( storage,uitheme,columns,filter,stickyHeaders,resizable,saveSort ) */
-(function(factory) {
- if (typeof define === 'function' && define.amd) {
- define(['jquery'], factory);
- } else if (typeof module === 'object' && typeof module.exports === 'object') {
- module.exports = factory(require('jquery'));
- } else {
- factory(jQuery);
- }
-}(function($) {
-
-/*! Widget: storage - updated 3/1/2016 (v2.25.5) */
-/*global JSON:false */
-;(function ($, window, document) {
- 'use strict';
-
- var ts = $.tablesorter || {};
- // *** Store data in local storage, with a cookie fallback ***
- /* IE7 needs JSON library for JSON.stringify - (http://caniuse.com/#search=json)
- if you need it, then include https://github.com/douglascrockford/JSON-js
-
- $.parseJSON is not available is jQuery versions older than 1.4.1, using older
- versions will only allow storing information for one page at a time
-
- // *** Save data (JSON format only) ***
- // val must be valid JSON... use http://jsonlint.com/ to ensure it is valid
- var val = { "mywidget" : "data1" }; // valid JSON uses double quotes
- // $.tablesorter.storage(table, key, val);
- $.tablesorter.storage(table, 'tablesorter-mywidget', val);
-
- // *** Get data: $.tablesorter.storage(table, key); ***
- v = $.tablesorter.storage(table, 'tablesorter-mywidget');
- // val may be empty, so also check for your data
- val = (v && v.hasOwnProperty('mywidget')) ? v.mywidget : '';
- alert(val); // 'data1' if saved, or '' if not
- */
- ts.storage = function(table, key, value, options) {
- table = $(table)[0];
- var cookieIndex, cookies, date,
- hasStorage = false,
- values = {},
- c = table.config,
- wo = c && c.widgetOptions,
- storageType = ( options && options.useSessionStorage ) || ( wo && wo.storage_useSessionStorage ) ?
- 'sessionStorage' : 'localStorage',
- $table = $(table),
- // id from (1) options ID, (2) table 'data-table-group' attribute, (3) widgetOptions.storage_tableId,
- // (4) table ID, then (5) table index
- id = options && options.id ||
- $table.attr( options && options.group || wo && wo.storage_group || 'data-table-group') ||
- wo && wo.storage_tableId || table.id || $('.tablesorter').index( $table ),
- // url from (1) options url, (2) table 'data-table-page' attribute, (3) widgetOptions.storage_fixedUrl,
- // (4) table.config.fixedUrl (deprecated), then (5) window location path
- url = options && options.url ||
- $table.attr(options && options.page || wo && wo.storage_page || 'data-table-page') ||
- wo && wo.storage_fixedUrl || c && c.fixedUrl || window.location.pathname;
- // https://gist.github.com/paulirish/5558557
- if (storageType in window) {
- try {
- window[storageType].setItem('_tmptest', 'temp');
- hasStorage = true;
- window[storageType].removeItem('_tmptest');
- } catch (error) {
- if (c && c.debug) {
- console.warn( storageType + ' is not supported in this browser' );
- }
- }
- }
- // *** get value ***
- if ($.parseJSON) {
- if (hasStorage) {
- values = $.parseJSON( window[storageType][key] || 'null' ) || {};
- } else {
- // old browser, using cookies
- cookies = document.cookie.split(/[;\s|=]/);
- // add one to get from the key to the value
- cookieIndex = $.inArray(key, cookies) + 1;
- values = (cookieIndex !== 0) ? $.parseJSON(cookies[cookieIndex] || 'null') || {} : {};
- }
- }
- // allow value to be an empty string too
- if (typeof value !== 'undefined' && window.JSON && JSON.hasOwnProperty('stringify')) {
- // add unique identifiers = url pathname > table ID/index on page > data
- if (!values[url]) {
- values[url] = {};
- }
- values[url][id] = value;
- // *** set value ***
- if (hasStorage) {
- window[storageType][key] = JSON.stringify(values);
- } else {
- date = new Date();
- date.setTime(date.getTime() + (31536e+6)); // 365 days
- document.cookie = key + '=' + (JSON.stringify(values)).replace(/\"/g, '\"') + '; expires=' + date.toGMTString() + '; path=/';
- }
- } else {
- return values && values[url] ? values[url][id] : '';
- }
- };
-
-})(jQuery, window, document);
-
-/*! Widget: uitheme - updated 3/26/2015 (v2.21.3) */
-;(function ($) {
- 'use strict';
- var ts = $.tablesorter || {};
-
- ts.themes = {
- 'bootstrap' : {
- table : 'table table-bordered table-striped',
- caption : 'caption',
- // header class names
- header : 'bootstrap-header', // give the header a gradient background (theme.bootstrap_2.css)
- sortNone : '',
- sortAsc : '',
- sortDesc : '',
- active : '', // applied when column is sorted
- hover : '', // custom css required - a defined bootstrap style may not override other classes
- // icon class names
- icons : '', // add 'icon-white' to make them white; this icon class is added to the in the header
- iconSortNone : 'bootstrap-icon-unsorted', // class name added to icon when column is not sorted
- iconSortAsc : 'icon-chevron-up glyphicon glyphicon-chevron-up', // class name added to icon when column has ascending sort
- iconSortDesc : 'icon-chevron-down glyphicon glyphicon-chevron-down', // class name added to icon when column has descending sort
- filterRow : '', // filter row class
- footerRow : '',
- footerCells : '',
- even : '', // even row zebra striping
- odd : '' // odd row zebra striping
- },
- 'jui' : {
- table : 'ui-widget ui-widget-content ui-corner-all', // table classes
- caption : 'ui-widget-content',
- // header class names
- header : 'ui-widget-header ui-corner-all ui-state-default', // header classes
- sortNone : '',
- sortAsc : '',
- sortDesc : '',
- active : 'ui-state-active', // applied when column is sorted
- hover : 'ui-state-hover', // hover class
- // icon class names
- icons : 'ui-icon', // icon class added to the in the header
- iconSortNone : 'ui-icon-carat-2-n-s', // class name added to icon when column is not sorted
- iconSortAsc : 'ui-icon-carat-1-n', // class name added to icon when column has ascending sort
- iconSortDesc : 'ui-icon-carat-1-s', // class name added to icon when column has descending sort
- filterRow : '',
- footerRow : '',
- footerCells : '',
- even : 'ui-widget-content', // even row zebra striping
- odd : 'ui-state-default' // odd row zebra striping
- }
- };
-
- $.extend(ts.css, {
- wrapper : 'tablesorter-wrapper' // ui theme & resizable
- });
-
- ts.addWidget({
- id: 'uitheme',
- priority: 10,
- format: function(table, c, wo) {
- var i, hdr, icon, time, $header, $icon, $tfoot, $h, oldtheme, oldremove, oldIconRmv, hasOldTheme,
- themesAll = ts.themes,
- $table = c.$table.add( $( c.namespace + '_extra_table' ) ),
- $headers = c.$headers.add( $( c.namespace + '_extra_headers' ) ),
- theme = c.theme || 'jui',
- themes = themesAll[theme] || {},
- remove = $.trim( [ themes.sortNone, themes.sortDesc, themes.sortAsc, themes.active ].join( ' ' ) ),
- iconRmv = $.trim( [ themes.iconSortNone, themes.iconSortDesc, themes.iconSortAsc ].join( ' ' ) );
- if (c.debug) { time = new Date(); }
- // initialization code - run once
- if (!$table.hasClass('tablesorter-' + theme) || c.theme !== c.appliedTheme || !wo.uitheme_applied) {
- wo.uitheme_applied = true;
- oldtheme = themesAll[c.appliedTheme] || {};
- hasOldTheme = !$.isEmptyObject(oldtheme);
- oldremove = hasOldTheme ? [ oldtheme.sortNone, oldtheme.sortDesc, oldtheme.sortAsc, oldtheme.active ].join( ' ' ) : '';
- oldIconRmv = hasOldTheme ? [ oldtheme.iconSortNone, oldtheme.iconSortDesc, oldtheme.iconSortAsc ].join( ' ' ) : '';
- if (hasOldTheme) {
- wo.zebra[0] = $.trim( ' ' + wo.zebra[0].replace(' ' + oldtheme.even, '') );
- wo.zebra[1] = $.trim( ' ' + wo.zebra[1].replace(' ' + oldtheme.odd, '') );
- c.$tbodies.children().removeClass( [ oldtheme.even, oldtheme.odd ].join(' ') );
- }
- // update zebra stripes
- if (themes.even) { wo.zebra[0] += ' ' + themes.even; }
- if (themes.odd) { wo.zebra[1] += ' ' + themes.odd; }
- // add caption style
- $table.children('caption')
- .removeClass(oldtheme.caption || '')
- .addClass(themes.caption);
- // add table/footer class names
- $tfoot = $table
- // remove other selected themes
- .removeClass( (c.appliedTheme ? 'tablesorter-' + (c.appliedTheme || '') : '') + ' ' + (oldtheme.table || '') )
- .addClass('tablesorter-' + theme + ' ' + (themes.table || '')) // add theme widget class name
- .children('tfoot');
- c.appliedTheme = c.theme;
-
- if ($tfoot.length) {
- $tfoot
- // if oldtheme.footerRow or oldtheme.footerCells are undefined, all class names are removed
- .children('tr').removeClass(oldtheme.footerRow || '').addClass(themes.footerRow)
- .children('th, td').removeClass(oldtheme.footerCells || '').addClass(themes.footerCells);
- }
- // update header classes
- $headers
- .removeClass( (hasOldTheme ? [ oldtheme.header, oldtheme.hover, oldremove ].join(' ') : '') || '' )
- .addClass(themes.header)
- .not('.sorter-false')
- .unbind('mouseenter.tsuitheme mouseleave.tsuitheme')
- .bind('mouseenter.tsuitheme mouseleave.tsuitheme', function(event) {
- // toggleClass with switch added in jQuery 1.3
- $(this)[ event.type === 'mouseenter' ? 'addClass' : 'removeClass' ](themes.hover || '');
- });
-
- $headers.each(function(){
- var $this = $(this);
- if (!$this.find('.' + ts.css.wrapper).length) {
- // Firefox needs this inner div to position the icon & resizer correctly
- $this.wrapInner('
');
- }
- });
- if (c.cssIcon) {
- // if c.cssIcon is '', then no is added to the header
- $headers
- .find('.' + ts.css.icon)
- .removeClass(hasOldTheme ? [ oldtheme.icons, oldIconRmv ].join(' ') : '')
- .addClass(themes.icons || '');
- }
- if ($table.hasClass('hasFilters')) {
- $table.children('thead').children('.' + ts.css.filterRow)
- .removeClass(hasOldTheme ? oldtheme.filterRow || '' : '')
- .addClass(themes.filterRow || '');
- }
- }
- for (i = 0; i < c.columns; i++) {
- $header = c.$headers
- .add($(c.namespace + '_extra_headers'))
- .not('.sorter-false')
- .filter('[data-column="' + i + '"]');
- $icon = (ts.css.icon) ? $header.find('.' + ts.css.icon) : $();
- $h = $headers.not('.sorter-false').filter('[data-column="' + i + '"]:last');
- if ($h.length) {
- $header.removeClass(remove);
- $icon.removeClass(iconRmv);
- if ($h[0].sortDisabled) {
- // no sort arrows for disabled columns!
- $icon.removeClass(themes.icons || '');
- } else {
- hdr = themes.sortNone;
- icon = themes.iconSortNone;
- if ($h.hasClass(ts.css.sortAsc)) {
- hdr = [ themes.sortAsc, themes.active ].join(' ');
- icon = themes.iconSortAsc;
- } else if ($h.hasClass(ts.css.sortDesc)) {
- hdr = [ themes.sortDesc, themes.active ].join(' ');
- icon = themes.iconSortDesc;
- }
- $header.addClass(hdr);
- $icon.addClass(icon || '');
- }
- }
- }
- if (c.debug) {
- console.log('Applying ' + theme + ' theme' + ts.benchmark(time));
- }
- },
- remove: function(table, c, wo, refreshing) {
- if (!wo.uitheme_applied) { return; }
- var $table = c.$table,
- theme = c.appliedTheme || 'jui',
- themes = ts.themes[ theme ] || ts.themes.jui,
- $headers = $table.children('thead').children(),
- remove = themes.sortNone + ' ' + themes.sortDesc + ' ' + themes.sortAsc,
- iconRmv = themes.iconSortNone + ' ' + themes.iconSortDesc + ' ' + themes.iconSortAsc;
- $table.removeClass('tablesorter-' + theme + ' ' + themes.table);
- wo.uitheme_applied = false;
- if (refreshing) { return; }
- $table.find(ts.css.header).removeClass(themes.header);
- $headers
- .unbind('mouseenter.tsuitheme mouseleave.tsuitheme') // remove hover
- .removeClass(themes.hover + ' ' + remove + ' ' + themes.active)
- .filter('.' + ts.css.filterRow)
- .removeClass(themes.filterRow);
- $headers.find('.' + ts.css.icon).removeClass(themes.icons + ' ' + iconRmv);
- }
- });
-
-})(jQuery);
-
-/*! Widget: columns */
-;(function ($) {
- 'use strict';
- var ts = $.tablesorter || {};
-
- ts.addWidget({
- id: 'columns',
- priority: 30,
- options : {
- columns : [ 'primary', 'secondary', 'tertiary' ]
- },
- format: function(table, c, wo) {
- var $tbody, tbodyIndex, $rows, rows, $row, $cells, remove, indx,
- $table = c.$table,
- $tbodies = c.$tbodies,
- sortList = c.sortList,
- len = sortList.length,
- // removed c.widgetColumns support
- css = wo && wo.columns || [ 'primary', 'secondary', 'tertiary' ],
- last = css.length - 1;
- remove = css.join(' ');
- // check if there is a sort (on initialization there may not be one)
- for (tbodyIndex = 0; tbodyIndex < $tbodies.length; tbodyIndex++ ) {
- $tbody = ts.processTbody(table, $tbodies.eq(tbodyIndex), true); // detach tbody
- $rows = $tbody.children('tr');
- // loop through the visible rows
- $rows.each(function() {
- $row = $(this);
- if (this.style.display !== 'none') {
- // remove all columns class names
- $cells = $row.children().removeClass(remove);
- // add appropriate column class names
- if (sortList && sortList[0]) {
- // primary sort column class
- $cells.eq(sortList[0][0]).addClass(css[0]);
- if (len > 1) {
- for (indx = 1; indx < len; indx++) {
- // secondary, tertiary, etc sort column classes
- $cells.eq(sortList[indx][0]).addClass( css[indx] || css[last] );
- }
- }
- }
- }
- });
- ts.processTbody(table, $tbody, false);
- }
- // add classes to thead and tfoot
- rows = wo.columns_thead !== false ? [ 'thead tr' ] : [];
- if (wo.columns_tfoot !== false) {
- rows.push('tfoot tr');
- }
- if (rows.length) {
- $rows = $table.find( rows.join(',') ).children().removeClass(remove);
- if (len) {
- for (indx = 0; indx < len; indx++) {
- // add primary. secondary, tertiary, etc sort column classes
- $rows.filter('[data-column="' + sortList[indx][0] + '"]').addClass(css[indx] || css[last]);
- }
- }
- }
- },
- remove: function(table, c, wo) {
- var tbodyIndex, $tbody,
- $tbodies = c.$tbodies,
- remove = (wo.columns || [ 'primary', 'secondary', 'tertiary' ]).join(' ');
- c.$headers.removeClass(remove);
- c.$table.children('tfoot').children('tr').children('th, td').removeClass(remove);
- for (tbodyIndex = 0; tbodyIndex < $tbodies.length; tbodyIndex++ ) {
- $tbody = ts.processTbody(table, $tbodies.eq(tbodyIndex), true); // remove tbody
- $tbody.children('tr').each(function() {
- $(this).children().removeClass(remove);
- });
- ts.processTbody(table, $tbody, false); // restore tbody
- }
- }
- });
-
-})(jQuery);
-
-/*! Widget: filter - updated 5/28/2016 (v2.26.2) *//*
- * Requires tablesorter v2.8+ and jQuery 1.7+
- * by Rob Garrison
- */
-;( function ( $ ) {
- 'use strict';
- var tsf, tsfRegex,
- ts = $.tablesorter || {},
- tscss = ts.css,
- tskeyCodes = ts.keyCodes;
-
- $.extend( tscss, {
- filterRow : 'tablesorter-filter-row',
- filter : 'tablesorter-filter',
- filterDisabled : 'disabled',
- filterRowHide : 'hideme'
- });
-
- $.extend( tskeyCodes, {
- backSpace : 8,
- escape : 27,
- space : 32,
- left : 37,
- down : 40
- });
-
- ts.addWidget({
- id: 'filter',
- priority: 50,
- options : {
- filter_cellFilter : '', // css class name added to the filter cell ( string or array )
- filter_childRows : false, // if true, filter includes child row content in the search
- filter_childByColumn : false, // ( filter_childRows must be true ) if true = search child rows by column; false = search all child row text grouped
- filter_childWithSibs : true, // if true, include matching child row siblings
- filter_columnAnyMatch: true, // if true, allows using '#:{query}' in AnyMatch searches ( column:query )
- filter_columnFilters : true, // if true, a filter will be added to the top of each table column
- filter_cssFilter : '', // css class name added to the filter row & each input in the row ( tablesorter-filter is ALWAYS added )
- filter_defaultAttrib : 'data-value', // data attribute in the header cell that contains the default filter value
- filter_defaultFilter : {}, // add a default column filter type '~{query}' to make fuzzy searches default; '{q1} AND {q2}' to make all searches use a logical AND.
- filter_excludeFilter : {}, // filters to exclude, per column
- filter_external : '', // jQuery selector string ( or jQuery object ) of external filters
- filter_filteredRow : 'filtered', // class added to filtered rows; define in css with "display:none" to hide the filtered-out rows
- filter_formatter : null, // add custom filter elements to the filter row
- filter_functions : null, // add custom filter functions using this option
- filter_hideEmpty : true, // hide filter row when table is empty
- filter_hideFilters : false, // collapse filter row when mouse leaves the area
- filter_ignoreCase : true, // if true, make all searches case-insensitive
- filter_liveSearch : true, // if true, search column content while the user types ( with a delay )
- filter_matchType : { 'input': 'exact', 'select': 'exact' }, // global query settings ('exact' or 'match'); overridden by "filter-match" or "filter-exact" class
- filter_onlyAvail : 'filter-onlyAvail', // a header with a select dropdown & this class name will only show available ( visible ) options within the drop down
- filter_placeholder : { search : '', select : '' }, // default placeholder text ( overridden by any header 'data-placeholder' setting )
- filter_reset : null, // jQuery selector string of an element used to reset the filters
- filter_resetOnEsc : true, // Reset filter input when the user presses escape - normalized across browsers
- filter_saveFilters : false, // Use the $.tablesorter.storage utility to save the most recent filters
- filter_searchDelay : 300, // typing delay in milliseconds before starting a search
- filter_searchFiltered: true, // allow searching through already filtered rows in special circumstances; will speed up searching in large tables if true
- filter_selectSource : null, // include a function to return an array of values to be added to the column filter select
- filter_selectSourceSeparator : '|', // filter_selectSource array text left of the separator is added to the option value, right into the option text
- filter_serversideFiltering : false, // if true, must perform server-side filtering b/c client-side filtering is disabled, but the ui and events will still be used.
- filter_startsWith : false, // if true, filter start from the beginning of the cell contents
- filter_useParsedData : false // filter all data using parsed content
- },
- format: function( table, c, wo ) {
- if ( !c.$table.hasClass( 'hasFilters' ) ) {
- tsf.init( table, c, wo );
- }
- },
- remove: function( table, c, wo, refreshing ) {
- var tbodyIndex, $tbody,
- $table = c.$table,
- $tbodies = c.$tbodies,
- events = 'addRows updateCell update updateRows updateComplete appendCache filterReset filterEnd search '
- .split( ' ' ).join( c.namespace + 'filter ' );
- $table
- .removeClass( 'hasFilters' )
- // add filter namespace to all BUT search
- .unbind( events.replace( ts.regex.spaces, ' ' ) )
- // remove the filter row even if refreshing, because the column might have been moved
- .find( '.' + tscss.filterRow ).remove();
- wo.filter_initialized = false;
- if ( refreshing ) { return; }
- for ( tbodyIndex = 0; tbodyIndex < $tbodies.length; tbodyIndex++ ) {
- $tbody = ts.processTbody( table, $tbodies.eq( tbodyIndex ), true ); // remove tbody
- $tbody.children().removeClass( wo.filter_filteredRow ).show();
- ts.processTbody( table, $tbody, false ); // restore tbody
- }
- if ( wo.filter_reset ) {
- $( document ).undelegate( wo.filter_reset, 'click' + c.namespace + 'filter' );
- }
- }
- });
-
- tsf = ts.filter = {
-
- // regex used in filter 'check' functions - not for general use and not documented
- regex: {
- regex : /^\/((?:\\\/|[^\/])+)\/([mig]{0,3})?$/, // regex to test for regex
- child : /tablesorter-childRow/, // child row class name; this gets updated in the script
- filtered : /filtered/, // filtered (hidden) row class name; updated in the script
- type : /undefined|number/, // check type
- exact : /(^[\"\'=]+)|([\"\'=]+$)/g, // exact match (allow '==')
- operators : /[<>=]/g, // replace operators
- query : '(q|query)', // replace filter queries
- wild01 : /\?/g, // wild card match 0 or 1
- wild0More : /\*/g, // wild care match 0 or more
- quote : /\"/g,
- isNeg1 : /(>=?\s*-\d)/,
- isNeg2 : /(<=?\s*\d)/
- },
- // function( c, data ) { }
- // c = table.config
- // data.$row = jQuery object of the row currently being processed
- // data.$cells = jQuery object of all cells within the current row
- // data.filters = array of filters for all columns ( some may be undefined )
- // data.filter = filter for the current column
- // data.iFilter = same as data.filter, except lowercase ( if wo.filter_ignoreCase is true )
- // data.exact = table cell text ( or parsed data if column parser enabled; may be a number & not a string )
- // data.iExact = same as data.exact, except lowercase ( if wo.filter_ignoreCase is true; may be a number & not a string )
- // data.cache = table cell text from cache, so it has been parsed ( & in all lower case if c.ignoreCase is true )
- // data.cacheArray = An array of parsed content from each table cell in the row being processed
- // data.index = column index; table = table element ( DOM )
- // data.parsed = array ( by column ) of boolean values ( from filter_useParsedData or 'filter-parsed' class )
- types: {
- or : function( c, data, vars ) {
- // look for "|", but not if it is inside of a regular expression
- if ( ( tsfRegex.orTest.test( data.iFilter ) || tsfRegex.orSplit.test( data.filter ) ) &&
- // this test for regex has potential to slow down the overall search
- !tsfRegex.regex.test( data.filter ) ) {
- var indx, filterMatched, query, regex,
- // duplicate data but split filter
- data2 = $.extend( {}, data ),
- filter = data.filter.split( tsfRegex.orSplit ),
- iFilter = data.iFilter.split( tsfRegex.orSplit ),
- len = filter.length;
- for ( indx = 0; indx < len; indx++ ) {
- data2.nestedFilters = true;
- data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], data ) || '' );
- data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], data ) || '' );
- query = '(' + ( tsf.parseFilter( c, data2.filter, data ) || '' ) + ')';
- try {
- // use try/catch, because query may not be a valid regex if "|" is contained within a partial regex search,
- // e.g "/(Alex|Aar" -> Uncaught SyntaxError: Invalid regular expression: /(/(Alex)/: Unterminated group
- regex = new RegExp( data.isMatch ? query : '^' + query + '$', c.widgetOptions.filter_ignoreCase ? 'i' : '' );
- // filterMatched = data2.filter === '' && indx > 0 ? true
- // look for an exact match with the 'or' unless the 'filter-match' class is found
- filterMatched = regex.test( data2.exact ) || tsf.processTypes( c, data2, vars );
- if ( filterMatched ) {
- return filterMatched;
- }
- } catch ( error ) {
- return null;
- }
- }
- // may be null from processing types
- return filterMatched || false;
- }
- return null;
- },
- // Look for an AND or && operator ( logical and )
- and : function( c, data, vars ) {
- if ( tsfRegex.andTest.test( data.filter ) ) {
- var indx, filterMatched, result, query, regex,
- // duplicate data but split filter
- data2 = $.extend( {}, data ),
- filter = data.filter.split( tsfRegex.andSplit ),
- iFilter = data.iFilter.split( tsfRegex.andSplit ),
- len = filter.length;
- for ( indx = 0; indx < len; indx++ ) {
- data2.nestedFilters = true;
- data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], data ) || '' );
- data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], data ) || '' );
- query = ( '(' + ( tsf.parseFilter( c, data2.filter, data ) || '' ) + ')' )
- // replace wild cards since /(a*)/i will match anything
- .replace( tsfRegex.wild01, '\\S{1}' ).replace( tsfRegex.wild0More, '\\S*' );
- try {
- // use try/catch just in case RegExp is invalid
- regex = new RegExp( data.isMatch ? query : '^' + query + '$', c.widgetOptions.filter_ignoreCase ? 'i' : '' );
- // look for an exact match with the 'and' unless the 'filter-match' class is found
- result = ( regex.test( data2.exact ) || tsf.processTypes( c, data2, vars ) );
- if ( indx === 0 ) {
- filterMatched = result;
- } else {
- filterMatched = filterMatched && result;
- }
- } catch ( error ) {
- return null;
- }
- }
- // may be null from processing types
- return filterMatched || false;
- }
- return null;
- },
- // Look for regex
- regex: function( c, data ) {
- if ( tsfRegex.regex.test( data.filter ) ) {
- var matches,
- // cache regex per column for optimal speed
- regex = data.filter_regexCache[ data.index ] || tsfRegex.regex.exec( data.filter ),
- isRegex = regex instanceof RegExp;
- try {
- if ( !isRegex ) {
- // force case insensitive search if ignoreCase option set?
- // if ( c.ignoreCase && !regex[2] ) { regex[2] = 'i'; }
- data.filter_regexCache[ data.index ] = regex = new RegExp( regex[1], regex[2] );
- }
- matches = regex.test( data.exact );
- } catch ( error ) {
- matches = false;
- }
- return matches;
- }
- return null;
- },
- // Look for operators >, >=, < or <=
- operators: function( c, data ) {
- // ignore empty strings... because '' < 10 is true
- if ( tsfRegex.operTest.test( data.iFilter ) && data.iExact !== '' ) {
- var cachedValue, result, txt,
- table = c.table,
- parsed = data.parsed[ data.index ],
- query = ts.formatFloat( data.iFilter.replace( tsfRegex.operators, '' ), table ),
- parser = c.parsers[ data.index ] || {},
- savedSearch = query;
- // parse filter value in case we're comparing numbers ( dates )
- if ( parsed || parser.type === 'numeric' ) {
- txt = $.trim( '' + data.iFilter.replace( tsfRegex.operators, '' ) );
- result = tsf.parseFilter( c, txt, data, true );
- query = ( typeof result === 'number' && result !== '' && !isNaN( result ) ) ? result : query;
- }
- // iExact may be numeric - see issue #149;
- // check if cached is defined, because sometimes j goes out of range? ( numeric columns )
- if ( ( parsed || parser.type === 'numeric' ) && !isNaN( query ) &&
- typeof data.cache !== 'undefined' ) {
- cachedValue = data.cache;
- } else {
- txt = isNaN( data.iExact ) ? data.iExact.replace( ts.regex.nondigit, '' ) : data.iExact;
- cachedValue = ts.formatFloat( txt, table );
- }
- if ( tsfRegex.gtTest.test( data.iFilter ) ) {
- result = tsfRegex.gteTest.test( data.iFilter ) ? cachedValue >= query : cachedValue > query;
- } else if ( tsfRegex.ltTest.test( data.iFilter ) ) {
- result = tsfRegex.lteTest.test( data.iFilter ) ? cachedValue <= query : cachedValue < query;
- }
- // keep showing all rows if nothing follows the operator
- if ( !result && savedSearch === '' ) {
- result = true;
- }
- return result;
- }
- return null;
- },
- // Look for a not match
- notMatch: function( c, data ) {
- if ( tsfRegex.notTest.test( data.iFilter ) ) {
- var indx,
- txt = data.iFilter.replace( '!', '' ),
- filter = tsf.parseFilter( c, txt, data ) || '';
- if ( tsfRegex.exact.test( filter ) ) {
- // look for exact not matches - see #628
- filter = filter.replace( tsfRegex.exact, '' );
- return filter === '' ? true : $.trim( filter ) !== data.iExact;
- } else {
- indx = data.iExact.search( $.trim( filter ) );
- return filter === '' ? true :
- // return true if not found
- data.anyMatch ? indx < 0 :
- // return false if found
- !( c.widgetOptions.filter_startsWith ? indx === 0 : indx >= 0 );
- }
- }
- return null;
- },
- // Look for quotes or equals to get an exact match; ignore type since iExact could be numeric
- exact: function( c, data ) {
- /*jshint eqeqeq:false */
- if ( tsfRegex.exact.test( data.iFilter ) ) {
- var txt = data.iFilter.replace( tsfRegex.exact, '' ),
- filter = tsf.parseFilter( c, txt, data ) || '';
- return data.anyMatch ? $.inArray( filter, data.rowArray ) >= 0 : filter == data.iExact;
- }
- return null;
- },
- // Look for a range ( using ' to ' or ' - ' ) - see issue #166; thanks matzhu!
- range : function( c, data ) {
- if ( tsfRegex.toTest.test( data.iFilter ) ) {
- var result, tmp, range1, range2,
- table = c.table,
- index = data.index,
- parsed = data.parsed[index],
- // make sure the dash is for a range and not indicating a negative number
- query = data.iFilter.split( tsfRegex.toSplit );
-
- tmp = query[0].replace( ts.regex.nondigit, '' ) || '';
- range1 = ts.formatFloat( tsf.parseFilter( c, tmp, data ), table );
- tmp = query[1].replace( ts.regex.nondigit, '' ) || '';
- range2 = ts.formatFloat( tsf.parseFilter( c, tmp, data ), table );
- // parse filter value in case we're comparing numbers ( dates )
- if ( parsed || c.parsers[ index ].type === 'numeric' ) {
- result = c.parsers[ index ].format( '' + query[0], table, c.$headers.eq( index ), index );
- range1 = ( result !== '' && !isNaN( result ) ) ? result : range1;
- result = c.parsers[ index ].format( '' + query[1], table, c.$headers.eq( index ), index );
- range2 = ( result !== '' && !isNaN( result ) ) ? result : range2;
- }
- if ( ( parsed || c.parsers[ index ].type === 'numeric' ) && !isNaN( range1 ) && !isNaN( range2 ) ) {
- result = data.cache;
- } else {
- tmp = isNaN( data.iExact ) ? data.iExact.replace( ts.regex.nondigit, '' ) : data.iExact;
- result = ts.formatFloat( tmp, table );
- }
- if ( range1 > range2 ) {
- tmp = range1; range1 = range2; range2 = tmp; // swap
- }
- return ( result >= range1 && result <= range2 ) || ( range1 === '' || range2 === '' );
- }
- return null;
- },
- // Look for wild card: ? = single, * = multiple, or | = logical OR
- wild : function( c, data ) {
- if ( tsfRegex.wildOrTest.test( data.iFilter ) ) {
- var query = '' + ( tsf.parseFilter( c, data.iFilter, data ) || '' );
- // look for an exact match with the 'or' unless the 'filter-match' class is found
- if ( !tsfRegex.wildTest.test( query ) && data.nestedFilters ) {
- query = data.isMatch ? query : '^(' + query + ')$';
- }
- // parsing the filter may not work properly when using wildcards =/
- try {
- return new RegExp(
- query.replace( tsfRegex.wild01, '\\S{1}' ).replace( tsfRegex.wild0More, '\\S*' ),
- c.widgetOptions.filter_ignoreCase ? 'i' : ''
- )
- .test( data.exact );
- } catch ( error ) {
- return null;
- }
- }
- return null;
- },
- // fuzzy text search; modified from https://github.com/mattyork/fuzzy ( MIT license )
- fuzzy: function( c, data ) {
- if ( tsfRegex.fuzzyTest.test( data.iFilter ) ) {
- var indx,
- patternIndx = 0,
- len = data.iExact.length,
- txt = data.iFilter.slice( 1 ),
- pattern = tsf.parseFilter( c, txt, data ) || '';
- for ( indx = 0; indx < len; indx++ ) {
- if ( data.iExact[ indx ] === pattern[ patternIndx ] ) {
- patternIndx += 1;
- }
- }
- return patternIndx === pattern.length;
- }
- return null;
- }
- },
- init: function( table ) {
- // filter language options
- ts.language = $.extend( true, {}, {
- to : 'to',
- or : 'or',
- and : 'and'
- }, ts.language );
-
- var options, string, txt, $header, column, val, fxn, noSelect,
- c = table.config,
- wo = c.widgetOptions;
- c.$table.addClass( 'hasFilters' );
- c.lastSearch = [];
-
- // define timers so using clearTimeout won't cause an undefined error
- wo.filter_searchTimer = null;
- wo.filter_initTimer = null;
- wo.filter_formatterCount = 0;
- wo.filter_formatterInit = [];
- wo.filter_anyColumnSelector = '[data-column="all"],[data-column="any"]';
- wo.filter_multipleColumnSelector = '[data-column*="-"],[data-column*=","]';
-
- val = '\\{' + tsfRegex.query + '\\}';
- $.extend( tsfRegex, {
- child : new RegExp( c.cssChildRow ),
- filtered : new RegExp( wo.filter_filteredRow ),
- alreadyFiltered : new RegExp( '(\\s+(' + ts.language.or + '|-|' + ts.language.to + ')\\s+)', 'i' ),
- toTest : new RegExp( '\\s+(-|' + ts.language.to + ')\\s+', 'i' ),
- toSplit : new RegExp( '(?:\\s+(?:-|' + ts.language.to + ')\\s+)', 'gi' ),
- andTest : new RegExp( '\\s+(' + ts.language.and + '|&&)\\s+', 'i' ),
- andSplit : new RegExp( '(?:\\s+(?:' + ts.language.and + '|&&)\\s+)', 'gi' ),
- orTest : new RegExp( '(\\||\\s+' + ts.language.or + '\\s+)', 'i' ),
- orSplit : new RegExp( '(?:\\s+(?:' + ts.language.or + ')\\s+|\\|)', 'gi' ),
- iQuery : new RegExp( val, 'i' ),
- igQuery : new RegExp( val, 'ig' ),
- operTest : /^[<>]=?/,
- gtTest : />/,
- gteTest : />=/,
- ltTest : /,
- lteTest : /<=/,
- notTest : /^\!/,
- wildOrTest : /[\?\*\|]/,
- wildTest : /\?\*/,
- fuzzyTest : /^~/,
- exactTest : /[=\"\|!]/
- });
-
- // don't build filter row if columnFilters is false or all columns are set to 'filter-false'
- // see issue #156
- val = c.$headers.filter( '.filter-false, .parser-false' ).length;
- if ( wo.filter_columnFilters !== false && val !== c.$headers.length ) {
- // build filter row
- tsf.buildRow( table, c, wo );
- }
-
- txt = 'addRows updateCell update updateRows updateComplete appendCache filterReset ' +
- 'filterResetSaved filterEnd search '.split( ' ' ).join( c.namespace + 'filter ' );
- c.$table.bind( txt, function( event, filter ) {
- val = wo.filter_hideEmpty &&
- $.isEmptyObject( c.cache ) &&
- !( c.delayInit && event.type === 'appendCache' );
- // hide filter row using the 'filtered' class name
- c.$table.find( '.' + tscss.filterRow ).toggleClass( wo.filter_filteredRow, val ); // fixes #450
- if ( !/(search|filter)/.test( event.type ) ) {
- event.stopPropagation();
- tsf.buildDefault( table, true );
- }
- if ( event.type === 'filterReset' ) {
- c.$table.find( '.' + tscss.filter ).add( wo.filter_$externalFilters ).val( '' );
- tsf.searching( table, [] );
- } else if ( event.type === 'filterResetSaved' ) {
- ts.storage( table, 'tablesorter-filters', '' );
- } else if ( event.type === 'filterEnd' ) {
- tsf.buildDefault( table, true );
- } else {
- // send false argument to force a new search; otherwise if the filter hasn't changed,
- // it will return
- filter = event.type === 'search' ? filter :
- event.type === 'updateComplete' ? c.$table.data( 'lastSearch' ) : '';
- if ( /(update|add)/.test( event.type ) && event.type !== 'updateComplete' ) {
- // force a new search since content has changed
- c.lastCombinedFilter = null;
- c.lastSearch = [];
- }
- // pass true ( skipFirst ) to prevent the tablesorter.setFilters function from skipping the first
- // input ensures all inputs are updated when a search is triggered on the table
- // $( 'table' ).trigger( 'search', [...] );
- tsf.searching( table, filter, true );
- }
- return false;
- });
-
- // reset button/link
- if ( wo.filter_reset ) {
- if ( wo.filter_reset instanceof $ ) {
- // reset contains a jQuery object, bind to it
- wo.filter_reset.click( function() {
- c.$table.triggerHandler( 'filterReset' );
- });
- } else if ( $( wo.filter_reset ).length ) {
- // reset is a jQuery selector, use event delegation
- $( document )
- .undelegate( wo.filter_reset, 'click' + c.namespace + 'filter' )
- .delegate( wo.filter_reset, 'click' + c.namespace + 'filter', function() {
- // trigger a reset event, so other functions ( filter_formatter ) know when to reset
- c.$table.triggerHandler( 'filterReset' );
- });
- }
- }
- if ( wo.filter_functions ) {
- for ( column = 0; column < c.columns; column++ ) {
- fxn = ts.getColumnData( table, wo.filter_functions, column );
- if ( fxn ) {
- // remove 'filter-select' from header otherwise the options added here are replaced with
- // all options
- $header = c.$headerIndexed[ column ].removeClass( 'filter-select' );
- // don't build select if 'filter-false' or 'parser-false' set
- noSelect = !( $header.hasClass( 'filter-false' ) || $header.hasClass( 'parser-false' ) );
- options = '';
- if ( fxn === true && noSelect ) {
- tsf.buildSelect( table, column );
- } else if ( typeof fxn === 'object' && noSelect ) {
- // add custom drop down list
- for ( string in fxn ) {
- if ( typeof string === 'string' ) {
- options += options === '' ?
- '' +
- ( $header.data( 'placeholder' ) ||
- $header.attr( 'data-placeholder' ) ||
- wo.filter_placeholder.select ||
- ''
- ) +
- ' ' : '';
- val = string;
- txt = string;
- if ( string.indexOf( wo.filter_selectSourceSeparator ) >= 0 ) {
- val = string.split( wo.filter_selectSourceSeparator );
- txt = val[1];
- val = val[0];
- }
- options += '' + txt + ' ';
- }
- }
- c.$table
- .find( 'thead' )
- .find( 'select.' + tscss.filter + '[data-column="' + column + '"]' )
- .append( options );
- txt = wo.filter_selectSource;
- fxn = typeof txt === 'function' ? true : ts.getColumnData( table, txt, column );
- if ( fxn ) {
- // updating so the extra options are appended
- tsf.buildSelect( c.table, column, '', true, $header.hasClass( wo.filter_onlyAvail ) );
- }
- }
- }
- }
- }
- // not really updating, but if the column has both the 'filter-select' class &
- // filter_functions set to true, it would append the same options twice.
- tsf.buildDefault( table, true );
-
- tsf.bindSearch( table, c.$table.find( '.' + tscss.filter ), true );
- if ( wo.filter_external ) {
- tsf.bindSearch( table, wo.filter_external );
- }
-
- if ( wo.filter_hideFilters ) {
- tsf.hideFilters( c );
- }
-
- // show processing icon
- if ( c.showProcessing ) {
- txt = 'filterStart filterEnd '.split( ' ' ).join( c.namespace + 'filter ' );
- c.$table
- .unbind( txt.replace( ts.regex.spaces, ' ' ) )
- .bind( txt, function( event, columns ) {
- // only add processing to certain columns to all columns
- $header = ( columns ) ?
- c.$table
- .find( '.' + tscss.header )
- .filter( '[data-column]' )
- .filter( function() {
- return columns[ $( this ).data( 'column' ) ] !== '';
- }) : '';
- ts.isProcessing( table, event.type === 'filterStart', columns ? $header : '' );
- });
- }
-
- // set filtered rows count ( intially unfiltered )
- c.filteredRows = c.totalRows;
-
- // add default values
- txt = 'tablesorter-initialized pagerBeforeInitialized '.split( ' ' ).join( c.namespace + 'filter ' );
- c.$table
- .unbind( txt.replace( ts.regex.spaces, ' ' ) )
- .bind( txt, function() {
- tsf.completeInit( this );
- });
- // if filter widget is added after pager has initialized; then set filter init flag
- if ( c.pager && c.pager.initialized && !wo.filter_initialized ) {
- c.$table.triggerHandler( 'filterFomatterUpdate' );
- setTimeout( function() {
- tsf.filterInitComplete( c );
- }, 100 );
- } else if ( !wo.filter_initialized ) {
- tsf.completeInit( table );
- }
- },
- completeInit: function( table ) {
- // redefine 'c' & 'wo' so they update properly inside this callback
- var c = table.config,
- wo = c.widgetOptions,
- filters = tsf.setDefaults( table, c, wo ) || [];
- if ( filters.length ) {
- // prevent delayInit from triggering a cache build if filters are empty
- if ( !( c.delayInit && filters.join( '' ) === '' ) ) {
- ts.setFilters( table, filters, true );
- }
- }
- c.$table.triggerHandler( 'filterFomatterUpdate' );
- // trigger init after setTimeout to prevent multiple filterStart/End/Init triggers
- setTimeout( function() {
- if ( !wo.filter_initialized ) {
- tsf.filterInitComplete( c );
- }
- }, 100 );
- },
-
- // $cell parameter, but not the config, is passed to the filter_formatters,
- // so we have to work with it instead
- formatterUpdated: function( $cell, column ) {
- // prevent error if $cell is undefined - see #1056
- var wo = $cell && $cell.closest( 'table' )[0].config.widgetOptions;
- if ( wo && !wo.filter_initialized ) {
- // add updates by column since this function
- // may be called numerous times before initialization
- wo.filter_formatterInit[ column ] = 1;
- }
- },
- filterInitComplete: function( c ) {
- var indx, len,
- wo = c.widgetOptions,
- count = 0,
- completed = function() {
- wo.filter_initialized = true;
- c.$table.triggerHandler( 'filterInit', c );
- tsf.findRows( c.table, c.$table.data( 'lastSearch' ) || [] );
- };
- if ( $.isEmptyObject( wo.filter_formatter ) ) {
- completed();
- } else {
- len = wo.filter_formatterInit.length;
- for ( indx = 0; indx < len; indx++ ) {
- if ( wo.filter_formatterInit[ indx ] === 1 ) {
- count++;
- }
- }
- clearTimeout( wo.filter_initTimer );
- if ( !wo.filter_initialized && count === wo.filter_formatterCount ) {
- // filter widget initialized
- completed();
- } else if ( !wo.filter_initialized ) {
- // fall back in case a filter_formatter doesn't call
- // $.tablesorter.filter.formatterUpdated( $cell, column ), and the count is off
- wo.filter_initTimer = setTimeout( function() {
- completed();
- }, 500 );
- }
- }
- },
- // encode or decode filters for storage; see #1026
- processFilters: function( filters, encode ) {
- var indx,
- mode = encode ? encodeURIComponent : decodeURIComponent,
- len = filters.length;
- for ( indx = 0; indx < len; indx++ ) {
- if ( filters[ indx ] ) {
- filters[ indx ] = mode( filters[ indx ] );
- }
- }
- return filters;
- },
- setDefaults: function( table, c, wo ) {
- var isArray, saved, indx, col, $filters,
- // get current ( default ) filters
- filters = ts.getFilters( table ) || [];
- if ( wo.filter_saveFilters && ts.storage ) {
- saved = ts.storage( table, 'tablesorter-filters' ) || [];
- isArray = $.isArray( saved );
- // make sure we're not just getting an empty array
- if ( !( isArray && saved.join( '' ) === '' || !isArray ) ) {
- filters = tsf.processFilters( saved );
- }
- }
- // if no filters saved, then check default settings
- if ( filters.join( '' ) === '' ) {
- // allow adding default setting to external filters
- $filters = c.$headers.add( wo.filter_$externalFilters )
- .filter( '[' + wo.filter_defaultAttrib + ']' );
- for ( indx = 0; indx <= c.columns; indx++ ) {
- // include data-column='all' external filters
- col = indx === c.columns ? 'all' : indx;
- filters[ indx ] = $filters
- .filter( '[data-column="' + col + '"]' )
- .attr( wo.filter_defaultAttrib ) || filters[indx] || '';
- }
- }
- c.$table.data( 'lastSearch', filters );
- return filters;
- },
- parseFilter: function( c, filter, data, parsed ) {
- return parsed || data.parsed[ data.index ] ?
- c.parsers[ data.index ].format( filter, c.table, [], data.index ) :
- filter;
- },
- buildRow: function( table, c, wo ) {
- var $filter, col, column, $header, makeSelect, disabled, name, ffxn, tmp,
- // c.columns defined in computeThIndexes()
- cellFilter = wo.filter_cellFilter,
- columns = c.columns,
- arry = $.isArray( cellFilter ),
- buildFilter = '';
- for ( column = 0; column < columns; column++ ) {
- if ( c.$headerIndexed[ column ].length ) {
- // account for entire column set with colspan. See #1047
- tmp = c.$headerIndexed[ column ] && c.$headerIndexed[ column ][0].colSpan || 0;
- if ( tmp > 1 ) {
- buildFilter += ' ';
- }
- }
- c.$filters = $( buildFilter += ' ' )
- .appendTo( c.$table.children( 'thead' ).eq( 0 ) )
- .children( 'td' );
- // build each filter input
- for ( column = 0; column < columns; column++ ) {
- disabled = false;
- // assuming last cell of a column is the main column
- $header = c.$headerIndexed[ column ];
- if ( $header && $header.length ) {
- // $filter = c.$filters.filter( '[data-column="' + column + '"]' );
- $filter = tsf.getColumnElm( c, c.$filters, column );
- ffxn = ts.getColumnData( table, wo.filter_functions, column );
- makeSelect = ( wo.filter_functions && ffxn && typeof ffxn !== 'function' ) ||
- $header.hasClass( 'filter-select' );
- // get data from jQuery data, metadata, headers option or header class name
- col = ts.getColumnData( table, c.headers, column );
- disabled = ts.getData( $header[0], col, 'filter' ) === 'false' ||
- ts.getData( $header[0], col, 'parser' ) === 'false';
-
- if ( makeSelect ) {
- buildFilter = $( '' ).appendTo( $filter );
- } else {
- ffxn = ts.getColumnData( table, wo.filter_formatter, column );
- if ( ffxn ) {
- wo.filter_formatterCount++;
- buildFilter = ffxn( $filter, column );
- // no element returned, so lets go find it
- if ( buildFilter && buildFilter.length === 0 ) {
- buildFilter = $filter.children( 'input' );
- }
- // element not in DOM, so lets attach it
- if ( buildFilter && ( buildFilter.parent().length === 0 ||
- ( buildFilter.parent().length && buildFilter.parent()[0] !== $filter[0] ) ) ) {
- $filter.append( buildFilter );
- }
- } else {
- buildFilter = $( ' ' ).appendTo( $filter );
- }
- if ( buildFilter ) {
- tmp = $header.data( 'placeholder' ) ||
- $header.attr( 'data-placeholder' ) ||
- wo.filter_placeholder.search || '';
- buildFilter.attr( 'placeholder', tmp );
- }
- }
- if ( buildFilter ) {
- // add filter class name
- name = ( $.isArray( wo.filter_cssFilter ) ?
- ( typeof wo.filter_cssFilter[column] !== 'undefined' ? wo.filter_cssFilter[column] || '' : '' ) :
- wo.filter_cssFilter ) || '';
- // copy data-column from table cell (it will include colspan)
- buildFilter.addClass( tscss.filter + ' ' + name ).attr( 'data-column', $filter.attr( 'data-column' ) );
- if ( disabled ) {
- buildFilter.attr( 'placeholder', '' ).addClass( tscss.filterDisabled )[0].disabled = true;
- }
- }
- }
- }
- },
- bindSearch: function( table, $el, internal ) {
- table = $( table )[0];
- $el = $( $el ); // allow passing a selector string
- if ( !$el.length ) { return; }
- var tmp,
- c = table.config,
- wo = c.widgetOptions,
- namespace = c.namespace + 'filter',
- $ext = wo.filter_$externalFilters;
- if ( internal !== true ) {
- // save anyMatch element
- tmp = wo.filter_anyColumnSelector + ',' + wo.filter_multipleColumnSelector;
- wo.filter_$anyMatch = $el.filter( tmp );
- if ( $ext && $ext.length ) {
- wo.filter_$externalFilters = wo.filter_$externalFilters.add( $el );
- } else {
- wo.filter_$externalFilters = $el;
- }
- // update values ( external filters added after table initialization )
- ts.setFilters( table, c.$table.data( 'lastSearch' ) || [], internal === false );
- }
- // unbind events
- tmp = ( 'keypress keyup keydown search change input '.split( ' ' ).join( namespace + ' ' ) );
- $el
- // use data attribute instead of jQuery data since the head is cloned without including
- // the data/binding
- .attr( 'data-lastSearchTime', new Date().getTime() )
- .unbind( tmp.replace( ts.regex.spaces, ' ' ) )
- .bind( 'keydown' + namespace, function( event ) {
- if ( event.which === tskeyCodes.escape && !wo.filter_resetOnEsc ) {
- // prevent keypress event
- return false;
- }
- })
- .bind( 'keyup' + namespace, function( event ) {
- var column = parseInt( $( this ).attr( 'data-column' ), 10 );
- $( this ).attr( 'data-lastSearchTime', new Date().getTime() );
- // emulate what webkit does.... escape clears the filter
- if ( event.which === tskeyCodes.escape ) {
- // make sure to restore the last value on escape
- this.value = wo.filter_resetOnEsc ? '' : c.lastSearch[column];
- // live search
- } else if ( wo.filter_liveSearch === false ) {
- return;
- // don't return if the search value is empty ( all rows need to be revealed )
- } else if ( this.value !== '' && (
- // liveSearch can contain a min value length; ignore arrow and meta keys, but allow backspace
- ( typeof wo.filter_liveSearch === 'number' && this.value.length < wo.filter_liveSearch ) ||
- // let return & backspace continue on, but ignore arrows & non-valid characters
- ( event.which !== tskeyCodes.enter && event.which !== tskeyCodes.backSpace &&
- ( event.which < tskeyCodes.space || ( event.which >= tskeyCodes.left && event.which <= tskeyCodes.down ) ) ) ) ) {
- return;
- }
- // change event = no delay; last true flag tells getFilters to skip newest timed input
- tsf.searching( table, true, true );
- })
- // include change for select - fixes #473
- .bind( 'search change keypress input '.split( ' ' ).join( namespace + ' ' ), function( event ) {
- // don't get cached data, in case data-column changes dynamically
- var column = parseInt( $( this ).attr( 'data-column' ), 10 );
- // don't allow 'change' event to process if the input value is the same - fixes #685
- if ( wo.filter_initialized && ( event.which === tskeyCodes.enter || event.type === 'search' ||
- ( event.type === 'change' ) && this.value !== c.lastSearch[column] ) ||
- // only "input" event fires in MS Edge when clicking the "x" to clear the search
- ( event.type === 'input' && this.value === '' ) ) {
- event.preventDefault();
- // init search with no delay
- $( this ).attr( 'data-lastSearchTime', new Date().getTime() );
- tsf.searching( table, event.type !== 'keypress', true );
- }
- });
- },
- searching: function( table, filter, skipFirst ) {
- var wo = table.config.widgetOptions;
- clearTimeout( wo.filter_searchTimer );
- if ( typeof filter === 'undefined' || filter === true ) {
- // delay filtering
- wo.filter_searchTimer = setTimeout( function() {
- tsf.checkFilters( table, filter, skipFirst );
- }, wo.filter_liveSearch ? wo.filter_searchDelay : 10 );
- } else {
- // skip delay
- tsf.checkFilters( table, filter, skipFirst );
- }
- },
- checkFilters: function( table, filter, skipFirst ) {
- var c = table.config,
- wo = c.widgetOptions,
- filterArray = $.isArray( filter ),
- filters = ( filterArray ) ? filter : ts.getFilters( table, true ),
- combinedFilters = ( filters || [] ).join( '' ); // combined filter values
- // prevent errors if delay init is set
- if ( $.isEmptyObject( c.cache ) ) {
- // update cache if delayInit set & pager has initialized ( after user initiates a search )
- if ( c.delayInit && ( !c.pager || c.pager && c.pager.initialized ) ) {
- ts.updateCache( c, function() {
- tsf.checkFilters( table, false, skipFirst );
- });
- }
- return;
- }
- // add filter array back into inputs
- if ( filterArray ) {
- ts.setFilters( table, filters, false, skipFirst !== true );
- if ( !wo.filter_initialized ) { c.lastCombinedFilter = ''; }
- }
- if ( wo.filter_hideFilters ) {
- // show/hide filter row as needed
- c.$table
- .find( '.' + tscss.filterRow )
- .triggerHandler( combinedFilters === '' ? 'mouseleave' : 'mouseenter' );
- }
- // return if the last search is the same; but filter === false when updating the search
- // see example-widget-filter.html filter toggle buttons
- if ( c.lastCombinedFilter === combinedFilters && filter !== false ) {
- return;
- } else if ( filter === false ) {
- // force filter refresh
- c.lastCombinedFilter = null;
- c.lastSearch = [];
- }
- // define filter inside it is false
- filters = filters || [];
- // convert filters to strings - see #1070
- filters = Array.prototype.map ?
- filters.map( String ) :
- // for IE8 & older browsers - maybe not the best method
- filters.join( '\ufffd' ).split( '\ufffd' );
-
- if ( wo.filter_initialized ) {
- c.$table.triggerHandler( 'filterStart', [ filters ] );
- }
- if ( c.showProcessing ) {
- // give it time for the processing icon to kick in
- setTimeout( function() {
- tsf.findRows( table, filters, combinedFilters );
- return false;
- }, 30 );
- } else {
- tsf.findRows( table, filters, combinedFilters );
- return false;
- }
- },
- hideFilters: function( c, $table ) {
- var timer,
- $row = ( $table || c.$table ).find( '.' + tscss.filterRow ).addClass( tscss.filterRowHide );
- $row
- .bind( 'mouseenter mouseleave', function( e ) {
- // save event object - http://bugs.jquery.com/ticket/12140
- var event = e,
- $filterRow = $( this );
- clearTimeout( timer );
- timer = setTimeout( function() {
- if ( /enter|over/.test( event.type ) ) {
- $filterRow.removeClass( tscss.filterRowHide );
- } else {
- // don't hide if input has focus
- // $( ':focus' ) needs jQuery 1.6+
- if ( $( document.activeElement ).closest( 'tr' )[0] !== $filterRow[0] ) {
- // don't hide row if any filter has a value
- if ( c.lastCombinedFilter === '' ) {
- $filterRow.addClass( tscss.filterRowHide );
- }
- }
- }
- }, 200 );
- })
- .find( 'input, select' ).bind( 'focus blur', function( e ) {
- var event = e,
- $row = $( this ).closest( 'tr' );
- clearTimeout( timer );
- timer = setTimeout( function() {
- clearTimeout( timer );
- // don't hide row if any filter has a value
- if ( ts.getFilters( c.$table ).join( '' ) === '' ) {
- $row.toggleClass( tscss.filterRowHide, event.type !== 'focus' );
- }
- }, 200 );
- });
- },
- defaultFilter: function( filter, mask ) {
- if ( filter === '' ) { return filter; }
- var regex = tsfRegex.iQuery,
- maskLen = mask.match( tsfRegex.igQuery ).length,
- query = maskLen > 1 ? $.trim( filter ).split( /\s/ ) : [ $.trim( filter ) ],
- len = query.length - 1,
- indx = 0,
- val = mask;
- if ( len < 1 && maskLen > 1 ) {
- // only one 'word' in query but mask has >1 slots
- query[1] = query[0];
- }
- // replace all {query} with query words...
- // if query = 'Bob', then convert mask from '!{query}' to '!Bob'
- // if query = 'Bob Joe Frank', then convert mask '{q} OR {q}' to 'Bob OR Joe OR Frank'
- while ( regex.test( val ) ) {
- val = val.replace( regex, query[indx++] || '' );
- if ( regex.test( val ) && indx < len && ( query[indx] || '' ) !== '' ) {
- val = mask.replace( regex, val );
- }
- }
- return val;
- },
- getLatestSearch: function( $input ) {
- if ( $input ) {
- return $input.sort( function( a, b ) {
- return $( b ).attr( 'data-lastSearchTime' ) - $( a ).attr( 'data-lastSearchTime' );
- });
- }
- return $input || $();
- },
- findRange: function( c, val, ignoreRanges ) {
- // look for multiple columns '1-3,4-6,8' in data-column
- var temp, ranges, range, start, end, singles, i, indx, len,
- columns = [];
- if ( /^[0-9]+$/.test( val ) ) {
- // always return an array
- return [ parseInt( val, 10 ) ];
- }
- // process column range
- if ( !ignoreRanges && /-/.test( val ) ) {
- ranges = val.match( /(\d+)\s*-\s*(\d+)/g );
- len = ranges ? ranges.length : 0;
- for ( indx = 0; indx < len; indx++ ) {
- range = ranges[indx].split( /\s*-\s*/ );
- start = parseInt( range[0], 10 ) || 0;
- end = parseInt( range[1], 10 ) || ( c.columns - 1 );
- if ( start > end ) {
- temp = start; start = end; end = temp; // swap
- }
- if ( end >= c.columns ) {
- end = c.columns - 1;
- }
- for ( ; start <= end; start++ ) {
- columns[ columns.length ] = start;
- }
- // remove processed range from val
- val = val.replace( ranges[ indx ], '' );
- }
- }
- // process single columns
- if ( !ignoreRanges && /,/.test( val ) ) {
- singles = val.split( /\s*,\s*/ );
- len = singles.length;
- for ( i = 0; i < len; i++ ) {
- if ( singles[ i ] !== '' ) {
- indx = parseInt( singles[ i ], 10 );
- if ( indx < c.columns ) {
- columns[ columns.length ] = indx;
- }
- }
- }
- }
- // return all columns
- if ( !columns.length ) {
- for ( indx = 0; indx < c.columns; indx++ ) {
- columns[ columns.length ] = indx;
- }
- }
- return columns;
- },
- getColumnElm: function( c, $elements, column ) {
- // data-column may contain multiple columns '1-3,5-6,8'
- // replaces: c.$filters.filter( '[data-column="' + column + '"]' );
- return $elements.filter( function() {
- var cols = tsf.findRange( c, $( this ).attr( 'data-column' ) );
- return $.inArray( column, cols ) > -1;
- });
- },
- multipleColumns: function( c, $input ) {
- // look for multiple columns '1-3,4-6,8' in data-column
- var wo = c.widgetOptions,
- // only target 'all' column inputs on initialization
- // & don't target 'all' column inputs if they don't exist
- targets = wo.filter_initialized || !$input.filter( wo.filter_anyColumnSelector ).length,
- val = $.trim( tsf.getLatestSearch( $input ).attr( 'data-column' ) || '' );
- return tsf.findRange( c, val, !targets );
- },
- processTypes: function( c, data, vars ) {
- var ffxn,
- filterMatched = null,
- matches = null;
- for ( ffxn in tsf.types ) {
- if ( $.inArray( ffxn, vars.excludeMatch ) < 0 && matches === null ) {
- matches = tsf.types[ffxn]( c, data, vars );
- if ( matches !== null ) {
- filterMatched = matches;
- }
- }
- }
- return filterMatched;
- },
- matchType: function( c, columnIndex ) {
- var isMatch,
- wo = c.widgetOptions,
- $el = c.$headerIndexed[ columnIndex ];
- // filter-exact > filter-match > filter_matchType for type
- if ( $el.hasClass( 'filter-exact' ) ) {
- isMatch = false;
- } else if ( $el.hasClass( 'filter-match' ) ) {
- isMatch = true;
- } else {
- // filter-select is not applied when filter_functions are used, so look for a select
- if ( wo.filter_columnFilters ) {
- $el = c.$filters
- .find( '.' + tscss.filter )
- .add( wo.filter_$externalFilters )
- .filter( '[data-column="' + columnIndex + '"]' );
- } else if ( wo.filter_$externalFilters ) {
- $el = wo.filter_$externalFilters.filter( '[data-column="' + columnIndex + '"]' );
- }
- isMatch = $el.length ?
- c.widgetOptions.filter_matchType[ ( $el[ 0 ].nodeName || '' ).toLowerCase() ] === 'match' :
- // default to exact, if no inputs found
- false;
- }
- return isMatch;
- },
- processRow: function( c, data, vars ) {
- var result, filterMatched,
- fxn, ffxn, txt,
- wo = c.widgetOptions,
- showRow = true,
-
- // if wo.filter_$anyMatch data-column attribute is changed dynamically
- // we don't want to do an "anyMatch" search on one column using data
- // for the entire row - see #998
- columnIndex = wo.filter_$anyMatch && wo.filter_$anyMatch.length ?
- // look for multiple columns '1-3,4-6,8'
- tsf.multipleColumns( c, wo.filter_$anyMatch ) :
- [];
- data.$cells = data.$row.children();
- if ( data.anyMatchFlag && columnIndex.length > 1 || data.anyMatchFilter ) {
- data.anyMatch = true;
- data.isMatch = true;
- data.rowArray = data.$cells.map( function( i ) {
- if ( $.inArray( i, columnIndex ) > -1 || data.anyMatchFilter ) {
- if ( data.parsed[ i ] ) {
- txt = data.cacheArray[ i ];
- } else {
- txt = data.rawArray[ i ];
- txt = $.trim( wo.filter_ignoreCase ? txt.toLowerCase() : txt );
- if ( c.sortLocaleCompare ) {
- txt = ts.replaceAccents( txt );
- }
- }
- return txt;
- }
- }).get();
- data.filter = data.anyMatchFilter;
- data.iFilter = data.iAnyMatchFilter;
- data.exact = data.rowArray.join( ' ' );
- data.iExact = wo.filter_ignoreCase ? data.exact.toLowerCase() : data.exact;
- data.cache = data.cacheArray.slice( 0, -1 ).join( ' ' );
- vars.excludeMatch = vars.noAnyMatch;
- filterMatched = tsf.processTypes( c, data, vars );
- if ( filterMatched !== null ) {
- showRow = filterMatched;
- } else {
- if ( wo.filter_startsWith ) {
- showRow = false;
- // data.rowArray may not contain all columns
- columnIndex = Math.min( c.columns, data.rowArray.length );
- while ( !showRow && columnIndex > 0 ) {
- columnIndex--;
- showRow = showRow || data.rowArray[ columnIndex ].indexOf( data.iFilter ) === 0;
- }
- } else {
- showRow = ( data.iExact + data.childRowText ).indexOf( data.iFilter ) >= 0;
- }
- }
- data.anyMatch = false;
- // no other filters to process
- if ( data.filters.join( '' ) === data.filter ) {
- return showRow;
- }
- }
-
- for ( columnIndex = 0; columnIndex < c.columns; columnIndex++ ) {
- data.filter = data.filters[ columnIndex ];
- data.index = columnIndex;
-
- // filter types to exclude, per column
- vars.excludeMatch = vars.excludeFilter[ columnIndex ];
-
- // ignore if filter is empty or disabled
- if ( data.filter ) {
- data.cache = data.cacheArray[ columnIndex ];
- result = data.parsed[ columnIndex ] ? data.cache : data.rawArray[ columnIndex ] || '';
- data.exact = c.sortLocaleCompare ? ts.replaceAccents( result ) : result; // issue #405
- data.iExact = !tsfRegex.type.test( typeof data.exact ) && wo.filter_ignoreCase ?
- data.exact.toLowerCase() : data.exact;
- data.isMatch = tsf.matchType( c, columnIndex );
-
- result = showRow; // if showRow is true, show that row
-
- // in case select filter option has a different value vs text 'a - z|A through Z'
- ffxn = wo.filter_columnFilters ?
- c.$filters.add( wo.filter_$externalFilters )
- .filter( '[data-column="' + columnIndex + '"]' )
- .find( 'select option:selected' )
- .attr( 'data-function-name' ) || '' : '';
- // replace accents - see #357
- if ( c.sortLocaleCompare ) {
- data.filter = ts.replaceAccents( data.filter );
- }
-
- // replace column specific default filters - see #1088
- if ( wo.filter_defaultFilter && tsfRegex.iQuery.test( vars.defaultColFilter[ columnIndex ] ) ) {
- data.filter = tsf.defaultFilter( data.filter, vars.defaultColFilter[ columnIndex ] );
- }
-
- // data.iFilter = case insensitive ( if wo.filter_ignoreCase is true ),
- // data.filter = case sensitive
- data.iFilter = wo.filter_ignoreCase ? ( data.filter || '' ).toLowerCase() : data.filter;
- fxn = vars.functions[ columnIndex ];
- filterMatched = null;
- if ( fxn ) {
- if ( fxn === true ) {
- // default selector uses exact match unless 'filter-match' class is found
- filterMatched = data.isMatch ?
- // data.iExact may be a number
- ( '' + data.iExact ).search( data.iFilter ) >= 0 :
- data.filter === data.exact;
- } else if ( typeof fxn === 'function' ) {
- // filter callback( exact cell content, parser normalized content,
- // filter input value, column index, jQuery row object )
- filterMatched = fxn( data.exact, data.cache, data.filter, columnIndex, data.$row, c, data );
- } else if ( typeof fxn[ ffxn || data.filter ] === 'function' ) {
- // selector option function
- txt = ffxn || data.filter;
- filterMatched =
- fxn[ txt ]( data.exact, data.cache, data.filter, columnIndex, data.$row, c, data );
- }
- }
- if ( filterMatched === null ) {
- // cycle through the different filters
- // filters return a boolean or null if nothing matches
- filterMatched = tsf.processTypes( c, data, vars );
- if ( filterMatched !== null ) {
- result = filterMatched;
- // Look for match, and add child row data for matching
- } else {
- txt = ( data.iExact + data.childRowText ).indexOf( tsf.parseFilter( c, data.iFilter, data ) );
- result = ( ( !wo.filter_startsWith && txt >= 0 ) || ( wo.filter_startsWith && txt === 0 ) );
- }
- } else {
- result = filterMatched;
- }
- showRow = ( result ) ? showRow : false;
- }
- }
- return showRow;
- },
- findRows: function( table, filters, combinedFilters ) {
- if ( table.config.lastCombinedFilter === combinedFilters ||
- !table.config.widgetOptions.filter_initialized ) {
- return;
- }
- var len, norm_rows, rowData, $rows, $row, rowIndex, tbodyIndex, $tbody, columnIndex,
- isChild, childRow, lastSearch, showRow, showParent, time, val, indx,
- notFiltered, searchFiltered, query, injected, res, id, txt,
- storedFilters = $.extend( [], filters ),
- c = table.config,
- wo = c.widgetOptions,
- // data object passed to filters; anyMatch is a flag for the filters
- data = {
- anyMatch: false,
- filters: filters,
- // regex filter type cache
- filter_regexCache : []
- },
- vars = {
- // anyMatch really screws up with these types of filters
- noAnyMatch: [ 'range', 'operators' ],
- // cache filter variables that use ts.getColumnData in the main loop
- functions : [],
- excludeFilter : [],
- defaultColFilter : [],
- defaultAnyFilter : ts.getColumnData( table, wo.filter_defaultFilter, c.columns, true ) || ''
- };
-
- // parse columns after formatter, in case the class is added at that point
- data.parsed = [];
- for ( columnIndex = 0; columnIndex < c.columns; columnIndex++ ) {
- data.parsed[ columnIndex ] = wo.filter_useParsedData ||
- // parser has a "parsed" parameter
- ( c.parsers && c.parsers[ columnIndex ] && c.parsers[ columnIndex ].parsed ||
- // getData may not return 'parsed' if other 'filter-' class names exist
- // ( e.g. )
- ts.getData && ts.getData( c.$headerIndexed[ columnIndex ],
- ts.getColumnData( table, c.headers, columnIndex ), 'filter' ) === 'parsed' ||
- c.$headerIndexed[ columnIndex ].hasClass( 'filter-parsed' ) );
-
- vars.functions[ columnIndex ] =
- ts.getColumnData( table, wo.filter_functions, columnIndex ) ||
- c.$headerIndexed[ columnIndex ].hasClass( 'filter-select' );
- vars.defaultColFilter[ columnIndex ] =
- ts.getColumnData( table, wo.filter_defaultFilter, columnIndex ) || '';
- vars.excludeFilter[ columnIndex ] =
- ( ts.getColumnData( table, wo.filter_excludeFilter, columnIndex, true ) || '' ).split( /\s+/ );
- }
-
- if ( c.debug ) {
- console.log( 'Filter: Starting filter widget search', filters );
- time = new Date();
- }
- // filtered rows count
- c.filteredRows = 0;
- c.totalRows = 0;
- // combindedFilters are undefined on init
- combinedFilters = ( storedFilters || [] ).join( '' );
-
- for ( tbodyIndex = 0; tbodyIndex < c.$tbodies.length; tbodyIndex++ ) {
- $tbody = ts.processTbody( table, c.$tbodies.eq( tbodyIndex ), true );
- // skip child rows & widget added ( removable ) rows - fixes #448 thanks to @hempel!
- // $rows = $tbody.children( 'tr' ).not( c.selectorRemove );
- columnIndex = c.columns;
- // convert stored rows into a jQuery object
- norm_rows = c.cache[ tbodyIndex ].normalized;
- $rows = $( $.map( norm_rows, function( el ) {
- return el[ columnIndex ].$row.get();
- }) );
-
- if ( combinedFilters === '' || wo.filter_serversideFiltering ) {
- $rows
- .removeClass( wo.filter_filteredRow )
- .not( '.' + c.cssChildRow )
- .css( 'display', '' );
- } else {
- // filter out child rows
- $rows = $rows.not( '.' + c.cssChildRow );
- len = $rows.length;
-
- if ( ( wo.filter_$anyMatch && wo.filter_$anyMatch.length ) ||
- typeof filters[c.columns] !== 'undefined' ) {
- data.anyMatchFlag = true;
- data.anyMatchFilter = '' + (
- filters[ c.columns ] ||
- wo.filter_$anyMatch && tsf.getLatestSearch( wo.filter_$anyMatch ).val() ||
- ''
- );
- if ( wo.filter_columnAnyMatch ) {
- // specific columns search
- query = data.anyMatchFilter.split( tsfRegex.andSplit );
- injected = false;
- for ( indx = 0; indx < query.length; indx++ ) {
- res = query[ indx ].split( ':' );
- if ( res.length > 1 ) {
- // make the column a one-based index ( non-developers start counting from one :P )
- id = parseInt( res[0], 10 ) - 1;
- if ( id >= 0 && id < c.columns ) { // if id is an integer
- filters[ id ] = res[1];
- query.splice( indx, 1 );
- indx--;
- injected = true;
- }
- }
- }
- if ( injected ) {
- data.anyMatchFilter = query.join( ' && ' );
- }
- }
- }
-
- // optimize searching only through already filtered rows - see #313
- searchFiltered = wo.filter_searchFiltered;
- lastSearch = c.lastSearch || c.$table.data( 'lastSearch' ) || [];
- if ( searchFiltered ) {
- // cycle through all filters; include last ( columnIndex + 1 = match any column ). Fixes #669
- for ( indx = 0; indx < columnIndex + 1; indx++ ) {
- val = filters[indx] || '';
- // break out of loop if we've already determined not to search filtered rows
- if ( !searchFiltered ) { indx = columnIndex; }
- // search already filtered rows if...
- searchFiltered = searchFiltered && lastSearch.length &&
- // there are no changes from beginning of filter
- val.indexOf( lastSearch[indx] || '' ) === 0 &&
- // if there is NOT a logical 'or', or range ( 'to' or '-' ) in the string
- !tsfRegex.alreadyFiltered.test( val ) &&
- // if we are not doing exact matches, using '|' ( logical or ) or not '!'
- !tsfRegex.exactTest.test( val ) &&
- // don't search only filtered if the value is negative
- // ( '> -10' => '> -100' will ignore hidden rows )
- !( tsfRegex.isNeg1.test( val ) || tsfRegex.isNeg2.test( val ) ) &&
- // if filtering using a select without a 'filter-match' class ( exact match ) - fixes #593
- !( val !== '' && c.$filters && c.$filters.filter( '[data-column="' + indx + '"]' ).find( 'select' ).length &&
- !tsf.matchType( c, indx ) );
- }
- }
- notFiltered = $rows.not( '.' + wo.filter_filteredRow ).length;
- // can't search when all rows are hidden - this happens when looking for exact matches
- if ( searchFiltered && notFiltered === 0 ) { searchFiltered = false; }
- if ( c.debug ) {
- console.log( 'Filter: Searching through ' +
- ( searchFiltered && notFiltered < len ? notFiltered : 'all' ) + ' rows' );
- }
- if ( data.anyMatchFlag ) {
- if ( c.sortLocaleCompare ) {
- // replace accents
- data.anyMatchFilter = ts.replaceAccents( data.anyMatchFilter );
- }
- if ( wo.filter_defaultFilter && tsfRegex.iQuery.test( vars.defaultAnyFilter ) ) {
- data.anyMatchFilter = tsf.defaultFilter( data.anyMatchFilter, vars.defaultAnyFilter );
- // clear search filtered flag because default filters are not saved to the last search
- searchFiltered = false;
- }
- // make iAnyMatchFilter lowercase unless both filter widget & core ignoreCase options are true
- // when c.ignoreCase is true, the cache contains all lower case data
- data.iAnyMatchFilter = !( wo.filter_ignoreCase && c.ignoreCase ) ?
- data.anyMatchFilter :
- data.anyMatchFilter.toLowerCase();
- }
-
- // loop through the rows
- for ( rowIndex = 0; rowIndex < len; rowIndex++ ) {
-
- txt = $rows[ rowIndex ].className;
- // the first row can never be a child row
- isChild = rowIndex && tsfRegex.child.test( txt );
- // skip child rows & already filtered rows
- if ( isChild || ( searchFiltered && tsfRegex.filtered.test( txt ) ) ) {
- continue;
- }
-
- data.$row = $rows.eq( rowIndex );
- data.cacheArray = norm_rows[ rowIndex ];
- rowData = data.cacheArray[ c.columns ];
- data.rawArray = rowData.raw;
- data.childRowText = '';
-
- if ( !wo.filter_childByColumn ) {
- txt = '';
- // child row cached text
- childRow = rowData.child;
- // so, if 'table.config.widgetOptions.filter_childRows' is true and there is
- // a match anywhere in the child row, then it will make the row visible
- // checked here so the option can be changed dynamically
- for ( indx = 0; indx < childRow.length; indx++ ) {
- txt += ' ' + childRow[indx].join( ' ' ) || '';
- }
- data.childRowText = wo.filter_childRows ?
- ( wo.filter_ignoreCase ? txt.toLowerCase() : txt ) :
- '';
- }
-
- showRow = false;
- showParent = tsf.processRow( c, data, vars );
- $row = rowData.$row;
-
- // don't pass reference to val
- val = showParent ? true : false;
- childRow = rowData.$row.filter( ':gt(0)' );
- if ( wo.filter_childRows && childRow.length ) {
- if ( wo.filter_childByColumn ) {
- if ( !wo.filter_childWithSibs ) {
- // hide all child rows
- childRow.addClass( wo.filter_filteredRow );
- // if only showing resulting child row, only include parent
- $row = $row.eq( 0 );
- }
- // cycle through each child row
- for ( indx = 0; indx < childRow.length; indx++ ) {
- data.$row = childRow.eq( indx );
- data.cacheArray = rowData.child[ indx ];
- data.rawArray = data.cacheArray;
- val = tsf.processRow( c, data, vars );
- // use OR comparison on child rows
- showRow = showRow || val;
- if ( !wo.filter_childWithSibs && val ) {
- childRow.eq( indx ).removeClass( wo.filter_filteredRow );
- }
- }
- }
- // keep parent row match even if no child matches... see #1020
- showRow = showRow || showParent;
- } else {
- showRow = val;
- }
- $row
- .toggleClass( wo.filter_filteredRow, !showRow )[0]
- .display = showRow ? '' : 'none';
- }
- }
- c.filteredRows += $rows.not( '.' + wo.filter_filteredRow ).length;
- c.totalRows += $rows.length;
- ts.processTbody( table, $tbody, false );
- }
- c.lastCombinedFilter = combinedFilters; // save last search
- // don't save 'filters' directly since it may have altered ( AnyMatch column searches )
- c.lastSearch = storedFilters;
- c.$table.data( 'lastSearch', storedFilters );
- if ( wo.filter_saveFilters && ts.storage ) {
- ts.storage( table, 'tablesorter-filters', tsf.processFilters( storedFilters, true ) );
- }
- if ( c.debug ) {
- console.log( 'Completed filter widget search' + ts.benchmark(time) );
- }
- if ( wo.filter_initialized ) {
- c.$table.triggerHandler( 'filterBeforeEnd', c );
- c.$table.triggerHandler( 'filterEnd', c );
- }
- setTimeout( function() {
- ts.applyWidget( c.table ); // make sure zebra widget is applied
- }, 0 );
- },
- getOptionSource: function( table, column, onlyAvail ) {
- table = $( table )[0];
- var c = table.config,
- wo = c.widgetOptions,
- arry = false,
- source = wo.filter_selectSource,
- last = c.$table.data( 'lastSearch' ) || [],
- fxn = typeof source === 'function' ? true : ts.getColumnData( table, source, column );
-
- if ( onlyAvail && last[column] !== '' ) {
- onlyAvail = false;
- }
-
- // filter select source option
- if ( fxn === true ) {
- // OVERALL source
- arry = source( table, column, onlyAvail );
- } else if ( fxn instanceof $ || ( $.type( fxn ) === 'string' && fxn.indexOf( '' ) >= 0 ) ) {
- // selectSource is a jQuery object or string of options
- return fxn;
- } else if ( $.isArray( fxn ) ) {
- arry = fxn;
- } else if ( $.type( source ) === 'object' && fxn ) {
- // custom select source function for a SPECIFIC COLUMN
- arry = fxn( table, column, onlyAvail );
- }
- if ( arry === false ) {
- // fall back to original method
- arry = tsf.getOptions( table, column, onlyAvail );
- }
-
- return tsf.processOptions( table, column, arry );
-
- },
- processOptions: function( table, column, arry ) {
- if ( !$.isArray( arry ) ) {
- return false;
- }
- table = $( table )[0];
- var cts, txt, indx, len, parsedTxt, str,
- c = table.config,
- validColumn = typeof column !== 'undefined' && column !== null && column >= 0 && column < c.columns,
- parsed = [];
- // get unique elements and sort the list
- // if $.tablesorter.sortText exists ( not in the original tablesorter ),
- // then natural sort the list otherwise use a basic sort
- arry = $.grep( arry, function( value, indx ) {
- if ( value.text ) {
- return true;
- }
- return $.inArray( value, arry ) === indx;
- });
- if ( validColumn && c.$headerIndexed[ column ].hasClass( 'filter-select-nosort' ) ) {
- // unsorted select options
- return arry;
- } else {
- len = arry.length;
- // parse select option values
- for ( indx = 0; indx < len; indx++ ) {
- txt = arry[ indx ];
- // check for object
- str = txt.text ? txt.text : txt;
- // sortNatural breaks if you don't pass it strings
- parsedTxt = ( validColumn && c.parsers && c.parsers.length &&
- c.parsers[ column ].format( str, table, [], column ) || str ).toString();
- parsedTxt = c.widgetOptions.filter_ignoreCase ? parsedTxt.toLowerCase() : parsedTxt;
- // parse array data using set column parser; this DOES NOT pass the original
- // table cell to the parser format function
- if ( txt.text ) {
- txt.parsed = parsedTxt;
- parsed[ parsed.length ] = txt;
- } else {
- parsed[ parsed.length ] = {
- text : txt,
- // check parser length - fixes #934
- parsed : parsedTxt
- };
- }
- }
- // sort parsed select options
- cts = c.textSorter || '';
- parsed.sort( function( a, b ) {
- var x = a.parsed,
- y = b.parsed;
- if ( validColumn && typeof cts === 'function' ) {
- // custom OVERALL text sorter
- return cts( x, y, true, column, table );
- } else if ( validColumn && typeof cts === 'object' && cts.hasOwnProperty( column ) ) {
- // custom text sorter for a SPECIFIC COLUMN
- return cts[column]( x, y, true, column, table );
- } else if ( ts.sortNatural ) {
- // fall back to natural sort
- return ts.sortNatural( x, y );
- }
- // using an older version! do a basic sort
- return true;
- });
- // rebuild arry from sorted parsed data
- arry = [];
- len = parsed.length;
- for ( indx = 0; indx < len; indx++ ) {
- arry[ arry.length ] = parsed[indx];
- }
- return arry;
- }
- },
- getOptions: function( table, column, onlyAvail ) {
- table = $( table )[0];
- var rowIndex, tbodyIndex, len, row, cache, indx, child, childLen,
- c = table.config,
- wo = c.widgetOptions,
- arry = [];
- for ( tbodyIndex = 0; tbodyIndex < c.$tbodies.length; tbodyIndex++ ) {
- cache = c.cache[tbodyIndex];
- len = c.cache[tbodyIndex].normalized.length;
- // loop through the rows
- for ( rowIndex = 0; rowIndex < len; rowIndex++ ) {
- // get cached row from cache.row ( old ) or row data object
- // ( new; last item in normalized array )
- row = cache.row ?
- cache.row[ rowIndex ] :
- cache.normalized[ rowIndex ][ c.columns ].$row[0];
- // check if has class filtered
- if ( onlyAvail && row.className.match( wo.filter_filteredRow ) ) {
- continue;
- }
- // get non-normalized cell content
- if ( wo.filter_useParsedData ||
- c.parsers[column].parsed ||
- c.$headerIndexed[column].hasClass( 'filter-parsed' ) ) {
- arry[ arry.length ] = '' + cache.normalized[ rowIndex ][ column ];
- // child row parsed data
- if ( wo.filter_childRows && wo.filter_childByColumn ) {
- childLen = cache.normalized[ rowIndex ][ c.columns ].$row.length - 1;
- for ( indx = 0; indx < childLen; indx++ ) {
- arry[ arry.length ] = '' + cache.normalized[ rowIndex ][ c.columns ].child[ indx ][ column ];
- }
- }
- } else {
- // get raw cached data instead of content directly from the cells
- arry[ arry.length ] = cache.normalized[ rowIndex ][ c.columns ].raw[ column ];
- // child row unparsed data
- if ( wo.filter_childRows && wo.filter_childByColumn ) {
- childLen = cache.normalized[ rowIndex ][ c.columns ].$row.length;
- for ( indx = 1; indx < childLen; indx++ ) {
- child = cache.normalized[ rowIndex ][ c.columns ].$row.eq( indx ).children().eq( column );
- arry[ arry.length ] = '' + ts.getElementText( c, child, column );
- }
- }
- }
- }
- }
- return arry;
- },
- buildSelect: function( table, column, arry, updating, onlyAvail ) {
- table = $( table )[0];
- column = parseInt( column, 10 );
- if ( !table.config.cache || $.isEmptyObject( table.config.cache ) ) {
- return;
- }
-
- var indx, val, txt, t, $filters, $filter, option,
- c = table.config,
- wo = c.widgetOptions,
- node = c.$headerIndexed[ column ],
- // t.data( 'placeholder' ) won't work in jQuery older than 1.4.3
- options = '' +
- ( node.data( 'placeholder' ) ||
- node.attr( 'data-placeholder' ) ||
- wo.filter_placeholder.select || ''
- ) + ' ',
- // Get curent filter value
- currentValue = c.$table
- .find( 'thead' )
- .find( 'select.' + tscss.filter + '[data-column="' + column + '"]' )
- .val();
-
- // nothing included in arry ( external source ), so get the options from
- // filter_selectSource or column data
- if ( typeof arry === 'undefined' || arry === '' ) {
- arry = tsf.getOptionSource( table, column, onlyAvail );
- }
-
- if ( $.isArray( arry ) ) {
- // build option list
- for ( indx = 0; indx < arry.length; indx++ ) {
- option = arry[ indx ];
- if ( option.text ) {
- // OBJECT!! add data-function-name in case the value is set in filter_functions
- option['data-function-name'] = typeof option.value === 'undefined' ? option.text : option.value;
-
- // support jQuery < v1.8, otherwise the below code could be shortened to
- // options += $( '', option )[ 0 ].outerHTML;
- options += ' ' + option.text + ' ';
- // above code is needed in jQuery < v1.8
-
- // make sure we don't turn an object into a string (objects without a "text" property)
- } else if ( '' + option !== '[object Object]' ) {
- txt = option = ( '' + option ).replace( tsfRegex.quote, '"' );
- val = txt;
- // allow including a symbol in the selectSource array
- // 'a-z|A through Z' so that 'a-z' becomes the option value
- // and 'A through Z' becomes the option text
- if ( txt.indexOf( wo.filter_selectSourceSeparator ) >= 0 ) {
- t = txt.split( wo.filter_selectSourceSeparator );
- val = t[0];
- txt = t[1];
- }
- // replace quotes - fixes #242 & ignore empty strings
- // see http://stackoverflow.com/q/14990971/145346
- options += option !== '' ?
- '' + txt +
- ' ' : '';
- }
- }
- // clear arry so it doesn't get appended twice
- arry = [];
- }
-
- // update all selects in the same column ( clone thead in sticky headers &
- // any external selects ) - fixes 473
- $filters = ( c.$filters ? c.$filters : c.$table.children( 'thead' ) )
- .find( '.' + tscss.filter );
- if ( wo.filter_$externalFilters ) {
- $filters = $filters && $filters.length ?
- $filters.add( wo.filter_$externalFilters ) :
- wo.filter_$externalFilters;
- }
- $filter = $filters.filter( 'select[data-column="' + column + '"]' );
-
- // make sure there is a select there!
- if ( $filter.length ) {
- $filter[ updating ? 'html' : 'append' ]( options );
- if ( !$.isArray( arry ) ) {
- // append options if arry is provided externally as a string or jQuery object
- // options ( default value ) was already added
- $filter.append( arry ).val( currentValue );
- }
- $filter.val( currentValue );
- }
- },
- buildDefault: function( table, updating ) {
- var columnIndex, $header, noSelect,
- c = table.config,
- wo = c.widgetOptions,
- columns = c.columns;
- // build default select dropdown
- for ( columnIndex = 0; columnIndex < columns; columnIndex++ ) {
- $header = c.$headerIndexed[columnIndex];
- noSelect = !( $header.hasClass( 'filter-false' ) || $header.hasClass( 'parser-false' ) );
- // look for the filter-select class; build/update it if found
- if ( ( $header.hasClass( 'filter-select' ) ||
- ts.getColumnData( table, wo.filter_functions, columnIndex ) === true ) && noSelect ) {
- tsf.buildSelect( table, columnIndex, '', updating, $header.hasClass( wo.filter_onlyAvail ) );
- }
- }
- }
- };
-
- // filter regex variable
- tsfRegex = tsf.regex;
-
- ts.getFilters = function( table, getRaw, setFilters, skipFirst ) {
- var i, $filters, $column, cols,
- filters = false,
- c = table ? $( table )[0].config : '',
- wo = c ? c.widgetOptions : '';
- if ( ( getRaw !== true && wo && !wo.filter_columnFilters ) ||
- // setFilters called, but last search is exactly the same as the current
- // fixes issue #733 & #903 where calling update causes the input values to reset
- ( $.isArray(setFilters) && setFilters.join('') === c.lastCombinedFilter ) ) {
- return $( table ).data( 'lastSearch' );
- }
- if ( c ) {
- if ( c.$filters ) {
- $filters = c.$filters.find( '.' + tscss.filter );
- }
- if ( wo.filter_$externalFilters ) {
- $filters = $filters && $filters.length ?
- $filters.add( wo.filter_$externalFilters ) :
- wo.filter_$externalFilters;
- }
- if ( $filters && $filters.length ) {
- filters = setFilters || [];
- for ( i = 0; i < c.columns + 1; i++ ) {
- cols = ( i === c.columns ?
- // 'all' columns can now include a range or set of columms ( data-column='0-2,4,6-7' )
- wo.filter_anyColumnSelector + ',' + wo.filter_multipleColumnSelector :
- '[data-column="' + i + '"]' );
- $column = $filters.filter( cols );
- if ( $column.length ) {
- // move the latest search to the first slot in the array
- $column = tsf.getLatestSearch( $column );
- if ( $.isArray( setFilters ) ) {
- // skip first ( latest input ) to maintain cursor position while typing
- if ( skipFirst && $column.length > 1 ) {
- $column = $column.slice( 1 );
- }
- if ( i === c.columns ) {
- // prevent data-column='all' from filling data-column='0,1' ( etc )
- cols = $column.filter( wo.filter_anyColumnSelector );
- $column = cols.length ? cols : $column;
- }
- $column
- .val( setFilters[ i ] )
- // must include a namespace here; but not c.namespace + 'filter'?
- .trigger( 'change' + c.namespace );
- } else {
- filters[i] = $column.val() || '';
- // don't change the first... it will move the cursor
- if ( i === c.columns ) {
- // don't update range columns from 'all' setting
- $column
- .slice( 1 )
- .filter( '[data-column*="' + $column.attr( 'data-column' ) + '"]' )
- .val( filters[ i ] );
- } else {
- $column
- .slice( 1 )
- .val( filters[ i ] );
- }
- }
- // save any match input dynamically
- if ( i === c.columns && $column.length ) {
- wo.filter_$anyMatch = $column;
- }
- }
- }
- }
- }
- if ( filters.length === 0 ) {
- filters = false;
- }
- return filters;
- };
-
- ts.setFilters = function( table, filter, apply, skipFirst ) {
- var c = table ? $( table )[0].config : '',
- valid = ts.getFilters( table, true, filter, skipFirst );
- // default apply to "true"
- if ( typeof apply === 'undefined' ) {
- apply = true;
- }
- if ( c && apply ) {
- // ensure new set filters are applied, even if the search is the same
- c.lastCombinedFilter = null;
- c.lastSearch = [];
- tsf.searching( c.table, filter, skipFirst );
- c.$table.triggerHandler( 'filterFomatterUpdate' );
- }
- return !!valid;
- };
-
-})( jQuery );
-
-/*! Widget: stickyHeaders - updated 5/1/2016 (v2.26.0) *//*
- * Requires tablesorter v2.8+ and jQuery 1.4.3+
- * by Rob Garrison
- */
-;(function ($, window) {
- 'use strict';
- var ts = $.tablesorter || {};
-
- $.extend(ts.css, {
- sticky : 'tablesorter-stickyHeader', // stickyHeader
- stickyVis : 'tablesorter-sticky-visible',
- stickyHide: 'tablesorter-sticky-hidden',
- stickyWrap: 'tablesorter-sticky-wrapper'
- });
-
- // Add a resize event to table headers
- ts.addHeaderResizeEvent = function(table, disable, settings) {
- table = $(table)[0]; // make sure we're using a dom element
- if ( !table.config ) { return; }
- var defaults = {
- timer : 250
- },
- options = $.extend({}, defaults, settings),
- c = table.config,
- wo = c.widgetOptions,
- checkSizes = function( triggerEvent ) {
- var index, headers, $header, sizes, width, height,
- len = c.$headers.length;
- wo.resize_flag = true;
- headers = [];
- for ( index = 0; index < len; index++ ) {
- $header = c.$headers.eq( index );
- sizes = $header.data( 'savedSizes' ) || [ 0, 0 ]; // fixes #394
- width = $header[0].offsetWidth;
- height = $header[0].offsetHeight;
- if ( width !== sizes[0] || height !== sizes[1] ) {
- $header.data( 'savedSizes', [ width, height ] );
- headers.push( $header[0] );
- }
- }
- if ( headers.length && triggerEvent !== false ) {
- c.$table.triggerHandler( 'resize', [ headers ] );
- }
- wo.resize_flag = false;
- };
- clearInterval(wo.resize_timer);
- if (disable) {
- wo.resize_flag = false;
- return false;
- }
- checkSizes( false );
- wo.resize_timer = setInterval(function() {
- if (wo.resize_flag) { return; }
- checkSizes();
- }, options.timer);
- };
-
- // Sticky headers based on this awesome article:
- // http://css-tricks.com/13465-persistent-headers/
- // and https://github.com/jmosbech/StickyTableHeaders by Jonas Mosbech
- // **************************
- ts.addWidget({
- id: 'stickyHeaders',
- priority: 60, // sticky widget must be initialized after the filter widget!
- options: {
- stickyHeaders : '', // extra class name added to the sticky header row
- stickyHeaders_attachTo : null, // jQuery selector or object to attach sticky header to
- stickyHeaders_xScroll : null, // jQuery selector or object to monitor horizontal scroll position (defaults: xScroll > attachTo > window)
- stickyHeaders_yScroll : null, // jQuery selector or object to monitor vertical scroll position (defaults: yScroll > attachTo > window)
- stickyHeaders_offset : 0, // number or jquery selector targeting the position:fixed element
- stickyHeaders_filteredToTop: true, // scroll table top into view after filtering
- stickyHeaders_cloneId : '-sticky', // added to table ID, if it exists
- stickyHeaders_addResizeEvent : true, // trigger 'resize' event on headers
- stickyHeaders_includeCaption : true, // if false and a caption exist, it won't be included in the sticky header
- stickyHeaders_zIndex : 2 // The zIndex of the stickyHeaders, allows the user to adjust this to their needs
- },
- format: function(table, c, wo) {
- // filter widget doesn't initialize on an empty table. Fixes #449
- if ( c.$table.hasClass('hasStickyHeaders') || ($.inArray('filter', c.widgets) >= 0 && !c.$table.hasClass('hasFilters')) ) {
- return;
- }
- var index, len, $t,
- $table = c.$table,
- // add position: relative to attach element, hopefully it won't cause trouble.
- $attach = $(wo.stickyHeaders_attachTo),
- namespace = c.namespace + 'stickyheaders ',
- // element to watch for the scroll event
- $yScroll = $(wo.stickyHeaders_yScroll || wo.stickyHeaders_attachTo || window),
- $xScroll = $(wo.stickyHeaders_xScroll || wo.stickyHeaders_attachTo || window),
- $thead = $table.children('thead:first'),
- $header = $thead.children('tr').not('.sticky-false').children(),
- $tfoot = $table.children('tfoot'),
- $stickyOffset = isNaN(wo.stickyHeaders_offset) ? $(wo.stickyHeaders_offset) : '',
- stickyOffset = $stickyOffset.length ? $stickyOffset.height() || 0 : parseInt(wo.stickyHeaders_offset, 10) || 0,
- // is this table nested? If so, find parent sticky header wrapper (div, not table)
- $nestedSticky = $table.parent().closest('.' + ts.css.table).hasClass('hasStickyHeaders') ?
- $table.parent().closest('table.tablesorter')[0].config.widgetOptions.$sticky.parent() : [],
- nestedStickyTop = $nestedSticky.length ? $nestedSticky.height() : 0,
- // clone table, then wrap to make sticky header
- $stickyTable = wo.$sticky = $table.clone()
- .addClass('containsStickyHeaders ' + ts.css.sticky + ' ' + wo.stickyHeaders + ' ' + c.namespace.slice(1) + '_extra_table' )
- .wrap(''),
- $stickyWrap = $stickyTable.parent()
- .addClass(ts.css.stickyHide)
- .css({
- position : $attach.length ? 'absolute' : 'fixed',
- padding : parseInt( $stickyTable.parent().parent().css('padding-left'), 10 ),
- top : stickyOffset + nestedStickyTop,
- left : 0,
- visibility : 'hidden',
- zIndex : wo.stickyHeaders_zIndex || 2
- }),
- $stickyThead = $stickyTable.children('thead:first'),
- $stickyCells,
- laststate = '',
- spacing = 0,
- setWidth = function($orig, $clone){
- var index, width, border, $cell, $this,
- $cells = $orig.filter(':visible'),
- len = $cells.length;
- for ( index = 0; index < len; index++ ) {
- $cell = $clone.filter(':visible').eq(index);
- $this = $cells.eq(index);
- // code from https://github.com/jmosbech/StickyTableHeaders
- if ($this.css('box-sizing') === 'border-box') {
- width = $this.outerWidth();
- } else {
- if ($cell.css('border-collapse') === 'collapse') {
- if (window.getComputedStyle) {
- width = parseFloat( window.getComputedStyle($this[0], null).width );
- } else {
- // ie8 only
- border = parseFloat( $this.css('border-width') );
- width = $this.outerWidth() - parseFloat( $this.css('padding-left') ) - parseFloat( $this.css('padding-right') ) - border;
- }
- } else {
- width = $this.width();
- }
- }
- $cell.css({
- 'width': width,
- 'min-width': width,
- 'max-width': width
- });
- }
- },
- resizeHeader = function() {
- stickyOffset = $stickyOffset.length ? $stickyOffset.height() || 0 : parseInt(wo.stickyHeaders_offset, 10) || 0;
- spacing = 0;
- $stickyWrap.css({
- left : $attach.length ? parseInt($attach.css('padding-left'), 10) || 0 :
- $table.offset().left - parseInt($table.css('margin-left'), 10) - $xScroll.scrollLeft() - spacing,
- width: $table.outerWidth()
- });
- setWidth( $table, $stickyTable );
- setWidth( $header, $stickyCells );
- },
- scrollSticky = function( resizing ) {
- if (!$table.is(':visible')) { return; } // fixes #278
- // Detect nested tables - fixes #724
- nestedStickyTop = $nestedSticky.length ? $nestedSticky.offset().top - $yScroll.scrollTop() + $nestedSticky.height() : 0;
- var offset = $table.offset(),
- yWindow = $.isWindow( $yScroll[0] ), // $.isWindow needs jQuery 1.4.3
- xWindow = $.isWindow( $xScroll[0] ),
- attachTop = $attach.length ?
- ( yWindow ? $yScroll.scrollTop() : $yScroll.offset().top ) :
- $yScroll.scrollTop(),
- captionHeight = wo.stickyHeaders_includeCaption ? 0 : $table.children( 'caption' ).height() || 0,
- scrollTop = attachTop + stickyOffset + nestedStickyTop - captionHeight,
- tableHeight = $table.height() - ($stickyWrap.height() + ($tfoot.height() || 0)) - captionHeight,
- isVisible = ( scrollTop > offset.top ) && ( scrollTop < offset.top + tableHeight ) ? 'visible' : 'hidden',
- cssSettings = { visibility : isVisible };
- if ($attach.length) {
- cssSettings.top = yWindow ? scrollTop - $attach.offset().top : $attach.scrollTop();
- }
- if (xWindow) {
- // adjust when scrolling horizontally - fixes issue #143
- cssSettings.left = $table.offset().left - parseInt($table.css('margin-left'), 10) - $xScroll.scrollLeft() - spacing;
- }
- if ($nestedSticky.length) {
- cssSettings.top = ( cssSettings.top || 0 ) + stickyOffset + nestedStickyTop;
- }
- $stickyWrap
- .removeClass( ts.css.stickyVis + ' ' + ts.css.stickyHide )
- .addClass( isVisible === 'visible' ? ts.css.stickyVis : ts.css.stickyHide )
- .css(cssSettings);
- if (isVisible !== laststate || resizing) {
- // make sure the column widths match
- resizeHeader();
- laststate = isVisible;
- }
- };
- // only add a position relative if a position isn't already defined
- if ($attach.length && !$attach.css('position')) {
- $attach.css('position', 'relative');
- }
- // fix clone ID, if it exists - fixes #271
- if ($stickyTable.attr('id')) { $stickyTable[0].id += wo.stickyHeaders_cloneId; }
- // clear out cloned table, except for sticky header
- // include caption & filter row (fixes #126 & #249) - don't remove cells to get correct cell indexing
- $stickyTable.find('thead:gt(0), tr.sticky-false').hide();
- $stickyTable.find('tbody, tfoot').remove();
- $stickyTable.find('caption').toggle(wo.stickyHeaders_includeCaption);
- // issue #172 - find td/th in sticky header
- $stickyCells = $stickyThead.children().children();
- $stickyTable.css({ height:0, width:0, margin: 0 });
- // remove resizable block
- $stickyCells.find('.' + ts.css.resizer).remove();
- // update sticky header class names to match real header after sorting
- $table
- .addClass('hasStickyHeaders')
- .bind('pagerComplete' + namespace, function() {
- resizeHeader();
- });
-
- ts.bindEvents(table, $stickyThead.children().children('.' + ts.css.header));
-
- // add stickyheaders AFTER the table. If the table is selected by ID, the original one (first) will be returned.
- $table.after( $stickyWrap );
-
- // onRenderHeader is defined, we need to do something about it (fixes #641)
- if (c.onRenderHeader) {
- $t = $stickyThead.children('tr').children();
- len = $t.length;
- for ( index = 0; index < len; index++ ) {
- // send second parameter
- c.onRenderHeader.apply( $t.eq( index ), [ index, c, $stickyTable ] );
- }
- }
-
- // make it sticky!
- $xScroll.add($yScroll)
- .unbind( ('scroll resize '.split(' ').join( namespace )).replace(/\s+/g, ' ') )
- .bind('scroll resize '.split(' ').join( namespace ), function( event ) {
- scrollSticky( event.type === 'resize' );
- });
- c.$table
- .unbind('stickyHeadersUpdate' + namespace)
- .bind('stickyHeadersUpdate' + namespace, function(){
- scrollSticky( true );
- });
-
- if (wo.stickyHeaders_addResizeEvent) {
- ts.addHeaderResizeEvent(table);
- }
-
- // look for filter widget
- if ($table.hasClass('hasFilters') && wo.filter_columnFilters) {
- // scroll table into view after filtering, if sticky header is active - #482
- $table.bind('filterEnd' + namespace, function() {
- // $(':focus') needs jQuery 1.6+
- var $td = $(document.activeElement).closest('td'),
- column = $td.parent().children().index($td);
- // only scroll if sticky header is active
- if ($stickyWrap.hasClass(ts.css.stickyVis) && wo.stickyHeaders_filteredToTop) {
- // scroll to original table (not sticky clone)
- window.scrollTo(0, $table.position().top);
- // give same input/select focus; check if c.$filters exists; fixes #594
- if (column >= 0 && c.$filters) {
- c.$filters.eq(column).find('a, select, input').filter(':visible').focus();
- }
- }
- });
- ts.filter.bindSearch( $table, $stickyCells.find('.' + ts.css.filter) );
- // support hideFilters
- if (wo.filter_hideFilters) {
- ts.filter.hideFilters(c, $stickyTable);
- }
- }
-
- // resize table (Firefox)
- if (wo.stickyHeaders_addResizeEvent) {
- $table.bind('resize' + c.namespace + 'stickyheaders', function() {
- resizeHeader();
- });
- }
-
- $table.triggerHandler('stickyHeadersInit');
-
- },
- remove: function(table, c, wo) {
- var namespace = c.namespace + 'stickyheaders ';
- c.$table
- .removeClass('hasStickyHeaders')
- .unbind( ('pagerComplete resize filterEnd stickyHeadersUpdate '.split(' ').join(namespace)).replace(/\s+/g, ' ') )
- .next('.' + ts.css.stickyWrap).remove();
- if (wo.$sticky && wo.$sticky.length) { wo.$sticky.remove(); } // remove cloned table
- $(window)
- .add(wo.stickyHeaders_xScroll)
- .add(wo.stickyHeaders_yScroll)
- .add(wo.stickyHeaders_attachTo)
- .unbind( ('scroll resize '.split(' ').join(namespace)).replace(/\s+/g, ' ') );
- ts.addHeaderResizeEvent(table, true);
- }
- });
-
-})(jQuery, window);
-
-/*! Widget: resizable - updated 5/16/2015 (v2.26.1) */
-/*jshint browser:true, jquery:true, unused:false */
-;(function ($, window) {
- 'use strict';
- var ts = $.tablesorter || {};
-
- $.extend(ts.css, {
- resizableContainer : 'tablesorter-resizable-container',
- resizableHandle : 'tablesorter-resizable-handle',
- resizableNoSelect : 'tablesorter-disableSelection',
- resizableStorage : 'tablesorter-resizable'
- });
-
- // Add extra scroller css
- $(function(){
- var s = '';
- $(s).appendTo('body');
- });
-
- ts.resizable = {
- init : function( c, wo ) {
- if ( c.$table.hasClass( 'hasResizable' ) ) { return; }
- c.$table.addClass( 'hasResizable' );
-
- var noResize, $header, column, storedSizes, tmp,
- $table = c.$table,
- $parent = $table.parent(),
- marginTop = parseInt( $table.css( 'margin-top' ), 10 ),
-
- // internal variables
- vars = wo.resizable_vars = {
- useStorage : ts.storage && wo.resizable !== false,
- $wrap : $parent,
- mouseXPosition : 0,
- $target : null,
- $next : null,
- overflow : $parent.css('overflow') === 'auto' ||
- $parent.css('overflow') === 'scroll' ||
- $parent.css('overflow-x') === 'auto' ||
- $parent.css('overflow-x') === 'scroll',
- storedSizes : []
- };
-
- // set default widths
- ts.resizableReset( c.table, true );
-
- // now get measurements!
- vars.tableWidth = $table.width();
- // attempt to autodetect
- vars.fullWidth = Math.abs( $parent.width() - vars.tableWidth ) < 20;
-
- /*
- // Hacky method to determine if table width is set to 'auto'
- // http://stackoverflow.com/a/20892048/145346
- if ( !vars.fullWidth ) {
- tmp = $table.width();
- $header = $table.wrap('
').parent(); // temp variable
- storedSizes = parseInt( $table.css( 'margin-left' ), 10 ) || 0;
- $table.css( 'margin-left', storedSizes + 50 );
- vars.tableWidth = $header.width() > tmp ? 'auto' : tmp;
- $table.css( 'margin-left', storedSizes ? storedSizes : '' );
- $header = null;
- $table.unwrap('');
- }
- */
-
- if ( vars.useStorage && vars.overflow ) {
- // save table width
- ts.storage( c.table, 'tablesorter-table-original-css-width', vars.tableWidth );
- tmp = ts.storage( c.table, 'tablesorter-table-resized-width' ) || 'auto';
- ts.resizable.setWidth( $table, tmp, true );
- }
- wo.resizable_vars.storedSizes = storedSizes = ( vars.useStorage ?
- ts.storage( c.table, ts.css.resizableStorage ) :
- [] ) || [];
- ts.resizable.setWidths( c, wo, storedSizes );
- ts.resizable.updateStoredSizes( c, wo );
-
- wo.$resizable_container = $( '' )
- .css({ top : marginTop })
- .insertBefore( $table );
- // add container
- for ( column = 0; column < c.columns; column++ ) {
- $header = c.$headerIndexed[ column ];
- tmp = ts.getColumnData( c.table, c.headers, column );
- noResize = ts.getData( $header, tmp, 'resizable' ) === 'false';
- if ( !noResize ) {
- $( '
' )
- .appendTo( wo.$resizable_container )
- .attr({
- 'data-column' : column,
- 'unselectable' : 'on'
- })
- .data( 'header', $header )
- .bind( 'selectstart', false );
- }
- }
- ts.resizable.bindings( c, wo );
- },
-
- updateStoredSizes : function( c, wo ) {
- var column, $header,
- len = c.columns,
- vars = wo.resizable_vars;
- vars.storedSizes = [];
- for ( column = 0; column < len; column++ ) {
- $header = c.$headerIndexed[ column ];
- vars.storedSizes[ column ] = $header.is(':visible') ? $header.width() : 0;
- }
- },
-
- setWidth : function( $el, width, overflow ) {
- // overflow tables need min & max width set as well
- $el.css({
- 'width' : width,
- 'min-width' : overflow ? width : '',
- 'max-width' : overflow ? width : ''
- });
- },
-
- setWidths : function( c, wo, storedSizes ) {
- var column, $temp,
- vars = wo.resizable_vars,
- $extra = $( c.namespace + '_extra_headers' ),
- $col = c.$table.children( 'colgroup' ).children( 'col' );
- storedSizes = storedSizes || vars.storedSizes || [];
- // process only if table ID or url match
- if ( storedSizes.length ) {
- for ( column = 0; column < c.columns; column++ ) {
- // set saved resizable widths
- ts.resizable.setWidth( c.$headerIndexed[ column ], storedSizes[ column ], vars.overflow );
- if ( $extra.length ) {
- // stickyHeaders needs to modify min & max width as well
- $temp = $extra.eq( column ).add( $col.eq( column ) );
- ts.resizable.setWidth( $temp, storedSizes[ column ], vars.overflow );
- }
- }
- $temp = $( c.namespace + '_extra_table' );
- if ( $temp.length && !ts.hasWidget( c.table, 'scroller' ) ) {
- ts.resizable.setWidth( $temp, c.$table.outerWidth(), vars.overflow );
- }
- }
- },
-
- setHandlePosition : function( c, wo ) {
- var startPosition,
- tableHeight = c.$table.height(),
- $handles = wo.$resizable_container.children(),
- handleCenter = Math.floor( $handles.width() / 2 );
-
- if ( ts.hasWidget( c.table, 'scroller' ) ) {
- tableHeight = 0;
- c.$table.closest( '.' + ts.css.scrollerWrap ).children().each(function(){
- var $this = $(this);
- // center table has a max-height set
- tableHeight += $this.filter('[style*="height"]').length ? $this.height() : $this.children('table').height();
- });
- }
- // subtract out table left position from resizable handles. Fixes #864
- startPosition = c.$table.position().left;
- $handles.each( function() {
- var $this = $(this),
- column = parseInt( $this.attr( 'data-column' ), 10 ),
- columns = c.columns - 1,
- $header = $this.data( 'header' );
- if ( !$header ) { return; } // see #859
- if ( !$header.is(':visible') ) {
- $this.hide();
- } else if ( column < columns || column === columns && wo.resizable_addLastColumn ) {
- $this.css({
- display: 'inline-block',
- height : tableHeight,
- left : $header.position().left - startPosition + $header.outerWidth() - handleCenter
- });
- }
- });
- },
-
- // prevent text selection while dragging resize bar
- toggleTextSelection : function( c, wo, toggle ) {
- var namespace = c.namespace + 'tsresize';
- wo.resizable_vars.disabled = toggle;
- $( 'body' ).toggleClass( ts.css.resizableNoSelect, toggle );
- if ( toggle ) {
- $( 'body' )
- .attr( 'unselectable', 'on' )
- .bind( 'selectstart' + namespace, false );
- } else {
- $( 'body' )
- .removeAttr( 'unselectable' )
- .unbind( 'selectstart' + namespace );
- }
- },
-
- bindings : function( c, wo ) {
- var namespace = c.namespace + 'tsresize';
- wo.$resizable_container.children().bind( 'mousedown', function( event ) {
- // save header cell and mouse position
- var column,
- vars = wo.resizable_vars,
- $extras = $( c.namespace + '_extra_headers' ),
- $header = $( event.target ).data( 'header' );
-
- column = parseInt( $header.attr( 'data-column' ), 10 );
- vars.$target = $header = $header.add( $extras.filter('[data-column="' + column + '"]') );
- vars.target = column;
-
- // if table is not as wide as it's parent, then resize the table
- vars.$next = event.shiftKey || wo.resizable_targetLast ?
- $header.parent().children().not( '.resizable-false' ).filter( ':last' ) :
- $header.nextAll( ':not(.resizable-false)' ).eq( 0 );
-
- column = parseInt( vars.$next.attr( 'data-column' ), 10 );
- vars.$next = vars.$next.add( $extras.filter('[data-column="' + column + '"]') );
- vars.next = column;
-
- vars.mouseXPosition = event.pageX;
- ts.resizable.updateStoredSizes( c, wo );
- ts.resizable.toggleTextSelection(c, wo, true );
- });
-
- $( document )
- .bind( 'mousemove' + namespace, function( event ) {
- var vars = wo.resizable_vars;
- // ignore mousemove if no mousedown
- if ( !vars.disabled || vars.mouseXPosition === 0 || !vars.$target ) { return; }
- if ( wo.resizable_throttle ) {
- clearTimeout( vars.timer );
- vars.timer = setTimeout( function() {
- ts.resizable.mouseMove( c, wo, event );
- }, isNaN( wo.resizable_throttle ) ? 5 : wo.resizable_throttle );
- } else {
- ts.resizable.mouseMove( c, wo, event );
- }
- })
- .bind( 'mouseup' + namespace, function() {
- if (!wo.resizable_vars.disabled) { return; }
- ts.resizable.toggleTextSelection( c, wo, false );
- ts.resizable.stopResize( c, wo );
- ts.resizable.setHandlePosition( c, wo );
- });
-
- // resizeEnd event triggered by scroller widget
- $( window ).bind( 'resize' + namespace + ' resizeEnd' + namespace, function() {
- ts.resizable.setHandlePosition( c, wo );
- });
-
- // right click to reset columns to default widths
- c.$table
- .bind( 'columnUpdate' + namespace, function() {
- ts.resizable.setHandlePosition( c, wo );
- })
- .find( 'thead:first' )
- .add( $( c.namespace + '_extra_table' ).find( 'thead:first' ) )
- .bind( 'contextmenu' + namespace, function() {
- // $.isEmptyObject() needs jQuery 1.4+; allow right click if already reset
- var allowClick = wo.resizable_vars.storedSizes.length === 0;
- ts.resizableReset( c.table );
- ts.resizable.setHandlePosition( c, wo );
- wo.resizable_vars.storedSizes = [];
- return allowClick;
- });
-
- },
-
- mouseMove : function( c, wo, event ) {
- if ( wo.resizable_vars.mouseXPosition === 0 || !wo.resizable_vars.$target ) { return; }
- // resize columns
- var column,
- total = 0,
- vars = wo.resizable_vars,
- $next = vars.$next,
- tar = vars.storedSizes[ vars.target ],
- leftEdge = event.pageX - vars.mouseXPosition;
- if ( vars.overflow ) {
- if ( tar + leftEdge > 0 ) {
- vars.storedSizes[ vars.target ] += leftEdge;
- ts.resizable.setWidth( vars.$target, vars.storedSizes[ vars.target ], true );
- // update the entire table width
- for ( column = 0; column < c.columns; column++ ) {
- total += vars.storedSizes[ column ];
- }
- ts.resizable.setWidth( c.$table.add( $( c.namespace + '_extra_table' ) ), total );
- }
- if ( !$next.length ) {
- // if expanding right-most column, scroll the wrapper
- vars.$wrap[0].scrollLeft = c.$table.width();
- }
- } else if ( vars.fullWidth ) {
- vars.storedSizes[ vars.target ] += leftEdge;
- vars.storedSizes[ vars.next ] -= leftEdge;
- ts.resizable.setWidths( c, wo );
- } else {
- vars.storedSizes[ vars.target ] += leftEdge;
- ts.resizable.setWidths( c, wo );
- }
- vars.mouseXPosition = event.pageX;
- // dynamically update sticky header widths
- c.$table.triggerHandler('stickyHeadersUpdate');
- },
-
- stopResize : function( c, wo ) {
- var vars = wo.resizable_vars;
- ts.resizable.updateStoredSizes( c, wo );
- if ( vars.useStorage ) {
- // save all column widths
- ts.storage( c.table, ts.css.resizableStorage, vars.storedSizes );
- ts.storage( c.table, 'tablesorter-table-resized-width', c.$table.width() );
- }
- vars.mouseXPosition = 0;
- vars.$target = vars.$next = null;
- // will update stickyHeaders, just in case, see #912
- c.$table.triggerHandler('stickyHeadersUpdate');
- }
- };
-
- // this widget saves the column widths if
- // $.tablesorter.storage function is included
- // **************************
- ts.addWidget({
- id: 'resizable',
- priority: 40,
- options: {
- resizable : true, // save column widths to storage
- resizable_addLastColumn : false,
- resizable_widths : [],
- resizable_throttle : false, // set to true (5ms) or any number 0-10 range
- resizable_targetLast : false,
- resizable_fullWidth : null
- },
- init: function(table, thisWidget, c, wo) {
- ts.resizable.init( c, wo );
- },
- format: function( table, c, wo ) {
- ts.resizable.setHandlePosition( c, wo );
- },
- remove: function( table, c, wo, refreshing ) {
- if (wo.$resizable_container) {
- var namespace = c.namespace + 'tsresize';
- c.$table.add( $( c.namespace + '_extra_table' ) )
- .removeClass('hasResizable')
- .children( 'thead' )
- .unbind( 'contextmenu' + namespace );
-
- wo.$resizable_container.remove();
- ts.resizable.toggleTextSelection( c, wo, false );
- ts.resizableReset( table, refreshing );
- $( document ).unbind( 'mousemove' + namespace + ' mouseup' + namespace );
- }
- }
- });
-
- ts.resizableReset = function( table, refreshing ) {
- $( table ).each(function(){
- var index, $t,
- c = this.config,
- wo = c && c.widgetOptions,
- vars = wo.resizable_vars;
- if ( table && c && c.$headerIndexed.length ) {
- // restore the initial table width
- if ( vars.overflow && vars.tableWidth ) {
- ts.resizable.setWidth( c.$table, vars.tableWidth, true );
- if ( vars.useStorage ) {
- ts.storage( table, 'tablesorter-table-resized-width', 'auto' );
- }
- }
- for ( index = 0; index < c.columns; index++ ) {
- $t = c.$headerIndexed[ index ];
- if ( wo.resizable_widths && wo.resizable_widths[ index ] ) {
- ts.resizable.setWidth( $t, wo.resizable_widths[ index ], vars.overflow );
- } else if ( !$t.hasClass( 'resizable-false' ) ) {
- // don't clear the width of any column that is not resizable
- ts.resizable.setWidth( $t, '', vars.overflow );
- }
- }
-
- // reset stickyHeader widths
- c.$table.triggerHandler( 'stickyHeadersUpdate' );
- if ( ts.storage && !refreshing ) {
- ts.storage( this, ts.css.resizableStorage, {} );
- }
- }
- });
- };
-
-})( jQuery, window );
-
-/*! Widget: saveSort - updated 10/31/2015 (v2.24.0) *//*
-* Requires tablesorter v2.16+
-* by Rob Garrison
-*/
-;(function ($) {
- 'use strict';
- var ts = $.tablesorter || {};
-
- // this widget saves the last sort only if the
- // saveSort widget option is true AND the
- // $.tablesorter.storage function is included
- // **************************
- ts.addWidget({
- id: 'saveSort',
- priority: 20,
- options: {
- saveSort : true
- },
- init: function(table, thisWidget, c, wo) {
- // run widget format before all other widgets are applied to the table
- thisWidget.format(table, c, wo, true);
- },
- format: function(table, c, wo, init) {
- var stored, time,
- $table = c.$table,
- saveSort = wo.saveSort !== false, // make saveSort active/inactive; default to true
- sortList = { 'sortList' : c.sortList };
- if (c.debug) {
- time = new Date();
- }
- if ($table.hasClass('hasSaveSort')) {
- if (saveSort && table.hasInitialized && ts.storage) {
- ts.storage( table, 'tablesorter-savesort', sortList );
- if (c.debug) {
- console.log('saveSort widget: Saving last sort: ' + c.sortList + ts.benchmark(time));
- }
- }
- } else {
- // set table sort on initial run of the widget
- $table.addClass('hasSaveSort');
- sortList = '';
- // get data
- if (ts.storage) {
- stored = ts.storage( table, 'tablesorter-savesort' );
- sortList = (stored && stored.hasOwnProperty('sortList') && $.isArray(stored.sortList)) ? stored.sortList : '';
- if (c.debug) {
- console.log('saveSort: Last sort loaded: "' + sortList + '"' + ts.benchmark(time));
- }
- $table.bind('saveSortReset', function(event) {
- event.stopPropagation();
- ts.storage( table, 'tablesorter-savesort', '' );
- });
- }
- // init is true when widget init is run, this will run this widget before all other widgets have initialized
- // this method allows using this widget in the original tablesorter plugin; but then it will run all widgets twice.
- if (init && sortList && sortList.length > 0) {
- c.sortList = sortList;
- } else if (table.hasInitialized && sortList && sortList.length > 0) {
- // update sort change
- ts.sortOn( c, sortList );
- }
- }
- },
- remove: function(table, c) {
- c.$table.removeClass('hasSaveSort');
- // clear storage
- if (ts.storage) { ts.storage( table, 'tablesorter-savesort', '' ); }
- }
- });
-
-})(jQuery);
-
-return $.tablesorter;
-}));
diff --git a/webif/html/lib/jquery.plugin/tablesorter2/jquery.tablesorter.widgets.min.js b/webif/html/lib/jquery.plugin/tablesorter2/jquery.tablesorter.widgets.min.js
new file mode 100644
index 0000000..4d985c3
--- /dev/null
+++ b/webif/html/lib/jquery.plugin/tablesorter2/jquery.tablesorter.widgets.min.js
@@ -0,0 +1,3 @@
+/*! tablesorter (FORK) - updated 01-28-2017 (v2.28.5)*/
+!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof module&&"object"==typeof module.exports?module.exports=a(require("jquery")):a(jQuery)}(function(a){return function(a,b,c){"use strict";var d=a.tablesorter||{};d.storage=function(e,f,g,h){e=a(e)[0];var i,j,k,l=!1,m={},n=e.config,o=n&&n.widgetOptions,p=h&&h.useSessionStorage||o&&o.storage_useSessionStorage?"sessionStorage":"localStorage",q=a(e),r=h&&h.id||q.attr(h&&h.group||o&&o.storage_group||"data-table-group")||o&&o.storage_tableId||e.id||a(".tablesorter").index(q),s=h&&h.url||q.attr(h&&h.page||o&&o.storage_page||"data-table-page")||o&&o.storage_fixedUrl||n&&n.fixedUrl||b.location.pathname;if(a.extend(!0,d.defaults,{fixedUrl:"",widgetOptions:{storage_fixedUrl:"",storage_group:"",storage_page:"",storage_tableId:"",storage_useSessionStorage:""}}),p in b)try{b[p].setItem("_tmptest","temp"),l=!0,b[p].removeItem("_tmptest")}catch(a){n&&n.debug&&console.warn(p+" is not supported in this browser")}return a.parseJSON&&(l?m=a.parseJSON(b[p][f]||"null")||{}:(j=c.cookie.split(/[;\s|=]/),i=a.inArray(f,j)+1,m=0!==i?a.parseJSON(j[i]||"null")||{}:{})),"undefined"!=typeof g&&b.JSON&&JSON.hasOwnProperty("stringify")?(m[s]||(m[s]={}),m[s][r]=g,l?b[p][f]=JSON.stringify(m):(k=new Date,k.setTime(k.getTime()+31536e6),c.cookie=f+"="+JSON.stringify(m).replace(/\"/g,'"')+"; expires="+k.toGMTString()+"; path=/"),void 0):m&&m[s]?m[s][r]:""}}(a,window,document),function(a){"use strict";var b=a.tablesorter||{};b.themes={bootstrap:{table:"table table-bordered table-striped",caption:"caption",header:"bootstrap-header",sortNone:"",sortAsc:"",sortDesc:"",active:"",hover:"",icons:"",iconSortNone:"bootstrap-icon-unsorted",iconSortAsc:"icon-chevron-up glyphicon glyphicon-chevron-up",iconSortDesc:"icon-chevron-down glyphicon glyphicon-chevron-down",filterRow:"",footerRow:"",footerCells:"",even:"",odd:""},jui:{table:"ui-widget ui-widget-content ui-corner-all",caption:"ui-widget-content",header:"ui-widget-header ui-corner-all ui-state-default",sortNone:"",sortAsc:"",sortDesc:"",active:"ui-state-active",hover:"ui-state-hover",icons:"ui-icon",iconSortNone:"ui-icon-carat-2-n-s ui-icon-caret-2-n-s",iconSortAsc:"ui-icon-carat-1-n ui-icon-caret-1-n",iconSortDesc:"ui-icon-carat-1-s ui-icon-caret-1-s",filterRow:"",footerRow:"",footerCells:"",even:"ui-widget-content",odd:"ui-state-default"}},a.extend(b.css,{wrapper:"tablesorter-wrapper"}),b.addWidget({id:"uitheme",priority:10,format:function(c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q,r,s=b.themes,t=d.$table.add(a(d.namespace+"_extra_table")),u=d.$headers.add(a(d.namespace+"_extra_headers")),v=d.theme||"jui",w=s[v]||{},x=a.trim([w.sortNone,w.sortDesc,w.sortAsc,w.active].join(" ")),y=a.trim([w.iconSortNone,w.iconSortDesc,w.iconSortAsc].join(" "));for(d.debug&&(j=new Date),t.hasClass("tablesorter-"+v)&&d.theme===d.appliedTheme&&e.uitheme_applied||(e.uitheme_applied=!0,o=s[d.appliedTheme]||{},r=!a.isEmptyObject(o),p=r?[o.sortNone,o.sortDesc,o.sortAsc,o.active].join(" "):"",q=r?[o.iconSortNone,o.iconSortDesc,o.iconSortAsc].join(" "):"",r&&(e.zebra[0]=a.trim(" "+e.zebra[0].replace(" "+o.even,"")),e.zebra[1]=a.trim(" "+e.zebra[1].replace(" "+o.odd,"")),d.$tbodies.children().removeClass([o.even,o.odd].join(" "))),w.even&&(e.zebra[0]+=" "+w.even),w.odd&&(e.zebra[1]+=" "+w.odd),t.children("caption").removeClass(o.caption||"").addClass(w.caption),m=t.removeClass((d.appliedTheme?"tablesorter-"+(d.appliedTheme||""):"")+" "+(o.table||"")).addClass("tablesorter-"+v+" "+(w.table||"")).children("tfoot"),d.appliedTheme=d.theme,m.length&&m.children("tr").removeClass(o.footerRow||"").addClass(w.footerRow).children("th, td").removeClass(o.footerCells||"").addClass(w.footerCells),u.removeClass((r?[o.header,o.hover,p].join(" "):"")||"").addClass(w.header).not(".sorter-false").unbind("mouseenter.tsuitheme mouseleave.tsuitheme").bind("mouseenter.tsuitheme mouseleave.tsuitheme",function(b){a(this)["mouseenter"===b.type?"addClass":"removeClass"](w.hover||"")}),u.each(function(){var c=a(this);c.find("."+b.css.wrapper).length||c.wrapInner('
')}),d.cssIcon&&u.find("."+b.css.icon).removeClass(r?[o.icons,q].join(" "):"").addClass(w.icons||""),b.hasWidget(d.table,"filter")&&(g=function(){t.children("thead").children("."+b.css.filterRow).removeClass(r?o.filterRow||"":"").addClass(w.filterRow||"")},e.filter_initialized?g():t.one("filterInit",function(){g()}))),f=0;f
1)))for(m=1;m=]/g,query:"(q|query)",wild01:/\?/g,wild0More:/\*/g,quote:/\"/g,isNeg1:/(>=?\s*-\d)/,isNeg2:/(<=?\s*\d)/},types:{or:function(d,e,f){if((c.orTest.test(e.iFilter)||c.orSplit.test(e.filter))&&!c.regex.test(e.filter)){var g,h,i,j,k=a.extend({},e),l=e.filter.split(c.orSplit),m=e.iFilter.split(c.orSplit),n=l.length;for(g=0;g=l:g>l:c.ltTest.test(f.iFilter)&&(h=c.lteTest.test(f.iFilter)?g<=l:g=0)))}return null},exact:function(d,e){if(c.exact.test(e.iFilter)){var f=e.iFilter.replace(c.exact,""),g=b.parseFilter(d,f,e)||"";return e.anyMatch?a.inArray(g,e.rowArray)>=0:g==e.iExact}return null},range:function(a,e){if(c.toTest.test(e.iFilter)){var f,g,h,i,j=a.table,k=e.index,l=e.parsed[k],m=e.iFilter.split(c.toSplit);return g=m[0].replace(d.regex.nondigit,"")||"",h=d.formatFloat(b.parseFilter(a,g,e),j),g=m[1].replace(d.regex.nondigit,"")||"",i=d.formatFloat(b.parseFilter(a,g,e),j),(l||"numeric"===a.parsers[k].type)&&(f=a.parsers[k].format(""+m[0],j,a.$headers.eq(k),k),h=""===f||isNaN(f)?h:f,f=a.parsers[k].format(""+m[1],j,a.$headers.eq(k),k),i=""===f||isNaN(f)?i:f),!l&&"numeric"!==a.parsers[k].type||isNaN(h)||isNaN(i)?(g=isNaN(e.iExact)?e.iExact.replace(d.regex.nondigit,""):e.iExact,f=d.formatFloat(g,j)):f=e.cache,h>i&&(g=h,h=i,i=g),f>=h&&f<=i||""===h||""===i}return null},wild:function(a,d){if(c.wildOrTest.test(d.iFilter)){var e=""+(b.parseFilter(a,d.iFilter,d)||"");!c.wildTest.test(e)&&d.nestedFilters&&(e=d.isMatch?e:"^("+e+")$");try{return new RegExp(e.replace(c.wild01,"\\S{1}").replace(c.wild0More,"\\S*"),a.widgetOptions.filter_ignoreCase?"i":"").test(d.exact)}catch(a){return null}}return null},fuzzy:function(a,d){if(c.fuzzyTest.test(d.iFilter)){var e,f=0,g=d.iExact.length,h=d.iFilter.slice(1),i=b.parseFilter(a,h,d)||"";for(e=0;e]=?/,gtTest:/>/,gteTest:/>=/,ltTest:/,lteTest:/<=/,notTest:/^\!/,wildOrTest:/[\?\*\|]/,wildTest:/\?\*/,fuzzyTest:/^~/,exactTest:/[=\"\|!]/}),l=o.$headers.filter(".filter-false, .parser-false").length,p.filter_columnFilters!==!1&&l!==o.$headers.length&&b.buildRow(f,o,p),i="addRows updateCell update updateRows updateComplete appendCache filterReset "+"filterResetSaved filterEnd search ".split(" ").join(o.namespace+"filter "),o.$table.bind(i,function(c,g){return l=p.filter_hideEmpty&&a.isEmptyObject(o.cache)&&!(o.delayInit&&"appendCache"===c.type),o.$table.find("."+e.filterRow).toggleClass(p.filter_filteredRow,l),/(search|filter)/.test(c.type)||(c.stopPropagation(),b.buildDefault(f,!0)),"filterReset"===c.type?(o.$table.find("."+e.filter).add(p.filter_$externalFilters).val(""),b.searching(f,[])):"filterResetSaved"===c.type?d.storage(f,"tablesorter-filters",""):"filterEnd"===c.type?b.buildDefault(f,!0):(g="search"===c.type?g:"updateComplete"===c.type?o.$table.data("lastSearch"):"",/(update|add)/.test(c.type)&&"updateComplete"!==c.type&&(o.lastCombinedFilter=null,o.lastSearch=[],setTimeout(function(){o.$table.triggerHandler("filterFomatterUpdate")},100)),b.searching(f,g,!0)),!1}),p.filter_reset&&(p.filter_reset instanceof a?p.filter_reset.click(function(){o.$table.triggerHandler("filterReset")}):a(p.filter_reset).length&&a(document).undelegate(p.filter_reset,"click"+o.namespace+"filter").delegate(p.filter_reset,"click"+o.namespace+"filter",function(){o.$table.triggerHandler("filterReset")})),p.filter_functions)for(k=0;k'+(j.data("placeholder")||j.attr("data-placeholder")||p.filter_placeholder.select||"")+"":"",l=h,i=h,h.indexOf(p.filter_selectSourceSeparator)>=0&&(l=h.split(p.filter_selectSourceSeparator),i=l[1],l=l[0]),g+="'+i+" ");o.$table.find("thead").find("select."+e.filter+'[data-column="'+k+'"]').append(g),i=p.filter_selectSource,m="function"==typeof i||d.getColumnData(f,i,k),m&&b.buildSelect(o.table,k,"",!0,j.hasClass(p.filter_onlyAvail))}b.buildDefault(f,!0),b.bindSearch(f,o.$table.find("."+e.filter),!0),p.filter_external&&b.bindSearch(f,p.filter_external),p.filter_hideFilters&&b.hideFilters(o),o.showProcessing&&(i="filterStart filterEnd ".split(" ").join(o.namespace+"filter "),o.$table.unbind(i.replace(d.regex.spaces," ")).bind(i,function(b,c){j=c?o.$table.find("."+e.header).filter("[data-column]").filter(function(){return""!==c[a(this).data("column")]}):"",d.isProcessing(f,"filterStart"===b.type,c?j:"")})),o.filteredRows=o.totalRows,i="tablesorter-initialized pagerBeforeInitialized ".split(" ").join(o.namespace+"filter "),o.$table.unbind(i.replace(d.regex.spaces," ")).bind(i,function(){b.completeInit(this)}),o.pager&&o.pager.initialized&&!p.filter_initialized?(o.$table.triggerHandler("filterFomatterUpdate"),setTimeout(function(){b.filterInitComplete(o)},100)):p.filter_initialized||b.completeInit(f)},completeInit:function(a){var c=a.config,e=c.widgetOptions,f=b.setDefaults(a,c,e)||[];f.length&&(c.delayInit&&""===f.join("")||d.setFilters(a,f,!0)),c.$table.triggerHandler("filterFomatterUpdate"),setTimeout(function(){e.filter_initialized||b.filterInitComplete(c)},100)},formatterUpdated:function(a,b){var c=a&&a.closest("table")[0].config.widgetOptions;c&&!c.filter_initialized&&(c.filter_formatterInit[b]=1)},filterInitComplete:function(c){var d,e,f=c.widgetOptions,g=0,h=function(){f.filter_initialized=!0,c.lastSearch=c.$table.data("lastSearch"),c.$table.triggerHandler("filterInit",c),b.findRows(c.table,c.lastSearch||[])};if(a.isEmptyObject(f.filter_formatter))h();else{for(e=f.filter_formatterInit.length,d=0;d';for(j=0;j1?' ");for(f.$filters=a(t+="
").appendTo(f.$table.children("thead").eq(0)).children("td"),j=0;j