From e7ce90db8c1c3e1e53de5d5db25c04cb68d6cb2f Mon Sep 17 00:00:00 2001 From: puttyman Date: Tue, 28 Apr 2015 09:33:09 +1000 Subject: [PATCH] Fixed Affix directive has a flickering bug in IE8-IE11. #13 --- dist/ngScrollSpy.debug.js | 14 ++++++++++++-- dist/ngScrollSpy.js | 18 ++++++++++++++---- dist/ngScrollSpy.min.js | 2 +- src/scrollspy.js | 10 ++++++++++ 4 files changed, 37 insertions(+), 7 deletions(-) diff --git a/dist/ngScrollSpy.debug.js b/dist/ngScrollSpy.debug.js index ed97dfe..b525a6a 100755 --- a/dist/ngScrollSpy.debug.js +++ b/dist/ngScrollSpy.debug.js @@ -9,14 +9,24 @@ Licence: MIT mod.service('ScrollSpy', function($window) { var rawData= function(w) { + // Fix for IE browsers + // See https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollY?redirectlocale=en-US&redirectslug=DOM%2Fwindow.scrollY for more info + var innerWidth = w.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; + var innerHeight = w.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; + var supportPageOffset = w.pageXOffset !== undefined; + var isCSS1Compat = ((document.compatMode || "") === "CSS1Compat"); + + var scrollX = supportPageOffset ? w.pageXOffset : isCSS1Compat ? document.documentElement.scrollLeft : document.body.scrollLeft; + var scrollY= supportPageOffset ? w.pageYOffset : isCSS1Compat ? document.documentElement.scrollTop : document.body.scrollTop; + // retrieve interesting data var raw= { width: w.innerWidth, height: w.innerHeight, maxWidth: w.document.body.scrollWidth, maxHeight: w.document.body.scrollHeight, - posX: w.scrollX, - posY: w.scrollY + posX: w.scrollX || w.pageXOffset || w.document.documentElement.scrollLeft, + posY: w.scrollY || w.pageYOffset || w.document.documentElement.scrollTop }; // remove but log overscroll diff --git a/dist/ngScrollSpy.js b/dist/ngScrollSpy.js index fa73362..f208fc9 100755 --- a/dist/ngScrollSpy.js +++ b/dist/ngScrollSpy.js @@ -9,14 +9,24 @@ Licence: MIT mod.service('ScrollSpy', function($window) { var rawData= function(w) { + // Fix for IE browsers + // See https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollY?redirectlocale=en-US&redirectslug=DOM%2Fwindow.scrollY for more info + var innerWidth = w.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; + var innerHeight = w.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; + var supportPageOffset = w.pageXOffset !== undefined; + var isCSS1Compat = ((document.compatMode || "") === "CSS1Compat"); + + var scrollX = supportPageOffset ? w.pageXOffset : isCSS1Compat ? document.documentElement.scrollLeft : document.body.scrollLeft; + var scrollY= supportPageOffset ? w.pageYOffset : isCSS1Compat ? document.documentElement.scrollTop : document.body.scrollTop; + // retrieve interesting data var raw= { width: w.innerWidth, height: w.innerHeight, maxWidth: w.document.body.scrollWidth, maxHeight: w.document.body.scrollHeight, - posX: w.scrollX, - posY: w.scrollY + posX: w.scrollX || w.pageXOffset || w.document.documentElement.scrollLeft, + posY: w.scrollY || w.pageYOffset || w.document.documentElement.scrollTop }; // remove but log overscroll @@ -379,7 +389,7 @@ mod.directive('pageitems', function(ScrollSpy) { } var pos = spyElem.getBoundingClientRect().top; - if (Math.floor(pos) <= topmargin) { + if (pos <= topmargin) { // the window has been scrolled past the top of a spy element spy.pos = pos; @@ -559,4 +569,4 @@ mod.directive('pagemenuspy', function($location, $anchorScroll) { }); function getState() { return state; } -})(angular); +})(angular); \ No newline at end of file diff --git a/dist/ngScrollSpy.min.js b/dist/ngScrollSpy.min.js index fb68729..6ace399 100755 --- a/dist/ngScrollSpy.min.js +++ b/dist/ngScrollSpy.min.js @@ -2,4 +2,4 @@ Copyright (c) 2014 Magnús Örn Gylfason Licence: MIT */ -!function(t){"use strict";function n(){return o}var e=t.module("ngScrollSpy",[]);e.service("ScrollSpy",["$window",function(n){var e,o=function(t){var n={width:t.innerWidth,height:t.innerHeight,maxWidth:t.document.body.scrollWidth,maxHeight:t.document.body.scrollHeight,posX:t.scrollX,posY:t.scrollY};return n.posX<0?(n.posX=0,n.overscrollLeft=!0):n.posX+n.width>n.maxWidth&&(n.posX=n.maxWidth-n.width,n.overscrollRight=!0),n.posY<0?(n.posY=0,n.overscrollTop=!0):n.posY+n.height>n.maxHeight&&(n.posY=n.maxHeight-n.height,n.overscrollBottom=!0),n.hasOverscroll=n.overscrollTop||n.overscrollBottom||n.overscrollLeft||n.overscrollRight,n},i=function(n,e){if(!n||!e)return t.extend({isEqual:!1,velocityX:0,velocityY:0},e);var o={posX:e.posX-n.posX,posY:e.posY-n.posY,width:e.width-n.width,height:e.height-n.height,maxWidth:e.maxWidth-n.maxWidth,maxHeight:e.maxHeight-n.maxHeight};return e.width>0&&(o.velocityX=o.posX/e.width),e.height>0&&(o.velocityY=o.posY/e.height),o.isEqual=!(0!==o.posX||0!==o.posY||0!==o.width||0!==o.height||0!==o.maxWidth||0!==o.maxHeight),o},r={},l=function(t){var l=o(n),s=i(e,l);if(!s.isEqual||l.hasOverscroll||t){for(var c in r){var u=r[c].cond;(u(l,s)||t)&&r[c].handler(l,s)}e=l}};t.element(n).on("scroll",l);var s=this,c=0;this.trigger=function(){this.isForced=!0,l(!0),this.isForced=!1},this.addHandler=function(t,n){return r[c]={cond:t,handler:n},c++,c-1},this.removeHandler=function(t){delete r[t]},this.onScroll=function(t){return s.addHandler(function(){return!0},function(n,e){t(n,e)})},this.onXScroll=function(t){return s.addHandler(function(t,n){return 0!==n.posX},function(n,e){t(n.posX,e.posX,n,e)})},this.onYScroll=function(t){return s.addHandler(function(t,n){return 0!==n.posY},function(n,e){t(n.posY,e.posY,n,e)})},this.onOverscrollHorz=function(t){return s.addHandler(function(t){return t.overscrollLeft||t.overscrollRight},t)},this.onOverscrollLeft=function(t){return s.addHandler(function(t){return t.overscrollLeft},t)},this.onOverscrollRight=function(t){return s.addHandler(function(t){return t.overscrollRight},t)},this.onOverscrollVert=function(t){return s.addHandler(function(t){return t.overscrollTop||t.overscrollBottom},t)},this.onOverscrollTop=function(t){return s.addHandler(function(t){return t.overscrollTop},t)},this.onOverscrollBottom=function(t){return s.addHandler(function(t){return t.overscrollBottom},t)}}]),e.directive("affix",["ScrollSpy",function(t){var n,e=function(t,n,e,o){var i=t(o[0].getBoundingClientRect());i!==n&&(i?o.addClass(e):o.removeClass(e))},o=function(o,i,r){var l,s=!1,c=!1,u=!1;"top"===o?n=t.onYScroll(function(t){c=s,e(function(n){return s?s=t>=l:n.top<=0?(l=n.top<0?t+n.top:t,s=!0):!1},c,i,r)}):"bottom"===o?(u=!0,n=t.onYScroll(function(n,o,u){c=s,e(function(e){return s?s=l>=n:e.bottom>=u.height?(l=t.isForced&&0===n?n+e.bottom-u.height-e.height:n+e.bottom-u.height,s=!0):!1},c,i,r)})):"left"===o?n=t.onXScroll(function(t){c=s,e(function(n){return s?s=t>=l:n.left<=0?(l=n.left<0?t+n.left:t,s=!0):!1},c,i,r)}):"right"===o&&(u=!0,n=t.onXScroll(function(n,o,u){c=s,e(function(e){return s?s=l>=n:e.right>=u.width?(l=t.isForced&&0===n?n+e.right-u.width-e.width:n+e.right-u.width,s=!0):!1},c,i,r)})),u&&t.trigger()};return{restrict:"A",scope:{affix:"@",affixClass:"@"},link:function(e,i){e.affix=e.affix||"top",e.affixClass=e.affixClass||"affix",o(e.affix,e.affixClass,i),e.$on("destroy",function(){t.removeHandler(n)})}}}]);var o={onRun:null,state:null,store:function(t){for(var n in t)this[n]=t[n];this.state=!0,this.run()},builder:null,setBuilder:function(t){this.builder=t,this.run()},run:function(){this.builder&&this.state&&(this.builder(),this.builder=null,this.state=null,this.onRun&&(this.onRun(),this.onRun=null))}};e.directive("pageitems",["ScrollSpy",function(e){var o=function(o,i){if(t.isDefined(o.selector)){o.spyElems=i[0].getElementsByClassName(o.selector),o.spies={},n().onRun=function(){o.spies[o.spyElems[0].id].set()},n().store({topMargin:function(){return 0|o.topmargin},addSpy:function(t){o.spies[t.id]=t},getSpy:function(t){return o.spies[t]},items:function(){return o.spyElems}});var r=o.spyElems,l=0|o.topmargin,s=e.onYScroll(function(t,n,i){for(var c=null,u=o.spies,a=0;a=d?(f.pos=d,null===c&&(c=f),c.pos=i.maxHeight&&(c=u[r[r.length-1].id]),c.set(),o.$on("destroy",function(){e.removeHandler(s)})})}};return{restrict:"A",scope:{selector:"@",topmargin:"@"},link:o}}]),e.directive("pagemenu",["$compile","$location","$anchorScroll",function(t,e,o){var i=function(i,r){for(var l,s=[],c=[],u=function(t){for(var n={link:t.id,text:t.textContent||t.innerText,parent:""},e=t.tagName,o=0;o=0&&e!=s[r];r--);if(0>r)s.push(e),n.push=!0,c.push(l);else for(n.pop=i-1-r;s.length>r+1;)s.pop(),c.pop()}return c.length>0&&(n.parent=c[c.length-1]),l=n.link,n},a=n().items(),h="",f=0;f';else if(d.pop)for(var p=0;p";else 0!==f&&(h+="");h+='
  • ',h+='',h+=d.text,h+=""}h+="
  • ",r.append(t(h)(i)),r.on("click",function(t){var i=t.target.hash.substring(1);e.hash(i),o(),0!==n().topMargin()&&setTimeout(function(){window.scrollTo(window.pageXOffset,window.pageYOffset-n().topMargin())},0)})};return{restrict:"E",replace:!0,template:'',link:function(t,e){n().setBuilder(function(){i(t,e)})}}}]),e.directive("pagemenuspy",["$location","$anchorScroll",function(){return{restrict:"A",link:function(t,e,o){n().addSpy({id:o.pagemenuspy,parent:o.parent,set:function(){e.addClass("active");var t=n().getSpy(this.parent);t&&t.set()},clear:function(){e.removeClass("active")}})}}}])}(angular); \ No newline at end of file +!function(t){"use strict";function n(){return o}var e=t.module("ngScrollSpy",[]);e.service("ScrollSpy",["$window",function(n){var e,o=function(t){var n=(t.innerWidth||document.documentElement.clientWidth||document.body.clientWidth,t.innerHeight||document.documentElement.clientHeight||document.body.clientHeight,void 0!==t.pageXOffset),e="CSS1Compat"===(document.compatMode||""),o=(n?t.pageXOffset:e?document.documentElement.scrollLeft:document.body.scrollLeft,n?t.pageYOffset:e?document.documentElement.scrollTop:document.body.scrollTop,{width:t.innerWidth,height:t.innerHeight,maxWidth:t.document.body.scrollWidth,maxHeight:t.document.body.scrollHeight,posX:t.scrollX||t.pageXOffset||t.document.documentElement.scrollLeft,posY:t.scrollY||t.pageYOffset||t.document.documentElement.scrollTop});return o.posX<0?(o.posX=0,o.overscrollLeft=!0):o.posX+o.width>o.maxWidth&&(o.posX=o.maxWidth-o.width,o.overscrollRight=!0),o.posY<0?(o.posY=0,o.overscrollTop=!0):o.posY+o.height>o.maxHeight&&(o.posY=o.maxHeight-o.height,o.overscrollBottom=!0),o.hasOverscroll=o.overscrollTop||o.overscrollBottom||o.overscrollLeft||o.overscrollRight,o},i=function(n,e){if(!n||!e)return t.extend({isEqual:!1,velocityX:0,velocityY:0},e);var o={posX:e.posX-n.posX,posY:e.posY-n.posY,width:e.width-n.width,height:e.height-n.height,maxWidth:e.maxWidth-n.maxWidth,maxHeight:e.maxHeight-n.maxHeight};return e.width>0&&(o.velocityX=o.posX/e.width),e.height>0&&(o.velocityY=o.posY/e.height),o.isEqual=!(0!==o.posX||0!==o.posY||0!==o.width||0!==o.height||0!==o.maxWidth||0!==o.maxHeight),o},r={},l=function(t){var l=o(n),s=i(e,l);if(!s.isEqual||l.hasOverscroll||t){for(var c in r){var u=r[c].cond;(u(l,s)||t)&&r[c].handler(l,s)}e=l}};t.element(n).on("scroll",l);var s=this,c=0;this.trigger=function(){this.isForced=!0,l(!0),this.isForced=!1},this.addHandler=function(t,n){return r[c]={cond:t,handler:n},c++,c-1},this.removeHandler=function(t){delete r[t]},this.onScroll=function(t){return s.addHandler(function(){return!0},function(n,e){t(n,e)})},this.onXScroll=function(t){return s.addHandler(function(t,n){return 0!==n.posX},function(n,e){t(n.posX,e.posX,n,e)})},this.onYScroll=function(t){return s.addHandler(function(t,n){return 0!==n.posY},function(n,e){t(n.posY,e.posY,n,e)})},this.onOverscrollHorz=function(t){return s.addHandler(function(t,n){return t.overscrollLeft||t.overscrollRight},t)},this.onOverscrollLeft=function(t){return s.addHandler(function(t,n){return t.overscrollLeft},t)},this.onOverscrollRight=function(t){return s.addHandler(function(t,n){return t.overscrollRight},t)},this.onOverscrollVert=function(t){return s.addHandler(function(t,n){return t.overscrollTop||t.overscrollBottom},t)},this.onOverscrollTop=function(t){return s.addHandler(function(t,n){return t.overscrollTop},t)},this.onOverscrollBottom=function(t){return s.addHandler(function(t,n){return t.overscrollBottom},t)}}]),e.directive("affix",["ScrollSpy",function(t){var n,e=function(t,n,e,o){var i=t(o[0].getBoundingClientRect());i!==n&&(i?o.addClass(e):o.removeClass(e))},o=function(o,i,r){var l,s=!1,c=!1,u=!1;"top"===o?n=t.onYScroll(function(t){c=s,e(function(n){return s?s=t>=l:n.top<=0?(l=n.top<0?t+n.top:t,s=!0):!1},c,i,r)}):"bottom"===o?(u=!0,n=t.onYScroll(function(n,o,u){c=s,e(function(e){return s?s=l>=n:e.bottom>=u.height?(l=t.isForced&&0===n?n+e.bottom-u.height-e.height:n+e.bottom-u.height,s=!0):!1},c,i,r)})):"left"===o?n=t.onXScroll(function(t){c=s,e(function(n){return s?s=t>=l:n.left<=0?(l=n.left<0?t+n.left:t,s=!0):!1},c,i,r)}):"right"===o&&(u=!0,n=t.onXScroll(function(n,o,u){c=s,e(function(e){return s?s=l>=n:e.right>=u.width?(l=t.isForced&&0===n?n+e.right-u.width-e.width:n+e.right-u.width,s=!0):!1},c,i,r)})),u&&t.trigger()};return{restrict:"A",scope:{affix:"@",affixClass:"@"},link:function(e,i,r,l){e.affix=e.affix||"top",e.affixClass=e.affixClass||"affix",o(e.affix,e.affixClass,i),e.$on("destroy",function(){t.removeHandler(n)})}}}]);var o={onRun:null,state:null,store:function(t){for(var n in t)this[n]=t[n];this.state=!0,this.run()},builder:null,setBuilder:function(t){this.builder=t,this.run()},run:function(){this.builder&&this.state&&(this.builder(),this.builder=null,this.state=null,this.onRun&&(this.onRun(),this.onRun=null))}};e.directive("pageitems",["ScrollSpy",function(e){var o=function(o,i,r){if(t.isDefined(o.selector)){o.spyElems=i[0].getElementsByClassName(o.selector),o.spies={},n().onRun=function(){o.spies[o.spyElems[0].id].set()},n().store({topMargin:function(){return 0|o.topmargin},addSpy:function(t){o.spies[t.id]=t},getSpy:function(t){return o.spies[t]},items:function(){return o.spyElems}});var l=o.spyElems,s=0|o.topmargin,c=e.onYScroll(function(t,n,i){for(var r=null,u=o.spies,a=0;a=h?(f.pos=h,null===r&&(r=f),r.pos=i.maxHeight&&(r=u[l[l.length-1].id]),r.set(),o.$on("destroy",function(){e.removeHandler(c)})})}};return{restrict:"A",scope:{selector:"@",topmargin:"@"},link:o}}]),e.directive("pagemenu",["$compile","$location","$anchorScroll",function(t,e,o){var i=function(i,r){for(var l,s=[],c=[],u=function(t){for(var n={link:t.id,text:t.textContent||t.innerText,parent:""},e=t.tagName,o=0;o=0&&e!=s[r];r--);if(0>r)s.push(e),n.push=!0,c.push(l);else for(n.pop=i-1-r;s.length>r+1;)s.pop(),c.pop()}return c.length>0&&(n.parent=c[c.length-1]),l=n.link,n},a=n().items(),d="",f=0;f';else if(h.pop)for(var p=0;p";else 0!==f&&(d+="");d+='
  • ',d+='',d+=h.text,d+=""}d+="
  • ",r.append(t(d)(i)),r.on("click",function(t){var i=t.target.hash.substring(1);e.hash(i),o(),0!==n().topMargin()&&setTimeout(function(){window.scrollTo(window.pageXOffset,window.pageYOffset-n().topMargin())},0)})};return{restrict:"E",replace:!0,template:'',link:function(t,e){n().setBuilder(function(){i(t,e)})}}}]),e.directive("pagemenuspy",["$location","$anchorScroll",function(t,e){return{restrict:"A",link:function(t,e,o){n().addSpy({id:o.pagemenuspy,parent:o.parent,set:function(){e.addClass("active");var t=n().getSpy(this.parent);t&&t.set()},clear:function(){e.removeClass("active")}})}}}])}(angular); \ No newline at end of file diff --git a/src/scrollspy.js b/src/scrollspy.js index 25ecb7f..0bfb68a 100644 --- a/src/scrollspy.js +++ b/src/scrollspy.js @@ -1,5 +1,15 @@ mod.service('ScrollSpy', function($window) { var rawData= function(w) { + // Fix for IE browsers + // See https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollY?redirectlocale=en-US&redirectslug=DOM%2Fwindow.scrollY for more info + var innerWidth = w.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; + var innerHeight = w.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; + var supportPageOffset = w.pageXOffset !== undefined; + var isCSS1Compat = ((document.compatMode || "") === "CSS1Compat"); + + var scrollX = supportPageOffset ? w.pageXOffset : isCSS1Compat ? document.documentElement.scrollLeft : document.body.scrollLeft; + var scrollY= supportPageOffset ? w.pageYOffset : isCSS1Compat ? document.documentElement.scrollTop : document.body.scrollTop; + // retrieve interesting data var raw= { width: w.innerWidth,