@pernod-ricard-global-cms/jsutils 1.6.4 → 1.6.5
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/.prettierrc +19 -0
- package/jsutils.js +192 -184
- package/package.json +2 -1
package/.prettierrc
ADDED
package/jsutils.js
CHANGED
|
@@ -2,47 +2,50 @@
|
|
|
2
2
|
/* eslint-disable no-console */
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* This function accepts an html element and returns the position of that element on the page.
|
|
6
|
-
*
|
|
5
|
+
* This function accepts an html element and returns the position of that element on the page.
|
|
6
|
+
*
|
|
7
7
|
* @param {htmlElement} element The element whose position you want to get.
|
|
8
8
|
* @returns {object} An object with the x and y pixel values.
|
|
9
9
|
*/
|
|
10
|
-
export function getPosition(
|
|
10
|
+
export function getPosition(element) {
|
|
11
11
|
const scrollElementTag = document.scrollingElement.tagName;
|
|
12
12
|
let xPosition = 0;
|
|
13
13
|
let yPosition = 0;
|
|
14
|
-
while (
|
|
15
|
-
xPosition +=
|
|
16
|
-
element.offsetLeft - element.scrollLeft + element.clientLeft;
|
|
14
|
+
while (element) {
|
|
15
|
+
xPosition += element.offsetLeft - element.scrollLeft + element.clientLeft;
|
|
17
16
|
yPosition += element.offsetTop - element.scrollTop + element.clientTop;
|
|
18
17
|
element = element.offsetParent;
|
|
19
18
|
}
|
|
20
19
|
// Quirks mode safety - in case of missing DOCTYPE
|
|
21
|
-
if (
|
|
22
|
-
yPosition += document.querySelector(
|
|
20
|
+
if (scrollElementTag === 'BODY') {
|
|
21
|
+
yPosition += document.querySelector('body').scrollTop;
|
|
23
22
|
}
|
|
24
23
|
return { x: xPosition, y: yPosition };
|
|
25
24
|
}
|
|
26
25
|
|
|
27
26
|
/**
|
|
28
|
-
* Adds or removes a 'valid' class to an input and button element depending on whether the value of the input is valid.
|
|
27
|
+
* Adds or removes a 'valid' class to an input and button element depending on whether the value of the input is valid.
|
|
29
28
|
* @param {htmlElement} input The input element to check.
|
|
30
|
-
* @param {htmlElement} button A corresponding button to disable if invalid.
|
|
29
|
+
* @param {htmlElement} button A corresponding button to disable if invalid.
|
|
31
30
|
*/
|
|
32
|
-
export function toggleClassByValidity(
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
if (
|
|
36
|
-
button.classList.
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
input.classList.
|
|
31
|
+
export function toggleClassByValidity(input, button) {
|
|
32
|
+
try {
|
|
33
|
+
input.addEventListener('input', () => {
|
|
34
|
+
if (input.validity.valid && input.value) {
|
|
35
|
+
if (!button.classList.contains('valid')) {
|
|
36
|
+
button.classList.add('valid');
|
|
37
|
+
}
|
|
38
|
+
if (!input.classList.contains('valid')) {
|
|
39
|
+
input.classList.add('valid');
|
|
40
|
+
}
|
|
41
|
+
} else {
|
|
42
|
+
button.classList.remove('valid');
|
|
43
|
+
input.classList.remove('valid');
|
|
40
44
|
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
} );
|
|
45
|
+
});
|
|
46
|
+
} catch (error) {
|
|
47
|
+
console.error('jsutils.js ~ toggleClassByValidity ~ error', error);
|
|
48
|
+
}
|
|
46
49
|
}
|
|
47
50
|
|
|
48
51
|
/**
|
|
@@ -51,13 +54,13 @@ export function toggleClassByValidity( input, button ) {
|
|
|
51
54
|
* @param {string} assetKey The assetkey string of the block.
|
|
52
55
|
* @returns {boolean}
|
|
53
56
|
*/
|
|
54
|
-
export function inCriticalCssConfig(
|
|
55
|
-
if(!globalThis.criticalConfig) {
|
|
57
|
+
export function inCriticalCssConfig(assetKey) {
|
|
58
|
+
if (!globalThis.criticalConfig) {
|
|
56
59
|
return false;
|
|
57
60
|
}
|
|
58
61
|
if (
|
|
59
62
|
globalThis.criticalConfig &&
|
|
60
|
-
globalThis.criticalConfig.indexOf(
|
|
63
|
+
globalThis.criticalConfig.indexOf(assetKey) === -1
|
|
61
64
|
) {
|
|
62
65
|
return false;
|
|
63
66
|
}
|
|
@@ -70,16 +73,16 @@ export function inCriticalCssConfig( assetKey ) {
|
|
|
70
73
|
* @param {object} options The options object which will at the very least contain the css property set to true.
|
|
71
74
|
* @returns {promise}
|
|
72
75
|
*/
|
|
73
|
-
export function loadCss(
|
|
74
|
-
const promise = new Promise(
|
|
75
|
-
if (
|
|
76
|
+
export function loadCss(assetKey, options = { css: true }) {
|
|
77
|
+
const promise = new Promise((resolve) => {
|
|
78
|
+
if (options.css === true && !inCriticalCssConfig(assetKey)) {
|
|
76
79
|
import(
|
|
77
|
-
/* webpackChunkName: "[request]" */ `Assets/scss/components/blocks/${
|
|
78
|
-
).then(
|
|
80
|
+
/* webpackChunkName: "[request]" */ `Assets/scss/components/blocks/${assetKey}.scss`
|
|
81
|
+
).then(() => resolve(true));
|
|
79
82
|
} else {
|
|
80
|
-
return resolve(
|
|
83
|
+
return resolve(true);
|
|
81
84
|
}
|
|
82
|
-
}
|
|
85
|
+
});
|
|
83
86
|
return promise;
|
|
84
87
|
}
|
|
85
88
|
|
|
@@ -89,104 +92,106 @@ export function loadCss( assetKey, options = { css: true } ) {
|
|
|
89
92
|
export function checkDevice() {
|
|
90
93
|
try {
|
|
91
94
|
const deviceAgent = navigator.userAgent.toLowerCase();
|
|
92
|
-
const htmlElement = document.querySelector(
|
|
93
|
-
if (
|
|
94
|
-
|
|
95
|
+
const htmlElement = document.querySelector('html');
|
|
96
|
+
if (
|
|
97
|
+
'ontouchstart' in globalThis &&
|
|
98
|
+
window.screen.width * window.devicePixelRatio >= 2048 &&
|
|
99
|
+
window.screen.width < window.screen.height
|
|
100
|
+
) {
|
|
101
|
+
htmlElement.classList.add('highResTabletPortrait');
|
|
95
102
|
}
|
|
96
|
-
if (
|
|
97
|
-
htmlElement.classList.add(
|
|
103
|
+
if ('ontouchstart' in globalThis) {
|
|
104
|
+
htmlElement.classList.add('touch');
|
|
98
105
|
}
|
|
99
|
-
if (
|
|
100
|
-
htmlElement.classList.add(
|
|
106
|
+
if (navigator.connection) {
|
|
107
|
+
htmlElement.classList.add(navigator.connection.effectiveType);
|
|
101
108
|
}
|
|
102
|
-
if (
|
|
109
|
+
if (navigator.platform) {
|
|
103
110
|
let platform = navigator.platform.toLowerCase();
|
|
104
111
|
let platformArray = [platform];
|
|
105
|
-
if (
|
|
112
|
+
if (platform.search('-')) {
|
|
106
113
|
platformArray = platform.split('-');
|
|
107
114
|
}
|
|
108
|
-
if (
|
|
115
|
+
if (platform.search(' ')) {
|
|
109
116
|
platformArray = platform.split(' ');
|
|
110
117
|
}
|
|
111
|
-
htmlElement.classList.add(
|
|
118
|
+
htmlElement.classList.add(...platformArray);
|
|
112
119
|
}
|
|
113
|
-
if (
|
|
114
|
-
htmlElement.classList.add(
|
|
115
|
-
htmlElement.classList.add(
|
|
120
|
+
if (deviceAgent.match(/(iphone|ipod|ipad)/)) {
|
|
121
|
+
htmlElement.classList.add('ios');
|
|
122
|
+
htmlElement.classList.add('mobile');
|
|
116
123
|
}
|
|
117
|
-
if (deviceAgent.match(
|
|
118
|
-
|
|
124
|
+
if (deviceAgent.match(/(windows)/)) {
|
|
125
|
+
htmlElement.classList.add('windows');
|
|
119
126
|
}
|
|
120
|
-
if (deviceAgent.match(
|
|
121
|
-
|
|
127
|
+
if (deviceAgent.match(/(macintosh)/)) {
|
|
128
|
+
htmlElement.classList.add('mac');
|
|
122
129
|
}
|
|
123
|
-
if (deviceAgent.match(
|
|
124
|
-
|
|
130
|
+
if (deviceAgent.match(/(android)/)) {
|
|
131
|
+
htmlElement.classList.add('android');
|
|
125
132
|
}
|
|
126
|
-
if (
|
|
127
|
-
htmlElement.classList.add(
|
|
128
|
-
} else if (
|
|
129
|
-
htmlElement.classList.add(
|
|
130
|
-
} else if (
|
|
131
|
-
htmlElement.classList.add(
|
|
132
|
-
} else if (
|
|
133
|
-
htmlElement.classList.add(
|
|
133
|
+
if (navigator.userAgent.search('MSIE') >= 0) {
|
|
134
|
+
htmlElement.classList.add('ie');
|
|
135
|
+
} else if (navigator.userAgent.search('Edge') >= 0) {
|
|
136
|
+
htmlElement.classList.add('edge-legacy');
|
|
137
|
+
} else if (navigator.userAgent.search('Chrome') >= 0) {
|
|
138
|
+
htmlElement.classList.add('chrome');
|
|
139
|
+
} else if (navigator.userAgent.search('Firefox') >= 0) {
|
|
140
|
+
htmlElement.classList.add('firefox');
|
|
134
141
|
} else if (
|
|
135
|
-
navigator.userAgent.search(
|
|
136
|
-
navigator.userAgent.search(
|
|
142
|
+
navigator.userAgent.search('Safari') >= 0 &&
|
|
143
|
+
navigator.userAgent.search('Chrome') < 0
|
|
137
144
|
) {
|
|
138
|
-
htmlElement.classList.add(
|
|
139
|
-
} else if (
|
|
140
|
-
htmlElement.classList.add(
|
|
145
|
+
htmlElement.classList.add('safari');
|
|
146
|
+
} else if (navigator.userAgent.search('Opera') >= 0) {
|
|
147
|
+
htmlElement.classList.add('opera');
|
|
141
148
|
}
|
|
142
149
|
} catch (error) {
|
|
143
|
-
console.error(error)
|
|
150
|
+
console.error(error);
|
|
144
151
|
}
|
|
145
152
|
}
|
|
146
153
|
|
|
147
154
|
/**
|
|
148
|
-
* Check and possibly wait for an image to have downloaded before running an optional function.
|
|
155
|
+
* Check and possibly wait for an image to have downloaded before running an optional function.
|
|
149
156
|
* Returns a resolved promise when the load event has fired.
|
|
150
157
|
* @param {htmlElement} img The image element you want to wait for.
|
|
151
|
-
* @param {function} delayedFunction The optional function you want to run when/if the image has downloaded.
|
|
158
|
+
* @param {function} delayedFunction The optional function you want to run when/if the image has downloaded.
|
|
152
159
|
* @returns {promise}
|
|
153
160
|
*/
|
|
154
|
-
export async function waitForLoad(
|
|
155
|
-
const loaded = new Promise(
|
|
156
|
-
if (
|
|
157
|
-
if (
|
|
161
|
+
export async function waitForLoad(img, delayedFunction) {
|
|
162
|
+
const loaded = new Promise((resolve) => {
|
|
163
|
+
if (img.complete) {
|
|
164
|
+
if (typeof delayedFunction === 'function') {
|
|
158
165
|
delayedFunction();
|
|
159
166
|
}
|
|
160
|
-
return resolve(
|
|
167
|
+
return resolve(true);
|
|
161
168
|
}
|
|
162
169
|
img.addEventListener(
|
|
163
170
|
'load',
|
|
164
171
|
() => {
|
|
165
|
-
if (
|
|
172
|
+
if (typeof delayedFunction === 'function') {
|
|
166
173
|
delayedFunction();
|
|
167
174
|
}
|
|
168
|
-
return resolve(
|
|
175
|
+
return resolve(true);
|
|
169
176
|
},
|
|
170
177
|
{ once: true }
|
|
171
178
|
);
|
|
172
|
-
}
|
|
173
|
-
console.log( error, 'could not load the image', img )
|
|
174
|
-
);
|
|
179
|
+
}).catch((error) => console.log(error, 'could not load the image', img));
|
|
175
180
|
return loaded;
|
|
176
181
|
}
|
|
177
182
|
|
|
178
183
|
/**
|
|
179
|
-
* Check whether the current environment supports the webp image format.
|
|
180
|
-
* Returns true if it does.
|
|
184
|
+
* Check whether the current environment supports the webp image format.
|
|
185
|
+
* Returns true if it does.
|
|
181
186
|
* @returns {boolean}
|
|
182
187
|
*/
|
|
183
188
|
export async function supportsWebp() {
|
|
184
189
|
// eslint-disable-next-line no-restricted-globals
|
|
185
|
-
if (
|
|
190
|
+
if (!self.createImageBitmap) return false;
|
|
186
191
|
const webpData =
|
|
187
192
|
'data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAAAAAAfQ//73v/+BiOh/AAA=';
|
|
188
|
-
const blob = await fetch(
|
|
189
|
-
return createImageBitmap(
|
|
193
|
+
const blob = await fetch(webpData).then((r) => r.blob());
|
|
194
|
+
return createImageBitmap(blob).then(
|
|
190
195
|
() => true,
|
|
191
196
|
() => false
|
|
192
197
|
);
|
|
@@ -199,30 +204,28 @@ export async function supportsWebp() {
|
|
|
199
204
|
// } )();
|
|
200
205
|
|
|
201
206
|
/**
|
|
202
|
-
* DEPRECATED!! footerIntersection will be removed in a future version.
|
|
207
|
+
* DEPRECATED!! footerIntersection will be removed in a future version.
|
|
203
208
|
*/
|
|
204
|
-
export function footerIntersection(
|
|
205
|
-
entries.forEach(
|
|
206
|
-
if (
|
|
207
|
-
if (
|
|
209
|
+
export function footerIntersection(entries, element) {
|
|
210
|
+
entries.forEach((entry) => {
|
|
211
|
+
if (element) {
|
|
212
|
+
if (entry.isIntersecting) {
|
|
208
213
|
const { height } = entry.boundingClientRect;
|
|
209
|
-
element.style.bottom = `${
|
|
214
|
+
element.style.bottom = `${height}px`;
|
|
210
215
|
} else {
|
|
211
216
|
element.style.bottom = '0px';
|
|
212
217
|
}
|
|
213
218
|
}
|
|
214
|
-
}
|
|
219
|
+
});
|
|
215
220
|
}
|
|
216
221
|
|
|
217
222
|
/**
|
|
218
|
-
* Dynamically retrieves the swiper css and js and returns a resolved promise when they have both been successfully fetched.
|
|
223
|
+
* Dynamically retrieves the swiper css and js and returns a resolved promise when they have both been successfully fetched.
|
|
219
224
|
* @returns {promise}
|
|
220
225
|
*/
|
|
221
226
|
export function getSwiperAssets() {
|
|
222
227
|
const getSwiperJs = () =>
|
|
223
|
-
import(
|
|
224
|
-
/* webpackChunkName: 'swiper' */ '../../swiper/swiper-bundle.js'
|
|
225
|
-
);
|
|
228
|
+
import(/* webpackChunkName: 'swiper' */ '../../swiper/swiper-bundle.js');
|
|
226
229
|
|
|
227
230
|
const getSwiperCss = () =>
|
|
228
231
|
import(
|
|
@@ -230,8 +233,8 @@ export function getSwiperAssets() {
|
|
|
230
233
|
'../../swiper/swiper-bundle.min.css'
|
|
231
234
|
);
|
|
232
235
|
|
|
233
|
-
const promisedJs = Promise.all(
|
|
234
|
-
(
|
|
236
|
+
const promisedJs = Promise.all([getSwiperJs(), getSwiperCss()]).then(
|
|
237
|
+
(values) => {
|
|
235
238
|
return values;
|
|
236
239
|
}
|
|
237
240
|
);
|
|
@@ -239,11 +242,11 @@ export function getSwiperAssets() {
|
|
|
239
242
|
}
|
|
240
243
|
|
|
241
244
|
/**
|
|
242
|
-
* Dynamically retrieves the jQuery and returns a resolved promise when it has been successfully fetched.
|
|
245
|
+
* Dynamically retrieves the jQuery and returns a resolved promise when it has been successfully fetched.
|
|
243
246
|
* @returns {promise}
|
|
244
247
|
*/
|
|
245
248
|
export function getJquery() {
|
|
246
|
-
if (
|
|
249
|
+
if (!window.jQuery) {
|
|
247
250
|
const importCode = () =>
|
|
248
251
|
import(
|
|
249
252
|
/* webpackChunkName: 'jquery' */ '../../jquery/dist/jquery.min.js'
|
|
@@ -254,29 +257,25 @@ export function getJquery() {
|
|
|
254
257
|
}
|
|
255
258
|
|
|
256
259
|
/**
|
|
257
|
-
* Dynamically retrieves GSAP and the scrolltrigger plugin and returns a resolved promise when they have both been successfully fetched.
|
|
260
|
+
* Dynamically retrieves GSAP and the scrolltrigger plugin and returns a resolved promise when they have both been successfully fetched.
|
|
258
261
|
* @returns {promise}
|
|
259
262
|
*/
|
|
260
263
|
export function getGsap() {
|
|
261
264
|
const gsapCore = () =>
|
|
262
|
-
import(
|
|
265
|
+
import('../../gsap/dist/gsap.min.js').then((gsapObj) => {
|
|
263
266
|
const { gsap } = gsapObj;
|
|
264
267
|
return gsap;
|
|
265
|
-
}
|
|
268
|
+
});
|
|
266
269
|
|
|
267
270
|
const gsapPlugin = () =>
|
|
268
|
-
import(
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
( values ) => {
|
|
277
|
-
return values;
|
|
278
|
-
}
|
|
279
|
-
);
|
|
271
|
+
import('../../gsap/dist/ScrollTrigger.min.js').then((scrollObj) => {
|
|
272
|
+
const ScrollTrigger = scrollObj;
|
|
273
|
+
return ScrollTrigger;
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
const prom = Promise.all([gsapCore(), gsapPlugin()]).then((values) => {
|
|
277
|
+
return values;
|
|
278
|
+
});
|
|
280
279
|
return prom;
|
|
281
280
|
}
|
|
282
281
|
|
|
@@ -285,7 +284,7 @@ export function getGsap() {
|
|
|
285
284
|
* @param {*} userAgent Pass the value of navigator.userAgent.
|
|
286
285
|
* @returns {boolean}
|
|
287
286
|
*/
|
|
288
|
-
export function isTablet(
|
|
287
|
+
export function isTablet(userAgent) {
|
|
289
288
|
return /(ipad|tablet|(android(?!.*mobile))|(windows(?!.*phone)(.*touch))|kindle|playbook|silk|(puffin(?!.*(IP|AP|WP))))/.test(
|
|
290
289
|
userAgent.toLowerCase()
|
|
291
290
|
);
|
|
@@ -293,35 +292,45 @@ export function isTablet( userAgent ) {
|
|
|
293
292
|
|
|
294
293
|
/**
|
|
295
294
|
* Returns true if the device is a mobile device. Checks navigator.userAgent||navigator.vendor||window.opera.
|
|
296
|
-
* @returns {boolean}
|
|
295
|
+
* @returns {boolean}
|
|
297
296
|
*/
|
|
298
|
-
export function mobileCheck
|
|
297
|
+
export function mobileCheck() {
|
|
299
298
|
let check = false;
|
|
300
|
-
(function
|
|
299
|
+
(function (a) {
|
|
300
|
+
if (
|
|
301
|
+
/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(
|
|
302
|
+
a
|
|
303
|
+
) ||
|
|
304
|
+
/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(
|
|
305
|
+
a.substr(0, 4)
|
|
306
|
+
)
|
|
307
|
+
)
|
|
308
|
+
check = true;
|
|
309
|
+
})(navigator.userAgent || navigator.vendor || window.opera);
|
|
301
310
|
return check;
|
|
302
|
-
|
|
311
|
+
}
|
|
303
312
|
|
|
304
313
|
/**
|
|
305
|
-
* Run a function after a window resize event, but only after the alloted time has ended.
|
|
314
|
+
* Run a function after a window resize event, but only after the alloted time has ended.
|
|
306
315
|
* If another resize even occurs it resets the time window.
|
|
307
316
|
* @param {function} debouncedFunction The function you want to run after a window resize event.
|
|
308
317
|
* @param {number} time The time in ms.
|
|
309
|
-
*/
|
|
310
|
-
export function resizeDebouncer(
|
|
318
|
+
*/
|
|
319
|
+
export function resizeDebouncer(debouncedFunction, time = 250) {
|
|
311
320
|
let resizeTimer;
|
|
312
|
-
window.addEventListener(
|
|
313
|
-
clearTimeout(
|
|
314
|
-
resizeTimer = setTimeout(
|
|
321
|
+
window.addEventListener('resize', () => {
|
|
322
|
+
clearTimeout(resizeTimer);
|
|
323
|
+
resizeTimer = setTimeout(() => {
|
|
315
324
|
debouncedFunction();
|
|
316
|
-
}, time
|
|
317
|
-
}
|
|
325
|
+
}, time);
|
|
326
|
+
});
|
|
318
327
|
}
|
|
319
328
|
|
|
320
329
|
/**
|
|
321
|
-
* General purpose utility for running a function after a particular event fires on a specified element. The function only fires after the alloted time has ended.
|
|
330
|
+
* General purpose utility for running a function after a particular event fires on a specified element. The function only fires after the alloted time has ended.
|
|
322
331
|
* If another resize even occurs it resets the time window.
|
|
323
332
|
* @param {htmlElement} element The element that emits the event.
|
|
324
|
-
* @param {string} eventType The type of event to listen for.
|
|
333
|
+
* @param {string} eventType The type of event to listen for.
|
|
325
334
|
* @param {function} debouncedFunction The function to run after the event.
|
|
326
335
|
* @param {number} time The time in ms.
|
|
327
336
|
*/
|
|
@@ -332,49 +341,49 @@ export function eventListenerDebouncer(
|
|
|
332
341
|
time = 250
|
|
333
342
|
) {
|
|
334
343
|
let timer;
|
|
335
|
-
element.addEventListener(
|
|
336
|
-
clearTimeout(
|
|
337
|
-
timer = setTimeout(
|
|
338
|
-
debouncedFunction(
|
|
339
|
-
}, time
|
|
340
|
-
}
|
|
344
|
+
element.addEventListener(eventType, (event) => {
|
|
345
|
+
clearTimeout(timer);
|
|
346
|
+
timer = setTimeout(() => {
|
|
347
|
+
debouncedFunction(event);
|
|
348
|
+
}, time);
|
|
349
|
+
});
|
|
341
350
|
}
|
|
342
351
|
|
|
343
352
|
/**
|
|
344
353
|
* Injects the youtube iframe api script and waits for the YT object to be instantiated before resolving the promise
|
|
345
|
-
* @returns {promise} Resolves once the YT object is available.
|
|
354
|
+
* @returns {promise} Resolves once the YT object is available.
|
|
346
355
|
*/
|
|
347
356
|
export function injectYouTubeIframeScript() {
|
|
348
|
-
const prom = new Promise(
|
|
349
|
-
if (
|
|
357
|
+
const prom = new Promise((resolve) => {
|
|
358
|
+
if (globalThis.YT) {
|
|
350
359
|
return resolve();
|
|
351
360
|
}
|
|
352
|
-
const tag = document.createElement(
|
|
361
|
+
const tag = document.createElement('script');
|
|
353
362
|
tag.id = 'iframe-api';
|
|
354
363
|
tag.src = 'https://www.youtube.com/iframe_api';
|
|
355
364
|
|
|
356
|
-
const firstScriptTag = document.getElementsByTagName(
|
|
357
|
-
firstScriptTag.parentNode.insertBefore(
|
|
365
|
+
const firstScriptTag = document.getElementsByTagName('script')[0];
|
|
366
|
+
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
|
|
358
367
|
|
|
359
|
-
tag.addEventListener(
|
|
368
|
+
tag.addEventListener('load', () => {
|
|
360
369
|
if (!YT.loaded) {
|
|
361
370
|
const loadingCheck = setInterval(() => {
|
|
362
371
|
if (YT.loaded) {
|
|
363
372
|
clearInterval(loadingCheck);
|
|
364
|
-
return resolve(
|
|
373
|
+
return resolve(true);
|
|
365
374
|
}
|
|
366
375
|
}, 50);
|
|
367
376
|
} else {
|
|
368
|
-
return resolve(
|
|
377
|
+
return resolve(true);
|
|
369
378
|
}
|
|
370
|
-
}
|
|
371
|
-
}
|
|
379
|
+
});
|
|
380
|
+
});
|
|
372
381
|
|
|
373
382
|
return prom;
|
|
374
383
|
}
|
|
375
384
|
|
|
376
|
-
export function fallbackCopyToClipboard(
|
|
377
|
-
const textArea = document.createElement(
|
|
385
|
+
export function fallbackCopyToClipboard(text) {
|
|
386
|
+
const textArea = document.createElement('textarea');
|
|
378
387
|
textArea.value = text;
|
|
379
388
|
|
|
380
389
|
// Avoid scrolling to bottom
|
|
@@ -382,58 +391,55 @@ export function fallbackCopyToClipboard( text ) {
|
|
|
382
391
|
textArea.style.left = '0';
|
|
383
392
|
textArea.style.position = 'fixed';
|
|
384
393
|
|
|
385
|
-
document.body.appendChild(
|
|
394
|
+
document.body.appendChild(textArea);
|
|
386
395
|
textArea.focus();
|
|
387
396
|
textArea.select();
|
|
388
397
|
|
|
389
398
|
try {
|
|
390
|
-
const successful = document.execCommand(
|
|
399
|
+
const successful = document.execCommand('copy');
|
|
391
400
|
const msg = successful ? 'successful' : 'unsuccessful';
|
|
392
|
-
console.log(
|
|
393
|
-
} catch (
|
|
394
|
-
console.error(
|
|
401
|
+
console.log(`Fallback: Copying text command was ${msg}`);
|
|
402
|
+
} catch (err) {
|
|
403
|
+
console.error('Fallback: Oops, unable to copy', err);
|
|
395
404
|
}
|
|
396
405
|
|
|
397
|
-
document.body.removeChild(
|
|
406
|
+
document.body.removeChild(textArea);
|
|
398
407
|
}
|
|
399
408
|
|
|
400
|
-
|
|
401
409
|
export function copyToClipboard() {
|
|
402
|
-
const copyLinks = document.querySelectorAll(
|
|
410
|
+
const copyLinks = document.querySelectorAll('.copy-to-clipboard');
|
|
403
411
|
let timeout;
|
|
404
|
-
copyLinks.forEach(
|
|
405
|
-
link.addEventListener(
|
|
412
|
+
copyLinks.forEach((link) => {
|
|
413
|
+
link.addEventListener('click', function () {
|
|
406
414
|
const copyToClipboardDone = link.nextElementSibling;
|
|
407
|
-
if (
|
|
408
|
-
fallbackCopyToClipboard(
|
|
415
|
+
if (!navigator.clipboard) {
|
|
416
|
+
fallbackCopyToClipboard(this.dataset.url);
|
|
409
417
|
return;
|
|
410
418
|
}
|
|
411
419
|
|
|
412
|
-
navigator.clipboard.writeText(
|
|
420
|
+
navigator.clipboard.writeText(this.dataset.url).then(
|
|
413
421
|
function () {
|
|
414
|
-
console.log(
|
|
422
|
+
console.log('Copying to clipboard was successful!');
|
|
415
423
|
},
|
|
416
|
-
function (
|
|
417
|
-
console.error(
|
|
424
|
+
function (err) {
|
|
425
|
+
console.error('Could not copy text: ', err);
|
|
418
426
|
}
|
|
419
427
|
);
|
|
420
428
|
|
|
421
429
|
if (
|
|
422
430
|
copyToClipboardDone &&
|
|
423
431
|
copyToClipboardDone.classList &&
|
|
424
|
-
copyToClipboardDone.classList.contains(
|
|
425
|
-
'sharing__clipboard-done'
|
|
426
|
-
)
|
|
432
|
+
copyToClipboardDone.classList.contains('sharing__clipboard-done')
|
|
427
433
|
) {
|
|
428
|
-
clearTimeout(
|
|
429
|
-
copyToClipboardDone.classList.remove(
|
|
434
|
+
clearTimeout(timeout);
|
|
435
|
+
copyToClipboardDone.classList.remove('hidden');
|
|
430
436
|
|
|
431
|
-
timeout = setTimeout(
|
|
432
|
-
copyToClipboardDone.classList.add(
|
|
433
|
-
}, 2000
|
|
437
|
+
timeout = setTimeout(() => {
|
|
438
|
+
copyToClipboardDone.classList.add('hidden');
|
|
439
|
+
}, 2000);
|
|
434
440
|
}
|
|
435
|
-
}
|
|
436
|
-
}
|
|
441
|
+
});
|
|
442
|
+
});
|
|
437
443
|
}
|
|
438
444
|
|
|
439
445
|
/**
|
|
@@ -442,21 +448,25 @@ export function copyToClipboard() {
|
|
|
442
448
|
* @returns {boolean} True if visible and false if not.
|
|
443
449
|
*/
|
|
444
450
|
export function isInViewport(element) {
|
|
445
|
-
|
|
446
|
-
|
|
451
|
+
const position = element.getBoundingClientRect();
|
|
452
|
+
return (
|
|
453
|
+
(position.top >= 0 && position.bottom <= window.innerHeight) ||
|
|
454
|
+
(position.top < window.innerHeight && position.bottom >= 0)
|
|
455
|
+
);
|
|
447
456
|
}
|
|
448
457
|
|
|
449
458
|
/* eslint-disable-next-line */
|
|
450
|
-
const emailRegex =
|
|
459
|
+
const emailRegex =
|
|
460
|
+
/^[-!#$%&'*+\/0-9=?A-Z^_a-z`{|}~](\.?[-!#$%&'*+\/0-9=?A-Z^_a-z`{|}~])*@[a-zA-Z0-9](-*\.?[a-zA-Z0-9])*\.[a-zA-Z](-?[a-zA-Z0-9])+$/;
|
|
451
461
|
|
|
452
462
|
/**
|
|
453
463
|
* Checks to make sure a passed string has a valid email address structure and characters.
|
|
454
464
|
* @param {RegExp} email - The email address as a string.
|
|
455
465
|
* @returns {boolean} True if valid and false if not.
|
|
456
466
|
*/
|
|
457
|
-
export function isEmailValid(
|
|
458
|
-
return emailRegex.test(
|
|
459
|
-
}
|
|
467
|
+
export function isEmailValid(email) {
|
|
468
|
+
return emailRegex.test(email);
|
|
469
|
+
}
|
|
460
470
|
|
|
461
471
|
/**
|
|
462
472
|
* Get the value of a css property on a specific element.
|
|
@@ -526,9 +536,7 @@ export function detectSwipe(element, callback, removeHandlers = false) {
|
|
|
526
536
|
function (event) {
|
|
527
537
|
touchendX = event.changedTouches[0].screenX;
|
|
528
538
|
touchendY = event.changedTouches[0].screenY;
|
|
529
|
-
callback(
|
|
530
|
-
handleGesture(touchstartX, touchstartY, touchendX, touchendY)
|
|
531
|
-
);
|
|
539
|
+
callback(handleGesture(touchstartX, touchstartY, touchendX, touchendY));
|
|
532
540
|
},
|
|
533
541
|
false
|
|
534
542
|
);
|
|
@@ -541,7 +549,7 @@ export function detectSwipe(element, callback, removeHandlers = false) {
|
|
|
541
549
|
|
|
542
550
|
/**
|
|
543
551
|
* Function for getting the ios operating system version
|
|
544
|
-
*
|
|
552
|
+
*
|
|
545
553
|
* @returns {number} the ios version
|
|
546
554
|
*/
|
|
547
555
|
export function checkIosVersion() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pernod-ricard-global-cms/jsutils",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.5",
|
|
4
4
|
"description": "Handy collection of Javascript utility functions",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "jsutils.js",
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"gsap": "^3.7.1",
|
|
22
22
|
"jquery": "^3.6.0",
|
|
23
|
+
"prettier": "^2.5.1",
|
|
23
24
|
"swiper": "^6.8.3"
|
|
24
25
|
},
|
|
25
26
|
"devDependencies": {
|