Change the directory of Tablesorter from '_assets' to static 'assets'.
This commit is contained in:
191
assets/vendor/tablesorter/js/extras/jquery.quicksearch.js
vendored
Normal file
191
assets/vendor/tablesorter/js/extras/jquery.quicksearch.js
vendored
Normal file
@@ -0,0 +1,191 @@
|
||||
/* jQuery Quicksearch plugin
|
||||
by riklomas https://github.com/riklomas/quicksearch
|
||||
Modified to include childRows (for tablesorter)
|
||||
|
||||
See http://stackoverflow.com/q/20342203/145346 for
|
||||
more details
|
||||
*/
|
||||
(function($, window, document, undefined) {
|
||||
$.fn.quicksearch = function (target, opt) {
|
||||
|
||||
var timeout, cache, rowcache, jq_results, val = '', e = this, options = $.extend({
|
||||
delay: 100,
|
||||
selector: null,
|
||||
stripeRows: null,
|
||||
loader: null,
|
||||
noResults: '',
|
||||
childRow: 'tablesorter-childRow', // include child row with search results
|
||||
matchedResultsCount: 0,
|
||||
bind: 'keyup',
|
||||
onBefore: function () {
|
||||
return;
|
||||
},
|
||||
onAfter: function () {
|
||||
return;
|
||||
},
|
||||
show: function () {
|
||||
this.style.display = "";
|
||||
},
|
||||
hide: function () {
|
||||
this.style.display = "none";
|
||||
},
|
||||
prepareQuery: function (val) {
|
||||
return val.toLowerCase().split(' ');
|
||||
},
|
||||
testQuery: function (query, txt, _row) {
|
||||
for (var i = 0; i < query.length; i += 1) {
|
||||
if (txt.indexOf(query[i]) === -1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}, opt);
|
||||
|
||||
this.go = function () {
|
||||
|
||||
var i = 0,
|
||||
numMatchedRows = 0,
|
||||
noresults = true,
|
||||
query = options.prepareQuery(val),
|
||||
val_empty = (val.replace(' ', '').length === 0);
|
||||
|
||||
for (var i = 0, len = rowcache.length; i < len; i++) {
|
||||
if (val_empty || options.testQuery(query, cache[i], rowcache[i]) ||
|
||||
($(rowcache[i]).hasClass(options.childRow) && $(rowcache[i > 1 ? i - 1 : 0]).is(':visible'))) {
|
||||
options.show.apply(rowcache[i]);
|
||||
noresults = false;
|
||||
numMatchedRows++;
|
||||
} else {
|
||||
options.hide.apply(rowcache[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (noresults) {
|
||||
this.results(false);
|
||||
} else {
|
||||
this.results(true);
|
||||
this.stripe();
|
||||
}
|
||||
|
||||
this.matchedResultsCount = numMatchedRows;
|
||||
this.loader(false);
|
||||
options.onAfter();
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/*
|
||||
* External API so that users can perform search programatically.
|
||||
* */
|
||||
this.search = function (submittedVal) {
|
||||
val = submittedVal;
|
||||
e.trigger();
|
||||
};
|
||||
|
||||
/*
|
||||
* External API to get the number of matched results as seen in
|
||||
* https://github.com/ruiz107/quicksearch/commit/f78dc440b42d95ce9caed1d087174dd4359982d6
|
||||
* */
|
||||
this.currentMatchedResults = function() {
|
||||
return this.matchedResultsCount;
|
||||
};
|
||||
|
||||
this.stripe = function () {
|
||||
|
||||
if (typeof options.stripeRows === "object" && options.stripeRows !== null)
|
||||
{
|
||||
var joined = options.stripeRows.join(' ');
|
||||
var stripeRows_length = options.stripeRows.length;
|
||||
|
||||
jq_results.not(':hidden').each(function (i) {
|
||||
$(this).removeClass(joined).addClass(options.stripeRows[i % stripeRows_length]);
|
||||
});
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
this.strip_html = function (input) {
|
||||
var output = input.replace(new RegExp('<[^<]+\>', 'g'), "");
|
||||
output = $.trim(output.toLowerCase());
|
||||
return output;
|
||||
};
|
||||
|
||||
this.results = function (bool) {
|
||||
if (typeof options.noResults === "string" && options.noResults !== "") {
|
||||
if (bool) {
|
||||
$(options.noResults).hide();
|
||||
} else {
|
||||
$(options.noResults).show();
|
||||
}
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
this.loader = function (bool) {
|
||||
if (typeof options.loader === "string" && options.loader !== "") {
|
||||
(bool) ? $(options.loader).show() : $(options.loader).hide();
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
this.cache = function () {
|
||||
|
||||
jq_results = $(target);
|
||||
|
||||
if (typeof options.noResults === "string" && options.noResults !== "") {
|
||||
jq_results = jq_results.not(options.noResults);
|
||||
}
|
||||
|
||||
var t = (typeof options.selector === "string") ?
|
||||
jq_results.find(options.selector) : $(target).not(options.noResults);
|
||||
cache = t.map(function () {
|
||||
return e.strip_html(this.innerHTML);
|
||||
});
|
||||
|
||||
rowcache = jq_results.map(function () {
|
||||
return this;
|
||||
});
|
||||
|
||||
/*
|
||||
* Modified fix for sync-ing "val".
|
||||
* Original fix https://github.com/michaellwest/quicksearch/commit/4ace4008d079298a01f97f885ba8fa956a9703d1
|
||||
* */
|
||||
val = val || this.val() || "";
|
||||
|
||||
return this.go();
|
||||
};
|
||||
|
||||
this.trigger = function () {
|
||||
this.loader(true);
|
||||
options.onBefore();
|
||||
|
||||
window.clearTimeout(timeout);
|
||||
timeout = window.setTimeout(function () {
|
||||
e.go();
|
||||
}, options.delay);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
this.cache();
|
||||
this.results(true);
|
||||
this.stripe();
|
||||
this.loader(false);
|
||||
|
||||
return this.each(function () {
|
||||
|
||||
/*
|
||||
* Changed from .bind to .on.
|
||||
* */
|
||||
$(this).on(options.bind, function () {
|
||||
|
||||
val = $(this).val();
|
||||
e.trigger();
|
||||
});
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
}(jQuery, this, document));
|
1026
assets/vendor/tablesorter/js/extras/semver-mod.js
vendored
Normal file
1026
assets/vendor/tablesorter/js/extras/semver-mod.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1011
assets/vendor/tablesorter/js/extras/semver.js
vendored
Normal file
1011
assets/vendor/tablesorter/js/extras/semver.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
116
assets/vendor/tablesorter/js/jquery.metadata.js
vendored
Normal file
116
assets/vendor/tablesorter/js/jquery.metadata.js
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Metadata - jQuery plugin for parsing metadata from elements
|
||||
*
|
||||
* Copyright (c) 2006 John Resig, Yehuda Katz, Jörn Zaefferer, Paul McLanahan
|
||||
*
|
||||
* Dual licensed under the MIT and GPL licenses:
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
* http://www.gnu.org/licenses/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Sets the type of metadata to use. Metadata is encoded in JSON, and each property
|
||||
* in the JSON will become a property of the element itself.
|
||||
*
|
||||
* There are three supported types of metadata storage:
|
||||
*
|
||||
* attr: Inside an attribute. The name parameter indicates *which* attribute.
|
||||
*
|
||||
* class: Inside the class attribute, wrapped in curly braces: { }
|
||||
*
|
||||
* elem: Inside a child element (e.g. a script tag). The
|
||||
* name parameter indicates *which* element.
|
||||
*
|
||||
* The metadata for an element is loaded the first time the element is accessed via jQuery.
|
||||
*
|
||||
* As a result, you can define the metadata type, use $(expr) to load the metadata into the elements
|
||||
* matched by expr, then redefine the metadata type and run another $(expr) for other elements.
|
||||
*
|
||||
* @name $.metadata.setType
|
||||
*
|
||||
* @example <p id="one" class="some_class {item_id: 1, item_label: 'Label'}">This is a p</p>
|
||||
* @before $.metadata.setType("class")
|
||||
* @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
|
||||
* @desc Reads metadata from the class attribute
|
||||
*
|
||||
* @example <p id="one" class="some_class" data="{item_id: 1, item_label: 'Label'}">This is a p</p>
|
||||
* @before $.metadata.setType("attr", "data")
|
||||
* @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
|
||||
* @desc Reads metadata from a "data" attribute
|
||||
*
|
||||
* @example <p id="one" class="some_class"><script>{item_id: 1, item_label: 'Label'}</script>This is a p</p>
|
||||
* @before $.metadata.setType("elem", "script")
|
||||
* @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
|
||||
* @desc Reads metadata from a nested script element
|
||||
*
|
||||
* @param String type The encoding type
|
||||
* @param String name The name of the attribute to be used to get metadata (optional)
|
||||
* @cat Plugins/Metadata
|
||||
* @descr Sets the type of encoding to be used when loading metadata for the first time
|
||||
* @type undefined
|
||||
* @see metadata()
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
|
||||
$.extend({
|
||||
metadata : {
|
||||
defaults : {
|
||||
type: 'class',
|
||||
name: 'metadata',
|
||||
cre: /(\{.*\})/,
|
||||
single: 'metadata'
|
||||
},
|
||||
setType: function( type, name ){
|
||||
this.defaults.type = type;
|
||||
this.defaults.name = name;
|
||||
},
|
||||
get: function( elem, opts ){
|
||||
var data, m, e, attr,
|
||||
settings = $.extend({},this.defaults,opts);
|
||||
// check for empty string in single property
|
||||
if ( !settings.single.length ) { settings.single = 'metadata'; }
|
||||
|
||||
data = $.data(elem, settings.single);
|
||||
// returned cached data if it already exists
|
||||
if ( data ) { return data; }
|
||||
|
||||
data = "{}";
|
||||
|
||||
if ( settings.type === "class" ) {
|
||||
m = settings.cre.exec( elem.className );
|
||||
if ( m ) { data = m[1]; }
|
||||
} else if ( settings.type === "elem" ) {
|
||||
if( !elem.getElementsByTagName ) { return undefined; }
|
||||
e = elem.getElementsByTagName(settings.name);
|
||||
if ( e.length ) { data = $.trim(e[0].innerHTML); }
|
||||
} else if ( elem.getAttribute !== undefined ) {
|
||||
attr = elem.getAttribute( settings.name );
|
||||
if ( attr ) { data = attr; }
|
||||
}
|
||||
|
||||
if ( data.indexOf( '{' ) <0 ) { data = "{" + data + "}"; }
|
||||
|
||||
data = eval("(" + data + ")");
|
||||
|
||||
$.data( elem, settings.single, data );
|
||||
return data;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Returns the metadata object for the first member of the jQuery object.
|
||||
*
|
||||
* @name metadata
|
||||
* @descr Returns element's metadata object
|
||||
* @param Object opts An object contianing settings to override the defaults
|
||||
* @type jQuery
|
||||
* @cat Plugins/Metadata
|
||||
*/
|
||||
$.fn.metadata = function( opts ){
|
||||
return $.metadata.get( this[0], opts );
|
||||
};
|
||||
|
||||
})(jQuery);
|
1694
assets/vendor/tablesorter/js/jquery.tablesorter.js
vendored
Normal file
1694
assets/vendor/tablesorter/js/jquery.tablesorter.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
5
assets/vendor/tablesorter/js/jquery.tablesorter.min.js
vendored
Normal file
5
assets/vendor/tablesorter/js/jquery.tablesorter.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1130
assets/vendor/tablesorter/js/jquery.tablesorter.widgets-filter-formatter.js
vendored
Normal file
1130
assets/vendor/tablesorter/js/jquery.tablesorter.widgets-filter-formatter.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
6
assets/vendor/tablesorter/js/jquery.tablesorter.widgets-filter-formatter.min.js
vendored
Normal file
6
assets/vendor/tablesorter/js/jquery.tablesorter.widgets-filter-formatter.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1535
assets/vendor/tablesorter/js/jquery.tablesorter.widgets.js
vendored
Normal file
1535
assets/vendor/tablesorter/js/jquery.tablesorter.widgets.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
17
assets/vendor/tablesorter/js/jquery.tablesorter.widgets.min.js
vendored
Normal file
17
assets/vendor/tablesorter/js/jquery.tablesorter.widgets.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
34
assets/vendor/tablesorter/js/parsers/parser-date-iso8601.js
vendored
Normal file
34
assets/vendor/tablesorter/js/parsers/parser-date-iso8601.js
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
/*! ISO-8601 date parser
|
||||
* This parser will work with dates in ISO8601 format
|
||||
* 2013-02-18T18:18:44+00:00
|
||||
* Written by Sean Ellingham :https://github.com/seanellingham
|
||||
* See https://github.com/Mottie/tablesorter/issues/247
|
||||
*/
|
||||
/*global jQuery: false */
|
||||
;(function($){
|
||||
"use strict";
|
||||
|
||||
var iso8601date = /^([0-9]{4})(-([0-9]{2})(-([0-9]{2})(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?$/;
|
||||
$.tablesorter.addParser({
|
||||
id : 'iso8601date',
|
||||
is : function(s) {
|
||||
return s.match(iso8601date);
|
||||
},
|
||||
format : function(s) {
|
||||
var result = s.match(iso8601date);
|
||||
if (result) {
|
||||
var date = new Date(result[1], 0, 1);
|
||||
if (result[3]) { date.setMonth(result[3] - 1); }
|
||||
if (result[5]) { date.setDate(result[5]); }
|
||||
if (result[7]) { date.setHours(result[7]); }
|
||||
if (result[8]) { date.setMinutes(result[8]); }
|
||||
if (result[10]) { date.setSeconds(result[10]); }
|
||||
if (result[12]) { date.setMilliseconds(Number('0.' + result[12]) * 1000); }
|
||||
return date;
|
||||
}
|
||||
return s;
|
||||
},
|
||||
type : 'numeric'
|
||||
});
|
||||
|
||||
})(jQuery);
|
33
assets/vendor/tablesorter/js/parsers/parser-date-month.js
vendored
Normal file
33
assets/vendor/tablesorter/js/parsers/parser-date-month.js
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
/*! Month parser
|
||||
* Demo: http://jsfiddle.net/Mottie/abkNM/477/
|
||||
*/
|
||||
/*jshint jquery:true */
|
||||
;(function($){
|
||||
"use strict";
|
||||
|
||||
var ts = $.tablesorter;
|
||||
ts.dates = $.extend({}, ts.dates, {
|
||||
// *** modify this array to change match the language ***
|
||||
monthCased : [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ]
|
||||
});
|
||||
ts.dates.monthLower = ts.dates.monthCased.join(',').toLocaleLowerCase().split(',');
|
||||
|
||||
ts.addParser({
|
||||
id: "month",
|
||||
is: function(){
|
||||
return false;
|
||||
},
|
||||
format: function(s, table) {
|
||||
var j = -1, c = table.config,
|
||||
n = c.ignoreCase ? s.toLocaleLowerCase() : s;
|
||||
$.each(ts.dates[ 'month' + (c.ignoreCase ? 'Lower' : 'Cased') ], function(i,v){
|
||||
if (j < 0 && n.match(v)) { j = i; }
|
||||
});
|
||||
// return s (original string) if there isn't a match
|
||||
// (non-weekdays will sort separately and empty cells will sort as expected)
|
||||
return j < 0 ? s : j;
|
||||
},
|
||||
type: "numeric"
|
||||
});
|
||||
|
||||
})(jQuery);
|
74
assets/vendor/tablesorter/js/parsers/parser-date-two-digit-year.js
vendored
Normal file
74
assets/vendor/tablesorter/js/parsers/parser-date-two-digit-year.js
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
/*! Two digit year parser
|
||||
* Demo: http://jsfiddle.net/Mottie/abkNM/427/
|
||||
*/
|
||||
/*jshint jquery:true */
|
||||
;(function($){
|
||||
"use strict";
|
||||
|
||||
var ts = $.tablesorter,
|
||||
|
||||
// Make the date be within +/- range of the 2 digit year
|
||||
// so if the current year is 2020, and the 2 digit year is 80 (2080 - 2020 > 50), it becomes 1980
|
||||
// if the 2 digit year is 50 (2050 - 2020 < 50), then it becomes 2050.
|
||||
range = 50;
|
||||
|
||||
ts.dates = $.extend({}, ts.dates, {
|
||||
regxxxxyy: /(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{2})/,
|
||||
regyyxxxx: /(\d{2})[\/\s](\d{1,2})[\/\s](\d{1,2})/
|
||||
});
|
||||
|
||||
ts.formatDate = function(s, regex, format, table){
|
||||
var n = s
|
||||
// replace separators
|
||||
.replace(/\s+/g," ").replace(/[-.,]/g, "/")
|
||||
// reformat xx/xx/xx to mm/dd/19yy;
|
||||
.replace(regex, format),
|
||||
d = new Date(n),
|
||||
y = d.getFullYear(),
|
||||
rng = table && table.config.dateRange || range,
|
||||
now = new Date().getFullYear();
|
||||
// if date > 50 years old (set range), add 100 years
|
||||
// this will work when people start using "50" and mean "2050"
|
||||
while (now - y > rng) {
|
||||
y += 100;
|
||||
}
|
||||
return d.setFullYear(y) || s;
|
||||
};
|
||||
|
||||
$.tablesorter.addParser({
|
||||
id: "ddmmyy",
|
||||
is: function() {
|
||||
return false;
|
||||
},
|
||||
format: function(s, table) {
|
||||
// reformat dd/mm/yy to mm/dd/19yy;
|
||||
return ts.formatDate(s, ts.dates.regxxxxyy, "$2/$1/19$3", table);
|
||||
},
|
||||
type: "numeric"
|
||||
});
|
||||
|
||||
$.tablesorter.addParser({
|
||||
id: "mmddyy",
|
||||
is: function() {
|
||||
return false;
|
||||
},
|
||||
format: function(s, table) {
|
||||
// reformat mm/dd/yy to mm/dd/19yy
|
||||
return ts.formatDate(s, ts.dates.regxxxxyy, "$1/$2/19$3", table);
|
||||
},
|
||||
type: "numeric"
|
||||
});
|
||||
|
||||
$.tablesorter.addParser({
|
||||
id: "yymmdd",
|
||||
is: function() {
|
||||
return false;
|
||||
},
|
||||
format: function(s, table) {
|
||||
// reformat yy/mm/dd to mm/dd/19yy
|
||||
return ts.formatDate(s, ts.dates.regyyxxxx, "$2/$3/19$1", table);
|
||||
},
|
||||
type: "numeric"
|
||||
});
|
||||
|
||||
})(jQuery);
|
33
assets/vendor/tablesorter/js/parsers/parser-date-weekday.js
vendored
Normal file
33
assets/vendor/tablesorter/js/parsers/parser-date-weekday.js
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
/*! Weekday parser
|
||||
* Demo: http://jsfiddle.net/Mottie/abkNM/477/
|
||||
*/
|
||||
/*jshint jquery:true */
|
||||
;(function($){
|
||||
"use strict";
|
||||
|
||||
var ts = $.tablesorter;
|
||||
ts.dates = $.extend({}, ts.dates, {
|
||||
// *** modify this array to change match the language ***
|
||||
weekdayCased : [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ]
|
||||
});
|
||||
ts.dates.weekdayLower = ts.dates.weekdayCased.join(',').toLocaleLowerCase().split(',');
|
||||
|
||||
ts.addParser({
|
||||
id: "weekday",
|
||||
is: function(){
|
||||
return false;
|
||||
},
|
||||
format: function(s, table) {
|
||||
var j = -1, c = table.config;
|
||||
s = c.ignoreCase ? s.toLocaleLowerCase() : s;
|
||||
$.each(ts.dates[ 'weekday' + (c.ignoreCase ? 'Lower' : 'Cased') ], function(i,v){
|
||||
if (j < 0 && s.match(v)) { j = i; }
|
||||
});
|
||||
// return s (original string) if there isn't a match
|
||||
// (non-weekdays will sort separately and empty cells will sort as expected)
|
||||
return j < 0 ? s : j;
|
||||
},
|
||||
type: "numeric"
|
||||
});
|
||||
|
||||
})(jQuery);
|
36
assets/vendor/tablesorter/js/parsers/parser-date.js
vendored
Normal file
36
assets/vendor/tablesorter/js/parsers/parser-date.js
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/*!
|
||||
* Extract dates using popular natural language date parsers
|
||||
*/
|
||||
/*jshint jquery:true */
|
||||
;(function($){
|
||||
"use strict";
|
||||
|
||||
/*! Sugar (http://sugarjs.com/dates#comparing_dates)
|
||||
* demo: http://jsfiddle.net/Mottie/abkNM/551/
|
||||
*/
|
||||
$.tablesorter.addParser({
|
||||
id: "sugar",
|
||||
is: function() {
|
||||
return false;
|
||||
},
|
||||
format: function(s) {
|
||||
return Date.create ? Date.create(s).getTime() || s : new Date(s).getTime() || s;
|
||||
},
|
||||
type: "numeric"
|
||||
});
|
||||
|
||||
/*! Datejs (http://www.datejs.com/)
|
||||
* demo: http://jsfiddle.net/Mottie/abkNM/550/
|
||||
*/
|
||||
$.tablesorter.addParser({
|
||||
id: "datejs",
|
||||
is: function() {
|
||||
return false;
|
||||
},
|
||||
format: function(s) {
|
||||
return Date.parse && Date.parse(s) || s;
|
||||
},
|
||||
type: "numeric"
|
||||
});
|
||||
|
||||
})(jQuery);
|
63
assets/vendor/tablesorter/js/parsers/parser-feet-inch-fraction.js
vendored
Normal file
63
assets/vendor/tablesorter/js/parsers/parser-feet-inch-fraction.js
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
/*! Distance parser
|
||||
* This parser will parser numbers like 5'10" (5 foot 10 inches)
|
||||
* and 31½ into sortable values.
|
||||
* Demo: http://jsfiddle.net/Mottie/abkNM/154/
|
||||
*/
|
||||
/*global jQuery: false */
|
||||
;(function($){
|
||||
"use strict";
|
||||
|
||||
var ts = $.tablesorter;
|
||||
ts.symbolRegex = /[\u215b\u215c\u215d\u215e\u00bc\u00bd\u00be]/g;
|
||||
ts.processFractions = function(n, table) {
|
||||
if (n) {
|
||||
var t, p = 0;
|
||||
n = $.trim(n.replace(/\"/,''));
|
||||
// look for a space in the first part of the number: "10 3/4" and save the "10"
|
||||
if (/\s/.test(n)) {
|
||||
p = ts.formatFloat(n.split(' ')[0], table);
|
||||
// remove stuff to the left of the space
|
||||
n = $.trim(n.substring(n.indexOf(' '), n.length));
|
||||
}
|
||||
// look for a "/" to calculate fractions
|
||||
if (/\//g.test(n)) {
|
||||
t = n.split('/');
|
||||
// turn 3/4 into .75; make sure we don't divide by zero
|
||||
n = p + parseInt(t[0], 10) / parseInt(t[1] || 1, 10);
|
||||
// look for fraction symbols
|
||||
} else if (ts.symbolRegex.test(n)) {
|
||||
n = p + n.replace(ts.symbolRegex, function(m){
|
||||
return {
|
||||
'\u215b' : '.125', // 1/8
|
||||
'\u215c' : '.375', // 3/8
|
||||
'\u215d' : '.625', // 5/8
|
||||
'\u215e' : '.875', // 7/8
|
||||
'\u00bc' : '.25', // 1/4
|
||||
'\u00bd' : '.5', // 1/2
|
||||
'\u00be' : '.75' // 3/4
|
||||
}[m];
|
||||
});
|
||||
}
|
||||
}
|
||||
return n || 0;
|
||||
};
|
||||
|
||||
$.tablesorter.addParser({
|
||||
id: 'distance',
|
||||
is: function() {
|
||||
// return false so this parser is not auto detected
|
||||
return false;
|
||||
},
|
||||
format: function(s, table) {
|
||||
if (s === '') { return ''; }
|
||||
// look for feet symbol = '
|
||||
// very generic test to catch 1.1', 1 1/2' and 1½'
|
||||
var d = (/^\s*\S*(\s+\S+)?\s*\'/.test(s)) ? s.split("'") : [0,s],
|
||||
f = ts.processFractions(d[0], table), // feet
|
||||
i = ts.processFractions(d[1], table); // inches
|
||||
return (/[\'\"]/).test(s) ? parseFloat(f) + (parseFloat(i)/12 || 0) : parseFloat(f) + parseFloat(i);
|
||||
},
|
||||
type: 'numeric'
|
||||
});
|
||||
|
||||
})(jQuery);
|
73
assets/vendor/tablesorter/js/parsers/parser-file-type.js
vendored
Normal file
73
assets/vendor/tablesorter/js/parsers/parser-file-type.js
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
/*! File Type parser
|
||||
* When a file type extension is found, the equivalent name is
|
||||
* prefixed into the parsed data, so sorting occurs in groups
|
||||
*/
|
||||
/*global jQuery: false */
|
||||
;(function($){
|
||||
"use strict";
|
||||
|
||||
// basic list from http://en.wikipedia.org/wiki/List_of_file_formats
|
||||
// To add a custom equivalent, define:
|
||||
// $.tablesorter.fileTypes.equivalents['xx'] = "A|B|C";
|
||||
$.tablesorter.fileTypes = {
|
||||
// divides filetype extensions in the equivalent list below
|
||||
separator : '|',
|
||||
equivalents : {
|
||||
"3D Image" : "3dm|3ds|dwg|max|obj",
|
||||
"Audio" : "aif|aac|ape|flac|la|m4a|mid|midi|mp2|mp3|ogg|ra|raw|rm|wav|wma",
|
||||
"Compressed" : "7z|bin|cab|cbr|gz|gzip|iso|lha|lz|rar|tar|tgz|zip|zipx|zoo",
|
||||
"Database" : "csv|dat|db|dbf|json|ldb|mdb|myd|pdb|sql|tsv|wdb|wmdb|xlr|xls|xlsx|xml",
|
||||
"Development" : "asm|c|class|cls|cpp|cc|cs|cxx|cbp|cs|dba|fla|h|java|lua|pl|py|pyc|pyo|sh|sln|r|rb|vb",
|
||||
"Document" : "doc|docx|odt|ott|pages|pdf|rtf|tex|wpd|wps|wrd|wri",
|
||||
"Executable" : "apk|app|com|exe|gadget|lnk|msi",
|
||||
"Fonts" : "eot|fnt|fon|otf|ttf|woff",
|
||||
"Icons" : "ani|cur|icns|ico",
|
||||
"Images" : "bmp|gif|jpg|jpeg|jpe|jp2|pic|png|psd|tga|tif|tiff|wmf|webp",
|
||||
"Presentation" : "pps|ppt",
|
||||
"Published" : "chp|epub|lit|pub|ppp|fm|mobi",
|
||||
"Script" : "as|bat|cgi|cmd|jar|js|lua|scpt|scptd|sh|vbs|vb|wsf",
|
||||
"Styles" : "css|less|sass",
|
||||
"Text" : "info|log|md|markdown|nfo|tex|text|txt",
|
||||
"Vectors" : "awg|ai|eps|cdr|ps|svg",
|
||||
"Video" : "asf|avi|flv|m4v|mkv|mov|mp4|mpe|mpeg|mpg|ogg|rm|rv|swf|vob|wmv",
|
||||
"Web" : "asp|aspx|cer|cfm|htm|html|php|url|xhtml"
|
||||
}
|
||||
};
|
||||
|
||||
$.tablesorter.addParser({
|
||||
id: 'filetype',
|
||||
is: function() {
|
||||
return false;
|
||||
},
|
||||
format: function(s, table) {
|
||||
var t,
|
||||
c = table.config,
|
||||
wo = c.widgetOptions,
|
||||
i = s.lastIndexOf('.'),
|
||||
sep = $.tablesorter.fileTypes.separator,
|
||||
m = $.tablesorter.fileTypes.matching,
|
||||
types = $.tablesorter.fileTypes.equivalents;
|
||||
if (!m) {
|
||||
// make a string to "quick" match the existing equivalents
|
||||
var t = [];
|
||||
$.each(types, function(i,v){
|
||||
t.push(v);
|
||||
});
|
||||
m = $.tablesorter.fileTypes.matching = sep + t.join(sep) + sep;
|
||||
}
|
||||
if (i >= 0) {
|
||||
t = sep + s.substring(i + 1, s.length) + sep;
|
||||
if (m.indexOf(t) >= 0) {
|
||||
for (i in types) {
|
||||
if ((sep + types[i] + sep).indexOf(t) >= 0) {
|
||||
return i + (wo.group_separator ? wo.group_separator : '-') + s;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return s;
|
||||
},
|
||||
type: 'text'
|
||||
});
|
||||
|
||||
})(jQuery);
|
47
assets/vendor/tablesorter/js/parsers/parser-ignore-articles.js
vendored
Normal file
47
assets/vendor/tablesorter/js/parsers/parser-ignore-articles.js
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
/*! Title parser
|
||||
* This parser will remove "The", "A" and "An" from the beginning of a book
|
||||
* or movie title, so it sorts by the second word or number
|
||||
* Demo: http://jsfiddle.net/Mottie/abkNM/5/
|
||||
*/
|
||||
/*global jQuery: false */
|
||||
;(function($){
|
||||
"use strict";
|
||||
|
||||
// basic list from http://en.wikipedia.org/wiki/Article_%28grammar%29
|
||||
$.tablesorter.ignoreArticles = {
|
||||
"en" : "the, a, an",
|
||||
"de" : "der, die, das, des, dem, den, ein, eine, einer, eines, einem, einen",
|
||||
"nl" : "de, het, de, een",
|
||||
"es" : "el, la, lo, los, las, un, una, unos, unas",
|
||||
"pt" : "o, a, os, as, um, uma, uns, umas",
|
||||
"fr" : "le, la, l'_, les, un, une, des",
|
||||
"it" : "il, lo, la, l'_, i, gli, le, un', uno, una, un",
|
||||
"hu" : "a, az, egy"
|
||||
};
|
||||
|
||||
// To add a custom parser, define:
|
||||
// $.tablesorter.ignoreArticles['xx'] = "A, B, C";
|
||||
// and then set the language id 'xx' in the headers option
|
||||
// ignoreArticles : 'xx'
|
||||
|
||||
$.tablesorter.addParser({
|
||||
id: 'ignoreArticles',
|
||||
is: function() {
|
||||
return false;
|
||||
},
|
||||
format: function(s, table, cell, cellIndex) {
|
||||
var c = table.config, art, lang;
|
||||
if ( !(c.headers && c.headers[cellIndex] && c.headers[cellIndex].ignoreArticlesRegex) ) {
|
||||
// initialize - save regex in c.headers[cellIndex].ignoreArticles
|
||||
if (!c.headers) { c.headers = {}; }
|
||||
if (!c.headers[cellIndex]) { c.headers[cellIndex] = {}; }
|
||||
lang = $.tablesorter.getData(c.$headers.eq(cellIndex), c.headers[cellIndex], 'ignoreArticles');
|
||||
art = ($.tablesorter.ignoreArticles[lang] || "the, a, an" ) + "";
|
||||
c.headers[cellIndex].ignoreArticlesRegex = new RegExp('^(' + $.trim( art.split(/\s*\,\s*/).join('\\s|') + "\\s" ).replace("_\\s","") + ')', 'i');
|
||||
}
|
||||
return (s || '').replace(c.headers[cellIndex].ignoreArticlesRegex, '');
|
||||
},
|
||||
type: 'text'
|
||||
});
|
||||
|
||||
})(jQuery);
|
87
assets/vendor/tablesorter/js/parsers/parser-input-select.js
vendored
Normal file
87
assets/vendor/tablesorter/js/parsers/parser-input-select.js
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
/*! input & select parsers for jQuery 1.7+ & tablesorter 2.7.11+
|
||||
* Updated 2/19/2014 (v2.15.0)
|
||||
* Demo: http://mottie.github.com/tablesorter/docs/example-widget-grouping.html
|
||||
*/
|
||||
/*jshint browser: true, jquery:true, unused:false */
|
||||
;(function($){
|
||||
"use strict";
|
||||
|
||||
var resort = true, // resort table after update
|
||||
updateServer = function(event, $table, $input){
|
||||
// do something here to update your server, if needed
|
||||
// event = change event object
|
||||
// $table = jQuery object of the table that was just updated
|
||||
// $input = jQuery object of the input or select that was modified
|
||||
};
|
||||
|
||||
// Custom parser for parsing input values
|
||||
// updated dynamically using the "change" function below
|
||||
$.tablesorter.addParser({
|
||||
id: "inputs",
|
||||
is: function(){
|
||||
return false;
|
||||
},
|
||||
format: function(s, table, cell) {
|
||||
return $(cell).find('input').val() || s;
|
||||
},
|
||||
parsed : true, // filter widget flag
|
||||
type: "text"
|
||||
});
|
||||
|
||||
// Custom parser for including checkbox status if using the grouping widget
|
||||
// updated dynamically using the "change" function below
|
||||
$.tablesorter.addParser({
|
||||
id: "checkbox",
|
||||
is: function(){
|
||||
return false;
|
||||
},
|
||||
format: function(s, table, cell, cellIndex) {
|
||||
var $c = $(cell),
|
||||
$input = $c.find('input[type="checkbox"]'),
|
||||
isChecked = $input.length ? $input[0].checked : '';
|
||||
// adding class to row, indicating that a checkbox is checked; includes
|
||||
// a column index in case more than one checkbox happens to be in a row
|
||||
$c.closest('tr').toggleClass('checked-' + cellIndex, isChecked);
|
||||
// returning plain language here because this is what is shown in the
|
||||
// group headers - change it as desired
|
||||
return $input.length ? isChecked ? 'checked' : 'unchecked' : s;
|
||||
},
|
||||
parsed : true, // filter widget flag
|
||||
type: "text"
|
||||
});
|
||||
|
||||
// Custom parser which returns the currently selected options
|
||||
// updated dynamically using the "change" function below
|
||||
$.tablesorter.addParser({
|
||||
id: "select",
|
||||
is: function(){
|
||||
return false;
|
||||
},
|
||||
format: function(s, table, cell) {
|
||||
return $(cell).find('select').val() || s;
|
||||
},
|
||||
parsed : true, // filter widget flag
|
||||
type: "text"
|
||||
});
|
||||
|
||||
// update select and all input types in the tablesorter cache when the change event fires.
|
||||
// This method only works with jQuery 1.7+
|
||||
// you can change it to use delegate (v1.4.3+) or live (v1.3+) as desired
|
||||
// if this code interferes somehow, target the specific table $('#mytable'), instead of $('table')
|
||||
$(window).load(function(){
|
||||
// this flag prevents the updateCell event from being spammed
|
||||
// it happens when you modify input text and hit enter
|
||||
var alreadyUpdating = false;
|
||||
$('table').find('tbody').on('change', 'select, input', function(e){
|
||||
if (!alreadyUpdating) {
|
||||
var $tar = $(e.target),
|
||||
$table = $tar.closest('table');
|
||||
alreadyUpdating = true;
|
||||
$table.trigger('updateCell', [ $tar.closest('td'), resort ]);
|
||||
updateServer(e, $table, $tar);
|
||||
setTimeout(function(){ alreadyUpdating = false; }, 10);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
})(jQuery);
|
76
assets/vendor/tablesorter/js/parsers/parser-ipv6.js
vendored
Normal file
76
assets/vendor/tablesorter/js/parsers/parser-ipv6.js
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
/*! IPv6 Address parser (WIP)
|
||||
* IPv6 Address (ffff:0000:0000:0000:0000:0000:0000:0000)
|
||||
* needs to support short versions like "::8" or "1:2::7:8"
|
||||
* and "::00:192.168.10.184" (embedded IPv4 address)
|
||||
* see http://www.intermapper.com/support/tools/IPV6-Validator.aspx
|
||||
*/
|
||||
/*global jQuery: false */
|
||||
;(function($){
|
||||
"use strict";
|
||||
|
||||
var ts = $.tablesorter;
|
||||
|
||||
$.extend( ts.regex, {}, {
|
||||
ipv4Validate : /((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})/,
|
||||
ipv4Extract : /([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/,
|
||||
|
||||
// simplified regex from http://www.intermapper.com/support/tools/IPV6-Validator.aspx
|
||||
// (specifically from http://download.dartware.com/thirdparty/ipv6validator.js)
|
||||
ipv6Validate : /^\s*((([0-9a-f]{1,4}:){7}([0-9a-f]{1,4}|:))|(([0-9a-f]{1,4}:){6}(:[0-9a-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){5}(((:[0-9a-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){4}(((:[0-9a-f]{1,4}){1,3})|((:[0-9a-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){3}(((:[0-9a-f]{1,4}){1,4})|((:[0-9a-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){2}(((:[0-9a-f]{1,4}){1,5})|((:[0-9a-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){1}(((:[0-9a-f]{1,4}){1,6})|((:[0-9a-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9a-f]{1,4}){1,7})|((:[0-9a-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/i
|
||||
});
|
||||
|
||||
ts.addParser({
|
||||
id: "ipv6Address",
|
||||
is: function(s) {
|
||||
return ts.regex.ipv6Validate.test(s);
|
||||
},
|
||||
format: function(address, table) {
|
||||
// code modified from http://forrst.com/posts/JS_Expand_Abbreviated_IPv6_Addresses-1OR
|
||||
var i, t, sides, groups, groupsPresent,
|
||||
hex = table ? (typeof table === "boolean" ? table : table && table.config.ipv6HexFormat || false) : false,
|
||||
fullAddress = '',
|
||||
expandedAddress = '',
|
||||
validGroupCount = 8,
|
||||
validGroupSize = 4;
|
||||
// remove any extra spaces
|
||||
address = address.replace(/\s*/g, '');
|
||||
// look for embedded ipv4
|
||||
if (ts.regex.ipv4Validate.test(address)) {
|
||||
groups = address.match(ts.regex.ipv4Extract);
|
||||
t = '';
|
||||
for (i = 1; i < groups.length; i++){
|
||||
t += ('00' + (parseInt(groups[i], 10).toString(16)) ).slice(-2) + ( i === 2 ? ':' : '' );
|
||||
}
|
||||
address = address.replace( ts.regex.ipv4Extract, t );
|
||||
}
|
||||
|
||||
if (address.indexOf("::") == -1) {
|
||||
// All eight groups are present
|
||||
fullAddress = address;
|
||||
} else {
|
||||
// Consecutive groups of zeroes have been collapsed with "::".
|
||||
sides = address.split("::");
|
||||
groupsPresent = 0;
|
||||
for (i = 0; i < sides.length; i++) {
|
||||
groupsPresent += sides[i].split(":").length;
|
||||
}
|
||||
fullAddress += sides[0] + ":";
|
||||
for (i = 0; i < validGroupCount - groupsPresent; i++) {
|
||||
fullAddress += "0000:";
|
||||
}
|
||||
fullAddress += sides[1];
|
||||
}
|
||||
groups = fullAddress.split(":");
|
||||
for (i = 0; i < validGroupCount; i++) {
|
||||
// it's fastest & easiest for tablesorter to sort decimal values (vs hex)
|
||||
groups[i] = hex ? ('0000' + groups[i]).slice(-4) :
|
||||
('00000' + (parseInt(groups[i], 16) || 0)).slice(-5);
|
||||
expandedAddress += ( i != validGroupCount-1) ? groups[i] + ':' : groups[i];
|
||||
}
|
||||
return hex ? expandedAddress : expandedAddress.replace(/:/g, '');
|
||||
},
|
||||
// uses natural sort hex compare
|
||||
type: "numeric"
|
||||
});
|
||||
|
||||
})(jQuery);
|
77
assets/vendor/tablesorter/js/parsers/parser-metric.js
vendored
Normal file
77
assets/vendor/tablesorter/js/parsers/parser-metric.js
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
/*! Metric parser
|
||||
* Demo: http://jsfiddle.net/Mottie/abkNM/382/
|
||||
* Set the metric name in the header (defaults to "m|meter"), e.g.
|
||||
* <th data-metric-name="b|byte">HDD Size</th>
|
||||
* <th data-metric-name="m|meter">Distance</th>
|
||||
*/
|
||||
/*jshint jquery:true */
|
||||
;(function($){
|
||||
"use strict";
|
||||
|
||||
var prefixes = {
|
||||
// "prefix" : [ base 10, base 2 ]
|
||||
// skipping IEEE 1541 defined prefixes: kibibyte, mebibyte, etc, for now.
|
||||
"Y|Yotta|yotta" : [ 1e24, Math.pow(1024, 8) ], // 1024^8
|
||||
"Z|Zetta|zetta" : [ 1e21, Math.pow(1024, 7) ], // 1024^7
|
||||
"E|Exa|exa" : [ 1e18, Math.pow(1024, 6) ], // 1024^6
|
||||
"P|Peta|peta" : [ 1e15, Math.pow(1024, 5) ], // 1024^5
|
||||
"T|Tera|tera" : [ 1e12, Math.pow(1024, 4) ], // 1024^4
|
||||
"G|Giga|giga" : [ 1e9, Math.pow(1024, 3) ], // 1024^3
|
||||
"M|Mega|mega" : [ 1e6, Math.pow(1024, 2) ], // 1024^2
|
||||
"k|Kilo|kilo" : [ 1e3, 1024 ], // 1024
|
||||
// prefixes below here are rarely, if ever, used in binary
|
||||
"h|hecto" : [ 1e2, 1e2 ],
|
||||
"da|deka" : [ 1e1, 1e1 ],
|
||||
"d|deci" : [ 1e-1, 1e-1 ],
|
||||
"c|centi" : [ 1e-2, 1e-2],
|
||||
"m|milli" : [ 1e-3, 1e-3 ],
|
||||
"µ|micro" : [ 1e-6, 1e-6 ],
|
||||
"n|nano" : [ 1e-9, 1e-9 ],
|
||||
"p|pico" : [ 1e-12, 1e-12 ],
|
||||
"f|femto" : [ 1e-15, 1e-15 ],
|
||||
"a|atto" : [ 1e-18, 1e-18 ],
|
||||
"z|zepto" : [ 1e-21, 1e-21 ],
|
||||
"y|yocto" : [ 1e-24, 1e-24 ]
|
||||
},
|
||||
// the \\d+ will not catch digits with spaces, commas or decimals; so use the value from n instead
|
||||
RegLong = "(\\d+)(\\s+)?([Zz]etta|[Ee]xa|[Pp]eta|[Tt]era|[Gg]iga|[Mm]ega|kilo|hecto|deka|deci|centi|milli|micro|nano|pico|femto|atto|zepto|yocto)(",
|
||||
RegAbbr = "(\\d+)(\\s+)?(Z|E|P|T|G|M|k|h|da|d|c|m|µ|n|p|f|a|z|y)(";
|
||||
|
||||
$.tablesorter.addParser({
|
||||
id: 'metric',
|
||||
is: function() {
|
||||
return false;
|
||||
},
|
||||
format: function(s, table, cell, cellIndex) {
|
||||
var v = 'm|meter',
|
||||
b, t,
|
||||
// process number here to get a numerical format (us or eu)
|
||||
n = $.tablesorter.formatFloat(s.replace(/[^\w,. \-()]/g, ""), table),
|
||||
$t = table.config.$headers.filter('[data-column="' + cellIndex + '"]'),
|
||||
m = $t.data('metric');
|
||||
if (!m) {
|
||||
// stored values
|
||||
t = ($t.attr('data-metric-name') || v).split('|');
|
||||
m = [ t[1] || t[0].substring(1), t[0] ];
|
||||
m[2] = new RegExp(RegLong + m[0] + "|" + m[1] + ")");
|
||||
m[3] = new RegExp(RegAbbr + m[1] + ")");
|
||||
$t.data('metric', m);
|
||||
}
|
||||
// find match to full name or abbreviation
|
||||
t = s.match(m[2]) || s.match(m[3]);
|
||||
if (t) {
|
||||
for (v in prefixes) {
|
||||
if (t[3].match(v)) {
|
||||
// exception when using binary prefix
|
||||
// change base for binary use
|
||||
b = /^[b|bit|byte|o|octet]/.test(t[4]) ? 1 : 0;
|
||||
return n * prefixes[v][b];
|
||||
}
|
||||
}
|
||||
}
|
||||
return n;
|
||||
},
|
||||
type: 'numeric'
|
||||
});
|
||||
|
||||
})(jQuery);
|
145
assets/vendor/tablesorter/js/widgets/widget-alignChar.js
vendored
Normal file
145
assets/vendor/tablesorter/js/widgets/widget-alignChar.js
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
/*! tablesorter Align Character widget - updated 3/12/2014 (core v2.15.8)
|
||||
* Requires tablesorter v2.8+ and jQuery 1.7+
|
||||
* by Rob Garrison
|
||||
*/
|
||||
/*jshint browser:true, jquery:true, unused:false */
|
||||
/*global jQuery: false */
|
||||
;(function($){
|
||||
"use strict";
|
||||
var ts = $.tablesorter;
|
||||
|
||||
ts.alignChar = {
|
||||
|
||||
init : function(table, c, wo) {
|
||||
c.$headers.filter('[' + wo.alignChar_charAttrib + ']').each(function(){
|
||||
var $this = $(this),
|
||||
vars = {
|
||||
column : this.column,
|
||||
align : $this.attr(wo.alignChar_charAttrib),
|
||||
alignIndex : parseInt( $this.attr(wo.alignChar_indexAttrib) || 0, 10),
|
||||
adjust : parseFloat($this.attr(wo.alignChar_adjustAttrib)) || 0,
|
||||
};
|
||||
vars.regex = new RegExp('\\' + vars.align, 'g');
|
||||
if (typeof vars.align !== 'undefined') {
|
||||
wo.alignChar_savedVars[this.column] = vars;
|
||||
ts.alignChar.setup(table, c, wo, vars);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
setup: function(table, c, wo, v){
|
||||
// do nothing for empty tables
|
||||
if ($.isEmptyObject(c.cache)) { return; }
|
||||
var tbodyIndex, rowIndex, start, end, last, index, rows, val, count,
|
||||
len, wLeft, wRight, alignChar, $row,
|
||||
left = [],
|
||||
right = [];
|
||||
for (tbodyIndex = 0; tbodyIndex < c.$tbodies.length; tbodyIndex++){
|
||||
rows = c.cache[tbodyIndex];
|
||||
len = rows.normalized.length;
|
||||
for (rowIndex = 0; rowIndex < len; rowIndex++) {
|
||||
// set up to work with modified cache v2.16.0+
|
||||
$row = rows.row ? rows.row[rowIndex] : rows.normalized[rowIndex][c.columns].$row;
|
||||
val = $row.find('td').eq(v.column).text().replace(/[ ]/g, "\u00a0");
|
||||
// count how many "align" characters are in the string
|
||||
count = (val.match( v.regex ) || []).length;
|
||||
// set alignment @ alignIndex (one-based index)
|
||||
if (count > 0 && v.alignIndex > 0) {
|
||||
end = Math.min(v.alignIndex, count);
|
||||
start = 0;
|
||||
index = 0;
|
||||
last = 0;
|
||||
// find index of nth align character based on alignIndex (data-align-index)
|
||||
while (start++ < end) {
|
||||
last = val.indexOf(v.align, last + 1);
|
||||
index = last < 0 ? index : last;
|
||||
}
|
||||
} else {
|
||||
index = val.indexOf(v.align);
|
||||
}
|
||||
if ( index >= 0 ) {
|
||||
left.push( val.substring(0, index) || '' );
|
||||
right.push( val.substring(index, val.length) || '' );
|
||||
} else {
|
||||
// no align character found!
|
||||
// put val in right or left based on the align index
|
||||
left.push( (count >= 1 && v.alignIndex >= count) ? '' : val || '' );
|
||||
right.push( (count >= 1 && v.alignIndex >= count) ? val || '' : '' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// find widest segments
|
||||
wLeft = ($.extend([], left)).sort(function(a,b){ return b.length - a.length; })[0];
|
||||
wRight = ($.extend([], right)).sort(function(a,b){ return b.length - a.length; })[0];
|
||||
// calculate percentage widths
|
||||
v.width = v.width || ( Math.floor(wLeft.length / (wLeft.length + wRight.length) * 100) + v.adjust );
|
||||
wLeft = 'min-width:' + v.width + '%';
|
||||
wRight = 'min-width:' + (100 - v.width) + '%';
|
||||
|
||||
for (tbodyIndex = 0; tbodyIndex < c.$tbodies.length; tbodyIndex++){
|
||||
rows = c.cache[tbodyIndex];
|
||||
len = rows.normalized.length;
|
||||
for (rowIndex = 0; rowIndex < len; rowIndex++) {
|
||||
alignChar = $(wo.alignChar_wrap).length ? $(wo.alignChar_wrap).html(v.align)[0].outerHTML : v.align;
|
||||
$row = rows.row ? rows.row[rowIndex] : rows.normalized[rowIndex][c.columns].$row;
|
||||
$row.find('td').eq(v.column).html(
|
||||
'<span class="ts-align-wrap"><span class="ts-align-left" style="' + wLeft + '">' + left[rowIndex] + '</span>' +
|
||||
'<span class="ts-align-right" style="' + wRight + '">' + alignChar +
|
||||
right[rowIndex].slice(v.align.length) + '</span></span>'
|
||||
);
|
||||
}
|
||||
}
|
||||
wo.alignChar_initialized = true;
|
||||
|
||||
},
|
||||
remove: function(table, c, column){
|
||||
if ($.isEmptyObject(c.cache)) { return; }
|
||||
var tbodyIndex, rowIndex, len, rows, $row, $cell;
|
||||
for (tbodyIndex = 0; tbodyIndex < c.$tbodies.length; tbodyIndex++){
|
||||
rows = c.cache[tbodyIndex];
|
||||
len = rows.normalized.length;
|
||||
for (rowIndex = 0; rowIndex < len; rowIndex++) {
|
||||
$row = rows.row ? rows.row[rowIndex] : rows.normalized[rowIndex][c.columns].$row;
|
||||
$cell = $row.find('td').eq(column);
|
||||
$cell.html( $cell.text().replace(/\s/g, ' ') );
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ts.addWidget({
|
||||
id: 'alignChar',
|
||||
priority: 100,
|
||||
options: {
|
||||
alignChar_wrap : '',
|
||||
alignChar_charAttrib : 'data-align-char',
|
||||
alignChar_indexAttrib : 'data-align-index',
|
||||
alignChar_adjustAttrib : 'data-align-adjust' // percentage width adjustments
|
||||
},
|
||||
init: function(table, thisWidget, c, wo){
|
||||
wo.alignChar_initialized = false;
|
||||
wo.alignChar_savedVars = [];
|
||||
ts.alignChar.init(table, c, wo);
|
||||
c.$table.on('pagerEnd refreshAlign', function(){
|
||||
c.$headers.filter('[' + wo.alignChar_charAttrib + ']').each(function(){
|
||||
ts.alignChar.remove(table, c, this.column);
|
||||
});
|
||||
ts.alignChar.init(table, c, wo);
|
||||
});
|
||||
},
|
||||
format : function(table, c, wo){
|
||||
// reinitialize in case table is empty when first initialized
|
||||
if (!wo.alignChar_initialized) {
|
||||
c.$table.trigger('refreshAlign');
|
||||
}
|
||||
},
|
||||
remove : function(table, c, wo){
|
||||
c.$headers.filter('[' + wo.alignChar_charAttrib + ']').each(function(){
|
||||
ts.alignChar.remove(table, c, this.column);
|
||||
});
|
||||
wo.alignChar_initialized = false;
|
||||
}
|
||||
});
|
||||
|
||||
})(jQuery);
|
441
assets/vendor/tablesorter/js/widgets/widget-build-table.js
vendored
Normal file
441
assets/vendor/tablesorter/js/widgets/widget-build-table.js
vendored
Normal file
@@ -0,0 +1,441 @@
|
||||
/*! Build Table widget * by Rob Garrison */
|
||||
/*jshint browser:true, jquery:true, unused:false */
|
||||
/*global jQuery: false */
|
||||
;(function($){
|
||||
"use strict";
|
||||
var ts = $.tablesorter = $.tablesorter || {},
|
||||
|
||||
// build a table from data (requires existing <table> tag)
|
||||
// data.header contains an array of header titles
|
||||
// data.rows contains an array of rows which contains an array of cells
|
||||
bt = ts.buildTable = function(tar, c){
|
||||
// add table if one doesn't exist
|
||||
var $tbl = tar.tagName === 'TABLE' ? $(tar) : $('<table>').appendTo(tar),
|
||||
table = $tbl[0],
|
||||
wo = c.widgetOptions = $.extend( true, {}, bt.defaults, c.widgetOptions ),
|
||||
p = wo.build_processing,
|
||||
typ = wo.build_type,
|
||||
d = wo.build_source || c.data,
|
||||
|
||||
// determine type: html, json, array, csv, object
|
||||
runType = function(d){
|
||||
var t = $.type(d),
|
||||
jq = d instanceof jQuery;
|
||||
// run any processing if set
|
||||
if ( typeof p === 'function' ) { d = p(d, wo); }
|
||||
// store processed data in table.config.data
|
||||
c.data = d;
|
||||
// String (html or unprocessed json) or jQuery object
|
||||
if ( jq || t === 'string' ) {
|
||||
// look for </tr> closing tag, then we have an HTML string
|
||||
if ( jq || /<\s*\/tr\s*>/.test(d) ) {
|
||||
return bt.html( table, d, wo );
|
||||
}
|
||||
try {
|
||||
d = $.parseJSON(d);
|
||||
if (d) {
|
||||
// valid JSON!
|
||||
return bt.object( table, d, wo );
|
||||
}
|
||||
} catch(ignore) {}
|
||||
// fall through in case it's a csv string
|
||||
}
|
||||
// Array
|
||||
if (t === 'array' || t === 'string' || typ === 'array' || typ === 'csv') {
|
||||
// build table using an array (csv & array combined script)
|
||||
return bt.csv( table, d, wo );
|
||||
}
|
||||
// if we got here, it's an object, or nothing
|
||||
return bt.object( table, d, wo );
|
||||
};
|
||||
|
||||
// store config
|
||||
table.config = c;
|
||||
|
||||
// even if wo.build_type is undefined, we can try to figure out the type
|
||||
if ( !ts.buildTable.hasOwnProperty(typ) && typ !== '' ) {
|
||||
if (c.debug) { ts.log('aborting build table widget, incorrect build type'); }
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( d instanceof jQuery ) {
|
||||
// get data from within a jQuery object (csv)
|
||||
runType( $.trim( d.html() ) );
|
||||
} else if ( d && ( d.hasOwnProperty('url') || typ === 'json' ) ) {
|
||||
// load data via ajax
|
||||
$.ajax( wo.build_source )
|
||||
.done(function(data) {
|
||||
runType(data);
|
||||
})
|
||||
.fail(function( jqXHR, textStatus, errorThrown) {
|
||||
if (c.debug) { ts.log('aborting build table widget, failed ajax load'); }
|
||||
$tbl.html('<tr><td class="error">' + jqXHR.status + ' ' + textStatus + '</td></tr>');
|
||||
});
|
||||
} else {
|
||||
runType(d);
|
||||
}
|
||||
};
|
||||
|
||||
bt.defaults = {
|
||||
// *** build widget core ***
|
||||
build_type : '', // array, csv, object, json, html
|
||||
build_source : '', // array, object, jQuery Object or ajaxObject { url: '', dataType: 'json' },
|
||||
build_processing : null, // function that returns a useable build_type (e.g. string to array)
|
||||
build_complete : 'tablesorter-build-complete', // triggered event when build completes
|
||||
|
||||
// *** CSV & Array ***
|
||||
build_headers : {
|
||||
rows : 1, // Number of header rows from the csv
|
||||
classes : [], // Header classes to apply to cells
|
||||
text : [], // Header cell text
|
||||
widths : [] // set header cell widths (set in colgroup)
|
||||
},
|
||||
build_footers : {
|
||||
rows : 1, // Number of header rows from the csv
|
||||
classes : [], // Footer classes to apply to cells
|
||||
text : [] // Footer cell text
|
||||
},
|
||||
build_numbers : {
|
||||
addColumn : false, // include row numbering column?
|
||||
sortable : false // make column sortable?
|
||||
},
|
||||
|
||||
// *** CSV only options ***
|
||||
build_csvStartLine : 0, // line within the csv to start adding to table
|
||||
build_csvSeparator : ",", // csv separator
|
||||
|
||||
// *** build object options ***
|
||||
build_objectRowKey : 'rows', // object key containing table rows
|
||||
build_objectCellKey : 'cells', // object key containing table cells (within the rows object)
|
||||
build_objectHeaderKey : 'headers', // object key containing table headers
|
||||
build_objectFooterKey : 'footers' // object key containing table footers
|
||||
};
|
||||
|
||||
bt.build = {
|
||||
colgroup : function(widths) {
|
||||
var t = '';
|
||||
// add colgroup if widths set
|
||||
if (widths && widths.length) {
|
||||
t += '<colgroup>';
|
||||
$.each(widths, function(i, w){
|
||||
t += '<col' + ( w ? ' style="width:' + w + '"' : '' ) + '>';
|
||||
});
|
||||
t += '</colgroup>';
|
||||
}
|
||||
return t;
|
||||
},
|
||||
// d = cell data; typ = 'th' or 'td'; first = save widths from first header row only
|
||||
cell : function(d, wo, typ, col, first){
|
||||
var j, $td,
|
||||
$col = first ? $('<col>') : '',
|
||||
cls = wo.build_headers.classes,
|
||||
cw = wo.build_headers.widths;
|
||||
// d is just an array
|
||||
if (/string|number/.test(typeof d)) {
|
||||
// add classes from options, but not text
|
||||
$td = $('<' + typ + (cls && cls[col] ? ' class="' + cls[col] + '"' : '') + '>' + d + '</' + typ + '>');
|
||||
// get widths from options (only from first row)
|
||||
if (first && cw && cw[col]) {
|
||||
$col.width(cw[col] || '');
|
||||
}
|
||||
} else {
|
||||
// assume we have an object
|
||||
$td = $('<' + typ + '>');
|
||||
for (j in d) {
|
||||
if (d.hasOwnProperty(j)){
|
||||
if (j === 'text' || j === 'html') {
|
||||
$td[j]( d[j] );
|
||||
} else if (first && j === 'width') {
|
||||
// set column width, but only from first row
|
||||
$col.width(d[j] || '');
|
||||
} else {
|
||||
$td.attr(j, d[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return [ $td, $col ];
|
||||
},
|
||||
// h1 = header text from data
|
||||
header : function(h1, wo){
|
||||
var h2 = wo.build_headers.text,
|
||||
cls = wo.build_headers.classes,
|
||||
t = '<tr>' + (wo.build_numbers.addColumn ? '<th' + (wo.build_numbers.sortable ? '' :
|
||||
' class="sorter-false"') + '>' + wo.build_numbers.addColumn + '</th>' : '');
|
||||
$.each(h1, function(i, h) {
|
||||
t += '<th' + (cls && cls[i] ? ' class="' + cls[i] + '"' : '') + '>' +
|
||||
(h2 && h2[i] ? h2[i] : h) + '</th>';
|
||||
});
|
||||
return t + '</tr>';
|
||||
},
|
||||
rows : function(items, txt, c, wo, num, ftr){
|
||||
var h = (ftr ? 'th' : 'td'),
|
||||
t = '<tr>' + (wo.build_numbers.addColumn ? '<' + h + '>' + (ftr ? '' : num) + '</' + h + '>' : '');
|
||||
$.each(items, function(i, item) {
|
||||
t += '<' + (ftr ? h + (c && c[i] ? ' class="' + c[i] + '"' : '') : h) + '>' +
|
||||
(ftr && txt && txt.length && txt[i] ? txt[i] : item) + '</' + h + '>';
|
||||
});
|
||||
return t + '</tr>';
|
||||
}
|
||||
};
|
||||
|
||||
bt.buildComplete = function(table, wo){
|
||||
$(table).trigger(wo.build_complete);
|
||||
ts.setup(table, table.config);
|
||||
};
|
||||
|
||||
/* ==== Array example ====
|
||||
[
|
||||
[ "header1", "header2", ... "headerN" ],
|
||||
[ "row1cell1", "row1cell2", ... "row1cellN" ],
|
||||
[ "row2cell1", "row2cell2", ... "row2cellN" ],
|
||||
...
|
||||
[ "rowNcell1", "rowNcell2", ... "rowNcellN" ]
|
||||
]
|
||||
*/
|
||||
bt.array = function(table, data, wo) {
|
||||
return bt.csv(table, data, wo);
|
||||
};
|
||||
|
||||
/* ==== CSV example ====
|
||||
ID, Name, Age, Date
|
||||
A42b, Parker, 28, "Jul 6, 2006 8:14 AM"
|
||||
A255, Hood, 33, "Dec 10, 2002 5:14 AM"
|
||||
A33, Kent, 18, "Jan 12, 2003 11:14 AM"
|
||||
A1, Franklin, 45, "Jan 18, 2001 9:12 AM"
|
||||
A102, Evans, 22, "Jan 18, 2007 9:12 AM"
|
||||
A42a, Everet, 22, "Jan 18, 2007 9:12 AM"
|
||||
ID, Name, Age, Date
|
||||
*/
|
||||
// Adapted & modified from csvToTable.js by Steve Sobel
|
||||
// MIT license: https://code.google.com/p/jquerycsvtotable/
|
||||
bt.csv = function(table, data, wo) {
|
||||
var c, h,
|
||||
csv = wo.build_type === 'csv' || typeof data === 'string',
|
||||
$t = $(table),
|
||||
lines = csv ? data.replace('\r','').split('\n') : data,
|
||||
len = lines.length,
|
||||
printedLines = 0,
|
||||
infooter = false,
|
||||
r = wo.build_headers.rows + (csv ? wo.build_csvStartLine : 0),
|
||||
f = wo.build_footers.rows,
|
||||
headerCount = 0,
|
||||
error = '',
|
||||
items,
|
||||
tableHTML = bt.build.colgroup( wo.build_headers.widths ) + '<thead>';
|
||||
|
||||
$.each(lines, function(n, line) {
|
||||
if ( n >= len - f ) { infooter = true; }
|
||||
// build header
|
||||
if ( (csv ? n >= wo.build_csvStartLine : true) && ( n < r ) ) {
|
||||
h = csv ? bt.splitCSV( line, wo.build_csvSeparator ) : line;
|
||||
headerCount = h.length;
|
||||
tableHTML += bt.build.header(h, wo);
|
||||
} else if ( n >= r ) {
|
||||
// build tbody & tfoot rows
|
||||
if (n === r) {
|
||||
tableHTML += '</thead><tbody>';
|
||||
}
|
||||
items = csv ? bt.splitCSV( line, wo.build_csvSeparator ) : line;
|
||||
if (infooter && f > 0) {
|
||||
tableHTML += (n === len - f ? '</tbody><tfoot>' : '') +
|
||||
(n === len ? '</tfoot>' : '');
|
||||
}
|
||||
if (items.length > 1) {
|
||||
printedLines++;
|
||||
if ( items.length !== headerCount ) {
|
||||
error += 'error on line ' + n + ': Item count (' + items.length +
|
||||
') does not match header count (' + headerCount + ') \n';
|
||||
}
|
||||
c = infooter ? wo.build_footers.classes : '';
|
||||
tableHTML += bt.build.rows(items, wo.build_footers.text, c, wo, printedLines, infooter);
|
||||
}
|
||||
}
|
||||
});
|
||||
tableHTML += (f > 0 ? '' : '</tbody>');
|
||||
if (error) {
|
||||
$t.html(error);
|
||||
} else {
|
||||
$t.html(tableHTML);
|
||||
bt.buildComplete(table, wo);
|
||||
}
|
||||
};
|
||||
|
||||
// CSV Parser by Brian Huisman (http://www.greywyvern.com/?post=258)
|
||||
bt.splitCSV = function(str, sep) {
|
||||
var x, tl,
|
||||
thisCSV = $.trim(str).split(sep = sep || ",");
|
||||
for ( x = thisCSV.length - 1; x >= 0; x-- ) {
|
||||
if ( thisCSV[x].replace(/\"\s+$/, '"').charAt(thisCSV[x].length - 1) === '"' ) {
|
||||
if ( (tl = thisCSV[x].replace(/^\s+\"/, '"')).length > 1 && tl.charAt(0) === '"' ) {
|
||||
thisCSV[x] = thisCSV[x].replace(/^\s*"|"\s*$/g, '').replace(/""/g, '"');
|
||||
} else if (x) {
|
||||
thisCSV.splice(x - 1, 2, [thisCSV[x - 1], thisCSV[x]].join(sep));
|
||||
} else {
|
||||
thisCSV = thisCSV.shift().split(sep).concat(thisCSV);
|
||||
}
|
||||
} else {
|
||||
thisCSV[x].replace(/""/g, '"');
|
||||
}
|
||||
}
|
||||
return thisCSV;
|
||||
};
|
||||
|
||||
// data may be a jQuery object after processing
|
||||
bt.html = function(table, data, wo) {
|
||||
var $t = $(table);
|
||||
if ( data instanceof jQuery ) {
|
||||
$t.empty().append(data);
|
||||
} else {
|
||||
$t.html(data);
|
||||
}
|
||||
bt.buildComplete(table, wo);
|
||||
};
|
||||
|
||||
/* ==== Object example ====
|
||||
data : {
|
||||
headers : [
|
||||
[
|
||||
{ text: 'First Name', class: 'fname', width: '20%' }, // row 1 cell 1
|
||||
'Last Name',
|
||||
{ text: 'Age', class: 'age', 'data-sorter' : false },
|
||||
'Total',
|
||||
{ text: 'Discount', class : 'sorter-false' },
|
||||
{ text: 'Date', class : 'date' } // row 1 cell 6
|
||||
]
|
||||
],
|
||||
footers : 'clone', // clone headers or assign array like headers
|
||||
rows : [
|
||||
// TBODY 1
|
||||
[ 'Peter', 'Parker', 28, '$9.99', '20%', 'Jul 6, 2006 8:14 AM' ], // row 1
|
||||
[ 'John', 'Hood', 33, '$19.99', '25%', 'Dec 10, 2002 5:14 AM' ], // row 2
|
||||
[ 'Clark', 'Kent', 18, '$15.89', '44%', 'Jan 12, 2003 11:14 AM' ], // row 3
|
||||
|
||||
// TBODY 2
|
||||
{ newTbody: true, class: 'tablesorter-infoOnly' },
|
||||
{ cells : [ { text: 'Info Row', colSpan: 6 } ] }, // row 4
|
||||
|
||||
// TBODY 3
|
||||
{ newTbody: true },
|
||||
[ 'Bruce', 'Evans', 22, '$13.19', '11%', 'Jan 18, 2007 9:12 AM' ], // row 5
|
||||
[ 'Brice', 'Almighty', 45, '$153.19', '44%', 'Jan 18, 2001 9:12 AM' ], // row 6
|
||||
|
||||
{ class: 'specialRow', // row 7
|
||||
cells: [
|
||||
{ text: 'Fred', class: 'fname' },
|
||||
{ text: 'Smith', class: 'lname' },
|
||||
{ text: 18, class: 'age', 'data-info': 'fake ID!, he is really 16' },
|
||||
{ text: '$22.44', class: 'total' },
|
||||
{ text: '8%', class: 'discount' },
|
||||
{ text: 'Aug 20, 2012 10:15 AM', class: 'date' }
|
||||
],
|
||||
'data-info' : 'This row likes turtles'
|
||||
}
|
||||
]
|
||||
}
|
||||
*/
|
||||
bt.object = function(table, data, wo) {
|
||||
// "rows"
|
||||
var j, l, t, $c, $t, $tb, $tr,
|
||||
c = table.config,
|
||||
kh = wo.build_objectHeaderKey,
|
||||
kr = wo.build_objectRowKey,
|
||||
h = data.hasOwnProperty(kh) && !$.isEmptyObject(data.kh) ? data.kh : data.hasOwnProperty('headers') ? data.headers : false,
|
||||
r = data.hasOwnProperty(kr) && !$.isEmptyObject(data.kr) ? data.kr : data.hasOwnProperty('rows') ? data.rows : false;
|
||||
|
||||
if (!h || !r || h.length === 0 || r.length === 0) {
|
||||
if (c.debug) { ts.log('aborting build table widget, missing data for object build'); }
|
||||
return false;
|
||||
}
|
||||
|
||||
$c = $('<colgroup>');
|
||||
$t = $('<table><thead/></table>');
|
||||
|
||||
// Build thead
|
||||
// h = [ ['headerRow1Cell1', 'headerRow1Cell2', ... 'headerRow1CellN' ], ['headerRow2Cell1', ... ] ]
|
||||
// or h = [ [ { text: 'firstCell', class: 'fc', width: '20%' }, ..., { text: 'last Cell' } ], [ /* second row */ ] ]
|
||||
$.each(h, function(i, d){
|
||||
$tr = $('<tr>').appendTo( $t.find('thead') );
|
||||
l = d.length; // header row
|
||||
for ( j = 0; j < l; j++ ) {
|
||||
// cell(cellData, widgetOptions, 'th', first row)
|
||||
t = bt.build.cell(d[j], wo, 'th', j, i === 0);
|
||||
if (t[0] && t[0].length) { t[0].appendTo( $tr ); } // add cell
|
||||
if (i === 0 && t[1]) { t[1].appendTo( $c ); } // add col to colgroup
|
||||
}
|
||||
});
|
||||
if ($c.find('col[style]').length) {
|
||||
// add colgroup if it contains col elements
|
||||
$t.prepend( $c );
|
||||
}
|
||||
|
||||
$tb = $('<tbody>');
|
||||
// Build tbody
|
||||
$.each(r, function(i, d){
|
||||
t = $.type(d) === 'object';
|
||||
// add new tbody
|
||||
if (t && d.newTbody) {
|
||||
$tb = $('<tbody>').appendTo( $t );
|
||||
for (j in d) {
|
||||
if (d.hasOwnProperty(j) && j !== 'newTbody'){
|
||||
$tb.attr(j, d[j]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (i === 0) {
|
||||
// add tbody, if the first item in the object isn't a call for a new tbody
|
||||
$tb.appendTo( $t );
|
||||
}
|
||||
|
||||
$tr = $('<tr>').appendTo( $tb );
|
||||
if (t) {
|
||||
// row defined by object
|
||||
for (j in d) {
|
||||
if (d.hasOwnProperty(j) && j !== wo.build_objectCellKey){
|
||||
$tr.attr(j, d[j]);
|
||||
}
|
||||
}
|
||||
if (d.hasOwnProperty(wo.build_objectCellKey)) {
|
||||
// cells contains each cell info
|
||||
d = d.cells;
|
||||
}
|
||||
}
|
||||
|
||||
l = d.length;
|
||||
for ( j = 0; j < l; j++ ) {
|
||||
// cell(cellData, widgetOptions, 'td')
|
||||
$c = bt.build.cell(d[j], wo, 'td', j);
|
||||
if ($c[0] && $c[0].length) { $c[0].appendTo( $tr ); } // add cell
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// add footer
|
||||
if (data.hasOwnProperty(wo.build_objectFooterKey)) {
|
||||
t = data[wo.build_objectFooterKey];
|
||||
if (t === 'clone') {
|
||||
$c = $t.find('thead').html();
|
||||
$t.append('<tfoot>' + $c + '</tfoot>');
|
||||
} else {
|
||||
$c = $('<tfoot>').appendTo( $t );
|
||||
$.each(t, function(i, d) {
|
||||
$tr = $('<tr>').appendTo( $c );
|
||||
l = d.length; // footer cells
|
||||
for ( j = 0; j < l; j++ ) {
|
||||
// cell(cellData, widgetOptions, 'th')
|
||||
$tb = bt.build.cell(d[j], wo, 'th', j);
|
||||
if ($tb[0] && $tb[0].length) { $tb[0].appendTo( $tr ); } // add cell
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$(table).html( $t.html() );
|
||||
bt.buildComplete(table, wo);
|
||||
};
|
||||
|
||||
bt.ajax = bt.json = function(table, data, wo) {
|
||||
return bt.object(table, data, wo);
|
||||
};
|
||||
|
||||
})(jQuery);
|
306
assets/vendor/tablesorter/js/widgets/widget-columnSelector.js
vendored
Normal file
306
assets/vendor/tablesorter/js/widgets/widget-columnSelector.js
vendored
Normal file
@@ -0,0 +1,306 @@
|
||||
/* Column Selector/Responsive table widget (beta) for TableSorter 12/17/2013 (v2.15.0)
|
||||
* Requires tablesorter v2.8+ and jQuery 1.7+
|
||||
* by Justin Hallett & Rob Garrison
|
||||
*/
|
||||
/*jshint browser:true, jquery:true, unused:false */
|
||||
/*global jQuery: false */
|
||||
;(function($){
|
||||
"use strict";
|
||||
|
||||
var ts = $.tablesorter,
|
||||
namespace = '.tscolsel',
|
||||
tsColSel = ts.columnSelector = {
|
||||
|
||||
queryAll : '@media only all { [columns] { display: none; } }',
|
||||
queryBreak : '@media screen and (min-width: [size]) { [columns] { display: table-cell; } }',
|
||||
|
||||
init: function(table, c, wo) {
|
||||
var $t, colSel;
|
||||
|
||||
// abort if no input is contained within the layout
|
||||
$t = $(wo.columnSelector_layout);
|
||||
if (!$t.find('input').add( $t.filter('input') ).length) {
|
||||
if (c.debug) {
|
||||
ts.log('*** ERROR: Column Selector aborting, no input found in the layout! ***');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// unique table class name
|
||||
c.tableId = 'tablesorter' + new Date().getTime();
|
||||
c.$table.addClass( c.tableId );
|
||||
|
||||
// build column selector/state array
|
||||
colSel = c.selector = { $container : $(wo.columnSelector_container || '<div>') };
|
||||
colSel.$style = $('<style></style>').prop('disabled', true).appendTo('head');
|
||||
colSel.$breakpoints = $('<style></style>').prop('disabled', true).appendTo('head');
|
||||
|
||||
colSel.isInitializing = true;
|
||||
tsColSel.setupSelector(table, c, wo);
|
||||
|
||||
if (wo.columnSelector_mediaquery) {
|
||||
tsColSel.setupBreakpoints(c, wo);
|
||||
}
|
||||
|
||||
colSel.isInitializing = false;
|
||||
if (colSel.$container.length) {
|
||||
tsColSel.updateCols(c, wo);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
setupSelector: function(table, c, wo) {
|
||||
var name,
|
||||
colSel = c.selector,
|
||||
$container = colSel.$container,
|
||||
useStorage = wo.columnSelector_saveColumns && ts.storage,
|
||||
// get stored column states
|
||||
saved = useStorage ? ts.storage( table, 'tablesorter-columnSelector' ) : [],
|
||||
state = useStorage ? ts.storage( table, 'tablesorter-columnSelector-auto') : {};
|
||||
|
||||
// initial states
|
||||
colSel.auto = $.isEmptyObject(state) || $.type(state.auto) !== "boolean" ? wo.columnSelector_mediaqueryState : state.auto;
|
||||
colSel.states = [];
|
||||
colSel.$column = [];
|
||||
colSel.$wrapper = [];
|
||||
colSel.$checkbox = [];
|
||||
// populate the selector container
|
||||
c.$table.children('thead').find('tr:first th', table).each(function() {
|
||||
var $this = $(this),
|
||||
// if no data-priority is assigned, default to 1, but don't remove it from the selector list
|
||||
priority = $this.attr(wo.columnSelector_priority) || 1,
|
||||
colId = $this.attr('data-column'),
|
||||
state = ts.getData(this, c.headers[colId], 'columnSelector');
|
||||
|
||||
|
||||
// if this column not hidable at all
|
||||
// include getData check (includes "columnSelector-false" class, data attribute, etc)
|
||||
if ( isNaN(priority) && priority.length > 0 || state === 'disable' ||
|
||||
( wo.columnSelector_columns[colId] && wo.columnSelector_columns[colId] === 'disable') ) {
|
||||
return true; // goto next
|
||||
}
|
||||
|
||||
// set default state; storage takes priority
|
||||
colSel.states[colId] = saved && typeof(saved[colId]) !== 'undefined' ?
|
||||
saved[colId] : typeof(wo.columnSelector_columns[colId]) !== 'undefined' ?
|
||||
wo.columnSelector_columns[colId] : state === 'true' || !(state === 'false');
|
||||
colSel.$column[colId] = $(this);
|
||||
|
||||
// set default col title
|
||||
name = $this.attr(wo.columnSelector_name) || $this.text();
|
||||
|
||||
if ($container.length) {
|
||||
colSel.$wrapper[colId] = $(wo.columnSelector_layout.replace(/\{name\}/g, name)).appendTo($container);
|
||||
colSel.$checkbox[colId] = colSel.$wrapper[colId]
|
||||
// input may not be wrapped within the layout template
|
||||
.find('input').add( colSel.$wrapper[colId].filter('input') )
|
||||
.attr('data-column', colId)
|
||||
.prop('checked', colSel.states[colId])
|
||||
.bind('change', function(){
|
||||
colSel.states[colId] = this.checked;
|
||||
tsColSel.updateCols(c, wo);
|
||||
}).change();
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
setupBreakpoints: function(c, wo){
|
||||
var colSel = c.selector;
|
||||
|
||||
// add responsive breakpoints
|
||||
if (wo.columnSelector_mediaquery) {
|
||||
// used by window resize function
|
||||
colSel.lastIndex = -1;
|
||||
wo.columnSelector_breakpoints.sort();
|
||||
tsColSel.updateBreakpoints(c, wo);
|
||||
c.$table.unbind('updateAll' + namespace).bind('updateAll' + namespace, function(){
|
||||
tsColSel.updateBreakpoints(c, wo);
|
||||
tsColSel.updateCols(c, wo);
|
||||
});
|
||||
}
|
||||
|
||||
if (colSel.$container.length) {
|
||||
// Add media queries toggle
|
||||
if (wo.columnSelector_mediaquery) {
|
||||
colSel.$auto = $( wo.columnSelector_layout.replace(/\{name\}/g, wo.columnSelector_mediaqueryName) ).prependTo(colSel.$container);
|
||||
colSel.$auto
|
||||
// needed in case the input in the layout is not wrapped
|
||||
.find('input').add( colSel.$auto.filter('input') )
|
||||
.attr('data-column', 'auto')
|
||||
.prop('checked', colSel.auto)
|
||||
.bind('change', function(){
|
||||
colSel.auto = this.checked;
|
||||
$.each( colSel.$checkbox, function(i, $cb){
|
||||
if ($cb) {
|
||||
$cb[0].disabled = colSel.auto;
|
||||
colSel.$wrapper[i].toggleClass('disabled', colSel.auto);
|
||||
}
|
||||
});
|
||||
if (wo.columnSelector_mediaquery) {
|
||||
tsColSel.updateBreakpoints(c, wo);
|
||||
}
|
||||
tsColSel.updateCols(c, wo);
|
||||
// copy the column selector to a popup/tooltip
|
||||
if (c.selector.$popup) {
|
||||
c.selector.$popup.find('.tablesorter-column-selector')
|
||||
.html( colSel.$container.html() )
|
||||
.find('input').each(function(){
|
||||
var indx = $(this).attr('data-column');
|
||||
$(this).prop( 'checked', indx === 'auto' ? colSel.auto : colSel.states[indx] );
|
||||
});
|
||||
}
|
||||
if (wo.columnSelector_saveColumns && ts.storage) {
|
||||
ts.storage( c.$table[0], 'tablesorter-columnSelector-auto', { auto : colSel.auto } );
|
||||
}
|
||||
}).change();
|
||||
}
|
||||
// Add a bind on update to re-run col setup
|
||||
c.$table.unbind('update' + namespace).bind('update' + namespace, function() {
|
||||
tsColSel.updateCols(c, wo);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
updateBreakpoints: function(c, wo) {
|
||||
var priority, column, breaks,
|
||||
colSel = c.selector,
|
||||
prefix = '.' + c.tableId,
|
||||
mediaAll = [],
|
||||
breakpts = '';
|
||||
if (wo.columnSelector_mediaquery && !colSel.auto) {
|
||||
colSel.$breakpoints.prop('disabled', true);
|
||||
colSel.$style.prop('disabled', false);
|
||||
return;
|
||||
}
|
||||
|
||||
// only 6 breakpoints (same as jQuery Mobile)
|
||||
for (priority = 0; priority < 6; priority++){
|
||||
/*jshint loopfunc:true */
|
||||
breaks = [];
|
||||
c.$headers.filter('[' + wo.columnSelector_priority + '=' + (priority + 1) + ']').each(function(){
|
||||
column = parseInt($(this).attr('data-column'), 10) + 1;
|
||||
breaks.push(prefix + ' tr th:nth-child(' + column + ')');
|
||||
breaks.push(prefix + ' tr td:nth-child(' + column + ')');
|
||||
});
|
||||
if (breaks.length) {
|
||||
mediaAll = mediaAll.concat( breaks );
|
||||
breakpts += tsColSel.queryBreak
|
||||
.replace(/\[size\]/g, wo.columnSelector_breakpoints[priority])
|
||||
.replace(/\[columns\]/g, breaks.join(','));
|
||||
}
|
||||
}
|
||||
if (colSel.$style) {
|
||||
colSel.$style.prop('disabled', true);
|
||||
}
|
||||
colSel.$breakpoints
|
||||
.prop('disabled', false)
|
||||
.html( tsColSel.queryAll.replace(/\[columns\]/g, mediaAll.join(',')) + breakpts );
|
||||
},
|
||||
|
||||
updateCols: function(c, wo) {
|
||||
if (wo.columnSelector_mediaquery && c.selector.auto || c.selector.isInitializing) {
|
||||
return;
|
||||
}
|
||||
var column,
|
||||
colSel = c.selector,
|
||||
styles = [],
|
||||
prefix = '.' + c.tableId;
|
||||
colSel.$container.find('input[data-column]').filter('[data-column!="auto"]').each(function(){
|
||||
if (!this.checked) {
|
||||
column = parseInt( $(this).attr('data-column'), 10 ) + 1;
|
||||
styles.push(prefix + ' tr th:nth-child(' + column + ')');
|
||||
styles.push(prefix + ' tr td:nth-child(' + column + ')');
|
||||
}
|
||||
});
|
||||
if (wo.columnSelector_mediaquery){
|
||||
colSel.$breakpoints.prop('disabled', true);
|
||||
}
|
||||
if (colSel.$style) {
|
||||
colSel.$style.prop('disabled', false).html( styles.length ? styles.join(',') + ' { display: none; }' : '' );
|
||||
}
|
||||
if (wo.columnSelector_saveColumns && ts.storage) {
|
||||
ts.storage( c.$table[0], 'tablesorter-columnSelector', colSel.states );
|
||||
}
|
||||
},
|
||||
|
||||
attachTo : function(table, elm) {
|
||||
table = $(table)[0];
|
||||
var colSel, wo, indx,
|
||||
c = table.config,
|
||||
$popup = $(elm);
|
||||
if ($popup.length && c) {
|
||||
if (!$popup.find('.tablesorter-column-selector').length) {
|
||||
// add a wrapper to add the selector into, in case the popup has other content
|
||||
$popup.append('<span class="tablesorter-column-selector"></span>');
|
||||
}
|
||||
colSel = c.selector;
|
||||
wo = c.widgetOptions;
|
||||
$popup.find('.tablesorter-column-selector')
|
||||
.html( colSel.$container.html() )
|
||||
.find('input').each(function(){
|
||||
var indx = $(this).attr('data-column');
|
||||
$(this).prop( 'checked', indx === 'auto' ? colSel.auto : colSel.states[indx] );
|
||||
});
|
||||
colSel.$popup = $popup.on('change', 'input', function(){
|
||||
// data input
|
||||
indx = $(this).attr('data-column');
|
||||
// update original popup
|
||||
colSel.$container.find('input[data-column="' + indx + '"]')
|
||||
.prop('checked', this.checked)
|
||||
.trigger('change');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
ts.addWidget({
|
||||
id: "columnSelector",
|
||||
priority: 10,
|
||||
options: {
|
||||
// target the column selector markup
|
||||
columnSelector_container : null,
|
||||
// column status, true = display, false = hide
|
||||
// disable = do not display on list
|
||||
columnSelector_columns : {},
|
||||
// remember selected columns
|
||||
columnSelector_saveColumns: true,
|
||||
|
||||
// container layout
|
||||
columnSelector_layout : '<label><input type="checkbox">{name}</label>',
|
||||
// data attribute containing column name to use in the selector container
|
||||
columnSelector_name : 'data-selector-name',
|
||||
|
||||
/* Responsive Media Query settings */
|
||||
// enable/disable mediaquery breakpoints
|
||||
columnSelector_mediaquery: true,
|
||||
// toggle checkbox name
|
||||
columnSelector_mediaqueryName: 'Auto: ',
|
||||
// breakpoints checkbox initial setting
|
||||
columnSelector_mediaqueryState: true,
|
||||
// responsive table hides columns with priority 1-6 at these breakpoints
|
||||
// see http://view.jquerymobile.com/1.3.2/dist/demos/widgets/table-column-toggle/#Applyingapresetbreakpoint
|
||||
// *** set to false to disable ***
|
||||
columnSelector_breakpoints : [ '20em', '30em', '40em', '50em', '60em', '70em' ],
|
||||
// data attribute containing column priority
|
||||
// duplicates how jQuery mobile uses priorities:
|
||||
// http://view.jquerymobile.com/1.3.2/dist/demos/widgets/table-column-toggle/
|
||||
columnSelector_priority : 'data-priority'
|
||||
|
||||
},
|
||||
init: function(table, thisWidget, c, wo) {
|
||||
tsColSel.init(table, c, wo);
|
||||
},
|
||||
remove: function(table, c){
|
||||
var csel = c.selector;
|
||||
csel.$container.empty();
|
||||
csel.$popup.empty();
|
||||
csel.$style.remove();
|
||||
csel.$breakpoints.remove();
|
||||
c.$table.unbind('updateAll' + namespace + ',update' + namespace);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
})(jQuery);
|
67
assets/vendor/tablesorter/js/widgets/widget-cssStickyHeaders.js
vendored
Normal file
67
assets/vendor/tablesorter/js/widgets/widget-cssStickyHeaders.js
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
/*! tablesorter CSS Sticky Headers widget - updated 12/17/2013 (v2.15.0)
|
||||
* Requires a modern browser, tablesorter v2.8+
|
||||
*/
|
||||
/*global jQuery: false, unused:false */
|
||||
;(function($){
|
||||
"use strict";
|
||||
|
||||
$.tablesorter.addWidget({
|
||||
id: "cssStickyHeaders",
|
||||
priority: 10,
|
||||
options: {
|
||||
cssStickyHeaders_offset : 0,
|
||||
cssStickyHeaders_addCaption : false,
|
||||
cssStickyHeaders_attachTo : null,
|
||||
cssStickyHeaders_zIndex : 10
|
||||
},
|
||||
init : function(table, thisWidget, c, wo) {
|
||||
var $attach = $(wo.cssStickyHeaders_attachTo),
|
||||
namespace = '.cssstickyheader',
|
||||
$thead = c.$table.children('thead'),
|
||||
$caption = c.$table.find('caption'),
|
||||
$win = $attach.length ? $attach : $(window);
|
||||
$win.bind('scroll resize '.split(' ').join(namespace + ' '), function() {
|
||||
var top = $attach.length ? $attach.offset().top : $win.scrollTop(),
|
||||
// add caption height; include table padding top & border-spacing or text may be above the fold (jQuery UI themes)
|
||||
// border-spacing needed in Firefox, but not webkit... not sure if I should account for that
|
||||
captionTop = wo.cssStickyHeaders_addCaption ? $caption.outerHeight(true) +
|
||||
(parseInt(c.$table.css('padding-top'), 10) || 0) + (parseInt(c.$table.css('border-spacing'), 10) || 0) : 0,
|
||||
bottom = c.$table.height() - $thead.height() - (c.$table.find('tfoot').height() || 0) - captionTop,
|
||||
deltaY = top - $thead.offset().top + (parseInt(c.$table.css('border-top-width'), 10) || 0) +
|
||||
(wo.cssStickyHeaders_offset || 0) + captionTop,
|
||||
finalY = (deltaY > 0 && deltaY <= bottom ? deltaY : 0),
|
||||
// IE can only transform header cells - fixes #447 thanks to @gakreol!
|
||||
$cells = $thead.children().children();
|
||||
if (wo.cssStickyHeaders_addCaption) {
|
||||
$cells = $cells.add($caption);
|
||||
}
|
||||
$cells.css({
|
||||
"position" : "relative",
|
||||
"z-index" : wo.cssStickyHeaders_zIndex,
|
||||
"transform" : finalY === 0 ? "" : "translate(0px," + finalY + "px)",
|
||||
"-ms-transform" : finalY === 0 ? "" : "translate(0px," + finalY + "px)",
|
||||
"-webkit-transform" : finalY === 0 ? "" : "translate(0px," + finalY + "px)"
|
||||
});
|
||||
});
|
||||
c.$table.bind('filterEnd', function() {
|
||||
// scroll top of table into view
|
||||
window.scrollTo(0, c.$table.position().top);
|
||||
});
|
||||
|
||||
},
|
||||
remove: function(table, c, wo){
|
||||
var namespace = '.cssstickyheader';
|
||||
$(window).unbind('scroll resize '.split(' ').join(namespace + ' '));
|
||||
c.$table
|
||||
.unbind('update updateAll '.split(' ').join(namespace + ' '))
|
||||
.children('thead, caption').css({
|
||||
"position" : "",
|
||||
"z-index" : "",
|
||||
"transform" : "",
|
||||
"-ms-transform" : "",
|
||||
"-webkit-transform" : ""
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
})(jQuery);
|
89
assets/vendor/tablesorter/js/widgets/widget-editable.js
vendored
Normal file
89
assets/vendor/tablesorter/js/widgets/widget-editable.js
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
/*! tablesorter Editable Content widget - updated 1/24/2014 (core v2.15.0)
|
||||
* Requires tablesorter v2.8+ and jQuery 1.7+
|
||||
* by Rob Garrison
|
||||
*/
|
||||
/*jshint browser:true, jquery:true, unused:false */
|
||||
/*global jQuery: false */
|
||||
;(function($){
|
||||
"use strict";
|
||||
|
||||
$.tablesorter.addWidget({
|
||||
id: 'editable',
|
||||
options : {
|
||||
editable_columns : [],
|
||||
editable_enterToAccept : true,
|
||||
editable_autoResort : false,
|
||||
editable_noEdit : 'no-edit',
|
||||
editable_editComplete : 'editComplete'
|
||||
},
|
||||
init: function(table, thisWidget, c, wo){
|
||||
if (!wo.editable_columns.length) { return; }
|
||||
var indx, tmp, $t, cols = [];
|
||||
if (wo.editable_columns.indexOf('-') >= 0) {
|
||||
// editable_columns can contain a range string (i.e. "2-4" )
|
||||
tmp = wo.editable_columns.split('-');
|
||||
indx = parseInt(tmp[0],10) || 0;
|
||||
tmp = parseInt(tmp[1],10) || (c.columns - 1);
|
||||
if (tmp > c.columns) { tmp = c.columns - 1; }
|
||||
for (; indx <= tmp; indx++) {
|
||||
cols.push('td:nth-child(' + (indx + 1) + ')');
|
||||
}
|
||||
} else if ($.isArray(wo.editable_columns)) {
|
||||
$.each(wo.editable_columns, function(i, col){
|
||||
cols.push('td:nth-child(' + (col + 1) + ')');
|
||||
});
|
||||
}
|
||||
// IE does not allow making TR/TH/TD cells directly editable (issue #404)
|
||||
// so add a div or span inside ( it's faster than using wrapInner() )
|
||||
c.$tbodies.find( cols.join(',') ).not('.' + wo.editable_noEdit).each(function(){
|
||||
// test for children, if they exist, then make the children editable
|
||||
$t = $(this);
|
||||
( $t.children().length ? $t.children() : $t ).prop('contenteditable', true);
|
||||
});
|
||||
c.$tbodies
|
||||
.on('mouseleave.tseditable', function(){
|
||||
if (c.$table.data('contentFocused')) {
|
||||
$(':focus').trigger('blur');
|
||||
}
|
||||
})
|
||||
.on('focus.tseditable', '[contenteditable]', function(){
|
||||
c.$table.data('contentFocused', true);
|
||||
var $this = $(this), v = $this.html();
|
||||
if (wo.editable_enterToAccept) {
|
||||
// prevent enter from adding into the content
|
||||
$this.on('keydown.tseditable', function(e){
|
||||
if (e.which === 13) {
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
}
|
||||
$this.data({ before : v, original: v });
|
||||
})
|
||||
.on('blur focusout keyup '.split(' ').join('.tseditable '), '[contenteditable]', function(e){
|
||||
if (!c.$table.data('contentFocused')) { return; }
|
||||
var $this = $(e.target), t;
|
||||
if (e.which === 27) {
|
||||
// user cancelled
|
||||
$this.html( $this.data('original') ).trigger('blur.tseditable');
|
||||
c.$table.data('contentFocused', false);
|
||||
return false;
|
||||
}
|
||||
t = e.type !== 'keyup' || (wo.editable_enterToAccept && e.which === 13);
|
||||
// change if new or user hits enter (if option set)
|
||||
if ($this.data('before') !== $this.html() || t) {
|
||||
$this.data('before', $this.html()).trigger('change');
|
||||
if (t) {
|
||||
c.$table
|
||||
.data('contentFocused', false)
|
||||
.trigger('updateCell', [ $this.closest('td'), wo.editable_autoResort, function(table){
|
||||
$this.trigger( wo.editable_editComplete );
|
||||
c.$table.trigger('applyWidgets');
|
||||
} ]);
|
||||
$this.trigger('blur.tseditable');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
})(jQuery);
|
250
assets/vendor/tablesorter/js/widgets/widget-grouping.js
vendored
Normal file
250
assets/vendor/tablesorter/js/widgets/widget-grouping.js
vendored
Normal file
@@ -0,0 +1,250 @@
|
||||
/*! tablesorter Grouping widget - updated 3/7/2014 (core v2.15.6)
|
||||
* Requires tablesorter v2.8+ and jQuery 1.7+
|
||||
* by Rob Garrison
|
||||
*/
|
||||
/*jshint browser:true, jquery:true, unused:false */
|
||||
/*global jQuery: false */
|
||||
;(function($){
|
||||
"use strict";
|
||||
var ts = $.tablesorter;
|
||||
|
||||
ts.grouping = {
|
||||
|
||||
types : {
|
||||
number : function(c, $column, txt, num, group){
|
||||
var value, word;
|
||||
if (num > 1 && txt !== '') {
|
||||
if ($column.hasClass(ts.css.sortAsc)) {
|
||||
value = Math.floor(parseFloat(txt)/num) * num;
|
||||
return value > parseFloat(group || 0) ? value : parseFloat(group || 0);
|
||||
} else {
|
||||
value = Math.ceil(parseFloat(txt)/num) * num;
|
||||
return value < parseFloat(group || num) - value ? parseFloat(group || num) - value : value;
|
||||
}
|
||||
} else {
|
||||
word = (txt + '').match(/\d+/g);
|
||||
return word && word.length >= num ? word[num - 1] : txt || '';
|
||||
}
|
||||
},
|
||||
separator : function(c, $column, txt, num){
|
||||
var word = (txt + '').split(c.widgetOptions.group_separator);
|
||||
return $.trim(word && num > 0 && word.length >= num ? word[(num || 1) - 1] : '');
|
||||
},
|
||||
word : function(c, $column, txt, num){
|
||||
var word = (txt + ' ').match(/\w+/g);
|
||||
return word && word.length >= num ? word[num - 1] : txt || '';
|
||||
},
|
||||
letter : function(c, $column, txt, num){
|
||||
return txt ? (txt + ' ').substring(0, num) : '';
|
||||
},
|
||||
date : function(c, $column, txt, part, group){
|
||||
var wo = c.widgetOptions,
|
||||
time = new Date(txt || ''),
|
||||
hours = time.getHours();
|
||||
return part === 'year' ? time.getFullYear() :
|
||||
part === 'month' ? wo.group_months[time.getMonth()] :
|
||||
part === 'day' ? wo.group_months[time.getMonth()] + ' ' + time.getDate() :
|
||||
part === 'week' ? wo.group_week[time.getDay()] :
|
||||
part === 'time' ? ('00' + (hours > 12 ? hours - 12 : hours === 0 ? hours + 12 : hours)).slice(-2) + ':' +
|
||||
('00' + time.getMinutes()).slice(-2) + ' ' + ('00' + wo.group_time[hours >= 12 ? 1 : 0]).slice(-2) :
|
||||
wo.group_dateString(time);
|
||||
}
|
||||
},
|
||||
|
||||
update : function(table, c, wo){
|
||||
if ($.isEmptyObject(c.cache)) { return; }
|
||||
var rowIndex, tbodyIndex, currentGroup, $rows, groupClass, grouping, time, cache, saveName, direction,
|
||||
lang = wo.grouping_language,
|
||||
group = '',
|
||||
savedGroup = false,
|
||||
column = c.sortList[0] ? c.sortList[0][0] : -1;
|
||||
c.$table
|
||||
.find('tr.group-hidden').removeClass('group-hidden').end()
|
||||
.find('tr.group-header').remove();
|
||||
if (wo.group_collapsible) {
|
||||
// clear pager saved spacer height (in case the rows are collapsed)
|
||||
c.$table.data('pagerSavedHeight', 0);
|
||||
}
|
||||
if (column >= 0 && !c.$headers.filter('[data-column="' + column + '"]:last').hasClass('group-false')) {
|
||||
if (c.debug){ time = new Date(); }
|
||||
wo.group_currentGroup = ''; // save current groups
|
||||
wo.group_currentGroups = {};
|
||||
|
||||
// group class finds "group-{word/separator/letter/number/date/false}-{optional:#/year/month/day/week/time}"
|
||||
groupClass = (c.$headers.filter('[data-column="' + column + '"]:last').attr('class') || '').match(/(group-\w+(-\w+)?)/g);
|
||||
// grouping = [ 'group', '{word/separator/letter/number/date/false}', '{#/year/month/day/week/time}' ]
|
||||
grouping = groupClass ? groupClass[0].split('-') : ['group','letter',1]; // default to letter 1
|
||||
|
||||
// save current grouping
|
||||
if (wo.group_collapsible && wo.group_saveGroups && ts.storage) {
|
||||
wo.group_currentGroups = ts.storage( table, 'tablesorter-groups' ) || {};
|
||||
// include direction when grouping numbers > 1 (reversed direction shows different range values)
|
||||
direction = (grouping[1] === 'number' && grouping[2] > 1) ? 'dir' + c.sortList[0][1] : '';
|
||||
// combine column, sort direction & grouping as save key
|
||||
saveName = wo.group_currentGroup = '' + column + direction + grouping.join('');
|
||||
if (!wo.group_currentGroups[saveName]) {
|
||||
wo.group_currentGroups[saveName] = [];
|
||||
} else {
|
||||
savedGroup = true;
|
||||
}
|
||||
}
|
||||
for (tbodyIndex = 0; tbodyIndex < c.$tbodies.length; tbodyIndex++) {
|
||||
cache = c.cache[tbodyIndex].normalized;
|
||||
group = ''; // clear grouping across tbodies
|
||||
$rows = c.$tbodies.eq(tbodyIndex).children('tr').not('.' + c.cssChildRow);
|
||||
for (rowIndex = 0; rowIndex < $rows.length; rowIndex++) {
|
||||
if ( $rows.eq(rowIndex).is(':visible') ) {
|
||||
// fixes #438
|
||||
if (ts.grouping.types[grouping[1]]) {
|
||||
currentGroup = cache[rowIndex] ?
|
||||
ts.grouping.types[grouping[1]]( c, c.$headers.filter('[data-column="' + column + '"]:last'), cache[rowIndex][column], /date/.test(groupClass) ?
|
||||
grouping[2] : parseInt(grouping[2] || 1, 10) || 1, group, lang ) : currentGroup;
|
||||
if (group !== currentGroup) {
|
||||
group = currentGroup;
|
||||
// show range if number > 1
|
||||
if (grouping[1] === 'number' && grouping[2] > 1 && currentGroup !== '') {
|
||||
currentGroup += ' - ' + (parseInt(currentGroup, 10) +
|
||||
((parseInt(grouping[2],10) - 1) * (c.$headers.filter('[data-column="' + column + '"]:last').hasClass(ts.css.sortAsc) ? 1 : -1)));
|
||||
}
|
||||
if ($.isFunction(wo.group_formatter)) {
|
||||
currentGroup = wo.group_formatter((currentGroup || '').toString(), column, table, c, wo) || currentGroup;
|
||||
}
|
||||
$rows.eq(rowIndex).before('<tr class="group-header ' + c.selectorRemove.slice(1) +
|
||||
// (wo.group_collapsed && wo.group_collapsible ? ' collapsed' : '') +
|
||||
'" unselectable="on"><td colspan="' +
|
||||
c.columns + '">' + (wo.group_collapsible ? '<i/>' : '') + '<span class="group-name">' +
|
||||
currentGroup + '</span><span class="group-count"></span></td></tr>');
|
||||
if (wo.group_saveGroups && !savedGroup && wo.group_collapsed && wo.group_collapsible) {
|
||||
// all groups start collapsed
|
||||
wo.group_currentGroups[wo.group_currentGroup].push(currentGroup);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
c.$table.find('tr.group-header')
|
||||
.bind('selectstart', false)
|
||||
.each(function(){
|
||||
var isHidden, $label,
|
||||
$row = $(this),
|
||||
name = $row.find('.group-name').text().toLowerCase(),
|
||||
$rows = $row.nextUntil('tr.group-header').filter(':visible');
|
||||
if (wo.group_count || $.isFunction(wo.group_callback)) {
|
||||
$label = $row.find('.group-count');
|
||||
if ($label.length) {
|
||||
if (wo.group_count) {
|
||||
$label.html( wo.group_count.replace(/\{num\}/g, $rows.length) );
|
||||
}
|
||||
if ($.isFunction(wo.group_callback)) {
|
||||
wo.group_callback($row.find('td'), $rows, column, table);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (wo.group_saveGroups && wo.group_currentGroups[wo.group_currentGroup].length) {
|
||||
isHidden = $.inArray( name, wo.group_currentGroups[wo.group_currentGroup] ) > -1;
|
||||
$row.toggleClass('collapsed', isHidden);
|
||||
$rows.toggleClass('group-hidden', isHidden);
|
||||
} else if (wo.group_collapsed && wo.group_collapsible) {
|
||||
$row.addClass('collapsed');
|
||||
$rows.addClass('group-hidden');
|
||||
}
|
||||
});
|
||||
c.$table.trigger(wo.group_complete);
|
||||
if (c.debug) {
|
||||
$.tablesorter.benchmark("Applying groups widget: ", time);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
bindEvents : function(table, c, wo){
|
||||
if (wo.group_collapsible) {
|
||||
wo.group_currentGroups = [];
|
||||
// .on() requires jQuery 1.7+
|
||||
c.$table.on('click toggleGroup', 'tr.group-header', function(event){
|
||||
event.stopPropagation();
|
||||
var isCollapsed, $groups, indx,
|
||||
$this = $(this),
|
||||
name = $this.find('.group-name').text();
|
||||
// use shift-click to toggle ALL groups
|
||||
if (event.type === 'click' && event.shiftKey) {
|
||||
$this.siblings('.group-header').trigger('toggleGroup');
|
||||
}
|
||||
$this.toggleClass('collapsed');
|
||||
// nextUntil requires jQuery 1.4+
|
||||
$this.nextUntil('tr.group-header').toggleClass('group-hidden', $this.hasClass('collapsed') );
|
||||
// save collapsed groups
|
||||
if (wo.group_saveGroups && ts.storage) {
|
||||
$groups = c.$table.find('.group-header');
|
||||
isCollapsed = $this.hasClass('collapsed');
|
||||
if (!wo.group_currentGroups[wo.group_currentGroup]) {
|
||||
wo.group_currentGroups[wo.group_currentGroup] = [];
|
||||
}
|
||||
if (isCollapsed && wo.group_currentGroup) {
|
||||
wo.group_currentGroups[wo.group_currentGroup].push( name );
|
||||
} else if (wo.group_currentGroup) {
|
||||
indx = $.inArray( name, wo.group_currentGroups[wo.group_currentGroup] );
|
||||
if (indx > -1) {
|
||||
wo.group_currentGroups[wo.group_currentGroup].splice( indx, 1 );
|
||||
}
|
||||
}
|
||||
ts.storage( table, 'tablesorter-groups', wo.group_currentGroups );
|
||||
}
|
||||
});
|
||||
}
|
||||
$(wo.group_saveReset).on('click', function(){
|
||||
ts.grouping.clearSavedGroups(table);
|
||||
});
|
||||
c.$table.on('pagerChange.tsgrouping', function(){
|
||||
ts.grouping.update(table, c, wo);
|
||||
});
|
||||
},
|
||||
|
||||
clearSavedGroups: function(table){
|
||||
if (table && ts.storage) {
|
||||
ts.storage(table, 'tablesorter-groups', '');
|
||||
ts.grouping.update(table, table.config, table.config.widgetOptions);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
ts.addWidget({
|
||||
id: 'group',
|
||||
priority: 100,
|
||||
options: {
|
||||
group_collapsible : true, // make the group header clickable and collapse the rows below it.
|
||||
group_collapsed : false, // start with all groups collapsed
|
||||
group_saveGroups : true, // remember collapsed groups
|
||||
group_saveReset : null, // element to clear saved collapsed groups
|
||||
group_count : ' ({num})', // if not false, the "{num}" string is replaced with the number of rows in the group
|
||||
group_separator : '-', // group name separator; used when group-separator-# class is used.
|
||||
group_formatter : null, // function(txt, column, table, c, wo) { return txt; }
|
||||
group_callback : null, // function($cell, $rows, column, table){}, callback allowing modification of the group header labels
|
||||
group_complete : 'groupingComplete', // event triggered on the table when the grouping widget has finished work
|
||||
|
||||
// change these default date names based on your language preferences
|
||||
group_months : [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ],
|
||||
group_week : [ 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday' ],
|
||||
group_time : [ 'AM', 'PM' ],
|
||||
// this function is used when "group-date" is set to create the date string
|
||||
// you can just return date, date.toLocaleString(), date.toLocaleDateString() or d.toLocaleTimeString()
|
||||
// reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#Conversion_getter
|
||||
group_dateString : function(date) { return date.toLocaleString(); }
|
||||
},
|
||||
init: function(table, thisWidget, c, wo){
|
||||
ts.grouping.bindEvents(table, c, wo);
|
||||
},
|
||||
format: function(table, c, wo) {
|
||||
ts.grouping.update(table, c, wo);
|
||||
},
|
||||
remove : function(table, c, wo){
|
||||
c.$table
|
||||
.off('click', 'tr.group-header')
|
||||
.off('pagerChange.tsgrouping')
|
||||
.find('.group-hidden').removeClass('group-hidden').end()
|
||||
.find('tr.group-header').remove();
|
||||
}
|
||||
});
|
||||
|
||||
})(jQuery);
|
91
assets/vendor/tablesorter/js/widgets/widget-headerTitles.js
vendored
Normal file
91
assets/vendor/tablesorter/js/widgets/widget-headerTitles.js
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
/*! tablesorter headerTitles widget - updated 3/5/2014 (core v2.15.6)
|
||||
* Requires tablesorter v2.8+ and jQuery 1.7+
|
||||
* by Rob Garrison
|
||||
*/
|
||||
/*jshint browser:true, jquery:true, unused:false */
|
||||
/*global jQuery: false */
|
||||
;(function($){
|
||||
"use strict";
|
||||
var ts = $.tablesorter;
|
||||
|
||||
ts.addWidget({
|
||||
id: 'headerTitles',
|
||||
options: {
|
||||
// use aria-label text
|
||||
// e.g. "First Name: Ascending sort applied, activate to apply a descending sort"
|
||||
headerTitle_useAria : false,
|
||||
// add tooltip class
|
||||
headerTitle_tooltip : '',
|
||||
// custom titles [ ascending, descending, unsorted ]
|
||||
headerTitle_cur_text : [ ' sort: A - Z', ' sort: Z - A', 'ly unsorted' ],
|
||||
headerTitle_cur_numeric : [ ' sort: 0 - 9', ' sort: 9 - 0', 'ly unsorted' ],
|
||||
headerTitle_nxt_text : [ ' sort: A - Z', ' sort: Z - A', 'remove sort' ],
|
||||
headerTitle_nxt_numeric : [ ' sort: 0 - 9', ' sort: 9 - 0', 'remove sort' ],
|
||||
|
||||
// title display; {prefix} adds above prefix
|
||||
// {type} adds the current sort order from above (text or numeric)
|
||||
// {next} adds the next sort direction using the sort order above
|
||||
headerTitle_output_sorted : 'current{current}; activate to {next}',
|
||||
headerTitle_output_unsorted : 'current{current}; activate to {next} ',
|
||||
headerTitle_output_nosort : 'No sort available',
|
||||
// use this type to override the parser detection result
|
||||
// e.g. use for numerically parsed columns (e.g. dates), but you
|
||||
// want the user to see a text sort, e.g. [ 'text', 'numeric' ]
|
||||
headerTitle_type : [],
|
||||
// manipulate the title as desired
|
||||
headerTitle_callback : null // function($cell, txt) { return txt; }
|
||||
},
|
||||
init: function(table, thisWidget, c, wo){
|
||||
// force refresh
|
||||
c.$table.on('refreshHeaderTitle', function(){
|
||||
thisWidget.format(table, c, wo);
|
||||
});
|
||||
// add tooltip class
|
||||
if ($.isArray(wo.headerTitle_tooltip)) {
|
||||
c.$headers.each(function(){
|
||||
$(this).addClass( wo.headerTitle_tooltip[this.column] || '' );
|
||||
});
|
||||
} else if (wo.headerTitle_tooltip !== '') {
|
||||
c.$headers.addClass( wo.headerTitle_tooltip );
|
||||
}
|
||||
},
|
||||
format: function (table, c, wo) {
|
||||
var txt;
|
||||
c.$headers.each(function(){
|
||||
var t = this,
|
||||
$this = $(this),
|
||||
sortType = wo.headerTitle_type[t.column] || c.parsers[ t.column ].type || 'text',
|
||||
sortDirection = $this.hasClass(ts.css.sortAsc) ? 0 : $this.hasClass(ts.css.sortDesc) ? 1 : 2,
|
||||
sortNext = t.order[(t.count + 1) % (c.sortReset ? 3 : 2)];
|
||||
if (wo.headerTitle_useAria) {
|
||||
txt = $this.hasClass('sorter-false') ? wo.headerTitle_output_nosort : $this.attr('aria-label') || '';
|
||||
} else {
|
||||
txt = (wo.headerTitle_prefix || '') + // now deprecated
|
||||
($this.hasClass('sorter-false') ? wo.headerTitle_output_nosort :
|
||||
ts.isValueInArray( t.column, c.sortList ) >= 0 ? wo.headerTitle_output_sorted : wo.headerTitle_output_unsorted);
|
||||
txt = txt.replace(/\{(current|next|name)\}/gi, function(m){
|
||||
return {
|
||||
'{name}' : $this.text(),
|
||||
'{current}' : wo[ 'headerTitle_cur_' + sortType ][ sortDirection ] || '',
|
||||
'{next}' : wo[ 'headerTitle_nxt_' + sortType ][ sortNext ] || ''
|
||||
}[m.toLowerCase()];
|
||||
});
|
||||
}
|
||||
$this.attr('title', $.isFunction(wo.headerTitle_callback) ? wo.headerTitle_callback($this, txt) : txt);
|
||||
});
|
||||
},
|
||||
remove: function (table, c, wo) {
|
||||
c.$headers.attr('title', '');
|
||||
c.$table.off('refreshHeaderTitle');
|
||||
// remove tooltip class
|
||||
if ($.isArray(wo.headerTitle_tooltip)) {
|
||||
c.$headers.each(function(){
|
||||
$(this).removeClass( wo.headerTitle_tooltip[this.column] || '' );
|
||||
});
|
||||
} else if (wo.headerTitle_tooltip !== '') {
|
||||
c.$headers.removeClass( wo.headerTitle_tooltip );
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
})(jQuery);
|
847
assets/vendor/tablesorter/js/widgets/widget-pager.js
vendored
Normal file
847
assets/vendor/tablesorter/js/widgets/widget-pager.js
vendored
Normal file
@@ -0,0 +1,847 @@
|
||||
/* Pager widget (beta) for TableSorter 3/7/2014 (v2.15.6) */
|
||||
/*jshint browser:true, jquery:true, unused:false */
|
||||
;(function($){
|
||||
"use strict";
|
||||
var tsp,
|
||||
ts = $.tablesorter;
|
||||
|
||||
ts.addWidget({
|
||||
id: "pager",
|
||||
priority: 55, // load pager after filter widget
|
||||
options : {
|
||||
// output default: '{page}/{totalPages}'
|
||||
// possible variables: {page}, {totalPages}, {filteredPages}, {startRow}, {endRow}, {filteredRows} and {totalRows}
|
||||
pager_output: '{startRow} to {endRow} of {totalRows} rows', // '{page}/{totalPages}'
|
||||
|
||||
// apply disabled classname to the pager arrows when the rows at either extreme is visible
|
||||
pager_updateArrows: true,
|
||||
|
||||
// starting page of the pager (zero based index)
|
||||
pager_startPage: 0,
|
||||
|
||||
// Number of visible rows
|
||||
pager_size: 10,
|
||||
|
||||
// Save pager page & size if the storage script is loaded (requires $.tablesorter.storage in jquery.tablesorter.widgets.js)
|
||||
pager_savePages: true,
|
||||
|
||||
//defines custom storage key
|
||||
pager_storageKey: 'tablesorter-pager',
|
||||
|
||||
// if true, the table will remain the same height no matter how many records are displayed. The space is made up by an empty
|
||||
// table row set to a height to compensate; default is false
|
||||
pager_fixedHeight: false,
|
||||
|
||||
// count child rows towards the set page size? (set true if it is a visible table row within the pager)
|
||||
// if true, child row(s) may not appear to be attached to its parent row, may be split across pages or
|
||||
// may distort the table if rowspan or cellspans are included.
|
||||
pager_countChildRows: false,
|
||||
|
||||
// remove rows from the table to speed up the sort of large tables.
|
||||
// setting this to false, only hides the non-visible rows; needed if you plan to add/remove rows with the pager enabled.
|
||||
pager_removeRows: false, // removing rows in larger tables speeds up the sort
|
||||
|
||||
// use this format: "http://mydatabase.com?page={page}&size={size}&{sortList:col}&{filterList:fcol}"
|
||||
// where {page} is replaced by the page number, {size} is replaced by the number of records to show,
|
||||
// {sortList:col} adds the sortList to the url into a "col" array, and {filterList:fcol} adds
|
||||
// the filterList to the url into an "fcol" array.
|
||||
// So a sortList = [[2,0],[3,0]] becomes "&col[2]=0&col[3]=0" in the url
|
||||
// and a filterList = [[2,Blue],[3,13]] becomes "&fcol[2]=Blue&fcol[3]=13" in the url
|
||||
pager_ajaxUrl: null,
|
||||
|
||||
// modify the url after all processing has been applied
|
||||
pager_customAjaxUrl: function(table, url) { return url; },
|
||||
|
||||
// modify the $.ajax object to allow complete control over your ajax requests
|
||||
pager_ajaxObject: {
|
||||
dataType: 'json'
|
||||
},
|
||||
|
||||
// set this to false if you want to block ajax loading on init
|
||||
pager_processAjaxOnInit: true,
|
||||
|
||||
// process ajax so that the following information is returned:
|
||||
// [ total_rows (number), rows (array of arrays), headers (array; optional) ]
|
||||
// example:
|
||||
// [
|
||||
// 100, // total rows
|
||||
// [
|
||||
// [ "row1cell1", "row1cell2", ... "row1cellN" ],
|
||||
// [ "row2cell1", "row2cell2", ... "row2cellN" ],
|
||||
// ...
|
||||
// [ "rowNcell1", "rowNcell2", ... "rowNcellN" ]
|
||||
// ],
|
||||
// [ "header1", "header2", ... "headerN" ] // optional
|
||||
// ]
|
||||
pager_ajaxProcessing: function(ajax){ return [ 0, [], null ]; },
|
||||
|
||||
// css class names of pager arrows
|
||||
pager_css: {
|
||||
container : 'tablesorter-pager',
|
||||
errorRow : 'tablesorter-errorRow', // error information row (don't include period at beginning)
|
||||
disabled : 'disabled' // class added to arrows @ extremes (i.e. prev/first arrows "disabled" on first page)
|
||||
},
|
||||
|
||||
// jQuery selectors
|
||||
pager_selectors: {
|
||||
container : '.pager', // target the pager markup
|
||||
first : '.first', // go to first page arrow
|
||||
prev : '.prev', // previous page arrow
|
||||
next : '.next', // next page arrow
|
||||
last : '.last', // go to last page arrow
|
||||
goto : '.gotoPage', // go to page selector - select dropdown that sets the current page
|
||||
pageDisplay : '.pagedisplay', // location of where the "output" is displayed
|
||||
pageSize : '.pagesize' // page size selector - select dropdown that sets the "size" option
|
||||
}
|
||||
},
|
||||
init: function(table){
|
||||
tsp.init(table);
|
||||
},
|
||||
// only update to complete sorter initialization
|
||||
format: function(table, c){
|
||||
if (!(c.pager && c.pager.initialized)){
|
||||
return tsp.initComplete(table, c);
|
||||
}
|
||||
tsp.moveToPage(table, c.pager, false);
|
||||
},
|
||||
remove: function(table, c){
|
||||
tsp.destroyPager(table, c);
|
||||
}
|
||||
});
|
||||
|
||||
/* pager widget functions */
|
||||
tsp = ts.pager = {
|
||||
|
||||
init: function(table) {
|
||||
// check if tablesorter has initialized
|
||||
if (table.hasInitialized && table.config.pager.initialized) { return; }
|
||||
var t,
|
||||
c = table.config,
|
||||
wo = c.widgetOptions,
|
||||
s = wo.pager_selectors,
|
||||
|
||||
// save pager variables
|
||||
p = c.pager = $.extend({
|
||||
totalPages: 0,
|
||||
filteredRows: 0,
|
||||
filteredPages: 0,
|
||||
currentFilters: [],
|
||||
page: wo.pager_startPage,
|
||||
size: wo.pager_size,
|
||||
startRow: 0,
|
||||
endRow: 0,
|
||||
ajaxCounter: 0,
|
||||
$size: null,
|
||||
last: {}
|
||||
}, c.pager);
|
||||
|
||||
// pager initializes multiple times before table has completed initialization
|
||||
if (p.isInitializing) { return; }
|
||||
|
||||
p.isInitializing = true;
|
||||
if (c.debug) {
|
||||
ts.log('Pager initializing');
|
||||
}
|
||||
|
||||
// added in case the pager is reinitialized after being destroyed.
|
||||
p.$container = $(s.container).addClass(wo.pager_css.container).show();
|
||||
// goto selector
|
||||
p.$goto = p.$container.find(s.goto);
|
||||
// page size selector
|
||||
p.$size = p.$container.find(s.pageSize);
|
||||
p.totalRows = c.$tbodies.eq(0).children().length;
|
||||
p.oldAjaxSuccess = p.oldAjaxSuccess || wo.pager_ajaxObject.success;
|
||||
c.appender = tsp.appender;
|
||||
if (ts.filter && $.inArray('filter', c.widgets) >= 0) {
|
||||
// get any default filter settings (data-value attribute) fixes #388
|
||||
p.currentFilters = c.$table.data('lastSearch') || ts.filter.setDefaults(table, c, wo) || [];
|
||||
// set, but don't apply current filters
|
||||
ts.setFilters(table, p.currentFilters, false);
|
||||
}
|
||||
if (wo.pager_savePages && ts.storage) {
|
||||
t = ts.storage(table, wo.pager_storageKey) || {}; // fixes #387
|
||||
p.page = isNaN(t.page) ? p.page : t.page;
|
||||
p.size = ( isNaN(t.size) ? p.size : t.size ) || 10;
|
||||
$.data(table, 'pagerLastSize', p.size);
|
||||
}
|
||||
// clear initialized flag
|
||||
p.initialized = false;
|
||||
// before initialization event
|
||||
c.$table.trigger('pagerBeforeInitialized', c);
|
||||
|
||||
tsp.enablePager(table, c, false);
|
||||
|
||||
if ( typeof(wo.pager_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.
|
||||
wo.filter_serversideFiltering = true;
|
||||
c.serverSideSorting = true;
|
||||
tsp.moveToPage(table, p);
|
||||
} else {
|
||||
p.ajax = false;
|
||||
// Regular pager; all rows stored in memory
|
||||
c.$table.trigger("appendCache", true);
|
||||
tsp.hideRowsSetup(table, c);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
initComplete: function(table, c){
|
||||
var p = c.pager;
|
||||
tsp.changeHeight(table, c);
|
||||
tsp.bindEvents(table, c);
|
||||
|
||||
// pager initialized
|
||||
p.initialized = true;
|
||||
p.isInitializing = false;
|
||||
tsp.setPageSize(table, 0, c); // page size 0 is ignored
|
||||
c.$table.trigger('pagerInitialized', c);
|
||||
|
||||
},
|
||||
|
||||
bindEvents: function(table, c){
|
||||
var ctrls, fxn,
|
||||
p = c.pager,
|
||||
wo = c.widgetOptions,
|
||||
s = wo.pager_selectors;
|
||||
|
||||
c.$table
|
||||
.unbind('filterStart filterEnd sortEnd disable enable destroy update updateRows updateAll addRows pageSize '.split(' ').join('.pager '))
|
||||
.bind('filterStart.pager', function(e, filters) {
|
||||
p.currentFilters = filters;
|
||||
p.page = 0; // fixes #456
|
||||
})
|
||||
// update pager after filter widget completes
|
||||
.bind('filterEnd.pager sortEnd.pager', function() {
|
||||
if (p.initialized) {
|
||||
tsp.moveToPage(table, p, false);
|
||||
tsp.updatePageDisplay(table, c, false);
|
||||
tsp.fixHeight(table, c);
|
||||
}
|
||||
})
|
||||
.bind('disable.pager', function(e){
|
||||
e.stopPropagation();
|
||||
tsp.showAllRows(table, c);
|
||||
})
|
||||
.on('enable.pager', function(e){
|
||||
e.stopPropagation();
|
||||
tsp.enablePager(table, c, true);
|
||||
})
|
||||
.on('destroy.pager', function(e){
|
||||
e.stopPropagation();
|
||||
tsp.destroyPager(table, c);
|
||||
})
|
||||
.on('update updateRows updateAll addRows '.split(' ').join('.pager '), function(e){
|
||||
e.stopPropagation();
|
||||
tsp.hideRows(table, c);
|
||||
// make sure widgets are applied - fixes #450
|
||||
c.$table.trigger('applyWidgets');
|
||||
})
|
||||
.on('pageSize.pager', function(e,v){
|
||||
e.stopPropagation();
|
||||
tsp.setPageSize(table, parseInt(v, 10) || 10, c);
|
||||
tsp.hideRows(table, c);
|
||||
tsp.updatePageDisplay(table, c, false);
|
||||
if (p.$size.length) { p.$size.val(p.size); } // twice?
|
||||
})
|
||||
.on('pageSet.pager', function(e,v){
|
||||
e.stopPropagation();
|
||||
p.page = (parseInt(v, 10) || 1) - 1;
|
||||
if (p.$goto.length) { p.$goto.val(c.size); } // twice?
|
||||
tsp.moveToPage(table, p);
|
||||
tsp.updatePageDisplay(table, c, false);
|
||||
});
|
||||
|
||||
// clicked controls
|
||||
ctrls = [ s.first, s.prev, s.next, s.last ];
|
||||
fxn = [ 'moveToFirstPage', 'moveToPrevPage', 'moveToNextPage', 'moveToLastPage' ];
|
||||
p.$container.find(ctrls.join(','))
|
||||
.attr("tabindex", 0)
|
||||
.unbind('click.pager')
|
||||
.bind('click.pager', function(e){
|
||||
e.stopPropagation();
|
||||
var i,
|
||||
$c = $(this),
|
||||
l = ctrls.length;
|
||||
if ( !$c.hasClass(wo.pager_css.disabled) ) {
|
||||
for (i = 0; i < l; i++) {
|
||||
if ($c.is(ctrls[i])) {
|
||||
tsp[fxn[i]](table, p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if ( p.$goto.length ) {
|
||||
p.$goto
|
||||
.unbind('change')
|
||||
.bind('change', function(){
|
||||
p.page = $(this).val() - 1;
|
||||
tsp.moveToPage(table, p);
|
||||
tsp.updatePageDisplay(table, c, false);
|
||||
});
|
||||
}
|
||||
|
||||
if ( p.$size.length ) {
|
||||
p.$size
|
||||
.unbind('change.pager')
|
||||
.bind('change.pager', function() {
|
||||
p.$size.val( $(this).val() ); // in case there are more than one pagers
|
||||
if ( !$(this).hasClass(wo.pager_css.disabled) ) {
|
||||
tsp.setPageSize(table, parseInt( $(this).val(), 10 ), c);
|
||||
tsp.changeHeight(table, c);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
// hide arrows at extremes
|
||||
pagerArrows: function(c, disable) {
|
||||
var p = c.pager,
|
||||
dis = !!disable,
|
||||
first = dis || p.page === 0,
|
||||
tp = Math.min( p.totalPages, p.filteredPages ),
|
||||
last = dis || p.page === tp - 1 || p.totalPages === 0,
|
||||
wo = c.widgetOptions,
|
||||
s = wo.pager_selectors;
|
||||
if ( wo.pager_updateArrows ) {
|
||||
p.$container.find(s.first + ',' + s.prev).toggleClass(wo.pager_css.disabled, first).attr('aria-disabled', first);
|
||||
p.$container.find(s.next + ',' + s.last).toggleClass(wo.pager_css.disabled, last).attr('aria-disabled', last);
|
||||
}
|
||||
},
|
||||
|
||||
updatePageDisplay: function(table, c, completed) {
|
||||
var i, pg, s, out,
|
||||
wo = c.widgetOptions,
|
||||
p = c.pager,
|
||||
f = c.$table.hasClass('hasFilters') && !wo.pager_ajaxUrl,
|
||||
t = (c.widgetOptions && c.widgetOptions.filter_filteredRow || 'filtered') + ',' + c.selectorRemove +
|
||||
(wo.pager_countChildRows ? '' : ',.' + c.cssChildRow),
|
||||
sz = p.size || 10; // don't allow dividing by zero
|
||||
p.$size.add(p.$goto).removeClass(wo.pager_css.disabled).removeAttr('disabled').attr('aria-disabled', 'false');
|
||||
p.totalPages = Math.ceil( p.totalRows / sz ); // needed for "pageSize" method
|
||||
p.filteredRows = (f) ? c.$tbodies.eq(0).children('tr').not('.' + t).length : p.totalRows;
|
||||
p.filteredPages = (f) ? Math.ceil( p.filteredRows / sz ) || 1 : p.totalPages;
|
||||
if ( Math.min( p.totalPages, p.filteredPages ) >= 0 ) {
|
||||
t = (p.size * p.page > p.filteredRows);
|
||||
p.startRow = (t) ? 1 : (p.filteredRows === 0 ? 0 : p.size * p.page + 1);
|
||||
p.page = (t) ? 0 : p.page;
|
||||
p.endRow = Math.min( p.filteredRows, p.totalRows, p.size * ( p.page + 1 ) );
|
||||
out = p.$container.find(wo.pager_selectors.pageDisplay);
|
||||
// form the output string (can now get a new output string from the server)
|
||||
s = ( p.ajaxData && p.ajaxData.output ? p.ajaxData.output || wo.pager_output : wo.pager_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 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 : '';
|
||||
return extra.length > 1 && data && data[extra[0]] ? data[extra[0]][extra[1]] : p[str] || (data ? data[str] : deflt) || deflt;
|
||||
});
|
||||
if (out.length) {
|
||||
out[ (out[0].tagName === 'INPUT') ? 'val' : 'html' ](s);
|
||||
if ( p.$goto.length ) {
|
||||
t = '';
|
||||
pg = Math.min( p.totalPages, p.filteredPages );
|
||||
for ( i = 1; i <= pg; i++ ) {
|
||||
t += '<option>' + i + '</option>';
|
||||
}
|
||||
p.$goto.html(t).val( p.page + 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
tsp.pagerArrows(c);
|
||||
if (p.initialized && completed !== false) {
|
||||
c.$table.trigger('pagerComplete', c);
|
||||
// save pager info to storage
|
||||
if (wo.pager_savePages && ts.storage) {
|
||||
ts.storage(table, wo.pager_storageKey, {
|
||||
page : p.page,
|
||||
size : p.size
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
fixHeight: function(table, c) {
|
||||
var d, h,
|
||||
p = c.pager,
|
||||
wo = c.widgetOptions,
|
||||
$b = c.$tbodies.eq(0);
|
||||
if (wo.pager_fixedHeight) {
|
||||
$b.find('tr.pagerSavedHeightSpacer').remove();
|
||||
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 ) {
|
||||
$b.append('<tr class="pagerSavedHeightSpacer ' + wo.pager_selectors.remove.replace(/(tr)?\./g,'') + '" style="height:' + d + 'px;"></tr>');
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
changeHeight: function(table, c) {
|
||||
var $b = c.$tbodies.eq(0);
|
||||
$b.find('tr.pagerSavedHeightSpacer').remove();
|
||||
$.data(table, 'pagerSavedHeight', $b.height());
|
||||
tsp.fixHeight(table, c);
|
||||
$.data(table, 'pagerLastSize', c.pager.size);
|
||||
},
|
||||
|
||||
hideRows: function(table, c){
|
||||
if (!c.widgetOptions.pager_ajaxUrl) {
|
||||
var i,
|
||||
p = c.pager,
|
||||
wo = c.widgetOptions,
|
||||
rows = c.$tbodies.eq(0).children(),
|
||||
l = rows.length,
|
||||
s = ( p.page * p.size ),
|
||||
e = s + p.size,
|
||||
f = wo && wo.filter_filteredRow || 'filtered',
|
||||
j = 0; // size counter
|
||||
for ( i = 0; i < l; i++ ){
|
||||
if ( !rows[i].className.match(f) ) {
|
||||
rows[i].style.display = ( j >= s && j < e ) ? '' : 'none';
|
||||
// don't count child rows
|
||||
j += rows[i].className.match(c.cssChildRow + '|' + c.selectorRemove.slice(1)) && !wo.pager_countChildRows ? 0 : 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
hideRowsSetup: function(table, c){
|
||||
var p = c.pager;
|
||||
p.size = parseInt( p.$size.val(), 10 ) || p.size;
|
||||
$.data(table, 'pagerLastSize', p.size);
|
||||
tsp.pagerArrows(c);
|
||||
if ( !c.widgetOptions.pager_removeRows ) {
|
||||
tsp.hideRows(table, c);
|
||||
c.$table.on('sortEnd.pager filterEnd.pager', function(){
|
||||
tsp.hideRows(table, c);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
renderAjax: function(data, table, c, xhr, exception){
|
||||
var p = c.pager,
|
||||
wo = c.widgetOptions;
|
||||
// process data
|
||||
if ( $.isFunction(wo.pager_ajaxProcessing) ) {
|
||||
// ajaxProcessing result: [ total, rows, headers ]
|
||||
var i, j, t, hsh, $f, $sh, th, d, l, rr_count,
|
||||
$t = c.$table,
|
||||
tds = '',
|
||||
result = wo.pager_ajaxProcessing(data, table) || [ 0, [] ],
|
||||
hl = $t.find('thead th').length;
|
||||
|
||||
// Clean up any previous error.
|
||||
ts.showError(table);
|
||||
|
||||
if ( exception ) {
|
||||
if (c.debug) {
|
||||
ts.log('Ajax Error', xhr, exception);
|
||||
}
|
||||
ts.showError(table, exception.message + ' (' + xhr.status + ')');
|
||||
c.$tbodies.eq(0).empty();
|
||||
p.totalRows = 0;
|
||||
} else {
|
||||
// process ajax object
|
||||
if (!$.isArray(result)) {
|
||||
p.ajaxData = result;
|
||||
p.totalRows = 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;
|
||||
d = p.totalRows === 0 ? [""] : result[t ? 0 : 1] || []; // row data
|
||||
th = result[2]; // headers
|
||||
}
|
||||
l = d.length;
|
||||
if (d instanceof jQuery) {
|
||||
// append jQuery object
|
||||
c.$tbodies.eq(0).empty().append(d);
|
||||
} else if (l) {
|
||||
// build table from array
|
||||
for ( i = 0; i < l; i++ ) {
|
||||
tds += '<tr>';
|
||||
for ( j = 0; j < d[i].length; j++ ) {
|
||||
// build tbody cells; watch for data containing HTML markup - see #434
|
||||
tds += /^\s*<td/.test(d[i][j]) ? $.trim(d[i][j]) : '<td>' + d[i][j] + '</td>';
|
||||
}
|
||||
tds += '</tr>';
|
||||
}
|
||||
// add rows to first tbody
|
||||
if (wo.pager_processAjaxOnInit) {
|
||||
c.$tbodies.eq(0).html( tds );
|
||||
} else {
|
||||
wo.pager_processAjaxOnInit = true;
|
||||
}
|
||||
}
|
||||
// only add new header text if the length matches
|
||||
if ( th && th.length === hl ) {
|
||||
hsh = $t.hasClass('hasStickyHeaders');
|
||||
$sh = hsh ? wo.$sticky.children('thead:first').children().children() : '';
|
||||
$f = $t.find('tfoot tr:first').children();
|
||||
// don't change td headers (may contain pager)
|
||||
c.$headers.filter('th').each(function(j){
|
||||
var $t = $(this), icn;
|
||||
// add new test within the first span it finds, or just in the header
|
||||
if ( $t.find('.' + ts.css.icon).length ) {
|
||||
icn = $t.find('.' + ts.css.icon).clone(true);
|
||||
$t.find('.tablesorter-header-inner').html( th[j] ).append(icn);
|
||||
if ( hsh && $sh.length ) {
|
||||
icn = $sh.eq(j).find('.' + ts.css.icon).clone(true);
|
||||
$sh.eq(j).find('.tablesorter-header-inner').html( th[j] ).append(icn);
|
||||
}
|
||||
} else {
|
||||
$t.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
|
||||
}
|
||||
// make sure last pager settings are saved, prevents multiple server side calls with
|
||||
// the same parameters
|
||||
p.totalPages = Math.ceil( p.totalRows / ( p.size || 10 ) );
|
||||
p.last.totalRows = p.totalRows;
|
||||
p.last.currentFilters = p.currentFilters;
|
||||
p.last.sortList = (c.sortList || []).join(',');
|
||||
tsp.updatePageDisplay(table, c);
|
||||
tsp.fixHeight(table, c);
|
||||
$t.trigger('updateCache', [function(){
|
||||
if (p.initialized) {
|
||||
// apply widgets after table has rendered
|
||||
$t.trigger('applyWidgets');
|
||||
$t.trigger('pagerChange', p);
|
||||
}
|
||||
}]);
|
||||
}
|
||||
if (!p.initialized) {
|
||||
c.$table.trigger('applyWidgets');
|
||||
}
|
||||
},
|
||||
|
||||
getAjax: function(table, c){
|
||||
var counter,
|
||||
url = tsp.getAjaxUrl(table, c),
|
||||
$doc = $(document),
|
||||
wo = c.widgetOptions,
|
||||
p = c.pager;
|
||||
if ( url !== '' ) {
|
||||
if (c.showProcessing) {
|
||||
ts.isProcessing(table, true); // show loading icon
|
||||
}
|
||||
$doc.on('ajaxError.pager', function(e, xhr, settings, exception) {
|
||||
tsp.renderAjax(null, table, c, xhr, exception);
|
||||
$doc.unbind('ajaxError.pager');
|
||||
});
|
||||
counter = ++p.ajaxCounter;
|
||||
wo.pager_ajaxObject.url = url; // from the ajaxUrl option and modified by customAjaxUrl
|
||||
wo.pager_ajaxObject.success = function(data) {
|
||||
// Refuse to process old ajax commands that were overwritten by new ones - see #443
|
||||
if (counter < p.ajaxCounter){
|
||||
return;
|
||||
}
|
||||
tsp.renderAjax(data, table, c);
|
||||
$doc.unbind('ajaxError.pager');
|
||||
if (typeof p.oldAjaxSuccess === 'function') {
|
||||
p.oldAjaxSuccess(data);
|
||||
}
|
||||
};
|
||||
if (c.debug) {
|
||||
ts.log('ajax initialized', wo.pager_ajaxObject);
|
||||
}
|
||||
$.ajax(wo.pager_ajaxObject);
|
||||
}
|
||||
},
|
||||
|
||||
getAjaxUrl: function(table, c) {
|
||||
var p = c.pager,
|
||||
wo = c.widgetOptions,
|
||||
url = (wo.pager_ajaxUrl) ? wo.pager_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); })
|
||||
.replace(/\{size\}/g, p.size) : '',
|
||||
sl = c.sortList,
|
||||
fl = 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];
|
||||
$.each(sl, function(i,v){
|
||||
arry.push(sortCol + '[' + v[0] + ']=' + v[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];
|
||||
$.each(fl, function(i,v){
|
||||
if (v) {
|
||||
arry.push(filterCol + '[' + i + ']=' + encodeURIComponent(v));
|
||||
}
|
||||
});
|
||||
// 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 = fl;
|
||||
}
|
||||
if ( $.isFunction(wo.pager_customAjaxUrl) ) {
|
||||
url = wo.pager_customAjaxUrl(table, url);
|
||||
}
|
||||
if (c.debug) {
|
||||
ts.log('Pager ajax url: ' + url);
|
||||
}
|
||||
return url;
|
||||
},
|
||||
|
||||
renderTable: function(table, rows) {
|
||||
var i, $tb,
|
||||
c = table.config,
|
||||
p = c.pager,
|
||||
wo = c.widgetOptions,
|
||||
l = rows && rows.length || 0, // rows may be undefined
|
||||
s = ( p.page * p.size ),
|
||||
e = ( s + p.size );
|
||||
if ( l < 1 ) { return; } // empty table, abort!
|
||||
if ( p.page >= p.totalPages ) {
|
||||
// lets not render the table more than once
|
||||
return tsp.moveToLastPage(table, p);
|
||||
}
|
||||
p.isDisabled = false; // needed because sorting will change the page and re-enable the pager
|
||||
if (p.initialized) { c.$table.trigger('pagerChange', c); }
|
||||
|
||||
if ( !wo.pager_removeRows ) {
|
||||
tsp.hideRows(table, c);
|
||||
} else {
|
||||
if ( e > rows.length ) {
|
||||
e = rows.length;
|
||||
}
|
||||
ts.clearTableBody(table);
|
||||
$tb = ts.processTbody(table, c.$tbodies.eq(0), true);
|
||||
for ( i = s; i < e; i++ ) {
|
||||
$tb.append(rows[i]);
|
||||
}
|
||||
ts.processTbody(table, $tb, false);
|
||||
}
|
||||
|
||||
tsp.updatePageDisplay(table, c);
|
||||
if ( !p.isDisabled ) { tsp.fixHeight(table, c); }
|
||||
|
||||
wo.pager_startPage = p.page;
|
||||
wo.pager_size = p.size;
|
||||
c.$table.trigger('applyWidgets');
|
||||
if (table.isUpdating) {
|
||||
c.$table.trigger('updateComplete');
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
showAllRows: function(table, c){
|
||||
var p = c.pager,
|
||||
wo = c.widgetOptions;
|
||||
if ( p.ajax ) {
|
||||
tsp.pagerArrows(c, true);
|
||||
} else {
|
||||
p.isDisabled = true;
|
||||
$.data(table, 'pagerLastPage', p.page);
|
||||
$.data(table, 'pagerLastSize', p.size);
|
||||
p.page = 0;
|
||||
p.size = p.totalRows;
|
||||
p.totalPages = 1;
|
||||
c.$table
|
||||
.addClass('pagerDisabled')
|
||||
.removeAttr('aria-describedby')
|
||||
.find('tr.pagerSavedHeightSpacer').remove();
|
||||
tsp.renderTable(table, c.rowsCopy);
|
||||
if (c.debug) {
|
||||
ts.log('pager disabled');
|
||||
}
|
||||
}
|
||||
// disable size selector
|
||||
p.$size.add(p.$goto).each(function(){
|
||||
$(this).attr('aria-disabled', 'true').addClass(wo.pager_css.disabled)[0].disabled = true;
|
||||
});
|
||||
},
|
||||
|
||||
moveToPage: function(table, p, pageMoved) {
|
||||
if ( p.isDisabled ) { return; }
|
||||
var c = table.config,
|
||||
l = p.last,
|
||||
pg = Math.min( p.totalPages, p.filteredPages );
|
||||
if ( p.page < 0 ) { p.page = 0; }
|
||||
if ( p.page > ( pg - 1 ) && pg !== 0 ) { p.page = pg - 1; }
|
||||
// fixes issue where one current filter is [] and the other is ['','',''],
|
||||
// making the next if comparison think the filters as different. 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(',') &&
|
||||
l.sortList === (c.sortList || []).join(',') ) {
|
||||
return;
|
||||
}
|
||||
if (c.debug) {
|
||||
ts.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 || []
|
||||
};
|
||||
if (p.ajax) {
|
||||
tsp.getAjax(table, c);
|
||||
} else if (!p.ajax) {
|
||||
tsp.renderTable(table, c.rowsCopy);
|
||||
}
|
||||
$.data(table, 'pagerLastPage', p.page);
|
||||
if (p.initialized && pageMoved !== false) {
|
||||
c.$table.trigger('pageMoved', c);
|
||||
if (!p.ajax && table.isUpdating) {
|
||||
c.$table.trigger('updateComplete');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
setPageSize: function(table, size, c) {
|
||||
var p = c.pager;
|
||||
p.size = size || p.size || 10;
|
||||
p.$size.val(p.size);
|
||||
$.data(table, 'pagerLastPage', p.page);
|
||||
$.data(table, 'pagerLastSize', p.size);
|
||||
p.totalPages = Math.ceil( p.totalRows / p.size );
|
||||
tsp.moveToPage(table, p);
|
||||
},
|
||||
|
||||
moveToFirstPage: function(table, p) {
|
||||
p.page = 0;
|
||||
tsp.moveToPage(table, p);
|
||||
},
|
||||
|
||||
moveToLastPage: function(table, p) {
|
||||
p.page = ( Math.min( p.totalPages, p.filteredPages ) - 1 );
|
||||
tsp.moveToPage(table, p);
|
||||
},
|
||||
|
||||
moveToNextPage: function(table, p) {
|
||||
p.page++;
|
||||
if ( p.page >= ( Math.min( p.totalPages, p.filteredPages ) - 1 ) ) {
|
||||
p.page = ( Math.min( p.totalPages, p.filteredPages ) - 1 );
|
||||
}
|
||||
tsp.moveToPage(table, p);
|
||||
},
|
||||
|
||||
moveToPrevPage: function(table, p) {
|
||||
p.page--;
|
||||
if ( p.page <= 0 ) {
|
||||
p.page = 0;
|
||||
}
|
||||
tsp.moveToPage(table, p);
|
||||
},
|
||||
|
||||
destroyPager: function(table, c){
|
||||
var p = c.pager;
|
||||
tsp.showAllRows(table, c);
|
||||
p.$container.hide(); // hide pager
|
||||
c.appender = null; // remove pager appender function
|
||||
p.initialized = false;
|
||||
c.$table.unbind('destroy.pager sortEnd.pager filterEnd.pager enable.pager disable.pager');
|
||||
if (ts.storage) {
|
||||
ts.storage(table, c.widgetOptions.pager_storageKey, '');
|
||||
}
|
||||
},
|
||||
|
||||
enablePager: function(table, c, triggered){
|
||||
var info, p = c.pager;
|
||||
p.isDisabled = false;
|
||||
p.page = $.data(table, 'pagerLastPage') || p.page || 0;
|
||||
p.size = $.data(table, 'pagerLastSize') || parseInt(p.$size.find('option[selected]').val(), 10) || p.size || 10;
|
||||
p.$size.val(p.size); // set page size
|
||||
p.totalPages = Math.ceil( Math.min( p.totalRows, p.filteredRows ) / p.size );
|
||||
c.$table.removeClass('pagerDisabled');
|
||||
// if table id exists, include page display with aria info
|
||||
if ( table.id ) {
|
||||
info = table.id + '_pager_info';
|
||||
p.$container.find(c.widgetOptions.pager_selectors.pageDisplay).attr('id', info);
|
||||
c.$table.attr('aria-describedby', info);
|
||||
}
|
||||
if ( triggered ) {
|
||||
c.$table.trigger('updateRows');
|
||||
tsp.setPageSize(table, p.size, c);
|
||||
tsp.hideRowsSetup(table, c);
|
||||
tsp.fixHeight(table, c);
|
||||
if (c.debug) {
|
||||
ts.log('pager enabled');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
appender: function(table, rows) {
|
||||
var c = table.config,
|
||||
wo = c.widgetOptions,
|
||||
p = c.pager;
|
||||
if ( !p.ajax ) {
|
||||
c.rowsCopy = rows;
|
||||
p.totalRows = c.widgetOptions.pager_countChildRows ? c.$tbodies.eq(0).children().length : rows.length;
|
||||
p.size = $.data(table, 'pagerLastSize') || p.size || wo.pager_size || 10;
|
||||
p.totalPages = Math.ceil( p.totalRows / p.size );
|
||||
tsp.moveToPage(table, p, true);
|
||||
// update display here in case all rows are removed
|
||||
tsp.updatePageDisplay(table, c, false);
|
||||
} else {
|
||||
tsp.moveToPage(table, p, true);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// see #486
|
||||
ts.showError = function(table, message){
|
||||
$(table).each(function(){
|
||||
var $row,
|
||||
c = this.config,
|
||||
errorRow = c.pager && c.pager.cssErrorRow || c.widgetOptions.pager_css && c.widgetOptions.pager_css.errorRow || 'tablesorter-errorRow';
|
||||
if (c) {
|
||||
if (typeof message === 'undefined') {
|
||||
c.$table.find('thead').find(c.selectorRemove).remove();
|
||||
} else {
|
||||
$row = ( /tr\>/.test(message) ? $(message) : $('<tr><td colspan="' + c.columns + '">' + message + '</td></tr>') )
|
||||
.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.replace(/^[.#]/, '') )
|
||||
.attr({
|
||||
role : 'alert',
|
||||
'aria-live' : 'assertive'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
})(jQuery);
|
50
assets/vendor/tablesorter/js/widgets/widget-repeatheaders.js
vendored
Normal file
50
assets/vendor/tablesorter/js/widgets/widget-repeatheaders.js
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
/*! tablesorter repeatHeaders widget - updated 4/12/2013
|
||||
* Requires tablesorter v2.8+ and jQuery 1.7+
|
||||
* Original by Christian Bach from the example-widgets.html demo
|
||||
*/
|
||||
/*global jQuery: false */
|
||||
;(function($){
|
||||
"use strict";
|
||||
|
||||
$.tablesorter.addWidget({
|
||||
id: "repeatHeaders",
|
||||
priority: 10,
|
||||
options: {
|
||||
rowsToSkip : 4
|
||||
},
|
||||
// format is called on init and when a sorting has finished
|
||||
format: function(table, c, wo) {
|
||||
var h = '', i, $tr, l, skip;
|
||||
// cache and collect all TH headers
|
||||
if (!wo.repeatHeaders) {
|
||||
h = '<tr class="repeated-header remove-me">';
|
||||
$.each(c.headerContent, function(i,t) {
|
||||
h += '<th>' + t + '</th>';
|
||||
});
|
||||
// "remove-me" class was added in case the table needs to be updated, the "remove-me" rows will be
|
||||
// removed prior to the update to prevent including the rows in the update - see "selectorRemove" option
|
||||
wo.repeatHeaders = h + '</tr>';
|
||||
}
|
||||
|
||||
// number of rows to skip
|
||||
skip = wo && wo.rowsToSkip || 4;
|
||||
|
||||
// remove appended headers by classname
|
||||
c.$table.find("tr.repeated-header").remove();
|
||||
$tr = c.$tbodies.find('tr');
|
||||
l = $tr.length;
|
||||
// loop all tr elements and insert a copy of the "headers"
|
||||
for (i = skip; i < l; i += skip) {
|
||||
// insert a copy of the table head every X rows
|
||||
$tr.eq(i).before(wo.repeatHeaders);
|
||||
}
|
||||
},
|
||||
// this remove function is called when using the refreshWidgets method or when destroying the tablesorter plugin
|
||||
// this function only applies to tablesorter v2.4+
|
||||
remove: function(table, c){
|
||||
c.$table.find("tr.repeated-header").remove();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
})(jQuery);
|
241
assets/vendor/tablesorter/js/widgets/widget-scroller.js
vendored
Normal file
241
assets/vendor/tablesorter/js/widgets/widget-scroller.js
vendored
Normal file
@@ -0,0 +1,241 @@
|
||||
/*!
|
||||
Copyright (C) 2011 T. Connell & Associates, Inc.
|
||||
|
||||
Dual-licensed under the MIT and GPL licenses
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Resizable scroller widget for the jQuery tablesorter plugin
|
||||
|
||||
Version 2.0 - modified by Rob Garrison (4/12/2013)
|
||||
Requires jQuery, v1.2.3 or higher
|
||||
Requires the tablesorter plugin, v2.0 or higher, available at http://mottie.github.com/tablesorter/docs/
|
||||
|
||||
Usage:
|
||||
|
||||
$(function() {
|
||||
|
||||
$('table.tablesorter').tablesorter({
|
||||
widgets: ['zebra', 'scroller'],
|
||||
widgetOptions : {
|
||||
scroller_height : 300, // height of scroll window
|
||||
scroller_barWidth : 17, // scroll bar width
|
||||
scroller_jumpToHeader : true, // header snap to browser top when scrolling the tbody
|
||||
scroller_idPrefix : 's_' // cloned thead id prefix (random number added to end)
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Website: www.tconnell.com
|
||||
*/
|
||||
/*jshint browser:true, jquery:true, unused:false */
|
||||
;(function($){
|
||||
"use strict";
|
||||
|
||||
$.fn.hasScrollBar = function(){
|
||||
return this.get(0).scrollHeight > this.height();
|
||||
};
|
||||
var ts = $.tablesorter;
|
||||
|
||||
ts.window_resize = function(){
|
||||
if (this.resize_timer) {
|
||||
clearTimeout(this.resize_timer);
|
||||
}
|
||||
this.resize_timer = setTimeout(function(){
|
||||
$(this).trigger('resizeEnd');
|
||||
}, 250);
|
||||
};
|
||||
|
||||
// Add extra scroller css
|
||||
$(function(){
|
||||
var s = '<style>' +
|
||||
'.tablesorter-scroller-header table.tablesorter { margin-bottom: 0; }' +
|
||||
'.tablesorter-scroller-table table.tablesorter { margin-top: 0; } ' +
|
||||
'.tablesorter-scroller-table .tablesorter-filter-row, .tablesorter-scroller-table tfoot { display: none; }' +
|
||||
'.tablesorter-scroller-table table.tablesorter thead tr.tablesorter-headerRow * {' +
|
||||
'line-height:0;height:0;border:none;background-image:none;padding-top:0;padding-bottom:0;margin-top:0;margin-bottom:0;overflow:hidden;' +
|
||||
'}</style>';
|
||||
$(s).appendTo('body');
|
||||
});
|
||||
|
||||
ts.addWidget({
|
||||
id: 'scroller',
|
||||
priority: 60, // run after the filter widget
|
||||
options: {
|
||||
scroller_height : 300,
|
||||
scroller_barWidth : 17,
|
||||
scroller_jumpToHeader: true,
|
||||
scroller_idPrefix : 's_'
|
||||
},
|
||||
init: function(table, thisWidget, c, wo){
|
||||
var $win = $(window);
|
||||
//Setup window.resizeEnd event
|
||||
$win
|
||||
.bind('resize', ts.window_resize)
|
||||
.bind('resizeEnd', function(e) {
|
||||
// init is run before format, so scroller_resizeWidth
|
||||
// won't be defined within the "c" or "wo" parameters
|
||||
if (typeof table.config.widgetOptions.scroller_resizeWidth === 'function') {
|
||||
//IE calls resize when you modify content, so we have to unbind the resize event
|
||||
//so we don't end up with an infinite loop. we can rebind after we're done.
|
||||
$win.unbind('resize', ts.window_resize);
|
||||
table.config.widgetOptions.scroller_resizeWidth();
|
||||
$win.bind('resize', ts.window_resize);
|
||||
}
|
||||
});
|
||||
},
|
||||
format: function(table, c, wo) {
|
||||
var h, $hdr, id, t, resize, $cells,
|
||||
$win = $(window),
|
||||
$tbl = c.$table,
|
||||
flag = false,
|
||||
filterInputs = 'input, select';
|
||||
|
||||
if (!c.isScrolling) {
|
||||
h = wo.scroller_height || 300;
|
||||
t = $tbl.find('tbody').height();
|
||||
if (t !== 0 && h > t) { h = t + 10; } // Table is less than h px
|
||||
id = wo.scroller_id = wo.scroller_idPrefix + Math.floor(Math.random() * 101);
|
||||
|
||||
$hdr = $('<table class="' + $tbl.attr('class') + '" cellpadding=0 cellspacing=0><thead>' + $tbl.find('thead:first').html() + '</thead></table>');
|
||||
$tbl
|
||||
.wrap('<div id="' + id + '" class="tablesorter-scroller" style="text-align:left;" />')
|
||||
.before($hdr)
|
||||
.find('.tablesorter-filter-row').addClass('hideme');
|
||||
|
||||
$cells = $hdr
|
||||
.wrap('<div class="tablesorter-scroller-header" style="width:' + $tbl.width() + ';" />')
|
||||
.find('.' + ts.css.header)
|
||||
.bind('mousedown', function(){
|
||||
this.onselectstart = function(){ return false; };
|
||||
return false;
|
||||
});
|
||||
|
||||
$tbl
|
||||
.wrap('<div class="tablesorter-scroller-table" style="height:' + h + 'px;width:' + $tbl.width() + ';overflow-y:scroll;" />')
|
||||
.unbind('sortEnd.tsScroller')
|
||||
.bind('sortEnd.tsScroller', function(){
|
||||
c.$headers.each(function(i){
|
||||
var t = $cells.eq(i);
|
||||
t
|
||||
.attr('class', $(this).attr('class'))
|
||||
// remove processing icon
|
||||
.removeClass(ts.css.processing + ' ' + c.cssProcessing);
|
||||
if (ts.css.icon){
|
||||
t
|
||||
.find('.' + ts.css.icon)
|
||||
.attr('class', $(this).find('.' + ts.css.icon).attr('class'));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// make scroller header sortable
|
||||
c.$headers.find(c.selectorSort).add( c.$headers.filter(c.selectorSort) ).each(function(i){
|
||||
var t = $(this);
|
||||
$cells.eq(i)
|
||||
// clicking on new header will trigger a sort
|
||||
.bind('mouseup', function(e){
|
||||
t.trigger(e, true); // external mouseup flag (click timer is ignored)
|
||||
})
|
||||
// prevent header text selection
|
||||
.bind('mousedown', function(){
|
||||
this.onselectstart = function(){ return false; };
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
// look for filter widget
|
||||
$tbl.bind('filterEnd', function(){
|
||||
if (flag) { return; }
|
||||
$cells.each(function(i){
|
||||
$(this).find(filterInputs).val( c.$filters.find(filterInputs).eq(i).val() );
|
||||
});
|
||||
});
|
||||
$hdr.find(filterInputs).bind('keyup search', function(e){
|
||||
// ignore arrow and meta keys; allow backspace
|
||||
if ((e.which < 32 && e.which !== 8) || (e.which >= 37 && e.which <=40)) { return; }
|
||||
flag = true;
|
||||
var $f = $(this), col = $f.attr('data-column');
|
||||
c.$filters.find(filterInputs).eq(col)
|
||||
.val( $f.val() )
|
||||
.trigger('search');
|
||||
setTimeout(function(){
|
||||
flag = false;
|
||||
}, wo.filter_searchDelay);
|
||||
});
|
||||
|
||||
resize = function(){
|
||||
var d,
|
||||
//Hide other scrollers so we can resize
|
||||
$div = $('div.scroller[id != "' + id + '"]').hide();
|
||||
|
||||
$tbl.find('thead').show();
|
||||
|
||||
//Reset sizes so parent can resize.
|
||||
$hdr
|
||||
.width(0)
|
||||
.parent().width(0)
|
||||
.find('th,td').width(0);
|
||||
|
||||
$tbl
|
||||
.width(0)
|
||||
.find('thead').find('th,td').width(0);
|
||||
d = $tbl.parent();
|
||||
d.width(0);
|
||||
|
||||
d.parent().trigger('resize');
|
||||
// Shrink a bit to accommodate scrollbar
|
||||
d.width( d.parent().innerWidth() - ( d.parent().hasScrollBar() ? wo.scroller_barWidth : 0 ) );
|
||||
|
||||
$tbl.width( d.innerWidth() - ( d.hasScrollBar() ? wo.scroller_barWidth : 0 ) );
|
||||
$tbl.find('thead').find('th,td').filter(':visible').each(function(i, c){
|
||||
var $th = $(c),
|
||||
//Wrap in browser detect??
|
||||
w = parseInt( $th.css('min-width').replace('auto', '0').replace(/(px|em)/, ''), 10 );
|
||||
if ( $th.width() < w ) {
|
||||
$th.width(w);
|
||||
} else {
|
||||
w = $th.width();
|
||||
}
|
||||
$hdr.find('th,td').eq(i).width(w);
|
||||
});
|
||||
|
||||
$hdr.width($tbl.innerWidth());
|
||||
$div.show();
|
||||
};
|
||||
|
||||
//Expose to external calls
|
||||
wo.scroller_resizeWidth = resize;
|
||||
|
||||
resize();
|
||||
|
||||
$tbl.find('thead').css('visibility', 'hidden');
|
||||
c.isScrolling = true;
|
||||
|
||||
t = $tbl.parent().parent().height();
|
||||
// The header will always jump into view if scrolling the table body
|
||||
$tbl.parent().bind('scroll', function(){
|
||||
if (wo.scroller_jumpToHeader) {
|
||||
var pos = $win.scrollTop() - $hdr.offset().top;
|
||||
if ($(this).scrollTop() !== 0 && pos < t && pos > 0) {
|
||||
$win.scrollTop( $hdr.offset().top );
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
//Sorting, so scroll to top
|
||||
$tbl.parent().animate({ scrollTop: 0 }, 'fast');
|
||||
|
||||
},
|
||||
remove : function(table, c, wo){
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
})(jQuery);
|
Reference in New Issue
Block a user