2015-02-13 03:10:38 +00:00
|
|
|
/*! Widget: resizable */
|
|
|
|
;(function ($, window) {
|
|
|
|
'use strict';
|
|
|
|
var ts = $.tablesorter = $.tablesorter || {};
|
|
|
|
|
|
|
|
$.extend(ts.css, {
|
|
|
|
resizer : 'tablesorter-resizer' // resizable
|
|
|
|
});
|
|
|
|
|
|
|
|
// this widget saves the column widths if
|
|
|
|
// $.tablesorter.storage function is included
|
|
|
|
// **************************
|
|
|
|
ts.addWidget({
|
|
|
|
id: "resizable",
|
|
|
|
priority: 40,
|
|
|
|
options: {
|
|
|
|
resizable : true,
|
|
|
|
resizable_addLastColumn : false,
|
|
|
|
resizable_widths : [],
|
|
|
|
resizable_throttle : false // set to true (5ms) or any number 0-10 range
|
|
|
|
},
|
|
|
|
format: function(table, c, wo) {
|
|
|
|
if (c.$table.hasClass('hasResizable')) { return; }
|
|
|
|
c.$table.addClass('hasResizable');
|
|
|
|
ts.resizableReset(table, true); // set default widths
|
|
|
|
var $rows, $columns, $column, column, timer,
|
|
|
|
storedSizes = {},
|
|
|
|
$table = c.$table,
|
|
|
|
$wrap = $table.parent(),
|
|
|
|
overflow = $table.parent().css('overflow') === 'auto',
|
|
|
|
mouseXPosition = 0,
|
|
|
|
$target = null,
|
|
|
|
$next = null,
|
|
|
|
fullWidth = Math.abs($table.parent().width() - $table.width()) < 20,
|
|
|
|
mouseMove = function(event){
|
|
|
|
if (mouseXPosition === 0 || !$target) { return; }
|
|
|
|
// resize columns
|
|
|
|
var leftEdge = event.pageX - mouseXPosition,
|
|
|
|
targetWidth = $target.width();
|
|
|
|
$target.width( targetWidth + leftEdge );
|
|
|
|
if ($target.width() !== targetWidth && fullWidth) {
|
|
|
|
$next.width( $next.width() - leftEdge );
|
|
|
|
} else if (overflow) {
|
|
|
|
$table.width(function(i, w){
|
|
|
|
return w + leftEdge;
|
|
|
|
});
|
|
|
|
if (!$next.length) {
|
|
|
|
// if expanding right-most column, scroll the wrapper
|
|
|
|
$wrap[0].scrollLeft = $table.width();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mouseXPosition = event.pageX;
|
|
|
|
},
|
|
|
|
stopResize = function() {
|
|
|
|
if (ts.storage && $target && $next) {
|
|
|
|
storedSizes = {};
|
|
|
|
storedSizes[$target.index()] = $target.width();
|
|
|
|
storedSizes[$next.index()] = $next.width();
|
|
|
|
$target.width( storedSizes[$target.index()] );
|
|
|
|
$next.width( storedSizes[$next.index()] );
|
|
|
|
if (wo.resizable !== false) {
|
|
|
|
// save all column widths
|
|
|
|
ts.storage(table, 'tablesorter-resizable', c.$headers.map(function(){ return $(this).width(); }).get() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mouseXPosition = 0;
|
|
|
|
$target = $next = null;
|
|
|
|
$(window).trigger('resize'); // will update stickyHeaders, just in case
|
|
|
|
};
|
|
|
|
storedSizes = (ts.storage && wo.resizable !== false) ? ts.storage(table, 'tablesorter-resizable') : {};
|
|
|
|
// process only if table ID or url match
|
|
|
|
if (storedSizes) {
|
|
|
|
for (column in storedSizes) {
|
|
|
|
if (!isNaN(column) && column < c.$headers.length) {
|
|
|
|
c.$headers.eq(column).width(storedSizes[column]); // set saved resizable widths
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$rows = $table.children('thead:first').children('tr');
|
|
|
|
// add resizable-false class name to headers (across rows as needed)
|
|
|
|
$rows.children().each(function() {
|
|
|
|
var canResize,
|
|
|
|
$column = $(this);
|
|
|
|
column = $column.attr('data-column');
|
|
|
|
canResize = ts.getData( $column, ts.getColumnData( table, 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
|
|
|
|
$rows.each(function() {
|
|
|
|
$column = $(this).children().not('.resizable-false');
|
|
|
|
if (!$(this).find('.' + ts.css.wrapper).length) {
|
|
|
|
// Firefox needs this inner div to position the resizer correctly
|
|
|
|
$column.wrapInner('<div class="' + ts.css.wrapper + '" style="position:relative;height:100%;width:100%"></div>');
|
|
|
|
}
|
|
|
|
// don't include the last column of the row
|
|
|
|
if (!wo.resizable_addLastColumn) { $column = $column.slice(0,-1); }
|
|
|
|
$columns = $columns ? $columns.add($column) : $column;
|
|
|
|
});
|
|
|
|
$columns
|
|
|
|
.each(function() {
|
|
|
|
var $column = $(this),
|
|
|
|
padding = parseInt($column.css('padding-right'), 10) + 10; // 10 is 1/2 of the 20px wide resizer
|
|
|
|
$column
|
|
|
|
.find('.' + ts.css.wrapper)
|
|
|
|
.append('<div class="' + ts.css.resizer + '" style="cursor:w-resize;position:absolute;z-index:1;right:-' +
|
|
|
|
padding + 'px;top:0;height:100%;width:20px;"></div>');
|
|
|
|
})
|
|
|
|
.find('.' + ts.css.resizer)
|
|
|
|
.bind('mousedown', function(event) {
|
|
|
|
// save header cell and mouse position
|
|
|
|
$target = $(event.target).closest('th');
|
2015-02-27 20:26:16 +00:00
|
|
|
var $header = c.$headers.filter('[data-column="' + $target.attr('data-column') + '"]');
|
2015-02-13 03:10:38 +00:00
|
|
|
if ($header.length > 1) { $target = $target.add($header); }
|
|
|
|
// if table is not as wide as it's parent, then resize the table
|
|
|
|
$next = event.shiftKey ? $target.parent().find('th').not('.resizable-false').filter(':last') : $target.nextAll(':not(.resizable-false)').eq(0);
|
|
|
|
mouseXPosition = event.pageX;
|
|
|
|
});
|
|
|
|
$(document)
|
|
|
|
.bind('mousemove.tsresize', function(event) {
|
|
|
|
// ignore mousemove if no mousedown
|
|
|
|
if (mouseXPosition === 0 || !$target) { return; }
|
|
|
|
if (wo.resizable_throttle) {
|
|
|
|
clearTimeout(timer);
|
|
|
|
timer = setTimeout(function(){
|
|
|
|
mouseMove(event);
|
|
|
|
}, isNaN(wo.resizable_throttle) ? 5 : wo.resizable_throttle );
|
|
|
|
} else {
|
|
|
|
mouseMove(event);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.bind('mouseup.tsresize', function() {
|
|
|
|
stopResize();
|
|
|
|
});
|
|
|
|
|
|
|
|
// right click to reset columns to default widths
|
|
|
|
$table.find('thead:first').bind('contextmenu.tsresize', function() {
|
|
|
|
ts.resizableReset(table);
|
|
|
|
// $.isEmptyObject() needs jQuery 1.4+; allow right click if already reset
|
|
|
|
var allowClick = $.isEmptyObject ? $.isEmptyObject(storedSizes) : true;
|
|
|
|
storedSizes = {};
|
|
|
|
return allowClick;
|
|
|
|
});
|
|
|
|
},
|
|
|
|
remove: function(table, c) {
|
|
|
|
c.$table
|
|
|
|
.removeClass('hasResizable')
|
|
|
|
.children('thead')
|
|
|
|
.unbind('mouseup.tsresize mouseleave.tsresize contextmenu.tsresize')
|
|
|
|
.children('tr').children()
|
|
|
|
.unbind('mousemove.tsresize mouseup.tsresize')
|
|
|
|
// don't remove "tablesorter-wrapper" as uitheme uses it too
|
|
|
|
.find('.' + ts.css.resizer).remove();
|
|
|
|
ts.resizableReset(table);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
ts.resizableReset = function(table, nosave) {
|
|
|
|
$(table).each(function(){
|
|
|
|
var $t,
|
|
|
|
c = this.config,
|
|
|
|
wo = c && c.widgetOptions;
|
|
|
|
if (table && c) {
|
|
|
|
c.$headers.each(function(i){
|
|
|
|
$t = $(this);
|
|
|
|
if (wo.resizable_widths && wo.resizable_widths[i]) {
|
|
|
|
$t.css('width', wo.resizable_widths[i]);
|
|
|
|
} else if (!$t.hasClass('resizable-false')) {
|
|
|
|
// don't clear the width of any column that is not resizable
|
|
|
|
$t.css('width','');
|
|
|
|
}
|
|
|
|
});
|
|
|
|
if (ts.storage && !nosave) { ts.storage(this, 'tablesorter-resizable', {}); }
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
})(jQuery, window);
|