From dcb6733d7255dee279261ff89b6eecd0fc84bd5b Mon Sep 17 00:00:00 2001 From: chprpipr Date: Wed, 3 Aug 2011 17:51:02 -0700 Subject: [PATCH] Sorry for the reworked formatting. There are a few nuggets in this check in that I think are worthwhile: - Takes colspans into account - Clones and hides the original THEAD and TFOOT rather than removing them. This helps to preserve column alignment - Inserts TH/TD elements to account for addition of scroll bar (preserves column alignment, particularly if the column is right justified - Adds a window.resize event handler to update the table's display if the window changes dimensions. --- jquery.tablescroll.js | 167 +++++++++++++++++++++++++++++------------- 1 file changed, 115 insertions(+), 52 deletions(-) diff --git a/jquery.tablescroll.js b/jquery.tablescroll.js index c9db760..245c229 100644 --- a/jquery.tablescroll.js +++ b/jquery.tablescroll.js @@ -29,52 +29,20 @@ OTHER DEALINGS IN THE SOFTWARE. */ ;(function($){ - - var scrollbarWidth = 0; - - // http://jdsharp.us/jQuery/minute/calculate-scrollbar-width.php - function getScrollbarWidth() - { - if (scrollbarWidth) return scrollbarWidth; - var div = $('
'); - $('body').append(div); - var w1 = $('div', div).innerWidth(); - div.css('overflow-y', 'auto'); - var w2 = $('div', div).innerWidth(); - $(div).remove(); - scrollbarWidth = (w1 - w2); - return scrollbarWidth; - } $.fn.tableScroll = function(options) { - if (options == 'undo') - { - var container = $(this).parent().parent(); - if (container.hasClass('tablescroll_wrapper')) - { - container.find('.tablescroll_head thead').prependTo(this); - container.find('.tablescroll_foot tfoot').appendTo(this); - container.before(this); - container.empty(); - } - return; - } + var Me = this; + var timeoutHandle; + + this.scrollbarWidth = 0; - var settings = $.extend({},$.fn.tableScroll.defaults,options); - - // Bail out if there's no vertical overflow - //if ($(this).height() <= settings.height) - //{ - // return this; - //} - - settings.scrollbarWidth = getScrollbarWidth(); - - this.each(function() + this.FormatTable = function() { var flush = settings.flush; + var originalClass = $(this).attr("class"); + var tb = $(this).addClass('tablescroll_body'); var wrapper = $('
').insertBefore(tb).append(tb); @@ -101,7 +69,7 @@ OTHER DEALINGS IN THE SOFTWARE. var diff = wrapper_width-width; // assume table will scroll - wrapper.css({width:((width-diff)+settings.scrollbarWidth)+'px'}); + wrapper.css({width:((width-diff)+Me.scrollbarWidth)+'px'}); tb.css('width',(width-diff)+'px'); if (tb.outerHeight() <= settings.height) @@ -121,26 +89,62 @@ OTHER DEALINGS IN THE SOFTWARE. var tbody_tr_first = $('tbody tr:first',tb); var tfoot_tr_first = $('tfoot tr:first',tb); - // remember width of last cell - var w = 0; - + // Record cell widths + // Shoud colspan > 1, evenly distribute width among grouped cells + var aWidths = []; $('th, td',thead_tr_first).each(function(i) { - w = $(this).width(); + var jCell = $(this); + var colspan = jCell.attr('colspan') || 1; + var colspanIterator = colspan; + var avgWidth = jCell.width()/colspan; + while (colspanIterator) { + aWidths.push(avgWidth); + colspanIterator--; + } - $('th:eq('+i+'), td:eq('+i+')',thead_tr_first).css('width',w+'px'); - $('th:eq('+i+'), td:eq('+i+')',tbody_tr_first).css('width',w+'px'); - if (has_tfoot) $('th:eq('+i+'), td:eq('+i+')',tfoot_tr_first).css('width',w+'px'); }); + // Explicitly set width of header cells + function SetCellWidths(_selector, _base, _aCellWidths) { + var cellIdx = 0; + var w = 0; + $(_selector, _base).each(function(i) { + var jCell = $(this); + var colspan = jCell.attr('colspan') || 1; + var w = 0; + while (colspan) { + w += _aCellWidths[cellIdx]; + cellIdx++; + colspan--; + } + jCell.width(w); + }); + } + + SetCellWidths("th, td", thead_tr_first, aWidths); + SetCellWidths("th, td", tbody_tr_first, aWidths); + if (has_tfoot) SetCellWidths("th, td", tfoot_tr_first, aWidths); + if (has_thead) { - var tbh = $('
').insertBefore(wrapper).prepend($('thead',tb)); + var thead = $('thead',tb); + var tbh = $('
') + .insertBefore(wrapper) + .css({'margin-bottom':'0'}) + .prepend(thead.clone()); + tb.css({'table-layout':'fixed'}); + thead.hide(); } if (has_tfoot) { - var tbf = $('
').insertAfter(wrapper).prepend($('tfoot',tb)); + var tfoot = $('tfoot',tb); + var tbf = $('
') + .insertAfter(wrapper) + .css({'margin-top':'0'}) + .prepend(tfoot.clone()); + tfoot.hide(); } if (tbh != undefined) @@ -149,7 +153,10 @@ OTHER DEALINGS IN THE SOFTWARE. if (flush) { - $('tr:first th:last, tr:first td:last',tbh).css('width',(w+settings.scrollbarWidth)+'px'); + $('tr:first', tbh).append($('').css({ + 'width': Me.scrollbarWidth + 'px' + , 'padding': 0 + })); tbh.css('width',wrapper.outerWidth() + 'px'); } } @@ -160,11 +167,67 @@ OTHER DEALINGS IN THE SOFTWARE. if (flush) { - $('tr:first th:last, tr:first td:last',tbf).css('width',(w+settings.scrollbarWidth)+'px'); + $('tr:first', tbf).append($('').css({ + 'width': Me.scrollbarWidth + 'px' + , 'padding': 0 + })); tbf.css('width',wrapper.outerWidth() + 'px'); } } - }); + }; + + this.UndoFormatTable = function() { + var jThis = $(this); + var container = jThis.parents("div.tablescroll"); + if (container.length > 0) + { + container.before(this); + container.empty(); + jThis.removeAttr("style"); + jThis.find("thead, tfoot").show(); + } + return; + } + + // http://jdsharp.us/jQuery/minute/calculate-scrollbar-width.php + this.GetScrollbarWidth = function() { + if (Me.scrollbarWidth) return Me.scrollbarWidth; + var div = $('
'); + $('body').append(div); + var w1 = $('div', div).innerWidth(); + div.css('overflow-y', 'auto'); + var w2 = $('div', div).innerWidth(); + $(div).remove(); + Me.scrollbarWidth = (w1 - w2); + } + + // ----------------------------------------------------------------------------- + if (options == 'undo') { + Me.UndoFormatTable(); + } + + var settings = $.extend({}, $.fn.tableScroll.defaults, options); + + // Bail out if there's no vertical overflow + //if ($(this).height() <= settings.height) + //{ + // return this; + //} + + // Calculate scrollbar width and save for later + Me.GetScrollbarWidth(); + + // Apply formatting to each table + this.each(Me.FormatTable); + + // Setup window.resize event handler + $(window).unbind("resize.tableScroll").bind("resize.tableScroll", function() { + clearTimeout(Me.timeoutHandle); + Me.timeoutHandle = setTimeout(function() { + Me.each(Me.UndoFormatTable); + Me.each(Me.FormatTable); + }, 300); + }); return this; };