PluginProbe
Easy Elements for Elementor – Addons & Website Templates / 1.2.7
Easy Elements for Elementor – Addons & Website Templates v1.2.7
1.5.3 1.5.2 1.5.1 1.5.0 1.4.9 1.4.6 1.4.7 1.4.8 1.4.5 1.4.4 1.4.3 1.2.7 1.2.8 1.2.9 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 All 47 releases
easy-elements / assets / js / jarallax.js

jarallax.js in Easy Elements for Elementor – Addons & Website Templates 1.2.7, at assets/js/jarallax.js

795 lines 24.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /*!
2 * Jarallax v2.2.1 (https://github.com/nk-o/jarallax)
3 * Copyright 2024 nK <https://nkdev.info>
4 * Licensed under MIT (https://github.com/nk-o/jarallax/blob/master/LICENSE)
5 */
6
7 (function (global, factory) {
8 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
9 typeof define === 'function' && define.amd ? define(factory) :
10 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.jarallax = factory());
11 })(this, (function () { 'use strict';
12
13 /**
14 * Document ready callback.
15 * @param {Function} callback - callback will be fired once Document ready.
16 */
17 function ready(callback) {
18 if (document.readyState === 'complete' || document.readyState === 'interactive') {
19 // Already ready or interactive, execute callback
20 callback();
21 } else {
22 document.addEventListener('DOMContentLoaded', callback, {
23 capture: true,
24 once: true,
25 passive: true
26 });
27 }
28 }
29
30 /* eslint-disable import/no-mutable-exports */
31 /* eslint-disable no-restricted-globals */
32 let win;
33 if (typeof window !== 'undefined') {
34 win = window;
35 } else if (typeof global !== 'undefined') {
36 win = global;
37 } else if (typeof self !== 'undefined') {
38 win = self;
39 } else {
40 win = {};
41 }
42 var global$1 = win;
43
44 var defaults = {
45 // Base parallax options.
46 type: 'scroll',
47 speed: 0.5,
48 containerClass: 'jarallax-container',
49 imgSrc: null,
50 imgElement: '.jarallax-img',
51 imgSize: 'cover',
52 imgPosition: '50% 50%',
53 imgRepeat: 'no-repeat',
54 keepImg: false,
55 elementInViewport: null,
56 zIndex: -100,
57 disableParallax: false,
58 // Callbacks.
59 onScroll: null,
60 onInit: null,
61 onDestroy: null,
62 onCoverImage: null,
63 // Video options.
64 videoClass: 'jarallax-video',
65 videoSrc: null,
66 videoStartTime: 0,
67 videoEndTime: 0,
68 videoVolume: 0,
69 videoLoop: true,
70 videoPlayOnlyVisible: true,
71 videoLazyLoading: true,
72 disableVideo: false,
73 // Video callbacks.
74 onVideoInsert: null,
75 onVideoWorkerInit: null
76 };
77
78 /**
79 * Add styles to element.
80 *
81 * @param {Element} el - element.
82 * @param {String|Object} styles - styles list.
83 *
84 * @returns {Element}
85 */
86 function css(el, styles) {
87 if (typeof styles === 'string') {
88 return global$1.getComputedStyle(el).getPropertyValue(styles);
89 }
90 Object.keys(styles).forEach(key => {
91 el.style[key] = styles[key];
92 });
93 return el;
94 }
95
96 /**
97 * Extend like jQuery.extend
98 *
99 * @param {Object} out - output object.
100 * @param {...any} args - additional objects to extend.
101 *
102 * @returns {Object}
103 */
104 function extend(out, ...args) {
105 out = out || {};
106 Object.keys(args).forEach(i => {
107 if (!args[i]) {
108 return;
109 }
110 Object.keys(args[i]).forEach(key => {
111 out[key] = args[i][key];
112 });
113 });
114 return out;
115 }
116
117 /**
118 * Get all parents of the element.
119 *
120 * @param {Element} elem - DOM element.
121 *
122 * @returns {Array}
123 */
124 function getParents(elem) {
125 const parents = [];
126 while (elem.parentElement !== null) {
127 elem = elem.parentElement;
128 if (elem.nodeType === 1) {
129 parents.push(elem);
130 }
131 }
132 return parents;
133 }
134
135 const {
136 navigator: navigator$1
137 } = global$1;
138 const mobileAgent = /*#__PURE__*/ /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator$1.userAgent);
139 function isMobile() {
140 return mobileAgent;
141 }
142
143 let wndW;
144 let wndH;
145 let $deviceHelper;
146
147 /**
148 * The most popular mobile browsers changes height after page scroll and this generates image jumping.
149 * We can fix it using this workaround with vh units.
150 */
151 function getDeviceHeight() {
152 if (!$deviceHelper && document.body) {
153 $deviceHelper = document.createElement('div');
154 $deviceHelper.style.cssText = 'position: fixed; top: -9999px; left: 0; height: 100vh; width: 0;';
155 document.body.appendChild($deviceHelper);
156 }
157 return ($deviceHelper ? $deviceHelper.clientHeight : 0) || global$1.innerHeight || document.documentElement.clientHeight;
158 }
159 function updateWindowHeight() {
160 wndW = global$1.innerWidth || document.documentElement.clientWidth;
161 if (isMobile()) {
162 wndH = getDeviceHeight();
163 } else {
164 wndH = global$1.innerHeight || document.documentElement.clientHeight;
165 }
166 }
167 updateWindowHeight();
168 global$1.addEventListener('resize', updateWindowHeight);
169 global$1.addEventListener('orientationchange', updateWindowHeight);
170 global$1.addEventListener('load', updateWindowHeight);
171 ready(() => {
172 updateWindowHeight();
173 });
174 function getWindowSize() {
175 return {
176 width: wndW,
177 height: wndH
178 };
179 }
180
181 // List with all jarallax instances
182 // need to render all in one scroll/resize event.
183 const jarallaxList = [];
184 function updateParallax() {
185 if (!jarallaxList.length) {
186 return;
187 }
188 const {
189 width: wndW,
190 height: wndH
191 } = getWindowSize();
192 jarallaxList.forEach((data, k) => {
193 const {
194 instance,
195 oldData
196 } = data;
197 if (!instance.isVisible()) {
198 return;
199 }
200 const clientRect = instance.$item.getBoundingClientRect();
201 const newData = {
202 width: clientRect.width,
203 height: clientRect.height,
204 top: clientRect.top,
205 bottom: clientRect.bottom,
206 wndW,
207 wndH
208 };
209 const isResized = !oldData || oldData.wndW !== newData.wndW || oldData.wndH !== newData.wndH || oldData.width !== newData.width || oldData.height !== newData.height;
210 const isScrolled = isResized || !oldData || oldData.top !== newData.top || oldData.bottom !== newData.bottom;
211 jarallaxList[k].oldData = newData;
212 if (isResized) {
213 instance.onResize();
214 }
215 if (isScrolled) {
216 instance.onScroll();
217 }
218 });
219 global$1.requestAnimationFrame(updateParallax);
220 }
221 const visibilityObserver = /*#__PURE__*/new global$1.IntersectionObserver(entries => {
222 entries.forEach(entry => {
223 entry.target.jarallax.isElementInViewport = entry.isIntersecting;
224 });
225 }, {
226 // We have to start parallax calculation before the block is in view
227 // to prevent possible parallax jumping.
228 rootMargin: '50px'
229 });
230 function addObserver(instance) {
231 jarallaxList.push({
232 instance
233 });
234 if (jarallaxList.length === 1) {
235 global$1.requestAnimationFrame(updateParallax);
236 }
237 visibilityObserver.observe(instance.options.elementInViewport || instance.$item);
238 }
239 function removeObserver(instance) {
240 jarallaxList.forEach((data, key) => {
241 if (data.instance.instanceID === instance.instanceID) {
242 jarallaxList.splice(key, 1);
243 }
244 });
245 visibilityObserver.unobserve(instance.options.elementInViewport || instance.$item);
246 }
247
248 /* eslint-disable class-methods-use-this */
249 const {
250 navigator
251 } = global$1;
252 let instanceID = 0;
253
254 // Jarallax class
255 class Jarallax {
256 constructor(item, userOptions) {
257 const self = this;
258 self.instanceID = instanceID;
259 instanceID += 1;
260 self.$item = item;
261 self.defaults = {
262 ...defaults
263 };
264
265 // prepare data-options
266 const dataOptions = self.$item.dataset || {};
267 const pureDataOptions = {};
268 Object.keys(dataOptions).forEach(key => {
269 const lowerCaseOption = key.substr(0, 1).toLowerCase() + key.substr(1);
270 if (lowerCaseOption && typeof self.defaults[lowerCaseOption] !== 'undefined') {
271 pureDataOptions[lowerCaseOption] = dataOptions[key];
272 }
273 });
274 self.options = self.extend({}, self.defaults, pureDataOptions, userOptions);
275 self.pureOptions = self.extend({}, self.options);
276
277 // prepare 'true' and 'false' strings to boolean
278 Object.keys(self.options).forEach(key => {
279 if (self.options[key] === 'true') {
280 self.options[key] = true;
281 } else if (self.options[key] === 'false') {
282 self.options[key] = false;
283 }
284 });
285
286 // fix speed option [-1.0, 2.0]
287 self.options.speed = Math.min(2, Math.max(-1, parseFloat(self.options.speed)));
288
289 // prepare disableParallax callback
290 if (typeof self.options.disableParallax === 'string') {
291 self.options.disableParallax = new RegExp(self.options.disableParallax);
292 }
293 if (self.options.disableParallax instanceof RegExp) {
294 const disableParallaxRegexp = self.options.disableParallax;
295 self.options.disableParallax = () => disableParallaxRegexp.test(navigator.userAgent);
296 }
297 if (typeof self.options.disableParallax !== 'function') {
298 // Support for `true` option value.
299 const disableParallaxDefault = self.options.disableParallax;
300 self.options.disableParallax = () => disableParallaxDefault === true;
301 }
302
303 // prepare disableVideo callback
304 if (typeof self.options.disableVideo === 'string') {
305 self.options.disableVideo = new RegExp(self.options.disableVideo);
306 }
307 if (self.options.disableVideo instanceof RegExp) {
308 const disableVideoRegexp = self.options.disableVideo;
309 self.options.disableVideo = () => disableVideoRegexp.test(navigator.userAgent);
310 }
311 if (typeof self.options.disableVideo !== 'function') {
312 // Support for `true` option value.
313 const disableVideoDefault = self.options.disableVideo;
314 self.options.disableVideo = () => disableVideoDefault === true;
315 }
316
317 // custom element to check if parallax in viewport
318 let elementInVP = self.options.elementInViewport;
319 // get first item from array
320 if (elementInVP && typeof elementInVP === 'object' && typeof elementInVP.length !== 'undefined') {
321 [elementInVP] = elementInVP;
322 }
323 // check if dom element
324 if (!(elementInVP instanceof Element)) {
325 elementInVP = null;
326 }
327 self.options.elementInViewport = elementInVP;
328 self.image = {
329 src: self.options.imgSrc || null,
330 $container: null,
331 useImgTag: false,
332 // 1. Position fixed is needed for the most of browsers because absolute position have glitches
333 // 2. On MacOS with smooth scroll there is a huge lags with absolute position - https://github.com/nk-o/jarallax/issues/75
334 // 3. Previously used 'absolute' for mobile devices. But we re-tested on iPhone 12 and 'fixed' position is working better, then 'absolute', so for now position is always 'fixed'
335 position: 'fixed'
336 };
337 if (self.initImg() && self.canInitParallax()) {
338 self.init();
339 }
340 }
341 css(el, styles) {
342 return css(el, styles);
343 }
344 extend(out, ...args) {
345 return extend(out, ...args);
346 }
347
348 // get window size and scroll position. Useful for extensions
349 getWindowData() {
350 const {
351 width,
352 height
353 } = getWindowSize();
354 return {
355 width,
356 height,
357 y: document.documentElement.scrollTop
358 };
359 }
360
361 // Jarallax functions
362 initImg() {
363 const self = this;
364
365 // find image element
366 let $imgElement = self.options.imgElement;
367 if ($imgElement && typeof $imgElement === 'string') {
368 $imgElement = self.$item.querySelector($imgElement);
369 }
370
371 // check if dom element
372 if (!($imgElement instanceof Element)) {
373 if (self.options.imgSrc) {
374 $imgElement = new Image();
375 $imgElement.src = self.options.imgSrc;
376 } else {
377 $imgElement = null;
378 }
379 }
380 if ($imgElement) {
381 if (self.options.keepImg) {
382 self.image.$item = $imgElement.cloneNode(true);
383 } else {
384 self.image.$item = $imgElement;
385 self.image.$itemParent = $imgElement.parentNode;
386 }
387 self.image.useImgTag = true;
388 }
389
390 // true if there is img tag
391 if (self.image.$item) {
392 return true;
393 }
394
395 // get image src
396 if (self.image.src === null) {
397 self.image.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';
398 self.image.bgImage = self.css(self.$item, 'background-image');
399 }
400 return !(!self.image.bgImage || self.image.bgImage === 'none');
401 }
402 canInitParallax() {
403 return !this.options.disableParallax();
404 }
405 init() {
406 const self = this;
407 const containerStyles = {
408 position: 'absolute',
409 top: 0,
410 left: 0,
411 width: '100%',
412 height: '100%',
413 overflow: 'hidden'
414 };
415 let imageStyles = {
416 pointerEvents: 'none',
417 transformStyle: 'preserve-3d',
418 backfaceVisibility: 'hidden'
419 };
420 if (!self.options.keepImg) {
421 // save default user styles
422 const curStyle = self.$item.getAttribute('style');
423 if (curStyle) {
424 self.$item.setAttribute('data-jarallax-original-styles', curStyle);
425 }
426 if (self.image.useImgTag) {
427 const curImgStyle = self.image.$item.getAttribute('style');
428 if (curImgStyle) {
429 self.image.$item.setAttribute('data-jarallax-original-styles', curImgStyle);
430 }
431 }
432 }
433
434 // set relative position and z-index to the parent
435 if (self.css(self.$item, 'position') === 'static') {
436 self.css(self.$item, {
437 position: 'relative'
438 });
439 }
440 if (self.css(self.$item, 'z-index') === 'auto') {
441 self.css(self.$item, {
442 zIndex: 0
443 });
444 }
445
446 // container for parallax image
447 self.image.$container = document.createElement('div');
448 self.css(self.image.$container, containerStyles);
449 self.css(self.image.$container, {
450 'z-index': self.options.zIndex
451 });
452
453 // it will remove some image overlapping
454 // overlapping occur due to an image position fixed inside absolute position element
455 // needed only when background in fixed position
456 if (this.image.position === 'fixed') {
457 self.css(self.image.$container, {
458 '-webkit-clip-path': 'polygon(0 0, 100% 0, 100% 100%, 0 100%)',
459 'clip-path': 'polygon(0 0, 100% 0, 100% 100%, 0 100%)'
460 });
461 }
462
463 // Add container unique ID.
464 self.image.$container.setAttribute('id', `jarallax-container-${self.instanceID}`);
465
466 // Add container class.
467 if (self.options.containerClass) {
468 self.image.$container.setAttribute('class', self.options.containerClass);
469 }
470 self.$item.appendChild(self.image.$container);
471
472 // use img tag
473 if (self.image.useImgTag) {
474 imageStyles = self.extend({
475 'object-fit': self.options.imgSize,
476 'object-position': self.options.imgPosition,
477 'max-width': 'none'
478 }, containerStyles, imageStyles);
479
480 // use div with background image
481 } else {
482 self.image.$item = document.createElement('div');
483 if (self.image.src) {
484 imageStyles = self.extend({
485 'background-position': self.options.imgPosition,
486 'background-size': self.options.imgSize,
487 'background-repeat': self.options.imgRepeat,
488 'background-image': self.image.bgImage || `url("${self.image.src}")`
489 }, containerStyles, imageStyles);
490 }
491 }
492 if (self.options.type === 'opacity' || self.options.type === 'scale' || self.options.type === 'scale-opacity' || self.options.speed === 1) {
493 self.image.position = 'absolute';
494 }
495
496 // 1. Check if one of parents have transform style (without this check, scroll transform will be inverted if used parallax with position fixed)
497 // discussion - https://github.com/nk-o/jarallax/issues/9
498 // 2. Check if parents have overflow scroll
499 if (self.image.position === 'fixed') {
500 const $parents = getParents(self.$item).filter(el => {
501 const styles = global$1.getComputedStyle(el);
502 const parentTransform = styles['-webkit-transform'] || styles['-moz-transform'] || styles.transform;
503 const overflowRegex = /(auto|scroll)/;
504 return parentTransform && parentTransform !== 'none' || overflowRegex.test(styles.overflow + styles['overflow-y'] + styles['overflow-x']);
505 });
506 self.image.position = $parents.length ? 'absolute' : 'fixed';
507 }
508
509 // add position to parallax block
510 imageStyles.position = self.image.position;
511
512 // insert parallax image
513 self.css(self.image.$item, imageStyles);
514 self.image.$container.appendChild(self.image.$item);
515
516 // set initial position and size
517 self.onResize();
518 self.onScroll(true);
519
520 // call onInit event
521 if (self.options.onInit) {
522 self.options.onInit.call(self);
523 }
524
525 // remove default user background
526 if (self.css(self.$item, 'background-image') !== 'none') {
527 self.css(self.$item, {
528 'background-image': 'none'
529 });
530 }
531 addObserver(self);
532 }
533 destroy() {
534 const self = this;
535 removeObserver(self);
536
537 // return styles on container as before jarallax init
538 const originalStylesTag = self.$item.getAttribute('data-jarallax-original-styles');
539 self.$item.removeAttribute('data-jarallax-original-styles');
540 // null occurs if there is no style tag before jarallax init
541 if (!originalStylesTag) {
542 self.$item.removeAttribute('style');
543 } else {
544 self.$item.setAttribute('style', originalStylesTag);
545 }
546 if (self.image.useImgTag) {
547 // return styles on img tag as before jarallax init
548 const originalStylesImgTag = self.image.$item.getAttribute('data-jarallax-original-styles');
549 self.image.$item.removeAttribute('data-jarallax-original-styles');
550 // null occurs if there is no style tag before jarallax init
551 if (!originalStylesImgTag) {
552 self.image.$item.removeAttribute('style');
553 } else {
554 self.image.$item.setAttribute('style', originalStylesTag);
555 }
556
557 // move img tag to its default position
558 if (self.image.$itemParent) {
559 self.image.$itemParent.appendChild(self.image.$item);
560 }
561 }
562
563 // remove additional dom elements
564 if (self.image.$container) {
565 self.image.$container.parentNode.removeChild(self.image.$container);
566 }
567
568 // call onDestroy event
569 if (self.options.onDestroy) {
570 self.options.onDestroy.call(self);
571 }
572
573 // delete jarallax from item
574 delete self.$item.jarallax;
575 }
576 coverImage() {
577 const self = this;
578 const {
579 height: wndH
580 } = getWindowSize();
581 const rect = self.image.$container.getBoundingClientRect();
582 const contH = rect.height;
583 const {
584 speed
585 } = self.options;
586 const isScroll = self.options.type === 'scroll' || self.options.type === 'scroll-opacity';
587 let scrollDist = 0;
588 let resultH = contH;
589 let resultMT = 0;
590
591 // scroll parallax
592 if (isScroll) {
593 // scroll distance and height for image
594 if (speed < 0) {
595 scrollDist = speed * Math.max(contH, wndH);
596 if (wndH < contH) {
597 scrollDist -= speed * (contH - wndH);
598 }
599 } else {
600 scrollDist = speed * (contH + wndH);
601 }
602
603 // size for scroll parallax
604 if (speed > 1) {
605 resultH = Math.abs(scrollDist - wndH);
606 } else if (speed < 0) {
607 resultH = scrollDist / speed + Math.abs(scrollDist);
608 } else {
609 resultH += (wndH - contH) * (1 - speed);
610 }
611 scrollDist /= 2;
612 }
613
614 // store scroll distance
615 self.parallaxScrollDistance = scrollDist;
616
617 // vertical center
618 if (isScroll) {
619 resultMT = (wndH - resultH) / 2;
620 } else {
621 resultMT = (contH - resultH) / 2;
622 }
623
624 // apply result to item
625 self.css(self.image.$item, {
626 height: `${resultH}px`,
627 marginTop: `${resultMT}px`,
628 left: self.image.position === 'fixed' ? `${rect.left}px` : '0',
629 width: `${rect.width}px`
630 });
631
632 // call onCoverImage event
633 if (self.options.onCoverImage) {
634 self.options.onCoverImage.call(self);
635 }
636
637 // return some useful data. Used in the video cover function
638 return {
639 image: {
640 height: resultH,
641 marginTop: resultMT
642 },
643 container: rect
644 };
645 }
646 isVisible() {
647 return this.isElementInViewport || false;
648 }
649 onScroll(force) {
650 const self = this;
651
652 // stop calculations if item is not in viewport
653 if (!force && !self.isVisible()) {
654 return;
655 }
656 const {
657 height: wndH
658 } = getWindowSize();
659 const rect = self.$item.getBoundingClientRect();
660 const contT = rect.top;
661 const contH = rect.height;
662 const styles = {};
663
664 // calculate parallax helping variables
665 const beforeTop = Math.max(0, contT);
666 const beforeTopEnd = Math.max(0, contH + contT);
667 const afterTop = Math.max(0, -contT);
668 const beforeBottom = Math.max(0, contT + contH - wndH);
669 const beforeBottomEnd = Math.max(0, contH - (contT + contH - wndH));
670 const afterBottom = Math.max(0, -contT + wndH - contH);
671 const fromViewportCenter = 1 - 2 * ((wndH - contT) / (wndH + contH));
672
673 // calculate on how percent of section is visible
674 let visiblePercent = 1;
675 if (contH < wndH) {
676 visiblePercent = 1 - (afterTop || beforeBottom) / contH;
677 } else if (beforeTopEnd <= wndH) {
678 visiblePercent = beforeTopEnd / wndH;
679 } else if (beforeBottomEnd <= wndH) {
680 visiblePercent = beforeBottomEnd / wndH;
681 }
682
683 // opacity
684 if (self.options.type === 'opacity' || self.options.type === 'scale-opacity' || self.options.type === 'scroll-opacity') {
685 styles.transform = 'translate3d(0,0,0)';
686 styles.opacity = visiblePercent;
687 }
688
689 // scale
690 if (self.options.type === 'scale' || self.options.type === 'scale-opacity') {
691 let scale = 1;
692 if (self.options.speed < 0) {
693 scale -= self.options.speed * visiblePercent;
694 } else {
695 scale += self.options.speed * (1 - visiblePercent);
696 }
697 styles.transform = `scale(${scale}) translate3d(0,0,0)`;
698 }
699
700 // scroll
701 if (self.options.type === 'scroll' || self.options.type === 'scroll-opacity') {
702 let positionY = self.parallaxScrollDistance * fromViewportCenter;
703
704 // fix if parallax block in absolute position
705 if (self.image.position === 'absolute') {
706 positionY -= contT;
707 }
708 styles.transform = `translate3d(0,${positionY}px,0)`;
709 }
710 self.css(self.image.$item, styles);
711
712 // call onScroll event
713 if (self.options.onScroll) {
714 self.options.onScroll.call(self, {
715 section: rect,
716 beforeTop,
717 beforeTopEnd,
718 afterTop,
719 beforeBottom,
720 beforeBottomEnd,
721 afterBottom,
722 visiblePercent,
723 fromViewportCenter
724 });
725 }
726 }
727 onResize() {
728 this.coverImage();
729 }
730 }
731
732 // global definition
733 const jarallax = function (items, options, ...args) {
734 // check for dom element
735 // thanks: http://stackoverflow.com/questions/384286/javascript-isdom-how-do-you-check-if-a-javascript-object-is-a-dom-object
736 if (typeof HTMLElement === 'object' ? items instanceof HTMLElement : items && typeof items === 'object' && items !== null && items.nodeType === 1 && typeof items.nodeName === 'string') {
737 items = [items];
738 }
739 const len = items.length;
740 let k = 0;
741 let ret;
742 for (k; k < len; k += 1) {
743 if (typeof options === 'object' || typeof options === 'undefined') {
744 if (!items[k].jarallax) {
745 items[k].jarallax = new Jarallax(items[k], options);
746 }
747 } else if (items[k].jarallax) {
748 // eslint-disable-next-line prefer-spread
749 ret = items[k].jarallax[options].apply(items[k].jarallax, args);
750 }
751 if (typeof ret !== 'undefined') {
752 return ret;
753 }
754 }
755 return items;
756 };
757 jarallax.constructor = Jarallax;
758
759 const $ = global$1.jQuery;
760
761 // jQuery support
762 if (typeof $ !== 'undefined') {
763 const $Plugin = function (...args) {
764 Array.prototype.unshift.call(args, this);
765 const res = jarallax.apply(global$1, args);
766 return typeof res !== 'object' ? res : this;
767 };
768 $Plugin.constructor = jarallax.constructor;
769
770 // no conflict
771 const old$Plugin = $.fn.jarallax;
772 $.fn.jarallax = $Plugin;
773 $.fn.jarallax.noConflict = function () {
774 $.fn.jarallax = old$Plugin;
775 return this;
776 };
777 }
778
779 // data-jarallax initialization
780 ready(() => {
781 jarallax(document.querySelectorAll('[data-jarallax]'));
782 });
783
784 return jarallax;
785
786 }));
787
788 (function($) {
789 'use strict';
790 $('.has-jarallax-img > .elementor-widget-container img').wrap('<div class="jarallax jarallax-container"></div>');
791 $('.has-jarallax-img > img').wrap('<div class="jarallax jarallax-container"></div>');
792 $('.has-jarallax-img > .elementor-widget-container img').addClass('jarallax-img');
793 $('.has-jarallax-img .jarallax-container img').addClass('jarallax-img');
794 $(".jarallax").jarallax();
795 })(jQuery);