1;(function(){ 2 3 /** 4 * AlertDialog implements fancy alert and confirm dialog windows. 5 * 6 * - alertMessage(message) 7 * - confirmMessage(message, function(ok)) 8 */ 9 class AlertDialog extends oc.ControlBase 10 { 11 connect() { 12 addEventListener('ajax:error-message', this.proxy(this.onErrorMessage)); 13 addEventListener('ajax:confirm-message', this.proxy(this.onConfirmMessage)); 14 } 15 16 disconnect() { 17 removeEventListener('ajax:error-message', this.proxy(this.onErrorMessage)); 18 removeEventListener('ajax:confirm-message', this.proxy(this.onConfirmMessage)); 19 } 20 21 onErrorMessage(event) { 22 const { message } = event.detail; 23 if (!message) { 24 return; 25 } 26 27 this.alertMessage(message); 28 29 // Prevent the default alert() message 30 event.preventDefault(); 31 } 32 33 onConfirmMessage(event) { 34 const { message, promise } = event.detail; 35 if (!message) { 36 return; 37 } 38 39 this.confirmMessage(message, isConfirm => { 40 if (isConfirm) { 41 promise.resolve(); 42 } 43 else { 44 promise.reject(); 45 } 46 }); 47 48 // Prevent the default confirm() message 49 event.preventDefault(); 50 } 51 52 alertMessage(message) { 53 var popup = this.getDialogElement(); 54 document.body.appendChild(popup); 55 56 popup.querySelector('[data-cancel]').remove(); 57 popup.querySelector('[data-message]').innerText = message; 58 59 var modal = new bootstrap.Modal(popup); 60 modal.show(); 61 62 popup.querySelector('[data-ok]').addEventListener('click', () => { 63 modal.hide(); 64 }, { once: true }); 65 66 popup.addEventListener('hidden.bs.modal', () => { 67 modal.dispose(); 68 popup.remove(); 69 }, { once: true }); 70 71 popup.querySelector('[data-ok]').focus(); 72 } 73 74 confirmMessage(message, callback) { 75 var popup = this.getDialogElement(); 76 document.body.appendChild(popup); 77 78 popup.querySelector('[data-message]').innerText = message; 79 80 var modal = new bootstrap.Modal(popup); 81 modal.show(); 82 83 popup.querySelector('[data-ok]').addEventListener('click', () => { 84 callback && callback(true); 85 modal.hide(); 86 }, { once: true }); 87 88 popup.querySelector('[data-cancel]').addEventListener('click', () => { 89 callback && callback(false); 90 modal.hide(); 91 }, { once: true }); 92 93 popup.addEventListener('hidden.bs.modal', () => { 94 modal.dispose(); 95 popup.remove(); 96 }, { once: true }); 97 98 popup.querySelector('[data-cancel]').focus(); 99 } 100 101 getDialogElement() { 102 var template = document.createElement('template'); 103 template.innerHTML = this.element.innerHTML.trim(); 104 return template.content.firstChild; 105 } 106 107 static alertMessageGlobal(message) { 108 const alertDialog = oc.fetchControl('[data-control=alert-dialog]'); 109 if (alertDialog) { 110 alertDialog.alertMessage(message); 111 } 112 } 113 114 static confirmMessageGlobal(message, callback) { 115 const alertDialog = oc.fetchControl('[data-control=alert-dialog]'); 116 if (alertDialog) { 117 alertDialog.confirmMessage(message, callback); 118 } 119 } 120 } 121 122 oc.registerControl('alert-dialog', AlertDialog); 123 124 window.alertMessage = AlertDialog.alertMessageGlobal; 125 126 window.confirmMessage = AlertDialog.confirmMessageGlobal; 127 128})(); 129 130;(function(){ 131 132 /** 133 * PasswordDialog implements a password confirmation screen for sensitive actions 134 */ 135 class PasswordDialog extends oc.ControlBase { 136 connect() { 137 addEventListener('app:password-confirming', this.proxy(this.onShowPasswordPrompt)); 138 } 139 140 disconnect() { 141 removeEventListener('app:password-confirming', this.proxy(this.onShowPasswordPrompt)); 142 } 143 144 onShowPasswordPrompt(event) { 145 this.target = event.target; 146 this.popup = this.getDialogElement(); 147 this.form = this.popup.querySelector('form'); 148 149 document.body.appendChild(this.popup); 150 151 // Create a new modal 152 this.modal = new bootstrap.Modal(this.popup); 153 this.modal.show(); 154 155 // Focus the input 156 this.popup.querySelector('input[name=confirmable_password]').focus(); 157 158 // Bind events 159 this.popup.querySelector('[data-cancel]').addEventListener('click', () => this.modal.hide(), { once: true }); 160 this.popup.addEventListener('hidden.bs.modal', () => this.disposeDialog(), { once: true }); 161 this.form.addEventListener('ajax:done', this.proxy(this.onPasswordConfirmed), { once: true }); 162 163 // Prevent the update workflow 164 event.preventDefault(); 165 } 166 167 onPasswordConfirmed(event) { 168 const { data } = event.detail; 169 170 // Resubmit original AJAX event, skipping confirmation prompts 171 if (data.passwordConfirmed) { 172 oc.request(this.target, null, { confirm: false }); 173 } 174 175 this.modal.hide(); 176 } 177 178 disposeDialog() {
179 this.modal.dispose(); 180 this.form.removeEventListener('ajax:done', this.proxy(this.onPasswordConfirmed), { once: true }); 181 this.popup.remove(); 182 183 this.form = null; 184 this.popup = null; 185 this.modal = null; 186 this.target = null; 187 } 188 189 getDialogElement() { 190 var template = document.createElement('template'); 191 template.innerHTML = this.element.innerHTML.trim(); 192 return template.content.firstChild; 193 } 194 } 195 196 oc.registerControl('password-dialog', PasswordDialog); 197 198})(); 199 200;(function(){ 201 202 oc.registerControl('gallery-slider', class extends oc.ControlBase { 203 init() { 204 this.$thumbs = this.element.querySelector('[data-slider-thumbs]') || this.element; 205 this.$previews = this.element.querySelector('[data-slider-previews]'); 206 } 207 208 connect() { 209 this.connectSlickThumbs(); 210 if (this.$previews) { 211 this.connectSlickPreviews(); 212 } 213 214 this.connectLightbox(); 215 setTimeout(() => { 216 this.prepareLightbox(); 217 }, 1); 218 } 219 220 disconnect() { 221 if (this.lightbox) { 222 this.lightbox.destroy(); 223 this.lightbox = null; 224 } 225 226 $(this.$thumbs).slick('unslick'); 227 this.$thumbs = null; 228 229 if (this.$previews) { 230 $(this.$previews).slick('unslick'); 231 this.$previews = null; 232 } 233 } 234 235 connectSlickPreviews() { 236 $(this.$previews).slick({ 237 slidesToShow: 1, 238 slidesToScroll: 1, 239 arrows: false, 240 fade: true, 241 asNavFor: this.$thumbs 242 }); 243 } 244 245 connectSlickThumbs() { 246 $(this.$thumbs).slick({ 247 dots: true, 248 infinite: false, 249 speed: 300, 250 slidesToShow: 3, 251 slidesToScroll: 3, 252 focusOnSelect: !!this.$previews, 253 asNavFor: this.$previews, 254 responsive: [ 255 { 256 breakpoint: 992, 257 settings: { 258 slidesToShow: 2, 259 slidesToScroll: 2 260 } 261 }, 262 { 263 breakpoint: 576, 264 settings: { 265 slidesToShow: 1, 266 slidesToScroll: 1 267 } 268 } 269 ] 270 }); 271 } 272 273 connectLightbox() { 274 this.lightbox = new PhotoSwipeLightbox({ 275 gallery: this.$previews || this.$thumbs, 276 children: '.slick-slide', 277 pswpModule: PhotoSwipeModule, 278 showHideAnimationType: 'none' 279 }); 280 281 new PhotoSwipeDynamicCaption(this.lightbox, { 282 type: 'auto' 283 }); 284 285 this.lightbox.init(); 286 } 287 288 prepareLightbox() { 289 $('.slick-slide a', this.$el).each(function () { 290 var image = new Image(), 291 link = this; 292 293 image.src = this.getAttribute('href'); 294 image.onload = function () { 295 link.setAttribute('data-pswp-width', image.naturalWidth); 296 link.setAttribute('data-pswp-height', image.naturalHeight); 297 }; 298 }); 299 } 300 }); 301 302})(); 303 304;(function(){ 305 306 oc.registerControl('card-slider', class extends oc.ControlBase { 307 init() { 308 this.$el = $(this.element); 309 this.sliderType = this.config.sliderType || 'hero'; 310 this.element.classList.add('type-' + this.sliderType); 311 } 312 313 connect() { 314 this.connectSlick(); 315 } 316 317 disconnect() { 318 this.$el.slick('unslick'); 319 this.$el = null; 320 } 321 322 connectSlick() { 323 this.$el.slick(this.getSlickOptions()); 324 } 325 326 getSlickOptions() { 327 if (this.sliderType === 'hero') { 328 return this.getHeroTypeOptions(); 329 } 330 331 if (this.sliderType === 'team') { 332 return this.getTeamTypeOptions(); 333 } 334 335 if (this.sliderType === 'category') { 336 return this.getCategoryTypeOptions(); 337 } 338 339 return {}; 340 } 341 342 getHeroTypeOptions() { 343 return { 344 infinite: true, 345 slidesToShow: 1, 346 slidesToScroll: 1, 347 autoplay: true, 348 dots: true,
349 arrows: false, 350 }; 351 } 352 353 getTeamTypeOptions() { 354 return { 355 dots: true, 356 infinite: false, 357 speed: 300, 358 slidesToShow: 4, 359 slidesToScroll: 4, 360 responsive: [ 361 { 362 breakpoint: 1200, 363 settings: { 364 slidesToShow: 3, 365 slidesToScroll: 3, 366 infinite: true, 367 dots: true 368 } 369 }, 370 { 371 breakpoint: 992, 372 settings: { 373 slidesToShow: 2, 374 slidesToScroll: 2 375 } 376 }, 377 { 378 breakpoint: 576, 379 settings: { 380 slidesToShow: 1, 381 slidesToScroll: 1 382 } 383 } 384 ] 385 }; 386 } 387 388 getCategoryTypeOptions() { 389 return { 390 dots: false, 391 infinite: true, 392 slidesToShow: 6, 393 slidesToScroll: 1, 394 autoplay: true, 395 arrows: true, 396 prevArrow: '<span class="slick-prev"><i class="bi bi-chevron-left"></i></span>', 397 nextArrow: '<span class="slick-next"><i class="bi bi-chevron-right"></i></span>', 398 responsive: [ 399 { 400 breakpoint: 1400, 401 settings: { 402 slidesToShow: 4, 403 slidesToScroll: 4 404 } 405 }, 406 { 407 breakpoint: 820, 408 settings: { 409 slidesToShow: 2, 410 slidesToScroll: 1 411 } 412 }, 413 { 414 breakpoint: 480, 415 settings: { 416 slidesToShow: 2, 417 slidesToScroll: 1 418 } 419 } 420 ] 421 }; 422 } 423 }); 424 425})(); 426 427;(function(){ 428 429 oc.registerControl('quantity-input', class extends oc.ControlBase { 430 connect() { 431 this.$qty = this.element.querySelector('input.quantity-field'); 432 this.listen('click', '.button-plus', this.onIncrementValue); 433 this.listen('click', '.button-minus', this.onDecrementValue); 434 } 435 436 disconnect() { 437 this.$qty = null; 438 } 439 440 onIncrementValue(ev) { 441 ev.preventDefault(); 442 var value = parseInt(this.$qty.value, 10); 443 if (isNaN(value)) { 444 value = 0; 445 } 446 447 this.$qty.value = Math.max(++value, 0); 448 } 449 450 onDecrementValue(ev) { 451 ev.preventDefault(); 452 var value = parseInt(this.$qty.value, 10); 453 if (isNaN(value)) { 454 value = 0; 455 } 456 457 this.$qty.value = Math.max(--value, 0); 458 } 459 460 }); 461 462})(); 463 464addEventListener('render', function() { 465 466 // Auto Collapsed List 467 $('ul.bullet-list li.active:first').each(function() { 468 $(this).parents('ul.collapse').each(function() { 469 $(this).addClass('show').prevAll('.collapse-caret:first').removeClass('collapsed'); 470 }); 471 }); 472 473 // Tooltips 474 $('[data-bs-toggle="tooltip"]').each(function() { 475 $(this).tooltip(); 476 }); 477 478 // Popovers 479 $('[data-bs-toggle="popover"]').each(function() { 480 var $el = $(this); 481 if ($el.data('content-target')) { 482 $el 483 .popover({ html: true, content: $($el.data('content-target')).get(0) }) 484 .on('shown.bs.popover', function() { 485 $('input:first', $($el.data('content-target'))).focus(); 486 }) 487 ; 488 } 489 else { 490 $el.popover(); 491 } 492 }); 493 494 // How it is made 495 setTimeout(function() { 496 $('.how-its-made').removeClass('init'); 497 }, 1); 498 499}
499); 500 501function registerMobileMenuEvents() { 502 const menuToggleButton = document.querySelector("#toggleMobileMenu"); 503 const mainMenuNav = document.querySelector("#mainNav"); 504 const mainMenuNavItems = document.querySelectorAll(".header-content__nav-item"); 505 let mainMenuItemAnimationIncrement = 0.1; 506 507 // On menu toggle 508 menuToggleButton.addEventListener("click", (event) => { 509 event.stopPropagation(); 510 // Add transition delays for the menu elements 511 mainMenuNavItems.forEach((item, index) => { 512 item.style.transitionDelay = `${index * mainMenuItemAnimationIncrement}s`; 513 }); 514 if (mainMenuNav.style.display === "none" || !mainMenuNav.style.display) { 515 menuToggleButton.classList.add("header-content__toggle--active"); 516 this.slideDown(mainMenuNav); 517 mainMenuNav.classList.add("header-content__nav--active"); 518 } else { 519 mainMenuNav.classList.remove("header-content__nav--active"); 520 menuToggleButton.classList.remove("header-content__toggle--active"); 521 this.slideUp(mainMenuNav); 522 } 523 }); 524} 525 526function registerHiddenContentToggleEvents() { 527 document.querySelectorAll("[data-show]").forEach((trigger) => { 528 trigger.addEventListener("click", (event) => { 529 event.preventDefault(); 530 const targetId = trigger.getAttribute("data-show"); 531 const shouldScroll = trigger.getAttribute("data-scroll"); 532 const shouldScrollToContainer = (trigger.getAttribute("data-scroll-to-container") != undefined 533 && trigger.getAttribute("data-scroll-to-container") != false 534 ) ? true : false; 535 const containerElement = trigger.closest(".content--wbg"); 536 const contentElement = document.getElementById(targetId); 537 const showLabel = trigger.getAttribute("data-show-label"); 538 const hideLabel = trigger.getAttribute("data-hide-label"); 539 if (contentElement && !contentElement.classList.contains("slide-animation")) { 540 const isCollapsed = contentElement.clientHeight === 0; 541 if (isCollapsed) { 542 slideDown(contentElement, 200); 543 setTimeout(function(){ 544 if(hideLabel!=undefined && showLabel!=undefined) {trigger.innerHTML=hideLabel;} 545 if (shouldScroll) { 546 if(shouldScrollToContainer) { 547 containerElement.scrollIntoView({ behavior: "smooth", block: "start" }); 548 } 549 else { 550 contentElement.scrollIntoView({ behavior: "smooth", block: "start" }); 551 } 552 } 553 }, 210); 554 } else { 555 slideUp(contentElement, 300); 556 if(hideLabel!=undefined && showLabel!=undefined) {trigger.innerHTML=showLabel;} 557 } 558 } 559 }); 560 561 if(trigger.getAttribute("data-show")!='' && '#open_'+trigger.getAttribute("data-show") == document.location.hash) { 562 trigger.setAttribute("data-scroll-to-container", "true"); 563 trigger.click(); 564 setTimeout(function(){ 565 trigger.setAttribute("data-scroll-to-container", "false"); 566 }, 500); 567 } 568 }); 569} 570 571function registerButtonEvents() { 572 document.querySelectorAll("[data-scroll]").forEach((trigger) => { 573 trigger.addEventListener("click", (event) => { 574 event.preventDefault(); 575 const targetId = trigger.getAttribute("data-scroll"); 576 const contentElement = document.getElementById(targetId); 577 if (contentElement) { 578 contentElement.scrollIntoView({ behavior: "smooth", block: "start" }); 579 const href = trigger.getAttribute("href"); 580 if (href && window.history.pushState) { 581 window.history.pushState({ path: href }, "", href); 582 } 583 } 584 }); 585 });
586} 587 588function scrollToUrlTarget() { 589 setTimeout(() => { 590 const hash = window.location.hash; 591 if (hash) { 592 const targetElement = document.getElementById(hash.substring(1)); 593 if (targetElement) { 594 targetElement.scrollIntoView({ behavior: "smooth", block: "start" }); 595 } 596 } 597 }, 600); 598} 599 600function slideUp(element, duration = 200) { 601 element.classList.add("slide-animation"); 602 element.style.maxHeight = element.scrollHeight + "px"; 603 element.offsetHeight; // Force reflow 604 element.style.maxHeight = 0; 605 window.setTimeout(() => { 606 element.style.display = "none"; 607 element.classList.remove("slide-animation"); 608 element.style.removeProperty("max-height"); 609 }, duration); 610} 611 612function slideDown(element, duration = 200) { 613 element.style.removeProperty("display"); 614 let display = window.getComputedStyle(element).display; 615 if (display === "none") display = "block"; 616 element.style.display = display; 617 618 element.style.maxHeight = "none"; 619 let maxHeight = element.scrollHeight + "px"; 620 element.style.maxHeight = 0; 621 element.offsetHeight; // Force reflow 622 element.classList.add("slide-animation"); 623 element.style.maxHeight = maxHeight; 624 window.setTimeout(() => { 625 element.classList.remove("slide-animation"); 626 element.style.removeProperty("max-height"); 627 }, duration); 628} 629 630addEventListener('render', () => { 631 console.log("here"); 632 registerMobileMenuEvents(); 633 registerHiddenContentToggleEvents(); 634 registerButtonEvents(); 635 scrollToUrlTarget(); 636})
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.