PageSourceSearch

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

js swicos.com.my collected 2026-10-06 13:15:36 UTC 18,007 bytes, 521 lines download raw bytes

1( function( $ ) {
2    'use strict';
3
4    /*! ------------------------------------------------
5 * Project Name: Rayo - Digital Agency & Personal Portfolio HTML Template
6 * Project Description: Elevate your digital presence with Rayo - dynamic and stylish HTML template designed for creative agencies and personal brands. With modern layouts, smooth interactions and a polished aesthetic, Rayo template helps showcase projects, services and expertise with clarity and impact.
7 * Tags: mix_design, resume, portfolio, personal page, cv, template, one page, responsive, html5, css3, creative, clean, agency, studio
8 * Version: 1.0.0
9 * Build Date: July 2025
10 * Last Update: July 2025
11 * This product is available exclusively on Themeforest
12 * Author: mix_design
13 * Author URI: https://themeforest.net/user/mix_design
14 * File name: app.js
15 * ------------------------------------------------
16
17 * ------------------------------------------------
18 * Table of Contents
19 * ------------------------------------------------
20 *
21 *  01. Loader & Loading Animation
22 *  02. Lenis Scroll Plugin
23 *  03. Typed.js Plugin
24 *  04. Header Scroll Behavior
25 *  05. Hero #02 Scroll Out Animation
26 *  06. Hero #07 Scroll Out Animation
27 *  07. Hero #08 Scroll Out Animation
28 *  08. SVG Fallback
29 *  09. Chrome Smooth Scroll
30 *  10. Images Moving Ban
31 *  11. Detecting Mobile/Desktop
32 *  12. Smooth Scrolling
33 *  13. Menu & Hamburger
34 *  14. Menu Accordion
35 *  15. Layout Masonry
36 *  16. Accordion
37 *  17. Magnific Popup Video
38 *  18. Mailchimp Subscribe Form
39 *  19. Contact Form
40 *  20. Parallax - Ukiyo Images & Video
41 *  21. Pinned Images
42 *  22. Stacking Cards
43 *  23. Animation - Buttons Common
44 *  24. Animation - Text Reveal
45 *  25. Animation - Scroll Universal
46 *  26. Animation - Images Reveal on Hover
47 *  27. Swiper Slider - Testimonials #01
48 *  28. Swiper Slider - Testimonials #02
49 *  29. Swiper Slider - Inner Pages Demo
50 *  30. CountUp - All Counters Options
51 *  31. Marquee - Two Lines
52 *  32. Marquee - One Line To Right
53 *  33. Marquee - One Line To Left
54 *  34. SVG DOM Injection
55 *  35. Color Switch
56 *  36. Scroll to Top Button
57 *  37. Parallax Universal
58 *
59 * ------------------------------------------------
60 * Table of Contents End
61 * ------------------------------------------------ */
62
63gsap.registerPlugin(ScrollTrigger);
64gsap.registerPlugin(Flip);
65
66// --------------------------------------------- //
67// Lenis Scroll Plugin Start
68// --------------------------------------------- //
69const lenis = new Lenis();
70lenis.on('scroll', ScrollTrigger.update);
71gsap.ticker.add((time) => {
72    lenis.raf(time * 1000)
73});
74gsap.ticker.lagSmoothing(0);
75// --------------------------------------------- //
76// Lenis Scroll Plugin End
77// --------------------------------------------- //
78
79$(window).on("scroll", function() {
80
81    // --------------------------------------------- //
82    // Header Scroll Behavior Start
83    // --------------------------------------------- //
84    if($(window).scrollTop() > 10) {
85        $(".mxd-header").addClass("is-hidden");
86    } else {
87        $(".mxd-header").removeClass("is-hidden");
88    }
89    // --------------------------------------------- //
90    // Header Scroll Behavior End
91    // --------------------------------------------- //
92
93});
94
95// --------------------------------------------- //
96// Hero #02 Scroll Out Animation Start
97// --------------------------------------------- //
98// Hero #02 scroll animated elements
99const createScrollEffect1 = (selector, trigger, start, end, from, to, ease = "sine") => {
100  document.querySelectorAll(selector).forEach(el => {
101    gsap.timeline({
102      scrollTrigger: { trigger, start, end, scrub: true, ease }
103    }).fromTo(el, from, to);
104  });
105};
106
107// Hero #02 main elements
108createScrollEffect1(".hero-02-static-anim-el", ".hero-02-static__tl-trigger",
109  "top 14%", "top 0.2%",
110  { y: 0, scaleY: 1, opacity: 1 },
111  { y: -80, scaleY: 1.3, opacity: 0 }
112);
113
114// Hero #02 pinned elements
115createScrollEffect1(".hero-02-fade-out-scroll", ".mxd-pinned-fullscreen__tl-trigger",
116  "top 80%", "top 10%",
117  { opacity: 1 },
118  { opacity: 0 }
119);
120
121// --------------------------------------------- //
122// Hero #02 Scroll Out Animation End
123// --------------------------------------------- //
124
125// --------------------------------------------- //
126// Hero #07 Scroll Out Animation Start
127// --------------------------------------------- //
128const createScrollEffect = (selector, trigger, start, end, from, to, ease = "power4.out") => {
129    document.querySelectorAll(selector).forEach(el => {
130        gsap.timeline({
131        scrollTrigger: { trigger, start, end, scrub: true, ease }
132        }).fromTo(el, from, to);
133    });
134};
135
136// Slide-out mạnh
137createScrollEffect(".hero-07-slide-out-scroll", ".mxd-hero-07__tl-trigger", 
138    "top 86%", "top 10%", 
139    { y: 0, scaleY: 1 },
140    { y: -416, scaleY: 0.8 }
141);
142
143// Fade-out nhẹ
144createScrollEffect(".hero-07-fade-out-scroll", ".mxd-hero-07__tl-trigger", 
145    "top 70%", "top 40%", 
146    { y: 0, opacity: 1 },
147    { y: -160, opacity: 0 },
148    "elastic.out(1,0.3)"
149);
150// --------------------------------------------- //
151// Hero #07 Scroll Out Animation End
152// --------------------------------------------- //
153
154// --------------------------------------------- //
155// Hero #08 Scroll Out Animation Start
156// --------------------------------------------- //
157const createScrollOut = (selector, trigger, start, end, from, to) => {
158  document.querySelectorAll(selector).forEach(el => {
159    gsap.timeline({
160      scrollTrigger: { trigger, start, end, scrub: true, ease: "power4.inOut" }
161    }).fromTo(el, from, to);
162  });
163};
164
165// Fade out
166createScrollOut(".hero-08-slide-out-scroll", ".mxd-hero-08__tl-trigger", "top 80%", "top 40%", 
167  { y: 0, opacity: 1 }, 
168  { y: -80, opacity: 0 }
169);
170
171// Scale out
172createScrollOut(".hero-08-scale-out-scroll", ".mxd-hero-08__tl-trigger", "top 40%", "top 10%", 
173  { y: 0, scaleY: 1, opacity: 1 }, 
174  { y: -80, scaleY: 1.2, opacity: 0 }
175);
176// --------------------------------------------- //
177// Hero #08 Scroll Out Animation End
178// --------------------------------------------- //
179
180
181$(function() {
182
183    // --------------------------------------------- //
184    // Chrome Smooth Scroll Start
185    // --------------------------------------------- //
186    try {
187        $.browserSelector();
188        if($("html").hasClass("chrome")) {
189            $.smoothScroll();
190        }
191    } catch(err) {
192};
193// --------------------------------------------- //
194// Chrome Smooth Scroll End
195// --------------------------------------------- //
196
197// --------------------------------------------- //
198// Images Moving Ban Start
199// --------------------------------------------- //
200$("img, a").on("dragstart", function(event) { event.preventDefault(); });
201// --------------------------------------------- //
202// Images Moving Ban End
203// --------------------------------------------- //
204
205// --------------------------------------------- //
206// Detecting Mobile/Desktop Start
207// --------------------------------------------- //
208var isMobile = false;
209if( /Android|webOS|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
210    $('html').addClass('touch');
211    isMobile = true;
212}
213else {
214    $('html').addClass('no-touch');
215    isMobile = false;
216}
217//IE, Edge
218var isIE = /MSIE 9/i.test(navigator.userAgent) || /rv:11.0/i.test(navigator.userAgent) || /MSIE 10/i.test(navigator.userAgent) || /Edge\/\d+/.test(navigator.userAgent);
219// --------------------------------------------- //
220// Detecting Mobile/Desktop End
221// --------------------------------------------- //
222
223// --------------------------------------------- //
224// Smooth Scrolling Start
225// --------------------------------------------- //
226$('a[href*="#"]').not('[href="#"]').not('[href="#0"]').click(function(event) {
227    if (location.pathname.replace(/^\//, '') == this.pathname.replace(/^\//, '') && location.hostname == this.hostname) {
228        var target = $(this.hash);
229        target = target.length ? target : $('[name=' + this.hash.slice(1) + ']');
230        if (target.length) {
231            event.preventDefault();
232            $('html, body').animate({
233                scrollTop: target.offset().top
234            }, 1000, function() {
235            var $target = $(target);
236            $target.focus();
237                if ($target.is(":focus")) {
238                    return false;
239                } else {
240                    $target.attr('tabindex','-1');
241                    $target.focus();
242                };
243            });
244        }
245    }
246});
247// --------------------------------------------- //
248// Smooth Scrolling End
249// --------------------------------------------- //
250
251// --------------------------------------------- //
252// Menu & Hamburger Start
253// --------------------------------------------- //
254$(".mxd-nav__wrap").each(function() {
255    let navWrap       = $(this);
256    let hamburgerEl   = $(this).find(".mxd-nav__hamburger");
257    let navLineEl     = $(this).find(".hamburger__line");
258    let menuContainEl = $(this).find(".mxd-menu__contain");
259    let flipItemEl    = $(this).find(".hamburger__base");
260    let menuWrapEl    = $(this).find(".mxd-menu__wrapper");
261    let menuBaseEl    = $(this).find(".mxd-menu__base");
262    let menuLinkEl    = $(this).find(".mxd-menu__link");
263    let menuItem      = $(this).find(".main-menu__item");
264    let videoEl       = $(this).find(".menu-promo__video video");
265    let fadeInEl      = $(this).find(".menu-fade-in");
266    let flipDuration = 0.6;
267
268    function flip(forwards) {
269        let state = Flip.getState(flipItemEl);
270        if (forwards) {
271            flipItemEl.appendTo(menuContainEl);
272        } else {
273            flipItemEl.appendTo(hamburgerEl);
274        }
275        Flip.from(state, { ease: "power4.inOut", duration: 0.8 });
276    }
277
278    let tl = gsap.timeline({ paused: true });
279    tl.set(menuWrapEl, { display: "flex" });
280    tl.from(menuBaseEl, { 
281        opacity: 0,
282        duration: flipDuration,
283        ease: "none",
284        onStart: () => {
285            flip(true);
286        }
287    });
288    tl.to(navLineEl.eq(0), { y: 5, duration: 0.16 }, "<")
289    tl.to(navLineEl.eq(1), { y: -5, duration: 0.16 }, "<")
290    tl.to(navLineEl.eq(0), { rotate: 45, duration: 0.16 }, 0.2)
291    tl.to(navLineEl.eq(1), { rotate: -45, duration: 0.16 }, 0.2)
292    tl.add("fade-in-up")
293    .from(menuItem, {
294        opacity: 0,
295        yPercent: 50,
296        duration: 0.2,
297        stagger: {amount: 0.2},
298        onReverseComplete: () => {
299            flip(false);
300        }
301    }, "fade-in-up")
302    .from(menuLinkEl, {
303        opacity: 0,
304        yPercent: 20,
305        duration: 0.2,
306    }, "fade-in-up")
307    .from(videoEl, {
308        opacity: 0,
309        yPercent: 20,
310        duration: 0.2,
311    }, "fade-in-up");
312    tl.from(fadeInEl, { opacity: 0, duration: 0.3, });
313
314    function openMenu(open) {
315        if (!tl.isActive()) {
316            if (open) {
317                tl.play();
318                navWrap.addClass("wrap-open");
319                hamburgerEl.addClass("nav-open");
320            } else {
321                tl.reverse();
322                navWrap.removeClass("wrap-open");
323                hamburgerEl.removeClass("nav-open");
324            }
325        }
326    }
327
328    hamburgerEl.on("click", function() {
329        event.preventDefault();
330        if ($(this).hasClass("nav-open")) {
331            openMenu(false);
332        } else {
333            openMenu(true);
334        }
335    });
336    menuBaseEl.on("click", function () {
337        openMenu(false);
338    });
339    $(document).on("keydown", function (e) {
340        if (e.key === "Escape") {
341            openMenu(false);
342        }
343    });
344
345    window.addEventListener("beforeunload", (event) => {
346        openMenu(false);
347    });
348
349});
350  // --------------------------------------------- //
351  // Menu & Hamburger End
352  // --------------------------------------------- //
353
354  // --------------------------------------------- //
355  // Header/Menu Z-index Change Start
356  // --------------------------------------------- //
357  $(".mxd-nav__hamburger").on("click", function() {
358    if ($(".mxd-nav__hamburger").hasClass("nav-open")) {
359        $(".mxd-header").addClass("menu-is-visible");
360    } else {
361        setTimeout(function() {
362            $(".mxd-header").removeClass("menu-is-visible");
363        }, 1100);
364    }
365  });
366  // --------------------------------------------- //
367  // Header/Menu Z-index Change End
368  // --------------------------------------------- //
369
370  // --------------------------------------------- //
371  // Menu Accordion Start
372  // --------------------------------------------- //
373  var Accordion = function(el, multiple) {
374    this.el = el || {};
375    this.multiple = multiple || false;
376    var links = this.el.find('.main-menu__toggle');
377    links.on('click', {el: this.el, multiple: this.multiple}, this.dropdown)
378  }
379    Accordion.prototype.dropdown = function(e) {
380        var $el   = e.data.el,
381            $this = $(this),
382            $next = $this.next();
383        $next.slideToggle();
384        $this.parent().toggleClass('open');
385        if (!e.data.multiple) {
386            $el.find('.submenu').not($next).slideUp().parent().removeClass('open');
387        };
388    }
389  var accordion = new Accordion($('#main-menu'), false);
390    // --------------------------------------------- //
391    // Menu Accordion End
392    // --------------------------------------------- //
393
394    // --------------------------------------------- //
395    // Layout Masonry After Each Image Loads Start
396    // --------------------------------------------- //
397    $('.mxd-projects-masonry__gallery').imagesLoaded().progress( function() {
398        $('.mxd-projects-masonry__gallery').masonry('layout');
399        ScrollTrigger.refresh();
400    });
401    // --------------------------------------------- //
402    // Layout Masonry After Each Image Loads End
403    // --------------------------------------------- //
404  
405});
406
407// --------------------------------------------- //
408// Parallax - Ukiyo Images & Video Start
409// --------------------------------------------- //
410const images = document.querySelectorAll(".parallax-img");
411const imagesSmall = document.querySelectorAll(".parallax-img-small");
412const video = document.querySelectorAll(".parallax-video");
413new Ukiyo(images,{
414    scale: 1.5,
415    speed: 1.5,
416    externalRAF: false,
417});
418imagesSmall.forEach(img => {
419    new Ukiyo(img, {
420        scale: 1.2,
421        speed: 1.5,
422        externalRAF: false
423    });
424    img.dataset.ukiyoInitialized = 'true';
425});
426new Ukiyo(video,{
427    scale: 1.5,
428    speed: 1.5,
429    externalRAF: false
430});
431// --------------------------------------------- //
432// Parallax - Ukiyo Images & Video End
433// --------------------------------------------- //
434
435// --------------------------------------------- //
436// Animation - Buttons Common Start
437// --------------------------------------------- //
438let elements = document.querySelectorAll(".btn-anim .btn-caption, .rayo-btn-anim .btn-caption");
439
440elements.forEach((element) => {
441    let innerText = element.innerText;
442    element.innerHTML = "";
443    let textContainer = document.createElement("div");
444    textContainer.classList.add("btn-anim__block");
445    for (let letter of innerText) {
446        let span = document.createElement("span");
447        span.innerText = letter.trim() === "" ? "\xa0" : letter;
448        span.classList.add("btn-anim__letter");
449        textContainer.appendChild(span);
450    }
451    element.appendChild(textContainer);
452    element.appendChild(textContainer.cloneNode(true));
453});
454
455elements.forEach((element) => {
456  element.addEventListener("mouseover", () => {
457    element.classList.remove("play");
458  })
459});
460// --------------------------------------------- //
461// Animation - Buttons Common End
462// --------------------------------------------- //
463
464// --------------------------------------------- //
465// Scroll to Top Button Start
466// --------------------------------------------- //
467const toTop = document.querySelector(".btn-to-top");
468
469$(".btn-to-top").each(function() {
470    toTop.addEventListener("click", function(event){
471        event.preventDefault()
472    });
473
474    toTop.addEventListener("click", () => gsap.to(window, { 
475        scrollTo: 0, 
476        ease: 'power4.inOut',
477        duration: 1.3,
478    }));
479
480    gsap.set(toTop, { opacity: 0 });
481
482    gsap.to(toTop, {
483        opacity: 1,
484        autoAlpha: 1,
485        scrollTrigger: {
486          trigger: "body",
487          start: "top -20%",
488          end: "top -20%",
489          toggleActions: "play none reverse none"
490        }
491    });
492});
493// --------------------------------------------- //
494// Scroll to Top Button End
495// --------------------------------------------- //
496
497// ------------------------------------------------------------------------------ //
498// Parallax Universal (apply parallax effect to any element with a data-speed attribute) Start
499// ------------------------------------------------------------------------------ //
500const parallaxEls = document.querySelectorAll("[data-speed]");
501if (parallaxEls.length > 0) {
502    gsap.to(parallaxEls, {
503        y: (i, el) => {
504            const speedAttr = el.getAttribute("data-speed");
505            const speed = speedAttr ? parseFloat(speedAttr) : 1;
506            return (1 - speed) * ScrollTrigger.maxScroll(window);
507        },
508        ease: "none",
509        scrollTrigger: {
510            start: 0,
511            end: "max",
512            scrub: 0,
513            invalidateOnRefresh: true,
514        }
515    });
516}
517// --------------------------------------------- //
518// Parallax Universal End
519// --------------------------------------------- //
520
521} )( 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.