1/** 2 * AJAX Add to Cart â simple & variable products. 3 * Ensures variation attributes are sent correctly and cart events fire. 4 */ 5(function ($) { 6 'use strict'; 7 8 $.fn.serializeArrayAll = function () { 9 var rCRLF = /\r?\n/g; 10 return this.map(function () { 11 return this.elements ? jQuery.makeArray(this.elements) : this; 12 }).map(function (i, elem) { 13 var val = jQuery(this).val(); 14 if (val == null) { 15 return null; 16 } 17 if (this.type === 'checkbox' && this.checked === false) { 18 return { name: this.name, value: '' }; 19 } 20 return jQuery.isArray(val) 21 ? jQuery.map(val, function (val) { 22 return { name: elem.name, value: val.replace(rCRLF, '\r\n') }; 23 }) 24 : { name: elem.name, value: String(val).replace(rCRLF, '\r\n') }; 25 }).get(); 26 }; 27 28 /** 29 * Collect selected variation attributes from the form. 30 */ 31 function getVariationData($form) { 32 var variation = {}; 33 $form.find('select[name^="attribute_"], input[name^="attribute_"]').each(function () { 34 var name = $(this).attr('name'); 35 var val = $(this).val(); 36 if (name && val) { 37 variation[name] = val; 38 } 39 }); 40 return variation; 41 } 42 43 $(document).on('click', '.single_add_to_cart_button:not(.disabled)', function (e) { 44 var $thisbutton = $(this); 45 var $form = $thisbutton.closest('form.cart'); 46 47 // Only intercept if form exists (single product / quick view). 48 if (!$form.length) { 49 return; 50 } 51 52 e.preventDefault(); 53 54 var product_id = $form.find('input[name="product_id"]').val() || $thisbutton.val(); 55 var variation_id = $form.find('input[name="variation_id"]').val() || 0; 56 var quantity = $form.find('input[name="quantity"]').val() || 1; 57 var is_variable = $form.find('input[name="variation_id"]').length > 0; 58 59 // Variable product: require a selected variation. 60 if (is_variable) { 61 variation_id = parseInt(variation_id, 10) || 0; 62 if (!variation_id) { 63 // Let WooCommerce show its own "please select options" notice. 64 $form.find('.single_add_to_cart_button').removeClass('loading'); 65 return false; 66 } 67 68 var variation = getVariationData($form); 69 var data_send = { 70 action: 'wcspc_add_variation_to_cart', 71 product_id: product_id, 72 variation_id: variation_id, 73 quantity: quantity, 74 variation: variation, 75 security: (typeof wcspcVars !== 'undefined') ? wcspcVars.nonce : '' 76 }; 77 78 $thisbutton.removeClass('added').addClass('loading'); 79 80 $.post(wcspcVars.ajaxurl, data_send) 81 .done(function (response) { 82 $thisbutton.removeClass('loading').addClass('added'); 83 84 // wp_send_json_error format 85 if (response && response.success === false) { 86 var url = (response.data && response.data.product_url) ? response.data.product_url : null; 87 if (url) { 88 window.location = url; 89 } 90 return; 91 } 92 93 // Legacy / WC fragments style 94 if (response && response.error && response.product_url) { 95 window.location = response.product_url; 96 return; 97 } 98 99 var fragments = response.fragments || (response.data && response.data.fragments); 100 var cart_hash = response.cart_hash || (response.data && response.data.cart_hash); 101 102 $(document.body).trigger('added_to_cart', [fragments, cart_hash, $thisbutton]); 103 }) 104 .fail(function () { 105 $thisbutton.removeClass('loading'); 106 }); 107 108 return false; 109 } 110 111 // Simple / grouped / other: use core WC AJAX endpoint. 112 var data = $form.find('input:not([name="product_id"]), select, button, textarea').serializeArrayAll() || []; 113 $.each(data, function (i, item) { 114 if (item.name === 'add-to-cart') { 115 item.name = 'product_id'; 116 item.value = product_id; 117 } 118 }); 119 120 $(document.body).trigger('adding_to_cart', [$thisbutton, data]); 121 122 $.ajax({ 123 type: 'POST', 124 url: (typeof wc_add_to_cart_params !== 'undefined') 125 ? wc_add_to_cart_params.wc_ajax_url.toString().replace('%%endpoint%%', 'add_to_cart') 126 : woocommerce_params.wc_ajax_url.toString().replace('%%endpoint%%', 'add_to_cart'), 127 data: data, 128 beforeSend: function () { 129 $thisbutton.removeClass('added').addClass('loading'); 130 }, 131 complete: function () { 132 $thisbutton.addClass('added').removeClass('loading'); 133 }, 134 success: function (response) { 135 if (response && response.error && response.product_url) { 136 window.location = response.product_url; 137 return; 138 } 139 $(document.body).trigger('added_to_cart', [response.fragments, response.cart_hash, $thisbutton]); 140 } 141 }); 142 143 return false;
144 }); 145})(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.