mirror of
https://github.com/wahyd4/cdnjs.git
synced 2026-08-21 02:36:13 +10:00
Updated jquery.tablesorter to version 2.10.8
This commit is contained in:
@@ -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);
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -0,0 +1,826 @@
|
||||
/*! Filter widget formatter functions - updated 6/4/2013
|
||||
* requires: tableSorter 2.7.7+ and jQuery 1.4.3+
|
||||
*
|
||||
* uiSpinner (jQuery UI spinner)
|
||||
* uiSlider (jQuery UI slider)
|
||||
* uiRange (jQuery UI range slider)
|
||||
* uiDateCompare (jQuery UI datepicker; 1 input)
|
||||
* uiDatepicker (jQuery UI datepicker; 2 inputs, filter range)
|
||||
* html5Number (spinner)
|
||||
* html5Range (slider)
|
||||
* html5Color (color)
|
||||
*/
|
||||
/*jshint browser:true, jquery:true, unused:false */
|
||||
/*global jQuery: false */
|
||||
;(function($){
|
||||
"use strict";
|
||||
$.tablesorter = $.tablesorter || {};
|
||||
|
||||
$.tablesorter.filterFormatter = {
|
||||
|
||||
/**********************\
|
||||
jQuery UI Spinner
|
||||
\**********************/
|
||||
uiSpinner: function($cell, indx, spinnerDef) {
|
||||
var o = $.extend({
|
||||
min : 0,
|
||||
max : 100,
|
||||
step : 1,
|
||||
value : 1,
|
||||
delayed : true,
|
||||
addToggle : true,
|
||||
disabled : false,
|
||||
exactMatch : true,
|
||||
compare : ''
|
||||
}, spinnerDef ),
|
||||
// Add a hidden input to hold the range values
|
||||
$input = $('<input class="filter" type="hidden">')
|
||||
.appendTo($cell)
|
||||
// hidden filter update (.tsfilter) namespace trigger by filter widget
|
||||
.bind('change.tsfilter', function(){
|
||||
updateSpinner({ value: this.value, delayed: false });
|
||||
}),
|
||||
$shcell = [],
|
||||
c = $cell.closest('table')[0].config,
|
||||
|
||||
// this function updates the hidden input and adds the current values to the header cell text
|
||||
updateSpinner = function(ui) {
|
||||
var chkd = true, state,
|
||||
// ui is not undefined on create
|
||||
v = ui && ui.value && $.tablesorter.formatFloat((ui.value + '').replace(/[><=]/g,'')) || $cell.find('.spinner').val() || o.value;
|
||||
if (o.addToggle) {
|
||||
chkd = $cell.find('.toggle').is(':checked');
|
||||
}
|
||||
state = o.disabled || !chkd ? 'disable' : 'enable';
|
||||
$cell.find('.filter')
|
||||
// add equal to the beginning, so we filter exact numbers
|
||||
.val( chkd ? (o.compare ? o.compare : o.exactMatch ? '=' : '') + v : '' )
|
||||
.trigger('search', ui && typeof ui.delayed === 'boolean' ? ui.delayed : o.delayed).end()
|
||||
.find('.spinner').spinner(state).val(v);
|
||||
// update sticky header cell
|
||||
if ($shcell.length) {
|
||||
$shcell.find('.spinner').spinner(state).val(v);
|
||||
if (o.addToggle) {
|
||||
$shcell.find('.toggle')[0].checked = chkd;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// add callbacks; preserve added callbacks
|
||||
o.oldcreate = o.create;
|
||||
o.oldspin = o.spin;
|
||||
o.create = function(event, ui) {
|
||||
updateSpinner(); // ui is an empty object on create
|
||||
if (typeof o.oldcreate === 'function') { o.oldcreate(event, ui); }
|
||||
};
|
||||
o.spin = function(event, ui) {
|
||||
updateSpinner(ui);
|
||||
if (typeof o.oldspin === 'function') { o.oldspin(event, ui); }
|
||||
};
|
||||
if (o.addToggle) {
|
||||
$('<div class="button"><input id="uispinnerbutton' + indx + '" type="checkbox" class="toggle" /><label for="uispinnerbutton' + indx + '"></label></div>')
|
||||
.appendTo($cell)
|
||||
.find('.toggle')
|
||||
.bind('change', function(){
|
||||
updateSpinner();
|
||||
});
|
||||
}
|
||||
// make sure we use parsed data
|
||||
$cell.closest('thead').find('th[data-column=' + indx + ']').addClass('filter-parsed');
|
||||
// add a jQuery UI spinner!
|
||||
$('<input class="spinner spinner' + indx + '" />')
|
||||
.val(o.value)
|
||||
.appendTo($cell)
|
||||
.spinner(o)
|
||||
.bind('change keyup', function(e){
|
||||
updateSpinner();
|
||||
});
|
||||
|
||||
// has sticky headers?
|
||||
c.$table.bind('stickyHeadersInit', function(){
|
||||
$shcell = c.widgetOptions.$sticky.find('.tablesorter-filter-row').children().eq(indx).empty();
|
||||
if (o.addToggle) {
|
||||
$('<div class="button"><input id="stickyuispinnerbutton' + indx + '" type="checkbox" class="toggle" /><label for="stickyuispinnerbutton' + indx + '"></label></div>')
|
||||
.appendTo($shcell)
|
||||
.find('.toggle')
|
||||
.bind('change', function(){
|
||||
$cell.find('.toggle')[0].checked = this.checked;
|
||||
updateSpinner();
|
||||
});
|
||||
}
|
||||
// add a jQuery UI spinner!
|
||||
$('<input class="spinner spinner' + indx + '" />')
|
||||
.val(o.value)
|
||||
.appendTo($shcell)
|
||||
.spinner(o)
|
||||
.bind('change keyup', function(e){
|
||||
$cell.find('.spinner').val( this.value );
|
||||
updateSpinner();
|
||||
});
|
||||
});
|
||||
|
||||
// on reset
|
||||
c.$table.bind('filterReset', function(){
|
||||
// turn off the toggle checkbox
|
||||
if (o.addToggle) {
|
||||
$cell.find('.toggle')[0].checked = false;
|
||||
}
|
||||
updateSpinner();
|
||||
});
|
||||
|
||||
updateSpinner();
|
||||
return $input;
|
||||
},
|
||||
|
||||
/**********************\
|
||||
jQuery UI Slider
|
||||
\**********************/
|
||||
uiSlider: function($cell, indx, sliderDef) {
|
||||
var o = $.extend({
|
||||
value : 0,
|
||||
min : 0,
|
||||
max : 100,
|
||||
step : 1,
|
||||
range : "min",
|
||||
delayed : true,
|
||||
valueToHeader : false,
|
||||
exactMatch : true,
|
||||
compare : '',
|
||||
allText : 'all'
|
||||
}, sliderDef ),
|
||||
// Add a hidden input to hold the range values
|
||||
$input = $('<input class="filter" type="hidden">')
|
||||
.appendTo($cell)
|
||||
// hidden filter update (.tsfilter) namespace trigger by filter widget
|
||||
.bind('change.tsfilter', function(){
|
||||
updateSlider({ value: this.value });
|
||||
}),
|
||||
$shcell = [],
|
||||
c = $cell.closest('table')[0].config,
|
||||
|
||||
// this function updates the hidden input and adds the current values to the header cell text
|
||||
updateSlider = function(ui) {
|
||||
// ui is not undefined on create
|
||||
var v = typeof ui !== "undefined" ? $.tablesorter.formatFloat((ui.value + '').replace(/[><=]/g,'')) || o.min : o.value,
|
||||
val = o.compare ? v : v === o.min ? o.allText : v,
|
||||
result = o.compare + val;
|
||||
if (o.valueToHeader) {
|
||||
// add range indication to the header cell above!
|
||||
$cell.closest('thead').find('th[data-column=' + indx + ']').find('.curvalue').html(' (' + result + ')');
|
||||
} else {
|
||||
// add values to the handle data-value attribute so the css tooltip will work properly
|
||||
$cell.find('.ui-slider-handle').addClass('value-popup').attr('data-value', result);
|
||||
}
|
||||
// update the hidden input;
|
||||
// ****** ADD AN EQUAL SIGN TO THE BEGINNING! <- this makes the slide exactly match the number ******
|
||||
// when the value is at the minimum, clear the hidden input so all rows will be seen
|
||||
$cell.find('.filter')
|
||||
.val( ( o.compare ? o.compare + v : v === o.min ? '' : (o.exactMatch ? '=' : '') + v ) )
|
||||
.trigger('search', ui && typeof ui.delayed === 'boolean' ? ui.delayed : o.delayed).end()
|
||||
.find('.slider').slider('value', v);
|
||||
|
||||
// update sticky header cell
|
||||
if ($shcell.length) {
|
||||
$shcell.find('.slider').slider('value', v);
|
||||
if (o.valueToHeader) {
|
||||
$shcell.closest('thead').find('th[data-column=' + indx + ']').find('.curvalue').html(' (' + result + ')');
|
||||
} else {
|
||||
$shcell.find('.ui-slider-handle').addClass('value-popup').attr('data-value', result);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
$cell.closest('thead').find('th[data-column=' + indx + ']').addClass('filter-parsed');
|
||||
|
||||
// add span to header for value - only works if the line in the updateSlider() function is also un-commented out
|
||||
if (o.valueToHeader) {
|
||||
$cell.closest('thead').find('th[data-column=' + indx + ']').find('.tablesorter-header-inner').append('<span class="curvalue" />');
|
||||
}
|
||||
|
||||
// add callbacks; preserve added callbacks
|
||||
o.oldcreate = o.create;
|
||||
o.oldslide = o.slide;
|
||||
o.create = function(event, ui) {
|
||||
updateSlider(); // ui is an empty object on create
|
||||
if (typeof o.oldcreate === 'function') { o.oldcreate(event, ui); }
|
||||
};
|
||||
o.slide = function(event, ui) {
|
||||
updateSlider(ui);
|
||||
if (typeof o.oldslide === 'function') { o.oldslide(event, ui); }
|
||||
};
|
||||
// add a jQuery UI slider!
|
||||
$('<div class="slider slider' + indx + '"/>')
|
||||
.appendTo($cell)
|
||||
.slider(o);
|
||||
|
||||
// on reset
|
||||
c.$table.bind('filterReset', function(){
|
||||
$cell.find('.slider').slider('value', o.value);
|
||||
updateSlider();
|
||||
});
|
||||
|
||||
// has sticky headers?
|
||||
c.$table.bind('stickyHeadersInit', function(){
|
||||
$shcell = c.widgetOptions.$sticky.find('.tablesorter-filter-row').children().eq(indx).empty();
|
||||
|
||||
// add a jQuery UI slider!
|
||||
$('<div class="slider slider' + indx + '"/>')
|
||||
.val(o.value)
|
||||
.appendTo($shcell)
|
||||
.slider(o)
|
||||
.bind('change keyup', function(e){
|
||||
$cell.find('.slider').val( this.value );
|
||||
updateSlider();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
return $input;
|
||||
},
|
||||
|
||||
/*************************\
|
||||
jQuery UI Range Slider (2 handles)
|
||||
\*************************/
|
||||
uiRange: function($cell, indx, rangeDef) {
|
||||
var o = $.extend({
|
||||
values : [0, 100],
|
||||
min : 0,
|
||||
max : 100,
|
||||
range : true,
|
||||
delayed : true,
|
||||
valueToHeader : false
|
||||
}, rangeDef ),
|
||||
// Add a hidden input to hold the range values
|
||||
$input = $('<input class="filter" type="hidden">')
|
||||
.appendTo($cell)
|
||||
// hidden filter update (.tsfilter) namespace trigger by filter widget
|
||||
.bind('change.tsfilter', function(){
|
||||
var v = this.value.split(' - ');
|
||||
if (this.value === '') { v = [ o.min, o.max ]; }
|
||||
if (v && v[1]) {
|
||||
updateUiRange({ values: v, delay: false });
|
||||
}
|
||||
}),
|
||||
$shcell = [],
|
||||
c = $cell.closest('table')[0].config,
|
||||
|
||||
// this function updates the hidden input and adds the current values to the header cell text
|
||||
updateUiRange = function(ui) {
|
||||
// ui.values are undefined for some reason on create
|
||||
var val = ui && ui.values || o.values,
|
||||
result = val[0] + ' - ' + val[1],
|
||||
// make range an empty string if entire range is covered so the filter row will hide (if set)
|
||||
range = val[0] === o.min && val[1] === o.max ? '' : result;
|
||||
if (o.valueToHeader) {
|
||||
// add range indication to the header cell above (if not using the css method)!
|
||||
$cell.closest('thead').find('th[data-column=' + indx + ']').find('.currange').html(' (' + result + ')');
|
||||
} else {
|
||||
// add values to the handle data-value attribute so the css tooltip will work properly
|
||||
$cell.find('.ui-slider-handle')
|
||||
.addClass('value-popup')
|
||||
.eq(0).attr('data-value', val[0]).end() // adding value to data attribute
|
||||
.eq(1).attr('data-value', val[1]); // value popup shown via css
|
||||
}
|
||||
// update the hidden input
|
||||
$cell.find('.filter').val(range)
|
||||
.trigger('search', ui && typeof ui.delayed === 'boolean' ? ui.delayed : o.delayed).end()
|
||||
.find('.range').slider('values', val);
|
||||
// update sticky header cell
|
||||
if ($shcell.length) {
|
||||
$shcell.find('.range').slider('values', val);
|
||||
if (o.valueToHeader) {
|
||||
$shcell.closest('thead').find('th[data-column=' + indx + ']').find('.currange').html(' (' + result + ')');
|
||||
} else {
|
||||
$shcell.find('.ui-slider-handle')
|
||||
.addClass('value-popup')
|
||||
.eq(0).attr('data-value', val[0]).end() // adding value to data attribute
|
||||
.eq(1).attr('data-value', val[1]); // value popup shown via css
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
$cell.closest('thead').find('th[data-column=' + indx + ']').addClass('filter-parsed');
|
||||
|
||||
// add span to header for value - only works if the line in the updateUiRange() function is also un-commented out
|
||||
if (o.valueToHeader) {
|
||||
$cell.closest('thead').find('th[data-column=' + indx + ']').find('.tablesorter-header-inner').append('<span class="currange"/>');
|
||||
}
|
||||
|
||||
// add callbacks; preserve added callbacks
|
||||
o.oldcreate = o.create;
|
||||
o.oldslide = o.slide;
|
||||
// add a jQuery UI range slider!
|
||||
o.create = function(event, ui) {
|
||||
updateUiRange(); // ui is an empty object on create
|
||||
if (typeof o.oldcreate === 'function') { o.oldcreate(event, ui); }
|
||||
};
|
||||
o.slide = function(event, ui) {
|
||||
updateUiRange(ui);
|
||||
if (typeof o.oldslide === 'function') { o.oldslide(event, ui); }
|
||||
};
|
||||
$('<div class="range range' + indx +'"/>')
|
||||
.appendTo($cell)
|
||||
.slider(o);
|
||||
|
||||
// on reset
|
||||
c.$table.bind('filterReset', function(){
|
||||
$cell.find('.range').slider('values', o.values);
|
||||
updateUiRange();
|
||||
});
|
||||
|
||||
// has sticky headers?
|
||||
c.$table.bind('stickyHeadersInit', function(){
|
||||
$shcell = c.widgetOptions.$sticky.find('.tablesorter-filter-row').children().eq(indx).empty();
|
||||
|
||||
// add a jQuery UI slider!
|
||||
$('<div class="range range' + indx + '"/>')
|
||||
.val(o.value)
|
||||
.appendTo($shcell)
|
||||
.slider(o)
|
||||
.bind('change keyup', function(e){
|
||||
$cell.find('.range').val( this.value );
|
||||
updateUiRange();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// return the hidden input so the filter widget has a reference to it
|
||||
return $input;
|
||||
},
|
||||
|
||||
/*************************\
|
||||
jQuery UI Datepicker compare (1 input)
|
||||
\*************************/
|
||||
uiDateCompare: function($cell, indx, defDate) {
|
||||
var o = $.extend({
|
||||
defaultDate : '',
|
||||
cellText : '',
|
||||
changeMonth : true,
|
||||
changeYear : true,
|
||||
numberOfMonths : 1,
|
||||
compare : ''
|
||||
}, defDate),
|
||||
$hdr = $cell.closest('thead').find('th[data-column=' + indx + ']'),
|
||||
// Add a hidden input to hold the range values
|
||||
$input = $('<input class="dateCompare" type="hidden">')
|
||||
.appendTo($cell)
|
||||
// hidden filter update (.tsfilter) namespace trigger by filter widget
|
||||
.bind('change.tsfilter', function(){
|
||||
var v = this.value;
|
||||
if (v) {
|
||||
o.onClose(v);
|
||||
}
|
||||
}),
|
||||
t, $shcell = [],
|
||||
c = $cell.closest('table')[0].config;
|
||||
|
||||
// make sure we're using parsed dates in the search
|
||||
$hdr.addClass('filter-parsed');
|
||||
// Add date range picker
|
||||
t = '<label>' + o.cellText + '</label><input type="text" class="date date' + indx +
|
||||
'" placeholder="' + ($hdr.data('placeholder') || $hdr.attr('data-placeholder') || '') + '" />';
|
||||
$(t).appendTo($cell);
|
||||
|
||||
// add callbacks; preserve added callbacks
|
||||
o.oldonClose = o.onClose;
|
||||
|
||||
o.onClose = function( selectedDate, ui ) {
|
||||
var date = new Date(selectedDate + ( o.compare.match('<') ? ' 23:59:59' : '' )).getTime() || '';
|
||||
$cell
|
||||
// update hidden input
|
||||
.find('.dateCompare').val( o.compare + date )
|
||||
.trigger('search').end()
|
||||
.find('.date')
|
||||
.datepicker('setDate', selectedDate);
|
||||
|
||||
// update sticky header cell
|
||||
if ($shcell.length) {
|
||||
$shcell.find('.date').datepicker('setDate', selectedDate);
|
||||
}
|
||||
|
||||
if (typeof o.oldonClose === 'function') { o.oldonClose(selectedDate, ui); }
|
||||
};
|
||||
$cell.find('.date').datepicker(o);
|
||||
|
||||
if (o.filterDate) {
|
||||
$cell.find('.date').datepicker('setDate', o.filterDate);
|
||||
}
|
||||
|
||||
// on reset
|
||||
c.$table.bind('filterReset', function(){
|
||||
$cell.find('.date').val('').datepicker('option', 'currentText', '' );
|
||||
if ($shcell.length) {
|
||||
$shcell.find('.date').val('').datepicker('option', 'currentText', '' );
|
||||
}
|
||||
});
|
||||
|
||||
// has sticky headers?
|
||||
c.$table.bind('stickyHeadersInit', function(){
|
||||
$shcell = c.widgetOptions.$sticky.find('.tablesorter-filter-row').children().eq(indx).empty();
|
||||
// add a jQuery datepicker!
|
||||
$shcell
|
||||
.append(t)
|
||||
.find('.date')
|
||||
.datepicker(o);
|
||||
});
|
||||
|
||||
// return the hidden input so the filter widget has a reference to it
|
||||
return $input.val( o.defaultDate ? o.defaultDate : '' );
|
||||
},
|
||||
|
||||
/*************************\
|
||||
jQuery UI Datepicker (2 inputs)
|
||||
\*************************/
|
||||
uiDatepicker: function($cell, indx, defDate) {
|
||||
var o = $.extend({
|
||||
from : '',
|
||||
to : '',
|
||||
textFrom : 'from',
|
||||
textTo : 'to',
|
||||
changeMonth : true,
|
||||
changeYear : true,
|
||||
numberOfMonths : 1
|
||||
}, defDate),
|
||||
t, closeFrom, $shcell = [],
|
||||
// Add a hidden input to hold the range values
|
||||
$input = $('<input class="dateRange" type="hidden">')
|
||||
.appendTo($cell)
|
||||
// hidden filter update (.tsfilter) namespace trigger by filter widget
|
||||
.bind('change.tsfilter', function(){
|
||||
var v = this.value;
|
||||
if (v.match(' - ')) {
|
||||
v = v.split(' - ');
|
||||
$cell.find('.dateTo').val(v[1]);
|
||||
closeFrom(v[0]);
|
||||
} else if (v.match('>=')) {
|
||||
closeFrom( v.replace('>=', '') );
|
||||
} else if (v.match('<=')) {
|
||||
o.onClose( v.replace('<=', '') );
|
||||
}
|
||||
}),
|
||||
c = $cell.closest('table')[0].config;
|
||||
|
||||
// make sure we're using parsed dates in the search
|
||||
$cell.closest('thead').find('th[data-column=' + indx + ']').addClass('filter-parsed');
|
||||
// Add date range picker
|
||||
t = '<label>' + o.textFrom + '</label><input type="text" class="dateFrom" /><label>' + o.textTo + '</label><input type="text" class="dateTo" />';
|
||||
$(t).appendTo($cell);
|
||||
|
||||
// add callbacks; preserve added callbacks
|
||||
o.oldonClose = o.onClose;
|
||||
|
||||
o.defaultDate = o.from || o.defaultDate;
|
||||
|
||||
closeFrom = o.onClose = function( selectedDate, ui ) {
|
||||
var from = ( (new Date(selectedDate)).getTime() || ''),
|
||||
to = (new Date($cell.find('.dateTo').val() + ' 23:59:59').getTime() || ''),
|
||||
range = from ? ( to ? from + ' - ' + to : '>=' + from ) : (to ? '<=' + to : '');
|
||||
$cell
|
||||
.find('.dateTo').datepicker('option', 'minDate', selectedDate ).end()
|
||||
.find('.dateFrom').val(selectedDate).end()
|
||||
// update hidden input
|
||||
.find('.dateRange').val(range)
|
||||
.trigger('search');
|
||||
// update sticky header cell
|
||||
if ($shcell.length) {
|
||||
$shcell
|
||||
.find('.dateTo').datepicker('option', 'minDate', selectedDate ).end()
|
||||
.find('.dateFrom').val(selectedDate);
|
||||
}
|
||||
if (typeof o.oldonClose === 'function') { o.oldonClose(selectedDate, ui); }
|
||||
};
|
||||
|
||||
$cell.find('.dateFrom').datepicker(o);
|
||||
o.defaultDate = o.to || '+7d'; // set to date +7 days from today (if not defined)
|
||||
o.onClose = function( selectedDate, ui ) {
|
||||
var from = new Date( $cell.find('.dateFrom').val() ).getTime() || '',
|
||||
to = new Date( selectedDate + ' 23:59:59' ).getTime() || '',
|
||||
range = from ? ( to ? from + ' - ' + to : '>=' + from ) : (to ? '<=' + to : '');
|
||||
$cell
|
||||
.find('.dateFrom').datepicker('option', 'maxDate', selectedDate ).end()
|
||||
.find('.dateTo').val(selectedDate).end()
|
||||
.find('.dateRange').val(range)
|
||||
.trigger('search');
|
||||
// update sticky header cell
|
||||
if ($shcell.length) {
|
||||
$shcell
|
||||
.find('.dateFrom').datepicker('option', 'maxDate', selectedDate ).end()
|
||||
.find('.dateTo').val(selectedDate);
|
||||
}
|
||||
if (typeof o.oldonClose === 'function') { o.oldonClose(selectedDate, ui); }
|
||||
};
|
||||
$cell.find('.dateTo').datepicker(o);
|
||||
|
||||
// has sticky headers?
|
||||
c.$table.bind('stickyHeadersInit', function(){
|
||||
$shcell = c.widgetOptions.$sticky.find('.tablesorter-filter-row').children().eq(indx).empty();
|
||||
// add a jQuery datepicker!
|
||||
$shcell.append(t).find('.dateTo').datepicker(o);
|
||||
o.defaultDate = o.from || o.defaultDate || new Date();
|
||||
o.onClose = closeFrom;
|
||||
$shcell.find('.dateFrom').datepicker(o);
|
||||
});
|
||||
|
||||
// on reset
|
||||
$cell.closest('table').bind('filterReset', function(){
|
||||
$cell.find('.dateFrom, .dateTo').val('');
|
||||
if ($shcell.length) {
|
||||
$shcell.find('.dateFrom, .dateTo').val('');
|
||||
}
|
||||
});
|
||||
|
||||
// return the hidden input so the filter widget has a reference to it
|
||||
t = o.from ? ( o.to ? o.from + ' - ' + o.to : '>=' + o.from ) : (o.to ? '<=' + o.to : '');
|
||||
return $input.val( t );
|
||||
},
|
||||
|
||||
/**********************\
|
||||
HTML5 Number (spinner)
|
||||
\**********************/
|
||||
html5Number : function($cell, indx, def5Num) {
|
||||
var t, o = $.extend({
|
||||
value : 0,
|
||||
min : 0,
|
||||
max : 100,
|
||||
step : 1,
|
||||
delayed : true,
|
||||
disabled : false,
|
||||
addToggle : true,
|
||||
exactMatch : true,
|
||||
compare : '',
|
||||
skipTest: false
|
||||
}, def5Num),
|
||||
|
||||
// test browser for HTML5 range support
|
||||
$number = $('<input type="number" style="visibility:hidden;" value="test">').appendTo($cell),
|
||||
// test if HTML5 number is supported - from Modernizr
|
||||
numberSupported = o.skipTest || $number.attr('type') === 'number' && $number.val() !== 'test',
|
||||
$shcell = [],
|
||||
c = $cell.closest('table')[0].config,
|
||||
|
||||
updateNumber = function(v, delayed){
|
||||
var chkd = o.addToggle ? $cell.find('.toggle').is(':checked') : true;
|
||||
$cell.find('input[type=hidden]')
|
||||
// add equal to the beginning, so we filter exact numbers
|
||||
.val( !o.addToggle || chkd ? (o.compare ? o.compare : o.exactMatch ? '=' : '') + v : '' )
|
||||
.trigger('search', delayed ? delayed : o.delayed).end()
|
||||
.find('.number').val(v);
|
||||
if ($cell.find('.number').length) {
|
||||
$cell.find('.number')[0].disabled = (o.disabled || !chkd);
|
||||
}
|
||||
// update sticky header cell
|
||||
if ($shcell.length) {
|
||||
$shcell.find('.number').val(v)[0].disabled = (o.disabled || !chkd);
|
||||
if (o.addToggle) {
|
||||
$shcell.find('.toggle')[0].checked = chkd;
|
||||
}
|
||||
}
|
||||
};
|
||||
$number.remove();
|
||||
|
||||
if (numberSupported) {
|
||||
t = o.addToggle ? '<div class="button"><input id="html5button' + indx + '" type="checkbox" class="toggle" /><label for="html5button' + indx + '"></label></div>' : '';
|
||||
t += '<input class="number" type="number" min="' + o.min + '" max="' + o.max + '" value="' +
|
||||
o.value + '" step="' + o.step + '" />';
|
||||
// add HTML5 number (spinner)
|
||||
$cell
|
||||
.html(t + '<input type="hidden" />')
|
||||
.find('.toggle, .number').bind('change', function(){
|
||||
updateNumber( $cell.find('.number').val() );
|
||||
})
|
||||
.closest('thead').find('th[data-column=' + indx + ']')
|
||||
.addClass('filter-parsed') // get exact numbers from column
|
||||
// on reset
|
||||
.closest('table').bind('filterReset', function(){
|
||||
// turn off the toggle checkbox
|
||||
if (o.addToggle) {
|
||||
$cell.find('.toggle')[0].checked = false;
|
||||
if ($shcell.length) {
|
||||
$shcell.find('.toggle')[0].checked = false;
|
||||
}
|
||||
}
|
||||
updateNumber( $cell.find('.number').val() );
|
||||
});
|
||||
|
||||
// hidden filter update (.tsfilter) namespace trigger by filter widget
|
||||
$cell.find('input[type=hidden]').bind('change.tsfilter', function(){
|
||||
updateNumber( this.value );
|
||||
});
|
||||
|
||||
// has sticky headers?
|
||||
c.$table.bind('stickyHeadersInit', function(){
|
||||
$shcell = c.widgetOptions.$sticky.find('.tablesorter-filter-row').children().eq(indx).empty();
|
||||
$shcell
|
||||
.html(t)
|
||||
.find('.toggle, .number').bind('change', function(){
|
||||
updateNumber( $shcell.find('.number').val() );
|
||||
});
|
||||
updateNumber( $cell.find('.number').val() );
|
||||
});
|
||||
|
||||
updateNumber( $cell.find('.number').val() );
|
||||
|
||||
}
|
||||
|
||||
return numberSupported ? $cell.find('input[type="hidden"]') : $('<input type="search">');
|
||||
},
|
||||
|
||||
/**********************\
|
||||
HTML5 range slider
|
||||
\**********************/
|
||||
html5Range : function($cell, indx, def5Range) {
|
||||
var t, o = $.extend({
|
||||
value : 0,
|
||||
min : 0,
|
||||
max : 100,
|
||||
step : 1,
|
||||
delayed : true,
|
||||
valueToHeader : true,
|
||||
exactMatch : true,
|
||||
compare : '',
|
||||
allText : 'all',
|
||||
skipTest : false
|
||||
}, def5Range),
|
||||
|
||||
// test browser for HTML5 range support
|
||||
$range = $('<input type="range" style="visibility:hidden;" value="test">').appendTo($cell),
|
||||
// test if HTML5 range is supported - from Modernizr (but I left out the method to detect in Safari 2-4)
|
||||
// see https://github.com/Modernizr/Modernizr/blob/master/feature-detects/inputtypes.js
|
||||
rangeSupported = o.skipTest || $range.attr('type') === 'range' && $range.val() !== 'test',
|
||||
$shcell = [],
|
||||
c = $cell.closest('table')[0].config,
|
||||
|
||||
updateRange = function(v, delayed){
|
||||
/*jshint eqeqeq:false */
|
||||
v = (v + '').replace(/[<>=]/g,'') || o.min; // hidden input changes may include compare symbols
|
||||
var t = ' (' + (o.compare ? o.compare + v : v == o.min ? o.allText : v) + ')';
|
||||
$cell.find('input[type=hidden]')
|
||||
// add equal to the beginning, so we filter exact numbers
|
||||
.val( ( o.compare ? o.compare + v : ( v == o.min ? '' : ( o.exactMatch ? '=' : '' ) + v ) ) )
|
||||
//( val == o.min ? '' : val + (o.exactMatch ? '=' : ''))
|
||||
.trigger('search', delayed ? delayed : o.delayed).end()
|
||||
.find('.range').val(v);
|
||||
// or add current value to the header cell, if desired
|
||||
$cell.closest('thead').find('th[data-column=' + indx + ']').find('.curvalue').html(t);
|
||||
// update sticky header cell
|
||||
if ($shcell.length) {
|
||||
$shcell.find('.range').val(v);
|
||||
$shcell.closest('thead').find('th[data-column=' + indx + ']').find('.curvalue').html(t);
|
||||
}
|
||||
};
|
||||
$range.remove();
|
||||
|
||||
if (rangeSupported) {
|
||||
// add HTML5 range
|
||||
$cell
|
||||
.html('<input type="hidden"><input class="range" type="range" min="' + o.min + '" max="' + o.max + '" value="' + o.value + '" />')
|
||||
.closest('thead').find('th[data-column=' + indx + ']')
|
||||
.addClass('filter-parsed') // get exact numbers from column
|
||||
// add span to header for the current slider value
|
||||
.find('.tablesorter-header-inner').append('<span class="curvalue" />');
|
||||
|
||||
$cell.find('.range').bind('change', function(){
|
||||
updateRange( this.value );
|
||||
});
|
||||
|
||||
// hidden filter update (.tsfilter) namespace trigger by filter widget
|
||||
$cell.find('input[type=hidden]').bind('change.tsfilter', function(){
|
||||
/*jshint eqeqeq:false */
|
||||
var v = this.value;
|
||||
if (v !== this.lastValue) {
|
||||
this.lastValue = ( o.compare ? o.compare + v : ( v == o.min ? '' : ( o.exactMatch ? '=' : '' ) + v ) );
|
||||
this.value = this.lastValue;
|
||||
updateRange( v );
|
||||
}
|
||||
});
|
||||
|
||||
// has sticky headers?
|
||||
c.$table.bind('stickyHeadersInit', function(){
|
||||
$shcell = c.widgetOptions.$sticky.find('.tablesorter-filter-row').children().eq(indx).empty();
|
||||
$shcell
|
||||
.html('<input class="range" type="range" min="' + o.min + '" max="' + o.max + '" value="' + o.value + '" />')
|
||||
.find('.range').bind('change', function(){
|
||||
updateRange( $shcell.find('.range').val() );
|
||||
});
|
||||
updateRange( $cell.find('.range').val() );
|
||||
});
|
||||
|
||||
// on reset
|
||||
$cell.closest('table').bind('filterReset', function(){
|
||||
// just turn off the colorpicker
|
||||
updateRange(o.value);
|
||||
});
|
||||
|
||||
updateRange( $cell.find('.range').val() );
|
||||
|
||||
}
|
||||
|
||||
return rangeSupported ? $cell.find('input[type="hidden"]') : $('<input type="search">');
|
||||
},
|
||||
|
||||
/**********************\
|
||||
HTML5 Color picker
|
||||
\**********************/
|
||||
html5Color: function($cell, indx, defColor) {
|
||||
var t, o = $.extend({
|
||||
value : '#000000',
|
||||
disabled : false,
|
||||
addToggle : true,
|
||||
exactMatch : true,
|
||||
valueToHeader : false,
|
||||
skipTest : false
|
||||
}, defColor),
|
||||
// Add a hidden input to hold the range values
|
||||
$color = $('<input type="color" style="visibility:hidden;" value="test">').appendTo($cell),
|
||||
// test if HTML5 color is supported - from Modernizr
|
||||
colorSupported = o.skipTest || $color.attr('type') === 'color' && $color.val() !== 'test',
|
||||
$shcell = [],
|
||||
c = $cell.closest('table')[0].config,
|
||||
|
||||
updateColor = function(v){
|
||||
v = v || o.value;
|
||||
var chkd = true,
|
||||
t = ' (' + v + ')';
|
||||
if (o.addToggle) {
|
||||
chkd = $cell.find('.toggle').is(':checked');
|
||||
}
|
||||
if ($cell.find('.colorpicker').length) {
|
||||
$cell.find('.colorpicker').val(v)[0].disabled = (o.disabled || !chkd);
|
||||
}
|
||||
|
||||
$cell.find('input[type=hidden]')
|
||||
.val( chkd ? v + (o.exactMatch ? '=' : '') : '' )
|
||||
.trigger('search');
|
||||
if (o.valueToHeader) {
|
||||
// add current color to the header cell
|
||||
$cell.closest('thead').find('th[data-column=' + indx + ']').find('.curcolor').html(t);
|
||||
} else {
|
||||
// current color to span in cell
|
||||
$cell.find('.currentColor').html(t);
|
||||
}
|
||||
|
||||
// update sticky header cell
|
||||
if ($shcell.length) {
|
||||
$shcell.find('.colorpicker').val(v)[0].disabled = (o.disabled || !chkd);
|
||||
if (o.addToggle) {
|
||||
$shcell.find('.toggle')[0].checked = chkd;
|
||||
}
|
||||
if (o.valueToHeader) {
|
||||
// add current color to the header cell
|
||||
$shcell.closest('thead').find('th[data-column=' + indx + ']').find('.curcolor').html(t);
|
||||
} else {
|
||||
// current color to span in cell
|
||||
$shcell.find('.currentColor').html(t);
|
||||
}
|
||||
}
|
||||
};
|
||||
$color.remove();
|
||||
|
||||
if (colorSupported) {
|
||||
// add HTML5 color picker
|
||||
t = '<div class="color-controls-wrapper">';
|
||||
t += o.addToggle ? '<div class="button"><input id="colorbutton' + indx + '" type="checkbox" class="toggle" /><label for="colorbutton' + indx + '"></label></div>' : '';
|
||||
t += '<input type="hidden"><input class="colorpicker" type="color" />';
|
||||
t += (o.valueToHeader ? '' : '<span class="currentColor">(#000000)</span>') + '</div>';
|
||||
$cell.html(t);
|
||||
|
||||
// add span to header for the current color value - only works if the line in the updateColor() function is also un-commented out
|
||||
if (o.valueToHeader) {
|
||||
$cell.closest('thead').find('th[data-column=' + indx + ']').find('.tablesorter-header-inner').append('<span class="curcolor" />');
|
||||
}
|
||||
|
||||
$cell.find('.toggle, .colorpicker').bind('change', function(){
|
||||
updateColor( $cell.find('.colorpicker').val() );
|
||||
});
|
||||
|
||||
// hidden filter update (.tsfilter) namespace trigger by filter widget
|
||||
$cell.find('input[type=hidden]').bind('change.tsfilter', function(){
|
||||
updateColor( this.value );
|
||||
});
|
||||
|
||||
// on reset
|
||||
$cell.closest('table').bind('filterReset', function(){
|
||||
// just turn off the colorpicker
|
||||
$cell.find('.toggle')[0].checked = false;
|
||||
updateColor( $cell.find('.colorpicker').val() );
|
||||
});
|
||||
|
||||
// has sticky headers?
|
||||
c.$table.bind('stickyHeadersInit', function(){
|
||||
$shcell = c.widgetOptions.$sticky.find('.tablesorter-filter-row').children().eq(indx);
|
||||
$shcell
|
||||
.html(t)
|
||||
.find('.toggle, .colorpicker').bind('change', function(){
|
||||
updateColor( $shcell.find('.colorpicker').val() );
|
||||
});
|
||||
updateColor( $shcell.find('.colorpicker').val() );
|
||||
});
|
||||
|
||||
updateColor( o.value );
|
||||
}
|
||||
return colorSupported ? $cell.find('input[type="hidden"]') : $('<input type="search">');
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
})(jQuery);
|
||||
+6
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -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 0;
|
||||
},
|
||||
type : 'numeric'
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
@@ -0,0 +1,32 @@
|
||||
/*! Month parser
|
||||
* Demo: http://jsfiddle.net/Mottie/abkNM/477/
|
||||
*/
|
||||
/*jshint jquery:true */
|
||||
;(function($){
|
||||
"use strict";
|
||||
|
||||
$.tablesorter.dates = $.extend({}, $.tablesorter.dates, {
|
||||
// *** modify this array to change match the language ***
|
||||
monthCased : [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ]
|
||||
});
|
||||
$.tablesorter.dates.monthLower = $.tablesorter.dates.monthCased.join(',').toLocaleLowerCase().split(',');
|
||||
|
||||
$.tablesorter.addParser({
|
||||
id: "month",
|
||||
is: function(){
|
||||
return false;
|
||||
},
|
||||
format: function(s, table) {
|
||||
var j = -1, c = table.config;
|
||||
s = c.ignoreCase ? s.toLocaleLowerCase() : s;
|
||||
$.each($.tablesorter.dates[ 'month' + (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);
|
||||
@@ -0,0 +1,68 @@
|
||||
/*! Two digit year parser
|
||||
* Demo: http://jsfiddle.net/Mottie/abkNM/427/
|
||||
*/
|
||||
/*jshint jquery:true */
|
||||
;(function($){
|
||||
"use strict";
|
||||
|
||||
// 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.
|
||||
var range = 50,
|
||||
|
||||
// ************
|
||||
regxxxxyy = /(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{2})/,
|
||||
regyyxxxx = /(\d{2})[\/\s](\d{1,2})[\/\s](\d{1,2})/,
|
||||
formatDate = function(s, regex, format){
|
||||
s = s
|
||||
// replace separators
|
||||
.replace(/\s+/g," ").replace(/[-.,]/g, "/")
|
||||
// reformat xx/xx/xx to mm/dd/19yy;
|
||||
.replace(regex, format);
|
||||
var d = new Date(s), y = d.getFullYear(),
|
||||
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 > range) {
|
||||
y += 100;
|
||||
}
|
||||
return d.setFullYear(y);
|
||||
};
|
||||
|
||||
$.tablesorter.addParser({
|
||||
id: "ddmmyy",
|
||||
is: function() {
|
||||
return false;
|
||||
},
|
||||
format: function(s) {
|
||||
// reformat dd/mm/yy to mm/dd/19yy;
|
||||
return formatDate(s, regxxxxyy, "$2/$1/19$3");
|
||||
},
|
||||
type: "numeric"
|
||||
});
|
||||
|
||||
$.tablesorter.addParser({
|
||||
id: "mmddyy",
|
||||
is: function() {
|
||||
return false;
|
||||
},
|
||||
format: function(s) {
|
||||
// reformat mm/dd/yy to mm/dd/19yy
|
||||
return formatDate(s, regxxxxyy, "$1/$2/19$3");
|
||||
},
|
||||
type: "numeric"
|
||||
});
|
||||
|
||||
$.tablesorter.addParser({
|
||||
id: "yymmdd",
|
||||
is: function() {
|
||||
return false;
|
||||
},
|
||||
format: function(s) {
|
||||
// reformat yy/mm/dd to mm/dd/19yy
|
||||
return formatDate(s, regyyxxxx, "$2/$3/19$1");
|
||||
},
|
||||
type: "numeric"
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
@@ -0,0 +1,32 @@
|
||||
/*! Weekday parser
|
||||
* Demo: http://jsfiddle.net/Mottie/abkNM/477/
|
||||
*/
|
||||
/*jshint jquery:true */
|
||||
;(function($){
|
||||
"use strict";
|
||||
|
||||
$.tablesorter.dates = $.extend({}, $.tablesorter.dates, {
|
||||
// *** modify this array to change match the language ***
|
||||
weekdayCased : [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ]
|
||||
});
|
||||
$.tablesorter.dates.weekdayLower = $.tablesorter.dates.weekdayCased.join(',').toLocaleLowerCase().split(',');
|
||||
|
||||
$.tablesorter.addParser({
|
||||
id: "weekday",
|
||||
is: function(){
|
||||
return false;
|
||||
},
|
||||
format: function(s, table) {
|
||||
var j = -1, c = table.config;
|
||||
s = c.ignoreCase ? s.toLocaleLowerCase() : s;
|
||||
$.each($.tablesorter.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);
|
||||
@@ -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 : 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);
|
||||
@@ -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 symbolRegex = /[\u215b\u215c\u215d\u215e\u00bc\u00bd\u00be]/g,
|
||||
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 = $.tablesorter.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 (symbolRegex.test(n)) {
|
||||
n = p + n.replace(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 = processFractions(d[0], table), // feet
|
||||
i = processFractions(d[1], table); // inches
|
||||
return (/[\'\"]/).test(s) ? parseFloat(f) + (parseFloat(i)/12 || 0) : parseFloat(f) + parseFloat(i);
|
||||
},
|
||||
type: 'numeric'
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
@@ -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);
|
||||
@@ -0,0 +1,78 @@
|
||||
/*! input & select parsers for jQuery 1.7+ & tablesorter 2.7.11+
|
||||
* 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;
|
||||
},
|
||||
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) {
|
||||
// using plain language here because this is what is shown in the group headers
|
||||
// change it as desired
|
||||
var $c = $(cell).find('input');
|
||||
return $c.length ? $c.is(':checked') ? 'checked' : 'unchecked' : s;
|
||||
},
|
||||
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;
|
||||
},
|
||||
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);
|
||||
@@ -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).find('thead').children().children('[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);
|
||||
@@ -0,0 +1,68 @@
|
||||
/*! tablesorter Editable Content widget - updated 4/12/2013
|
||||
* 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'
|
||||
},
|
||||
init: function(table, thisWidget, c, wo){
|
||||
if (!wo.editable_columns.length) { return; }
|
||||
var cols = [];
|
||||
$.each(wo.editable_columns, function(i, col){
|
||||
cols.push('td:nth-child(' + (col + 1) + ')');
|
||||
});
|
||||
c.$tbodies.find( cols.join(',') ).not('.' + wo.editable_noEdit).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, wo.editable_autoResort ]);
|
||||
$this.trigger('blur.tseditable');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
@@ -0,0 +1,114 @@
|
||||
/*! tablesorter Grouping widget - updated 4/12/2013
|
||||
* 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: 'group',
|
||||
options: {
|
||||
group_collapsible : true, // make the group header clickable and collapse the rows below it.
|
||||
group_count : ' ({num})', // if not false, the "{num}" string is replaced with the number of rows in the group
|
||||
// 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' ],
|
||||
group_formatter : null // function(curr, col, table, c, wo) { return curr; }
|
||||
},
|
||||
init: function(table, thisWidget, c, wo){
|
||||
if (wo.group_collapsible) {
|
||||
// .on() requires jQuery 1.7+
|
||||
c.$table.on('click', 'tr.group-header', function(){
|
||||
$(this).toggleClass('collapsed');
|
||||
// nextUntil requires jQuery 1.4+
|
||||
$(this).nextUntil('tr.group-header').toggleClass('group-hidden', $(this).hasClass('collapsed') );
|
||||
});
|
||||
}
|
||||
},
|
||||
format: function(table, c, wo) {
|
||||
var j, k, curr, $tr, t, t2, time,
|
||||
group = '',
|
||||
col = c.sortList[0] ? c.sortList[0][0] : -1,
|
||||
groupBy = {
|
||||
number : function($col, txt, num){
|
||||
if (num > 1 && txt !== '') {
|
||||
if ($col.hasClass(c.cssAsc)) {
|
||||
t = Math.floor(parseFloat(txt)/num) * num;
|
||||
return t > parseFloat(group || 0) ? t : parseFloat(group || 0);
|
||||
} else {
|
||||
t = Math.ceil(parseFloat(txt)/num) * num;
|
||||
return t < parseFloat(group || num) - t ? parseFloat(group || num) - t : t;
|
||||
}
|
||||
} else {
|
||||
var w = (txt + '').match(/\d+/g);
|
||||
return w && w.length >= num ? w[num - 1] : txt || '';
|
||||
}
|
||||
},
|
||||
word : function($col, txt, num){
|
||||
var w = (txt + ' ').match(/\w+/g);
|
||||
return w && w.length >= num ? w[num - 1] : txt || '';
|
||||
},
|
||||
letter : function($col, txt, num){
|
||||
return txt ? (txt + ' ').substring(0, num) : '';
|
||||
},
|
||||
date : function($col, txt, part){
|
||||
t = new Date(txt || '');
|
||||
t2 = t.getHours();
|
||||
return part === 'year' ? t.getFullYear() :
|
||||
part === 'month' ? wo.group_months[t.getMonth()] :
|
||||
part === 'day' ? wo.group_months[t.getMonth()] + ' ' + t.getDate() :
|
||||
part === 'week' ? wo.group_week[t.getDay()] :
|
||||
part === 'time' ? ('00' + (t2 > 12 ? t2 - 12 : t2 === 0 ? t2 + 12 : t2)).slice(-2) + ':' + ('00' + t.getMinutes()).slice(-2) + ' ' +
|
||||
('00' + wo.group_time[t2 >= 12 ? 1 : 0]).slice(-2) :
|
||||
t.toString();
|
||||
}
|
||||
};
|
||||
|
||||
c.$table
|
||||
.find('tr.group-hidden').removeClass('group-hidden').end()
|
||||
.find('tr.group-header').remove();
|
||||
if (col >= 0) {
|
||||
if (c.debug){ time = new Date(); }
|
||||
for (k = 0; k < c.$tbodies.length; k++) {
|
||||
$tr = c.$tbodies.children('tr');
|
||||
for (j = 0; j < $tr.length; j++) {
|
||||
t = (c.$headers.eq(col).attr('class') || '').match(/(group-\w+(-\w+)?)/g);
|
||||
// group-{type}-{number/date}
|
||||
t2 = t ? t[0].split('-') : ['','letter',1]; // default to letter 1
|
||||
curr = groupBy[t2[1]]( c.$headers.eq(col), c.cache[k].normalized[j][col], /date/.test(t) ? t2[2] : parseInt(t2[2] || 1, 10) || 1 );
|
||||
if (group !== curr) {
|
||||
group = curr;
|
||||
// show range if number > 1
|
||||
if (t2[1] === 'number' && t2[2] > 1 && curr !== '') {
|
||||
curr += ' - ' + (parseInt(curr, 10) + ((parseInt(t2[2],10) - 1) * (c.$headers.eq(col).hasClass(c.cssAsc) ? 1 : -1)));
|
||||
}
|
||||
if ($.isFunction(wo.group_formatter)) {
|
||||
curr = wo.group_formatter((curr || '').toString(), col, table, c, wo) || curr;
|
||||
}
|
||||
$tr.eq(j).before('<tr class="group-header ' + c.selectorRemove.slice(1) + '"><td colspan="' + (c.columns+1) + '">' +
|
||||
(wo.group_collapsible ? '<i/>' : '') + '<span class="group-name">' + curr + '</span><span class="group-count"></span></td></tr>');
|
||||
}
|
||||
}
|
||||
}
|
||||
if (wo.group_count) {
|
||||
c.$table.find('tr.group-header').each(function(){
|
||||
$(this).find('.group-count').html( wo.group_count.replace(/\{num\}/g, $(this).nextUntil('tr.group-header').length) );
|
||||
});
|
||||
}
|
||||
if (c.debug) {
|
||||
$.tablesorter.benchmark("Applying groups widget: ", time);
|
||||
}
|
||||
}
|
||||
},
|
||||
remove : function(table, c, wo){
|
||||
c.$table
|
||||
.off('click', 'tr.group-header')
|
||||
.find('.group-hidden').removeClass('group-hidden').end()
|
||||
.find('tr.group-header').remove();
|
||||
}
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
@@ -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);
|
||||
@@ -0,0 +1,240 @@
|
||||
/*!
|
||||
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();
|
||||
};
|
||||
|
||||
$.tablesorter.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');
|
||||
});
|
||||
|
||||
$.tablesorter.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', $.tablesorter.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', $.tablesorter.window_resize);
|
||||
table.config.widgetOptions.scroller_resizeWidth();
|
||||
$win.bind('resize', $.tablesorter.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('.' + c.cssHeader)
|
||||
.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(c.cssProcessing);
|
||||
if (c.cssIcon){
|
||||
t
|
||||
.find('.' + c.cssIcon)
|
||||
.attr('class', $(this).find('.' + c.cssIcon).attr('class'));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// make scroller header sortable
|
||||
c.$headers.find('*')[ $.fn.addBack ? 'addBack': 'andSelf' ]().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);
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jquery.tablesorter",
|
||||
"filename": "jquery.tablesorter.min.js",
|
||||
"version": "2.9.1",
|
||||
"version": "2.10.8",
|
||||
"description": "tablesorter is a jQuery plugin for turning a standard HTML table with THEAD and TBODY tags into a sortable table without page refreshes. tablesorter can successfully parse and sort many types of data including linked data in a cell.\n\nThis forked version adds lots of new enhancements including: alphanumeric sorting, pager callback functons, multiple widgets providing column styling, ui theme application, sticky headers, column filters and resizer, as well as extended documentation with a lot more demos.",
|
||||
"author": "Christian Bach, Mottie",
|
||||
"homepage": "http://mottie.github.com/tablesorter/docs/",
|
||||
|
||||
Reference in New Issue
Block a user