@madj2k/fe-frontend-kit 2.0.16 → 2.0.18
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 +29 -27
- package/tools/scrolling/scrolling-2.0.js +108 -38
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,37 +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
|
-
* $('.js-
|
|
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
|
-
*
|
|
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
|
+
*
|
|
51
53
|
* HTML example without data attributes:
|
|
52
54
|
* <div class="js-main-carousel owl-carousel">
|
|
53
55
|
* <div class="item"><img src="image1.jpg" alt=""></div>
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
*
|
|
13
13
|
* @author Steffen Kroggel <developer@steffenkroggel.de>
|
|
14
14
|
* @copyright 2025 Steffen Kroggel
|
|
15
|
-
* @version 2.0.
|
|
15
|
+
* @version 2.0.2
|
|
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,32 +222,43 @@ 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) => {
|
|
174
|
-
event.
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
if
|
|
178
|
-
|
|
235
|
+
const href = event.currentTarget.getAttribute('href');
|
|
236
|
+
if (!href) return;
|
|
237
|
+
|
|
238
|
+
// check if link is to the same page - with or without path
|
|
239
|
+
const [linkPath, hash] = href.split('#');
|
|
240
|
+
const currentUrl = window.location.origin + window.location.pathname;
|
|
241
|
+
const isSamePage = (
|
|
242
|
+
href.startsWith('#') ||
|
|
243
|
+
(window.location.origin + linkPath) === currentUrl
|
|
244
|
+
);
|
|
245
|
+
|
|
246
|
+
if (isSamePage && hash) {
|
|
247
|
+
event.preventDefault();
|
|
248
|
+
const anchor = document.getElementById(hash);
|
|
179
249
|
if (anchor) scrollToElement(anchor);
|
|
180
250
|
}
|
|
181
251
|
};
|
|
182
252
|
|
|
183
253
|
const getAnchorSelector = () => {
|
|
184
|
-
return this.config.
|
|
185
|
-
.map(sel => `${sel}:not(.visually-hidden-focusable):not(${this.config.
|
|
254
|
+
return this.config.anchorScrolling.selector
|
|
255
|
+
.map(sel => `${sel}:not(.visually-hidden-focusable):not(${this.config.anchorScrolling.disableSelector})`)
|
|
186
256
|
.join(', ');
|
|
187
257
|
};
|
|
188
258
|
|
|
189
259
|
const getCollapsibleSelector = () => {
|
|
190
|
-
return this.config.
|
|
191
|
-
.map(sel => `${sel}:not(${this.config.
|
|
260
|
+
return this.config.anchorScrolling.collapsibleSelector
|
|
261
|
+
.map(sel => `${sel}:not(${this.config.anchorScrolling.disableSelector})`)
|
|
192
262
|
.join(', ');
|
|
193
263
|
};
|
|
194
264
|
|
|
@@ -238,7 +308,7 @@ class Madj2kScrolling {
|
|
|
238
308
|
};
|
|
239
309
|
|
|
240
310
|
const getAppearOnScrollSelector = () => {
|
|
241
|
-
return this.config.
|
|
311
|
+
return this.config.appearOnScroll.selector.join(', ');
|
|
242
312
|
};
|
|
243
313
|
|
|
244
314
|
const updateOnScroll = () => {
|