/** * @ngdoc directive * @name ionInfiniteScroll * @module ionic * @parent ionic.directive:ionContent, ionic.directive:ionScroll * @restrict E * * @description * The ionInfiniteScroll directive allows you to call a function whenever * the user gets to the bottom of the page or near the bottom of the page. * * The expression you pass in for `on-infinite` is called when the user scrolls * greater than `distance` away from the bottom of the content. Once `on-infinite` * is done loading new data, it should broadcast the `scroll.infiniteScrollComplete` * event from your controller (see below example). * * @param {expression} on-infinite What to call when the scroller reaches the * bottom. * @param {string=} distance The distance from the bottom that the scroll must * reach to trigger the on-infinite expression. Default: 1%. * @param {string=} icon The icon to show while loading. Default: 'ion-loading-d'. * * @usage * ```html * * * * * ``` * ```js * function MyController($scope, $http) { * $scope.items = []; * $scope.loadMore = function() { * $http.get('/more-items').success(function(items) { * useItems(items); * $scope.$broadcast('scroll.infiniteScrollComplete'); * }); * }; * * $scope.$on('stateChangeSuccess', function() { * $scope.loadMore(); * }); * } * ``` * * An easy to way to stop infinite scroll once there is no more data to load * is to use angular's `ng-if` directive: * * ```html * * * ``` */ IonicModule .directive('ionInfiniteScroll', ['$timeout', function($timeout) { function calculateMaxValue(distance, maximum, isPercent) { return isPercent ? maximum * (1 - parseInt(distance,10) / 100) : maximum - parseInt(distance, 10); } return { restrict: 'E', require: ['^$ionicScroll', 'ionInfiniteScroll'], template: '
' + '
' + '' + '
' + '
', scope: true, controller: ['$scope', '$attrs', function($scope, $attrs) { this.isLoading = false; this.scrollView = null; //given by link function this.getMaxScroll = function() { var distance = ($attrs.distance || '1%').trim(); var isPercent = distance.indexOf('%') !== -1; var maxValues = this.scrollView.getScrollMax(); return { left: this.scrollView.options.scrollingX ? calculateMaxValue(distance, maxValues.left, isPercent) : -1, top: this.scrollView.options.scrollingY ? calculateMaxValue(distance, maxValues.top, isPercent) : -1 }; }; }], link: function($scope, $element, $attrs, ctrls) { var scrollCtrl = ctrls[0]; var infiniteScrollCtrl = ctrls[1]; var scrollView = infiniteScrollCtrl.scrollView = scrollCtrl.scrollView; $scope.icon = function() { return angular.isDefined($attrs.icon) ? $attrs.icon : 'ion-loading-d'; }; var onInfinite = function() { $element[0].classList.add('active'); infiniteScrollCtrl.isLoading = true; $scope.$parent && $scope.$parent.$apply($attrs.onInfinite || ''); }; var finishInfiniteScroll = function() { $element[0].classList.remove('active'); $timeout(function() { scrollView.resize(); }, 0, false); infiniteScrollCtrl.isLoading = false; }; $scope.$on('scroll.infiniteScrollComplete', function() { finishInfiniteScroll(); }); $scope.$on('$destroy', function() { scrollCtrl.$element.off('scroll', checkBounds); }); var checkBounds = ionic.animationFrameThrottle(checkInfiniteBounds); //Check bounds on start, after scrollView is fully rendered setTimeout(checkBounds); scrollCtrl.$element.on('scroll', checkBounds); function checkInfiniteBounds() { if (infiniteScrollCtrl.isLoading) return; var scrollValues = scrollView.getValues(); var maxScroll = infiniteScrollCtrl.getMaxScroll(); if ((maxScroll.left !== -1 && scrollValues.left >= maxScroll.left) || (maxScroll.top !== -1 && scrollValues.top >= maxScroll.top)) { onInfinite(); } } } }; }]);