From 87c91dc8f04a0dcb3c67d103eaeb8d3c919db494 Mon Sep 17 00:00:00 2001 From: tricinel Date: Fri, 15 Apr 2016 15:12:00 +0200 Subject: [PATCH 1/2] Add new infiniteScrollReset parameter to allow for easier list updates This parameter is needed if you want to reuse the same infinite scroll directive and your items will completely change. A use case is a file browser where you navigate the folder structure and you want all the levels of the hierarchy to benefit from infinite scroll. Without a reset such as this, as soon as you scroll to the bottom of the list, subsequent lists that are not bigger than that will no longer have infinite scroll. You can call the reset by adding an event listener and setting the reset to true. e.g.
[...]
--- build/ng-infinite-scroll.js | 20 ++++++++++++++------ build/ng-infinite-scroll.min.js | 4 ++-- src/infinite-scroll.coffee | 14 ++++++++++---- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/build/ng-infinite-scroll.js b/build/ng-infinite-scroll.js index 37d76b3..113be44 100644 --- a/build/ng-infinite-scroll.js +++ b/build/ng-infinite-scroll.js @@ -1,4 +1,4 @@ -/* ng-infinite-scroll - v1.2.1 - 2016-02-09 */ +/* ng-infinite-scroll - v1.2.1 - 2016-04-15 */ var mod; mod = angular.module('infinite-scroll', []); @@ -14,7 +14,8 @@ mod.directive('infiniteScroll', [ infiniteScrollDistance: '=', infiniteScrollDisabled: '=', infiniteScrollUseDocumentBottom: '=', - infiniteScrollListenForEvent: '@' + infiniteScrollListenForEvent: '@', + infiniteScrollReset: '=' }, link: function(scope, elem, attrs) { var changeContainer, checkInterval, checkWhenEnabled, container, handleInfiniteScrollContainer, handleInfiniteScrollDisabled, handleInfiniteScrollDistance, handleInfiniteScrollUseDocumentBottom, handler, height, immediateCheck, offsetTop, pageYOffset, scrollDistance, scrollEnabled, throttle, unregisterEventListener, useDocumentBottom, windowElement; @@ -49,8 +50,9 @@ mod.directive('infiniteScroll', [ return elem.ownerDocument.defaultView.pageYOffset; } }; - handler = function() { + handler = function(event, reset) { var containerBottom, containerTopOffset, elementBottom, remaining, shouldScroll; + reset = reset || false; if (container === windowElement) { containerBottom = height(container) + pageYOffset(container[0].document.documentElement); elementBottom = offsetTop(elem) + height(elem); @@ -66,9 +68,10 @@ mod.directive('infiniteScroll', [ elementBottom = height((elem[0].ownerDocument || elem[0].document).documentElement); } remaining = elementBottom - containerBottom; - shouldScroll = remaining <= height(container) * scrollDistance + 1; + shouldScroll = reset ? true : remaining <= height(container) * scrollDistance + 1; if (shouldScroll) { checkWhenEnabled = true; + scrollEnabled = reset ? true : scrollEnabled; if (scrollEnabled) { if (scope.$$phase || $rootScope.$$phase) { return scope.infiniteScroll(); @@ -116,7 +119,10 @@ mod.directive('infiniteScroll', [ container.unbind('scroll', handler); if (unregisterEventListener != null) { unregisterEventListener(); - return unregisterEventListener = null; + unregisterEventListener = null; + } + if (checkInterval) { + return $interval.cancel(checkInterval); } }); handleInfiniteScrollDistance = function(v) { @@ -149,7 +155,9 @@ mod.directive('infiniteScroll', [ }; changeContainer(windowElement); if (scope.infiniteScrollListenForEvent) { - unregisterEventListener = $rootScope.$on(scope.infiniteScrollListenForEvent, handler); + unregisterEventListener = $rootScope.$on(scope.infiniteScrollListenForEvent, function(event) { + handler(event, scope.infiniteScrollReset ? scroll.infiniteScrollReset : false); + }); } handleInfiniteScrollContainer = function(newContainer) { if ((newContainer == null) || newContainer.length === 0) { diff --git a/build/ng-infinite-scroll.min.js b/build/ng-infinite-scroll.min.js index 3f4f59c..c2e5222 100644 --- a/build/ng-infinite-scroll.min.js +++ b/build/ng-infinite-scroll.min.js @@ -1,2 +1,2 @@ -/* ng-infinite-scroll - v1.2.1 - 2016-02-09 */ -var mod;mod=angular.module("infinite-scroll",[]),mod.value("THROTTLE_MILLISECONDS",null),mod.directive("infiniteScroll",["$rootScope","$window","$interval","THROTTLE_MILLISECONDS",function(a,b,c,d){return{scope:{infiniteScroll:"&",infiniteScrollContainer:"=",infiniteScrollDistance:"=",infiniteScrollDisabled:"=",infiniteScrollUseDocumentBottom:"=",infiniteScrollListenForEvent:"@"},link:function(e,f,g){var h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z;return z=angular.element(b),u=null,v=null,j=null,k=null,r=!0,y=!1,x=null,i=!1,q=function(a){return a=a[0]||a,isNaN(a.offsetHeight)?a.document.documentElement.clientHeight:a.offsetHeight},s=function(a){return a[0].getBoundingClientRect&&!a.css("none")?a[0].getBoundingClientRect().top+t(a):void 0},t=function(a){return a=a[0]||a,isNaN(window.pageYOffset)?a.document.documentElement.scrollTop:a.ownerDocument.defaultView.pageYOffset},p=function(){var b,d,g,h,l;return k===z?(b=q(k)+t(k[0].document.documentElement),g=s(f)+q(f)):(b=q(k),d=0,void 0!==s(k)&&(d=s(k)),g=s(f)-d+q(f)),y&&(g=q((f[0].ownerDocument||f[0].document).documentElement)),h=g-b,l=h<=q(k)*u+1,l?(j=!0,v?e.$$phase||a.$$phase?e.infiniteScroll():e.$apply(e.infiniteScroll):void 0):(i&&c.cancel(i),j=!1)},w=function(a,b){var d,e,f;return f=null,e=0,d=function(){return e=(new Date).getTime(),c.cancel(f),f=null,a.call()},function(){var g,h;return g=(new Date).getTime(),h=b-(g-e),0>=h?(c.cancel(f),f=null,e=g,a.call()):f?void 0:f=c(d,h,1)}},null!=d&&(p=w(p,d)),e.$on("$destroy",function(){return k.unbind("scroll",p),null!=x?(x(),x=null):void 0}),n=function(a){return u=parseFloat(a)||0},e.$watch("infiniteScrollDistance",n),n(e.infiniteScrollDistance),m=function(a){return v=!a,v&&j?(j=!1,p()):void 0},e.$watch("infiniteScrollDisabled",m),m(e.infiniteScrollDisabled),o=function(a){return y=a},e.$watch("infiniteScrollUseDocumentBottom",o),o(e.infiniteScrollUseDocumentBottom),h=function(a){return null!=k&&k.unbind("scroll",p),k=a,null!=a?k.bind("scroll",p):void 0},h(z),e.infiniteScrollListenForEvent&&(x=a.$on(e.infiniteScrollListenForEvent,p)),l=function(a){if(null!=a&&0!==a.length){if(a.nodeType&&1===a.nodeType?a=angular.element(a):"function"==typeof a.append?a=angular.element(a[a.length-1]):"string"==typeof a&&(a=angular.element(document.querySelector(a))),null!=a)return h(a);throw new Error("invalid infinite-scroll-container attribute.")}},e.$watch("infiniteScrollContainer",l),l(e.infiniteScrollContainer||[]),null!=g.infiniteScrollParent&&h(angular.element(f.parent())),null!=g.infiniteScrollImmediateCheck&&(r=e.$eval(g.infiniteScrollImmediateCheck)),i=c(function(){return r&&p(),c.cancel(i)})}}}]); \ No newline at end of file +/* ng-infinite-scroll - v1.2.1 - 2016-04-15 */ +var mod;mod=angular.module("infinite-scroll",[]),mod.value("THROTTLE_MILLISECONDS",null),mod.directive("infiniteScroll",["$rootScope","$window","$interval","THROTTLE_MILLISECONDS",function(a,b,c,d){return{scope:{infiniteScroll:"&",infiniteScrollContainer:"=",infiniteScrollDistance:"=",infiniteScrollDisabled:"=",infiniteScrollUseDocumentBottom:"=",infiniteScrollListenForEvent:"@",infiniteScrollReset:"="},link:function(e,f,g){var h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z;return z=angular.element(b),u=null,v=null,j=null,k=null,r=!0,y=!1,x=null,i=!1,q=function(a){return a=a[0]||a,isNaN(a.offsetHeight)?a.document.documentElement.clientHeight:a.offsetHeight},s=function(a){return a[0].getBoundingClientRect&&!a.css("none")?a[0].getBoundingClientRect().top+t(a):void 0},t=function(a){return a=a[0]||a,isNaN(window.pageYOffset)?a.document.documentElement.scrollTop:a.ownerDocument.defaultView.pageYOffset},p=function(b,d){var g,h,l,m,n;return d=d||!1,k===z?(g=q(k)+t(k[0].document.documentElement),l=s(f)+q(f)):(g=q(k),h=0,void 0!==s(k)&&(h=s(k)),l=s(f)-h+q(f)),y&&(l=q((f[0].ownerDocument||f[0].document).documentElement)),m=l-g,n=d?!0:m<=q(k)*u+1,n?(j=!0,(v=d?!0:v)?e.$$phase||a.$$phase?e.infiniteScroll():e.$apply(e.infiniteScroll):void 0):(i&&c.cancel(i),j=!1)},w=function(a,b){var d,e,f;return f=null,e=0,d=function(){return e=(new Date).getTime(),c.cancel(f),f=null,a.call()},function(){var g,h;return g=(new Date).getTime(),h=b-(g-e),0>=h?(c.cancel(f),f=null,e=g,a.call()):f?void 0:f=c(d,h,1)}},null!=d&&(p=w(p,d)),e.$on("$destroy",function(){return k.unbind("scroll",p),null!=x&&(x(),x=null),i?c.cancel(i):void 0}),n=function(a){return u=parseFloat(a)||0},e.$watch("infiniteScrollDistance",n),n(e.infiniteScrollDistance),m=function(a){return v=!a,v&&j?(j=!1,p()):void 0},e.$watch("infiniteScrollDisabled",m),m(e.infiniteScrollDisabled),o=function(a){return y=a},e.$watch("infiniteScrollUseDocumentBottom",o),o(e.infiniteScrollUseDocumentBottom),h=function(a){return null!=k&&k.unbind("scroll",p),k=a,null!=a?k.bind("scroll",p):void 0},h(z),e.infiniteScrollListenForEvent&&(x=a.$on(e.infiniteScrollListenForEvent,function(a){p(a,e.infiniteScrollReset?scroll.infiniteScrollReset:!1)})),l=function(a){if(null!=a&&0!==a.length){if(a.nodeType&&1===a.nodeType?a=angular.element(a):"function"==typeof a.append?a=angular.element(a[a.length-1]):"string"==typeof a&&(a=angular.element(document.querySelector(a))),null!=a)return h(a);throw new Error("invalid infinite-scroll-container attribute.")}},e.$watch("infiniteScrollContainer",l),l(e.infiniteScrollContainer||[]),null!=g.infiniteScrollParent&&h(angular.element(f.parent())),null!=g.infiniteScrollImmediateCheck&&(r=e.$eval(g.infiniteScrollImmediateCheck)),i=c(function(){return r&&p(),c.cancel(i)})}}}]); \ No newline at end of file diff --git a/src/infinite-scroll.coffee b/src/infinite-scroll.coffee index 8c42929..0efff8c 100644 --- a/src/infinite-scroll.coffee +++ b/src/infinite-scroll.coffee @@ -11,6 +11,7 @@ mod.directive 'infiniteScroll', ['$rootScope', '$window', '$interval', 'THROTTLE infiniteScrollDisabled: '=' infiniteScrollUseDocumentBottom: '=', infiniteScrollListenForEvent: '@' + infiniteScrollReset: '=' link: (scope, elem, attrs) -> windowElement = angular.element($window) @@ -46,7 +47,8 @@ mod.directive 'infiniteScroll', ['$rootScope', '$window', '$interval', 'THROTTLE # document. It is recommended to use infinite-scroll-disabled # with a boolean that is set to true when the function is # called in order to throttle the function call. - handler = -> + handler = (event, reset) -> + reset = reset || false if container == windowElement containerBottom = height(container) + pageYOffset(container[0].document.documentElement) elementBottom = offsetTop(elem) + height(elem) @@ -61,11 +63,13 @@ mod.directive 'infiniteScroll', ['$rootScope', '$window', '$interval', 'THROTTLE elementBottom = height((elem[0].ownerDocument || elem[0].document).documentElement) remaining = elementBottom - containerBottom - shouldScroll = remaining <= height(container) * scrollDistance + 1 + shouldScroll = if reset then true else remaining <= height(container) * scrollDistance + 1 if shouldScroll checkWhenEnabled = true + scrollEnabled = if reset then true else scrollEnabled + if scrollEnabled if scope.$$phase || $rootScope.$$phase scope.infiniteScroll() @@ -108,7 +112,7 @@ mod.directive 'infiniteScroll', ['$rootScope', '$window', '$interval', 'THROTTLE if unregisterEventListener? unregisterEventListener() unregisterEventListener = null - if checkInterval + if checkInterval $interval.cancel checkInterval # infinite-scroll-distance specifies how close to the bottom of the page @@ -163,7 +167,9 @@ mod.directive 'infiniteScroll', ['$rootScope', '$window', '$interval', 'THROTTLE changeContainer windowElement if scope.infiniteScrollListenForEvent - unregisterEventListener = $rootScope.$on scope.infiniteScrollListenForEvent, handler + unregisterEventListener = $rootScope.$on scope.infiniteScrollListenForEvent, (event) -> + handler event, if scope.infiniteScrollReset then scroll.infiniteScrollReset else false + return handleInfiniteScrollContainer = (newContainer) -> # TODO: For some reason newContainer is sometimes null instead From 1d6b52b8ad06162f4139c55e537e45d37ad5245c Mon Sep 17 00:00:00 2001 From: tricinel Date: Fri, 15 Apr 2016 15:29:20 +0200 Subject: [PATCH 2/2] Fix silly typo --- build/ng-infinite-scroll.js | 2 +- build/ng-infinite-scroll.min.js | 2 +- src/infinite-scroll.coffee | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build/ng-infinite-scroll.js b/build/ng-infinite-scroll.js index 113be44..ba4f604 100644 --- a/build/ng-infinite-scroll.js +++ b/build/ng-infinite-scroll.js @@ -156,7 +156,7 @@ mod.directive('infiniteScroll', [ changeContainer(windowElement); if (scope.infiniteScrollListenForEvent) { unregisterEventListener = $rootScope.$on(scope.infiniteScrollListenForEvent, function(event) { - handler(event, scope.infiniteScrollReset ? scroll.infiniteScrollReset : false); + handler(event, scope.infiniteScrollReset ? scope.infiniteScrollReset : false); }); } handleInfiniteScrollContainer = function(newContainer) { diff --git a/build/ng-infinite-scroll.min.js b/build/ng-infinite-scroll.min.js index c2e5222..314abb7 100644 --- a/build/ng-infinite-scroll.min.js +++ b/build/ng-infinite-scroll.min.js @@ -1,2 +1,2 @@ /* ng-infinite-scroll - v1.2.1 - 2016-04-15 */ -var mod;mod=angular.module("infinite-scroll",[]),mod.value("THROTTLE_MILLISECONDS",null),mod.directive("infiniteScroll",["$rootScope","$window","$interval","THROTTLE_MILLISECONDS",function(a,b,c,d){return{scope:{infiniteScroll:"&",infiniteScrollContainer:"=",infiniteScrollDistance:"=",infiniteScrollDisabled:"=",infiniteScrollUseDocumentBottom:"=",infiniteScrollListenForEvent:"@",infiniteScrollReset:"="},link:function(e,f,g){var h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z;return z=angular.element(b),u=null,v=null,j=null,k=null,r=!0,y=!1,x=null,i=!1,q=function(a){return a=a[0]||a,isNaN(a.offsetHeight)?a.document.documentElement.clientHeight:a.offsetHeight},s=function(a){return a[0].getBoundingClientRect&&!a.css("none")?a[0].getBoundingClientRect().top+t(a):void 0},t=function(a){return a=a[0]||a,isNaN(window.pageYOffset)?a.document.documentElement.scrollTop:a.ownerDocument.defaultView.pageYOffset},p=function(b,d){var g,h,l,m,n;return d=d||!1,k===z?(g=q(k)+t(k[0].document.documentElement),l=s(f)+q(f)):(g=q(k),h=0,void 0!==s(k)&&(h=s(k)),l=s(f)-h+q(f)),y&&(l=q((f[0].ownerDocument||f[0].document).documentElement)),m=l-g,n=d?!0:m<=q(k)*u+1,n?(j=!0,(v=d?!0:v)?e.$$phase||a.$$phase?e.infiniteScroll():e.$apply(e.infiniteScroll):void 0):(i&&c.cancel(i),j=!1)},w=function(a,b){var d,e,f;return f=null,e=0,d=function(){return e=(new Date).getTime(),c.cancel(f),f=null,a.call()},function(){var g,h;return g=(new Date).getTime(),h=b-(g-e),0>=h?(c.cancel(f),f=null,e=g,a.call()):f?void 0:f=c(d,h,1)}},null!=d&&(p=w(p,d)),e.$on("$destroy",function(){return k.unbind("scroll",p),null!=x&&(x(),x=null),i?c.cancel(i):void 0}),n=function(a){return u=parseFloat(a)||0},e.$watch("infiniteScrollDistance",n),n(e.infiniteScrollDistance),m=function(a){return v=!a,v&&j?(j=!1,p()):void 0},e.$watch("infiniteScrollDisabled",m),m(e.infiniteScrollDisabled),o=function(a){return y=a},e.$watch("infiniteScrollUseDocumentBottom",o),o(e.infiniteScrollUseDocumentBottom),h=function(a){return null!=k&&k.unbind("scroll",p),k=a,null!=a?k.bind("scroll",p):void 0},h(z),e.infiniteScrollListenForEvent&&(x=a.$on(e.infiniteScrollListenForEvent,function(a){p(a,e.infiniteScrollReset?scroll.infiniteScrollReset:!1)})),l=function(a){if(null!=a&&0!==a.length){if(a.nodeType&&1===a.nodeType?a=angular.element(a):"function"==typeof a.append?a=angular.element(a[a.length-1]):"string"==typeof a&&(a=angular.element(document.querySelector(a))),null!=a)return h(a);throw new Error("invalid infinite-scroll-container attribute.")}},e.$watch("infiniteScrollContainer",l),l(e.infiniteScrollContainer||[]),null!=g.infiniteScrollParent&&h(angular.element(f.parent())),null!=g.infiniteScrollImmediateCheck&&(r=e.$eval(g.infiniteScrollImmediateCheck)),i=c(function(){return r&&p(),c.cancel(i)})}}}]); \ No newline at end of file +var mod;mod=angular.module("infinite-scroll",[]),mod.value("THROTTLE_MILLISECONDS",null),mod.directive("infiniteScroll",["$rootScope","$window","$interval","THROTTLE_MILLISECONDS",function(a,b,c,d){return{scope:{infiniteScroll:"&",infiniteScrollContainer:"=",infiniteScrollDistance:"=",infiniteScrollDisabled:"=",infiniteScrollUseDocumentBottom:"=",infiniteScrollListenForEvent:"@",infiniteScrollReset:"="},link:function(e,f,g){var h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z;return z=angular.element(b),u=null,v=null,j=null,k=null,r=!0,y=!1,x=null,i=!1,q=function(a){return a=a[0]||a,isNaN(a.offsetHeight)?a.document.documentElement.clientHeight:a.offsetHeight},s=function(a){return a[0].getBoundingClientRect&&!a.css("none")?a[0].getBoundingClientRect().top+t(a):void 0},t=function(a){return a=a[0]||a,isNaN(window.pageYOffset)?a.document.documentElement.scrollTop:a.ownerDocument.defaultView.pageYOffset},p=function(b,d){var g,h,l,m,n;return d=d||!1,k===z?(g=q(k)+t(k[0].document.documentElement),l=s(f)+q(f)):(g=q(k),h=0,void 0!==s(k)&&(h=s(k)),l=s(f)-h+q(f)),y&&(l=q((f[0].ownerDocument||f[0].document).documentElement)),m=l-g,n=d?!0:m<=q(k)*u+1,n?(j=!0,(v=d?!0:v)?e.$$phase||a.$$phase?e.infiniteScroll():e.$apply(e.infiniteScroll):void 0):(i&&c.cancel(i),j=!1)},w=function(a,b){var d,e,f;return f=null,e=0,d=function(){return e=(new Date).getTime(),c.cancel(f),f=null,a.call()},function(){var g,h;return g=(new Date).getTime(),h=b-(g-e),0>=h?(c.cancel(f),f=null,e=g,a.call()):f?void 0:f=c(d,h,1)}},null!=d&&(p=w(p,d)),e.$on("$destroy",function(){return k.unbind("scroll",p),null!=x&&(x(),x=null),i?c.cancel(i):void 0}),n=function(a){return u=parseFloat(a)||0},e.$watch("infiniteScrollDistance",n),n(e.infiniteScrollDistance),m=function(a){return v=!a,v&&j?(j=!1,p()):void 0},e.$watch("infiniteScrollDisabled",m),m(e.infiniteScrollDisabled),o=function(a){return y=a},e.$watch("infiniteScrollUseDocumentBottom",o),o(e.infiniteScrollUseDocumentBottom),h=function(a){return null!=k&&k.unbind("scroll",p),k=a,null!=a?k.bind("scroll",p):void 0},h(z),e.infiniteScrollListenForEvent&&(x=a.$on(e.infiniteScrollListenForEvent,function(a){p(a,e.infiniteScrollReset?e.infiniteScrollReset:!1)})),l=function(a){if(null!=a&&0!==a.length){if(a.nodeType&&1===a.nodeType?a=angular.element(a):"function"==typeof a.append?a=angular.element(a[a.length-1]):"string"==typeof a&&(a=angular.element(document.querySelector(a))),null!=a)return h(a);throw new Error("invalid infinite-scroll-container attribute.")}},e.$watch("infiniteScrollContainer",l),l(e.infiniteScrollContainer||[]),null!=g.infiniteScrollParent&&h(angular.element(f.parent())),null!=g.infiniteScrollImmediateCheck&&(r=e.$eval(g.infiniteScrollImmediateCheck)),i=c(function(){return r&&p(),c.cancel(i)})}}}]); \ No newline at end of file diff --git a/src/infinite-scroll.coffee b/src/infinite-scroll.coffee index 0efff8c..985d642 100644 --- a/src/infinite-scroll.coffee +++ b/src/infinite-scroll.coffee @@ -168,7 +168,7 @@ mod.directive 'infiniteScroll', ['$rootScope', '$window', '$interval', 'THROTTLE if scope.infiniteScrollListenForEvent unregisterEventListener = $rootScope.$on scope.infiniteScrollListenForEvent, (event) -> - handler event, if scope.infiniteScrollReset then scroll.infiniteScrollReset else false + handler event, if scope.infiniteScrollReset then scope.infiniteScrollReset else false return handleInfiniteScrollContainer = (newContainer) ->