PageSourceSearch

https://swicos.com.my/wp-content/themes/rayo/js/elementor.js?ver=20250922

js swicos.com.my collected 2026-10-06 13:15:35 UTC 19,991 bytes, 618 lines download raw bytes

1( function( $ ) {
2    'use strict';
3
4    /* rtl check */
5	function rtl_owl(){
6	if ($('body').hasClass("rtl")) {
7		return true;
8	} else {
9		return false;
10	}};
11
12	/* Swiper init */
13	function OTInitSwiper(swiperContainer, config) {
14        if ( 
15            window.elementorFrontend
16            && window.elementorFrontend.utils
17            && window.elementorFrontend.utils.swiper 
18        ) {
19            const asyncSwiper = window.elementorFrontend.utils.swiper;
20            new asyncSwiper( swiperContainer, config ).then( ( newSwiperInstance ) => {
21                var mySwiper = newSwiperInstance;
22            });
23        } else if ('undefined' !== typeof Swiper) {
24            var mySwiper = new Swiper( swiperContainer[0], config );
25        }
26    }
27
28	/* Button Common Animation Start */
29	function initBtnAnim($scope) {
30	    let elements = $scope[0].querySelectorAll(".rayo-btn-anim .rayo-btn-caption");
31	    elements.forEach((element) => {
32		    if (element.classList.contains('btn-anim--processed')) return;
33		    element.classList.add('btn-anim--processed');
34
35		    let innerText = element.innerText;
36		    element.innerHTML = "";
37		    let textContainer = document.createElement("div");
38		    textContainer.classList.add("btn-anim__block");
39		    for (let letter of innerText) {
40		        let span = document.createElement("span");
41		        span.innerText = letter.trim() === "" ? "\xa0" : letter;
42		        span.classList.add("btn-anim__letter");
43		        textContainer.appendChild(span);
44		   	}
45		    element.appendChild(textContainer);
46		    element.appendChild(textContainer.cloneNode(true));
47
48		    element.addEventListener("mouseover", () => {
49		        element.classList.remove("play");
50		    });
51	    });
52	}
53	/* Button Common Animation End */
54
55	/* Video Popup Start */
56	const initShowreelPopup = function ($scope) {
57	    const $trigger = $scope.find("#showreel-trigger");
58
59	    if (!$trigger.length) return;
60
61	    $trigger.magnificPopup({
62	      	type: "iframe",
63	      	mainClass: "mfp-fade",
64	      	removalDelay: 160,
65	      	preloader: false,
66	      	fixedContentPos: false,
67	      	callbacks: {
68	        	beforeOpen: function () {
69	          		$("body").addClass("overflow-hidden");
70	          		if (typeof lenis !== "undefined") {
71	            		lenis.stop();
72	          		}
73	        	},
74	        	close: function () {
75	          		$("body").removeClass("overflow-hidden");
76	         		if (typeof lenis !== "undefined") {
77	           			lenis.start();
78	          		}
79	        	},
80	      	},
81	    });
82	};
83	/* Video Popup End */
84
85	/* Button Rotating Start */
86	function initButtonRotating($scope) {
87    
88	    const wrapper = $scope.find(".rayo-btn-rotating");
89
90	    if (!wrapper.length) return;
91
92	    const section = wrapper.find(".animate-rotation")[0];
93	    if (!section) return;
94
95	    const value = $(section).data("value");
96
97	    gsap.fromTo(
98	      	section,
99	      	{
100	        	ease: "sine",
101	        	rotate: 0,
102	      	},
103	      	{
104	        	rotate: value,
105	        	scrollTrigger: {
106	          		trigger: section,
107	          		scrub: true,
108	          		toggleActions: "play none none reverse",
109	        	},
110	      	}
111	    );
112	}
113
114	/* Button Rotating End */
115
116	/* Marquee Start */
117	const initMarquee = function ($scope) {
118	    const $marquees = $scope.find(".marquee");
119
120	    $marquees.each(function () {
121	      	const $marquee = $(this);
122	      	const direction = $marquee.data("direction") || "right";
123
124	      	/*select the correct track*/
125	     	const track =
126	        direction === "left"
127	          	? $marquee.find(".marquee__toleft")[0]
128	          	: $marquee.find(".marquee__toright")[0];
129
130	      	if (!track) return;
131
132	      	/*prevent repeated processing*/
133	      	if (track.classList.contains("marquee--processed")) return;
134	      	track.classList.add("marquee--processed");
135
136	      	/*duplicate the content*/
137	      	track.innerHTML += track.innerHTML;
138
139	      	/*determine the direction*/
140	      	const dir = direction === "left" ? "-=50%" : "+=50%";
141
142	      	/*create a timeline for the marquee animation*/
143	      	let master = gsap.timeline().add(
144	        	gsap.to(track, {
145	          		duration: 30,
146	          		ease: "none",
147	          		x: dir,
148	          		modifiers: {
149	            		x: (x) => (x = gsap.utils.wrap(0, 50)(parseFloat(x)) + "%"),
150	          		},
151	          		repeat: -1,
152	        	}),
153	        	0
154	      	);
155
156	      	/*use tween to increase scroll speed*/
157	      	let tween = gsap.to(master, { duration: 1.5, timeScale: 1, paused: true });
158	      	let timeScaleClamp = gsap.utils.clamp(1, 6);
159
160	      	ScrollTrigger.create({
161	        	trigger: $marquee[0],
162	        	start: "top bottom",
163	        	end: "bottom top",
164	        	onUpdate: (self) => {
165	          		master.timeScale(
166	            		timeScaleClamp(Math.abs(self.getVelocity() / 200))
167	          		);
168	          		tween.invalidate().restart();
169	        	},
170	      	});
171	    });
172	};
173	/* Marquee End */
174
175	/* Counter Start */
176	const initCounter = function ($scope) {
177	    $scope.find(".mxd-stats-number").each(function () {
178	      	const el = $(this);
179	      	const endVal = parseInt(el.data("to"), 10) || 0;
180	      	const suffix = el.data("suffix") || "";
181	      	const duration = parseFloat(el.data("duration")) || 2;
182
183	      	const counter = new countUp.CountUp(this, endVal, {
184	        	suffix: suffix,
185	        	duration: duration,
186	        	enableScrollSpy: true
187	      	});
188
189	      	if (!counter.error) {
190	        	counter.start();
191	      	} else {
192	        	console.error(counter.error);
193	      	}
194	    });
195	};
196	/* Counter End */
197
198	/* Accordions Start */
199	const initAccordion = function($scope, $) {
200
201	    const $accordion = $scope.find(".mxd-accordion");
202	    const $titles = $accordion.find(".mxd-accordion__title");
203	    const $contents = $accordion.find(".mxd-accordion__content");
204	    const $arrows = $accordion.find(".mxd-accordion__arrow");
205
206	    /*reset all to closed state*/
207	    $contents.hide();
208	    $titles.removeClass("accordion-active");
209	    $arrows.removeClass("accordion-rotate");
210
211	    /*activate default item if available*/
212	    const $defaultTitle = $titles.filter('[data-default="yes"]');
213	    if ($defaultTitle.length) {
214	      	$defaultTitle.addClass("accordion-active");
215	      	$defaultTitle.next(".mxd-accordion__content").show();
216	      	$(".mxd-accordion__arrow", $defaultTitle).addClass("accordion-rotate");
217	    }
218
219	    /*Click event*/
220	    $titles.off("click").on("click", function(e) {
221	      	e.preventDefault();
222	      	var $this = $(this);
223
224	      	if (!$this.hasClass("accordion-active")) {
225	        	/*Close all*/
226	        	$contents.stop(true,true).slideUp(400);
227	        	$titles.removeClass("accordion-active");
228	        	$arrows.removeClass("accordion-rotate");
229	      	}
230
231	      	/*toggle current item*/
232	      	$this.toggleClass("accordion-active");
233	      	$this.next(".mxd-accordion__content").stop(true,true).slideToggle();
234	      	$(".mxd-accordion__arrow", this).toggleClass("accordion-rotate");
235	    });
236	};
237	/* Accordions End */
238
239	/* Testimonials Slider Start */
240
241	const initTestimonialsSlider = function($scope) {
242		const parent = $scope.find(".testimonials-slider");
243
244		let sliderSettings = {};
245		try {
246		    sliderSettings = JSON.parse(parent.attr("data-slider_options") || "{}");
247		 }catch (e) {
248		    console.error("Invalid JSON in data-slider_options", e);
249		}
250
251	    const slider = parent.find(".swiper-testimonials")[0];
252	    if (!slider || slider.classList.contains("swiper-initialized")) return;
253
254	    const uniqueId = slider.getAttribute("data-id");
255		const pagination = parent.find(`.swiper-pagination[data-id="${uniqueId}"]`)[0];
256		const nextBtn = parent.find(`.swiper-button-next[data-id="${uniqueId}"]`)[0];
257		const prevBtn = parent.find(`.swiper-button-prev[data-id="${uniqueId}"]`)[0];
258		
259        /*init Swiper*/
260        new Swiper(slider, {
261          	slidesPerView: 1,
262          	slidesPerGroup: 1,
263          	grabCursor: true,
264          	effect: 'yes' === sliderSettings.fade ? 'fade' : 'slide',
265          	spaceBetween: 30,
266          	autoplay: 'yes' === sliderSettings.autoplay ? {
267		      	delay: sliderSettings.autoplay_time_out || 3000,
268		      	disableOnInteraction: false
269		    } : false,
270          	speed: 1000,
271          	loop: 'yes' === sliderSettings.loop,
272          	parallax: true,
273			loopFillGroupWithBlank: true,
274          	pagination: {
275            	el: pagination,
276            	type: "fraction",
277          	},
278          	navigation: {
279            	nextEl: nextBtn,
280            	prevEl: prevBtn,
281          	},
282          	breakpoints: {
283          		0 : {
284          			slidesPerView: sliderSettings.slides_show_mobile !== 'auto' ? parseInt(sliderSettings.slides_show_mobile) : 'auto',
285                    spaceBetween: parseInt(sliderSettings.margin_mobile),
286                },
287                576: {
288                	slidesPerView: sliderSettings.slides_show_mobile_extra !== 'auto' ? parseInt(sliderSettings.slides_show_mobile_extra) : 'auto',
289                    spaceBetween: parseInt(sliderSettings.margin_mobile_extra),
290                },
291                768: {
292                	slidesPerView: sliderSettings.slides_show_tablet !== 'auto' ? parseInt(sliderSettings.slides_show_tablet) : 'auto',
293                    spaceBetween: parseInt(sliderSettings.margin_tablet),
294                },
295                992: {
296                	slidesPerView: sliderSettings.slides_show_tablet_extra !== 'auto' ? parseInt(sliderSettings.slides_show_tablet_extra) : 'auto',
297                    spaceBetween: parseInt(sliderSettings.margin_tablet_extra),
298                },
299                1200: {
300                	slidesPerView: sliderSettings.slides_show_laptop !== 'auto' ? parseInt(sliderSettings.slides_show_laptop) : 'auto',
301                    spaceBetween: parseInt(sliderSettings.margin_laptop),
302                },
303                1400: {
304                    slidesPerView: sliderSettings.slides_show_desktop !== 'auto' ? parseInt(sliderSettings.slides_show_desktop) : 'auto',
305                    spaceBetween: parseInt(sliderSettings.margin_desktop),
306                },
307            }
308        });
309		    
310	    
311	};
312    /* Testimonials Slider End */
313
314	/* Animation - Images Reveal on Hover Start */
315    function initHoverReveal($scope) {
316	    /*find container in the current widget*/
317	    const container = $scope.find(".hover-reveal");
318	    if (!container.length) return;
319
320	    /*find all items in the container*/
321	    const items = container.find(".hover-reveal__item");
322
323	    items.each(function () {
324	      	const $item = $(this);
325	      	const content = $item.find(".hover-reveal__content")[0];
326	      	const image = $item.find(".hover-reveal__image")[0];
327
328	      	/* exit if content or image is missing */
329	      	if (!content || !image) return;
330
331	      	/*Mouse move*/
332	      	$item.on("mousemove", function (e) {
333	        	content.style.opacity = 1;
334	        	content.style.transform = "translate(-80%, -50%)";
335	        	image.style.transform = "scale(1, 1)";
336	        	content.style.left = e.clientX + "px";
337	      	});
338
339	      	/*Mouse leave*/
340	      	$item.on("mouseleave", function () {
341	        	content.style.opacity = 0;
342	        	content.style.transform = "translate(-80%, -50%)";
343	        	image.style.transform = "scale(1, 1.4)";
344	      	});
345	    });
346	}
347	/* Animation - Images Reveal on Hover End */
348
349	/* Animation - Stacking List Start */
350	const initStackedList = function($scope) {
351	    const $wrapper = $scope.find('.stack-wrapper');
352	    if (!$wrapper.length) return;
353
354	    const cards = $scope.find('.stack-item');
355	    const stickySpace = $scope.find('.stack-offset')[0];
356
357	   	/*exit if there is no .stack-item or .stack-offset*/
358	    if (!cards.length || !stickySpace) return;
359
360	    const animation = gsap.timeline();
361	    let cardHeight;
362
363	    function initCards() {
364	      	animation.clear();
365	      	cardHeight = cards[0].offsetHeight;
366
367	      	cards.each(function(index, card) {
368	        	if (index > 0) {
369		          	gsap.set(card, { y: index * cardHeight });
370		          	animation.to(card, { 
371		            	y: 0, 
372		            	duration: index * 0.5, 
373		            	ease: "none" 
374		          	}, 0);
375	        	}
376	      	});
377	    }
378
379	    initCards();
380
381	    ScrollTrigger.create({
382	      	trigger: $wrapper[0],
383	      	start: "top top",
384	      	pin: true,
385	      	end: () => `+=${(cards.length * cardHeight) + stickySpace.offsetHeight}`,
386	      	scrub: true,
387	      	animation: animation,
388	      	invalidateOnRefresh: true
389	    });
390
391	    ScrollTrigger.addEventListener("refreshInit", initCards);
392	};
393	/* Animation - Stacking List End */
394
395	/* Animation - Pinned Image List Start */
396	const initPinnedSection = function($scope) {
397	    const $pinned = $scope.find('.mxd-pinned');
398	    if (!$pinned.length) return;
399
400	    $pinned.each(function() {
401	      	const $this = $(this);
402	      	const $childTriggers = $this.find('.mxd-pinned__text-item');
403	      	const $childTargets = $this.find('.mxd-pinned__img-item');
404
405	      	/*exit if there is no text/image*/
406	      	if (!$childTriggers.length || !$childTargets.length) return;
407
408	      	function makeItemActive(index) {
409	        	$childTriggers.removeClass('is-active');
410	        	$childTargets.removeClass('is-active');
411	        	$childTriggers.eq(index).addClass('is-active');
412	        	$childTargets.eq(index).addClass('is-active');
413	      	}
414
415	      	/*activate the first element*/
416	      	makeItemActive(0);
417
418	      	/*create a ScrollTrigger for each text-item*/
419	      	$childTriggers.each(function(index, el) {
420	        	ScrollTrigger.create({
421	          		trigger: el,
422	          		start: "top center",
423	          		end: "bottom center",
424	          		onToggle: (self) => {
425	            		if (self.isActive) {
426	              			makeItemActive(index);
427	            		}
428	          		}
429	        	});
430	      	});
431	    });
432	   
433	};
434	/* Animation - Pinned Image List End */
435
436	/* Animation - Text Typed Start */
437	const initAnimatedTyped = function ($scope) {
438	    /*find element in the current widget*/
439	    const animatedHeadline = $scope.find(".animated-type");
440
441	    /*exit if not found*/
442	    if (!animatedHeadline.length) return;
443
444	    /*find child elements*/
445	    const typedElement = animatedHeadline.find("#typed");
446	    const stringsElement = animatedHeadline.find("#typed-strings");
447
448	    /*check existence*/
449	    if (!typedElement.length || !stringsElement.length) return;
450
451	    /*init Typed.js instance for typing animation*/
452	    new Typed(typedElement[0], {
453	      	stringsElement: stringsElement[0],
454	      	showCursor: true,
455	      	cursorChar: "_",
456	      	loop: true,
457	      	typeSpeed: 70,
458	      	backSpeed: 30,
459	      	backDelay: 2500
460	    });
461	};
462	/* Animation - Text Typed End */
463
464	/* Animation - Text Reveal Start */
465	const initRevealType = ($scope) => {
466	    const splitTypes = $scope.find(".reveal-type");
467	    if (!splitTypes.length) return;
468
469	    splitTypes.each(function () {
470	      	const char = this;
471	      	const text = new SplitType(char, { types: "words, chars" });
472
473	      	gsap.from(text.chars, {
474	        	scrollTrigger: {
475	          		trigger: char,
476	          		start: "top 80%",
477	          		end: "top 20%",
478	          		scrub: true,
479	          		markers: false,
480	        	},
481	        	opacity: 0.2,
482	        	stagger: 0.1,
483	      	});
484	    });
485  	};
486
487	/* Animation - Text Reveal End */
488
489	$(window).on('load', function () {
490        initMarquee($(document));
491    });
492
493    /**
494     * Elementor JS Hooks
495     */
496    $(window).on("elementor/frontend/init", function () {
497    	/* Button */
498        elementorFrontend.hooks.addAction(
499            "frontend/element_ready/rayo-button.default",
500            function ($scope) {
501			    initBtnAnim($scope);
502			    initShowreelPopup($scope);
503			}
504        );
505        /* Button */
506        elementorFrontend.hooks.addAction(
507            "frontend/element_ready/rayo-button-rotating.default",
508            function ($scope) {
509			    initButtonRotating($scope);
510			    initShowreelPopup($scope);
511			}
512        );
513
514        /* Marquee 1 */
515        elementorFrontend.hooks.addAction(
516            "frontend/element_ready/rayo-marquee_1.default",
517            initMarquee
518        );
519        elementorFrontend.hooks.addAction(
520            "frontend/element_ready/rayo-marquee_2.default",
521            function ($scope) {
522			    initMarquee($scope);
523			    initBtnAnim($scope);
524			}
525            
526        );
527        elementorFrontend.hooks.addAction(
528            "frontend/element_ready/rayo-marquee_3.default",
529            initMarquee
530        );
531        elementorFrontend.hooks.addAction(
532            "frontend/element_ready/rayo-icon-box-marquee.default",
533            initMarquee
534        );
535        /* Counter */
536        elementorFrontend.hooks.addAction(
537            "frontend/element_ready/rayo-counter.default",
538            initCounter
539        );
540        /* Accordions */
541        elementorFrontend.hooks.addAction(
542            "frontend/element_ready/rayo-accordions.default",
543            initAccordion
544        );
545		/* Testimonial */
546        elementorFrontend.hooks.addAction(
547            "frontend/element_ready/rayo-testimonials-slider.default",
548            function ($scope) {
549			    initTestimonialsSlider($scope);
550			    initBtnAnim($scope);
551			}
552        );
553        elementorFrontend.hooks.addAction(
554            "frontend/element_ready/rayo-testimonials-slider-2.default",
555            function ($scope) {
556			    initTestimonialsSlider($scope);
557			    initBtnAnim($scope);
558			}
559        );
560        /* Hover Reveal */
561        elementorFrontend.hooks.addAction(
562            "frontend/element_ready/rayo-awards-list.default",
563            initHoverReveal
564        );
565        elementorFrontend.hooks.addAction(
566            "frontend/element_ready/rayo-capabilities-list.default",
567            initHoverReveal
568        );
569        elementorFrontend.hooks.addAction(
570            "frontend/element_ready/rayo-services-list.default",
571            initHoverReveal
572        );
573        elementorFrontend.hooks.addAction(
574            "frontend/element_ready/rayo-projects-list.default",
575            initHoverReveal
576        );
577        /* Statistics */
578        elementorFrontend.hooks.addAction(
579            "frontend/element_ready/rayo-statistics-grid.default",
580            initCounter
581        );
582        /* Stacking List */
583        elementorFrontend.hooks.addAction(
584            "frontend/element_ready/rayo-stacked-list.default",
585            initStackedList
586        );
587        /* Pinned Image List */
588        elementorFrontend.hooks.addAction(
589            "frontend/element_ready/rayo-pinned-image-list.default",
590            initPinnedSection
591        );
592        /* Text Typed */
593        elementorFrontend.hooks.addAction(
594            "frontend/element_ready/rayo-text-typed.default",
595            initAnimatedTyped
596        );
597        /* Text Reveal */
598        elementorFrontend.hooks.addAction(
599            "frontend/element_ready/rayo-heading.default",
600            initRevealType
601        );
602        /* Team */
603        elementorFrontend.hooks.addAction(
604            "frontend/element_ready/rayo-team.default",
605            function ($scope) {
606			    initBtnAnim($scope);
607			}
608        );
609        /* Portfolio Button Load More */
610        elementorFrontend.hooks.addAction(
611            "frontend/element_ready/ray-portfolio-list.default",
612            function ($scope) {
613			    initBtnAnim($scope);
614			}
615        );
616    });
617
618} )( jQuery );

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.