PageSourceSearch

https://designerpetsuk.com/wp-content/plugins/variation-swatches-f…/assets/js/frontend.js?ver=2.2.7

js designerpetsuk.com collected 2026-10-10 02:09:16 UTC 16,424 bytes, 349 lines download raw bytes

1;(function ($) {
2    'use strict';
3
4    /**
5     * Is there at least one in-stock, purchasable variation that matches the
6     * given attribute value combined with the attributes already chosen?
7     *
8     * Drives stock-aware swatch greying independently of the WooCommerce
9     * "Hide out of stock items" setting. An attribute value in a variation is
10     * treated as a wildcard when it is empty (the "any" value).
11     *
12     * @param {string} attrName   e.g. "attribute_pa_size"
13     * @param {string} value      term slug for this swatch
14     * @param {Object} chosen     map of attribute_name -> selected slug
15     * @param {Array}  variations variation data (is_in_stock/is_purchasable per item)
16     * @returns {boolean} true when no data is available, so existing behavior stands
17     */
18    function matchingVariationInStock(attrName, value, chosen, variations) {
19        if (!Array.isArray(variations)) {
20            return true;
21        }
22
23        return variations.some(function (variation) {
24            if (!(variation.is_in_stock && variation.is_purchasable)) {
25                return false;
26            }
27
28            var attrs = variation.attributes || {};
29
30            // This attribute must match the swatch value (or be a wildcard).
31            var ownValue = attrs[attrName];
32            if (typeof ownValue !== 'undefined' && ownValue !== '' && ownValue !== value) {
33                return false;
34            }
35
36            // Every other already-selected attribute must match (or be a wildcard).
37            for (var key in chosen) {
38                if (key === attrName || !chosen.hasOwnProperty(key)) {
39                    continue;
40                }
41                var otherValue = attrs[key];
42                if (typeof otherValue !== 'undefined' && otherValue !== '' && otherValue !== chosen[key]) {
43                    return false;
44                }
45            }
46
47            return true;
48        });
49    }
50
51    /**
52     * SIMPLIFIED: Original variation swatches form - PHP-only optimized
53     * No AJAX delays, no loading states, instant response
54     */
55    $.fn.tawcvs_variation_swatches_form = function () {
56        return this.each(function () {
57            var $form = $(this);
58
59            // OPTIMIZED: All data is loaded upfront by PHP, no special handling needed
60            if (typeof $form.find(".tawcvs-available-product-variation").data("product_variations") !== "undefined") {
61                $form.data("product_variations", $form.find(".tawcvs-available-product-variation").data("product_variations"))
62                    .trigger('reload_product_variations')
63                    .trigger('update_variation_values');
64            }
65
66            $form
67                .addClass('swatches-support')
68                .on("found_variation", function (event, variation) {
69                    $form.change_variation_image_on_shop_page(variation);
70                })
71                .on("reset_image", function (event) {
72                    $form.change_variation_image_on_shop_page(false);
73                })
74                .on('click', '.swatch', function (e) {
75                    e.preventDefault();
76                    e.stopImmediatePropagation();
77
78                    var $el = $(this);
79                    let $select = false, value = false;
80
81                    // PERFORMANCE: Quick debounce for rapid clicks
82                    if ($el.data('clicking')) return;
83                    $el.data('clicking', true);
84                    setTimeout(() => $el.removeData('clicking'), 50);
85
86                    if (!$("body").hasClass("single-product") &&
87                        $("body").find(".wc-product-table-wrapper").length) {
88                        //For product table page
89                        let attribute_name = $el.closest('.tawcvs-swatches').data("attribute_name");
90                        $select = $el.closest('.variations').find('select[data-attribute_name="' + attribute_name + '"]');
91                        value = $el.attr('data-value');
92                    } else {
93                        //For normal variable product page
94                        $select = $el.closest('.value').find('select');
95                        value = $el.attr('data-value');
96                    }
97
98                    if ($el.hasClass('disabled')) {
99                        return;
100                    }
101
102                    //Woo product bundle plugin uses "select" class instead of "value" class
103                    if (!$select.length) {
104                        if ($form.closest(".woosb-product").length) {
105                            $select = $el.closest('.select').find('select');
106                        }
107                    }
108
109                    //Disabling other swatches, then resetting the select value to empty
110                    $el.parents('.tawcvs-swatches').find(".swatch.selected").each(function () {
111                        $(this).not($el).removeClass("selected");
112                        $select.val('');
113                    })
114
115                    // For old WC
116                    $select.trigger('focusin');
117
118                    // Check if this combination is available
119                    if (!$select.find('option[value="' + value + '"]').length) {
120                        $el.siblings('.swatch').removeClass('selected');
121                        $select.val('').change();
122                        $form.trigger('tawcvs_no_matching_variations', [$el]);
123                        return;
124                    }
125
126                    if ($el.hasClass('selected')) {
127                        $select.val('');
128                        $el.removeClass('selected');
129
130                        if ($el.attr('type') == 'radio') {
131                            setTimeout(function() {
132                                $el.prop('checked', false);
133                            }, 100);
134                        }
135                    } else {
136                        $el.addClass('selected').siblings('.selected').removeClass('selected');
137                        $select.val(value);
138
139                        if ($el.attr('type') == 'radio') {
140                            setTimeout(function() {
141                                $el.prop('checked', true);
142                            }, 100);
143                        }
144                    }
145
146                    $select.change();
147                })
148                .on('click', '.reset_variations', function () {
149                    $form.find('.swatch.selected').removeClass('selected');
150                    if( !$form.find('.swatch.disabled').hasClass('blur-cross') ){
151                        $form.find('.swatch.disabled').removeClass('disabled');
152                    }
153
154                    if ($form.find('input[type="radio"]').length > 1) {
155                        $form.find('input[type="radio"]').prop('checked', false);
156                    }
157                })
158                .on('woocommerce_update_variation_values', function () {
159                    // OPTIMIZED: Efficient variation value updates
160                    setTimeout(function () {
161                        // Stock-aware data: works regardless of the WooCommerce
162                        // "Hide out of stock items" setting. Bails (returns "available")
163                        // when no variation data is present so existing behavior stands.
164                        var variations = $form.data('product_variations');
165
166                        // Attributes the shopper has currently selected.
167                        var chosen = {};
168                        $form.find('.variation-selector select').each(function () {
169                            var name = $(this).data('attribute_name') || $(this).attr('name'),
170                                val = $(this).val();
171                            if (name && val) {
172                                chosen[name] = val;
173                            }
174                        });
175
176                        $form.find('.variation-selector').each(function () {
177                            var $variationSelector = $(this),
178                                $select = $variationSelector.find('select'),
179                                $options = $select.find('option'),
180                                $selected = $options.filter(':selected'),
181                                attrName = $select.data('attribute_name') || $select.attr('name'),
182                                values = [];
183
184                            $options.each(function (index, option) {
185                                if (option.value !== '') {
186                                    values.push(option.value);
187                                }
188                            });
189
190                            $variationSelector.closest('.value').find('.swatch').each(function () {
191                                var $swatch = $(this),
192                                    value = $swatch.attr('data-value');
193
194                                $swatch.closest('.swatch-item-wrapper').show();
195
196                                if (values.indexOf(value) > -1) {
197                                    if( !$swatch.hasClass('blur-cross')) {
198                                        $swatch.removeClass('disabled');
199                                    }
200
201                                    // Combo exists but is out of stock for the current
202                                    // selection -> disable it the same way as a missing combo.
203                                    if (!$swatch.hasClass('blur-cross') &&
204                                        !matchingVariationInStock(attrName, value, chosen, variations)) {
205                                        $swatch.addClass('disabled');
206
207                                        if ($swatch.closest('.tawcvs-swatches').hasClass('oss-hide')) {
208                                            $swatch.closest('.swatch-item-wrapper').hide();
209                                        }
210
211                                        if ($selected.length && value === $selected.val()) {
212                                            $swatch.removeClass('selected');
213                                        }
214                                    }
215                                } else {
216                                    $swatch.addClass('disabled');
217
218                                    if ($swatch.closest('.tawcvs-swatches').hasClass('oss-hide')) {
219                                        $swatch.closest('.swatch-item-wrapper').hide();
220                                    }
221
222                                    if ($selected.length && value === $selected.val()) {
223                                        $swatch.removeClass('selected');
224                                    }
225                                }
226                            });
227                        });
228                    }, 50); // Faster response time
229                })
230                .on('tawcvs_no_matching_variations', function () {
231                    window.alert(wc_add_to_cart_variation_params.i18n_no_matching_variations_text);
232                });
233        });
234    };
235
236    $.fn.change_variation_image_on_shop_page = function (variation) {
237        var $product = $(this).closest('.product'),
238            $product_img = $product.find('.woocommerce-LoopProduct-link img');
239
240        if ($product_img.length !== 1) {
241            return false;
242        }
243
244        if (variation && variation.image && variation.image.src && variation.image.src.length > 1) {
245            $product_img.wc_set_variation_attr('src', variation.image.src);
246            $product_img.wc_set_variation_attr('height', variation.image.src_h);
247            $product_img.wc_set_variation_attr('width', variation.image.src_w);
248            $product_img.wc_set_variation_attr('srcset', variation.image.srcset);
249            $product_img.wc_set_variation_attr('sizes', variation.image.sizes);
250            $product_img.wc_set_variation_attr('title', variation.image.title);
251            $product_img.wc_set_variation_attr('data-caption', variation.image.caption);
252            $product_img.wc_set_variation_attr('alt', variation.image.alt);
253            $product_img.wc_set_variation_attr('data-src', variation.image.full_src);
254            $product_img.wc_set_variation_attr('data-large_image', variation.image.full_src);
255            $product_img.wc_set_variation_attr('data-large_image_width', variation.image.full_src_w);
256            $product_img.wc_set_variation_attr('data-large_image_height', variation.image.full_src_h);
257        } else {
258            $product_img.wc_reset_variation_attr('src');
259            $product_img.wc_reset_variation_attr('width');
260            $product_img.wc_reset_variation_attr('height');
261            $product_img.wc_reset_variation_attr('srcset');
262            $product_img.wc_reset_variation_attr('sizes');
263            $product_img.wc_reset_variation_attr('title');
264            $product_img.wc_reset_variation_attr('data-caption');
265            $product_img.wc_reset_variation_attr('alt');
266            $product_img.wc_reset_variation_attr('data-src');
267            $product_img.wc_reset_variation_attr('data-large_image');
268            $product_img.wc_reset_variation_attr('data-large_image_width');
269            $product_img.wc_reset_variation_attr('data-large_image_height');
270        }
271    }
272
273    //Tracking the reset_variations button on change visibility -> change the corresponding display state
274    function toggle_hidden_variation_btn() {
275        const resetVariationNodes = document.getElementsByClassName('reset_variations');
276        if (resetVariationNodes.length) {
277            Array.prototype.forEach.call(resetVariationNodes, function (resetVariationEle) {
278                let observer = new MutationObserver(function () {
279                    if (resetVariationEle.style.visibility !== 'hidden') {
280                        resetVariationEle.style.display = 'block';
281                    } else {
282                        resetVariationEle.style.display = 'none';
283                    }
284                });
285                observer.observe(resetVariationEle, {attributes: true, childList: true});
286            })
287        }
288    }
289
290    // OPTIMIZED: Performance monitoring for large products
291    function logPerformanceInfo() {
292        if (typeof tawcvs_config !== 'undefined' && console && console.log) {
293            const $forms = $('.variations_form');
294            const $largeProductForms = $forms.filter(function() {
295                const variationData = $(this).find('.tawcvs-available-product-variation').data('product_variations');
296                return variationData && variationData.length > tawcvs_config.large_product_threshold;
297            });
298
299            if ($largeProductForms.length > 0) {
300                console.log('TAWCVS: PHP-optimized handling for', $largeProductForms.length, 'large product(s)');
301
302                $largeProductForms.each(function() {
303                    const variationData = $(this).find('.tawcvs-available-product-variation').data('product_variations');
304                    if (variationData) {
305                        console.log('TAWCVS: Loaded', variationData.length, 'variations instantly for product');
306                    }
307                });
308            }
309        }
310    }
311
312    // OPTIMIZED: Efficient initialization
313    function initializeSwatches() {
314        $('.variations_form').tawcvs_variation_swatches_form().trigger('woocommerce_update_variation_values');
315        $(document.body).trigger('tawcvs_initialized');
316        toggle_hidden_variation_btn();
317        logPerformanceInfo();
318    }
319
320    // OPTIMIZED: Throttled re-initialization for AJAX content
321    let reinitTimeout;
322    function throttledReinit() {
323        clearTimeout(reinitTimeout);
324        reinitTimeout = setTimeout(() => {
325            var $variations_form = $('.variations_form:not(.swatches-support)');
326            if ($variations_form.length > 0) {
327                $variations_form.each(function () {
328                    $(this).wc_variation_form();
329                });
330                $variations_form.tawcvs_variation_swatches_form();
331            }
332        }, 50); // Faster reinit
333    }
334
335    $(function () {
336        // Initialize swatches immediately
337        initializeSwatches();
338    });
339
340    $(document).ajaxComplete(function () {
341        throttledReinit();
342    });
343
344    // Handle dynamic content updates
345    $(document).on('updated_wc_div wc_fragments_refreshed', function() {
346        throttledReinit();
347    });
348
349})(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.