@madj2k/fe-frontend-kit 2.0.14 → 2.0.17
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 +1 -1
- package/readme.md +43 -28
- package/tools/owl-thumbnail/owl-thumbnail-2.0.js +42 -24
- package/tools/scrolling/scrolling-2.0.js +94 -33
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -86,26 +86,33 @@ where content may change dynamically.
|
|
|
86
86
|
|
|
87
87
|
Init with available options:
|
|
88
88
|
```
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
89
|
+
$('.js-slider-container').each(function () {
|
|
90
|
+
const owlThumbnail = new Madj2kOwlThumbnail(
|
|
91
|
+
'.js-main-carousel',
|
|
92
|
+
'.js-thumbs-carousel',
|
|
93
|
+
{
|
|
94
|
+
main: {
|
|
95
|
+
items: 1,
|
|
96
|
+
margin: 20,
|
|
97
|
+
dots: true,
|
|
98
|
+
nav: true,
|
|
99
|
+
autoHeight: true
|
|
100
|
+
},
|
|
101
|
+
thumbs: {
|
|
102
|
+
items: 3,
|
|
103
|
+
margin: 10,
|
|
104
|
+
dots: false,
|
|
105
|
+
nav: true,
|
|
106
|
+
center: true
|
|
107
|
+
},
|
|
108
|
+
resizeEvent: 'custom.resize',
|
|
109
|
+
equalizeThumbHeights: true,
|
|
110
|
+
noStageOffset: true
|
|
111
|
+
},
|
|
112
|
+
false,
|
|
113
|
+
this
|
|
114
|
+
});
|
|
115
|
+
});
|
|
109
116
|
```
|
|
110
117
|
|
|
111
118
|
HTML:
|
|
@@ -160,14 +167,22 @@ Init with available options:
|
|
|
160
167
|
```
|
|
161
168
|
import { Madj2kScrolling } from '@madj2k/frontend-kit/tools/scrolling';
|
|
162
169
|
const scrolling = new Madj2kScrolling({
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
170
|
+
anchorScrolling: {
|
|
171
|
+
selector: ['a[href^="#"]'],
|
|
172
|
+
offsetSelector: null,
|
|
173
|
+
disableSelector: '.js-no-scroll',
|
|
174
|
+
collapsibleSelector: ['.collapse'],
|
|
175
|
+
behavior: 'smooth',
|
|
176
|
+
scriptScrollTimeout: 800,
|
|
177
|
+
timeout: 500,
|
|
178
|
+
threshold: 40
|
|
179
|
+
},
|
|
180
|
+
appearOnScroll: {
|
|
181
|
+
selector: ['.js-appear-on-scroll'],
|
|
182
|
+
timeout: 500,
|
|
183
|
+
threshold: 25
|
|
184
|
+
},
|
|
185
|
+
debug: false
|
|
171
186
|
});
|
|
172
187
|
```
|
|
173
188
|
Usage with Appear-On-Scroll (HTML):
|
|
@@ -17,31 +17,39 @@
|
|
|
17
17
|
*
|
|
18
18
|
* @author Steffen Kroggel <developer@steffenkroggel.de>
|
|
19
19
|
* @copyright 2025 Steffen Kroggel
|
|
20
|
-
* @version
|
|
20
|
+
* @version 2.0.1
|
|
21
21
|
* @license GNU General Public License v3.0
|
|
22
22
|
* @see https://www.gnu.org/licenses/gpl-3.0.en.html
|
|
23
23
|
*
|
|
24
24
|
* @example:
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
25
|
+
* $('.js-slider-container').each(function () {
|
|
26
|
+
* const owlThumbnail = new Madj2kOwlThumbnail(
|
|
27
|
+
* '.js-main-carousel',
|
|
28
|
+
* '.js-thumbs-carousel',
|
|
29
|
+
* {
|
|
30
|
+
* main: {
|
|
31
|
+
* items: 1,
|
|
32
|
+
* margin: 20,
|
|
33
|
+
* dots: true,
|
|
34
|
+
* nav: true,
|
|
35
|
+
* autoHeight: true
|
|
36
|
+
* },
|
|
37
|
+
* thumbs: {
|
|
38
|
+
* items: 3,
|
|
39
|
+
* margin: 10,
|
|
40
|
+
* dots: false,
|
|
41
|
+
* nav: true,
|
|
42
|
+
* center: true
|
|
43
|
+
* },
|
|
44
|
+
* resizeEvent: 'custom.resize',
|
|
45
|
+
* equalizeThumbHeights: true,
|
|
46
|
+
* noStageOffset: true
|
|
47
|
+
* },
|
|
48
|
+
* false,
|
|
49
|
+
* this
|
|
50
|
+
* });
|
|
51
|
+
* });
|
|
52
|
+
*
|
|
45
53
|
* HTML example without data attributes:
|
|
46
54
|
* <div class="js-main-carousel owl-carousel">
|
|
47
55
|
* <div class="item"><img src="image1.jpg" alt=""></div>
|
|
@@ -68,10 +76,20 @@
|
|
|
68
76
|
*
|
|
69
77
|
*/
|
|
70
78
|
class Madj2kOwlThumbnail {
|
|
71
|
-
|
|
79
|
+
/**
|
|
80
|
+
* Creates a new OwlThumbnail instance
|
|
81
|
+
* @param {string} mainSelector - CSS selector for main carousel element
|
|
82
|
+
* @param {string} thumbSelector - CSS selector for thumbnail carousel element
|
|
83
|
+
* @param {Object} options - Configuration options
|
|
84
|
+
* @param {boolean} debug - Enables debug logging
|
|
85
|
+
* @param {Document} container - DOM container to use for event listeners
|
|
86
|
+
*/
|
|
87
|
+
constructor(mainSelector, thumbSelector, options = {}, debug = false, container = document) {
|
|
72
88
|
this.debug = debug;
|
|
73
|
-
|
|
74
|
-
this.$
|
|
89
|
+
|
|
90
|
+
this.$context = $(container);
|
|
91
|
+
this.$main = this.$context.find(mainSelector);
|
|
92
|
+
this.$thumbs = this.$context.find(thumbSelector);
|
|
75
93
|
this.options = options;
|
|
76
94
|
this.syncing = false;
|
|
77
95
|
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
*
|
|
13
13
|
* @author Steffen Kroggel <developer@steffenkroggel.de>
|
|
14
14
|
* @copyright 2025 Steffen Kroggel
|
|
15
|
-
* @version 2.0.1
|
|
15
|
+
* @version 2.0.1
|
|
16
16
|
* @license GNU General Public License v3.0
|
|
17
17
|
* @see https://www.gnu.org/licenses/gpl-3.0.en.html
|
|
18
18
|
*
|
|
@@ -23,14 +23,22 @@
|
|
|
23
23
|
* @example
|
|
24
24
|
* // Initialize with custom config
|
|
25
25
|
* const scrolling = new Madj2kScrolling({
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
26
|
+
* anchorScrolling: {
|
|
27
|
+
* selector: ['a[href^="#"]'],
|
|
28
|
+
* offsetSelector: null,
|
|
29
|
+
* disableSelector: '.js-no-scroll',
|
|
30
|
+
* collapsibleSelector: ['.collapse'],
|
|
31
|
+
* behavior: 'smooth',
|
|
32
|
+
* scriptScrollTimeout: 800,
|
|
33
|
+
* timeout: 500,
|
|
34
|
+
* threshold: 40
|
|
35
|
+
* },
|
|
36
|
+
* appearOnScroll: {
|
|
37
|
+
* selector: ['.js-appear-on-scroll'],
|
|
38
|
+
* timeout: 500,
|
|
39
|
+
* threshold: 25
|
|
40
|
+
* },
|
|
41
|
+
* debug: false
|
|
34
42
|
* });
|
|
35
43
|
*
|
|
36
44
|
* @example
|
|
@@ -64,20 +72,47 @@
|
|
|
64
72
|
|
|
65
73
|
class Madj2kScrolling {
|
|
66
74
|
config = {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
75
|
+
anchorScrolling: {
|
|
76
|
+
selector: ['a[href^="#"]'],
|
|
77
|
+
offsetSelector: null,
|
|
78
|
+
disableSelector: '.js-no-scroll',
|
|
79
|
+
collapsibleSelector: ['.collapse'],
|
|
80
|
+
behavior: 'smooth',
|
|
81
|
+
scriptScrollTimeout: 800,
|
|
82
|
+
timeout: 500,
|
|
83
|
+
threshold: 40
|
|
84
|
+
},
|
|
85
|
+
appearOnScroll: {
|
|
86
|
+
selector: ['.js-appear-on-scroll'],
|
|
87
|
+
timeout: 500,
|
|
88
|
+
threshold: 25
|
|
89
|
+
},
|
|
76
90
|
debug: false
|
|
77
91
|
};
|
|
78
92
|
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
*
|
|
96
|
+
* @param config
|
|
97
|
+
*/
|
|
79
98
|
constructor(config) {
|
|
80
|
-
|
|
99
|
+
|
|
100
|
+
// backwards compatibility
|
|
101
|
+
this._normalizeNestedConfig(config, 'anchorScrolling', 'anchorScrolling');
|
|
102
|
+
this._normalizeNestedConfig(config, 'appearOnScroll', 'appearOnScroll');
|
|
103
|
+
|
|
104
|
+
this.config = {
|
|
105
|
+
...this.config,
|
|
106
|
+
...config,
|
|
107
|
+
anchorScrolling: {
|
|
108
|
+
...this.config.anchorScrolling,
|
|
109
|
+
...config.anchorScrolling
|
|
110
|
+
},
|
|
111
|
+
appearOnScroll: {
|
|
112
|
+
...this.config.appearOnScroll,
|
|
113
|
+
...config.appearOnScroll
|
|
114
|
+
}
|
|
115
|
+
};
|
|
81
116
|
|
|
82
117
|
this.lastScrollTop = window.scrollY;
|
|
83
118
|
this.lastContentHeight = document.documentElement.scrollHeight;
|
|
@@ -89,6 +124,29 @@ class Madj2kScrolling {
|
|
|
89
124
|
this.initAppearOnScroll();
|
|
90
125
|
}
|
|
91
126
|
|
|
127
|
+
/**
|
|
128
|
+
* Converts flat config keys starting with a prefix into nested objects.
|
|
129
|
+
* E.g., "anchorScrollingOffsetSelector" → config.anchorScrolling.offsetSelector
|
|
130
|
+
* @param {Object} config - The config object to normalize
|
|
131
|
+
* @param {String} prefix - The prefix to search for (e.g., "anchorScrolling")
|
|
132
|
+
* @param {String} targetKey - The target key to write into (e.g., "anchorScrolling")
|
|
133
|
+
* @private
|
|
134
|
+
*/
|
|
135
|
+
_normalizeNestedConfig(config, prefix, targetKey) {
|
|
136
|
+
const prefixLength = prefix.length;
|
|
137
|
+
|
|
138
|
+
Object.keys(config).forEach((key) => {
|
|
139
|
+
if (key.startsWith(prefix) && key.length > prefixLength) {
|
|
140
|
+
const subKey = key.substring(prefixLength);
|
|
141
|
+
const camelCaseKey = subKey.charAt(0).toLowerCase() + subKey.slice(1);
|
|
142
|
+
|
|
143
|
+
config[targetKey] ??= {};
|
|
144
|
+
config[targetKey][camelCaseKey] = config[key];
|
|
145
|
+
delete config[key];
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
92
150
|
/**
|
|
93
151
|
* Adds scroll classes to body based on scroll direction
|
|
94
152
|
* @private
|
|
@@ -132,13 +190,14 @@ class Madj2kScrolling {
|
|
|
132
190
|
* @private
|
|
133
191
|
*/
|
|
134
192
|
initAnchorScrolling() {
|
|
135
|
-
|
|
193
|
+
|
|
136
194
|
let scriptScrollTimer = null;
|
|
195
|
+
const offsetElement = document.querySelector(this.config.anchorScrolling.offsetSelector);
|
|
137
196
|
|
|
138
197
|
const scrollToElement = (element) => {
|
|
139
198
|
if (element) {
|
|
140
199
|
const rect = element.getBoundingClientRect();
|
|
141
|
-
let scrollTo = window.scrollY + rect.top -
|
|
200
|
+
let scrollTo = window.scrollY + rect.top - this.config.anchorScrolling.threshold;
|
|
142
201
|
|
|
143
202
|
if (offsetElement && offsetElement.offsetTop >= 0 && !offsetElement.hidden) {
|
|
144
203
|
scrollTo -= offsetElement.offsetHeight;
|
|
@@ -151,11 +210,11 @@ class Madj2kScrolling {
|
|
|
151
210
|
|
|
152
211
|
scriptScrollTimer = setTimeout(() => {
|
|
153
212
|
document.body.classList.remove('block-scroll-classes');
|
|
154
|
-
}, this.config.
|
|
213
|
+
}, this.config.anchorScrolling.scriptScrollTimeout);
|
|
155
214
|
|
|
156
215
|
window.scrollTo({
|
|
157
216
|
top: scrollTo,
|
|
158
|
-
behavior: this.config.
|
|
217
|
+
behavior: this.config.anchorScrolling.behavior
|
|
159
218
|
});
|
|
160
219
|
|
|
161
220
|
this._log('Anchor scroll to:', element);
|
|
@@ -163,11 +222,13 @@ class Madj2kScrolling {
|
|
|
163
222
|
};
|
|
164
223
|
|
|
165
224
|
const jumpToAnchorByUrl = () => {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
225
|
+
setTimeout(() => {
|
|
226
|
+
const anchorName = window.location.hash.replace('#', '');
|
|
227
|
+
if (anchorName) {
|
|
228
|
+
const anchor = document.querySelector(`a[id="${anchorName}"], #${anchorName}`);
|
|
229
|
+
if (anchor) scrollToElement(anchor);
|
|
230
|
+
}
|
|
231
|
+
}, this.config.anchorScrolling.timeout);
|
|
171
232
|
};
|
|
172
233
|
|
|
173
234
|
const jumpToAnchorByLink = (event) => {
|
|
@@ -181,14 +242,14 @@ class Madj2kScrolling {
|
|
|
181
242
|
};
|
|
182
243
|
|
|
183
244
|
const getAnchorSelector = () => {
|
|
184
|
-
return this.config.
|
|
185
|
-
.map(sel => `${sel}:not(.visually-hidden-focusable):not(${this.config.
|
|
245
|
+
return this.config.anchorScrolling.selector
|
|
246
|
+
.map(sel => `${sel}:not(.visually-hidden-focusable):not(${this.config.anchorScrolling.disableSelector})`)
|
|
186
247
|
.join(', ');
|
|
187
248
|
};
|
|
188
249
|
|
|
189
250
|
const getCollapsibleSelector = () => {
|
|
190
|
-
return this.config.
|
|
191
|
-
.map(sel => `${sel}:not(${this.config.
|
|
251
|
+
return this.config.anchorScrolling.collapsibleSelector
|
|
252
|
+
.map(sel => `${sel}:not(${this.config.anchorScrolling.disableSelector})`)
|
|
192
253
|
.join(', ');
|
|
193
254
|
};
|
|
194
255
|
|
|
@@ -238,7 +299,7 @@ class Madj2kScrolling {
|
|
|
238
299
|
};
|
|
239
300
|
|
|
240
301
|
const getAppearOnScrollSelector = () => {
|
|
241
|
-
return this.config.
|
|
302
|
+
return this.config.appearOnScroll.selector.join(', ');
|
|
242
303
|
};
|
|
243
304
|
|
|
244
305
|
const updateOnScroll = () => {
|