diff --git a/dist/jquery.floatThead-slim.js b/dist/jquery.floatThead-slim.js index f88c4fa..b515b1d 100644 --- a/dist/jquery.floatThead-slim.js +++ b/dist/jquery.floatThead-slim.js @@ -94,6 +94,12 @@ window && window.console && window.console.log && window.console.log("jQuery.floatThead: " + str); } + //returns fractional pixel widths + function getOffsetWidth(el) { + var rect = el.getBoundingClientRect(); + return rect.right - rect.left; + } + /** * try to calculate the scrollbar width for your browser/os * @return {Number} @@ -439,6 +445,14 @@ $table.css('minWidth', tableWidth($table, $fthCells)); //#121 } } + var isHeaderFloatingLogical = false; //for the purpose of this event, the header is/isnt floating, even though the element + //might be in some other state. this is what the header looks like to the user + function triggerFloatEvent(isFloating){ + if(isHeaderFloatingLogical != isFloating){ + isHeaderFloatingLogical = isFloating; + $table.triggerHandler("floatThead", [isFloating, $floatContainer]) + } + } function changePositioning(isAbsolute){ if(useAbsolutePositioning != isAbsolute){ useAbsolutePositioning = isAbsolute; @@ -478,7 +492,7 @@ unfloat(); var widths = []; for(i=0; i < numCols; i++){ - widths[i] = $rowCells.get(i).offsetWidth; + widths[i] = getOffsetWidth($rowCells.get(i)); } for(i=0; i < numCols; i++){ $headerCells.eq(i).width(widths[i]); @@ -542,7 +556,7 @@ if(!isTableHidden && floatTableHidden) { floatTableHidden = false; setTimeout(function(){ - $table.trigger("reflow"); + $table.triggerHandler("reflow"); }, 1); return null; } @@ -579,7 +593,7 @@ return null; //event is fired when they stop scrolling. ignore it if not 'absoluteToFixedOnScroll' } - tableOffset = $table.offset(); + tableOffset = $table[0].getBoundingClientRect(); if(haveCaption && captionAlignTop){ tableOffset.top += captionHeight; } @@ -590,45 +604,53 @@ if (tableContainerGap >= scrollingContainerTop) { var gap = tableContainerGap - scrollingContainerTop; top = gap > 0 ? gap : 0; + triggerFloatEvent(false); } else { top = wrappedContainer ? 0 : scrollingContainerTop; //headers stop at the top of the viewport + triggerFloatEvent(true); } left = tableLeftGap; } else if(!locked && useAbsolutePositioning) { //window scrolling, absolute positioning if(windowTop > floatEnd + tableHeight + captionScrollOffset){ top = tableHeight - floatContainerHeight + captionScrollOffset; //scrolled past table - } else if (tableOffset.top > windowTop + scrollingTop) { + } else if (tableOffset.top > scrollingTop) { top = 0; //scrolling to table unfloat(); + triggerFloatEvent(false); } else { - top = scrollingTop + windowTop - tableOffset.top + tableContainerGap + (captionAlignTop ? captionHeight : 0); + top = scrollingTop - tableOffset.top + tableContainerGap + (captionAlignTop ? captionHeight : 0); refloat(); //scrolling within table. header floated + triggerFloatEvent(true); } left = 0; } else if(locked && !useAbsolutePositioning){ //inner scrolling, fixed positioning if (tableContainerGap > scrollingContainerTop || scrollingContainerTop - tableContainerGap > tableHeight) { - top = tableOffset.top - windowTop; + top = tableOffset.top; unfloat(); + triggerFloatEvent(false); } else { - top = tableOffset.top + scrollingContainerTop - windowTop - tableContainerGap; + top = tableOffset.top + scrollingContainerTop - tableContainerGap; refloat(); + triggerFloatEvent(true); //headers stop at the top of the viewport } - left = tableOffset.left + scrollContainerLeft - windowLeft; + left = tableOffset.left + scrollContainerLeft; } else if(!locked && !useAbsolutePositioning) { //window scrolling, fixed positioning if(windowTop > floatEnd + tableHeight + captionScrollOffset){ top = tableHeight + scrollingTop - windowTop + floatEnd + captionScrollOffset; //scrolled past the bottom of the table - } else if (tableOffset.top > windowTop + scrollingTop) { - top = tableOffset.top - windowTop; + } else if (tableOffset.top > scrollingTop) { + top = tableOffset.top; refloat(); + triggerFloatEvent(false); //this is a weird case, the header never gets unfloated and i have no no way to know //scrolled past the top of the table } else { //scrolling within the table top = scrollingTop; + triggerFloatEvent(true); } - left = tableOffset.left - windowLeft; + left = tableOffset.left; } return {top: top, left: left}; }; diff --git a/dist/jquery.floatThead-slim.min.js b/dist/jquery.floatThead-slim.min.js index 0c3d605..59a0f0a 100644 --- a/dist/jquery.floatThead-slim.min.js +++ b/dist/jquery.floatThead-slim.min.js @@ -1,3 +1,3 @@ // @preserve jQuery.floatThead 1.2.12dev - http://mkoryak.github.io/floatThead/ - Copyright (c) 2012 - 2015 Misha Koryak // @license MIT -!function(a){function b(a,b,c){if(8==i){var d=n.width(),e=g.debounce(function(){var a=n.width();d!=a&&(d=a,c())},a);n.on(b,e)}else n.on(b,g.debounce(c,a))}function c(a){window&&window.console&&window.console.log&&window.console.log("jQuery.floatThead: "+a)}function d(){var b=a('
');a("body").append(b);var c=b.innerWidth(),d=a("div",b).innerWidth();return b.remove(),c-d}function e(a){if(a.dataTableSettings)for(var b=0;b*:visible",zIndex:1001,debounceResizeMs:10,useAbsolutePositioning:!0,scrollingTop:0,scrollingBottom:0,scrollContainer:function(){return a([])},getSizingRow:function(a){return a.find("tbody tr:visible:first>*:visible")},floatTableClass:"floatThead-table",floatWrapperClass:"floatThead-wrapper",floatContainerClass:"floatThead-container",copyTableClass:!0,enableAria:!1,autoReflow:!1,debug:!1};var g=window._,h="undefined"!=typeof MutationObserver,i=function(){for(var a=3,b=document.createElement("b"),c=b.all||[];a=1+a,b.innerHTML="",c[0];);return a>4?a:document.documentMode}(),j=/Gecko\//.test(navigator.userAgent),k=/WebKit\//.test(navigator.userAgent),l=function(){if(k){var b=a('
X
');a("body").append(b);var c=0==b.find("table").width();return b.remove(),c}return!1},m=!j&&!i,n=a(window);a.fn.floatThead=function(j){if(j=j||{},!g&&(g=window._||a.floatThead._,!g))throw new Error("jquery.floatThead-slim.js requires underscore. You should use the non-lite version since you do not have underscore.");if(8>i)return this;var o=null;if(g.isFunction(l)&&(l=l()),g.isString(j)){var p=j,q=this;return this.filter("table").each(function(){var b=a(this).data("floatThead-attached");if(b&&g.isFunction(b[p])){var c=b[p]();"undefined"!=typeof c&&(q=c)}}),q}var r=a.extend({},a.floatThead.defaults||{},j);if(a.each(j,function(b){b in a.floatThead.defaults||!r.debug||c("Used ["+b+"] key to init plugin, but that param is not an option for the plugin. Valid options are: "+g.keys(a.floatThead.defaults).join(", "))}),r.debug){var s=a.fn.jquery.split(".");1==parseInt(s[0],10)&&parseInt(s[1],10)<=7&&c("jQuery version "+a.fn.jquery+" detected! This plugin supports 1.8 or better, or 1.7.x with jQuery UI 1.8.24 -> http://jqueryui.com/resources/download/jquery-ui-1.8.24.zip")}return this.filter(":not(."+r.floatTableClass+")").each(function(){function c(a){return a+".fth-"+B+".floatTHead"}function j(){var b=0;D.find("tr:visible").each(function(){b+=a(this).outerHeight(!0)}),bb.outerHeight(b),cb.outerHeight(b)}function l(){var a=f(C,fb,!0),b=L.width()||a,c="hidden"!=L.css("overflow-y")?b-I.vertical:b;if($.width(c),M){var d=100*a/c;V.css("width",d+"%")}else V.outerWidth(a)}function p(){F=(g.isFunction(r.scrollingTop)?r.scrollingTop(C):r.scrollingTop)||0,G=(g.isFunction(r.scrollingBottom)?r.scrollingBottom(C):r.scrollingBottom)||0}function q(){var b,c;if(Y)b=X.find("col").length;else{var d;if(d=null==r.cellTag&&r.headerCellSelector?r.headerCellSelector:"tr:first>"+r.cellTag,g.isNumber(d))return d;c=D.find(d),b=0,c.each(function(){b+=parseInt(a(this).attr("colspan")||1,10)})}if(b!=K){K=b;for(var e,f=[],h=[],i=[],j=0;b>j;j++)f.push(r.enableAria&&(e=c.eq(j).text())?''+e+"":''),h.push(""),i.push("");h=h.join(""),f=f.join(""),m&&(i=i.join(""),Z.html(i),fb=Z.find("fthtd")),bb.html(f),cb=bb.find("th"),Y||X.html(h),db=X.find("col"),W.html(h),eb=W.find("col")}return b}function s(){if(!H){if(H=!0,N){var a=f(C,fb),b=T.width();a>b&&C.css("minWidth",a)}C.css(ib),V.css(ib),V.append(D),E.before(ab),j()}}function t(){H&&(H=!1,N&&C.width(kb),ab.detach(),C.prepend(D),C.css(jb),V.css(jb),C.css("minWidth",lb),C.css("minWidth",f(C,fb)))}function u(a){N!=a&&(N=a,$.css({position:N?"absolute":"fixed"}))}function v(a,b,c,d){return m?c:d?r.getSizingRow(a,b,c):b}function w(){var a,b=q();return function(){db=X.find("col");var c=v(C,db,fb,i);if(c.length==b&&b>0){if(!Y)for(a=0;b>a;a++)db.eq(a).css("width","");t();var d=[];for(a=0;b>a;a++)d[a]=c.get(a).offsetWidth;for(a=0;b>a;a++)eb.eq(a).width(d[a]),db.eq(a).width(d[a]);s()}else V.append(D),C.css(jb),V.css(jb),j()}}function x(a){var b=L.css("border-"+a+"-width"),c=0;return b&&~b.indexOf("px")&&(c=parseInt(b,10)),c}function y(){var a,b=L.scrollTop(),c=0,d=P?O.outerHeight(!0):0,e=Q?d:-d,f=$.height(),g=C.offset(),h=0;if(M){var i=L.offset();c=g.top-i.top+b,P&&Q&&(c+=d),c-=x("top"),h=x("left")}else a=g.top-F-f+G+I.horizontal;var j=n.scrollTop(),l=n.scrollLeft(),m=L.scrollLeft();return b=L.scrollTop(),function(i){var o=C[0].offsetWidth<=0&&C[0].offsetHeight<=0;if(!o&&_)return _=!1,setTimeout(function(){C.trigger("reflow")},1),null;if(o&&(_=!0,!N))return null;if("windowScroll"==i?(j=n.scrollTop(),l=n.scrollLeft()):"containerScroll"==i?(b=L.scrollTop(),m=L.scrollLeft()):"init"!=i&&(j=n.scrollTop(),l=n.scrollLeft(),b=L.scrollTop(),m=L.scrollLeft()),!k||!(0>j||0>l)){if(U)u("windowScrollDone"==i?!0:!1);else if("windowScrollDone"==i)return null;g=C.offset(),P&&Q&&(g.top+=d);var p,q,r=C.outerHeight();if(M&&N){if(c>=b){var v=c-b;p=v>0?v:0}else p=S?0:b;q=h}else!M&&N?(j>a+r+e?p=r-f+e:g.top>j+F?(p=0,t()):(p=F+j-g.top+c+(Q?d:0),s()),q=0):M&&!N?(c>b||b-c>r?(p=g.top-j,t()):(p=g.top+b-j-c,s()),q=g.left+m-l):M||N||(j>a+r+e?p=r+F-j+a+e:g.top>j+F?(p=g.top-j,s()):p=F,q=g.left-l);return{top:p,left:q}}}}function z(){var a=null,b=null,c=null;return function(d,e,f){null==d||a==d.top&&b==d.left||($.css({top:d.top,left:d.left}),a=d.top,b=d.left),e&&l(),f&&j();var g=L.scrollLeft();N&&c==g||($.scrollLeft(g),c=g)}}function A(){if(L.length)if(L.data().perfectScrollbar)I={horizontal:0,vertical:0};else{var a=L.width(),b=L.height(),c=C.height(),d=f(C,fb),e=d>a?J:0,g=c>b?J:0;I.horizontal=d>a-g?J:0,I.vertical=c>b-e?J:0}}var B=g.uniqueId(),C=a(this);if(C.data("floatThead-attached"))return!0;if(!C.is("table"))throw new Error('jQuery.floatThead must be run on a table element. ex: $("table").floatThead();');h=r.autoReflow&&h;var D=C.find("thead:first"),E=C.find("tbody:first");if(0==D.length)throw new Error("jQuery.floatThead must be run on a table that contains a element");var F,G,H=!1,I={vertical:0,horizontal:0},J=d(),K=0,L=r.scrollContainer(C)||a([]),M=L.length>0,N=r.useAbsolutePositioning;null==N&&(N=M),N||(H=!0);var O=C.find("caption"),P=1==O.length;if(P)var Q="top"===(O.css("caption-side")||O.attr("align")||"top");var R=a(''),S=!1,T=a([]),U=9>=i&&!M&&N,V=a(""),W=a(""),X=C.find("colgroup:first"),Y=!0;0==X.length&&(X=a(""),Y=!1);var Z=a(''),$=a(''),_=!1,ab=a(""),bb=a(''),cb=a([]),db=a([]),eb=a([]),fb=a([]);ab.append(bb),C.prepend(X),m&&(R.append(Z),C.append(R)),V.append(W),$.append(V),r.copyTableClass&&V.attr("class",C.attr("class")),V.attr({cellpadding:C.attr("cellpadding"),cellspacing:C.attr("cellspacing"),border:C.attr("border")});var gb=C.css("display");if(V.css({borderCollapse:C.css("borderCollapse"),border:C.css("border"),display:gb}),"none"==gb&&(_=!0),V.addClass(r.floatTableClass).css("margin",0),N){var hb=function(a,b){var c=a.css("position"),d="relative"==c||"absolute"==c;if(!d||b){var e={paddingLeft:a.css("paddingLeft"),paddingRight:a.css("paddingRight")};$.css(e),a=a.wrap("
").parent(),S=!0}return a};M?(T=hb(L,!0),T.append($)):(T=hb(C),C.after($))}else C.after($);$.css({position:N?"absolute":"fixed",marginTop:0,top:N?0:"auto",zIndex:r.zIndex}),$.addClass(r.floatContainerClass),p();var ib={"table-layout":"fixed"},jb={"table-layout":C.css("tableLayout")||"auto"},kb=C[0].style.width||"",lb=C.css("minWidth")||"";A();var mb,nb=function(){(mb=w())()};nb();var ob=y(),pb=z();pb(ob("init"),!0);var qb=g.debounce(function(){pb(ob("windowScrollDone"),!1)},300),rb=function(){pb(ob("windowScroll"),!1),qb()},sb=function(){pb(ob("containerScroll"),!1)},tb=function(){p(),A(),nb(),ob=y(),(pb=z())(ob("resize"),!0,!0)},ub=g.debounce(function(){A(),p(),nb(),ob=y(),pb(ob("reflow"),!0)},1);if(M?N?L.on(c("scroll"),sb):(L.on(c("scroll"),sb),n.on(c("scroll"),rb)):n.on(c("scroll"),rb),n.on(c("load"),ub),b(r.debounceResizeMs,c("resize"),tb),C.on("reflow",ub),e(C)&&C.on("filter",ub).on("sort",ub).on("page",ub),h){var vb=L.length?L[0]:C[0];o=new MutationObserver(function(a){for(var b=function(a){return a&&a[0]&&"THEAD"==a[0].nodeName},c=0;c
');a("body").append(b);var c=b.innerWidth(),d=a("div",b).innerWidth();return b.remove(),c-d}function f(a){if(a.dataTableSettings)for(var b=0;b*:visible",zIndex:1001,debounceResizeMs:10,useAbsolutePositioning:!0,scrollingTop:0,scrollingBottom:0,scrollContainer:function(){return a([])},getSizingRow:function(a){return a.find("tbody tr:visible:first>*:visible")},floatTableClass:"floatThead-table",floatWrapperClass:"floatThead-wrapper",floatContainerClass:"floatThead-container",copyTableClass:!0,enableAria:!1,autoReflow:!1,debug:!1};var h=window._,i="undefined"!=typeof MutationObserver,j=function(){for(var a=3,b=document.createElement("b"),c=b.all||[];a=1+a,b.innerHTML="",c[0];);return a>4?a:document.documentMode}(),k=/Gecko\//.test(navigator.userAgent),l=/WebKit\//.test(navigator.userAgent),m=function(){if(l){var b=a('
X
');a("body").append(b);var c=0==b.find("table").width();return b.remove(),c}return!1},n=!k&&!j,o=a(window);a.fn.floatThead=function(k){if(k=k||{},!h&&(h=window._||a.floatThead._,!h))throw new Error("jquery.floatThead-slim.js requires underscore. You should use the non-lite version since you do not have underscore.");if(8>j)return this;var p=null;if(h.isFunction(m)&&(m=m()),h.isString(k)){var q=k,r=this;return this.filter("table").each(function(){var b=a(this).data("floatThead-attached");if(b&&h.isFunction(b[q])){var c=b[q]();"undefined"!=typeof c&&(r=c)}}),r}var s=a.extend({},a.floatThead.defaults||{},k);if(a.each(k,function(b){b in a.floatThead.defaults||!s.debug||c("Used ["+b+"] key to init plugin, but that param is not an option for the plugin. Valid options are: "+h.keys(a.floatThead.defaults).join(", "))}),s.debug){var t=a.fn.jquery.split(".");1==parseInt(t[0],10)&&parseInt(t[1],10)<=7&&c("jQuery version "+a.fn.jquery+" detected! This plugin supports 1.8 or better, or 1.7.x with jQuery UI 1.8.24 -> http://jqueryui.com/resources/download/jquery-ui-1.8.24.zip")}return this.filter(":not(."+s.floatTableClass+")").each(function(){function c(a){return a+".fth-"+D+".floatTHead"}function k(){var b=0;F.find("tr:visible").each(function(){b+=a(this).outerHeight(!0)}),db.outerHeight(b),eb.outerHeight(b)}function m(){var a=g(E,hb,!0),b=N.width()||a,c="hidden"!=N.css("overflow-y")?b-K.vertical:b;if(ab.width(c),O){var d=100*a/c;X.css("width",d+"%")}else X.outerWidth(a)}function q(){H=(h.isFunction(s.scrollingTop)?s.scrollingTop(E):s.scrollingTop)||0,I=(h.isFunction(s.scrollingBottom)?s.scrollingBottom(E):s.scrollingBottom)||0}function r(){var b,c;if($)b=Z.find("col").length;else{var d;if(d=null==s.cellTag&&s.headerCellSelector?s.headerCellSelector:"tr:first>"+s.cellTag,h.isNumber(d))return d;c=F.find(d),b=0,c.each(function(){b+=parseInt(a(this).attr("colspan")||1,10)})}if(b!=M){M=b;for(var e,f=[],g=[],i=[],j=0;b>j;j++)f.push(s.enableAria&&(e=c.eq(j).text())?''+e+"":''),g.push(""),i.push("");g=g.join(""),f=f.join(""),n&&(i=i.join(""),_.html(i),hb=_.find("fthtd")),db.html(f),eb=db.find("th"),$||Z.html(g),fb=Z.find("col"),Y.html(g),gb=Y.find("col")}return b}function t(){if(!J){if(J=!0,P){var a=g(E,hb),b=V.width();a>b&&E.css("minWidth",a)}E.css(kb),X.css(kb),X.append(F),G.before(cb),k()}}function u(){J&&(J=!1,P&&E.width(mb),cb.detach(),E.prepend(F),E.css(lb),X.css(lb),E.css("minWidth",nb),E.css("minWidth",g(E,hb)))}function v(a){ob!=a&&(ob=a,E.triggerHandler("floatThead",[a,ab]))}function w(a){P!=a&&(P=a,ab.css({position:P?"absolute":"fixed"}))}function x(a,b,c,d){return n?c:d?s.getSizingRow(a,b,c):b}function y(){var a,b=r();return function(){fb=Z.find("col");var c=x(E,fb,hb,j);if(c.length==b&&b>0){if(!$)for(a=0;b>a;a++)fb.eq(a).css("width","");u();var e=[];for(a=0;b>a;a++)e[a]=d(c.get(a));for(a=0;b>a;a++)gb.eq(a).width(e[a]),fb.eq(a).width(e[a]);t()}else X.append(F),E.css(lb),X.css(lb),k()}}function z(a){var b=N.css("border-"+a+"-width"),c=0;return b&&~b.indexOf("px")&&(c=parseInt(b,10)),c}function A(){var a,b=N.scrollTop(),c=0,d=R?Q.outerHeight(!0):0,e=S?d:-d,f=ab.height(),g=E.offset(),h=0;if(O){var i=N.offset();c=g.top-i.top+b,R&&S&&(c+=d),c-=z("top"),h=z("left")}else a=g.top-H-f+I+K.horizontal;var j=o.scrollTop(),k=o.scrollLeft(),m=N.scrollLeft();return b=N.scrollTop(),function(i){var n=E[0].offsetWidth<=0&&E[0].offsetHeight<=0;if(!n&&bb)return bb=!1,setTimeout(function(){E.triggerHandler("reflow")},1),null;if(n&&(bb=!0,!P))return null;if("windowScroll"==i?(j=o.scrollTop(),k=o.scrollLeft()):"containerScroll"==i?(b=N.scrollTop(),m=N.scrollLeft()):"init"!=i&&(j=o.scrollTop(),k=o.scrollLeft(),b=N.scrollTop(),m=N.scrollLeft()),!l||!(0>j||0>k)){if(W)w("windowScrollDone"==i?!0:!1);else if("windowScrollDone"==i)return null;g=E[0].getBoundingClientRect(),R&&S&&(g.top+=d);var p,q,r=E.outerHeight();if(O&&P){if(c>=b){var s=c-b;p=s>0?s:0,v(!1)}else p=U?0:b,v(!0);q=h}else!O&&P?(j>a+r+e?p=r-f+e:g.top>H?(p=0,u(),v(!1)):(p=H-g.top+c+(S?d:0),t(),v(!0)),q=0):O&&!P?(c>b||b-c>r?(p=g.top,u(),v(!1)):(p=g.top+b-c,t(),v(!0)),q=g.left+m):O||P||(j>a+r+e?p=r+H-j+a+e:g.top>H?(p=g.top,t(),v(!1)):(p=H,v(!0)),q=g.left);return{top:p,left:q}}}}function B(){var a=null,b=null,c=null;return function(d,e,f){null==d||a==d.top&&b==d.left||(ab.css({top:d.top,left:d.left}),a=d.top,b=d.left),e&&m(),f&&k();var g=N.scrollLeft();P&&c==g||(ab.scrollLeft(g),c=g)}}function C(){if(N.length)if(N.data().perfectScrollbar)K={horizontal:0,vertical:0};else{var a=N.width(),b=N.height(),c=E.height(),d=g(E,hb),e=d>a?L:0,f=c>b?L:0;K.horizontal=d>a-f?L:0,K.vertical=c>b-e?L:0}}var D=h.uniqueId(),E=a(this);if(E.data("floatThead-attached"))return!0;if(!E.is("table"))throw new Error('jQuery.floatThead must be run on a table element. ex: $("table").floatThead();');i=s.autoReflow&&i;var F=E.find("thead:first"),G=E.find("tbody:first");if(0==F.length)throw new Error("jQuery.floatThead must be run on a table that contains a element");var H,I,J=!1,K={vertical:0,horizontal:0},L=e(),M=0,N=s.scrollContainer(E)||a([]),O=N.length>0,P=s.useAbsolutePositioning;null==P&&(P=O),P||(J=!0);var Q=E.find("caption"),R=1==Q.length;if(R)var S="top"===(Q.css("caption-side")||Q.attr("align")||"top");var T=a(''),U=!1,V=a([]),W=9>=j&&!O&&P,X=a(""),Y=a(""),Z=E.find("colgroup:first"),$=!0;0==Z.length&&(Z=a(""),$=!1);var _=a(''),ab=a(''),bb=!1,cb=a(""),db=a(''),eb=a([]),fb=a([]),gb=a([]),hb=a([]);cb.append(db),E.prepend(Z),n&&(T.append(_),E.append(T)),X.append(Y),ab.append(X),s.copyTableClass&&X.attr("class",E.attr("class")),X.attr({cellpadding:E.attr("cellpadding"),cellspacing:E.attr("cellspacing"),border:E.attr("border")});var ib=E.css("display");if(X.css({borderCollapse:E.css("borderCollapse"),border:E.css("border"),display:ib}),"none"==ib&&(bb=!0),X.addClass(s.floatTableClass).css("margin",0),P){var jb=function(a,b){var c=a.css("position"),d="relative"==c||"absolute"==c;if(!d||b){var e={paddingLeft:a.css("paddingLeft"),paddingRight:a.css("paddingRight")};ab.css(e),a=a.wrap("
").parent(),U=!0}return a};O?(V=jb(N,!0),V.append(ab)):(V=jb(E),E.after(ab))}else E.after(ab);ab.css({position:P?"absolute":"fixed",marginTop:0,top:P?0:"auto",zIndex:s.zIndex}),ab.addClass(s.floatContainerClass),q();var kb={"table-layout":"fixed"},lb={"table-layout":E.css("tableLayout")||"auto"},mb=E[0].style.width||"",nb=E.css("minWidth")||"",ob=!1;C();var pb,qb=function(){(pb=y())()};qb();var rb=A(),sb=B();sb(rb("init"),!0);var tb=h.debounce(function(){sb(rb("windowScrollDone"),!1)},300),ub=function(){sb(rb("windowScroll"),!1),tb()},vb=function(){sb(rb("containerScroll"),!1)},wb=function(){q(),C(),qb(),rb=A(),(sb=B())(rb("resize"),!0,!0)},xb=h.debounce(function(){C(),q(),qb(),rb=A(),sb(rb("reflow"),!0)},1);if(O?P?N.on(c("scroll"),vb):(N.on(c("scroll"),vb),o.on(c("scroll"),ub)):o.on(c("scroll"),ub),o.on(c("load"),xb),b(s.debounceResizeMs,c("resize"),wb),E.on("reflow",xb),f(E)&&E.on("filter",xb).on("sort",xb).on("page",xb),i){var yb=N.length?N[0]:E[0];p=new MutationObserver(function(a){for(var b=function(a){return a&&a[0]&&"THEAD"==a[0].nodeName},c=0;c= scrollingContainerTop) { var gap = tableContainerGap - scrollingContainerTop; top = gap > 0 ? gap : 0; + triggerFloatEvent(false); } else { top = wrappedContainer ? 0 : scrollingContainerTop; //headers stop at the top of the viewport + triggerFloatEvent(true); } left = tableLeftGap; } else if(!locked && useAbsolutePositioning) { //window scrolling, absolute positioning if(windowTop > floatEnd + tableHeight + captionScrollOffset){ top = tableHeight - floatContainerHeight + captionScrollOffset; //scrolled past table - } else if (tableOffset.top > windowTop + scrollingTop) { + } else if (tableOffset.top > scrollingTop) { top = 0; //scrolling to table unfloat(); + triggerFloatEvent(false); } else { - top = scrollingTop + windowTop - tableOffset.top + tableContainerGap + (captionAlignTop ? captionHeight : 0); + top = scrollingTop - tableOffset.top + tableContainerGap + (captionAlignTop ? captionHeight : 0); refloat(); //scrolling within table. header floated + triggerFloatEvent(true); } left = 0; } else if(locked && !useAbsolutePositioning){ //inner scrolling, fixed positioning if (tableContainerGap > scrollingContainerTop || scrollingContainerTop - tableContainerGap > tableHeight) { - top = tableOffset.top - windowTop; + top = tableOffset.top; unfloat(); + triggerFloatEvent(false); } else { - top = tableOffset.top + scrollingContainerTop - windowTop - tableContainerGap; + top = tableOffset.top + scrollingContainerTop - tableContainerGap; refloat(); + triggerFloatEvent(true); //headers stop at the top of the viewport } - left = tableOffset.left + scrollContainerLeft - windowLeft; + left = tableOffset.left + scrollContainerLeft; } else if(!locked && !useAbsolutePositioning) { //window scrolling, fixed positioning if(windowTop > floatEnd + tableHeight + captionScrollOffset){ top = tableHeight + scrollingTop - windowTop + floatEnd + captionScrollOffset; //scrolled past the bottom of the table - } else if (tableOffset.top > windowTop + scrollingTop) { - top = tableOffset.top - windowTop; + } else if (tableOffset.top > scrollingTop) { + top = tableOffset.top; refloat(); + triggerFloatEvent(false); //this is a weird case, the header never gets unfloated and i have no no way to know //scrolled past the top of the table } else { //scrolling within the table top = scrollingTop; + triggerFloatEvent(true); } - left = tableOffset.left - windowLeft; + left = tableOffset.left; } return {top: top, left: left}; }; diff --git a/dist/jquery.floatThead.min.js b/dist/jquery.floatThead.min.js index 7f2ffef..e807b89 100644 --- a/dist/jquery.floatThead.min.js +++ b/dist/jquery.floatThead.min.js @@ -1,3 +1,3 @@ // @preserve jQuery.floatThead 1.2.12dev - http://mkoryak.github.io/floatThead/ - Copyright (c) 2012 - 2015 Misha Koryak // @license MIT -!function(a){function b(a,b,c){if(8==i){var d=n.width(),e=g.debounce(function(){var a=n.width();d!=a&&(d=a,c())},a);n.on(b,e)}else n.on(b,g.debounce(c,a))}function c(a){window&&window.console&&window.console.log&&window.console.log("jQuery.floatThead: "+a)}function d(){var b=a('
');a("body").append(b);var c=b.innerWidth(),d=a("div",b).innerWidth();return b.remove(),c-d}function e(a){if(a.dataTableSettings)for(var b=0;b*:visible",zIndex:1001,debounceResizeMs:10,useAbsolutePositioning:!0,scrollingTop:0,scrollingBottom:0,scrollContainer:function(){return a([])},getSizingRow:function(a){return a.find("tbody tr:visible:first>*:visible")},floatTableClass:"floatThead-table",floatWrapperClass:"floatThead-wrapper",floatContainerClass:"floatThead-container",copyTableClass:!0,enableAria:!1,autoReflow:!1,debug:!1};var g=window._,h="undefined"!=typeof MutationObserver,i=function(){for(var a=3,b=document.createElement("b"),c=b.all||[];a=1+a,b.innerHTML="",c[0];);return a>4?a:document.documentMode}(),j=/Gecko\//.test(navigator.userAgent),k=/WebKit\//.test(navigator.userAgent),l=function(){if(k){var b=a('
X
');a("body").append(b);var c=0==b.find("table").width();return b.remove(),c}return!1},m=!j&&!i,n=a(window);a.fn.floatThead=function(j){if(j=j||{},!g&&(g=window._||a.floatThead._,!g))throw new Error("jquery.floatThead-slim.js requires underscore. You should use the non-lite version since you do not have underscore.");if(8>i)return this;var o=null;if(g.isFunction(l)&&(l=l()),g.isString(j)){var p=j,q=this;return this.filter("table").each(function(){var b=a(this).data("floatThead-attached");if(b&&g.isFunction(b[p])){var c=b[p]();"undefined"!=typeof c&&(q=c)}}),q}var r=a.extend({},a.floatThead.defaults||{},j);if(a.each(j,function(b){b in a.floatThead.defaults||!r.debug||c("Used ["+b+"] key to init plugin, but that param is not an option for the plugin. Valid options are: "+g.keys(a.floatThead.defaults).join(", "))}),r.debug){var s=a.fn.jquery.split(".");1==parseInt(s[0],10)&&parseInt(s[1],10)<=7&&c("jQuery version "+a.fn.jquery+" detected! This plugin supports 1.8 or better, or 1.7.x with jQuery UI 1.8.24 -> http://jqueryui.com/resources/download/jquery-ui-1.8.24.zip")}return this.filter(":not(."+r.floatTableClass+")").each(function(){function c(a){return a+".fth-"+B+".floatTHead"}function j(){var b=0;D.find("tr:visible").each(function(){b+=a(this).outerHeight(!0)}),bb.outerHeight(b),cb.outerHeight(b)}function l(){var a=f(C,fb,!0),b=L.width()||a,c="hidden"!=L.css("overflow-y")?b-I.vertical:b;if($.width(c),M){var d=100*a/c;V.css("width",d+"%")}else V.outerWidth(a)}function p(){F=(g.isFunction(r.scrollingTop)?r.scrollingTop(C):r.scrollingTop)||0,G=(g.isFunction(r.scrollingBottom)?r.scrollingBottom(C):r.scrollingBottom)||0}function q(){var b,c;if(Y)b=X.find("col").length;else{var d;if(d=null==r.cellTag&&r.headerCellSelector?r.headerCellSelector:"tr:first>"+r.cellTag,g.isNumber(d))return d;c=D.find(d),b=0,c.each(function(){b+=parseInt(a(this).attr("colspan")||1,10)})}if(b!=K){K=b;for(var e,f=[],h=[],i=[],j=0;b>j;j++)f.push(r.enableAria&&(e=c.eq(j).text())?''+e+"":''),h.push(""),i.push("");h=h.join(""),f=f.join(""),m&&(i=i.join(""),Z.html(i),fb=Z.find("fthtd")),bb.html(f),cb=bb.find("th"),Y||X.html(h),db=X.find("col"),W.html(h),eb=W.find("col")}return b}function s(){if(!H){if(H=!0,N){var a=f(C,fb),b=T.width();a>b&&C.css("minWidth",a)}C.css(ib),V.css(ib),V.append(D),E.before(ab),j()}}function t(){H&&(H=!1,N&&C.width(kb),ab.detach(),C.prepend(D),C.css(jb),V.css(jb),C.css("minWidth",lb),C.css("minWidth",f(C,fb)))}function u(a){N!=a&&(N=a,$.css({position:N?"absolute":"fixed"}))}function v(a,b,c,d){return m?c:d?r.getSizingRow(a,b,c):b}function w(){var a,b=q();return function(){db=X.find("col");var c=v(C,db,fb,i);if(c.length==b&&b>0){if(!Y)for(a=0;b>a;a++)db.eq(a).css("width","");t();var d=[];for(a=0;b>a;a++)d[a]=c.get(a).offsetWidth;for(a=0;b>a;a++)eb.eq(a).width(d[a]),db.eq(a).width(d[a]);s()}else V.append(D),C.css(jb),V.css(jb),j()}}function x(a){var b=L.css("border-"+a+"-width"),c=0;return b&&~b.indexOf("px")&&(c=parseInt(b,10)),c}function y(){var a,b=L.scrollTop(),c=0,d=P?O.outerHeight(!0):0,e=Q?d:-d,f=$.height(),g=C.offset(),h=0;if(M){var i=L.offset();c=g.top-i.top+b,P&&Q&&(c+=d),c-=x("top"),h=x("left")}else a=g.top-F-f+G+I.horizontal;var j=n.scrollTop(),l=n.scrollLeft(),m=L.scrollLeft();return b=L.scrollTop(),function(i){var o=C[0].offsetWidth<=0&&C[0].offsetHeight<=0;if(!o&&_)return _=!1,setTimeout(function(){C.trigger("reflow")},1),null;if(o&&(_=!0,!N))return null;if("windowScroll"==i?(j=n.scrollTop(),l=n.scrollLeft()):"containerScroll"==i?(b=L.scrollTop(),m=L.scrollLeft()):"init"!=i&&(j=n.scrollTop(),l=n.scrollLeft(),b=L.scrollTop(),m=L.scrollLeft()),!k||!(0>j||0>l)){if(U)u("windowScrollDone"==i?!0:!1);else if("windowScrollDone"==i)return null;g=C.offset(),P&&Q&&(g.top+=d);var p,q,r=C.outerHeight();if(M&&N){if(c>=b){var v=c-b;p=v>0?v:0}else p=S?0:b;q=h}else!M&&N?(j>a+r+e?p=r-f+e:g.top>j+F?(p=0,t()):(p=F+j-g.top+c+(Q?d:0),s()),q=0):M&&!N?(c>b||b-c>r?(p=g.top-j,t()):(p=g.top+b-j-c,s()),q=g.left+m-l):M||N||(j>a+r+e?p=r+F-j+a+e:g.top>j+F?(p=g.top-j,s()):p=F,q=g.left-l);return{top:p,left:q}}}}function z(){var a=null,b=null,c=null;return function(d,e,f){null==d||a==d.top&&b==d.left||($.css({top:d.top,left:d.left}),a=d.top,b=d.left),e&&l(),f&&j();var g=L.scrollLeft();N&&c==g||($.scrollLeft(g),c=g)}}function A(){if(L.length)if(L.data().perfectScrollbar)I={horizontal:0,vertical:0};else{var a=L.width(),b=L.height(),c=C.height(),d=f(C,fb),e=d>a?J:0,g=c>b?J:0;I.horizontal=d>a-g?J:0,I.vertical=c>b-e?J:0}}var B=g.uniqueId(),C=a(this);if(C.data("floatThead-attached"))return!0;if(!C.is("table"))throw new Error('jQuery.floatThead must be run on a table element. ex: $("table").floatThead();');h=r.autoReflow&&h;var D=C.find("thead:first"),E=C.find("tbody:first");if(0==D.length)throw new Error("jQuery.floatThead must be run on a table that contains a element");var F,G,H=!1,I={vertical:0,horizontal:0},J=d(),K=0,L=r.scrollContainer(C)||a([]),M=L.length>0,N=r.useAbsolutePositioning;null==N&&(N=M),N||(H=!0);var O=C.find("caption"),P=1==O.length;if(P)var Q="top"===(O.css("caption-side")||O.attr("align")||"top");var R=a(''),S=!1,T=a([]),U=9>=i&&!M&&N,V=a(""),W=a(""),X=C.find("colgroup:first"),Y=!0;0==X.length&&(X=a(""),Y=!1);var Z=a(''),$=a(''),_=!1,ab=a(""),bb=a(''),cb=a([]),db=a([]),eb=a([]),fb=a([]);ab.append(bb),C.prepend(X),m&&(R.append(Z),C.append(R)),V.append(W),$.append(V),r.copyTableClass&&V.attr("class",C.attr("class")),V.attr({cellpadding:C.attr("cellpadding"),cellspacing:C.attr("cellspacing"),border:C.attr("border")});var gb=C.css("display");if(V.css({borderCollapse:C.css("borderCollapse"),border:C.css("border"),display:gb}),"none"==gb&&(_=!0),V.addClass(r.floatTableClass).css("margin",0),N){var hb=function(a,b){var c=a.css("position"),d="relative"==c||"absolute"==c;if(!d||b){var e={paddingLeft:a.css("paddingLeft"),paddingRight:a.css("paddingRight")};$.css(e),a=a.wrap("
").parent(),S=!0}return a};M?(T=hb(L,!0),T.append($)):(T=hb(C),C.after($))}else C.after($);$.css({position:N?"absolute":"fixed",marginTop:0,top:N?0:"auto",zIndex:r.zIndex}),$.addClass(r.floatContainerClass),p();var ib={"table-layout":"fixed"},jb={"table-layout":C.css("tableLayout")||"auto"},kb=C[0].style.width||"",lb=C.css("minWidth")||"";A();var mb,nb=function(){(mb=w())()};nb();var ob=y(),pb=z();pb(ob("init"),!0);var qb=g.debounce(function(){pb(ob("windowScrollDone"),!1)},300),rb=function(){pb(ob("windowScroll"),!1),qb()},sb=function(){pb(ob("containerScroll"),!1)},tb=function(){p(),A(),nb(),ob=y(),(pb=z())(ob("resize"),!0,!0)},ub=g.debounce(function(){A(),p(),nb(),ob=y(),pb(ob("reflow"),!0)},1);if(M?N?L.on(c("scroll"),sb):(L.on(c("scroll"),sb),n.on(c("scroll"),rb)):n.on(c("scroll"),rb),n.on(c("load"),ub),b(r.debounceResizeMs,c("resize"),tb),C.on("reflow",ub),e(C)&&C.on("filter",ub).on("sort",ub).on("page",ub),h){var vb=L.length?L[0]:C[0];o=new MutationObserver(function(a){for(var b=function(a){return a&&a[0]&&"THEAD"==a[0].nodeName},c=0;cj?d=setTimeout(i,b-j):(d=null,c||(h=a.apply(f,e)))},j=c&&!d;return d||(d=setTimeout(i,b)),j&&(h=a.apply(f,e)),h}},b}()}(jQuery); \ No newline at end of file +!function(a){function b(a,b,c){if(8==j){var d=o.width(),e=h.debounce(function(){var a=o.width();d!=a&&(d=a,c())},a);o.on(b,e)}else o.on(b,h.debounce(c,a))}function c(a){window&&window.console&&window.console.log&&window.console.log("jQuery.floatThead: "+a)}function d(a){var b=a.getBoundingClientRect();return b.right-b.left}function e(){var b=a('
');a("body").append(b);var c=b.innerWidth(),d=a("div",b).innerWidth();return b.remove(),c-d}function f(a){if(a.dataTableSettings)for(var b=0;b*:visible",zIndex:1001,debounceResizeMs:10,useAbsolutePositioning:!0,scrollingTop:0,scrollingBottom:0,scrollContainer:function(){return a([])},getSizingRow:function(a){return a.find("tbody tr:visible:first>*:visible")},floatTableClass:"floatThead-table",floatWrapperClass:"floatThead-wrapper",floatContainerClass:"floatThead-container",copyTableClass:!0,enableAria:!1,autoReflow:!1,debug:!1};var h=window._,i="undefined"!=typeof MutationObserver,j=function(){for(var a=3,b=document.createElement("b"),c=b.all||[];a=1+a,b.innerHTML="",c[0];);return a>4?a:document.documentMode}(),k=/Gecko\//.test(navigator.userAgent),l=/WebKit\//.test(navigator.userAgent),m=function(){if(l){var b=a('
X
');a("body").append(b);var c=0==b.find("table").width();return b.remove(),c}return!1},n=!k&&!j,o=a(window);a.fn.floatThead=function(k){if(k=k||{},!h&&(h=window._||a.floatThead._,!h))throw new Error("jquery.floatThead-slim.js requires underscore. You should use the non-lite version since you do not have underscore.");if(8>j)return this;var p=null;if(h.isFunction(m)&&(m=m()),h.isString(k)){var q=k,r=this;return this.filter("table").each(function(){var b=a(this).data("floatThead-attached");if(b&&h.isFunction(b[q])){var c=b[q]();"undefined"!=typeof c&&(r=c)}}),r}var s=a.extend({},a.floatThead.defaults||{},k);if(a.each(k,function(b){b in a.floatThead.defaults||!s.debug||c("Used ["+b+"] key to init plugin, but that param is not an option for the plugin. Valid options are: "+h.keys(a.floatThead.defaults).join(", "))}),s.debug){var t=a.fn.jquery.split(".");1==parseInt(t[0],10)&&parseInt(t[1],10)<=7&&c("jQuery version "+a.fn.jquery+" detected! This plugin supports 1.8 or better, or 1.7.x with jQuery UI 1.8.24 -> http://jqueryui.com/resources/download/jquery-ui-1.8.24.zip")}return this.filter(":not(."+s.floatTableClass+")").each(function(){function c(a){return a+".fth-"+D+".floatTHead"}function k(){var b=0;F.find("tr:visible").each(function(){b+=a(this).outerHeight(!0)}),db.outerHeight(b),eb.outerHeight(b)}function m(){var a=g(E,hb,!0),b=N.width()||a,c="hidden"!=N.css("overflow-y")?b-K.vertical:b;if(ab.width(c),O){var d=100*a/c;X.css("width",d+"%")}else X.outerWidth(a)}function q(){H=(h.isFunction(s.scrollingTop)?s.scrollingTop(E):s.scrollingTop)||0,I=(h.isFunction(s.scrollingBottom)?s.scrollingBottom(E):s.scrollingBottom)||0}function r(){var b,c;if($)b=Z.find("col").length;else{var d;if(d=null==s.cellTag&&s.headerCellSelector?s.headerCellSelector:"tr:first>"+s.cellTag,h.isNumber(d))return d;c=F.find(d),b=0,c.each(function(){b+=parseInt(a(this).attr("colspan")||1,10)})}if(b!=M){M=b;for(var e,f=[],g=[],i=[],j=0;b>j;j++)f.push(s.enableAria&&(e=c.eq(j).text())?''+e+"":''),g.push(""),i.push("");g=g.join(""),f=f.join(""),n&&(i=i.join(""),_.html(i),hb=_.find("fthtd")),db.html(f),eb=db.find("th"),$||Z.html(g),fb=Z.find("col"),Y.html(g),gb=Y.find("col")}return b}function t(){if(!J){if(J=!0,P){var a=g(E,hb),b=V.width();a>b&&E.css("minWidth",a)}E.css(kb),X.css(kb),X.append(F),G.before(cb),k()}}function u(){J&&(J=!1,P&&E.width(mb),cb.detach(),E.prepend(F),E.css(lb),X.css(lb),E.css("minWidth",nb),E.css("minWidth",g(E,hb)))}function v(a){ob!=a&&(ob=a,E.triggerHandler("floatThead",[a,ab]))}function w(a){P!=a&&(P=a,ab.css({position:P?"absolute":"fixed"}))}function x(a,b,c,d){return n?c:d?s.getSizingRow(a,b,c):b}function y(){var a,b=r();return function(){fb=Z.find("col");var c=x(E,fb,hb,j);if(c.length==b&&b>0){if(!$)for(a=0;b>a;a++)fb.eq(a).css("width","");u();var e=[];for(a=0;b>a;a++)e[a]=d(c.get(a));for(a=0;b>a;a++)gb.eq(a).width(e[a]),fb.eq(a).width(e[a]);t()}else X.append(F),E.css(lb),X.css(lb),k()}}function z(a){var b=N.css("border-"+a+"-width"),c=0;return b&&~b.indexOf("px")&&(c=parseInt(b,10)),c}function A(){var a,b=N.scrollTop(),c=0,d=R?Q.outerHeight(!0):0,e=S?d:-d,f=ab.height(),g=E.offset(),h=0;if(O){var i=N.offset();c=g.top-i.top+b,R&&S&&(c+=d),c-=z("top"),h=z("left")}else a=g.top-H-f+I+K.horizontal;var j=o.scrollTop(),k=o.scrollLeft(),m=N.scrollLeft();return b=N.scrollTop(),function(i){var n=E[0].offsetWidth<=0&&E[0].offsetHeight<=0;if(!n&&bb)return bb=!1,setTimeout(function(){E.triggerHandler("reflow")},1),null;if(n&&(bb=!0,!P))return null;if("windowScroll"==i?(j=o.scrollTop(),k=o.scrollLeft()):"containerScroll"==i?(b=N.scrollTop(),m=N.scrollLeft()):"init"!=i&&(j=o.scrollTop(),k=o.scrollLeft(),b=N.scrollTop(),m=N.scrollLeft()),!l||!(0>j||0>k)){if(W)w("windowScrollDone"==i?!0:!1);else if("windowScrollDone"==i)return null;g=E[0].getBoundingClientRect(),R&&S&&(g.top+=d);var p,q,r=E.outerHeight();if(O&&P){if(c>=b){var s=c-b;p=s>0?s:0,v(!1)}else p=U?0:b,v(!0);q=h}else!O&&P?(j>a+r+e?p=r-f+e:g.top>H?(p=0,u(),v(!1)):(p=H-g.top+c+(S?d:0),t(),v(!0)),q=0):O&&!P?(c>b||b-c>r?(p=g.top,u(),v(!1)):(p=g.top+b-c,t(),v(!0)),q=g.left+m):O||P||(j>a+r+e?p=r+H-j+a+e:g.top>H?(p=g.top,t(),v(!1)):(p=H,v(!0)),q=g.left);return{top:p,left:q}}}}function B(){var a=null,b=null,c=null;return function(d,e,f){null==d||a==d.top&&b==d.left||(ab.css({top:d.top,left:d.left}),a=d.top,b=d.left),e&&m(),f&&k();var g=N.scrollLeft();P&&c==g||(ab.scrollLeft(g),c=g)}}function C(){if(N.length)if(N.data().perfectScrollbar)K={horizontal:0,vertical:0};else{var a=N.width(),b=N.height(),c=E.height(),d=g(E,hb),e=d>a?L:0,f=c>b?L:0;K.horizontal=d>a-f?L:0,K.vertical=c>b-e?L:0}}var D=h.uniqueId(),E=a(this);if(E.data("floatThead-attached"))return!0;if(!E.is("table"))throw new Error('jQuery.floatThead must be run on a table element. ex: $("table").floatThead();');i=s.autoReflow&&i;var F=E.find("thead:first"),G=E.find("tbody:first");if(0==F.length)throw new Error("jQuery.floatThead must be run on a table that contains a element");var H,I,J=!1,K={vertical:0,horizontal:0},L=e(),M=0,N=s.scrollContainer(E)||a([]),O=N.length>0,P=s.useAbsolutePositioning;null==P&&(P=O),P||(J=!0);var Q=E.find("caption"),R=1==Q.length;if(R)var S="top"===(Q.css("caption-side")||Q.attr("align")||"top");var T=a(''),U=!1,V=a([]),W=9>=j&&!O&&P,X=a(""),Y=a(""),Z=E.find("colgroup:first"),$=!0;0==Z.length&&(Z=a(""),$=!1);var _=a(''),ab=a(''),bb=!1,cb=a(""),db=a(''),eb=a([]),fb=a([]),gb=a([]),hb=a([]);cb.append(db),E.prepend(Z),n&&(T.append(_),E.append(T)),X.append(Y),ab.append(X),s.copyTableClass&&X.attr("class",E.attr("class")),X.attr({cellpadding:E.attr("cellpadding"),cellspacing:E.attr("cellspacing"),border:E.attr("border")});var ib=E.css("display");if(X.css({borderCollapse:E.css("borderCollapse"),border:E.css("border"),display:ib}),"none"==ib&&(bb=!0),X.addClass(s.floatTableClass).css("margin",0),P){var jb=function(a,b){var c=a.css("position"),d="relative"==c||"absolute"==c;if(!d||b){var e={paddingLeft:a.css("paddingLeft"),paddingRight:a.css("paddingRight")};ab.css(e),a=a.wrap("
").parent(),U=!0}return a};O?(V=jb(N,!0),V.append(ab)):(V=jb(E),E.after(ab))}else E.after(ab);ab.css({position:P?"absolute":"fixed",marginTop:0,top:P?0:"auto",zIndex:s.zIndex}),ab.addClass(s.floatContainerClass),q();var kb={"table-layout":"fixed"},lb={"table-layout":E.css("tableLayout")||"auto"},mb=E[0].style.width||"",nb=E.css("minWidth")||"",ob=!1;C();var pb,qb=function(){(pb=y())()};qb();var rb=A(),sb=B();sb(rb("init"),!0);var tb=h.debounce(function(){sb(rb("windowScrollDone"),!1)},300),ub=function(){sb(rb("windowScroll"),!1),tb()},vb=function(){sb(rb("containerScroll"),!1)},wb=function(){q(),C(),qb(),rb=A(),(sb=B())(rb("resize"),!0,!0)},xb=h.debounce(function(){C(),q(),qb(),rb=A(),sb(rb("reflow"),!0)},1);if(O?P?N.on(c("scroll"),vb):(N.on(c("scroll"),vb),o.on(c("scroll"),ub)):o.on(c("scroll"),ub),o.on(c("load"),xb),b(s.debounceResizeMs,c("resize"),wb),E.on("reflow",xb),f(E)&&E.on("filter",xb).on("sort",xb).on("page",xb),i){var yb=N.length?N[0]:E[0];p=new MutationObserver(function(a){for(var b=function(a){return a&&a[0]&&"THEAD"==a[0].nodeName},c=0;cj?d=setTimeout(i,b-j):(d=null,c||(h=a.apply(f,e)))},j=c&&!d;return d||(d=setTimeout(i,b)),j&&(h=a.apply(f,e)),h}},b}()}(jQuery); \ No newline at end of file diff --git a/jquery.floatThead.js b/jquery.floatThead.js index f88c4fa..b515b1d 100644 --- a/jquery.floatThead.js +++ b/jquery.floatThead.js @@ -94,6 +94,12 @@ window && window.console && window.console.log && window.console.log("jQuery.floatThead: " + str); } + //returns fractional pixel widths + function getOffsetWidth(el) { + var rect = el.getBoundingClientRect(); + return rect.right - rect.left; + } + /** * try to calculate the scrollbar width for your browser/os * @return {Number} @@ -439,6 +445,14 @@ $table.css('minWidth', tableWidth($table, $fthCells)); //#121 } } + var isHeaderFloatingLogical = false; //for the purpose of this event, the header is/isnt floating, even though the element + //might be in some other state. this is what the header looks like to the user + function triggerFloatEvent(isFloating){ + if(isHeaderFloatingLogical != isFloating){ + isHeaderFloatingLogical = isFloating; + $table.triggerHandler("floatThead", [isFloating, $floatContainer]) + } + } function changePositioning(isAbsolute){ if(useAbsolutePositioning != isAbsolute){ useAbsolutePositioning = isAbsolute; @@ -478,7 +492,7 @@ unfloat(); var widths = []; for(i=0; i < numCols; i++){ - widths[i] = $rowCells.get(i).offsetWidth; + widths[i] = getOffsetWidth($rowCells.get(i)); } for(i=0; i < numCols; i++){ $headerCells.eq(i).width(widths[i]); @@ -542,7 +556,7 @@ if(!isTableHidden && floatTableHidden) { floatTableHidden = false; setTimeout(function(){ - $table.trigger("reflow"); + $table.triggerHandler("reflow"); }, 1); return null; } @@ -579,7 +593,7 @@ return null; //event is fired when they stop scrolling. ignore it if not 'absoluteToFixedOnScroll' } - tableOffset = $table.offset(); + tableOffset = $table[0].getBoundingClientRect(); if(haveCaption && captionAlignTop){ tableOffset.top += captionHeight; } @@ -590,45 +604,53 @@ if (tableContainerGap >= scrollingContainerTop) { var gap = tableContainerGap - scrollingContainerTop; top = gap > 0 ? gap : 0; + triggerFloatEvent(false); } else { top = wrappedContainer ? 0 : scrollingContainerTop; //headers stop at the top of the viewport + triggerFloatEvent(true); } left = tableLeftGap; } else if(!locked && useAbsolutePositioning) { //window scrolling, absolute positioning if(windowTop > floatEnd + tableHeight + captionScrollOffset){ top = tableHeight - floatContainerHeight + captionScrollOffset; //scrolled past table - } else if (tableOffset.top > windowTop + scrollingTop) { + } else if (tableOffset.top > scrollingTop) { top = 0; //scrolling to table unfloat(); + triggerFloatEvent(false); } else { - top = scrollingTop + windowTop - tableOffset.top + tableContainerGap + (captionAlignTop ? captionHeight : 0); + top = scrollingTop - tableOffset.top + tableContainerGap + (captionAlignTop ? captionHeight : 0); refloat(); //scrolling within table. header floated + triggerFloatEvent(true); } left = 0; } else if(locked && !useAbsolutePositioning){ //inner scrolling, fixed positioning if (tableContainerGap > scrollingContainerTop || scrollingContainerTop - tableContainerGap > tableHeight) { - top = tableOffset.top - windowTop; + top = tableOffset.top; unfloat(); + triggerFloatEvent(false); } else { - top = tableOffset.top + scrollingContainerTop - windowTop - tableContainerGap; + top = tableOffset.top + scrollingContainerTop - tableContainerGap; refloat(); + triggerFloatEvent(true); //headers stop at the top of the viewport } - left = tableOffset.left + scrollContainerLeft - windowLeft; + left = tableOffset.left + scrollContainerLeft; } else if(!locked && !useAbsolutePositioning) { //window scrolling, fixed positioning if(windowTop > floatEnd + tableHeight + captionScrollOffset){ top = tableHeight + scrollingTop - windowTop + floatEnd + captionScrollOffset; //scrolled past the bottom of the table - } else if (tableOffset.top > windowTop + scrollingTop) { - top = tableOffset.top - windowTop; + } else if (tableOffset.top > scrollingTop) { + top = tableOffset.top; refloat(); + triggerFloatEvent(false); //this is a weird case, the header never gets unfloated and i have no no way to know //scrolled past the top of the table } else { //scrolling within the table top = scrollingTop; + triggerFloatEvent(true); } - left = tableOffset.left - windowLeft; + left = tableOffset.left; } return {top: top, left: left}; };