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.