1(function ($) { 2 3 (function () { 4 function addStyle() { 5 if (document.head) { 6 var style = document.createElement('style'); 7 style.textContent = '.pxl-animate { opacity: 0 !important; visibility: hidden !important; }'; 8 document.head.appendChild(style); 9 } else { 10 setTimeout(addStyle, 10); 11 } 12 } 13 addStyle(); 14 })(); 15 16 function auregon_animation_handler($scope) { 17 var $elements = $scope ? $scope.find('.pxl-animate') : $(document).find('.pxl-animate'); 18 19 $elements.each(function () { 20 var $el = $(this); 21 if (!$el.hasClass('pxl-invisible')) { 22 $el.addClass('pxl-invisible'); 23 } 24 }); 25 26 if (window.elementorFrontend && typeof elementorFrontend.waypoint === 'function') { 27 elementorFrontend.waypoint($elements, function () { 28 var $animate_el = $(this), 29 data = $animate_el.data('settings'); 30 if (typeof data !== 'undefined' && typeof data['animation'] !== 'undefined') { 31 setTimeout(function () { 32 $animate_el.removeClass('pxl-invisible').addClass('animated ' + data['animation']); 33 }, data['animation_delay'] || 0); 34 } else { 35 setTimeout(function () { 36 $animate_el.removeClass('pxl-invisible').addClass('animated fadeInUp'); 37 }, 300); 38 } 39 }); 40 } 41 42 if ($scope && window.elementorFrontend && typeof elementorFrontend.waypoint === 'function') { 43 elementorFrontend.waypoint($scope.find('.pxl-border-animated'), function () { 44 $(this).addClass('pxl-animated'); 45 }); 46 elementorFrontend.waypoint($scope.find('.pxl-section-divider'), function () { 47 $(this).addClass('pxl-animated'); 48 }); 49 elementorFrontend.waypoint($scope.find('.TextOutlineAnimation'), function () { 50 $(this).addClass('pxl-animated'); 51 }); 52 elementorFrontend.waypoint($scope.find('.PXLfadeInUp'), function () { 53 $(this).addClass('pxl-animated'); 54 }); 55 elementorFrontend.waypoint($scope.find('.pxl-icon1.style-balloon'), function () { 56 $(this).addClass('pxl-animated'); 57 }); 58 } 59 } 60 61 const PXLDIV_MAX_DIST = 140; 62 const PXLDIV_PEAK = 0.75; 63 const PXLDIV_SPREAD_MIN = 170; 64 const PXLDIV_SPREAD_MAX = 250; 65 66 const PXLBORDER_MAX_DIST = 300; 67 const PXLBORDER_PEAK = 0.75; 68 const PXLBORDER_SPREAD_MIN = 170; 69 const PXLBORDER_SPREAD_MAX = 300; 70 71 function pxl_divider_clamp(v, a, b) { 72 return Math.max(a, Math.min(b, v)); 73 } 74 75 function pxl_divider_smoothstep(t) { 76 return t * t * (3 - 2 * t); 77 } 78 79 function bind_divider_glow(container) { 80 if (!container || container.getAttribute('data-divider-glow-bound') === '1') return; 81 82 var dividers = container.querySelectorAll('.pxl-section-divider'); 83 if (!dividers.length) return; 84 85 container.setAttribute('data-divider-glow-bound', '1'); 86 87 var state = { 88 x: 0, 89 y: 0, 90 inside: false, 91 raf: null 92 }; 93 94 function render() { 95 state.raf = null; 96 var rect = container.getBoundingClientRect(); 97 if (!rect || rect.width === 0 || rect.height === 0) return; 98 99 var x = pxl_divider_clamp(state.x - rect.left, 0, rect.width); 100 var y = pxl_divider_clamp(state.y - rect.top, 0, rect.height); 101 102 dividers.forEach(function (divider) { 103 var isHorizontal = divider.classList.contains('pxl-section-divider--top') || divider.classList.contains('pxl-section-divider--bottom'); 104 var target = isHorizontal ? (divider.classList.contains('pxl-section-divider--top') ? 0 : rect.height) : (divider.classList.contains('pxl-section-divider--left') ? 0 : rect.width); 105 var dist = Math.abs((isHorizontal ? y : x) - target); 106 var t = state.inside ? pxl_divider_clamp(1 - dist / PXLDIV_MAX_DIST, 0, 1) : 0; 107 var eased = pxl_divider_smoothstep(t); 108 var alpha = PXLDIV_PEAK * eased; 109 var spread = PXLDIV_SPREAD_MAX - (PXLDIV_SPREAD_MAX - PXLDIV_SPREAD_MIN) * eased; 110 111 divider.style.setProperty('--pxl-divider-gx', x + 'px'); 112 divider.style.setProperty('--pxl-divider-gy', y + 'px'); 113 divider.style.setProperty('--pxl-divider-alpha', alpha.toFixed(3)); 114 divider.style.setProperty('--pxl-divider-spread', spread.toFixed(1) + 'px'); 115 divider.setAttribute('data-glow', state.inside && alph
115a > 0.003 ? '1' : '0'); 116 }); 117 } 118 119 function schedule() { 120 if (state.raf) return; 121 state.raf = requestAnimationFrame(render); 122 } 123 124 function handleMove(e) { 125 state.x = e.clientX; 126 state.y = e.clientY; 127 state.inside = true; 128 schedule(); 129 } 130 131 function handleLeave() { 132 state.inside = false; 133 schedule(); 134 } 135 136 var rect = container.getBoundingClientRect(); 137 state.x = rect.left + rect.width / 2; 138 state.y = rect.top + rect.height / 2; 139 140 container.addEventListener('mousemove', handleMove); 141 container.addEventListener('mouseenter', handleMove); 142 container.addEventListener('mouseleave', handleLeave); 143 144 schedule(); 145 } 146 147 function auregon_section_divider_glow($scope) { 148 var $context = $scope && $scope.length ? $scope : $(document); 149 var hosts = []; 150 151 $context.find('.pxl-section-divider').each(function () { 152 var host = this.closest('.elementor-element'); 153 if (host && hosts.indexOf(host) === -1) { 154 hosts.push(host); 155 } 156 }); 157 158 hosts.forEach(function (host) { 159 bind_divider_glow(host); 160 }); 161 } 162 163 function bind_border_glow(host) { 164 if (!host || host.getAttribute('data-border-glow-bound') === '1') return; 165 166 var glowHost = host.querySelector('.pxl-border-glow'); 167 if (!glowHost) return; 168 169 host.setAttribute('data-border-glow-bound', '1'); 170 171 var topGlow = glowHost.querySelector('.pxl-bd-glow.top'); 172 var rightGlow = glowHost.querySelector('.pxl-bd-glow.right'); 173 var bottomGlow = glowHost.querySelector('.pxl-bd-glow.bottom'); 174 var leftGlow = glowHost.querySelector('.pxl-bd-glow.left'); 175 176 var state = { 177 x: 0, 178 y: 0, 179 inViewport: false, 180 raf: 0, 181 rect: null, 182 obs: null, 183 onMove: null, 184 onResize: null 185 }; 186 187 function clamp(v, a, b) { return v < a ? a : (v > b ? b : v); } 188 function smoothstep(t) { return t * t * (3 - 2 * t); } // nếu bạn Äã có pxl_divider_smoothstep thì dùng cái Äó 189 190 function updateRect() { 191 state.rect = host.getBoundingClientRect(); 192 } 193 194 // Calculate distance from point to rectangle 195 // Returns 0 if point is inside rectangle, otherwise distance to nearest edge 196 function distanceToRect(px, py, rect) { 197 var dx = Math.max(0, Math.max(rect.left - px, px - rect.right)); 198 var dy = Math.max(0, Math.max(rect.top - py, py - rect.bottom)); 199 return Math.sqrt(dx * dx + dy * dy); 200 } 201 202 function render() { 203 state.raf = 0; 204 205 if (!state.inViewport) { 206 // out viewport -> tắt sạch 207 host.style.setProperty('--pxl-bd-alpha', '0'); 208 if (topGlow) topGlow.style.opacity = 0; 209 if (rightGlow) rightGlow.style.opacity = 0; 210 if (bottomGlow) bottomGlow.style.opacity = 0; 211 if (leftGlow) leftGlow.style.opacity = 0; 212 return; 213 } 214 215 if (!state.rect) updateRect(); 216 var rect = state.rect; 217 if (!rect || !rect.width || !rect.height) return; 218 219 // Calculate distance from mouse to rectangle 220 var distance = distanceToRect(state.x, state.y, rect); 221 222 // If distance > MAX_DIST, turn off 223 if (distance > PXLBORDER_MAX_DIST) { 224 host.style.setProperty('--pxl-bd-alpha', '0'); 225 if (topGlow) topGlow.style.opacity = 0; 226 if (rightGlow) rightGlow.style.opacity = 0; 227 if (bottomGlow) bottomGlow.style.opacity = 0; 228 if (leftGlow) leftGlow.style.opacity = 0; 229 return; 230 } 231 232 // Calculate distance to each edge 233 var x = clamp(state.x - rect.left, 0, rect.width);
234 var y = clamp(state.y - rect.top, 0, rect.height); 235 236 var distTop = y; 237 var distRight = rect.width - x; 238 var distBottom = rect.height - y; 239 var distLeft = x; 240 241 // Alpha based on distance to rectangle: 1 - distance / MAX_DIST 242 var baseAlpha = clamp(1 - distance / PXLBORDER_MAX_DIST, 0, 1); 243 var easedBase = smoothstep(baseAlpha); 244 245 // Each edge's intensity based on its distance (closer = brighter) 246 var tTop = clamp(1 - distTop / PXLBORDER_MAX_DIST, 0, 1); 247 var tRight = clamp(1 - distRight / PXLBORDER_MAX_DIST, 0, 1); 248 var tBottom = clamp(1 - distBottom / PXLBORDER_MAX_DIST, 0, 1); 249 var tLeft = clamp(1 - distLeft / PXLBORDER_MAX_DIST, 0, 1); 250 251 var easedTop = smoothstep(tTop); 252 var easedRight = smoothstep(tRight); 253 var easedBottom = smoothstep(tBottom); 254 var easedLeft = smoothstep(tLeft); 255 256 // Main alpha uses base distance 257 var alpha = PXLBORDER_PEAK * easedBase; 258 var spread = PXLBORDER_SPREAD_MAX - (PXLBORDER_SPREAD_MAX - PXLBORDER_SPREAD_MIN) * easedBase; 259 260 host.style.setProperty('--pxl-bd-gx', x + 'px'); 261 host.style.setProperty('--pxl-bd-gy', y + 'px'); 262 host.style.setProperty('--pxl-bd-alpha', alpha.toFixed(3)); 263 host.style.setProperty('--pxl-bd-spread', spread.toFixed(1) + 'px'); 264 265 // Edge closest to mouse glows brightest 266 if (topGlow) topGlow.style.opacity = easedTop; 267 if (rightGlow) rightGlow.style.opacity = easedRight; 268 if (bottomGlow) bottomGlow.style.opacity = easedBottom; 269 if (leftGlow) leftGlow.style.opacity = easedLeft; 270 } 271 272 function schedule(forceRect) { 273 if (forceRect) state.rect = null; 274 if (state.raf) return; 275 state.raf = requestAnimationFrame(render); 276 } 277 278 state.onMove = function (e) { 279 state.x = e.clientX; 280 state.y = e.clientY; 281 schedule(false); 282 }; 283 284 state.onResize = function () { 285 // khi resize/scroll layout Äá»i -> refresh rect 286 schedule(true); 287 }; 288 289 // IntersectionObserver 290 state.obs = new IntersectionObserver(function (entries) { 291 for (var i = 0; i < entries.length; i++) { 292 if (entries[i].target !== host) continue; 293 state.inViewport = !!entries[i].isIntersecting; 294 schedule(true); // và o/ra viewport Äá»u render Äá» báºt/tắt ngay 295 } 296 }, { threshold: 0.1 }); 297 298 state.obs.observe(host); 299 300 // PROXIMITY MODE: Listen to pointermove on document to detect mouse near border 301 document.addEventListener('pointermove', state.onMove, { passive: true }); 302 303 window.addEventListener('resize', state.onResize, { passive: true }); 304 window.addEventListener('scroll', state.onResize, { passive: true }); 305 306 // init center 307 updateRect(); 308 var r = state.rect; 309 state.x = r.left + r.width / 2; 310 state.y = r.top + r.height / 2; 311 312 schedule(false); 313 314 // cleanup Äá» tránh leak (Elementor re-render) 315 host._pxlBorderGlowCleanup = function () { 316 if (state.raf) cancelAnimationFrame(state.raf); 317 if (state.obs) state.obs.disconnect(); 318 319 document.removeEventListener('pointermove', state.onMove); 320 321 window.removeEventListener('resize', state.onResize); 322 window.removeEventListener('scroll', state.onResize); 323 324 host.removeAttribute('data-border-glow-bound'); 325 delete host._pxlBorderGlowCleanup; 326 }; 327 } 328 329 330 function auregon_border_glow($scope) { 331 var $context = $scope && $scope.length ? $scope : $(document); 332 $context.find('.pxl-border-section-anm').each(function () { 333 bind_border_glow(this); 334 }); 335 } 336 337 function auregon_polyfill_waypoint() { 338 if (!window.elementorFrontend || typeof elementorFrontend.waypoint === 'function') return; 339 elementorFrontend.waypoint = function ($elements, handler, options) { 340 options = options || {}; 341 var triggerOnce = typeof options.triggerOnce === 'boolean' ? options.triggerOnce : true; 342 var offset = options.offset; 343 var rootMargin = '0px 0px 0px 0px'; 344 if (typeof offset === 'string' && /%$/.test(offset)) { 345 var percent = parseFloat(offset); 346 if (!isNaN(percent)) { 347 var bottomPercent = Math.max(0, 100 - percent); 348 rootMargin = '0px 0px -' + bottomPercent + '% 0px'; 349 } 350 } else if (typeof offset === 'number') { 351 rootMargin = '0px 0px -' + offset + 'px 0px'; 352 } 353 if ('IntersectionObserver' in window) { 354 var observer = new IntersectionObserver(function (entries) {
355 entries.forEach(function (entry) { 356 if (entry.isIntersecting || entry.intersectionRatio > 0) { 357 handler.call(entry.target); 358 if (triggerOnce) { 359 observer.unobserve(entry.target); 360 } 361 } 362 }); 363 }, { root: null, rootMargin: rootMargin, threshold: 0 }); 364 $($elements).each(function () { 365 var dom = this instanceof Element ? this : (this && this[0] instanceof Element ? this[0] : null); 366 if (dom) observer.observe(dom); 367 }); 368 } else { 369 $($elements).each(function () { handler.call(this); }); 370 } 371 }; 372 } 373 374 function auregon_section_start_render() { 375 var _elementor = typeof elementor !== 'undefined' ? elementor : elementorFrontend; 376 377 _elementor.hooks.addFilter('pxl_element_container/before-render', function (html, settings) { 378 if (typeof settings.pxl_parallax_bg_img !== 'undefined' && settings.pxl_parallax_bg_img && settings.pxl_parallax_bg_img.url !== '') { 379 html += '<div class="pxl-section-bg-parallax"></div>'; 380 } 381 382 if (typeof settings.pxl_color_offset !== 'undefined' && settings.pxl_color_offset !== 'none') { 383 html += '<div class="pxl-section-overlay-color"></div>'; 384 } 385 386 if (typeof settings.pxl_overlay_img !== 'undefined' && settings.pxl_overlay_img && settings.pxl_overlay_img.url !== '') { 387 html += '<div class="pxl-overlay--image pxl-overlay--imageLeft"><div class="bg-image"></div></div>'; 388 } 389 390 if (typeof settings.pxl_overlay_img2 !== 'undefined' && settings.pxl_overlay_img2 && settings.pxl_overlay_img2.url !== '') { 391 html += '<div class="pxl-overlay--image pxl-overlay--imageRight"><div class="bg-image"></div></div>'; 392 } 393 394 return html; 395 }); 396 397 // Chá» DOM ready trưá»c khi tìm elements 398 $(document).ready(function () { 399 $('.pxl-section-bg-parallax').closest('.elementor-element').addClass('pxl-section-parallax-overflow'); 400 }); 401 } 402 403 function auregon_css_inline_js() { 404 var _inline_css = "<style>"; 405 $(document).find('.pxl-inline-css').each(function () { 406 var _this = $(this); 407 _inline_css += _this.attr("data-css") + " "; 408 _this.remove(); 409 }); 410 _inline_css += "</style>"; 411 $('head').append(_inline_css); 412 } 413 414 function auregon_section_before_render() { 415 var _elementor = typeof elementor !== 'undefined' ? elementor : elementorFrontend; 416 _elementor.hooks.addFilter('pxl-custom-section/before-render', function (html, settings, el) { 417 if (typeof settings['row_divider'] !== 'undefined') { 418 if (settings['row_divider'] === 'angle-top' || settings['row_divider'] === 'angle-bottom' || settings['row_divider'] === 'angle-top-right' || settings['row_divider'] === 'angle-bottom-left') { 419 html = '<svg class="pxl-row-angle" style="fill:#ffffff" xmlns="http://www.w3.org/2000/svg" width="100%" viewBox="0 0 100 100" version="1.1" preserveAspectRatio="none" height="130px"><path stroke="" stroke-width="0" d="M0 100 L100 0 L200 100"></path></svg>'; 420 return html; 421 } 422 if (settings['row_divider'] === 'angle-top-bottom' || settings['row_divider'] === 'angle-top-bottom-left') { 423 html = '<svg class="pxl-row-angle pxl-row-angle-top" style="fill:#ffffff" xmlns="http://www.w3.org/2000/svg" width="100%" viewBox="0 0 100 100" version="1.1" preserveAspectRatio="none" height="130px"><path stroke="" stroke-width="0" d="M0 100 L100 0 L200 100"></path></svg><svg class="pxl-row-angle pxl-row-angle-bottom" style="fill:#ffffff" xmlns="http://www.w3.org/2000/svg" width="100%" viewB
423ox="0 0 100 100" version="1.1" preserveAspectRatio="none" height="130px"><path stroke="" stroke-width="0" d="M0 100 L100 0 L200 100"></path></svg>'; 424 return html; 425 } 426 if (settings['row_divider'] === 'wave-animation-top' || settings['row_divider'] === 'wave-animation-bottom') { 427 html = '<svg class="pxl-row-angle" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none" viewBox="0 0 1440 150" fill="#fff"><path d="M 0 26.1978 C 275.76 83.8152 430.707 65.0509 716.279 25.6386 C 930.422 -3.86123 1210.32 -3.98357 1439 9.18045 C 2072.34 45.9691 2201.93 62.4429 2560 26.198 V 172.199 L 0 172.199 V 26.1978 Z"><animate repeatCount="indefinite" fill="freeze" attributeName="d" dur="10s" values="M0 25.9086C277 84.5821 433 65.736 720 25.9086C934.818 -3.9019 1214.06 -5.23669 1442 8.06597C2079 45.2421 2208 63.5007 2560 25.9088V171.91L0 171.91V25.9086Z; M0 86.3149C316 86.315 444 159.155 884 51.1554C1324 -56.8446 1320.29 34.1214 1538 70.4063C1814 116.407 2156 188.408 2560 86.315V232.317L0 232.316V86.3149Z; M0 53.6584C158 11.0001 213 0 363 0C513 0 855.555 115.001 1154 115.001C1440 115.001 1626 -38.0004 2560 53.6585V199.66L0 199.66V53.6584Z; M0 25.9086C277 84.5821 433 65.736 720 25.9086C934.818 -3.9019 1214.06 -5.23669 1442 8.06597C2079 45.2421 2208 63.5007 2560 25.9088V171.91L0 171.91V25.9086Z"></animate></path></svg>'; 428 return html; 429 } 430 if (settings['row_divider'] === 'curved-top' || settings['row_divider'] === 'curved-bottom') { 431 html = '<svg class="pxl-row-angle" xmlns="http://www.w3.org/2000/svg" width="100%" viewBox="0 0 1920 128" version="1.1" preserveAspectRatio="none" style="fill:#ffffff"><path stroke-width="0" d="M-1,126a3693.886,3693.886,0,0,1,1921,2.125V-192H-7Z"></path></svg>'; 432 return html; 433 } 434 } 435 }); 436 } 437 438 var PXL_Icon_Contact_Form = function ($scope, $) { 439 440 setTimeout(function () { 441 $('.pxl--item').each(function () { 442 var icon_input = $(this).find(".pxl--form-icon"), 443 control_wrap = $(this).find('.wpcf7-form-control'); 444 control_wrap.before(icon_input.clone()); 445 icon_input.remove(); 446 }); 447 }, 10); 448 449 }; 450 451 452 function auregon_split_text($scope) { 453 var st = $scope.find(".pxl-split-text"); 454 if (st.length === 0) return; 455 456 // Kiá»m tra GSAP và SplitText có tá»n tại 457 if (typeof gsap === 'undefined' || typeof SplitText === 'undefined') { 458 console.warn('GSAP or SplitText plugin not loaded'); 459 return; 460 } 461 462 gsap.registerPlugin(SplitText); 463 464 st.each(function (index, el) { 465 var els = $(el).find('p').length > 0 ? $(el).find('p')[0] : el; 466 const pxl_split = new SplitText(els, { 467 type: "lines, words, chars", 468 lineThreshold: 0.5, 469 linesClass: "split-line" 470 }); 471 var split_type_set = pxl_split.chars; 472 473 gsap.set(els, { perspective: 400 }); 474 475 var settings = { 476 scrollTrigger: { 477 trigger: els, 478 toggleActions: "play none none none", 479 start: "top 86%", 480 once: true 481 }, 482 duration: 0.35, 483 stagger: 0.02, 484 ease: "Expo.out" 485 }; 486 if ($(el).hasClass('split-in-fade')) { 487 settings.opacity = 0; 488 } 489 if ($(el).hasClass('split-in-right')) { 490 settings.opacity = 0; 491 settings.x = "50"; 492 } 493 if ($(el).hasClass('split-in-left')) { 494 settings.opacity = 0; 495 settings.x = "-50"; 496 } 497 if ($(el).hasClass('split-in-up')) { 498 settings.opacity = 0; 499 settings.y = "80"; 500 } 501 if ($(el).hasClass('split-in-down')) { 502 settings.opacity = 0; 503 settings.y = "-80"; 504 } 505 if ($(el).hasClass('split-in-rotate')) { 506 settings.opacity = 0; 507 settings.rotateX = "50deg"; 508 } 509 if ($(el).hasClass('split-in-scale')) { 510 settings.opacity = 0; 511 settings.scale = "0.5"; 512 } 513 514 if ($(el).hasClass('split-up')) { 515 pxl_split.split({ type: "words" }); 516 split_type_set = pxl_split.words; 517 518 $(split_type_set).each(function (index, elw) { 519 gsap.from(elw, { 520 opacity: 0, 521 duration: 0.65, 522 y: 60, 523 delay: 0.25 + index * 0.065, 524 ease: "expo.out", 525 scrollTrigger: { 526 trigger: el, 527 start: "top 86%", 528 toggleActions: "play none none none", 529 }, 530 }); 531 }); 532 } 533 534 if ($(el).hasClass('split-words-scale')) { 535 pxl_split.split({ type: "words" }); 536 split_type_set = pxl_split.words; 537 538 $(split_type_set).each(function (index, elw) { 539 gsap.set(elw, { 540 opacity: 0, 541 scale: index % 2 === 0 ? 0 : 2, 542 force3D: true, 543 duration: 0.1, 544 ease: "Linear.easeNone", 545 stagger: 0.02, 546 }, index * 0.01); 547 }); 548 549 var pxl_anim = gsap.to(split_type_set, { 550 scrollTrigger: { 551 trigger: el, 552 toggleActions: "play reverse play reverse", 553 start: "top 86%", 554 }, 555 rotateX: "0", 556 scale: 1, 557 opacity: 1, 558 }); 559 560 } else { 561 var pxl_anim = gsap.from(split_type_set, settings); 562 } 563 564 if ($(el).hasClass('hover-split-text')) { 565 $(el).mouseenter(function (e) { 566 pxl_anim.restart(); 567 }); 568 } 569 }); 570 } 571 572 function auregon_scroll_trigger($scope) { 573 if (typeof ScrollTrigger === 'undefined' || typeof gsap === 'undefined') { 574 console.warn('GSAP or ScrollTrigger not loaded'); 575 return; 576 } 577 578 ScrollTrigger.matchMedia({ 579 "(min-width: 1401px)": function () { 580 let t2 = gsap.timeline({ 581 scrollTrigger: { 582 trigger: ".pxl-section-scale",
583 scrub: true, 584 start: "top top", 585 end: "bottom bottom", 586 pin: ".pxl-section-sticky", 587 }, 588 }); 589 t2.to(".pxl-section-slide", { 590 padding: "7.5rem" 591 }, ">"); 592 t2.to(".pxl-sticky-mask", { 593 borderRadius: "2rem" 594 }, "<"); 595 t2.from(".is-shape-1", { 596 right: "-10%" 597 }, "<"); 598 t2.from(".is-shape-2", { 599 left: "-10%" 600 }, "<"); 601 }, 602 "(max-width: 1400px)": function () { 603 let t2 = gsap.timeline({ 604 scrollTrigger: { 605 trigger: ".pxl-section-scale", 606 scrub: true, 607 start: "top top", 608 end: "bottom bottom", 609 pin: ".pxl-section-sticky", 610 }, 611 }); 612 t2.to(".pxl-section-slide", { 613 padding: "4.8rem" 614 }, ">"); 615 t2.to(".pxl-sticky-mask", { 616 borderRadius: "1.6rem" 617 }, "<"); 618 t2.from(".is-shape-1", { 619 right: "-10%" 620 }, "<"); 621 t2.from(".is-shape-2", { 622 left: "-10%" 623 }, "<"); 624 }, 625 "(max-width: 991px)": function () { 626 let t2 = gsap.timeline({ 627 scrollTrigger: { 628 trigger: ".pxl-section-scale", 629 scrub: true, 630 start: "top bottom", 631 end: "bottom top", 632 }, 633 }); 634 t2.to(".pxl-section-slide", { 635 padding: "2rem" 636 }, ">"); 637 t2.to(".pxl-sticky-mask", { 638 borderRadius: "2rem" 639 }, "<"); 640 t2.from(".is-shape-1", { 641 right: "-10%" 642 }, "<"); 643 t2.from(".is-shape-2", { 644 left: "-10%" 645 }, "<"); 646 647 }, 648 }); 649 const rotatingStickerSelector = ".pxl-sticker-shape.is-rotate"; 650 if (document.querySelector(rotatingStickerSelector)) { 651 gsap.to(rotatingStickerSelector, { 652 rotation: "800", 653 scrollTrigger: { 654 trigger: "#pxl-content-main", 655 scrub: true, 656 start: "top top", 657 end: "bottom bottom", 658 }, 659 }); 660 } 661 } 662 663 function auregon_zoom_point() { 664 if (!window.elementorFrontend || typeof elementorFrontend.waypoint !== 'function') return; 665 666 var $zoomPoints = $(document).find('.pxl-zoom-point'); 667 if ($zoomPoints.length === 0) return; 668 669 elementorFrontend.waypoint($zoomPoints, function () { 670 var $el = $(this); 671 // Thêm logic zoom point nếu cần 672 $el.addClass('pxl-zoom-active'); 673 }, { 674 offset: -100, 675 triggerOnce: true 676 }); 677 } 678 679 function auregon_text_marquee($scope) { 680 if (typeof gsap === 'undefined') { 681 console.warn('GSAP not loaded'); 682 return; 683 } 684 685 const text_marquee = $scope.find('.pxl-text--marquee'); 686 if (text_marquee.length === 0) return; 687 688 const boxes = gsap.utils.toArray(text_marquee); 689 690 const loop = text_horizontalLoop(boxes, { paused: false, repeat: -1, }); 691 692 function text_horizontalLoop(items, config) { 693 items = gsap.utils.toArray(items); 694 config = config || {}; 695 let tl = gsap.timeline({ repeat: config.repeat, paused: config.paused, defaults: { ease: "none" }, onReverseComplete: () => tl.totalTime(tl.rawTime() + tl.duration() * 100) }), 696 length = items.length, 697 startX = items[0].offsetLeft, 698 times = [], 699 widths = [], 700 xPercents = [], 701 curIndex = 0, 702 pixelsPerSecond = (config.speed || 1) * 100, 703 snap = config.snap === false ? v => v : gsap.utils.snap(config.snap || 1), 704 totalWidth, curX, distanceToStart, distanceToLoop, item, i; 705 gsap.set(items, { 706 xPercent: (i, el) => { 707 let w = widths[i] = parseFloat(gsap.getProperty(el, "width", "px")); 708 xPercents[i] = snap(parseFloat(gsap.getProperty(el, "x", "px")) / w * 100 + gsap.getProperty(el, "xPercent"));
709 return xPercents[i]; 710 } 711 }); 712 gsap.set(items, { x: 0 }); 713 totalWidth = items[length - 1].offsetLeft + xPercents[length - 1] / 100 * widths[length - 1] - startX + items[length - 1].offsetWidth * gsap.getProperty(items[length - 1], "scaleX") + (parseFloat(config.paddingRight) || 0); 714 for (i = 0; i < length; i++) { 715 item = items[i]; 716 curX = xPercents[i] / 100 * widths[i]; 717 distanceToStart = item.offsetLeft + curX - startX; 718 distanceToLoop = distanceToStart + widths[i] * gsap.getProperty(item, "scaleX"); 719 tl.to(item, { xPercent: snap((curX - distanceToLoop) / widths[i] * 100), duration: distanceToLoop / pixelsPerSecond }, 0) 720 .fromTo(item, { xPercent: snap((curX - distanceToLoop + totalWidth) / widths[i] * 100) }, { xPercent: xPercents[i], duration: (curX - distanceToLoop + totalWidth - curX) / pixelsPerSecond, immediateRender: false }, distanceToLoop / pixelsPerSecond) 721 .add("label" + i, distanceToStart / pixelsPerSecond); 722 times[i] = distanceToStart / pixelsPerSecond; 723 } 724 function toIndex(index, vars) { 725 vars = vars || {}; 726 (Math.abs(index - curIndex) > length / 2) && (index += index > curIndex ? -length : length); 727 let newIndex = gsap.utils.wrap(0, length, index), 728 time = times[newIndex]; 729 if (time > tl.time() !== index > curIndex) { 730 vars.modifiers = { time: gsap.utils.wrap(0, tl.duration()) }; 731 time += tl.duration() * (index > curIndex ? 1 : -1); 732 } 733 curIndex = newIndex; 734 vars.overwrite = true; 735 return tl.tweenTo(time, vars); 736 } 737 tl.next = vars => toIndex(curIndex + 1, vars); 738 tl.previous = vars => toIndex(curIndex - 1, vars); 739 tl.current = () => curIndex; 740 tl.toIndex = (index, vars) => toIndex(index, vars); 741 tl.times = times; 742 tl.progress(1, true).progress(0, true); 743 if (config.reversed) { 744 tl.vars.onReverseComplete(); 745 tl.reverse(); 746 } 747 return tl; 748 } 749 } 750 751 function auregon_scroll_fixed_section() { 752 if (typeof ScrollTrigger === 'undefined' || typeof gsap === 'undefined') { 753 console.warn('GSAP or ScrollTrigger not loaded'); 754 return; 755 } 756 757 const fixed_section_top = $('.pxl-section-fix-top'); 758 const fixedSectionBottomSelector = ".pxl-section-fix-bottom"; 759 const hasFixedBottom = document.querySelector(fixedSectionBottomSelector); 760 if (fixed_section_top.length > 0 && hasFixedBottom) { 761 ScrollTrigger.matchMedia({ 762 "(min-width: 991px)": function () { 763 const pinnedSections = ['.pxl-section-fix-top']; 764 pinnedSections.forEach(className => { 765 gsap.to(fixedSectionBottomSelector, { 766 scrollTrigger: { 767 trigger: fixedSectionBottomSelector, 768 scrub: true, 769 pin: className, 770 pinSpacing: false, 771 start: 'top bottom', 772 end: "bottom top", 773 }, 774 }); 775 const bottomOverlaySelector = ".pxl-section-fix-bottom .pxl-section-overlay-color"; 776 if (!document.querySelector(bottomOverlaySelector)) { 777 return; 778 } 779 gsap.to(bottomOverlaySelector, { 780 scrollTrigger: { 781 trigger: fixedSectionBottomSelector, 782 scrub: true, 783 pin: className, 784 pinSpacing: false, 785 start: 'top bottom', 786 end: "bottom top", 787 }, 788 }); 789 }); 790 } 791 }); 792 } 793 794 const section_overlay_color = $('.pxl-section-overlay-color'); 795 const overlayScrollSelector = ".overlay-type-scroll"; 796 if (section_overlay_color.length > 0 && document.querySelector(overlayScrollSelector)) { 797 const space_top = section_overlay_color.data('space-top') || 0; 798 const space_left = section_overlay_color.data('space-left') || 0; 799 const space_right = section_overlay_color.data('space-right') || 0; 800 const space_bottom = section_overlay_color.data('space-bottom') || 0; 801 802 const radius_top = section_overlay_color.data('radius-top') || 0; 803 const radius_left = section_overlay_color.data('radius-left') || 0; 804 const radius_right = section_overlay_color.data('radius-right') || 0; 805 const radius_bottom = section_overlay_color.data('radius-bottom') || 0; 806
807 const overlay_radius = radius_top + 'px ' + radius_right + 'px ' + radius_bottom + 'px ' + radius_left + 'px '; 808 809 ScrollTrigger.matchMedia({ 810 "(min-width: 991px)": function () { 811 const pinnedSections = ['.pxl-bg-color-scroll']; 812 pinnedSections.forEach(className => { 813 gsap.to(overlayScrollSelector, { 814 scrollTrigger: { 815 trigger: ".pxl-bg-color-scroll", 816 scrub: true, 817 pinSpacing: false, 818 start: 'top bottom', 819 end: "bottom top", 820 }, 821 left: space_left + "px", 822 right: space_right + "px", 823 top: space_top + "px", 824 bottom: space_bottom + "px", 825 borderRadius: overlay_radiu
825s, 826 }); 827 }); 828 } 829 }); 830 } 831 } 832 function auregon_scroll_checkp($scope) { 833 $scope.find('.pxl-el-divider').each(function () { 834 var wcont1 = $(this); 835 var scrollHandler = null; 836 837 function checkScrollPosition() { 838 if (!wcont1.length || !wcont1.is(':visible')) return; 839 840 var pxl_scroll_top = $(window).scrollTop(), 841 viewportBottom = pxl_scroll_top + $(window).height(), 842 elementTop = wcont1.offset().top, 843 elementBottom = elementTop + wcont1.outerHeight(); 844 845 if (elementTop < viewportBottom && elementBottom > pxl_scroll_top) { 846 wcont1.addClass('visible'); 847 // Cleanup sau khi Äã visible 848 if (scrollHandler) { 849 $(window).off('scroll', scrollHandler); 850 scrollHandler = null; 851 } 852 } 853 } 854 855 checkScrollPosition(); 856 857 scrollHandler = function () { 858 checkScrollPosition(); 859 }; 860 $(window).on('scroll', scrollHandler); 861 862 // Cleanup khi element bá» remove 863 wcont1.on('remove', function () { 864 if (scrollHandler) { 865 $(window).off('scroll', scrollHandler); 866 } 867 }); 868 }); 869 } 870 871 function renderOrbit($scope) { 872 $scope.find(".orbit").each(function () { 873 const $orbit = $(this); 874 const settings = $orbit.data("settings") || {}; 875 const size = settings.size || 70; 876 const count = settings.count || 1; 877 const icons = Array.isArray(settings.icons) ? settings.icons : []; 878 const itemClasses = Array.isArray(settings.itemClasses) ? settings.itemClasses : []; 879 const iconClass = settings.iconClass || "green"; 880 const randomStart = !!settings.randomStart; 881 const useRandomColor = !!settings.randomColor; 882 const borderColor = settings.borderColor || null; 883 884 $orbit.css("--d", size + "%").empty(); 885 if (borderColor) { 886 $orbit.css("--orbit-border-color", borderColor); 887 } 888 889 const fragment = $(document.createDocumentFragment()); 890 891 const createItem = (idx) => { 892 const dur = (6 + Math.random() * 6).toFixed(1) + "s"; 893 const $rot = $("<div>", { class: "rotator" }).css("--dur", dur); 894 if (Math.random() > .5) $rot.addClass("reverse"); 895 896 let $item; 897 let iconChar = icons.length ? icons[idx % icons.length] : "â"; 898 const iconStr = (typeof iconChar === "string") ? iconChar.trim() : ""; 899 const isSvg = iconStr.startsWith("<svg"); 900 const isImg = iconStr.startsWith("<img"); 901 let classes = ["item", "icon", iconClass]; 902 if (isSvg) classes.push("is-svg"); 903 if (isImg) classes.push("is-media"); 904 // Add class from itemClasses array if available 905 if (itemClasses.length > 0) { 906 const itemClass = itemClasses[idx % itemClasses.length]; 907 if (itemClass && itemClass.trim() !== '') { 908 classes.push(itemClass); 909 } 910 } 911 $item = $("<div>", { 912 class: classes.join(" ") 913 }).html(iconChar); 914 915 return $rot.append($item); 916 }; 917 918 for (let i = 0; i < count; i++) { 919 fragment.append(createItem(i)); 920 } 921 922 $orbit.append(fragment); 923 924 const $rotators = $orbit.find(".rotator"); 925 const c = $rotators.length; 926 if (c) { 927 const baseAngles = Array.from({ length: c }, (_, idx) => (360 / c) * idx); 928 if (randomStart) { 929 for (let i = baseAngles.length - 1; i > 0; i--) { 930 const j = Math.floor(Math.random() * (i + 1)); 931 [baseAngles[i], baseAngles[j]] = [baseAngles[j], baseAngles[i]]; 932 } 933 } 934 $rotators.each(function (i) { 935 $(this).css("--start", baseAngles[i] + "deg"); 936 }); 937 938 const orbitWidth = $orbit.innerWidth(); 939 if (orbitWidth > 0) { 940 const radius = orbitWidth / 2; 941 const arcLength = (2 * Math.PI * radius) / c; 942 const maxIconSize = Math.max(28, Math.min(60, arcLength - 8)); 943 $orbit.css("--orbit-icon-size", `${maxIconSize}px`); 944 } 945 } 946 947 const randCol = () => '#' + Math.floor(Math.random() * 16777215).toString(16).padStart(6, '0'); 948 $orbit.find('.item').each(function () { 949 const $it = $(this); 950 let color = null; 951 952 if (useRandomColor) { 953 color = randCol(); 954 } 955 956 if (color && !$it.hasClass('is-media')) { 957 if ($it.hasClass('is-svg')) { 958 $it.find('svg, path, circle, rect, polygon, polyline, ellipse, line') 959 .css({ fill: color, color }); 960 } else { 961 $it.css('color', color); 962 } 963 } 964 }); 965 }); 966 } 967 968 function pxl_widget_sphere_handler($scope) { 969 const canvas = $scope.find(".pxl-sphere canvas"); 970 if (!canvas.length) return; 971 972 const sphereEl = $scope.find(".pxl-sphere"); 973 const size = parseInt(sphereEl.data("size")) || 950; 974 const radius = parseInt(sphereEl.data("radius")) || size * 0.5; 975 const sphereColor = sphereEl.data("color") || "rgba(255, 255, 255, 0.15)"; 976 const rotationType = sphereEl.data("rotation") || "y_axis"; 977 const rotationSpeed = parseFloat(sphereEl.data("speed")) || 0.005; 978 const customXSpeed = parseFloat(sphereEl.data("xspeed")) || 0.003; 979 const customYSpeed = parseFloat(sphereEl.data("yspeed")) || 0.005; 980 const tiltAngle = 981 ((parseFloat(sphereEl.data("tilt")) || -30) * Math.PI) / 180; 982 983 const ctx = canvas[0].getContext("2d"); 984 if (!ctx) return; 985 986 canvas[0].width = size; 987 canvas[0].height = size; 988 989 let angleX = tiltAngle; 990 let angleY = 0; 991 let animationId = null; 992 let isRunning = true; 993 994 function rotate(point, angleX, angleY) { 995 let cosX = Math.cos(angleX), 996 sinX = Math.sin(angleX);
997 let cosY = Math.cos(angleY), 998 sinY = Math.sin(angleY); 999 1000 let y = point.y * cosX - point.z * sinX; 1001 let z = point.y * sinX + point.z * cosX; 1002 let x = point.x * cosY - z * sinY; 1003 z = point.x * sinY + z * cosY; 1004 return { x, y, z }; 1005 } 1006 1007 function drawSphere() { 1008 ctx.clearRect(0, 0, canvas[0].width, canvas[0].height); 1009 ctx.strokeStyle = sphereColor; 1010 ctx.lineWidth = 1; 1011 const cx = canvas[0].width / 2; 1012 const cy = canvas[0].height / 2; 1013 1014 for ( 1015 let lat = -Math.PI / 2; 1016 lat <= Math.PI / 2; 1017 lat += Math.PI / 10 1018 ) { 1019 let circlePoints = []; 1020 for (let lon = 0; lon < 2 * Math.PI; lon += Math.PI / 20) { 1021 let x = Math.cos(lat) * Math.cos(lon); 1022 let y = Math.sin(lat); 1023 let z = Math.cos(lat) * Math.sin(lon); 1024 let rotatedPoint = rotate({ x, y, z }, angleX, angleY); 1025 circlePoints.push(rotatedPoint); 1026 } 1027 ctx.beginPath(); 1028 circlePoints.forEach((p, i) => { 1029 if (i === 0) { 1030 ctx.moveTo(cx + p.x * radius, cy + p.y * radius); 1031 } else { 1032 ctx.lineTo(cx + p.x * radius, cy + p.y * radius); 1033 } 1034 }); 1035 ctx.closePath(); 1036 ctx.stroke(); 1037 } 1038 1039 for (let lon = 0; lon < 2 * Math.PI; lon += Math.PI / 10) { 1040 let circlePoints = []; 1041 for ( 1042 let lat = -Math.PI / 2; 1043 lat <= Math.PI / 2; 1044 lat += Math.PI / 20 1045 ) { 1046 let x = Math.cos(lat) * Math.cos(lon); 1047 let y = Math.sin(lat); 1048 let z = Math.cos(lat) * Math.sin(lon); 1049 let rotatedPoint = rotate({ x, y, z }, angleX, angleY); 1050 circlePoints.push(rotatedPoint); 1051 } 1052 ctx.beginPath(); 1053 circlePoints.forEach((p, i) => { 1054 if (i === 0) { 1055 ctx.moveTo(cx + p.x * radius, cy + p.y * radius); 1056 } else { 1057 ctx.lineTo(cx + p.x * radius, cy + p.y * radius); 1058 } 1059 }); 1060 ctx.stroke(); 1061 } 1062 } 1063 1064 function updateRotation() { 1065 switch (rotationType) { 1066 case "y_axis": 1067 angleY += rotationSpeed; 1068 break; 1069 case "x_axis": 1070 angleX += rotationSpeed; 1071 break; 1072 case "both_axis": 1073 angleX += rotationSpeed; 1074 angleY += rotationSpeed; 1075 break; 1076 case "custom": 1077 angleX += customXSpeed; 1078 angleY += customYSpeed; 1079 break; 1080 } 1081 } 1082 1083 function animate() { 1084 if (!isRunning) return; 1085 updateRotation(); 1086 drawSphere(); 1087 animationId = requestAnimationFrame(animate); 1088 } 1089 1090 animate(); 1091 1092 // Cleanup khi element bá» remove 1093 sphereEl.on('remove', function () { 1094 isRunning = false; 1095 if (animationId) { 1096 cancelAnimationFrame(animationId); 1097 } 1098 }); 1099 1100 // Lưu reference Äá» có thá» cleanup từ bên ngoà i 1101 sphereEl.data('sphere-animation-id', animationId); 1102 sphereEl.data('sphere-is-running', isRunning); 1103 }; 1104 1105 function auregon_parallax_bg() { 1106 // Kiá»m tra plugin parallaxBackground có tá»n tại 1107 if (typeof $.fn.parallaxBackground === 'undefined') { 1108 console.warn('parallaxBackground plugin not loaded'); 1109 return; 1110 } 1111 1112 $(document).find('.pxl-parallax-background').parallaxBackgroun
1112d({ 1113 event: 'mouse_move', 1114 animation_type: 'shift', 1115 animate_duration: 2 1116 }); 1117 $(document).find('.pxl-pll-basic').parallaxBackground(); 1118 $(document).find('.pxl-pll-rotate').parallaxBackground({ 1119 animation_type: 'rotate', 1120 zoom: 50, 1121 rotate_perspective: 500 1122 }); 1123 $(document).find('.pxl-pll-mouse-move').parallaxBackground({ 1124 event: 'mouse_move', 1125 animation_type: 'shift', 1126 animate_duration: 2 1127 }); 1128 $(document).find('.pxl-pll-mouse-move-rotate').parallaxBackground({ 1129 event: 'mouse_move', 1130 animation_type: 'rotate', 1131 animate_duration: 1, 1132 zoom: 70, 1133 rotate_perspective: 1000 1134 }); 1135 1136 $(document).find('.pxl-bg-prx-effect-pinned-zoom-clipped').each(function (index, el) { 1137 // Kiá»m tra GSAP và ScrollTrigger có tá»n tại 1138 if (typeof gsap === 'undefined' || typeof ScrollTrigger === 'undefined') { 1139 return; 1140 } 1141 1142 var $el = $(el); 1143 const clipped_bg_pinned = $el.find('.clipped-bg-pinned'); 1144 const clipped_bg = $el.find('.clipped-bg'); 1145 1146 if (!clipped_bg_pinned.length || !clipped_bg.length) return; 1147 1148 var clipped_bg_animation = gsap.to(clipped_bg, { 1149 clipPath: 'inset(0% 0% 0%)', 1150 scale: 1, 1151 duration: 1, 1152 ease: 'Linear.easeNone' 1153 }); 1154 1155 var clipped_bg_scene = ScrollTrigger.create({ 1156 trigger: clipped_bg_pinned, 1157 start: function () { 1158 const start_pin = 350; 1159 return "top +=" + start_pin; 1160 }, 1161 end: function () { 1162 const end_pin = 0; 1163 return "+=" + end_pin; 1164 }, 1165 animation: clipped_bg_animation, 1166 scrub: 1, 1167 pin: true, 1168 pinSpacing: false, 1169 }); 1170 1171 function set_clipped_bg_wrapper_height() { 1172 if (typeof gsap !== 'undefined' && clipped_bg.length) { 1173 gsap.set(clipped_bg, { height: window.innerHeight }); 1174 } 1175 } 1176 1177 var resizeHandler = set_clipped_bg_wrapper_height; 1178 window.addEventListener('resize', resizeHandler); 1179 1180 // Cleanup khi element bá» remove 1181 $el.on('remove', function () { 1182 window.removeEventListener('resize', resizeHandler); 1183 if (clipped_bg_scene && typeof ScrollTrigger !== 'undefined') { 1184 clipped_bg_scene.kill(); 1185 } 1186 }); 1187 }); 1188 1189 1190 1191 $(document).find('.pxl-bg-prx-effect-pinned-circle-zoom-clipped').each(function (index, el) { 1192 // Kiá»m tra GSAP và ScrollTrigger có tá»n tại 1193 if (typeof gsap === 'undefined' || typeof ScrollTrigger === 'undefined') { 1194 return; 1195 } 1196 1197 const $el = $(el); 1198 1199 var svg = $el.find('.circle-zoom-mask-svg'); 1200 var img = $el.find('.clipped-bg-circle-pinned'); 1201 let circle = $el.find('.circle-zoom'); 1202 1203 // Kiá»m tra null/undefined 1204 if (!circle.length || !circle[0] || !img.length || !img[0]) return; 1205 1206 let radiusAttr = circle[0].getAttribute("r"); 1207 let radius = radiusAttr ? parseFloat(radiusAttr) : 0;
1208 if (isNaN(radius)) radius = 0; 1209 1210 gsap.set(img[0], { 1211 scale: 2 1212 }); 1213 1214 var tl = gsap.timeline({ 1215 scrollTrigger: { 1216 trigger: el, 1217 start: "50% 90%", 1218 end: "80% 100%", 1219 scrub: 2, 1220 }, 1221 defaults: { 1222 duration: 2 1223 } 1224 }) 1225 .to(circle[0], { 1226 attr: { 1227 r: () => radius 1228 } 1229 }, 0) 1230 .to(img[0], { 1231 scale: 1, 1232 }, 0) 1233 .to(".circle-inner-layer", { 1234 alpha: 0, 1235 ease: "power1.in", 1236 duration: 1 - 0.25 1237 }, 0.25); 1238 1239 1240 window.addEventListener("load", auregon_circle_init); 1241 window.addEventListener("resize", auregon_circle_resize); 1242 1243 function auregon_circle_init() { 1244 auregon_circle_resize(); 1245 } 1246 1247 function auregon_circle_resize() { 1248 if (typeof gsap === 'undefined' || typeof ScrollTrigger === 'undefined') return; 1249 1250 tl.progress(0); 1251 var rect = $(el)[0].getBoundingClientRect(); 1252 const rectWidth = rect.width; 1253 const rectHeight = rect.height; 1254 const dx = rectWidth / 2; 1255 const dy = rectHeight / 2; 1256 radius = Math.sqrt(dx * dx + dy * dy); 1257 1258 tl.invalidate(); 1259 ScrollTrigger.refresh(); 1260 } 1261 1262 // Cleanup khi element bá» remove 1263 $el.on('remove', function () { 1264 window.removeEventListener("load", auregon_circle_init); 1265 window.removeEventListener("resize", auregon_circle_resize); 1266 if (tl && typeof ScrollTrigger !== 'undefined') { 1267 tl.kill(); 1268 } 1269 }); 1270 }); 1271 } 1272 1273 function auregon_logo_marquee($scope) { 1274 const logos = $scope.find('.pxl-item--marquee'); 1275 gsap.set(logos, { autoAlpha: 1 }) 1276 1277 logos.each(function (index, el) { 1278 gsap.set(el, { xPercent: 100 * index }); 1279 }); 1280 1281 if (logos.length > 2) { 1282 const logosWrap = gsap.utils.wrap(-100, ((logos.length - 1) * 100)); 1283 const durationNumber = logos.data('duration'); 1284 const slipType = logos.data('slip-type'); 1285 var slipResult = `-=${logos.length * 100}`; 1286 if (slipType == 'right') { 1287 slipResult = `+=${logos.length * 100}`; 1288 } 1289 gsap.to(logos, { 1290 xPercent: slipResult, 1291 duration: durationNumber, 1292 repeat: -1, 1293 ease: 'none', 1294 modifiers: { 1295 xPercent: xPercent => logosWrap(parseFloat(xPercent)) 1296 } 1297 }); 1298 } 1299 } 1300 1301 function auregon_progressbar_handler($scope) { 1302 if (!window.elementorFrontend || typeof elementorFrontend.waypoint !== 'function') return; 1303 1304 elementorFrontend.waypoint($scope.find('.pxl-progress-bar'), function () { 1305 if (typeof $(this).progressbar === 'function') { 1306 $(this).progressbar(); 1307 } 1308 }); 1309 elementorFrontend.waypoint($scope.find('.pxl-progressbar.circle'), function () { 1310 var $progressbarElem = $scope.find(".pxl-progressbar-container"), 1311 $progressbarElemInner = $scope.find(".pxl-progressbar-inner"), 1312 settings = $progressbarElem.data("settings"); 1313 1314 // Kiá»m tra settings có tá»n tại 1315 if (!settings || typeof settings !== 'object') return; 1316 1317 var length = settings.circle_percent || 0, 1318 number = settings.circle_number || 0, 1319 prefix = settings.prefix || '', 1320 suffix = settings.suffix || '', 1321 speed = settings.speed || 1000; 1322 1323 if (length > 100) 1324 length = 100; 1325 1326 $progressbarElem.prop({ 1327 'percent': 0 1328 }).animate({ 1329 percent: number 1330 }, { 1331 duration: speed, 1332 easing: 'linear', 1333 step: function (percent) { 1334 var rotate = (100 - percent); 1335 var rotate1 = (percent + 8); 1336 $progressbarElem.find(".js-progress-bar").css('stroke-dashoffset', rotate); 1337 $progressbarElem.find(".js-progress-bar1").css('stroke-dashoffset', rotate1); 1338 } 1339 }); 1340 1341 $progressbarElemInner.prop({ 1342 'counter': 0, 1343 }).animate({ 1344 counter: number, 1345 }, { 1346 duration: speed, 1347 easing: 'linear', 1348 step: function (counter) { 1349 var $numberEl = $progressbarElem.find(".progress-number"); 1350 if ($numberEl.length) { 1351 $numberEl.text(Math.ceil(counter)); 1352 } else { 1353 $progressbarElem.find(".progress-percentage").text(prefix + Math.
1353ceil(counter) + suffix); 1354 } 1355 } 1356 }); 1357 1358 }); 1359 } 1360 1361 function auregon_care_orbit_tabs_handler($scope) { 1362 1363 var px1209_width = $(window).width(); 1364 1365 const root = $scope && $scope[0] ? $scope[0] : ($scope || document); 1366 const svgTexts = root.querySelectorAll('.svg-tab-text'); 1367 const tabColumns = root.querySelectorAll('.care-orbit-col.tab-pane'); 1368 const svgEl = root.querySelector('.pxl-care-orbit-tabs .pxl-tabs--title svg'); 1369 1370 // Chá» chạy dots cho mà n hình lá»n 1371 let dotsLeft = null; 1372 let dotsRight = null; 1373 if (px1209_width >= 1281) { 1374 dotsLeft = svgEl ? svgEl.querySelector('.orbit-dots-left') : null; 1375 dotsRight = svgEl ? svgEl.querySelector('.orbit-dots-right') : null; 1376 1377 if (!svgEl || !dotsLeft || !dotsRight) { 1378 return; 1379 } 1380 } 1381 1382 // Kiá»m tra svgEl có tá»n tại (cần thiết cho cả trưá»ng hợp width < 1281) 1383 if (!svgEl) return; 1384 1385 const vb = svgEl.viewBox && svgEl.viewBox.baseVal ? svgEl.viewBox.baseVal : null; 1386 if (!vb || vb.width === 0 || vb.height === 0) return; 1387 1388 const centerX = vb.x + vb.width / 2; 1389 const centerY = vb.y + vb.height / 2; 1390 const outerR = Math.min(vb.width, vb.height) / 2; 1391 const inset = 3; 1392 const dotRpx = 9.5; 1393 1394 function pxToVb() { 1395 const rect = svgEl.getBoundingClientRect(); 1396 return { 1397 sx: vb.width / rect.width, 1398 sy: vb.height / rect.height 1399 }; 1400 } 1401 1402 function clearDots() { 1403 dotsLeft.innerHTML = ''; 1404 dotsRight.innerHTML = ''; 1405 } 1406 1407 let rafId = null; 1408 function schedulePlaceDots() { 1409 if (rafId) cancelAnimationFrame(rafId); 1410 rafId = requestAnimationFrame(placeDots); 1411 } 1412 1413 function placeDots() { 1414 // Chá» chạy dots nếu có dotsLeft và dotsRight 1415 if (!dotsLeft || !dotsRight) return; 1416 1417 clearDots(); 1418 1419 const activePanes = root.querySelectorAll('.pxl-care-orbit-tabs .tab-pane.active'); 1420 if (!activePanes.length) return; 1421 1422 const rect = svgEl.getBoundingClientRect(); 1423 const { sx, sy } = pxToVb(); 1424 1425 const dotRv = dotRpx * ((sx + sy) / 2); 1426 1427 activePanes.forEach(pane => { 1428 const isLeft = pane.classList.contains('care-orbit-col-left'); 1429 const entries = pane.querySelectorAll('.entry-body'); 1430 1431 entries.forEach(entry => { 1432 const r = entry.getBoundingClientRect(); 1433 const yScreen = r.top + r.height / 2; 1434 1435 const ySvg = (yScreen - rect.top) * sy + vb.y; 1436 1437 const dy = ySvg - centerY; 1438 const clamp = Math.max(outerR * outerR - dy * dy, 0); 1439 const xOn = Math.sqrt(clamp); 1440 const xSvg = isLeft ? (centerX - xOn + inset) : (centerX + xOn - inset); 1441 1442 const g = isLeft ? dotsLeft : dotsRight; 1443 const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle'); 1444 circle.setAttribute('cx', xSvg); 1445 circle.setAttribute('cy', ySvg); 1446 circle.setAttribute('r', dotRv); 1447 circle.setAttribute('fill', '#192273'); 1448 circle.setAttribute('stroke', '#D3DDFF'); 1449 circle.setAttribute('stroke-width', (2.5 * ((sx + sy) / 2))); 1450 circle.setAttribute('vector-effect', 'non-scaling-stroke'); 1451 g.appendChild(circle); 1452 }); 1453 }); 1454 } 1455
1456 svgTexts.forEach(svgText => { 1457 svgText.addEventListener('click', function () { 1458 const targetId = this.getAttribute('data-target'); 1459 1460 svgTexts.forEach(t => t.classList.remove('active')); 1461 this.classList.add('active'); 1462 1463 tabColumns.forEach(c => { 1464 c.classList.remove('active'); 1465 c.style.display = 'none'; 1466 }); 1467 1468 const matchCols = root.querySelectorAll('.care-orbit-col.tab-pane[data-tab="' + targetId + '"]'); 1469 matchCols.forEach(c => { 1470 c.classList.add('active'); 1471 c.style.display = 'flex'; 1472 }); 1473 1474 // Chá» gá»i schedulePlaceDots nếu có dots 1475 if (dotsLeft && dotsRight) { 1476 schedulePlaceDots(); 1477 } 1478 }); 1479 }); 1480 1481 // Chá» setup dots observers nếu có dots 1482 let ro = null; 1483 if (dotsLeft && dotsRight) { 1484 ro = new ResizeObserver(schedulePlaceDots); 1485 ro.observe(svgEl); 1486 const contentHost = root.querySelector('.pxl-care-orbit-tabs'); 1487 if (contentHost) ro.observe(contentHost); 1488 1489 if (document.fonts && document.fonts.ready) { 1490 document.fonts.ready.then(schedulePlaceDots).catch(() => { }); 1491 } 1492 1493 window.addEventListener('resize', schedulePlaceDots, { passive: true }); 1494 1495 requestAnimationFrame(schedulePlaceDots); 1496 } 1497 1498 return function cleanup() { 1499 if (dotsLeft && dotsRight) { 1500 window.removeEventListener('resize', schedulePlaceDots); 1501 if (ro) ro.disconnect(); 1502 if (rafId) cancelAnimationFrame(rafId); 1503 clearDots(); 1504 } 1505 }; 1506 } 1507 1508 function auregon_post_carousel_handler($scope) { 1509 const rootEl = $scope && $scope[0] ? $scope[0] : document; 1510 const stepsContainer = rootEl.querySelector(".pxl-grid-filter.style-3"); 1511 const pill = rootEl.querySelector("#pxl-item-step-active-pill"); 1512 const steps = Array.from(rootEl.querySelectorAll(".filter-item")); 1513 1514 if (!stepsContainer || !pill || !steps.length) return; 1515 1516 const getActiveIndex = () => { 1517 const i = steps.findIndex((b) => b.classList.contains("active")); 1518 return i === -1 ? 0 : i; 1519 }; 1520 1521 const setActive = (index) => { 1522 index = Math.min(Math.max(index, 0), steps.length - 1); 1523 steps.forEach((b) => b.classList.remove("active")); 1524 steps[index].classList.add("active"); 1525 updatePill(index); 1526 }; 1527 1528 const updatePill = (index = getActiveIndex()) => { 1529 index = Math.min(Math.max(index, 0), steps.length - 1); 1530 const containerRect = stepsContainer.getBoundingClientRect(); 1531 const stepRect = steps[index].getBoundingClientRect(); 1532 const stepWidth = stepRect.width || steps[index].offsetWidth || 0; 1533 const translateX = stepRect.left - containerRect.left; 1534 1535 pill.style.width = `${Math.max(0, stepWidth - 2)}px`; 1536 pill.style.transform = `translateX(${translateX}px)`; 1537 }; 1538 1539 steps.forEach((btn, index) => { 1540 btn.addEventListener("click", () => {
1541 setActive(index); 1542 }); 1543 }); 1544 1545 setActive(getActiveIndex()); 1546 1547 const onResize = () => { 1548 if (rootEl !== document && !rootEl.isConnected) { 1549 window.removeEventListener("resize", onResize); 1550 return; 1551 } 1552 updatePill(); 1553 }; 1554 1555 window.addEventListener("resize", onResize, { passive: true }); 1556 1557 } 1558 1559 // function auregon_text_carousel_style2_handler($scope) { 1560 // if (typeof gsap === 'undefined' || typeof ScrollTrigger === 'undefined') { 1561 // console.warn('GSAP or ScrollTrigger not loaded'); 1562 // return; 1563 // } 1564 1565 // const widget = $scope.find('.pxl-text-carousel3.style-2'); 1566 // if (!widget.length) return; 1567 1568 // const steps = widget.find('.pxl-item--step'); 1569 // const cards = widget.find('.pxl-item--inner'); 1570 1571 // if (!steps.length || !cards.length) return; 1572 1573 // // Initialize first item active 1574 // steps.removeClass('is-active'); 1575 // cards.removeClass('is-active'); 1576 // steps.first().addClass('is-active'); 1577 // cards.first().addClass('is-active'); 1578 1579 // // Pin the section 1580 // ScrollTrigger.create({ 1581 // trigger: widget, 1582 // start: "top 20%", 1583 // end: "+=" + (steps.length * 500), // Adjust scroll distance per step 1584 // pin: true, 1585 // scrub: true, 1586 // onUpdate: (self) => { 1587 // const progress = self.progress; 1588 // const totalSteps = steps.length; 1589 // let activeIndex = Math.floor(progress * totalSteps); 1590 1591 // // Ensure index is within bounds 1592 // if (activeIndex >= totalSteps) activeIndex = totalSteps - 1; 1593 1594 // // Update active classes if changed 1595 // if (!steps.eq(activeIndex).hasClass('is-active')) { 1596 // steps.removeClass('is-active'); 1597 // cards.removeClass('is-active'); 1598 1599 // steps.eq(activeIndex).addClass('is-active'); 1600 // cards.eq(activeIndex).addClass('is-active'); 1601 // } 1602 // } 1603 // }); 1604 // } 1605 1606function auregon_text_carousel_handler($scope) { 1607 const root = $scope && $scope[0] ? $scope[0] : document; 1608 1609 const stepsContainer = root.querySelector(".pxl-item--steps"); 1610 const pill = 1611 root.querySelector("#pxl-item-step-active-pill") || 1612 root.querySelector(".pxl-item-step-active-pill"); 1613 1614 const steps = Array.from(root.querySelectorAll(".pxl-item--step")); 1615 const cards = Array.from(root.querySelectorAll(".pxl-item--inner")); 1616 1617 if (!stepsContainer || !pill || !steps.length || !cards.length) return; 1618 1619 // Prevent duplicate init (Elementor re-render) 1620 if (root.__auregonTextCarouselDestroy) { 1621 root.__auregonTextCarouselDestroy(); 1622 root.__auregonTextCarouselDestroy = null; 1623 } 1624 1625 // ---------------- Utils ---------------- 1626 const clamp = (n, min, max) => Math.min(Math.max(n, min), max); 1627 1628 const stepIdByIndex = (i) => steps[i]?.getAttribute("data-step") || null; 1629 1630 const findIndexByStepId = (stepId) => { 1631 let i = steps.findIndex((s) => s.getAttribute("data-step") === stepId); 1632 if (i !== -1) return i; 1633 i = cards.findIndex((c) => c.getAttribute("data-step") === stepId); 1634 return i; 1635 }; 1636 1637 const getActiveIndex = () => { 1638 const i = steps.findIndex((s) => s.classList.contains("is-active")); 1639 return i === -1 ? 0 : i; 1640 }; 1641 1642 // Measure once per âupdate cycleâ 1643 let metrics = null; 1644 const measure = () => { 1645 const containerRect = stepsContainer.getBoundingClientRect(); 1646 const firstRect = steps[0].getBoundingClientRect(); 1647 1648 const stepWidth = firstRect.width || steps[0].offsetWidth || 0; 1649 1650 // Compute gap: prefer actual distance between step[0] and step[1] 1651 let gapPx = 6; 1652 if (steps.length > 1) { 1653 const secondRect = steps[1].getBoundingClientRect(); 1654 const raw = secondRect.left - firstRect.left - stepWidth; 1655 if (raw > 0) gapPx = raw; 1656 } else { 1657 const cs = getComputedStyle(stepsContainer); 1658 const g = parseFloat(cs.columnGap || cs.gap || "6"); 1659 if (!Number.isNaN(g)) gapPx = g; 1660 } 1661 1662 const baseOffset = firstRect.left - containerRect.left; 1663 metrics = { stepWidth, gapPx, baseOffset }; 1664 }; 1665 1666 const updatePill = (index = getActiveIndex()) => { 1667 index = clamp(index, 0, steps.length - 1); 1668 if (!metrics) measure(); 1669 1670 const { stepWidth, gapPx, baseOffset } = metrics; 1671 const translateX = baseOffset + index * (stepWidth + gapPx); 1672 1673 pill.style.width = `${Math.max(0, stepWidth - 2)}px`; 1674 pill.style.transform = `translateX(${translateX}px)`; 1675 }; 1676 1677 const setActive = (index) => { 1678 index = clamp(index, 0, steps.length - 1); 1679 const stepId = stepIdByIndex(index); 1680 if (!stepId) return; 1681 1682 steps.forEach((s, i) => s.classList.toggle("is-active", i === index)); 1683 cards.forEach((c) => 1684 c.classList.toggle("is-active", c.getAttribute("data-step") === stepId) 1685 ); 1686 1687 updatePill(index); 1688 }; 1689 1690 const activateByStepId = (stepId) => { 1691 if (!stepId) return; 1692 const index = findIndexByStepId(stepId); 1693 if (index === -1) return; 1694 setActive(index); 1695 }; 1696 1697 // ---------------- Init ---------------- 1698 const initialStepId = 1699 steps.find((s) => s.classList.contains("is-active"))?.getAttribute("data-step") || 1700 cards.find((c) => c.classList.contains("is-active"))?.getAttribute("data-step") || 1701 steps[0].getAttribute("data-step") || 1702 cards[0].getAttribute("data-step"); 1703 1704 steps.forEach((s) => s.classList.remove("is-active"));
1705 cards.forEach((c) => c.classList.remove("is-active")); 1706 1707 metrics = null; // ensure fresh measurement 1708 if (initialStepId) activateByStepId(initialStepId); 1709 else setActive(0); 1710 1711 // ---------------- Events ---------------- 1712 const onStepClick = (e) => { 1713 const step = e.target.closest(".pxl-item--step"); 1714 if (!step || !stepsContainer.contains(step)) return; 1715 activateByStepId(step.getAttribute("data-step")); 1716 }; 1717 stepsContainer.addEventListener("click", onStepClick); 1718 1719 let lastStepId = null; 1720 const cardEnterHandlers = new Map(); 1721 1722 cards.forEach((card) => { 1723 const fn = () => { 1724 const stepId = card.getAttribute("data-step"); 1725 if (!stepId || stepId === lastStepId) return; 1726 lastStepId = stepId; 1727 activateByStepId(stepId); 1728 }; 1729 cardEnterHandlers.set(card, fn); 1730 card.addEventListener("pointerenter", fn, { passive: true }); 1731 }); 1732 1733 const onResize = () => { 1734 if (root !== document && !root.isConnected) return; 1735 metrics = null; // re-measure on next update 1736 updatePill(); 1737 }; 1738 window.addEventListener("resize", onResize, { passive: true }); 1739 1740 // Layout settle (fonts/Elementor) 1741 const t = setTimeout(() => { 1742 metrics = null; 1743 updatePill(); 1744 }, 0); 1745 1746 // ---------------- Destroy ---------------- 1747 root.__auregonTextCarouselDestroy = () => { 1748 stepsContainer.removeEventListener("click", onStepClick); 1749 1750 cards.forEach((card) => { 1751 const fn = cardEnterHandlers.get(card); 1752 if (fn) card.removeEventListener("pointerenter", fn); 1753 }); 1754 cardEnterHandlers.clear(); 1755 1756 window.removeEventListener("resize", onResize); 1757 clearTimeout(t); 1758 1759 metrics = null; 1760 }; 1761} 1762 1763 function setupGlowAnimation($scope) { 1764 var $wrapper = $scope.find(".pxl-section-mouse-follower"); 1765 if (!$wrapper.length) return; 1766 1767 // Check if already initialized 1768 if ($wrapper.data("glow-animation-initialized")) return; 1769 1770 var $mouseGlow = $wrapper.find(".pxl-section-mouse-follower-shape1"); 1771 var $blobPurple = $wrapper.find(".pxl-section-mouse-follower-shape2"); 1772 1773 // Create HTML elements if they don't exist 1774 if (!$mouseGlow.length) { 1775 $mouseGlow = $('<div class="pxl-section-mouse-follower-shape1"></div>'); 1776 $wrapper.append($mouseGlow); 1777 } 1778 if (!$blobPurple.length) { 1779 $blobPurple = $('<div class="pxl-section-mouse-follower-shape2"></div>'); 1780 $wrapper.append($blobPurple); 1781 } 1782 1783 var state = { 1784 glowIntensity: 0, 1785 mouseX: 0, 1786 mouseY: 0, 1787 isActive: false, 1788 rafId: null, 1789 isRunning: true 1790 }; 1791 1792 // Unique namespace for this wrapper 1793 var namespace = "pxlGlow_" + ($wrapper[0] ? $wrapper[0].getAttribute('data-id') || Date.now() : Date.now()); 1794 1795 function handleMouseMove(e) { 1796 if (!state.isRunning) return; 1797 1798 var rect = $wrapper[0] ? $wrapper[0].getBoundingClientRect() : null; 1799 if (!rect) return; 1800 1801 var inside = e.clientX >= rect.left && e.clientX <= rect.right && e.clientY >= rect.top && e.clientY <= rect.bottom; 1802 if (!inside) { 1803 state.isActive = false; 1804 $mouseGlow.css("opacity", 0); 1805 return; 1806 } 1807 1808 state.isActive = true; 1809 state.mouseX = e.clientX - rect.left; 1810 state.mouseY = e.clientY - rect.top; 1811 1812 $mouseGlow.css({ 1813 left: state.mouseX + "px", 1814 top: state.mouseY + "px", 1815 opacity: 1 1816 }); 1817 $blobPurple.css("opacity", 1); 1818 } 1819 1820 // Bind mouse move event with unique namespace 1821 $(document).on("mousemove." + namespace, handleMouseMove); 1822 1823 function animate() { 1824 if (!state.isRunning) return; 1825 1826 state.glowIntensity = (state.glowIntensity + 0.06) % (Math.PI * 2); 1827 1828 if (!state.isActive) { 1829 state.rafId = requestAnimationFrame(animate); 1830 return; 1831 } 1832 1833 var scale = 1 + Math.sin(state.glowIntensity) * 0.2; 1834 $mouseGlow.css("transform", "translate(-50%, -50%) scale(" + scale + ")"); 1835
1836 var blobScale = 1 + Math.cos(state.glowIntensity) * 0.15; 1837 $blobPurple.css("transform", "translate(-50%, -50%) scale(" + blobScale + ")"); 1838 1839 state.rafId = requestAnimationFrame(animate); 1840 } 1841 1842 // Start animation 1843 state.rafId = requestAnimationFrame(animate); 1844 1845 // Mark as initialized 1846 $wrapper.data("glow-animation-initialized", true); 1847 1848 // Cleanup function 1849 $wrapper.data("glow-animation-cleanup", function () { 1850 state.isRunning = false; 1851 if (state.rafId) { 1852 cancelAnimationFrame(state.rafId); 1853 state.rafId = null; 1854 } 1855 $(document).off("mousemove." + namespace); 1856 $wrapper.removeData("glow-animation-initialized"); 1857 $wrapper.removeData("glow-animation-cleanup"); 1858 }); 1859 1860 // Cleanup when element is removed 1861 $wrapper.on('remove', function () { 1862 var cleanup = $wrapper.data("glow-animation-cleanup"); 1863 if (cleanup && typeof cleanup === 'function') { 1864 cleanup(); 1865 } 1866 }); 1867 } 1868 1869 function auregon_text_hover_image($scope) { 1870 1871 if ($scope.find('.pxl-awards-list,.pxl-portfolio-grid-layout3').length <= 0) return; 1872 var mouseX = 0, 1873 mouseY = 0; 1874 1875 $scope.find('.pxl-awards-list .content-inner,.pxl-portfolio-grid-layout3 .pxl-grid-inner').mousemove(function (e) { 1876 var offset = $(this).offset(); 1877 mouseX = (e.pageX - offset.left); 1878 mouseY = (e.pageY - offset.top); 1879 1880 }); 1881 gsap.utils.toArray(".pxl-awards-list .fade-in-up, .pxl-portfolio-grid-layout3 .fade-in-up").forEach((element) => { 1882 gsap.from(element, { 1883 scrollTrigger: { 1884 trigger: element, 1885 start: "top 80%", 1886 toggleActions: "play none none none" 1887 }, 1888 duration: 1, 1889 opacity: 0, 1890 y: 80, 1891 ease: "power4.out" 1892 }); 1893 }); 1894 1895 $scope.find('.pxl-awards-list .pxl--item,.pxl-portfolio-grid-layout3 .pxl-grid-item').on("mouseenter", function () { 1896 $(this).removeClass('deactive').addClass('active'); 1897 var target = $(this).attr('data-target'); 1898 $(this).closest('.content-inner,.pxl-grid-inner').find(target).removeClass('deactive').addClass('active'); 1899 }); 1900 $scope.find('.pxl-awards-list .pxl--item,.pxl-portfolio-grid-layout3 .pxl-grid-item').on("mouseleave", function () { 1901 $(this).addClass('deactive').removeClass('active'); 1902 var target = $(this).attr('data-target'); 1903 $(this).closest('.content-inner,.pxl-grid-inner').find(target).addClass('deactive').removeClass('active'); 1904 }); 1905 const s = { 1906 x: window.innerWidth / 2, 1907 y: window.innerHeight / 2 1908 }, 1909 t = gsap.quickSetter($scope.find('.pxl-awards-list .content-inner,.pxl-portfolio-grid-layout3 .pxl-grid-inner'), "css"), 1910 e = gsap.quickSetter($scope.find('.pxl-awards-list .content-inner,.pxl-portfolio-grid-layout3 .pxl-grid-inner'), "css"); 1911 1912 gsap.ticker.add((() => { 1913 const o = .15, 1914 i = 1 - Math.pow(.85, gsap.ticker.deltaRatio()); 1915 s.x += (mouseX - s.x) * i, 1916 s.y += (mouseY - s.y) * i, 1917 t({ 1918 "--pxl-mouse-x": `${s.x}px` 1919 }), e({ 1920 "--pxl-mouse-y": `${s.y}px` 1921 }) 1922 })) 1923 } 1924 1925 1926 $(document).ready(function () { 1927 if (window.elementorFrontend && typeof elementorFrontend.waypoint === 'function') { 1928 auregon_animation_handler(); 1929 } 1930 auregon_section_divider_glow(); 1931 auregon_border_glow(); 1932 }); 1933 1934 $(window).on('elementor/frontend/init', function () { 1935 // BỠsung waypoint nếu thiếu 1936 auregon_polyfill_waypoint(); 1937 elementorFrontend.hooks.addAction('frontend/element_ready/global', function ($scope) { 1938 auregon_scroll_checkp($scope); 1939 auregon_animation_handler($scope); 1940 auregon_section_divider_glow($scope); 1941 auregon_border_glow($scope); 1942 renderOrbit($scope); 1943 setupGlowAnimation($scope); 1944 }); 1945 auregon_section_start_render(); 1946 auregon_parallax_bg(); 1947 auregon_css_inline_js(); 1948 auregon_section_before_render(); 1949 auregon_zoom_point(); 1950 auregon_scroll_fixed_section(); 1951 elementorFrontend.hooks.addAction('frontend/element_ready/pxl_contact_form.default', PXL_Icon_Contact_Form); 1952 elementorFrontend.hooks.addAction('frontend/element_ready/pxl_heading.default', function ($scope) { 1953 auregon_split_text($scope); 1954 }); 1955 elementorFrontend.hooks.addAction('frontend/element_ready/pxl_post_c
1955arousel.default', function ($scope) { 1956 auregon_post_carousel_handler($scope); 1957 }); 1958 elementorFrontend.hooks.addAction('frontend/element_ready/pxl_sphere.default', function ($scope) { 1959 pxl_widget_sphere_handler($scope); 1960 }); 1961 elementorFrontend.hooks.addAction('frontend/element_ready/pxl_text_carousel.default', function ($scope) { 1962 auregon_text_carousel_handler($scope); 1963 // auregon_text_carousel_style2_handler($scope); 1964 }); 1965 elementorFrontend.hooks.addAction('frontend/element_ready/pxl_post_slip.default', function ($scope) { 1966 auregon_split_text($scope); 1967 }); 1968 elementorFrontend.hooks.addAction('frontend/element_ready/pxl_section_scale.default', function ($scope) { 1969 auregon_scroll_trigger($scope); 1970 }); 1971 elementorFrontend.hooks.addAction('frontend/element_ready/pxl_progressbar.default', function ($scope) { 1972 auregon_progressbar_handler($scope); 1973 }); 1974 elementorFrontend.hooks.addAction('frontend/element_ready/pxl_logo_marquee.default', function ($scope) { 1975 auregon_logo_marquee($scope); 1976 }); 1977 elementorFrontend.hooks.addAction('frontend/element_ready/pxl_awards_list.default', function ($scope) { 1978 auregon_text_hover_image($scope); 1979 }); 1980 1981 elementorFrontend.hooks.addAction('frontend/element_ready/pxl_text_marquee.default', function ($scope) { 1982 auregon_text_marquee($scope); 1983 }); 1984 elementorFrontend.hooks.addAction('frontend/element_ready/pxl_care_orbit_tabs.default', function ($scope) { 1985 setTimeout(function () { 1986 auregon_care_orbit_tabs_handler($scope); 1987 }, 0); 1988 }); 1989 }); 1990})(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.