1<!doctype html> 2<html lang="de"> 3<head > 4 <meta charset="utf-8"/> 5<meta name="title" content="Homepage"/> 6<meta name="robots" content="INDEX,FOLLOW"/> 7<meta name="viewport" content="width=device-width, initial-scale=1"/> 8<title>Homepage</title> 9 <link rel="stylesheet" type="text/css" media="all" href="https://shop.hk-verlag.de/static/version1787125028/frontend/DieMayrei/hyva_child/de_DE/css/styles.css" /> 10<link rel="stylesheet" type="text/css" media="all" href="https://shop.hk-verlag.de/static/version1787125028/frontend/DieMayrei/hyva_child/de_DE/DieMayrei_Widerruf/css/widerruf.css" /> 11<link rel="stylesheet" type="text/css" media="all" href="https://shop.hk-verlag.de/static/version1787125028/frontend/DieMayrei/hyva_child/de_DE/Payone_Core/css/payone.css" /> 12<link rel="icon" type="image/x-icon" href="https://shop.hk-verlag.de/media/favicon/default/HK_Bildmarke_96px.png" /> 13<link rel="shortcut icon" type="image/x-icon" href="https://shop.hk-verlag.de/media/favicon/default/HK_Bildmarke_96px.png" /> 14
14<script> 15 var BASE_URL = 'https://shop.hk-verlag.de/de/'; 16 var THEME_PATH = 'https://shop.hk-verlag.de/static/version1787125028/frontend/DieMayrei/hyva_child/de_DE'; 17 var COOKIE_CONFIG = { 18 "expires": null, 19 "path": "\u002F", 20 "domain": ".shop.hk\u002Dverlag.de", 21 "secure": true, 22 "lifetime": "3600", 23 "cookie_restriction_enabled": false }; 24 var CURRENT_STORE_CODE = 'de'; 25 var CURRENT_WEBSITE_ID = '1'; 26 27 window.hyva = window.hyva || {} 28 29 window.cookie_consent_groups = window.cookie_consent_groups || {} 30 window.cookie_consent_groups['necessary'] = true; 31 32 window.cookie_consent_config = window.cookie_consent_config || {}; 33 window.cookie_consent_config['necessary'] = [].concat( 34 window.cookie_consent_config['necessary'] || [], 35 [ 36 'user_allowed_save_cookie', 37 'form_key', 38 'mage-messages', 39 'private_content_version', 40 'mage-cache-sessid', 41 'last_visited_store', 42 'section_data_ids' 43 ] 44 ); 45</script>
vendor: 1 bytes, line 45
45
46<script> 47 (function( hyva, undefined ) { 48 49 function lifetimeToExpires(options, defaults) { 50 51 const lifetime = options.lifetime || defaults.lifetime; 52 53 if (lifetime) { 54 const date = new Date; 55 date.setTime(date.getTime() + lifetime * 1000); 56 return date; 57 } 58 59 return null; 60 } 61 62 function generateRandomString() { 63 64 const allowedCharacters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', 65 length = 16; 66 67 let formKey = '', 68 charactersLength = allowedCharacters.length; 69 70 for (let i = 0; i < length; i++) { 71 formKey += allowedCharacters[Math.round(Math.random() * (charactersLength - 1))] 72 } 73 74 return formKey; 75 } 76 77 const sessionCookieMarker = {noLifetime: true} 78 79 const cookieTempStorage = {}; 80 81 const internalCookie = { 82 get(name) { 83 const v = document.cookie.match('(^|;) ?' + name + '=([^;]*)(;|$)'); 84 return v ? v[2] : null; 85 }, 86 set(name, value, days, skipSetDomain) { 87 let expires, 88 path, 89 domain, 90 secure, 91 samesite; 92 93 const defaultCookieConfig = { 94 expires: null, 95 path: '/', 96 domain: null, 97 secure: false, 98 lifetime: null, 99 samesite: 'lax' 100 }; 101 102 const cookieConfig = window.COOKIE_CONFIG || {}; 103 104 expires = days && days !== sessionCookieMarker 105 ? lifetimeToExpires({lifetime: 24 * 60 * 60 * days, expires: null}, defaultCookieConfig) 106 : lifetimeToExpires(window.COOKIE_CONFIG, defaultCookieConfig) || defaultCookieConfig.expires; 107 108 path = cookieConfig.path || defaultCookieConfig.path; 109 domain = !skipSetDomain && (cookieConfig.domain || defaultCookieConfig.domain); 110 secure = cookieConfig.secure || defaultCookieConfig.secure; 111 samesite = cookieConfig.samesite || defaultCookieConfig.samesite; 112 113 document.cookie = name + "=" + encodeURIComponent(value) + 114 (expires && days !== sessionCookieMarker ? '; expires=' + expires.toGMTString() : '') + 115 (path ? '; path=' + path : '') + 116 (domain ? '; domain=' + domain : '') + 117 (secure ? '; secure' : '') + 118 (samesite ? '; samesite=' + samesite : 'lax'); 119 }, 120 isWebsiteAllowedToSaveCookie() { 121 const allowedCookies = this.get('user_allowed_save_cookie'); 122 if (allowedCookies) { 123 const allowedWebsites = JSON.parse(unescape(allowedCookies)); 124 125 return allowedWebsites[CURRENT_WEBSITE_ID] === 1; 126 } 127 return false; 128 }, 129 getGroupByCookieName(name) { 130 const cookieConsentConfig = window.cookie_consent_config || {}; 131 let group = null; 132 for (let prop in cookieConsentConfig) { 133 if (!cookieConsentConfig.hasOwnProperty(prop)) continue; 134 if (cookieConsentConfig[prop].includes(name)) { 135 group = prop; 136 break; 137 } 138 } 139 return group; 140 }, 141 isCookieAllowed(name) { 142 const cookieGroup = this.getGroupByCookieName(name); 143 return cookieGroup 144 ? window.cookie_consent_groups[cookieGroup] 145 : this.isWebsiteAllowedToSaveCookie(); 146 }, 147 saveTempStorageCookies() { 148 for (const [name, data] of Object.entries(cookieTempStorage)) { 149 if (this.isCookieAllowed(name)) { 150 this.set(name, data['value'], data['days'], data['skipSetDomain']); 151 delete cookieTempStorage[name]; 152 } 153 } 154 } 155 }; 156 157 hyva.getCookie = (name) => { 158 const cookieConfig = window.COOKIE_CONFIG || {}; 159 160 if (cookieConfig.cookie_restriction_enabled && ! internalCookie.isCookieAllowed(name)) { 161 return cookieTempStorage[name] ? cookieTempStorage[name]['value'] : null; 162 } 163 164 return internalCookie.get(name); 165 } 166 167 hyva.setCookie = (name, value, days, skipSetDomain) => { 168 const cookieConfig = window.COOKIE_CONFIG || {}; 169 170 if (cookieConfig.cookie_restriction_enabled && ! internalCookie.isCookieAllowed(name)) { 171 cookieTempStorage[name] = {value, days, skipSetDomain}; 172 return; 173 } 174 return internalCookie.set(name, value, days, skipSetDomain); 175 } 176 177 178 hyva.setSessionCookie = (name, value, skipSetDomain) => { 179 return hyva.setCookie(name, value, sessionCookieMarker, skipSetDomain) 180 } 181 182 hyva.getBrowserStorage = () => { 183 const browserStorage = window.localStorage || window.sessionStorage; 184 if (!browserStorage) { 185 console.warn('Browser Storage is unavailable'); 186 return false;
187 } 188 try { 189 browserStorage.setItem('storage_test', '1'); 190 browserStorage.removeItem('storage_test'); 191 } catch (error) { 192 console.warn('Browser Storage is not accessible', error); 193 return false; 194 } 195 return browserStorage; 196 } 197 198 hyva.postForm = (postParams) => { 199 const form = document.createElement("form"); 200 201 let data = postParams.data; 202 203 if (! postParams.skipUenc && ! data.uenc) { 204 data.uenc = btoa(window.location.href); 205 } 206 form.method = "POST"; 207 form.action = postParams.action; 208 209 Object.keys(postParams.data).map(key => { 210 const field = document.createElement("input"); 211 field.type = 'hidden' 212 field.value = postParams.data[key]; 213 field.name = key; 214 form.appendChild(field); 215 }); 216 217 const form_key = document.createElement("input"); 218 form_key.type = 'hidden'; 219 form_key.value = hyva.getFormKey(); 220 form_key.name="form_key"; 221 form.appendChild(form_key); 222 223 document.body.appendChild(form); 224 225 form.submit(); 226 } 227 228 hyva.getFormKey = function () { 229 let formKey = hyva.getCookie('form_key'); 230 231 if (!formKey) { 232 formKey = generateRandomString(); 233 hyva.setCookie('form_key', formKey); 234 } 235 236 return formKey; 237 } 238 239 hyva.formatPrice = (value, showSign, options = {}) => { 240 const groupSeparator = options.groupSeparator; 241 const decimalSeparator = options.decimalSeparator 242 delete options.groupSeparator; 243 delete options.decimalSeparator; 244 const formatter = new Intl.NumberFormat( 245 'de\u002DDE', 246 Object.assign({ 247 style: 'currency', 248 currency: 'EUR', 249 signDisplay: showSign ? 'always' : 'auto' 250 }, options) 251 ); 252 return (typeof Intl.NumberFormat.prototype.formatToParts === 'function') ? 253 formatter.formatToParts(value).map(({type, value}) => { 254 switch (type) { 255 case 'currency': 256 return '\u20AC' || value; 257 case 'minusSign': 258 return '- '; 259 case 'plusSign': 260 return '+ '; 261 case 'group': 262 return groupSeparator !== undefined ? groupSeparator : value; 263 case 'decimal': 264 return decimalSeparator !== undefined ? decimalSeparator : value; 265 default : 266 return value; 267 } 268 }).reduce((string, part) => string + part) : 269 formatter.format(value); 270 } 271 272 const formatStr = function (str, nStart) { 273 const args = Array.from(arguments).slice(2); 274 275 return str.replace(/(%+)([0-9]+)/g, (m, p, n) => { 276 const idx = parseInt(n) - nStart; 277 278 if (args[idx] === null || args[idx] === void 0) { 279 return m; 280 } 281 return p.length % 2 282 ? p.slice(0, -1).replace('%%', '%') + args[idx] 283 : p.replace('%%', '%') + n; 284 }) 285 } 286 287 hyva.str = function (string) { 288 const args = Array.from(arguments); 289 args.splice(1, 0, 1); 290 291 return formatStr.apply(undefined, args); 292 } 293 294 hyva.strf = function () { 295 const args = Array.from(arguments); 296 args.splice(1, 0, 0); 297 298 return formatStr.apply(undefined, args); 299 } 300 301 /** 302 * Take a html string as `content` parameter and 303 * extract an element from the DOM to replace in 304 * the current page under the same selector, 305 * defined by `targetSelector` 306 */ 307 hyva.replaceDomElement = (targetSelector, content) => { 308 // Parse the content and extract the DOM node using the `targetSelector` 309 const parser = new DOMParser(); 310 const doc = parser.parseFromString(content, 'text/html');
311 const contentNode = doc.querySelector(targetSelector); 312 313 // Bail if content or target can't be found 314 if (!contentNode || !document.querySelector(targetSelector)) { 315 return; 316 } 317 318 hyva.activateScripts(contentNode); 319 320 // Replace the old DOM node with the new content 321 document.querySelector(targetSelector).replaceWith(contentNode); 322 323 // Reload customerSectionData and display cookie-messages if present 324 window.dispatchEvent(new CustomEvent("reload-customer-section-data")); 325 hyva.initMessages(); 326 } 327 328 hyva.removeScripts = (contentNode) => { 329 const scripts = contentNode.getElementsByTagName('script'); 330 for (let i = 0; i < scripts.length; i++) { 331 scripts[i].parentNode.removeChild(scripts[i]); 332 } 333 const templates = contentNode.getElementsByTagName('template'); 334 for (let i = 0; i < templates.length; i++) { 335 const container = document.createElement('div'); 336 container.innerHTML = templates[i].innerHTML; 337 hyva.removeScripts(container); 338 templates[i].innerHTML = container.innerHTML; 339 } 340 } 341 342 hyva.activateScripts = (contentNode) => { 343 // Create new array from HTMLCollection to avoid mutation of collection while manipulating the DOM. 344 const scripts = Array.from(contentNode.getElementsByTagName('script')); 345 346 // Iterate over all script tags to duplicate+inject each into the head 347 for (const original of scripts) { 348 const script = document.createElement('script'); 349 original.type && (script.type = original.type); 350 script.innerHTML = original.innerHTML; 351 352 // Remove the original (non-executing) script from the contentNode 353 original.parentNode.removeChild(original) 354 355 // Add script to head 356 document.head.appendChild(script); 357 } 358 359 return contentNode; 360 } 361 362 const replace = {['+']: '-', ['/']: '_', ['=']: ','}; 363 hyva.getUenc = () => btoa(window.location.href).replace(/[+/=]/g, match => replace[match]); 364 365 let currentTrap; 366 367 const focusableElements = (rootElement) => { 368 const selector = 'button, [href], input, select, textarea, details, [tabindex]:not([tabindex="-1"]'; 369 return Array.from(rootElement.querySelectorAll(selector)) 370 .filter(el => { 371 return el.style.display !== 'none' 372 && !el.disabled 373 && el.tabIndex !== -1 374 && (el.offsetWidth || el.offsetHeight || el.getClientRects().length) 375 }) 376 } 377 378 const focusTrap = (e) => { 379 const isTabPressed = e.key === 'Tab' || e.keyCode === 9; 380 if (!isTabPressed) return; 381 382 const focusable = focusableElements(currentTrap) 383 const firstFocusableElement = focusable[0] 384 const lastFocusableElement = focusable[focusable.length - 1] 385 386 e.shiftKey 387 ? document.activeElement === firstFocusableElement && (lastFocusableElement.focus(), e.preventDefault()) 388 : document.activeElement === lastFocusableElement && (firstFocusableElement.focus(), e.preventDefault()) 389 }; 390 391 hyva.releaseFocus = (rootElement) => { 392 if (currentTrap && (!rootElement || rootElement === currentTrap)) { 393 currentTrap.removeEventListener('keydown', focusTrap) 394 currentTrap = null 395 } 396 } 397 hyva.trapFocus = (rootElement) => { 398 if (!rootElement) return; 399 hyva.releaseFocus() 400 currentTrap = rootElement 401 rootElement.addEventListener('keydown', focusTrap) 402 const firstElement = focusableElements(rootElement)[0] 403 firstElement && firstElement.focus() 404 } 405 406 hyva.safeParseNumber = (rawValue) => { 407 const number = rawValue ? parseFloat(rawValue) : null; 408 409 return Array.isArray(number) || isNaN(number) ? rawValue : number; 410 } 411 412 const toCamelCase = s => s.split('_').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(''); 413 hyva.createBooleanObject = (name, value = false, additionalMethods = {}) => { 414 415 const camelCase = toCamelCase(name);
416 const key = '__hyva_bool_' + name 417 418 return new Proxy(Object.assign( 419 additionalMethods, 420 { 421 [key]: !!value, 422 [name]() {return !!this[key]}, 423 ['!' + name]() {return !this[key]}, // @deprecated This does not work with non-CSP Alpine 424 ['not' + camelCase]() {return !this[key]}, 425 ['toggle' + camelCase]() {this[key] = !this[key]}, 426 [`set${camelCase}True`]() {this[key] = true}, 427 [`set${camelCase}False`]() {this[key] = false}, 428 } 429 ), { 430 set(target, prop, value) { 431 return prop === name 432 ? (target[key] = !!value) 433 : Reflect.set(...arguments); 434 } 435 }) 436 } 437 438 hyva.alpineInitialized = (fn) => window.addEventListener('alpine:initialized', fn, {once: true}) 439 window.addEventListener('alpine:init', () => Alpine.data('{}', () => ({})), {once: true}); 440 window.addEventListener('user-allowed-save-cookie', () => internalCookie.saveTempStorageCookies()) 441 442 }( window.hyva = window.hyva || {} )); 443</script>
vendor: 1 bytes, line 443
443
444<script type="speculationrules"> 445{ 446 "tag": "Hyva Theme", 447 "prefetch": [{ 448 "source": "document", 449 "where": { 450 "and": [ 451 { "href_matches": "/*" }, 452 { "not": { 453 "href_matches": ["/customer/*","*/customer/*","/search/*","*/search/*","/sales/*","*/sales/*","/wishlist/*","*/wishlist/*","/checkout/*","*/checkout/*","/paypal/*","*/paypal/*"] }}, 454 { "not": { 455 "selector_matches": [".no-preload", ".do-not-prerender", "[download]", "[rel~=nofollow]", "[target]"] 456 }} 457 ] 458 }, 459 "eagerness": "moderate" 460 }] 461} 462</script>
462 463
464<script> 465 const setTransitionNameBetweenGallery = async (url, promise) => { 466 if (window.matchMedia('(prefers-reduced-motion)').matches) return; 467 468 const productGallery = document.getElementById('gallery-main'); 469 const productListItem = document.querySelector(`.product-item-photo[href="${url}"]`); 470 const targetElement = productListItem || productGallery; 471 472 if (targetElement) { 473 targetElement.style.viewTransitionName = 'view-transition-to-gallery'; 474 475 await promise; 476 targetElement.style.viewTransitionName = ''; 477 } 478 }; 479 480 window.addEventListener('pageswap', async (e) => { 481 if (!e.viewTransition) return; 482 const target = new URL(e.activation.entry.url); 483 setTransitionNameBetweenGallery(target.href, e.viewTransition.finished); 484 }); 485 486 window.addEventListener('pagereveal', async (e) => { 487 if (!e.viewTransition || (window.navigation && !window.navigation.activation.from)) return; 488 const target = new URL(window.navigation.activation.from.url); 489 setTransitionNameBetweenGallery(target.href, e.viewTransition.ready); 490 }); 491</script>
491 492</head> 493<body id="html-body" class="cms-home cms-index-index page-layout-1column"> 494<input name="form_key" type="hidden" value="kkcpuVAPRlPQQfhv" /> 495 <noscript> 496 <section 497 class="message global noscript border-b-2 border-blue-500 bg-blue-50 shadow-none m-0 px-0 rounded-none font-normal" 498 aria-labelledby="messageGlobalNoScriptMessage" 499 > 500 <div class="container text-center"> 501 <p id="messageGlobalNoScriptMessage"> 502 <strong>JavaScript scheint in Ihrem Browser deaktiviert zu sein.</strong> 503 <span> 504 Um unsere Website in bester Weise zu erfahren, aktivieren Sie Javascript in Ihrem Browser. </span> 505 </p> 506 </div> 507 </section> 508 </noscript> 509 510
511<script> 512 document.body.addEventListener('touchstart', () => {}, {passive: true}) 513</script>
513 514<div class="page-wrapper"><header class="page-header"><a class="action skip sr-only focus:not-sr-only focus:absolute focus:z-40 focus:bg-white 515 contentarea" 516 href="#contentarea"> 517 <span> 518 Zum Inhalt springen </span> 519</a>
520<script> 521 function initHeader() { 522 return { 523 searchOpen: false, 524 cart: {}, 525 isCartOpen: false, 526 getData(data) { 527 this.cart = data.cart ?? {}; 528 }, 529 summaryCount() { 530 return this.cart.summary_count || 0; 531 }, 532 cartAriaLabel() { 533 return 'Mini\u002DWarenkorb\u0020umschalten, ' + 534 (this.isCartEmpty() ? 'Warenkorb\u0020ist\u0020leer' : ( 535 Math.abs(this.summaryCount()) > 1 ? 536 hyva.str('\u00251\u0020Artikel', this.summaryCount()) : 537 hyva.str('\u00251\u0020Element', this.summaryCount()) 538 )) 539 }, 540 isCartEmpty() { 541 return !this.cart.summary_count; 542 }, 543 toggleCart() { 544 this.isCartOpen = this.$event.detail?.isOpen ?? true; 545 this.$dispatch('toggle-cart', { isOpen: this.isCartOpen }) 546 }, 547 toggleSearch() { 548 this.searchOpen = !this.searchOpen; 549 this.$dispatch('search-open'); 550 }, 551 searchClose() { 552 this.searchOpen = false; 553 this.$refs.searchButton.focus(); 554 }, 555 searchEscape() { 556 this.searchClose(); 557 } 558 } 559 } 560 561 window.addEventListener('alpine:init', () => { 562 Alpine.data('initHeader', initHeader); 563 }, { once: true }) 564</script>
564 565 566<div id="header" 567 class="relative z-30 w-full border-b shadow bg-white border-gray-100" 568 x-data="initHeader()" 569 @private-content-loaded.window="getData(event.detail.data)" 570> 571 <div class="container flex flex-wrap lg:flex-nowrap items-center justify-between w-full px-6 py-3 mx-auto mt-0"> 572 <!--Logo--> 573 <div class="sm:order-1 lg:order-0 w-full pb-2 sm:w-auto sm:pb-0"> 574 <a 575 class="flex items-center justify-center text-xl font-medium" 576 href="https://shop.hk-verlag.de/de/" 577 aria-label="Zur Startseite gehen" 578> 579 <img 580 src="https://shop.hk-verlag.de/media/logo/default/HK_Shop_Logo_140px.png" 581 alt="Geschäfts-Logo" 582 width="109" height="70" loading="eager" 583 > 584 </a> 585 </div> 586 587 <!--Main Navigation--> 588 <div x-data="initMobileMenu" x-bind="eventListeners" class="lg:hidden"> 589 <button 590 type="button" 591 class="btn bg-transparent border-transparent p-2" 592 aria-label="Menü öffnen" 593 @click="open" 594 > 595 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><path d="M4 12h16M4 18h16M4 6h16"/></svg> 596 </button> 597 <dialog 598 class="size-full max-h-full ms-0 p-0 open:flex flex-col transition ease-out duration-300 motion-reduce:duration-0 rounded-s-none" 599 x-show="isOpen" 600 x-htmldialog="close" 601 closeby="any" 602 x-transition:enter-start="-translate-x-full" 603 x-transition:enter-end="translate-x-0" 604 x-transition:leave-start="translate-x-0" 605 x-transition:leave-end="-translate-x-full" 606 > 607 <div class="border-b border-slate-200"> 608 <div class="flex justify-between items-center gap-2 py-4 px-6"> 609 <div></div> 610 <button 611 type="button" 612 @click="close" 613 class="btn bg-transparent border-transparent p-1" 614 aria-label="Menü schließen" 615 > 616 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><path d="M18 6 6 18M6 6l12 12"/></svg> 617 </button> 618 </div> 619 </div> 620 <div class="grow relative overflow-y-auto overflow-x-clip py-0.5" :style="lockWrapperScroll"> 621 <nav aria-label="Mobile Main Menu"> 622 <ul> 623 <li data-level="0"> 624 <a 625 href="https://shop.hk-verlag.de/de/geflugelzeitung" 626 class="flex items-center gap-2 py-3 px-6 border-b border-slate-200 outline-offset-0" 627 > 628 Geflügelzeitung </a> 629 </li> 630 <li data-level="0"> 631 <a 632 href="https://shop.hk-verlag.de/de/kaninchenzeitung" 633 class="flex items-center gap-2 py-3 px-6 border-b border-slate-200 outline-offset-0" 634 > 635 Kaninchenzeitung </a> 636 </li> 637 </ul> 638 </nav> 639 </div> 640 </dialog> 641</div>
642<script> 643 const initMobileMenu = () => { 644 return { 645 isOpen: false, 646 isSubMenuOpen: false, 647 isOverflowing: false, 648 init() { 649 Array.from(this.$root.querySelectorAll('a')).forEach(link => { 650 if (link.href === `${window.location.origin}${window.location.pathname}`) { 651 link.setAttribute('aria-current', 'page'); 652 } 653 }); 654 }, 655 open() { 656 this.isOpen = true; 657 }, 658 close() { 659 this.isOpen = false; 660 }, 661 lockWrapperScroll() { 662 return this.isSubMenuOpen ? { overflow: 'hidden' } : {} 663 }, 664 hasActiveSubMenu() { 665 this.isSubMenuOpen = !!this.$root.querySelector('[data-open]'); 666 }, 667 eventListeners: { 668 ['@pageshow.window'](event) { 669 if (event.persisted) { 670 this.close(); 671 }; 672 } 673 } 674 } 675 }; 676 677 const initMobileSubMenu = () => { 678 return { 679 isOpen: false, 680 open() { 681 this.isOpen = true; 682 this.$root.setAttribute('data-open', ''); 683 this.$nextTick(() => { 684 this.$dispatch('sub-menu-state-change'); 685 this.$refs.closeSubMenuBtn.focus(); 686 this.toggleInert(); 687 }) 688 }, 689 close() { 690 this.isOpen = false; 691 this.$root.removeAttribute('data-open'); 692 this.toggleInert(); 693 this.$nextTick(() => { 694 this.$dispatch('sub-menu-state-change') 695 this.$refs.openSubMenuBtn.focus(); 696 }) 697 }, 698 toggleInert() { 699 const items = this.$root.parentElement.children; 700 701 for (item of items) { 702 if (item.hasAttribute('data-open')) continue; 703 item.toggleAttribute('inert', this.isOpen); 704 } 705 } 706 } 707 } 708 709 document.addEventListener('alpine:init', () => { 710 Alpine.data('initMobileMenu', initMobileMenu); 711 Alpine.data('initMobileSubMenu', initMobileSubMenu); 712 }, { once: true }); 713</script>
713 714<div x-data="initMenuDesktop" class="z-20 navigation hidden lg:flex"> 715 <div class="hidden lg:block lg:px-8"> 716 <nav 717 class="relative" 718 aria-label="Hauptmenü" 719 > 720 <ul class="flex justify-start flex-wrap gap-x-7 py-4"> 721 <li 722 class="relative level-0 border-b-2 border-transparent hover:border-primary data-[active]:border-primary" 723 x-data="initMenuDesktopItem" 724 x-bind="eventListeners" 725 @click.outside="close" 726 @keydown.escape="close" 727 @mouseenter="canHoverOpen" 728 @mouseleave="canHoverClose" 729 > 730 <span class="flex items-center text-md"> 731 <a 732 href="https://shop.hk-verlag.de/de/geflugelzeitung" 733 class="level-0 block py-2 px-1 rounded aria-[current=page]:font-medium" 734 > 735 Geflügelzeitung </a> 736 </span> 737 </li> 738 <li 739 class="relative level-0 border-b-2 border-transparent hover:border-primary data-[active]:border-primary" 740 x-data="initMenuDesktopItem" 741 x-bind="eventListeners" 742 @click.outside="close" 743 @keydown.escape="close" 744 @mouseenter="canHoverOpen" 745 @mouseleave="canHoverClose" 746 > 747 <span class="flex items-center text-md"> 748 <a 749 href="https://shop.hk-verlag.de/de/kaninchenzeitung" 750 class="level-0 block py-2 px-1 rounded aria-[current=page]:font-medium" 751 > 752 Kaninchenzeitung </a> 753 </span> 754 </li> 755 </ul> 756 </nav> 757 </div> 758</div> 759
760<script> 761 function initMenuDesktop() { 762 return { 763 init() { 764 this.setActiveMenu(); 765 }, 766 setActiveMenu() { 767 Array.from(this.$root.querySelectorAll('a')).forEach(link => { 768 if (link.href === `${window.location.origin}${window.location.pathname}`) { 769 link.setAttribute('aria-current', 'page'); 770 } 771 }); 772 } 773 } 774 } 775 776 function initMenuDesktopItem() { 777 return { 778 open: false, 779 canHover(func) { 780 return window.matchMedia('(hover: hover) and (pointer: fine)').matches; 781 }, 782 canHoverOpen() { 783 if (!this.canHover()) return; 784 this.open = true; 785 }, 786 canHoverClose() { 787 if (!this.canHover()) return; 788 this.open = false; 789 }, 790 toggle() { 791 this.open = !this.open; 792 }, 793 close() { 794 this.open = false; 795 }, 796 eventListeners: { 797 ['@pageshow.window'](event) { 798 if (event.persisted) { 799 this.open = false; 800 }; 801 } 802 } 803 } 804 } 805 806 window.addEventListener('alpine:init', () => { 807 Alpine.data('initMenuDesktop', initMenuDesktop); 808 Alpine.data('initMenuDesktopItem', initMenuDesktopItem); 809 }, { once: true }) 810</script>
810 811 812 <div class="flex items-center gap-2 md:gap-1 order-1 lg:order-0 md:-mr-1"> 813 814<a 815 id="compare-link" 816 class="relative hidden md:inline-flex btn bg-transparent border-transparent p-1 invisible" 817 :class="hiddenIfEmpty" 818 href="https://shop.hk-verlag.de/de/catalog/product_compare/index/" 819 title="Produkte vergleichen" 820 x-data="initCompareHeader" 821 @private-content-loaded.window="receiveCompareData" 822 :aria-label="linkAriaLabel" 823> 824 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><path d="m16 16 3-8 3 8c-.87.65-1.92 1-3 1s-2.13-.35-3-1M2 16l3-8 3 8c-.87.65-1.92 1-3 1s-2.13-.35-3-1M7 21h10M12 3v18M3 7h2c2 0 5-1 7-2 2 1 5 2 7 2h2"/></svg> 825 <span 826 x-text="itemCount" 827 class="absolute -top-1.5 -right-1.5 px-2 py-1 rounded-full bg-primary text-on-primary 828 text-xs font-semibold leading-none text-center uppercase tabular-nums" 829 aria-hidden="true" 830 ></span> 831</a> 832
833<script> 834 function initCompareHeader() { 835 return { 836 compareProducts: null, 837 itemCount: 0, 838 hiddenIfEmpty() { 839 return { 840 'invisible': this.itemCount < 1 841 } 842 }, 843 linkAriaLabel() { 844 const countLabel = this.itemCount > 1 845 ? hyva.str('\u00251\u0020Elemente', this.itemCount) 846 : hyva.str('\u00251\u0020Artikel', this.itemCount); 847 return `Produkte\u0020vergleichen (${countLabel})`; 848 }, 849 receiveCompareData() { 850 const data = this.$event.detail.data; 851 if (data['compare-products'] && data['compare-products'].count) { 852 this.compareProducts = data['compare-products']; 853 this.itemCount = this.compareProducts.count; 854 } 855 }, 856 itemCountLabel() { 857 return `(${this.itemCount})`; 858 } 859 } 860 } 861 862 window.addEventListener('alpine:init', () => { 863 Alpine.data('initCompareHeader', initCompareHeader); 864 }, { once: true }) 865</script>
865 866 867 <button 868 id="menu-search-icon" 869 class="btn bg-transparent border-transparent p-1" 870 @click.prevent="toggleSearch" 871 aria-label="Suchformular umschalten" 872 aria-haspopup="true" 873 :aria-expanded="searchOpen" 874 x-ref="searchButton" 875 > 876 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><path d="m21 21-4.34-4.34"/><circle cx="11" cy="11" r="8"/></svg> 877 </button> 878 879 880 <!-- BLOCK header.customer --> 881<div 882 class="relative inline-block" 883 x-data="{ open: false }" 884 @keyup.escape="open = false" 885 @click.outside="open = false" 886> 887 <button 888 type="button" 889 id="customer-menu" 890 class="btn bg-transparent border-transparent p-1" 891 @click="open = !open" 892 :aria-expanded="open ? 'true' : 'false'" 893 aria-label="Mein Konto" 894 aria-haspopup="true" 895 > 896 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg> 897 </button> 898 <nav 899 class="z-10 absolute right-0 w-40 sm:w-48 mt-2 lg:mt-3 -me-4 py-2 px-1 rounded-md shadow-lg bg-white overflow-auto" 900 aria-labelledby="customer-menu" 901 x-show="open" 902 x-transition 903 x-cloak 904 > 905 906<a id="customer.header.sign.in.link" 907 class="block px-4 py-2 lg:px-5 lg:py-2 hover:bg-gray-100" 908 onclick="hyva.setCookie && hyva.setCookie( 909 'login_redirect', 910 window.location.href, 911 1 912 )" 913 href="https://shop.hk-verlag.de/de/customer/account/index/" 914 title="Anmelden" 915> 916 Anmelden</a> 917 918 <a id="customer.header.register.link" 919 class="block px-4 py-2 lg:px-5 lg:py-2 hover:bg-gray-100" 920 href="https://shop.hk-verlag.de/de/customer/account/create/" 921 title="Ein Konto erstellen" 922 > 923 Ein Konto erstellen </a> 924 </nav> 925</div> 926<!-- /BLOCK header.customer --> 927 928 <button 929 id="menu-cart-icon" 930 type="button" 931 class="relative btn bg-transparent border-transparent p-1" 932 x-ref="cartButton" 933 :aria-label="cartAriaLabel" 934 @click="toggleCart" 935 :aria-expanded="isCartOpen" 936 aria-haspopup="dialog" 937 > 938 <svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" class="md:h-6 md:w-6" aria-hidden="true"><circle cx="8" cy="21" r="1"/><circle cx="19" cy="21" r="1"/><path d="M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12"/></svg> 939 <span 940 x-text="summaryCount" 941 x-show="summaryCount" 942 x-cloak 943 class="absolute -top-1.5 -right-1.5 px-2 py-1 rounded-full bg-primary text-on-primary text-xs 944 font-semibold leading-none text-center uppercase tabular-nums" 945 aria-hidden="true" 946 ></span> 947 </button> 948 949 <!-- Website Switcher --> 950 <div x-data="{ open: false }" class="relative"> 951 <button @click.prevent="open = !open" 952 @click.outside="open = false" 953 @keydown.window.escape="open = false" 954 type="button" 955 class="btn bg-transparent border-transparent p-1 inline-flex items-center gap-1" 956 aria-haspopup="true" 957 :aria-expanded="open" 958 aria-label="Switch Website" 959 > 960 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewB
960ox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20M2 12h20"/></svg> 961 <span class="hidden sm:inline text-sm">Deutschland</span> 962 <svg xmlns="http://www.w3.org/2000/svg" 963 width="16" height="16" viewBox="0 0 24 24" 964 fill="none" stroke="currentColor" stroke-width="2" 965 stroke-linecap="round" stroke-linejoin="round" 966 class="w-4 h-4 transition-transform duration-200" 967 :class="open ? 'rotate-180' : ''" 968 aria-hidden="true"> 969 <path d="m6 9 6 6 6-6"/> 970 </svg> 971 </button> 972 <nav x-cloak 973 x-show="open" 974 x-transition 975 class="absolute right-0 top-full z-50 mt-0.5 min-w-max py-2 px-1 rounded-md shadow-lg bg-white/95"> 976 <a href="https://shop.hk-verlag.de/de/stores/store/redirect/___store/int/___from_store/de/uenc/aHR0cHM6Ly9zaG9wLmhrLXZlcmxhZy5kZS9pbnQv/" 977 class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100" 978 > 979 International </a> 980 </nav> 981 </div> 982 </div> 983 </div> 984 985 <div 986 id="search-content" 987 class="absolute z-10 w-full border-t shadow-sm bg-white border-gray-100" 988 x-cloak 989 x-show="searchOpen" 990 @click.outside="searchClose" 991 @keydown.escape="searchEscape" 992 > 993
993<script> 994 'use strict'; 995 996 function initMiniSearch() { 997 return { 998 minSearchLength: 3, 999 suggestions: [], 1000 suggest() { 1001 const search = this.$refs.searchInput; 1002 if (search.value.length >= this.minSearchLength) { 1003 search.setCustomValidity(''); 1004 search.reportValidity(); 1005 this.fetchSuggestions(search.value); 1006 } else { 1007 this.suggestions = []; 1008 } 1009 }, 1010 fetchSuggestions(term) { 1011 fetch( 1012 window.BASE_URL + 'search/ajax/suggest?' + new URLSearchParams({q: term}), 1013 { 1014 headers: { 1015 'X-Requested-With': 'XMLHttpRequest' 1016 } 1017 } 1018 ) 1019 .then(response => response.json()) 1020 .then(result => this.suggestions = result); 1021 }, 1022 search(term) { 1023 const search = this.$refs.searchInput; 1024 term = term || search.value; 1025 if (term.length < this.minSearchLength) { 1026 search.setCustomValidity('Die\u0020minimale\u0020L\u00E4nge\u0020der\u0020Suchbegriffe\u0020ist\u00203\u0020Zeichen'); 1027 search.reportValidity(); 1028 } else { 1029 search.setCustomValidity(''); 1030 search.value = term; 1031 this.$refs.form.submit(); 1032 } 1033 }, 1034 focusElement(element) { 1035 if (element && element.nodeName === "DIV") { 1036 element.focus(); 1037 return true; 1038 } else { 1039 return false; 1040 } 1041 } 1042 } 1043 } 1044</script>
1044 1045<div class="container py-2 mx-auto text-black" x-data="initMiniSearch()"> 1046 <search title="Shop" role="search"> 1047 <form 1048 id="search_mini_form" 1049 class="form minisearch flex" 1050 action="https://shop.hk-verlag.de/de/catalogsearch/result/" 1051 method="get" 1052 @submit.prevent="search()" 1053 x-ref="form" 1054 > 1055 <label class="sr-only" for="search"> 1056 Suche </label> 1057 <input 1058 id="search" 1059 x-ref="searchInput" 1060 type="search" 1061 autocomplete="off" 1062 name="q" 1063 value="" 1064 placeholder="Gesamten Shop hier durchsuchen..." 1065 maxlength="128" 1066 class="form-input w-full rounded-e-none" 1067 @search-open.window.debounce.10="$el.focus(); $el.select()" 1068 @focus.once="suggest" 1069 @input.debounce.300="suggest" 1070 @keydown.arrow-down.prevent="focusElement($root.querySelector('[tabindex]'))" 1071 > 1072 <button 1073 type="submit" 1074 class="btn btn-primary p-2.5 rounded-s-none shrink-0 outline-offset-0" 1075 title="Suche" 1076 aria-label="Suche" 1077 > 1078 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><path d="m21 21-4.34-4.34"/><circle cx="11" cy="11" r="8"/></svg> 1079 </button> 1080 </form> 1081 </search> 1082 <template x-if="suggestions.length > 0"> 1083 <nav 1084 aria-label="Search Suggestions" 1085 class="flex flex-col mt-1 text-grey-800 gap-1" 1086 > 1087 <template x-for="suggestion in suggestions"> 1088 <button 1089 type="button" 1090 class="flex justify-between p-2 bg-white even:bg-gray-50 border border-gray-300 hover:bg-gray-100" 1091 @click="search(suggestion.title)" 1092 @keydown.enter="search(suggestion.title)" 1093 @keydown.arrow-up.prevent="focusElement($event.target.previousElementSibling) || $refs.searchInput.focus()" 1094 @keydown.arrow-down.prevent="focusElement($event.target.nextElementSibling)" 1095 > 1096 <span x-text="suggestion.title"></span> 1097 <span x-text="suggestion.num_results"></span> 1098 </button> 1099 </template> 1100 </nav> 1101 </template> 1102 </div> 1103 </div> 1104
1105 <!--Cart Drawer--> 1106
1107<script> 1108 function initCartDrawer() { 1109 return { 1110 open: false, 1111 isLoading: false, 1112 cart: {}, 1113 maxItemsToDisplay: 10, 1114 itemsCount: 0, 1115 showSku: false, 1116 autocompleteNumber: 100, 1117 init() { 1118 if (document.prerendering) { 1119 document.addEventListener("prerenderingchange", () => { 1120 this.reloadData() 1121 }, { once: true }); 1122 } 1123 }, 1124 showDetails() { 1125 return this.item.options && this.item.options.length || this.showSku; 1126 }, 1127 cartIsEmpty() { 1128 return this.itemsCount === 0 1129 }, 1130 getData() { 1131 const data = this.$event.detail.data; 1132 1133 if (data.cart) { 1134 this.cart = data.cart; 1135 this.itemsCount = data.cart.items && data.cart.items.length || 0; 1136 this.setCartItems(); 1137 } 1138 this.isLoading = false; 1139 }, 1140 cartItems: [], 1141 getItemCountTitle() { 1142 return hyva.strf('\u00250\u0020von\u0020\u00251\u0020Produkten\u0020im\u0020Warenkorb\u0020angezeigt', this.maxItemsToDisplay, this.itemsCount) 1143 }, 1144 shouldShowItemCount() { 1145 return this.maxItemsToDisplay && this.maxItemsToDisplay < this.itemsCount; 1146 }, 1147 setCartItems() { 1148 this.cartItems = this.cart.items && this.cart.items.sort((a, b) => b.item_id - a.item_id) || []; 1149 1150 if (this.maxItemsToDisplay > 0) { 1151 this.cartItems = this.cartItems.slice(0, parseInt(this.maxItemsToDisplay, 10)); 1152 } 1153 }, 1154 updateItemQty(event) { 1155 const form = event.target; 1156 this.isLoading = true; 1157 hyvaAjaxFormMinicart({ form, redirect: false }, () => { 1158 this.isLoading = false; 1159 }); 1160 }, 1161 deleteItemFromCart() { 1162 const itemId = this.item.item_id; 1163 const formKey = hyva.getFormKey(); 1164 this.isLoading = true; 1165 1166 hyvaAjaxFormMinicart({ 1167 url: BASE_URL + 'checkout/sidebar/removeItem/', 1168 body: 'form_key=' + formKey + '&item_id=' + itemId, 1169 message: 'Sie\u0020haben\u0020den\u0020Artikel\u0020entfernt.' 1170 }, () => { 1171 this.isLoading = false 1172 }); 1173 }, 1174 toggleCartDrawer(event) { 1175 if (event.detail && event.detail.isOpen) { 1176 this.open = event.detail.isOpen; 1177 } else { 1178 this.open = !this.open; 1179 } 1180 }, 1181 openCartDrawer() { 1182 this.open = true; 1183 }, 1184 closeCartDrawer() { 1185 this.open = false; 1186 }, 1187 getSectionDataExtraActions() { 1188 if (!this.cart.extra_actions) { 1189 return ''; 1190 } 1191 1192 const contentNode = document.createElement('div'); 1193 contentNode.innerHTML = this.cart.extra_actions; 1194 1195 hyva.activateScripts(contentNode); 1196 1197 return contentNode.innerHTML; 1198 }, 1199 productIsVisibleInSite() { 1200 return this.item.product_has_url && this.item.is_visible_in_site_visibility 1201 }, 1202 productIsNotVisibleInSite() { 1203 return !this.productIsVisibleInSite() 1204 }, 1205 productIsNotGroupedAndVisibleInSite() { 1206 return this.item.product_type !== 'grouped' && this.item.is_visible_in_site_visibility 1207 }, 1208 productAriaLabel() { 1209 return hyva.strf(this.$el.dataset.ariaLabel, this.item.product_name) 1210 }, 1211 proceedToCheckout() { 1212 this.closeCartDrawer() 1213 1214 this.$dispatch( 1215 'toggle-authentication', 1216 { 1217 url: 'https://shop.hk-verlag.de/de/checkout/' 1218 } 1219 ) 1220 }, 1221 setItemMessage(itemId, message) { 1222 const items = this.cartItems;
1223 items.forEach((item) => { 1224 if (item.item_id === itemId) { 1225 item.message = message; 1226 } 1227 }); 1228 }, 1229 cartListeners: { 1230 ['@private-content-loaded.window'](event) { 1231 this.getData(event.detail.data); 1232 }, 1233 ['@toggle-cart.window'](event) { 1234 this.toggleCartDrawer(event); 1235 }, 1236 ['@minicart-error-message.window'](event) { 1237 if (!event.detail) return; 1238 const { itemId, message } = event.detail; 1239 this.setItemMessage(itemId, message); 1240 } 1241 } 1242 } 1243 } 1244 1245 window.addEventListener('alpine:init', () => { 1246 Alpine.data('initCartDrawer', initCartDrawer); 1247 }, { once: true }) 1248 1249 async function hyvaAjaxFormMinicart( 1250 { 1251 form = null, 1252 url = '', 1253 body = '', 1254 redirect = 'default', 1255 message = '', 1256 } = {}, 1257 callback = () => {} 1258 ) { 1259 const formData = body ? body : (form ? new FormData(form) : ''); 1260 const postUrl = url ? url : (form ? form.action : ''); 1261 if (!formData || !postUrl) { 1262 console.warn('You must provide the form or formData and postUrl!'); 1263 return; 1264 } 1265 1266 const formUenc = hyva.getUenc(); 1267 const itemId = body ? new URLSearchParams(body).get('item_id') : formData.get('item_id'); 1268 let bodyUrl = new URLSearchParams(formData); 1269 bodyUrl.append('uenc', formUenc); 1270 1271 try { 1272 const response = await fetch(postUrl, { 1273 method: 'POST', 1274 body: bodyUrl.toString(), 1275 mode: 'cors', 1276 credentials: 'include', 1277 headers: { 1278 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', 1279 'X-Requested-With': 'XMLHttpRequest' 1280 } 1281 }); 1282 1283 if (!response.ok) { 1284 return form.submit(); 1285 } 1286 1287 if (redirect === 'default' && response.redirected) { 1288 return window.location.href = response.url; 1289 } else if (redirect !== 'default' && redirect !== false) { 1290 return window.location.href = redirect; 1291 } 1292 1293 const responseBody = await response.json(); 1294 1295 if (!responseBody.success) { 1296 throw responseBody.error_message; 1297 } 1298 1299 window.dispatchEvent(new CustomEvent('reload-customer-section-data')); 1300 } catch (error) { 1301 window.dispatchEvent(new CustomEvent('minicart-error-message', { detail: { itemId, message: error } })); 1302 } finally { 1303 callback(); 1304 } 1305 } 1306</script>
1306 1307 1308<dialog 1309 id="cart-drawer" 1310 aria-labelledby="cart-drawer-title" 1311 class="w-[480px] md:w-[640px] h-full max-h-full me-0 open:flex flex-col transition ease-out duration-300 motion-reduce:duration-0 rounded-e-none" 1312 x-data="initCartDrawer" 1313 x-bind="cartListeners" 1314 x-show="open" 1315 x-htmldialog="closeCartDrawer" 1316 closeby="any" 1317 x-transition:enter="transition ease-in-out duration-500" 1318 x-transition:enter-start="translate-x-full" 1319 x-transition:enter-end="translate-x-0" 1320 x-transition:leave="transition ease-in-out duration-300" 1321 x-transition:leave-start="translate-x-0" 1322 x-transition:leave-end="translate-x-full" 1323> 1324 1325 <div class="flex gap-2 justify-between items-center"> 1326 <p id="cart-drawer-title" class="text-2xl"> 1327 <strong>Mein Warenkorb</strong> 1328 <span 1329 class="items-total text-xs" 1330 x-show="shouldShowItemCount" 1331 x-text="getItemCountTitle" 1332 ></span> 1333 </p> 1334 <button 1335 type="button" 1336 class="btn bg-transparent border-transparent p-2" 1337 @click="closeCartDrawer" 1338 aria-label="Mini-Warenkorb schließen" 1339 > 1340 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><path d="M18 6 6 18M6 6l12 12"/></svg> 1341 </button> 1342 </div> 1343 1344 1345 <template x-if="cartIsEmpty"> 1346 <div class="grow grid place-items-center"> 1347 <div class="text-center"> 1348 <svg xmlns="http://www.w3.org/2000/svg" width="120" height="120" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" class="inline-block text-fg/30 max-w-full h-auto" aria-hidden="true"><path d="m15 11-1 9M19 11l-4-7M2 11h20M3.5 11l1.6 7.4a2 2 0 0 0 2 1.6h9.8a2 2 0 0 0 2-1.6l1.7-7.4M4.5 15.5h15M5 11l4-7M9 11l1 9"/></svg> 1349 <p class="mt-10 text-xl"> 1350 <strong>Warenkorb ist leer</strong> 1351 </p> 1352 </div> 1353 </div> 1354 </template> 1355 1356 <template x-if="itemsCount"> 1357 <ul class="grow flex flex-col overflow-y-auto overscroll-y-contain mask-overflow mask-dir-y"> 1358 <template x-for="item in cartItems"> 1359 <li class="flex gap-4 md:gap-6 items-start py-4 px-1 border-b border-slate-200"> 1360 <template x-if="productIsVisibleInSite"> 1361 <a 1362 class="block shrink-0 max-w-[25%]" 1363 :href="item.product_url" 1364 data-aria-label="Produkt "%0"" 1365 :title="item.product_name" 1366 > 1367 <img 1368 :src="item.product_image.src" 1369 :width="item.product_image.width" 1370 :height="item.product_image.height" 1371 loading="lazy" 1372 :alt="item.product_name" 1373 > 1374 </a> 1375 </template> 1376 <template x-if="productIsNotVisibleInSite"> 1377 <div class="block shrink-0 max-w-[25%]"> 1378 <img 1379 :src="item.product_image.src" 1380 :width="item.product_image.width" 1381 :height="item.product_image.height" 1382 loading="lazy" 1383 :alt="item.product_name" 1384 /> 1385 </div> 1386 </template> 1387 <div class="grow space-y-4"> 1388 <div class="flex gap-2 justify-between items-center"> 1389 <p class="text-lg"> 1390 <span x-html="item.qty"></span> x <span x-html="item.product_name"></span> 1391 <strong x-html="item.product_name"></strong> 1392 </p>
1393 <span x-html="item.product_price"></span> 1394 </div> 1395 <template x-if="showDetails"> 1396 <dl class="table text-sm"> 1397 <template x-if="showSku"> 1398 <div class="table-row"> 1399 <dt class="table-cell font-normal min-w-16 pe-2 pb-2"> 1400 Artikelnr. </dt> 1401 <dd class="table-cell font-bold pb-2" x-html="item.product_sku"></dd> 1402 </div> 1403 </template> 1404 <template x-for="option in item.options"> 1405 <div class="table-row"> 1406 <dt 1407 class="table-cell font-normal min-w-16 pe-2 pb-2" 1408 x-text="option.label" 1409 ></dt> 1410 <dd class="table-cell font-bold pb-2" x-html="option.value"></dd> 1411 </div> 1412 </template> 1413 </dl> 1414 </template> 1415 <div class="flex flex-wrap gap-2 justify-end items-center"> 1416 <div class="inline-flex flex-wrap items-center gap-1"> 1417 <a 1418 :href="item.configure_url" 1419 x-show="productIsNotGroupedAndVisibleInSite" 1420 class="btn p-2" 1421 data-aria-label="Produkt bearbeiten "%0"" 1422 :aria-label="productAriaLabel" 1423 > 1424 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497zM15 5l4 4"/></svg> 1425 </a> 1426 <button 1427 type="button" 1428 class="btn p-2" 1429 @click="deleteItemFromCart" 1430 data-aria-label="Produkt "%0" aus dem Warenkorb entfernen" 1431 :aria-label="productAriaLabel" 1432 > 1433 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><path d="M3 6h18M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"/></svg> 1434 </button> 1435 </div> 1436 <template x-if="item.message"> 1437 <div class="message error" x-text="item.message"></div> 1438 </template> 1439 </div> 1440 </div> 1441 </li> 1442 </template> 1443 </ul> 1444 </template> 1445 1446 1447 <template x-if="itemsCount"> 1448 <div> 1449 1450 <dl class="flex gap-2 justify-between items-center text-sm font-bold"> 1451 <dt>Zwischensumme</dt> 1452 <dd x-html="cart.subtotal"></dd> 1453 </dl> 1454 1455 <div class="flex flex-col gap-y-4 mt-8"> 1456 <a 1457 @click.prevent.stop="proceedToCheckout" 1458 href="https://shop.hk-verlag.de/de/checkout/" 1459 class="btn btn-primary" 1460 > 1461 Kasse </a> 1462 <a 1463 href="https://shop.hk-verlag.de/de/checkout/cart/" 1464 class="btn btn-secondary" 1465 > 1466 Warenkorb anzeigen und bearbeiten </a>
1467 <div x-html="getSectionDataExtraActions"></div> 1468 </div> 1469 </div> 1470 </template> 1471 1472 <template x-if="cartIsEmpty"> 1473 <div class="flex flex-col"> 1474 <button 1475 type="button" 1476 @click="closeCartDrawer" 1477 class="btn btn-primary" 1478 >Einkauf fortsetzen</button> 1479 </div> 1480 </template> 1481 1482 <div 1483 class="z-50 fixed inset-0 flex justify-center items-center bg-white/70 select-none" 1484 x-show="isLoading" 1485 x-cloak 1486 x-transition.opacity.duration.200ms 1487> 1488 <div class="flex items-center"> 1489 <svg xmlns="http://www.w3.org/2000/svg" width="54" height="54" viewBox="0 0 24 24" stroke="currentColor" fill="none" stroke-width="2" stroke-linecap="round" class="animate-spin" aria-hidden="true"> 1490 <circle style="opacity: .3;" cx="12" cy="12" r="10"/> 1491 <path fill="none" stroke-width="2" d="M12,2 a10,10 0 0,1 10,10"/> 1492</svg> 1493 <div class="ml-10 text-xl"> 1494 Wird geladen … </div> 1495 </div> 1496</div> 1497</dialog> 1498 1499 <!--Authentication Pop-Up--> 1500 <!-- BLOCK authentication-popup -->
1500<script> 1501 function initAuthentication() { 1502 return { 1503 open: false, 1504 close() { 1505 this.open = false; 1506 }, 1507 forceAuthentication: false, 1508 checkoutUrl: 'https://shop.hk-verlag.de/de/checkout/index/', 1509 errors: 0, 1510 hasCaptchaToken: 0, 1511 displayErrorMessage: false, 1512 errorMessages: [], 1513 setErrorMessages(message) { 1514 this.errorMessages = [message]; 1515 this.displayErrorMessage = true; 1516 }, 1517 submitForm() { 1518 // Do not rename $form, the variable is expected to be declared in the recaptcha output 1519 const $form = document.querySelector('#login-form'); 1520 1521 if (this.errors === 0) { 1522 this.dispatchLoginRequest($form); 1523 } 1524 }, 1525 onPrivateContentLoaded() { 1526 const data = this.$event.detail.data; 1527 const isLoggedIn = data.customer && data.customer.firstname; 1528 if (data.cart && !isLoggedIn) { 1529 this.forceAuthentication = !data.cart.isGuestCheckoutAllowed; 1530 } 1531 }, 1532 redirectIfAuthenticated() { 1533 const event = this.$event; 1534 this.open = this.forceAuthentication; 1535 1536 if (event.detail && event.detail.url) { 1537 this.checkoutUrl = event.detail.url; 1538 } 1539 if (!this.forceAuthentication) { 1540 window.location.href = this.checkoutUrl; 1541 } 1542 }, 1543 resetErrors() { 1544 this.errors = 0; 1545 }, 1546 dispatchLoginRequest(form) { 1547 this.isLoading = true; 1548 const username = this.$refs['customer-email'].value; 1549 const password = this.$refs['customer-password'].value; 1550 const formKey = hyva.getFormKey(); 1551 const bodyFields = { 1552 'username': username, 1553 'password': password, 1554 'formKey': formKey 1555 }; 1556 const fieldName = 'g\u002Drecaptcha\u002Dresponse'; 1557 const recaptchaField = fieldName && form[fieldName]; 1558 if (recaptchaField) { 1559 bodyFields[fieldName] = recaptchaField.value; 1560 } 1561 fetch('https://shop.hk-verlag.de/de/customer/ajax/login/', { 1562 method: 'POST', 1563 headers: { 1564 'Content-Type': 'application/json', 1565 'X-Requested-With': 'XMLHttpRequest' 1566 }, 1567 body: JSON.stringify(bodyFields) 1568 } 1569 ).then(response => { 1570 return response.json() 1571 } 1572 ).then(data => { 1573 this.isLoading = false; 1574 if (data.errors) { 1575 this.setErrorMessages(data.message); 1576 this.errors = 1; 1577 this.hasCaptchaToken = 0; 1578 } else { 1579 window.location.href = this.checkoutUrl; 1580 } 1581 }); 1582 }, 1583 eventListeners: { 1584 ['@private-content-loaded.window']() { 1585 this.onPrivateContentLoaded(); 1586 }, 1587 ['@toggle-authentication.window']() { 1588 this.redirectIfAuthenticated(); 1589 }, 1590 ['@pageshow.window'](event) { 1591 if (event.persisted) { 1592 this.close(); 1593 }; 1594 } 1595 } 1596 } 1597 } 1598 1599 window.addEventListener('alpine:init', () => Alpine.data('initAuthentication', initAuthentication), {once: true}) 1600</script>
1600 1601 1602<dialog 1603 id="authentication-popup" 1604 aria-labelledby="cart-drawer-title" 1605 class="open:flex flex-col transition ease-out duration-300 motion-reduce:duration-0 p-0" 1606 x-data="initAuthentication" 1607 x-bind="eventListeners" 1608 x-show="open" 1609 x-htmldialog="close" 1610 closeby="any" 1611 x-transition 1612> 1613 <div class="pt-8 px-8"> 1614 <div class="flex gap-2 justify-between items-center"> 1615 <p class="text-xl"> 1616 <strong>Kundenlogin</strong> 1617 </p> 1618 <button 1619 type="button" 1620 class="btn bg-transparent border-transparent p-2" 1621 @click="close" 1622 aria-label="Panel schließen" 1623 > 1624 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><path d="M18 6 6 18M6 6l12 12"/></svg> 1625 </button> 1626 </div> 1627 1628 <div class="message error" x-show="errors" x-cloak> 1629 <template x-for="(message, index) in errorMessages" :key="index"> 1630 <div> 1631 <template x-if="message"> 1632 <span x-html="message"></span> 1633 </template> 1634 </div> 1635 </template> 1636 </div> 1637 </div> 1638 1639 <div class="block-customer-login p-8"> 1640 <p id="authenticate-customer-login" class="text-lg mb-2"> 1641 <strong>Anmelden und Bezahlen</strong> 1642 </p> 1643 1644 <form 1645 id="login-form" 1646 class="form form-login" 1647 method="post" 1648 @submit.prevent="submitForm" 1649 > 1650 <input name="context" type="hidden" value="checkout"> 1651 1652 <div class="flex flex-col gap-4"> 1653 <div class="field email required"> 1654 <label for="form-login-username"> 1655 <span>E-Mail-Adresse</span> 1656 </label> 1657 <div class="control"> 1658 <input 1659 id="form-login-username" 1660 name="username" 1661 type="email" 1662 class="form-input w-full" 1663 required 1664 autocomplete="off" 1665 x-ref="customer-email" 1666 @change="resetErrors" 1667 > 1668 </div> 1669 </div> 1670 <div class="field password required"> 1671 <label for="form-login-password"> 1672 <span>Passwort</span> 1673 </label> 1674 <div class="control"> 1675 <input 1676 id="form-login-password" 1677 name="password" 1678 type="password" 1679 class="form-input w-full" 1680 required 1681 autocomplete="off" 1682 x-ref="customer-password" 1683 @change="resetErrors" 1684 > 1685 </div> 1686 </div> 1687 </div> 1688 1689 <div class="actions-toolbar"> 1690 <button 1691 type="submit" 1692 class="btn btn-primary" 1693 > 1694 Anmelden </button> 1695 <a 1696 href="https://shop.hk-verlag.de/de/customer/account/forgotpassword/" 1697 class="underline hover:no-underline" 1698 > 1699 Passwort vergessen? </a> 1700 </div> 1701 </form> 1702 </div> 1703 <div class="block-new-customer p-8 border-t border-gray-300"> 1704 <p id="authenticate-new-customer" class="text-lg mb-2"> 1705 <strong>Als neuer Kunde bestellen</strong> 1706 </p> 1707 1708 <div class="block-content"> 1709 <p class="mb-1"> 1710 Das Erstellen eines Kontos hat viele Vorteile: </p> 1711 <ul class="list-disc pl-5"> 1712 <li> Bestell- und Versandstatus</li> 1713 <li> Bestellhistorie</li> 1714 <li> Schneller bestellen</li> 1715 </ul> 1716 <div class="actions-toolbar mt-6 mb-2"> 1717 <a href="https://shop.hk-verlag.de/de/customer/account/create/" 1718 class="inline-flex btn btn-primary"> 1719 Ein Konto erstellen </a> 1720 </div> 1721 </div> 1722 </div> 1723</section> 1724<!-- /BLOCK authentication-popup --></div> 1725</header>
1725<main id="maincontent" class="page-main"><div id="contentarea" tabindex="-1"></div> 1726<div class="page messages">
1726<script> 1727 function initMessages() { 1728 "use strict"; 1729 return { 1730 messages: window.mageMessages || [], 1731 isEmpty() { 1732 return this.messages.reduce( 1733 function (isEmpty, message) { 1734 return isEmpty && message === undefined 1735 }, true 1736 ) 1737 }, 1738 hasMessages() { 1739 return !this.isEmpty(); 1740 }, 1741 hasMessage() { 1742 return !!this.message; 1743 }, 1744 removeMessage() { 1745 this.messages[this.index] = undefined; 1746 }, 1747 addMessages(messages, hideAfter) { 1748 messages.map((message) => { 1749 this.messages = this.messages.concat(message); 1750 if (hideAfter === undefined && message.type === 'success' && window.defaultSuccessMessageTimeout) { 1751 hideAfter = window.defaultSuccessMessageTimeout; 1752 } 1753 if (hideAfter) { 1754 this.setHideTimeOut(this.messages.length -1, hideAfter); 1755 } 1756 }); 1757 }, 1758 setHideTimeOut(messageIndex, hideAfter) { 1759 setTimeout((messageIndex) => { 1760 this.messages[messageIndex] = undefined; 1761 }, hideAfter, messageIndex); 1762 }, 1763 eventListeners: { 1764 ['@messages-loaded.window'](event) { 1765 this.addMessages(event.detail.messages, event.detail.hideAfter) 1766 }, 1767 ['@private-content-loaded.window'](event) { 1768 const data = event.detail.data; 1769 if ( 1770 data.messages && 1771 data.messages.messages && 1772 data.messages.messages.length 1773 ) { 1774 this.addMessages(data.messages.messages); 1775 } 1776 }, 1777 ['@clear-messages.window']() { 1778 this.messages = []; 1779 }, 1780 ['@pageshow.window'](event) { 1781 if (event.persisted) { 1782 this.messages = []; 1783 }; 1784 } 1785 }, 1786 getMessageUiId() { 1787 return 'message-' + this.message.type; 1788 } 1789 } 1790 } 1791 1792 window.addEventListener('alpine:init', () => Alpine.data('initMessages', initMessages), {once: true}) 1793</script>
1793 1794<section id="messages" 1795 x-data="initMessages" 1796 x-bind="eventListeners" 1797 role="alert" 1798> 1799 <template x-if="hasMessages"> 1800 <div class="w-full"> 1801 <div class="messages container mx-auto py-3"> 1802 <template x-for="(message, index) in messages" :key="index"> 1803 <div> 1804 <template x-if="hasMessage"> 1805 <div class="message" 1806 :class="message.type" 1807 :ui-id="getMessageUiId" 1808 > 1809 <span x-html="message.text"></span> 1810 <button 1811 type="button" 1812 class="text-gray-600 hover:text-black" 1813 aria-label="Nachricht schließen" 1814 @click.prevent="removeMessage" 1815 > 1816 <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="stroke-current" width="18" height="18" aria-hidden="true"> 1817 <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/> 1818</svg> 1819 </button> 1820 </div> 1821 </template> 1822 </div> 1823 </template> 1824 </div> 1825 </div> 1826 </template> 1827</section> 1828</div><div class="columns"><div class="column main"> 1829<section class="mb-24 lg:mt-6 grid gap-8 grid-cols-1 md:grid-cols-2" aria-labelledby="category-hero"> 1830 <div class="card card-interactive overflow-hidden p-0 hover:transform hover:scale-101 transition duration-300 ease-in-out"> 1831 <a href="https://shop.hk-verlag.de/de/geflugelzeitung" class="block group"> 1832 <img 1833 src="https://shop.hk-verlag.de/media/catalog/category/gefluegelzeitung.jpg" 1834 alt="Geflügelzeitung" 1835 class="w-full h-auto" 1836 loading="lazy" 1837 > 1838 </a> 1839 </div> 1840 <div class="card card-interactive overflow-hidden p-0 hover:transform hover:scale-101 transition duration-300 ease-in-out"> 1841 <a href="https://shop.hk-verlag.de/de/kaninchenzeitung" class="block group"> 1842 <img 1843 src="https://shop.hk-verlag.de/media/catalog/category/kaninchenzeitung.jpg" 1844 alt="Kaninchenzeitung" 1845 class="w-full h-auto" 1846 loading="lazy" 1847 > 1848 </a> 1849 </div> 1850 </section> 1851<style>#html-body [data-pb-style=EXXYY8V]{justify-content:flex-start;display:flex;flex-direction:column;background-position:left top;background-size:cover;background-repeat:no-repeat;background-attachment:scroll}</style><div data-content-type="row" data-appearance="contained" data-element="main"><div data-enable-parallax="0" data-parallax-speed="0.5" data-background-images="{}" data-background-type="image" data-video-loop="true" data-video-play-only-visible="true" data-video-lazy-load="true" data-video-fallback-src="" data-background-lazy-load="" data-element="inner" data-pb-style="EXXYY8V"><div data-content-type="products" data-appearance="carousel" data-autoplay="false" data-autoplay-speed="4000" data-infinite-loop="false" data-show-arrows="false" data-show-dots="true" data-carousel-mode="default" data-center-padding="90px" data-element="main"><section 1852 id="product_productslist_0" 1853 class="widget-product-carousel" 1854 data-slider-type="widget-product-carousel" 1855 > 1856 <a 1857 href="#product_productslist_0-slider-end" 1858 class="sr-only focus:not-sr-only focus:absolute focus:p-2 focus:bg-white" 1859 >Clicken, um das Karussell zu überspringen</a> 1860 1861 <div class="snap-track md:[--snap-cols:2] lg:[--snap-cols:3] xl:[--snap-cols:4]" data-track> 1862 <div class="flex flex-col"> 1863 1864<form method="post" 1865 action="https://shop.hk-verlag.de/de/checkout/cart/add/uenc/%25uenc%25/product/24/" 1866 class="item product product-item product_addtocart_form card card-interactive grow flex flex-col w-full " 1867 data-sku="KZ-26-09" 1868 > 1869 <input name="form_key" type="hidden" value="J80ZjYOFy6hnDq7j" /> <input type="hidden" name="product" value="24"> 1870 <a href="https://shop.hk-verlag.de/de/ausgabe-9-2026-der-kaninchenzeitung" 1871 title="Ausgabe 9/2026 der Kaninchenzeitung" 1872 class="product photo product-item-photo block mx-auto mb-3 " 1873 tabindex="-1" 1874 > 1875 <img 1876 src="https://shop.hk-verlag.de/media/catalog/product/cache/2765542505660baab28ecd555e27366e/k/0/k09_26__01_titel_hk_shop_360x360.jpg" 1877 width="240" 1878 height="300" 1879 alt="Ausgabe 9/2026 der Kaninchenzeitung" 1880 class="product-image-photo" 1881 loading="lazy" 1882 x-data="initProductItemImage" 1883 @update-gallery-24.window="updateImage" 1884 > 1885 </a> 1886 <div class="product-info flex flex-col grow "> 1887 <div class="mt-2 mb-1 items-center justify-center font-semibold text-lg text-center "> 1888 <a 1889 class="product-item-link" 1890 href="https://shop.hk-verlag.de/de/ausgabe-9-2026-der-kaninchenzeitung" 1891 > 1892 Ausgabe 9/2026 der Kaninchenzeitung </a> 1893 </div> 1894 1895 <div class="py-1 mx-auto "> 1896 </div> 1897 1898 1899 1900 1901 <div class="pt-1" 1902 x-data="initPriceBox()" 1903 x-defer="intersect" 1904 @update-prices-24.window="updatePrice($event.detail);" 1905 > 1906 <div class="price-box price-final_price" data-role="priceBox" data-product-id="24" data-price-box="product-id-24"> 1907 <span
1908 x-data x-id="['product\u002Dprice\u002D24']" class="price-container price-final_price tax weee" 1909 > 1910 <span :id="$id('product\u002Dprice\u002D24')" data-price-amount="14.5" 1911 data-price-type="finalPrice" 1912 class="price-wrapper " 1913 ><span class="price">14,50 €</span></span> 1914 </span> 1915 1916</div> </div> 1917 1918 <div class="mt-auto pt-3 flex flex-wrap items-center gap-y-4 gap-x-2 1919 "> 1920 <button 1921 class="w-auto btn btn-primary justify-center text-sm mr-auto" 1922 title="In den Warenkorb Ausgabe 9/2026 der Kaninchenzeitung" 1923 aria-label="In den Warenkorb Ausgabe 9/2026 der Kaninchenzeitung" 1924 data-addto="cart" 1925 > 1926 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><circle cx="8" cy="21" r="1"/><circle cx="19" cy="21" r="1"/><path d="M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12"/></svg> 1927 <span class="inline md:hidden lg:inline"> 1928 In den Warenkorb </span> 1929 </button> 1930 1931 <div class="flex flex-wrap gap-2"> 1932 1933<button x-data="initWishlist()" 1934 x-defer="intersect" 1935 @click.prevent="addToWishlist(24)" 1936 aria-label="Zur Wunschliste hinzufügen Ausgabe 9/2026 der Kaninchenzeitung" 1937 type="button" 1938 class="btn p-2 rounded-full" 1939 data-addto="wishlist" 1940> 1941 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><path d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"/></svg> 1942</button> 1943 </div> 1944 </div> 1945 </div> 1946</form> 1947 </div> 1948 <div class="flex flex-col"> 1949 1950<form method="post" 1951 action="https://shop.hk-verlag.de/de/checkout/cart/add/uenc/%25uenc%25/product/23/" 1952 class="item product product-item product_addtocart_form card card-interactive grow flex flex-col w-full " 1953 data-sku="HK21" 1954 > 1955 <input name="form_key" type="hidden" value="J80ZjYOFy6hnDq7j" /> <input type="hidden" name="product" value="23"> 1956 <a href="https://shop.hk-verlag.de/de/bildkalender-rassegeflugel-2027" 1957 title="Bildkalender Rassegeflügel 2027" 1958 class="product photo product-item-photo block mx-auto mb-3 " 1959 tabindex="-1" 1960 > 1961 <img 1962 src="https://shop.hk-verlag.de/media/catalog/product/cache/2765542505660baab28ecd555e27366e/2/6/261500_gef_shopabbildung_bildkalender_gefl_gel_2027_600x600.jpg" 1963 width="240" 1964 height="300" 1965 alt="Bildkalender Rassegeflügel 2027" 1966 class="product-image-photo" 1967 loading="lazy" 1968 x-data="initProductItemImage" 1969 @update-gallery-23.window="updateImage" 1970 > 1971 </a> 1972 <div class="product-info flex flex-col grow "> 1973 <div class="mt-2 mb-1 items-center justify-center font-semibold text-lg text-center "> 1974 <a 1975 class="product-item-link" 1976 href="https://shop.hk-verlag.de/de/bildkalender-rassegeflugel-2027" 1977 > 1978 Bildkalender Rassegeflügel 2027 </a> 1979 </div> 1980 1981 <div class="py-1 mx-auto "> 1982 </div> 1983 1984 1985 1986 1987 <div class="pt-1" 1988 x-data="initPriceBox()" 1989 x-defer="intersect" 1990 @update-prices-23.window="updatePrice($event.detail);" 1991 > 1992 <div class="price-box price-final_price" data-role="priceBox" data-product-id="23" data-price-box="product-id-23"> 1993 <span
1994 x-data x-id="['product\u002Dprice\u002D23']" class="price-container price-final_price tax weee" 1995 > 1996 <span :id="$id('product\u002Dprice\u002D23')" data-price-amount="9.9" 1997 data-price-type="finalPrice" 1998 class="price-wrapper " 1999 ><span class="price">9,90 €</span></span> 2000 </span> 2001 2002</div> </div> 2003 2004 <div class="mt-auto pt-3 flex flex-wrap items-center gap-y-4 gap-x-2 2005 "> 2006 <button 2007 class="w-auto btn btn-primary justify-center text-sm mr-auto" 2008 title="In den Warenkorb Bildkalender Rassegeflügel 2027" 2009 aria-label="In den Warenkorb Bildkalender Rassegeflügel 2027" 2010 data-addto="cart" 2011 > 2012 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><circle cx="8" cy="21" r="1"/><circle cx="19" cy="21" r="1"/><path d="M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12"/></svg> 2013 <span class="inline md:hidden lg:inline"> 2014 In den Warenkorb </span> 2015 </button> 2016 2017 <div class="flex flex-wrap gap-2"> 2018 2019<button x-data="initWishlist()" 2020 x-defer="intersect" 2021 @click.prevent="addToWishlist(23)" 2022 aria-label="Zur Wunschliste hinzufügen Bildkalender Rassegeflügel 2027" 2023 type="button" 2024 class="btn p-2 rounded-full" 2025 data-addto="wishlist" 2026> 2027 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><path d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"/></svg> 2028</button> 2029 </div> 2030 </div> 2031 </div> 2032</form> 2033 </div> 2034 <div class="flex flex-col"> 2035 2036<form method="post" 2037 action="https://shop.hk-verlag.de/de/checkout/cart/add/uenc/%25uenc%25/product/22/" 2038 class="item product product-item product_addtocart_form card card-interactive grow flex flex-col w-full " 2039 data-sku="HK20" 2040 > 2041 <input name="form_key" type="hidden" value="J80ZjYOFy6hnDq7j" /> <input type="hidden" name="product" value="22"> 2042 <a href="https://shop.hk-verlag.de/de/bildkalender-rassekaninchen-2027" 2043 title="Bildkalender Rassekaninchen 2027" 2044 class="product photo product-item-photo block mx-auto mb-3 " 2045 tabindex="-1" 2046 > 2047 <img 2048 src="https://shop.hk-verlag.de/media/catalog/product/cache/2765542505660baab28ecd555e27366e/2/6/261501_kan_shopabbildung_bildkalender_kaninchen_2027_600x600.jpg" 2049 width="240" 2050 height="300" 2051 alt="Bildkalender Rassekaninchen 2027" 2052 class="product-image-photo" 2053 loading="lazy" 2054 x-data="initProductItemImage" 2055 @update-gallery-22.window="updateImage" 2056 > 2057 </a> 2058 <div class="product-info flex flex-col grow "> 2059 <div class="mt-2 mb-1 items-center justify-center font-semibold text-lg text-center "> 2060 <a 2061 class="product-item-link" 2062 href="https://shop.hk-verlag.de/de/bildkalender-rassekaninchen-2027" 2063 > 2064 Bildkalender Rassekaninchen 2027 </a> 2065 </div> 2066 2067 <div class="py-1 mx-auto "> 2068 </div> 2069 2070 2071 2072 2073 <div class="pt-1" 2074 x-data="initPriceBox()" 2075 x-defer="intersect" 2076 @update-prices-22.window="updatePrice($event.detail);" 2077 > 2078 <div class="price-box price-final_price" data-role="priceBox" data-product-id="22" data-price-box="product-id-22"> 2079 <span
2080 x-data x-id="['product\u002Dprice\u002D22']" class="price-container price-final_price tax weee" 2081 > 2082 <span :id="$id('product\u002Dprice\u002D22')" data-price-amount="9.9" 2083 data-price-type="finalPrice" 2084 class="price-wrapper " 2085 ><span class="price">9,90 €</span></span> 2086 </span> 2087 2088</div> </div> 2089 2090 <div class="mt-auto pt-3 flex flex-wrap items-center gap-y-4 gap-x-2 2091 "> 2092 <button 2093 class="w-auto btn btn-primary justify-center text-sm mr-auto" 2094 title="In den Warenkorb Bildkalender Rassekaninchen 2027" 2095 aria-label="In den Warenkorb Bildkalender Rassekaninchen 2027" 2096 data-addto="cart" 2097 > 2098 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><circle cx="8" cy="21" r="1"/><circle cx="19" cy="21" r="1"/><path d="M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12"/></svg> 2099 <span class="inline md:hidden lg:inline"> 2100 In den Warenkorb </span> 2101 </button> 2102 2103 <div class="flex flex-wrap gap-2"> 2104 2105<button x-data="initWishlist()" 2106 x-defer="intersect" 2107 @click.prevent="addToWishlist(22)" 2108 aria-label="Zur Wunschliste hinzufügen Bildkalender Rassekaninchen 2027" 2109 type="button" 2110 class="btn p-2 rounded-full" 2111 data-addto="wishlist" 2112> 2113 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><path d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"/></svg> 2114</button> 2115 </div> 2116 </div> 2117 </div> 2118</form> 2119 </div> 2120 <div class="flex flex-col"> 2121 2122<form method="post" 2123 action="https://shop.hk-verlag.de/de/checkout/cart/add/uenc/%25uenc%25/product/21/" 2124 class="item product product-item product_addtocart_form card card-interactive grow flex flex-col w-full " 2125 data-sku="HK22" 2126 > 2127 <input name="form_key" type="hidden" value="J80ZjYOFy6hnDq7j" /> <input type="hidden" name="product" value="21"> 2128 <a href="https://shop.hk-verlag.de/de/kunstkalender-geflugel-2027" 2129 title="Kunstkalender Geflügel 2027" 2130 class="product photo product-item-photo block mx-auto mb-3 " 2131 tabindex="-1" 2132 > 2133 <img 2134 src="https://shop.hk-verlag.de/media/catalog/product/cache/2765542505660baab28ecd555e27366e/2/6/261499_gef_shopabbildung_kunstkalender_gefl_gel_2027_600x600.jpg" 2135 width="240" 2136 height="300" 2137 alt="Kunstkalender Geflügel 2027" 2138 class="product-image-photo" 2139 loading="lazy" 2140 x-data="initProductItemImage" 2141 @update-gallery-21.window="updateImage" 2142 > 2143 </a> 2144 <div class="product-info flex flex-col grow "> 2145 <div class="mt-2 mb-1 items-center justify-center font-semibold text-lg text-center "> 2146 <a 2147 class="product-item-link" 2148 href="https://shop.hk-verlag.de/de/kunstkalender-geflugel-2027" 2149 > 2150 Kunstkalender Geflügel 2027 </a> 2151 </div> 2152 2153 <div class="py-1 mx-auto "> 2154 </div> 2155 2156 2157 2158 2159 <div class="pt-1" 2160 x-data="initPriceBox()" 2161 x-defer="intersect" 2162 @update-prices-21.window="updatePrice($event.detail);" 2163 > 2164 <div class="price-box price-final_price" data-role="priceBox" data-product-id="21" data-price-box="product-id-21"> 2165 <span
2166 x-data x-id="['product\u002Dprice\u002D21']" class="price-container price-final_price tax weee" 2167 > 2168 <span :id="$id('product\u002Dprice\u002D21')" data-price-amount="24.9" 2169 data-price-type="finalPrice" 2170 class="price-wrapper " 2171 ><span class="price">24,90 €</span></span> 2172 </span> 2173 2174</div> </div> 2175 2176 <div class="mt-auto pt-3 flex flex-wrap items-center gap-y-4 gap-x-2 2177 "> 2178 <button 2179 class="w-auto btn btn-primary justify-center text-sm mr-auto" 2180 title="In den Warenkorb Kunstkalender Geflügel 2027" 2181 aria-label="In den Warenkorb Kunstkalender Geflügel 2027" 2182 data-addto="cart" 2183 > 2184 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><circle cx="8" cy="21" r="1"/><circle cx="19" cy="21" r="1"/><path d="M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12"/></svg> 2185 <span class="inline md:hidden lg:inline"> 2186 In den Warenkorb </span> 2187 </button> 2188 2189 <div class="flex flex-wrap gap-2"> 2190 2191<button x-data="initWishlist()" 2192 x-defer="intersect" 2193 @click.prevent="addToWishlist(21)" 2194 aria-label="Zur Wunschliste hinzufügen Kunstkalender Geflügel 2027" 2195 type="button" 2196 class="btn p-2 rounded-full" 2197 data-addto="wishlist" 2198> 2199 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><path d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"/></svg> 2200</button> 2201 </div> 2202 </div> 2203 </div> 2204</form> 2205 </div> 2206 <div class="flex flex-col"> 2207 2208<form method="post" 2209 action="https://shop.hk-verlag.de/de/checkout/cart/add/uenc/%25uenc%25/product/18/" 2210 class="item product product-item product_addtocart_form card card-interactive grow flex flex-col w-full " 2211 data-sku="HK02" 2212 > 2213 <input name="form_key" type="hidden" value="J80ZjYOFy6hnDq7j" /> <input type="hidden" name="product" value="18"> 2214 <a href="https://shop.hk-verlag.de/de/deutsche-riesen" 2215 title="Deutsche Riesen" 2216 class="product photo product-item-photo block mx-auto mb-3 " 2217 tabindex="-1" 2218 > 2219 <img 2220 src="https://shop.hk-verlag.de/media/catalog/product/cache/2765542505660baab28ecd555e27366e/h/k/hk02_buch_deutsche-riesen.jpg" 2221 width="240" 2222 height="300" 2223 alt="Deutsche Riesen" 2224 class="product-image-photo" 2225 loading="lazy" 2226 x-data="initProductItemImage" 2227 @update-gallery-18.window="updateImage" 2228 > 2229 </a> 2230 <div class="product-info flex flex-col grow "> 2231 <div class="mt-2 mb-1 items-center justify-center font-semibold text-lg text-center "> 2232 <a 2233 class="product-item-link" 2234 href="https://shop.hk-verlag.de/de/deutsche-riesen" 2235 > 2236 Deutsche Riesen </a> 2237 </div> 2238 2239 <div class="py-1 mx-auto "> 2240 </div> 2241 2242 2243 2244 2245 <div class="pt-1" 2246 x-data="initPriceBox()" 2247 x-defer="intersect" 2248 @update-prices-18.window="updatePrice($event.detail);" 2249 > 2250 <div class="price-box price-final_price" data-role="priceBox" data-product-id="18" data-price-box="product-id-18"> 2251 <span
2252 x-data x-id="['product\u002Dprice\u002D18']" class="price-container price-final_price tax weee" 2253 > 2254 <span :id="$id('product\u002Dprice\u002D18')" data-price-amount="8.9" 2255 data-price-type="finalPrice" 2256 class="price-wrapper " 2257 ><span class="price">8,90 €</span></span> 2258 </span> 2259 2260</div> </div> 2261 2262 <div class="mt-auto pt-3 flex flex-wrap items-center gap-y-4 gap-x-2 2263 "> 2264 <button 2265 class="w-auto btn btn-primary justify-center text-sm mr-auto" 2266 title="In den Warenkorb Deutsche Riesen" 2267 aria-label="In den Warenkorb Deutsche Riesen" 2268 data-addto="cart" 2269 > 2270 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><circle cx="8" cy="21" r="1"/><circle cx="19" cy="21" r="1"/><path d="M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12"/></svg> 2271 <span class="inline md:hidden lg:inline"> 2272 In den Warenkorb </span> 2273 </button> 2274 2275 <div class="flex flex-wrap gap-2"> 2276 2277<button x-data="initWishlist()" 2278 x-defer="intersect" 2279 @click.prevent="addToWishlist(18)" 2280 aria-label="Zur Wunschliste hinzufügen Deutsche Riesen" 2281 type="button" 2282 class="btn p-2 rounded-full" 2283 data-addto="wishlist" 2284> 2285 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><path d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"/></svg> 2286</button> 2287 </div> 2288 </div> 2289 </div> 2290</form> 2291 </div> 2292 <div class="flex flex-col"> 2293 2294<form method="post" 2295 action="https://shop.hk-verlag.de/de/checkout/cart/add/uenc/%25uenc%25/product/15/" 2296 class="item product product-item product_addtocart_form card card-interactive grow flex flex-col w-full " 2297 data-sku="KZ26HP-21" 2298 > 2299 <input name="form_key" type="hidden" value="J80ZjYOFy6hnDq7j" /> <input type="hidden" name="product" value="15"> 2300 <a href="https://shop.hk-verlag.de/de/testabo-3-monate-kaninchenzeitung" 2301 title="Testabo 3 Monate" 2302 class="product photo product-item-photo block mx-auto mb-3 " 2303 tabindex="-1" 2304 > 2305 <img 2306 src="https://shop.hk-verlag.de/media/catalog/product/cache/2765542505660baab28ecd555e27366e/k/a/kaninchenzeitung-1764330677.jpg" 2307 width="240" 2308 height="300" 2309 alt="Testabo 3 Monate" 2310 class="product-image-photo" 2311 loading="lazy" 2312 x-data="initProductItemImage" 2313 @update-gallery-15.window="updateImage" 2314 > 2315 </a> 2316 <div class="product-info flex flex-col grow "> 2317 <div class="mt-2 mb-1 items-center justify-center font-semibold text-lg text-center "> 2318 <a 2319 class="product-item-link" 2320 href="https://shop.hk-verlag.de/de/testabo-3-monate-kaninchenzeitung" 2321 > 2322 Testabo 3 Monate </a> 2323 </div> 2324 2325 <div class="py-1 mx-auto "> 2326 </div> 2327 2328 2329 2330 2331 <div class="pt-1" 2332 x-data="initPriceBox()" 2333 x-defer="intersect" 2334 @update-prices-15.window="updatePrice($event.detail);" 2335 > 2336 <div class="price-box price-final_price" data-role="priceBox" data-product-id="15" data-price-box="product-id-15"> 2337 <span
2338 x-data x-id="['product\u002Dprice\u002D15']" class="price-container price-final_price tax weee" 2339 > 2340 <span :id="$id('product\u002Dprice\u002D15')" data-price-amount="12.5" 2341 data-price-type="finalPrice" 2342 class="price-wrapper " 2343 ><span class="price">12,50 €</span></span> 2344 </span> 2345 2346</div> </div> 2347 2348 <div class="mt-auto pt-3 flex flex-wrap items-center gap-y-4 gap-x-2 2349 "> 2350 <button 2351 class="w-auto btn btn-primary justify-center text-sm mr-auto" 2352 title="In den Warenkorb Testabo 3 Monate" 2353 aria-label="In den Warenkorb Testabo 3 Monate" 2354 data-addto="cart" 2355 > 2356 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><circle cx="8" cy="21" r="1"/><circle cx="19" cy="21" r="1"/><path d="M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12"/></svg> 2357 <span class="inline md:hidden lg:inline"> 2358 In den Warenkorb </span> 2359 </button> 2360 2361 <div class="flex flex-wrap gap-2"> 2362 2363<button x-data="initWishlist()" 2364 x-defer="intersect" 2365 @click.prevent="addToWishlist(15)" 2366 aria-label="Zur Wunschliste hinzufügen Testabo 3 Monate" 2367 type="button" 2368 class="btn p-2 rounded-full" 2369 data-addto="wishlist" 2370> 2371 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><path d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"/></svg> 2372</button> 2373 </div> 2374 </div> 2375 </div> 2376</form> 2377 </div> 2378 <div class="flex flex-col"> 2379 2380<form method="post" 2381 action="https://shop.hk-verlag.de/de/checkout/cart/add/uenc/%25uenc%25/product/14/" 2382 class="item product product-item product_addtocart_form card card-interactive grow flex flex-col w-full " 2383 data-sku="KZ26DMHP-12" 2384 > 2385 <input name="form_key" type="hidden" value="J80ZjYOFy6hnDq7j" /> <input type="hidden" name="product" value="14"> 2386 <a href="https://shop.hk-verlag.de/de/digital-upgrade-kaninchenzeitung" 2387 title="Digital-Upgrade" 2388 class="product photo product-item-photo block mx-auto mb-3 " 2389 tabindex="-1" 2390 > 2391 <img 2392 src="https://shop.hk-verlag.de/media/catalog/product/cache/2765542505660baab28ecd555e27366e/k/a/kaninchenzeitung_digital-1764330678.png" 2393 width="240" 2394 height="300" 2395 alt="Digital-Upgrade" 2396 class="product-image-photo" 2397 loading="lazy" 2398 x-data="initProductItemImage" 2399 @update-gallery-14.window="updateImage" 2400 > 2401 </a> 2402 <div class="product-info flex flex-col grow "> 2403 <div class="mt-2 mb-1 items-center justify-center font-semibold text-lg text-center "> 2404 <a 2405 class="product-item-link" 2406 href="https://shop.hk-verlag.de/de/digital-upgrade-kaninchenzeitung" 2407 > 2408 Digital-Upgrade </a> 2409 </div> 2410 2411 <div class="py-1 mx-auto "> 2412 </div> 2413 2414 2415 2416 2417 <div class="pt-1" 2418 x-data="initPriceBox()" 2419 x-defer="intersect" 2420 @update-prices-14.window="updatePrice($event.detail);" 2421 > 2422 <div class="price-box price-final_price" data-role="priceBox" data-product-id="14" data-price-box="product-id-14"> 2423 <span
2424 x-data x-id="['product\u002Dprice\u002D14']" class="price-container price-final_price tax weee" 2425 > 2426 <span :id="$id('product\u002Dprice\u002D14')" data-price-amount="9" 2427 data-price-type="finalPrice" 2428 class="price-wrapper " 2429 ><span class="price">9,00 €</span></span> 2430 </span> 2431 2432</div> </div> 2433 2434 <div class="mt-auto pt-3 flex flex-wrap items-center gap-y-4 gap-x-2 2435 "> 2436 <button 2437 class="w-auto btn btn-primary justify-center text-sm mr-auto" 2438 title="In den Warenkorb Digital-Upgrade" 2439 aria-label="In den Warenkorb Digital-Upgrade" 2440 data-addto="cart" 2441 > 2442 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><circle cx="8" cy="21" r="1"/><circle cx="19" cy="21" r="1"/><path d="M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12"/></svg> 2443 <span class="inline md:hidden lg:inline"> 2444 In den Warenkorb </span> 2445 </button> 2446 2447 <div class="flex flex-wrap gap-2"> 2448 2449<button x-data="initWishlist()" 2450 x-defer="intersect" 2451 @click.prevent="addToWishlist(14)" 2452 aria-label="Zur Wunschliste hinzufügen Digital-Upgrade" 2453 type="button" 2454 class="btn p-2 rounded-full" 2455 data-addto="wishlist" 2456> 2457 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><path d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"/></svg> 2458</button> 2459 </div> 2460 </div> 2461 </div> 2462</form> 2463 </div> 2464 <div class="flex flex-col"> 2465 2466<form method="post" 2467 action="https://shop.hk-verlag.de/de/checkout/cart/add/uenc/%25uenc%25/product/12/" 2468 class="item product product-item product_addtocart_form card card-interactive grow flex flex-col w-full " 2469 data-sku="KZ26DMHP-11" 2470 > 2471 <input name="form_key" type="hidden" value="J80ZjYOFy6hnDq7j" /> <input type="hidden" name="product" value="12"> 2472 <a href="https://shop.hk-verlag.de/de/jahresabo-e-paper-kaninchenzeitung" 2473 title="Jahresabo E-Paper " 2474 class="product photo product-item-photo block mx-auto mb-3 " 2475 tabindex="-1" 2476 > 2477 <img 2478 src="https://shop.hk-verlag.de/media/catalog/product/cache/2765542505660baab28ecd555e27366e/k/a/kaninchenzeitung_digital-1764330678.png" 2479 width="240" 2480 height="300" 2481 alt="Jahresabo E-Paper " 2482 class="product-image-photo" 2483 loading="lazy" 2484 x-data="initProductItemImage" 2485 @update-gallery-12.window="updateImage" 2486 > 2487 </a> 2488 <div class="product-info flex flex-col grow "> 2489 <div class="mt-2 mb-1 items-center justify-center font-semibold text-lg text-center "> 2490 <a 2491 class="product-item-link" 2492 href="https://shop.hk-verlag.de/de/jahresabo-e-paper-kaninchenzeitung" 2493 > 2494 Jahresabo E-Paper </a> 2495 </div> 2496 2497 <div class="py-1 mx-auto "> 2498 </div> 2499 2500 2501 2502 2503 <div class="pt-1" 2504 x-data="initPriceBox()" 2505 x-defer="intersect" 2506 @update-prices-12.window="updatePrice($event.detail);" 2507 > 2508 <div class="price-box price-final_price" data-role="priceBox" data-product-id="12" data-price-box="product-id-12"> 2509 <span
2510 x-data x-id="['product\u002Dprice\u002D12']" class="price-container price-final_price tax weee" 2511 > 2512 <span :id="$id('product\u002Dprice\u002D12')" data-price-amount="59.99" 2513 data-price-type="finalPrice" 2514 class="price-wrapper " 2515 ><span class="price">59,99 €</span></span> 2516 </span> 2517 2518</div> </div> 2519 2520 <div class="mt-auto pt-3 flex flex-wrap items-center gap-y-4 gap-x-2 2521 "> 2522 <button 2523 class="w-auto btn btn-primary justify-center text-sm mr-auto" 2524 title="In den Warenkorb Jahresabo E-Paper " 2525 aria-label="In den Warenkorb Jahresabo E-Paper " 2526 data-addto="cart" 2527 > 2528 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><circle cx="8" cy="21" r="1"/><circle cx="19" cy="21" r="1"/><path d="M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12"/></svg> 2529 <span class="inline md:hidden lg:inline"> 2530 In den Warenkorb </span> 2531 </button> 2532 2533 <div class="flex flex-wrap gap-2"> 2534 2535<button x-data="initWishlist()" 2536 x-defer="intersect" 2537 @click.prevent="addToWishlist(12)" 2538 aria-label="Zur Wunschliste hinzufügen Jahresabo E-Paper " 2539 type="button" 2540 class="btn p-2 rounded-full" 2541 data-addto="wishlist" 2542> 2543 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><path d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"/></svg> 2544</button> 2545 </div> 2546 </div> 2547 </div> 2548</form> 2549 </div> 2550 <div class="flex flex-col"> 2551 2552<form method="post" 2553 action="https://shop.hk-verlag.de/de/checkout/cart/add/uenc/%25uenc%25/product/11/" 2554 class="item product product-item product_addtocart_form card card-interactive grow flex flex-col w-full " 2555 data-sku="KZ26HP-11" 2556 > 2557 <input name="form_key" type="hidden" value="J80ZjYOFy6hnDq7j" /> <input type="hidden" name="product" value="11"> 2558 <a href="https://shop.hk-verlag.de/de/jahresabo-print-kaninchenzeitung" 2559 title="Jahresabo Print" 2560 class="product photo product-item-photo block mx-auto mb-3 " 2561 tabindex="-1" 2562 > 2563 <img 2564 src="https://shop.hk-verlag.de/media/catalog/product/cache/2765542505660baab28ecd555e27366e/k/a/kaninchenzeitung-1764330677.jpg" 2565 width="240" 2566 height="300" 2567 alt="Jahresabo Print" 2568 class="product-image-photo" 2569 loading="lazy" 2570 x-data="initProductItemImage" 2571 @update-gallery-11.window="updateImage" 2572 > 2573 </a> 2574 <div class="product-info flex flex-col grow "> 2575 <div class="mt-2 mb-1 items-center justify-center font-semibold text-lg text-center "> 2576 <a 2577 class="product-item-link" 2578 href="https://shop.hk-verlag.de/de/jahresabo-print-kaninchenzeitung" 2579 > 2580 Jahresabo Print </a> 2581 </div> 2582 2583 <div class="py-1 mx-auto "> 2584 </div> 2585 2586 2587 2588 2589 <div class="pt-1" 2590 x-data="initPriceBox()" 2591 x-defer="intersect" 2592 @update-prices-11.window="updatePrice($event.detail);" 2593 > 2594 <div class="price-box price-final_price" data-role="priceBox" data-product-id="11" data-price-box="product-id-11"> 2595 <span
2596 x-data x-id="['product\u002Dprice\u002D11']" class="price-container price-final_price tax weee" 2597 > 2598 <span :id="$id('product\u002Dprice\u002D11')" data-price-amount="89.9" 2599 data-price-type="finalPrice" 2600 class="price-wrapper " 2601 ><span class="price">89,90 €</span></span> 2602 </span> 2603 2604</div> </div> 2605 2606 <div class="mt-auto pt-3 flex flex-wrap items-center gap-y-4 gap-x-2 2607 "> 2608 <button 2609 class="w-auto btn btn-primary justify-center text-sm mr-auto" 2610 title="In den Warenkorb Jahresabo Print" 2611 aria-label="In den Warenkorb Jahresabo Print" 2612 data-addto="cart" 2613 > 2614 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><circle cx="8" cy="21" r="1"/><circle cx="19" cy="21" r="1"/><path d="M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12"/></svg> 2615 <span class="inline md:hidden lg:inline"> 2616 In den Warenkorb </span> 2617 </button> 2618 2619 <div class="flex flex-wrap gap-2"> 2620 2621<button x-data="initWishlist()" 2622 x-defer="intersect" 2623 @click.prevent="addToWishlist(11)" 2624 aria-label="Zur Wunschliste hinzufügen Jahresabo Print" 2625 type="button" 2626 class="btn p-2 rounded-full" 2627 data-addto="wishlist" 2628> 2629 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><path d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"/></svg> 2630</button> 2631 </div> 2632 </div> 2633 </div> 2634</form> 2635 </div> 2636 <div class="flex flex-col"> 2637 2638<form method="post" 2639 action="https://shop.hk-verlag.de/de/checkout/cart/add/uenc/%25uenc%25/product/6/" 2640 class="item product product-item product_addtocart_form card card-interactive grow flex flex-col w-full " 2641 data-sku="GZ26HP-21" 2642 > 2643 <input name="form_key" type="hidden" value="J80ZjYOFy6hnDq7j" /> <input type="hidden" name="product" value="6"> 2644 <a href="https://shop.hk-verlag.de/de/testabo-3-monate" 2645 title="Testabo 3 Monate " 2646 class="product photo product-item-photo block mx-auto mb-3 " 2647 tabindex="-1" 2648 > 2649 <img 2650 src="https://shop.hk-verlag.de/media/catalog/product/cache/2765542505660baab28ecd555e27366e/g/e/gefluegelzeitung-1764330678.jpg" 2651 width="240" 2652 height="300" 2653 alt="Testabo 3 Monate " 2654 class="product-image-photo" 2655 loading="lazy" 2656 x-data="initProductItemImage" 2657 @update-gallery-6.window="updateImage" 2658 > 2659 </a> 2660 <div class="product-info flex flex-col grow "> 2661 <div class="mt-2 mb-1 items-center justify-center font-semibold text-lg text-center "> 2662 <a 2663 class="product-item-link" 2664 href="https://shop.hk-verlag.de/de/testabo-3-monate" 2665 > 2666 Testabo 3 Monate </a> 2667 </div> 2668 2669 <div class="py-1 mx-auto "> 2670 </div> 2671 2672 2673 2674 2675 <div class="pt-1" 2676 x-data="initPriceBox()" 2677 x-defer="intersect" 2678 @update-prices-6.window="updatePrice($event.detail);" 2679 > 2680 <div class="price-box price-final_price" data-role="priceBox" data-product-id="6" data-price-box="product-id-6"> 2681 <span
2682 x-data x-id="['product\u002Dprice\u002D6']" class="price-container price-final_price tax weee" 2683 > 2684 <span :id="$id('product\u002Dprice\u002D6')" data-price-amount="16.9" 2685 data-price-type="finalPrice" 2686 class="price-wrapper " 2687 ><span class="price">16,90 €</span></span> 2688 </span> 2689 2690</div> </div> 2691 2692 <div class="mt-auto pt-3 flex flex-wrap items-center gap-y-4 gap-x-2 2693 "> 2694 <button 2695 class="w-auto btn btn-primary justify-center text-sm mr-auto" 2696 title="In den Warenkorb Testabo 3 Monate " 2697 aria-label="In den Warenkorb Testabo 3 Monate " 2698 data-addto="cart" 2699 > 2700 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><circle cx="8" cy="21" r="1"/><circle cx="19" cy="21" r="1"/><path d="M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12"/></svg> 2701 <span class="inline md:hidden lg:inline"> 2702 In den Warenkorb </span> 2703 </button> 2704 2705 <div class="flex flex-wrap gap-2"> 2706 2707<button x-data="initWishlist()" 2708 x-defer="intersect" 2709 @click.prevent="addToWishlist(6)" 2710 aria-label="Zur Wunschliste hinzufügen Testabo 3 Monate " 2711 type="button" 2712 class="btn p-2 rounded-full" 2713 data-addto="wishlist" 2714> 2715 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><path d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"/></svg> 2716</button> 2717 </div> 2718 </div> 2719 </div> 2720</form> 2721 </div> 2722 <div class="flex flex-col"> 2723 2724<form method="post" 2725 action="https://shop.hk-verlag.de/de/checkout/cart/add/uenc/%25uenc%25/product/5/" 2726 class="item product product-item product_addtocart_form card card-interactive grow flex flex-col w-full " 2727 data-sku="GZ26DMHP-12" 2728 > 2729 <input name="form_key" type="hidden" value="J80ZjYOFy6hnDq7j" /> <input type="hidden" name="product" value="5"> 2730 <a href="https://shop.hk-verlag.de/de/digital-upgrade" 2731 title="Digital-Upgrade " 2732 class="product photo product-item-photo block mx-auto mb-3 " 2733 tabindex="-1" 2734 > 2735 <img 2736 src="https://shop.hk-verlag.de/media/catalog/product/cache/2765542505660baab28ecd555e27366e/g/e/gefluegelzeitung_digital-1764330679.png" 2737 width="240" 2738 height="300" 2739 alt="Digital-Upgrade " 2740 class="product-image-photo" 2741 loading="lazy" 2742 x-data="initProductItemImage" 2743 @update-gallery-5.window="updateImage" 2744 > 2745 </a> 2746 <div class="product-info flex flex-col grow "> 2747 <div class="mt-2 mb-1 items-center justify-center font-semibold text-lg text-center "> 2748 <a 2749 class="product-item-link" 2750 href="https://shop.hk-verlag.de/de/digital-upgrade" 2751 > 2752 Digital-Upgrade </a> 2753 </div> 2754 2755 <div class="py-1 mx-auto "> 2756 </div> 2757 2758 2759 2760 2761 <div class="pt-1" 2762 x-data="initPriceBox()" 2763 x-defer="intersect" 2764 @update-prices-5.window="updatePrice($event.detail);" 2765 > 2766 <div class="price-box price-final_price" data-role="priceBox" data-product-id="5" data-price-box="product-id-5"> 2767 <span
2768 x-data x-id="['product\u002Dprice\u002D5']" class="price-container price-final_price tax weee" 2769 > 2770 <span :id="$id('product\u002Dprice\u002D5')" data-price-amount="18" 2771 data-price-type="finalPrice" 2772 class="price-wrapper " 2773 ><span class="price">18,00 €</span></span> 2774 </span> 2775 2776</div> </div> 2777 2778 <div class="mt-auto pt-3 flex flex-wrap items-center gap-y-4 gap-x-2 2779 "> 2780 <button 2781 class="w-auto btn btn-primary justify-center text-sm mr-auto" 2782 title="In den Warenkorb Digital-Upgrade " 2783 aria-label="In den Warenkorb Digital-Upgrade " 2784 data-addto="cart" 2785 > 2786 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><circle cx="8" cy="21" r="1"/><circle cx="19" cy="21" r="1"/><path d="M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12"/></svg> 2787 <span class="inline md:hidden lg:inline"> 2788 In den Warenkorb </span> 2789 </button> 2790 2791 <div class="flex flex-wrap gap-2"> 2792 2793<button x-data="initWishlist()" 2794 x-defer="intersect" 2795 @click.prevent="addToWishlist(5)" 2796 aria-label="Zur Wunschliste hinzufügen Digital-Upgrade " 2797 type="button" 2798 class="btn p-2 rounded-full" 2799 data-addto="wishlist" 2800> 2801 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><path d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"/></svg> 2802</button> 2803 </div> 2804 </div> 2805 </div> 2806</form> 2807 </div> 2808 <div class="flex flex-col"> 2809 2810<form method="post" 2811 action="https://shop.hk-verlag.de/de/checkout/cart/add/uenc/%25uenc%25/product/4/" 2812 class="item product product-item product_addtocart_form card card-interactive grow flex flex-col w-full " 2813 data-sku="GZ26HP-12" 2814 > 2815 <input name="form_key" type="hidden" value="J80ZjYOFy6hnDq7j" /> <input type="hidden" name="product" value="4"> 2816 <a href="https://shop.hk-verlag.de/de/kombiabo" 2817 title="Kombiabo" 2818 class="product photo product-item-photo block mx-auto mb-3 " 2819 tabindex="-1" 2820 > 2821 <img 2822 src="https://shop.hk-verlag.de/media/catalog/product/cache/2765542505660baab28ecd555e27366e/g/e/gefluegelzeitung-1764330678.jpg" 2823 width="240" 2824 height="300" 2825 alt="Kombiabo" 2826 class="product-image-photo" 2827 loading="lazy" 2828 x-data="initProductItemImage" 2829 @update-gallery-4.window="updateImage" 2830 > 2831 </a> 2832 <div class="product-info flex flex-col grow "> 2833 <div class="mt-2 mb-1 items-center justify-center font-semibold text-lg text-center "> 2834 <a 2835 class="product-item-link" 2836 href="https://shop.hk-verlag.de/de/kombiabo" 2837 > 2838 Kombiabo </a> 2839 </div> 2840 2841 <div class="py-1 mx-auto "> 2842 </div> 2843 2844 2845 2846 2847 <div class="pt-1" 2848 x-data="initPriceBox()" 2849 x-defer="intersect" 2850 @update-prices-4.window="updatePrice($event.detail);" 2851 > 2852 <div class="price-box price-final_price" data-role="priceBox" data-product-id="4" data-price-box="product-id-4"> 2853 <span
2854 x-data x-id="['product\u002Dprice\u002D4']" class="price-container price-final_price tax weee" 2855 > 2856 <span :id="$id('product\u002Dprice\u002D4')" data-price-amount="127.5" 2857 data-price-type="finalPrice" 2858 class="price-wrapper " 2859 ><span class="price">127,50 €</span></span> 2860 </span> 2861 2862</div> </div> 2863 2864 <div class="mt-auto pt-3 flex flex-wrap items-center gap-y-4 gap-x-2 2865 "> 2866 <button 2867 class="w-auto btn btn-primary justify-center text-sm mr-auto" 2868 title="In den Warenkorb Kombiabo" 2869 aria-label="In den Warenkorb Kombiabo" 2870 data-addto="cart" 2871 > 2872 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><circle cx="8" cy="21" r="1"/><circle cx="19" cy="21" r="1"/><path d="M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12"/></svg> 2873 <span class="inline md:hidden lg:inline"> 2874 In den Warenkorb </span> 2875 </button> 2876 2877 <div class="flex flex-wrap gap-2"> 2878 2879<button x-data="initWishlist()" 2880 x-defer="intersect" 2881 @click.prevent="addToWishlist(4)" 2882 aria-label="Zur Wunschliste hinzufügen Kombiabo" 2883 type="button" 2884 class="btn p-2 rounded-full" 2885 data-addto="wishlist" 2886> 2887 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><path d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"/></svg> 2888</button> 2889 </div> 2890 </div> 2891 </div> 2892</form> 2893 </div> 2894 <div class="flex flex-col"> 2895 2896<form method="post" 2897 action="https://shop.hk-verlag.de/de/checkout/cart/add/uenc/%25uenc%25/product/3/" 2898 class="item product product-item product_addtocart_form card card-interactive grow flex flex-col w-full " 2899 data-sku="GZ26DMHP-11" 2900 > 2901 <input name="form_key" type="hidden" value="J80ZjYOFy6hnDq7j" /> <input type="hidden" name="product" value="3"> 2902 <a href="https://shop.hk-verlag.de/de/jahresabo-e-paper-gefluegelzeitung" 2903 title="Jahresabo E-Paper" 2904 class="product photo product-item-photo block mx-auto mb-3 " 2905 tabindex="-1" 2906 > 2907 <img 2908 src="https://shop.hk-verlag.de/media/catalog/product/cache/2765542505660baab28ecd555e27366e/g/e/gefluegelzeitung_digital-1764330679.png" 2909 width="240" 2910 height="300" 2911 alt="Jahresabo E-Paper" 2912 class="product-image-photo" 2913 loading="lazy" 2914 x-data="initProductItemImage" 2915 @update-gallery-3.window="updateImage" 2916 > 2917 </a> 2918 <div class="product-info flex flex-col grow "> 2919 <div class="mt-2 mb-1 items-center justify-center font-semibold text-lg text-center "> 2920 <a 2921 class="product-item-link" 2922 href="https://shop.hk-verlag.de/de/jahresabo-e-paper-gefluegelzeitung" 2923 > 2924 Jahresabo E-Paper </a> 2925 </div> 2926 2927 <div class="py-1 mx-auto "> 2928 </div> 2929 2930 2931 2932 2933 <div class="pt-1" 2934 x-data="initPriceBox()" 2935 x-defer="intersect" 2936 @update-prices-3.window="updatePrice($event.detail);" 2937 > 2938 <div class="price-box price-final_price" data-role="priceBox" data-product-id="3" data-price-box="product-id-3"> 2939 <span
2940 x-data x-id="['product\u002Dprice\u002D3']" class="price-container price-final_price tax weee" 2941 > 2942 <span :id="$id('product\u002Dprice\u002D3')" data-price-amount="72.99" 2943 data-price-type="finalPrice" 2944 class="price-wrapper " 2945 ><span class="price">72,99 €</span></span> 2946 </span> 2947 2948</div> </div> 2949 2950 <div class="mt-auto pt-3 flex flex-wrap items-center gap-y-4 gap-x-2 2951 "> 2952 <button 2953 class="w-auto btn btn-primary justify-center text-sm mr-auto" 2954 title="In den Warenkorb Jahresabo E-Paper" 2955 aria-label="In den Warenkorb Jahresabo E-Paper" 2956 data-addto="cart" 2957 > 2958 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><circle cx="8" cy="21" r="1"/><circle cx="19" cy="21" r="1"/><path d="M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12"/></svg> 2959 <span class="inline md:hidden lg:inline"> 2960 In den Warenkorb </span> 2961 </button> 2962 2963 <div class="flex flex-wrap gap-2"> 2964 2965<button x-data="initWishlist()" 2966 x-defer="intersect" 2967 @click.prevent="addToWishlist(3)" 2968 aria-label="Zur Wunschliste hinzufügen Jahresabo E-Paper" 2969 type="button" 2970 class="btn p-2 rounded-full" 2971 data-addto="wishlist" 2972> 2973 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><path d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"/></svg> 2974</button> 2975 </div> 2976 </div> 2977 </div> 2978</form> 2979 </div> 2980 <div class="flex flex-col"> 2981 2982<form method="post" 2983 action="https://shop.hk-verlag.de/de/checkout/cart/add/uenc/%25uenc%25/product/1/" 2984 class="item product product-item product_addtocart_form card card-interactive grow flex flex-col w-full " 2985 data-sku="GZ26HP-11" 2986 > 2987 <input name="form_key" type="hidden" value="J80ZjYOFy6hnDq7j" /> <input type="hidden" name="product" value="1"> 2988 <a href="https://shop.hk-verlag.de/de/jahresabo-print" 2989 title="Jahresabo Print" 2990 class="product photo product-item-photo block mx-auto mb-3 " 2991 tabindex="-1" 2992 > 2993 <img 2994 src="https://shop.hk-verlag.de/media/catalog/product/cache/2765542505660baab28ecd555e27366e/g/e/gefluegelzeitung-1764330678.jpg" 2995 width="240" 2996 height="300" 2997 alt="Jahresabo Print" 2998 class="product-image-photo" 2999 loading="lazy" 3000 x-data="initProductItemImage" 3001 @update-gallery-1.window="updateImage" 3002 > 3003 </a> 3004 <div class="product-info flex flex-col grow "> 3005 <div class="mt-2 mb-1 items-center justify-center font-semibold text-lg text-center "> 3006 <a 3007 class="product-item-link" 3008 href="https://shop.hk-verlag.de/de/jahresabo-print" 3009 > 3010 Jahresabo Print </a> 3011 </div> 3012 3013 <div class="py-1 mx-auto "> 3014 </div> 3015 3016 3017 3018 3019 <div class="pt-1" 3020 x-data="initPriceBox()" 3021 x-defer="intersect" 3022 @update-prices-1.window="updatePrice($event.detail);" 3023 > 3024 <div class="price-box price-final_price" data-role="priceBox" data-product-id="1" data-price-box="product-id-1"> 3025 <span
3026 x-data x-id="['product\u002Dprice\u002D1']" class="price-container price-final_price tax weee" 3027 > 3028 <span :id="$id('product\u002Dprice\u002D1')" data-price-amount="109.5" 3029 data-price-type="finalPrice" 3030 class="price-wrapper " 3031 ><span class="price">109,50 €</span></span> 3032 </span> 3033 3034</div> </div> 3035 3036 <div class="mt-auto pt-3 flex flex-wrap items-center gap-y-4 gap-x-2 3037 "> 3038 <button 3039 class="w-auto btn btn-primary justify-center text-sm mr-auto" 3040 title="In den Warenkorb Jahresabo Print" 3041 aria-label="In den Warenkorb Jahresabo Print" 3042 data-addto="cart" 3043 > 3044 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><circle cx="8" cy="21" r="1"/><circle cx="19" cy="21" r="1"/><path d="M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12"/></svg> 3045 <span class="inline md:hidden lg:inline"> 3046 In den Warenkorb </span> 3047 </button> 3048 3049 <div class="flex flex-wrap gap-2"> 3050 3051<button x-data="initWishlist()" 3052 x-defer="intersect" 3053 @click.prevent="addToWishlist(1)" 3054 aria-label="Zur Wunschliste hinzufügen Jahresabo Print" 3055 type="button" 3056 class="btn p-2 rounded-full" 3057 data-addto="wishlist" 3058> 3059 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true"><path d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"/></svg> 3060</button> 3061 </div> 3062 </div> 3063 </div> 3064</form> 3065 </div> 3066 </div> 3067 3068<div data-page-builder-slider-nav class="flex justify-between items-center gap-2"> 3069 <button 3070 class="btn btn-secondary p-2" 3071 aria-label="Previous Slide" 3072 data-prev 3073 disabled 3074 ><svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" class="rtl:-rotate-180" aria-hidden="true"><path d="m12 19-7-7 7-7M19 12H5"/></svg> 3075</button> 3076 <div class="snap-pager" data-init-pager></div> 3077 <button 3078 class="btn btn-secondary p-2" 3079 aria-label="Next Slide" 3080 data-next 3081 disabled 3082 ><svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" class="rtl:-rotate-180" aria-hidden="true"><path d="M5 12h14M12 5l7 7-7 7"/></svg> 3083</button> 3084</div> 3085 <span id="product_productslist_0-slider-end" tabindex="-1"></span> 3086 </section></div></div></div></div></div></main><footer class="page-footer"><div class="footer content"> 3087<section class="video-banner container mx-auto px-4 py-6" 3088 x-data="{ isVisible: false, isMobile: window.innerWidth < 768 }" 3089 x-intersect:enter="isVisible = true"> 3090 <a href="https://www.dlv-shop.de/" target="_blank" rel="noopener"> 3091 <div class="relative w-full overflow-hidden rounded-lg aspect-[375/175] md:aspect-[1488/300]"> 3092 3093 <!-- Loading Background --> 3094 <div class="absolute inset-0 bg-gray-300 animate-pulse"></div> 3095 3096 <!-- Desktop Video --> 3097 <video 3098 class="hidden md:block w-full h-full object-cover relative" 3099 muted 3100 loop 3101 playsinline 3102 autoplay 3103 preload="none" 3104 :src="isVisible && !isMobile ? 'https://shop.hk-verlag.de/static/version1787125028/frontend/DieMayrei/hyva_child/de_DE/videos/dlv_Shop_AD_Banner_HK_1488x300.mp4' : ''"> 3105 </video> 3106 3107 <!-- Mobile Video --> 3108 <video 3109 class="md:hidden w-full h-full object-cover relative" 3110 muted 3111 loop 3112 playsinline 3113 autoplay 3114 preload="none" 3115 :src="isVisible && isMobile ? 'https://shop.hk-verlag.de/static/version1787125028/frontend/DieMayrei/hyva_child/de_DE/videos/dlv_Shop_AD_Banner_HK_375x175.mp4' : ''"> 3116 </video> 3117 </div> 3118 </a> 3119</section><div class="bg-gray-100 border-t border-gray-300 pb-16"> 3120 <div class="container py-8"> 3121 <div class="flex flex-wrap gap-y-16"> 3122 <div class="w-full grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-4 gap-8"> 3123 <nav aria-label="Company Menu"> 3124 <h2 class="text-md leading-5 font-semibold tracking-wider up
3124percase"> 3125 HK-Verlag 3126 </h2> 3127 <ul class="mt-4 space-y-2"> 3128 3129 <li> 3130 <a href="https://shop.hk-verlag.de/de/kundenservice/" class="text-base leading-6"> 3131 Kundenservice </a> 3132 </li> 3133 <li> 3134 <a href="https://shop.hk-verlag.de/de/versand-und-zahlung/" class="text-base leading-6"> 3135 Versand und Zahlung </a> 3136 </li> 3137 <li> 3138 <a href="https://www.hk-verlag.de/agb/" class="text-base leading-6"> 3139 AGB </a> 3140 </li> 3141 <li> 3142 <a href="https://www.hk-verlag.de/impressum/" class="text-base leading-6"> 3143 Impressum </a> 3144 </li> 3145 <li> 3146 <a href="https://www.hk-verlag.de/datenschutz/" class="text-base leading-6"> 3147 Datenschutz </a> 3148 </li> 3149 <li> 3150 <a href="https://www.hk-verlag.de/widerrufsrecht/" class="text-base leading-6"> 3151 Widerrufsrecht </a> 3152 </li> 3153 </ul> 3154 </nav> 3155 <nav aria-label="Legal Menu"> 3156 <h2 class="text-md leading-5 font-semibold tracking-wider uppercase"> 3157 Navigation 3158 </h2> 3159 <ul class="mt-4 space-y-2"> 3160 <li> 3161 <a href="https://shop.hk-verlag.de/de/geflugelzeitung" class="text-base leading-6"> 3162 Geflügelzeitung </a> 3163 </li> 3164 <li> 3165 <a href="https://shop.hk-verlag.de/de/kaninchenzeitung" class="text-base leading-6"> 3166 Kaninchenzeitung </a> 3167 </li> 3168 </ul> 3169 </nav> 3170 <diV class="col-span-2"> 3171 <div class="flex flex-col justify-between w-full"> 3172 <div> 3173 <h2 class="text-md leading-5 font-semibold tracking-wider uppercase"> 3174 Unser Kundenservice </h2> 3175 <p class="mt-4 text-sm text-gray-700"> 3176 Sie haben noch Fragen? Unser Kundenservice hilft telefonisch oder per E-Mail weiter. </p> 3177 <p class="mt-2 text-sm text-gray-700"> 3178 Sie erreichen uns während unserer Geschäftszeiten von: <span class="mt-2 font-semibold text-sm text-gray-900"> 3179 Montag – Freitag: 07:30 – 18:00 Uhr </span> 3180 </p> 3181 </div> 3182 <div class="mt-6 grid grid-cols-1 gap-2 md:grid-cols-2"> 3183 <a href="/kundenservice" class="p-2 w-full flex items-center justify-center gap-2 text-center text-white font-semibold text-xs tracking-wide uppercase py-3 rounded-lg bg-primary hover:bg-primary-lighter transition duration-300 ease-in-out"> 3184 <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-person-vcard-fill" viewBox="0 0 16 16"> 3185 <path d="M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2zm9 1.5a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 0-1h-4a.5.5 0 0 0-.5.5M9 8a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 0-1h-4A.5.5 0 0 0 9 8m1 2.5a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 0-1h-3a.5.5 0 0 0-.5.5m-1 2C9 10.567 7.21 9 5 9c-2.086 0-3.8 1.398-3.984 3.181A1 1 0 0 0 2 13h6.96q.04-.245.04-.5M7 6a2 2 0 1 0-4 0 2 2 0 0 0 4 0" /> 3186 </svg> 3187 Übersicht </a> 3188 <a href="/widerrufserklaerung" class="p-2 w-full flex items-center justify-center gap-2 text-center text-white font-semibold text-xs tracking-wide uppercase py-3 rounded-lg bg-primary hover:bg-primary-lighter transition duration-300 ease-in-out"> 3189 <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-90deg-left" viewBox="0 0 16 16"> 3190 <path fill-rule="evenodd" d="M1.146 4.854a.5.5 0 0 1 0-.708l4-4a.5.5 0 1 1 .708.708
3190L2.707 4H12.5A2.5 2.5 0 0 1 15 6.5v8a.5.5 0 0 1-1 0v-8A1.5 1.5 0 0 0 12.5 5H2.707l3.147 3.146a.5.5 0 1 1-.708.708z"/> 3191 </svg> 3192 Widerruf </a> 3193 <a href="tel:+493029397447" class="p-2 w-full flex items-center justify-center gap-2 text-center text-white font-semibold text-xs tracking-wide uppercase py-3 rounded-lg bg-secondary hover:bg-secondary-lighter transition duration-300 ease-in-out"> 3194 <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-telephone-fill" viewBox="0 0 16 16"> 3195 <path fill-rule="evenodd" d="M1.885.511a1.745 1.745 0 0 1 2.61.163L6.29 2.98c.329.423.445.974.315 1.494l-.547 2.19a.68.68 0 0 0 .178.643l2.457 2.457a.68.68 0 0 0 .644.178l2.189-.547a1.75 1.75 0 0 1 1.494.315l2.306 1.794c.829.645.905 1.87.163 2.611l-1.034 1.034c-.74.74-1.846 1.065-2.877.702a18.6 18.6 0 0 1-7.01-4.42 18.6 18.6 0 0 1-4.42-7.009c-.362-1.03-.037-2.137.703-2.877z" /> 3196 </svg> 3197 +49 30 293974-47 </a> 3198 <a href="mailto:#" class="p-2 w-full flex items-center justify-center gap-2 text-center text-white font-semibold text-xs tracking-wide uppercase py-3 rounded-lg bg-secondary hover:bg-secondary-lighter transition duration-300 ease-in-out"> 3199 <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-envelope-at-fill" viewBox="0 0 16 16"> 3200 <path d="M2 2A2 2 0 0 0 .05 3.555L8 8.414l7.95-4.859A2 2 0 0 0 14 2zm-2 9.8V4.698l5.803 3.546zm6.761-2.97-6.57 4.026A2 2 0 0 0 2 14h6.256A4.5 4.5 0 0 1 8 12.5a4.49 4.49 0 0 1 1.606-3.446l-.367-.225L8 9.586zM16 9.671V4.697l-5.803 3.546.338.208A4.5 4.5 0 0 1 12.5 8c1.414 0 2.675.652 3.5 1.671" /> 3201 <path d="M15.834 12.244c0 1.168-.577 2.025-1.587 2.025-.503 0-1.002-.228-1.12-.648h-.043c-.118.416-.543.643-1.015.643-.77 0-1.259-.542-1.259-1.434v-.529c0-.844.481-1.4 1.26-1.4.585 0 .87.333.953.63h.03v-.568h.905v2.19c0 .272.18.42.411.42.315 0 .639-.415.639-1.39v-.118c0-1.277-.95-2.326-2.484-2.326h-.04c-1.582 0-2.64 1.067-2.64 2.724v.157c0 1.867 1.237 2.654 2.57 2.654h.045c.507 0 .935-.07 1.18-.18v.731c-.219.1-.643.175-1.237.175h-.044C10.438 16 9 14.82 9 12.646v-.214C9 10.36 10.421 9 12.485 9h.035c2.12 0 3.314 1.43 3.314 3.034zm-4.04.21v.227c0 .586.227.8.581.8.31 0 .564-.17.564-.743v-.367c0-.516-.275-.708-.572-.708-.346 0-.573.245-.573.791" /> 3202 </svg> 3203 [email protected] </a> 3204 </div> 3205</div> 3206 </diV> 3207 </div> 3208 </div> 3209 </div> 3210 <div class="bg-surface border-t border-b border-gray-300"> 3211 <div class="container py-6 flex items-center sm:flex-row flex-col"> 3212 <a href="https://hyva.io" class="text-xl font-medium">HK Verlag</a> 3213 <p><small class="text-sm text-gray-800 sm:ml-6 sm:mt-0 mt-4"> 3214 © 2026 - HK Hobby- und Kleintierzüchter Verlagsgesellschaft mbH & Co. KG 3215</small></p> 3216 </div> 3217 </div> 3218</div></div></footer>
3219<script> 3220 let SnapSlider = class { 3221 constructor(el, { 3222 labelSepparator = 'von', 3223 autoPager, 3224 groupPager 3225 } = {}) { 3226 this.el = el; 3227 this.track = this.el.querySelector("[data-track]"); 3228 if (!this.track) { 3229 console.warn( 3230 "No Slider track defined, reverting back to CSS slider.\nPlease create a wrapper for your slides with the attribute data-track", 3231 this.el 3232 ); 3233 return; 3234 } 3235 this.initialLoad = true; 3236 this.slides = []; 3237 this.inViewObserver; 3238 this.mutationObserver; 3239 this.resizeObserver; 3240 this.pager = this.el.querySelector("[data-pager]"); 3241 this.navBtns = Array.from( 3242 this.el.querySelectorAll("[data-next], [data-prev]") 3243 ); 3244 this.slideLabelSepparator = this.el.dataset.slideLabelSepparator || labelSepparator; 3245 this.useAutoPager = autoPager || this.el.hasAttribute("data-auto-pager") || false; 3246 this.useGroupPager = groupPager || this.el.hasAttribute("data-group-pager") || false; 3247 this.sliderLabel = this.el.hasAttribute("aria-label") && this.el.getAttribute("aria-label").toLowerCase().trim().replace(/[^a-z0-9_-]+/g, "-").replace(/^-+|-+$/g, ""); 3248 this.sliderId = this.el.id || this.sliderLabel || "slider"; 3249 this.markerIdName = "data-target-id"; 3250 this.pagerClasses = this.el.dataset.pagerClass || "snap-pager"; 3251 this.markerClasses = this.el.dataset.markerClass || "snap-marker"; 3252 this.init(); 3253 } 3254 init() { 3255 this.setupSlides(); 3256 this.setupNav(); 3257 if (this.useAutoPager) { 3258 this.createPager(); 3259 } else { 3260 this.setupPager(); 3261 } 3262 this.setupObservers(); 3263 this.setupMutationObserver(); 3264 this.setupResizeObserver(); 3265 this.el.addEventListener("click", this.eventHandler.bind(this)); 3266 this.el.addEventListener("keydown", this.eventHandler.bind(this)); 3267 } 3268 destroy() { 3269 this.inViewObserver?.disconnect(); 3270 this.mutationObserver?.disconnect(); 3271 this.resizeObserver?.disconnect(); 3272 this.el.removeEventListener("click", this.eventHandler.bind(this)); 3273 this.el.removeEventListener("keydown", this.eventHandler.bind(this)); 3274 } 3275 roundUpIfGreaterThan(number, min = 8) { 3276 const decimalPart = number - Math.floor(number); 3277 return decimalPart >= min ? Math.ceil(number) : Math.floor(number); 3278 } 3279 getInViewItems() { 3280 const inViewSlides = this.track.querySelectorAll("[data-in-view]"); 3281 const firstInViewSlide = inViewSlides[0] || null; 3282 const lastInViewSlide = inViewSlides[inViewSlides.length - 1] || null; 3283 const isAtStart = firstInViewSlide === this.slides[0]; 3284 const isAtEnd = lastInViewSlide === this.slides[this.slides.length - 1]; 3285 return { 3286 inViewSlides, 3287 totalInViewSlides: inViewSlides.length, 3288 firstInViewSlide, 3289 lastInViewSlide, 3290 isAtStart, 3291 isAtEnd, 3292 hasNoOverflow: isAtStart && isAtEnd 3293 }; 3294 } 3295 groupPagerMarkers() { 3296 if (!this.pager || !this.useGroupPager) return; 3297 const totalVisibleSlides = this.roundUpIfGreaterThan( 3298 this.track.offsetWidth / this.slides[0].offsetWidth 3299 ); 3300 const markers = Array.from(this.pager.querySelectorAll("a, button")); 3301 markers.forEach((marker, index) => { 3302 marker.style.display = index % totalVisibleSlides === 0 ? null : "none"; 3303 }); 3304 } 3305 handleInView(entries) { 3306 entries.forEach((entry) => { 3307 const marker = this.pager && (this.pager.querySelector(`[href="#${entry.target.id}"]`) || this.pager.querySelector( 3308 `[${this.markerIdName}="${entry.target.id}"]` 3309 )); 3310 entry.target.toggleAttribute("data-in-view", entry.isIntersecting); 3311 entry.target.toggleAttribute("inert", !entry.isIntersecting); 3312 marker?.setAttribute("aria-current", entry.isIntersecting); 3313 marker?.setAttribute("tabindex", entry.isIntersecting ? "0" : "-1"); 3314 }); 3315 const { 3316 isAtStart, 3317 isAtEnd, 3318 hasNoOverflow 3319 } = this.getInViewItems(); 3320 this.navBtns.forEach((btn) => { 3321 if (btn.hasAttribute("data-next")) { 3322 btn.style.visibility = hasNoOverflow ? "hidden" : null; 3323 isAtEnd ? btn.setAttribute("disabled", "") : btn.removeAttribute("disabled"); 3324 } 3325 if (btn.hasAttribute("data-prev")) { 3326 btn.style.visibility = hasNoOverflow ? "hidden" : null; 3327 isAtStart ? btn.setAttribute("disabled", "") : btn.removeAttribute("disabled"); 3328 } 3329 }); 3330 if (this.pager) { 3331 this.pager.style.visibility = hasNoOverflow ? "hidden" : null; 3332 } 3333 if (!this.initialLoad) { 3334 this.el.dispatchEvent( 3335 new CustomEvent("slideChange", { 3336 detail: this.getInViewItems() 3337 }) 3338 ); 3339 } else { 3340 this.initialLoad = false;
3341 } 3342 if (document.activeElement.parentElement.hasAttribute("data-pager")) { 3343 const activeItems = this.pager.querySelectorAll('[tabindex="0"]'); 3344 if (activeItems.length) { 3345 activeItems[0].focus(); 3346 } 3347 } 3348 } 3349 getSlides() { 3350 if (!this.track) return []; 3351 return Array.from(this.track.children).filter( 3352 (child) => child.tagName.toLowerCase() !== "template" && child.tagName.toLowerCase() !== "script" 3353 ); 3354 } 3355 refreshSlides() { 3356 this.initialLoad = true; 3357 this.slides = this.getSlides(); 3358 this.setupSlides(); 3359 if (this.useAutoPager) { 3360 this.createPager(); 3361 } else { 3362 this.setupPager(); 3363 } 3364 this.groupPagerMarkers(); 3365 this.setupObservers(); 3366 } 3367 setupSlides() { 3368 this.slides = this.getSlides(); 3369 this.slides.forEach((slide, index) => { 3370 const totalSlides = this.slides.length; 3371 const currentSlide = index + 1; 3372 const existingLabel = slide.getAttribute("aria-label") || ""; 3373 const isImage = slide.tagName.toLowerCase() === "img" || slide.tagName.toLowerCase() === "picture"; 3374 const slideLabelTag = isImage ? "alt" : "aria-label"; 3375 const hasAutoLabel = existingLabel.startsWith( 3376 `${currentSlide} ${this.slideLabelSepparator} ` 3377 ); 3378 if (!slide.hasAttribute("id")) { 3379 slide.setAttribute( 3380 "id", 3381 `${this.sliderId}-item-${currentSlide}` 3382 ); 3383 } 3384 if (!slide.hasAttribute(slideLabelTag) || slide.getAttribute(slideLabelTag) === "" || hasAutoLabel) { 3385 slide.setAttribute( 3386 slideLabelTag, 3387 `${currentSlide} ${this.slideLabelSepparator} ${totalSlides}` 3388 ); 3389 } 3390 if (slide.tagName.toLowerCase() === "div" && !slide.hasAttribute("role")) { 3391 slide.setAttribute("role", "group"); 3392 } 3393 if (this.pager && !isImage) { 3394 slide.setAttribute("role", "tabpanel"); 3395 } 3396 if (slide.getAttribute("role") === "group") { 3397 slide.setAttribute("aria-roledescription", "item"); 3398 } 3399 }); 3400 if (!this.el.hasAttribute("role") && this.el.tagName !== "SECTION") { 3401 this.el.setAttribute("role", "region"); 3402 } 3403 if (!this.el.hasAttribute("aria-roledescription")) { 3404 this.el.setAttribute("aria-roledescription", "carousel"); 3405 } 3406 this.track.setAttribute("tabindex", 0); 3407 this.track.setAttribute("aria-live", "polite"); 3408 } 3409 setupNav() { 3410 this.navBtns.forEach((btn) => { 3411 btn.setAttribute("disabled", ""); 3412 btn.removeAttribute("hidden"); 3413 btn.classList.remove("invisible"); 3414 btn.style.visibility = null; 3415 }); 3416 } 3417 createPager() { 3418 const newPager = document.createElement("nav"); 3419 newPager.setAttribute("data-pager", ""); 3420 newPager.setAttribute("role", "tablist"); 3421 newPager.classList.add(...this.pagerClasses.split(" ")); 3422 this.slides.forEach((slide, index) => { 3423 const marker = document.createElement("button"); 3424 const slideId = slide.id || `${this.sliderId}-item-${index + 1}`; 3425 marker.setAttribute(this.markerIdName, slideId); 3426 marker.classList.add(...this.markerClasses.split(" ")); 3427 this.setupPagerMarker(marker, index); 3428 newPager.appendChild(marker); 3429 if (slide.tagName.toLowerCase() !== "img" && slide.tagName.toLowerCase() !== "picture") { 3430 slide.removeAttribute("aria-roledescription"); 3431 slide.setAttribute("role", "tabpanel"); 3432 } 3433 }); 3434 if (this.pager) { 3435 this.pager.setAttribute("role", "tablist"); 3436 this.pager.replaceChildren(...newPager.children); 3437 } else { 3438 this.track.after(newPager); 3439 this.pager = this.el.querySelector("[data-pager]"); 3440 } 3441 } 3442 setupPager() { 3443 if (!this.pager) return; 3444 this.pager.setAttribute("role", "tablist"); 3445 const items = Array.from(this.pager.querySelectorAll("a, button"));
3446 items.forEach((marker, index) => this.setupPagerMarker(marker, index)); 3447 } 3448 setupPagerMarker(marker, index) { 3449 const markerId = marker.getAttribute("href")?.slice(1) || marker.getAttribute(this.markerIdName); 3450 const slideId = markerId || `${this.sliderId}-item-${index + 1}`; 3451 if (!markerId) { 3452 marker.setAttribute(this.markerIdName, slideId); 3453 } 3454 marker.setAttribute("role", "tab"); 3455 marker.setAttribute("aria-controls", slideId); 3456 marker.setAttribute("aria-posinset", index + 1); 3457 marker.setAttribute("aria-setsize", this.slides.length); 3458 marker.setAttribute("tabindex", "-1"); 3459 if (!marker.hasAttribute("aria-label")) { 3460 marker.setAttribute("aria-label", `Slide ${index + 1}`); 3461 } 3462 } 3463 setupObservers() { 3464 if (this.inViewObserver) { 3465 this.inViewObserver.disconnect(); 3466 } 3467 this.inViewObserver = new IntersectionObserver( 3468 this.handleInView.bind(this), { 3469 root: this.track, 3470 threshold: 0.8 3471 } 3472 ); 3473 this.slides.forEach((slide) => this.inViewObserver.observe(slide)); 3474 } 3475 setupMutationObserver() { 3476 this.mutationObserver = new MutationObserver( 3477 this.refreshSlides.bind(this) 3478 ); 3479 this.mutationObserver.observe(this.track, { 3480 childList: true, 3481 subtree: false 3482 }); 3483 } 3484 setupResizeObserver() { 3485 this.resizeObserver = new ResizeObserver( 3486 this.groupPagerMarkers.bind(this) 3487 ); 3488 this.resizeObserver.observe(this.el); 3489 } 3490 goToSlideDir(dir = "next") { 3491 const { 3492 firstInViewSlide, 3493 lastInViewSlide 3494 } = this.getInViewItems(); 3495 const isPrev = dir === "prev"; 3496 let targetSlide = isPrev ? firstInViewSlide?.previousElementSibling : lastInViewSlide?.nextElementSibling; 3497 if (!targetSlide) return; 3498 if (targetSlide.tagName.toLowerCase() === "template") { 3499 targetSlide = isPrev ? targetSlide?.previousElementSibling : targetSlide?.nextElementSibling; 3500 } 3501 targetSlide.scrollIntoView({ block: "nearest", inline: isPrev ? "end" : "start" }); 3502 } 3503 pagerToSlide(event) { 3504 if (!event.target.closest("[data-pager]")) return; 3505 const marker = event.target.closest("a, button"); 3506 if (!marker) return; 3507 event.preventDefault(); 3508 const slideId = marker.getAttribute("href")?.slice(1) || marker.getAttribute(this.markerIdName); 3509 const targetSlide = this.track.querySelector(`#${slideId}`); 3510 targetSlide?.scrollIntoView({ block: "nearest", inline: "start" }); 3511 } 3512 eventHandler(event) { 3513 const target = event.target.closest( 3514 "[data-next], [data-prev], [data-pager]" 3515 ); 3516 if (!target) return; 3517 if (event.type === "click") { 3518 if (target.hasAttribute("data-next")) { 3519 this.goToSlideDir("next"); 3520 } else if (target.hasAttribute("data-prev")) { 3521 this.goToSlideDir("prev"); 3522 } else if (target.closest("[data-pager]")) { 3523 this.pagerToSlide(event); 3524 } 3525 } 3526 if (event.type === "keydown" && target.closest("[data-pager]")) { 3527 if (event.key === "ArrowRight") { 3528 this.goToSlideDir("next"); 3529 } else if (event.key === "ArrowLeft") { 3530 this.goToSlideDir("prev"); 3531 } 3532 } 3533 } 3534 }; 3535 3536 (() => { 3537 function alpineSnapSlider(Alpine) { 3538 Alpine.directive("snap-slider", (el, { 3539 modifiers 3540 }, { 3541 cleanup 3542 }) => { 3543 const autoPager = modifiers.includes("auto-pager");
3544 const groupPager = modifiers.includes("group-pager"); 3545 const slider = new SnapSlider(el, { 3546 autoPager, 3547 groupPager 3548 }); 3549 cleanup(() => { 3550 slider.destroy(); 3551 }); 3552 }); 3553 } 3554 3555 document.addEventListener("alpine:init", () => { 3556 window.Alpine.plugin(alpineSnapSlider); 3557 }); 3558 })(); 3559</script>
vendor: 1 bytes, line 3559
3559
3560<script> 3561 (() => { 3562 // src/dialog.js 3563 function dialog_default(Alpine) { 3564 Alpine.directive("htmldialog", fylgjaAlpineDialog); 3565 function fylgjaAlpineDialog(el, { expression, modifiers }, { evaluateLater, cleanup }) { 3566 const evaluate = expression.length ? evaluateLater(expression) : () => {}; 3567 const canEvaluate = expression.length > 0; 3568 const lockPageScroll = modifiers.includes("noscroll"); 3569 const closeBy = el.getAttribute("closeby") || modifierValue(modifiers, "closeby", "closerequest"); 3570 el.style.display = null; 3571 el.style.length === 0 && el.removeAttribute("style"); 3572 if (el._x_isShown) { 3573 open(); 3574 } 3575 const closeBySupported = (() => { 3576 return "closedBy" in HTMLDialogElement.prototype; 3577 })(); 3578 function scrollLock(use = true) { 3579 document.body.style.overflow = use ? "hidden" : ""; 3580 } 3581 function dialogSubmit(event) { 3582 if (event.target.getAttribute("method") === "dialog" || event.submitter?.getAttribute("formmethod") === "dialog") { 3583 event.preventDefault(); 3584 evaluate(); 3585 } 3586 } 3587 function escapeDialog(event) { 3588 if (event.key !== "Escape") return; 3589 event.preventDefault(); 3590 if (closeBy === "none") return; 3591 evaluate(); 3592 } 3593 function handleCloseByEvent(event) { 3594 if (event.target !== el) return; 3595 const rect = el.getBoundingClientRect(); 3596 const isInDialog = rect.top <= event.clientY && event.clientY <= rect.top + rect.height && rect.left <= event.clientX && event.clientX <= rect.left + rect.width; 3597 if (!isInDialog) { 3598 if (closeBy === "any") { 3599 if (closeBySupported) { 3600 event.preventDefault(); 3601 } 3602 evaluate(); 3603 } 3604 } 3605 } 3606 function handleCloseEvent() { 3607 evaluate(); 3608 } 3609 function open() { 3610 if (el.hasAttribute("open")) return; 3611 el.showModal(); 3612 scrollLock(lockPageScroll); 3613 } 3614 function close() { 3615 if (!el.hasAttribute("open")) return; 3616 el.close(); 3617 scrollLock(false); 3618 } 3619 el._x_doShow = () => open(); 3620 el._x_doHide = () => close(); 3621 el.addEventListener("keydown", escapeDialog); 3622 el.addEventListener("submit", dialogSubmit); 3623 el.addEventListener("click", handleCloseByEvent); 3624 el.addEventListener("cancel", handleCloseEvent); 3625 cleanup(() => { 3626 el.removeEventListener("keydown", escapeDialog); 3627 el.removeEventListener("submit", dialogSubmit); 3628 el.removeEventListener("click", handleCloseByEvent); 3629 el.removeEventListener("cancel", handleCloseEvent); 3630 scrollLock(false); 3631 }); 3632 } 3633 } 3634 function modifierValue(modifiers, key, fallback) { 3635 if (modifiers.indexOf(key) === -1) return fallback; 3636 const rawValue = modifiers[modifiers.indexOf(key) + 1]; 3637 if (!rawValue) return fallback; 3638 if (key === "closeby") { 3639 const allowedValues = ["auto", "none", "closerequest", "any"]; 3640 const options = allowedValues.join(", "); 3641 if (!allowedValues.includes(rawValue)) { 3642 console.warn( 3643 `"${rawValue}" is not one of the allowed values for closeby: ${options}` 3644 ); 3645 return fallback; 3646 } 3647 } 3648 return rawValue; 3649 } 3650 3651 // src/cdn.js 3652 document.addEventListener("alpine:init", () => { 3653 window.Alpine.plugin(dialog_default); 3654 }); 3655 })(); 3656</script>
vendor: 1 bytes, line 3656
3656
vendor: 2,348 bytes, lines 3657-3716
3657<script> 3658 (() => { 3659 function src_default(Alpine) { 3660 Alpine.directive("intersect", Alpine.skipDuringClone((el, { value, expression, modifiers }, { evaluateLater, cleanup }) => { 3661 let evaluate = evaluateLater(expression); 3662 let options = { 3663 rootMargin: getRootMargin(modifiers), 3664 threshold: getThreshold(modifiers) 3665 }; 3666 let observer = new IntersectionObserver((entries) => { 3667 entries.forEach((entry) => { 3668 if (entry.isIntersecting === (value === "leave")) 3669 return; 3670 evaluate(); 3671 modifiers.includes("once") && observer.disconnect(); 3672 }); 3673 }, options); 3674 observer.observe(el); 3675 cleanup(() => { 3676 observer.disconnect(); 3677 }); 3678 })); 3679 } 3680 function getThreshold(modifiers) { 3681 if (modifiers.includes("full")) 3682 return 0.99; 3683 if (modifiers.includes("half")) 3684 return 0.5; 3685 if (!modifiers.includes("threshold")) 3686 return 0; 3687 let threshold = modifiers[modifiers.indexOf("threshold") + 1]; 3688 if (threshold === "100") 3689 return 1; 3690 if (threshold === "0") 3691 return 0; 3692 return Number(`.${threshold}`); 3693 } 3694 function getLengthValue(rawValue) { 3695 let match = rawValue.match(/^(-?[0-9]+)(px|%)?$/); 3696 return match ? match[1] + (match[2] || "px") : void 0; 3697 } 3698 function getRootMargin(modifiers) { 3699 const key = "margin"; 3700 const fallback = "0px 0px 0px 0px"; 3701 const index = modifiers.indexOf(key); 3702 if (index === -1) 3703 return fallback; 3704 let values = []; 3705 for (let i = 1; i < 5; i++) { 3706 values.push(getLengthValue(modifiers[index + i] || "")); 3707 } 3708 values = values.filter((v) => v !== void 0); 3709 return values.length ? values.join(" ").trim() : fallback; 3710 } 3711 3712 document.addEventListener("alpine:init", () => { 3713 window.Alpine.plugin(src_default); 3714 }); 3715 })(); 3716</script>
vendor: 1 bytes, line 3716
3716
3717<script> 3718 for (const [selector, deferUntil] of Object.entries({".product-slider section[x-data]:not([x-data] [x-data])":"intersect",".product-info [x-data]:not([x-data] [x-data])":"intersect","#filters-content [x-data]:not([x-data] [x-data])":"intersect","#review_form":"intersect","section[x-data^=initRecentlyViewedProductsComponent]":"intersect","div[x-data^=initBundleOptions]":"intersect","#product_addtocart_form [x-data]:not([x-data] [x-data])":"intersect","#notice-cookie-block":"idle"})) { 3719 document.querySelectorAll(selector).forEach(el => el.setAttribute('x-defer', `${deferUntil}`)); 3720 } 3721</script>
vendor: 1 bytes, line 3721
3721
3722<script> 3723 (function () { 3724 "use strict"; 3725 3726 const hasAlpine = new Promise(resolve => { 3727 window.addEventListener('alpine:initialized', resolve, {once: true, passive: true}); 3728 }); 3729 3730 const hasInteract = new Promise(resolve => { 3731 (events => { 3732 const onInteract = () => { 3733 resolve(); 3734 events.forEach(type => window.removeEventListener(type, onInteract)); 3735 } 3736 events.forEach(type => window.addEventListener(type, onInteract, {once: true, passive: true})) 3737 })(['touchstart', 'mouseover', 'wheel', 'scroll', 'keydown']) 3738 }); 3739 3740 const onIntersect = (el) => { 3741 return new Promise(resolve => { 3742 const observer = new IntersectionObserver(entries => { 3743 for (const entry of entries) { 3744 if (entry.isIntersecting) { 3745 observer.disconnect() 3746 resolve(); 3747 } 3748 } 3749 }, {}); 3750 observer.observe(el); 3751 }); 3752 } 3753 3754 function runComponent(el) { 3755 hasAlpine.then(() => { 3756 el.removeAttribute('x-ignore'); 3757 queueMicrotask(() => Alpine.initTree(el)); 3758 }); 3759 } 3760 3761 function initDeferredComponents() { 3762 document.querySelectorAll('[x-data][x-defer]').forEach(el => { 3763 el.setAttribute('x-ignore', ''); 3764 const deferUntil = (el.getAttribute('x-defer') || '').trim(); 3765 switch (deferUntil) { 3766 case 'interact': 3767 hasInteract.then(() => runComponent(el)); 3768 break; 3769 case 'intersect': 3770 onIntersect(el).then(() => runComponent(el)) 3771 break; 3772 case 'idle': 3773 window.requestIdleCallback 3774 ? window.requestIdleCallback(() => runComponent(el), {timeout: 4000}) 3775 : setTimeout(() => runComponent(el), 4000); 3776 break; 3777 case 'eager': 3778 runComponent(el); 3779 break; 3780 default: 3781 if (deferUntil.startsWith('event:') && deferUntil.length > 6) { 3782 window.addEventListener(deferUntil.substring(6), () => runComponent(el), {once: true, passive: true}); 3783 } 3784 } 3785 }); 3786 } 3787 3788 window.addEventListener('alpine:init', initDeferredComponents, {once: true, passive: true}); 3789 })() 3790</script>
3790 3791
3792<script type="module" 3793 src="https://shop.hk-verlag.de/static/version1787125028/frontend/DieMayrei/hyva_child/de_DE/Hyva_Theme/js/alpine3.min.js" 3794 defer 3795 crossorigin 3796></script>
vendor: 1 bytes, line 3796
3796
3797<script> 3798 function dispatchMessages(messages, hideAfter) { 3799 const messagesEvent = new CustomEvent("messages-loaded", { 3800 detail: { 3801 messages: messages, 3802 hideAfter: hideAfter 3803 } 3804 }); 3805 window.dispatchEvent(messagesEvent); 3806 } 3807 3808 if (typeof hyva === 'undefined' || (!hyva.getBrowserStorage || !hyva.getCookie || !hyva.setCookie)) { 3809 console.warn("Hyvä helpers are not loaded yet. Make sure they are included before this script"); 3810 } 3811 3812 (function( hyva, undefined ) { 3813 3814 hyva.initFormKey = () => { 3815 const inputSelector = 'input[name="form_key"]', 3816 formKey = hyva.getFormKey(); 3817 3818 Array.from(document.querySelectorAll(inputSelector)).map(function (input) { 3819 input.value = formKey 3820 }); 3821 } 3822 3823 hyva.initMessages = () => { 3824 try { 3825 const messages = hyva.getCookie('mage-messages'); 3826 window.mageMessages = messages ? JSON.parse(decodeURIComponent(messages).replace(/\+/g, ' ')) : []; 3827 3828 dispatchMessages(window.mageMessages); 3829 3830 // empty `mage-messages` cookie 3831 const skipSetDomain = true; 3832 hyva.setCookie('mage-messages','', -1, skipSetDomain); 3833 3834 } catch (error) { 3835 console.warn('Error parsing Cookie Messages:', error); 3836 } 3837 } 3838 3839 window.addEventListener('DOMContentLoaded', hyva.initFormKey); 3840 hyva.alpineInitialized(hyva.initMessages) 3841 3842 }( window.hyva = window.hyva || {} )); 3843</script>
vendor: 1 bytes, line 3843
3843
3844<script> 3845 { 3846 const private_content_key = 'mage-cache-storage'; 3847 const private_content_expire_key = 'mage-cache-timeout'; 3848 const private_content_version_key = 'private_content_version'; 3849 const section_data_ids_key = 'section_data_ids'; 3850 const mage_cache_session_id_key = 'mage-cache-sessid'; 3851 const last_visited_store_key = 'last_visited_store'; 3852 3853 const ttl = 3600; 3854 3855 if (typeof hyva === 'undefined' || (!hyva.getBrowserStorage || !hyva.getCookie || !hyva.setCookie)) { 3856 console.warn("Hyvä helpers are not loaded yet. Make sure they are included before this script"); 3857 } 3858 3859 function loadSectionData () { 3860 const browserStorage = hyva.getBrowserStorage(); 3861 if (!browserStorage) { 3862 typeof window.dispatchMessages !== "undefined" && window.dispatchMessages( 3863 [{ 3864 type: "warning", 3865 text: "Bitte aktivieren Sie LocalStorage in Ihrem Browser." 3866 }] 3867 ); 3868 return; 3869 } 3870 try { 3871 let isInvalid = false; 3872 3873 if (hyva.getCookie(last_visited_store_key) !== CURRENT_STORE_CODE) { 3874 isInvalid = true; 3875 } 3876 hyva.setCookie(last_visited_store_key, CURRENT_STORE_CODE, false, false); 3877 3878 if (!hyva.getCookie(mage_cache_session_id_key)) { 3879 isInvalid = true; 3880 browserStorage.removeItem(private_content_key); 3881 const skipSetDomain = true; 3882 const days = false; 3883 hyva.setCookie(mage_cache_session_id_key, true, days, skipSetDomain) 3884 } 3885 3886 const cookieVersion = hyva.getCookie(private_content_version_key); 3887 const storageVersion = browserStorage.getItem(private_content_version_key); 3888 3889 if (cookieVersion && !storageVersion || cookieVersion !== storageVersion) { 3890 isInvalid = true; 3891 } 3892 3893 const privateContentExpires = browserStorage.getItem(private_content_expire_key); 3894 if (privateContentExpires && new Date(privateContentExpires) < new Date()) { 3895 browserStorage.removeItem(private_content_key); 3896 } 3897 3898 if (isInvalid && cookieVersion) { 3899 fetchPrivateContent([]); 3900 } else if (cookieVersion && storageVersion && cookieVersion === storageVersion) { 3901 const privateContent = JSON.parse(browserStorage.getItem(private_content_key)); 3902 if ( 3903 privateContent && 3904 privateContentExpires && 3905 privateContent.cart && 3906 privateContent.customer 3907 ) { 3908 dispatchPrivateContent(privateContent); 3909 } else { 3910 fetchPrivateContent([]); 3911 } 3912 } else { 3913 if (document.getElementById('default-section-data')) { 3914 const privateContent = JSON.parse(document.getElementById('default-section-data').innerText.trim()); 3915 dispatchPrivateContent(privateContent); 3916 } else { 3917 dispatchPrivateContent({}); 3918 } 3919 } 3920 3921 } catch (error) { 3922 console.warn('Error retrieving Private Content:', error); 3923 } 3924 } 3925 3926 hyva.alpineInitialized(loadSectionData) 3927 window.addEventListener('reload-customer-section-data', loadSectionData); 3928 3929 window.processSectionDataBeforeDispatch = window.processSectionDataBeforeDispatch || (data => data); 3930 3931 function dispatchPrivateContent(data) { 3932 3933 const privateContentEvent = new CustomEvent("private-content-loaded", { 3934 detail: { 3935 data: window.processSectionDataBeforeDispatch(data) 3936 } 3937 }); 3938 window.dispatchEvent(privateContentEvent); 3939 } 3940 3941 function fetchPrivateContent(sections) { 3942 fetch(`${BASE_URL}customer/section/load/?sections=${encodeURIComponent(sections.join(','))}`, { 3943 method: 'GET', 3944 headers: { 3945 'Content-Type': 'application/json', 3946 'X-Requested-With': 'XMLHttpRequest' 3947 } 3948 }) 3949 .then(response => response.ok && response.json()) 3950 .then( 3951 data => { 3952 if (data) { 3953 try { 3954 const browserStorage = hyva.getBrowserStorage(); 3955 3956 // merge new data preserving non-invalidated sections 3957 const oldSectionData = JSON.parse(browserStorage.getItem(private_content_key) || '{}') || {}; 3958 3959 if ((! data.cart || ! data.cart.cartId) && oldSectionData['checkout-data']) { 3960 delete oldSectionData['checkout-data']; 3961 } 3962 const newSectionData = Object.assign(oldSectionData, data); 3963 3964 dispatchPrivateContent(newSectionData); 3965 3966 // don't persist messages, they've been dispatched already 3967 if (newSectionData.messages && newSectionData.messages.messages ) { 3968 newSectionData.messages.messages = []; 3969 } 3970 3971 browserStorage.setItem(private_content_key, JSON.stringify(newSectionData)); 3972 3973 const expiresAt = new Date(Date.now() + (ttl * 1000)).toISOString(); 3974 browserStorage.setItem(private_content_expire_key, expiresAt); 3975 3976 const newCookieVersion = hyva.getCookie(private_content_version_key); 3977 browserStorage.setItem(private_content_version_key, newCookieVersion); 3978 3979 // We don't need the section_data_ids in Hyvä, but we store them for compatibility 3980 // with Luma Fallback. Otherwise, not all sections are loaded in Luma Checkout 3981 hyva.setCookie( 3982 section_data_ids_key, 3983 JSON.stringify( 3984 Object.keys(data).reduce((sectionDataIds, sectionKey) => { 3985 sectionDataIds[sectionKey] = data[sectionKey]['data_id']; 3986 return sectionDataIds; 3987 }, {}) 3988 ), 3989 false, 3990 true 3991 ); 3992 } catch (error) { 3993 console.warn("Couldn't store privateContent", error); 3994 } 3995 } 3996 } 3997 ); 3998 } 3999 } 4000</script>
vendor: 1 bytes, line 4000
4000
4001<script> 4002 (() => { 4003 document.addEventListener('submit', event => event.target.action = event.target.action.replace('%25uenc%25', hyva.getUenc())); 4004 })() 4005</script>
vendor: 1 bytes, line 4005
4005
4006<script> 4007 (events => { 4008 const dispatchUserInteractionEvent = () => { 4009 events.forEach(type => window.removeEventListener(type, dispatchUserInteractionEvent)) 4010 window.dispatchEvent(new Event('init-external-scripts')) 4011 }; 4012 events.forEach(type => window.addEventListener(type, dispatchUserInteractionEvent, {once: true, passive: true})) 4013 })(['touchstart', 'mousemove', 'wheel', 'scroll', 'keydown']) 4014</script>
vendor: 1 bytes, line 4014
4014
4015<script> 4016 function initWishlist() { 4017 return { 4018 addToWishlist(productId) { 4019 const formKey = hyva.getFormKey(); 4020 const postUrl = BASE_URL + 'wishlist/index/add/'; 4021 4022 fetch(postUrl, { 4023 "headers": { 4024 "content-type": "application/x-www-form-urlencoded; charset=UTF-8", 4025 }, 4026 "body": "form_key=" + formKey + "&product=" + productId + "&uenc=" + hyva.getUenc(), 4027 "method": "POST", 4028 "mode": "cors", 4029 "credentials": "include" 4030 }).then(function (response) { 4031 if (response.redirected) { 4032 window.location.href = response.url; 4033 } else if (response.ok) { 4034 return response.json(); 4035 } else { 4036 typeof window.dispatchMessages !== "undefined" && window.dispatchMessages( 4037 [{ 4038 type: "warning", 4039 text: "Der\u0020Artikel\u0020konnte\u0020nicht\u0020zur\u0020Wunschliste\u0020hinzugef\u00FCgt\u0020werden." 4040 }], 5000 4041 ); 4042 } 4043 }).then(function (response) { 4044 if (!response) { return } 4045 typeof window.dispatchMessages !== "undefined" && window.dispatchMessages( 4046 [{ 4047 type: (response.success) ? "success" : "error", 4048 text: (response.success) 4049 ? "Produkt\u0020wurde\u0020zu\u0020Ihrer\u0020Wunschliste\u0020hinzugef\u00FCgt." 4050 : response.error_message 4051 }], 5000 4052 ); 4053 const reloadCustomerDataEvent = new CustomEvent("reload-customer-section-data"); 4054 window.dispatchEvent(reloadCustomerDataEvent); 4055 }).catch(function (error) { 4056 typeof window.dispatchMessages !== "undefined" && window.dispatchMessages( 4057 [{ 4058 type: "error", 4059 text: error 4060 }], 5000 4061 ); 4062 }); 4063 } 4064 } 4065 } 4066</script>
vendor: 1 bytes, line 4066
4066
4067<script> 4068 function initProductItemImage() { 4069 return { 4070 updateImage() { 4071 const image = this.$event.detail.medium; 4072 if (!image) return; 4073 this.$el.src = image; 4074 } 4075 } 4076 } 4077 window.addEventListener('alpine:init', () => { 4078 Alpine.data('initProductItemImage', initProductItemImage); 4079 }, { once: true }); 4080</script>
vendor: 1 bytes, line 4080
4080
4081<script> 4082 (() => { 4083 const initSliderCarousel = (el) => { 4084 const sliderId = el.getAttribute('data-pb-style'); 4085 4086 const skipLink = document.createElement('a'); 4087 skipLink.setAttribute('href', `#${sliderId}-slider-end`); 4088 skipLink.classList.add('sr-only', 'focus:not-sr-only', 'focus:absolute', 'focus:p-2', 'focus:bg-white'); 4089 skipLink.innerText = 'Clicken,\u0020um\u0020das\u0020Karussell\u0020zu\u0020\u00FCberspringen'; 4090 4091 const skipLinkTarget = document.createElement('span'); 4092 skipLinkTarget.setAttribute('id', `${sliderId}-slider-end`); 4093 skipLinkTarget.setAttribute('tabindex', '-1'); 4094 4095 const track = document.createElement('div'); 4096 track.setAttribute('data-track', ''); 4097 track.classList.add('snap-track'); 4098 Array.from(el.children).forEach(slide => track.appendChild(slide)); 4099 4100 el.appendChild(track); 4101 el.insertBefore(skipLink, track); 4102 el.appendChild(skipLinkTarget); 4103 el.classList.add('snap-slider'); 4104 } 4105 4106 window.addEventListener('DOMContentLoaded', () => { 4107 if (typeof SnapSlider === 'undefined') return; 4108 4109 const carousels = document.querySelectorAll(` 4110 [data-content-type="products"][data-appearance="carousel"], 4111 [data-content-type="slider"] 4112 `); 4113 4114 carousels.forEach(el => { 4115 const sliderOptions = el.dataset; 4116 const autoPager = sliderOptions.showDots === "true"; 4117 const showArrows = sliderOptions.showArrows === "true"; 4118 4119 if (el.dataset.contentType === 'slider') { 4120 initSliderCarousel(el); 4121 4122 if (showArrows) { 4123 el.insertAdjacentHTML( 4124 'beforeend', 4125 '\u000A\u003Cdiv\u0020data\u002Dpage\u002Dbuilder\u002Dslider\u002Dnav\u0020class\u003D\u0022flex\u0020justify\u002Dbetween\u0020items\u002Dcenter\u0020gap\u002D2\u0022\u003E\u000A\u0020\u0020\u0020\u0020\u003Cbutton\u000A\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020class\u003D\u0022btn\u0020btn\u002Dsecondary\u0020p\u002D2\u0022\u000A\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020aria\u002Dlabel\u003D\u0022Previous\u0020Slide\u0022\u000A\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020data\u002Dprev\u000A\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020disabled\u000A\u0020\u0020\u0020\u0020\u003E\u003Csvg\u0020xmlns\u003D\u0022http\u003A\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\u0022\u0020width\u003D\u002218\u0022\u0020height\u003D\u002218\u0022\u0020fill\u003D\u0022none\u0022\u0020stroke\u003D\u0022currentColor\u0022\u0020stroke\u002Dlinecap\u003D\u0022round\u0022\u0020stroke\u002Dlinejoin\u003D\u0022round\u0022\u0020stroke\u002Dwidth\u003D\u00221.5\u0022\u0020viewBox\u003D\u00220\u00200\u002024\u002024\u0022\u0020class\u003D\u0022rtl\u003A\u002Drotate\u002D180\u0022\u0020aria\u002Dhidden\u003D\u0022true\u0022\u003E\u003Cpath\u0020d\u003D\u0022m12\u002019\u002D7\u002D7\u00207\u002D7M19\u002012H5\u0022\u002F\u003E\u003C\u002Fsvg\u003E\u000A\u003C\u002Fbutton\u003E\u000A\u0020\u0020\u0020\u0020\u003Cdiv\u0020class\u003D\u0022snap\u002Dpager\u0022\u0020data\u002Dinit\u002Dpager\u003E\u003C\u002Fdiv\u003E\u000A\u0020\u0020\u0020\u0020\u003Cbutton\u000A\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020class\u003D\u0022btn\u0020btn\u002Dsecondary\u0020p\u002D2\u0022\u000A\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020aria\u002Dlabel\u003D\u0022Next\u0020Slide\u0022\u000A\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020data\u002Dnext\u000A\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020disabled\u000A\u0020\u0020\u0020\u0020\u003E\u003Csvg\u0020xmlns\u003D\u0022http\u003A\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\u0022\u0020width\u003D\u002218\u0022\u0020height\u003D\u002218\u0022\u0020fill\u003D\u0022none\u0022\u0020stroke\u003D\u0022currentColor\u0022\u0020stroke\u002Dlinecap\u003D\u0022round\u0022\u0020stroke\u002Dlinejoin\u003D\u0022round\u0022\u0020stroke\u002Dwidth\u003D\u00221.5\u0022\u0020viewBox\u003D\u00220\u00200\u002024\u002024\u0022\u0020class\u003D\u0022rtl\u003A\u002Drotate\u002D180\u0022\u0020aria\u002Dhidden\u003D\u0022true\u0022\u003E\u003Cpath\u0020d\u003D\u0022M5\u002012h14M12\u00205l7\u00207\u002D7\u00207\u0022\u002F\u003E\u003C\u002Fsvg\u003E\u000A\u003C\u002Fbutton\u003E\u000A\u003C\u002Fdiv\u003E\u000A' 4126 ); 4127 } 4128 4129 if (autoPager) { 4130 const pager = el.querySelector('[data-init-pager]'); 4131 pager.setAttribute('data-pager', ''); 4132 pager.removeAttribute('data-init-pager'); 4133 } 4134 4135 new SnapSlider(el, { autoPager, groupPager: true }); 4136 } 4137 4138 if (el.dataset.contentType === 'products') {
4139 const slider = el.querySelector('[data-slider-type]'); 4140 const sliderNav = el.querySelector('[data-page-builder-slider-nav]'); 4141 4142 if (sliderNav && autoPager) { 4143 const pager = sliderNav.querySelector('[data-init-pager]'); 4144 pager.setAttribute('data-pager', ''); 4145 pager.removeAttribute('data-init-pager'); 4146 } 4147 4148 if (sliderNav && !showArrows) { 4149 sliderNav.querySelectorAll('[data-prev],[data-next]').forEach((btn) => btn.remove()); 4150 } 4151 4152 new SnapSlider(slider, { autoPager, groupPager: true }); 4153 } 4154 }); 4155 }); 4156 })(); 4157</script>
vendor: 1 bytes, line 4157
4157
4158<script> 4159 function initConfigurableOptions(productId, optionConfig) { 4160 4161 function findPathParam(key) { 4162 const baseUrl = (BASE_URL.substring(0, 2) === '//' ? 'http:' : '') + BASE_URL; 4163 const baseUrlParts = (new URL(baseUrl)).pathname.replace(/\/$/, '').split('/'); 4164 const pathParts = window.location.pathname.split('/').slice(baseUrlParts.length + 3); 4165 for (let i = 0; i < pathParts.length; i += 2) { 4166 if (pathParts[i] === key && pathParts.length > i) { 4167 return pathParts[i + 1]; 4168 } 4169 } 4170 } 4171 4172 return { 4173 optionConfig, 4174 productId, 4175 itemId: (new URLSearchParams(window.location.search)).get('id') || findPathParam('id'), 4176 allowedAttributeOptions: [], 4177 selectedValues: [], 4178 init() { 4179 this.findAllowedAttributeOptions(); 4180 this.$nextTick(() => { 4181 if (typeof this.optionConfig.defaultValues === 'object') { 4182 for (const [attributeId, value] of Object.entries(this.optionConfig.defaultValues)) { 4183 this.changeOption(attributeId, value + ''); 4184 } 4185 } 4186 this.preselectQuerystringItems(); 4187 this.preselectLocationHashItems(); 4188 }); 4189 }, 4190 productIndex: 0, 4191 productIndexForPrice: 0, 4192 optionIsActive(attributeId, optionId) { 4193 return !!this.getAllowedAttributeOptions(attributeId).find( 4194 option => option.id === optionId 4195 ) 4196 }, 4197 optionIsEnabled(attributeId, optionId) { 4198 for (const productId in this.optionConfig.index) { 4199 if (this.optionConfig.index[productId][attributeId] === optionId) { 4200 return true; 4201 } 4202 } 4203 return false; 4204 }, 4205 findSimpleIndex() { 4206 this.productIndex = this.calculateSimpleIndexForPartialSelection(this.selectedValues); 4207 this.productIndexForPrice = this.findCheapestProductForPartialSelection(this.selectedValues); 4208 }, 4209 calculateSimpleIndexForPartialSelection(selectedValues) { 4210 if (selectedValues.length === 0) return 0; 4211 return this.findProductIdsForPartialSelection(selectedValues)[0]; 4212 }, 4213 calculateSimpleIndexForFullSelection(selectedValues) { 4214 if (! this.isFullSelection(selectedValues)) return false; 4215 4216 const productIndexes = this.optionConfig.index; 4217 return Object.keys(productIndexes).find(productIndex => { 4218 const productCandidateOptions = productIndexes[productIndex]; 4219 4220 for (const productOption in productCandidateOptions) { 4221 if ( 4222 !selectedValues[productOption] || 4223 selectedValues[productOption] !== productCandidateOptions[productOption] 4224 ) { 4225 return false; 4226 } 4227 } 4228 return productIndex; 4229 }); 4230 }, 4231 findAllowedAttributeOptions() { 4232 this.allowedAttributeOptions = this.calculateAllowedAttributeOptions(this.selectedValues); 4233 }, 4234 calculateAllowedAttributeOptions(selectedValues) { 4235 const allAttributes = this.optionConfig.attributes; 4236 const allAttributesSorted = Object.values(allAttributes).sort((a,b) => { 4237 return a.position - b.position 4238 }); 4239 4240 const newAllowedAttributeOptions = []; 4241 4242 allAttributesSorted.forEach(attribute => { 4243 const selectionWithoutAttr = Object.assign({}, this.removeAttrFromSelection(selectedValues, attribute.id)); 4244 const availableIndexes = this.calculateAvailableProductIndexes(selectionWithoutAttr); 4245 newAllowedAttributeOptions[attribute.id] = allAttributes[attribute.id].options.filter(option => { 4246 return !!option.products.find(product => { 4247 return availableIndexes.includes(product); 4248 }) 4249 }); 4250 }); 4251 return newAllowedAttributeOptions; 4252 }, 4253 calculateAvailableProductIndexes(selectedOptions) { 4254 if (Object.keys(selectedOptions).length === 0) { 4255 if (Object.values(this.optionConfig.salable || {}).length) { 4256 return [].concat.apply([], [].concat.apply([], Object.values(this.optionConfig.salable).map(Object.values))).filter((x, i, a) => a.indexOf(x) === i) 4257 } 4258 return Object.keys(this.optionConfig.index); 4259 } 4260 4261 const selectedIds = Object.keys(selectedOptions); 4262 if (Object.values(this.optionConfig.salable || {}).length) { 4263 const selectedOptionIndexes = selectedIds.map(attrId => { 4264 const optionValue = selectedOptions[attrId]; 4265 return this.optionConfig.salable[attrId] && this.optionConfig.salable[attrId][optionValue] || [] 4266 }) 4267 return selectedOptionIndexes.reduce((acc, optionIndexes) => { 4268 return acc.filter(index => optionIndexes.includes(index)); 4269 }); 4270 } else { 4271 const productIndexes = this.optionConfig.index; 4272 return Object.keys(productIndexes).filter(index => { 4273 for (const attrId of selectedIds) { 4274 if (productIndexes[index][attrId] !== `${selectedOptions[attrId]}`) return false 4275 } 4276 return true 4277 }); 4278 } 4279 }, 4280 findAttributeByOptionId(optionId) { 4281 for (const attributeId in this.optionConfig.attributes) { 4282 const attributeOptions = this.optionConfig.attributes[attributeId].options || []; 4283 if (attributeOptions.find(option => option.id === optionId)) { 4284 return attributeId; 4285 } 4286 } 4287 }, 4288 getAllowedAttributeOptions(attributeId) { 4289 return this.allowedAttributeOptions[attributeId] || [] 4290 }, 4291 getAllAttributeOptions(attributeId) { 4292 return ( 4293 this.optionConfig.attributes[attributeId] && 4294 this.optionConfig.attributes[attributeId].options 4295 ) || [] 4296 }, 4297 getProductIdsForOption(option) { 4298 const attributeId = this.findAttributeByOptionId(option.id); 4299 const allOptions = this.optionConfig.attributes[attributeId]; 4300 const opt = (allOptions && allOptions.options || []).find(o => o.id === option.id); 4301 return opt && opt.products 4302 ? opt.products 4303 : []; 4304 }, 4305 findProductIdsForPartialSelection(optionSelection) { 4306 const candidateProducts = Object.values(optionSelection).reduce((candidates, optionId) => { 4307 const newCandidates = this.getProductIdsForOption({id: optionId}); 4308 return candidates === null 4309 ? newCandidates 4310 : candidates.filter(productId => newCandidates.includes(productId)); 4311 }, null); 4312 return candidateProducts || []; 4313 },
4314 findCheapestProductForPartialSelection(optionSelection) { 4315 const candidateProducts = this.findProductIdsForPartialSelection(optionSelection); 4316 return candidateProducts.reduce((cheapest, simpleIdx) => { 4317 // in the first iteration we start with simpleIdx as the currently cheapest product 4318 if (! this.optionConfig.optionPrices[cheapest]) return simpleIdx; 4319 const knownCheapestPrice = this.optionConfig.optionPrices[cheapest].finalPrice.amount; 4320 return knownCheapestPrice > this.optionConfig.optionPrices[simpleIdx].finalPrice.amount 4321 ? simpleIdx 4322 : cheapest; 4323 }, 0) 4324 }, 4325 findProductIdToUseForOptionPrice(option) { 4326 // try to find a product for a complete selection 4327 const attributeId = this.findAttributeByOptionId(option.id); 4328 const optionSelection = Object.assign({}, this.selectedValues, {[attributeId]: option.id}); 4329 const matchingSimpleIndex = this.calculateSimpleIndexForFullSelection(optionSelection); 4330 // if there is no complete selection, use the cheapest product for the option 4331 return matchingSimpleIndex || this.findCheapestProductForPartialSelection(optionSelection); 4332 }, 4333 getAttributeOptionLabel(option) { 4334 const optionProduct = this.findProductIdToUseForOptionPrice(option); 4335 4336 if ((! optionProduct) || (optionProduct === this.productIndexForPrice)) { 4337 return option.label; 4338 } 4339 4340 const currentPrice = this.getOptionPriceAdjustmentBasePrice(); 4341 4342 if (this.optionConfig.optionPrices[optionProduct]) { 4343 const optionPrice = this.optionConfig.optionPrices[optionProduct].finalPrice.amount; 4344 if (optionPrice !== currentPrice){ 4345 return option.label + ' ' + hyva.formatPrice(optionPrice - currentPrice, true); 4346 } 4347 } 4348 return option.label; 4349 }, 4350 getOptionPriceAdjustmentBasePrice() { 4351 if (this.optionConfig.optionPrices[this.productIndexForPrice]) { 4352 return this.optionConfig.optionPrices[this.productIndexForPrice].finalPrice.amount 4353 } 4354 return this.optionConfig.prices.finalPrice.amount; // default price if no option selection 4355 }, 4356 clearOptionIfActive(optionId, value) { 4357 if (this.selectedValues[optionId] === value) { 4358 this.blurLabel() 4359 this.changeOption(optionId, '') 4360 } 4361 }, 4362 removeAttrFromSelection(selectedValues, attributeId) { 4363 attributeId = parseInt(attributeId); 4364 return selectedValues.reduce((newSelection, val, attr) => { 4365 if (attr !== attributeId) { 4366 newSelection[attr] = val; 4367 } 4368 return newSelection; 4369 }, []); 4370 }, 4371 changeOption(attributeId, value) { 4372 if (value === '') { 4373 this.selectedValues = this.removeAttrFromSelection(this.selectedValues, attributeId) 4374 } else if (value && this.getAllowedAttributeOptions(attributeId).find(option => option.id === value)) { 4375 this.selectedValues[attributeId] = value; 4376 } 4377 this.findSimpleIndex(); 4378 this.findAllowedAttributeOptions(); 4379 this.updatePrices(); 4380 this.updateGallery(); 4381 4382 const candidates = this.findProductIdsForPartialSelection(this.selectedValues); 4383 4384 window.dispatchEvent( 4385 new CustomEvent( 4386 'configurable-selection-changed', 4387 { 4388 detail: { 4389 productId: this.productId, 4390 optionId: attributeId, 4391 value: value, 4392 productIndex: this.productIndex, 4393 selectedValues: this.selectedValues, 4394 candidates: candidates, 4395 skuCandidates: Object.values(candidates).map(id =>
4395 this.optionConfig.sku?.[id] ?? null).filter(Boolean), 4396 } 4397 } 4398 ) 4399 ); 4400 }, 4401 calculateIsMinimalPrice() { 4402 return ! this.isFullSelection(this.selectedValues); 4403 }, 4404 isFullSelection(selectedValues) { 4405 return Object.values(selectedValues).length === Object.keys(this.optionConfig.attributes).length; 4406 }, 4407 updatePrices() { 4408 const value = this.optionConfig.optionPrices[this.productIndexForPrice] || this.optionConfig.prices; 4409 window.dispatchEvent( 4410 new CustomEvent( 4411 "update-prices-" + this.productId, 4412 { 4413 detail: Object.assign( 4414 value, 4415 { isMinimalPrice: this.calculateIsMinimalPrice() } 4416 ) 4417 } 4418 ) 4419 ); 4420 }, 4421 updateGallery () { 4422 if (this.productIndex) { 4423 const images = this.optionConfig.images[this.productIndex]; 4424 images && window.dispatchEvent(new CustomEvent( 4425 "update-gallery", 4426 { detail: this.sortImagesByPosition(images) } 4427 )); 4428 } else { 4429 window.dispatchEvent(new Event("reset-gallery")); 4430 } 4431 }, 4432 sortImagesByPosition(images) { 4433 return images.sort((x, y) => { 4434 return x.position === y.position ? 0 : (parseInt(x.position) > parseInt(y.position) ? 1 : -1) 4435 }); 4436 }, 4437 onGetCartData(data) { 4438 }, 4439 preselectCartItems(data) { 4440 // pre-select options based on cart data for current (quote) itemId 4441 const cart = data && data.cart; 4442 if (cart && cart.items) { 4443 const cartItem = cart.items.find((item) => { 4444 return ( 4445 item.item_id === this.itemId 4446 && item.product_id === this.productId 4447 ) 4448 }); 4449 if (cartItem && cartItem.options && cartItem.options.length) { 4450 cartItem.options.map(option => { 4451 this.changeOption(option.option_id, option.option_value); 4452 }) 4453 } 4454 } 4455 }, 4456 preselectQuerystringItems() { 4457 // pre-select option like ?size=167 4458 const urlQueryParams = new URLSearchParams(window.location.search.replace('?','')); 4459 this.preselectItemsBasedOnLocation(attribute => urlQueryParams.get(attribute.code)); 4460 }, 4461 preselectLocationHashItems() { 4462 // pre-select option like #144=167 4463 const urlHashParams = new URLSearchParams(window.location.hash.replace('#','')); 4464 this.preselectItemsBasedOnLocation(attribute => urlHashParams.get(attribute.id)); 4465 }, 4466 preselectItemsBasedOnLocation(getLocationValue) { 4467 Object.values(this.optionConfig.attributes).map(attribute => { 4468 const v = getLocationValue(attribute); 4469 v && this.changeOption(attribute.id, v) 4470 }); 4471 } 4472 } 4473 } 4474</script>
vendor: 1 bytes, line 4474
4474
4475<script> 4476 function initSwatchOptions(swatchConfig) { 4477 return { 4478 swatchConfig, 4479 getAttributeSwatchData(attributeId) { 4480 const swatchConfig = Object.assign({}, this.swatchConfig[attributeId]); 4481 swatchConfig['details'] = JSON.parse(swatchConfig['additional_data']); 4482 4483 return swatchConfig; 4484 }, 4485 mapSwatchTypeNumberToTypeCode(typeNumber) { 4486 switch ("" + typeNumber) { 4487 case "1": 4488 return "color" 4489 case "2": 4490 return "image" 4491 case "3": 4492 return "empty" 4493 case "0": 4494 default: 4495 return "text" 4496 } 4497 }, 4498 getTypeOfFirstOption(attributeId) { 4499 for (const optionId in this.swatchConfig[attributeId]) { 4500 const option = this.swatchConfig[attributeId][optionId]; 4501 if (typeof option.type !== 'undefined') { 4502 return this.mapSwatchTypeNumberToTypeCode(option.type); 4503 } 4504 } 4505 }, 4506 getVisualSwatchType(attributeId, targetOptionId) { 4507 // If a type configuration is present for the given option id, use it 4508 const config = this.swatchConfig[attributeId]; 4509 if (config[targetOptionId] && typeof config[targetOptionId].type !== 'undefined') { 4510 return this.mapSwatchTypeNumberToTypeCode(config[targetOptionId].type); 4511 } 4512 4513 // Otherwise - if no config is present for the target option - use the type of the first option 4514 // with a type property from the attribute, thus assuming its the same type as the target option. 4515 // (This edge case condition can occur on single swatch products if some options are not salable) 4516 return this.getTypeOfFirstOption(attributeId); 4517 }, 4518 getSwatchType(attributeId, optionId) { 4519 // Deserialize the attribute details the first time they are used 4520 if (this.swatchConfig[attributeId] && ! this.swatchConfig[attributeId].details) { 4521 this.swatchConfig[attributeId] = this.getAttributeSwatchData(attributeId); 4522 } 4523 const type = this.swatchConfig[attributeId] && 4524 this.swatchConfig[attributeId].details && 4525 this.swatchConfig[attributeId].details.swatch_input_type || 4526 "empty"; 4527 return type === 'visual' ? this.getVisualSwatchType(attributeId, optionId) : type; 4528 }, 4529 isTextSwatch(attributeId, optionId) { 4530 return this.getSwatchType(attributeId, optionId) === 'text'; 4531 }, 4532 isVisualSwatch(attributeId, optionId) { 4533 const type = this.getSwatchType(attributeId, optionId); 4534 4535 return ['image', 'color'].includes(type); 4536 }, 4537 getSwatchBackgroundStyle(attributeId, optionId) { 4538 const config = this.getSwatchConfig(attributeId, optionId); 4539 const type = this.getSwatchType(attributeId, optionId); 4540 4541 if (type === "color") { 4542 return 'background-color:' + config.value; 4543 } else if (type === "image") { 4544 return "background: #fff url('" + config.value + "') no-repeat center"; 4545 } else { 4546 return ''; 4547 } 4548 }, 4549 getSwatchText(attributeId, optionId) { 4550 const config = this.getSwatchConfig(attributeId, optionId); 4551 return config.label || config.value || this.getOptionLabelFromOptionConfig(attributeId, optionId); 4552 }, 4553 getOptionLabelFromOptionConfig(attributeId, optionId) { 4554 // Fallback if no value is present in swatchConfig data 4555 // Reference issue https://gitlab.hyva.io/hyva-themes/magento2-default-theme/-/issues/190 4556 const option = this.getAllAttributeOptions(attributeId).filter(option => option.id === optionId); 4557 return option && option[0] && option[0].label ||''; 4558 }, 4559 getSwatchConfig(attributeId, optionId) { 4560 return this.swatchConfig[attributeId] && this.swatchConfig[attributeId][optionId] 4561 ? this.swatchConfig[attributeId][optionId] 4562 : false;
4563 }, 4564 activeTooltipItem: false, 4565 tooltipPositionElement: false, 4566 isTooltipVisible() { 4567 return this.activeTooltipItem && 4568 this.getSwatchConfig( 4569 this.activeTooltipItem.attribute, 4570 this.activeTooltipItem.item 4571 ); 4572 }, 4573 isFirstItemCol() { 4574 return this.activeTooltipItem.index === 0; 4575 }, 4576 getTooltipImageStyle(attributeId, optionId) { 4577 const config = this.getSwatchConfig(attributeId, optionId); 4578 const type = this.getSwatchType(attributeId, optionId); 4579 4580 if (type === "color") { 4581 return 'background-color:' + config.value + '; width: 110px; height: 90px;'; 4582 } else if (type === "image") { 4583 return "background: #ffffff url('" + config.thumb + 4584 "') center center no-repeat; width: 110px; height: 90px;"; 4585 } else { 4586 return 'display:none'; 4587 } 4588 }, 4589 getTooltipPosition() { 4590 return this.tooltipPositionElement ? 4591 `top: ${this.tooltipPositionElement.offsetTop}px;` + 4592 `left: ${ 4593 this.tooltipPositionElement.offsetLeft - ( 4594 this.tooltipPositionElement.closest('.snap') && 4595 this.tooltipPositionElement.closest('.snap').scrollLeft || 4596 0 4597 ) 4598 }px;` : '' 4599 }, 4600 getTooltipLabel() { 4601 return this.getSwatchConfig(this.activeTooltipItem.attribute, this.activeTooltipItem.item).label 4602 }, 4603 focusedLabel: false, 4604 focusLabel(optionId) { 4605 this.focusedLabel = optionId; 4606 }, 4607 blurLabel() { 4608 this.focusedLabel = false; 4609 } 4610 } 4611 } 4612</script>
4612 4613
4614<script type="text/json" id="default-section-data"> 4615 {"messages":[],"customer":[],"compare-products":[],"last-ordered-items":[],"cart":[],"directory-data":{"DE":{"name":"Deutschland","regions":{"80":{"code":"BAW","name":"Baden-W\u00fcrttemberg"},"81":{"code":"BAY","name":"Bayern"},"82":{"code":"BER","name":"Berlin"},"83":{"code":"BRG","name":"Brandenburg"},"84":{"code":"BRE","name":"Bremen"},"85":{"code":"HAM","name":"Hamburg"},"86":{"code":"HES","name":"Hessen"},"87":{"code":"MEC","name":"Mecklenburg-Vorpommern"},"79":{"code":"NDS","name":"Niedersachsen"},"88":{"code":"NRW","name":"Nordrhein-Westfalen"},"89":{"code":"RHE","name":"Rheinland-Pfalz"},"90":{"code":"SAR","name":"Saarland"},"91":{"code":"SAS","name":"Sachsen"},"92":{"code":"SAC","name":"Sachsen-Anhalt"},"93":{"code":"SCN","name":"Schleswig-Holstein"},"94":{"code":"THE","name":"Th\u00fcringen"}}},"data_id":1790306796},"captcha":[],"instant-purchase":[],"loggedAsCustomer":[],"persistent":[],"review":[],"payments":[],"wishlist":{"items":[]},"location":[],"checkout-data":[],"recently_viewed_product":[],"recently_compared_product":[],"product_data_storage":[],"paypal-billing-agreement":[],"paypal-buyer-country":[]}</script>
4615 4616</div></body> 4617</html>
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.