Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allows to bind "reach top" callback. #174

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 49 additions & 17 deletions build/ng-infinite-scroll.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* ng-infinite-scroll - v1.2.0 - 2015-02-14 */
/* ng-infinite-scroll - v1.2.0 - 2015-05-23 */
var mod;

mod = angular.module('infinite-scroll', []);
Expand All @@ -10,17 +10,20 @@ mod.directive('infiniteScroll', [
return {
scope: {
infiniteScroll: '&',
infiniteScrollTop: '&',
infiniteScrollContainer: '=',
infiniteScrollDistance: '=',
infiniteScrollDisabled: '=',
infiniteScrollTopDisabled: '=',
infiniteScrollUseDocumentBottom: '=',
infiniteScrollListenForEvent: '@'
},
link: function(scope, elem, attrs) {
var changeContainer, checkWhenEnabled, container, handleInfiniteScrollContainer, handleInfiniteScrollDisabled, handleInfiniteScrollDistance, handleInfiniteScrollUseDocumentBottom, handler, height, immediateCheck, offsetTop, pageYOffset, scrollDistance, scrollEnabled, throttle, unregisterEventListener, useDocumentBottom, windowElement;
var changeContainer, checkWhenEnabled, container, handleInfiniteScrollContainer, handleInfiniteScrollDisabled, handleInfiniteScrollDistance, handleInfiniteScrollUseDocumentBottom, handleinfiniteScrollTopDisabled, handler, height, immediateCheck, isVisible, offsetTop, pageYOffset, scrollDistance, scrollEnabled, scrollTopEnabled, throttle, unregisterEventListener, useDocumentBottom, windowElement;
windowElement = angular.element($window);
scrollDistance = null;
scrollEnabled = null;
scrollTopEnabled = null;
checkWhenEnabled = null;
container = null;
immediateCheck = true;
Expand All @@ -34,6 +37,9 @@ mod.directive('infiniteScroll', [
return elem.offsetHeight;
}
};
isVisible = function(elem) {
return elem[0].offsetWidth && elem[0].offsetHeight;
};
offsetTop = function(elem) {
if (!elem[0].getBoundingClientRect || elem.css('none')) {
return;
Expand All @@ -49,23 +55,31 @@ mod.directive('infiniteScroll', [
}
};
handler = function() {
var containerBottom, containerTopOffset, elementBottom, remaining, shouldScroll;
if (container === windowElement) {
containerBottom = height(container) + pageYOffset(container[0].document.documentElement);
elementBottom = offsetTop(elem) + height(elem);
} else {
containerBottom = height(container);
containerTopOffset = 0;
if (offsetTop(container) !== void 0) {
containerTopOffset = offsetTop(container);
var containerBottom, containerTopOffset, elementBottom, remaining, remainingTop, shouldScroll, shouldScrollTop;
if (isVisible(elem)) {
if (container === windowElement) {
containerBottom = height(container) + pageYOffset(container[0].document.documentElement);
elementBottom = offsetTop(elem) + height(elem);
containerTopOffset = container.scrollTop();
} else {
containerBottom = height(container);
containerTopOffset = 0;
if (offsetTop(container) !== void 0) {
containerTopOffset = offsetTop(container);
}
elementBottom = offsetTop(elem) - containerTopOffset + height(elem);
}
elementBottom = offsetTop(elem) - containerTopOffset + height(elem);
}
if (useDocumentBottom) {
elementBottom = height((elem[0].ownerDocument || elem[0].document).documentElement);
if (useDocumentBottom) {
elementBottom = height((elem[0].ownerDocument || elem[0].document).documentElement);
}
remaining = elementBottom - containerBottom;
shouldScroll = remaining <= height(container) * scrollDistance + 1;
remainingTop = containerTopOffset - offsetTop(elem);
shouldScrollTop = remainingTop <= height(container) * scrollDistance + 1;
} else {
shouldScroll = false;
shouldScrollTop = false;
}
remaining = elementBottom - containerBottom;
shouldScroll = remaining <= height(container) * scrollDistance + 1;
if (shouldScroll) {
checkWhenEnabled = true;
if (scrollEnabled) {
Expand All @@ -75,6 +89,15 @@ mod.directive('infiniteScroll', [
return scope.$apply(scope.infiniteScroll);
}
}
} else if (shouldScrollTop) {
checkWhenEnabled = true;
if (scrollTopEnabled) {
if (scope.$$phase || $rootScope.$$phase) {
return scope.infiniteScrollTop();
} else {
return scope.$apply(scope.infiniteScrollTop);
}
}
} else {
return checkWhenEnabled = false;
}
Expand Down Expand Up @@ -132,6 +155,15 @@ mod.directive('infiniteScroll', [
};
scope.$watch('infiniteScrollDisabled', handleInfiniteScrollDisabled);
handleInfiniteScrollDisabled(scope.infiniteScrollDisabled);
handleinfiniteScrollTopDisabled = function(v) {
scrollTopEnabled = !v;
if (scrollTopEnabled && checkWhenEnabled) {
checkWhenEnabled = false;
return handler();
}
};
scope.$watch('infiniteScrollTopDisabled', handleinfiniteScrollTopDisabled);
handleinfiniteScrollTopDisabled(scope.infiniteScrollTopDisabled);
handleInfiniteScrollUseDocumentBottom = function(v) {
return useDocumentBottom = v;
};
Expand Down
4 changes: 2 additions & 2 deletions build/ng-infinite-scroll.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

61 changes: 46 additions & 15 deletions src/infinite-scroll.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ mod.value('THROTTLE_MILLISECONDS', null)
mod.directive 'infiniteScroll', ['$rootScope', '$window', '$interval', 'THROTTLE_MILLISECONDS', \
($rootScope, $window, $interval, THROTTLE_MILLISECONDS) ->
scope:
infiniteScroll: '&'
infiniteScroll: '&',
infiniteScrollTop: '&'
infiniteScrollContainer: '='
infiniteScrollDistance: '='
infiniteScrollDisabled: '='
infiniteScrollTopDisabled: '='
infiniteScrollUseDocumentBottom: '=',
infiniteScrollListenForEvent: '@'

Expand All @@ -17,6 +19,7 @@ mod.directive 'infiniteScroll', ['$rootScope', '$window', '$interval', 'THROTTLE

scrollDistance = null
scrollEnabled = null
scrollTopEnabled = null
checkWhenEnabled = null
container = null
immediateCheck = true
Expand All @@ -28,6 +31,9 @@ mod.directive 'infiniteScroll', ['$rootScope', '$window', '$interval', 'THROTTLE

if isNaN(elem.offsetHeight) then elem.document.documentElement.clientHeight else elem.offsetHeight

isVisible = (elem) ->
elem[0].offsetWidth and elem[0].offsetHeight

offsetTop = (elem) ->
if not elem[0].getBoundingClientRect or elem.css('none')
return
Expand All @@ -46,21 +52,29 @@ mod.directive 'infiniteScroll', ['$rootScope', '$window', '$interval', 'THROTTLE
# with a boolean that is set to true when the function is
# called in order to throttle the function call.
handler = ->
if container == windowElement
containerBottom = height(container) + pageYOffset(container[0].document.documentElement)
elementBottom = offsetTop(elem) + height(elem)
if isVisible(elem)
if container == windowElement
containerBottom = height(container) + pageYOffset(container[0].document.documentElement)
elementBottom = offsetTop(elem) + height(elem)
containerTopOffset = container.scrollTop()
else
containerBottom = height(container)
containerTopOffset = 0
if offsetTop(container) != undefined
containerTopOffset = offsetTop(container)
elementBottom = offsetTop(elem) - containerTopOffset + height(elem)

if(useDocumentBottom)
elementBottom = height((elem[0].ownerDocument || elem[0].document).documentElement)

remaining = elementBottom - containerBottom
shouldScroll = remaining <= height(container) * scrollDistance + 1

remainingTop = containerTopOffset - offsetTop(elem)
shouldScrollTop = remainingTop <= height(container) * scrollDistance + 1
else
containerBottom = height(container)
containerTopOffset = 0
if offsetTop(container) != undefined
containerTopOffset = offsetTop(container)
elementBottom = offsetTop(elem) - containerTopOffset + height(elem)

if(useDocumentBottom)
elementBottom = height((elem[0].ownerDocument || elem[0].document).documentElement)

remaining = elementBottom - containerBottom
shouldScroll = remaining <= height(container) * scrollDistance + 1
shouldScroll = false
shouldScrollTop = false

if shouldScroll
checkWhenEnabled = true
Expand All @@ -70,6 +84,14 @@ mod.directive 'infiniteScroll', ['$rootScope', '$window', '$interval', 'THROTTLE
scope.infiniteScroll()
else
scope.$apply(scope.infiniteScroll)
else if shouldScrollTop
checkWhenEnabled = true

if scrollTopEnabled
if scope.$$phase || $rootScope.$$phase
scope.infiniteScrollTop()
else
scope.$apply(scope.infiniteScrollTop)
else
checkWhenEnabled = false

Expand Down Expand Up @@ -137,6 +159,15 @@ mod.directive 'infiniteScroll', ['$rootScope', '$window', '$interval', 'THROTTLE
# If I don't explicitly call the handler here, tests fail. Don't know why yet.
handleInfiniteScrollDisabled scope.infiniteScrollDisabled

handleinfiniteScrollTopDisabled = (v) ->
scrollTopEnabled = !v
if scrollTopEnabled && checkWhenEnabled
checkWhenEnabled = false
handler()

scope.$watch 'infiniteScrollTopDisabled', handleinfiniteScrollTopDisabled
handleinfiniteScrollTopDisabled scope.infiniteScrollTopDisabled

# use the bottom of the document instead of the element's bottom.
# This useful when the element does not have a height due to its
# children being absolute positioned.
Expand Down
8 changes: 8 additions & 0 deletions test/spec/ng-infinite-scroll.spec.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ getTemplate = (angularVersion, container, attrs, throttle) ->
html, body {
height: 100%;
}
[infinite-scroll] {
min-height: 50px;
}
</style>
<script src='http://ajax.googleapis.com/ajax/libs/angularjs/#{angularVersion}/angular.min.js'></script>
<script src="../../build/ng-infinite-scroll.js"></script>
Expand Down Expand Up @@ -150,6 +153,11 @@ describe "ng-infinite-scroll", ->
browser.driver.executeScript(scrollToLastScreenScript(container, 20))
expect(getItems().count()).toBe 200

it "do not trigger when element is invisible", ->
replaceIndexFile "style='display: none;'", throttle
browser.get pathToDocument
expect(getItems().count()).toBe 0

describe "with an event handler", ->

it "calls the event handler on an event", ->
Expand Down