1(function($){ 2 3 function readCols($root){ 4 return { 5 d: parseInt($root.attr('data-cols-d') || '4', 10), 6 t: parseInt($root.attr('data-cols-t') || '2', 10), 7 m: parseInt($root.attr('data-cols-m') || '1', 10) 8 }; 9 } 10 11 function setupAutoHideNav($root){ 12 var timer = null; 13 var delay = 2500; // ms før pilene fades bort 14 15 function show(){ 16 $root.addClass('is-nav-visible'); 17 if(timer) clearTimeout(timer); 18 timer = setTimeout(hide, delay); 19 } 20 21 function hide(){ 22 $root.removeClass('is-nav-visible'); 23 } 24 25 // Desktop hover 26 $root.on('mouseenter', show); 27 $root.on('mouseleave', function(){ 28 if(timer) clearTimeout(timer); 29 timer = setTimeout(hide, 600); 30 }); 31 32 // Touch / drag / click 33 $root.on('touchstart mousedown', show); 34 $root.on('touchend mouseup', function(){ 35 if(timer) clearTimeout(timer); 36 timer = setTimeout(hide, delay); 37 }); 38 39 // Hvis piler klikkes, hold synlig litt 40 $root.on('click', '.pew-ls-nav', function(){ 41 show(); 42 }); 43 } 44 45function buildOpts($root){ 46 var c = readCols($root); 47 48 var nav = ($root.attr('data-nav') || 'arrows_dots'); 49 var useArrows = (nav === 'arrows' || nav === 'arrows_dots'); 50 var useDots = (nav === 'dots' || nav === 'arrows_dots'); 51 52 var peek = ($root.attr('data-peek') === '1'); 53 var peekFrac = parseFloat($root.attr('data-peek-frac') || '0.22'); 54 if (isNaN(peekFrac)) peekFrac = 0.22; 55 if (peekFrac < 0.05) peekFrac = 0.05; 56 if (peekFrac > 0.45) peekFrac = 0.45; 57 58 var group = parseInt($root.attr('data-group') || '1', 10); 59 if (isNaN(group) || group < 1) group = 1; 60 61 function colsForWidth(w){ 62 if (w >= 1025) return c.d; 63 if (w >= 768) return c.t; 64 return c.m; 65 } 66 67 function applyPeekVar(){ 68 // CSS-variabel basert pÃ¥ faktisk slide-bredde 69 var $sw = $root.find('.pew-ls__swiper'); 70 if (!$sw.length) return; 71 72 var w = $sw[0].clientWidth || 0; 73 var perView = colsForWidth(window.innerWidth || 1200); 74 if (perView < 1) perView = 1; 75 76 var slideW = w / perView; 77 var px = Math.round(slideW * peekFrac); 78 79 $root.toggleClass('is-peek', !!peek); 80 $root[0].style.setProperty('--pew-peek', px + 'px'); 81 } 82 83 return { 84 rtl: false, 85 86 // Viktig: behold heltall, ellers mister du â4 fullt synligeâ 87 slidesPerView: c.d, 88 slidesPerGroup: group, 89 spaceBetween: 16, 90 speed: 350, 91 watchOverflow: true, 92 93 // Peek med loop for Ã¥ vise âsisteâ litt til venstre pÃ¥ første slide 94 loop: !!peek, 95 loopAdditionalSlides: 3, 96 97 // IKKE centered (da blir det â3 i midten + litt pÃ¥ sideneâ nÃ¥r du vil ha 4) 98 centeredSlides: false, 99 centeredSlidesBounds: false, 100 101 // Drag/touch 102 simulateTouch: true, 103 grabCursor: true, 104 followFinger: true, 105 threshold: 8, 106 touchStartPreventDefault: false, 107 touchMoveStopPropagation: true, 108 109 navigation: useArrows ? { 110 nextEl: $root.find('.pew-ls-nav--next')[0], 111 prevEl: $root.find('.pew-ls-nav--prev')[0] 112 } : false, 113 114 pagination: useDots ? { 115 el: $root.find('.pew-ls-pagination')[0], 116 clickable: true 117 } : false, 118 119 breakpoints: { 120 0: { slidesPerView: c.m, slidesPerGroup: group, spaceBetween: 12 }, 121 768: { slidesPerView: c.t, slidesPerGroup: group, spaceBetween: 14 }, 122 1025: { slidesPerView: c.d, slidesPerGroup: group, spaceBetween: 16 } 123 }, 124 125 on: { 126 init: function(){ applyPeekVar(); }, 127 resize: function(){ applyPeekVar(); }, 128 breakpoint: function(){ applyPeekVar(); } 129 } 130 }; 131} 132 133 function createSwiper(el, opts){ 134 // Foretrekk global Swiper hvis den finnes 135 if (window.Swiper) { 136 return new window.Swiper(el, opts); 137 } 138 139 // Elementor sin wrapper kan være funksjon eller class 140 if (window.elementorFrontend && elementorFrontend.utils && elementorFrontend.utils.swiper) { 141 var Ctor = elementorFrontend.utils.swiper; 142 try { return new Ctor(el, opts); } catch(e) {} 143 try { return Ctor(el, opts); } catch(e) {} 144 } 145 146 return null; 147 } 148 149 function initOne($root){ 150 if(!$root || !$root.length) return; 151 152 // Tving LTR (i tilfelle forelder har RTL/direction) 153 $root.css('direction', 'ltr'); 154 $root.find('.pew-ls-pagination').css('direction', 'ltr'); 155 156 // Auto-hide piler 157 setupAutoHideNav($root); 158 159 var el = $root.find('.pew-ls__swiper')[0]; 160 if(!el) return; 161 162 // Ikke init 2 ganger 163 if (el.dataset && el.dataset.pewInit === '1') return; 164 if (el.dataset) el.dataset.pewInit = '1'; 165 166 var inst = createSwiper(el, buildOpts($root)); 167 168 // Elementor kan reflowe â oppdater litt etter init 169 if (inst && typeof inst.update === 'function') {
170 setTimeout(function(){ inst.update(); }, 60); 171 setTimeout(function(){ inst.update(); }, 260); 172 } 173 174 // Hvis Promise (noen Elementor-versjoner) 175 if (inst && typeof inst.then === 'function') { 176 inst.then(function(sw){ 177 if(sw && sw.update){ 178 setTimeout(function(){ sw.update(); }, 60); 179 } 180 }).catch(function(){}); 181 } 182 183 // Vis piler kort ved init, så auto-hide 184 $root.addClass('is-nav-visible'); 185 setTimeout(function(){ $root.removeClass('is-nav-visible'); }, 1800); 186 } 187 188function initSectionHeading($root){ 189 if(!$root || !$root.length) return; 190 191 $root.each(function(){ 192 var root = this; 193 var $item = $(root); 194 if (root.dataset && root.dataset.pewSectionHeadingInit === '1') return; 195 if (root.dataset) root.dataset.pewSectionHeadingInit = '1'; 196 197 var slot = $item.find('[data-pew-animated-slot]')[0]; 198 if (!slot) return; 199 200 var textEl = slot.querySelector('.pew-section-heading__animated-text'); 201 if (!textEl) return; 202 203 var effect = $item.attr('data-effect') || 'none'; 204 if (effect === 'none') return; 205 206 var reduceMotion = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches; 207 var words = []; 208 try { words = JSON.parse($item.attr('data-words') || '[]'); } catch(e) { words = []; } 209 words = words.filter(function(word){ return typeof word === 'string' && word.length; }); 210 if (!words.length) return; 211 212 var speed = parseInt($item.attr('data-speed') || '70', 10); 213 var pause = parseInt($item.attr('data-pause') || '1800', 10); 214 var loopMode = $item.attr('data-loop') || 'loop'; 215 216 if (isNaN(speed) || speed < 20) speed = 70; 217 if (isNaN(pause) || pause < 500) pause = 1800; 218 if (loopMode !== 'once') loopMode = 'loop'; 219 220 if (reduceMotion) { 221 textEl.textContent = words[0]; 222 return; 223 } 224 225 var index = 0; 226 227 function showStaticWord(i){ 228 textEl.textContent = words[i] || words[0]; 229 } 230 231 function showNextWord(){ 232 index = (index + 1) % words.length; 233 $item.addClass('is-changing-word'); 234 setTimeout(function(){ 235 showStaticWord(index); 236 $item.removeClass('is-changing-word'); 237 }, 180); 238 } 239 240 if (effect === 'fade' || effect === 'slide') { 241 showStaticWord(0); 242 243 if (words.length === 1) { 244 $item.addClass('is-changing-word'); 245 setTimeout(function(){ 246 $item.removeClass('is-changing-word'); 247 }, 180); 248 return; 249 } 250 251 if (loopMode === 'once') { 252 var onceFadeIndex = 0; 253 var onceFadeTimer = setInterval(function(){ 254 onceFadeIndex++; 255 if (onceFadeIndex >= words.length) { 256 clearInterval(onceFadeTimer); 257 showStaticWord(words.length - 1); 258 return; 259 } 260 index = onceFadeIndex - 1; 261 showNextWord(); 262 }, pause); 263 return; 264 } 265 266 setInterval(showNextWord, pause); 267 return; 268 } 269 270 if (effect === 'typing') { 271 var charIndex = 0; 272 var deleting = false; 273 274 textEl.textContent = ''; 275 276 function tick(){ 277 var word = words[index]; 278 279 if (!deleting) { 280 charIndex++; 281 textEl.textContent = word.substring(0, charIndex); 282 283 if (charIndex >= word.length) { 284 if (loopMode === 'once' && index >= words.length - 1) { 285 textEl.textContent = word; 286 return; 287 } 288 289 deleting = true; 290 setTimeout(tick, pause); 291 return; 292 } 293 } else { 294 charIndex--; 295 textEl.textContent = word.substring(0, charIndex); 296 297 if (charIndex <= 0) { 298 deleting = false; 299 index = (index + 1) % words.length; 300 } 301 } 302 303 setTimeout(tick, deleting ? Math.max(25, speed * 0.55) : speed); 304 } 305 306 tick(); 307 } 308 }); 309} 310 311 // Elementor editor + frontend 312 $(window).on('elementor/frontend/init', function(){ 313 elementorFrontend.hooks.addAction('frontend/element_ready/para-livestudio-slider.default', function($scope){ 314 initOne($scope.find('.pew-ls')); 315 }); 316 elementorFrontend.hooks.addAction('frontend/element_ready/para-post-slider-card.default', function($scope){ 317 initOne($scope.find('.pew-ls')); 318 }); 319 elementorFrontend.hooks.addAction('frontend/element_ready/para-section-heading.default', function($scope){ 320 initSectionHeading($scope.find('.pew-section-heading')); 321 }); 322 323 324 }); 325 326 327 328 // Frontend safety-net 329 $(function(){ 330 $('.pew-ls').each(function(){ 331 initOne($(this)); 332 }); 333 334 $('.pew-section-heading').each(function(){ 335 initSectionHeading($(this)); 336 }); 337 }); 338 339 function paraOpeningHoursLegacyToday(){ 340 var now = new Date(); 341 var y = now.getFullYear(); 342 var m = String(now.getMonth() + 1).padStart(2, '0'); 343 var d = String(now.getDate()).padStart(2, '0'); 344 return y + '-' + m + '-' + d; 345 } 346 347 function paraOpeningHoursNumber(value){ 348 var parsed = parseInt(value || '0', 10); 349 return Number.isFinite(parsed) ? parsed : 0; 350 } 351 352 function paraOpeningHoursRefreshDates(){ 353 var now = Math.floor(Date.now() / 1000); 354 var legacyToday = paraOpeningHoursLegacyToday(); 355 356 $('.pew-opening-hours__card[data-pew-opening-date]').each(function(){ 357 var $card = $(this); 358 var date = $card.attr('data-pew-opening-date') || ''; 359 var dayStart = paraOpeningHoursNumber($card.attr('data-pew-opening-day-start')); 360 var dayEnd = paraOpeningHoursNumber($card.attr('data-pew-opening-day-end')); 361 var pastAt = paraOpeningHoursNumber($card.attr('data-pew-opening-past-at')); 362 var mutePast = $card.attr('data-pew-opening-mute-past') === '1'; 363 var markToday = $card.attr('data-pew-opening-mark-today') === '1'; 364 var isToday = dayStart && dayEnd ? now >= dayStart && now < dayEnd : date === legacyToday; 365 var isPast = pastAt ? now >= pastAt : date < legacyToday; 366 var $dot = $card.find('.pew-opening-hours__status-dot'); 367 368 if (!date) return; 369 370 $card.removeClass('is-past is-today'); 371 372 if (mutePast && isPast) { 373 $card.addClass('is-past'); 374 } 375 376 if (isPast) { 377 $dot.attr('aria-hidden', 'true').hide(); 378 } else { 379 $dot.removeAttr('aria-hidden').show(); 380 } 381 382 if (markToday && isToday) { 383 $card.addClass('is-today'); 384 } 385 }); 386 } 387 388 function paraOpeningHoursParseSchedule(raw){ 389 if (!raw) return []; 390 391 try { 392 var parsed = JSON.parse(raw); 393 return Array.isArray(parsed) ? parsed : []; 394 } catch (error) { 395 return []; 396 } 397 } 398 399 function paraOpeningHoursOpenMessage(template, time){ 400 return String(template || '').split('%s').join(String(time || '')); 401 } 402 403 function paraOpeningHoursClosedMessage(template, day, time){ 404 var message = String(template || ''); 405 message = message.split('%1$s').join(String(day || '')); 406 message = message.split('%2$s').join(String(time || '')); 407 408 if (message.indexOf('%s') !== -1) { 409 message = message.replace('%s', String(day || '')); 410 message = message.replace('%s', String(time || '')); 411 } 412 413 return message; 414 } 415 416 function paraOpeningHoursRefreshCompact(){ 417 var now = Math.floor(Date.now() / 1000); 418 419 $('.pew-opening-hours__compact[data-pew-opening-schedule]').each(function(){ 420 var $compact = $(this); 421 var schedule = paraOpeningHoursParseSchedule($compact.attr('data-pew-opening-schedule')); 422 var openLabel = $compact.attr('data-pew-opening-open-label') || 'à PENT'; 423 var closedLabel = $compact.attr('data-pew-opening-closed-label') || 'STENGT'; 424 var openTemplate = $compact.attr('data-pew-opening-open-template') || 'Holder åpent til klokken %s'; 425 var closedTemplate = $compact.attr('data-pew-opening-closed-template') || 'à pner igjen %1$s klokken %2$s'; 426 var todayLabel = $compact.attr('data-pew-opening-today-label') || 'i dag'; 427 var noUpcoming = $compact.attr('data-pew-opening-no-upcoming') || 'Ingen kommende åpningstid er satt.'; 428 var active = null; 429 var next = null; 430 431 schedule.forEach(function(entry){ 432 var openAt = paraOpeningHoursNumber(entry.open_at); 433 var closeAt = paraOpeningHoursNumber(entry.close_at); 434 435 if (!active && openAt && closeAt && now >= openAt && now < closeAt) { 436 active = entry; 437 } 438 439 if (openAt > now && (!next || openAt < paraOpeningHoursNumber(next.open_at))) { 440 next = entry; 441 } 442 }); 443 444 if (active) { 445 $compact.removeClass('is-closed').addClass('is-open'); 446 $compact.find('.pew-opening-hours__compact-badge').text(openLabel); 447 $compact.find('.pew-opening-hours__compact-message').text( 448 paraOpeningHoursOpenMessage(openTemplate, active.to) 449 ); 450 return; 451 } 452 453 $compact.removeClass('is-open').addClass('is-closed'); 454 $compact.find('.pew-opening-hours__compact-badge').text(closedLabel); 455 456 if (next) { 457 var dayStart = paraOpeningHoursNumber(next.day_start); 458 var dayEnd = paraOpeningHoursNumber(next.day_end); 459 var dayLabel = dayStart && dayEnd && now >= dayStart && now < dayEnd 460 ? todayLabel 461 : (next.day_name || ''); 462 463 $compact.find('.pew-opening-hours__compact-message').text( 464 paraOpeningHoursClosedMessage(closedTemplate, dayLabel, next.from) 465 ); 466 } else { 467 $compact.find('.pew-opening-hours__compact-message').text(noUpcoming); 468 } 469 }); 470 } 471 472 function paraOpeningHoursRefresh(){ 473 paraOpeningHoursRefreshDates(); 474 paraOpeningHoursRefreshCompact(); 475 } 476 477 $(document).ready(function(){ 478 paraOpeningHoursRefresh(); 479 setInterval(paraOpeningHoursRefresh, 30000); 480 }); 481 482 $(window).on('focus pageshow', paraOpeningHoursRefresh); 483 484 document.addEventListener('visibilitychange', function(){ 485 if (!document.hidden) { 486 paraOpeningHoursRefresh(); 487 } 488 }); 489 490 $(window).on('elementor/frontend/init', function(){ 491 if (window.elementorFrontend && elementorFrontend.hooks) { 492 elementorFrontend.hooks.addAction('frontend/element_ready/para-opening-hours.default', function(){ 493 paraOpeningHoursRefresh(); 494 }); 495 } 496 }); 497})(jQuery); 498 499(function(){ 500 'use strict'; 501 502 function initParaEwSliders(root){ 503 var scope = root || document; 504 scope.querySelectorAll('[data-para-ew-slider]').forEach(function(slider){ 505 var track = slider.querySelector('[data-para-ew-slider-track]'); 506 var prev = slider.querySelector('[data-para-ew-slider-prev]'); 507 var next = slider.querySelector('[data-para-ew-slider-next]');
508 var dotsWrap = slider.querySelector('[data-para-ew-slider-dots]'); 509 var scrollByCards = parseInt(slider.getAttribute('data-para-ew-slider-scroll-by') || '1', 10); 510 511 if (!track) { return; } 512 if (!scrollByCards || scrollByCards < 1) { scrollByCards = 1; } 513 514 function amount(){ 515 var card = track.querySelector('.para-ew-employee-slider-card'); 516 if (!card) { return Math.max(220, Math.round(track.clientWidth * 0.75)); } 517 var styles = window.getComputedStyle(track); 518 var gap = parseFloat(styles.columnGap || styles.gap || '0') || 0; 519 return (card.getBoundingClientRect().width + gap) * scrollByCards; 520 } 521 522 function maxScroll(){ 523 return Math.max(0, track.scrollWidth - track.clientWidth); 524 } 525 526 function pageCount(){ 527 var step = amount(); 528 if (!step || maxScroll() <= 2) { return 1; } 529 return Math.max(1, Math.ceil(maxScroll() / step) + 1); 530 } 531 532 function activePage(){ 533 var step = amount(); 534 if (!step) { return 0; } 535 return Math.min(pageCount() - 1, Math.round(track.scrollLeft / step)); 536 } 537 538 function updateDots(){ 539 var dots = slider.querySelectorAll('.para-ew-employee-slider-dot'); 540 if (!dots.length) { return; } 541 var active = activePage(); 542 dots.forEach(function(dot, index){ 543 dot.classList.toggle('is-active', index === active); 544 }); 545 } 546 547 function buildDots(){ 548 if (!dotsWrap) { return; } 549 dotsWrap.innerHTML = ''; 550 var count = pageCount(); 551 if (count <= 1) { return; } 552 for (var i = 0; i < count; i++) { 553 (function(index){ 554 var dot = document.createElement('button'); 555 dot.type = 'button'; 556 dot.className = 'para-ew-employee-slider-dot' + (index === 0 ? ' is-active' : ''); 557 dot.setAttribute('aria-label', 'GÃ¥ til slide ' + (index + 1)); 558 dot.addEventListener('click', function(){ 559 track.scrollTo({left: amount() * index, behavior: 'smooth'}); 560 }); 561 dotsWrap.appendChild(dot); 562 })(i); 563 } 564 } 565 566 function refresh(){ 567 buildDots(); 568 updateDots(); 569 } 570 571 if (slider.getAttribute('data-para-ew-slider-ready') !== '1') { 572 slider.setAttribute('data-para-ew-slider-ready', '1'); 573 574 if (prev) { 575 prev.addEventListener('click', function(){ 576 track.scrollBy({left: -amount(), behavior: 'smooth'}); 577 }); 578 } 579 580 if (next) { 581 next.addEventListener('click', function(){ 582 track.scrollBy({left: amount(), behavior: 'smooth'}); 583 }); 584 } 585 586 track.addEventListener('scroll', function(){ 587 window.requestAnimationFrame(updateDots); 588 }); 589 590 window.addEventListener('resize', refresh); 591 } 592 593 window.setTimeout(refresh, 40); 594 }); 595 } 596 597 if (document.readyState === 'loading') { 598 document.addEventListener('DOMContentLoaded', function(){ initParaEwSliders(document); }); 599 } else { 600 initParaEwSliders(document); 601 } 602 603 window.paraEwInitSliders = initParaEwSliders; 604 605 if (window.elementorFrontend && window.elementorFrontend.hooks) { 606 window.elementorFrontend.hooks.addAction('frontend/element_ready/para-employees.default', function($scope){ 607 var el = $scope && $scope[0] ? $scope[0] : document; 608 initParaEwSliders(el); 609 }); 610 } 611})(); 612 613 614(function($){ 615 function initParaLogoCarousel($scope){ 616 var $widgets = $scope && $scope.length ? $scope.find('.para-ew-logo-carousel-slider') : $('.para-ew-logo-carousel-slider'); 617 if ($scope && $scope.hasClass && $scope.hasClass('para-ew-logo-carousel-slider')) $widgets = $widgets.add($scope); 618 619 $widgets.each(function(){ 620 var $wrap = $(this); 621 if ($wrap.data('paraLogoReady')) return; 622 $wrap.data('paraLogoReady', true); 623 624 var $track = $wrap.find('.para-ew-logo-carousel-track').first(); 625 var $slides = $track.find('.para-ew-logo-carousel-slide'); 626 var $dotsWrap = $wrap.find('.para-ew-logo-carousel-dots').first(); 627 var autoplay = String($wrap.attr('data-autoplay') || '0') === '1'; 628 var speed = parseInt($wrap.attr('data-autoplay-speed') || '3500', 10); 629 var pauseOnHover = $wrap.hasClass('slider-pause-on-hover'); 630 var timer = null; 631 var paused = false;
632 633 if (!$track.length || !$slides.length) return; 634 635 function slideStep(){ 636 var first = $slides.get(0); 637 if (!first) return Math.max(1, Math.round($track.width())); 638 var rect = first.getBoundingClientRect(); 639 var gap = parseFloat(window.getComputedStyle($track.get(0)).columnGap || window.getComputedStyle($track.get(0)).gap || 0) || 0; 640 return Math.max(1, Math.round(rect.width + gap)); 641 } 642 643 function maxScroll(){ 644 return Math.max(0, $track.get(0).scrollWidth - $track.innerWidth()); 645 } 646 647 function currentIndex(){ 648 return Math.round($track.scrollLeft() / slideStep()); 649 } 650 651 function goTo(index){ 652 var max = maxScroll(); 653 var left = Math.min(max, Math.max(0, index * slideStep())); 654 $track.get(0).scrollTo({left:left, behavior:'smooth'}); 655 } 656 657 function next(){ 658 var max = maxScroll(); 659 var left = $track.scrollLeft(); 660 if (left >= max - 2) { 661 $track.get(0).scrollTo({left:0, behavior:'smooth'}); 662 } else { 663 $track.get(0).scrollBy({left:slideStep(), behavior:'smooth'}); 664 } 665 } 666 667 function prev(){ 668 var left = $track.scrollLeft(); 669 if (left <= 2) { 670 $track.get(0).scrollTo({left:maxScroll(), behavior:'smooth'}); 671 } else { 672 $track.get(0).scrollBy({left:-slideStep(), behavior:'smooth'}); 673 } 674 } 675 676 function buildDots(){ 677 if (!$dotsWrap.length) return; 678 $dotsWrap.empty(); 679 var pages = Math.max(1, Math.ceil(maxScroll() / slideStep()) + 1); 680 for (var i = 0; i < pages; i++) { 681 $('<button type="button" class="para-ew-logo-carousel-dot" aria-label="GÃ¥ til slide '+(i+1)+'"></button>').attr('data-index', i).appendTo($dotsWrap); 682 } 683 updateDots(); 684 } 685 686 function updateDots(){ 687 if (!$dotsWrap.length) return; 688 var idx = currentIndex(); 689 $dotsWrap.find('.para-ew-logo-carousel-dot').removeClass('is-active').eq(idx).addClass('is-active'); 690 } 691 692 function stop(){ 693 if (timer) window.clearInterval(timer); 694 timer = null; 695 } 696 697 function start(){ 698 stop(); 699 if (!autoplay) return; 700 timer = window.setInterval(function(){ 701 if (!paused) next(); 702 }, Math.max(1000, speed)); 703 } 704 705 $wrap.on('click', '.para-ew-logo-carousel-arrow-next', function(e){ e.preventDefault(); next(); }); 706 $wrap.on('click', '.para-ew-logo-carousel-arrow-prev', function(e){ e.preventDefault(); prev(); }); 707 $wrap.on('click', '.para-ew-logo-carousel-dot', function(e){ e.preventDefault(); goTo(parseInt($(this).attr('data-index') || '0', 10)); }); 708 $track.on('scroll', function(){ window.requestAnimationFrame(updateDots); }); 709 710 if (pauseOnHover) { 711 $wrap.on('mouseenter focusin', function(){ paused = true; }); 712 $wrap.on('mouseleave focusout', function(){ paused = false; }); 713 } 714 715 var resizeTimer = null; 716 $(window).on('resize.paraLogoCarousel', function(){ 717 window.clearTimeout(resizeTimer); 718 resizeTimer = window.setTimeout(function(){ buildDots(); }, 160); 719 }); 720 721 buildDots(); 722 start(); 723 }); 724 } 725 726 $(window).on('elementor/frontend/init', function(){ 727 if (window.elementorFrontend && elementorFrontend.hooks) { 728 elementorFrontend.hooks.addAction('frontend/element_ready/para-logo-carousel.default', function($scope){ 729 initParaLogoCarousel($scope); 730 }); 731 } 732 }); 733 734 $(function(){ 735 initParaLogoCarousel($(document)); 736 }); 737})(jQuery); 738 739(function($){ 740 'use strict'; 741 742 function setOpen($item, open, animate){ 743 var $panel = $item.children('.para-ew-accordion-panel'); 744 var $button = $item.children('.para-ew-accordion-header'); 745 746 if (!$panel.length || !$button.length) return; 747 748 if (open) { 749 $item.addClass('is-open'); 750 $button.attr('aria-expanded', 'true'); 751 752 if (!animate) { 753 $panel.css('height', 'auto'); 754 return; 755 } 756 757 $panel.css('height', '0px'); 758 var target = $panel[0].scrollHeight; 759 window.requestAnimationFrame(function(){ 760 $panel.css('height', target + 'px'); 761 }); 762 763 window.setTimeout(function(){ 764 if ($item.hasClass('is-open')) $panel.css('height', 'auto'); 765 }, 310); 766 } else { 767 $button.attr('aria-expanded', 'false'); 768 769 if (!animate) { 770 $item.removeClass('is-open'); 771 $panel.css('height', '0px'); 772 return; 773 } 774 775 var current = $panel[0].scrollHeight; 776 $panel.css('height', current + 'px'); 777 778 window.requestAnimationFrame(function(){ 779 $item.removeClass('is-open'); 780 $panel.css('height', '0px'); 781 }); 782 } 783 } 784 785 function initAccordion($scope){ 786 var $accordions = $scope.find('.para-ew-accordion'); 787 if ($scope.hasClass('para-ew-accordion')) $accordions = $accordions.add($scope); 788 789 $accordions.each(function(){ 790 var $accordion = $(this); 791 if ($accordion.data('paraAccordionReady')) return; 792 $accordion.data('paraAccordionReady', true); 793 794 $accordion.children('.para-ew-accordion-item').each(function(){ 795 setOpen($(this), $(this).hasClass('is-open'), false); 796 }); 797 798 $accordion.on('click', '.para-ew-accordion-header', function(e){ 799 e.preventDefault(); 800 801 var $button = $(this); 802 var $item = $button.closest('.para-ew-accordion-item'); 803 var $root = $item.closest('.para-ew-accordion'); 804 var mode = $root.attr('data-mode') || 'accordion'; 805 var willOpen = !$item.hasClass('is-open'); 806 807 if (mode === 'accordion' && willOpen) { 808 $root.children('.para-ew-accordion-item.is-open').not($item).each(function(){ 809 setOpen($(this), false, true); 810 }); 811 } 812 813 setOpen($item, willOpen, true); 814 815 if (willOpen && $root.attr('data-scroll-mobile') === 'yes' && window.matchMedia('(max-width: 767px)').matches) { 816 window.setTimeout(function(){ 817 var top = $item.offset().top - 90; 818 $('html, body').stop(true).animate({ scrollTop: top }, 260); 819 }, 320); 820 } 821 }); 822 }); 823 } 824 825 $(window).on('resize', function(){ 826 $('.para-ew-accordion .para-ew-accordion-item.is-open > .para-ew-accordion-panel').css('height', 'auto'); 827 }); 828 829 $(function(){ 830 initAccordion($(document)); 831 }); 832 833 $(window).on('elementor/frontend/init', function(){ 834 if (window.elementorFrontend && elementorFrontend.hooks) { 835 elementorFrontend.hooks.addAction('frontend/element_ready/para-accordion.default', function($scope){ 836 initAccordion($scope); 837 }); 838 } 839 }); 840})(jQuery); 841 842(function($){ 843 'use strict'; 844 845 function formatNumber(value, decimals){ 846 decimals = parseInt(decimals, 10) || 0; 847 try { 848 return new Intl.NumberFormat(undefined, { minimumFractionDigits: decimals, maximumFractionDigits: decimals }).format(value); 849 } catch(e) { 850 return Number(value).toFixed(decimals); 851 } 852 } 853 854 function animateStats($scope){ 855 var $widgets = $scope.find('.para-ew-stats.has-counter-animation'); 856 if ($scope.hasClass('para-ew-stats')) $widgets = $widgets.add($scope); 857 858 $widgets.each(function(){ 859 var widget = this; 860 var $widget = $(widget); 861 var duration = parseInt($widget.attr('data-duration'), 10) || 1400; 862 var $numbers = $widget.find('.para-ew-stats-number'); 863 if (!$numbers.length) return; 864 865 var run = function(){ 866 if ($widget.data('paraStatsAnimated')) return; 867 $widget.data('paraStatsAnimated', true); 868 869 $numbers.each(function(){ 870 var el = this; 871 var target = parseFloat($(el).attr('data-target')) || 0; 872 var decimals = parseInt($(el).attr('data-decimals'), 10) || 0; 873 var start = target < 0 ? target : 0; 874 var startTime = null; 875 876 function tick(timestamp){ 877 if (!startTime) startTime = timestamp; 878 var progress = Math.min((timestamp - startTime) / duration, 1); 879 var eased = 1 - Math.pow(1 - progress, 3); 880 var current = start + (target - start) * eased; 881 el.textContent = formatNumber(current, decimals); 882 if (progress < 1) { 883 window.requestAnimationFrame(tick); 884 } else { 885 el.textContent = formatNumber(target, decimals); 886 } 887 } 888 889 window.requestAnimationFrame(tick); 890 }); 891 }; 892 893 if ('IntersectionObserver' in window) { 894 var observer = new IntersectionObserver(function(entries){
895 entries.forEach(function(entry){ 896 if (entry.isIntersecting) { 897 run(); 898 observer.unobserve(widget); 899 } 900 }); 901 }, { threshold: 0.25 }); 902 observer.observe(widget); 903 } else { 904 run(); 905 } 906 }); 907 } 908 909 $(window).on('elementor/frontend/init', function(){ 910 elementorFrontend.hooks.addAction('frontend/element_ready/para-stats-counter.default', animateStats); 911 }); 912 913 $(function(){ 914 animateStats($(document)); 915 }); 916})(jQuery); 917 918/* PARA Button/Testimonial/Video additions */ 919(function($){ 920 function initTestimonials($root){ 921 if(!$root || !$root.length) return; 922 $root.each(function(){ 923 var root = this; 924 var $r = $(root); 925 if(!$r.hasClass('pew-testimonials--slider')) return; 926 if(root.dataset && root.dataset.pewTestimonialsInit === '1') return; 927 if(root.dataset) root.dataset.pewTestimonialsInit = '1'; 928 var $track = $r.find('.pew-testimonials__track'); 929 var $slides = $r.find('.pew-testimonials__slide'); 930 var $dots = $r.find('.pew-testimonials__dots'); 931 var index = 0; 932 var timer = null; 933 function perView(){ var v = parseInt(getComputedStyle(root).getPropertyValue('--pew-testimonial-cols') || '1', 10); return Math.max(1, isNaN(v) ? 1 : v); } 934 function maxIndex(){ return Math.max(0, $slides.length - perView()); } 935 function buildDots(){ $dots.empty(); var count = maxIndex() + 1; for(var i=0;i<count;i++){ $('<button class="pew-testimonials__dot" type="button" aria-label="GÃ¥ til slide '+(i+1)+'"></button>').appendTo($dots); } } 936 function go(i){ index = Math.max(0, Math.min(i, maxIndex())); var slide = $slides.get(0); if(!slide) return; var gap = parseFloat(getComputedStyle(root).getPropertyValue('--pew-testimonial-gap')) || 0; var w = slide.getBoundingClientRect().width + gap; $track.css('transform', 'translateX(' + (-index * w) + 'px)'); $dots.find('.pew-testimonials__dot').removeClass('is-active').eq(index).addClass('is-active'); } 937 function start(){ if(($r.attr('data-autoplay') || '') !== 'yes') return; stop(); var speed = parseInt($r.attr('data-autoplay-speed') || '4500', 10); timer = setInterval(function(){ go(index >= maxIndex() ? 0 : index + 1); }, Math.max(1200, speed)); } 938 function stop(){ if(timer) clearInterval(timer); timer = null; } 939 buildDots(); go(0); start(); 940 $r.on('click', '.pew-testimonials__nav--next', function(){ stop(); go(index + 1); start(); }); 941 $r.on('click', '.pew-testimonials__nav--prev', function(){ stop(); go(index - 1); start(); }); 942 $r.on('click', '.pew-testimonials__dot', function(){ stop(); go($(this).index()); start(); }); 943 $r.on('mouseenter focusin', stop).on('mouseleave focusout', start); 944 $(window).on('resize', function(){ buildDots(); go(index); }); 945 }); 946 } 947 function fmt(sec){ sec = Math.max(0, Math.floor(sec || 0)); var m = Math.floor(sec / 60); var s = sec % 60; return m + ':' + (s < 10 ? '0' : '') + s; } 948 function initVideo($root){ 949 if(!$root || !$root.length) return; 950 $root.each(function(){ 951 var root = this; 952 var $r = $(root); 953 if(root.dataset && root.dataset.pewVideoInit === '1') return; 954 if(root.dataset) root.dataset.pewVideoInit = '1'; 955 var video = $r.find('video.pew-video__media').get(0); 956 var iframe = $r.find('iframe.pew-video__iframe').get(0);
957 var $overlay = $r.find('.pew-video__overlay'); 958 function playYoutube(){ if(!iframe) return; var src = iframe.getAttribute('src') || iframe.getAttribute('data-src') || ''; if(!src) return; if(src.indexOf('autoplay=1') === -1) src += (src.indexOf('?') === -1 ? '?' : '&') + 'autoplay=1'; iframe.setAttribute('src', src); $r.addClass('is-playing'); } 959 if(video){ 960 var $range = $r.find('.pew-video__range'); 961 var $cur = $r.find('.pew-video__time--current'); 962 var $dur = $r.find('.pew-video__time--duration'); 963 function sync(){ var d = video.duration || 0; var c = video.currentTime || 0; $cur.text(fmt(c)); $dur.text(fmt(d)); if(d) $range.val(Math.round((c / d) * 1000)); $r.toggleClass('is-playing', !video.paused); $r.toggleClass('is-paused', video.paused); $r.toggleClass('is-muted', video.muted); } 964 function toggle(){ if(video.paused){ video.play().catch(function(){}); } else { video.pause(); } } 965 $overlay.on('click', toggle); 966 $r.find('.pew-video__toggle').on('click', toggle); 967 $r.find('.pew-video__mute').on('click', function(){ video.muted = !video.muted; sync(); }); 968 $r.find('.pew-video__fullscreen').on('click', function(){ var el = $r.find('.pew-video__frame').get(0); if(el && el.requestFullscreen) el.requestFullscreen(); }); 969 $range.on('input change', function(){ if(video.duration) video.currentTime = (parseFloat(this.value) / 1000) * video.duration; }); 970 $(video).on('loadedmetadata timeupdate play pause volumechange ended', sync); 971 sync(); 972 } else if(iframe){ 973 $overlay.on('click', playYoutube); 974 } 975 }); 976 } 977 function boot($scope){ initTestimonials($scope.find('.pew-testimonials')); initVideo($scope.find('.pew-video')); } 978 $(window).on('elementor/frontend/init', function(){ elementorFrontend.hooks.addAction('frontend/element_ready/global', boot); }); 979 $(function(){ boot($(document)); }); 980})(jQuery); 981 982(function($){ 983 function initParaNotices($scope){ 984 var $items = $scope.find('.pew-notice'); 985 $items.each(function(){ 986 var el = this; 987 var key = el.getAttribute('data-dismiss-key') || ''; 988 if(key && window.sessionStorage && sessionStorage.getItem(key) === '1') $(el).addClass('is-dismissed'); 989 }); 990 } 991 $(document).on('click', '.pew-notice__close', function(e){ 992 e.preventDefault(); 993 var el = $(this).closest('.pew-notice').get(0); 994 if(!el) return; 995 var key = el.getAttribute('data-dismiss-key') || ''; 996 if(key && window.sessionStorage) sessionStorage.setItem(key, '1'); 997 $(el).addClass('is-dismissed'); 998 }); 999 $(window).on('elementor/frontend/init', function(){ elementorFrontend.hooks.addAction('frontend/element_ready/global', initParaNotices); }); 1000 $(function(){ initParaNotices($(document)); }); 1001})(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.