From 94ffc9adeaea95e146bd480392aa58835b1f5bc1 Mon Sep 17 00:00:00 2001 From: hiddes Date: Fri, 28 Feb 2014 14:42:23 +0700 Subject: [PATCH] FIXED ISSUE #109 Collapsed header column wrong width fix --- demo/test.html | 5 +- jquery.fixedheadertable.js | 234 +++++++++++++++++++++++++++------ jquery.fixedheadertable.min.js | 2 +- 3 files changed, 201 insertions(+), 40 deletions(-) diff --git a/demo/test.html b/demo/test.html index f5856db..6b701d6 100644 --- a/demo/test.html +++ b/demo/test.html @@ -186,7 +186,10 @@ - + + + + diff --git a/jquery.fixedheadertable.js b/jquery.fixedheadertable.js index 1d052d8..a6b4fc5 100644 --- a/jquery.fixedheadertable.js +++ b/jquery.fixedheadertable.js @@ -561,26 +561,16 @@ tbody: {}, tfoot: {}, border: 0 - }, - borderCollapse = 1; + }; - if (settings.borderCollapse == true) { - borderCollapse = 2; - } + tableProp.border = ($obj.find('th:first-child').outerWidth() - $obj.find('th:first-child').innerWidth()) + / settings.borderCollapse ? 2 : 1; - tableProp.border = ($obj.find('th:first-child').outerWidth() - $obj.find('th:first-child').innerWidth()) / borderCollapse; + tableProp.thead = helpers._getColumnsWidth($obj.find('thead').children('tr')); - $obj.find('thead tr:first-child > *').each(function(index) { - tableProp.thead[index] = $(this).width() + tableProp.border; - }); + tableProp.tfoot = helpers._getColumnsWidth($obj.find('tfoot').children('tr')); - $obj.find('tfoot tr:first-child > *').each(function(index) { - tableProp.tfoot[index] = $(this).width() + tableProp.border; - }); - - $obj.find('tbody tr:first-child > *').each(function(index) { - tableProp.tbody[index] = $(this).width() + tableProp.border; - }); + tableProp.tbody = helpers._getColumnsWidth($obj.find('tbody').children('tr')); return tableProp; }, @@ -590,32 +580,200 @@ * Fix widths of each cell in the first row of obj. */ _setupClone: function($obj, cellArray) { - var $self = $obj, - selector = ($self.find('thead').length) ? - 'thead tr:first-child > *' : - ($self.find('tfoot').length) ? - 'tfoot tr:first-child > *' : - 'tbody tr:first-child > *', - $cell; - - $self.find(selector).each(function(index) { - $cell = ($(this).find('div.fht-cell').length) ? $(this).find('div.fht-cell') : $('
').appendTo($(this)); - - $cell.css({ - 'width': parseInt(cellArray[index], 10) + var selector = ($obj.find('thead').length) + ? 'thead tr' + : ($obj.find('tfoot').length) + ? 'tfoot tr' + : 'tbody tr'; + + helpers._trCellIterator( + $obj.find(selector), + { + cell: function(context) { + if (typeof cellArray[context.colIndex] !== 'undefined' + && cellArray[context.colIndex].colspan == context.colspan + ) { + + var $cell = ($(this).find('div.fht-cell').length) + ? $(this).find('div.fht-cell') + : $('
').appendTo($(this)); + + $cell.css({ + 'width': parseInt(cellArray[context.colIndex].width, 10) + }); + + /* + * Fixed Header and Footer should extend the full width + * to align with the scrollbar of the body + */ + if (!$(this).closest('.fht-tbody').length && $(this).is(':last-child') + && !$(this).closest('.fht-fixed-column').length + ) { + var padding = Math.max((($(this).innerWidth() - $(this).width()) / 2), settings.scrollbarOffset); + $(this).css({ + 'padding-right': parseInt($(this).css('padding-right')) + padding + 'px' + }); + } + } + } + } + ); + }, + + /* + * return object + * Iterates over cells within given set of rows + * Using: + * _trCellIterator( + * $('#table tr'), + * { + * beforeRow: function(context){ + * context.rowCount++; + * //return true; // breaks row iteration + * }, + * cell: function(context){ + * context.cellCount += context.colspan; + * //return true; // breaks current row cell iteration + * }, + * afterRow: function(context){ + * if (context.rowCount > 2) { + * return true; // breaks row iteration + * } + * }, + * }, + * { + * rowCount: 0, + * cellCount: 0 + * } + * ); + */ + _trCellIterator: function($trs, callbacks, context) { + var rowspanData = {}; + + if (typeof callbacks === "undefined") { + callbacks = {}; + } + if (typeof context === "undefined") { + context = {}; + } + + $trs.each(function(rowIndex) { + var colspanShift = 0, + rowspanShift = 0, + ret; + + context.rowIndex = rowIndex; + + if (typeof callbacks.beforeRow === 'function') { + if (ret = callbacks.beforeRow.call(this, context)) { + return false; // break + } + } + + $(this).children().each(function(colIndex) { + var colspan = parseInt($(this).attr('colspan')) || 1, + rowspan = parseInt($(this).attr('rowspan')) || 1; + + while (typeof rowspanData[colIndex + rowspanShift] !== "undefined" + && rowspanData[colIndex + rowspanShift].rowspan > 1 + ) { + rowspanData[colIndex + rowspanShift].rowspan--; + rowspanShift += rowspanData[colIndex].colspan; + } + + colIndex += (colspanShift + rowspanShift); + + colspanShift += colspan - 1; + if (rowspan > 1) { + rowspanData[colIndex] = { + rowspan: rowspan, + colspan: colspan + }; + } + + context.colIndex = colIndex; + context.colspan = colspan; + context.rowspan = rowspan; + + if (typeof callbacks.cell === 'function') { + if (ret = callbacks.cell.call(this, context)) { + return false; // break + } + } }); - /* - * Fixed Header and Footer should extend the full width - * to align with the scrollbar of the body - */ - if (!$(this).closest('.fht-tbody').length && $(this).is(':last-child') && !$(this).closest('.fht-fixed-column').length) { - var padding = Math.max((($(this).innerWidth() - $(this).width()) / 2), settings.scrollbarOffset); - $(this).css({ - 'padding-right': parseInt($(this).css('padding-right')) + padding + 'px' - }); + if (typeof callbacks.afterRow === 'function') { + if (ret = callbacks.afterRow.call(this, context)) { + return false; // break + } } }); + + return context; + }, + + /** + * return int + * Calculates columns count within given set of rows + */ + _getColumnsCount: function($trs) { + var ret = helpers._trCellIterator( + $trs, + { + cell: function(context) { + context.count += context.colspan; + }, + afterRow: function(context) { + if (context.count > 1 || context.rowspan == 1) { + return true; + } + } + }, + { + count: 0 + } + ); + + return ret.count; + }, + + /* + * return object + * Calculates columns width within given set of rows + */ + _getColumnsWidth: function($trs) { + var ret = helpers._trCellIterator( + $trs, + { + cell: function(context) { + if (typeof context.result[context.colIndex] === 'undefined' + || context.result[context.colIndex].colspan > 1) { + var border = parseFloat($(this).outerWidth() - $(this).innerWidth()) + / (settings.borderCollapse ? 2 : 1); + context.result[context.colIndex] = { + width: $(this).width() + border, + colspan: context.colspan + }; + + if (context.colspan == 1) { + context.definedWidthCount++; + } + } + }, + afterRow: function(context) { + if (context.definedWidthCount == context.columnsCount) { + return true; // break + } + } + }, + { + result: {}, + definedWidthCount: 0, + columnsCount: helpers._getColumnsCount($trs) + } + ); + + return ret.result; }, /* diff --git a/jquery.fixedheadertable.min.js b/jquery.fixedheadertable.min.js index 6c8a9ef..11132c4 100644 --- a/jquery.fixedheadertable.min.js +++ b/jquery.fixedheadertable.min.js @@ -16,5 +16,5 @@ * * * all CSS sizing (width,height) is done in pixels (px) - */(function(c){c.fn.fixedHeaderTable=function(m){var u={width:"100%",height:"100%",themeClass:"fht-default",borderCollapse:!0,fixedColumns:0,fixedColumn:!1,sortable:!1,autoShow:!0,footer:!1,cloneHeadToFoot:!1,autoResize:!1,create:null},b={},n={init:function(a){b=c.extend({},u,a);return this.each(function(){var a=c(this);h._isTable(a)?(n.setup.apply(this,Array.prototype.slice.call(arguments,1)),c.isFunction(b.create)&&b.create.call(this)):c.error("Invalid table mark-up")})},setup:function(){var a=c(this), d=a.find("thead"),e=a.find("tfoot"),g=0,f,k,p;b.originalTable=c(this).clone();b.includePadding=h._isPaddingIncludedWithWidth();b.scrollbarOffset=h._getScrollbarWidth();b.themeClassName=b.themeClass;f=-1'));f=a.closest(".fht-table-wrapper");!0==b.fixedColumn&&0>=b.fixedColumns&&(b.fixedColumns= 1);0'),c('
').prependTo(f),k=f.find(".fht-fixed-body"));f.css({width:b.width,height:b.height}).addClass(b.themeClassName);a.hasClass("fht-table-init")||a.wrap('
');p=a.closest(".fht-tbody");var l=h._getTableProps(a);h._setupClone(p,l.tbody);a.hasClass("fht-table-init")?k=f.find("div.fht-thead"):(k=0
BrowserBrowserThis is merged column
Visits Pages/Visit Avg. Time on Site
').prependTo(k): c('
').prependTo(f),k.find("table.fht-table").addClass(b.originalTable.attr("class")).attr("style",b.originalTable.attr("style")),d.clone().appendTo(k.find("table")));h._setupClone(k,l.thead);a.css({"margin-top":-k.outerHeight(!0)});!0==b.footer&&(h._setupTableFooter(a,this,l),e.length||(e=f.find("div.fht-tfoot table")),g=e.outerHeight(!0));d=f.height()-d.outerHeight(!0)-g-l.border;p.css({height:d});a.addClass("fht-table-init");"undefined"!== typeof b.altClass&&n.altRows.apply(this);0
'),p=c('
');a=c('
'); var g=g.width(),l=f.find(".fht-tbody").height()-b.scrollbarOffset,q,t,r,s;k.find("table.fht-table").addClass(b.originalTable.attr("class"));p.find("table.fht-table").addClass(b.originalTable.attr("class"));a.find("table.fht-table").addClass(b.originalTable.attr("class"));q=f.find(".fht-thead thead tr > *:lt("+b.fixedColumns+")");r=b.fixedColumns*e.border;q.each(function(){r+=c(this).outerWidth(!0)});h._fixHeightWithCss(q,e);h._fixWidthWithCss(q,e);var m=[];q.each(function(){m.push(c(this).width())}); t=f.find("tbody tr > *:not(:nth-child(n+"+(b.fixedColumns+1)+"))").each(function(a){h._fixHeightWithCss(c(this),e);h._fixWidthWithCss(c(this),e,m[a%b.fixedColumns])});k.appendTo(d).find("tr").append(q.clone());p.appendTo(d).css({"margin-top":-1,height:l+e.border});t.each(function(a){0==a%b.fixedColumns&&(s=c("").appendTo(p.find("tbody")),b.altClass&&c(this).parent().hasClass(b.altClass)&&s.addClass(b.altClass));c(this).clone().appendTo(s)});d.css({height:0,width:r});var n=d.find(".fht-tbody .fht-table").height()- d.find(".fht-tbody").height();d.find(".fht-tbody .fht-table").bind("mousewheel",function(a,d,b,e){if(0!=e)return a=parseInt(c(this).css("marginTop"),10)+(0 *:lt("+b.fixedColumns+")"),h._fixHeightWithCss(k,e),a.appendTo(d).find("tr").append(k.clone()),d=a.find("table").innerWidth(),a.css({top:b.scrollbarOffset, width:d})},_setupTableFooter:function(a,d,e){d=a.closest(".fht-table-wrapper");var g=a.find("tfoot");a=d.find("div.fht-tfoot");a.length||(a=0
').appendTo(d.find(".fht-fixed-body")):c('
').appendTo(d));a.find("table.fht-table").addClass(b.originalTable.attr("class"));switch(!0){case !g.length&&!0==b.cloneHeadToFoot&&!0==b.footer:e=d.find("div.fht-thead");a.empty(); e.find("table").clone().appendTo(a);break;case g.length&&!1==b.cloneHeadToFoot&&!0==b.footer:a.find("table").append(g).css({"margin-top":-e.border}),h._setupClone(a,e.tfoot)}},_getTableProps:function(a){var d={thead:{},tbody:{},tfoot:{},border:0},c=1;!0==b.borderCollapse&&(c=2);d.border=(a.find("th:first-child").outerWidth()-a.find("th:first-child").innerWidth())/c;d.thead=h._getColumnsWidth(a.find("thead tr"));d.tfoot=h._getColumnsWidth(a.find("tfoot tr"));d.tbody=h._getColumnsWidth(a.find("tbody tr")); return d},_getColumnsWidth:function(a){var d={},b={},g=0,f,k;f=h._getColumnsCount(a);for(k=0;k').appendTo(c(this))).css({width:parseInt(d[a].width,10)}),c(this).closest(".fht-tbody").length||!c(this).is(":last-child")||c(this).closest(".fht-fixed-column").length|| (a=Math.max((c(this).innerWidth()-c(this).width())/2,b.scrollbarOffset),c(this).css({"padding-right":parseInt(c(this).css("padding-right"))+a+"px"})))})})},_isPaddingIncludedWithWidth:function(){var a=c('
test
'),d,e;a.addClass(b.originalTable.attr("class"));a.appendTo("body");d=a.find("td").height();a.find("td").css("height",a.find("tr").height());e=a.find("td").height();a.remove();return d!=e?!0:!1},_getScrollbarWidth:function(){var a= 0;if(!a)if(/msie/.test(navigator.userAgent.toLowerCase())){var b=c('').css({position:"absolute",top:-1E3,left:-1E3}).appendTo("body"),e=c('').css({position:"absolute",top:-1E3,left:-1E3}).appendTo("body"),a=b.width()-e.width()+2;b.add(e).remove()}else b=c("
").css({width:100,height:100,overflow:"auto",position:"absolute",top:-1E3,left:-1E3}).prependTo("body").append("
").find("div").css({width:"100%", height:200}),a=100-b.width(),b.parent().remove();return a}};if(n[m])return n[m].apply(this,Array.prototype.slice.call(arguments,1));if("object"!==typeof m&&m)c.error('Method "'+m+'" does not exist in fixedHeaderTable plugin!');else return n.init.apply(this,arguments)}})(jQuery); + */(function(d){d.fn.fixedHeaderTable=function(l){var u={width:"100%",height:"100%",themeClass:"fht-default",borderCollapse:!0,fixedColumns:0,fixedColumn:!1,sortable:!1,autoShow:!0,footer:!1,cloneHeadToFoot:!1,autoResize:!1,create:null},b={},n={init:function(a){b=d.extend({},u,a);return this.each(function(){var a=d(this);g._isTable(a)?(n.setup.apply(this,Array.prototype.slice.call(arguments,1)),d.isFunction(b.create)&&b.create.call(this)):d.error("Invalid table mark-up")})},setup:function(){var a=d(this), c=a.find("thead"),e=a.find("tfoot"),h=0,f,m,k;b.originalTable=d(this).clone();b.includePadding=g._isPaddingIncludedWithWidth();b.scrollbarOffset=g._getScrollbarWidth();b.themeClassName=b.themeClass;f=-1
'));f=a.closest(".fht-table-wrapper");!0==b.fixedColumn&&0>=b.fixedColumns&&(b.fixedColumns= 1);0
'),d('
').prependTo(f),m=f.find(".fht-fixed-body"));f.css({width:b.width,height:b.height}).addClass(b.themeClassName);a.hasClass("fht-table-init")||a.wrap('
');k=a.closest(".fht-tbody");var p=g._getTableProps(a);g._setupClone(k,p.tbody);a.hasClass("fht-table-init")?m=f.find("div.fht-thead"):(m=0
').prependTo(m): d('
').prependTo(f),m.find("table.fht-table").addClass(b.originalTable.attr("class")).attr("style",b.originalTable.attr("style")),c.clone().appendTo(m.find("table")));g._setupClone(m,p.thead);a.css({"margin-top":-m.outerHeight(!0)});!0==b.footer&&(g._setupTableFooter(a,this,p),e.length||(e=f.find("div.fht-tfoot table")),h=e.outerHeight(!0));c=f.height()-c.outerHeight(!0)-h-p.border;k.css({height:c});a.addClass("fht-table-init");"undefined"!== typeof b.altClass&&n.altRows.apply(this);0
'),k=d('
'); a=d('
');var h=h.width(),p=f.find(".fht-tbody").height()-b.scrollbarOffset,q,r,l,n;m.find("table.fht-table").addClass(b.originalTable.attr("class"));k.find("table.fht-table").addClass(b.originalTable.attr("class"));a.find("table.fht-table").addClass(b.originalTable.attr("class"));q=f.find(".fht-thead thead tr > *:lt("+b.fixedColumns+")");l=b.fixedColumns*e.border;q.each(function(){l+=d(this).outerWidth(!0)});g._fixHeightWithCss(q, e);g._fixWidthWithCss(q,e);var s=[];q.each(function(){s.push(d(this).width())});r=f.find("tbody tr > *:not(:nth-child(n+"+(b.fixedColumns+1)+"))").each(function(a){g._fixHeightWithCss(d(this),e);g._fixWidthWithCss(d(this),e,s[a%b.fixedColumns])});m.appendTo(c).find("tr").append(q.clone());k.appendTo(c).css({"margin-top":-1,height:p+e.border});r.each(function(a){0==a%b.fixedColumns&&(n=d("").appendTo(k.find("tbody")),b.altClass&&d(this).parent().hasClass(b.altClass)&&n.addClass(b.altClass)); d(this).clone().appendTo(n)});c.css({height:0,width:l});var t=c.find(".fht-tbody .fht-table").height()-c.find(".fht-tbody").height();c.find(".fht-tbody .fht-table").bind("mousewheel",function(a,c,b,e){if(0!=e)return a=parseInt(d(this).css("marginTop"),10)+(0 *:lt("+b.fixedColumns+")"),g._fixHeightWithCss(m, e),a.appendTo(c).find("tr").append(m.clone()),c=a.find("table").innerWidth(),a.css({top:b.scrollbarOffset,width:c})},_setupTableFooter:function(a,c,e){c=a.closest(".fht-table-wrapper");var h=a.find("tfoot");a=c.find("div.fht-tfoot");a.length||(a=0
').appendTo(c.find(".fht-fixed-body")):d('
').appendTo(c));a.find("table.fht-table").addClass(b.originalTable.attr("class")); switch(!0){case !h.length&&!0==b.cloneHeadToFoot&&!0==b.footer:e=c.find("div.fht-thead");a.empty();e.find("table").clone().appendTo(a);break;case h.length&&!1==b.cloneHeadToFoot&&!0==b.footer:a.find("table").append(h).css({"margin-top":-e.border}),g._setupClone(a,e.tfoot)}},_getTableProps:function(a){var c={thead:{},tbody:{},tfoot:{},border:0};c.border=(a.find("th:first-child").outerWidth()-a.find("th:first-child").innerWidth())/b.borderCollapse?2:1;c.thead=g._getColumnsWidth(a.find("thead").children("tr")); c.tfoot=g._getColumnsWidth(a.find("tfoot").children("tr"));c.tbody=g._getColumnsWidth(a.find("tbody").children("tr"));return c},_setupClone:function(a,c){var e=a.find("thead").length?"thead tr":a.find("tfoot").length?"tfoot tr":"tbody tr";g._trCellIterator(a.find(e),{cell:function(a){"undefined"!==typeof c[a.colIndex]&&c[a.colIndex].colspan==a.colspan&&((d(this).find("div.fht-cell").length?d(this).find("div.fht-cell"):d('
').appendTo(d(this))).css({width:parseInt(c[a.colIndex].width, 10)}),d(this).closest(".fht-tbody").length||!d(this).is(":last-child")||d(this).closest(".fht-fixed-column").length||(a=Math.max((d(this).innerWidth()-d(this).width())/2,b.scrollbarOffset),d(this).css({"padding-right":parseInt(d(this).css("padding-right"))+a+"px"})))}})},_trCellIterator:function(a,c,b){var h={};"undefined"===typeof c&&(c={});"undefined"===typeof b&&(b={});a.each(function(a){var g=0,k=0;b.rowIndex=a;if("function"===typeof c.beforeRow&&c.beforeRow.call(this,b))return!1;d(this).children().each(function(a){for(var f= parseInt(d(this).attr("colspan"))||1,l=parseInt(d(this).attr("rowspan"))||1;"undefined"!==typeof h[a+k]&&1test'),c,e;a.addClass(b.originalTable.attr("class"));a.appendTo("body");c=a.find("td").height();a.find("td").css("height",a.find("tr").height());e=a.find("td").height();a.remove();return c!=e?!0:!1},_getScrollbarWidth:function(){var a=0;if(!a)if(/msie/.test(navigator.userAgent.toLowerCase())){var b=d('').css({position:"absolute", top:-1E3,left:-1E3}).appendTo("body"),e=d('').css({position:"absolute",top:-1E3,left:-1E3}).appendTo("body"),a=b.width()-e.width()+2;b.add(e).remove()}else b=d("
").css({width:100,height:100,overflow:"auto",position:"absolute",top:-1E3,left:-1E3}).prependTo("body").append("
").find("div").css({width:"100%",height:200}),a=100-b.width(),b.parent().remove();return a}};if(n[l])return n[l].apply(this,Array.prototype.slice.call(arguments, 1));if("object"!==typeof l&&l)d.error('Method "'+l+'" does not exist in fixedHeaderTable plugin!');else return n.init.apply(this,arguments)}})(jQuery);