1(function ( $ ) { 2 'use strict'; 3 4 var sober = sober || {}; 5 6 sober.init = function () { 7 this.$window = $( window ); 8 this.$body = $( document.body ); 9 this.$sideMenu = $( '.side-menu' ); 10 11 this.data = soberData || {}; 12 13 this.closeTopbar(); 14 this.menuHover(); 15 this.toggleSideMenu(); 16 this.toggleModal(); 17 this.removeCartItem(); 18 this.toggleTabs(); 19 this.focusInputs(); 20 this.filterProducts(); 21 this.sortProducts(); 22 this.productQuantity(); 23 this.productImagesLightbox(); 24 this.stickyProductSummary(); 25 this.stickUpSells(); 26 this.upsellsCarousel(); 27 this.checkBox(); 28 this.formatGallery(); 29 this.backToTop(); 30 this.toggleProductFilter(); 31 this.productQuickView(); 32 this.instanceSearch(); 33 this.fakeScrollbar(); 34 this.stickyHeader(); 35 this.navAjax(); 36 this.portfolioFilter(); 37 this.productVariationSwatches(); 38 this.productGallerySlider(); 39 this.productImageZoom(); 40 this.productImageSlider(); 41 this.singeProductAjaxAddToCart(); 42 this.openCartModalAfterAdd(); 43 this.pageHeaderParallax(); 44 this.responsive(); 45 this.preload(); 46 this.popup(); 47 this.addedToCartNotice(); 48 this.checkoutTerms(); 49 50 $( document.body ).trigger( 'sober_init', [sober] ); 51 }; 52 53 /** 54 * Check if a node is blocked for processing. 55 * 56 * @param {object} $node 57 * @return {bool} True if the DOM Element is UI Blocked, false if not. 58 */ 59 sober.isBlocked = function ( $node ) { 60 return $node.is( '.processing' ) || $node.parents( '.processing' ).length; 61 }; 62 63 /** 64 * Block a node visually for processing. 65 * 66 * @param {object} $node 67 */ 68 sober.block = function ( $node ) { 69 if ( !sober.isBlocked( $node ) ) { 70 $node.addClass( 'processing' ).block( { 71 message : null, 72 overlayCSS: { 73 background: '#fff', 74 opacity : 0.6 75 } 76 } ); 77 } 78 }; 79 80 /** 81 * Unblock a node after processing is complete. 82 * 83 * @param {object} $node 84 */ 85 sober.unblock = function ( $node ) { 86 $node.removeClass( 'processing' ).unblock(); 87 }; 88 89 /** 90 * Check if an element is in view-port or not 91 * 92 * @param el 93 * @returns {boolean} 94 */ 95 sober.isVisible = function ( el ) { 96 if ( el instanceof jQuery ) { 97 el = el[0]; 98 } 99 100 var rect = el.getBoundingClientRect(); 101 102 return rect.bottom > 0 && 103 rect.right > 0 && 104 rect.left < ( window.innerWidth || document.documentElement.clientWidth ) && 105 rect.top < ( window.innerHeight || document.documentElement.clientHeight ); 106 }; 107 108 /** 109 * Post format gallery with carousel slider 110 */ 111 sober.formatGallery = function () { 112 $( '.entry-gallery' ).addClass( 'owl-carousel' ).owlCarousel( { 113 singleItem: true, 114 items : 1, 115 navSpeed : 800, 116 nav : true, 117 dots : false, 118 autoplay : true, 119 dotsSpeed : 1000, 120 rtl : sober.data.isRTL === "1", 121 navText : ['<svg viewBox="0 0 20 20"><use xlink:href="#left-arrow"></use></svg>', '<svg viewBox="0 0 20 20"><use xlink:href="#right-arrow"></use></svg>'] 122 } ); 123 }; 124 125 /** 126 * Style checkboxes 127 */ 128 sober.checkBox = function () { 129 // Checkbox: Ship to a different address 130 $( '#ship-to-different-address' ).find( '.input-checkbox' ).on( 'change', function () { 131 if ( $( this ).is( ':checked' ) ) { 132 $( this ).parent().find( '.checkbox' ).addClass( 'checked' ); 133 } else { 134 $( this ).parent().find( '.checkbox' ).removeClass( 'checked' ); 135 } 136 } ).trigger( 'change' ); 137 }; 138 139 /** 140 * Load ajax on shop page and blog 141 */ 142 sober.navAjax = function () { 143 // Blog & Portfolio 144 sober.$body.on( 'click', '.ajax-navigation a', function ( e ) { 145 e.preventDefault(); 146 147 var $button = $( this ), 148 $nav = $button.parent(), 149 $main = $( '#main' ), 150 url = $button.attr( 'href' ); 151 152 if ( $nav.hasClass( 'loading' ) ) { 153 return; 154 } 155 156 $nav.addClass( 'loading' ); 157 158 $.get( 159 url, 160 function ( response ) { 161 var $response = $( response ), 162 nextTitle = $response.filter( 'title' ).text(); 163 164 if ( $nav.hasClass( 'posts-navigation' ) ) { 165 var $content = $( $response.find( '#main' ).html() ); 166 $content.hide(); 167 168 $main.append( $content ); 169 $content.fadeIn( 1000 ); 170 $nav.remove(); 171 } else if ( $nav.hasClass( 'portfolio-navigation' ) ) { 172 var $items = $response.find( '.portfolio-items .portfolio' ), 173 $link = $response.find( '.ajax-navigation a' ); 174 175 if ( $items.length ) { 176 $items.imagesLoaded( function () { 177 $main.find( '.portfolio-items' ).isotope( 'insert', $items ); 178 } ); 179 $nav.removeClass( 'loading' ); 180 181 if ( $link.length ) { 182 $nav.html( $link ); 183 } else { 184 $nav.fadeOut(); 185 } 186 } 187 } 188 189 window.history.pushState( null, nextTitle, url ); 190 } 191 ); 192 } ); 193 194 // Shop 195 if ( 'ajax' === sober.data.shop_nav_type || 'infinity' === sober.data.shop_nav_type ) { 196 sober.$body.on( 'click', '.woocommerce-pagination .next', function ( e ) { 197 e.preventDefault(); 198 199 var $button = $( this ), 200 $nav = $button.closest( '.woocommerce-pagination' ), 201 $products = $nav.prev( 'ul.products' ), 202 url = $button.attr( 'href' ); 203 204 if ( $button.hasClass( 'loading' ) ) { 205 return; 206 } 207 208 $button.addClass( 'loading' ); 209 210 load_products( url, $products, function ( response ) { 211 var $pagination = $( response ).find( '.woocommerce-pagination' ); 212 213 if ( $pagination.length ) { 214 $nav.html( $pagination.html() ); 215 } else { 216 $nav.html( '' ); 217 } 218 } ); 219 } ); 220 } 221 222 // Infinity Shop 223 if ( 'infinity' === sober.data.shop_nav_type ) {
224 var $nav = $( '.woocommerce-pagination' ), 225 $button = $nav.find( '.next' ), 226 $products = $( 'ul.products' ); 227 228 if ( $button.length ) { 229 // Use this variable to control scroll event handle for better performance 230 var waiting = false, 231 endScrollHandle; 232 233 sober.$window.on( 'scroll', function () { 234 if ( waiting ) { 235 return; 236 } 237 238 waiting = true; 239 240 // clear previous scheduled endScrollHandle 241 clearTimeout( endScrollHandle ); 242 243 infiniteScoll(); 244 245 setTimeout( function () { 246 waiting = false; 247 }, 100 ); 248 249 // schedule an extra execution of infiniteScoll() after 200ms 250 // in case the scrolling stops in next 100ms 251 endScrollHandle = setTimeout( function () { 252 infiniteScoll(); 253 }, 200 ); 254 } ); 255 } 256 257 var infiniteScoll = function () { 258 // When almost reach to nav and new next button is exists 259 if ( sober.isVisible( $nav ) && $button.length ) { 260 if ( $button.hasClass( 'loading' ) ) { 261 return; 262 } 263 264 $button.addClass( 'loading' ); 265 266 load_products( $button.attr( 'href' ), $products, function ( response ) { 267 var $pagination = $( response ).find( '.woocommerce-pagination' ); 268 269 if ( $pagination.length ) { 270 $nav.html( $pagination.html() ); 271 272 // Re-select because DOM has been changed 273 $button = $nav.find( '.next' ); 274 } else { 275 $nav.html( '' ); 276 $button.length = 0; 277 } 278 } ); 279 } 280 } 281 } 282 283 /** 284 * Private function for ajax loading product 285 * 286 * @param url 287 * @param $holder 288 * @param callback 289 */ 290 function load_products( url, $holder, callback ) { 291 $.get( 292 url, 293 function ( response ) { 294 var $primary = $( response ).find( '#primary' ), 295 $_products = $primary.find( 'ul.products' ).children(); 296 297 $_products.imagesLoaded( function () { 298 $holder.isotope( 'insert', $_products ); 299 300 if ( 'function' === typeof callback ) { 301 callback( response ); 302 } 303 } ); 304 305 window.history.pushState( null, '', url ); 306 } 307 ); 308 } 309 }; 310 311 /** 312 * Close topbar 313 */ 314 sober.closeTopbar = function () { 315 $( '#topbar' ).on( 'click', '.close', function ( e ) { 316 e.preventDefault(); 317 318 $( this ).closest( '#topbar' ).slideUp(); 319 } ); 320 }; 321 322 /** 323 * Main navigation sub-menu hover 324 */ 325 sober.menuHover = function () { 326 var animations = { 327 none : ['show', 'hide'], 328 fade : ['fadeIn', 'fadeOut'], 329 slide: ['slideDown', 'slideUp'] 330 }; 331 332 var animation = sober.data.menu_animation ? animations[sober.data.menu_animation] : 'fade'; 333 334 $( '.site-navigation li, .topbar-menu li' ).on( 'mouseenter', function () { 335 $( this ).addClass( 'active' ).children( '.sub-menu' ).stop( true, true )[animation[0]](); 336 } ).on( 'mouseleave', function () { 337 $( this ).removeClass( 'active' ).children( '.sub-menu' ).stop( true, true )[animation[1]](); 338 } ); 339 }; 340 341 /** 342 * Toggle modal 343 */ 344 sober.toggleModal = function () { 345 sober.$body.on( 'click', '[data-toggle="modal"]', function ( e ) { 346 e.preventDefault(); 347 348 var $el = $( this ), 349 $target = $( '#' + $el.data( 'target' ) ), 350 tab = $el.data( 'tab' ); 351 352 if ( !$target.length ) { 353 return; 354 } 355 356 sober.openModal( $target, tab ); 357 } ); 358 359 sober.$body.on( 'click', '.close-modal, .sober-modal-backdrop', function ( e ) { 360 e.preventDefault(); 361 362 sober.closeModal(); 363 } ); 364 365 // Close when press escape button 366 $( document ).on( 'keyup', function ( e ) { 367 if ( e.keyCode === 27 ) { 368 sober.closeModal(); 369 } 370 } ); 371 }; 372 373 /** 374 * Open modal 375 * 376 * @param $modal 377 * @param tab 378 */ 379 sober.openModal = function ( $modal, tab ) { 380 $modal = $modal instanceof jQuery ? $modal : $( $modal ); 381 382 if ( ! $modal.length ) { 383 return; 384 } 385 386 sober.$body.addClass( 'modal-open' ); 387 $modal.fadeIn(); 388 $modal.addClass( 'open' ); 389 390 if ( tab ) { 391 var $tab = $modal.find( '.tab-nav' ).filter( '[data-tab="' + tab + '"]' ); 392 393 $tab.trigger( 'click' ); 394 } 395 }; 396 397 /** 398 * Close modal 399 */ 400 sober.closeModal = function () { 401 sober.$body.removeClass( 'modal-open' ); 402 403 var $opened = $( '.sober-modal.open' ); 404 405 $opened.fadeOut( function () { 406 $( this ).removeClass( 'open' ); 407 } ); 408 409 sober.$body.trigger( 'sober_modal_closed', [$opened] ); 410 }; 411 412 /* 413 * Remove Cart Item 414 */ 415 sober.removeCartItem = function () { 416 var $cartModal = $( '#cart-modal' ); 417 418 $cartModal.on( 'click', '.remove', function ( e ) { 419 e.preventDefault(); 420 $cartModal.addClass( 'loading' ); 421 sober.block( $cartModal ); 422 var currentURL = $( this ).attr( 'href' ); 423 424 $.ajax( { 425 type : 'GET', 426 url : currentURL, 427 dataType: 'html', 428 success : function () { 429 $( document.body ).trigger( 'wc_fragment_refresh' ); 430 431 $( document.body ).on( 'wc_fragments_refreshed', function () { 432 $cartModal.removeClass( 'loading' ); 433 sober.unblock( $cartModal ); 434 } ); 435 } 436 } ); 437 } ); 438 }; 439 440 /** 441 * Toggle side menu and its' child items 442 */ 443 sober.toggleSideMenu = function () { 444 // Toggle side menu 445 sober.$body.on( 'click', '.toggle-nav', function () { 446 var target = '#' + $( this ).data( 'target' ); 447 448 $( target ).toggleClass( 'open' ); 449 sober.$body.toggleClass( 'side-menu-opened' ); 450 } ); 451 452 // Close when click to backdrop 453 sober.$body.on( 'click touchstart', '.side-menu-backdrop', function () { 454 $( '.side-menu' ).removeClass( 'open' ); 455 sober.$body.removeClass( 'side-menu-opened' ); 456 } ); 457 458 // Add class 'open' to current menu item 459 sober.$sideMenu.find( '.menu > .menu-item-has-children, .menu > ul > .menu-item-has-children' ).filter( function () { 460 return $( this ).hasClass( 'current-menu-item' ) || $( this ).hasClass( 'current-menu-ancestor' ); 461 } ).addClass( 'open' ); 462 463 // Toggle sub-menu 464 sober.$sideMenu.on( 'click', '.menu > .menu-item-has-children > a, .menu > ul > .menu-item-has-children > a', function ( e ) { 465 e.stopPropagation(); 466 e.preventDefault(); 467 468 $( this ).parent().toggleClass( 'open' ).children( 'ul' ).slideToggle(); 469 $( this ).parent().siblings( '.open' ).removeClass( 'open' ).children( 'ul' ).slide
469Up(); 470 } ); 471 }; 472 473 /** 474 * Focusing inputs and adds 'active' class 475 */ 476 sober.focusInputs = function () { 477 478 $( '.woocommerce-account, .woocommerce-checkout' ).on( 'focus', '.input-text', function () { 479 $( this ).closest( '.form-row' ).addClass( 'active' ); 480 } ).on( 'focusout', '.input-text', function () { 481 if ( $( this ).val() === '' ) { 482 $( this ).closest( '.form-row' ).removeClass( 'active' ); 483 } 484 } ).find( '.input-text' ).each( function () { 485 if ( $( this ).val() !== '' ) { 486 $( this ).closest( '.form-row' ).addClass( 'active' ); 487 } 488 } ); 489 490 491 $( '#commentform' ).on( 'focus', ':input', function () { 492 $( this ).closest( 'p' ).addClass( 'active' ); 493 } ).on( 'focusout', ':input', function () { 494 if ( $( this ).val() === '' ) { 495 $( this ).closest( 'p' ).removeClass( 'active' ); 496 } 497 } ).find( ':input' ).each( function () { 498 if ( $( this ).val() !== '' ) { 499 $( this ).closest( 'p' ).addClass( 'active' ); 500 } 501 } ); 502 503 }; 504 505 /** 506 * Toggle tabs 507 */ 508 sober.toggleTabs = function () { 509 sober.$body.on( 'click', '.tabs-nav .tab-nav', function () { 510 var $tab = $( this ), 511 tab = $tab.data( 'tab' ); 512 513 if ( $tab.hasClass( 'active' ) ) { 514 return; 515 } 516 517 $tab.addClass( 'active' ).siblings( '.active' ).removeClass( 'active' ); 518 $tab.closest( '.tabs-nav' ).next( '.tab-panels' ) 519 .children( '[data-tab="' + tab + '"]' ).addClass( 'active' ) 520 .siblings( '.active' ).removeClass( 'active' ); 521 } ) 522 }; 523 524 /** 525 * Make products filterable with Isotope 526 */ 527 sober.filterProducts = function () { 528 $( 'body.archive ul.products' ).imagesLoaded( function () { 529 $( this.elements ).isotope( { 530 itemSelector : '.product', 531 transitionDuration: 700, 532 layoutMode : 'fitRows', 533 isOriginLeft : !(sober.data.isRTL === '1') 534 } ); 535 } ); 536 537 $( '.products-filter' ).on( 'click', 'li', function ( e ) { 538 e.preventDefault(); 539 540 var $this = $( this ), 541 selector = $this.attr( 'data-filter' ); 542 543 if ( $this.hasClass( 'active' ) ) { 544 return; 545 } 546 var q = $.query; 547 // https://github.com/alrusdi/jquery-plugin-query-object 548 switch(selector) { 549 case 'remarquables': 550 q = $.query.set("paged", '1').REMOVE("product_cat").set("product_cat", 'remarquables').set("filtre", '1').REMOVE("woof_new").REMOVE("stock").set("stock", 'instock'); 551 break; 552 case 'soldes': 553 q = $.query.set("paged", '1').REMOVE("product_cat").set("product_cat", 'promotion-10,promotion-30,promotion-50').set("filtre", '1').REMOVE("woof_new").REMOVE("stock").set("stock", 'instock'); 554 break; 555 case 'new': 556 q = $.query.set("paged", '1').set("woof_new", '1').set("filtre", '1').REMOVE("product_cat").REMOVE("stock").set("stock", 'instock'); 557 break; 558 case 'vendus': 559 q = $.query.set("paged", '1').REMOVE("stock").set("stock", 'outofstock').set("filtre", '1').REMOVE("product_cat").REMOVE("woof_new"); 560 break; 561 default: 562 q = $.query.empty().set("filtre", '1').set("stock", 'instock'); 563 break; 564 } 565 566 $this.addClass( 'active' ).siblings( '.active' ).removeClass( 'active' ); 567 window.location.search = q; 568 // if (selector != "") 569 // location.href = "/catalogue/?"+selector; 570 // else 571 // location.href = "/catalogue/"; 572 // $this.closest( '.shop-toolbar' ).next( 'ul.products' ).isotope( { 573 // filter: selector 574 // } ); 575 } ); 576 }; 577 578 /** 579 * Use select2 to styling the dropdown of the ordring 580 */ 581 sober.sortProducts = function() { 582 if ( ! $.fn.select2 ) { 583 return; 584 } 585 586 $( '.woocommerce-ordering select' ).select2( { 587 minimumResultsForSearch: -1, 588 width: 'auto', 589 dropdownAutoWidth: true 590 } ); 591 }; 592 593 /** 594 * Change product quantity 595 */ 596 sober.productQuantity = function () { 597 sober.$body.on( 'click', '.quantity .increase, .quantity .decrease', function ( e ) { 598 e.preventDefault(); 599 600 var $this = $( this ), 601 $qty = $this.siblings( '.qty' ), 602 current = parseInt( $qty.val(), 10 ), 603 min = parseInt( $qty.attr( 'min' ), 10 ), 604 max = parseInt( $qty.attr( 'max' ), 10 ); 605 606 min = min ? min : 1; 607 max = max ? max : current + 1; 608 609 if ( $this.hasClass( 'decrease' ) && current > min ) { 610 $qty.val( current - 1 ); 611 $qty.trigger( 'change' ); 612 } 613 if ( $this.hasClass( 'increase' ) && current < max ) { 614 $qty.val( current + 1 ); 615 $qty.trigger( 'change' ); 616 } 617 } ); 618 }; 619 620 /** 621 * Make up sells products be sticky 622 */
623 sober.stickUpSells = function () { 624 if ( !sober.$body.hasClass( 'product-style-3' ) ) { 625 return; 626 } 627 628 var $topbar = $( '#topbar' ), 629 $header = $( '#masthead' ), 630 $upsells = $( '.upsells' ); 631 632 if ( !$upsells.length ) { 633 return; 634 } 635 636 var $primary = $( '#primary' ); 637 638 var offset = $topbar.length ? $topbar.outerHeight() : 0; 639 offset += $header.length ? $header.outerHeight() : 0; 640 641 $( window ).on( 'scroll', function () { 642 if ( $( document ).scrollTop() >= offset ) { 643 $upsells.addClass( 'sticky' ); 644 645 if ( !$upsells.data( 'wrap' ) ) { 646 $upsells.wrap( '<div id="upsells-wrap" class="upsells-wrap"/>' ); 647 $upsells.data( 'wrap', true ); 648 } 649 } else { 650 $upsells.removeClass( 'sticky' ); 651 652 if ( $upsells.data( 'wrap' ) ) { 653 $upsells.unwrap(); 654 $upsells.data( 'wrap', false ); 655 } 656 } 657 658 if ( $( window ).scrollTop() >= $primary.offset().top + $primary.outerHeight() - window.innerHeight ) { 659 var $wrap = $( '#upsells-wrap' ); 660 661 $wrap.addClass( 'sticky-bottom' ).css( 'top', function () { 662 return $( window ).scrollTop() - $primary.offset().top; 663 } ); 664 665 if ( $wrap.outerHeight() <= $upsells.outerHeight() ) { 666 $wrap.addClass( 'reach-bottom' ); 667 } else { 668 $wrap.removeClass( 'reach-bottom' ); 669 } 670 } else { 671 $( '#upsells-wrap' ).removeClass( 'sticky-bottom' ).css( 'top', 0 ); 672 } 673 } ).trigger( 'scroll' ); 674 }; 675 676 /** 677 * Prepare and init carousel for up sell products 678 */ 679 sober.upsellsCarousel = function () { 680 if ( !sober.$body.hasClass( 'product-style-3' ) ) { 681 return; 682 } 683 684 var $upsells = $( '.upsells' ); 685 686 if ( !$upsells.length ) { 687 return; 688 } 689 690 if ( $upsells.find( 'li.product' ).length > 4 ) { 691 $upsells.find( 'ul.products' ).addClass( 'owl-carousel' ).owlCarousel( { 692 rtl : sober.data.isRTL === "1", 693 owl2row : true, 694 owl2rowTarget: 'product', 695 dots : true, 696 nav : true, 697 navText : ['<svg viewBox="0 0 20 20"><use xlink:href="#left-arrow"></use></svg>', '<svg viewBox="0 0 20 20"><use xlink:href="#right-arrow"></use></svg>'], 698 items : 2, 699 responsive : { 700 0 : { 701 items: 1 702 }, 703 992 : { 704 items: 1 705 }, 706 1200: { 707 items: 2 708 } 709 } 710 } ); 711 } 712 }; 713 714 /** 715 * Show photoSwipe lightbox for product images 716 */ 717 sober.productImagesLightbox = function () { 718 if ( 'no' === sober.data.lightbox || '0' === sober.data.lightbox ) { 719 return; 720 } 721 722 var $gallery = $( 'div.product div.images' ), 723 $slides = $( '.woocommerce-product-gallery__slider .woocommerce-product-gallery__image', $gallery ); 724 725 if ( !$gallery.length ) { 726 return; 727 } 728 729 $gallery.on( 'click', '.woocommerce-product-gallery__slider .woocommerce-product-gallery__image a', function ( e ) { 730 e.preventDefault(); 731 732 var items = getGalleryItems(), 733 $target = $( e.target ), 734 $clicked = $target.closest( '.owl-item' ), 735 options = { 736 index : $clicked.length ? $clicked.index() : $target.closest( '.woocommerce-product-gallery__image' ).index(), 737 history : false, 738 bgOpacity : 0.85, 739 showHideOpacity : true, 740 mainClass : 'pswp--minimal-dark', 741 captionEl : true, 742 fullscreenEl : false, 743 shareEl : false, 744 tapToClose : true, 745 tapToToggleControls: false 746 }; 747 748 var lightBox = new PhotoSwipe( $( '.pswp' ).get(0), window.PhotoSwipeUI_Default, items, options ); 749 lightBox.init(); 750 } ); 751 752 /** 753 * Private function to get gallery items 754 * @returns {Array} 755 */ 756 function getGalleryItems() { 757 var items = []; 758 759 if ( $slides.length > 0 ) { 760 $slides.each( function( i, el ) { 761 var img = $( el ).find( 'img' ), 762 large_image_src = img.attr( 'data-large_image' ), 763 large_image_w = img.attr( 'data-large_image_width' ), 764 large_image_h = img.attr( 'data-large_image_height' ), 765 item = { 766 src : large_image_src, 767 w : large_image_w, 768 h : large_image_h, 769 title: img.attr( 'data-caption' ) ? img.attr( 'data-caption' ) : '' 770 }; 771 items.push( item ); 772 } ); 773 } 774 775 return items; 776 } 777 }; 778 779 /** 780 * Make product summary be sticky when use product layout 1 781 */ 782 sober.stickyProductSummary = function () { 783 if ( $.fn.stick_in_parent && sober.$window.width() > 767 ) { 784 $( 'div.product .sticky-summary' ).stick_in_parent( { 785 parent: '.product-summary' 786 } ); 787 } 788 }; 789 790 /** 791 * Back to top icon 792 */
793 sober.backToTop = function () { 794 sober.$body.on( 'click', '#gotop', function ( e ) { 795 e.preventDefault(); 796 797 $( 'html, body' ).animate( {scrollTop: 0}, 'slow' ); 798 } ); 799 }; 800 801 /** 802 * Toggle product filter widgets 803 */ 804 sober.toggleProductFilter = function () { 805 sober.$body.on( 'click', '.toggle-filter', function ( e ) { 806 e.preventDefault(); 807 808 $( this ).next( '.filter-widgets' ).fadeIn( function () { 809 $( this ).addClass( 'active' ); 810 } ); 811 } ).on( 'click', '.filter-widgets button.close', function () { 812 $( this ).closest( '.filter-widgets' ).fadeOut( function () { 813 $( this ).removeClass( 'active' ); 814 } ); 815 } ); 816 817 }; 818 819 /** 820 * Toggle product quick view 821 */ 822 sober.productQuickView = function () { 823 if ( !sober.$body.hasClass( 'product-quickview-enable' ) ) { 824 return; 825 } 826 827 var target = 'ul.products .woocommerce-LoopProduct-link'; 828 829 switch ( sober.data.quickview ) { 830 case 'buy_button': 831 target = 'ul.products .add_to_cart_button, ul.products .button.product_type_external'; 832 break; 833 834 case 'view_button': 835 target = 'ul.products .quick_view_button'; 836 break; 837 838 case 'title': 839 target = 'ul.products h3 a'; 840 break; 841 } 842 843 sober.$body.on( 'click', target, function ( e ) { 844 if ( sober.$window.width() <= 768 ) { 845 return; 846 } 847 848 e.preventDefault(); 849 850 var $a = $( this ), 851 url = $a.data( 'url' ) ? $a.data( 'url' ) : $a.attr( 'href' ), 852 $modal = $( '#quick-view-modal' ), 853 $product = $modal.find( '.product' ), 854 $button = $modal.find( '.modal-header .close-modal' ).first().clone(); 855 856 $product.hide().html( '' ).addClass( 'invisible' ); 857 $modal.addClass( 'loading' ); 858 sober.openModal( $modal ); 859 860 $.get( url, function ( response ) { 861 var $html = $( response ), 862 $summary = $html.find( '#content' ).find( '.product-summary' ), 863 $gallery = $summary.find( '.images' ), 864 $variations = $summary.find( '.variations_form' ), 865 $carousel = $( '.woocommerce-product-gallery__slider', $gallery ); 866 867 // Remove unused elements 868 $summary.find( '.product-toolbar' ).remove(); 869 $summary.find( 'h1.product_title' ).wrapInner( '<a href="' + url + '"></a>' ); 870 $gallery.find( '.thumbnails' ).remove(); 871 $product.show().html( $summary ).prepend( $button ); 872 873 // Force height for images 874 $carousel.find( 'img' ).css( 'height', $product.outerHeight() ); 875 876 if ( $carousel.children().length > 1 ) { 877 $carousel.addClass( 'owl-carousel' ).owlCarousel( { 878 rtl : sober.data.isRTL === "1", 879 items : 1, 880 smartSpeed: 500, 881 dots : false, 882 nav : true, 883 navText : ['<svg width="20" height="20"><use xlink:href="#left-arrow"></use></svg>', '<svg width="20" height="20"><use xlink:href="#right-arrow"></use></svg>'], 884 } ); 885 } 886 887 $gallery.css( 'opacity', 1 ); 888 889 $carousel.on( 'click', '.woocommerce-product-gallery__image a', function( event ) { 890 event.preventDefault(); 891 } ); 892 893 $variations.wc_variation_form().find( '.variations select:eq(0)' ).change(); 894 895 if ( $.fn.tawcvs_variation_swatches_form ) { 896 $variations.tawcvs_variation_swatches_form(); 897 sober.modifyVariationSwatches( $variations ); 898 } 899 900 $variations.on( 'reset_image found_variation', function() { 901 $carousel.trigger( 'to.owl.carousel', [0] ); 902 } ); 903 904 $modal.removeClass( 'loading' ); 905 $product.removeClass( 'invisible' ); 906 907 if ( typeof SimpleScrollbar !== 'undefined' ) { 908 SimpleScrollbar.initEl( $summary.find( '.summary' ).get( 0 ) ); 909 } 910 911 sober.$body.trigger( 'sober_quickview_opened', [$html, $modal, sober] ); 912 }, 'html' ); 913 914 if ( 'buy_button' === sober.data.quickview ) { 915 return false; // Prevent ajax add to cart 916 } 917 } ); 918 }; 919 920 /** 921 * Product instance search 922 */ 923 sober.instanceSearch = function () { 924 var xhr = null, 925 searchCache = {}, 926 $modal = $( '#search-modal' ), 927 $form = $modal.find( 'form' ),
928 $search = $form.find( 'input.search-field' ), 929 $results = $modal.find( '.search-results' ); 930 931 $modal.on( 'keyup', '.search-field', function ( e ) { 932 var valid = false; 933 934 if ( typeof e.which === 'undefined' ) { 935 valid = true; 936 } else if ( typeof e.which === 'number' && e.which > 0 ) { 937 valid = !e.ctrlKey && !e.metaKey && !e.altKey; 938 } 939 940 if ( !valid ) { 941 return; 942 } 943 944 if ( xhr ) { 945 xhr.abort(); 946 } 947 948 search(); 949 } ).on( 'change', '.product-cats input', function () { 950 if ( xhr ) { 951 xhr.abort(); 952 } 953 954 search(); 955 } ).on( 'click', '.search-reset', function () { 956 if ( xhr ) { 957 xhr.abort(); 958 } 959 960 $results.find( '.woocommerce, .buttons' ).slideUp( function () { 961 $modal.removeClass( 'searching searched found-products found-no-product invalid-length' ); 962 } ); 963 } ).on( 'focusout', '.search-field', function () { 964 if ( $search.val().length < 2 ) { 965 $results.find( '.woocommerce, .buttons' ).slideUp( function () { 966 $modal.removeClass( 'searching searched found-products found-no-product invalid-length' ); 967 } ); 968 } 969 } ); 970 971 /** 972 * Private function for search 973 */ 974 function search() { 975 var keyword = $search.val(); 976 977 if ( keyword.length < 2 ) { 978 $modal.removeClass( 'searching found-products found-no-product' ).addClass( 'invalid-length' ); 979 return; 980 } 981 982 var url = $form.attr( 'action' ) + '?' + $form.serialize(); 983 984 $modal.removeClass( 'found-products found-no-product' ).addClass( 'searching' ); 985 986 if ( keyword in searchCache ) { 987 var result = searchCache[keyword]; 988 989 $modal.removeClass( 'searching' ); 990 991 if ( result.found ) { 992 $modal.addClass( 'found-products' ); 993 994 $results.find( '.woocommerce' ).html( result.products ); 995 $results.find( '.buttons a' ).attr( 'href', url ); 996 997 $results.find( '.woocommerce, .buttons' ).slideDown( function () { 998 $modal.removeClass( 'invalid-length' ); 999 } ); 1000 } else { 1001 $modal.addClass( 'found-no-product' ); 1002 1003 $results.find( '.woocommerce' ).html( $( '<div class="not-found text-center" />' ).text( result.text ) ); 1004 $results.find( '.buttons a' ).attr( 'href', '#' ); 1005 1006 $results.find( '.buttons' ).slideUp(); 1007 $results.find( '.woocommerce' ).slideDown( function () { 1008 $modal.removeClass( 'invalid-length' ); 1009 } ); 1010 } 1011 1012 $modal.addClass( 'searched' ); 1013 } else { 1014 xhr = $.get( url, function ( response ) { 1015 var $html = $( response ), 1016 $products = $html.find( '#content #primary ul.products' ), 1017 $info = $html.find( '#content #primary .woocommerce-info' ); 1018 1019 $modal.removeClass( 'searching' ); 1020 1021 if ( $products.length ) { 1022 $products.children( '.last' ).nextAll().remove(); 1023 1024 $modal.addClass( 'found-products' ); 1025 1026 $results.find( '.woocommerce' ).html( $products ); 1027 $results.find( '.buttons a' ).attr( 'href', url ); 1028 1029 $results.find( '.woocommerce, .buttons' ).slideDown( function () { 1030 $modal.removeClass( 'invalid-length' ); 1031 } ); 1032 1033 // Cache 1034 searchCache[keyword] = { 1035 found : true, 1036 products: $products 1037 }; 1038 } else if ( $info.length ) { 1039 $modal.addClass( 'found-no-product' ); 1040 1041 $results.find( '.woocommerce' ).html( $( '<div class="not-found text-center" />' ).text( $info.text() ) ); 1042 $results.find( '.buttons a' ).attr( 'href', '#' ); 1043 1044 $results.find( '.buttons' ).slideUp(); 1045 $results.find( '.woocommerce' ).slideDown( function () { 1046 $modal.removeClass( 'invalid-length' ); 1047 } ); 1048 1049 // Cache 1050 searchCache[keyword] = { 1051 found: false, 1052 text : $info.text() 1053 }; 1054 } 1055 1056 $modal.addClass( 'searched' ); 1057 }, 'html' ); 1058 } 1059 } 1060 }; 1061 1062 /** 1063 * Init simple scrollbar 1064 */ 1065 sober.fakeScrollbar = function () { 1066 var el = document.querySelector( '.primary-menu.side-menu' ); 1067 1068 if ( el && typeof SimpleScrollbar !== 'undefined' ) { 1069 SimpleScrollbar.initEl( el ); 1070 } 1071 }; 1072 1073 /** 1074 * Sticky header 1075 */ 1076 sober.stickyHeader = function () { 1077 if ( !sober.data.sticky_header || 'none' === sober.data.sticky_header ) { 1078 return; 1079 } 1080 1081 var header = document.getElementById( 'masthead' ); 1082 var topbar = document.getElementById( 'topbar' ); 1083 var offset = 0; 1084 1085 // Prepare for white header 1086 if ( 1087 sober.$body.hasClass( 'header-white' ) 1088 || ( sober.$body.hasClass( 'no-page-header' ) && !sober.$body.hasClass( 'page-title-hidden' ) && !sober.$body.hasClass( 'page-template-homepage' ) ) 1089 ) { 1090 if ( topbar ) { 1091 topbar.style.marginBottom = header.clientHeight + 'px'; 1092 } else { 1093 document.getElementById( 'page' ).style.paddingTop = header.clientHeight + 'px'; 1094 } 1095 } 1096 1097 if ( 'smart' === sober.data.sticky_header && typeof Headroom !== 'undefined' ) { 1098 offset = topbar ? topbar.clientHeight : 1; 1099 1100 var stickyHeader = new Headroom( header, { 1101 offset : offset, 1102 onTop : function () { 1103 setTimeout( function () { 1104 header.classList.remove( 'headroom--animation' ); 1105 }, 500 ); 1106 }, 1107 onNotTop: function () { 1108 setTimeout( function () { 1109 header.classList.add( 'headroom--animation' ); 1110 }, 10 ); 1111 } 1112 } ); 1113 1114 stickyHeader.init(); 1115 } else if ( 'normal' === sober.data.sticky_header ) { 1116 offset = topbar ? topbar.clientHeight : 1; 1117 sticky(); 1118 1119 sober.$window.on( 'scroll', function () { 1120 sticky(); 1121 } ); 1122 } 1123 1124 /** 1125 * Private function for sticky header 1126 */ 1127 function sticky() { 1128 if ( sober.$window.scrollTop() >= offset ) { 1129 header.classList.add( 'sticky' ); 1130 } else { 1131 header.classList.remove( 'sticky' ); 1132 } 1133 } 1134 }; 1135 1136 /** 1137 * Initialize isotope for portfolio items 1138 */ 1139 sober.portfolioFilter = function () { 1140 var $items = $( '.portfolio-items' ); 1141 1142 if ( !$items.length ) { 1143 return; 1144 } 1145 1146 var options = { 1147 itemSelector : '.portfolio', 1148 transitionDuration: 700, 1149 isOriginLeft : !(sober.data.isRTL === '1') 1150 }; 1151 1152 if ( sober.$body.hasClass( 'portfolio-fullwidth' ) ) { 1153 options.masonry = { 1154 columnWidth: '.col-md-3' 1155 }; 1156 } 1157 1158 $items.imagesLoaded( function () { 1159 $( this.elements ).isotope( options ); 1160 } ); 1161 1162 var $filter = $( '.portfolio-filter' ); 1163 1164 $filter.on( 'click', 'li', function ( e ) { 1165 e.preventDefault(); 1166 1167 var $this = $( this ), 1168 selector = $this.attr( 'data-filter' ); 1169 1170 if ( $this.hasClass( 'active' ) ) { 1171 return; 1172 } 1173 1174 $this.addClass( 'active' ).siblings( '.active' ).removeClass( 'active' ); 1175 $this.closest( '.portfolio-filter' ).next( '.portfolio-items' ).isotope( { 1176 filter: selector 1177 } ); 1178 } ); 1179 }; 1180 1181 /** 1182 * Add extra script for product variation swatches 1183 * This function will run after plugin swatches did 1184 */ 1185 sober.productVariationSwatches = function () { 1186 sober.$body.on( 'tawcvs_initialized', function () { 1187 var $form = $( '.variations_form' ); 1188 1189 sober.modifyVariationSwatches( $form ); 1190 } ); 1191 }; 1192 1193 /** 1194 * Modify variation swatches 1195 * This function is used in sober.productVariationSwatches and sober.productQuickView 1196 * 1197 * @param $form 1198 */ 1199 sober.modifyVariationSwatches = function ( $form ) { 1200 var $variables = $form.find( '.variations .variable' ); 1201 1202 // Remove class "swatches-support" if there is no swatches in this product 1203 var hasSwatches = false;
1204 $variables.each( function() { 1205 if ( $( this ).hasClass( 'swatches' ) ) { 1206 hasSwatches = true; 1207 } 1208 } ); 1209 1210 if ( ! hasSwatches ) { 1211 $form.removeClass( 'swatches-support' ); 1212 } 1213 1214 // Add class for the last even variation 1215 if ( $variables.length % 2 ) { 1216 $variables.last().addClass( 'wide-variable' ); 1217 } 1218 1219 // Change alert style 1220 $form.off( 'tawcvs_no_matching_variations' ); 1221 $form.on( 'tawcvs_no_matching_variations', function () { 1222 event.preventDefault(); 1223 1224 $form.find( '.woocommerce-variation.single_variation' ).show(); 1225 if ( typeof wc_add_to_cart_variation_params !== 'undefined' ) { 1226 $form.find( '.single_variation' ).stop( true, true ).slideDown( 500 ).html( '<p class="invalid-variation-combination">' + wc_add_to_cart_variation_params.i18n_no_matching_variations_text + '</p>' ); 1227 } 1228 } ); 1229 }; 1230 1231 /** 1232 * Init product gallery as a slider 1233 */ 1234 sober.productGallerySlider = function() { 1235 if ( ! sober.$body.hasClass( 'single-product' ) ) { 1236 return; 1237 } 1238 1239 var $gallery = $( 'div.product div.images' ), 1240 $carousel = $( '.woocommerce-product-gallery__slider', $gallery ), 1241 $thumbnails = $( '.thumbnails', $gallery ); 1242 1243 if ( !sober.$body.hasClass( 'product-style-1' ) && !sober.$body.hasClass( 'product-style-4' ) && $carousel.children().length > 1 && !$carousel.hasClass( 'owl-loaded' ) ) { 1244 $carousel.addClass( 'owl-carousel' ).owlCarousel( { 1245 rtl : sober.data.isRTL === "1", 1246 dots : false, 1247 items : 1, 1248 loop : false, 1249 responsive: { 1250 0: { 1251 items: 1 1252 } 1253 } 1254 } ); 1255 } 1256 1257 if ( sober.$body.hasClass( 'product-style-1' ) && $carousel.children().length > 1 ) { 1258 if ( sober.$window.width() < 992 && ! $carousel.hasClass( 'owl-carousel' ) ) { 1259 $carousel.addClass( 'owl-carousel' ).owlCarousel( { 1260 rtl : sober.data.isRTL === "1", 1261 items : 1, 1262 loop : false, 1263 margin : 10, 1264 responsive: { 1265 0: { 1266 items: 1 1267 } 1268 } 1269 } ); 1270 } else if ( sober.$window.width() >= 992 && $carousel.hasClass( 'owl-carousel' ) ) { 1271 $carousel.trigger( 'destroy.owl.carousel' ).removeClass( 'owl-carousel' ); 1272 } 1273 } 1274 1275 if ( sober.$body.hasClass( 'product-style-4' ) && $carousel.children().length > 1 ) { 1276 var start = $carousel.children().length > 2 ? 1 : 0; 1277 1278 $carousel.addClass( 'owl-carousel' ).owlCarousel( { 1279 rtl : sober.data.isRTL === "1", 1280 items : 2, 1281 startPosition: start, 1282 loop : false, 1283 margin: 30, 1284 center: true, 1285 dots: false, 1286 nav: true, 1287 navText: ['<svg viewBox="0 0 20 20"><use xlink:href="#left-arrow"></use></svg>', '<svg viewBox="0 0 20 20"><use xlink:href="#right-arrow"></use></svg>'] 1288 } ); 1289 } 1290 1291 // Show it 1292 $gallery.css( 'opacity', 1 ); 1293 1294 // Use thumbnails as pagination 1295 $gallery.on( 'click', '.thumbnails .woocommerce-product-gallery__image a', function( event ) { 1296 event.preventDefault(); 1297 1298 var $image = $( this ).closest( '.woocommerce-product-gallery__image' ); 1299 1300 $carousel.trigger( 'to.owl.carousel', [$image.index()] ); 1301 } ); 1302 1303 // Change the active state of thumbnails 1304 $carousel.on( 'translated.owl.carousel', function( event ) { 1305 $thumbnails.children().removeClass( 'active' ).eq( event.item.index ).addClass( 'active' ); 1306 } ); 1307 1308 // Variation form changed 1309 $( '.variations_form' ).on( 'reset_image found_variation', function() { 1310 $carousel.trigger( 'to.owl.carousel', [0] ); 1311 } ).on( 'reset_image', function() { 1312 $thumbnails.children( ':eq(0)' ).find( 'img' ).wc_reset_variation_attr( 'src' ); 1313 } ).on( 'found_variation', function( event, variation ) { 1314 $thumbnails.children( ':eq(0)' ).find( 'img' ).wc_set_variation_attr( 'src', variation.image.thumb_src ); 1315 } ); 1316 }; 1317 1318 /** 1319 * Zoom product image when hover 1320 */ 1321 sober.productImageZoom = function() { 1322 var $thumbnails = $( '.product-thumbnail-zoom' ); 1323 1324 $thumbnails.each( function () { 1325 var $el = $( this ); 1326 1327 $el.zoom( { 1328 url: $el.attr( 'data-zoom_image' ) 1329 } ); 1330 } ); 1331 }; 1332 1333 /** 1334 * Display product thumbnail images as slider 1335 */ 1336 sober.productImageSlider = function() { 1337 $( '.product-images__slider' ).owlCarousel( { 1338 items: 1, 1339 lazyLoad: true, 1340 dots: false, 1341 nav: true, 1342 navText: ['<svg viewBox="0 0 14 20"><use xlink:href="#left"></use></svg>', '<svg viewBox="0 0 14 20"><use xlink:href="#right"></use></svg>'] 1343 } ); 1344 }; 1345 1346 /** 1347 * Ajaxify add to cart button on single product page 1348 */ 1349 sober.singeProductAjaxAddToCart = function () { 1350 if ( 'yes' !== sober.data.single_ajax_add_to_cart ) { 1351 return; 1352 } 1353 1354 sober.$body.on( 'submit', 'form.cart', function () { 1355 var $form = $( this ), 1356 $button = $form.find( '.single_add_to_cart_button' ), 1357 url = $form.attr( 'action' ) ? $form.attr( 'action' ) : window.location.href; 1358 1359 if ( $button.hasClass( 'loading' ) ) { 1360 return false;
1361 } 1362 1363 $button.removeClass( 'added' ).addClass( 'loading' ); 1364 1365 $.ajax( { 1366 url : url, 1367 data : $form.serialize(), 1368 method : 'POST', 1369 success: function ( response ) { 1370 $button.removeClass( 'loading' ).addClass( 'added' ); 1371 1372 // Show alert bar 1373 if ( sober.data.open_cart_modal_after_add !== '1' ) { 1374 var $message = $( response ).find( '.woocommerce-error, .woocommerce-info, .woocommerce-message' ), 1375 $alert = $( '.sober-alert-bar' ); 1376 1377 if ( !$alert.length ) { 1378 $alert = $( '<div class="sober-alert-bar"></div>' ); 1379 sober.$body.append( $alert ); 1380 } 1381 1382 $alert.html( $message ); 1383 setTimeout( function () { 1384 $alert.addClass( 'active' ); 1385 }, 500 ); 1386 1387 // Auto hide the alert bar after 5 seconds. Apply for success actions only 1388 if ( $message.hasClass( 'woocommerce-message' ) ) { 1389 setTimeout( function () { 1390 $alert.removeClass( 'active' ); 1391 }, 5000 ); 1392 } 1393 } else { 1394 sober.$body.trigger( 'added_to_cart' ); 1395 } 1396 1397 // Trigger fragment refresh 1398 sober.$body.trigger( 'wc_fragment_refresh' ); 1399 1400 if ( typeof wc_add_to_cart_params !== 'undefined' ) { 1401 if ( wc_add_to_cart_params.cart_redirect_after_add === 'yes' && wc_add_to_cart_params.cart_url ) { 1402 window.location.href = wc_add_to_cart_params.cart_url; 1403 } 1404 } 1405 } 1406 } ); 1407 1408 return false; 1409 } ); 1410 1411 // Close alert bar 1412 sober.$body.on( 'click', '.sober-alert-bar .close', function ( e ) { 1413 e.preventDefault(); 1414 1415 $( this ).closest( '.sober-alert-bar' ).removeClass( 'active' ); 1416 } ); 1417 }; 1418 1419 /** 1420 * Open the cart modal after successful addition 1421 */ 1422 sober.openCartModalAfterAdd = function () { 1423 if ( sober.data.open_cart_modal_after_add !== '1' ) { 1424 return; 1425 } 1426 1427 sober.$body.on( 'added_to_cart', function () { 1428 sober.closeModal(); 1429 sober.openModal( '#cart-modal', 'cart' ); 1430 } ); 1431 }; 1432 1433 /** 1434 * Init parallax for page header elements 1435 */ 1436 sober.pageHeaderParallax = function () { 1437 if ( typeof Rellax === 'undefined' ) { 1438 return; 1439 } 1440 1441 var $title = $( '.page-header .page-title' ), 1442 $breadcrumb = $( '.page-header .breadcrumb' ); 1443 1444 if ( 'up' === sober.data.page_header_parallax ) { 1445 if ( $title.length ) { 1446 new Rellax( '.page-header .page-title', {speed: 1} ); 1447 } 1448 if ( $breadcrumb.length ) { 1449 new Rellax( '.page-header .breadcrumb', {speed: 2} ); 1450 } 1451 } else if ( 'down' === sober.data.page_header_parallax ) { 1452 if ( $title.length ) { 1453 new Rellax( '.page-header .page-title', {speed: -2} ); 1454 } 1455 if ( $breadcrumb.length ) { 1456 new Rellax( '.page-header .breadcrumb', {speed: -1} ); 1457 } 1458 } 1459 }; 1460 1461 /** 1462 * Add page preloader 1463 */ 1464 sober.preload = function () { 1465 var $preloader = $( '#preloader' ); 1466 1467 if ( ! $preloader.length ) { 1468 return; 1469 } 1470 1471 sober.$window.on( 'beforeunload', function() { 1472 $preloader.fadeIn( 'slow' ); 1473 }); 1474 1475 $preloader.fadeOut( 800 ); 1476 }; 1477 1478 /** 1479 * Call functions for responsiveness 1480 */ 1481 sober.responsive = function () { 1482 // Initialize fitvids 1483 sober.responsiveVideos(); 1484 1485 // Init/destroy product image carousel for product style 1 1486 sober.$window.on( 'resize', sober.productGallerySlider ); 1487 }; 1488 1489 /** 1490 * Responsive videos 1491 */ 1492 sober.responsiveVideos = function () { 1493 $( document.body ).fitVids(); 1494 }; 1495 1496 /** 1497 * Open popup 1498 */ 1499 sober.popup = function() { 1500 var days = parseInt( sober.data.popup_frequency ), 1501 delay = parseInt( sober.data.popup_visible_delay ); 1502 1503 if ( days > 0 && document.cookie.match( /^(.*;)?\s*sober_popup\s*=\s*[^;]+(.*)?$/ ) ) { 1504 return; 1505 } 1506 1507 delay = Math.max( delay, 0 ); 1508 delay = 'delay' === sober.data.popup_visible ? delay : 0; 1509 1510 sober.$window.on( 'load', function() { 1511 setTimeout( function() { 1512 sober.openModal( '#popup' ); 1513 }, delay * 1000 ); 1514 } ); 1515 1516 sober.$body.on( 'sober_modal_closed', function (event, modal) { 1517 if ( ! modal.hasClass( 'sober-popup' ) ) { 1518 return; 1519 } 1520 1521 var date = new Date(), 1522 value = date.getTime(); 1523 1524 date.setTime( date.getTime() + (days * 24 * 60 * 60 * 1000) ); 1525 1526 document.cookie = 'sober_popup=' + value + ';expires=' + date.toGMTString() + ';path=/'; 1527 } ); 1528 }; 1529 1530 /** 1531 * Show a notification after added a product to cart successfully 1532 */ 1533 sober.addedToCartNotice = function() { 1534 if ( ! sober.data.added_to_cart_notice || ! $.fn.notify ) { 1535 return; 1536 } 1537 1538 $.notify.addStyle( 'sober', { 1539 html: '<div><svg viewBox="0 0 20 20" class="message-icon"><use xlink:href="#success" href="#success"></use></svg><span data-notify-text/></div>' 1540 }); 1541 1542 $( document ).on( 'added_to_cart', function() { 1543 $.notify( sober.data.l10n.added_to_cart_notice, { 1544 autoHideDelay: 2000,
vendor: 8,586 bytes, lines 1545-1814
1545 className: 'success', 1546 style: 'sober', 1547 showAnimation: 'fadeIn', 1548 hideAnimation: 'fadeOut' 1549 } ); 1550 } ); 1551 }; 1552 1553 /** 1554 * Turn off the event handler for terms and conditions link 1555 */ 1556 sober.checkoutTerms = function() { 1557 sober.$body.off( 'click', 'a.woocommerce-terms-and-conditions-link' ); 1558 }; 1559 1560 /** 1561 * Document ready 1562 */ 1563 $( function () { 1564 sober.init(); 1565 } ); 1566})( jQuery ); 1567 1568 1569/** 1570 * jQuery.query - Query String Modification and Creation for jQuery 1571 * Written by Blair Mitchelmore (blair DOT mitchelmore AT gmail DOT com) 1572 * Licensed under the WTFPL (http://sam.zoy.org/wtfpl/). 1573 * Date: 2009/8/13 1574 * 1575 * @author Blair Mitchelmore 1576 * @version 2.2.3 1577 * 1578 **/ 1579new function(settings) { 1580 // Various Settings 1581 var $separator = settings.separator || '&'; 1582 var $spaces = settings.spaces === false ? false : true; 1583 var $suffix = settings.suffix === false ? '' : '[]'; 1584 var $prefix = settings.prefix === false ? false : true; 1585 var $hash = $prefix ? settings.hash === true ? "#" : "?" : ""; 1586 var $numbers = settings.numbers === false ? false : true; 1587 1588 jQuery.query = new function() { 1589 var is = function(o, t) { 1590 return o != undefined && o !== null && (!!t ? o.constructor == t : true); 1591 }; 1592 var parse = function(path) { 1593 var m, rx = /\[([^[]*)\]/g, match = /^([^[]+)(\[.*\])?$/.exec(path), base = match[1], tokens = []; 1594 while (m = rx.exec(match[2])) tokens.push(m[1]); 1595 return [base, tokens]; 1596 }; 1597 var set = function(target, tokens, value) { 1598 var o, token = tokens.shift(); 1599 if (typeof target != 'object') target = null; 1600 if (token === "") { 1601 if (!target) target = []; 1602 if (is(target, Array)) { 1603 target.push(tokens.length == 0 ? value : set(null, tokens.slice(0), value)); 1604 } else if (is(target, Object)) { 1605 var i = 0; 1606 while (target[i++] != null); 1607 target[--i] = tokens.length == 0 ? value : set(target[i], tokens.slice(0), value); 1608 } else { 1609 target = []; 1610 target.push(tokens.length == 0 ? value : set(null, tokens.slice(0), value)); 1611 } 1612 } else if (token && token.match(/^\s*[0-9]+\s*$/)) { 1613 var index = parseInt(token, 10); 1614 if (!target) target = []; 1615 target[index] = tokens.length == 0 ? value : set(target[index], tokens.slice(0), value); 1616 } else if (token) { 1617 var index = token.replace(/^\s*|\s*$/g, ""); 1618 if (!target) target = {}; 1619 if (is(target, Array)) { 1620 var temp = {}; 1621 for (var i = 0; i < target.length; ++i) { 1622 temp[i] = target[i]; 1623 } 1624 target = temp; 1625 } 1626 target[index] = tokens.length == 0 ? value : set(target[index], tokens.slice(0), value); 1627 } else { 1628 return value; 1629 } 1630 return target; 1631 }; 1632 1633 var queryObject = function(a) { 1634 var self = this; 1635 self.keys = {}; 1636 1637 if (a.queryObject) { 1638 jQuery.each(a.get(), function(key, val) { 1639 self.SET(key, val); 1640 }); 1641 } else { 1642 self.parseNew.apply(self, arguments); 1643 } 1644 return self; 1645 }; 1646 1647 queryObject.prototype = { 1648 queryObject: true, 1649 parseNew: function(){ 1650 var self = this; 1651 self.keys = {}; 1652 jQuery.each(arguments, function() { 1653 var q = "" + this; 1654 q = q.replace(/^[?#]/,''); // remove any leading ? || # 1655 q = q.replace(/[;&]$/,''); // remove any trailing & || ; 1656 if ($spaces) q = q.replace(/[+]/g,' '); // replace +'s with spaces 1657 1658 jQuery.each(q.split(/[&;]/), function(){ 1659 var key = decodeURIComponent(this.split('=')[0] || ""); 1660 var val = decodeURIComponent(this.split('=')[1] || ""); 1661 1662 if (!key) return; 1663 1664 if ($numbers) { 1665 if (/^[+-]?[0-9]+\.[0-9]*$/.test(val)) // simple float regex 1666 val = parseFloat(val); 1667 else if (/^[+-]?[1-9][0-9]*$/.test(val)) // simple int regex 1668 val = parseInt(val, 10); 1669 } 1670 1671 val = (!val && val !== 0) ? true : val; 1672 1673 self.SET(key, val); 1674 }); 1675 }); 1676 return self; 1677 }, 1678 has: function(key, type) { 1679 var value = this.get(key); 1680 return is(value, type); 1681 }, 1682 GET: function(key) { 1683 if (!is(key)) return this.keys; 1684 var parsed = parse(key), base = parsed[0], tokens = parsed[1]; 1685 var target = this.keys[base]; 1686 while (target != null && tokens.length != 0) { 1687 target = target[tokens.shift()]; 1688 } 1689 return typeof target == 'number' ? target : target || ""; 1690 }, 1691 get: function(key) { 1692 var target = this.GET(key); 1693 if (is(target, Object)) 1694 return jQuery.extend(true, {}, target); 1695 else if (is(target, Array)) 1696 return target.slice(0); 1697 return target; 1698 }, 1699 SET: function(key, val) { 1700 var value = !is(val) ? null : val; 1701 var parsed = parse(key), base = parsed[0], tokens = parsed[1]; 1702 var target = this.keys[base]; 1703 this.keys[base] = set(target, tokens.slice(0), value); 1704 return this; 1705 }, 1706 set: function(key, val) { 1707 return this.copy().SET(key, val); 1708 }, 1709 REMOVE: function(key, val) { 1710 if (val) { 1711 var target = this.GET(key); 1712 if (is(target, Array)) { 1713 for (tval in target) { 1714 target[tval] = target[tval].toString(); 1715 } 1716 var index = $.inArray(val, target); 1717 if (index >= 0) { 1718 key = target.splice(index, 1); 1719 key = key[index]; 1720 } else { 1721 return; 1722 } 1723 } else if (val != target) { 1724 return; 1725 } 1726 } 1727 return this.SET(key, null).COMPACT(); 1728 }, 1729 remove: function(key, val) { 1730 return this.copy().REMOVE(key, val); 1731 }, 1732 EMPTY: function() { 1733 var self = this; 1734 jQuery.each(self.keys, function(key, value) { 1735 delete self.keys[key]; 1736 }); 1737 return self; 1738 }, 1739 load: function(url) { 1740 var hash = url.replace(/^.*?[#](.+?)(?:\?.+)?$/, "$1"); 1741 var search = url.replace(/^.*?[?](.+?)(?:#.+)?$/, "$1"); 1742 return new queryObject(url.length == search.length ? '' : search, url.length == hash.length ? '' : hash); 1743 }, 1744 empty: function() { 1745 return this.copy().EMPTY(); 1746 }, 1747 copy: function() { 1748 return new queryObject(this); 1749 }, 1750 COMPACT: function() { 1751 function build(orig) { 1752 var obj = typeof orig == "object" ? is(orig, Array) ? [] : {} : orig; 1753 if (typeof orig == 'object') { 1754 function add(o, key, value) { 1755 if (is(o, Array)) 1756 o.push(value); 1757 else 1758 o[key] = value; 1759 } 1760 jQuery.each(orig, function(key, value) { 1761 if (!is(value)) return true; 1762 add(obj, key, build(value)); 1763 }); 1764 } 1765 return obj; 1766 } 1767 this.keys = build(this.keys); 1768 return this; 1769 }, 1770 compact: function() { 1771 return this.copy().COMPACT(); 1772 }, 1773 toString: function() { 1774 var i = 0, queryString = [], chunks = [], self = this; 1775 var encode = function(str) { 1776 str = str + ""; 1777 str = encodeURIComponent(str); 1778 if ($spaces) str = str.replace(/%20/g, "+"); 1779 return str; 1780 }; 1781 var addFields = function(arr, key, value) { 1782 if (!is(value) || value === false) return; 1783 var o = [encode(key)]; 1784 if (value !== true) { 1785 o.push("="); 1786 o.push(encode(value)); 1787 } 1788 arr.push(o.join("")); 1789 }; 1790 var build = function(obj, base) { 1791 var newKey = function(key) { 1792 return !base || base == "" ? [key].join("") : [base, "[", key, "]"].join(""); 1793 }; 1794 jQuery.each(obj, function(key, value) { 1795 if (typeof value == 'object') 1796 build(value, newKey(key)); 1797 else 1798 addFields(chunks, newKey(key), value); 1799 }); 1800 }; 1801 1802 build(this.keys); 1803 1804 if (chunks.length > 0) queryString.push($hash); 1805 queryString.push(chunks.join($separator)); 1806 1807 return queryString.join(""); 1808 } 1809 }; 1810 1811 return new queryObject(location.search, location.hash); 1812 }; 1813}(jQuery.query || {}); // Pass in jQuery.query as settings object 1814
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.