Renamed all default widget variables

This commit is contained in:
Mottie 2013-11-13 21:23:25 -06:00
parent 118f819d26
commit 75976336a9

View File

@ -10,7 +10,7 @@
*/ */
/*jshint browser:true, jquery:true, unused:false, loopfunc:true */ /*jshint browser:true, jquery:true, unused:false, loopfunc:true */
/*global jQuery: false, localStorage: false, navigator: false */ /*global jQuery: false, localStorage: false, navigator: false */
;(function($){ ;(function($) {
"use strict"; "use strict";
var ts = $.tablesorter = $.tablesorter || {}; var ts = $.tablesorter = $.tablesorter || {};
@ -68,86 +68,93 @@ ts.themes = {
val = (v && v.hasOwnProperty('mywidget')) ? v.mywidget : ''; val = (v && v.hasOwnProperty('mywidget')) ? v.mywidget : '';
alert(val); // "data1" if saved, or "" if not alert(val); // "data1" if saved, or "" if not
*/ */
ts.storage = function(table, key, val, options){ ts.storage = function(table, key, value, options) {
var d, k, ls = false, v = {}, var cookieIndex, cookies, date,
hasLocalStorage = false,
values = {},
c = table.config, c = table.config,
id = options && options.id || $(table).attr(options && options.group || 'data-table-group') || table.id || $('.tablesorter').index( $(table) ), id = options && options.id || $(table).attr(options && options.group ||
url = options && options.url || $(table).attr(options && options.page || 'data-table-page') || c && c.fixedUrl || window.location.pathname; 'data-table-group') || table.id || $('.tablesorter').index( $(table) ),
url = options && options.url || $(table).attr(options && options.page ||
'data-table-page') || c && c.fixedUrl || window.location.pathname;
// https://gist.github.com/paulirish/5558557 // https://gist.github.com/paulirish/5558557
if ("localStorage" in window) { if ("localStorage" in window) {
try { try {
window.localStorage.setItem('_tmptest', 'temp'); window.localStorage.setItem('_tmptest', 'temp');
ls = true; hasLocalStorage = true;
window.localStorage.removeItem('_tmptest'); window.localStorage.removeItem('_tmptest');
} catch(e) {} } catch(error) {}
} }
// *** get val *** // *** get value ***
if ($.parseJSON){ if ($.parseJSON) {
if (ls){ if (hasLocalStorage) {
v = $.parseJSON(localStorage[key] || '{}'); values = $.parseJSON(localStorage[key] || '{}');
} else { } else {
k = document.cookie.split(/[;\s|=]/); // cookie // old browser, using cookies
d = $.inArray(key, k) + 1; // add one to get from the key to the value cookies = document.cookie.split(/[;\s|=]/);
v = (d !== 0) ? $.parseJSON(k[d] || '{}') : {}; // add one to get from the key to the value
cookieIndex = $.inArray(key, cookies) + 1;
values = (cookieIndex !== 0) ? $.parseJSON(cookies[cookieIndex] || '{}') : {};
} }
} }
// allow val to be an empty string to // allow value to be an empty string too
if ((val || val === '') && window.JSON && JSON.hasOwnProperty('stringify')){ if ((value || value === '') && window.JSON && JSON.hasOwnProperty('stringify')) {
// add unique identifiers = url pathname > table ID/index on page > data // add unique identifiers = url pathname > table ID/index on page > data
if (!v[url]) { if (!values[url]) {
v[url] = {}; values[url] = {};
} }
v[url][id] = val; values[url][id] = value;
// *** set val *** // *** set value ***
if (ls){ if (hasLocalStorage) {
localStorage[key] = JSON.stringify(v); localStorage[key] = JSON.stringify(values);
} else { } else {
d = new Date(); date = new Date();
d.setTime(d.getTime() + (31536e+6)); // 365 days date.setTime(date.getTime() + (31536e+6)); // 365 days
document.cookie = key + '=' + (JSON.stringify(v)).replace(/\"/g,'\"') + '; expires=' + d.toGMTString() + '; path=/'; document.cookie = key + '=' + (JSON.stringify(values)).replace(/\"/g,'\"') + '; expires=' + date.toGMTString() + '; path=/';
} }
} else { } else {
return v && v[url] ? v[url][id] : {}; return values && values[url] ? values[url][id] : {};
} }
}; };
// Add a resize event to table headers // Add a resize event to table headers
// ************************** // **************************
ts.addHeaderResizeEvent = function(table, disable, options){ ts.addHeaderResizeEvent = function(table, disable, settings) {
var defaults = { var headers,
defaults = {
timer : 250 timer : 250
}, },
o = $.extend({}, defaults, options), options = $.extend({}, defaults, settings),
c = table.config, c = table.config,
wo = c.widgetOptions, wo = c.widgetOptions,
headers, checkSizes = function(triggerEvent) {
checkSizes = function(){
wo.resize_flag = true; wo.resize_flag = true;
headers = []; headers = [];
c.$headers.each(function(){ c.$headers.each(function() {
var d = $.data(this, 'savedSizes') || [0,0], // fixes #394 var $header = $(this),
w = this.offsetWidth, sizes = $header.data('savedSizes') || [0,0], // fixes #394
h = this.offsetHeight; width = this.offsetWidth,
if (w !== d[0] || h !== d[1]) { height = this.offsetHeight;
$.data(this, 'savedSizes', [ w, h ]); if (width !== sizes[0] || height !== sizes[1]) {
$header.data('savedSizes', [ width, height ]);
headers.push(this); headers.push(this);
} }
}); });
if (headers.length) { c.$table.trigger('resize', [ headers ]); } if (headers.length && triggerEvent !== false) {
c.$table.trigger('resize', [ headers ]);
}
wo.resize_flag = false; wo.resize_flag = false;
}; };
c.$headers.each(function(){ checkSizes(false);
$.data(this, 'savedSizes', [ this.offsetWidth, this.offsetHeight ]);
});
clearInterval(wo.resize_timer); clearInterval(wo.resize_timer);
if (disable) { if (disable) {
wo.resize_flag = false; wo.resize_flag = false;
return false; return false;
} }
wo.resize_timer = setInterval(function(){ wo.resize_timer = setInterval(function() {
if (wo.resize_flag) { return; } if (wo.resize_flag) { return; }
checkSizes(); checkSizes();
}, o.timer); }, options.timer);
}; };
// Widget: General UI theme // Widget: General UI theme
@ -156,89 +163,88 @@ ts.addHeaderResizeEvent = function(table, disable, options){
ts.addWidget({ ts.addWidget({
id: "uitheme", id: "uitheme",
priority: 10, priority: 10,
options: { format: function(table, c, wo) {
uitheme : 'jui' var time, classes, $header, $icon, $tfoot,
}, themesAll = ts.themes,
format: function(table, c, wo){ $table = c.$table,
var time, klass, $el, $tar, $headers = c.$headers,
t = ts.themes, theme = c.theme || 'jui',
$t = c.$table, themes = themesAll[theme] || themesAll['jui'],
theme = c.theme !== 'default' ? c.theme : wo.uitheme || 'jui', remove = themes.sortNone + ' ' + themes.sortDesc + ' ' + themes.sortAsc;
o = t[ t[theme] ? theme : t[wo.uitheme] ? wo.uitheme : 'jui'],
$h = c.$headers,
sh = 'tr.' + (wo.stickyHeaders || 'tablesorter-stickyHeader'),
rmv = o.sortNone + ' ' + o.sortDesc + ' ' + o.sortAsc;
if (c.debug) { time = new Date(); } if (c.debug) { time = new Date(); }
// initialization code - run once // initialization code - run once
if (!$t.hasClass('tablesorter-' + theme) || c.theme === theme || !table.hasInitialized){ if (!$table.hasClass('tablesorter-' + theme) || c.theme === theme || !table.hasInitialized) {
// update zebra stripes // update zebra stripes
if (o.even !== '') { wo.zebra[0] += ' ' + o.even; } if (themes.even !== '') { wo.zebra[0] += ' ' + themes.even; }
if (o.odd !== '') { wo.zebra[1] += ' ' + o.odd; } if (themes.odd !== '') { wo.zebra[1] += ' ' + themes.odd; }
// add caption style // add caption style
$t.find('caption').addClass(o.caption); $table.find('caption').addClass(themes.caption);
// add table/footer class names // add table/footer class names
t = $t $tfoot = $table
// remove other selected themes; use widgetOptions.theme_remove // remove other selected themes
.removeClass( c.theme === '' ? '' : 'tablesorter-' + c.theme ) .removeClass( c.theme === '' ? '' : 'tablesorter-' + c.theme )
.addClass('tablesorter-' + theme + ' ' + o.table) // add theme widget class name .addClass('tablesorter-' + theme + ' ' + themes.table) // add theme widget class name
.find('tfoot'); .find('tfoot');
if (t.length) { if ($tfoot.length) {
t $tfoot
.find('tr').addClass(o.footerRow) .find('tr').addClass(themes.footerRow)
.children('th, td').addClass(o.footerCells); .children('th, td').addClass(themes.footerCells);
} }
// update header classes // update header classes
$h $headers
.addClass(o.header) .addClass(themes.header)
.filter(':not(.sorter-false)') .not('.sorter-false')
.bind('mouseenter.tsuitheme mouseleave.tsuitheme', function(e){ .bind('mouseenter.tsuitheme mouseleave.tsuitheme', function(event) {
// toggleClass with switch added in jQuery 1.3 // toggleClass with switch added in jQuery 1.3
$(this)[ e.type === 'mouseenter' ? 'addClass' : 'removeClass' ](o.hover); $(this)[ event.type === 'mouseenter' ? 'addClass' : 'removeClass' ](themes.hover);
}); });
if (!$h.find('.tablesorter-wrapper').length) { if (!$headers.find('.tablesorter-wrapper').length) {
// Firefox needs this inner div to position the icon/resizer correctly // Firefox needs this inner div to position the resizer correctly
$h.wrapInner('<div class="tablesorter-wrapper" style="position:relative;height:100%;width:100%"></div>'); $headers.wrapInner('<div class="tablesorter-wrapper" style="position:relative;height:100%;width:100%"></div>');
} }
if (c.cssIcon){ if (c.cssIcon) {
// if c.cssIcon is '', then no <i> is added to the header // if c.cssIcon is '', then no <i> is added to the header
$h.find('.' + ts.css.icon).addClass(o.icons); $headers.find('.' + ts.css.icon).addClass(themes.icons);
} }
if ($t.hasClass('hasFilters')){ if ($table.hasClass('hasFilters')) {
$h.find('.tablesorter-filter-row').addClass(o.filterRow); $headers.find('.tablesorter-filter-row').addClass(themes.filterRow);
} }
} }
$.each($h, function(i){ $.each($headers, function() {
$el = $(this); $header = $(this);
$tar = (ts.css.icon) ? $el.find('.' + ts.css.icon) : $el; $icon = (ts.css.icon) ? $header.find('.' + ts.css.icon) : $header;
if (this.sortDisabled){ if (this.sortDisabled) {
// no sort arrows for disabled columns! // no sort arrows for disabled columns!
$el.removeClass(rmv); $header.removeClass(remove);
$tar.removeClass(rmv + ' tablesorter-icon ' + o.icons); $icon.removeClass(remove + ' tablesorter-icon ' + themes.icons);
} else { } else {
t = ($t.hasClass('hasStickyHeaders')) ? $t.find(sh).find('th').eq(i).add($el) : $el; classes = ($header.hasClass(ts.css.sortAsc)) ?
klass = ($el.hasClass(ts.css.sortAsc)) ? o.sortAsc : ($el.hasClass(ts.css.sortDesc)) ? o.sortDesc : $el.hasClass(ts.css.header) ? o.sortNone : ''; themes.sortAsc :
$el[klass === o.sortNone ? 'removeClass' : 'addClass'](o.active); ($header.hasClass(ts.css.sortDesc)) ? themes.sortDesc :
$tar.removeClass(rmv).addClass(klass); $header.hasClass(ts.css.header) ? themes.sortNone : '';
$header[classes === themes.sortNone ? 'removeClass' : 'addClass'](themes.active);
$icon.removeClass(remove).addClass(classes);
} }
}); });
if (c.debug){ if (c.debug) {
ts.benchmark("Applying " + theme + " theme", time); ts.benchmark("Applying " + theme + " theme", time);
} }
}, },
remove: function(table, c, wo){ remove: function(table, c, wo) {
var $t = c.$table, var $table = c.$table,
theme = typeof wo.uitheme === 'object' ? 'jui' : wo.uitheme || 'jui', theme = c.theme || 'jui',
o = typeof wo.uitheme === 'object' ? wo.uitheme : ts.themes[ ts.themes.hasOwnProperty(theme) ? theme : 'jui'], themes = ts.themes[ theme ] || ts.themes['jui'],
$h = $t.children('thead').children(), $headers = $table.children('thead').children(),
rmv = o.sortNone + ' ' + o.sortDesc + ' ' + o.sortAsc; remove = themes.sortNone + ' ' + themes.sortDesc + ' ' + themes.sortAsc;
$t $table
.removeClass('tablesorter-' + theme + ' ' + o.table) .removeClass('tablesorter-' + theme + ' ' + themes.table)
.find(ts.css.header).removeClass(o.header); .find(ts.css.header).removeClass(themes.header);
$h $headers
.unbind('mouseenter.tsuitheme mouseleave.tsuitheme') // remove hover .unbind('mouseenter.tsuitheme mouseleave.tsuitheme') // remove hover
.removeClass(o.hover + ' ' + rmv + ' ' + o.active) .removeClass(themes.hover + ' ' + remove + ' ' + themes.active)
.find('.tablesorter-filter-row').removeClass(o.filterRow); .find('.tablesorter-filter-row')
$h.find('.tablesorter-icon').removeClass(o.icons); .removeClass(themes.filterRow);
$headers.find('.tablesorter-icon').removeClass(themes.icons);
} }
}); });
@ -252,76 +258,74 @@ ts.addWidget({
options : { options : {
columns : [ "primary", "secondary", "tertiary" ] columns : [ "primary", "secondary", "tertiary" ]
}, },
format: function(table, c, wo){ format: function(table, c, wo) {
var $tb, $tr, $td, $t, time, last, rmv, i, k, l, var time, $tbody, tbodyIndex, $rows, rows, $row, $cells, last, remove, indx,
$tbl = c.$table, $table = c.$table,
b = c.$tbodies, $tbodies = c.$tbodies,
list = c.sortList, sortList = c.sortList,
len = list.length, len = sortList.length,
// keep backwards compatibility, for now // removed c.widgetColumns support
css = (c.widgetColumns && c.widgetColumns.hasOwnProperty('css')) ? c.widgetColumns.css || css : css = wo && wo.columns || [ "primary", "secondary", "tertiary" ],
(wo && wo.hasOwnProperty('columns')) ? wo.columns || css : css; last = css.length - 1;
last = css.length-1; remove = css.join(' ');
rmv = css.join(' '); if (c.debug) {
if (c.debug){
time = new Date(); time = new Date();
} }
// check if there is a sort (on initialization there may not be one) // check if there is a sort (on initialization there may not be one)
for (k = 0; k < b.length; k++ ){ for (tbodyIndex = 0; tbodyIndex < $tbodies.length; tbodyIndex++ ) {
$tb = ts.processTbody(table, b.eq(k), true); // detach tbody $tbody = ts.processTbody(table, $tbodies.eq(tbodyIndex), true); // detach tbody
$tr = $tb.children('tr'); $rows = $tbody.children('tr');
l = $tr.length;
// loop through the visible rows // loop through the visible rows
$tr.each(function(){ $rows.each(function() {
$t = $(this); $row = $(this);
if (this.style.display !== 'none'){ if (this.style.display !== 'none') {
// remove all columns class names // remove all columns class names
$td = $t.children().removeClass(rmv); $cells = $row.children().removeClass(remove);
// add appropriate column class names // add appropriate column class names
if (list && list[0]){ if (sortList && sortList[0]) {
// primary sort column class // primary sort column class
$td.eq(list[0][0]).addClass(css[0]); $cells.eq(sortList[0][0]).addClass(css[0]);
if (len > 1){ if (len > 1) {
for (i = 1; i < len; i++){ for (indx = 1; indx < len; indx++) {
// secondary, tertiary, etc sort column classes // secondary, tertiary, etc sort column classes
$td.eq(list[i][0]).addClass( css[i] || css[last] ); $cells.eq(sortList[indx][0]).addClass( css[indx] || css[last] );
} }
} }
} }
} }
}); });
ts.processTbody(table, $tb, false); ts.processTbody(table, $tbody, false);
} }
// add classes to thead and tfoot // add classes to thead and tfoot
$tr = wo.columns_thead !== false ? ['thead tr'] : []; rows = wo.columns_thead !== false ? ['thead tr'] : [];
if (wo.columns_tfoot !== false) { if (wo.columns_tfoot !== false) {
$tr.push('tfoot tr'); rows.push('tfoot tr');
} }
if ($tr.length) { if (rows.length) {
$t = $tbl.find($tr.join(',')).children().removeClass(rmv); $rows = $table.find( rows.join(',') ).children().removeClass(remove);
if (len){ if (len) {
for (i = 0; i < len; i++){ for (indx = 0; indx < len; indx++) {
// add primary. secondary, tertiary, etc sort column classes // add primary. secondary, tertiary, etc sort column classes
$t.filter('[data-column="' + list[i][0] + '"]').addClass(css[i] || css[last]); $rows.filter('[data-column="' + sortList[indx][0] + '"]').addClass(css[indx] || css[last]);
} }
} }
} }
if (c.debug){ if (c.debug) {
ts.benchmark("Applying Columns widget", time); ts.benchmark("Applying Columns widget", time);
} }
}, },
remove: function(table, c, wo){ remove: function(table, c, wo) {
var k, $tb, var tbodyIndex, $tbody,
b = c.$tbodies, $tbodies = c.$tbodies,
rmv = (wo.columns || [ "primary", "secondary", "tertiary" ]).join(' '); remove = (wo.columns || [ "primary", "secondary", "tertiary" ]).join(' ');
c.$headers.removeClass(rmv); c.$headers.removeClass(remove);
c.$table.children('tfoot').children('tr').children('th, td').removeClass(rmv); c.$table.children('tfoot').children('tr').children('th, td').removeClass(remove);
for (k = 0; k < b.length; k++ ){ for (tbodyIndex = 0; tbodyIndex < $tbodies.length; tbodyIndex++ ) {
$tb = ts.processTbody(table, b.eq(k), true); // remove tbody $tbody = ts.processTbody(table, $tbodies.eq(tbodyIndex), true); // remove tbody
$tb.children('tr').each(function(){ $tbody.children('tr').each(function() {
$(this).children().removeClass(rmv); $(this).children().removeClass(remove);
}); });
ts.processTbody(table, $tb, false); // restore tbody ts.processTbody(table, $tbody, false); // restore tbody
} }
} }
}); });
@ -610,6 +614,7 @@ ts.filter = {
ts.isProcessing(table, event.type === 'filterStart', columns ? $header : ''); ts.isProcessing(table, event.type === 'filterStart', columns ? $header : '');
}); });
} }
if (c.debug) { if (c.debug) {
ts.benchmark("Applying Filter widget", time); ts.benchmark("Applying Filter widget", time);
} }
@ -625,7 +630,7 @@ ts.filter = {
c.$table.trigger('filterInit'); c.$table.trigger('filterInit');
ts.filter.checkFilters(table); ts.filter.checkFilters(table);
}, },
setDefaults: function(table, c, wo){ setDefaults: function(table, c, wo) {
var indx, var indx,
filters = [], filters = [],
columns = c.columns; columns = c.columns;
@ -782,7 +787,7 @@ ts.filter = {
columns = c.columns, columns = c.columns,
$tbodies = c.$tbodies, $tbodies = c.$tbodies,
// anyMatch really screws up with these types of filters // anyMatch really screws up with these types of filters
anyMatchNotAllowedTypes = [ 'range', 'operators' ], anyMatchNotAllowedTypes = [ 'range', 'notMatch', 'operators' ],
// parse columns after formatter, in case the class is added at that point // parse columns after formatter, in case the class is added at that point
parsed = c.$headers.map(function(columnIndex) { parsed = c.$headers.map(function(columnIndex) {
return (ts.getData) ? return (ts.getData) ?
@ -1015,7 +1020,7 @@ ts.setFilters = function(table, filter, apply) {
// ************************** // **************************
ts.addWidget({ ts.addWidget({
id: "stickyHeaders", id: "stickyHeaders",
priority: 60, priority: 60, // sticky widget must be initialized after the filter widget!
options: { options: {
stickyHeaders : '', // extra class name added to the sticky header row stickyHeaders : '', // extra class name added to the sticky header row
stickyHeaders_offset : 0, // number or jquery selector targeting the position:fixed element stickyHeaders_offset : 0, // number or jquery selector targeting the position:fixed element
@ -1024,55 +1029,54 @@ ts.addWidget({
stickyHeaders_includeCaption : true, // if false and a caption exist, it won't be included in the sticky header stickyHeaders_includeCaption : true, // if false and a caption exist, it won't be included in the sticky header
stickyHeaders_zIndex : 2 // The zIndex of the stickyHeaders, allows the user to adjust this to their needs stickyHeaders_zIndex : 2 // The zIndex of the stickyHeaders, allows the user to adjust this to their needs
}, },
format: function(table, c, wo){ format: function(table, c, wo) {
if (c.$table.hasClass('hasStickyHeaders')) { return; } if (c.$table.hasClass('hasStickyHeaders')) { return; }
var $t = c.$table, var $cell,
$table = c.$table,
$win = $(window), $win = $(window),
header = $t.children('thead:first'), $thead = $table.children('thead:first'),
hdrCells = header.children('tr:not(.sticky-false)').children(), $header = $thead.children('tr').not('.sticky-false').children(),
innr = '.tablesorter-header-inner', innerHeader = '.tablesorter-header-inner',
tfoot = $t.find('tfoot'), $tfoot = $table.find('tfoot'),
filterInputs = '.tablesorter-filter', filterInputs = '.tablesorter-filter',
$stickyOffset = isNaN(wo.stickyHeaders_offset) ? $(wo.stickyHeaders_offset) : '', $stickyOffset = isNaN(wo.stickyHeaders_offset) ? $(wo.stickyHeaders_offset) : '',
stickyOffset = $stickyOffset.length ? $stickyOffset.height() || 0 : parseInt(wo.stickyHeaders_offset, 10) || 0, stickyOffset = $stickyOffset.length ? $stickyOffset.height() || 0 : parseInt(wo.stickyHeaders_offset, 10) || 0,
stickyzIndex = wo.stickyHeaders_zIndex ? wo.stickyHeaders_zIndex : 2, $stickyTable = wo.$sticky = $table.clone()
$stickyTable = wo.$sticky = $t.clone()
.addClass('containsStickyHeaders') .addClass('containsStickyHeaders')
.css({ .css({
position : 'fixed', position : 'fixed',
margin : 0, margin : 0,
top : stickyOffset, top : stickyOffset,
visibility : 'hidden', visibility : 'hidden',
zIndex : stickyzIndex zIndex : wo.stickyHeaders_zIndex ? wo.stickyHeaders_zIndex : 2
}), }),
stkyHdr = $stickyTable.children('thead:first').addClass('tablesorter-stickyHeader ' + wo.stickyHeaders), $stickyThead = $stickyTable.children('thead:first').addClass('tablesorter-stickyHeader ' + wo.stickyHeaders),
stkyCells, $stickyCells,
laststate = '', laststate = '',
spacing = 0, spacing = 0,
flag = false, updatingStickyFilters = false,
resizeHdr = function(){ resizeHeader = function() {
stickyOffset = $stickyOffset.length ? $stickyOffset.height() || 0 : parseInt(wo.stickyHeaders_offset, 10) || 0; stickyOffset = $stickyOffset.length ? $stickyOffset.height() || 0 : parseInt(wo.stickyHeaders_offset, 10) || 0;
var bwsr = navigator.userAgent;
spacing = 0; spacing = 0;
// yes, I dislike browser sniffing, but it really is needed here :( // yes, I dislike browser sniffing, but it really is needed here :(
// webkit automatically compensates for border spacing // webkit automatically compensates for border spacing
if ($t.css('border-collapse') !== 'collapse' && !/(webkit|msie)/i.test(bwsr)) { if ($table.css('border-collapse') !== 'collapse' && !/(webkit|msie)/i.test(navigator.userAgent)) {
// Firefox & Opera use the border-spacing // Firefox & Opera use the border-spacing
// update border-spacing here because of demos that switch themes // update border-spacing here because of demos that switch themes
spacing = parseInt(hdrCells.eq(0).css('border-left-width'), 10) * 2; spacing = parseInt($header.eq(0).css('border-left-width'), 10) * 2;
} }
$stickyTable.css({ $stickyTable.css({
left : header.offset().left - $win.scrollLeft() - spacing, left : $thead.offset().left - $win.scrollLeft() - spacing,
width: $t.width() width: $table.width()
}); });
stkyCells.filter(':visible').each(function(i){ $stickyCells.filter(':visible').each(function(i) {
var $h = hdrCells.filter(':visible').eq(i); var $cell = $header.filter(':visible').eq(i);
$(this) $(this)
.css({ .css({
width: $h.width() - spacing, width: $cell.width() - spacing,
height: $h.height() height: $cell.height()
}) })
.find(innr).width( $h.find(innr).width() ); .find(innerHeader).width( $cell.find(innerHeader).width() );
}); });
}; };
// fix clone ID, if it exists - fixes #271 // fix clone ID, if it exists - fixes #271
@ -1084,36 +1088,35 @@ ts.addWidget({
$stickyTable.find('caption').remove(); $stickyTable.find('caption').remove();
} }
// issue #172 - find td/th in sticky header // issue #172 - find td/th in sticky header
stkyCells = stkyHdr.children().children(); $stickyCells = $stickyThead.children().children();
$stickyTable.css({ height:0, width:0, padding:0, margin:0, border:0 }); $stickyTable.css({ height:0, width:0, padding:0, margin:0, border:0 });
// remove resizable block // remove resizable block
stkyCells.find('.tablesorter-resizer').remove(); $stickyCells.find('.tablesorter-resizer').remove();
// update sticky header class names to match real header after sorting // update sticky header class names to match real header after sorting
$t $table
.addClass('hasStickyHeaders') .addClass('hasStickyHeaders')
.bind('sortEnd.tsSticky', function(){ .bind('sortEnd.tsSticky', function() {
hdrCells.filter(':visible').each(function(i){ $header.filter(':visible').each(function(indx) {
var t = stkyCells.filter(':visible').eq(i); $cell = $stickyCells.filter(':visible').eq(indx)
t
.attr('class', $(this).attr('class')) .attr('class', $(this).attr('class'))
// remove processing icon // remove processing icon
.removeClass(ts.css.processing + ' ' + c.cssProcessing); .removeClass(ts.css.processing + ' ' + c.cssProcessing);
if (c.cssIcon){ if (c.cssIcon) {
t $cell
.find('.' + ts.css.icon) .find('.' + ts.css.icon)
.attr('class', $(this).find('.' + ts.css.icon).attr('class')); .attr('class', $(this).find('.' + ts.css.icon).attr('class'));
} }
}); });
}) })
.bind('pagerComplete.tsSticky', function(){ .bind('pagerComplete.tsSticky', function() {
resizeHdr(); resizeHeader();
}); });
// http://stackoverflow.com/questions/5312849/jquery-find-self; // http://stackoverflow.com/questions/5312849/jquery-find-self;
hdrCells.find(c.selectorSort).add( c.$headers.filter(c.selectorSort) ).each(function(i){ $header.find(c.selectorSort).add( c.$headers.filter(c.selectorSort) ).each(function(indx) {
var t = $(this), var $header = $(this),
// clicking on sticky will trigger sort // clicking on sticky will trigger sort
$cell = stkyHdr.children('tr.tablesorter-headerRow').children().eq(i).bind('mouseup', function(e){ $cell = $stickyThead.children('tr.tablesorter-headerRow').children().eq(indx).bind('mouseup', function(event) {
t.trigger(e, true); // external mouseup flag (click timer is ignored) $header.trigger(event, true); // external mouseup flag (click timer is ignored)
}); });
// prevent sticky header text selection // prevent sticky header text selection
if (c.cancelSelection) { if (c.cancelSelection) {
@ -1127,28 +1130,28 @@ ts.addWidget({
} }
}); });
// add stickyheaders AFTER the table. If the table is selected by ID, the original one (first) will be returned. // add stickyheaders AFTER the table. If the table is selected by ID, the original one (first) will be returned.
$t.after( $stickyTable ); $table.after( $stickyTable );
// make it sticky! // make it sticky!
$win.bind('scroll.tsSticky resize.tsSticky', function(e){ $win.bind('scroll.tsSticky resize.tsSticky', function(event) {
if (!$t.is(':visible')) { return; } // fixes #278 if (!$table.is(':visible')) { return; } // fixes #278
var pre = 'tablesorter-sticky-', var prefix = 'tablesorter-sticky-',
offset = $t.offset(), offset = $table.offset(),
cap = (wo.stickyHeaders_includeCaption ? 0 : $t.find('caption').outerHeight(true)), captionHeight = (wo.stickyHeaders_includeCaption ? 0 : $table.find('caption').outerHeight(true)),
sTop = $win.scrollTop() + stickyOffset - cap, scrollTop = $win.scrollTop() + stickyOffset - captionHeight,
tableHt = $t.height() - ($stickyTable.height() + (tfoot.height() || 0)), tableHeight = $table.height() - ($stickyTable.height() + ($tfoot.height() || 0)),
vis = (sTop > offset.top) && (sTop < offset.top + tableHt) ? 'visible' : 'hidden'; isVisible = (scrollTop > offset.top) && (scrollTop < offset.top + tableHeight) ? 'visible' : 'hidden';
$stickyTable $stickyTable
.removeClass(pre + 'visible ' + pre + 'hidden') .removeClass(prefix + 'visible ' + prefix + 'hidden')
.addClass(pre + vis) .addClass(prefix + isVisible)
.css({ .css({
// adjust when scrolling horizontally - fixes issue #143 // adjust when scrolling horizontally - fixes issue #143
left : header.offset().left - $win.scrollLeft() - spacing, left : $thead.offset().left - $win.scrollLeft() - spacing,
visibility : vis visibility : isVisible
}); });
if (vis !== laststate || e.type === 'resize'){ if (isVisible !== laststate || event.type === 'resize') {
// make sure the column widths match // make sure the column widths match
resizeHdr(); resizeHeader();
laststate = vis; laststate = isVisible;
} }
}); });
if (wo.stickyHeaders_addResizeEvent) { if (wo.stickyHeaders_addResizeEvent) {
@ -1156,28 +1159,28 @@ ts.addWidget({
} }
// look for filter widget // look for filter widget
$t.bind('filterEnd', function(){ $table.bind('filterEnd', function() {
if (flag) { return; } if (updatingStickyFilters) { return; }
stkyHdr.find('.tablesorter-filter-row').children().each(function(i){ $stickyThead.find('.tablesorter-filter-row').children().each(function(indx) {
$(this).find(filterInputs).val( c.$filters.find(filterInputs).eq(i).val() ); $(this).find(filterInputs).val( c.$filters.find(filterInputs).eq(indx).val() );
}); });
}); });
stkyCells.find(filterInputs).bind('keyup search change', function(e){ $stickyCells.find(filterInputs).bind('keyup search change', function(event) {
// ignore arrow and meta keys; allow backspace // ignore arrow and meta keys; allow backspace
if ((e.which < 32 && e.which !== 8) || (e.which >= 37 && e.which <=40)) { return; } if ((event.which < 32 && event.which !== 8) || (event.which >= 37 && event.which <=40)) { return; }
flag = true; updatingStickyFilters = true;
var $f = $(this), col = $f.attr('data-column'); var $f = $(this), column = $f.attr('data-column');
c.$filters.find(filterInputs).eq(col) c.$filters.find(filterInputs).eq(column)
.val( $f.val() ) .val( $f.val() )
.trigger('search'); .trigger('search');
setTimeout(function(){ setTimeout(function() {
flag = false; updatingStickyFilters = false;
}, wo.filter_searchDelay); }, wo.filter_searchDelay);
}); });
$t.trigger('stickyHeadersInit'); $table.trigger('stickyHeadersInit');
}, },
remove: function(table, c, wo){ remove: function(table, c, wo) {
c.$table c.$table
.removeClass('hasStickyHeaders') .removeClass('hasStickyHeaders')
.unbind('sortEnd.tsSticky pagerComplete.tsSticky') .unbind('sortEnd.tsSticky pagerComplete.tsSticky')
@ -1202,119 +1205,120 @@ ts.addWidget({
resizable : true, resizable : true,
resizable_addLastColumn : false resizable_addLastColumn : false
}, },
format: function(table, c, wo){ format: function(table, c, wo) {
if (c.$table.hasClass('hasResizable')) { return; } if (c.$table.hasClass('hasResizable')) { return; }
c.$table.addClass('hasResizable'); c.$table.addClass('hasResizable');
var $t, t, i, j, s = {}, $c, $cols, w, tw, var $rows, $columns, $column, column,
$tbl = c.$table, storedSizes = {},
position = 0, $table = c.$table,
mouseXPosition = 0,
$target = null, $target = null,
$next = null, $next = null,
fullWidth = Math.abs($tbl.parent().width() - $tbl.width()) < 20, fullWidth = Math.abs($table.parent().width() - $table.width()) < 20,
stopResize = function(){ stopResize = function() {
if (ts.storage && $target){ if (ts.storage && $target) {
s[$target.index()] = $target.width(); storedSizes[$target.index()] = $target.width();
s[$next.index()] = $next.width(); storedSizes[$next.index()] = $next.width();
$target.width( s[$target.index()] ); $target.width( storedSizes[$target.index()] );
$next.width( s[$next.index()] ); $next.width( storedSizes[$next.index()] );
if (wo.resizable !== false){ if (wo.resizable !== false) {
ts.storage(table, 'tablesorter-resizable', s); ts.storage(table, 'tablesorter-resizable', storedSizes);
} }
} }
position = 0; mouseXPosition = 0;
$target = $next = null; $target = $next = null;
$(window).trigger('resize'); // will update stickyHeaders, just in case $(window).trigger('resize'); // will update stickyHeaders, just in case
}; };
s = (ts.storage && wo.resizable !== false) ? ts.storage(table, 'tablesorter-resizable') : {}; storedSizes = (ts.storage && wo.resizable !== false) ? ts.storage(table, 'tablesorter-resizable') : {};
// process only if table ID or url match // process only if table ID or url match
if (s){ if (storedSizes) {
for (j in s){ for (column in storedSizes) {
if (!isNaN(j) && j < c.$headers.length){ if (!isNaN(column) && column < c.$headers.length) {
c.$headers.eq(j).width(s[j]); // set saved resizable widths c.$headers.eq(column).width(storedSizes[column]); // set saved resizable widths
} }
} }
} }
$t = $tbl.children('thead:first').children('tr'); $rows = $table.children('thead:first').children('tr');
// add resizable-false class name to headers (across rows as needed) // add resizable-false class name to headers (across rows as needed)
$t.children().each(function(){ $rows.children().each(function() {
t = $(this); var canResize,
i = t.attr('data-column'); $column = $(this);
j = ts.getData( t, c.headers[i], 'resizable') === "false"; column = $column.attr('data-column');
$t.children().filter('[data-column="' + i + '"]').toggleClass('resizable-false', j); canResize = ts.getData( $column, c.headers[column], 'resizable') === "false";
$rows.children().filter('[data-column="' + column + '"]')[canResize ? 'addClass' : 'removeClass']('resizable-false');
}); });
// add wrapper inside each cell to allow for positioning of the resizable target block // add wrapper inside each cell to allow for positioning of the resizable target block
$t.each(function(){ $rows.each(function() {
$c = $(this).children(':not(.resizable-false)'); $column = $(this).children().not('.resizable-false');
if (!$(this).find('.tablesorter-wrapper').length) { if (!$(this).find('.tablesorter-wrapper').length) {
// Firefox needs this inner div to position the resizer correctly // Firefox needs this inner div to position the resizer correctly
$c.wrapInner('<div class="tablesorter-wrapper" style="position:relative;height:100%;width:100%"></div>'); $column.wrapInner('<div class="tablesorter-wrapper" style="position:relative;height:100%;width:100%"></div>');
} }
// don't include the last column of the row // don't include the last column of the row
if (!wo.resizable_addLastColumn) { $c = $c.slice(0,-1); } if (!wo.resizable_addLastColumn) { $column = $column.slice(0,-1); }
$cols = $cols ? $cols.add($c) : $c; $columns = $columns ? $columns.add($column) : $column;
}); });
$cols $columns
.each(function(){ .each(function() {
$t = $(this); var $column = $(this),
j = parseInt($t.css('padding-right'), 10) + 10; // 8 is 1/2 of the 16px wide resizer grip padding = parseInt($column.css('padding-right'), 10) + 10; // 10 is 1/2 of the 20px wide resizer grip
t = '<div class="tablesorter-resizer" style="cursor:w-resize;position:absolute;z-index:1;right:-' + j + $column
'px;top:0;height:100%;width:20px;"></div>';
$t
.find('.tablesorter-wrapper') .find('.tablesorter-wrapper')
.append(t); .append('<div class="tablesorter-resizer" style="cursor:w-resize;position:absolute;z-index:1;right:-' +
padding + 'px;top:0;height:100%;width:20px;"></div>');
}) })
.bind('mousemove.tsresize', function(e){ .bind('mousemove.tsresize', function(event) {
// ignore mousemove if no mousedown // ignore mousemove if no mousedown
if (position === 0 || !$target) { return; } if (mouseXPosition === 0 || !$target) { return; }
// resize columns // resize columns
w = e.pageX - position; var leftEdge = event.pageX - mouseXPosition,
tw = $target.width(); targetWidth = $target.width();
$target.width( tw + w ); $target.width( targetWidth + leftEdge );
if ($target.width() !== tw && fullWidth){ if ($target.width() !== targetWidth && fullWidth) {
$next.width( $next.width() - w ); $next.width( $next.width() - leftEdge );
} }
position = e.pageX; mouseXPosition = event.pageX;
}) })
.bind('mouseup.tsresize', function(){ .bind('mouseup.tsresize', function() {
stopResize(); stopResize();
}) })
.find('.tablesorter-resizer,.tablesorter-resizer-grip') .find('.tablesorter-resizer,.tablesorter-resizer-grip')
.bind('mousedown', function(e){ .bind('mousedown', function(event) {
// save header cell and mouse position; closest() not supported by jQuery v1.2.6 // save header cell and mouse position; closest() not supported by jQuery v1.2.6
$target = $(e.target).closest('th'); $target = $(event.target).closest('th');
t = c.$headers.filter('[data-column="' + $target.attr('data-column') + '"]'); var $header = c.$headers.filter('[data-column="' + $target.attr('data-column') + '"]');
if (t.length > 1) { $target = $target.add(t); } if ($header.length > 1) { $target = $target.add($header); }
// if table is not as wide as it's parent, then resize the table // if table is not as wide as it's parent, then resize the table
$next = e.shiftKey ? $target.parent().find('th:not(.resizable-false)').filter(':last') : $target.nextAll(':not(.resizable-false)').eq(0); $next = event.shiftKey ? $target.parent().find('th').not('.resizable-false').filter(':last') : $target.nextAll(':not(.resizable-false)').eq(0);
position = e.pageX; mouseXPosition = event.pageX;
}); });
$tbl.find('thead:first') $table.find('thead:first')
.bind('mouseup.tsresize mouseleave.tsresize', function(){ .bind('mouseup.tsresize mouseleave.tsresize', function() {
stopResize(); stopResize();
}) })
// right click to reset columns to default widths // right click to reset columns to default widths
.bind('contextmenu.tsresize', function(){ .bind('contextmenu.tsresize', function() {
ts.resizableReset(table); ts.resizableReset(table);
// $.isEmptyObject() needs jQuery 1.4+ // $.isEmptyObject() needs jQuery 1.4+; allow right click if already reset
var rtn = $.isEmptyObject ? $.isEmptyObject(s) : s === {}; // allow right click if already reset var allowClick = $.isEmptyObject ? $.isEmptyObject(storedSizes) : true;
s = {}; storedSizes = {};
return rtn; return allowClick;
}); });
}, },
remove: function(table, c, wo){ remove: function(table, c) {
c.$table c.$table
.removeClass('hasResizable') .removeClass('hasResizable')
.find('thead') .children('thead')
.unbind('mouseup.tsresize mouseleave.tsresize contextmenu.tsresize') .unbind('mouseup.tsresize mouseleave.tsresize contextmenu.tsresize')
.find('tr').children() .children('tr').children()
.unbind('mousemove.tsresize mouseup.tsresize') .unbind('mousemove.tsresize mouseup.tsresize')
// don't remove "tablesorter-wrapper" as uitheme uses it too // don't remove "tablesorter-wrapper" as uitheme uses it too
.find('.tablesorter-resizer,.tablesorter-resizer-grip').remove(); .find('.tablesorter-resizer,.tablesorter-resizer-grip').remove();
ts.resizableReset(table); ts.resizableReset(table);
} }
}); });
ts.resizableReset = function(table){ ts.resizableReset = function(table) {
table.config.$headers.filter(':not(.resizable-false)').css('width',''); table.config.$headers.not('.resizable-false').css('width','');
if (ts.storage) { ts.storage(table, 'tablesorter-resizable', {}); } if (ts.storage) { ts.storage(table, 'tablesorter-resizable', {}); }
}; };
@ -1329,52 +1333,52 @@ ts.addWidget({
options: { options: {
saveSort : true saveSort : true
}, },
init: function(table, thisWidget, c, wo){ init: function(table, thisWidget, c, wo) {
// run widget format before all other widgets are applied to the table // run widget format before all other widgets are applied to the table
thisWidget.format(table, c, wo, true); thisWidget.format(table, c, wo, true);
}, },
format: function(table, c, wo, init){ format: function(table, c, wo, init) {
var sl, time, var stored, time,
$t = c.$table, $table = c.$table,
ss = wo.saveSort !== false, // make saveSort active/inactive; default to true saveSort = wo.saveSort !== false, // make saveSort active/inactive; default to true
sortList = { "sortList" : c.sortList }; sortList = { "sortList" : c.sortList };
if (c.debug){ if (c.debug) {
time = new Date(); time = new Date();
} }
if ($t.hasClass('hasSaveSort')){ if ($table.hasClass('hasSaveSort')) {
if (ss && table.hasInitialized && ts.storage){ if (saveSort && table.hasInitialized && ts.storage) {
ts.storage( table, 'tablesorter-savesort', sortList ); ts.storage( table, 'tablesorter-savesort', sortList );
if (c.debug){ if (c.debug) {
ts.benchmark('saveSort widget: Saving last sort: ' + c.sortList, time); ts.benchmark('saveSort widget: Saving last sort: ' + c.sortList, time);
} }
} }
} else { } else {
// set table sort on initial run of the widget // set table sort on initial run of the widget
$t.addClass('hasSaveSort'); $table.addClass('hasSaveSort');
sortList = ''; sortList = '';
// get data // get data
if (ts.storage){ if (ts.storage) {
sl = ts.storage( table, 'tablesorter-savesort' ); stored = ts.storage( table, 'tablesorter-savesort' );
sortList = (sl && sl.hasOwnProperty('sortList') && $.isArray(sl.sortList)) ? sl.sortList : ''; sortList = (stored && stored.hasOwnProperty('sortList') && $.isArray(stored.sortList)) ? stored.sortList : '';
if (c.debug){ if (c.debug) {
ts.benchmark('saveSort: Last sort loaded: "' + sortList + '"', time); ts.benchmark('saveSort: Last sort loaded: "' + sortList + '"', time);
} }
$t.bind('saveSortReset', function(e){ $table.bind('saveSortReset', function(event) {
e.stopPropagation(); event.stopPropagation();
ts.storage( table, 'tablesorter-savesort', '' ); ts.storage( table, 'tablesorter-savesort', '' );
}); });
} }
// init is true when widget init is run, this will run this widget before all other widgets have initialized // init is true when widget init is run, this will run this widget before all other widgets have initialized
// this method allows using this widget in the original tablesorter plugin; but then it will run all widgets twice. // this method allows using this widget in the original tablesorter plugin; but then it will run all widgets twice.
if (init && sortList && sortList.length > 0){ if (init && sortList && sortList.length > 0) {
c.sortList = sortList; c.sortList = sortList;
} else if (table.hasInitialized && sortList && sortList.length > 0){ } else if (table.hasInitialized && sortList && sortList.length > 0) {
// update sort change // update sort change
$t.trigger('sorton', [sortList]); $table.trigger('sorton', [sortList]);
} }
} }
}, },
remove: function(table){ remove: function(table) {
// clear storage // clear storage
if (ts.storage) { ts.storage( table, 'tablesorter-savesort', '' ); } if (ts.storage) { ts.storage( table, 'tablesorter-savesort', '' ); }
} }