1(function($, document, window, viewport){ 2 'use strict'; 3 4 var _stock_info = ['out-of-stock', 'in-short-supply', 'in-stock'], 5 $v, 6 ArticleClass = function () { 7 this.init(); 8 }; 9 10 ArticleClass.DEFAULTS = { 11 input: { 12 id: 'a', 13 childId: 'VariKindArtikel', 14 quantity: 'anzahl' 15 }, 16 action: { 17 compareList: 'Vergleichsliste', 18 compareListRemove: 'Vergleichsliste.remove', 19 wishList: 'Wunschliste', 20 wishListRemove: 'Wunschliste.remove' 21 }, 22 selector: { 23 navUpdateCompare: '#comparelist-dropdown-content', 24 navBadgeUpdateCompare: '#comparelist-badge', 25 navCompare: '#shop-nav-compare', 26 navContainerWish: '#wishlist-dropdown-container', 27 navBadgeWish: '#badge-wl-count', 28 navBadgeAppend: '#shop-nav li.cart-menu', 29 boxContainer: '#sidebox', 30 boxContainerWish: '#sidebox', 31 quantity: 'input.quantity' 32 }, 33 modal: { 34 id: 'modal-article-dialog', 35 wrapper: '#result-wrapper', 36 wrapper_modal: '#result-wrapper-modal' 37 } 38 }; 39 40 ArticleClass.prototype = { 41 modalShown: false, 42 modalView: null, 43 44 constructor: ArticleClass, 45 46 init: function () { 47 this.options = ArticleClass.DEFAULTS; 48 this.gallery = null; 49 }, 50 51 onLoad: function() { 52 if (this.isSingleArticle()) { 53 var that = this; 54 var form = $.evo.io().getFormValues('buy_form'); 55 56 if (typeof history.replaceState === 'function') { 57 history.replaceState({ 58 a: form.a, 59 a2: form.VariKindArtikel || form.a, 60 url: document.location.href, 61 variations: {} 62 }, document.title, document.location.href); 63 } 64 65 window.addEventListener('popstate', function (event) { 66 if (event.state) { 67 that.setArticleContent(event.state.a, event.state.a2, event.state.url, event.state.variations); 68 } 69 }, false); 70 } 71 }, 72 73 isSingleArticle: function() { 74 return $('#buy_form').length > 0; 75 }, 76 77 getWrapper: function(wrapper) { 78 return typeof wrapper === 'undefined' ? $(this.options.modal.wrapper) : $(wrapper); 79 }, 80 81 getCurrent: function($item) { 82 var $current = $item.hasClass('variation') || ($item.length === 1 && $item[0].tagName === 'SELECT') 83 ? $item 84 : $item.closest('.variation'); 85 if ($current.length === 1 && $current[0].tagName === 'SELECT') { 86 $current = $item.find('option:selected'); 87 } else if ($current.length === 0) { 88 $current = $item.next('.variation'); 89 } 90 91 return $current; 92 }, 93 94 incrementProductVisitCount: function() { 95 console.log('This function is deprecated since JTL Shop 5.4.0'); 96 }, 97 98 navigateBackToList: function() { 99 console.log('This function is deprecated since JTL Shop 5.4.0'); 100 }, 101 102 register: function(wrapper) { 103 var $wrapper = this.getWrapper(wrapper); 104 105 if (this.isSingleArticle()) { 106 this.registerGallery($wrapper); 107 this.registerConfig(); 108 this.registerHoverVariations($wrapper); 109 } 110 111 this.registerSimpleVariations($wrapper); 112 this.registerSwitchVariations($wrapper); 113 this.registerBulkPrices($wrapper); 114 this.registerAccordion(); 115 // this.registerImageSwitch($wrapper); 116 this.registerArticleOverlay($wrapper); 117 this.registerImageHover($wrapper); 118 this.registerFinish($wrapper); 119 window.initNumberInput(); 120 this.initAbnahmeIntervallError(); 121 this.setClickableProductbox(); 122 }, 123 124 setClickableProductbox: function() { 125 $('.productbox[tabindex="0"]').on('keydown', function(e) { 126 // on Enter or Space 127 if (e.keyCode === 13 || e.keyCode === 32) { 128 e.preventDefault(); 129 $(this).find('a')[0].click(); 130 } 131 }); 132 }, 133 134 registerAccordion: function() { 135 $('.is-mobile .accordion [id^="tab-"]').on('shown.bs.collapse', function () { 136 let self = $(this); 137 $.evo.destroyScrollSearchEvent(); 138 setTimeout(function() { 139 $('html').animate( 140 {scrollTop: self.offset().top-40}, 141 100, 142 'linear', 143 function () { 144 setTimeout(function() { 145 $.evo.initScrollSearchEvent(); 146 }, 500); 147 }); 148 }, 400); 149 }); 150 }, 151 152 registerArticleOverlay: function($wrapper) { 153 var that = this; 154 155 $('.configpreview', $wrapper) 156 .each(function(i, item) { 157 let $item = $(item); 158 let wrapper = that.options.modal.wrapper_modal + '_modal'; 159 160 $item.on('click', function (event) { 161 event.preventDefault(); 162 that.modalArticleDetail(this, wrapper); 163 }); 164 }); 165 $wrapper.hover(null, function() { 166 $(this).removeClass('active'); 167 }) 168 }, 169 170 registerGallery: function(wrapper) { 171 /* 172 * product slider and zoom (details) 173 */ 174 function slickinit() 175 { 176 $('.initial-slick-dots').on('click', function () { 177 let mainNode = $('#gallery'); 178 mainNode.removeClass('slick-lazy'); 179 $.evo.extended().initSlick(mainNode, mainNode.data('slick-type')); 180 if(mainNode.slick('getSlick').slideCount > mainNode.slick('slickGetOption', 'slidesToShow')) { 181 mainNode.slick('slickGoTo', 1); 182 } 183 }); 184 } 185 186 function toggleFullscreen(fullscreen = false) 187 { 188 let $imgWrapper = $('#image_wrapper'), 189 $gallery = $('#gallery'); 190 if (!$gallery.hasClass('slick-initialized') || (fullscreen && $imgWrapper.hasClass('fullscreen'))){ 191 return; 192 } 193 194 let maxHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0
194), 195 otherElemHeight = 0, 196 current = ($('#gallery .slick-current').data('slick-index')), 197 $galleryImages = $('#gallery img, #gallery picture source'), 198 hidePreview = maxHeight < 700, 199 previewHeight = $('#gallery_preview_wrapper').length > 0 && !hidePreview ? 170 : 30, 200 $previewBar = $('.product-detail-image-preview-bar'); 201 202 if (fullscreen) { 203 $imgWrapper.addClass('fullscreen'); 204 let $galleryTopbar = $('#image_wrapper .product-detail-image-topbar'); 205 206 otherElemHeight = $galleryTopbar.outerHeight() 207 + 2*parseInt($imgWrapper.css('paddingTop')) 208 + previewHeight; 209 210 $galleryImages.removeAttr('sizes'); 211 // lazySizes.autoSizer.updateElem($galleryImages); 212 213 if (hidePreview) { 214 $previewBar.addClass('d-none'); 215 } 216 217 $galleryImages.css('max-height', maxHeight-otherElemHeight); 218 $gallery.css('max-height', maxHeight-otherElemHeight); 219 220 $('body').off('click.toggleFullscreen').on('click.toggleFullscreen', function (event) { 221 if (!($(event.target).hasClass('product-image') || $(event.target).hasClass('slick-arrow'))) { 222 toggleFullscreen(false); 223 $('body').off('click.toggleFullscreen'); 224 } 225 }); 226 } else { 227 $imgWrapper.removeClass('fullscreen'); 228 $galleryImages.css('max-height', '100%'); 229 $gallery.css('max-height', '100%'); 230 $previewBar.removeClass('d-none'); 231 } 232 233 $gallery.slick('slickSetOption','initialSlide', current, true); 234 $('#gallery_preview').slick('slickGoTo', current, true); 235 236 //fix firefox height bug 237 $('.slick-slide, .slick-arrow').css({'display': 'none'}); 238 setTimeout(function(){ 239 $('.slick-slide, .slick-arrow').css({'display': 'block'}); 240 }, 50); 241 } 242 243 function addClickListener() { 244 $('#gallery img').off('click').on('click', e => { 245 if (window.innerWidth > globals.breakpoints.lg) { 246 toggleFullscreen(true); 247 } 248 }); 249 } 250 251 slickinit(); 252 253 if (wrapper[0].id.indexOf(this.options.modal.wrapper_modal.slice(1)) === -1) { 254 addClickListener(); 255 256 $(document).on('keyup', e => { 257 if (e.key === "Escape" && $('#image_wrapper').hasClass('fullscreen')) { 258 toggleFullscreen(); 259 addClickListener(); 260 } 261 }); 262 } 263 }, 264 265 registerConfig: function() { 266 var that = this, 267 config = $('#product-configurator') 268 .closest('form') 269 .find('input[type="radio"], input[type="text"], input[type="checkbox"], input[type="number"], select'), 270 dropdown = $('#product-configurator') 271 .closest('form') 272 .find('select'); 273 let offset = $('#jtl-nav-wrapper').height(); 274 275 if (dropdown.length > 0) { 276 dropdown.on('change', function () { 277 var item = $(this).val(); 278 $(this).parents('.cfg-group').find('.cfg-drpdwn-item.collapse.show').collapse('hide'); 279 $('#drpdwn_qnt_' + item).collapse('show'); 280 }) 281 } 282 283 if (config.length > 0) { 284 config.on('change', function() { 285 that.configurator(); 286 }) 287 .on('keypress', function (e) { 288 if (e.key === 'Enter') { 289 return false;
290 } 291 }); 292 // timeout fixes problem with loading order of bootstrap dropdowns 293 setTimeout(function(){ 294 that.configurator(true); 295 },0); 296 } 297 298 function scroll (selector) { 299 $(selector).bind('click', function(event) { 300 event.preventDefault(); 301 let anchor = $(this).attr('href'); 302 $('html, body').stop().animate({ 303 scrollTop: $(anchor).offset().top - offset - 15 304 }); 305 }); 306 } 307 scroll('a[href="#cfg-container"]'); 308 309 310 $('#cfg-nav nav a').on('click', function() { 311 $('html, body').animate({ 312 scrollTop: $('#cfg-container').offset().top - offset - 15 313 }); 314 let anchor = $(this).attr('href'), 315 elOffset = $(anchor)[0].offsetTop; 316 $('#cfg-container .cfg-options').stop().animate({ 317 scrollTop: elOffset 318 }); 319 }); 320 321 $(document).on('scroll', function (e) { 322 let headerHeight = $('#jtl-nav-wrapper').outerHeight() + 10; 323 $('.cfg-position-details.cfg-layout-list #product-configuration-sidebar, ' + 324 '.cfg-position-details.cfg-layout-list .cfg-group .cfg-group-info').css('top', headerHeight + 'px'); 325 }); 326 }, 327 328 registerSimpleVariations: function($wrapper) { 329 var that = this; 330 331 $('.variations select', $wrapper).selectpicker({ 332 iconBase: 'fa', 333 tickIcon: 'fa-check', 334 hideDisabled: true, 335 showTick: true 336 }); 337 338 $('.simple-variations input[type="radio"]', $wrapper) 339 .on('change', function() { 340 var val = $(this).val(), 341 key = $(this).parent().data('key'); 342 $('.simple-variations [data-key="' + key + '"]').removeClass('active'); 343 $('.simple-variations [data-value="' + val + '"]').addClass('active'); 344 $(this).closest(".swatches").addClass("radio-selected"); 345 }); 346 347 $('.simple-variations input[type="radio"], .simple-variations select', $wrapper) 348 .each(function(i, item) { 349 var $item = $(item), 350 wrapper = '#' + $item.closest('form').closest('div[data-wrapper="true"]').attr('id'); 351 352 $item.on('change', function () { 353 that.variationPrice($(this), true, wrapper); 354 }); 355 }); 356 $('.simple-variations input[type="text"]', $wrapper) 357 .each(function(i, item) { 358 let $item = $(item), 359 wrapper = '#' + $item.closest('form').closest('div[data-wrapper="true"]').attr('id'), 360 timeout = null; 361 $item.on('keyup', function (e) { 362 clearTimeout(timeout); 363 let self = $(this); 364 365 timeout = setTimeout(function () { 366 that.variationPrice(self, true, wrapper); 367 }, 500); 368 }); 369 }); 370 }, 371 372 registerBulkPrices: function($wrapper) { 373 var $bulkPrice = $('.bulk-price', $wrapper), 374 that = this, 375 $config = $('#product-configurator'); 376 377 if (($bulkPrice.length > 0 && $config.length === 0) || $('#product-list').length > 0) { 378 $('#quantity, [data-bulk="1"] .quantity', $wrapper) 379 .each(function(i, item) { 380 let $item = $(item), 381 wrapper = '#' + $item.closest('form').closest('div[data-wrapper="true"]').attr('id'); 382 383 $item.on('change', function () { 384 that.variationPrice($(this), true, wrapper); 385 }); 386 that.variationPrice($(this), true, wrapper); 387 }); 388 } 389 }, 390 391 registerSwitchVariations: function($wrapper) { 392 var that = this; 393 394 $('.switch-variations input[type="radio"], .switch-variations select', $wrapper) 395 .each(function(i, item) { 396 var $item = $(item), 397 wrapper = '#' + $item.closest('form').closest('div[id]').attr('id'); 398 399 $item.on('change', function () { 400 that.variationSwitch($(this), false, wrapper); 401 }); 402 }); 403 404 if (isTouchCapable()) { 405 $('.variations .swatches .variation', $wrapper) 406 .on('mouseover', function() { 407 $(this).trigger('click'); 408 }); 409 } 410 411 // ie11 fallback 412 if (typeof document.body.style.msTransform === 'string') { 413 $('.variations label.variation', $wrapper) 414 .on('click', function (e) { 415 if (e.target.tagName === 'IMG') { 416 $(this).trigger('click'); 417 } 418 }); 419 } 420 }, 421 422 registerHoverVariations: function ($wrapper) { 423 let delay=300, setTimeoutConst; 424 $('.variations label.variation', $wrapper) 425 .on('mouseenter', function (e) { 426 setTimeoutConst = setTimeout(function () { 427 let mainImageHeight = $('.js-gallery-images').innerHeight(); 428 $('.variation-image-preview.vt' + $(e.currentTarget).data('value')).addClass('show d-md-block') 429 .css('top', $(e.currentTarget).offset().top - $(e.currentTarget).closest('#content').position().top - mainImageHeight / 2 - 12); 430 }, delay) 431 }) 432 .on('mouseleave', function (e) { 433 clearTimeout(setTimeoutConst); 434 $('.variation-image-preview.vt' + $(this).data('value')).removeClass('show d-md-block'); 435 }); 436 437 $('.variations .selectpicker') 438 .on('show.bs.select', function () { 439 let selectPicker = $(this); 440 $(this).parent().find('li .variation') 441 .on('mouseenter', function (e) { 442 setTimeoutConst = setTimeout(function () { 443 let mainImageHeight = $('.js-gallery-images').innerHeight(); 444 let selectOptionValue = selectPicker.find('option').eq( 445 e.currentTarget.ariaPosInSet 446 ).data("value"); 447 $('.variation-image-preview.vt' + selectOptionValue) 448 .addClass('show d-md-block') 449 .css('top', $(e.currentTarget).offset().top - $(e.currentTarget).closest('#content').position().top - mainImageHeight / 2 - 12); 450 }, delay) 451 }) 452 .on('mouseleave', function (e) { 453 clearTimeout(setTimeoutConst); 454 let selectOptionValue = selectPicker.find('option').eq( 455 e.currentTarget.ariaPosInSet 456 ).data("value"); 457 $('.variation-image-preview.vt' + selectOptionValue) 458 .removeClass('show d-md-block'); 459 }); 460 }) 461 .on('hide.bs.select', function () { 462 $(this).parent().find('li .variation').off('mouseenter mouseleave'); 463 $('.variation-image-preview').removeClass('show'); 464 }); 465 }, 466 467 registerImageSwitch: function($wrapper) { 468 var that = this, 469 imgSwitch, 470 gallery = this.gallery; 471 472 if (gallery !== null) { 473 imgSwitch = function (context, temporary, force) { 474 var $context = $(context), 475 id = $context.attr('data-key'), 476 value = $context.attr('data-value'), 477 data = $context.data('list'), 478 title = $context.attr('data-title'); 479 480 if (typeof temporary === 'undefined') { 481 temporary = true; 482 } 483 484 if ((!$context.hasClass('active') || force) && !!data) { 485 gallery.setItems([data], value); 486 487 if (!temporary) { 488 var items = [data], 489 stacks = gallery.getStacks(); 490 for (var s in stacks) { 491 if (stacks.hasOwnProperty(s) && s.match(/^_[0-9a-zA-Z]*$/) && s !== '_' + id) { 492 items = $.merge(items, stacks[s]); 493 } 494 } 495 496 gallery.setItems([data], '_' + id); 497 gallery.setItems(items, '__'); 498 gallery.render('__'); 499 500 that.galleryIndex = gallery.index; 501 that.galleryLastIdent = gallery.ident; 502 } else { 503 gallery.render(value); 504 } 505 } 506 } 507 } else { 508 imgSwitch = function (context, temporary) { 509 var $context = $(context), 510 value = $context.attr('data-value'), 511 data = $context.data('list'), 512 title = $context.attr('data-title'); 513 514 if (typeof temporary === 'undefined') { 515 temporary = true; 516 } 517 518 if (!!data) { 519 var $wrapper = $(context).closest('.product-wrapper'), 520 $img = $('.image-box img', $wrapper); 521 if ($img.length === 1) { 522 $img.attr('src', data.md.src); 523 if (!temporary) { 524 $img.data('src', data.md.src); 525 } 526 } 527 } 528 }; 529 } 530 531 $('.variations .bootstrap-select select', $wrapper) 532 .on('change', function() { 533 var sel = $(this).find('[value=' + this.value + ']'), 534 cont = $(this).closest('.variations'); 535 536 if (cont.hasClass('simple-variations')) { 537 imgSwitch(sel, false, false); 538 } else { 539 imgSwitch(sel, true, false); 540 } 541 }); 542 543 if (!isTouchCapable() || ResponsiveBootstrapToolkit.current() !== 'xs') { 544 $('.variations .bootstrap-select .dropdown-menu li', $wrapper) 545 .on('hover', function () { 546 var tmp_idx = parseInt($(this).attr('data-original-index')) + 1, 547 rule = 'select option:nth-child(' + tmp_idx + ')', 548 sel = $(this).closest('.bootstrap-select').find(rule); 549 imgSwitch(sel); 550 }, function () { 551 var tmp_idx = parseInt($(this).attr('data-original-index')) + 1, 552 rule = 'select option:nth-child(' + tmp_idx + ')', 553 sel = $(this).closest('.bootstrap-select').find(rule), 554 gallery = that.gallery, 555 active; 556 557 if (gallery !== null) { 558 active = $(sel).find('.variation.active'); 559 gallery.render(that.galleryLastIdent); 560 gallery.activate(that.galleryIndex); 561 } else { 562 var $wrapper = $(sel).closest('.product-wrapper'), 563 $img = $('.image-box img', $wrapper); 564 if ($img.length === 1) { 565 $img.attr('src', $img.data('src')); 566 } 567 } 568 }); 569 } 570 571 $('.variations.simple-variations .variation', $wrapper) 572 .on('click', function () { 573 imgSwitch(this, false); 574 }); 575 576 if (!isTouchCapable() || ResponsiveBootstrapToolkit.current() !== 'xs') { 577 $('.variations .variation', $wrapper) 578 .on('hover', function () { 579 imgSwitch(this); 580 }, function () { 581 var sel = $(this).closest('.variation'), 582 gallery = that.gallery; 583 584 if (gallery !== null) { 585 gallery.render(that.galleryLastIdent); 586 gallery.activate(that.galleryIndex); 587 } else { 588 var $wrapper = $(sel).closest('.product-wrapper'), 589 $img = $('.image-box img', $wrapper); 590 if ($img.length === 1) { 591 $img.attr('src', $img.data('src')); 592 } 593 } 594 }); 595 } 596 }, 597 598 registerImageHover: function($wrapper) { 599 $('.product-list .productbox-hover:not(.focus), .product-list .productbox-show-variations:not(.focus)', 600 $wrapper).on('mouseenter focusin', function () { 601 $(this).closest('.product-list').find('.focus').removeClass('focus'); 602 }); 603 $('.productbox-show-variations', $wrapper).on('mouseenter focusin', function () { 604 let collapse = $(this).find('.productbox-variations>.collapse') 605 606 $(this).addClass('focus'); 607 $(collapse).collapse('show'); 608 }); 609 $('.productlist-page-nav', $wrapper).on('focusin', function () { 610 $('.productbox-show-variations.focus', $wrapper).removeClass('focus'); 611 }); 612 $('.productbox-show-variations', $wrapper).on('mouseleave', function () { 613 let collapse = $(this).not('.focus').find('.productbox-variations>.collapse') 614 let box = $(this) 615 616 box.removeClass('focus'); 617 if (collapse.length === 1) { 618 box.addClass('transition'); 619 $(collapse).collapse('hide'); 620 $(collapse).on('hidden.bs.collapse', function () { 621 box.removeClass('transition'); 622 }); 623 } 624 }); 625 $('.is-mobile .show-variation-collapse a').on('click', function (e) { 626 if (!$(this).closest('.show-variation-collapse').find('.collapse').hasClass('show')) { 627 e.preventDefault(); 628 } 629 }); 630 }, 631 632 registerFinish: function($wrapper) { 633 $('#jump-to-votes-tab', $wrapper).on('click', function () { 634 let $tabID = $('#content a[href="#tab-votes"]'); 635 if ($tabID.length > 0) { 636 $tabID.tab('show'); 637 } else { 638 $tabID = $('#tab-votes'); 639 $tabID.collapse('show'); 640 } 641 642 $([document.documentElement, document.body]).animate({ 643 scrollTop: $tabID.offset().top 644 }, 200); 645 }); 646 647 let $tabID = $('#product-tabs a[href="' + window.location.hash + '"]'); 648 if ($tabID.length) { 649 $tabID.tab('show'); 650 $([document.documentElement, document.body]).animate({ 651
651 scrollTop: $tabID.offset().top 652 }, 200); 653 } 654 655 if (this.isSingleArticle()) { 656 if ($('.switch-variations .form-group', $wrapper).length === 1) { 657 var wrapper = '#' + $($wrapper).attr('id'); 658 this.variationSwitch($('.switch-variations', $wrapper), false, wrapper); 659 } 660 } 661 else { 662 var that = this; 663 664 $('.product-cell.hover-enabled') 665 .on('click', function (event) { 666 if (isTouchCapable() && ResponsiveBootstrapToolkit.current() !== 'xs') { 667 var $this = $(this); 668 669 if (!$this.hasClass('active')) { 670 event.preventDefault(); 671 event.stopPropagation(); 672 $('.product-cell').removeClass('active'); 673 $this.addClass('active'); 674 } 675 } 676 }) 677 .on('mouseenter', function (event) { 678 var $this = $(this), 679 wrapper = '#' + $this.attr('id'); 680 681 if (!$this.data('varLoaded') && $('.switch-variations .form-group', $this).length === 1) { 682 that.variationSwitch($('.switch-variations', $this), false, wrapper); 683 } 684 $this.data('varLoaded', true); 685 }); 686 } 687 688 this.registerProductActions($('#sidepanel_left')); 689 this.registerProductActions($('#footer')); 690 this.registerProductActions($('#shop-nav')); 691 this.registerProductActions($wrapper); 692 this.registerProductActions('#cart-form'); 693 }, 694 695 registerProductActions: function($wrapper) { 696 var that = this; 697 698 $('*[data-toggle="product-actions"] button', $wrapper) 699 .on('click', function(event) { 700 var data = $(this.form).serializeObject(); 701 702 if ($wrapper === '#cart-form') { 703 data.wlPos = $(this).data('wl-pos'); 704 data.a = $(this).data('product-id-wl'); 705 } 706 707 if (that.handleProductAction(this, data)) { 708 event.preventDefault(); 709 } 710 }); 711 $('a[data-toggle="product-actions"]', $wrapper) 712 .on('click', function(event) { 713 var data = $(this).data('value'); 714 this.name = $(this).data('name'); 715 716 if (that.handleProductAction(this, data)) { 717 event.preventDefault(); 718 } 719 }); 720 }, 721 722 loadModalArticle: function(url, wrapper, done, fail) { 723 var that = this, 724 id = wrapper.slice(1), 725 $modalBody = $('.modal-body', this.modalView); 726 727 $.ajax(url, {data: {'isAjax':1, 'quickView':1}}) 728 .done(function(data) { 729 var $html = $('<div />').html(data); 730 var $headerCSS = $html.find('link[type="text/css"]'); 731 var $headerJS = $html.find('script[src][src!=""]'); 732 var content = $html.find(that.options.modal.wrapper).html(); 733 734 $headerCSS.each(function (pos, item) { 735 var $cssLink = $('head link[href="' + item.href + '"]'); 736 if ($cssLink.length === 0) { 737 $('head').append('<link rel="stylesheet" type="text/css" href="' + item.href + '" >'); 738 } 739 }); 740 741 $headerJS.each(function (pos, item) { 742 if (typeof item.src !== 'undefined' && item.src.length > 0) { 743 var $jsLink = $('head script[src="' + item.src + '"]'); 744 if ($jsLink.length === 0) { 745 $('head').append('<script defer src="' + item.src + '" >'); 746 } 747 } 748 }); 749 750 $modalBody.html($('<div id="' + id + '" />').html(content)); 751 752 var $modal = $modalBody.closest(".modal-dialog"),
753 title = $modal.find('.modal-body h1'), 754 $config = $('#product-configurator', $modalBody); 755 756 if ($config.length > 0) { 757 // Configurator in child article!? Currently not supported! 758 $config.remove(); 759 $.evo.extended().startSpinner($modalBody); 760 location.href = url; 761 } 762 if (title.length > 0 && title.text().length > 0) { 763 $modal.find('.modal-title').text(title.text()); 764 title.remove(); 765 } 766 767 $('form', $modalBody).on('submit', function(event) { 768 event.preventDefault(); 769 770 var $form = $(this); 771 var data = $form.serializeObject(); 772 if (data['VariKindArtikel']) { 773 data['a'] = data['VariKindArtikel']; 774 } 775 776 $.evo.basket().addToBasket($form, data); 777 that.modalView.modal('hide'); 778 }); 779 780 if (typeof done === 'function') { 781 done(); 782 } 783 }) 784 .fail(function() { 785 if (typeof fail === 'function') { 786 fail(); 787 } 788 }) 789 .always(function() { 790 $.evo.extended().stopSpinner(); 791 }); 792 }, 793 794 addToComparelist: function(data, $action) { 795 var productId = parseInt(data[this.options.input.id]); 796 var childId = parseInt(data[this.options.input.childId]); 797 if (childId > 0) { 798 productId = childId; 799 } 800 if (productId > 0) { 801 var that = this; 802 $.evo.io().call('pushToComparelist', [productId], that, function(error, data) { 803 if (error) { 804 return; 805 } 806 807 var response = data.response; 808 809 if (response) { 810 switch (response.nType) { 811 case 0: // error 812 var errorlist = '<ul><li>' + response.cHints.join('</li><li>') + '</li></ul>'; 813 eModal.alert({ 814 title: response.cTitle, 815 message: errorlist, 816 keyboard: true, 817 tabindex: -1,
818 buttons: false 819 }); 820 break; 821 case 1: // forwarding 822 window.location.href = response.cLocation; 823 break; 824 case 2: // added to comparelist 825 that.updateComparelist(response); 826 break; 827 } 828 } 829 }); 830 831 return true; 832 } 833 834 return false; 835 }, 836 837 removeFromCompareList: function(data) { 838 var productId = parseInt(data[this.options.input.id]); 839 if (productId > 0) { 840 var that = this; 841 $.evo.io().call('removeFromComparelist', [productId], that, function(error, data) { 842 if (error) { 843 return; 844 } 845 846 var response = data.response; 847 848 if (response) { 849 switch (response.nType) { 850 case 0: // error 851 var errorlist = '<ul><li>' + response.cHints.join('</li><li>') + '</li></ul>'; 852 eModal.alert({ 853 title: response.cTitle, 854 message: errorlist, 855 keyboard: true, 856 tabindex: -1,
857 buttons: false 858 }); 859 break; 860 case 1: // forwarding 861 window.location.href = response.cLocation; 862 break; 863 case 2: // removed from comparelist 864 that.updateComparelist(response); 865 break; 866 } 867 } 868 }); 869 870 return true; 871 } 872 873 return false; 874 }, 875 876 updateComparelist: function(data) { 877 var $badgeUpd = $(this.options.selector.navUpdateCompare); 878 879 var badge = $(data.navDropdown); 880 $badgeUpd.html(badge); 881 $(this.options.selector.navBadgeUpdateCompare).html(data.nCount); 882 883 if (data.nCount > 0) { 884 $(this.options.selector.navCompare).removeClass('d-none'); 885 } else { 886 $(this.options.selector.navCompare).addClass('d-none'); 887 $('#nav-comparelist-collapse').removeClass('show'); 888 } 889 if (data.nCount > 1) { 890 $('#nav-comparelist-goto').removeClass('d-none'); 891 } else { 892 $('#nav-comparelist-goto').addClass('d-none'); 893 } 894 this.registerProductActions($('#shop-nav')); 895 896 if (data.productID) { 897 let $action = $('button[data-product-id-cl="' + data.productID + '"]') 898 $action.removeClass("on-list"); 899 $action.next().removeClass("press"); 900 $('.comparelist [data-product-id-cl="' + data.productID + '"]').remove(); 901 } 902 903 for (var ind in data.cBoxContainer) { 904 var $list = $(this.options.selector.boxContainer+ind); 905 906 if ($list.length > 0) { 907 if (data.cBoxContainer[ind].length) { 908 var $boxContent = $(data.cBoxContainer[ind]); 909 this.registerProductActions($boxContent); 910 $list.replaceWith($boxContent).removeClass('d-none'); 911 } else { 912 $list.html('').addClass('d-none'); 913 } 914 } 915 } 916 }, 917 918 addToWishlist: function(data, $action) { 919 let productId = parseInt(data[this.options.input.id]), 920 childId = parseInt(data[this.options.input.childId]), 921 qty = parseFloat(data[this.options.input.quantity]); 922 if (childId > 0) { 923 productId = childId; 924 } 925 if (isNaN(qty)) { 926 qty = 1; 927 } 928 if (productId > 0) { 929 var that = this; 930 $.evo.io().call('pushToWishlist', [productId, qty, data], that, function(error, data) { 931 if (error) { 932 $action.closest('form')[0].reportValidity(); 933 return; 934 } 935 if ($action.hasClass('action-tip-animation-b')) { 936 $action.addClass("on-list"); 937 $action.next().addClass("press"); 938 $action.next().next().removeClass("press"); 939 } 940 var response = data.response; 941 942 if (response) { 943 switch (response.nType) { 944 case 0: // error 945 var errorlist = '<ul><li>' + response.cHints.join('</li><li>') + '</li></ul>'; 946 eModal.alert({ 947 title: response.cTitle, 948 message: errorlist, 949 keyboard: true, 950 tabindex: -1,
951 buttons: false 952 }); 953 break; 954 case 1: // forwarding 955 window.location.href = response.cLocation; 956 break; 957 case 2: // added to wishlist 958 that.updateWishlist(response); 959 break; 960 } 961 } 962 }); 963 964 return true; 965 } 966 967 return false; 968 }, 969 970 removeFromWishList: function(data) { 971 var productId = parseInt(data[this.options.input.id]); 972 if (productId > 0) { 973 var that = this; 974 $.evo.io().call('removeFromWishlist', [productId], that, function(error, data) { 975 if (error) { 976 return; 977 } 978 979 var response = data.response; 980 981 if (response) { 982 switch (response.nType) { 983 case 0: // error 984 var errorlist = '<ul><li>' + response.cHints.join('</li><li>') + '</li></ul>'; 985 eModal.alert({ 986 title: response.cTitle, 987 message: errorlist, 988 keyboard: true, 989 tabindex: -1,
990 buttons: false 991 }); 992 break; 993 case 1: // forwarding 994 window.location.href = response.cLocation; 995 break; 996 case 2: // removed from wishlist 997 that.updateWishlist(response); 998 break; 999 } 1000 } 1001 }); 1002 1003 return true; 1004 } 1005 1006 return false; 1007 }, 1008 1009 updateWishlist: function(data) { 1010 var $navContainerWish = $(this.options.selector.navContainerWish); 1011 var $navBadgeWish = $(this.options.selector.navBadgeWish); 1012 1013 if (data.wlPosRemove) { 1014 let $action = $('button[data-wl-pos="' + data.wlPosRemove + '"]'); 1015 $action.removeClass("on-list"); 1016 $action.next().removeClass("press"); 1017 $action.find('.wishlist-icon').addClass('far').removeClass('fas'); 1018 } 1019 if (data.wlPosAdd) { 1020 let $action = $('button[data-product-id-wl="' + data.productID + '"]'); 1021 $action.attr('data-wl-pos', data.wlPosAdd); 1022 $action.data('wl-pos', data.wlPosAdd); 1023 $action.closest('form').find('input[name="wlPos"]').val(data.wlPosAdd) 1024 $action.find('.wishlist-icon').addClass('fas').removeClass('far'); 1025 } 1026 $.evo.io().call('updateWishlistDropdown', [$navContainerWish, $navBadgeWish], this, function(error, data) { 1027 if (error) { 1028 return; 1029 } 1030 if (data.response.currentPosCount > 0) { 1031 $navBadgeWish.removeClass('d-none'); 1032 } else { 1033 $navBadgeWish.addClass('d-none'); 1034 } 1035 $navContainerWish.html(data.response.content); 1036 $navBadgeWish.html(data.response.currentPosCount); 1037 setClickableRow(); 1038 }); 1039 1040 for (var ind in data.cBoxContainer) { 1041 var $list = $(this.options.selector.boxContainerWish+ind); 1042 if ($list.length > 0) { 1043 if (data.cBoxContainer[ind].length) { 1044 var $boxContent = $(data.cBoxContainer[ind]); 1045 this.registerProductActions($boxContent); 1046 $list.replaceWith($boxContent).removeClass('d-none'); 1047 } else { 1048 $list.html('').addClass('d-none'); 1049 } 1050 } 1051 } 1052 }, 1053 1054 handleProductAction: function(action, data) { 1055 let $action = $(action); 1056 switch (action.name) { 1057 case this.options.action.compareList: 1058 if ($action.hasClass('action-tip-animation-b')) { 1059 if ($action.hasClass('on-list')) { 1060 $action.removeClass("on-list"); 1061 $action.next().removeClass("press"); 1062 $action.next().next().addClass("press"); 1063 return this.removeFromCompareList(data); 1064 } else { 1065 $action.addClass("on-list"); 1066 $action.next().addClass("press"); 1067 $action.next().next().removeClass("press"); 1068 $(this.options.selector.navCompare).removeClass('d-none'); 1069 1070 let $moveTo = isMobileByBodyClass() 1071 ? $('.wish-compare-animation-mobile #burger-menu') 1072 : $('.wish-compare-animation-desktop #shop-nav-compare'); 1073 $.evo.article().moveItemAnimation($action, $moveTo); 1074 1075 return this.addToComparelist(data, $action); 1076 } 1077 } else { 1078 return this.addToComparelist(data, $action); 1079 } 1080 case this.options.action.compareListRemove: 1081 return this.removeFromCompareList(data); 1082 case this.options.action.wishList: 1083 data[this.options.input.quantity] = $('input[data-product-id="' + data.a + '"]').val() 1084 || $('#buy_form_'+data.a+' '+this.options.selector.quantity).val() 1085 || $('#quantity').val(); 1086 if ($action.hasClass('on-list')) { 1087 $action.removeClass("on-list"); 1088 $action.next().removeClass("press"); 1089 $action.next().next().addClass("press"); 1090 data.a = data.wlPos; 1091 return this.removeFromWishList(data); 1092 } else { 1093 $action.addClass("on-list"); 1094 let $moveTo = isMobileByBodyClass() 1095 ? $('.wish-compare-animation-mobile #burger-menu') 1096 : $('.wish-compare-animation-desktop #shop-nav-wish');
1097 $.evo.article().moveItemAnimation($action, $moveTo); 1098 return this.addToWishlist(data, $action); 1099 } 1100 case this.options.action.wishListRemove: 1101 return this.removeFromWishList(data); 1102 } 1103 1104 return false; 1105 }, 1106 1107 configurator: function(init) { 1108 if (this.isSingleArticle()) { 1109 var that = this, 1110 container = $('#cfg-container'), 1111 sidebar = $('#cfg-sticky-sidebar'), 1112 width, 1113 form; 1114 1115 if (container.length === 0) { 1116 return; 1117 } 1118 1119 $.evo.extended().startSpinner(container); 1120 1121 $('#buy_form').find('*[data-selected="true"]') 1122 .attr('checked', true) 1123 .attr('selected', true) 1124 .attr('data-selected', null); 1125 1126 form = $.evo.io().getFormValues('buy_form'); 1127 1128 $.evo.io().call('buildConfiguration', [form], that, function (error, data) { 1129 var result, 1130 i, 1131 j, 1132 item, 1133 cBeschreibung, 1134 quantityWrapper, 1135 grp, 1136 value, 1137 enableQuantity, 1138 nNetto, 1139 quantityInput; 1140 $('.js-start-configuration').prop('disabled', !(data.response.variationsSelected && data.response.inStock)); 1141 $('.js-choose-variations-wrapper').toggleClass('d-none', data.response.variationsSelected); 1142 $('.js-cfg-group').each(function (i, item) { 1143 let iconChecked = $('a[href="#'+this.id+'"] .js-group-checked'), 1144 badgeInfoDanger = 'alert-info'; 1145 if (data.response.invalidGroups && data.response.invalidGroups.includes($(this).data('id'))) { 1146 iconChecked.addClass('d-none'); 1147 if ($(this).hasClass('visited')) { 1148 badgeInfoDanger = 'alert-danger'; 1149 } 1150 $(this).find('.js-group-badge-checked') 1151 .removeClass('alert-success alert-info') 1152 .addClass(badgeInfoDanger); 1153 } else { 1154 iconChecked.removeClass('d-none'); 1155 $(this).find('.js-group-badge-checked') 1156 .addClass('alert-success') 1157 .removeClass('alert-danger alert-info'); 1158 } 1159 }); 1160 $('.js-cfg-group-error').addClass('d-none').html(''); 1161 $.each(data.response.errorMessages, function (i, item) { 1162 $('.js-cfg-group-error[data-id="' + item.group + '"]').removeClass('d-none').html(item.message); 1163 }); 1164 let $summaryFinish = $('#cfg-tab-summary-finish'); 1165 if (data.response.valid) { 1166 $('.js-cfg-validate').prop('disabled', false); 1167 $summaryFinish.children().removeClass('disabled'); 1168 $summaryFinish.removeClass('disabled'); 1169 } else { 1170 $('.js-cfg-validate').prop('disabled', true); 1171 $summaryFinish.children().addClass('disabled'); 1172 $summaryFinish.addClass('disabled'); 1173 } 1174 $.evo.extended().stopSpinner(); 1175 if (error) { 1176 $.evo.error(data); 1177 return; 1178 } 1179 result = data.response; 1180 1181 if (!result.oKonfig_arr) { 1182 $.evo.error('Missing configuration groups'); 1183 return; 1184 } 1185 1186 // global price 1187 nNetto = result.nNettoPreise; 1188 that.setPrice(result.fGesamtpreis[nNetto], result.cPreisLocalized[nNetto], result.cPreisString); 1189 that.setStockInformation(result.cEstimatedDelivery); 1190 1191 $('#content .summary').html(result.cTemplate); 1192 $.evo.tooltips(); 1193 $.evo.extended() 1194 .trigger('priceChanged', result); 1195 }); 1196 } 1197 }, 1198 1199 initConfigListeners: function () { 1200 $('.js-cfg-group').on('click', function () { 1201 $(this).addClass('visited'); 1202 }); 1203 $('#cfg-tab-summary-finish').on('click', function () { 1204 if (!$(this).hasClass('disabled')) { 1205 $('#cfg-modal-tabs').find('.nav-link').removeClass('active'); 1206 $('#cfg-tab-summary').children().addClass('active'); 1207 $(this).children().removeClass('active'); 1208 } 1209 }); 1210 $('.js-cfg-group-collapse').on('click', function () { 1211 $(this).addClass('visited'); 1212 }); 1213 }, 1214 1215 variationRefreshAll: function($wrapper) { 1216 $('.variations select', $wrapper).selectpicker('refresh'); 1217 $.evo.initSliders() 1218 }, 1219 1220 getConfigGroupQuantity: function (groupId) { 1221 return $('.cfg-group[data-id="' + groupId + '"] .quantity'); 1222 }, 1223 1224 getConfigGroupQuantityInput: function (groupId) { 1225 return $('.cfg-group[data-id="' + groupId + '"] .quantity input'); 1226 }, 1227 1228 getConfigGroupImage: function (groupId) { 1229 return $('.cfg-group[data-id="' + groupId + '"] .group-image img'); 1230 }, 1231 1232 setConfigItemImage: function (groupId, img) { 1233 $('.cfg-group[data-id="' + groupId + '"] .group-image img').attr('src', img).first(); 1234 }, 1235 1236 setConfigItemDescription: function (groupId, itemBeschreibung) { 1237 var groupItems = $('.cfg-group[data-id="' + groupId + '"] .group-items'); 1238 var descriptionDropdownContent = groupItems.find('#filter-collapsible_dropdown_' + groupId + ''); 1239 var descriptionDropdownContentHidden = groupItems.find('.d-none'); 1240 var descriptionCheckdioContent = groupItems.find('div[id^="filter-collapsible_checkdio"]'); 1241 var multiselect = groupItems.find('select').attr("multiple"); 1242 1243 // Bisher kein Content mit einer Beschreibung vorhanden, aber ein Artikel mit Beschreibung ausgewählt 1244 if (descriptionDropdownContentHidden.length > 0 && descriptionCheckdioContent.length === 0 && itemBeschreibung.length > 0 && multiselect !== "multiple") { 1245 groupItems.find('a[href="#filter-collapsible_dropdown_' + groupId + '"]').removeClass('d-none'); 1246 descriptionDropdownContent.replaceWith('<div id="filter-collapsible_dropdown_' + groupId + '" class="collapse top10 panel-body">' + itemBeschreibung + '</div>'); 1247 // Bisher Content mit einer Beschreibung vorhanden, aber ein Artikel ohne Beschreibung ausgewählt 1248 } else if (descriptionDropdownContentHidden.length === 0 && descriptionCheckdioContent.length === 0 && itemBeschreibung.length === 0 && multiselect !== "multiple") { 1249 groupItems.find('a[href="#filter-collapsible_dropdown_' + groupId + '"]').addClass('d-none'); 1250 descriptionDropdownContent.addClass('d-none'); 1251 // Bisher Content mit einer Beschreibung vorhanden und ein Artikel mit Beschreibung ausgewählt 1252 } else if (descriptionDropdownContentHidden.length === 0 && descriptionCheckdioContent.length === 0 && itemBeschreibung.length > 0 && multiselect !== "multiple") { 1253 descriptionDropdownContent.replaceWith('<div id="filter-collapsible_dropdown_' + groupId + '" class="collapse top10 panel-body">' + itemBeschreibung + '</div>'); 1254 } 1255 }, 1256 1257 setPrice: function(price, fmtPrice, priceLabel, wrapper) { 1258 var $wrapper = this.getWrapper(wrapper); 1259 1260 if (this.isSingleArticle()) { 1261 $('#product-offer .price', $wrapper).html(fmtPrice); 1262 $('#product-offer meta[itemprop="price"]', $wrapper).attr('content',price); 1263 if (priceLabel.length > 0) { 1264 $('#product-offer .price_label', $wrapper).html(priceLabel); 1265 } 1266 } else { 1267 var $price = $('.price_wrapper', $wrapper); 1268 1269 $('.price span:first-child', $price).html(fmtPrice); 1270 if (priceLabel.length > 0) { 1271 $('.price_label', $price).html(priceLabel); 1272 } 1273 } 1274 1275 $.evo.trigger('changed.article.price', { price: price }); 1276 }, 1277 1278 setStockInformation: function(cEstimatedDelivery, wrapper) { 1279 var $wrapper = this.getWrapper(wrapper); 1280 1281 $('.delivery-status .estimated-delivery span', $wrapper).html(cEstimatedDelivery); 1282 }, 1283 1284 setStaffelPrice: function(prices, fmtPrices, wrapper) { 1285 var $wrapper = this.getWrapper(wrapper), 1286 $container = $('#product-offer', $wrapper); 1287 1288 $.each(fmtPrices, function(index, value){ 1289 $('.bulk-price-' + index + ' .bulk-price', $container).html(value); 1290 }); 1291 }, 1292
1293 setVPEPrice: function(fmtVPEPrice, VPEPrices, fmtVPEPrices, wrapper) { 1294 var $wrapper = this.getWrapper(wrapper), 1295 $container = $('#product-offer', $wrapper); 1296 1297 $('.base-price .value', $container).html(fmtVPEPrice); 1298 $.each(fmtVPEPrices, function(index, value){ 1299 $('.bulk-price-' + index + ' .bulk-base-price', $container).html(value); 1300 }); 1301 }, 1302 1303 /** 1304 * @deprecated since 4.05 - use setArticleWeight instead 1305 */ 1306 setUnitWeight: function(UnitWeight, newUnitWeight) { 1307 $('#article-tabs .product-attributes .weight-unit').html(newUnitWeight); 1308 }, 1309 1310 setArticleWeight: function(ArticleWeight, wrapper) { 1311 if (this.isSingleArticle()) { 1312 var $articleTabs = $('#article-tabs'); 1313 1314 if ($.isArray(ArticleWeight)) { 1315 $('.product-attributes .weight-unit', $articleTabs).html(ArticleWeight[0][1]); 1316 $('.product-attributes .weight-unit-article', $articleTabs).html(ArticleWeight[1][1]); 1317 } else { 1318 $('.product-attributes .weight-unit', $articleTabs).html(ArticleWeight); 1319 } 1320 } else { 1321 var $wrapper = this.getWrapper(wrapper); 1322 1323 if ($.isArray(ArticleWeight)) { 1324 $('.attr-weight .value', $wrapper).html(ArticleWeight[0][1]); 1325 $('.attr-weight.weight-unit-article .value', $wrapper).html(ArticleWeight[1][1]); 1326 } else { 1327 $('.attr-weight .value', $wrapper).html(ArticleWeight); 1328 } 1329 } 1330 1331 }, 1332 1333 setProductNumber: function(productNumber, wrapper) { 1334 var $wrapper = this.getWrapper(wrapper); 1335 1336 $('#product-offer span[itemprop="sku"]', $wrapper).html(productNumber); 1337 }, 1338 1339 setArticleContent: function(id, variation, url, variations, wrapper) { 1340 var $wrapper = this.getWrapper(wrapper), 1341 listStyle = $('#product-list-type').val(); 1342 1343 if (listStyle === 'undefined') { 1344 listStyle = $('#ed_list.active').length > 0 ? 'list' : 'gallery'; 1345 } 1346 1347 $.evo.extended().startSpinner($wrapper); 1348 1349 if (this.modalShown) { 1350 this.loadModalArticle(url, wrapper, 1351 function() { 1352 var article = new ArticleClass(); 1353 article.register(wrapper); 1354 $.evo.extended().stopSpinner(); 1355 }, 1356 function() { 1357 $.evo.extended().stopSpinner(); 1358 $.evo.error('Error loading ' + url); 1359 } 1360 ); 1361 } else if (this.isSingleArticle()) { 1362 if($('#opc-startmenu').length > 0) { 1363 return this.redirectToArticle(id, variation, url, variations, wrapper); 1364 } 1365 1366 $.evo.extended().loadContent(url, () => { 1367 $.evo.extended().register(); 1368 $.evo.article().register(wrapper); 1369 1370 $(variations).each(function (i, item) { 1371 $.evo.article().variationSetVal(item.key, item.value, wrapper); 1372 }); 1373 1374 if (document.location.href !== url) { 1375 history.pushState({a: id, a2: variation, url: url, variations: variations}, "", url); 1376 } 1377 $.evo.extended().stopSpinner(); 1378 }, function () { 1379 $.evo.error('Error loading ' + url); 1380 $.evo.extended().stopSpinner(); 1381 }, false, wrapper); 1382 } else { 1383 $.evo.extended().loadContent(url + (url.indexOf('?') >= 0 ? '&' : '?') + 'isListStyle=' + listStyle, function (content) { 1384 $.evo.article().register(wrapper); 1385 1386 $('[data-toggle="basket-add"]', $(wrapper)).on('submit', function(event) { 1387 event.preventDefault(); 1388 event.stopPropagation(); 1389 1390 var $form = $(this); 1391 var data = $form.serializeObject(); 1392 data['a'] = variation; 1393 1394 $.evo.basket().addToBasket($form, data); 1395 }); 1396 1397 $(variations).each(function (i, item) {
1398 $.evo.article().variationSetVal(item.key, item.value, wrapper); 1399 }); 1400 1401 $.evo.extended().stopSpinner(); 1402 }, function () { 1403 $.evo.error('Error loading ' + url); 1404 $.evo.extended().stopSpinner(); 1405 }, false, wrapper); 1406 } 1407 }, 1408 1409 redirectToArticle: function(id, variation, url, variations, wrapper) { 1410 var $wrapper = this.getWrapper(wrapper), 1411 listStyle = $('#product-list-type').val(); 1412 1413 $.evo.extended().startSpinner($wrapper); 1414 1415 window.open(url, '_top'); 1416 1417 $.evo.extended().stopSpinner($wrapper); 1418 }, 1419 1420 variationResetAll: function(wrapper) { 1421 var $wrapper = this.getWrapper(wrapper); 1422 1423 $('.variation[data-value] input:checked', $wrapper).prop('checked', false); 1424 $('.variations select option', $wrapper).prop('selected', false); 1425 $('.variations select', $wrapper).selectpicker('refresh'); 1426 }, 1427 1428 variationDisableAll: function(wrapper) { 1429 let $wrapper = this.getWrapper(wrapper); 1430 1431 $('.swatches-selected', $wrapper).text(''); 1432 $('[data-value].variation', $wrapper).each(function(i, item) { 1433 $(item) 1434 .removeClass('active loading') 1435 .addClass('not-available'); 1436 $.evo.article() 1437 .removeStockInfo($(item)); 1438 }); 1439 }, 1440 1441 variationSetVal: function(key, value, wrapper) { 1442 var $wrapper = this.getWrapper(wrapper); 1443 1444 $('[data-key="' + key + '"]', $wrapper).val(value); 1445 }, 1446 1447 variationEnable: function(key, value, wrapper) { 1448 var $wrapper = this.getWrapper(wrapper), 1449 $item = $('[data-value="' + value + '"].variation', $wrapper); 1450 1451 $item.removeClass('not-available swatches-sold-out swatches-not-in-stock'); 1452 }, 1453 1454 showGalleryVariation: function(key, wrapper) { 1455 var $wrapper = this.getWrapper(wrapper), 1456 $item = $('.variation-' + key, $wrapper); 1457 1458 $item.collapse(); 1459 }, 1460 1461 variationActive: function(key, value, def, wrapper) { 1462 var $wrapper = this.getWrapper(wrapper), 1463 $item = $('[data-value="' + value + '"].variation', $wrapper); 1464 $item.addClass('active') 1465 .find('input') 1466 .prop('checked', true) 1467 .end() 1468 .prop('selected', true); 1469 1470 $('[data-id="'+key+'"].swatches-selected') 1471 .text($item.attr('data-original')); 1472 }, 1473 1474 removeStockInfo: function($item) { 1475 if (this.isSingleArticle()) { 1476 var type = $item.attr('data-type'), 1477 elem, 1478 label, 1479 wrapper; 1480 1481 switch (type) { 1482 case 'option': 1483 label = $item.data('content'); 1484 wrapper = $('<div />').append(label); 1485 $(wrapper) 1486 .find('.badge-not-available') 1487 .remove(); 1488 label = $(wrapper).html(); 1489 $item.data('content', label) 1490 .attr('data-content', label); 1491 1492 break; 1493 case 'radio': 1494 elem = $item.find('.badge-not-available'); 1495 if (elem.length === 1) { 1496 $(elem).remove(); 1497 } 1498 break; 1499 case 'swatch': 1500 $item.tooltip('dispose'); 1501 break; 1502 } 1503 1504 $item.removeAttr('data-stock'); 1505 } 1506 }, 1507 1508 variationInfo: function(value, status, note, notExists) { 1509 let $item = $('[data-value="' + value + '"].variation'), 1510 type = $item.attr('data-type'), 1511 text, 1512 content, 1513 $wrapper, 1514 label; 1515 1516 $item.attr('data-stock', _stock_info[status]); 1517 1518 switch (type) { 1519 case 'option': 1520 text = ' (' + note + ')'; 1521 content = $item.data('content');
1522 $wrapper = $('<div />'); 1523 1524 $wrapper.append(content); 1525 $wrapper 1526 .find('.badge-not-available') 1527 .remove(); 1528 1529 label = $('<span />') 1530 .addClass('badge badge-danger badge-not-available') 1531 .text(' '+note); 1532 1533 $wrapper.append(label); 1534 1535 $item.data('content', $wrapper.html()) 1536 .attr('data-content', $wrapper.html()); 1537 1538 $item.closest('select') 1539 .selectpicker('refresh'); 1540 break; 1541 case 'radio': 1542 $item.find('.badge-not-available') 1543 .remove(); 1544 1545 label = $('<span />') 1546 .addClass('badge badge-danger badge-not-available') 1547 .text(' '+note); 1548 1549 $item.append(label); 1550 break; 1551 case 'swatch': 1552 if (!$item.hasClass('gall-preview')) { 1553 $item.tooltip({ 1554 title: note, 1555 trigger: 'hover', 1556 container: 'body' 1557 }); 1558 } 1559 if (notExists) { 1560 $item.addClass('swatches-not-in-stock'); 1561 } else { 1562 $item.addClass('swatches-sold-out'); 1563 } 1564 break; 1565 } 1566 }, 1567 1568 variationSwitch: function($item, animation, wrapper) { 1569 if ($item) { 1570 var formID = $item.closest('form').attr('id'), 1571 $current = this.getCurrent($item), 1572 key = $current.data('key'), 1573 value = $current.data('value'), 1574 io = $.evo.io(), 1575 args = io.getFormValues(formID), 1576 layout = $('#product-list-type').val(), 1577 $wrapper = this.getWrapper(wrapper); 1578 1579 if (animation) { 1580 $.evo.extended().startSpinner(); 1581 } else { 1582 $('.updatingStockInfo', $wrapper).show(); 1583 } 1584 1585 $('.tooltip.show').remove(); 1586 args.wrapper = wrapper; 1587 args.layout = layout; 1588 1589 $.evo.article() 1590 .variationDispose(wrapper); 1591 1592 io.call('checkVarkombiDependencies', [args, key, value], $item, function (error, data) { 1593 if (animation) { 1594 $.evo.extended().stopSpinner(); 1595 } 1596 $('.updatingStockInfo', $wrapper).hide(); 1597 if (error) { 1598 $.evo.error('checkVarkombiDependencies'); 1599 } 1600 }); 1601 } 1602 }, 1603 1604 modalArticleDetail: function(item, wrapper) 1605 { 1606 let $item = $(item); 1607 let title = $item.data('title'); 1608 let url = $item.data('src'); 1609 1610 if (typeof this.modalView === 'undefined' || this.modalView === null) { 1611 this.modalView = $( 1612 '<div id="' + this.options.modal.id + '" class="modal fade" role="dialog" tabindex="-1" >' + 1613 ' <div class="modal-dialog modal-lg">' + 1614 ' <div class="modal-content">' + 1615 ' <div class="modal-header">' + 1616 ' <button type="button" class="x close" data-dismiss="modal"><i class="fa fa-times"></i></button>' + 1617 ' <div class="modal-title h4">' + title + '</div>' + 1618 ' </div>' + 1619 ' <div class="modal-body">' + 1620 ' <div id="' + wrapper.slice(1) + '" style="min-height:100px">' + 1621 '<div class="jtl-spinner"><i class="fa fa-spinner fa-pulse"></i></div>' + 1622 ' </div>' + 1623 ' </div>' + 1624 ' </div>' + 1625 ' </div>' + 1626 '</div>'); 1627 this.modalView 1628 .on('hidden.bs.modal', () => { 1629 $('.modal-body', this.modalView) 1630 .html('<div id="' + wrapper.slice(1) + '" style="min-height:100px" />'); 1631 $('.modal-title', this.modalView).html(''); 1632 this.modalView 1633 .off('shown.bs.modal'); 1634 this.modalShown = false;
1635 }); 1636 } else { 1637 $('.modal-title', this.modalView).html(title); 1638 $('.modal-body', this.modalView) 1639 .html('<div id="' + wrapper.slice(1) + '" style="min-height:100px">' + 1640 '<div class="jtl-spinner"><i class="fa fa-spinner fa-pulse"></i></div></div>'); 1641 } 1642 1643 this.modalView 1644 .on('shown.bs.modal', () => { 1645 this.modalShown = true; 1646 this.loadModalArticle(url, wrapper, 1647 function() { 1648 // no functionality needed in quickview 1649 // var article = new ArticleClass(); 1650 // article.register(wrapper); 1651 $.evo.extended().stopSpinner(); 1652 $('[data-toggle="popover"]', wrapper).popover({ html: true }); 1653 $('.product-image', wrapper).css('cursor', 'default'); 1654 }, 1655 function() { 1656 $.evo.extended().stopSpinner(); 1657 $.evo.error('Error loading ' + params.url); 1658 } 1659 ); 1660 }) 1661 .modal('show'); 1662 }, 1663 1664 variationPrice: function($item, animation, wrapper) { 1665 var formID = $item.closest('form').attr('id'), 1666 $wrapper = this.getWrapper(wrapper), 1667 io = $.evo.io(), 1668 args = io.getFormValues(formID); 1669 1670 if (animation) { 1671 $.evo.extended().startSpinner($wrapper); 1672 } 1673 1674 args.wrapper = wrapper; 1675 io.call('checkDependencies', [args], $(this), function (error, data) { 1676 let $action = $('button[data-product-id-wl="' + data.response.itemID + '"]'); 1677 if (data.response.check > 0) { 1678 $action.attr('data-wl-pos', data.response.check); 1679 $action.data('wl-pos', data.response.check); 1680 $action.closest('form').find('input[name="wlPos"]').val(data.response.check) 1681 $action.addClass('on-list'); 1682 } else { 1683 $action.removeClass('on-list'); 1684 } 1685 1686 if (animation) { 1687 $.evo.extended().stopSpinner(); 1688 } 1689 if (error) { 1690 $.evo.error('checkDependencies'); 1691 } 1692 }); 1693 }, 1694 1695 variationDispose: function(wrapper) { 1696 var $wrapper = this.getWrapper(wrapper); 1697 1698 $('[role="tooltip"]', $wrapper).remove(); 1699 }, 1700 1701 moveItemAnimation: function(item, moveTo) { 1702 if (!item.length || !moveTo.length || $(this).hasClass('on-list')) { 1703 return; 1704 } 1705 setTimeout(function() { 1706 let itemClone = item.clone() 1707 .offset({ 1708 top: item.offset().top, 1709 left: item.offset().left 1710 }).css({ 1711 'opacity': '0.5', 1712 'position': 'absolute', 1713 'z-index': '10000' 1714 }) 1715 .appendTo($('body')) 1716 .animate({ 1717 'top': moveTo.offset().top + 5, 1718 'left': moveTo.offset().left + 5, 1719 }, 700); 1720 1721 itemClone.animate({ 1722 'width': 0, 1723 'height': 0 1724 }, function () { 1725 $(this).detach() 1726 }); 1727 }, 0); 1728 }, 1729 1730 initAbnahmeIntervallError: function() { 1731 let $intervallNotice = $('#intervall-notice'); 1732 if ($intervallNotice.length > 0) { 1733 $('#quantity').on('change', function () { 1734 let $step = $(this).attr('step'), 1735 diff = Math.abs(($(this).val() % $step) - $step), 1736 epsilon = 0.00000001; 1737 if (diff < epsilon || diff + epsilon > $step) { 1738 $('#intervall-notice-danger').remove(); 1739 } else { 1740 $('#quantity-grp').after('<div id="intervall-notice-danger" class="alert alert-danger mt-2">' 1741 + $intervallNotice.html() + '</div>'); 1742 } 1743 }); 1744 } 1745 } 1746 }; 1747 1748 $v = new ArticleClass(); 1749 1750 $(document).ready(function () { 1751 $v.onLoad(); 1752 $v.register(); 1753 }); 1754 1755 $(window).on('resize', 1756 viewport.changed(function(){ 1757 $v.configurator(); 1758 }) 1759 ); 1760 1761 // PLUGIN DEFINITION 1762 // ================= 1763 $.evo.article = function () { 1764 return $v; 1765 }; 1766})(jQuery, document, window, ResponsiveBootstrapToolkit);
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.