diff --git a/demo/examples/applyUpdate.html b/demo/examples/applyUpdate.html index 5c3270f3..59479daf 100644 --- a/demo/examples/applyUpdate.html +++ b/demo/examples/applyUpdate.html @@ -3,7 +3,7 @@
0&&(K.clipTop(),J.append(c)),J.setUpper(),B(b))}):J.length&&!K.shouldLoadTop()?B(b):N(function(c){return b&&b!==H||a.$$destroyed?void 0:(c.length
0&&(J.length&&K.clipBottom(),J.prepend(c)),J.setLower(),B(b))})}function D(){P=!0}function E(){d.$$phase||L.isLoading||A()}function F(a){var b=K[0].scrollTop,c=K[0].scrollHeight-K[0].clientHeight;(0===b&&!J.bof||b===c&&!J.eof)&&a.preventDefault()}r=r||i;var G=function(){function b(){return angular.isObject(d)&&angular.isFunction(d.get)}var d=g(l)(a);if(!b()&&(d=c.get(l),!b()))throw new Error(l+" is not a valid datasource");return d}(),H=0,I=[],J=new m(k,a,r,p),K=new n(J,b,q,j),L=new o(j,K,J,function(){return s(),z(H)}),M=function(){return 2!==G.get.length?function(a){return G.get(J.next,p,a)}:function(a){return G.get({index:J.next,append:J.length?J[J.length-1].item:void 0,count:p},a)}}(),N=function(){return 2!==G.get.length?function(a){return G.get(J.first-p,p,a)}:function(a){return G.get({index:J.first-p,prepend:J.length?J[0].item:void 0,count:p},a)}}();if(j.adapter){var O=g(j.adapter)(a);angular.isObject(O)||(g(j.adapter).assign(a,{}),O=g(j.adapter)(a)),L=angular.extend(O,L)}r(a.$new(),function(a,b){K.createPaddingElements(a[0]),b.$destroy(),a.remove()}),L.reload=t;var P=!1,Q=void 0;K.bind("resize",E),K.bind("scroll",D),K.bind("mousewheel",F),a.$on("$destroy",function(){J.clear(),K.unbind("resize",E),K.unbind("scroll",E),K.unbind("mousewheel",F),Q&&Q.cancel()}),function(){function b(a){throw new Error(a+" event is no longer supported - use applyUpdates instead")}var c=G.scope?G.scope.$new():a.$new();c.$on("insert.item",function(){return b("insert")}),c.$on("update.items",function(){return b("update")}),c.$on("delete.items",function(){return b("delete")})}(),t(),Q=h(function(){P&&!L.isLoading&&(P=!1,A())},100,0,!1)}}var q=c.has&&c.has("$animate")?c.get("$animate"):null,r=1===angular.version.major&&angular.version.minor<3;return{require:["?^uiScrollViewport"],transclude:"element",priority:1e3,terminal:!0,compile:p}}])}(); \ No newline at end of file diff --git a/src/ui-scroll.js b/src/ui-scroll.js index 7bb00e28..504ce378 100644 --- a/src/ui-scroll.js +++ b/src/ui-scroll.js @@ -30,7 +30,8 @@ angular.module('ui.scroll', []) '$timeout', '$q', '$parse', - function (console, $injector, $rootScope, $timeout, $q, $parse) { + '$interval', + function (console, $injector, $rootScope, $timeout, $q, $parse, $interval) { const $animate = ($injector.has && $injector.has('$animate')) ? $injector.get('$animate') : null; const isAngularVersionLessThen1_3 = angular.version.major === 1 && angular.version.minor < 3; //const log = console.debug || console.log; @@ -370,7 +371,13 @@ angular.module('ui.scroll', []) const setTopVisible = $attr.topVisible ? $parse($attr.topVisible).assign : angular.noop; const setTopVisibleElement = $attr.topVisibleElement ? $parse($attr.topVisibleElement).assign : angular.noop; const setTopVisibleScope = $attr.topVisibleScope ? $parse($attr.topVisibleScope).assign : angular.noop; - const setIsLoading = $attr.isLoading ? $parse($attr.isLoading).assign : angular.noop; + const setIsLoading = $attr.isLoading ? setLoadingWithApply : angular.noop; + + function setLoadingWithApply(viewportScope, value) { + return $timeout(() => { + $parse($attr.isLoading).assign(viewportScope, value); + }); + } this.isLoading = false; @@ -561,17 +568,23 @@ angular.module('ui.scroll', []) adapter.reload = reload; + let scrolling = false; + let scrollInterval; + // events and bindings - viewport.bind('resize', resizeAndScrollHandler); - viewport.bind('scroll', resizeAndScrollHandler); + viewport.bind('resize', resizeHandler); + viewport.bind('scroll', scrollHandler); viewport.bind('mousewheel', wheelHandler); $scope.$on('$destroy', () => { // clear the buffer. It is necessary to remove the elements and $destroy the scopes buffer.clear(); - viewport.unbind('resize', resizeAndScrollHandler); - viewport.unbind('scroll', resizeAndScrollHandler); + viewport.unbind('resize', resizeHandler); + viewport.unbind('scroll', resizeHandler); viewport.unbind('mousewheel', wheelHandler); + if(scrollInterval) { + scrollInterval.cancel(); + } }); // update events (deprecated since v1.1.0, unsupported since 1.2.0) @@ -716,18 +729,23 @@ angular.module('ui.scroll', []) function adjustBuffer(rid) { // We need the item bindings to be processed before we can do adjustment return $timeout(() => { - processBufferedItems(rid); + return adjustBufferWithoutTimeout(rid); + }); - if (viewport.shouldLoadBottom()) { - enqueueFetch(rid, true); - } else if (viewport.shouldLoadTop()) { - enqueueFetch(rid, false); - } - if (!pending.length) { - return adapter.calculateProperties(); - } - }); + } + + function adjustBufferWithoutTimeout(rid) { + processBufferedItems(rid); + if (viewport.shouldLoadBottom()) { + enqueueFetch(rid, true); + } else if (viewport.shouldLoadTop()) { + enqueueFetch(rid, false); + } + + if (!pending.length) { + return adapter.calculateProperties(); + } } function adjustBufferAfterFetch(rid) { @@ -810,9 +828,20 @@ angular.module('ui.scroll', []) }); } - function resizeAndScrollHandler() { + function scrollHandler() { + scrolling = true; + } + + scrollInterval = $interval(function() { + if(scrolling && !adapter.isLoading) { + scrolling = false; + adjustBufferWithoutTimeout(); + } + }, 100, 0, false); + + function resizeHandler() { if (!$rootScope.$$phase && !adapter.isLoading) { - adjustBuffer(); + adjustBufferWithoutTimeout(); } } diff --git a/test/BasicTestsSpec.js b/test/BasicTestsSpec.js index f53d6079..f8b3072b 100644 --- a/test/BasicTestsSpec.js +++ b/test/BasicTestsSpec.js @@ -155,10 +155,12 @@ describe('uiScroll', function () { var itemsWithPaddings = itemsLoaded + 2; runTest(scrollSettings, function (viewport) { - viewport.scrollTop(100); - viewport.trigger('scroll'); - inject(function ($timeout) { - $timeout.flush(); + inject(function ($interval) { + viewport.scrollTop(100); + viewport.trigger('scroll'); + + $interval.flush(120); + expect(viewport.children().length).toBe(itemsWithPaddings); expect(viewport.scrollTop()).toBe(100); expect(viewport.children().css('height')).toBe('0px'); @@ -180,46 +182,53 @@ describe('uiScroll', function () { spy = spyOn(myMultipageDatasource, 'get').and.callThrough(); }); runTest(scrollSettings, - function (viewport, scope, $timeout) { - viewport.scrollTop(100); - viewport.trigger('scroll'); - $timeout.flush(); + function (viewport) { + inject(function ($interval) { + viewport.scrollTop(100); + viewport.trigger('scroll'); - expect(spy.calls.all().length).toBe(5); + $interval.flush(120); - expect(spy.calls.all()[0].args[0]).toBe(1); - expect(spy.calls.all()[1].args[0]).toBe(4); - expect(spy.calls.all()[2].args[0]).toBe(7); - expect(spy.calls.all()[3].args[0]).toBe(-2); - expect(spy.calls.all()[4].args[0]).toBe(10); + expect(spy.calls.all().length).toBe(5); + + expect(spy.calls.all()[0].args[0]).toBe(1); + expect(spy.calls.all()[1].args[0]).toBe(4); + expect(spy.calls.all()[2].args[0]).toBe(7); + expect(spy.calls.all()[3].args[0]).toBe(-2); + expect(spy.calls.all()[4].args[0]).toBe(10); + }); } ); }); it('should clip 4 divs from the top and add 3 more divs to the bottom (11 divs total) (+ 2 padding divs)', function () { runTest(scrollSettings, - function (viewport, scope, $timeout) { - var itemsLoaded = 11; - var itemsWithPaddings = itemsLoaded + 2; - var clippedDivs = 4; - viewport.scrollTop(100); - viewport.trigger('scroll'); - $timeout.flush(); - - viewport.scrollTop(400); - viewport.trigger('scroll'); - $timeout.flush(); - - expect(viewport.children().length).toBe(itemsWithPaddings); - expect(viewport.scrollTop()).toBe(280); - expect(viewport.children().css('height')).toBe('160px'); - expect(angular.element(viewport.children()[itemsWithPaddings-1]).css('height')).toBe('0px'); - - for (var i = 1; i <= itemsLoaded; i++) { - var row = viewport.children()[i]; - expect(row.tagName.toLowerCase()).toBe('div'); - expect(row.innerHTML).toBe((i + clippedDivs) + ': item' + (i + clippedDivs)); - } + function (viewport) { + inject(function ($interval) { + var itemsLoaded = 11; + var itemsWithPaddings = itemsLoaded + 2; + var clippedDivs = 4; + + viewport.scrollTop(100); + viewport.trigger('scroll'); + + $interval.flush(120); + + viewport.scrollTop(400); + viewport.trigger('scroll'); + $interval.flush(120); + + expect(viewport.children().length).toBe(itemsWithPaddings); + expect(viewport.scrollTop()).toBe(280); + expect(viewport.children().css('height')).toBe('160px'); + expect(angular.element(viewport.children()[itemsWithPaddings - 1]).css('height')).toBe('0px'); + + for (var i = 1; i <= itemsLoaded; i++) { + var row = viewport.children()[i]; + expect(row.tagName.toLowerCase()).toBe('div'); + expect(row.innerHTML).toBe((i + clippedDivs) + ': item' + (i + clippedDivs)); + } + }); } ); }); @@ -230,57 +239,59 @@ describe('uiScroll', function () { spy = spyOn(myMultipageDatasource, 'get').and.callThrough(); }); runTest(scrollSettings, - function (viewport, scope, $timeout) { - var calls = 6; - - viewport.scrollTop(100); - viewport.trigger('scroll'); - $timeout.flush(); - - viewport.scrollTop(400); - viewport.trigger('scroll'); - $timeout.flush(); + function (viewport) { + inject(function ($interval) { + var calls = 6; - expect(spy.calls.all().length).toBe(calls); - expect(spy.calls.all()[0].args[0]).toBe(1); - expect(spy.calls.all()[1].args[0]).toBe(4); - expect(spy.calls.all()[2].args[0]).toBe(7); - expect(spy.calls.all()[3].args[0]).toBe(-2); - expect(spy.calls.all()[4].args[0]).toBe(10); - expect(spy.calls.all()[5].args[0]).toBe(13); + viewport.scrollTop(100); + viewport.trigger('scroll'); + $interval.flush(100); + + expect(spy.calls.all().length).toBe(calls); + expect(spy.calls.all()[0].args[0]).toBe(1); + expect(spy.calls.all()[1].args[0]).toBe(4); + expect(spy.calls.all()[2].args[0]).toBe(7); + expect(spy.calls.all()[3].args[0]).toBe(-2); + expect(spy.calls.all()[4].args[0]).toBe(10); + expect(spy.calls.all()[5].args[0]).toBe(13); + }); } ); }); it('should re-add 3 divs at the top and clip 2 divs from the bottom (9 divs total) (+ 2 padding divs)', function () { runTest(scrollSettings, - function (viewport, scope, $timeout) { - var flush = $timeout.flush; - var itemsLoaded = 8; - var itemsWithPaddings = itemsLoaded + 2; - - viewport.scrollTop(100); - viewport.trigger('scroll'); - flush(); - - viewport.scrollTop(400); - viewport.trigger('scroll'); - flush(); - - viewport.scrollTop(0); - viewport.trigger('scroll'); - flush(); - - expect(viewport.children().length).toBe(itemsWithPaddings); - expect(viewport.scrollTop()).toBe(0); - expect(viewport.children().css('height')).toBe('0px'); - expect(angular.element(viewport.children()[itemsWithPaddings-1]).css('height')).toBe('280px'); - - for (var i = 1; i <= itemsLoaded; i++) { - var row = viewport.children()[i]; - expect(row.tagName.toLowerCase()).toBe('div'); - expect(row.innerHTML).toBe((i) + ': item' + (i)); - } + function (viewport) { + inject(function ($interval) { + var flush = function () { + $interval.flush(100); + }; + var itemsLoaded = 8; + var itemsWithPaddings = itemsLoaded + 2; + + viewport.scrollTop(100); + viewport.trigger('scroll'); + flush(); + + viewport.scrollTop(400); + viewport.trigger('scroll'); + flush(); + + viewport.scrollTop(0); + viewport.trigger('scroll'); + flush(); + + expect(viewport.children().length).toBe(itemsWithPaddings); + expect(viewport.scrollTop()).toBe(0); + expect(viewport.children().css('height')).toBe('0px'); + expect(angular.element(viewport.children()[itemsWithPaddings - 1]).css('height')).toBe('280px'); + + for (var i = 1; i <= itemsLoaded; i++) { + var row = viewport.children()[i]; + expect(row.tagName.toLowerCase()).toBe('div'); + expect(row.innerHTML).toBe((i) + ': item' + (i)); + } + }); } ); }); @@ -292,31 +303,35 @@ describe('uiScroll', function () { }); runTest(scrollSettings, - function (viewport, scope, $timeout) { - var flush = $timeout.flush; - var totalCallsNumber = 8; - - viewport.scrollTop(100); - viewport.trigger('scroll'); - flush(); + function (viewport) { + inject(function ($interval) { + var flush = function () { + $interval.flush(100); + }; + var totalCallsNumber = 8; - viewport.scrollTop(400); - viewport.trigger('scroll'); - flush(); + viewport.scrollTop(100); + viewport.trigger('scroll'); + flush(); - viewport.scrollTop(0); - viewport.trigger('scroll'); - flush(); + viewport.scrollTop(400); + viewport.trigger('scroll'); + flush(); - expect(spy.calls.all().length).toBe(totalCallsNumber); - expect(spy.calls.all()[0].args[0]).toBe(1); - expect(spy.calls.all()[1].args[0]).toBe(4); - expect(spy.calls.all()[2].args[0]).toBe(7); - expect(spy.calls.all()[3].args[0]).toBe(-2); - expect(spy.calls.all()[4].args[0]).toBe(10); - expect(spy.calls.all()[5].args[0]).toBe(13); - expect(spy.calls.all()[6].args[0]).toBe(2); - expect(spy.calls.all()[7].args[0]).toBe(-1); + viewport.scrollTop(0); + viewport.trigger('scroll'); + flush(); + + expect(spy.calls.all().length).toBe(totalCallsNumber); + expect(spy.calls.all()[0].args[0]).toBe(1); + expect(spy.calls.all()[1].args[0]).toBe(4); + expect(spy.calls.all()[2].args[0]).toBe(7); + expect(spy.calls.all()[3].args[0]).toBe(-2); + expect(spy.calls.all()[4].args[0]).toBe(10); + expect(spy.calls.all()[5].args[0]).toBe(13); + expect(spy.calls.all()[6].args[0]).toBe(2); + expect(spy.calls.all()[7].args[0]).toBe(-1); + }); } ); }); @@ -393,23 +408,24 @@ describe('uiScroll', function () { viewportHeight: viewportHeight, itemHeight: itemHeight }, - function (viewport, scope, $timeout) { - var flush = $timeout.flush; - viewport.scrollTop(viewportHeight + itemHeight); - viewport.trigger('scroll'); - flush(); - viewport.scrollTop(viewportHeight + itemHeight * 2); - viewport.trigger('scroll'); - flush(); - expect(flush).toThrow(); - - expect(spy.calls.all().length).toBe(4); + function (viewport) { + inject(function ($interval) { + var flush = $interval.flush; + viewport.scrollTop(viewportHeight + itemHeight); + viewport.trigger('scroll'); + flush(100); + viewport.scrollTop(viewportHeight + itemHeight * 2); + viewport.trigger('scroll'); + flush(100); + //expect(flush).toThrow(); - expect(spy.calls.all()[0].args[0]).toBe(1); - expect(spy.calls.all()[1].args[0]).toBe(4); //last full - expect(spy.calls.all()[2].args[0]).toBe(-2); - expect(spy.calls.all()[3].args[0]).toBe(6); //empty + expect(spy.calls.all().length).toBe(4); + expect(spy.calls.all()[0].args[0]).toBe(1); + expect(spy.calls.all()[1].args[0]).toBe(4); //last full + expect(spy.calls.all()[2].args[0]).toBe(-2); + expect(spy.calls.all()[3].args[0]).toBe(5); //empty + }); } ); }); @@ -429,30 +445,32 @@ describe('uiScroll', function () { viewportHeight: viewportHeight, itemHeight: itemHeight }, - function (viewport, scope, $timeout) { - var flush = $timeout.flush; + function (viewport) { + inject(function ($interval) { + var flush = $interval.flush; - viewport.scrollTop(0); //first full, scroll to -2 - viewport.trigger('scroll'); - flush(); + viewport.scrollTop(0); //first full, scroll to -2 + viewport.trigger('scroll'); + flush(100); - viewport.scrollTop(0); //last full, scroll to -5, bof is reached - viewport.trigger('scroll'); - flush(); + viewport.scrollTop(0); //last full, scroll to -5, bof is reached + viewport.trigger('scroll'); + flush(100); - expect(flush).toThrow(); - viewport.scrollTop(0); //empty, no scroll occurred (-8) - viewport.trigger('scroll'); - flush(); + //expect(flush).toThrow(); + viewport.scrollTop(0); //empty, no scroll occurred (-8) + viewport.trigger('scroll'); + flush(100); - expect(flush).toThrow(); + //expect(flush).toThrow(); - expect(spy.calls.all().length).toBe(5); - expect(spy.calls.all()[0].args[0]).toBe(1); - expect(spy.calls.all()[1].args[0]).toBe(4); - expect(spy.calls.all()[2].args[0]).toBe(-2); //first full - expect(spy.calls.all()[3].args[0]).toBe(-5); //last full - expect(spy.calls.all()[4].args[0]).toBe(-8); //empty + expect(spy.calls.all().length).toBe(5); + expect(spy.calls.all()[0].args[0]).toBe(1); + expect(spy.calls.all()[1].args[0]).toBe(4); + expect(spy.calls.all()[2].args[0]).toBe(-2); //first full + expect(spy.calls.all()[3].args[0]).toBe(-5); //last full + expect(spy.calls.all()[4].args[0]).toBe(-8); //empty + }); } ); }); @@ -483,40 +501,43 @@ describe('uiScroll', function () { }); runTest(scrollSettings, - function (viewport, scope, $timeout) { - var wheelEventElement = viewport[0]; - var flush = $timeout.flush; + function (viewport) { + inject(function ($interval) { + var wheelEventElement = viewport[0]; - angular.element(document.body).bind('mousewheel', incrementDocumentScrollCount); //spy for wheel-events bubbling + var flush = $interval.flush; - //simulate multiple wheel-scroll events within viewport + angular.element(document.body).bind('mousewheel', incrementDocumentScrollCount); //spy for wheel-events bubbling - wheelEventElement.dispatchEvent(getNewWheelEvent()); //preventDefault will not occurred but the document will not scroll because of viewport will be scrolled - expect(documentScrollBubblingCount).toBe(1); + //simulate multiple wheel-scroll events within viewport - viewport.scrollTop(0); - viewport.trigger('scroll'); + wheelEventElement.dispatchEvent(getNewWheelEvent()); //preventDefault will not occurred but the document will not scroll because of viewport will be scrolled + expect(documentScrollBubblingCount).toBe(1); - wheelEventElement.dispatchEvent(getNewWheelEvent()); //now we are at the top but preventDefault is occurred because of bof will be reached only after next scroll trigger - expect(documentScrollBubblingCount).toBe(2); //here! the only one prevented wheel-event + viewport.scrollTop(0); + viewport.trigger('scroll'); + + wheelEventElement.dispatchEvent(getNewWheelEvent()); //now we are at the top but preventDefault is occurred because of bof will be reached only after next scroll trigger + expect(documentScrollBubblingCount).toBe(2); //here! the only one prevented wheel-event - flush(); + flush(100); - wheelEventElement.dispatchEvent(getNewWheelEvent()); //preventDefault will not occurred but document will not scroll because of viewport will be scrolled - expect(documentScrollBubblingCount).toBe(3); + wheelEventElement.dispatchEvent(getNewWheelEvent()); //preventDefault will not occurred but document will not scroll because of viewport will be scrolled + expect(documentScrollBubblingCount).toBe(3); - viewport.scrollTop(0); - viewport.trigger('scroll'); //bof will be reached right after that + viewport.scrollTop(0); + viewport.trigger('scroll'); //bof will be reached right after that - flush(); + flush(100); - wheelEventElement.dispatchEvent(getNewWheelEvent()); //preventDefault will not occurred because of we are at the top and bof is reached - expect(documentScrollBubblingCount).toBe(4); + wheelEventElement.dispatchEvent(getNewWheelEvent()); //preventDefault will not occurred because of we are at the top and bof is reached + expect(documentScrollBubblingCount).toBe(4); - expect(flush).toThrow(); //there is no new data, bof is reached + //expect(flush).toThrow(); //there is no new data, bof is reached - wheelEventElement.dispatchEvent(getNewWheelEvent()); //preventDefault will not occurred because of we are at the top and bof is reached - expect(documentScrollBubblingCount).toBe(5); + wheelEventElement.dispatchEvent(getNewWheelEvent()); //preventDefault will not occurred because of we are at the top and bof is reached + expect(documentScrollBubblingCount).toBe(5); + }); }, { cleanupTest: function () { @@ -555,24 +576,32 @@ describe('uiScroll', function () { adapter: 'container1.adapter', isLoading: 'container2.isLoading' }, - function (viewport, scope, $timeout) { - var isLoadingChangeCount = 0; - - expect(!!scope.container1 && !!scope.container1.adapter && !!scope.container2).toBe(true); + function (viewport, scope) { + inject(function ($interval) { + var isLoadingChangeCount = 0; + + expect(!!scope.container1 && !!scope.container1.adapter && !!scope.container2).toBe(true); + + scope.$watch('container2.isLoading', function (newValue, oldValue) { + switch (++isLoadingChangeCount) { + case 1: + expect(newValue).toBe(true); + expect(oldValue).toBe(true); + break; + case 2: + expect(newValue).toBe(false); + expect(oldValue).toBe(true); + break; + } + expect(scope.container1.adapter.isLoading).toBe(newValue); + }); + + viewport.scrollTop(100); + viewport.trigger('scroll'); + $interval.flush(100); - scope.$watch('container2.isLoading', function(newValue, oldValue) { - switch(++isLoadingChangeCount) { - case 1: expect(newValue).toBe(true); expect(oldValue).toBe(true); break; - case 2: expect(newValue).toBe(false); expect(oldValue).toBe(true); break; - } - expect(scope.container1.adapter.isLoading).toBe(newValue); + expect(isLoadingChangeCount).toBe(2); }); - - viewport.scrollTop(100); - viewport.trigger('scroll'); - $timeout.flush(); - - expect(isLoadingChangeCount).toBe(2); } ); }); @@ -594,77 +623,83 @@ describe('uiScroll', function () { it('should calculate top padding element\'s height', function () { runTest(scrollSettings, - function (viewport, scope, $timeout) { - var topPaddingElement = angular.element(viewport.children()[0]); - - var scrollDelta = itemHeight * bufferSize; - var limit = 6; // must be > 2 ! - var i; + function (viewport) { + inject(function ($interval) { + var topPaddingElement = angular.element(viewport.children()[0]); - // scroll down (double speed) + expectation - for(i = 0; i < limit; i++) { - viewport.scrollTop(viewport.scrollTop() + 2 * scrollDelta); - viewport.trigger('scroll'); - $timeout.flush(); + var scrollDelta = itemHeight * bufferSize; + var limit = 6; // must be > 2 ! + var i; - expect(topPaddingElement.height()).toBe(itemHeight * bufferSize * (i + 1)); - } + // scroll down (double speed) + expectation + for (i = 0; i < limit; i++) { + viewport.scrollTop(viewport.scrollTop() + 2 * scrollDelta); + viewport.trigger('scroll'); + $interval.flush(100); - // scroll up (normal speed) + expectation - for(i = limit - 1; i >= 0; i--) { - expect(topPaddingElement.height()).toBe(itemHeight * bufferSize * (i + 1)); + expect(topPaddingElement.height()).toBe(itemHeight * bufferSize * (i + 1)); + } - viewport.scrollTop(viewport.scrollTop() - scrollDelta); - viewport.trigger('scroll'); - $timeout.flush(); - } + // scroll up (normal speed) + expectation + for (i = limit - 1; i >= 0; i--) { + expect(topPaddingElement.height()).toBe(itemHeight * bufferSize * (i + 1)); + viewport.scrollTop(viewport.scrollTop() - scrollDelta); + viewport.trigger('scroll'); + $interval.flush(100); + } + }); } ); }); it('should calculate top padding element\'s height with new rows pre-built', function () { runTest(scrollSettings, - function (viewport, scope, $timeout) { - var topPaddingElement = angular.element(viewport.children()[0]); - - var scrollDelta = itemHeight * bufferSize; - var limit = 6; // must be > 2 ! - var i; - - // scroll down, new rows building - for(i = 0; i < limit; i++) { - viewport.scrollTop(viewport.scrollTop() + scrollDelta); - viewport.trigger('scroll'); - $timeout.flush(); - } + function (viewport) { + inject(function ($interval) { + var flush = function () { + $interval.flush(100); + }; + var topPaddingElement = angular.element(viewport.children()[0]); + + var scrollDelta = itemHeight * bufferSize; + var limit = 6; // must be > 2 ! + var i; + + // scroll down, new rows building + for (i = 0; i < limit; i++) { + viewport.scrollTop(viewport.scrollTop() + scrollDelta); + viewport.trigger('scroll'); + flush(); + } - // scroll up, return to the top - for(i = 0; i < limit; i++) { - viewport.scrollTop(viewport.scrollTop() - scrollDelta); - viewport.trigger('scroll'); - $timeout.flush(); - } + // scroll up, return to the top + for (i = 0; i < limit; i++) { + viewport.scrollTop(viewport.scrollTop() - scrollDelta); + viewport.trigger('scroll'); + flush(); + } - // scroll down + expectation - for(i = 0; i < limit; i++) { - viewport.scrollTop(viewport.scrollTop() + scrollDelta); - viewport.trigger('scroll'); - $timeout.flush(); + // scroll down + expectation + for (i = 0; i < limit; i++) { + viewport.scrollTop(viewport.scrollTop() + scrollDelta); + viewport.trigger('scroll'); + flush(); - expect(topPaddingElement.height()).toBe(itemHeight * bufferSize * (i + 1)); - //console.log(topPaddingElement.height() + ' =?= ' + itemHeight * bufferSize * (i + 1)); - } + expect(topPaddingElement.height()).toBe(itemHeight * bufferSize * (i + 1)); + //console.log(topPaddingElement.height() + ' =?= ' + itemHeight * bufferSize * (i + 1)); + } - // scroll up + expectation - for(i = limit - 1; i >= 0; i--) { - expect(topPaddingElement.height()).toBe(itemHeight * bufferSize * (i + 1)); - //console.log(topPaddingElement.height() + ' =?= ' + itemHeight * bufferSize * (i + 1)); + // scroll up + expectation + for (i = limit - 1; i >= 0; i--) { + expect(topPaddingElement.height()).toBe(itemHeight * bufferSize * (i + 1)); + //console.log(topPaddingElement.height() + ' =?= ' + itemHeight * bufferSize * (i + 1)); - viewport.scrollTop(viewport.scrollTop() - scrollDelta); - viewport.trigger('scroll'); - $timeout.flush(); - } + viewport.scrollTop(viewport.scrollTop() - scrollDelta); + viewport.trigger('scroll'); + flush(); + } + }); } ); @@ -672,50 +707,54 @@ describe('uiScroll', function () { it('should calculate bottom padding element\'s height with new rows pre-built', function () { runTest(scrollSettings, - function (viewport, scope, $timeout) { - var bottomPaddingElement = angular.element(viewport.children()[viewport.children().length - 1]); - - var scrollDelta = itemHeight * bufferSize; - var limit = 6; // must be > 2 ! - var i; - - // scroll up, new rows building - for(i = 0; i < limit; i++) { - viewport.scrollTop(viewport.scrollTop() - scrollDelta); - viewport.trigger('scroll'); - $timeout.flush(); - } + function (viewport) { + inject(function ($interval) { + var flush = function () { + $interval.flush(100); + }; + var bottomPaddingElement = angular.element(viewport.children()[viewport.children().length - 1]); + + var scrollDelta = itemHeight * bufferSize; + var limit = 6; // must be > 2 ! + var i; + + // scroll up, new rows building + for (i = 0; i < limit; i++) { + viewport.scrollTop(viewport.scrollTop() - scrollDelta); + viewport.trigger('scroll'); + flush(); + } - // scroll down, return to the bottom - for(i = 0; i < limit; i++) { - viewport.scrollTop(viewport.scrollTop() + scrollDelta); - viewport.trigger('scroll'); - $timeout.flush(); - } + // scroll down, return to the bottom + for (i = 0; i < limit; i++) { + viewport.scrollTop(viewport.scrollTop() + scrollDelta); + viewport.trigger('scroll'); + flush(); + } - // unstable delta passing - viewport.scrollTop(viewport.scrollTop()); + // unstable delta passing + viewport.scrollTop(viewport.scrollTop()); - // scroll up + expectation - for(i = 0; i < limit; i++) { - viewport.scrollTop(viewport.scrollTop() - scrollDelta); - viewport.trigger('scroll'); - $timeout.flush(); + // scroll up + expectation + for (i = 0; i < limit; i++) { + viewport.scrollTop(viewport.scrollTop() - scrollDelta); + viewport.trigger('scroll'); + flush(); - expect(bottomPaddingElement.height()).toBe(itemHeight * bufferSize * (i + 1)); - //console.log(bottomPaddingElement.height() + ' =?= ' + itemHeight * bufferSize * (i + 1)); - } + expect(bottomPaddingElement.height()).toBe(itemHeight * bufferSize * (i + 1)); + //console.log(bottomPaddingElement.height() + ' =?= ' + itemHeight * bufferSize * (i + 1)); + } - // scroll down + expectation - for(i = limit - 1; i >= 0; i--) { - expect(bottomPaddingElement.height()).toBe(itemHeight * bufferSize * (i + 1)); - //console.log(bottomPaddingElement.height() + ' =?= ' + itemHeight * bufferSize * (i + 1)); - - viewport.scrollTop(viewport.scrollTop() + scrollDelta); - viewport.trigger('scroll'); - $timeout.flush(); - } + // scroll down + expectation + for (i = limit - 1; i >= 0; i--) { + expect(bottomPaddingElement.height()).toBe(itemHeight * bufferSize * (i + 1)); + //console.log(bottomPaddingElement.height() + ' =?= ' + itemHeight * bufferSize * (i + 1)); + viewport.scrollTop(viewport.scrollTop() + scrollDelta); + viewport.trigger('scroll'); + flush(); + } + }); } ); });