handy-scroll 1.1.5 → 2.0.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.
@@ -1,279 +0,0 @@
1
- /*!
2
- handy-scroll v1.1.5
3
- https://amphiluke.github.io/handy-scroll/
4
- (c) 2024 Amphiluke
5
- */
6
- (function (global, factory) {
7
- typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
8
- typeof define === 'function' && define.amd ? define(factory) :
9
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.handyScroll = factory());
10
- })(this, (function () { 'use strict';
11
-
12
- let slice = Array.prototype.slice;
13
-
14
- let dom = {
15
- // Precaution to avoid reference errors when imported for SSR (issue #13)
16
- isDOMAvailable: typeof document === "object" && !!document.documentElement,
17
-
18
- ready(handler) {
19
- if (document.readyState === "loading") {
20
- document.addEventListener("DOMContentLoaded", () => void handler(), {once: true});
21
- } else {
22
- handler();
23
- }
24
- },
25
-
26
- $(ref) {
27
- if (typeof ref === "string") { // ref is a selector
28
- return document.body.querySelector(ref);
29
- }
30
- return ref; // ref is already an element
31
- },
32
-
33
- $$(ref) {
34
- if (Array.isArray(ref)) { // ref is an array of elements
35
- return ref;
36
- }
37
- if (ref.nodeType === Node.ELEMENT_NODE) { // ref is an element
38
- return [ref];
39
- }
40
- if (typeof ref === "string") { // ref is a selector
41
- return slice.call(document.body.querySelectorAll(ref));
42
- }
43
- return slice.call(ref); // ref is an array-like object (NodeList or HTMLCollection)
44
- }
45
- };
46
-
47
- let handyScrollProto = {
48
- init(container) {
49
- let instance = this;
50
- let scrollBodies = dom.$$(".handy-scroll-body")
51
- .filter(node => node.contains(container));
52
- if (scrollBodies.length) {
53
- instance.scrollBody = scrollBodies[0];
54
- }
55
- instance.container = container;
56
- instance.visible = true;
57
- instance.initWidget();
58
- instance.update(); // recalculate scrollbar parameters and set its visibility
59
- instance.addEventHandlers();
60
- // Set skipSync flags to their initial values (because update() above calls syncWidget())
61
- instance.skipSyncContainer = instance.skipSyncWidget = false;
62
- },
63
-
64
- initWidget() {
65
- let instance = this;
66
- let widget = instance.widget = document.createElement("div");
67
- widget.classList.add("handy-scroll");
68
- let strut = document.createElement("div");
69
- strut.style.width = `${instance.container.scrollWidth}px`;
70
- widget.appendChild(strut);
71
- instance.container.appendChild(widget);
72
- },
73
-
74
- addEventHandlers() {
75
- let instance = this;
76
- let eventHandlers = instance.eventHandlers = [
77
- {
78
- el: instance.scrollBody || window,
79
- handlers: {
80
- scroll() {
81
- instance.checkVisibility();
82
- },
83
- resize() {
84
- instance.update();
85
- }
86
- }
87
- },
88
- {
89
- el: instance.widget,
90
- handlers: {
91
- scroll() {
92
- if (instance.visible && !instance.skipSyncContainer) {
93
- instance.syncContainer();
94
- }
95
- // Resume widget->container syncing after the widget scrolling has finished
96
- // (it might be temporally disabled by the container while syncing the widget)
97
- instance.skipSyncContainer = false;
98
- }
99
- }
100
- },
101
- {
102
- el: instance.container,
103
- handlers: {
104
- scroll() {
105
- if (!instance.skipSyncWidget) {
106
- instance.syncWidget();
107
- }
108
- // Resume container->widget syncing after the container scrolling has finished
109
- // (it might be temporally disabled by the widget while syncing the container)
110
- instance.skipSyncWidget = false;
111
- },
112
- focusin() {
113
- setTimeout(() => {
114
- // The widget might be destroyed before the timer is triggered (issue #14)
115
- if (instance.widget) {
116
- instance.syncWidget();
117
- }
118
- }, 0);
119
- }
120
- }
121
- }
122
- ];
123
- eventHandlers.forEach(({el, handlers}) => {
124
- Object.keys(handlers).forEach(event => el.addEventListener(event, handlers[event], false));
125
- });
126
- },
127
-
128
- checkVisibility() {
129
- let instance = this;
130
- let {widget, container, scrollBody} = instance;
131
- let mustHide = (widget.scrollWidth <= widget.offsetWidth);
132
- if (!mustHide) {
133
- let containerRect = container.getBoundingClientRect();
134
- let maxVisibleY = scrollBody ?
135
- scrollBody.getBoundingClientRect().bottom :
136
- window.innerHeight || document.documentElement.clientHeight;
137
- mustHide = ((containerRect.bottom <= maxVisibleY) || (containerRect.top > maxVisibleY));
138
- }
139
- if (instance.visible === mustHide) {
140
- instance.visible = !mustHide;
141
- // We cannot simply hide the scrollbar since its scrollLeft property will not update in that case
142
- widget.classList.toggle("handy-scroll-hidden");
143
- }
144
- },
145
-
146
- syncContainer() {
147
- let instance = this;
148
- let {scrollLeft} = instance.widget;
149
- if (instance.container.scrollLeft !== scrollLeft) {
150
- // Prevents container’s “scroll” event handler from syncing back again widget scroll position
151
- instance.skipSyncWidget = true;
152
- // Note that this makes container’s “scroll” event handlers execute
153
- instance.container.scrollLeft = scrollLeft;
154
- }
155
- },
156
-
157
- syncWidget() {
158
- let instance = this;
159
- let {scrollLeft} = instance.container;
160
- if (instance.widget.scrollLeft !== scrollLeft) {
161
- // Prevents widget’s “scroll” event handler from syncing back again container scroll position
162
- instance.skipSyncContainer = true;
163
- // Note that this makes widget’s “scroll” event handlers execute
164
- instance.widget.scrollLeft = scrollLeft;
165
- }
166
- },
167
-
168
- // Recalculate scroll width and container boundaries
169
- update() {
170
- let instance = this;
171
- let {widget, container, scrollBody} = instance;
172
- let {clientWidth, scrollWidth} = container;
173
- widget.style.width = `${clientWidth}px`;
174
- if (!scrollBody) {
175
- widget.style.left = `${container.getBoundingClientRect().left}px`;
176
- }
177
- widget.firstElementChild.style.width = `${scrollWidth}px`;
178
- // Fit widget height to the native scroll bar height if needed
179
- if (scrollWidth > clientWidth) {
180
- widget.style.height = `${widget.offsetHeight - widget.clientHeight + 1}px`; // +1px JIC
181
- }
182
- instance.syncWidget();
183
- instance.checkVisibility(); // fixes issue Amphiluke/floating-scroll#2
184
- },
185
-
186
- // Remove a scrollbar and all related event handlers
187
- destroy() {
188
- let instance = this;
189
- instance.eventHandlers.forEach(({el, handlers}) => {
190
- Object.keys(handlers).forEach(event => el.removeEventListener(event, handlers[event], false));
191
- });
192
- instance.widget.remove();
193
- instance.eventHandlers = instance.widget = instance.container = instance.scrollBody = null;
194
- }
195
- };
196
-
197
- let instances = []; // if it were not for IE, it would be better to use Map (container -> instance)
198
-
199
- let handyScroll = {
200
- /**
201
- * Mount widgets in the given containers
202
- * @param {HTMLElement|NodeList|HTMLCollection|HTMLElement[]|String} containerRef - Widget container reference (either an element, or a list of elements, or a selector)
203
- */
204
- mount(containerRef) {
205
- dom.$$(containerRef).forEach(container => {
206
- if (handyScroll.mounted(container)) {
207
- return;
208
- }
209
- let instance = Object.create(handyScrollProto);
210
- instances.push(instance);
211
- instance.init(container);
212
- });
213
- },
214
-
215
- /**
216
- * Check if a widget is already mounted in the given container
217
- * @param {HTMLElement|String} containerRef - Widget container reference (either an element, or a selector)
218
- * @returns {Boolean}
219
- */
220
- mounted(containerRef) {
221
- let container = dom.$(containerRef);
222
- return instances.some(instance => instance.container === container);
223
- },
224
-
225
- /**
226
- * Update widget parameters and position
227
- * @param {HTMLElement|NodeList|HTMLCollection|HTMLElement[]|String} containerRef - Widget container reference (either an element, or a list of elements, or a selector)
228
- */
229
- update(containerRef) {
230
- dom.$$(containerRef).forEach(container => {
231
- instances.some(instance => {
232
- if (instance.container === container) {
233
- instance.update();
234
- return true;
235
- }
236
- return false;
237
- });
238
- });
239
- },
240
-
241
- /**
242
- * Destroy widgets mounted in the given containers
243
- * @param {HTMLElement|NodeList|HTMLCollection|HTMLElement[]|String} containerRef - Widget container reference (either an element, or a list of elements, or a selector)
244
- */
245
- destroy(containerRef) {
246
- dom.$$(containerRef).forEach(container => {
247
- instances.some((instance, index) => {
248
- if (instance.container === container) {
249
- instances.splice(index, 1)[0].destroy();
250
- return true;
251
- }
252
- return false;
253
- });
254
- });
255
- },
256
-
257
- /**
258
- * Destroy handyScroll widgets whose containers are not in the document anymore
259
- */
260
- destroyDetached() {
261
- instances = instances.filter(instance => {
262
- if (!document.body.contains(instance.container)) {
263
- instance.destroy();
264
- return false;
265
- }
266
- return true;
267
- });
268
- }
269
- };
270
-
271
- if (dom.isDOMAvailable) {
272
- dom.ready(() => {
273
- handyScroll.mount("[data-handy-scroll]");
274
- });
275
- }
276
-
277
- return handyScroll;
278
-
279
- }));
@@ -1,6 +0,0 @@
1
- /*!
2
- handy-scroll v1.1.5
3
- https://amphiluke.github.io/handy-scroll/
4
- (c) 2024 Amphiluke
5
- */
6
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).handyScroll=t()}(this,(function(){"use strict";let e=Array.prototype.slice,t={isDOMAvailable:"object"==typeof document&&!!document.documentElement,ready(e){"loading"===document.readyState?document.addEventListener("DOMContentLoaded",(()=>{e()}),{once:!0}):e()},$:e=>"string"==typeof e?document.body.querySelector(e):e,$$:t=>Array.isArray(t)?t:t.nodeType===Node.ELEMENT_NODE?[t]:"string"==typeof t?e.call(document.body.querySelectorAll(t)):e.call(t)},n={init(e){let n=this,i=t.$$(".handy-scroll-body").filter((t=>t.contains(e)));i.length&&(n.scrollBody=i[0]),n.container=e,n.visible=!0,n.initWidget(),n.update(),n.addEventHandlers(),n.skipSyncContainer=n.skipSyncWidget=!1},initWidget(){let e=this,t=e.widget=document.createElement("div");t.classList.add("handy-scroll");let n=document.createElement("div");n.style.width=`${e.container.scrollWidth}px`,t.appendChild(n),e.container.appendChild(t)},addEventHandlers(){let e=this;(e.eventHandlers=[{el:e.scrollBody||window,handlers:{scroll(){e.checkVisibility()},resize(){e.update()}}},{el:e.widget,handlers:{scroll(){e.visible&&!e.skipSyncContainer&&e.syncContainer(),e.skipSyncContainer=!1}}},{el:e.container,handlers:{scroll(){e.skipSyncWidget||e.syncWidget(),e.skipSyncWidget=!1},focusin(){setTimeout((()=>{e.widget&&e.syncWidget()}),0)}}}]).forEach((({el:e,handlers:t})=>{Object.keys(t).forEach((n=>e.addEventListener(n,t[n],!1)))}))},checkVisibility(){let e=this,{widget:t,container:n,scrollBody:i}=e,l=t.scrollWidth<=t.offsetWidth;if(!l){let e=n.getBoundingClientRect(),t=i?i.getBoundingClientRect().bottom:window.innerHeight||document.documentElement.clientHeight;l=e.bottom<=t||e.top>t}e.visible===l&&(e.visible=!l,t.classList.toggle("handy-scroll-hidden"))},syncContainer(){let e=this,{scrollLeft:t}=e.widget;e.container.scrollLeft!==t&&(e.skipSyncWidget=!0,e.container.scrollLeft=t)},syncWidget(){let e=this,{scrollLeft:t}=e.container;e.widget.scrollLeft!==t&&(e.skipSyncContainer=!0,e.widget.scrollLeft=t)},update(){let e=this,{widget:t,container:n,scrollBody:i}=e,{clientWidth:l,scrollWidth:o}=n;t.style.width=`${l}px`,i||(t.style.left=`${n.getBoundingClientRect().left}px`),t.firstElementChild.style.width=`${o}px`,o>l&&(t.style.height=t.offsetHeight-t.clientHeight+1+"px"),e.syncWidget(),e.checkVisibility()},destroy(){let e=this;e.eventHandlers.forEach((({el:e,handlers:t})=>{Object.keys(t).forEach((n=>e.removeEventListener(n,t[n],!1)))})),e.widget.remove(),e.eventHandlers=e.widget=e.container=e.scrollBody=null}},i=[],l={mount(e){t.$$(e).forEach((e=>{if(l.mounted(e))return;let t=Object.create(n);i.push(t),t.init(e)}))},mounted(e){let n=t.$(e);return i.some((e=>e.container===n))},update(e){t.$$(e).forEach((e=>{i.some((t=>t.container===e&&(t.update(),!0)))}))},destroy(e){t.$$(e).forEach((e=>{i.some(((t,n)=>t.container===e&&(i.splice(n,1)[0].destroy(),!0)))}))},destroyDetached(){i=i.filter((e=>!!document.body.contains(e.container)||(e.destroy(),!1)))}};return t.isDOMAvailable&&t.ready((()=>{l.mount("[data-handy-scroll]")})),l}));
@@ -1,281 +0,0 @@
1
- /*!
2
- handy-scroll v1.1.5
3
- https://amphiluke.github.io/handy-scroll/
4
- (c) 2024 Amphiluke
5
- */
6
- (function (global, factory) {
7
- typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
8
- typeof define === 'function' && define.amd ? define(factory) :
9
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.handyScroll = factory());
10
- })(this, (function () { 'use strict';
11
-
12
- var slice = Array.prototype.slice;
13
- var dom = {
14
- // Precaution to avoid reference errors when imported for SSR (issue #13)
15
- isDOMAvailable: typeof document === "object" && !!document.documentElement,
16
- ready: function ready(handler) {
17
- if (document.readyState === "loading") {
18
- document.addEventListener("DOMContentLoaded", function () {
19
- return void handler();
20
- }, {
21
- once: true
22
- });
23
- } else {
24
- handler();
25
- }
26
- },
27
- $: function $(ref) {
28
- if (typeof ref === "string") {
29
- // ref is a selector
30
- return document.body.querySelector(ref);
31
- }
32
- return ref; // ref is already an element
33
- },
34
- $$: function $$(ref) {
35
- if (Array.isArray(ref)) {
36
- // ref is an array of elements
37
- return ref;
38
- }
39
- if (ref.nodeType === Node.ELEMENT_NODE) {
40
- // ref is an element
41
- return [ref];
42
- }
43
- if (typeof ref === "string") {
44
- // ref is a selector
45
- return slice.call(document.body.querySelectorAll(ref));
46
- }
47
- return slice.call(ref); // ref is an array-like object (NodeList or HTMLCollection)
48
- }
49
- };
50
-
51
- var handyScrollProto = {
52
- init: function init(container) {
53
- var instance = this;
54
- var scrollBodies = dom.$$(".handy-scroll-body").filter(function (node) {
55
- return node.contains(container);
56
- });
57
- if (scrollBodies.length) {
58
- instance.scrollBody = scrollBodies[0];
59
- }
60
- instance.container = container;
61
- instance.visible = true;
62
- instance.initWidget();
63
- instance.update(); // recalculate scrollbar parameters and set its visibility
64
- instance.addEventHandlers();
65
- // Set skipSync flags to their initial values (because update() above calls syncWidget())
66
- instance.skipSyncContainer = instance.skipSyncWidget = false;
67
- },
68
- initWidget: function initWidget() {
69
- var instance = this;
70
- var widget = instance.widget = document.createElement("div");
71
- widget.classList.add("handy-scroll");
72
- var strut = document.createElement("div");
73
- strut.style.width = instance.container.scrollWidth + "px";
74
- widget.appendChild(strut);
75
- instance.container.appendChild(widget);
76
- },
77
- addEventHandlers: function addEventHandlers() {
78
- var instance = this;
79
- var eventHandlers = instance.eventHandlers = [{
80
- el: instance.scrollBody || window,
81
- handlers: {
82
- scroll: function scroll() {
83
- instance.checkVisibility();
84
- },
85
- resize: function resize() {
86
- instance.update();
87
- }
88
- }
89
- }, {
90
- el: instance.widget,
91
- handlers: {
92
- scroll: function scroll() {
93
- if (instance.visible && !instance.skipSyncContainer) {
94
- instance.syncContainer();
95
- }
96
- // Resume widget->container syncing after the widget scrolling has finished
97
- // (it might be temporally disabled by the container while syncing the widget)
98
- instance.skipSyncContainer = false;
99
- }
100
- }
101
- }, {
102
- el: instance.container,
103
- handlers: {
104
- scroll: function scroll() {
105
- if (!instance.skipSyncWidget) {
106
- instance.syncWidget();
107
- }
108
- // Resume container->widget syncing after the container scrolling has finished
109
- // (it might be temporally disabled by the widget while syncing the container)
110
- instance.skipSyncWidget = false;
111
- },
112
- focusin: function focusin() {
113
- setTimeout(function () {
114
- // The widget might be destroyed before the timer is triggered (issue #14)
115
- if (instance.widget) {
116
- instance.syncWidget();
117
- }
118
- }, 0);
119
- }
120
- }
121
- }];
122
- eventHandlers.forEach(function (_ref) {
123
- var el = _ref.el,
124
- handlers = _ref.handlers;
125
- Object.keys(handlers).forEach(function (event) {
126
- return el.addEventListener(event, handlers[event], false);
127
- });
128
- });
129
- },
130
- checkVisibility: function checkVisibility() {
131
- var instance = this;
132
- var widget = instance.widget,
133
- container = instance.container,
134
- scrollBody = instance.scrollBody;
135
- var mustHide = widget.scrollWidth <= widget.offsetWidth;
136
- if (!mustHide) {
137
- var containerRect = container.getBoundingClientRect();
138
- var maxVisibleY = scrollBody ? scrollBody.getBoundingClientRect().bottom : window.innerHeight || document.documentElement.clientHeight;
139
- mustHide = containerRect.bottom <= maxVisibleY || containerRect.top > maxVisibleY;
140
- }
141
- if (instance.visible === mustHide) {
142
- instance.visible = !mustHide;
143
- // We cannot simply hide the scrollbar since its scrollLeft property will not update in that case
144
- widget.classList.toggle("handy-scroll-hidden");
145
- }
146
- },
147
- syncContainer: function syncContainer() {
148
- var instance = this;
149
- var scrollLeft = instance.widget.scrollLeft;
150
- if (instance.container.scrollLeft !== scrollLeft) {
151
- // Prevents container’s “scroll” event handler from syncing back again widget scroll position
152
- instance.skipSyncWidget = true;
153
- // Note that this makes container’s “scroll” event handlers execute
154
- instance.container.scrollLeft = scrollLeft;
155
- }
156
- },
157
- syncWidget: function syncWidget() {
158
- var instance = this;
159
- var scrollLeft = instance.container.scrollLeft;
160
- if (instance.widget.scrollLeft !== scrollLeft) {
161
- // Prevents widget’s “scroll” event handler from syncing back again container scroll position
162
- instance.skipSyncContainer = true;
163
- // Note that this makes widget’s “scroll” event handlers execute
164
- instance.widget.scrollLeft = scrollLeft;
165
- }
166
- },
167
- // Recalculate scroll width and container boundaries
168
- update: function update() {
169
- var instance = this;
170
- var widget = instance.widget,
171
- container = instance.container,
172
- scrollBody = instance.scrollBody;
173
- var clientWidth = container.clientWidth,
174
- scrollWidth = container.scrollWidth;
175
- widget.style.width = clientWidth + "px";
176
- if (!scrollBody) {
177
- widget.style.left = container.getBoundingClientRect().left + "px";
178
- }
179
- widget.firstElementChild.style.width = scrollWidth + "px";
180
- // Fit widget height to the native scroll bar height if needed
181
- if (scrollWidth > clientWidth) {
182
- widget.style.height = widget.offsetHeight - widget.clientHeight + 1 + "px"; // +1px JIC
183
- }
184
- instance.syncWidget();
185
- instance.checkVisibility(); // fixes issue Amphiluke/floating-scroll#2
186
- },
187
- // Remove a scrollbar and all related event handlers
188
- destroy: function destroy() {
189
- var instance = this;
190
- instance.eventHandlers.forEach(function (_ref2) {
191
- var el = _ref2.el,
192
- handlers = _ref2.handlers;
193
- Object.keys(handlers).forEach(function (event) {
194
- return el.removeEventListener(event, handlers[event], false);
195
- });
196
- });
197
- instance.widget.remove();
198
- instance.eventHandlers = instance.widget = instance.container = instance.scrollBody = null;
199
- }
200
- };
201
-
202
- var instances = []; // if it were not for IE, it would be better to use Map (container -> instance)
203
-
204
- var handyScroll = {
205
- /**
206
- * Mount widgets in the given containers
207
- * @param {HTMLElement|NodeList|HTMLCollection|HTMLElement[]|String} containerRef - Widget container reference (either an element, or a list of elements, or a selector)
208
- */
209
- mount: function mount(containerRef) {
210
- dom.$$(containerRef).forEach(function (container) {
211
- if (handyScroll.mounted(container)) {
212
- return;
213
- }
214
- var instance = Object.create(handyScrollProto);
215
- instances.push(instance);
216
- instance.init(container);
217
- });
218
- },
219
- /**
220
- * Check if a widget is already mounted in the given container
221
- * @param {HTMLElement|String} containerRef - Widget container reference (either an element, or a selector)
222
- * @returns {Boolean}
223
- */
224
- mounted: function mounted(containerRef) {
225
- var container = dom.$(containerRef);
226
- return instances.some(function (instance) {
227
- return instance.container === container;
228
- });
229
- },
230
- /**
231
- * Update widget parameters and position
232
- * @param {HTMLElement|NodeList|HTMLCollection|HTMLElement[]|String} containerRef - Widget container reference (either an element, or a list of elements, or a selector)
233
- */
234
- update: function update(containerRef) {
235
- dom.$$(containerRef).forEach(function (container) {
236
- instances.some(function (instance) {
237
- if (instance.container === container) {
238
- instance.update();
239
- return true;
240
- }
241
- return false;
242
- });
243
- });
244
- },
245
- /**
246
- * Destroy widgets mounted in the given containers
247
- * @param {HTMLElement|NodeList|HTMLCollection|HTMLElement[]|String} containerRef - Widget container reference (either an element, or a list of elements, or a selector)
248
- */
249
- destroy: function destroy(containerRef) {
250
- dom.$$(containerRef).forEach(function (container) {
251
- instances.some(function (instance, index) {
252
- if (instance.container === container) {
253
- instances.splice(index, 1)[0].destroy();
254
- return true;
255
- }
256
- return false;
257
- });
258
- });
259
- },
260
- /**
261
- * Destroy handyScroll widgets whose containers are not in the document anymore
262
- */
263
- destroyDetached: function destroyDetached() {
264
- instances = instances.filter(function (instance) {
265
- if (!document.body.contains(instance.container)) {
266
- instance.destroy();
267
- return false;
268
- }
269
- return true;
270
- });
271
- }
272
- };
273
- if (dom.isDOMAvailable) {
274
- dom.ready(function () {
275
- handyScroll.mount("[data-handy-scroll]");
276
- });
277
- }
278
-
279
- return handyScroll;
280
-
281
- }));
@@ -1,6 +0,0 @@
1
- /*!
2
- handy-scroll v1.1.5
3
- https://amphiluke.github.io/handy-scroll/
4
- (c) 2024 Amphiluke
5
- */
6
- !function(t,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(t="undefined"!=typeof globalThis?globalThis:t||self).handyScroll=n()}(this,(function(){"use strict";var t=Array.prototype.slice,n="object"==typeof document&&!!document.documentElement,e=function(t){return"string"==typeof t?document.body.querySelector(t):t},i=function(n){return Array.isArray(n)?n:n.nodeType===Node.ELEMENT_NODE?[n]:"string"==typeof n?t.call(document.body.querySelectorAll(n)):t.call(n)},o={init:function(t){var n=this,e=i(".handy-scroll-body").filter((function(n){return n.contains(t)}));e.length&&(n.scrollBody=e[0]),n.container=t,n.visible=!0,n.initWidget(),n.update(),n.addEventHandlers(),n.skipSyncContainer=n.skipSyncWidget=!1},initWidget:function(){var t=this,n=t.widget=document.createElement("div");n.classList.add("handy-scroll");var e=document.createElement("div");e.style.width=t.container.scrollWidth+"px",n.appendChild(e),t.container.appendChild(n)},addEventHandlers:function(){var t=this;(t.eventHandlers=[{el:t.scrollBody||window,handlers:{scroll:function(){t.checkVisibility()},resize:function(){t.update()}}},{el:t.widget,handlers:{scroll:function(){t.visible&&!t.skipSyncContainer&&t.syncContainer(),t.skipSyncContainer=!1}}},{el:t.container,handlers:{scroll:function(){t.skipSyncWidget||t.syncWidget(),t.skipSyncWidget=!1},focusin:function(){setTimeout((function(){t.widget&&t.syncWidget()}),0)}}}]).forEach((function(t){var n=t.el,e=t.handlers;Object.keys(e).forEach((function(t){return n.addEventListener(t,e[t],!1)}))}))},checkVisibility:function(){var t=this,n=t.widget,e=t.container,i=t.scrollBody,o=n.scrollWidth<=n.offsetWidth;if(!o){var c=e.getBoundingClientRect(),r=i?i.getBoundingClientRect().bottom:window.innerHeight||document.documentElement.clientHeight;o=c.bottom<=r||c.top>r}t.visible===o&&(t.visible=!o,n.classList.toggle("handy-scroll-hidden"))},syncContainer:function(){var t=this,n=t.widget.scrollLeft;t.container.scrollLeft!==n&&(t.skipSyncWidget=!0,t.container.scrollLeft=n)},syncWidget:function(){var t=this,n=t.container.scrollLeft;t.widget.scrollLeft!==n&&(t.skipSyncContainer=!0,t.widget.scrollLeft=n)},update:function(){var t=this,n=t.widget,e=t.container,i=t.scrollBody,o=e.clientWidth,c=e.scrollWidth;n.style.width=o+"px",i||(n.style.left=e.getBoundingClientRect().left+"px"),n.firstElementChild.style.width=c+"px",c>o&&(n.style.height=n.offsetHeight-n.clientHeight+1+"px"),t.syncWidget(),t.checkVisibility()},destroy:function(){var t=this;t.eventHandlers.forEach((function(t){var n=t.el,e=t.handlers;Object.keys(e).forEach((function(t){return n.removeEventListener(t,e[t],!1)}))})),t.widget.remove(),t.eventHandlers=t.widget=t.container=t.scrollBody=null}},c=[],r={mount:function(t){i(t).forEach((function(t){if(!r.mounted(t)){var n=Object.create(o);c.push(n),n.init(t)}}))},mounted:function(t){var n=e(t);return c.some((function(t){return t.container===n}))},update:function(t){i(t).forEach((function(t){c.some((function(n){return n.container===t&&(n.update(),!0)}))}))},destroy:function(t){i(t).forEach((function(t){c.some((function(n,e){return n.container===t&&(c.splice(e,1)[0].destroy(),!0)}))}))},destroyDetached:function(){c=c.filter((function(t){return!!document.body.contains(t.container)||(t.destroy(),!1)}))}};return n&&function(t){"loading"===document.readyState?document.addEventListener("DOMContentLoaded",(function(){t()}),{once:!0}):t()}((function(){r.mount("[data-handy-scroll]")})),r}));
package/src/dom.js DELETED
@@ -1,36 +0,0 @@
1
- let slice = Array.prototype.slice;
2
-
3
- let dom = {
4
- // Precaution to avoid reference errors when imported for SSR (issue #13)
5
- isDOMAvailable: typeof document === "object" && !!document.documentElement,
6
-
7
- ready(handler) {
8
- if (document.readyState === "loading") {
9
- document.addEventListener("DOMContentLoaded", () => void handler(), {once: true});
10
- } else {
11
- handler();
12
- }
13
- },
14
-
15
- $(ref) {
16
- if (typeof ref === "string") { // ref is a selector
17
- return document.body.querySelector(ref);
18
- }
19
- return ref; // ref is already an element
20
- },
21
-
22
- $$(ref) {
23
- if (Array.isArray(ref)) { // ref is an array of elements
24
- return ref;
25
- }
26
- if (ref.nodeType === Node.ELEMENT_NODE) { // ref is an element
27
- return [ref];
28
- }
29
- if (typeof ref === "string") { // ref is a selector
30
- return slice.call(document.body.querySelectorAll(ref));
31
- }
32
- return slice.call(ref); // ref is an array-like object (NodeList or HTMLCollection)
33
- }
34
- };
35
-
36
- export default dom;