From ee3a604fd72874e1479f9ed488406def95285a1d Mon Sep 17 00:00:00 2001 From: Oleg Korsunsky Date: Wed, 18 Jun 2014 19:56:33 +0400 Subject: [PATCH] now watching for vertical layout changes --- dist/stickyfill.js | 39 +++++++++++++++++++++++++++++++++------ dist/stickyfill.min.js | 2 +- src/stickyfill.js | 39 +++++++++++++++++++++++++++++++++------ test/index.htm | 32 +++++++++++++++++++------------- 4 files changed, 86 insertions(+), 26 deletions(-) diff --git a/dist/stickyfill.js b/dist/stickyfill.js index d3043d5..a4d5b5d 100644 --- a/dist/stickyfill.js +++ b/dist/stickyfill.js @@ -10,7 +10,8 @@ scroll, initialized = false, html = doc.documentElement, - noop = function() {}; + noop = function() {}, + checkTimer; //test getComputedStyle if (!win.getComputedStyle) { @@ -65,12 +66,13 @@ function onScroll() { if (win.pageXOffset != scroll.left) { - scroll.left = win.pageXOffset; + updateScrollPos(); rebuild(); + return; } if (win.pageYOffset != scroll.top) { - scroll.top = win.pageYOffset; + updateScrollPos(); recalcAllPos(); } } @@ -99,10 +101,21 @@ } } + //checks whether stickies start or stop positions have changed + function fastCheck() { + for (var i = watchArray.length - 1; i >= 0; i--) { + if (getDocOffsetTop(watchArray[i].clone) - watchArray[i].docOffsetTop >= 2 || + watchArray[i].parent.node.offsetHeight - watchArray[i].parent.height >= 2) return false; + } + return true; + } + function initElement(el) { if (!el.clone) clone(el); el.parent.node.style.position = 'relative'; if (!el.numeric.zIndex) el.node.style.zIndex = 999; + el.docOffsetTop = getDocOffsetTop(el.node); + el.parent.height = el.parent.node.offsetHeight; } function deinitElement(el) { @@ -185,8 +198,6 @@ el.node.parentNode.insertBefore(el.clone, refElement); if (el.cell) el.clone.appendChild(el.node); - - return el.clone; } function killClone(el) { @@ -270,7 +281,6 @@ height: nodeOffset.win.bottom - nodeOffset.win.top, mode: -1, parent: parent, - clone: undefined, limit: { start: nodeOffset.doc.top - numeric.top, end: parentOffset.doc.top + parentNode.offsetHeight - parent.numeric.borderBottomWidth - @@ -281,6 +291,17 @@ return el; } + function getDocOffsetTop(node) { + var docOffsetTop = 0; + + while (node) { + docOffsetTop += node.offsetTop; + node = node.offsetParent; + } + + return docOffsetTop; + } + function getElementOffset(node) { var box = node.getBoundingClientRect(); @@ -306,6 +327,10 @@ win.addEventListener('resize', rebuild); win.addEventListener('orientationchange', rebuild); + checkTimer = setInterval(function() { + !fastCheck() && rebuild(); + }, 500); + initialized = true; } @@ -328,6 +353,8 @@ win.removeEventListener('resize', rebuild); win.removeEventListener('orientationchange', rebuild); + clearInterval(checkTimer); + initialized = false; } diff --git a/dist/stickyfill.min.js b/dist/stickyfill.min.js index a4e734c..82689e2 100644 --- a/dist/stickyfill.min.js +++ b/dist/stickyfill.min.js @@ -5,4 +5,4 @@ * * MIT License */ -!function(a,b){function c(){u=z=v=w=x=y=E}function d(a,b){for(key in b)b.hasOwnProperty(key)&&(a[key]=b[key])}function e(a){return parseFloat(a)||0}function f(){return e(getComputedStyle(D).marginLeft)+e(getComputedStyle(D).marginRight)+D.offsetWidth}function g(){A={top:b.pageYOffset,left:b.pageXOffset}}function h(){b.pageXOffset!=A.left&&(A.left=b.pageXOffset,v()),b.pageYOffset!=A.top&&(A.top=b.pageYOffset,j())}function i(){setTimeout(function(){b.pageYOffset!=A.top&&(A.top=b.pageYOffset,j())},0)}function j(){for(var a=B.length-1;a>=0;a--)k(B[a])}function k(a){var b=A.top<=a.limit.start||isNaN(parseFloat(a.computed.top))?0:A.top>=a.limit.end?2:1;a.mode!=b&&p(a,b)}function l(a){a.clone||q(a),a.parent.node.style.position="relative",a.numeric.zIndex||(a.node.style.zIndex=999)}function m(a){a.clone&&r(a),d(a.node.style,a.css),a.parent.node.style.position=a.parent.css.position,a.mode=-1}function n(){for(var a=B.length-1;a>=0;a--)l(B[a])}function o(){for(var a=B.length-1;a>=0;a--)m(B[a])}function p(a,b){var c=a.node.style;switch(b){case 0:c.position="absolute",c.left=a.offset.left+"px",c.right=a.offset.right+"px",c.top=a.offset.top+"px",c.bottom="auto",c.width="auto",c.marginLeft=0,c.marginRight=0,c.marginTop=0;break;case 1:c.position="fixed",c.left=a.box.left+"px",c.right=a.box.right+"px",c.top=a.css.top,c.bottom="auto",c.width="auto",c.marginLeft=0,c.marginRight=0,c.marginTop=0;break;case 2:c.position="absolute",c.left=a.offset.left+"px",c.right=a.offset.right+"px",c.top="auto",c.bottom=0,c.width="auto",c.marginLeft=0,c.marginRight=0}a.mode=b}function q(a){a.clone=document.createElement(a.cell?a.node.tagName:"div");var b=a.node.nextSibling||a.node,c=a.clone.style;return c.height=a.height+"px",c.width=a.width+"px",c.marginTop=a.computed.marginTop,c.marginBottom=a.computed.marginBottom,c.marginLeft=a.computed.marginLeft,c.marginRight=a.computed.marginRight,c.padding=c.border=c.borderSpacing=0,c.position="static",a.node.parentNode.insertBefore(a.clone,b),a.cell&&a.clone.appendChild(a.node),a.clone}function r(a){a.cell&&a.clone.parentNode.insertBefore(a.node,a.clone),a.clone.parentNode.removeChild(a.clone),a.clone=void 0}function s(a){var c=getComputedStyle(a),d="table-cell"==c.display,g=d?a.offsetParent:a.parentNode,h=getComputedStyle(g),i=a.style.position;(b.opera||d)&&(a.style.position="absolute");var j={top:c.top,marginTop:c.marginTop,marginBottom:c.marginBottom,marginLeft:c.marginLeft,marginRight:c.marginRight},k={top:e(c.top),marginBottom:e(c.marginBottom),paddingLeft:e(c.paddingLeft),paddingRight:e(c.paddingRight),borderLeftWidth:e(c.borderLeftWidth),borderRightWidth:e(c.borderRightWidth),zIndex:e(c.zIndex)};(b.opera||d)&&(a.style.position=i);var l={position:a.style.position,top:a.style.top,bottom:a.style.bottom,left:a.style.left,right:a.style.right,width:a.style.width,marginTop:a.style.marginTop,marginLeft:a.style.marginLeft,marginRight:a.style.marginRight,zIndex:a.style.zIndex},m=t(a),n=t(g),o={node:g,css:{position:g.style.position},numeric:{borderLeftWidth:e(h.borderLeftWidth),borderRightWidth:e(h.borderRightWidth),borderTopWidth:e(h.borderTopWidth),borderBottomWidth:e(h.borderBottomWidth)}},p={node:a,box:{left:m.win.left,right:f()-m.win.right},offset:{top:m.win.top-n.win.top-o.numeric.borderTopWidth,left:m.win.left-n.win.left-o.numeric.borderLeftWidth,right:-m.win.right+n.win.right-o.numeric.borderRightWidth},css:l,cell:d,computed:j,numeric:k,width:m.win.right-m.win.left,height:m.win.bottom-m.win.top,mode:-1,parent:o,clone:void 0,limit:{start:m.doc.top-k.top,end:n.doc.top+g.offsetHeight-o.numeric.borderBottomWidth-a.offsetHeight-k.top-k.marginBottom}};return p}function t(a){var c=a.getBoundingClientRect();return{doc:{top:c.top+b.pageYOffset,left:c.left+b.pageXOffset},win:c}}function u(){C||(n(),g(),j(),b.addEventListener("scroll",h),b.addEventListener("wheel",i),b.addEventListener("resize",v),b.addEventListener("orientationchange",v),C=!0)}function v(){if(C){o();for(var a=B.length-1;a>=0;a--)B[a]=s(B[a].node);n(),j()}}function w(){b.removeEventListener("scroll",h),b.removeEventListener("wheel",i),b.removeEventListener("resize",v),b.removeEventListener("orientationchange",v),C=!1}function x(){w(),o()}function y(){x(),B=[]}function z(a){var b=s(a);B.push(b),C?(l(b),k(b)):u()}var A,B=[],C=!1,D=a.documentElement,E=function(){};b.getComputedStyle||c();for(var F=["","-webkit-","-moz-","-ms-"],G=document.createElement("div"),H=F.length-1;H>=0;H--){try{G.style.position=F[H]+"sticky"}catch(I){}""!=G.style.position&&c()}g(),b.Stickyfill={stickies:B,add:z,init:u,rebuild:v,pause:w,stop:x,kill:y}}(document,window),window.jQuery&&!function($){$.fn.Stickyfill=function(){return this.each(function(){Stickyfill.add(this)}),this}}(window.jQuery); \ No newline at end of file +!function(a,b){function c(){w=B=x=y=z=A=H}function d(a,b){for(key in b)b.hasOwnProperty(key)&&(a[key]=b[key])}function e(a){return parseFloat(a)||0}function f(){return e(getComputedStyle(G).marginLeft)+e(getComputedStyle(G).marginRight)+G.offsetWidth}function g(){C={top:b.pageYOffset,left:b.pageXOffset}}function h(){return b.pageXOffset!=C.left?(g(),void x()):void(b.pageYOffset!=C.top&&(g(),j()))}function i(){setTimeout(function(){b.pageYOffset!=C.top&&(C.top=b.pageYOffset,j())},0)}function j(){for(var a=E.length-1;a>=0;a--)k(E[a])}function k(a){var b=C.top<=a.limit.start||isNaN(parseFloat(a.computed.top))?0:C.top>=a.limit.end?2:1;a.mode!=b&&q(a,b)}function l(){for(var a=E.length-1;a>=0;a--)if(u(E[a].clone)-E[a].docOffsetTop>=2||E[a].parent.node.offsetHeight-E[a].parent.height>=2)return!1;return!0}function m(a){a.clone||r(a),a.parent.node.style.position="relative",a.numeric.zIndex||(a.node.style.zIndex=999),a.docOffsetTop=u(a.node),a.parent.height=a.parent.node.offsetHeight}function n(a){a.clone&&s(a),d(a.node.style,a.css),a.parent.node.style.position=a.parent.css.position,a.mode=-1}function o(){for(var a=E.length-1;a>=0;a--)m(E[a])}function p(){for(var a=E.length-1;a>=0;a--)n(E[a])}function q(a,b){var c=a.node.style;switch(b){case 0:c.position="absolute",c.left=a.offset.left+"px",c.right=a.offset.right+"px",c.top=a.offset.top+"px",c.bottom="auto",c.width="auto",c.marginLeft=0,c.marginRight=0,c.marginTop=0;break;case 1:c.position="fixed",c.left=a.box.left+"px",c.right=a.box.right+"px",c.top=a.css.top,c.bottom="auto",c.width="auto",c.marginLeft=0,c.marginRight=0,c.marginTop=0;break;case 2:c.position="absolute",c.left=a.offset.left+"px",c.right=a.offset.right+"px",c.top="auto",c.bottom=0,c.width="auto",c.marginLeft=0,c.marginRight=0}a.mode=b}function r(a){a.clone=document.createElement(a.cell?a.node.tagName:"div");var b=a.node.nextSibling||a.node,c=a.clone.style;c.height=a.height+"px",c.width=a.width+"px",c.marginTop=a.computed.marginTop,c.marginBottom=a.computed.marginBottom,c.marginLeft=a.computed.marginLeft,c.marginRight=a.computed.marginRight,c.padding=c.border=c.borderSpacing=0,c.position="static",a.node.parentNode.insertBefore(a.clone,b),a.cell&&a.clone.appendChild(a.node)}function s(a){a.cell&&a.clone.parentNode.insertBefore(a.node,a.clone),a.clone.parentNode.removeChild(a.clone),a.clone=void 0}function t(a){var c=getComputedStyle(a),d="table-cell"==c.display,g=d?a.offsetParent:a.parentNode,h=getComputedStyle(g),i=a.style.position;(b.opera||d)&&(a.style.position="absolute");var j={top:c.top,marginTop:c.marginTop,marginBottom:c.marginBottom,marginLeft:c.marginLeft,marginRight:c.marginRight},k={top:e(c.top),marginBottom:e(c.marginBottom),paddingLeft:e(c.paddingLeft),paddingRight:e(c.paddingRight),borderLeftWidth:e(c.borderLeftWidth),borderRightWidth:e(c.borderRightWidth),zIndex:e(c.zIndex)};(b.opera||d)&&(a.style.position=i);var l={position:a.style.position,top:a.style.top,bottom:a.style.bottom,left:a.style.left,right:a.style.right,width:a.style.width,marginTop:a.style.marginTop,marginLeft:a.style.marginLeft,marginRight:a.style.marginRight,zIndex:a.style.zIndex},m=v(a),n=v(g),o={node:g,css:{position:g.style.position},numeric:{borderLeftWidth:e(h.borderLeftWidth),borderRightWidth:e(h.borderRightWidth),borderTopWidth:e(h.borderTopWidth),borderBottomWidth:e(h.borderBottomWidth)}},p={node:a,box:{left:m.win.left,right:f()-m.win.right},offset:{top:m.win.top-n.win.top-o.numeric.borderTopWidth,left:m.win.left-n.win.left-o.numeric.borderLeftWidth,right:-m.win.right+n.win.right-o.numeric.borderRightWidth},css:l,cell:d,computed:j,numeric:k,width:m.win.right-m.win.left,height:m.win.bottom-m.win.top,mode:-1,parent:o,limit:{start:m.doc.top-k.top,end:n.doc.top+g.offsetHeight-o.numeric.borderBottomWidth-a.offsetHeight-k.top-k.marginBottom}};return p}function u(a){for(var b=0;a;)b+=a.offsetTop,a=a.offsetParent;return b}function v(a){var c=a.getBoundingClientRect();return{doc:{top:c.top+b.pageYOffset,left:c.left+b.pageXOffset},win:c}}function w(){F||(o(),g(),j(),b.addEventListener("scroll",h),b.addEventListener("wheel",i),b.addEventListener("resize",x),b.addEventListener("orientationchange",x),D=setInterval(function(){!l()&&x()},500),F=!0)}function x(){if(F){p();for(var a=E.length-1;a>=0;a--)E[a]=t(E[a].node);o(),j()}}function y(){b.removeEventListener("scroll",h),b.removeEventListener("wheel",i),b.removeEventListener("resize",x),b.removeEventListener("orientationchange",x),clearInterval(D),F=!1}function z(){y(),p()}function A(){z(),E=[]}function B(a){var b=t(a);E.push(b),F?(m(b),k(b)):w()}var C,D,E=[],F=!1,G=a.documentElement,H=function(){};b.getComputedStyle||c();for(var I=["","-webkit-","-moz-","-ms-"],J=document.createElement("div"),K=I.length-1;K>=0;K--){try{J.style.position=I[K]+"sticky"}catch(L){}""!=J.style.position&&c()}g(),b.Stickyfill={stickies:E,add:B,init:w,rebuild:x,pause:y,stop:z,kill:A}}(document,window),window.jQuery&&!function($){$.fn.Stickyfill=function(){return this.each(function(){Stickyfill.add(this)}),this}}(window.jQuery); \ No newline at end of file diff --git a/src/stickyfill.js b/src/stickyfill.js index 1df3e8f..28de158 100644 --- a/src/stickyfill.js +++ b/src/stickyfill.js @@ -3,7 +3,8 @@ scroll, initialized = false, html = doc.documentElement, - noop = function() {}; + noop = function() {}, + checkTimer; //test getComputedStyle if (!win.getComputedStyle) { @@ -58,12 +59,13 @@ function onScroll() { if (win.pageXOffset != scroll.left) { - scroll.left = win.pageXOffset; + updateScrollPos(); rebuild(); + return; } if (win.pageYOffset != scroll.top) { - scroll.top = win.pageYOffset; + updateScrollPos(); recalcAllPos(); } } @@ -92,10 +94,21 @@ } } + //checks whether stickies start or stop positions have changed + function fastCheck() { + for (var i = watchArray.length - 1; i >= 0; i--) { + if (getDocOffsetTop(watchArray[i].clone) - watchArray[i].docOffsetTop >= 2 || + watchArray[i].parent.node.offsetHeight - watchArray[i].parent.height >= 2) return false; + } + return true; + } + function initElement(el) { if (!el.clone) clone(el); el.parent.node.style.position = 'relative'; if (!el.numeric.zIndex) el.node.style.zIndex = 999; + el.docOffsetTop = getDocOffsetTop(el.node); + el.parent.height = el.parent.node.offsetHeight; } function deinitElement(el) { @@ -178,8 +191,6 @@ el.node.parentNode.insertBefore(el.clone, refElement); if (el.cell) el.clone.appendChild(el.node); - - return el.clone; } function killClone(el) { @@ -263,7 +274,6 @@ height: nodeOffset.win.bottom - nodeOffset.win.top, mode: -1, parent: parent, - clone: undefined, limit: { start: nodeOffset.doc.top - numeric.top, end: parentOffset.doc.top + parentNode.offsetHeight - parent.numeric.borderBottomWidth - @@ -274,6 +284,17 @@ return el; } + function getDocOffsetTop(node) { + var docOffsetTop = 0; + + while (node) { + docOffsetTop += node.offsetTop; + node = node.offsetParent; + } + + return docOffsetTop; + } + function getElementOffset(node) { var box = node.getBoundingClientRect(); @@ -299,6 +320,10 @@ win.addEventListener('resize', rebuild); win.addEventListener('orientationchange', rebuild); + checkTimer = setInterval(function() { + !fastCheck() && rebuild(); + }, 500); + initialized = true; } @@ -321,6 +346,8 @@ win.removeEventListener('resize', rebuild); win.removeEventListener('orientationchange', rebuild); + clearInterval(checkTimer); + initialized = false; } diff --git a/test/index.htm b/test/index.htm index e7793dd..888c846 100644 --- a/test/index.htm +++ b/test/index.htm @@ -54,7 +54,7 @@ padding: 0.5em; background: #69A9D3; border-radius: 0.5em; - z-index: 10; + z-index: 5000; } .arrows button { @@ -803,22 +803,28 @@

div {box-sizing: border-box; margin: 3em; border: 5px} (static)