1! function( $ ) { 2 "use strict"; 3 4 if ( typeof Codevz_Plus != 'object' ) { 5 var Codevz_Plus = {}; 6 } 7 8 Codevz_Plus.woocommerce = function() { 9 10 var body = $( document.body ), 11 adminBar = document.getElementById('wpadminbar') ? 32 : 0; 12 13 // Fix WC message button. 14 document.querySelectorAll( '.button.wc-forward' ).forEach( function( el ) { 15 el.classList.remove( 'wc-forward' ); 16 }); 17 18 // AJAX Filters. 19 if ( document.querySelector( '.codevz-plus-shop-ajax-filters' ) ) { 20 21 function filterByPrice( page = 1 ) { 22 const filtersDiv = $('.codevz-plus-shop-ajax-filters'); 23 const nonce = filtersDiv.data('nonce'); 24 const [min, max] = [parseInt($('#min_price').val(), 10), parseInt($('#max_price').val(), 10)]; 25 const rangeMin = $('.price_slider').slider('option', 'min'); 26 const rangeMax = $('.price_slider').slider('option', 'max'); 27 28 $('ul.products').addClass('codevz-plus-loading-products'); 29 30 $.post(body.data('ajax'), { action: 'filter_products_by_price', min_price: min, max_price: max, page, nonce }, (res) => { 31 if (res.error) { 32 alert(res.data.message || 'Security check failed.'); 33 return; 34 } 35 36 $('ul.products').removeClass('codevz-plus-loading-products').html(res.products); 37 $('.woocommerce-pagination').replaceWith(res.pagination); 38 39 // Show selected price filter if range changed 40 const filterHtml = (min > rangeMin || max < rangeMax) ? ` 41 <div data-filter="price"> 42 <span>Price: $${min} - $${max}</span> 43 <i class="fa czico-close-bold codevz-plus-shop-ajax-remove-filter"></i> 44 </div>` : '';
45 filtersDiv.find('> div').html(filterHtml); 46 }); 47 } 48 49 // Debounce and optimize slider event 50 let debounceTimer; 51 body.on('slidechange', '.widget .price_slider', function() { 52 clearTimeout(debounceTimer); 53 debounceTimer = setTimeout(function() { filterByPrice() }, 200 ); 54 }); 55 56 // Remove filter 57 body.on('click', '.codevz-plus-shop-ajax-remove-filter', function() { 58 $(this).parent().remove(); 59 $('.widget .price_slider').slider('values', [0, $('.price_slider').slider('option', 'max')]); 60 filterByPrice(); 61 }); 62 63 // Pagination 64 body.on('click', '.woocommerce-pagination a', function(e) { 65 e.preventDefault(); 66 filterByPrice($(this).data('page') || 1); 67 }); 68 } 69 70 // Product quantity field. 71 document.addEventListener( 'click', function (e) { 72 73 const btn = e.target.closest('.quantity-up, .quantity-down'); 74 if (!btn) { return; } 75 76 const wrap = btn.closest('.quantity'); 77 if (!wrap) { return; } 78 79 const i = wrap.querySelector('input.qty'); 80 if (!i || i.disabled || i.readOnly) { return; } 81 82 const max = parseFloat(i.max) || Infinity; 83 84 let current = parseFloat(i.value); 85 if (isNaN(current)) { current = 0; } 86 87 const next = btn.classList.contains('quantity-up') 88 ? Math.min(current + 1, max) 89 : Math.max(current - 1, 1); 90 91 if (next === current) { return; } 92 93 i.value = next; 94 i.dispatchEvent(new Event('change', { bubbles: true })); 95 96 if ( ! i.closest( '.product-type-grouped, .cz_popup_in, .woocommerce-cart-form' ) ) { 97 document.querySelectorAll('.page_content input.qty').forEach(function (other) { 98 if ( 99 other === i || 100 other.closest('.product-type-grouped') || 101 parseFloat(other.value) === next 102 ) { 103 return; 104 } 105 106 other.value = next; 107 other.dispatchEvent(new Event('change', { bubbles: true })); 108 }); 109 } 110 }); 111 112 // Cart page. 113 if ( document.querySelector( '.woocommerce-cart-form' ) ) { 114 115 // When cart page is empty, refresh 116 body.on( 'updated_wc_div', function() { 117 if ( ! document.querySelector( '.cart_item' ) ) { 118 window.location.reload(); 119 } 120 }); 121 122 // Auto update cart on quantity change 123 let timeout; 124 document.body.addEventListener( 'change', function(e) { 125 const input = e.target.closest( '.woocommerce-cart-form input.qty' ); 126 if (!input) {return;} 127 128 clearTimeout(timeout); 129 130 timeout = setTimeout(function() { 131 const updateBtn = document.querySelector( '[name="update_cart"]' ); 132 if (updateBtn) {updateBtn.click();} 133 }, 1000); 134 }); 135 136 } 137 138 // Custom variations. 139 document.addEventListener('click', function(e) { 140 const label = e.target.closest('.codevz-variations label'); 141 if (!label) {return;} 142 143 const radio = label.previousElementSibling; 144 if (radio && radio.type === 'radio') { 145 radio.checked = true; 146 147 const val = radio.value; 148 const form = label.closest('.variations_form'); 149 const container = label.closest('.value'); 150 151 if (container) { 152 const select = container.querySelector('select'); 153 if (select) { 154 select.value = val; 155 select.dispatchEvent(new Event('change', { bubbles: true })); 156 157 if (form) { 158 const jqueryForm = window.jQuery && window.jQuery(form); 159 if (jqueryForm) { 160 jqueryForm.trigger('check_variations'); 161 } 162 } 163 } 164 } 165 } 166 }); 167 168 // Single add to cart fake loading. 169 let clickedButton = null; 170 body.on( 'click', '.single_add_to_cart_button', function() { 171 clickedButton = $( this ); 172 sessionStorage.wooclicked = '1'; 173 }); 174 $(window).on( 'beforeunload', function() { 175 if ( clickedButton && sessionStorage.wooclicked ) { 176 clickedButton.addClass( 'loading' ); 177 sessionStorage.removeItem( 'wooclicked' ); 178 } 179 }); 180 181 // Single AJAX add to cart. 182 document.addEventListener( 'submit', function(e) { 183 const form = e.target.closest('form.cart'); 184 if (!form || form.closest('.product-type-external') || ! form.closest( '.codevz-woo-ajax-add-to-cart' ) ) { 185 return; 186 } 187 188 if ( typeof wc_add_to_cart_params !== 'undefined' && wc_add_to_cart_params.cart_redirect_after_add === 'yes' ) { 189 return; 190 } 191 192 e.preventDefault(); 193 194 const button = form.querySelector('.single_add_to_cart_button');
195 const qty = form.querySelector('input.qty'); 196 const formData = new FormData(form); 197 198 if (!formData.has('product_id')) { 199 const idInput = form.querySelector('input[name="add-to-cart"]') || form.querySelector('button[name="add-to-cart"]'); 200 if (idInput) formData.append('product_id', idInput.value); 201 } 202 203 formData.append('action', 'single_add_to_cart'); 204 formData.append('nonce', xtra_strings.nonce); 205 206 button.classList.add('loading'); 207 if (qty) { 208 qty.disabled = true; 209 qty.parentNode.style.opacity = '0.3'; 210 } 211 212 fetch(wc_add_to_cart_params.ajax_url, { 213 method: 'POST', 214 body: formData 215 }) 216 .then(response => response.json()) 217 .then(data => { 218 if (data.error) { 219 window.location = data.product_url; 220 return; 221 } 222 223 if (data.fragments) { 224 Object.entries(data.fragments).forEach(([selector, html]) => { 225 const target = document.querySelector(selector); 226 if (target) { 227 if (selector === '.cz_cart_items' || target.classList.contains('cz_cart_items')) { 228 const temp = document.createElement('div'); 229 temp.innerHTML = html; 230 const newContent = temp.querySelector(selector) ? temp.querySelector(selector).innerHTML : temp.innerHTML; 231 target.innerHTML = newContent; 232 } else { 233 target.outerHTML = html; 234 } 235 } 236 }); 237 } 238 239 if (typeof jQuery !== 'undefined') { 240 jQuery(document.body).trigger('added_to_cart', [data.fragments, data.cart_hash, jQuery(button)]); 241 } 242 243 button.classList.remove('loading'); 244 button.classList.add('added'); 245 246 // Show shopping mini cart after added. 247 setTimeout(() => { 248 const elmsCart = document.querySelector('.elms_shop_cart'); 249 if ( elmsCart && ! form.closest( '.cz_popup_in' ) ) { 250 document.querySelector('.elms_shop_cart').dispatchEvent(new MouseEvent('mouseover', { bubbles: true })); 251 252 window.scrollTo({ 253 top: 0, 254 behavior: 'smooth' 255 }); 256 } 257 }, 10); 258 259 if (qty) { 260 qty.disabled = true; 261 qty.parentNode.style.opacity = '0.3'; 262 } 263 }) 264 .catch(() => { 265 button.classList.remove('loading'); 266 if (qty) { 267 qty.disabled = false; 268 qty.parentNode.style.opacity = '1'; 269 } 270 }); 271 }); 272 273 // AJAX remove from mini cart. 274 document.addEventListener('click', function(e) { 275 const removeLink = e.target.closest('a.remove'); 276 if (!removeLink) {return;} 277 278 removeLink.classList.add( 'codevz-remove' ); 279 280 e.preventDefault(); 281 282 const cartContainer = removeLink.closest('.cz_cart_items'); 283 const itemRow = removeLink.closest('.item_small'); 284 const url = new URL(removeLink.getAttribute('href')); 285 const removeKey = url.searchParams.get('remove_item'); 286 287 if (!removeKey) {return;} 288 if (itemRow) {itemRow.style.opacity = '0.3';} 289 290 function update_cart() { 291 const updateBtn = document.querySelector('[name="update_cart"]'); 292 if (updateBtn) { 293 updateBtn.disabled = false; 294 updateBtn.click(); 295 } 296 setTimeout(() => document.querySelector( '.elms_shop_cart' ).dispatchEvent(new MouseEvent('mouseover', { bubbles: true })), 10 ); 297 } 298 299 fetch(wc_add_to_cart_params.ajax_url, { 300 method: 'POST', 301 body: new URLSearchParams({ 302 action: 'single_add_to_cart_remove', 303 remove_item: removeKey, 304 nonce: xtra_strings.nonce 305 }) 306 }) 307 .then(response => response.json()) 308 .then(data => { 309 if (data.fragments) { 310 Object.entries(data.fragments).forEach(([selector, html]) => { 311 const target = document.querySelector(selector); 312 if (!target) {return;} 313 314 if (selector === '.cz_cart_items' || target.classList.contains('cz_cart_items')) { 315 const temp = document.createElement('div'); 316 temp.innerHTML = html; 317 const newContent = temp.querySelector(selector) ? temp.querySelector(selector).innerHTML : temp.innerHTML; 318 target.innerHTML = newContent; 319 } else { 320 target.outerHTML = html; 321 } 322 update_cart(); 323 }); 324 } 325 326 if (typeof jQuery !== 'undefined') { 327 jQuery(document.body).trigger('removed_from_cart', [data.fragments, data.cart_hash, jQuery(removeLink)]); 328 } 329 }) 330 .catch(() => { 331 if (itemRow) {itemRow.style.opacity = '1';} 332 update_cart(); 333 }); 334 }); 335 336 // Widgets accordion. 337 document.querySelectorAll( '.codevz-widgets-toggle .page_content .sidebar_inner' ).forEach( c => c.addEventListener( 'click', e => { 338 const t = e.target.closest('.codevz-widget-title'); 339 if (!t) {return;} 340 const n = t.nextElementSibling; 341 if (!n) {return;} 342 n.hidden = !n.hidden; 343 })); 344 345 // Auto x-position shop cart in header. 346 if ( document.querySelector( '.elms_shop_cart' ) ) { 347 348 if ( document.querySelector( '.elms_shop_cart_offcanvas' ) ) { 349 350 // v6.0 - Custom cart offcanvas. 351 body.off( 'click.elms_shop_cart_offcanvas' ).on( 'click.elms_shop_cart_offcanvas', '.elms_shop_cart_offcanvas', function( e ) { 352 353 Codevz.offCanvas( $( this ).addClass( 'done' ), 1, $( '[data-offcanvas="cart"]' ) ); 354 e.preventDefault(); 355 }); 356 357 } else { 358
359 const overlay = document.querySelector('.codevz-plus-dropdown-overlay .inner_layout > .cz_overlay'); 360 let hoverTimeout; 361 let isCartActive = false; 362 363 document.body.addEventListener('click', (e) => { 364 const dropdown = document.querySelector('.cz_cart_items'); 365 366 if (dropdown && !dropdown.contains(e.target) && !e.target.closest('.elms_shop_cart') && !e.target.closest('.cz')) { 367 dropdown.style.opacity = '0'; 368 dropdown.style.visibility = 'hidden'; 369 dropdown.style.pointerEvents = 'none'; 370 if (overlay) { 371 overlay.style.display = 'none'; 372 } 373 isCartActive = false; 374 } 375 }); 376 377 document.body.addEventListener('mouseover', (e) => { 378 const cartX = e.target.closest('.elms_shop_cart'); 379 if (!cartX) { 380 return; 381 } 382 383 isCartActive = true; 384 clearTimeout(hoverTimeout); 385 386 const dropdown = cartX.querySelector('.cz_cart_items'); 387 const icon = cartX.querySelector('.shop_icon i'); 388 const isRtl = document.body.classList.contains('rtl'); 389 390 if (!dropdown) { 391 return; 392 } 393 394 dropdown.style.pointerEvents = 'auto'; 395 396 if ((window.innerWidth / 2) > (cartX.getBoundingClientRect().left + window.scrollX + 300)) { 397 cartX.classList.add('inview_right'); 398 const iconMl = parseFloat(getComputedStyle(icon).marginLeft) || 0; 399 const leftVal = (icon.offsetWidth / 2) + (isRtl ? -38 : 36) + iconMl; 400 dropdown.style.left = isRtl ? `${leftVal}px` : `-${leftVal}px`; 401 } else { 402 const iconMr = parseFloat(getComputedStyle(icon).marginRight) || 0; 403 dropdown.style.right = `${(icon.offsetWidth / 2) - 36 + iconMr}px`; 404 } 405 406 setTimeout(() => { 407 dropdown.style.opacity = '1'; 408 dropdown.style.visibility = 'visible'; 409 if (overlay) { 410 overlay.style.zIndex = '99'; 411 overlay.style.display = 'block'; 412 } 413 }, 100); 414 }); 415 416 document.body.addEventListener('mouseout', (e) => { 417 if (!isCartActive) { 418 return; 419 } 420 421 const cartX = e.target.closest('.elms_shop_cart'); 422 if (!cartX) { 423 return; 424 } 425 426 const dropdown = cartX.querySelector('.cz_cart_items'); 427 const relatedTarget = e.relatedTarget; 428 429 if (!dropdown) { 430 return; 431 } 432 433 if (relatedTarget && cartX.contains(relatedTarget)) { 434 return; 435 } 436 437 isCartActive = false; 438 439 hoverTimeout = setTimeout(() => { 440 dropdown.style.opacity = '0'; 441 dropdown.style.visibility = 'hidden'; 442 dropdown.style.pointerEvents = 'none'; 443 if (overlay) { 444 overlay.style.display = 'none'; 445 } 446 }, 250); 447 }); 448 449 } 450 451 } 452 453 // Move cart count to icon data. 454 const cartBox = document.querySelector( '.elms_shop_cart' ); 455 if ( cartBox ) { 456 let mutationTimeout; 457 const observer = new MutationObserver(() => { 458 clearTimeout(mutationTimeout); 459 mutationTimeout = setTimeout(() => { 460 cartBox.querySelector( '.shop_icon > i' ).setAttribute( 'data-count', cartBox.querySelector( '.cz_cart_count' ).innerHTML ); 461 }, 100 ); 462 }); 463 observer.observe( cartBox, { childList: true, subtree: true }); 464 } 465 466 // Wishlist & Compare popup. 467 var wishComPopup = $( '#xtra_wish_compare' ); 468 wishComPopup.appendTo( 'body' ); 469 470 // Fix wishComPopup link issue. 471 wishComPopup.on( 'click', 'a', function() { 472 window.location = $( this ).attr( 'href' ); 473 }); 474 475 // Current wishlist items 476 if ( document.querySelector( '.xtra-add-to-wishlist, .xtra-wishlist, .wishlist_icon' ) ) { 477 478 var wishlist = localStorage.getItem( 'xtraWishlist' ), 479 wishlistDiv = $( '.xtra-wishlist' ), 480 noWishlist = '<h2 class="xtra-wish-compare-empty xtra-wishlist-empty tac"><i class="fa fa-heart-o"></i>' + wishlistDiv.attr( 'data-empty' ) + '<small>' + xtra_strings.wishlist_desc + '</small></h2><a href="' + xtra_strings.shop_url + '" class="button" style="margin:40px auto;display:table;"><span><strong>' + xtra_strings.back_to_shop + '</strong></span></a>'; 481 482 // Wishlist shortcode 483 wishlistDiv.length && wishlistDiv.each( function() { 484 485 var en = $( this ), 486 nonce = en.data( 'nonce' ), 487 col = en.data( 'col' ); 488 489 if ( wishlist ) { 490 491 // Check ID's. 492 $.post( body.data( 'ajax' ), 'action=xtra_wishlist_content&check=1&ids=' + wishlist + '&nonce=' + nonce, function( msg ) { 493 494 localStorage.setItem( 'xtraWishlist', msg ); 495 496 wishlist = msg; 497 498 // Get wishlist products. 499 $.post( body.data( 'ajax' ), 'action=xtra_wishlist_content&ids=' + wishlist + '&nonce=' + nonce + '&
499col=' + col, function( msg ) { 500 501 en.removeClass( 'xtra-icon-loading' ).html( msg ); 502 503 $( '.woocommerce-loop-product__link' ).prepend( '<i class="xtra-remove-from-wishlist fas fa-times"></i>' ); 504 505 var count = localStorage.getItem( 'xtraWishlist' ).replace( /\d+/g,'' ).length; 506 507 $( '.wishlist_icon > i' ).attr( 'data-count', count || 0 ); 508 509 if ( ! count ) { 510 en.removeClass( 'xtra-icon-loading' ).html( noWishlist ); 511 } 512 513 if ( ! en.find( 'li' ).length ) { 514 en.removeClass( 'xtra-icon-loading' ).html( noWishlist ); 515 } 516 517 }); 518 519 }); 520 521 } else { 522 523 en.removeClass( 'xtra-icon-loading' ).html( noWishlist ); 524 525 } 526 527 }); 528 529 // Set wishlist products 530 if ( wishlist ) { 531 wishlist = wishlist.split( ',' ); 532 533 $.each( wishlist, function( index, id ) { 534 var product = $( '[data-id="' + id + '"] .xtra-add-to-wishlist' ); 535 536 if ( product.length ) { 537 product.removeClass( 'fa-heart-o' ).addClass( 'fa-heart' ).attr( 'data-title', xtra_strings.added_wishlist ); 538 } 539 }); 540 541 var count = localStorage.getItem( 'xtraWishlist' ).replace( /\d+/g,'' ).length; 542 543 $( '.wishlist_icon > i' ).attr( 'data-count', count || 0 ); 544 545 if ( ! count ) { 546 wishlistDiv.removeClass( 'xtra-icon-loading' ).html( noWishlist ); 547 } 548 } 549 550 // Wishlist icon. 551 body.on( 'click', '.xtra-add-to-wishlist,.xtra-remove-from-wishlist', function(e) { 552 553 var en = $( this ), 554 id = en.closest( '.product' ).find( '[data-id]' ).data( 'id' ) + ',', 555 ls = localStorage.getItem( 'xtraWishlist' ) || '', 556 tt = en.attr( 'data-title' ); 557 558 if ( en.hasClass( 'fa-heart' ) && ! en.closest( '.xtra-wishlist' ).length ) { 559 560 window.location.replace( xtra_strings.wishlist_url ); 561 562 } else { 563 564 en.addClass( 'xtra-icon-loading' ).removeAttr( 'data-title' ); 565 566 setTimeout(function() { 567 568 if ( en.hasClass( 'fa-heart' ) || en.hasClass( 'fa-times' ) ) { 569 570 ls = ls.replace( id, '' ); 571 572 localStorage.setItem( 'xtraWishlist', ls ); 573 574 tt = xtra_strings.add_wishlist; 575 576 en.removeClass( 'fa-heart' ).addClass( 'fa-heart-o' ); 577 578 } else if ( ls.indexOf( id ) < 0 ) { 579 580 localStorage.setItem( 'xtraWishlist', ls + id ); 581 582 tt = xtra_strings.added_wishlist; 583 584 setTimeout( function() { 585 586 $( '[data-id="' + id.replace( ',', '' ) + '"] .xtra-add-to-wishlist' ).removeClass( 'fa-heart-o' ).addClass( 'fa-heart' ).attr( 'data-title', xtra_strings.added_wishlist ); 587 588 }, 500 ); 589 590 $( '.cz_close_popup' ).trigger( 'click' ); 591 592 setTimeout( function() { 593 594 wishComPopup.find( 'h3' ).html( en.closest( '.product' ).find( '.woocommerce-loop-product__title, .product_title' ).html() ); 595 wishComPopup.find( 'a' ).attr( 'href', xtra_strings.wishlist_url ).find( 'strong' ).html( xtra_strings.view_wishlist ); 596 wishComPopup.fadeIn( 'fast' ).delay( 1000 ).addClass( 'cz_show_popup' ); 597 598 }, $( '.cz_popup_modal' ).is( ':visible' ) ? 50 : 0 ); 599 } 600 601 en.removeClass( 'xtra-icon-loading' ); 602 603 setTimeout( function() { 604 605 en.attr( 'data-title', tt ); 606 607 }, 250 ); 608 609 // Wishlist page. 610 if ( en.closest( '.xtra-wishlist' ).length ) { 611 612 en.closest( 'li' ).fadeOut(function() { 613 614 $( this ).remove(); 615 616 if ( ! wishlistDiv.find( 'li' ).length ) { 617 wishlistDiv.removeClass( 'xtra-icon-loading' ).html( noWishlist ); 618 } 619 620 }); 621 622 } 623 624 var count = localStorage.getItem( 'xtraWishlist' ).replace( /\d+/g,'' ).length; 625 626 $( '.wishlist_icon > i' ).attr( 'data-count', count || 0 ); 627 628 if ( ! count ) { 629 wishlistDiv.removeClass( 'xtra-icon-loading' ).html( noWishlist ); 630 } 631 632 }, 1000 ); 633 634 } 635 636 e.preventDefault(); 637 }); 638 639 } 640 641 // Current compare items 642 if ( document.querySelector( '.xtra-add-to-compare, .xtra-compare, .compare_icon' ) ) { 643 644 // Compare icon. 645 body.on( 'click', '.xtra-add-to-compare,.xtra-remove-from-compare', function(e) { 646 647 var en = $( this ), 648 id = en.closest( '.product' ).find( '[data-id]' ).data( 'id' ) + ',', 649 ls = localStorage.getItem( 'xtraCompare' ) || '', 650 tt = en.attr( 'data-title' ); 651 652 // Remove from compare. 653 if ( en.attr( 'class' ).indexOf( 'remove' ) > 0 ) { 654 655 id = en.closest( 'td' ).find( '[data-id]' ).data( 'id' ) + ','; 656 657 en.addClass( 'xtra-icon-loading' ); 658 659 ls = ls.replace( id, '' ); 660 661 localStorage.setItem( 'xtraCompare', ls ); 662 663 window.location.replace( xtra_strings.compare_url ); 664 665 e.preventDefault(); 666 667 return false; 668 669 } 670 671 // ... 672 if ( en.hasClass( 'fa-check' ) && ! en.closest( '.xtra-compare' ).length ) { 673 674 window.location.replace( xtra_strings.compare_url ); 675 676 } else { 677 678 en.addClass( 'xtra-icon-loading' ).removeAttr( 'data-title' ); 679 680 setTimeout( function() { 681 682 if ( en.hasClass( 'fa-check' ) || en.hasClass( 'fa-times' ) ) { 683 684 ls = ls.replace( id, '' ); 685 686 localStorage.setItem( 'xtraCompare', ls ); 687 688 tt = xtra_strings.add_compare; 689 690 en.removeClass( 'fa-check' ).addClass( 'czico-shuffle' ).attr( 'data-title', xtra_strings.add_compare ); 691 692 } else if ( ls.indexOf( id ) < 0 ) { 693 694 localStorage.setItem( 'xtraCompare', ls + id ); 695 696 tt = xtra_strings.added_compare; 697 698 setTimeout( function() { 699 700 $( '[data-id="' + id.replace( ',', '' ) + '"] .xtra-add-to-compare' ).removeClass( 'czico-shuffle' ).addClass( 'fa-check' ).attr( 'data-title', xtra_strings.added_compare ); 701 702 }, 500 ); 703 704 $( '.cz_close_popup' ).trigger( 'click' ); 705 706 setTimeout( function() { 707 708 wishComPopup.find( 'h3' ).html( en.closest( '.product' ).find( '.woocommerce-loop-product__title, .product_title' ).html() ); 709 wishComPopup.find( 'a' ).attr( 'href', xtra_strings.compare_url ).find( 'strong' ).html( xtra_strings.view_compare ); 710 wishComPopup.fadeIn( 'fast' ).delay( 1000 ).addClass( 'cz_show_popup' ); 711 712 }, $( '.cz_popup_modal' ).is( ':visible' ) ? 50 : 0 ); 713 714 } 715 716 en.removeClass( 'xtra-icon-loading' ); 717 718 setTimeout( function() { 719 720 en.attr( 'data-title', tt ); 721 722 }, 250 ); 723 724 var compareDiv = null; 725 726 // Compare page. 727 if ( en.closest( '.xtra-compare' ).length ) { 728 729 en.closest( 'li' ).fadeOut(function() { 730 731 $( this ).remove(); 732 733 if ( ! compareDiv.find( 'li' ).length ) { 734 compareDiv.removeClass( 'xtra-icon-loading' ).html( noCompare ); 735 } 736 737 });
738 739 } 740 741 var count = localStorage.getItem( 'xtraCompare' ).replace( /\d+/g,'' ).length; 742 743 $( '.compare_icon > i' ).attr( 'data-count', count || 0 ); 744 745 if ( ! count ) { 746 compareDiv.removeClass( 'xtra-icon-loading' ).html( noCompare ); 747 } 748 749 }, 1000 ); 750 751 } 752 753 e.preventDefault(); 754 }); 755 756 var compare = localStorage.getItem( 'xtraCompare' ), 757 compareDiv = $( '.xtra-compare' ), 758 noCompare = '<h2 class="xtra-wish-compare-empty xtra-compare-empty tac"><i class="fa-solid fa-list-check"></i>' + compareDiv.attr( 'data-empty' ) + '<small>' + xtra_strings.wishlist_desc + '</small></h2><a href="' + xtra_strings.shop_url + '" class="button" style="margin:40px auto;display:table;"><span><strong>' + xtra_strings.back_to_shop + '</strong></span></a>'; 759 760 // Compare shortcode 761 compareDiv.length && compareDiv.each( function() { 762 763 var en = $( this ), 764 nonce = en.data( 'nonce' ); 765 766 if ( compare ) { 767 768 // Check ID's. 769 $.post( body.data( 'ajax' ), 'action=xtra_compare_content&check=1&ids=' + compare + '&nonce=' + nonce, function( msg ) { 770 771 localStorage.setItem( 'xtraCompare', msg ); 772 773 compare = msg; 774 775 // Get compare products. 776 $.post( body.data( 'ajax' ), 'action=xtra_compare_content&ids=' + compare + '&nonce=' + nonce, function( msg ) { 777 778 en.removeClass( 'xtra-icon-loading' ).html( msg ); 779 780 $( '.cz-compare-tr-general td' ).prepend( '<i class="xtra-remove-from-compare fas fa-times"></i>' ); 781 782 var count = localStorage.getItem( 'xtraCompare' ).replace( /\d+/g,'' ).length; 783 784 $( '.compare_icon > i' ).attr( 'data-count', count || 0 ); 785 786 if ( ! count ) { 787 en.removeClass( 'xtra-icon-loading' ).html( noCompare ); 788 } 789 790 if ( ! en.find( 'li' ).length ) { 791 en.removeClass( 'xtra-icon-loading' ).html( noCompare ); 792 } 793 794 }); 795 796 }); 797 798 } else { 799 800 en.removeClass( 'xtra-icon-loading' ).html( noCompare ); 801 802 } 803 804 }); 805 806 // Set compare products 807 if ( compare ) { 808 compare = compare.split( ',' ); 809 810 $.each( compare, function( index, id ) { 811 var product = id ? $( '[data-id="' + id + '"] .xtra-add-to-compare' ) : 0; 812 813 if ( product.length ) { 814 product.removeClass( 'czico-shuffle' ).addClass( 'fa-check' ).attr( 'data-title', xtra_strings.added_compare ); 815 } 816 }); 817 818 var count = localStorage.getItem( 'xtraCompare' ).replace( /\d+/g,'' ).length; 819 820 $( '.compare_icon > i' ).attr( 'data-count', count || 0 ); 821 822 if ( ! count ) { 823 compareDiv.removeClass( 'xtra-icon-loading' ).html( noCompare ); 824 } 825 } 826 827 } 828 829 // Product quick view. 830 if ( document.querySelector( '.xtra-product-quick-view' ) ) { 831 832 body.on( 'click', '.xtra-product-quick-view', function( e ) { 833 834 e.preventDefault(); 835 836 var x = $( this ), 837 id = x.parent().data( 'id' ), 838 nonce = x.data( 'nonce' ), 839 link = x.closest( 'a' ).attr( 'href' ), 840 popup = $( '#xtra_quick_view' ), 841 content = popup.find( '.cz_popup_in > div' ), 842 tt = x.attr( 'data-title' ); 843 844 popup.appendTo( 'body' ); 845 846 x.addClass( 'xtra-icon-loading' ).removeAttr( 'data-title' ); 847 848 content.html( '' ); 849 content.addClass( 'xtra-qv-loading' ); 850 851 popup.fadeIn( 'fast' ).delay( 1000 ).addClass( 'cz_show_popup' ); 852 853 $( 'html, body' ).addClass( 'no-scroll' ); 854 855 $.post( body.data( 'ajax' ), 'action=xtra_quick_view&id=' + id + '&nonce=' + nonce, function( msg ) { 856 857 x.removeClass( 'xtra-icon-loading' ).attr( 'data-title', tt ); 858 content.removeClass().html( msg ); 859 860 // Add link to full product view. 861 content.find( '.product_title' ).append( '<a href="' + link + '"><small>' + xtra_strings.quick_view_full + '</small></a>' ); 862 863 // Set wishlist in quickview. 864 if ( localStorage.getItem( 'xtraWishlist' ) && localStorage.getItem( 'xtraWishlist' ).indexOf( id ) >= 0 ) { 865 $( '[data-id="' + id + '"] .xtra-add-to-wishlist' ).removeClass( 'fa-heart-o' ).addClass( 'fa-heart' ).attr( 'data-title', xtra_strings.added_wishlist ); 866 } 867 868 // Set compare in quickview. 869 if ( localStorage.getItem( 'xtraCompare' ) && localStorage.getItem( 'xtraCompare' ).indexOf( id ) >= 0 ) { 870 $( '[data-id="' + id + '"] .xtra-add-to-compare' ).removeClass( 'czico-shuffle' ).addClass( 'fa-check' ).attr( 'data-title', xtra_strings.added_compare ); 871 } 872 873 // Fix flex slider. 874 setTimeout( function() { 875 876 // Init variations 877 content.find('.variations_form').each(function () { 878 var $form = $( this ); 879 $form.wc_variation_form(); 880 $form.trigger('wc_variation_form'); 881 $form.find('.variations select').trigger('change'); 882 });
883 884 content.find( '.woocommerce-product-gallery' ).each( function() { 885 $( this ).wc_product_gallery(); 886 } ); 887 888 $( window ).trigger( 'resize' ); 889 890 }, 500 ); 891 892 // Fix onsale position. 893 content.find( 'div.product, .xtra-single-product' ).find( '> .onsale' ).prependTo( $( '.woocommerce-product-gallery' ) ); 894 895 // Add to cart redirect to cart on quick view popup. 896 content.find( '[name="add-to-cart"]' ).closest( 'form' ).attr( 'action', xtra_strings.cart_url ); 897 898 }); 899 900 return false; 901 902 }); 903 904 } 905 906 // Append onsale badge to parent in archive. 907 document.querySelectorAll('ul.products .onsale').forEach(badge => { 908 const parentLink = badge.closest('a'); 909 if (parentLink) { 910 parentLink.appendChild(badge); 911 } 912 }); 913 914 // Checkout page functions. 915 if ( document.querySelector( '.woocommerce-checkout' ) ) { 916 917 // Fix checkout section title! 918 $( 'wc-order-attribution-inputs' ).each( function() { 919 920 var $this = $( this ); 921 922 $this.appendTo( $this.parent() ); 923 924 }); 925 926 // Fix City and state in RTL. 927 if ( body.hasClass( 'rtl' ) ) { 928 929 setTimeout( function() { 930 931 $( '#billing_state_field' ).insertBefore( '#billing_city_field' ); 932 933 }, 500 ); 934 935 } 936 937 } 938 939 // Add button class to restore-item link in message box. 940 $( '.woocommerce-message .restore-item' ).addClass( 'button' ); 941 942 // Added to cart notification. 943 body.on( 'added_to_cart', function( e, fragments, cart_hash, $button ) { 944 945 // Show view cart btn. 946 setTimeout( function() { 947 $button.hide().next().addClass( 'button product_type_codevz' ).fadeIn(); 948 }, 100 ); 949 950 // Notification. 951 var notif = $( '.codevz-added-to-cart-notif' ), 952 width = notif.find( 'span' ).outerWidth(); 953 954 // Check if its on single page with sticky mode. 955 notif[ $( '.cz-sticky-add-to-cart-show' ).length ? 'addClass' : 'removeClass' ]( 'codevz-added-to-cart-notif-above-sticky' ); 956 957 setTimeout( function() { 958 959 var parent = $button.closest( 'li.product' ).length ? $button.closest( 'li.product' ) : $button.closest( '.summary' ), 960 title = parent.find( '.woocommerce-loop-product__title' ).html(), 961 title = title ? title : $( '.cz-sticky-add-to-cart' ).attr( 'data-title' ) || '-'; 962 963 // Show the notification. 964 notif.addClass( 'codevz-added-to-cart-notif-show' ).find( 'strong' ).text( title.replace( /<[^>]*>.*?<\/[^>]*>/g, '' ) ); 965 966 setTimeout( function() { 967 968 // Show the added details span. 969 notif.addClass( 'codevz-added-to-cart-notif-show-span' ); 970 971 }, 1200 ); 972 973 setTimeout( function() { 974 975 // Hide the notification after a delay. 976 notif.removeClass( 'codevz-added-to-cart-notif-show-span' ); 977 978 setTimeout( function() { 979 980 // Hide the span. 981 notif.removeClass( 'codevz-added-to-cart-notif-show' ); 982 983 }, 500 ); 984 985 }, 6000 ); 986 987 }, 100 ); 988 989 }); 990 991 // Single product page. 992 if ( body.hasClass( 'single-product' ) ) { 993 994 setTimeout( function() { 995 996 // Sticky product tabs row. 997 var woot = $( '.codevz-sticky-product-tabs .woocommerce-tabs' ), 998 tabs = woot.find( 'ul.tabs' ), 999 panels = woot.find( '.panel' ),
1000 lastTab = panels.last(), 1001 scrollTop, isFixed, activeTabId; 1002 1003 if ( tabs.length ) { 1004 1005 var tabsOffset = tabs.offset().top, 1006 placeholder = $( '<div>' ).css({ 1007 'height': tabs.outerHeight(), 1008 'margin': tabs.css( 'margin' ) 1009 }).insertBefore( tabs ); 1010 1011 $( window ).on( 'scroll', function() { 1012 1013 if ( Codevz.inview( woot, 100 ) ) { 1014 1015 requestAnimationFrame(function() { 1016 1017 scrollTop = $(window).scrollTop() + adminBar; 1018 isFixed = scrollTop > tabsOffset; 1019 1020 tabs.toggleClass( 'fixed-tabs', isFixed ); 1021 placeholder[ isFixed ? 'show' : 'hide' ](); 1022 1023 // Determine which tab content is currently in view 1024 panels.each( function() { 1025 var tabContent = $(this); 1026 var topOffset = tabContent.offset().top - 150; 1027 var bottomOffset = topOffset + tabContent.outerHeight(); 1028 1029 // Check if the tab content is within the viewport 1030 if ( topOffset <= ( scrollTop + tabs.outerHeight()) && bottomOffset >= scrollTop ) { 1031 activeTabId = tabContent.attr('id'); 1032 return false; 1033 } 1034 });
1035 1036 // Set active class on corresponding tab link 1037 tabs.find('li').removeClass('active'); 1038 if ( activeTabId ) { 1039 tabs.find('a[href="#' + activeTabId + '"]').closest('li').addClass('active'); 1040 } else if ( scrollTop <= tabsOffset ) { // If at top of page, set first tab as active 1041 tabs.find('li:first').addClass('active'); 1042 } 1043 1044 // Last tab out of viewport, hide sticky. 1045 tabs.toggle( ( lastTab.offset().top + lastTab.outerHeight() - tabs.outerHeight() ) >= scrollTop ); 1046 1047 }); 1048 1049 } 1050 1051 }); 1052 1053 } 1054 1055 // Tabs scroll to. 1056 body.on( 'click', '.wc-tabs a', function() { 1057 1058 var $page = $( 'html, body' ), 1059 tabs = $( 'body:not(.woo-product-tabs-vertical) .wc-tabs' ), 1060 tab = $( this ).attr( 'href' ).replace( '#', '' ), 1061 sticky = $( '.header_is_sticky' ).not( '.smart_sticky,.header_4' ); 1062 1063 tab && $page.stop( true, true ).animate({ 1064 1065 scrollTop: $( '#' + tab ).offset().top - ( tabs.outerHeight() || 0 ) - ( sticky.outerHeight() || 0 ) - adminBar - ( $( '.xtra-preview-header' ).outerHeight() || 0 ) - 50 1066 1067 }, 1000, 'easeInOutCodevz', function() { 1068 1069 $page.stop( true, true ); 1070 1071 }); 1072 1073 }).on( 'click', '.codevz-woo-rating-count', function(e) { 1074 1075 $( '.reviews_tab a' ).trigger( 'click' ); 1076 e.preventDefault(); 1077 1078 }); 1079 1080 }, 1000 ); 1081 1082 // Disable product page lightbox 1083 $( '.woo-disable-lightbox .woocommerce-product-gallery__wrapper > div:first-child a' ).removeAttr( 'href' ).css( 'cursor', 'default' ); 1084 1085 // Move single onSale badge to sticky. 1086 $( 'div.product, .xtra-single-product' ).find( '> .onsale' ).prependTo( $( '.woocommerce-product-gallery' ) ); 1087 1088 // Woo sticky column. 1089 $( '.woocommerce-product-gallery' ).addClass( 'cz_sticky_col' ); 1090 1091 // Edit reviews count in tab and add span. 1092 $( '.wc-tabs [href="#tab-reviews"]' ).html( function( i, html ) { 1093 return html.replace( '(', '<span>' ).replace( ')', '</span>' ); 1094 }); 1095 1096 // Out of stock message. 1097 var outofstock_p = $( 'p.stock.out-of-stock' ); 1098 1099 // Add error class to outofstock p tag. 1100 outofstock_p.addClass( 'woocommerce-error' ); 1101 1102 // Sticky add to cart. 1103 if ( $( '.cz-sticky-add-to-cart' ).length && ! outofstock_p.length ) { 1104 1105 var sticky = $( '.cz-sticky-add-to-cart .row' ), 1106 product = $( '.xtra-single-product' ), 1107 cart = product.find( '.cart' ), 1108 footer = $( '.layout_1,.layout_2' ).length ? $( '.layout_1,.layout_2' ) : $( '#site_footer' ); 1109 1110 // Set product details in sticky bar. 1111 sticky.append( '<h3>' + sticky.parent().attr( 'data-title' ) + '</h3>' ); 1112 sticky.append( product.find( '.cart' ).clone() ); 1113 sticky.find( 'h3' ).append( product.find( '.price' ).clone() ); 1114 1115 // Change add to cart to select options for variation products. 1116 if ( sticky.find( '.variations_form' ).length && ! $( '.codevz-select-options' ).length ) { 1117 1118 sticky.find( '.single_add_to_cart_button' ).hide().after( '<a href="#" class="codevz-select-options button alt">' + xtra_strings.select_options + '</a>' ); 1119 1120 body.on( 'click', '.codevz-select-options', function() { 1121 1122 var targetOffsetTop = $( '.summary .variations_form' ).offset().top - 800; 1123 1124 $( 'html, body' ).animate( { scrollTop: targetOffsetTop }, 1200, 'easeInOutCodevz' ); 1125 1126 return false; 1127 1128 }); 1129 1130 } 1131 1132 // Product image. 1133 var image = product.find( '.woocommerce-product-gallery__image a > img' ).attr( 'src' ), 1134 offset; 1135 1136 if ( image ) {
1137 sticky.prepend( '<img src="' + image + '" />' ); 1138 } 1139 1140 // Show/hide sticky on scroll. 1141 let timeout; 1142 $( window ).on( 'scroll.sticky_add_to_cart', function() { 1143 1144 clearTimeout( timeout ); 1145 1146 timeout = setTimeout( function() { 1147 1148 offset = $( window ).scrollTop() > cart.offset().top + cart.outerHeight(); 1149 1150 // Show/Hide sticky row. 1151 sticky.parent()[ offset ? 'addClass' : 'removeClass' ]( 'cz-sticky-add-to-cart-show' ); 1152 1153 // Fix footer margin. 1154 footer.css( 'margin-bottom', sticky.parent().outerHeight() ); 1155 1156 // Fixed icons. 1157 $( 'i.backtotop,i.fixed_contact' ).css( 'bottom', ( offset ? ( $( window ).width() > 769 ? $( '.cz-sticky-add-to-cart' ).outerHeight() + 20 : '' ) : '' ) ); 1158 1159 }, 100 ); 1160 1161 }); 1162 1163 } // Sticky add to cart. 1164 1165 // Add title to product image zoom + new icon. 1166 Codevz.heightChanged( $( '.woocommerce-product-gallery' ), function() { 1167 1168 setTimeout( function() { 1169 1170 const trigger = $( '.woocommerce-product-gallery__trigger' ); 1171 const thumbs = $( '.flex-control-thumbs' ); 1172 1173 if ( ! $( '.codevz-woo-zoom' ).length ) { 1174 trigger.html( '<i class="fa czico-010-expand"></i><span class="codevz-woo-zoom">' + xtra_strings.zoom_text + '</span>' ); 1175 } 1176 1177 if ( thumbs.length ) { 1178 trigger.css( 'bottom', thumbs.outerHeight() + 30 ); 1179 } 1180 1181 }, 500 ); 1182 1183 }); 1184 1185 } // Single product page. 1186 1187 }; 1188 1189 Codevz_Plus.woocommerce(); 1190 1191}( jQuery );
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.