PluginProbe
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder / 51.1.78
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder v51.1.78
51.1.83 51.1.82 51.1.81 51.1.79 51.1.78 51.1.77 51.1.76 51.1.74 51.1.75 51.1.65 51.1.64 51.1.63 trunk 51.1.14 51.1.2 51.1.35 51.1.36 51.1.37 51.1.38 51.1.39 51.1.44 51.1.45 51.1.46 51.1.47 51.1.49 All 37 releases
king-addons / includes / widgets / Woo_Product_Add_To_Cart / script.js

script.js in King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder 51.1.78, at includes/widgets/Woo_Product_Add_To_Cart/script.js

168 lines 5.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * Woo Product Add To Cart widget behavior.
3 *
4 * Adds products to cart via WooCommerce AJAX and refreshes fragments.
5 */
6 (function ($) {
7 "use strict";
8
9 const INIT_FLAG = "kaWooProductAtcInit";
10
11 const ajaxUrl = (window?.king_addons_grid_data && window.king_addons_grid_data.ajaxUrl) || window.ajaxurl || '';
12
13 const postAddToCart = async (payload) => {
14 const formData = new FormData();
15 formData.append('action', 'woocommerce_ajax_add_to_cart');
16 Object.entries(payload).forEach(([k, v]) => formData.append(k, v));
17
18 const response = await fetch(ajaxUrl, {
19 method: 'POST',
20 credentials: 'same-origin',
21 body: formData,
22 });
23
24 if (!response.ok) {
25 throw new Error('Request failed');
26 }
27 return response.json();
28 };
29
30 const updateFragments = (data) => {
31 if (!window.jQuery || !data || !data.fragments) return;
32 window.jQuery(document.body).trigger('wc_fragment_refresh');
33 window.jQuery.each(data.fragments, (key, value) => {
34 window.jQuery(key).replaceWith(value);
35 });
36 window.jQuery(document.body).trigger('added_to_cart', [data.fragments, data.cart_hash, data.cart_totals]);
37 };
38
39 const showState = (wrapper, type, text) => {
40 const stateEl = wrapper.querySelector('.ka-woo-product-atc__state');
41 if (!stateEl) return;
42 stateEl.textContent = text || '';
43 stateEl.dataset.state = type || '';
44 stateEl.classList.toggle('is-visible', !!text);
45 };
46
47 const collectVariation = () => {
48 const variationForm = document.querySelector('form.variations_form');
49 if (!variationForm) return { valid: true, payload: {} };
50
51 const payload = {};
52 let hasEmpty = false;
53
54 const variationIdField = variationForm.querySelector('input[name="variation_id"]');
55 const variationId = variationIdField ? parseInt(variationIdField.value || '0', 10) : 0;
56 const attrs = variationForm.querySelectorAll('select[name^="attribute_"]');
57 attrs.forEach((sel) => {
58 const name = sel.name;
59 if (!name) return;
60 const val = sel.value;
61 if (!val) {
62 hasEmpty = true;
63 return;
64 }
65 payload[name] = val;
66 });
67
68 if (variationId) {
69 payload.variation_id = variationId;
70 }
71
72 const valid = variationId || !hasEmpty;
73 return { valid, payload };
74 };
75
76 const handleATC = (wrapper) => {
77 if (!wrapper || !wrapper.dataset) return;
78 if (wrapper.dataset[INIT_FLAG] === "1") return;
79 wrapper.dataset[INIT_FLAG] = "1";
80
81 const btns = wrapper.querySelectorAll('.ka-woo-product-atc__button');
82 if (!btns.length) return;
83 const qtyInput = wrapper.querySelector('.ka-woo-product-atc__qty input[type="number"]');
84 const productId = parseInt(wrapper.dataset.productId || '0', 10);
85 const ajax = wrapper.dataset.ajax === 'yes';
86 const defaultRedirect = wrapper.dataset.redirect || 'stay';
87 const successText = wrapper.dataset.success || '';
88 const errorText = wrapper.dataset.error || '';
89 const hasVariations = wrapper.dataset.hasVariations === 'yes';
90
91 const setLoading = (isLoading) => {
92 btns.forEach((b) => {
93 b.disabled = isLoading;
94 b.classList.toggle('is-loading', isLoading);
95 });
96 if (qtyInput) {
97 qtyInput.disabled = isLoading;
98 }
99 };
100
101 btns.forEach((btn) => {
102 btn.addEventListener('click', async (e) => {
103 if (!ajax) return;
104 e.preventDefault();
105 const redirect = btn.dataset.redirect || defaultRedirect;
106 const qty = qtyInput ? parseInt(qtyInput.value || '1', 10) || 1 : 1;
107
108 if (!productId) return;
109
110 const variation = collectVariation();
111 if (hasVariations && !variation.valid) {
112 showState(wrapper, 'error', errorText || 'Please choose product options.');
113 return;
114 }
115
116 setLoading(true);
117 showState(wrapper, '', '');
118
119 try {
120 const payload = {
121 product_id: productId,
122 quantity: qty,
123 ...variation.payload,
124 };
125
126 const result = await postAddToCart(payload);
127
128 if (redirect === 'cart' && window.wc_add_to_cart_params?.cart_url) {
129 window.location.href = window.wc_add_to_cart_params.cart_url;
130 return;
131 }
132 if (redirect === 'checkout' && window.wc_add_to_cart_params?.checkout_url) {
133 window.location.href = window.wc_add_to_cart_params.checkout_url;
134 return;
135 }
136
137 updateFragments(result);
138 showState(wrapper, 'success', successText || 'Added to cart');
139 } catch (err) {
140 showState(wrapper, 'error', errorText || 'Could not add to cart.');
141 } finally {
142 setLoading(false);
143 }
144 });
145 });
146 };
147
148 const initAll = (root) => {
149 const ctx = root && root.querySelectorAll ? root : document;
150 ctx.querySelectorAll('.ka-woo-product-atc[data-ajax="yes"]').forEach(handleATC);
151 };
152
153 document.addEventListener("DOMContentLoaded", () => initAll(document));
154
155 $(window).on("elementor/frontend/init", function () {
156 elementorFrontend.hooks.addAction(
157 "frontend/element_ready/woo_product_add_to_cart.default",
158 function ($scope) {
159 initAll($scope && $scope[0] ? $scope[0] : document);
160 }
161 );
162 });
163 })(jQuery);
164
165
166
167
168