1jQuery(document).ready(function($){ 2 3 var isCartPage = xoo_wsc_params.isCart == '1', 4 isCheckoutPage = xoo_wsc_params.isCheckout == '1'; 5 6 var get_wcurl = function( endpoint ) { 7 return xoo_wsc_params.wc_ajax_url.toString().replace( 8 '%%endpoint%%', 9 endpoint 10 ); 11 }; 12 13 14 var markupTimeout = null; 15 16 class Notice{ 17 18 constructor( $modal ){ 19 this.$modal = $modal; 20 this.timeout = null; 21 } 22 23 add( notice, type = 'success', clearPrevious = true ){ 24 25 var $noticeCont = this.$modal.find('.xoo-wsc-notice-container'); 26 27 if( clearPrevious ){ 28 $noticeCont.html(''); 29 } 30 31 var noticeHTML = type === 'success' ? xoo_wsc_params.html.successNotice.toString().replace( '%s%', notice ) : xoo_wsc_params.html.errorNotice.toString().replace( '%s%', notice ); 32 33 $noticeCont.html( noticeHTML ); 34 35 } 36 37 showNotification(){ 38 39 Notice.showMarkupNotice(); 40 41 var $noticeCont = this.$modal.find('.xoo-wsc-notice-container'); 42 43 if( !$noticeCont.length || $noticeCont.children().length === 0 ) return; 44 45 $noticeCont.slideDown(); 46 47 clearTimeout(this.timeout); 48 49 this.timeout = setTimeout(function(){ 50 $noticeCont.slideUp('slow',function(){ 51 //$noticeCont.html(''); 52 }); 53 },xoo_wsc_params.notificationTime ) 54 55 } 56 57 58 59 hideNotification(){ 60 this.$modal.find('.xoo-wsc-notice-container').hide(); 61 } 62 63 static hideMarkupNotice(){ 64 Notice.$noticeContainer().removeClass('xoo-wsc-active'); 65 } 66 67 static $noticeContainer(){ 68 return $('.xoo-wsc-markup-notices') 69 } 70 71 static showMarkupNotice(){ 72 73 if( cart.isOpen() ) return; 74 75 var $markupNotice = Notice.$noticeContainer(); 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(markupTimeout); 84 85 markupTimeout = setTimeout(function(){ 86 $markupNotice.removeClass('xoo-wsc-active'); 87 },xoo_wsc_params.notificationTime ) 88 } 89 } 90 91 class Container{ 92 93 static eventHandlerCalled = false; 94 95 constructor( $modal, container ){ 96 this.$modal = $modal; 97 this.container = container || 'cart'; 98 this.notice = new Notice( this.$modal ); 99 } 100 101 102 isOpen(){ 103 return this.$modal.hasClass('xoo-wsc-'+this.container+'-active'); 104 } 105 106 eventHandlers(){ 107 if( !Container.eventHandlerCalled ){ 108 $(document.body).on( 'wc_fragments_loaded updated_checkout', this.onCartUpdate.bind(this) ); 109 Container.eventHandlerCalled = true; 110 } 111 } 112 113 onCartUpdate(){ 114 this.unblock(); 115 this.notice.showNotification(); 116 } 117 118 setAjaxData( data, noticeSection ){ 119 120 var ajaxData = { 121 container: this.container, 122 noticeSection: noticeSection || this.noticeSection || this.container, 123 isCheckout: isCheckoutPage, 124 isCart: isCartPage 125 } 126 127 128 if( typeof data === 'object' ){ 129 130 $.extend( ajaxData, data ); 131 132 } 133 else{ 134 135 var serializedData = data; 136 137 $.each( ajaxData, function( key, value ){ 138 serializedData += ( '&'+key+'='+value ); 139 } ) 140 141 ajaxData = serializedData; 142 143 } 144 145 return ajaxData; 146 } 147 148 149 toggle( type ){ 150 151 var $activeEls = this.$modal.add( 'body' ).add('html'), 152 activeClass = 'xoo-wsc-'+ this.container +'-active'; 153 154 if( type === 'show' ){ 155 $activeEls.addClass(activeClass); 156 } 157 else if( type === 'hide' ){ 158 $activeEls.removeClass(activeClass); 159 this.notice.hideNotification(); 160 } 161 else{ 162 $activeEls.toggleClass(activeClass); 163 } 164 165 166 $(document.body).trigger( 'xoo_wsc_' + this.container + '_toggled', [ type ] ); 167 168 } 169 170 171 block(){ 172 this.$modal.addClass('xoo-wsc-loading'); 173 } 174 175 unblock(){ 176 this.$modal.removeClass('xoo-wsc-loading'); 177 } 178 179 180 refreshMyFragments(){ 181 182 if( xoo_wsc_params.refreshCart === "yes" && typeof wc_cart_fragments_params !== 'undefined' ){ 183 $( document.body ).trigger( 'wc_fragment_refresh' ); 184 return; 185 } 186 187 this.block(); 188 189 $.ajax({
190 url: get_wcurl( 'xoo_wsc_refresh_fragments' ), 191 type: 'POST', 192 context: this, 193 data: {}, 194 success: function( response ){ 195 this.updateFragments(response); 196 $( document.body ).trigger( 'wc_fragments_refreshed' ); 197 }, 198 complete: function(){ 199 this.unblock(); 200 } 201 }) 202 203 } 204 205 206 updateCartCheckoutPage(){ 207 208 //Refresh checkout page 209 if( isCheckoutPage ){ 210 if( $( 'form.checkout' ).length === 0 ){ 211 location.reload(); 212 return; 213 } 214 $(document.body).trigger("update_checkout"); 215 } 216 217 //Refresh Cart page 218 if( isCartPage ){ 219 $(document.body).trigger("wc_update_cart"); 220 } 221 222 } 223 224 updateFragments( response ){ 225 226 if( response.fragments ){ 227 228 $( document.body ).trigger( 'xoo_wsc_before_loading_fragments', [ response ] ); 229 230 this.block(); 231 232 //Set fragments 233 $.each( response.fragments, function( key, value ) { 234 $( key ).replaceWith( value ); 235 }); 236 237 if( typeof wc_cart_fragments_params !== 'undefined' && ( 'sessionStorage' in window && window.sessionStorage !== null ) ){ 238 239 sessionStorage.setItem( wc_cart_fragments_params.fragment_name, JSON.stringify( response.fragments ) ); 240 localStorage.setItem( wc_cart_fragments_params.cart_hash_key, response.cart_hash ); 241 sessionStorage.setItem( wc_cart_fragments_params.cart_hash_key, response.cart_hash ); 242 243 if ( response.cart_hash ) { 244 sessionStorage.setItem( 'wc_cart_created', ( new Date() ).getTime() ); 245 } 246 247 } 248 249 $( document.body ).trigger( 'wc_fragments_loaded' ); 250 251 this.unblock(); 252 253 } 254 255 if( xoo_wsc_params.refreshCart === "yes" && typeof wc_cart_fragments_params !== 'undefined' ){ 256 this.block(); 257 $( document.body ).trigger( 'wc_fragment_refresh' ); 258 return; 259 } 260 261 } 262 263 } 264 265 266 class Cart extends Container{ 267 268 constructor( $modal ){ 269 270 super( $modal, 'cart' ); 271 272 this.baseQty = 1; 273 this.qtyUpdateDelay = null; 274 275 this.refreshFragmentsOnPageLoad(); 276 this.eventHandlers(); 277 this.initSlider(); 278 279 } 280 281 282 refreshFragmentsOnPageLoad(){ 283 setTimeout(function(){ 284 this.refreshMyFragments(); 285 }.bind(this), xoo_wsc_params.fetchDelay ) 286 } 287 288 eventHandlers(){ 289 290 super.eventHandlers(); 291 292 this.$modal.on( 'click', '.xoo-wsc-chng', this.toggleQty.bind(this) ); 293 this.$modal.on( 'change', '.xoo-wsc-qty', this.changeInputQty.bind(this) ); 294 this.$modal.on( 'click', '.xoo-wsc-undo-item', this.undoItem.bind(this) ); 295 this.$modal.on( 'focusin', '.xoo-wsc-qty', this.saveQtyFocus.bind(this) ); 296 this.$modal.on( 'click', '.xoo-wsc-smr-del', this.deleteIconClick.bind(this) ); 297 this.$modal.on( 'click', '.xoo-wsch-close, .xoo-wsc-opac, .xoo-wsc-cart-close', this.closeCartOnClick.bind(this) ); 298 this.$modal.on( 'click', '.xoo-wsc-basket', this.toggleCart.bind(this) ); 299 300 $( document.body ).on( 'click', '.xoo-wsc-ecl', this.emptyCart.bind(this) ); 301 302 $(document.body).on( 'xoo_wsc_cart_updated', this.updateCartCheckoutPage.bind(this) ); 303 $(document.body).on( 'click', 'a.added_to_cart, .xoo-wsc-cart-trigger', this.openCart.bind(this) ); 304 $(document.body).on( 'added_to_cart', this.addedToCart.bind(this) ); 305 306 if( xoo_wsc_params.ajaxAddToCart === 'yes' ){ 307 $(document.body).on( 'submit', 'form.cart', this.addToCartFormSubmit.bind(this) ); 308 } 309 310 if( typeof wc_cart_fragments_params === 'undefined' ){ 311 $( window ).on( 'pageshow' , this.onPageShow.bind(this) ); 312 } 313 314 if( xoo_wsc_params.triggerClass ){ 315 $(document.body).on( 'click', '.'+xoo_wsc_params.triggerClass, this.openCart.bind(this) ); 316 } 317 318 319 320 if( isCheckoutPage || isCartPage ){ 321 $(document.body).on( 'updated_shipping_method', this.refreshMyFragments.bind(this) ); 322 } 323 324 $(document.body).on( 'wc-blocks_added_to_cart', this.blockAddedToCart.bind(this) ); 325 326 $(document.body).on( 'adding_to_cart', this.checkIfWCAjaxAddToCart.bind(this) ); 327 328 //Animate shipping bar 329 $(document.body).on( 'xoo_wsc_before_loading_fragments adding_to_cart wc_fragment_refresh', this.storeProgressBarWidth.bind(this) ); 330 331 $(document.body).on( 'wc_fragments_loaded', this.checkIfWCAjaxAddToCartUnset.bind(this) ); 332 333 this.initMasonryLayout(); 334 335 if( xoo_wsc_params.autoOpenCart === 'yes' && xoo_wsc_params.addedToCart === 'yes'){ 336 this.openCart(); 337 } 338 339 } 340 341 checkIfWCAjaxAddToCartUnset(){ 342 this.isWCAjaxAddToCart = false; 343 } 344 345 checkIfWCAjaxAddToCart(e, $button, data){ 346 347 this.isWCAjaxAddToCart = false; 348 349 if( ( !(data instanceof FormData) || !data.has('action') || !data.get('action') === 'xoo_wsc_add_to_cart' ) && $button.hasClass('ajax_add_to_cart') ){ 350 this.isWCAjaxAddToCart = true; 351 } 352 } 353 354 355 toggleCart(e){ 356 if( this.isOpen() ){ 357 this.closeCartOnClick(e); 358 } 359 else{ 360 this.openCart(e); 361 } 362 363 } 364 365 366 openCart(e){ 367 if( e ){ 368 e.preventDefault(); 369 e.stopImmediatePropagation(); 370 } 371 this.toggle('show'); 372 this.animateProgressBar(); 373 Notice.hideMarkupNotice(); 374 } 375 376 addToCartFormSubmit(e){ 377 378 var $form = $(e.currentTarget); 379 380 if( $form.closest('.product').hasClass('product-type-external') || $form.siblings('.xoo-wsc-disable-atc').length ) return; 381 382 var $button = e.originalEvent && e.originalEvent.submitter ? $(e.originalEvent.submitter) : $form.find( 'button[type="submit"]'), 383 formData = new FormData($form.get(0)), 384 productData = $form.serializeArray(), 385 hasProductId = false; 386 387 //Check for woocommerce custom quantity code 388 //https://docs.woocommerce.com/document/override-loop-template-and-show-quantities-next-to-add-to-cart-buttons/ 389 $.each( productData, function( key, form_item ){ 390 if( form_item.name === 'productID' || form_item.name === 'add-to-cart' ){ 391 if( form_item.value ){ 392 hasProductId = true; 393 return false; 394 } 395 } 396 }) 397 398 //If no product id found , look for the form action URL 399 if( !hasProductId && $form.attr('action') ){ 400 var is_url = $form.attr('action').match(/add-to-cart=([0-9]+)/), 401 productID = is_url ? is_url[1] : false; 402 } 403 404 // Add submitted button value 405 if( $button.attr('name') && $button.attr('value') ){ 406 formData.append( $button.attr('name'), $button.attr('value') ); 407 } 408 409 if( productID ){ 410 formData.append( 'add-to-cart', productID ); 411 } 412 413 formData.append( 'action', 'xoo_wsc_add_to_cart' ); 414
415 var doAjaxAddToCart = true; 416 417 418 $.each( xoo_wsc_params.skipAjaxForData, function( key, value ){ 419 if( formData.has(key) && ( !value || formData.get(key) == value ) ){ 420 doAjaxAddToCart = false; 421 return false; 422 } 423 } ) 424 425 426 if( doAjaxAddToCart ){ 427 e.preventDefault(); 428 this.addToCartAjax( $button, formData );//Ajax add to cart 429 } 430 431 } 432 433 434 addToCartAjax( $button, formData ){ 435 436 this.block(); 437 438 $button.addClass('loading'); 439 440 // Trigger event. 441 $( document.body ).trigger( 'adding_to_cart', [ $button, formData ] ); 442 443 $.ajax({ 444 url: get_wcurl( 'xoo_wsc_add_to_cart' ), 445 type: 'POST', 446 context: this, 447 cache: false, 448 contentType: false, 449 processData: false, 450 data: formData, 451 success: function(response){ 452 453 if(response.fragments){ 454 // Trigger event so themes can refresh other areas. 455 $( document.body ).trigger( 'added_to_cart', [ response.fragments, response.cart_hash, $button ] ); 456 }else if(response.error){ 457 Notice.$noticeContainer().html(response.notice); 458 Notice.showMarkupNotice(); 459 } 460 else{ 461 window.location.reload(); 462 } 463 464 }, 465 complete: function(){ 466 this.unblock(); 467 $button 468 .removeClass('loading') 469 .addClass('added'); 470 } 471 }) 472 } 473 474 addedToCart( e, response, hash, $button ){ 475 476 $(document.body).trigger( 'xoo_wsc_cart_updated', [response] ); 477 478 var _this = this; 479 480 this.flyToCart( $button, function(){ 481 if( xoo_wsc_params.autoOpenCart === "yes" ){ 482 setTimeout(function(){ 483 _this.openCart(); 484 },20 ) 485 } 486 } ); 487 } 488 489 490 blockAddedToCart(){ 491 492 if( this.isWCAjaxAddToCart ) return; 493 494 this.refreshMyFragments(); 495 496 var _this = this; 497 498 if( xoo_wsc_params.autoOpenCart === "yes" ){ 499 setTimeout(function(){ 500 _this.openCart(); 501 },20 ) 502 } 503 } 504 505 506 flyToCart( $atcEL, callback ){ 507 508 var $basket = this.$modal.find('.xoo-wsc-basket').length ? this.$modal.find('.xoo-wsc-basket') : $(document.body).find('.xoo-wsc-sc-cont'); 509 510 if( !$basket.length || xoo_wsc_params.flyToCart !== 'yes' || !$atcEL || !$atcEL.length ){ 511 callback(); 512 return; 513 } 514 515 var customDragImgClass = xoo_wsc_params.productFlyClass, 516 $dragIMG = null, 517 $product = $atcEL.closest('.product'); 518 519 520 //If has product container 521 if( $product.length ){ 522 523 $product = $($product[0]); 524 525 var $productGallery = $product.find('.woocommerce-product-gallery'); 526 527 if( customDragImgClass && $product.find( customDragImgClass ).length ){ 528 $dragIMG = $product.find( customDragImgClass ); 529 } 530 else if( $product.find( 'img[data-xooWscFly="fly"]' ).length ){ 531 if( $productGallery.length ){ 532 $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"]' ) 533 } 534 else{ 535 $dragIMG = $product.find( 'img[data-xooWscFly="fly"]' ); 536 } 537 } 538 else if( $productGallery.length ){ 539 $dragIMG = $productGallery; 540 } 541 else{ 542 $dragIMG = $product; 543 } 544 545 } 546 else if( customDragImgClass ){ 547 var moveUp = 4; 548 for ( var i = moveUp; i >= 0; i-- ) { 549 var $foundImg = $atcEL.parent().find( customDragImgClass ); 550 if( $foundImg.length ){ 551 $dragIMG = $foundImg; 552 return false; 553 } 554 } 555 } 556 557 558 if( !$dragIMG || !$dragIMG.length ){ 559 callback(); 560 return; 561 } 562 563 $dragIMG = $dragIMG.eq(0); 564 565 var $imgclone = $dragIMG 566 .clone() 567 .offset({ 568 top: $dragIMG.offset().top, 569 left: $dragIMG.offset().left 570 }) 571 .addClass( 'xoo-wsc-fly-animating' ) 572 .appendTo( $('body') ) 573 .animate({ 574 'top': $basket.offset().top - 20, 575 'left': $basket.offset().left - 20, 576 'width': 75, 577 'height': 75 578 }, parseInt( xoo_wsc_params.flyToCartTime ), 'easeInOutExpo' ); 579 580 setTimeout(function () { 581 callback() 582 }, parseInt( xoo_wsc_params.flyToCartTime ) ); 583 584 $imgclone.animate({ 585 'width': 0, 586 'height': 0 587 }, function () { 588 $(this).detach(); 589 }); 590 591 } 592 593 594 toggleQty(e){ 595 596 var $toggler = $(e.currentTarget), 597 $input = $toggler.siblings('.xoo-wsc-qty'); 598 599 if( !$input.length ) return; 600 601 var baseQty = this.baseQty = parseFloat( $input.val() ), 602 step = parseFloat( $input.attr('step') ), 603 action = $toggler.hasClass( 'xoo-wsc-plus' ) ? 'add' : 'less', 604 newQty = action === 'add' ? baseQty + step : baseQty - step; 605 606 607 $input.val(newQty).trigger('change'); 608 609 } 610 611 changeInputQty(e){ 612 613 this.notice.hideNotification(); 614 615 var $_this = this, 616 $input = $(e.currentTarget), 617 newQty = parseFloat( $input.val() ), 618 step = parseFloat( $input.attr('step') ), 619 min = parseFloat( $input.attr('min') ), 620 max = parseFloat( $input.attr('max') ), 621 invalid = false, 622 message = false; 623 624 //Validation 625 626 if( isNaN( newQty ) || newQty < 0 || newQty < min ){ 627 invalid = true; 628 } 629 else if( newQty > max ){ 630 invalid = true;
631 message = xoo_wsc_params.strings.maxQtyError.replace( '%s%', max ); 632 } 633 else if( !Number.isInteger(newQty/step ) ){ 634 invalid = true; 635 message = xoo_wsc_params.strings.stepQtyError.replace( '%s%', step ); 636 } 637 638 //Set back to default quantity 639 if( invalid ){ 640 $input.val( this.baseQty ); 641 if( message ){ 642 this.notice.add( message, 'error' ); 643 this.notice.showNotification(); 644 } 645 return; 646 } 647 648 //Update 649 $input.val( newQty ); 650 651 clearTimeout( this.qtyUpdateDelay ); 652 653 this.qtyUpdateDelay = setTimeout(function(){ 654 $_this.updateItemQty( $input.parents('.xoo-wsc-product').data('key'), newQty ) 655 }, xoo_wsc_params.qtyUpdateDelay ); 656 657 658 } 659 660 updateItemQty( cart_key, qty ){ 661 662 if( !cart_key || qty === undefined ) return; 663 664 this.block(); 665 666 667 var bodyPosition = this.$modal.find('.xoo-wsc-body').length ? this.$modal.find('.xoo-wsc-body').scrollTop() : false; 668 669 670 var formData = { 671 cart_key: cart_key, 672 qty: qty 673 } 674 675 $.ajax({ 676 url: get_wcurl( 'xoo_wsc_update_item_quantity' ), 677 type: 'POST', 678 context: this, 679 data: this.setAjaxData(formData), 680 success: function(response){ 681 this.updateFragments( response ); 682 $(document.body).trigger( 'xoo_wsc_quantity_updated', [response] ); 683 $(document.body).trigger( 'xoo_wsc_cart_updated', [response] ); 684 if( bodyPosition !== false ){ 685 this.$modal.find( '.xoo-wsc-body' ).scrollTop( bodyPosition ); 686 } 687 this.unblock(); 688 } 689 690 }) 691 } 692 693 694 closeCartOnClick(e){ 695 e.preventDefault(); 696 if( drawer.isOpen() ){ 697 drawer.toggle('hide'); 698 setTimeout( function(){ 699 cart.toggle( 'hide' ) 700 }, 500 ); 701 } 702 else{ 703 cart.toggle('hide'); 704 } 705 706 } 707 708 709 saveQtyFocus(e){ 710 this.baseQty = $(e.currentTarget).val(); 711 } 712 713 714 onPageShow(e){ 715 if ( e.originalEvent.persisted ) { 716 this.refreshMyFragments(); 717 $( document.body ).trigger( 'wc_fragment_refresh' ); 718 } 719 } 720 721 deleteIconClick(e){ 722 this.updateItemQty( $( e.currentTarget ).parents('.xoo-wsc-product').data('key'), 0 ); 723 } 724 725 undoItem(e){ 726 727 var $undo = $(e.currentTarget), 728 formData = { 729 cart_key: $undo.data('key') 730 } 731 732 this.block(); 733 734 $.ajax({ 735 url: get_wcurl('xoo_wsc_undo_item'), 736 type: 'POST', 737 context: this, 738 data: this.setAjaxData(formData), 739 success: function(response){ 740 this.updateFragments( response ); 741 $(document.body).trigger( 'xoo_wsc_item_restored', [response] ); 742 $(document.body).trigger( 'xoo_wsc_cart_updated', [response] ); 743 this.unblock(); 744 } 745 746 }) 747 } 748 749 storeProgressBarWidth( e ){ 750 751 var $bar = $(document.body).find( '.xoo-wsc-bar-filled' ); 752 753 if( !$bar.length ) return; 754 755 this.progressBarWidth = $bar.prop('style').width; 756 757 var $barCont = $bar.closest('.xoo-wsc-bar-cont'), 758 barData = $barCont.data('bardata'); 759 760 if( !barData ) return; 761 762 this.progressBarData = barData; 763 } 764 765 onCartUpdate(){ 766 super.onCartUpdate(); 767 this.initAnimateProgressBar = true; 768 if( this.isOpen() ){ 769 this.animateProgressBar(); 770 } 771 this.initSlider(); 772 this.showBasket(); 773 this.initMasonryLayout(); 774 } 775 776 777 initMasonryLayout(){ 778 if( xoo_wsc_params.productLayout !== 'cards' ) return; 779 $('.xoo-wsc-products.xoo-wsc-pattern-card').masonry({ 780 // options 781 itemSelector: '.xoo-wsc-product-cont', 782 columnWidth: '.xoo-wsc-product-cont', /* Each column takes 50% */ 783 percentPosition: true 784 }); 785 } 786 787 showBasket(){ 788 789 var $basket = $('.xoo-wsc-basket'), 790 show = xoo_wsc_params.showBasket; 791 792 if( show === "always_show" ){ 793 $basket.show(); 794 } 795 else if( show === "hide_empty" ){ 796 if( this.$modal.find('.xoo-wsc-product').length ){ 797 $basket.show(); 798 } 799 else{ 800 $basket.hide(); 801 } 802 } 803 else{ 804 $basket.hide(); 805 } 806 } 807 808 animateProgressBar(){ 809 810 if( isCartPage || isCheckoutPage || !this.initAnimateProgressBar ) return; 811 812 var $bar = $(document.body).find( '.xoo-wsc-bar-filled' ); 813 814 if( !$bar.length || !this.progressBarWidth ) return; 815 var newWidth = $bar.prop('style').width; 816 817 $bar 818 .width( this.progressBarWidth ) 819 .animate({ width: newWidth }, 400, 'linear'); 820 821 this.checkPointAchievedAnimate(); 822 823 this.initAnimateProgressBar = false; 824 } 825 826 checkPointAchievedAnimate(){ 827 828 var pastBarData = this.progressBarData; 829 830 var $bar = $(document.body).find( '.xoo-wsc-bar-filled' ), 831 $barCont = $bar.closest('.xoo-wsc-bar-cont'), 832 barData = $barCont.data('bardata'); 833 834 var pastPointsReached = [], 835 newPointsReached = [], 836 allPointsReached = false; 837 838 $.each( pastBarData.points, function( index, point ){ 839 if( point.reached == true ){ 840 pastPointsReached.push(point.id); 841 } 842 } ) 843 844 $.each( barData.points, function( index, point ){ 845 if( point.reached == true && !pastPointsReached.includes(point.id) ){ 846 newPointsReached.push(point.id); 847 } 848 849 if( point.reached == true && (index + 1) === barData.points.length ){ 850 allPointsReached = true; 851 } 852 } ) 853 854 855 856 if( newPointsReached.length ){ 857 setTimeout( function(){ 858 Celebrate.Celebrate( allPointsReached && xoo_wsc_params.bar.fullCelebration !== 'none' ? xoo_wsc_params.bar.fullCelebration : xoo_wsc_params.bar.singleCelebration ); 859 }, 200 ); 860 } 861 862 this.progressBarData = barData; 863 } 864 865 866 emptyCart(){ 867 868 this.block(); 869 870 $.ajax({
871 url: get_wcurl( 'xoo_wsc_empty_cart' ), 872 type: 'POST', 873 context: this, 874 data: {}, 875 success: function(response){ 876 877 this.updateFragments( response ); 878 // Trigger event. 879 $( document.body ).trigger( 'xoo_wsc_cart_emptied' ); 880 $(document.body).trigger( 'xoo_wsc_cart_updated', [response] ); 881 }, 882 complete: function(){ 883 this.unblock(); 884 } 885 }) 886 } 887 888 889 initSlider(){ 890 891 if( typeof $.fn.lightSlider !== 'function' || xoo_wsc_params.spSlide.enable !== 'yes' ) return; 892 893 $('ul.xoo-wsc-sp-slider').each( function( index, el ){ 894 var $el = $(el); 895 896 if( $(this).parents('.xoo-wsc-drawer').length ) return; 897 898 $el.lightSlider(xoo_wsc_params.spSlide); 899 900 } ); 901 902 } 903 904 } 905 906 907 class Drawer extends Container{ 908 909 constructor( $modal ){ 910 911 super( $modal, 'drawer' ); 912 913 this.setHeaderHeight(); 914 915 this.eventHandlers(); 916 917 } 918 919 eventHandlers(){ 920 921 super.eventHandlers(); 922 923 $(document.body).on( 'xoo_wsc_cart_toggled', this.drawOutOnCartOpen.bind(this) ); 924 $(document.body).on( 'click', '.xoo-wsc-toggle-drawer', this.toggleDrawer.bind(this) ); 925 $(document.body).on( 'click', '.xoo-wscdh-close', this.close.bind(this) ); 926 $(document.body).on( 'wc_fragments_loaded', this.onCartUpdate.bind(this) ); 927 } 928 929 onCartUpdate(){ 930 super.onCartUpdate(); 931 this.setHeaderHeight(); 932 setTimeout(function(){ 933 drawer.toggleOnContentBasis(); 934 }, 0); 935 936 } 937 938 939 toggleOnContentBasis(){ 940 941 var hasContent = !this.isDrawerEmpty(); 942 943 if( this.isOpen() ){ 944 if( !hasContent ){ 945 this.toggle('hide'); 946 this.$modal.find('.xoo-wsc-dtg-icon').addClass('xoo-wsc-disabled'); 947 this.emptyClosed = true; 948 } 949 } 950 else{ 951 if( hasContent && cart.isOpen() && this.emptyClosed ){ 952 this.toggle('show'); 953 this.$modal.find('.xoo-wsc-dtg-icon').removeClass('xoo-wsc-disabled'); 954 this.emptyClosed = false; 955 } 956 } 957 } 958 959 setHeaderHeight(){ 960 var $cartHeader = $('.xoo-wsc-header'); 961 if( !$cartHeader.length ) return; 962 963 this.$modal.find('.xoo-wsc-drawer-header').height($cartHeader.height()); 964 } 965 966 isDrawerEmpty(){ 967 return !this.$modal.find('.xoo-wsc-dr-content').length; 968 } 969 970 971 toggleDrawer(){ 972 this.toggle(); 973 } 974 975 976 drawOutOnCartOpen(e,type){ 977 978 if( !cart.isOpen() || this.isDrawerEmpty() ) return; 979 980 setTimeout( function(){ 981 drawer.toggle('show'); 982 }, xoo_wsc_params.drawerWait ); 983 984 } 985 986 987 close(e){ 988 this.toggle('hide'); 989 } 990 991 992 } 993 994 995 996 class Slider extends Container{ 997 998 constructor( $modal ){ 999 1000 super( $modal, 'slider' ); 1001 1002 if( xoo_wsc_params.sliderAutoClose ) this.noticeSection = 'cart'; 1003 1004 this.eventHandlers(); 1005 1006 this.shipping = xoo_wsc_params.shippingEnabled ? Shipping.init( this ) : null; 1007 } 1008 1009 eventHandlers(){ 1010 1011 super.eventHandlers(); 1012 1013 1014 $( document.body ).on( 'click', '.xoo-wsc-toggle-slider', this.triggerSlider.bind(this) ); 1015 $( document.body ).on( 'xoo_wsc_cart_toggled', this.closeSliderOnCartClose.bind(this) ); 1016 1017 if( xoo_wsc_params.sliderAutoClose ){ 1018 $( document.body ).on( 'xoo_wsc_coupon_applied xoo_wsc_shipping_calculated updated_shipping_method xoo_wsc_coupon_removed', this.closeSlider.bind(this) ); 1019 } 1020 1021 $(document.body).on( 'submit', 'form.xoo-wsc-sl-apply-coupon', this.submitCouponForm.bind(this) ); 1022 $(document.body).on( 'click', '.xoo-wsc-coupon-apply-btn', this.applyCouponFromBtn.bind(this) ); 1023 $(document.body).on( 'click', '.xoo-wsc-remove-coupon', this.removeCoupon.bind(this) ); 1024 } 1025 1026 1027 removeCoupon(e){ 1028 1029 e.preventDefault(); 1030 1031 var $removeEl = $(e.currentTarget), 1032 coupon = $removeEl.data('code'), 1033 formData = { 1034 coupon: coupon 1035 }; 1036 1037 this.block(); 1038 1039 $.ajax( { 1040 url: get_wcurl( 'xoo_wsc_remove_coupon' ), 1041 type: 'POST', 1042 context: this, 1043 data: this.setAjaxData( formData, cart.$modal.find( $removeEl ).length ? 'cart' : 'slider' ), 1044 success: function( response ) { 1045 this.updateFragments(response); 1046 }, 1047 complete: function() { 1048 this.unblock(); 1049 this.updateCartCheckoutPage(); 1050 $( document.body ).trigger( 'xoo_wsc_coupon_removed' ); 1051 } 1052 } ); 1053 } 1054 1055 onCartUpdate(){ 1056 super.onCartUpdate(); 1057 this.toggleContent(); 1058 } 1059 1060 closeSlider(){ 1061 this.toggle('hide'); 1062 } 1063 1064 1065 applyCouponFromBtn(e){ 1066 this.applyCoupon( $(e.currentTarget).val() ); 1067 } 1068 1069 submitCouponForm(e){ 1070 1071 e.preventDefault(); 1072 1073 var $form = $(e.currentTarget); 1074 1075 this.applyCoupon( $form.find('input[name="xoo-wsc-slcf-input"]').val() ); 1076 1077 } 1078 1079 1080 closeSliderOnCartClose(e){ 1081 1082 var $this = $(e.currentTarget); 1083 1084 if( !cart.$modal.hasClass('xoo-wsc-cart-active') ){ 1085 this.toggle('hide'); 1086 } 1087 1088 } 1089 1090 1091 triggerSlider(e){ 1092 1093 var $toggler = $(e.currentTarget), 1094 slider = $toggler.data('slider'); 1095 1096 if( slider === 'shipping' && isCheckoutPage ){
1097 this.notice.add( xoo_wsc_params.strings.calculateCheckout, 'error' ); 1098 this.notice.showNotification(); 1099 return; 1100 } 1101 1102 1103 this.$modal.attr( 'data-slider', slider ); 1104 1105 this.toggle(); 1106 1107 this.toggleContent(); 1108 } 1109 1110 1111 toggleContent(){ 1112 1113 var activeSlider = ''; 1114 1115 $('.xoo-wsc-sl-content').hide(); 1116 1117 var activeSlider = this.$modal.attr('data-slider'), 1118 $toggleEl = $('.xoo-wsc-sl-content[data-slider="'+activeSlider+'"]'); 1119 1120 if( $toggleEl.length ) $toggleEl.show(); 1121 1122 $( document.body ).trigger( 'xoo_wsc_slider_data_toggled', [activeSlider] ); 1123 } 1124 1125 1126 applyCoupon( coupon ){ 1127 1128 if( !coupon ){ 1129 this.notice.add( xoo_wsc_params.strings.couponEmpty, 'error' ); 1130 this.notice.showNotification(); 1131 return; 1132 } 1133 1134 this.block(); 1135 1136 var formData = { 1137 'coupon': coupon, 1138 } 1139 1140 $.ajax( { 1141 url: get_wcurl('xoo_wsc_apply_coupon'), 1142 type: 'POST', 1143 context: this, 1144 data: this.setAjaxData( formData ), 1145 success: function( response ) { 1146 this.updateFragments(response); 1147 }, 1148 complete: function() { 1149 this.unblock(); 1150 this.updateCartCheckoutPage(); 1151 $( document.body ).trigger( 'xoo_wsc_coupon_applied' ); 1152 } 1153 } ); 1154 1155 } 1156 1157 } 1158 1159 1160 1161 var Shipping = { 1162 1163 init: function( slider ){ 1164 slider.$modal.on( 'change', 'input.xoo-wsc-shipping-method', this.shippingMethodChange ); 1165 slider.$modal.on( 'submit', 'form.woocommerce-shipping-calculator', this.shippingCalculatorSubmit ); 1166 slider.$modal.on( 'click', '.shipping-calculator-button', this.toggleCalculator ); 1167 $(document.body).on( 'wc_fragments_loaded xoo_wsc_slider_data_toggled', this.initSelect2 ); 1168 }, 1169 1170 toggleCalculator: function(e){ 1171 1172 e.preventDefault(); 1173 e.stopImmediatePropagation(); 1174 1175 $(this).siblings('.shipping-calculator-form').slideToggle(); 1176 $( document.body ).trigger( 'country_to_state_changed' ); 1177 }, 1178 1179 shippingCalculatorSubmit: function(e){ 1180 1181 e.preventDefault(); 1182 e.stopImmediatePropagation(); 1183 1184 var $form = $(this); 1185 1186 slider.block(); 1187 1188 // Provide the submit button value because wc-form-handler expects it. 1189 $( '<input />' ) 1190 .attr( 'type', 'hidden' ) 1191 .attr( 'name', 'calc_shipping' ) 1192 .attr( 'value', 'x' ) 1193 .appendTo( $form ); 1194 1195 var formData = $form.serialize(); 1196 1197 // Make call to actual form post URL. 1198 $.ajax( { 1199 url: get_wcurl( 'xoo_wsc_calculate_shipping' ), 1200 type: 'POST', 1201 context: this, 1202 data: slider.setAjaxData(formData), 1203 success: function( response ) { 1204 slider.updateFragments(response); 1205 }, 1206 complete: function() { 1207 slider.unblock(); 1208 slider.updateCartCheckoutPage(); 1209 $( document.body ).trigger( 'xoo_wsc_shipping_calculated' ); 1210 } 1211 } ); 1212 1213 }, 1214 1215 shippingMethodChange: function(e){ 1216 1217 e.preventDefault(); 1218 e.stopImmediatePropagation(); 1219 1220 var shipping_methods = {}; 1221 1222 slider.block(); 1223 1224 $( 'select.shipping_method, :input[name^=xoo-wsc-shipping_method][type=radio]:checked, :input[name^=shipping_method][type=hidden]' ).each( function() { 1225 shipping_methods[ $( this ).data( 'index' ) ] = $( this ).val(); 1226 } ); 1227 1228 var formData = { 1229 shipping_method: shipping_methods, 1230 } 1231 1232 $.ajax( { 1233 type: 'POST', 1234 url: get_wcurl( 'xoo_wsc_update_shipping_method' ), 1235 data: slider.setAjaxData( formData ), 1236 success: function( response ) { 1237 slider.updateFragments(response); 1238 }, 1239 complete: function() { 1240 slider.unblock(); 1241 slider.updateCartCheckoutPage(); 1242 $( document.body ).trigger( 'updated_shipping_method' ); 1243 } 1244 } ); 1245 1246 }, 1247 1248 initSelect2: function(e){ 1249 $( document.body ).trigger( 'country_to_state_changed' ); 1250 }, 1251 } 1252 1253 1254 var cart = new Cart( $('.xoo-wsc-modal') ), 1255 slider = new Slider( $('.xoo-wsc-slider-modal') ); 1256 drawer = new Drawer( $('.xoo-wsc-drawer-modal') ); 1257 1258 1259 var AnimateCard = { 1260 1261 type: xoo_wsc_params.cardAnimate.type, 1262 duration: xoo_wsc_params.cardAnimate.duration, 1263 1264 init: function(){ 1265 1266 var onEvent = xoo_wsc_params.cardAnimate.event === 'back_hover' ? 'mouseenter' : 'click'; 1267 1268 $('body').on( onEvent, '.xoo-wsc-has-back', this.animate ); 1269 $('body').on( 'mouseleave', '.xoo-wsc-has-back', this.reverseAnimate ); 1270 1271 }, 1272 animate: function(e){
1273 1274 if( e.target.classList.contains('xoo-wsc-smr-del') ) return; 1275 1276 var $img = $(this).find('.xoo-wsc-img-col'); 1277 1278 if( !$img.hasClass('xoo-wsc-caniming') ){ 1279 e.preventDefault(); 1280 } 1281 else{ 1282 return; 1283 } 1284 1285 $img.attr('data-exclasses', $img.attr('class') ); 1286 1287 $img.removeClass() 1288 $img.addClass($img.attr('data-exclasses')); 1289 1290 $img.addClass( 'xoo-wsc-caniming' + ' ' + AnimateCard.type ); 1291 1292 }, 1293 reverseAnimate: function(){ 1294 1295 var $img = $(this).find('.xoo-wsc-img-col'); 1296 1297 if( !$img.hasClass( 'xoo-wsc-caniming' ) ) return; 1298 1299 $img.addClass(AnimateCard.type+'Return'); 1300 1301 AnimateCard.clear = setTimeout(function(){ 1302 $img.removeClass().addClass( $img.attr('data-exclasses') ); 1303 }, AnimateCard.duration * 1000); 1304 1305 } 1306 } 1307 1308 if( xoo_wsc_params.cardAnimate.enable === "yes" ){ 1309 AnimateCard.init(); 1310 } 1311 1312 1313 1314 var Celebrate = { 1315 1316 canvasIndex: 0, 1317 1318 barPosition: false, 1319 1320 myconfetti: '', 1321 1322 Celebrate: async function( celebrationName ){ 1323 if( Celebrate[ celebrationName ] ){ 1324 await Celebrate.CreateCanvas(); 1325 Celebrate[ celebrationName ](); 1326 } 1327 }, 1328 1329 CreateCanvas: async function(){ 1330 1331 if( $('.xoo-wsc-container').find('canvas').length ){ 1332 $('.xoo-wsc-container').find('canvas').remove(); 1333 } 1334 1335 $('.xoo-wsc-container').append('<canvas id="xoo_canvas_'+Celebrate.canvasIndex+'"></canvas>').show(); 1336 1337 Celebrate.canvasIndex++; 1338 1339 var canvas = $('.xoo-wsc-container canvas').get(0); 1340 1341 Celebrate.myconfetti = await (confetti.create(canvas, { resize: true }) ); 1342 1343 }, 1344 1345 BarPosition: function(){ 1346 if( !Celebrate.barPosition ){ 1347 var windowHeight = $(window).height(), 1348 $bar = $('.xoo-wsc-bar'), 1349 barPosition = $bar.offset().top - $(window).scrollTop(); 1350 1351 Celebrate.barPosition = barPosition/windowHeight; 1352 } 1353 return Celebrate.barPosition; 1354 1355 }, 1356 1357 Fireworks: function(){ 1358 1359 const duration = 3 * 1000, 1360 animationEnd = Date.now() + duration, 1361 defaults = { startVelocity: 30, spread: 100, ticks: 60, zIndex: 0 }; 1362 1363 function randomInRange(min, max) { 1364 return Math.random() * (max - min) + min; 1365 } 1366 1367 const interval = setInterval(function() { 1368 const timeLeft = animationEnd - Date.now(); 1369 1370 if (timeLeft <= 0) { 1371 return clearInterval(interval); 1372 } 1373 1374 const particleCount = 50 * (timeLeft / duration); 1375 1376 // since particles fall down, start a bit higher than random 1377 Celebrate.myconfetti( 1378 Object.assign({}, defaults, { 1379 particleCount, 1380 origin: { x: randomInRange(0.1, 0.3), y: Celebrate.BarPosition() }, 1381 }) 1382 ); 1383 Celebrate.myconfetti( 1384 Object.assign({}, defaults, { 1385 particleCount, 1386 origin: { x: randomInRange(0.7, 0.9), y: Celebrate.BarPosition() }, 1387 }) 1388 ); 1389 }, 250); 1390 1391 }, 1392 1393 Stars: function(){ 1394 1395 const defaults = { 1396 origin: { x: 0.5, y: Celebrate.BarPosition() }, 1397 spread: 360, 1398 ticks: 50, 1399 gravity: 0, 1400 decay: 0.94, 1401 startVelocity: 30, 1402 shapes: ["star"], 1403 colors: ["FFE400", "FFBD00", "E89400", "FFCA6C", "FDFFB8"], 1404 }; 1405 1406 function shoot() { 1407 Celebrate.myconfetti({ 1408 ...defaults, 1409 particleCount: 40, 1410 scalar: 1, 1411 shapes: ["star"], 1412 }); 1413 1414 Celebrate.myconfetti({ 1415 ...defaults, 1416 particleCount: 10, 1417 scalar: 0.75, 1418 shapes: ["circle"], 1419 }); 1420 } 1421 1422 setTimeout(shoot, 0); 1423 setTimeout(shoot, 100); 1424 setTimeout(shoot, 200); 1425 }, 1426 1427 SchoolPride: function(){ 1428 1429 const end = Date.now() + 1.5 * 1000; 1430 1431 // go Buckeyes! 1432 const colors = ["#bb0000", "#ffffff"]; 1433 1434 (function frame() { 1435 Celebrate.myconfetti({ 1436 particleCount: 2, 1437 angle: 60, 1438 spread: 55, 1439 origin: { x: 0, y: Celebrate.BarPosition() }, 1440 colors: colors, 1441 }); 1442 1443 Celebrate.myconfetti({ 1444 particleCount: 2, 1445 angle: 120, 1446 spread: 55, 1447 origin: { x: 1, y: Celebrate.BarPosition() }, 1448 colors: colors, 1449 }); 1450 1451 if (Date.now() < end) { 1452 requestAnimationFrame(frame); 1453 } 1454 })(); 1455 }, 1456 1457 RealisticLook: function(){ 1458 1459 const count = 1000, 1460 1461 defaults = { 1462 origin: { y: Celebrate.BarPosition() }, 1463 }; 1464 1465 function fire(particleRatio, opts) { 1466 Celebrate.myconfetti( 1467 Object.assign({}, defaults, opts, { 1468 particleCount: Math.floor(count * particleRatio), 1469 }) 1470 ); 1471 } 1472 1473 fire(0.25, { 1474 spread: 26, 1475 startVelocity: 55, 1476 }); 1477 1478 fire(0.2, { 1479 spread: 60, 1480 }); 1481 1482 fire(0.35, { 1483 spread: 100, 1484 decay: 0.91, 1485 scalar: 0.8, 1486 }); 1487 1488 fire(0.1, { 1489 spread: 120, 1490 startVelocity: 25, 1491 decay: 0.92, 1492 scalar: 1.2, 1493 }); 1494 1495 fire(0.1, { 1496 spread: 120, 1497 startVelocity: 45, 1498 }); 1499 }, 1500 1501 BasicCannon: function(){ 1502 Celebrate.myconfetti({ 1503 particleCount: 400, 1504 spread: 70, 1505 origin: { y: Celebrate.BarPosition() }, 1506 }); 1507 } 1508 1509 } 1510 1511 1512 1513}) 1514
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.