1window.lazySizesConfig = window.lazySizesConfig || {}; 2window.lazySizesConfig.expand = 150; 3window.lazySizesConfig.loadMode = 1; 4window.lazySizesConfig.loadHidden = false; 5 6gsap.defaults({ 7 ease: 'power1.out' 8}); 9 10gsap.config({ 11 nullTargetWarn: false 12}); 13 14if (typeof debounce === 'undefined') { 15 function debounce(fn, wait) { 16 let t; 17 return (...args) => { 18 clearTimeout(t); 19 t = setTimeout(() => fn.apply(this, args), wait); 20 }; 21 } 22} 23 24/** 25 * @class 26 * @function ProductCard 27 */ 28if (!customElements.get('product-card')) { 29 class ProductCard extends HTMLElement { 30 constructor() { 31 super(); 32 this.quick_add = this.querySelector('.product-card--add-to-cart-button-simple'); 33 } 34 connectedCallback() { 35 if (this.quick_add) { 36 this.enableQuickAdd(); 37 } 38 } 39 enableQuickAdd() { 40 this.quick_add.addEventListener('click', this.quickAdd.bind(this)); 41 } 42 43 quickAdd(evt) { 44 evt.preventDefault(); 45 if (this.quick_add.disabled) { 46 return; 47 } 48 this.quick_add.classList.add('loading'); 49 this.classList.add('thb-loading'); 50 this.quick_add.innerHTML = window.theme.strings.addingToCart; 51 this.quick_add.setAttribute('aria-disabled', true); 52 53 const config = { 54 method: 'POST', 55 headers: { 56 'X-Requested-With': 'XMLHttpRequest', 57 'Accept': 'application/javascript' 58 } 59 }; 60 61 let formData = new FormData(this.form); 62 63 formData.append('id', this.quick_add.dataset.productId); 64 formData.append('quantity', 1); 65 formData.append('sections', this.getSectionsToRender().map((section) => section.section)); 66 formData.append('sections_url', window.location.pathname); 67 68 config.body = formData; 69 70 fetch(`${theme.routes.cart_add_url}`, config) 71 .then((response) => response.json()) 72 .then((response) => { 73 if (response.status) { 74 return; 75 } 76 this.renderContents(response); 77 78 dispatchCustomEvent('cart:item-added', { 79 product: response.hasOwnProperty('items') ? response.items[0] : response 80 }); 81 }) 82 .catch((e) => { 83 console.error(e); 84 }) 85 .finally(() => { 86 this.quick_add.innerHTML = window.theme.strings.addToCart; 87 this.classList.remove('thb-loading'); 88 this.quick_add.classList.remove('loading'); 89 this.quick_add.removeAttribute('aria-disabled'); 90 }); 91 92 return false; 93 } 94 getSectionsToRender() { 95 return [{ 96 id: 'Cart', 97 section: 'main-cart', 98 selector: '.thb-cart-form' 99 }, 100 { 101 id: 'Cart-Drawer', 102 section: 'cart-drawer', 103 selector: '.cart-drawer' 104 }, 105 { 106 id: 'cart-drawer-toggle', 107 section: 'cart-bubble', 108 selector: '.float_count' 109 }]; 110 } 111 renderContents(parsedState) {
112 this.getSectionsToRender().forEach((section => { 113 if (!document.getElementById(section.id)) { 114 return; 115 } 116 const elementToReplace = document.getElementById(section.id).querySelector(section.selector) || document.getElementById(section.id); 117 elementToReplace.innerHTML = this.getSectionInnerHTML(parsedState.sections[section.section], section.selector); 118 119 if (section.id == 'Cart-Drawer') { 120 if (typeof CartDrawer !== 'undefined') { 121 new CartDrawer(); 122 } 123 } 124 if (section.id == 'Cart') { 125 if (typeof Cart !== 'undefined') { 126 new Cart().renderContents(parsedState); 127 } 128 } 129 })); 130 131 let quick_shop = document.getElementById('Quick-Drawer'), 132 cart_drawer = document.getElementById('Cart-Drawer'), 133 latency = 100; 134 135 if (cart_drawer && quick_shop?.contains(this)) { 136 137 quick_shop.querySelector('.thb-close').click(); 138 139 latency = 750; 140 } 141 142 setTimeout(() => { 143 document.getElementById('cart-drawer-toggle').click(); 144 dispatchCustomEvent('cart-drawer:open'); 145 }, latency); 146 147 } 148 getSectionInnerHTML(html, selector = '.shopify-section') { 149 return new DOMParser() 150 .parseFromString(html, 'text/html') 151 .querySelector(selector).innerHTML; 152 } 153 } 154 customElements.define('product-card', ProductCard); 155} 156 157/** 158 * @class 159 * @function LocalizationForm 160 */ 161if (!customElements.get('localization-form')) { 162 class LocalizationForm extends HTMLElement { 163 constructor() { 164 super(); 165 this.form = this.querySelector('form'); 166 this.inputs = this.form.querySelectorAll('[name="locale_code"], [name="country_code"]'); 167 this.debouncedOnSubmit = debounce((event) => { 168 this.onSubmitHandler(event); 169 }, 200); 170 this.inputs.forEach(item => item.addEventListener('change', this.debouncedOnSubmit.bind(this))); 171 } 172 onSubmitHandler(event) { 173 if (this.form) this.form.submit(); 174 } 175 } 176 customElements.define('localization-form', LocalizationForm); 177} 178 179/** 180 * @class 181 * @function CartDrawer 182 */ 183class CartDrawer { 184 185 constructor(args) { 186 this.container = document.getElementById('Cart-Drawer'); 187 this.wrapper = document.getElementById('wrapper'); 188 this.cc = document.querySelector('.click-capture'); 189 190 if (!this.container) { 191 return; 192 } 193 this.close = this.container.querySelector('.thb-close'); 194 this.button = document.getElementById('cart-drawer-toggle'); 195 196 // Add functionality to buttons 197 this.setupCartAnimation(); 198 199 // Setup Events 200 this.setupEventListeners(); 201 202 // Notes Toggle 203 this.notesToggle(); 204 205 // Remove buttons 206 this.removeProductEvent(); 207 208 // Terms checkbox 209 this.termsCheckbox(); 210 } 211 setupCartAnimation() { 212 this.tl = gsap.timeline({ 213 paused: true, 214 onStart: () => { 215 this.wrapper.classList.add('open-cc'); 216 gsap.set(this.container, { 217 visibility: "visible" 218 }); 219 }, 220 onReverseComplete: () => { 221 this.wrapper.classList.remove('open-cc'); 222 gsap.set(this.container, { 223 clearProps: "transform" 224 }); 225 this.container.blur(); 226 }, 227 onComplete: () => { 228 this.container.focus(); 229 dispatchCustomEvent('cart-drawer:open'); 230 } 231 }); 232 this.tl.clear(); 233 this.tl 234 .to(this.container, { 235 x: "0%", 236 duration: 0.25 237 }, "start") 238 .fromTo(this.container.querySelectorAll('.mini_cart_item, .mini-cart__row, .mini-cart__notes, .mini-cart__buttons'), { 239 x: "30", 240 opacity: 0 241 }, { 242 duration: 0.25, 243 x: "0", 244 opacity: 1, 245 stagger: 0.05 246 }, "start+=0.2"); 247 } 248 closeDrawer() { 249 this.tl.timeScale(1.5).reverse(); 250 } 251 setupEventListeners() { 252 this.debouncedOnChange = debounce((event) => { 253 this.onChange(event); 254 }, 300); 255 256 document.addEventListener('cart:refresh', (event) => { 257 this.refresh(); 258 }); 259 260 this.container.addEventListener('change', this.debouncedOnChange.bind(this)); 261 262 this.button.addEventListener('click', (e) => { 263 264 if (document.body.classList.contains('template-cart')) { 265 return false;
266 } 267 this.tl.timeScale(1).play(); 268 e.preventDefault(); 269 }); 270 271 this.cc.addEventListener('click', this.closeDrawer.bind(this)); 272 this.close.addEventListener('click', this.closeDrawer.bind(this)); 273 274 document.addEventListener('keyup', (e) => { 275 if (e.code) { 276 if (e.code.toUpperCase() === 'ESCAPE') { 277 this.closeDrawer(); 278 } 279 } 280 }); 281 } 282 onChange(event) { 283 if (event.target.classList.contains('qty')) { 284 this.updateQuantity(event.target.dataset.index, event.target.value); 285 } 286 } 287 removeProductEvent() { 288 let removes = this.container.querySelectorAll('.remove'); 289 290 removes.forEach((remove) => { 291 remove.addEventListener('click', (event) => { 292 this.updateQuantity(event.target.dataset.index, '0'); 293 294 event.preventDefault(); 295 }); 296 }); 297 } 298 getSectionsToRender() { 299 return [{ 300 id: 'Cart-Drawer', 301 section: 'cart-drawer', 302 selector: '.side-panel-content' 303 }, 304 { 305 id: 'cart-drawer-toggle', 306 section: 'cart-bubble', 307 selector: '.float_count' 308 }]; 309 } 310 getSectionInnerHTML(html, selector) { 311 return new DOMParser() 312 .parseFromString(html, 'text/html') 313 .querySelector(selector).innerHTML; 314 } 315 termsCheckbox() { 316 let terms_checkbox = this.container.querySelector('#CartDrawerTerms'), 317 checkout_button = this.container.querySelector('.button.checkout'); 318 319 if (terms_checkbox && checkout_button) { 320 terms_checkbox.setCustomValidity(theme.strings.requiresTerms); 321 checkout_button.addEventListener('click', function (e) { 322 if (!terms_checkbox.checked) { 323 terms_checkbox.reportValidity(); 324 terms_checkbox.focus(); 325 e.preventDefault(); 326 } 327 }); 328 } 329 } 330 notesToggle() { 331 let notes_toggle = document.getElementById('order-note-toggle'); 332 333 if (!notes_toggle) { 334 return; 335 } 336 337 notes_toggle.addEventListener('click', function () { 338 notes_toggle.classList.toggle('active'); 339 }); 340 notes_toggle.nextElementSibling.querySelector('.button').addEventListener('click', () => { 341 notes_toggle.classList.remove('active'); 342 this.saveNotes(); 343 }); 344 } 345 saveNotes() { 346 fetch(`${theme.routes.cart_update_url}.js`, { 347 method: 'POST', 348 headers: { 349 'Content-Type': 'application/json', 350 'Accept': `application/json` 351 }, 352 body: JSON.stringify({ 353 'note': document.getElementById('mini-cart__notes').value 354 }) 355 }); 356 } 357 updateQuantity(line, quantity) { 358 this.container.querySelector(`#CartDrawerItem-${line}`).classList.add('thb-loading'); 359 const body = JSON.stringify({ 360 line, 361 quantity, 362 sections: this.getSectionsToRender().map((section) => section.section), 363 sections_url: window.location.pathname 364 }); 365 366 dispatchCustomEvent('line-item:change:start', { 367 quantity: quantity 368 }); 369 fetch(`${theme.routes.cart_change_url}`, { 370 method: 'POST', 371 headers: { 372 'Content-Type': 'application/json', 373 'Accept': `application/json` 374 }, 375 ...{ 376 body 377 } 378 }) 379 .then((response) => { 380 return response.text(); 381 }) 382 .then((state) => { 383 const parsedState = JSON.parse(state); 384
385 this.getSectionsToRender().forEach((section => { 386 const elementToReplace = document.getElementById(section.id).querySelector(section.selector) || document.getElementById(section.id); 387 388 if (parsedState.sections) { 389 elementToReplace.innerHTML = this.getSectionInnerHTML(parsedState.sections[section.section], section.selector); 390 } 391 })); 392 this.removeProductEvent(); 393 this.notesToggle(); 394 this.termsCheckbox(); 395 dispatchCustomEvent('line-item:change:end', { 396 quantity: quantity, 397 cart: parsedState 398 }); 399 if (this.container.querySelector(`#CartDrawerItem-${line}`)) { 400 this.container.querySelector(`#CartDrawerItem-${line}`).classList.remove('thb-loading'); 401 } 402 }); 403 } 404 refresh() { 405 let sections = 'cart-drawer,cart-bubble'; 406 fetch(`${window.location.pathname}?sections=${sections}`) 407 .then((response) => { 408 return response.text(); 409 }) 410 .then((state) => { 411 const parsedState = JSON.parse(state); 412
413 this.getSectionsToRender().forEach((section => { 414 const elementToReplace = document.getElementById(section.id).querySelector(section.selector) || document.getElementById(section.id); 415 416 elementToReplace.innerHTML = this.getSectionInnerHTML(parsedState[section.section], section.selector); 417 })); 418 419 this.removeProductEvent(); 420 this.notesToggle(); 421 this.termsCheckbox(); 422 }); 423 } 424} 425 426/** 427 * @class 428 * @function Animation 429 */ 430class ScrollAnimation { 431 constructor() { 432 this.elements = document.querySelectorAll('.animation'); 433 this.args = { 434 duration: 0.75, 435 ease: 'power1.out', 436 autoAlpha: 1, 437 x: 0, 438 y: 0, 439 z: 0, 440 scale: 1, 441 rotationZ: '0deg', 442 rotationX: '0deg', 443 rotationY: '0deg', 444 stagger: 0.3, 445 }; 446 447 this.setupScrollTrigger(); 448 } 449 setupScrollTrigger() { 450 451 ScrollTrigger.config({ limitCallbacks: true }); 452 ScrollTrigger.batch(this.elements, { 453 onEnter: batch => gsap.to(batch, this.args), 454 onEnterBack: batch => gsap.to(batch, this.args), 455 }); 456 window.dispatchEvent(new Event('scroll')); 457 } 458} 459 460/** 461 * @class 462 * @function RetinaJS 463 */ 464if (typeof RetinaJS == 'undefined') { 465 class RetinaJS { 466 constructor() { 467 this.elements = document.querySelectorAll('img.retina_size:not(.retina_active)'); 468 469 this.elements.forEach(function (elem) { 470 let w = elem.getAttribute('width'), 471 h = elem.getAttribute('height'); 472 473 elem.setAttribute('width', w / 2); 474 475 if (h) { 476 elem.setAttribute('height', h / 2); 477 } 478 479 elem.classList.add('retina_active'); 480 }); 481 } 482 } 483 new RetinaJS(); 484} 485 486/** 487 * @class 488 * @function ModalDialog 489 */ 490if (!customElements.get('modal-dialog')) { 491 class ModalDialog extends HTMLElement { 492 constructor() { 493 super(); 494 this.querySelector('[id^="ModalClose-"]').addEventListener( 495 'click', 496 this.hide.bind(this) 497 ); 498 this.addEventListener('keyup', (event) => { 499 if (event.code.toUpperCase() === 'ESCAPE') this.hide(); 500 }); 501 if (this.classList.contains('media-modal')) { 502 this.addEventListener('pointerup', (event) => { 503 if (event.pointerType === 'mouse' && !event.target.closest('product-model')) this.hide(); 504 }); 505 } else { 506 this.addEventListener('click', (event) => { 507 if (event.target.nodeName === 'MODAL-DIALOG') this.hide(); 508 }); 509 } 510 } 511 512 connectedCallback() { 513 if (this.moved) return; 514 this.moved = true; 515 document.body.querySelector('#wrapper').appendChild(this); 516 } 517 518 show(opener) { 519 this.openedBy = opener; 520 document.body.classList.add('overflow-hidden'); 521 this.setAttribute('open', ''); 522 } 523 524 hide() { 525 document.body.classList.remove('overflow-hidden'); 526 this.removeAttribute('open'); 527 this.querySelectorAll('.js-youtube').forEach((video) => { 528 video.contentWindow.postMessage('{"event":"command","func":"' + 'pauseVideo' + '","args":""}', '*'); 529 }); 530 this.querySelectorAll('.js-vimeo').forEach((video) => { 531 video.contentWindow.postMessage('{"method":"pause"}', '*'); 532 }); 533 this.querySelectorAll('video').forEach((video) => video.pause()); 534 } 535 } 536 customElements.define('modal-dialog', ModalDialog); 537 class ModalOpener extends HTMLElement { 538 constructor() { 539 super(); 540 541 const button = this.querySelector('button'); 542 543 if (!button) return; 544 button.addEventListener('click', () => { 545 const modal = document.querySelector(this.getAttribute('data-modal')); 546 if (modal) modal.show(button); 547 }); 548 } 549 } 550 customElements.define('modal-opener', ModalOpener); 551} 552 553 554window.addEventListener('resize', () => { 555 document.querySelectorAll('.footer .widget--menu').forEach((detail) => { 556 if (window.innerWidth < 768) { 557 detail.removeAttribute('open'); 558 } else { 559 detail.setAttribute('open', ''); 560 } 561 }); 562}); 563window.addEventListener('DOMContentLoaded', () => { 564 if (typeof CartDrawer !== 'undefined') { 565 new CartDrawer({ animations: true }); 566 } 567 if (typeof ScrollAnimation !== 'undefined') { 568 new ScrollAnimation(); 569 } 570});
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.