@pernod-ricard-global-cms/jsutils 1.6.4 → 1.7.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.
- package/.prettierrc +19 -0
- package/jsutils.js +223 -185
- package/package.json +28 -27
package/.prettierrc
ADDED
package/jsutils.js
CHANGED
|
@@ -2,47 +2,58 @@
|
|
|
2
2
|
/* eslint-disable no-console */
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* Function for check whether the code is running within the Wordpress admin page. Checks for wp-admin class.
|
|
6
|
+
* @returns {Boolean}
|
|
7
|
+
*/
|
|
8
|
+
export function isWpAdmin() {
|
|
9
|
+
return document.body.classList.contains('wp-admin') ? true : false;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* This function accepts an html element and returns the position of that element on the page.
|
|
14
|
+
*
|
|
7
15
|
* @param {htmlElement} element The element whose position you want to get.
|
|
8
16
|
* @returns {object} An object with the x and y pixel values.
|
|
9
17
|
*/
|
|
10
|
-
export function getPosition(
|
|
18
|
+
export function getPosition(element) {
|
|
11
19
|
const scrollElementTag = document.scrollingElement.tagName;
|
|
12
20
|
let xPosition = 0;
|
|
13
21
|
let yPosition = 0;
|
|
14
|
-
while (
|
|
15
|
-
xPosition +=
|
|
16
|
-
element.offsetLeft - element.scrollLeft + element.clientLeft;
|
|
22
|
+
while (element) {
|
|
23
|
+
xPosition += element.offsetLeft - element.scrollLeft + element.clientLeft;
|
|
17
24
|
yPosition += element.offsetTop - element.scrollTop + element.clientTop;
|
|
18
25
|
element = element.offsetParent;
|
|
19
26
|
}
|
|
20
27
|
// Quirks mode safety - in case of missing DOCTYPE
|
|
21
|
-
if (
|
|
22
|
-
yPosition += document.querySelector(
|
|
28
|
+
if (scrollElementTag === 'BODY') {
|
|
29
|
+
yPosition += document.querySelector('body').scrollTop;
|
|
23
30
|
}
|
|
24
31
|
return { x: xPosition, y: yPosition };
|
|
25
32
|
}
|
|
26
33
|
|
|
27
34
|
/**
|
|
28
|
-
* Adds or removes a 'valid' class to an input and button element depending on whether the value of the input is valid.
|
|
35
|
+
* Adds or removes a 'valid' class to an input and button element depending on whether the value of the input is valid.
|
|
29
36
|
* @param {htmlElement} input The input element to check.
|
|
30
|
-
* @param {htmlElement} button A corresponding button to disable if invalid.
|
|
37
|
+
* @param {htmlElement} button A corresponding button to disable if invalid.
|
|
31
38
|
*/
|
|
32
|
-
export function toggleClassByValidity(
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
if (
|
|
36
|
-
button.classList.
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
input.classList.
|
|
39
|
+
export function toggleClassByValidity(input, button) {
|
|
40
|
+
try {
|
|
41
|
+
input.addEventListener('input', () => {
|
|
42
|
+
if (input.validity.valid && input.value) {
|
|
43
|
+
if (!button.classList.contains('valid')) {
|
|
44
|
+
button.classList.add('valid');
|
|
45
|
+
}
|
|
46
|
+
if (!input.classList.contains('valid')) {
|
|
47
|
+
input.classList.add('valid');
|
|
48
|
+
}
|
|
49
|
+
} else {
|
|
50
|
+
button.classList.remove('valid');
|
|
51
|
+
input.classList.remove('valid');
|
|
40
52
|
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
} );
|
|
53
|
+
});
|
|
54
|
+
} catch (error) {
|
|
55
|
+
console.error('jsutils.js ~ toggleClassByValidity ~ error', error);
|
|
56
|
+
}
|
|
46
57
|
}
|
|
47
58
|
|
|
48
59
|
/**
|
|
@@ -51,13 +62,13 @@ export function toggleClassByValidity( input, button ) {
|
|
|
51
62
|
* @param {string} assetKey The assetkey string of the block.
|
|
52
63
|
* @returns {boolean}
|
|
53
64
|
*/
|
|
54
|
-
export function inCriticalCssConfig(
|
|
55
|
-
if(!globalThis.criticalConfig) {
|
|
65
|
+
export function inCriticalCssConfig(assetKey) {
|
|
66
|
+
if (!globalThis.criticalConfig) {
|
|
56
67
|
return false;
|
|
57
68
|
}
|
|
58
69
|
if (
|
|
59
70
|
globalThis.criticalConfig &&
|
|
60
|
-
globalThis.criticalConfig.indexOf(
|
|
71
|
+
globalThis.criticalConfig.indexOf(assetKey) === -1
|
|
61
72
|
) {
|
|
62
73
|
return false;
|
|
63
74
|
}
|
|
@@ -70,16 +81,16 @@ export function inCriticalCssConfig( assetKey ) {
|
|
|
70
81
|
* @param {object} options The options object which will at the very least contain the css property set to true.
|
|
71
82
|
* @returns {promise}
|
|
72
83
|
*/
|
|
73
|
-
export function loadCss(
|
|
74
|
-
const promise = new Promise(
|
|
75
|
-
if (
|
|
84
|
+
export function loadCss(assetKey, options = { css: true }) {
|
|
85
|
+
const promise = new Promise((resolve) => {
|
|
86
|
+
if (options.css === true && !inCriticalCssConfig(assetKey)) {
|
|
76
87
|
import(
|
|
77
|
-
/* webpackChunkName: "[request]" */ `Assets/scss/components/blocks/${
|
|
78
|
-
).then(
|
|
88
|
+
/* webpackChunkName: "[request]" */ `Assets/scss/components/blocks/${assetKey}.scss`
|
|
89
|
+
).then(() => resolve(true));
|
|
79
90
|
} else {
|
|
80
|
-
return resolve(
|
|
91
|
+
return resolve(true);
|
|
81
92
|
}
|
|
82
|
-
}
|
|
93
|
+
});
|
|
83
94
|
return promise;
|
|
84
95
|
}
|
|
85
96
|
|
|
@@ -89,104 +100,106 @@ export function loadCss( assetKey, options = { css: true } ) {
|
|
|
89
100
|
export function checkDevice() {
|
|
90
101
|
try {
|
|
91
102
|
const deviceAgent = navigator.userAgent.toLowerCase();
|
|
92
|
-
const htmlElement = document.querySelector(
|
|
93
|
-
if (
|
|
94
|
-
|
|
103
|
+
const htmlElement = document.querySelector('html');
|
|
104
|
+
if (
|
|
105
|
+
'ontouchstart' in globalThis &&
|
|
106
|
+
window.screen.width * window.devicePixelRatio >= 2048 &&
|
|
107
|
+
window.screen.width < window.screen.height
|
|
108
|
+
) {
|
|
109
|
+
htmlElement.classList.add('highResTabletPortrait');
|
|
95
110
|
}
|
|
96
|
-
if (
|
|
97
|
-
htmlElement.classList.add(
|
|
111
|
+
if ('ontouchstart' in globalThis) {
|
|
112
|
+
htmlElement.classList.add('touch');
|
|
98
113
|
}
|
|
99
|
-
if (
|
|
100
|
-
htmlElement.classList.add(
|
|
114
|
+
if (navigator.connection) {
|
|
115
|
+
htmlElement.classList.add(navigator.connection.effectiveType);
|
|
101
116
|
}
|
|
102
|
-
if (
|
|
117
|
+
if (navigator.platform) {
|
|
103
118
|
let platform = navigator.platform.toLowerCase();
|
|
104
119
|
let platformArray = [platform];
|
|
105
|
-
if (
|
|
120
|
+
if (platform.search('-')) {
|
|
106
121
|
platformArray = platform.split('-');
|
|
107
122
|
}
|
|
108
|
-
if (
|
|
123
|
+
if (platform.search(' ')) {
|
|
109
124
|
platformArray = platform.split(' ');
|
|
110
125
|
}
|
|
111
|
-
htmlElement.classList.add(
|
|
126
|
+
htmlElement.classList.add(...platformArray);
|
|
112
127
|
}
|
|
113
|
-
if (
|
|
114
|
-
htmlElement.classList.add(
|
|
115
|
-
htmlElement.classList.add(
|
|
128
|
+
if (deviceAgent.match(/(iphone|ipod|ipad)/)) {
|
|
129
|
+
htmlElement.classList.add('ios');
|
|
130
|
+
htmlElement.classList.add('mobile');
|
|
116
131
|
}
|
|
117
|
-
if (deviceAgent.match(
|
|
118
|
-
|
|
132
|
+
if (deviceAgent.match(/(windows)/)) {
|
|
133
|
+
htmlElement.classList.add('windows');
|
|
119
134
|
}
|
|
120
|
-
if (deviceAgent.match(
|
|
121
|
-
|
|
135
|
+
if (deviceAgent.match(/(macintosh)/)) {
|
|
136
|
+
htmlElement.classList.add('mac');
|
|
122
137
|
}
|
|
123
|
-
if (deviceAgent.match(
|
|
124
|
-
|
|
138
|
+
if (deviceAgent.match(/(android)/)) {
|
|
139
|
+
htmlElement.classList.add('android');
|
|
125
140
|
}
|
|
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(
|
|
141
|
+
if (navigator.userAgent.search('MSIE') >= 0) {
|
|
142
|
+
htmlElement.classList.add('ie');
|
|
143
|
+
} else if (navigator.userAgent.search('Edge') >= 0) {
|
|
144
|
+
htmlElement.classList.add('edge-legacy');
|
|
145
|
+
} else if (navigator.userAgent.search('Chrome') >= 0) {
|
|
146
|
+
htmlElement.classList.add('chrome');
|
|
147
|
+
} else if (navigator.userAgent.search('Firefox') >= 0) {
|
|
148
|
+
htmlElement.classList.add('firefox');
|
|
134
149
|
} else if (
|
|
135
|
-
navigator.userAgent.search(
|
|
136
|
-
navigator.userAgent.search(
|
|
150
|
+
navigator.userAgent.search('Safari') >= 0 &&
|
|
151
|
+
navigator.userAgent.search('Chrome') < 0
|
|
137
152
|
) {
|
|
138
|
-
htmlElement.classList.add(
|
|
139
|
-
} else if (
|
|
140
|
-
htmlElement.classList.add(
|
|
153
|
+
htmlElement.classList.add('safari');
|
|
154
|
+
} else if (navigator.userAgent.search('Opera') >= 0) {
|
|
155
|
+
htmlElement.classList.add('opera');
|
|
141
156
|
}
|
|
142
157
|
} catch (error) {
|
|
143
|
-
console.error(error)
|
|
158
|
+
console.error(error);
|
|
144
159
|
}
|
|
145
160
|
}
|
|
146
161
|
|
|
147
162
|
/**
|
|
148
|
-
* Check and possibly wait for an image to have downloaded before running an optional function.
|
|
163
|
+
* Check and possibly wait for an image to have downloaded before running an optional function.
|
|
149
164
|
* Returns a resolved promise when the load event has fired.
|
|
150
165
|
* @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.
|
|
166
|
+
* @param {function} delayedFunction The optional function you want to run when/if the image has downloaded.
|
|
152
167
|
* @returns {promise}
|
|
153
168
|
*/
|
|
154
|
-
export async function waitForLoad(
|
|
155
|
-
const loaded = new Promise(
|
|
156
|
-
if (
|
|
157
|
-
if (
|
|
169
|
+
export async function waitForLoad(img, delayedFunction) {
|
|
170
|
+
const loaded = new Promise((resolve) => {
|
|
171
|
+
if (img.complete) {
|
|
172
|
+
if (typeof delayedFunction === 'function') {
|
|
158
173
|
delayedFunction();
|
|
159
174
|
}
|
|
160
|
-
return resolve(
|
|
175
|
+
return resolve(true);
|
|
161
176
|
}
|
|
162
177
|
img.addEventListener(
|
|
163
178
|
'load',
|
|
164
179
|
() => {
|
|
165
|
-
if (
|
|
180
|
+
if (typeof delayedFunction === 'function') {
|
|
166
181
|
delayedFunction();
|
|
167
182
|
}
|
|
168
|
-
return resolve(
|
|
183
|
+
return resolve(true);
|
|
169
184
|
},
|
|
170
185
|
{ once: true }
|
|
171
186
|
);
|
|
172
|
-
}
|
|
173
|
-
console.log( error, 'could not load the image', img )
|
|
174
|
-
);
|
|
187
|
+
}).catch((error) => console.log(error, 'could not load the image', img));
|
|
175
188
|
return loaded;
|
|
176
189
|
}
|
|
177
190
|
|
|
178
191
|
/**
|
|
179
|
-
* Check whether the current environment supports the webp image format.
|
|
180
|
-
* Returns true if it does.
|
|
192
|
+
* Check whether the current environment supports the webp image format.
|
|
193
|
+
* Returns true if it does.
|
|
181
194
|
* @returns {boolean}
|
|
182
195
|
*/
|
|
183
196
|
export async function supportsWebp() {
|
|
184
197
|
// eslint-disable-next-line no-restricted-globals
|
|
185
|
-
if (
|
|
198
|
+
if (!self.createImageBitmap) return false;
|
|
186
199
|
const webpData =
|
|
187
200
|
'data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAAAAAAfQ//73v/+BiOh/AAA=';
|
|
188
|
-
const blob = await fetch(
|
|
189
|
-
return createImageBitmap(
|
|
201
|
+
const blob = await fetch(webpData).then((r) => r.blob());
|
|
202
|
+
return createImageBitmap(blob).then(
|
|
190
203
|
() => true,
|
|
191
204
|
() => false
|
|
192
205
|
);
|
|
@@ -199,30 +212,28 @@ export async function supportsWebp() {
|
|
|
199
212
|
// } )();
|
|
200
213
|
|
|
201
214
|
/**
|
|
202
|
-
* DEPRECATED!! footerIntersection will be removed in a future version.
|
|
215
|
+
* DEPRECATED!! footerIntersection will be removed in a future version.
|
|
203
216
|
*/
|
|
204
|
-
export function footerIntersection(
|
|
205
|
-
entries.forEach(
|
|
206
|
-
if (
|
|
207
|
-
if (
|
|
217
|
+
export function footerIntersection(entries, element) {
|
|
218
|
+
entries.forEach((entry) => {
|
|
219
|
+
if (element) {
|
|
220
|
+
if (entry.isIntersecting) {
|
|
208
221
|
const { height } = entry.boundingClientRect;
|
|
209
|
-
element.style.bottom = `${
|
|
222
|
+
element.style.bottom = `${height}px`;
|
|
210
223
|
} else {
|
|
211
224
|
element.style.bottom = '0px';
|
|
212
225
|
}
|
|
213
226
|
}
|
|
214
|
-
}
|
|
227
|
+
});
|
|
215
228
|
}
|
|
216
229
|
|
|
217
230
|
/**
|
|
218
|
-
* Dynamically retrieves the swiper css and js and returns a resolved promise when they have both been successfully fetched.
|
|
231
|
+
* Dynamically retrieves the swiper css and js and returns a resolved promise when they have both been successfully fetched.
|
|
219
232
|
* @returns {promise}
|
|
220
233
|
*/
|
|
221
234
|
export function getSwiperAssets() {
|
|
222
235
|
const getSwiperJs = () =>
|
|
223
|
-
import(
|
|
224
|
-
/* webpackChunkName: 'swiper' */ '../../swiper/swiper-bundle.js'
|
|
225
|
-
);
|
|
236
|
+
import(/* webpackChunkName: 'swiper' */ '../../swiper/swiper-bundle.js');
|
|
226
237
|
|
|
227
238
|
const getSwiperCss = () =>
|
|
228
239
|
import(
|
|
@@ -230,8 +241,8 @@ export function getSwiperAssets() {
|
|
|
230
241
|
'../../swiper/swiper-bundle.min.css'
|
|
231
242
|
);
|
|
232
243
|
|
|
233
|
-
const promisedJs = Promise.all(
|
|
234
|
-
(
|
|
244
|
+
const promisedJs = Promise.all([getSwiperJs(), getSwiperCss()]).then(
|
|
245
|
+
(values) => {
|
|
235
246
|
return values;
|
|
236
247
|
}
|
|
237
248
|
);
|
|
@@ -239,11 +250,11 @@ export function getSwiperAssets() {
|
|
|
239
250
|
}
|
|
240
251
|
|
|
241
252
|
/**
|
|
242
|
-
* Dynamically retrieves the jQuery and returns a resolved promise when it has been successfully fetched.
|
|
253
|
+
* Dynamically retrieves the jQuery and returns a resolved promise when it has been successfully fetched.
|
|
243
254
|
* @returns {promise}
|
|
244
255
|
*/
|
|
245
256
|
export function getJquery() {
|
|
246
|
-
if (
|
|
257
|
+
if (!window.jQuery) {
|
|
247
258
|
const importCode = () =>
|
|
248
259
|
import(
|
|
249
260
|
/* webpackChunkName: 'jquery' */ '../../jquery/dist/jquery.min.js'
|
|
@@ -254,29 +265,25 @@ export function getJquery() {
|
|
|
254
265
|
}
|
|
255
266
|
|
|
256
267
|
/**
|
|
257
|
-
* Dynamically retrieves GSAP and the scrolltrigger plugin and returns a resolved promise when they have both been successfully fetched.
|
|
268
|
+
* Dynamically retrieves GSAP and the scrolltrigger plugin and returns a resolved promise when they have both been successfully fetched.
|
|
258
269
|
* @returns {promise}
|
|
259
270
|
*/
|
|
260
271
|
export function getGsap() {
|
|
261
272
|
const gsapCore = () =>
|
|
262
|
-
import(
|
|
273
|
+
import('../../gsap/dist/gsap.min.js').then((gsapObj) => {
|
|
263
274
|
const { gsap } = gsapObj;
|
|
264
275
|
return gsap;
|
|
265
|
-
}
|
|
276
|
+
});
|
|
266
277
|
|
|
267
278
|
const gsapPlugin = () =>
|
|
268
|
-
import(
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
( values ) => {
|
|
277
|
-
return values;
|
|
278
|
-
}
|
|
279
|
-
);
|
|
279
|
+
import('../../gsap/dist/ScrollTrigger.min.js').then((scrollObj) => {
|
|
280
|
+
const ScrollTrigger = scrollObj;
|
|
281
|
+
return ScrollTrigger;
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
const prom = Promise.all([gsapCore(), gsapPlugin()]).then((values) => {
|
|
285
|
+
return values;
|
|
286
|
+
});
|
|
280
287
|
return prom;
|
|
281
288
|
}
|
|
282
289
|
|
|
@@ -285,7 +292,7 @@ export function getGsap() {
|
|
|
285
292
|
* @param {*} userAgent Pass the value of navigator.userAgent.
|
|
286
293
|
* @returns {boolean}
|
|
287
294
|
*/
|
|
288
|
-
export function isTablet(
|
|
295
|
+
export function isTablet(userAgent) {
|
|
289
296
|
return /(ipad|tablet|(android(?!.*mobile))|(windows(?!.*phone)(.*touch))|kindle|playbook|silk|(puffin(?!.*(IP|AP|WP))))/.test(
|
|
290
297
|
userAgent.toLowerCase()
|
|
291
298
|
);
|
|
@@ -293,35 +300,45 @@ export function isTablet( userAgent ) {
|
|
|
293
300
|
|
|
294
301
|
/**
|
|
295
302
|
* Returns true if the device is a mobile device. Checks navigator.userAgent||navigator.vendor||window.opera.
|
|
296
|
-
* @returns {boolean}
|
|
303
|
+
* @returns {boolean}
|
|
297
304
|
*/
|
|
298
|
-
export function mobileCheck
|
|
305
|
+
export function mobileCheck() {
|
|
299
306
|
let check = false;
|
|
300
|
-
(function
|
|
307
|
+
(function (a) {
|
|
308
|
+
if (
|
|
309
|
+
/(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(
|
|
310
|
+
a
|
|
311
|
+
) ||
|
|
312
|
+
/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(
|
|
313
|
+
a.substr(0, 4)
|
|
314
|
+
)
|
|
315
|
+
)
|
|
316
|
+
check = true;
|
|
317
|
+
})(navigator.userAgent || navigator.vendor || window.opera);
|
|
301
318
|
return check;
|
|
302
|
-
|
|
319
|
+
}
|
|
303
320
|
|
|
304
321
|
/**
|
|
305
|
-
* Run a function after a window resize event, but only after the alloted time has ended.
|
|
322
|
+
* Run a function after a window resize event, but only after the alloted time has ended.
|
|
306
323
|
* If another resize even occurs it resets the time window.
|
|
307
324
|
* @param {function} debouncedFunction The function you want to run after a window resize event.
|
|
308
325
|
* @param {number} time The time in ms.
|
|
309
|
-
*/
|
|
310
|
-
export function resizeDebouncer(
|
|
326
|
+
*/
|
|
327
|
+
export function resizeDebouncer(debouncedFunction, time = 250) {
|
|
311
328
|
let resizeTimer;
|
|
312
|
-
window.addEventListener(
|
|
313
|
-
clearTimeout(
|
|
314
|
-
resizeTimer = setTimeout(
|
|
329
|
+
window.addEventListener('resize', () => {
|
|
330
|
+
clearTimeout(resizeTimer);
|
|
331
|
+
resizeTimer = setTimeout(() => {
|
|
315
332
|
debouncedFunction();
|
|
316
|
-
}, time
|
|
317
|
-
}
|
|
333
|
+
}, time);
|
|
334
|
+
});
|
|
318
335
|
}
|
|
319
336
|
|
|
320
337
|
/**
|
|
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.
|
|
338
|
+
* 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
339
|
* If another resize even occurs it resets the time window.
|
|
323
340
|
* @param {htmlElement} element The element that emits the event.
|
|
324
|
-
* @param {string} eventType The type of event to listen for.
|
|
341
|
+
* @param {string} eventType The type of event to listen for.
|
|
325
342
|
* @param {function} debouncedFunction The function to run after the event.
|
|
326
343
|
* @param {number} time The time in ms.
|
|
327
344
|
*/
|
|
@@ -332,49 +349,49 @@ export function eventListenerDebouncer(
|
|
|
332
349
|
time = 250
|
|
333
350
|
) {
|
|
334
351
|
let timer;
|
|
335
|
-
element.addEventListener(
|
|
336
|
-
clearTimeout(
|
|
337
|
-
timer = setTimeout(
|
|
338
|
-
debouncedFunction(
|
|
339
|
-
}, time
|
|
340
|
-
}
|
|
352
|
+
element.addEventListener(eventType, (event) => {
|
|
353
|
+
clearTimeout(timer);
|
|
354
|
+
timer = setTimeout(() => {
|
|
355
|
+
debouncedFunction(event);
|
|
356
|
+
}, time);
|
|
357
|
+
});
|
|
341
358
|
}
|
|
342
359
|
|
|
343
360
|
/**
|
|
344
361
|
* 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.
|
|
362
|
+
* @returns {promise} Resolves once the YT object is available.
|
|
346
363
|
*/
|
|
347
364
|
export function injectYouTubeIframeScript() {
|
|
348
|
-
const prom = new Promise(
|
|
349
|
-
if (
|
|
365
|
+
const prom = new Promise((resolve) => {
|
|
366
|
+
if (globalThis.YT) {
|
|
350
367
|
return resolve();
|
|
351
368
|
}
|
|
352
|
-
const tag = document.createElement(
|
|
369
|
+
const tag = document.createElement('script');
|
|
353
370
|
tag.id = 'iframe-api';
|
|
354
371
|
tag.src = 'https://www.youtube.com/iframe_api';
|
|
355
372
|
|
|
356
|
-
const firstScriptTag = document.getElementsByTagName(
|
|
357
|
-
firstScriptTag.parentNode.insertBefore(
|
|
373
|
+
const firstScriptTag = document.getElementsByTagName('script')[0];
|
|
374
|
+
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
|
|
358
375
|
|
|
359
|
-
tag.addEventListener(
|
|
376
|
+
tag.addEventListener('load', () => {
|
|
360
377
|
if (!YT.loaded) {
|
|
361
378
|
const loadingCheck = setInterval(() => {
|
|
362
379
|
if (YT.loaded) {
|
|
363
380
|
clearInterval(loadingCheck);
|
|
364
|
-
return resolve(
|
|
381
|
+
return resolve(true);
|
|
365
382
|
}
|
|
366
383
|
}, 50);
|
|
367
384
|
} else {
|
|
368
|
-
return resolve(
|
|
385
|
+
return resolve(true);
|
|
369
386
|
}
|
|
370
|
-
}
|
|
371
|
-
}
|
|
387
|
+
});
|
|
388
|
+
});
|
|
372
389
|
|
|
373
390
|
return prom;
|
|
374
391
|
}
|
|
375
392
|
|
|
376
|
-
export function fallbackCopyToClipboard(
|
|
377
|
-
const textArea = document.createElement(
|
|
393
|
+
export function fallbackCopyToClipboard(text) {
|
|
394
|
+
const textArea = document.createElement('textarea');
|
|
378
395
|
textArea.value = text;
|
|
379
396
|
|
|
380
397
|
// Avoid scrolling to bottom
|
|
@@ -382,58 +399,55 @@ export function fallbackCopyToClipboard( text ) {
|
|
|
382
399
|
textArea.style.left = '0';
|
|
383
400
|
textArea.style.position = 'fixed';
|
|
384
401
|
|
|
385
|
-
document.body.appendChild(
|
|
402
|
+
document.body.appendChild(textArea);
|
|
386
403
|
textArea.focus();
|
|
387
404
|
textArea.select();
|
|
388
405
|
|
|
389
406
|
try {
|
|
390
|
-
const successful = document.execCommand(
|
|
407
|
+
const successful = document.execCommand('copy');
|
|
391
408
|
const msg = successful ? 'successful' : 'unsuccessful';
|
|
392
|
-
console.log(
|
|
393
|
-
} catch (
|
|
394
|
-
console.error(
|
|
409
|
+
console.log(`Fallback: Copying text command was ${msg}`);
|
|
410
|
+
} catch (err) {
|
|
411
|
+
console.error('Fallback: Oops, unable to copy', err);
|
|
395
412
|
}
|
|
396
413
|
|
|
397
|
-
document.body.removeChild(
|
|
414
|
+
document.body.removeChild(textArea);
|
|
398
415
|
}
|
|
399
416
|
|
|
400
|
-
|
|
401
417
|
export function copyToClipboard() {
|
|
402
|
-
const copyLinks = document.querySelectorAll(
|
|
418
|
+
const copyLinks = document.querySelectorAll('.copy-to-clipboard');
|
|
403
419
|
let timeout;
|
|
404
|
-
copyLinks.forEach(
|
|
405
|
-
link.addEventListener(
|
|
420
|
+
copyLinks.forEach((link) => {
|
|
421
|
+
link.addEventListener('click', function () {
|
|
406
422
|
const copyToClipboardDone = link.nextElementSibling;
|
|
407
|
-
if (
|
|
408
|
-
fallbackCopyToClipboard(
|
|
423
|
+
if (!navigator.clipboard) {
|
|
424
|
+
fallbackCopyToClipboard(this.dataset.url);
|
|
409
425
|
return;
|
|
410
426
|
}
|
|
411
427
|
|
|
412
|
-
navigator.clipboard.writeText(
|
|
428
|
+
navigator.clipboard.writeText(this.dataset.url).then(
|
|
413
429
|
function () {
|
|
414
|
-
console.log(
|
|
430
|
+
console.log('Copying to clipboard was successful!');
|
|
415
431
|
},
|
|
416
|
-
function (
|
|
417
|
-
console.error(
|
|
432
|
+
function (err) {
|
|
433
|
+
console.error('Could not copy text: ', err);
|
|
418
434
|
}
|
|
419
435
|
);
|
|
420
436
|
|
|
421
437
|
if (
|
|
422
438
|
copyToClipboardDone &&
|
|
423
439
|
copyToClipboardDone.classList &&
|
|
424
|
-
copyToClipboardDone.classList.contains(
|
|
425
|
-
'sharing__clipboard-done'
|
|
426
|
-
)
|
|
440
|
+
copyToClipboardDone.classList.contains('sharing__clipboard-done')
|
|
427
441
|
) {
|
|
428
|
-
clearTimeout(
|
|
429
|
-
copyToClipboardDone.classList.remove(
|
|
442
|
+
clearTimeout(timeout);
|
|
443
|
+
copyToClipboardDone.classList.remove('hidden');
|
|
430
444
|
|
|
431
|
-
timeout = setTimeout(
|
|
432
|
-
copyToClipboardDone.classList.add(
|
|
433
|
-
}, 2000
|
|
445
|
+
timeout = setTimeout(() => {
|
|
446
|
+
copyToClipboardDone.classList.add('hidden');
|
|
447
|
+
}, 2000);
|
|
434
448
|
}
|
|
435
|
-
}
|
|
436
|
-
}
|
|
449
|
+
});
|
|
450
|
+
});
|
|
437
451
|
}
|
|
438
452
|
|
|
439
453
|
/**
|
|
@@ -442,21 +456,25 @@ export function copyToClipboard() {
|
|
|
442
456
|
* @returns {boolean} True if visible and false if not.
|
|
443
457
|
*/
|
|
444
458
|
export function isInViewport(element) {
|
|
445
|
-
|
|
446
|
-
|
|
459
|
+
const position = element.getBoundingClientRect();
|
|
460
|
+
return (
|
|
461
|
+
(position.top >= 0 && position.bottom <= window.innerHeight) ||
|
|
462
|
+
(position.top < window.innerHeight && position.bottom >= 0)
|
|
463
|
+
);
|
|
447
464
|
}
|
|
448
465
|
|
|
449
466
|
/* eslint-disable-next-line */
|
|
450
|
-
const emailRegex =
|
|
467
|
+
const emailRegex =
|
|
468
|
+
/^[-!#$%&'*+\/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
469
|
|
|
452
470
|
/**
|
|
453
471
|
* Checks to make sure a passed string has a valid email address structure and characters.
|
|
454
472
|
* @param {RegExp} email - The email address as a string.
|
|
455
473
|
* @returns {boolean} True if valid and false if not.
|
|
456
474
|
*/
|
|
457
|
-
export function isEmailValid(
|
|
458
|
-
return emailRegex.test(
|
|
459
|
-
}
|
|
475
|
+
export function isEmailValid(email) {
|
|
476
|
+
return emailRegex.test(email);
|
|
477
|
+
}
|
|
460
478
|
|
|
461
479
|
/**
|
|
462
480
|
* Get the value of a css property on a specific element.
|
|
@@ -526,9 +544,7 @@ export function detectSwipe(element, callback, removeHandlers = false) {
|
|
|
526
544
|
function (event) {
|
|
527
545
|
touchendX = event.changedTouches[0].screenX;
|
|
528
546
|
touchendY = event.changedTouches[0].screenY;
|
|
529
|
-
callback(
|
|
530
|
-
handleGesture(touchstartX, touchstartY, touchendX, touchendY)
|
|
531
|
-
);
|
|
547
|
+
callback(handleGesture(touchstartX, touchstartY, touchendX, touchendY));
|
|
532
548
|
},
|
|
533
549
|
false
|
|
534
550
|
);
|
|
@@ -541,7 +557,7 @@ export function detectSwipe(element, callback, removeHandlers = false) {
|
|
|
541
557
|
|
|
542
558
|
/**
|
|
543
559
|
* Function for getting the ios operating system version
|
|
544
|
-
*
|
|
560
|
+
*
|
|
545
561
|
* @returns {number} the ios version
|
|
546
562
|
*/
|
|
547
563
|
export function checkIosVersion() {
|
|
@@ -556,6 +572,27 @@ export function checkIosVersion() {
|
|
|
556
572
|
return 0;
|
|
557
573
|
}
|
|
558
574
|
|
|
575
|
+
/**
|
|
576
|
+
* Function for adding a link tag with preconnect to the head of the document. Very useful if you need to add this dynamically.
|
|
577
|
+
* @param {string} domain The domain you wish to preconnect to.
|
|
578
|
+
* @returns {void} The preconnect will be appended to the head tag.
|
|
579
|
+
*/
|
|
580
|
+
export function appendPreconnect(domain) {
|
|
581
|
+
try {
|
|
582
|
+
if (!domain) {
|
|
583
|
+
console.log('The domain was missing or broken...');
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
const link = document.createElement('link');
|
|
587
|
+
link.rel = 'preconnect';
|
|
588
|
+
link.href = domain;
|
|
589
|
+
document.head.appendChild(link);
|
|
590
|
+
return;
|
|
591
|
+
} catch (error) {
|
|
592
|
+
console.error(error);
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
|
|
559
596
|
const api = {
|
|
560
597
|
copyToClipboard,
|
|
561
598
|
checkDevice,
|
|
@@ -579,6 +616,7 @@ const api = {
|
|
|
579
616
|
waitForLoad,
|
|
580
617
|
getElementStyles,
|
|
581
618
|
getPercent,
|
|
582
|
-
checkIosVersion
|
|
619
|
+
checkIosVersion,
|
|
620
|
+
appendPreconnect
|
|
583
621
|
};
|
|
584
622
|
export default api;
|
package/package.json
CHANGED
|
@@ -1,29 +1,30 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
2
|
+
"name": "@pernod-ricard-global-cms/jsutils",
|
|
3
|
+
"version": "1.7.1",
|
|
4
|
+
"description": "Handy collection of Javascript utility functions",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "jsutils.js",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"test": "jasmine"
|
|
9
|
+
},
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/Chivas-Brothers/jsUtils.git"
|
|
13
|
+
},
|
|
14
|
+
"author": "",
|
|
15
|
+
"license": "ISC",
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/Chivas-Brothers/jsUtils/issues"
|
|
18
|
+
},
|
|
19
|
+
"homepage": "https://github.com/Chivas-Brothers/jsUtils#readme",
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"gsap": "^3.7.1",
|
|
22
|
+
"jquery": "^3.6.0",
|
|
23
|
+
"prettier": "^2.5.1",
|
|
24
|
+
"swiper": "^6.8.3"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"jasmine": "^3.9.0",
|
|
28
|
+
"jsdoc": "^3.6.7"
|
|
29
|
+
}
|
|
29
30
|
}
|