flex_infinite_scroll 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2557a6f5390214ce8246d233d45b74c435935816
4
- data.tar.gz: 93605b2012ff14d17244b8daecdc74bf1c605d66
3
+ metadata.gz: d2fd414bc8323c2bb367697232a7e2e259cfed15
4
+ data.tar.gz: 1f5f35932d20c2049a2e28734677e41a466338df
5
5
  SHA512:
6
- metadata.gz: 9c1e4446ee54023638482f0c251b25ebea1e16d32adb13308bd48ba1c1cff6cabed59bb3add68beda0d42f8df782cf7a6a7e14fa5f010660c156546b42757e95
7
- data.tar.gz: e7c29fb2c5aa9a8f19d14bd3d707759876f7c684e4fc79965cdd1c62d0a35e7056d7ab7a30c635469f75b49b1b43edc9479c79fab08fe28cdb271158d0cee29a
6
+ metadata.gz: 78ddf99585b446ec32503783b6a300904dec526a8489e8de03bf1d0aeac1f2291ceb26d84ad452eb23d28c1387c1b5ec3efb64370e366e78312275bf8f825473
7
+ data.tar.gz: dac2a3773a6f1538873f57d20ec97ad85b98afeef77e2bf8a90c2e5672157a5081f1ee84d4efd552b76dfeec6bf7ea1e3aba68b42a316a3c95d925c56e1155d5
@@ -18,7 +18,11 @@
18
18
  customResponseAttributes: {
19
19
  next_page: 'next_page',
20
20
  data: 'data'
21
- }
21
+ },
22
+ virtualScroll: 'Enable virtual scroll',
23
+ virtualScrollElementSize: 'Element size for virtual scroll',
24
+ perfectScrollbarSupport: 'Enable perfect-scrollbar support'
25
+ perfectScrollbarConfig: 'Config for perfect-scrollbar'
22
26
  }
23
27
  */
24
28
 
@@ -30,6 +34,7 @@ class flexIS {
30
34
  this.config = {...config, ...this.targetObject.dataset};
31
35
  this.loading = false;
32
36
  this.nextPage = this.config.startPage || 1;
37
+ this.totalElements;
33
38
 
34
39
  this.config.requestType = this.config.requestType || 'GET';
35
40
  this.config.loadMargin = this.config.loadMargin || 150;
@@ -44,8 +49,18 @@ class flexIS {
44
49
  return eventTarget;
45
50
  }
46
51
  }
52
+
53
+ if (this.config.perfectScrollbarSupport) {
54
+ let PSConfig = this.config.perfectScrollbarConfig || {}
55
+ PSConfig.minScrollbarLength = PSConfig.minScrollbarLength || 40
56
+ this.perfectScrollbar = new PerfectScrollbar(
57
+ this.targetObject,
58
+ PSConfig
59
+ )
60
+ }
47
61
  }
48
62
 
63
+ // Init infinite scroll
49
64
  init() {
50
65
  this.#getData();
51
66
  this.config.eventTarget.addEventListener('scroll', () => {
@@ -57,6 +72,7 @@ class flexIS {
57
72
  return this;
58
73
  }
59
74
 
75
+ // Reset scroll to specific page
60
76
  resetScroll(page) {
61
77
  this.targetObject.innerHTML = '';
62
78
  this.nextPage = page || this.config.startPage || 1;
@@ -64,8 +80,15 @@ class flexIS {
64
80
  return this;
65
81
  }
66
82
 
83
+ // Append element to container
84
+ appendChild(el) {
85
+ this.#appendElementToContainer(el);
86
+ return this;
87
+ }
88
+
67
89
  // Private methods
68
90
 
91
+ // Run data request for next page
69
92
  #getData = (page = this.nextPage ) => {
70
93
  var xhr = new XMLHttpRequest();
71
94
  var params;
@@ -88,6 +111,10 @@ class flexIS {
88
111
  if (xhr.status === 200) {
89
112
  this.#customResponse(json);
90
113
  this.nextPage = json[this.config.customResponseAttributes.next_page];
114
+ if (this.config.virtualScroll) {
115
+ this.elementsLeft = json[this.config.customResponseAttributes.elements_left];
116
+ this.#virtualScroll().update();
117
+ }
91
118
  if (this.#scrollHitBottom()) this.#getData();
92
119
  }
93
120
 
@@ -97,18 +124,27 @@ class flexIS {
97
124
  xhr.send();
98
125
  }
99
126
 
127
+ // Full scroll height
100
128
  #scrollHeight = () => {
101
129
  return this.targetObject.scrollHeight;
102
130
  }
103
131
 
132
+ // Top scroll position
104
133
  #scrollTop = () => {
105
134
  return this.config.eventTarget.scrollTop || this.config.eventTarget.scrollY || 0;
106
135
  }
107
136
 
137
+ // Get container size
108
138
  #containerSize = () => {
109
139
  return this.config.eventTarget.innerHeight || this.targetObject.offsetHeight;
110
140
  }
111
141
 
142
+ // Container position
143
+ #containerPosition = () => {
144
+ return this.#scrollTop() + this.#containerSize() + this.config.loadMargin
145
+ }
146
+
147
+ // Add custom params to request
112
148
  #customParams = (params) => {
113
149
  var customParams = this.config.customParams;
114
150
  if (customParams) {
@@ -123,22 +159,49 @@ class flexIS {
123
159
  return params;
124
160
  }
125
161
 
162
+ // Response handling
126
163
  #customResponse = (json) => {
127
164
  var customResponse = this.config.customResponse;
165
+ var data = json[this.config.customResponseAttributes.data];
128
166
  var div;
129
- if (typeof customResponse === "function") {
130
- customResponse(this.targetObject, json);
131
- } else {
167
+
168
+ delete json[this.config.customResponseAttributes.data]
169
+
170
+ if (data.constructor === Array) {
171
+ data.forEach((el) => {
172
+ var htmlEl
173
+ if (typeof customResponse === "function") {
174
+ htmlEl = customResponse(el, json);
175
+ } else {
176
+ htmlEl = el;
177
+ }
178
+ this.#appendElementToContainer(htmlEl)
179
+ })
180
+ } else if (data.constructor === String) {
132
181
  div = document.createElement('div');
133
- div.innerHTML = json[this.config.customResponseAttributes.data];
182
+ div.innerHTML = data;
134
183
  while (div.children.length > 0) {
135
- this.targetObject.appendChild(div.children[0]);
184
+ this.#appendElementToContainer(div.children[0])
136
185
  }
137
186
  }
138
187
 
139
188
  this.#hideInvisibleContent();
189
+
190
+ if (this.perfectScrollbar) {
191
+ this.perfectScrollbar.update();
192
+ }
193
+ }
194
+
195
+ #appendElementToContainer = (el) => {
196
+ if (this.#virtualScroll().baloon()) {
197
+ this.targetObject.insertBefore(el, this.#virtualScroll().baloon());
198
+ } else {
199
+ this.targetObject.appendChild(el);
200
+ }
201
+ this.elementHeight = el.offsetHeight;
140
202
  }
141
203
 
204
+ // Hide invisible content, when leaving active zone
142
205
  #hideInvisibleContent = () => {
143
206
  var elems = this.targetObject.children;
144
207
  for (let i = 0; i < elems.length; i++) {
@@ -146,6 +209,8 @@ class flexIS {
146
209
  let elementTopPosition = elems[i].offsetTop + elems[i].offsetHeight - this.#scrollTop();
147
210
  let elementBottomPosition = elems[i].offsetTop - elems[i].offsetHeight - this.#scrollTop() - this.#containerSize();
148
211
 
212
+ if (elem.className.includes('ps__rail-x', 'ps__rail-y')) continue;
213
+
149
214
  if (elementTopPosition <= 0 || elementBottomPosition >= 0) {
150
215
  if (elem.style.visibility === 'hidden') continue;
151
216
  elem.style.visibility = 'hidden';
@@ -156,13 +221,60 @@ class flexIS {
156
221
  }
157
222
  }
158
223
 
224
+ #virtualScroll = () => {
225
+ // Find baloon
226
+ var baloon = this.targetObject.getElementsByClassName('fis-baloon')[0];
227
+
228
+ // Create new baloon
229
+ var createBaloon = () => {
230
+ baloon = document.createElement('div');
231
+ baloon.className = 'fis-baloon';
232
+ this.targetObject.appendChild(baloon);
233
+ return baloon;
234
+ }
235
+
236
+ // Check if baloon exist and return it
237
+ var baloonAdded = () => {
238
+ if (baloon) {
239
+ return baloon;
240
+ }
241
+ return false
242
+ }
243
+
244
+ // Update baloon size
245
+ var updateScroll = () => {
246
+ var elementHeight = this.config.virtualScrollElementSize || this.elementHeight;
247
+ if (!baloonAdded()) {
248
+ baloon = createBaloon();
249
+ }
250
+ if (this.elementsLeft > 0) {
251
+ baloon.style.height = (elementHeight * this.elementsLeft) + 'px';
252
+ } else {
253
+ // Remove baloon, if no more elements to load.
254
+ baloon.remove();
255
+ }
256
+ }
257
+
258
+ return {
259
+ update: () => {
260
+ updateScroll()
261
+ },
262
+ baloon: () => {
263
+ return baloonAdded();
264
+ }
265
+ }
266
+ }
267
+
268
+ // Update response attributes
159
269
  #customResponseAttributesSet = () => {
160
270
  var attr = this.config.customResponseAttributes || {};
161
271
  attr.next_page = attr.next_page || 'next_page';
162
272
  attr.data = attr.data || 'data';
273
+ attr.elements_left = attr.elements_left || 'elements_left';
163
274
  this.config.customResponseAttributes = attr
164
275
  }
165
276
 
277
+ // Generate url with params
166
278
  #requestUrl = (params) => {
167
279
  var encodedString = [];
168
280
  for (var prop in params) {
@@ -173,8 +285,15 @@ class flexIS {
173
285
  return this.config.requestUrl + '?' + encodedString.join('&');
174
286
  }
175
287
 
288
+ // Check when load next page
176
289
  #scrollHitBottom = () => {
177
- return (this.#scrollHeight() - this.#scrollTop() - this.#containerSize() - this.config.loadMargin <= 0);
290
+ var hitBottom;
291
+ if (this.#virtualScroll().baloon()) {
292
+ hitBottom = this.#containerPosition() > this.#virtualScroll().baloon().offsetTop;
293
+ } else {
294
+ hitBottom = this.#scrollHeight() - this.#containerPosition() <= 0;
295
+ }
296
+ return hitBottom;
178
297
  }
179
298
  }
180
299
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flex_infinite_scroll
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anton Ignatov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-05-12 00:00:00.000000000 Z
11
+ date: 2020-05-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -55,5 +55,7 @@ rubyforge_project:
55
55
  rubygems_version: 2.6.14.3
56
56
  signing_key:
57
57
  specification_version: 4
58
- summary: Infinite scroll for Ruby on Rails applications on pure JavaScript.
58
+ summary: 'Infinite scroll for Ruby on Rails applications on pure JavaScript. Supported
59
+ features: - Custom response handling. - Virtual scrollbar. - Perfect scrollbar support.
60
+ - Kaminari support.'
59
61
  test_files: []