1document.addEventListener('DOMContentLoaded', (e) => { 2 const embeds = document.querySelectorAll('[data-rkt-embed]'); 3 embeds.forEach(function(embed, index, array){ 4 embed.innerHTML = `<iframe width="100%" style="aspect-ratio: 560 / 315; display: block" src="${embed.getAttribute('data-rkt-embed')}" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>` 5 }); 6 7 //hero bg-orange hero-v2 darken-image text-center 8 const header = document.querySelector('header.header'); 9 const main = document.querySelector('main'); 10 if(header && main && (!main.children[0].classList.contains('hero') && !main.children[0].classList.contains('video-hero'))){ 11 header.classList.remove('transparent'); 12 //header.classList.add('header-static'); 13 } 14 15 const pane = document.querySelector('header.header .wsc-search-pane:not(.wsc-inline)'); 16 const search_buttons = document.querySelectorAll('header.header .search-btn'); 17 if(pane){ 18 search_buttons.forEach(function(element, index, array){ 19 element.addEventListener('click', function(e){ 20 pane.classList.add('wsc-show'); 21 setTimeout(function(){ 22 pane.querySelector('input[type="search"]').focus(); 23 //pane.querySelector('form').setAttribute('action', '/'); 24 }, 351); 25 }); 26 }); 27 28 document.addEventListener('keyup', function(e){ 29 if(e.code == 'Escape'){ 30 pane.classList.remove('wsc-show'); 31 } 32 }); 33 } 34 35 const video = document.querySelector('#home-page-video'); 36 if(video){ 37 video.pause(); 38 39 let observer = new IntersectionObserver((entries, observer) => { 40 entries.forEach(entry => { 41 if(entry.intersectionRatio <= 0){ 42 //out of viewport: 43 video.pause(); 44 video.currentTime = 0; 45 }else if(entry.intersectionRatio >= 0.5 && video.currentTime == 0){ 46 video.play(); 47 } 48 }); 49 }, {threshold: [0,0.25,0.5,0.75,1]}); 50 observer.observe(video); 51 } 52 53 //GDRP: 54 const gdrp_notice = document.querySelector('#gdrp-notice'); 55 if(gdrp_notice){ 56 const nodes = gdrp_notice.querySelectorAll('button, .close'); 57 nodes.forEach(function(element, index, array){ 58 element.addEventListener('click', function(e){ 59 e.preventDefault(); 60 const timestamp = new Date().getTime(); // current time 61 const exp = timestamp + (60 * 60 * 24 * 1000 * 365);//plus one year 62 setCookie('gdrpaccept', 1, exp); 63 64 gdrp_notice.classList.add('hide'); 65 return false; 66 }); 67 }); 68 69 if(document.cookie.indexOf('gdrpaccept=1') == -1){ 70 trace('document.cookie') 71 trace(document.cookie) 72 73 gdrp_notice.classList.remove('hide'); 74 } 75 } 76 77 function setCookie(variable, value, expires_seconds){ 78 var d = new Date(); 79 d = new Date(d.getTime() + 1000 * expires_seconds); 80 document.cookie = variable + '=' + value + '; path=/; expires=' + d.toGMTString() + ';'; 81 } 82 83 //because Safari does some weird thing on scroll to the map: 84 const map = document.querySelector('wsc-map'); 85 if(map && window.matchMedia('(hover: none)').matches){ 86 window.addEventListener('scroll', function(e){ 87 if(!map.classList.contains('wsc-active')){ 88 map.moveMap({left:-5000, top:-5000}); 89 } 90 }); 91 } 92 93 //WOOCOMMERCE PRODUCT BUTTONS HACK: 94 const product_buttons = document.querySelectorAll('li.product .button.add_to_cart_button'); 95 product_buttons.forEach(function(button, index, array){ 96 const div = document.createElement('div'); 97 button.parentNode.appendChild(div); 98 div.appendChild(button); 99 }); 100}); 101 102//trigger newsletter on home page if hash is "newsletter": 103document.addEventListener('DOMContentLoaded', function(e){ 104 const home_body = document.querySelector('body.home'); 105 if(home_body && window.location.hash.substr(1) == 'newsletter'){ 106 setTimeout(function(){ 107 jQuery('.hero__subscribe.btn').trigger('click'); 108 }, 125); 109 } 110}); 111 112document.addEventListener('DOMContentLoaded', function(e){ 113 const pa_color = document.querySelector('#pa_color'); 114 if(pa_color){ 115 removeDefaultValue(pa_color); 116 pa_color.addEventListener('change', removeDefaultValue); 117 } 118 119 const pa_size = document.querySelector('#pa_size'); 120 if(pa_size){ 121 removeDefaultValue(pa_size); 122 pa_size.addEventListener('change', removeDefaultValue); 123 } 124 125 function removeDefaultValue(select){ 126 const target = (typeof select.target === 'undefined') ? select : select.target; 127 if(target.options[0].value == '' && target.selectedIndex != 0){ 128 target.removeChild(target[0]); 129 target.removeEventListener('change', removeDefaultValue); 130 } 131 } 132}); 133 134function trace(m){console.log(m);} 135function createSVGElement(tag, target=null){ 136 var element = document.createElementNS('http://www.w3.org/2000/svg', tag); 137 if(target){ 138 target.appendChild(element); 139 } 140 return element; 141} 142//ex: setAttributes(circle, {cx:point.x, cy:point.y, r:1.5, fill:'#f00'}); 143function setAttributes(target, attributes){ 144 for(var prop in attributes) { 145 if(Object.prototype.hasOwnProperty.call(attributes, prop)){ 146 target.setAttribute(prop, attributes[prop]); 147 } 148 } 149} 150 151//wsc-map: 152customElements.define('wsc-map', class extends HTMLElement{ 153 #events = ['click', 'dblclick', 'dragstart', 'mousedown', 'mouseenter', 'mousemove', 'touchstart', 'touchmove', 'touchcancel', 'touchend', 'wheel']; 154 map; 155 #mw = 4777;//map width 156 #mh = 2016;//map height 157 #ZOOM_MAX = 2; 158 #vw;//viewport width 159 #vh;//viewport height 160 #min_zoom; 161 #mouse = {x:0, y:0} 162 #dragging_app = {dragging:false, x:0, y:0, offset:null}; 163 #dots; 164 #modals; 165 #is_touch_device; 166 167 constructor(){ 168 super(); 169 } 170 171 init(){ 172 const component = this; 173
174 const map = component.map = component.querySelector('.wsc-map'); 175 176 const svg = component.querySelector('.wsc-layer-0'); 177 178 const items = component.querySelector('.wsc-items'); 179 180 component.#dots = component.querySelectorAll('.wsc-dot'); 181 component.#modals = component.querySelectorAll('.wsc-modal-content'); 182 183 component.#events.forEach(function(event){ 184 component.addEventListener(event, component); 185 }); 186 187 component.size(); 188 189 const portrait = window.matchMedia('(orientation: portrait)'); 190 191 if(portrait.matches){ 192 //pan all the way to right: 193 component.moveMap({left:-5000, top:-5000}); 194 }else{ 195 //zoom map one "tick" and centering on the right: 196 component.zoomMap({center:{x:component.#vw, y:component.#vh * 0.5}, zoom_delta:0.125}); 197 } 198 199 window.addEventListener('resize', component.size.bind(component)); 200 document.addEventListener('mouseup', component.mouseUp.bind(component)); 201 202 const touch_device = window.matchMedia('(hover: none)'); 203 touch_device.addListener(deviceTypeChange); 204 205 deviceTypeChange(touch_device); 206 207 function deviceTypeChange(e){ 208 component.#is_touch_device = e.matches; 209 trace('is_touch_device: '+component.#is_touch_device); 210 } 211 } 212 213 connectedCallback(){ 214 const component = this; 215 216 if(document.readyState !== 'loading'){ 217 component.init(); 218 return; 219 } 220 document.addEventListener('DOMContentLoaded', () => component.init()); 221 } 222 223 disconnectedCallback(){ 224 const component = this; 225 component.#events.forEach(function(event){ 226 component.removeEventListener(event, component); 227 }); 228 229 window.removeEventListener('resize', component.resize.bind(component)); 230 document.removeEventListener('mouseup', component.mouseUp.bind(component)); 231 } 232 233 handleEvent(e){ 234 //trace(e.type); 235 236 const component = this; 237 238 if(['click', 'dblclick', 'dragstart', 'mousedown', 'touchstart', 'touchmove'].indexOf(e.type) != -1){ 239 if(component.#is_touch_device){ 240 //touch device, only register for link: 241 if(e.target.matches('a.wsc-touch-device')){ 242 component.querySelector('.wsc-intro').classList.add('wsc-hide'); 243 component.classList.add('wsc-active'); 244 return; 245 } 246 if(e.target.matches('[data-action="exit"]')){ 247 component.classList.remove('wsc-active'); 248 } 249 }else{ 250 component.classList.add('wsc-active'); 251 } 252 } 253 254 //on touch devices, don't handle events until map is active: 255 if(component.#is_touch_device && !component.classList.contains('wsc-active')){ 256 return; 257 } 258 259 if(e.type == 'dragstart' && e.target.matches('.wsc-map')){ 260 e.preventDefault(); 261 return false; 262 } 263 264 if(e.type == 'mousedown' || (e.type == 'touchstart' && e.changedTouches.length == 1)){ 265 //e.preventDefault(); 266 267 component.#dragging_app.dragging = true; 268 269 let x, y; 270 if(e.type == 'mousedown'){ 271 x = e.clientX; 272 y = e.clientY; 273 }else{ 274 const touch = e.changedTouches[0]; 275 x = touch.clientX; 276 y = touch.clientY; 277 } 278 component.#dragging_app.x = x - parseInt(component.map.style.left); 279 component.#dragging_app.y = y - parseInt(component.map.style.top); 280 281 //return; 282 } 283 284 if(e.type == 'mousemove' || (e.type == 'touchmove' && e.changedTouches.length == 1)){ 285 e.preventDefault(); 286 287 let x, y; 288 if(e.type == 'mousemove'){ 289 x = e.clientX; 290 y = e.clientY; 291 }else{ 292 const touch = e.changedTouches[0]; 293 x = touch.clientX; 294 y = touch.clientY; 295 } 296 297 component.#mouse = {x:x, y:y} 298 299 if(component.#dragging_app.dragging){ 300 component.moveMap({ 301 left: x-component.#dragging_app.x, 302 top: y-component.#dragging_app.y 303 }); 304 } 305 306 return; 307 } 308 309 if(e.type == 'wheel' && e.altKey){ 310 e.preventDefault(); 311 312 var delta = e.deltaY; 313 var zoom_delta = delta * -0.005; 314 var center = {x:component.#mouse.x, y:component.#mouse.y}; 315 316 component.zoomMap({center:center, zoom_delta:zoom_delta}); 317 318 return; 319 } 320 321 const click = (e.type == 'click' || (e.type == 'touchstart' && e.changedTouches.length == 1)); 322 323 //click on dot or dropdown menu item: 324 if(click && e.target.closest('[data-index]')){ 325 e.preventDefault(); 326 327 const item = e.target.closest('[data-index]'); 328 const index = parseInt(item.getAttribute('data-index')); 329 330 item.classList.add('wsc-active'); 331 332 component.showModal(index); 333 334 component.querySelector('.wsc-label').classList.remove('wsc-open'); 335 336 return; 337 } 338 339 if((click && e.target.closest('.wsc-modal-close')) || (click && e.target.closest('.wsc-modal.wsc-show'))){ 340 component.querySelector('.wsc-modal').classList.remove('wsc-show');
341 component.#dots.forEach(function(dot){ 342 dot.classList.remove('wsc-active'); 343 }); 344 345 return; 346 } 347 348 if(click && e.target.matches('[data-action="zoom"]')){ 349 e.preventDefault(); 350 351 const dir = e.target.getAttribute('data-value'); 352 const data = {zd:0, last:0} 353 const center = {x:component.#vw * 0.5, y:component.#vh * 0.5} 354 const mod = (dir == 'out') ? -1 : 1; 355 356 gsap.to(data, {duration:0.5, zd:0.125, ease:'power1.inOut', onUpdate:function(){ 357 component.zoomMap({center:center, zoom_delta:(data.zd - data.last) * mod}); 358 data.last = data.zd; 359 }}); 360 361 return; 362 } 363 364 if(click && e.target.closest('.wsc-label')){ 365 e.preventDefault(); 366 367 e.target.classList.toggle('wsc-open'); 368 369 return; 370 } 371 372 if(e.type == 'dblclick'){ 373 e.preventDefault(); 374 375 const data = {zd:0, last:0} 376 const center = {x:e.clientX, y:e.clientY}; 377 const mod = (e.altKey) ? -1 : 1; 378 379 gsap.to(data, {duration:0.5, zd:0.125, ease:'power1.inOut', onUpdate:function(){ 380 component.zoomMap({center:center, zoom_delta:(data.zd - data.last) * mod}); 381 data.last = data.zd; 382 }}); 383 384 return; 385 } 386 } 387 388 size(){ 389 const component = this; 390 391 const rect = component.getBoundingClientRect(); 392 393 const vw = component.#vw = rect.width;
394 const vh = component.#vh = rect.height; 395 const mw = component.#mw; 396 const mh = component.#mh; 397 398 component.zoom = Math.max(vh/mh, vw/mw); 399 400 component.#min_zoom = component.zoom; 401 402 gsap.set(component.map, {transformOrigin:'0 0', scale:component.zoom, left:vw * 0.5 - (mw * component.zoom * 0.5), top:vh * 0.5 - (mh * component.zoom * 0.5)}); 403 gsap.set(component.#dots, {transformOrigin:'50% 50%', scale:Math.max(2, 1/component.zoom)}); 404 } 405 406 mouseUp(){ 407 const component = this; 408 409 component.#dragging_app.dragging = false; 410 } 411 412 moveMap(pos){ 413 const component = this; 414 415 let top, right, bottom, left; 416 417 const mw = component.#mw; 418 const mh = component.#mh; 419 const vw = component.#vw; 420 const vh = component.#vh; 421 const zoom = component.zoom; 422 423// trace(component.#dragging_app) 424 trace('moveMap: '+pos); 425 426 //need to round off products b/c Chrome SUCKS SHIT! 427 428 if(Math.round(mw * zoom) < vw){ 429 let margin = (vw - (mw * zoom)) * 0.5; 430 left = margin; 431 right = (mw * zoom) + margin; 432 }else{ 433 left = 0; 434 right = mw * zoom; 435 } 436 437 if(Math.round(mh * zoom) < vh){ 438 let margin = (vh - (mh * zoom)) * 0.5; 439 top = margin; 440 bottom = (mh * zoom) + margin; 441 }else{ 442 top = 0; 443 bottom = mh * zoom; 444 } 445 446 if(pos.top > top){ 447 pos.top = top; 448 }else if(pos.top < vh-bottom){ 449 pos.top = vh-bottom; 450 } 451 if(pos.left > left){ 452 pos.left = left; 453 }else if(pos.left < vw-right){ 454 pos.left = vw-right; 455 } 456 457 gsap.set(component.map, {left:pos.left, top:pos.top}); 458 } 459 460 zoomMap({center, zoom_delta}){ 461 const component = this; 462 463 let width = component.#mw * component.zoom; 464 let height = component.#mh * component.zoom; 465 let xpct = ((center.x - component.map.offsetLeft) / width); 466 let ypct = ((center.y - component.map.offsetTop) / height); 467 468 component.zoom += zoom_delta; 469 component.zoom = Math.min(component.zoom, component.#ZOOM_MAX); 470 component.zoom = Math.max(component.zoom, component.#min_zoom); 471 472 gsap.set(component.map, {transformOrigin:'0 0', scale:component.zoom}); 473 474 gsap.set(component.#dots, {transformOrigin:'50% 50%', scale:Math.max(2, 1/component.zoom)}); 475 476 width = component.#mw * component.zoom; 477 height = component.#mh * component.zoom; 478 479 component.moveMap({ 480 left: center.x - (width * xpct), 481 top: center.y - (height * ypct) 482 }); 483 } 484 485 showModal(index){ 486 const component = this; 487 488 const modal = component.querySelector('.wsc-modal'); 489 490 component.#modals.forEach(function(element){ 491 const content_index = parseInt(element.dataset.modalIndex); 492 element.classList.toggle('wsc-show', index == content_index); 493 }); 494 495 modal.classList.add('wsc-show'); 496 497 trace(index) 498 } 499}); 500 501//wsc-photo-gallery: 502customElements.define('wsc-photo-gallery', class extends HTMLElement{ 503 #images; 504 505 init(){ 506 const component = this; 507 508 component.#images = component.querySelectorAll('img'); 509 510 component.addEventListener('click', component); 511 window.addEventListener('scroll', function(e){ 512 component.classList.remove('open'); 513 }); 514 document.addEventListener('keydown', function(e){ 515 if(!component.classList.contains('open')){return;} 516 517 if(e.key == 'Escape'){ 518 component.classList.remove('open'); 519 }else if(e.key == 'ArrowRight'){ 520 component.advance(1); 521 }else if(e.key == 'ArrowLeft'){ 522 component.advance(-1); 523 } 524 }); 525 } 526 527 connectedCallback(){ 528 const component = this; 529 530 if(document.readyState !== 'loading'){component.init(); return;} 531 document.addEventListener('DOMContentLoaded', () => component.init()); 532 } 533 534 handleEvent(e){ 535 const component = this; 536 537 if(e.target.matches('img')){ 538 component.classList.add('open'); 539 component.activateImage(e.target); 540 } 541 if(e.target.matches('.close')){ 542 component.classList.remove('open'); 543 } 544 if(e.target.matches('.next') || e.target.matches('.prev')){ 545 if(e.target.matches('.next')){ 546 component.advance(1); 547 }else{ 548 component.advance(-1) 549 } 550 } 551 } 552 553 advance(direction){ 554 const component = this; 555 556 const active_image = component.querySelector('img.active'); 557 let index = Array.from(component.#images).indexOf(active_image); 558 559 index += direction; 560 if(index >= component.#images.length){ 561 index = 0; 562 } 563 if(index < 0){ 564 index = component.#images.length-1; 565 } 566 567 component.activateImage(component.#images[index]); 568 } 569 570 activateImage(image_to_activate){ 571 const component = this;
572 component.#images.forEach(function(image){ 573 image.classList.toggle('active', image == image_to_activate); 574 }); 575 } 576});
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.