@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.
Files changed (3) hide show
  1. package/.prettierrc +19 -0
  2. package/jsutils.js +212 -183
  3. package/package.json +2 -1
package/.prettierrc ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "useTabs": true,
3
+ "overrides": [
4
+ {
5
+ "files": "*.test.js",
6
+ "options": {
7
+ "semi": true
8
+ }
9
+ },
10
+ {
11
+ "files": ["*.js"],
12
+ "options": {
13
+ "semi": true,
14
+ "singleQuote": true,
15
+ "trailingComma": "none"
16
+ }
17
+ }
18
+ ]
19
+ }
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( element ) {
10
+ export function getPosition(element) {
11
11
  const scrollElementTag = document.scrollingElement.tagName;
12
12
  let xPosition = 0;
13
13
  let yPosition = 0;
14
- while ( element ) {
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 ( scrollElementTag === 'BODY' ) {
22
- yPosition += document.querySelector( 'body' ).scrollTop;
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( input, button ) {
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' );
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
- } else {
42
- button.classList.remove( 'valid' );
43
- input.classList.remove( 'valid' );
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( assetKey ) {
57
+ export function inCriticalCssConfig(assetKey) {
58
+ if (!globalThis.criticalConfig) {
59
+ return false;
60
+ }
55
61
  if (
56
62
  globalThis.criticalConfig &&
57
- globalThis.criticalConfig.indexOf( assetKey ) === -1
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( assetKey, options = { css: true } ) {
71
- const promise = new Promise( ( resolve ) => {
72
- if ( options.css === true && ! inCriticalCssConfig( assetKey ) ) {
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/${ assetKey }.scss`
75
- ).then( () => resolve( true ) );
80
+ /* webpackChunkName: "[request]" */ `Assets/scss/components/blocks/${assetKey}.scss`
81
+ ).then(() => resolve(true));
76
82
  } else {
77
- return resolve( true );
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( 'html' );
90
- if ( ( 'ontouchstart' in globalThis )&&( (window.screen.width * window.devicePixelRatio) >= 2048 ) && (window.screen.width<window.screen.height)) {
91
- htmlElement.classList.add( 'highResTabletPortrait' );
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 ( 'ontouchstart' in globalThis ) {
94
- htmlElement.classList.add( 'touch' );
103
+ if ('ontouchstart' in globalThis) {
104
+ htmlElement.classList.add('touch');
95
105
  }
96
- if ( navigator.connection ) {
97
- htmlElement.classList.add( navigator.connection.effectiveType );
106
+ if (navigator.connection) {
107
+ htmlElement.classList.add(navigator.connection.effectiveType);
98
108
  }
99
- if ( navigator.platform ) {
109
+ if (navigator.platform) {
100
110
  let platform = navigator.platform.toLowerCase();
101
111
  let platformArray = [platform];
102
- if ( platform.search('-') ) {
112
+ if (platform.search('-')) {
103
113
  platformArray = platform.split('-');
104
114
  }
105
- if ( platform.search(' ') ) {
115
+ if (platform.search(' ')) {
106
116
  platformArray = platform.split(' ');
107
117
  }
108
- htmlElement.classList.add( ...platformArray );
118
+ htmlElement.classList.add(...platformArray);
109
119
  }
110
- if ( deviceAgent.match( /(iphone|ipod|ipad)/ ) ) {
111
- htmlElement.classList.add( 'ios' );
112
- htmlElement.classList.add( 'mobile' );
120
+ if (deviceAgent.match(/(iphone|ipod|ipad)/)) {
121
+ htmlElement.classList.add('ios');
122
+ htmlElement.classList.add('mobile');
113
123
  }
114
- if (deviceAgent.match( /(windows)/ )) {
115
- htmlElement.classList.add( 'windows' );
124
+ if (deviceAgent.match(/(windows)/)) {
125
+ htmlElement.classList.add('windows');
116
126
  }
117
- if (deviceAgent.match( /(macintosh)/ )) {
118
- htmlElement.classList.add( 'mac' );
127
+ if (deviceAgent.match(/(macintosh)/)) {
128
+ htmlElement.classList.add('mac');
119
129
  }
120
- if (deviceAgent.match( /(android)/ )) {
121
- htmlElement.classList.add( 'android' );
130
+ if (deviceAgent.match(/(android)/)) {
131
+ htmlElement.classList.add('android');
122
132
  }
123
- if ( navigator.userAgent.search( 'MSIE' ) >= 0 ) {
124
- htmlElement.classList.add( 'ie' );
125
- } else if ( navigator.userAgent.search( 'Edge' ) >= 0 ) {
126
- htmlElement.classList.add( 'edge-legacy' );
127
- } else if ( navigator.userAgent.search( 'Chrome' ) >= 0 ) {
128
- htmlElement.classList.add( 'chrome' );
129
- } else if ( navigator.userAgent.search( 'Firefox' ) >= 0 ) {
130
- htmlElement.classList.add( 'firefox' );
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( 'Safari' ) >= 0 &&
133
- navigator.userAgent.search( 'Chrome' ) < 0
142
+ navigator.userAgent.search('Safari') >= 0 &&
143
+ navigator.userAgent.search('Chrome') < 0
134
144
  ) {
135
- htmlElement.classList.add( 'safari' );
136
- } else if ( navigator.userAgent.search( 'Opera' ) >= 0 ) {
137
- htmlElement.classList.add( 'opera' );
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( img, delayedFunction ) {
152
- const loaded = new Promise( ( resolve ) => {
153
- if ( img.complete ) {
154
- if ( typeof delayedFunction === 'function' ) {
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( true );
167
+ return resolve(true);
158
168
  }
159
169
  img.addEventListener(
160
170
  'load',
161
171
  () => {
162
- if ( typeof delayedFunction === 'function' ) {
172
+ if (typeof delayedFunction === 'function') {
163
173
  delayedFunction();
164
174
  }
165
- return resolve( true );
175
+ return resolve(true);
166
176
  },
167
177
  { once: true }
168
178
  );
169
- } ).catch( ( error ) =>
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 ( ! self.createImageBitmap ) return false;
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( webpData ).then( ( r ) => r.blob() );
186
- return createImageBitmap( blob ).then(
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( entries, element ) {
202
- entries.forEach( ( entry ) => {
203
- if ( element ) {
204
- if ( entry.isIntersecting ) {
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 = `${ height }px`;
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( [ getSwiperJs(), getSwiperCss() ] ).then(
231
- ( values ) => {
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 ( ! window.jQuery ) {
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( '../../gsap/dist/gsap.min.js' ).then( ( gsapObj ) => {
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( '../../gsap/dist/ScrollTrigger.min.js' ).then(
266
- ( scrollObj ) => {
267
- const ScrollTrigger = scrollObj;
268
- return ScrollTrigger;
269
- }
270
- );
271
-
272
- const prom = Promise.all( [ gsapCore(), gsapPlugin() ] ).then(
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( userAgent ) {
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(a){if(/(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(a)||/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(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera);
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( debouncedFunction, time = 250 ) {
318
+ */
319
+ export function resizeDebouncer(debouncedFunction, time = 250) {
308
320
  let resizeTimer;
309
- window.addEventListener( 'resize', () => {
310
- clearTimeout( resizeTimer );
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( eventType, ( event ) => {
333
- clearTimeout( timer );
334
- timer = setTimeout( () => {
335
- debouncedFunction( event );
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( ( resolve ) => {
346
- if ( globalThis.YT ) {
357
+ const prom = new Promise((resolve) => {
358
+ if (globalThis.YT) {
347
359
  return resolve();
348
360
  }
349
- const tag = document.createElement( 'script' );
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( 'script' )[ 0 ];
354
- firstScriptTag.parentNode.insertBefore( tag, firstScriptTag );
365
+ const firstScriptTag = document.getElementsByTagName('script')[0];
366
+ firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
355
367
 
356
- tag.addEventListener( 'load', () => {
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( true );
373
+ return resolve(true);
362
374
  }
363
375
  }, 50);
364
376
  } else {
365
- return resolve( true );
377
+ return resolve(true);
366
378
  }
367
- } );
368
- } );
379
+ });
380
+ });
369
381
 
370
382
  return prom;
371
383
  }
372
384
 
373
- export function fallbackCopyToClipboard( text ) {
374
- const textArea = document.createElement( 'textarea' );
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( textArea );
394
+ document.body.appendChild(textArea);
383
395
  textArea.focus();
384
396
  textArea.select();
385
397
 
386
398
  try {
387
- const successful = document.execCommand( 'copy' );
399
+ const successful = document.execCommand('copy');
388
400
  const msg = successful ? 'successful' : 'unsuccessful';
389
- console.log( `Fallback: Copying text command was ${ msg }` );
390
- } catch ( err ) {
391
- console.error( 'Fallback: Oops, unable to copy', err );
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( textArea );
406
+ document.body.removeChild(textArea);
395
407
  }
396
408
 
397
-
398
409
  export function copyToClipboard() {
399
- const copyLinks = document.querySelectorAll( '.copy-to-clipboard' );
410
+ const copyLinks = document.querySelectorAll('.copy-to-clipboard');
400
411
  let timeout;
401
- copyLinks.forEach( ( link ) => {
402
- link.addEventListener( 'click', function () {
412
+ copyLinks.forEach((link) => {
413
+ link.addEventListener('click', function () {
403
414
  const copyToClipboardDone = link.nextElementSibling;
404
- if ( ! navigator.clipboard ) {
405
- fallbackCopyToClipboard( this.dataset.url );
415
+ if (!navigator.clipboard) {
416
+ fallbackCopyToClipboard(this.dataset.url);
406
417
  return;
407
418
  }
408
419
 
409
- navigator.clipboard.writeText( this.dataset.url ).then(
420
+ navigator.clipboard.writeText(this.dataset.url).then(
410
421
  function () {
411
- console.log( 'Copying to clipboard was successful!' );
422
+ console.log('Copying to clipboard was successful!');
412
423
  },
413
- function ( err ) {
414
- console.error( 'Could not copy text: ', err );
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( timeout );
426
- copyToClipboardDone.classList.remove( 'hidden' );
434
+ clearTimeout(timeout);
435
+ copyToClipboardDone.classList.remove('hidden');
427
436
 
428
- timeout = setTimeout( () => {
429
- copyToClipboardDone.classList.add( 'hidden' );
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
- const position = element.getBoundingClientRect();
443
- return ( position.top >= 0 && position.bottom <= window.innerHeight ) || ( position.top < window.innerHeight && position.bottom >= 0 );
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 = /^[-!#$%&'*+\/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])+$/;
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( email ) {
455
- return emailRegex.test( email );
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",
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": {