-
Notifications
You must be signed in to change notification settings - Fork 17
Expand file tree
/
Copy pathiron-scroll-threshold.js
More file actions
212 lines (181 loc) · 6.33 KB
/
iron-scroll-threshold.js
File metadata and controls
212 lines (181 loc) · 6.33 KB
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
/**
@license
Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at
http://polymer.github.io/LICENSE.txt The complete set of authors may be found at
http://polymer.github.io/AUTHORS.txt The complete set of contributors may be
found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as
part of the polymer project is also subject to an additional IP rights grant
found at http://polymer.github.io/PATENTS.txt
*/
import '@polymer/polymer/polymer-legacy.js';
import {IronScrollTargetBehavior} from '@polymer/iron-scroll-target-behavior/iron-scroll-target-behavior.js';
import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
import {html} from '@polymer/polymer/lib/utils/html-tag.js';
/**
`iron-scroll-threshold` is a utility element that listens for `scroll` events
from a scrollable region and fires events to indicate when the scroller has
reached a pre-defined limit, specified in pixels from the upper and lower bounds
of the scrollable region. This element may wrap a scrollable region and will
listen for `scroll` events bubbling through it from its children. In this case,
care should be taken that only one scrollable region with the same orientation
as this element is contained within. Alternatively, the `scrollTarget` property
can be set/bound to a non-child scrollable region, from which it will listen for
events.
Once a threshold has been reached, a `lower-threshold` or `upper-threshold`
event will be fired, at which point the user may perform actions such as
lazily-loading more data to be displayed. After any work is done, the user must
then clear the threshold by calling the `clearTriggers` method on this element,
after which it will begin listening again for the scroll position to reach the
threshold again assuming the content in the scrollable region has grown. If the
user no longer wishes to receive events (e.g. all data has been exhausted), the
threshold property in question (e.g. `lowerThreshold`) may be set to a falsy
value to disable events and clear the associated triggered property.
### Example
```html
<iron-scroll-threshold on-lower-threshold="loadMoreData">
<div>content</div>
</iron-scroll-threshold>
```
```js
loadMoreData: function() {
// load async stuff. e.g. XHR
asyncStuff(function done() {
ironScrollTheshold.clearTriggers();
});
}
```
### Using dom-repeat
```html
<iron-scroll-threshold on-lower-threshold="loadMoreData">
<template is="dom-repeat" items="[[items]]">
<div>[[index]]</div>
</template>
</iron-scroll-threshold>
```
### Using iron-list
```html
<iron-scroll-threshold on-lower-threshold="loadMoreData" id="threshold">
<iron-list scroll-target="threshold" items="[[items]]">
<template>
<div>[[index]]</div>
</template>
</iron-list>
</iron-scroll-threshold>
```
@element iron-scroll-threshold
@demo demo/scrolling-region.html Scrolling Region
@demo demo/document.html Document Element
*/
Polymer({
/** @override */
_template: html`
<style>
:host {
display: block;
}
</style>
<slot></slot>
`,
is: 'iron-scroll-threshold',
properties: {
/**
* Distance from the top (or left, for horizontal) bound of the scroller
* where the "upper trigger" will fire.
*/
upperThreshold: {type: Number, value: 100},
/**
* Distance from the bottom (or right, for horizontal) bound of the scroller
* where the "lower trigger" will fire.
*/
lowerThreshold: {type: Number, value: 100},
/**
* Read-only value that tracks the triggered state of the upper threshold.
*/
upperTriggered: {type: Boolean, value: false, notify: true, readOnly: true},
/**
* Read-only value that tracks the triggered state of the lower threshold.
*/
lowerTriggered: {type: Boolean, value: false, notify: true, readOnly: true},
/**
* True if the orientation of the scroller is horizontal.
*/
horizontal: {type: Boolean, value: false}
},
behaviors: [IronScrollTargetBehavior],
observers:
['_setOverflow(scrollTarget)', '_initCheck(horizontal, isAttached)'],
get _defaultScrollTarget() {
return this;
},
_setOverflow: function(scrollTarget) {
this.style.overflow = scrollTarget === this ? 'auto' : '';
this.style.webkitOverflowScrolling = scrollTarget === this ? 'touch' : '';
},
_scrollHandler: function() {
// throttle the work on the scroll event
var THROTTLE_THRESHOLD = 200;
if (!this.isDebouncerActive('_checkTheshold')) {
this.debounce('_checkTheshold', function() {
this.checkScrollThresholds();
}, THROTTLE_THRESHOLD);
}
},
_initCheck: function(horizontal, isAttached) {
if (isAttached) {
this.debounce('_init', function() {
this.clearTriggers();
this.checkScrollThresholds();
});
}
},
/**
* Checks the scroll thresholds.
* This method is automatically called by iron-scroll-threshold.
*
* @method checkScrollThresholds
*/
checkScrollThresholds: function() {
if (!this.scrollTarget || (this.lowerTriggered && this.upperTriggered)) {
return;
}
var upperScrollValue = this.horizontal ? this._scrollLeft : this._scrollTop;
var lowerScrollValue = this.horizontal ? this.scrollTarget.scrollWidth -
this._scrollTargetWidth - this._scrollLeft :
this.scrollTarget.scrollHeight -
this._scrollTargetHeight - this._scrollTop;
// Detect upper threshold
if (upperScrollValue <= this.upperThreshold && !this.upperTriggered) {
this._setUpperTriggered(true);
this.fire('upper-threshold');
}
// Detect lower threshold
if (lowerScrollValue <= this.lowerThreshold && !this.lowerTriggered) {
this._setLowerTriggered(true);
this.fire('lower-threshold');
}
},
checkScrollThesholds: function() {
// iron-scroll-threshold/issues/16
this.checkScrollThresholds();
},
/**
* Clear the upper and lower threshold states.
*
* @method clearTriggers
*/
clearTriggers: function() {
this._setUpperTriggered(false);
this._setLowerTriggered(false);
}
/**
* Fires when the lower threshold has been reached.
*
* @event lower-threshold
*/
/**
* Fires when the upper threshold has been reached.
*
* @event upper-threshold
*/
});