@cocreate/scroll 1.12.0 → 1.13.1

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocreate/scroll",
3
- "version": "1.12.0",
3
+ "version": "1.13.1",
4
4
  "description": "A simple scroll component in vanilla javascript. Easily configured using HTML5 attributes and/or JavaScript API.",
5
5
  "keywords": [
6
6
  "scroll",
@@ -0,0 +1,16 @@
1
+ module.exports = {
2
+ tabWidth: 4,
3
+ semi: true,
4
+ trailingComma: "none",
5
+ bracketSameLine: true,
6
+ useTabs: true,
7
+ overrides: [
8
+ {
9
+ files: ["*.json", "*.yml", "*.yaml"],
10
+ options: {
11
+ tabWidth: 2,
12
+ useTabs: false
13
+ },
14
+ }
15
+ ],
16
+ };
package/src/index.js CHANGED
@@ -1,288 +1,345 @@
1
- import Observer from '@cocreate/observer';
2
- import Actions from '@cocreate/actions';
1
+ import Observer from "@cocreate/observer";
2
+ import Actions from "@cocreate/actions";
3
3
 
4
4
  const CoCreateScroll = {
5
- delta: 3,
6
- observer: null,
7
- timer: null,
8
- firedEvents: new Map(),
9
-
10
- init: function () {
11
- let elements = document.querySelectorAll(`[scroll], [scroll-to]`);
12
- this.__initIntersectionObserver();
13
- this.initElements(elements);
14
- },
15
-
16
- initElements: function (elements) {
17
- for (let el of elements)
18
- this.initElement(el);
19
- },
20
-
21
- initElement: function (element) {
22
- const self = this;
23
- const upSize = this.__getSize(element.getAttribute('scroll-up'));
24
- const downSize = this.__getSize(element.getAttribute('scroll-down'));
25
- const attrName = element.getAttribute('scroll-attribute') || 'class';
26
- const targetSelector = element.getAttribute('scroll-selector');
27
- const scrollSelector = element.getAttribute('scroll-element');
28
- const intersectValue = element.getAttribute('scroll-intersect');
29
- const scrollTo = element.getAttribute('scroll-to');
30
-
31
- let values = element.getAttribute('scroll') || element.getAttribute('scroll-value');
32
- values = values.split(",").map(x => x.trim());
33
-
34
- let scrollInfo = {
35
- attrName: attrName,
36
- values: values,
37
- upSize: upSize,
38
- downSize: downSize,
39
- scrollTop: element.getAttribute('scroll-top'),
40
- scrollLimbo: element.getAttribute('scroll-limbo'),
41
- scrollBottom: element.getAttribute('scroll-bottom'),
42
- scrolling: element.getAttribute('scrolling'),
43
- scrollTo
44
- };
45
-
46
- let elements = [element];
47
- if (targetSelector) {
48
- elements = document.querySelectorAll(targetSelector);
49
- }
50
-
51
- elements.forEach(el => {
52
- el.scrollStatus = { currentPos: 0 };
53
- });
54
-
55
- // this.__runScrollEvent(element, scrollInfo);
56
-
57
- let scrollableElements;
58
- if (scrollSelector)
59
- scrollableElements = document.querySelectorAll(scrollSelector);
60
- else if (element.hasAttribute('scroll-element'))
61
- scrollableElements = [element]
62
-
63
- if (scrollableElements) {
64
- for (let scrollableEl of scrollableElements) {
65
- scrollableEl.addEventListener('scroll', function (event) {
66
- self._scrollEvent(elements, element, scrollInfo, scrollableEl)
67
- });
68
- }
69
- } else {
70
- // this.WindowInit = true;
71
- window.addEventListener('scroll', function (event) {
72
- self._scrollEvent(elements, element, scrollInfo)
73
- });
74
- }
75
-
76
- if (intersectValue && window.IntersectionObserver && this.observer) {
77
- this.observer.observe(element);
78
- }
79
-
80
- if (scrollTo) {
81
- this.setScrollPosition(element, scrollTo)
82
- }
83
- },
84
-
85
- _scrollEvent: function (elements, element, scrollInfo, scrollableEl) {
86
- const self = this;
87
- if (!element.scrollStatus) return;
88
- let scrollEl = scrollableEl || window;
89
- if (Math.abs(scrollEl.scrollTop || scrollEl.scrollY - element.scrollStatus.currentPos) <= self.delta) {
90
- return;
91
- }
92
-
93
- let timer = null;
94
- if (timer != null) {
95
- clearTimeout(timer);
96
- }
97
-
98
- elements.forEach((el) => {
99
- self.__setScrolling(el, scrollInfo, false);
100
- self.__runScrollEvent(el, scrollInfo, scrollableEl);
101
-
102
- });
103
-
104
- timer = setTimeout(function () {
105
- elements.forEach((el) => {
106
- self.__setScrolling(el, scrollInfo, true);
107
- });
108
- }, 500);
109
- },
110
-
111
- setScrollPosition: function (element, scrollTo) {
112
- if (scrollTo.includes('top')) {
113
- element.scrollTop = 0;
114
- } else if (scrollTo.includes('bottom')) {
115
- element.scrollTop = element.scrollHeight;
116
- }
117
-
118
- if (scrollTo.includes('left')) {
119
- element.scrollLeft = 0;
120
- } else if (scrollTo.includes('right')) {
121
- element.scrollLeft = element.scrollWidth;
122
- }
123
- },
124
-
125
- __initIntersectionObserver: function () {
126
- const self = this;
127
- this.observer = new IntersectionObserver(entries => {
128
- entries.forEach(entry => {
129
- let element = entry.target;
130
- const attrName = element.getAttribute('scroll-attribute') || 'class';
131
- const targetSelector = element.getAttribute('scroll-selector');
132
- const intersectValue = element.getAttribute('scroll-intersect');
133
-
134
- let targetElements = [element];
135
- if (targetSelector) {
136
- targetElements = document.querySelectorAll(targetSelector);
137
- }
138
- if (entry.isIntersecting > 0) {
139
- targetElements.forEach((el) => self.__addAttributeValue(el, attrName, intersectValue));
140
- } else {
141
- targetElements.forEach((el) => self.__removeAttrbuteValue(el, attrName, intersectValue));
142
- }
143
- });
144
- });
145
- },
146
-
147
- __setScrolling: function (element, info, stopped = false) {
148
- const { scrolling, attrName } = info;
149
- if (stopped) {
150
- this.__removeAttrbuteValue(element, attrName, scrolling);
151
- } else {
152
- this.__addAttributeValue(element, attrName, scrolling);
153
- }
154
- },
155
-
156
- __runScrollEvent: function (element, info, scrollableEl) {
157
- if (!element.scrollStatus) return
158
- const currentPos = element.scrollStatus.currentPos;
159
- let scrollY, scrollHeight, innerHeight;
160
- if (scrollableEl) {
161
- scrollY = scrollableEl.scrollTop;
162
- scrollHeight = scrollableEl.scrollHeight
163
- innerHeight = scrollableEl.clientHeight
164
- } else {
165
- scrollY = window.scrollY;
166
- scrollHeight = document.body.scrollHeight
167
- innerHeight = window.innerHeight
168
- }
169
- const { upSize, downSize, attrName, values, scrollTop, scrollBottom, scrollLimbo } = info;
170
-
171
- let newTime = new Date().getTime()
172
- if (!info.datetime || (newTime - info.datetime) > 200) {
173
- info['datetime'] = newTime
174
-
175
- if (upSize <= (currentPos - scrollY)) {
176
- this.__addAttributeValue(element, attrName, values[0]);
177
- this.__removeAttrbuteValue(element, attrName, values[1]);
178
- } else if (downSize <= (scrollY - currentPos)) {
179
- this.__removeAttrbuteValue(element, attrName, values[0]);
180
- this.__addAttributeValue(element, attrName, values[1]);
181
- }
182
- }
183
-
184
- //. scroll top case
185
- if (scrollY <= this.delta) {
186
- this.__removeAttrbuteValue(element, attrName, values[0]);
187
- this.__removeAttrbuteValue(element, attrName, values[1]);
188
-
189
- this.__addAttributeValue(element, attrName, scrollTop);
190
- } else {
191
- this.__removeAttrbuteValue(element, attrName, scrollTop);
192
- }
193
-
194
- //. scroll bottom case
195
- // if ((window.innerHeight + scrollY) >= document.body.scrollHeight) {
196
- if ((innerHeight + scrollY) >= scrollHeight) {
197
- // this.__removeAttrbuteValue(element, attrName, values[0]);
198
- // this.__removeAttrbuteValue(element, attrName, values[1]);
199
-
200
- this.__addAttributeValue(element, attrName, scrollBottom);
201
- } else {
202
- this.__removeAttrbuteValue(element, attrName, scrollBottom);
203
- }
204
-
205
- // if (scrollY != 0 && (scrollY + window.innerHeight) != document.body.scrollHeight){
206
- if (scrollY != 0 && (scrollY + innerHeight) != scrollHeight) {
207
- this.__addAttributeValue(element, attrName, scrollLimbo);
208
- } else {
209
- this.__removeAttrbuteValue(element, attrName, scrollLimbo);
210
- }
211
-
212
- element.scrollStatus.currentPos = scrollY;
213
- },
214
-
215
- __addAttributeValue: function (element, attrName, value) {
216
- if (!value) return;
217
- let check = new RegExp("(\\s|^)" + value + "(\\s|$)");
218
- let attrValue = element.getAttribute(attrName) || "";
219
-
220
- if (!check.test(attrValue)) {
221
- if (attrName === 'class')
222
- attrValue += " " + value;
223
- else
224
- attrValue = value
225
- element.setAttribute(attrName, attrValue);
226
- }
227
- },
228
-
229
- __removeAttrbuteValue: function (element, attrName, value) {
230
- if (!value) return;
231
- let check = new RegExp("(\\s|^)" + value + "(\\s|$)");
232
- let attrValue = element.getAttribute(attrName) || "";
233
-
234
- if (check.test(attrValue)) {
235
- attrValue = attrValue.replace(check, " ").trim();
236
- element.setAttribute(attrName, attrValue);
237
- }
238
- },
239
-
240
- __getSize: function (attrValue, isWidth) {
241
- let size = 0;
242
- if (!attrValue) {
243
- return 0;
244
- }
245
-
246
- if (attrValue.includes('%')) {
247
- size = attrValue.replace('%', '').trim();
248
- size = Number(size) || 0;
249
-
250
- size = isWidth ? window.innerWidth / size : window.innerHeight / size;
251
-
252
- } else {
253
- size = attrValue.replace('px', '').trim();
254
- size = Number(size) || 0;
255
- }
256
-
257
- return size;
258
- }
259
-
5
+ delta: 3,
6
+ observer: null,
7
+ timer: null,
8
+ firedEvents: new Map(),
9
+
10
+ init: function () {
11
+ let elements = document.querySelectorAll(
12
+ `[scroll], [scroll-to], [scrollable-x], [scrollable-y]`
13
+ );
14
+ this.__initIntersectionObserver();
15
+ this.initElements(elements);
16
+ },
17
+
18
+ initElements: function (elements) {
19
+ for (let el of elements) this.initElement(el);
20
+ },
21
+
22
+ initElement: function (element) {
23
+ const self = this;
24
+ const upSize = this.__getSize(element.getAttribute("scroll-up"));
25
+ const downSize = this.__getSize(element.getAttribute("scroll-down"));
26
+ const attrName = element.getAttribute("scroll-attribute") || "class";
27
+ const targetSelector = element.getAttribute("scroll-selector");
28
+ const scrollSelector = element.getAttribute("scroll-element");
29
+ const intersectValue = element.getAttribute("scroll-intersect");
30
+ const scrollTo = element.getAttribute("scroll-to");
31
+
32
+ updateScrollableAttributes(element);
33
+
34
+ let values =
35
+ element.getAttribute("scroll") ||
36
+ element.getAttribute("scroll-value");
37
+ if (values || values === "")
38
+ values = values.split(",").map((x) => x.trim());
39
+
40
+ let scrollInfo = {
41
+ attrName: attrName,
42
+ values: values,
43
+ upSize: upSize,
44
+ downSize: downSize,
45
+ scrollTop: element.getAttribute("scroll-top"),
46
+ scrollLimbo: element.getAttribute("scroll-limbo"),
47
+ scrollBottom: element.getAttribute("scroll-bottom"),
48
+ scrolling: element.getAttribute("scrolling"),
49
+ scrollTo
50
+ };
51
+
52
+ let elements = [element];
53
+ if (targetSelector) {
54
+ elements = document.querySelectorAll(targetSelector);
55
+ }
56
+
57
+ elements.forEach((el) => {
58
+ el.scrollStatus = { currentPos: 0 };
59
+ });
60
+
61
+ // this.__runScrollEvent(element, scrollInfo);
62
+
63
+ let scrollableElements;
64
+ if (scrollSelector)
65
+ scrollableElements = document.querySelectorAll(scrollSelector);
66
+ else if (element.hasAttribute("scroll-element"))
67
+ scrollableElements = [element];
68
+
69
+ if (scrollableElements) {
70
+ for (let scrollableEl of scrollableElements) {
71
+ scrollableEl.addEventListener("scroll", function (event) {
72
+ self._scrollEvent(
73
+ elements,
74
+ element,
75
+ scrollInfo,
76
+ scrollableEl
77
+ );
78
+ });
79
+ }
80
+ } else {
81
+ // this.WindowInit = true;
82
+ window.addEventListener("scroll", function (event) {
83
+ self._scrollEvent(elements, element, scrollInfo);
84
+ });
85
+ }
86
+
87
+ if (intersectValue && window.IntersectionObserver && this.observer) {
88
+ this.observer.observe(element);
89
+ }
90
+
91
+ if (scrollTo) {
92
+ this.setScrollPosition(element, scrollTo);
93
+ }
94
+ },
95
+
96
+ _scrollEvent: function (elements, element, scrollInfo, scrollableEl) {
97
+ const self = this;
98
+ if (!element.scrollStatus) return;
99
+ let scrollEl = scrollableEl || window;
100
+ if (
101
+ Math.abs(
102
+ scrollEl.scrollTop ||
103
+ scrollEl.scrollY - element.scrollStatus.currentPos
104
+ ) <= self.delta
105
+ ) {
106
+ return;
107
+ }
108
+
109
+ let timer = null;
110
+ if (timer != null) {
111
+ clearTimeout(timer);
112
+ }
113
+
114
+ elements.forEach((el) => {
115
+ self.__setScrolling(el, scrollInfo, false);
116
+ self.__runScrollEvent(el, scrollInfo, scrollableEl);
117
+ });
118
+
119
+ timer = setTimeout(function () {
120
+ elements.forEach((el) => {
121
+ self.__setScrolling(el, scrollInfo, true);
122
+ });
123
+ }, 500);
124
+ },
125
+
126
+ setScrollPosition: function (element, scrollTo) {
127
+ if (!scrollTo) return;
128
+ if (scrollTo.includes("top")) {
129
+ element.scrollTop = 0;
130
+ } else if (scrollTo.includes("bottom")) {
131
+ element.scrollTop = element.scrollHeight;
132
+ }
133
+
134
+ if (scrollTo.includes("left")) {
135
+ element.scrollLeft = 0;
136
+ } else if (scrollTo.includes("right")) {
137
+ element.scrollLeft = element.scrollWidth;
138
+ }
139
+ },
140
+
141
+ __initIntersectionObserver: function () {
142
+ const self = this;
143
+ this.observer = new IntersectionObserver((entries) => {
144
+ entries.forEach((entry) => {
145
+ let element = entry.target;
146
+ const attrName =
147
+ element.getAttribute("scroll-attribute") || "class";
148
+ const targetSelector = element.getAttribute("scroll-selector");
149
+ const intersectValue = element.getAttribute("scroll-intersect");
150
+
151
+ let targetElements = [element];
152
+ if (targetSelector) {
153
+ targetElements = document.querySelectorAll(targetSelector);
154
+ }
155
+ if (entry.isIntersecting > 0) {
156
+ targetElements.forEach((el) =>
157
+ self.__addAttributeValue(el, attrName, intersectValue)
158
+ );
159
+ } else {
160
+ targetElements.forEach((el) =>
161
+ self.__removeAttrbuteValue(el, attrName, intersectValue)
162
+ );
163
+ }
164
+ });
165
+ });
166
+ },
167
+
168
+ __setScrolling: function (element, info, stopped = false) {
169
+ const { scrolling, attrName } = info;
170
+ if (stopped) {
171
+ this.__removeAttrbuteValue(element, attrName, scrolling);
172
+ } else {
173
+ this.__addAttributeValue(element, attrName, scrolling);
174
+ }
175
+ },
176
+
177
+ __runScrollEvent: function (element, info, scrollableEl) {
178
+ if (!element.scrollStatus) return;
179
+ const currentPos = element.scrollStatus.currentPos;
180
+ let scrollY, scrollHeight, innerHeight;
181
+ if (scrollableEl) {
182
+ scrollY = scrollableEl.scrollTop;
183
+ scrollHeight = scrollableEl.scrollHeight;
184
+ innerHeight = scrollableEl.clientHeight;
185
+ } else {
186
+ scrollY = window.scrollY;
187
+ scrollHeight = document.body.scrollHeight;
188
+ innerHeight = window.innerHeight;
189
+ }
190
+ const {
191
+ upSize,
192
+ downSize,
193
+ attrName,
194
+ values,
195
+ scrollTop,
196
+ scrollBottom,
197
+ scrollLimbo
198
+ } = info;
199
+
200
+ let newTime = new Date().getTime();
201
+ if (!info.datetime || newTime - info.datetime > 200) {
202
+ info["datetime"] = newTime;
203
+
204
+ if (upSize <= currentPos - scrollY) {
205
+ this.__addAttributeValue(element, attrName, values[0]);
206
+ this.__removeAttrbuteValue(element, attrName, values[1]);
207
+ } else if (downSize <= scrollY - currentPos) {
208
+ this.__removeAttrbuteValue(element, attrName, values[0]);
209
+ this.__addAttributeValue(element, attrName, values[1]);
210
+ }
211
+ }
212
+
213
+ //. scroll top case
214
+ if (scrollY <= this.delta) {
215
+ this.__removeAttrbuteValue(element, attrName, values[0]);
216
+ this.__removeAttrbuteValue(element, attrName, values[1]);
217
+
218
+ this.__addAttributeValue(element, attrName, scrollTop);
219
+ } else {
220
+ this.__removeAttrbuteValue(element, attrName, scrollTop);
221
+ }
222
+
223
+ //. scroll bottom case
224
+ // if ((window.innerHeight + scrollY) >= document.body.scrollHeight) {
225
+ if (innerHeight + scrollY >= scrollHeight) {
226
+ // this.__removeAttrbuteValue(element, attrName, values[0]);
227
+ // this.__removeAttrbuteValue(element, attrName, values[1]);
228
+
229
+ this.__addAttributeValue(element, attrName, scrollBottom);
230
+ } else {
231
+ this.__removeAttrbuteValue(element, attrName, scrollBottom);
232
+ }
233
+
234
+ // if (scrollY != 0 && (scrollY + window.innerHeight) != document.body.scrollHeight){
235
+ if (scrollY != 0 && scrollY + innerHeight != scrollHeight) {
236
+ this.__addAttributeValue(element, attrName, scrollLimbo);
237
+ } else {
238
+ this.__removeAttrbuteValue(element, attrName, scrollLimbo);
239
+ }
240
+
241
+ element.scrollStatus.currentPos = scrollY;
242
+ },
243
+
244
+ __addAttributeValue: function (element, attrName, value) {
245
+ if (!value) return;
246
+ let check = new RegExp("(\\s|^)" + value + "(\\s|$)");
247
+ let attrValue = element.getAttribute(attrName) || "";
248
+
249
+ if (!check.test(attrValue)) {
250
+ if (attrName === "class") attrValue += " " + value;
251
+ else attrValue = value;
252
+ element.setAttribute(attrName, attrValue);
253
+ }
254
+ },
255
+
256
+ __removeAttrbuteValue: function (element, attrName, value) {
257
+ if (!value) return;
258
+ let check = new RegExp("(\\s|^)" + value + "(\\s|$)");
259
+ let attrValue = element.getAttribute(attrName) || "";
260
+
261
+ if (check.test(attrValue)) {
262
+ attrValue = attrValue.replace(check, " ").trim();
263
+ element.setAttribute(attrName, attrValue);
264
+ }
265
+ },
266
+
267
+ __getSize: function (attrValue, isWidth) {
268
+ let size = 0;
269
+ if (!attrValue) {
270
+ return 0;
271
+ }
272
+
273
+ if (attrValue.includes("%")) {
274
+ size = attrValue.replace("%", "").trim();
275
+ size = Number(size) || 0;
276
+
277
+ size = isWidth
278
+ ? window.innerWidth / size
279
+ : window.innerHeight / size;
280
+ } else {
281
+ size = attrValue.replace("px", "").trim();
282
+ size = Number(size) || 0;
283
+ }
284
+
285
+ return size;
286
+ }
260
287
  };
261
288
 
289
+ function updateScrollableAttributes(element) {
290
+ if (element.hasAttribute("scrollable-y")) {
291
+ if (element.scrollWidth > element.clientWidth)
292
+ element.setAttribute("scrollable-y", "true");
293
+ else element.setAttribute("scrollable-y", "false");
294
+ }
295
+
296
+ if (element.hasAttribute("scrollable-x")) {
297
+ if (element.scrollHeight > element.clientHeight)
298
+ element.setAttribute("scrollable-x", "true");
299
+ else element.setAttribute("scrollable-x", "false");
300
+ }
301
+ }
302
+
262
303
  Observer.init({
263
- name: 'CoCreateScrollCreate',
264
- observe: ['addedNodes'],
265
- target: '[scroll], [scroll-to]',
266
- callback: function (mutation) {
267
- CoCreateScroll.initElement(mutation.target);
268
- }
304
+ name: "CoCreateScrollCreate",
305
+ types: ["addedNodes"],
306
+ selector: "[scroll], [scroll-to], [scrollable-x], [scrollable-y]",
307
+ callback: function (mutation) {
308
+ CoCreateScroll.initElement(mutation.target);
309
+ }
269
310
  });
270
311
 
271
312
  Observer.init({
272
- name: 'CoCreateScrollAttributes',
273
- observe: ['attributes'],
274
- attributeName: ['scroll-to'],
275
- // target: selector, // blocks mutations when applied
276
- callback: function (mutation) {
277
- CoCreateScroll.setScrollPosition(mutation.target, mutation.target.getAttribute('scroll-to'))
278
- }
313
+ name: "CoCreateScrollAttributes",
314
+ types: ["attributes"],
315
+ attributeFilter: ["scroll-to"],
316
+ // target: selector, // blocks mutations when applied
317
+ callback: function (mutation) {
318
+ CoCreateScroll.setScrollPosition(
319
+ mutation.target,
320
+ mutation.target.getAttribute("scroll-to")
321
+ );
322
+ }
323
+ });
324
+ Observer.init({
325
+ name: "CoCreateScrollAttributes",
326
+ types: ["attributes"],
327
+ attributeFilter: ["scrollable-x", "scrollable-y"],
328
+ // target: selector, // blocks mutations when applied
329
+ callback: function (mutation) {
330
+ if (
331
+ mutation.oldValue !==
332
+ mutation.target.getAttribute(mutation.attributeName)
333
+ )
334
+ updateScrollableAttributes(mutation.target);
335
+ }
279
336
  });
280
337
 
281
338
  Actions.init({
282
- name: "scroll-to",
283
- callback: (action) => {
284
- // CoCreateScroll.setScrollPosition(mutation.target)
285
- }
339
+ name: "scroll-to",
340
+ callback: (action) => {
341
+ // CoCreateScroll.setScrollPosition(mutation.target)
342
+ }
286
343
  });
287
344
 
288
345
  CoCreateScroll.init();