forked from ionic-team/ionic-framework
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinfiniteScrollController.js
126 lines (112 loc) · 3.87 KB
/
infiniteScrollController.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
IonicModule
.controller('$ionInfiniteScroll', [
'$scope',
'$attrs',
'$element',
'$timeout',
function($scope, $attrs, $element, $timeout) {
var self = this;
self.isLoading = false;
$scope.icon = function() {
return isDefined($attrs.icon) ? $attrs.icon : 'ion-load-d';
};
$scope.spinner = function() {
return isDefined($attrs.spinner) ? $attrs.spinner : '';
};
$scope.$on('scroll.infiniteScrollComplete', function() {
finishInfiniteScroll();
});
$scope.$on('$destroy', function() {
if (self.scrollCtrl && self.scrollCtrl.$element) self.scrollCtrl.$element.off('scroll', self.checkBounds);
if (self.scrollEl && self.scrollEl.removeEventListener) {
self.scrollEl.removeEventListener('scroll', self.checkBounds);
}
});
// debounce checking infinite scroll events
self.checkBounds = ionic.Utils.throttle(checkInfiniteBounds, 300);
function onInfinite() {
ionic.requestAnimationFrame(function() {
$element[0].classList.add('active');
});
self.isLoading = true;
$scope.$parent && $scope.$parent.$apply($attrs.onInfinite || '');
}
function finishInfiniteScroll() {
ionic.requestAnimationFrame(function() {
$element[0].classList.remove('active');
});
$timeout(function() {
if (self.jsScrolling) self.scrollView.resize();
// only check bounds again immediately if the page isn't cached (scroll el has height)
if ((self.jsScrolling && self.scrollView.__container && self.scrollView.__container.offsetHeight > 0) ||
!self.jsScrolling) {
self.checkBounds();
}
}, 30, false);
self.isLoading = false;
}
// check if we've scrolled far enough to trigger an infinite scroll
function checkInfiniteBounds() {
if (self.isLoading) return;
var maxScroll = {};
if (self.jsScrolling) {
maxScroll = self.getJSMaxScroll();
var scrollValues = self.scrollView.getValues();
if ((maxScroll.left !== -1 && scrollValues.left >= maxScroll.left) ||
(maxScroll.top !== -1 && scrollValues.top >= maxScroll.top)) {
onInfinite();
}
} else {
maxScroll = self.getNativeMaxScroll();
if ((
maxScroll.left !== -1 &&
self.scrollEl.scrollLeft >= maxScroll.left - self.scrollEl.clientWidth
) || (
maxScroll.top !== -1 &&
self.scrollEl.scrollTop >= maxScroll.top - self.scrollEl.clientHeight
)) {
onInfinite();
}
}
}
// determine the threshold at which we should fire an infinite scroll
// note: this gets processed every scroll event, can it be cached?
self.getJSMaxScroll = function() {
var maxValues = self.scrollView.getScrollMax();
return {
left: self.scrollView.options.scrollingX ?
calculateMaxValue(maxValues.left) :
-1,
top: self.scrollView.options.scrollingY ?
calculateMaxValue(maxValues.top) :
-1
};
};
self.getNativeMaxScroll = function() {
var maxValues = {
left: self.scrollEl.scrollWidth,
top: self.scrollEl.scrollHeight
};
var computedStyle = window.getComputedStyle(self.scrollEl) || {};
return {
left: computedStyle.overflowX === 'scroll' ||
computedStyle.overflowX === 'auto' ||
self.scrollEl.style['overflow-x'] === 'scroll' ?
calculateMaxValue(maxValues.left) : -1,
top: computedStyle.overflowY === 'scroll' ||
computedStyle.overflowY === 'auto' ||
self.scrollEl.style['overflow-y'] === 'scroll' ?
calculateMaxValue(maxValues.top) : -1
};
};
// determine pixel refresh distance based on % or value
function calculateMaxValue(maximum) {
var distance = ($attrs.distance || '2.5%').trim();
var isPercent = distance.indexOf('%') !== -1;
return isPercent ?
maximum * (1 - parseFloat(distance) / 100) :
maximum - parseFloat(distance);
}
//for testing
self.__finishInfiniteScroll = finishInfiniteScroll;
}]);