@pernod-ricard-global-cms/jsutils 1.5.3 → 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 +212 -183
- 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,10 +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(
|
|
57
|
+
export function inCriticalCssConfig(assetKey) {
|
|
58
|
+
if (!globalThis.criticalConfig) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
55
61
|
if (
|
|
56
62
|
globalThis.criticalConfig &&
|
|
57
|
-
globalThis.criticalConfig.indexOf(
|
|
63
|
+
globalThis.criticalConfig.indexOf(assetKey) === -1
|
|
58
64
|
) {
|
|
59
65
|
return false;
|
|
60
66
|
}
|
|
@@ -67,16 +73,16 @@ export function inCriticalCssConfig( assetKey ) {
|
|
|
67
73
|
* @param {object} options The options object which will at the very least contain the css property set to true.
|
|
68
74
|
* @returns {promise}
|
|
69
75
|
*/
|
|
70
|
-
export function loadCss(
|
|
71
|
-
const promise = new Promise(
|
|
72
|
-
if (
|
|
76
|
+
export function loadCss(assetKey, options = { css: true }) {
|
|
77
|
+
const promise = new Promise((resolve) => {
|
|
78
|
+
if (options.css === true && !inCriticalCssConfig(assetKey)) {
|
|
73
79
|
import(
|
|
74
|
-
/* webpackChunkName: "[request]" */ `Assets/scss/components/blocks/${
|
|
75
|
-
).then(
|
|
80
|
+
/* webpackChunkName: "[request]" */ `Assets/scss/components/blocks/${assetKey}.scss`
|
|
81
|
+
).then(() => resolve(true));
|
|
76
82
|
} else {
|
|
77
|
-
return resolve(
|
|
83
|
+
return resolve(true);
|
|
78
84
|
}
|
|
79
|
-
}
|
|
85
|
+
});
|
|
80
86
|
return promise;
|
|
81
87
|
}
|
|
82
88
|
|
|
@@ -86,104 +92,106 @@ export function loadCss( assetKey, options = { css: true } ) {
|
|
|
86
92
|
export function checkDevice() {
|
|
87
93
|
try {
|
|
88
94
|
const deviceAgent = navigator.userAgent.toLowerCase();
|
|
89
|
-
const htmlElement = document.querySelector(
|
|
90
|
-
if (
|
|
91
|
-
|
|
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');
|
|
92
102
|
}
|
|
93
|
-
if (
|
|
94
|
-
htmlElement.classList.add(
|
|
103
|
+
if ('ontouchstart' in globalThis) {
|
|
104
|
+
htmlElement.classList.add('touch');
|
|
95
105
|
}
|
|
96
|
-
if (
|
|
97
|
-
htmlElement.classList.add(
|
|
106
|
+
if (navigator.connection) {
|
|
107
|
+
htmlElement.classList.add(navigator.connection.effectiveType);
|
|
98
108
|
}
|
|
99
|
-
if (
|
|
109
|
+
if (navigator.platform) {
|
|
100
110
|
let platform = navigator.platform.toLowerCase();
|
|
101
111
|
let platformArray = [platform];
|
|
102
|
-
if (
|
|
112
|
+
if (platform.search('-')) {
|
|
103
113
|
platformArray = platform.split('-');
|
|
104
114
|
}
|
|
105
|
-
if (
|
|
115
|
+
if (platform.search(' ')) {
|
|
106
116
|
platformArray = platform.split(' ');
|
|
107
117
|
}
|
|
108
|
-
htmlElement.classList.add(
|
|
118
|
+
htmlElement.classList.add(...platformArray);
|
|
109
119
|
}
|
|
110
|
-
if (
|
|
111
|
-
htmlElement.classList.add(
|
|
112
|
-
htmlElement.classList.add(
|
|
120
|
+
if (deviceAgent.match(/(iphone|ipod|ipad)/)) {
|
|
121
|
+
htmlElement.classList.add('ios');
|
|
122
|
+
htmlElement.classList.add('mobile');
|
|
113
123
|
}
|
|
114
|
-
if (deviceAgent.match(
|
|
115
|
-
|
|
124
|
+
if (deviceAgent.match(/(windows)/)) {
|
|
125
|
+
htmlElement.classList.add('windows');
|
|
116
126
|
}
|
|
117
|
-
if (deviceAgent.match(
|
|
118
|
-
|
|
127
|
+
if (deviceAgent.match(/(macintosh)/)) {
|
|
128
|
+
htmlElement.classList.add('mac');
|
|
119
129
|
}
|
|
120
|
-
if (deviceAgent.match(
|
|
121
|
-
|
|
130
|
+
if (deviceAgent.match(/(android)/)) {
|
|
131
|
+
htmlElement.classList.add('android');
|
|
122
132
|
}
|
|
123
|
-
if (
|
|
124
|
-
htmlElement.classList.add(
|
|
125
|
-
} else if (
|
|
126
|
-
htmlElement.classList.add(
|
|
127
|
-
} else if (
|
|
128
|
-
htmlElement.classList.add(
|
|
129
|
-
} else if (
|
|
130
|
-
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');
|
|
131
141
|
} else if (
|
|
132
|
-
navigator.userAgent.search(
|
|
133
|
-
navigator.userAgent.search(
|
|
142
|
+
navigator.userAgent.search('Safari') >= 0 &&
|
|
143
|
+
navigator.userAgent.search('Chrome') < 0
|
|
134
144
|
) {
|
|
135
|
-
htmlElement.classList.add(
|
|
136
|
-
} else if (
|
|
137
|
-
htmlElement.classList.add(
|
|
145
|
+
htmlElement.classList.add('safari');
|
|
146
|
+
} else if (navigator.userAgent.search('Opera') >= 0) {
|
|
147
|
+
htmlElement.classList.add('opera');
|
|
138
148
|
}
|
|
139
149
|
} catch (error) {
|
|
140
|
-
console.error(error)
|
|
150
|
+
console.error(error);
|
|
141
151
|
}
|
|
142
152
|
}
|
|
143
153
|
|
|
144
154
|
/**
|
|
145
|
-
* 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.
|
|
146
156
|
* Returns a resolved promise when the load event has fired.
|
|
147
157
|
* @param {htmlElement} img The image element you want to wait for.
|
|
148
|
-
* @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.
|
|
149
159
|
* @returns {promise}
|
|
150
160
|
*/
|
|
151
|
-
export async function waitForLoad(
|
|
152
|
-
const loaded = new Promise(
|
|
153
|
-
if (
|
|
154
|
-
if (
|
|
161
|
+
export async function waitForLoad(img, delayedFunction) {
|
|
162
|
+
const loaded = new Promise((resolve) => {
|
|
163
|
+
if (img.complete) {
|
|
164
|
+
if (typeof delayedFunction === 'function') {
|
|
155
165
|
delayedFunction();
|
|
156
166
|
}
|
|
157
|
-
return resolve(
|
|
167
|
+
return resolve(true);
|
|
158
168
|
}
|
|
159
169
|
img.addEventListener(
|
|
160
170
|
'load',
|
|
161
171
|
() => {
|
|
162
|
-
if (
|
|
172
|
+
if (typeof delayedFunction === 'function') {
|
|
163
173
|
delayedFunction();
|
|
164
174
|
}
|
|
165
|
-
return resolve(
|
|
175
|
+
return resolve(true);
|
|
166
176
|
},
|
|
167
177
|
{ once: true }
|
|
168
178
|
);
|
|
169
|
-
}
|
|
170
|
-
console.log( error, 'could not load the image', img )
|
|
171
|
-
);
|
|
179
|
+
}).catch((error) => console.log(error, 'could not load the image', img));
|
|
172
180
|
return loaded;
|
|
173
181
|
}
|
|
174
182
|
|
|
175
183
|
/**
|
|
176
|
-
* Check whether the current environment supports the webp image format.
|
|
177
|
-
* Returns true if it does.
|
|
184
|
+
* Check whether the current environment supports the webp image format.
|
|
185
|
+
* Returns true if it does.
|
|
178
186
|
* @returns {boolean}
|
|
179
187
|
*/
|
|
180
188
|
export async function supportsWebp() {
|
|
181
189
|
// eslint-disable-next-line no-restricted-globals
|
|
182
|
-
if (
|
|
190
|
+
if (!self.createImageBitmap) return false;
|
|
183
191
|
const webpData =
|
|
184
192
|
'data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAAAAAAfQ//73v/+BiOh/AAA=';
|
|
185
|
-
const blob = await fetch(
|
|
186
|
-
return createImageBitmap(
|
|
193
|
+
const blob = await fetch(webpData).then((r) => r.blob());
|
|
194
|
+
return createImageBitmap(blob).then(
|
|
187
195
|
() => true,
|
|
188
196
|
() => false
|
|
189
197
|
);
|
|
@@ -196,30 +204,28 @@ export async function supportsWebp() {
|
|
|
196
204
|
// } )();
|
|
197
205
|
|
|
198
206
|
/**
|
|
199
|
-
* DEPRECATED!! footerIntersection will be removed in a future version.
|
|
207
|
+
* DEPRECATED!! footerIntersection will be removed in a future version.
|
|
200
208
|
*/
|
|
201
|
-
export function footerIntersection(
|
|
202
|
-
entries.forEach(
|
|
203
|
-
if (
|
|
204
|
-
if (
|
|
209
|
+
export function footerIntersection(entries, element) {
|
|
210
|
+
entries.forEach((entry) => {
|
|
211
|
+
if (element) {
|
|
212
|
+
if (entry.isIntersecting) {
|
|
205
213
|
const { height } = entry.boundingClientRect;
|
|
206
|
-
element.style.bottom = `${
|
|
214
|
+
element.style.bottom = `${height}px`;
|
|
207
215
|
} else {
|
|
208
216
|
element.style.bottom = '0px';
|
|
209
217
|
}
|
|
210
218
|
}
|
|
211
|
-
}
|
|
219
|
+
});
|
|
212
220
|
}
|
|
213
221
|
|
|
214
222
|
/**
|
|
215
|
-
* 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.
|
|
216
224
|
* @returns {promise}
|
|
217
225
|
*/
|
|
218
226
|
export function getSwiperAssets() {
|
|
219
227
|
const getSwiperJs = () =>
|
|
220
|
-
import(
|
|
221
|
-
/* webpackChunkName: 'swiper' */ '../../swiper/swiper-bundle.js'
|
|
222
|
-
);
|
|
228
|
+
import(/* webpackChunkName: 'swiper' */ '../../swiper/swiper-bundle.js');
|
|
223
229
|
|
|
224
230
|
const getSwiperCss = () =>
|
|
225
231
|
import(
|
|
@@ -227,8 +233,8 @@ export function getSwiperAssets() {
|
|
|
227
233
|
'../../swiper/swiper-bundle.min.css'
|
|
228
234
|
);
|
|
229
235
|
|
|
230
|
-
const promisedJs = Promise.all(
|
|
231
|
-
(
|
|
236
|
+
const promisedJs = Promise.all([getSwiperJs(), getSwiperCss()]).then(
|
|
237
|
+
(values) => {
|
|
232
238
|
return values;
|
|
233
239
|
}
|
|
234
240
|
);
|
|
@@ -236,11 +242,11 @@ export function getSwiperAssets() {
|
|
|
236
242
|
}
|
|
237
243
|
|
|
238
244
|
/**
|
|
239
|
-
* 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.
|
|
240
246
|
* @returns {promise}
|
|
241
247
|
*/
|
|
242
248
|
export function getJquery() {
|
|
243
|
-
if (
|
|
249
|
+
if (!window.jQuery) {
|
|
244
250
|
const importCode = () =>
|
|
245
251
|
import(
|
|
246
252
|
/* webpackChunkName: 'jquery' */ '../../jquery/dist/jquery.min.js'
|
|
@@ -251,29 +257,25 @@ export function getJquery() {
|
|
|
251
257
|
}
|
|
252
258
|
|
|
253
259
|
/**
|
|
254
|
-
* 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.
|
|
255
261
|
* @returns {promise}
|
|
256
262
|
*/
|
|
257
263
|
export function getGsap() {
|
|
258
264
|
const gsapCore = () =>
|
|
259
|
-
import(
|
|
265
|
+
import('../../gsap/dist/gsap.min.js').then((gsapObj) => {
|
|
260
266
|
const { gsap } = gsapObj;
|
|
261
267
|
return gsap;
|
|
262
|
-
}
|
|
268
|
+
});
|
|
263
269
|
|
|
264
270
|
const gsapPlugin = () =>
|
|
265
|
-
import(
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
( values ) => {
|
|
274
|
-
return values;
|
|
275
|
-
}
|
|
276
|
-
);
|
|
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
|
+
});
|
|
277
279
|
return prom;
|
|
278
280
|
}
|
|
279
281
|
|
|
@@ -282,7 +284,7 @@ export function getGsap() {
|
|
|
282
284
|
* @param {*} userAgent Pass the value of navigator.userAgent.
|
|
283
285
|
* @returns {boolean}
|
|
284
286
|
*/
|
|
285
|
-
export function isTablet(
|
|
287
|
+
export function isTablet(userAgent) {
|
|
286
288
|
return /(ipad|tablet|(android(?!.*mobile))|(windows(?!.*phone)(.*touch))|kindle|playbook|silk|(puffin(?!.*(IP|AP|WP))))/.test(
|
|
287
289
|
userAgent.toLowerCase()
|
|
288
290
|
);
|
|
@@ -290,35 +292,45 @@ export function isTablet( userAgent ) {
|
|
|
290
292
|
|
|
291
293
|
/**
|
|
292
294
|
* Returns true if the device is a mobile device. Checks navigator.userAgent||navigator.vendor||window.opera.
|
|
293
|
-
* @returns {boolean}
|
|
295
|
+
* @returns {boolean}
|
|
294
296
|
*/
|
|
295
|
-
export function mobileCheck
|
|
297
|
+
export function mobileCheck() {
|
|
296
298
|
let check = false;
|
|
297
|
-
(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);
|
|
298
310
|
return check;
|
|
299
|
-
|
|
311
|
+
}
|
|
300
312
|
|
|
301
313
|
/**
|
|
302
|
-
* 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.
|
|
303
315
|
* If another resize even occurs it resets the time window.
|
|
304
316
|
* @param {function} debouncedFunction The function you want to run after a window resize event.
|
|
305
317
|
* @param {number} time The time in ms.
|
|
306
|
-
*/
|
|
307
|
-
export function resizeDebouncer(
|
|
318
|
+
*/
|
|
319
|
+
export function resizeDebouncer(debouncedFunction, time = 250) {
|
|
308
320
|
let resizeTimer;
|
|
309
|
-
window.addEventListener(
|
|
310
|
-
clearTimeout(
|
|
311
|
-
resizeTimer = setTimeout(
|
|
321
|
+
window.addEventListener('resize', () => {
|
|
322
|
+
clearTimeout(resizeTimer);
|
|
323
|
+
resizeTimer = setTimeout(() => {
|
|
312
324
|
debouncedFunction();
|
|
313
|
-
}, time
|
|
314
|
-
}
|
|
325
|
+
}, time);
|
|
326
|
+
});
|
|
315
327
|
}
|
|
316
328
|
|
|
317
329
|
/**
|
|
318
|
-
* 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.
|
|
319
331
|
* If another resize even occurs it resets the time window.
|
|
320
332
|
* @param {htmlElement} element The element that emits the event.
|
|
321
|
-
* @param {string} eventType The type of event to listen for.
|
|
333
|
+
* @param {string} eventType The type of event to listen for.
|
|
322
334
|
* @param {function} debouncedFunction The function to run after the event.
|
|
323
335
|
* @param {number} time The time in ms.
|
|
324
336
|
*/
|
|
@@ -329,49 +341,49 @@ export function eventListenerDebouncer(
|
|
|
329
341
|
time = 250
|
|
330
342
|
) {
|
|
331
343
|
let timer;
|
|
332
|
-
element.addEventListener(
|
|
333
|
-
clearTimeout(
|
|
334
|
-
timer = setTimeout(
|
|
335
|
-
debouncedFunction(
|
|
336
|
-
}, time
|
|
337
|
-
}
|
|
344
|
+
element.addEventListener(eventType, (event) => {
|
|
345
|
+
clearTimeout(timer);
|
|
346
|
+
timer = setTimeout(() => {
|
|
347
|
+
debouncedFunction(event);
|
|
348
|
+
}, time);
|
|
349
|
+
});
|
|
338
350
|
}
|
|
339
351
|
|
|
340
352
|
/**
|
|
341
353
|
* Injects the youtube iframe api script and waits for the YT object to be instantiated before resolving the promise
|
|
342
|
-
* @returns {promise} Resolves once the YT object is available.
|
|
354
|
+
* @returns {promise} Resolves once the YT object is available.
|
|
343
355
|
*/
|
|
344
356
|
export function injectYouTubeIframeScript() {
|
|
345
|
-
const prom = new Promise(
|
|
346
|
-
if (
|
|
357
|
+
const prom = new Promise((resolve) => {
|
|
358
|
+
if (globalThis.YT) {
|
|
347
359
|
return resolve();
|
|
348
360
|
}
|
|
349
|
-
const tag = document.createElement(
|
|
361
|
+
const tag = document.createElement('script');
|
|
350
362
|
tag.id = 'iframe-api';
|
|
351
363
|
tag.src = 'https://www.youtube.com/iframe_api';
|
|
352
364
|
|
|
353
|
-
const firstScriptTag = document.getElementsByTagName(
|
|
354
|
-
firstScriptTag.parentNode.insertBefore(
|
|
365
|
+
const firstScriptTag = document.getElementsByTagName('script')[0];
|
|
366
|
+
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
|
|
355
367
|
|
|
356
|
-
tag.addEventListener(
|
|
368
|
+
tag.addEventListener('load', () => {
|
|
357
369
|
if (!YT.loaded) {
|
|
358
370
|
const loadingCheck = setInterval(() => {
|
|
359
371
|
if (YT.loaded) {
|
|
360
372
|
clearInterval(loadingCheck);
|
|
361
|
-
return resolve(
|
|
373
|
+
return resolve(true);
|
|
362
374
|
}
|
|
363
375
|
}, 50);
|
|
364
376
|
} else {
|
|
365
|
-
return resolve(
|
|
377
|
+
return resolve(true);
|
|
366
378
|
}
|
|
367
|
-
}
|
|
368
|
-
}
|
|
379
|
+
});
|
|
380
|
+
});
|
|
369
381
|
|
|
370
382
|
return prom;
|
|
371
383
|
}
|
|
372
384
|
|
|
373
|
-
export function fallbackCopyToClipboard(
|
|
374
|
-
const textArea = document.createElement(
|
|
385
|
+
export function fallbackCopyToClipboard(text) {
|
|
386
|
+
const textArea = document.createElement('textarea');
|
|
375
387
|
textArea.value = text;
|
|
376
388
|
|
|
377
389
|
// Avoid scrolling to bottom
|
|
@@ -379,58 +391,55 @@ export function fallbackCopyToClipboard( text ) {
|
|
|
379
391
|
textArea.style.left = '0';
|
|
380
392
|
textArea.style.position = 'fixed';
|
|
381
393
|
|
|
382
|
-
document.body.appendChild(
|
|
394
|
+
document.body.appendChild(textArea);
|
|
383
395
|
textArea.focus();
|
|
384
396
|
textArea.select();
|
|
385
397
|
|
|
386
398
|
try {
|
|
387
|
-
const successful = document.execCommand(
|
|
399
|
+
const successful = document.execCommand('copy');
|
|
388
400
|
const msg = successful ? 'successful' : 'unsuccessful';
|
|
389
|
-
console.log(
|
|
390
|
-
} catch (
|
|
391
|
-
console.error(
|
|
401
|
+
console.log(`Fallback: Copying text command was ${msg}`);
|
|
402
|
+
} catch (err) {
|
|
403
|
+
console.error('Fallback: Oops, unable to copy', err);
|
|
392
404
|
}
|
|
393
405
|
|
|
394
|
-
document.body.removeChild(
|
|
406
|
+
document.body.removeChild(textArea);
|
|
395
407
|
}
|
|
396
408
|
|
|
397
|
-
|
|
398
409
|
export function copyToClipboard() {
|
|
399
|
-
const copyLinks = document.querySelectorAll(
|
|
410
|
+
const copyLinks = document.querySelectorAll('.copy-to-clipboard');
|
|
400
411
|
let timeout;
|
|
401
|
-
copyLinks.forEach(
|
|
402
|
-
link.addEventListener(
|
|
412
|
+
copyLinks.forEach((link) => {
|
|
413
|
+
link.addEventListener('click', function () {
|
|
403
414
|
const copyToClipboardDone = link.nextElementSibling;
|
|
404
|
-
if (
|
|
405
|
-
fallbackCopyToClipboard(
|
|
415
|
+
if (!navigator.clipboard) {
|
|
416
|
+
fallbackCopyToClipboard(this.dataset.url);
|
|
406
417
|
return;
|
|
407
418
|
}
|
|
408
419
|
|
|
409
|
-
navigator.clipboard.writeText(
|
|
420
|
+
navigator.clipboard.writeText(this.dataset.url).then(
|
|
410
421
|
function () {
|
|
411
|
-
console.log(
|
|
422
|
+
console.log('Copying to clipboard was successful!');
|
|
412
423
|
},
|
|
413
|
-
function (
|
|
414
|
-
console.error(
|
|
424
|
+
function (err) {
|
|
425
|
+
console.error('Could not copy text: ', err);
|
|
415
426
|
}
|
|
416
427
|
);
|
|
417
428
|
|
|
418
429
|
if (
|
|
419
430
|
copyToClipboardDone &&
|
|
420
431
|
copyToClipboardDone.classList &&
|
|
421
|
-
copyToClipboardDone.classList.contains(
|
|
422
|
-
'sharing__clipboard-done'
|
|
423
|
-
)
|
|
432
|
+
copyToClipboardDone.classList.contains('sharing__clipboard-done')
|
|
424
433
|
) {
|
|
425
|
-
clearTimeout(
|
|
426
|
-
copyToClipboardDone.classList.remove(
|
|
434
|
+
clearTimeout(timeout);
|
|
435
|
+
copyToClipboardDone.classList.remove('hidden');
|
|
427
436
|
|
|
428
|
-
timeout = setTimeout(
|
|
429
|
-
copyToClipboardDone.classList.add(
|
|
430
|
-
}, 2000
|
|
437
|
+
timeout = setTimeout(() => {
|
|
438
|
+
copyToClipboardDone.classList.add('hidden');
|
|
439
|
+
}, 2000);
|
|
431
440
|
}
|
|
432
|
-
}
|
|
433
|
-
}
|
|
441
|
+
});
|
|
442
|
+
});
|
|
434
443
|
}
|
|
435
444
|
|
|
436
445
|
/**
|
|
@@ -439,21 +448,25 @@ export function copyToClipboard() {
|
|
|
439
448
|
* @returns {boolean} True if visible and false if not.
|
|
440
449
|
*/
|
|
441
450
|
export function isInViewport(element) {
|
|
442
|
-
|
|
443
|
-
|
|
451
|
+
const position = element.getBoundingClientRect();
|
|
452
|
+
return (
|
|
453
|
+
(position.top >= 0 && position.bottom <= window.innerHeight) ||
|
|
454
|
+
(position.top < window.innerHeight && position.bottom >= 0)
|
|
455
|
+
);
|
|
444
456
|
}
|
|
445
457
|
|
|
446
458
|
/* eslint-disable-next-line */
|
|
447
|
-
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])+$/;
|
|
448
461
|
|
|
449
462
|
/**
|
|
450
463
|
* Checks to make sure a passed string has a valid email address structure and characters.
|
|
451
464
|
* @param {RegExp} email - The email address as a string.
|
|
452
465
|
* @returns {boolean} True if valid and false if not.
|
|
453
466
|
*/
|
|
454
|
-
export function isEmailValid(
|
|
455
|
-
return emailRegex.test(
|
|
456
|
-
}
|
|
467
|
+
export function isEmailValid(email) {
|
|
468
|
+
return emailRegex.test(email);
|
|
469
|
+
}
|
|
457
470
|
|
|
458
471
|
/**
|
|
459
472
|
* Get the value of a css property on a specific element.
|
|
@@ -523,9 +536,7 @@ export function detectSwipe(element, callback, removeHandlers = false) {
|
|
|
523
536
|
function (event) {
|
|
524
537
|
touchendX = event.changedTouches[0].screenX;
|
|
525
538
|
touchendY = event.changedTouches[0].screenY;
|
|
526
|
-
callback(
|
|
527
|
-
handleGesture(touchstartX, touchstartY, touchendX, touchendY)
|
|
528
|
-
);
|
|
539
|
+
callback(handleGesture(touchstartX, touchstartY, touchendX, touchendY));
|
|
529
540
|
},
|
|
530
541
|
false
|
|
531
542
|
);
|
|
@@ -536,6 +547,23 @@ export function detectSwipe(element, callback, removeHandlers = false) {
|
|
|
536
547
|
}
|
|
537
548
|
}
|
|
538
549
|
|
|
550
|
+
/**
|
|
551
|
+
* Function for getting the ios operating system version
|
|
552
|
+
*
|
|
553
|
+
* @returns {number} the ios version
|
|
554
|
+
*/
|
|
555
|
+
export function checkIosVersion() {
|
|
556
|
+
const agent = window.navigator.userAgent,
|
|
557
|
+
start = agent.indexOf('OS ');
|
|
558
|
+
if (
|
|
559
|
+
(agent.indexOf('iPhone') > -1 || agent.indexOf('iPad') > -1) &&
|
|
560
|
+
start > -1
|
|
561
|
+
) {
|
|
562
|
+
return window.Number(agent.substr(start + 3, 3).replace('_', '.'));
|
|
563
|
+
}
|
|
564
|
+
return 0;
|
|
565
|
+
}
|
|
566
|
+
|
|
539
567
|
const api = {
|
|
540
568
|
copyToClipboard,
|
|
541
569
|
checkDevice,
|
|
@@ -558,6 +586,7 @@ const api = {
|
|
|
558
586
|
toggleClassByValidity,
|
|
559
587
|
waitForLoad,
|
|
560
588
|
getElementStyles,
|
|
561
|
-
getPercent
|
|
589
|
+
getPercent,
|
|
590
|
+
checkIosVersion
|
|
562
591
|
};
|
|
563
592
|
export default api;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pernod-ricard-global-cms/jsutils",
|
|
3
|
-
"version": "1.5
|
|
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": {
|