1jQuery(document).ready(function($){ 2 3 var isCartPage = xoo_wsc_params.isCart == '1', 4 isCheckoutPage = xoo_wsc_params.isCheckout == '1'; 5 6 7 var get_wcurl = function( endpoint ) { 8 return xoo_wsc_params.wc_ajax_url.toString().replace( 9 '%%endpoint%%', 10 endpoint 11 ); 12 }; 13 14 15 var Notice = { 16 17 timeout: null, 18 19 markupTimeout: null, 20 21 $cartNoticeCont: function(){ 22 return $('.xoo-wsc-markup').find('.xoo-wsc-notice-container'); 23 }, 24 25 $markupNoticeCont: function(){ 26 return $('.xoo-wsc-markup-notices') 27 }, 28 29 add: function( notice, type = 'success', clearPrevious = true ){ 30 31 if( clearPrevious ){ 32 Notice.$cartNoticeCont().html(''); 33 } 34 35 var noticeHTML = type === 'success' ? xoo_wsc_params.html.successNotice.toString().replace( '%s%', notice ) : xoo_wsc_params.html.errorNotice.toString().replace( '%s%', notice ); 36 37 Notice.$cartNoticeCont().html( noticeHTML ); 38 39 }, 40 41 42 setHTML: function(noticeHTML){ 43 Notice.$cartNoticeCont().add( Notice.$markupNoticeCont() ).html(noticeHTML); 44 }, 45 46 showNotification: function(){ 47 48 if( !cart.isOpen() ){ 49 Notice.showMarkupNotice(); 50 return; 51 } 52 53 Notice.$cartNoticeCont().slideDown(); 54 55 clearTimeout(Notice.timeout); 56 57 Notice.timeout = setTimeout(function(){ 58 Notice.$cartNoticeCont().slideUp('slow'); 59 }, xoo_wsc_params.notificationTime ); 60 61 }, 62 63 64 hideNotification: function(){ 65 Notice.$cartNoticeCont().hide(); 66 }, 67 68 hideMarkupNotice: function(){ 69 Notice.$markupNoticeCont().removeClass('xoo-wsc-active'); 70 }, 71 72 73 showMarkupNotice: function(){ 74 75 var $markupNotice = Notice.$markupNoticeCont(); 76 77 var $noticeCont = $markupNotice.find('.xoo-wsc-notice-container .xoo-wsc-notices'); 78 79 if( !$noticeCont.length || $noticeCont.children().length === 0 ) return; 80 81 setTimeout(function(){$markupNotice.addClass('xoo-wsc-active')},10); 82 83 clearTimeout(Notice.markupTimeout); 84 85 Notice.markupTimeout = setTimeout(function(){ 86 $markupNotice.removeClass('xoo-wsc-active'); 87 },xoo_wsc_params.notificationTime ) 88 } 89 } 90 91 var masonryInitialised = {}; 92 93 function initMasonryLayout( type = '' ){ 94 95 var layouts = { 96 saveLater: {'.xoo-wsc-savl-column': '.xoo-wsc-savl-prod-cont'}, 97 cart: {'.xoo-wsc-pattern-card': '.xoo-wsc-product-cont'}, 98 suggested: {'.xoo-wsc-sp-column ul.xoo-wsc-sp-slider': '.xoo-wsc-sp-prod-cont'} 99 }; 100 101 var initLayouts = {}; 102 103 if( type ){ 104 if( Array.isArray( type ) ){ 105 $.each( type, function(index, type_val ){ 106 initLayouts[ type_val ] = layouts[ type_val ]; 107 } ) 108 } 109 else{ 110 initLayouts[type] = layouts[type]; 111 } 112 113 }else{ 114 initLayouts = layouts; 115 } 116 117 118 $.each( initLayouts, function(type, layout){ 119 120 if( masonryInitialised[type] && document.body.contains( masonryInitialised[type][0] ) ) return true; 121 122 $.each( layout, function(cont, childClass){ 123 if( $(cont).length && $(cont).is(':visible') ){ 124 $(cont).masonry({ 125 // options 126 itemSelector: childClass, 127 columnWidth: childClass, /* Each column takes 50% */ 128 percentPosition: true 129 }); 130 masonryInitialised[type] = $(cont); 131 } 132 }) 133 }) 134 135 136 } 137 138 139 var QuickView = { 140 141 init: function(){ 142 $( document.body ).on( 'found_variation', '.xoo-wsc-qv-container .variations_form', QuickView.onVariationSelect ); 143 $( document.body ).on( 'reset_data hide_variation', '.xoo-wsc-qv-container .variations_form', QuickView.onVariationReset ); 144 }, 145 146 load: function(){ 147 148 var $form = $( document.body ).find('.xoo-wsc-qv-container .variations_form'); 149 150 if( !$form.length ) return; 151 152 $form.each(function () { 153 $(this).wc_variation_form(); 154 $(this).find('.variations select').change(); 155 }); 156 157 }, 158 159 onVariationSelect: function( event, variation ){ 160 161 if( !variation || !variation.image || !variation.image.src ) return; 162 163 const $container = $( this ).closest('.xoo-wsc-qv-container'); 164 const $img = $container.find('.xoo-qv-product-image'); 165 166 QuickView.storeOriginalImageAttrs( $container ); 167 168 $img.attr({ 169 src : variation.image.src, 170 alt : variation.image.alt || '', 171 width : variation.image.src_w || '', 172 height : variation.image.src_h || '' 173 }); 174 175 if( variation.image.srcset ){ 176 $img.attr( 'srcset', variation.image.srcset ); 177 } 178 else{ 179 $img.removeAttr( 'srcset' ); 180 } 181 182 if( variation.image.sizes ){ 183 $img.attr( 'sizes', variation.image.sizes ); 184 } 185 else{ 186 $img.removeAttr( 'sizes' ); 187 } 188 189 }, 190 191 onVariationReset: function(){
192 const $img = $( this ).closest('.xoo-wsc-qv-container').find('.xoo-qv-product-image'); 193 QuickView.resetImage( $img ); 194 }, 195 196 storeOriginalImageAttrs: function( $container ){ 197 198 const $img = $container.find('.xoo-qv-product-image'); 199 200 if( !$img.length || $img.data('xoo-originalized') ) return; 201 202 [ 'src', 'srcset', 'sizes', 'alt', 'width', 'height' ].forEach(function( attr ){ 203 204 $img.attr( 'data-o_' + attr, $img.attr( attr ) || '' ); 205 206 }); 207 208 $img.data('xoo-originalized', true); 209 }, 210 211 resetImage: function( $img ){ 212 213 [ 'src', 'srcset', 'sizes', 'alt', 'width', 'height' ].forEach(function( attr ){ 214 215 const original = $img.attr( 'data-o_' + attr ); 216 217 if( original ){ 218 $img.attr( attr, original ); 219 } 220 else{ 221 $img.removeAttr( attr ); 222 } 223 224 }); 225 226 } 227 228 } 229 230 QuickView.init(); 231 232 class Container{ 233 234 static eventHandlerCalled = false; 235 236 constructor( $modal, container ){ 237 this.$modal = $modal; 238 this.container = container || 'cart'; 239 } 240 241 242 isOpen(){ 243 return this.$modal.hasClass('xoo-wsc-'+this.container+'-active'); 244 } 245 246 eventHandlers(){ 247 $(document.body).on( 'wc_fragments_loaded updated_checkout', this.onCartUpdate.bind(this) ); 248 } 249 250 onCartUpdate(){ 251 this.unblock(); 252 Notice.showNotification(); 253 } 254 255 setAjaxData( data, noticeSection ){ 256 257 var ajaxData = { 258 container: this.container, 259 noticeSection: this.container, 260 isCheckout: isCheckoutPage, 261 isCart: isCartPage 262 } 263 264 265 if( typeof data === 'object' ){ 266 267 $.extend( ajaxData, data ); 268 269 } 270 else{ 271 272 var serializedData = data; 273 274 $.each( ajaxData, function( key, value ){ 275 serializedData += ( '&'+key+'='+value ); 276 } ) 277 278 ajaxData = serializedData; 279 280 } 281 282 return ajaxData; 283 } 284 285 286 toggle( type ){ 287 288 var $activeEls = this.$modal.add( 'body' ).add('html'), 289 activeClass = 'xoo-wsc-'+ this.container +'-active'; 290 291 if( type === 'show' ){ 292 $activeEls.addClass(activeClass); 293 } 294 else if( type === 'hide' ){ 295 $activeEls.removeClass(activeClass); 296 Notice.hideNotification(); 297 } 298 else{ 299 $activeEls.toggleClass(activeClass); 300 } 301 302 303 $(document.body).trigger( 'xoo_wsc_' + this.container + '_toggled', [ type ] ); 304 305 } 306 307 308 block(){ 309 this.$modal.addClass('xoo-wsc-loading'); 310 } 311 312 unblock(){ 313 this.$modal.removeClass('xoo-wsc-loading'); 314 } 315 316 317 refreshMyFragments(){ 318 319 if( xoo_wsc_params.refreshCart === "yes" && typeof wc_cart_fragments_params !== 'undefined' ){ 320 $( document.body ).trigger( 'wc_fragment_refresh' ); 321 return; 322 } 323 324 this.block(); 325 326 $.ajax({ 327 url: get_wcurl( 'xoo_wsc_refresh_fragments' ), 328 type: 'POST', 329 context: this, 330 data: {}, 331 success: function( response ){ 332 this.updateFragments(response); 333 $( document.body ).trigger( 'wc_fragments_refreshed' ); 334 }, 335 complete: function(){ 336 this.unblock(); 337 } 338 }) 339 340 } 341 342 343 updateCartCheckoutPage(){ 344 345 //Refresh checkout page 346 if( isCheckoutPage ){ 347 if( $( 'form.checkout' ).length === 0 ){ 348 location.reload(); 349 return; 350 } 351 $(document.body).trigger("update_checkout"); 352 } 353 354 //Refresh Cart page 355 if( isCartPage ){ 356 $(document.body).trigger("wc_update_cart"); 357 } 358 359 } 360 361 updateFragments( response ){ 362 363 if( response.fragments ){ 364 365 $( document.body ).trigger( 'xoo_wsc_before_loading_fragments', [ response ] ); 366 367 this.block(); 368 369 //Set fragments 370 $.each( response.fragments, function( key, value ) { 371 $( key ).replaceWith( value ); 372 }); 373 374 if( typeof wc_cart_fragments_params !== 'undefined' && ( 'sessionStorage' in window && window.sessionStorage !== null ) ){ 375 376 sessionStorage.setItem( wc_cart_fragments_params.fragment_name, JSON.stringify( response.fragments ) ); 377 localStorage.setItem( wc_cart_fragments_params.cart_hash_key, response.cart_hash ); 378 sessionStorage.setItem( wc_cart_fragments_params.cart_hash_key, response.cart_hash ); 379 380 if ( response.cart_hash ) { 381 sessionStorage.setItem( 'wc_cart_created', ( new Date() ).getTime() ); 382 } 383 384 } 385 386 $( document.body ).trigger( 'wc_fragments_loaded' ); 387 388 this.unblock(); 389 390 } 391 392 if( xoo_wsc_params.refreshCart === "yes" && typeof wc_cart_fragments_params !== 'undefined' ){ 393 this.block(); 394 $( document.body ).trigger( 'wc_fragment_refresh' ); 395 return; 396 } 397 398 } 399 400 } 401 402 403 class Cart extends Container{ 404 405 static isWCAjaxAddToCart = false; 406 407 constructor( $modal ){ 408 409 super( $modal, 'cart' ); 410 411 this.baseQty = 1; 412 this.qtyUpdateDelay = null; 413 this.bodyPosition = false; 414 this.cartLoaded = false; 415 this.blockAddedToCartCalled = false; 416 this.barsData = {}; 417 this.barsWidth = {}; 418 419 this.refreshFragmentsOnPageLoad(); 420 this.eventHandlers(); 421 this.initSlider(); 422 this.toggleBasket(); 423 424 } 425 426 427 refreshFragmentsOnPageLoad(){ 428 if( xoo_wsc_params.fetchCart === 'page_load' ){ 429 setTimeout(function(){ 430 this.refreshMyFragments(); 431 }.bind(this), xoo_wsc_params.fetchDelay ) 432 } 433 } 434 435 eventHandlers(){ 436 437 super.eventHandlers(); 438 439 this.$modal.on( 'click', '.xoo-wsc-chng', this.toggleQty.bind(this) ); 440 this.$modal.on( 'change', '.xoo-wsc-qty', this.changeInputQty.bind(this) ); 441 this.$modal.on( 'click', '.xoo-wsc-undo-item', this.undoItem.bind(this) ); 442 this.$modal.on( 'focusin', '.xoo-wsc-qty', this.saveQtyFocus.bind(this) ); 443 this.$modal.on( 'click', '.xoo-wsc-smr-del', this.deleteIconClick.bind(this) ); 444 this.$modal.on( 'click', '.xoo-wsch-close, .xoo-wsc-opac, .xoo-wsc-cart-close', this.closeCartOnClick.bind(this) ); 445 this.$modal.on( 'click', '.xoo-wsc-basket', this.toggleCart.bind(this) ); 446 447 $( document.body ).on( 'click', '.xoo-wsc-ecl', this.emptyCart.bind(this) ); 448 449 $(document.body).on( 'xoo_wsc_cart_updated', this.updateCartCheckoutPage.bind(this) ); 450 $(document.body).on( 'click', 'a.added_to_cart, .xoo-wsc-cart-trigger', this.openCart.bind(this) ); 451 $(document.body).on( 'added_to_cart ', this.addedToCart.bind(this) ); 452 453 if( xoo_wsc_params.ajaxAddToCart === 'yes' ){ 454 $(document.body).on( 'submit', 'form.cart', this.addToCartFormSubmit.bind(this) ); 455 } 456 457 if( typeof wc_cart_fragments_params === 'undefined' ){ 458 $( window ).on( 'pageshow' , this.onPageShow.bind(this) ); 459 } 460 461 if( xoo_wsc_params.triggerClass ){ 462 $(document.body).on( 'click', '.'+xoo_wsc_params.triggerClass, this.openCart.bind(this) ); 463 } 464 465 466 467 if( isCheckoutPage || isCartPage ){ 468 $(document.body).on( 'updated_shipping_method', this.refreshMyFragments.bind(this) ); 469 } 470 471 $(document.body).on( 'wc-blocks_added_to_cart', this.blockAddedToCart.bind(this) ); 472 473 $(document.body).on( 'adding_to_cart', this.checkIfWCAjaxAddToCart.bind(this) ); 474 475 //Animate shipping bar 476 $(document.body).on( 'xoo_wsc_before_loading_fragments adding_to_cart wc_fragment_refresh', this.storeProgressBarWidth.bind(this) ); 477 478 //$(document.body).on( 'wc_fragments_loaded', this.checkIfWCAjaxAddToCartUnset.bind(this) ); 479 480 initMasonryLayout( ['cart', 'suggested' ] ); 481 482 if( xoo_wsc_params.autoOpenCart === 'yes' && xoo_wsc_params.addedToCart === 'yes'){ 483 this.openCart(); 484 } 485 486 487 this.$modal.on( 'click', '.xoo-wsc-save', this.saveForLater.bind(this) ); 488 489 } 490 491 492 saveForLater(e){ 493 494 if( xoo_wsc_params.saveForLaterNeedsLogin ) return; 495 496 var $product = $(e.currentTarget).closest('.xoo-wsc-product'), 497 cartKey = $product.data('key'), 498 formData = { 499 cart_key: cartKey, 500 } 501 502 this.block(); 503 this.saveScrollPosition(); 504 505 506 $.ajax({
507 url: get_wcurl( 'xoo_wsc_save_for_later' ), 508 type: 'POST', 509 context: this, 510 data: this.setAjaxData(formData), 511 success: function(response){ 512 513 this.updateFragments( response ); 514 515 $(document.body).trigger( 'xoo_wsc_added_to_save_list', [response, cartKey] ); 516 $(document.body).trigger( 'xoo_wsc_cart_updated', [response] ); 517 518 this.setScrollPosition(); 519 this.unblock(); 520 521 var $saveLaterIcon = this.$modal.find('.xoo-wsch-savelater'); 522 523 if( $saveLaterIcon.length ){ 524 $saveLaterIcon.addClass('xoo-wsc-shake-animate'); 525 setTimeout(function(){ 526 $saveLaterIcon.removeClass('xoo-wsc-shake-animate'); 527 },1200); 528 } 529 530 } 531 532 }) 533 534 } 535 536 checkIfWCAjaxAddToCartUnset(){ 537 this.isWCAjaxAddToCart = false; 538 } 539 540 checkIfWCAjaxAddToCart(e, $button, data){ 541 542 Cart.isWCAjaxAddToCart = true; 543 544 if( ( !(data instanceof FormData) || !data.has('action') || !data.get('action') === 'xoo_wsc_add_to_cart' ) && $button.hasClass('ajax_add_to_cart') ){ 545 this.isWCAjaxAddToCart = true; 546 } 547 } 548 549 550 toggleCart(e){ 551 if( this.isOpen() ){ 552 this.closeCartOnClick(e); 553 } 554 else{ 555 this.openCart(e); 556 } 557 558 } 559 560 561 openCart(e){ 562 if( e ){ 563 e.preventDefault(); 564 e.stopImmediatePropagation(); 565 } 566 567 if( !this.cartLoaded && xoo_wsc_params.fetchCart === 'cart_open' ){ 568 this.refreshMyFragments(); 569 this.cartLoaded = true; 570 } 571 572 this.toggle('show'); 573 this.animateProgressBar(); 574 Notice.hideMarkupNotice(); 575 576 } 577 578 addToCartFormSubmit(e){ 579 580 var $form = $(e.currentTarget); 581 582 if( $form.closest('.product').hasClass('product-type-external') || $form.siblings('.xoo-wsc-disable-atc').length ) return; 583 584 var $button = e.originalEvent && e.originalEvent.submitter ? $(e.originalEvent.submitter) : $form.find( 'button[type="submit"]'), 585 formData = new FormData($form.get(0)), 586 productData = $form.serializeArray(), 587 hasProductId = false; 588 589 //Check for woocommerce custom quantity code 590 //https://docs.woocommerce.com/document/override-loop-template-and-show-quantities-next-to-add-to-cart-buttons/ 591 $.each( productData, function( key, form_item ){ 592 if( form_item.name === 'productID' || form_item.name === 'add-to-cart' ){ 593 if( form_item.value ){ 594 hasProductId = true; 595 return false; 596 } 597 } 598 }) 599 600 //If no product id found , look for the form action URL 601 if( !hasProductId && $form.attr('action') ){ 602 var is_url = $form.attr('action').match(/add-to-cart=([0-9]+)/), 603 productID = is_url ? is_url[1] : false; 604 } 605 606 // Add submitted button value 607 if( $button.attr('name') && $button.attr('value') ){ 608 formData.append( $button.attr('name'), $button.attr('value') ); 609 } 610 611 if( productID ){ 612 formData.append( 'add-to-cart', productID ); 613 } 614 615 formData.append( 'action', 'xoo_wsc_add_to_cart' ); 616 617 var doAjaxAddToCart = true; 618 619 620 $.each( xoo_wsc_params.skipAjaxForData, function( key, value ){ 621 if( formData.has(key) && ( !value || formData.get(key) == value ) ){ 622 doAjaxAddToCart = false; 623 return false; 624 } 625 } ) 626 627 628 if( doAjaxAddToCart ){ 629 e.preventDefault(); 630 this.addToCartAjax( $button, formData );//Ajax add to cart 631 } 632 633 } 634 635 636 addToCartAjax( $button, formData ){ 637 638 var cart = this; 639 640 this.block(); 641 642 $button.addClass('loading'); 643 644 // Trigger event. 645 $( document.body ).trigger( 'adding_to_cart', [ $button, formData ] ); 646 647 //formData.append('noticeSection', 'slider'); 648 649 $.ajax({ 650 url: get_wcurl( 'xoo_wsc_add_to_cart' ), 651 type: 'POST', 652 context: this, 653 cache: false, 654 contentType: false, 655 processData: false, 656 data: formData, 657 success: function(response){ 658 659 if(response.fragments){ 660 // Trigger event so themes can refresh other areas. 661 $( document.body ).trigger( 'added_to_cart', [ response.fragments, response.cart_hash, $button ] ); 662 }else if(response.notice ){ 663 Notice.setHTML(response.notice); 664 Notice.showNotification(); 665 } 666 else{ 667 //window.location.reload(); 668 } 669 670 }, 671 complete: function(){ 672 this.unblock(); 673 $button.removeClass('loading').addClass('added'); 674 } 675 }) 676 } 677 678 addedToCart( e, response, hash, $button ){ 679 680 $(document.body).trigger( 'xoo_wsc_cart_updated', [response] ); 681 682 var _this = this; 683 684 this.flyToCart( $button, function(){ 685 if( xoo_wsc_params.autoOpenCart === "yes" ){ 686 setTimeout(function(){ 687 _this.openCart(); 688 },20 ) 689 } 690 } ); 691 } 692 693 694 blockAddedToCart(){ 695 696 if( !Cart.isWCAjaxAddToCart && !this.blockAddedToCartCalled ){ 697 698 this.refreshMyFragments(); 699 700 var _this = this; 701 702 if( xoo_wsc_params.autoOpenCart === "yes" ){ 703 setTimeout(function(){ 704 _this.openCart(); 705 },20 ) 706 } 707 708 this.blockAddedToCartCalled = true; 709 710 setTimeout( function(){ 711 _this.blockAddedToCartCalled = false; 712 }, 200 ); 713 714 Cart.isWCAjaxAddToCart = false; 715 716 } 717 718 719 720 } 721 722 723 flyToCart( $atcEL, callback ){ 724 725 var $basket = this.$modal.find('.xoo-wsc-basket').length ? this.$modal.find('.xoo-wsc-basket') : $(document.body).find('.xoo-wsc-sc-cont'); 726 727 if( !$basket.length || xoo_wsc_params.flyToCart !== 'yes' || !$atcEL || !$atcEL.length ){ 728 callback(); 729 return; 730 } 731 732 var customDragImgClass = xoo_wsc_params.productFlyClass, 733 $dragIMG = null, 734 $product = $atcEL.closest('.product'); 735 736 737 //If has product container 738 if( $product.length ){ 739 740 $product = $($product[0]); 741 742 var $productGallery = $product.find('.woocommerce-product-gallery'); 743 744 if( customDragImgClass && $product.find( customDragImgClass ).length ){ 745 $dragIMG = $product.find( customDragImgClass ); 746 }
747 else if( $product.find( 'img[data-xooWscFly="fly"]' ).length ){ 748 if( $productGallery.length ){ 749 $dragIMG = $productGallery.find( '.flex-active-slide img[data-xooWscFly="fly"]' ).length ? $productGallery.find( '.flex-active-slide img[data-xooWscFly="fly"]' ) : $productGallery.find( 'img[data-xooWscFly="fly"]' ) 750 } 751 else{ 752 $dragIMG = $product.find( 'img[data-xooWscFly="fly"]' ); 753 } 754 } 755 else if( $productGallery.length ){ 756 $dragIMG = $productGallery; 757 } 758 else{ 759 $dragIMG = $product; 760 } 761 762 } 763 else if( customDragImgClass ){ 764 var moveUp = 4; 765 for ( var i = moveUp; i >= 0; i-- ) { 766 var $foundImg = $atcEL.parent().find( customDragImgClass ); 767 if( $foundImg.length ){ 768 $dragIMG = $foundImg; 769 return false; 770 } 771 } 772 } 773 774 775 if( !$dragIMG || !$dragIMG.length ){ 776 callback(); 777 return; 778 } 779 780 $dragIMG = $dragIMG.eq(0); 781 782 var $imgclone = $dragIMG 783 .clone() 784 .offset({ 785 top: $dragIMG.offset().top, 786 left: $dragIMG.offset().left 787 }) 788 .addClass( 'xoo-wsc-fly-animating' ) 789 .appendTo( $('body') ) 790 .animate({ 791 'top': $basket.offset().top - 20, 792 'left': $basket.offset().left - 20, 793 'width': 75, 794 'height': 75 795 }, parseInt( xoo_wsc_params.flyToCartTime ), 'easeInOutExpo' ); 796 797 setTimeout(function () { 798 callback() 799 }, parseInt( xoo_wsc_params.flyToCartTime ) ); 800 801 $imgclone.animate({ 802 'width': 0, 803 'height': 0 804 }, function () { 805 $(this).detach(); 806 }); 807 808 } 809 810 811 toggleQty(e){ 812 813 var $toggler = $(e.currentTarget), 814 $input = $toggler.siblings('.xoo-wsc-qty'); 815 816 if( !$input.length ) return; 817 818 var baseQty = this.baseQty = parseFloat( $input.val() ), 819 step = parseFloat( $input.attr('step') ), 820 action = $toggler.hasClass( 'xoo-wsc-plus' ) ? 'add' : 'less', 821 newQty = action === 'add' ? baseQty + step : baseQty - step; 822 823 824 $input.val(newQty).trigger('change'); 825 826 } 827 828 changeInputQty(e){ 829 830 Notice.hideNotification(); 831 832 var $_this = this, 833 $input = $(e.currentTarget), 834 newQty = parseFloat( $input.val() ), 835 step = parseFloat( $input.attr('step') ), 836 min = parseFloat( $input.attr('min') ), 837 max = parseFloat( $input.attr('max') ), 838 invalid = false, 839 message = false; 840 841 //Validation 842 843 if( isNaN( newQty ) || newQty < 0 || newQty < min ){ 844 invalid = true; 845 } 846 else if( newQty > max ){ 847 invalid = true; 848 message = xoo_wsc_params.strings.maxQtyError.replace( '%s%', max ); 849 } 850 else if( !Number.isInteger(newQty/step ) ){ 851 invalid = true; 852 message = xoo_wsc_params.strings.stepQtyError.replace( '%s%', step ); 853 } 854 855 //Set back to default quantity 856 if( invalid ){ 857 $input.val( this.baseQty ); 858 if( message ){ 859 Notice.add( message, 'error' ); 860 Notice.showNotification(); 861 } 862 return; 863 } 864 865 //Update 866 $input.val( newQty ); 867 868 clearTimeout( this.qtyUpdateDelay ); 869 870 this.qtyUpdateDelay = setTimeout(function(){ 871 $_this.updateItemQty( $input.parents('.xoo-wsc-product').data('key'), newQty ) 872 }, xoo_wsc_params.qtyUpdateDelay ); 873 874 875 } 876 877 878 saveScrollPosition(){ 879 this.bodyPosition = this.$modal.find('.xoo-wsc-body').length ? this.$modal.find('.xoo-wsc-body').scrollTop() : false; 880 } 881 882 setScrollPosition(){ 883 if( this.bodyPosition !== false ){ 884 this.$modal.find( '.xoo-wsc-body' ).scrollTop( this.bodyPosition ); 885 this.bodyPosition = false; //reset 886 } 887 } 888 889 updateItemQty( cart_key, qty ){ 890 891 if( !cart_key || qty === undefined ) return; 892 893 this.block(); 894 895 this.saveScrollPosition(); 896 897 var formData = { 898 cart_key: cart_key, 899 qty: qty 900 } 901 902 $.ajax({ 903 url: get_wcurl( 'xoo_wsc_update_item_quantity' ), 904 type: 'POST', 905 context: this, 906 data: this.setAjaxData(formData), 907 success: function(response){ 908 this.updateFragments( response ); 909 $(document.body).trigger( 'xoo_wsc_quantity_updated', [response] ); 910 $(document.body).trigger( 'xoo_wsc_cart_updated', [response] ); 911 this.setScrollPosition(); 912 this.unblock(); 913 } 914 915 }) 916 } 917 918 919 closeCartOnClick(e){
920 e.preventDefault(); 921 if( drawer.isOpen() ){ 922 drawer.toggle('hide'); 923 setTimeout( function(){ 924 cart.toggle( 'hide' ) 925 }, 500 ); 926 } 927 else{ 928 cart.toggle('hide'); 929 } 930 931 } 932 933 934 saveQtyFocus(e){ 935 this.baseQty = $(e.currentTarget).val(); 936 } 937 938 939 onPageShow(e){ 940 if ( e.originalEvent.persisted ) { 941 this.refreshMyFragments(); 942 $( document.body ).trigger( 'wc_fragment_refresh' ); 943 } 944 } 945 946 deleteIconClick(e){ 947 this.updateItemQty( $( e.currentTarget ).parents('.xoo-wsc-product').data('key'), 0 ); 948 } 949 950 undoItem(e){ 951 952 var $undo = $(e.currentTarget), 953 formData = { 954 cart_key: $undo.data('key') 955 } 956 957 this.block(); 958 959 $.ajax({ 960 url: get_wcurl('xoo_wsc_undo_item'), 961 type: 'POST', 962 context: this, 963 data: this.setAjaxData(formData), 964 success: function(response){ 965 this.updateFragments( response ); 966 $(document.body).trigger( 'xoo_wsc_item_restored', [response] ); 967 $(document.body).trigger( 'xoo_wsc_cart_updated', [response] ); 968 this.unblock(); 969 } 970 971 }) 972 } 973 974 storeProgressBarWidth( e ){ 975 976 var $bars = $(document.body).find( '.xoo-wsc-bar-cont' ), 977 self = this; 978 979 if( !$bars.length ) return; 980 981 $.each( $bars, function( index, el ){ 982 983 var $bar = $(el), 984 $filled = $bar.find('.xoo-wsc-bar-filled'), 985 id = $bar.attr('id'); 986 987 self.barsWidth[ id ] = $filled.prop('style').width; 988 self.barsData[ id ] = $bar.data('bardata') 989 990 } ); 991 992 993 } 994 995 onCartUpdate(){ 996 super.onCartUpdate(); 997 this.cartLoaded = true; 998 this.initAnimateProgressBar = true; 999 if( this.isOpen() ){ 1000 this.animateProgressBar(); 1001 } 1002 this.initSlider(); 1003 this.toggleBasket(); 1004 initMasonryLayout( ['cart','suggested'] ); 1005 } 1006 1007 1008 1009 toggleBasket(){ 1010 1011 var $basket = $('.xoo-wsc-basket'), 1012 show = xoo_wsc_params.showBasket, 1013 hasProducts = this.$modal.find('.xoo-wsc-product').length; 1014 1015 if( show === "always_show" ){ 1016 $basket.show(); 1017 } 1018 else if( show === "hide_empty" ){ 1019 if( hasProducts ){ 1020 $basket.show(); 1021 } 1022 else{ 1023 $basket.hide(); 1024 } 1025 } 1026 else{ 1027 $basket.hide(); 1028 } 1029 1030 var $shortcode = $('.xoo-wsc-sc-cont'); 1031 1032 if( $shortcode.length && xoo_wsc_params.menuCartHideOnEmpty.length ){ 1033 1034 var shortcodeEls = xoo_wsc_params.shortcodeEls; 1035 1036 $.each( xoo_wsc_params.menuCartHideOnEmpty, function( index, val ){ 1037 1038 if( shortcodeEls[val] ){ 1039 if( hasProducts ){ 1040 $(shortcodeEls[val]).show(); 1041 } 1042 else{ 1043 $(shortcodeEls[val]).hide(); 1044 } 1045 } 1046 1047 }) 1048 1049 } 1050 1051 } 1052 1053 animateProgressBar(){ 1054 1055 if( isCartPage || isCheckoutPage || !this.initAnimateProgressBar ) return; 1056 1057 var $bars = $(document.body).find( '.xoo-wsc-bar-cont' ), 1058 self = this; 1059 1060 if( !$bars.length ) return; 1061 1062 $.each( $bars, function( index, el ){ 1063 1064 var $bar = $(el), 1065 $filled = $bar.find('.xoo-wsc-bar-filled'), 1066 id = $bar.attr('id'); 1067 1068 if( !self.barsWidth[ id ] ) return true; 1069 1070 var newWidth = $filled.prop('style').width; 1071 1072 $filled 1073 .width( self.barsWidth[ id ] ) 1074 .animate({ width: newWidth }, 400, 'linear'); 1075 1076 } ); 1077 1078 this.checkPointAchievedAnimate(); 1079 1080 this.initAnimateProgressBar = false; 1081 } 1082 1083 checkPointAchievedAnimate(){ 1084 1085 var $bars = $(document.body).find( '.xoo-wsc-bar-cont' ), 1086 self = this; 1087 1088 if( !this.barsData || !$bars.length ) return; 1089 1090 1091 $.each( $bars, function( index, el ){ 1092 1093 var $bar = $(el), 1094 $filled = $bar.find('.xoo-wsc-bar-filled'), 1095 id = $bar.attr('id'), 1096 barData = $bar.data('bardata'), 1097 pastBarData = self.barsData[ id ]; 1098 1099 if( !pastBarData ) return true; 1100 1101 var pastPointsReached = [], 1102 newPointsReached = [], 1103 allPointsReached = false; 1104 1105 $.each( pastBarData.points, function( point_index, point ){ 1106 if( point.reached == true ){ 1107 pastPointsReached.push('id_'+point_index); 1108 } 1109 } ) 1110 1111 $.each( barData.points, function( point_index, point ){ 1112 if( point.reached == true && !pastPointsReached.includes('id_'+point_index) ){ 1113 newPointsReached.push('id_'+point_index); 1114 } 1115 1116 if( point.reached == true && (point_index + 1) === barData.points.length ){ 1117 allPointsReached = true; 1118 } 1119 } ) 1120 1121 1122 1123 if( newPointsReached.length ){ 1124 setTimeout( function(){ 1125 Celebrate.Celebrate( $bar, allPointsReached && xoo_wsc_params.bar.fullCelebration !== 'none' ? xoo_wsc_params.bar.fullCelebration : xoo_wsc_params.bar.singleCelebration ); 1126 }, 200 ); 1127 } 1128 1129 self.barsData[id] = barData; 1130 1131 1132 }) 1133 1134 1135 } 1136 1137 1138 emptyCart(){ 1139 1140 this.block(); 1141 1142 $.ajax({
1143 url: get_wcurl( 'xoo_wsc_empty_cart' ), 1144 type: 'POST', 1145 context: this, 1146 data: {}, 1147 success: function(response){ 1148 1149 this.updateFragments( response ); 1150 // Trigger event. 1151 $( document.body ).trigger( 'xoo_wsc_cart_emptied' ); 1152 $(document.body).trigger( 'xoo_wsc_cart_updated', [response] ); 1153 }, 1154 complete: function(){ 1155 this.unblock(); 1156 } 1157 }) 1158 } 1159 1160 1161 initSlider(){ 1162 1163 if( typeof $.fn.lightSlider !== 'function' || xoo_wsc_params.spSlide.enable !== 'yes' ) return; 1164 1165 $('ul.xoo-wsc-sp-slider').each( function( index, el ){ 1166 var $el = $(el); 1167 1168 if( $(this).parents('.xoo-wsc-drawer').length ) return; 1169 1170 $el.lightSlider(xoo_wsc_params.spSlide); 1171 1172 } ); 1173 1174 } 1175 1176 } 1177 1178 1179 class Drawer extends Container{ 1180 1181 constructor( $modal ){ 1182 1183 super( $modal, 'drawer' ); 1184 1185 this.setHeaderHeight(); 1186 1187 this.eventHandlers(); 1188 1189 } 1190 1191 eventHandlers(){ 1192 1193 super.eventHandlers(); 1194 1195 $(document.body).on( 'xoo_wsc_cart_toggled', this.drawOutOnCartOpen.bind(this) ); 1196 $(document.body).on( 'click', '.xoo-wsc-toggle-drawer', this.toggleDrawer.bind(this) ); 1197 $(document.body).on( 'click', '.xoo-wscdh-close', this.close.bind(this) ); 1198 //$(document.body).on( 'wc_fragments_loaded', this.onCartUpdate.bind(this) ); 1199 } 1200 1201 onCartUpdate(){ 1202 super.onCartUpdate(); 1203 this.setHeaderHeight(); 1204 setTimeout(function(){ 1205 drawer.toggleOnContentBasis(); 1206 }, 0); 1207 1208 } 1209 1210 1211 toggleOnContentBasis(){ 1212 1213 var hasContent = !this.isDrawerEmpty(); 1214 1215 if( this.isOpen() ){ 1216 if( !hasContent ){ 1217 this.toggle('hide'); 1218 this.$modal.find('.xoo-wsc-dtg-icon').addClass('xoo-wsc-disabled'); 1219 this.emptyClosed = true; 1220 } 1221 } 1222 else{ 1223 if( hasContent && cart.isOpen() && this.emptyClosed ){ 1224 this.toggle('show'); 1225 this.$modal.find('.xoo-wsc-dtg-icon').removeClass('xoo-wsc-disabled'); 1226 this.emptyClosed = false; 1227 } 1228 } 1229 } 1230 1231 setHeaderHeight(){ 1232 var $cartHeader = $('.xoo-wsch-top'); 1233 if( !$cartHeader.length ) return; 1234 1235 var cartHeaderHeight = $cartHeader.height(); 1236 1237 this.$modal.closest('.xoo-wsc-markup').find('.xoo-wsc-drawer-header, .xoo-wsc-sl-heading').each(function( index, el ){ 1238 1239 var $el = $(el); 1240 1241 if( $el.height() < $cartHeader.height() ){ 1242 $el.height( cartHeaderHeight ); 1243 } 1244 }) 1245 1246 1247 } 1248 1249 isDrawerEmpty(){ 1250 return !this.$modal.find('.xoo-wsc-dr-content').length; 1251 } 1252 1253 1254 toggleDrawer(){ 1255 this.toggle(); 1256 } 1257 1258 1259 drawOutOnCartOpen(e,type){ 1260 1261 if( !cart.isOpen() || this.isDrawerEmpty() ) return; 1262 1263 setTimeout( function(){ 1264 drawer.toggle('show'); 1265 initMasonryLayout('suggested'); 1266 }, xoo_wsc_params.drawerWait ); 1267 1268 } 1269 1270 1271 close(e){ 1272 this.toggle('hide'); 1273 } 1274 1275 getDataType(){ 1276 return this.$modal.find('.xoo-wsc-dr-content').data('drawer'); 1277 } 1278 1279 1280 } 1281 1282 1283 1284 class Slider extends Container{ 1285 1286 constructor( $modal ){ 1287 1288 super( $modal, 'slider' ); 1289 1290 this.eventHandlers(); 1291 1292 this.shipping = xoo_wsc_params.shippingEnabled ? Shipping.init( this ) : null; 1293 1294 } 1295 1296 eventHandlers(){ 1297 1298 super.eventHandlers(); 1299 1300 1301 $( document.body ).on( 'click', '.xoo-wsc-toggle-slider', this.triggerSlider.bind(this) ); 1302 $( document.body ).on( 'xoo_wsc_cart_toggled', this.closeSliderOnCartClose.bind(this) ); 1303 1304 if( xoo_wsc_params.sliderAutoClose ){ 1305 $( document.body ).on( 'xoo_wsc_coupon_applied xoo_wsc_shipping_calculated updated_shipping_method xoo_wsc_coupon_removed xoo_wsc_moved_from_save_list added_to_cart', this.closeSlider.bind(this) ); 1306 } 1307 1308 $(document.body).on( 'submit', 'form.xoo-wsc-sl-apply-coupon', this.submitCouponForm.bind(this) ); 1309 $(document.body).on( 'click', '.xoo-wsc-coupon-apply-btn', this.applyCouponFromBtn.bind(this) ); 1310 $(document.body).on( 'click', '.xoo-wsc-remove-coupon', this.removeCoupon.bind(this) ); 1311 $(document.body).on( 'click', '.xoo-wsc-savl-del', this.deleteSavedForLaterItem.bind(this) ); 1312 $(document.body).on( 'click', '.xoo-wsc-savl-atc', this.moveSavedForLaterItemToCart.bind(this) ); 1313 1314 $( document.body ).on( 'click', '.xoo-wsc-toggle-slider[data-sli
1314der="quickview"]', this.loadQuickview.bind(this) ); 1315 1316 } 1317 1318 1319 loadQuickview(e){ 1320 1321 e.preventDefault(); 1322 1323 this.toggle('show'); 1324 1325 var $toggler = $(e.currentTarget), 1326 formData = {}; 1327 1328 if( $toggler.data('cart_key') ){ 1329 formData['cart_key'] = $toggler.data('cart_key'); 1330 } 1331 else if( $toggler.data('product_id') ){ 1332 formData['product_id'] = $toggler.data('product_id'); 1333 } 1334 else{ 1335 return; 1336 } 1337 1338 var $sliderContent = $('.xoo-wsc-sl-quickview .xoo-wsc-sl-body'); 1339 1340 $sliderContent.html(''); 1341 1342 this.block(); 1343 1344 $.ajax({ 1345 url: get_wcurl( 'xoo_wsc_load_quickview' ), 1346 type: 'POST', 1347 context: this, 1348 data: this.setAjaxData(formData), 1349 success: function(response){ 1350 1351 $sliderContent.html(response); 1352 1353 QuickView.load(); 1354 1355 $(document.body).trigger( 'xoo_wsc_quickview_loaded', [response, formData] ); 1356 1357 this.unblock(); 1358 1359 } 1360 1361 }) 1362 } 1363 1364 1365 moveSavedForLaterItemToCart(e){ 1366 1367 var $item = $(e.currentTarget).closest('.xoo-wsc-savl-product'), 1368 cartKey = $item.data('ckey'), 1369 formData = { 1370 cart_key: cartKey, 1371 } 1372 1373 this.block(); 1374 1375 $.ajax({ 1376 url: get_wcurl( 'xoo_wsc_move_save_for_later_item' ), 1377 type: 'POST', 1378 context: this, 1379 data: this.setAjaxData(formData), 1380 success: function(response){ 1381 1382 this.updateFragments( response ); 1383 1384 $(document.body).trigger( 'xoo_wsc_moved_from_save_list', [response, cartKey] ); 1385 1386 this.unblock(); 1387 1388 } 1389 1390 }) 1391 } 1392 1393 deleteSavedForLaterItem(e){ 1394 1395 var $item = $(e.currentTarget).closest('.xoo-wsc-savl-product'), 1396 cartKey = $item.data('ckey'), 1397 formData = { 1398 cart_key: cartKey, 1399 } 1400 1401 this.block(); 1402 1403 $.ajax({ 1404 url: get_wcurl( 'xoo_wsc_delete_save_for_later_item' ), 1405 type: 'POST', 1406 context: this, 1407 data: this.setAjaxData(formData, 'slider' ), 1408 success: function(response){ 1409 1410 this.updateFragments( response ); 1411 1412 $(document.body).trigger( 'xoo_wsc_delete_from_save_list', [response, cartKey] ); 1413 1414 this.unblock(); 1415 1416 } 1417 1418 }) 1419 } 1420 1421 1422 removeCoupon(e){ 1423 1424 e.preventDefault(); 1425 1426 var $removeEl = $(e.currentTarget), 1427 coupon = $removeEl.data('code'), 1428 formData = { 1429 coupon: coupon 1430 }; 1431 1432 this.block(); 1433 1434 $.ajax( { 1435 url: get_wcurl( 'xoo_wsc_remove_coupon' ), 1436 type: 'POST', 1437 context: this, 1438 data: this.setAjaxData( formData, cart.$modal.find( $removeEl ).length ? 'cart' : 'slider' ), 1439 success: function( response ) { 1440 this.updateFragments(response); 1441 }, 1442 complete: function() { 1443 this.unblock(); 1444 this.updateCartCheckoutPage(); 1445 $( document.body ).trigger( 'xoo_wsc_coupon_removed' ); 1446 } 1447 } ); 1448 } 1449 1450 onCartUpdate(){ 1451 super.onCartUpdate(); 1452 this.toggleContent(); 1453 } 1454 1455 closeSlider(){ 1456 this.toggle('hide'); 1457 } 1458 1459 1460 applyCouponFromBtn(e){ 1461 this.applyCoupon( $(e.currentTarget).val() ); 1462 } 1463 1464 submitCouponForm(e){ 1465 1466 e.preventDefault(); 1467 1468 var $form = $(e.currentTarget); 1469 1470 this.applyCoupon( $form.find('input[name="xoo-wsc-slcf-input"]').val() ); 1471 1472 } 1473 1474 1475 closeSliderOnCartClose(e){ 1476 1477 var $this = $(e.currentTarget); 1478 1479 if( !cart.$modal.hasClass('xoo-wsc-cart-active') ){ 1480 this.toggle('hide'); 1481 } 1482 1483 } 1484 1485 1486 triggerSlider(e){ 1487 1488 var $toggler = $(e.currentTarget), 1489 slider = $toggler.data('slider'); 1490 1491 if( slider === 'shipping' && isCheckoutPage ){ 1492 Notice.add( xoo_wsc_params.strings.calculateCheckout, 'error' ); 1493 Notice.showNotification(); 1494 return; 1495 } 1496 1497 1498 this.$modal.attr( 'data-slider', slider ); 1499 1500 this.toggle(); 1501 1502 this.toggleContent(); 1503 } 1504 1505 1506 toggleContent(){ 1507 1508 var activeSlider = ''; 1509 1510 $('.xoo-wsc-sl-content').hide(); 1511 1512 var activeSlider = this.$modal.attr('data-slider'), 1513 $toggleEl = $('.xoo-wsc-sl-content[data-slider="'+activeSlider+'"]'); 1514 1515 if( $toggleEl.length ) $toggleEl.show(); 1516 1517 if( activeSlider === 'savelater' && this.isOpen() ){ 1518 initMasonryLayout('saveLater'); 1519 } 1520 1521 $( document.body ).trigger( 'xoo_wsc_slider_data_toggled', [activeSlider] ); 1522 } 1523 1524 1525 applyCoupon( coupon ){ 1526 1527 if( !coupon ){
1528 Notice.add( xoo_wsc_params.strings.couponEmpty, 'error' ); 1529 Notice.showNotification(); 1530 return; 1531 } 1532 1533 this.block(); 1534 1535 var formData = { 1536 'coupon': coupon, 1537 } 1538 1539 $.ajax( { 1540 url: get_wcurl('xoo_wsc_apply_coupon'), 1541 type: 'POST', 1542 context: this, 1543 data: this.setAjaxData( formData ), 1544 success: function( response ) { 1545 this.updateFragments(response); 1546 }, 1547 complete: function() { 1548 this.unblock(); 1549 this.updateCartCheckoutPage(); 1550 $( document.body ).trigger( 'xoo_wsc_coupon_applied' ); 1551 } 1552 } ); 1553 1554 } 1555 1556 } 1557 1558 1559 1560 var Shipping = { 1561 1562 init: function( slider ){ 1563 slider.$modal.on( 'change', 'input.xoo-wsc-shipping-method', this.shippingMethodChange ); 1564 slider.$modal.on( 'submit', 'form.woocommerce-shipping-calculator', this.shippingCalculatorSubmit ); 1565 slider.$modal.on( 'click', '.shipping-calculator-button', this.toggleCalculator ); 1566 $(document.body).on( 'wc_fragments_loaded xoo_wsc_slider_data_toggled', this.initSelect2 ); 1567 }, 1568 1569 toggleCalculator: function(e){ 1570 1571 e.preventDefault(); 1572 e.stopImmediatePropagation(); 1573 1574 $(this).siblings('.shipping-calculator-form').slideToggle(); 1575 $( document.body ).trigger( 'country_to_state_changed' ); 1576 }, 1577 1578 shippingCalculatorSubmit: function(e){ 1579 1580 e.preventDefault(); 1581 e.stopImmediatePropagation(); 1582 1583 var $form = $(this); 1584 1585 slider.block(); 1586 1587 // Provide the submit button value because wc-form-handler expects it. 1588 $( '<input />' ) 1589 .attr( 'type', 'hidden' ) 1590 .attr( 'name', 'calc_shipping' ) 1591 .attr( 'value', 'x' ) 1592 .appendTo( $form ); 1593 1594 var formData = $form.serialize(); 1595 1596 // Make call to actual form post URL. 1597 $.ajax( { 1598 url: get_wcurl( 'xoo_wsc_calculate_shipping' ), 1599 type: 'POST', 1600 context: this, 1601 data: slider.setAjaxData(formData), 1602 success: function( response ) { 1603 slider.updateFragments(response); 1604 }, 1605 complete: function() { 1606 slider.unblock(); 1607 slider.updateCartCheckoutPage(); 1608 $( document.body ).trigger( 'xoo_wsc_shipping_calculated' ); 1609 } 1610 } ); 1611 1612 }, 1613 1614 shippingMethodChange: function(e){ 1615 1616 e.preventDefault(); 1617 e.stopImmediatePropagation(); 1618 1619 var shipping_methods = {}; 1620 1621 slider.block(); 1622 1623 $( 'select.shipping_method, :input[name^=xoo-wsc-shipping_method][type=radio]:checked, :input[name^=shipping_method][type=hidden]' ).each( function() { 1624 shipping_methods[ $( this ).data( 'index' ) ] = $( this ).val(); 1625 } ); 1626 1627 var formData = { 1628 shipping_method: shipping_methods, 1629 } 1630 1631 $.ajax( { 1632 type: 'POST', 1633 url: get_wcurl( 'xoo_wsc_update_shipping_method' ), 1634 data: slider.setAjaxData( formData ), 1635 success: function( response ) { 1636 slider.updateFragments(response); 1637 }, 1638 complete: function() { 1639 slider.unblock(); 1640 slider.updateCartCheckoutPage(); 1641 $( document.body ).trigger( 'updated_shipping_method' ); 1642 } 1643 } ); 1644 1645 }, 1646 1647 initSelect2: function(e){ 1648 $( document.body ).trigger( 'country_to_state_changed' ); 1649 }, 1650 } 1651 1652 1653 var cart = new Cart( $('.xoo-wsc-modal') ), 1654 slider = new Slider( $('.xoo-wsc-slider-modal') ); 1655 drawer = new Drawer( $('.xoo-wsc-drawer-modal') ); 1656 1657 1658 var AnimateCard = { 1659 1660 type: xoo_wsc_params.cardAnimate.type, 1661 duration: xoo_wsc_params.cardAnimate.duration, 1662 1663 init: function(){ 1664 1665 var onEvent = xoo_wsc_params.cardAnimate.event === 'back_hover' ? 'mouseenter' : 'click'; 1666 1667 $('body').on( onEvent, '.xoo-wsc-has-back', this.animate ); 1668 $('body').on( 'mouseleave', '.xoo-wsc-has-back', this.reverseAnimate ); 1669 1670 }, 1671 animate: function(e){ 1672 1673 if( e.target.classList.contains('xoo-wsc-smr-del') ) return; 1674 1675 var $img = $(this).find('.xoo-wsc-img-col'); 1676 1677 if( !$img.hasClass('xoo-wsc-caniming') ){ 1678 e.preventDefault(); 1679 } 1680 else{ 1681 return; 1682 } 1683 1684 $img.attr('data-exclasses', $img.attr('class') ); 1685 1686 $img.removeClass() 1687 $img.addClass($img.attr('data-exclasses')); 1688 1689 $img.addClass( 'xoo-wsc-caniming' + ' ' + AnimateCard.type ); 1690 1691 }, 1692 reverseAnimate: function(){ 1693 1694 var $img = $(this).find('.xoo-wsc-img-col'); 1695 1696 if( !$img.hasClass( 'xoo-wsc-caniming' ) ) return; 1697 1698 $img.addClass(AnimateCard.type+'Return'); 1699 1700 AnimateCard.clear = setTimeout(function(){
1701 $img.removeClass().addClass( $img.attr('data-exclasses') ); 1702 }, AnimateCard.duration * 1000); 1703 1704 } 1705 } 1706 1707 if( xoo_wsc_params.cardAnimate.enable === "yes" ){ 1708 AnimateCard.init(); 1709 } 1710 1711 1712 1713 var Celebrate = { 1714 1715 canvasIndex: 0, 1716 1717 myconfetti: '', 1718 1719 Celebrate: async function( $bar, celebrationName ){ 1720 1721 if (typeof Celebrate[celebrationName] !== 'function') return; 1722 1723 const index = Celebrate.canvasIndex++; 1724 1725 const myconfetti = await Celebrate.CreateCanvas(index); 1726 1727 const barPos = Celebrate.BarPosition( $bar ); 1728 1729 Celebrate[celebrationName](myconfetti, barPos); 1730 1731 }, 1732 1733 CreateCanvas: async function(index){ 1734 1735 const canvasID = 'xoo_canvas_' + index; 1736 1737 // Append a fresh canvas for this celebration 1738 $('.xoo-wsc-container').append('<canvas id="'+canvasID+'"></canvas>').show(); 1739 1740 const canvas = document.getElementById(canvasID); 1741 1742 // Create a separate confetti instance for this canvas 1743 return await confetti.create(canvas, { resize: true }); 1744 1745 }, 1746 1747 BarPosition: function( $bar ){ 1748 1749 var windowHeight = $(window).height(), 1750 $barPole = $bar.find('.xoo-wsc-bar'); 1751 1752 var barPosition = $barPole.offset().top - $(window).scrollTop(); 1753 1754 Celebrate.barPosition = barPosition/windowHeight; 1755 1756 return Celebrate.barPosition; 1757 1758 }, 1759 1760 Fireworks: function( myconfetti, barPos ){ 1761 const duration = 3 * 1000, 1762 animationEnd = Date.now() + duration, 1763 defaults = { startVelocity: 30, spread: 100, ticks: 60, zIndex: 0 }; 1764 1765 function randomInRange(min, max) { 1766 return Math.random() * (max - min) + min; 1767 } 1768 1769 const interval = setInterval(function(){ 1770 const timeLeft = animationEnd - Date.now(); 1771 if (timeLeft <= 0) return clearInterval(interval); 1772 1773 const particleCount = 50 * (timeLeft / duration); 1774 1775 myconfetti(Object.assign({}, defaults, { 1776 particleCount, 1777 origin: { x: randomInRange(0.1, 0.3), y: barPos } 1778 })); 1779 1780 myconfetti(Object.assign({}, defaults, { 1781 particleCount, 1782 origin: { x: randomInRange(0.7, 0.9), y: barPos } 1783 })); 1784 1785 }, 250); 1786 }, 1787 1788 Stars: function( myconfetti, barPos ){ 1789 1790 const defaults = { 1791 origin: { x: 0.5, y: barPos }, 1792 spread: 360, 1793 ticks: 50, 1794 gravity: 0, 1795 decay: 0.94, 1796 startVelocity: 30, 1797 shapes: ["star"], 1798 colors: ["FFE400", "FFBD00", "E89400", "FFCA6C", "FDFFB8"], 1799 }; 1800 1801 function shoot() { 1802 myconfetti({ 1803 ...defaults, 1804 particleCount: 40, 1805 scalar: 1, 1806 shapes: ["star"], 1807 }); 1808 1809 myconfetti({ 1810 ...defaults, 1811 particleCount: 10, 1812 scalar: 0.75, 1813 shapes: ["circle"], 1814 }); 1815 } 1816 1817 setTimeout(shoot, 0); 1818 setTimeout(shoot, 100); 1819 setTimeout(shoot, 200); 1820 }, 1821 1822 SchoolPride: function( myconfetti, barPos ){ 1823 1824 const end = Date.now() + 1.5 * 1000; 1825 1826 // go Buckeyes! 1827 const colors = ["#bb0000", "#ffffff"]; 1828 1829 (function frame() { 1830 myconfetti({ 1831 particleCount: 2, 1832 angle: 60, 1833 spread: 55, 1834 origin: { x: 0, y: barPos }, 1835 colors: colors, 1836 }); 1837 1838 myconfetti({ 1839 particleCount: 2, 1840 angle: 120, 1841 spread: 55, 1842 origin: { x: 1, y: barPos }, 1843 colors: colors, 1844 }); 1845 1846 if (Date.now() < end) { 1847 requestAnimationFrame(frame); 1848 } 1849 })(); 1850 }, 1851 1852 RealisticLook: function( myconfetti, barPos ){ 1853 1854 const count = 1000, 1855 1856 defaults = { 1857 origin: { y: barPos }, 1858 }; 1859 1860 function fire(particleRatio, opts) { 1861 myconfetti( 1862 Object.assign({}, defaults, opts, { 1863 particleCount: Math.floor(count * particleRatio), 1864 }) 1865 ); 1866 } 1867 1868 fire(0.25, { 1869 spread: 26, 1870 startVelocity: 55, 1871 }); 1872 1873 fire(0.2, { 1874 spread: 60, 1875 }); 1876 1877 fire(0.35, { 1878 spread: 100, 1879 decay: 0.91, 1880 scalar: 0.8, 1881 }); 1882 1883 fire(0.1, { 1884 spread: 120, 1885 startVelocity: 25, 1886 decay: 0.92, 1887 scalar: 1.2, 1888 }); 1889 1890 fire(0.1, { 1891 spread: 120, 1892 startVelocity: 45, 1893 }); 1894 }, 1895 1896 BasicCannon: function( myconfetti, barPos ){ 1897 myconfetti({ 1898 particleCount: 400, 1899 spread: 70, 1900 origin: { y: barPos }, 1901 }); 1902 } 1903 1904 } 1905 1906 1907 1908 var scrollBarWidth = window.innerWidth - document.documentElement.clientWidth; 1909 1910 $('<style>') 1911 .prop('type', 'text/css') 1912 .html('body.xoo-wsc-cart-active { padding-right: ' + scrollBarWidth + 'px; }') 1913 .appendTo('head'); 1914 }) 1915
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.