PageSourceSearch

https://tacda.org/wp-content/plugins/woocommerce-variation-swatche…/assets/js/swatches-and-photos.js?ver=3.0.6

js tacda.org collected 2026-10-02 10:27:02 UTC 19,123 bytes, 446 lines download raw bytes

1/*global wc_add_to_cart_variation_params */
2/*global wc_cart_fragments_params */
3/*!
4 * Variations Plugin
5 */
6;
7(function ($, window, document, undefined) {
8
9    function variation_calculator(variation_attributes, product_variations, all_set_callback, not_all_set_callback) {
10        this.recalc_needed = true;
11
12        this.all_set_callback = all_set_callback;
13        this.not_all_set_callback = not_all_set_callback;
14
15        //The varioius attributes and their values available as configured in woocommerce. Used to build and reset variations_current
16        this.variation_attributes = variation_attributes;
17
18        //The actual variations that are configured in woocommerce.
19        this.variations_available = product_variations;
20
21        //Stores the calculation result for attribute + values that are available based on the selected attributes.
22        this.variations_current = {};
23
24        //Stores the selected attributes + values
25        this.variations_selected = {};
26
27        //Reset all the attributes + values to disabled.  They will be reenabled durring the calcution.
28        this.reset_current = function () {
29            for (var attribute in this.variation_attributes) {
30                this.variations_current[attribute] = {};
31                for (var av = 0; av < this.variation_attributes[attribute].length; av++) {
32                    this.variations_current[attribute.toString()][this.variation_attributes[attribute][av].toString()] = 0;
33                }
34            }
35        };
36
37        //Do the things to update the variations_current object with attributes + values which are enabled.
38        this.update_current = function () {
39            this.reset_current();
40            for (var i = 0; i < this.variations_available.length; i++) {
41                if (!this.variations_available[i].variation_is_active) {
42                    continue; //Variation is unavailable, probably out of stock.
43                }
44
45                //the variation attributes for the product this variation.
46                var variation_attributes = this.variations_available[i].attributes;
47
48                //loop though each variation attribute, turning on and off attributes which won't be available.
49                for (var attribute in variation_attributes) {
50
51                    var maybe_available_attribute_value = variation_attributes[attribute];
52                    var selected_value = this.variations_selected[attribute];
53
54                    if (selected_value && selected_value == maybe_available_attribute_value) {
55                        this.variations_current[attribute][maybe_available_attribute_value] = 1; //this is a currently selected attribute value
56                    } else {
57
58                        var result = true;
59
60                        /*
61
62                         Loop though any other item that is selected,
63                         checking to see if the attribute value does not match one of the attributes for this variation.
64                         If it does not match the attributes for this variation we do nothing.
65                         If none have matched at the end of these loops, the atttribute_option will remain off and unavailable.
66
67                         */
68                        for (var other_selected_attribute in this.variations_selected) {
69
70                            if (other_selected_attribute == attribute) {
71                                //We are looking to see if any attribute that is selected will cause this to fail.
72                                //Continue the loop since this is the attribute from above and we don't need to check against ourselves.
73                                continue;
74                            }
75
76                            //Grab the value that is selected for the other attribute.
77                            var other_selected_attribute_value = this.variations_selected[other_selected_attribute];
78
79                            //Grab the current product variations attribute value for the other selected attribute we are checking.
80                            var other_available_attribute_value = variation_attributes[other_selected_attribute];
81
82                            if (other_selected_attribute_value) {
83                                if (other_available_attribute_value) {
84                                    if (other_selected_attribute_value != other_available_attribute_value) {
85                                        /*
86                                         The value this variation has for the "other_selected_attribute" does not match.
87                                         Since it does not match it does not allow us to turn on an available attribute value.
88
89                                         Set the result to false so we skip turning anything on.
90
91                                         Set the result to false so that we do not enable this attribute value.
92
93                                         If the value does match then we know that the current attribute we are looping through
94                                         might be available for us to set available attribute values.
95                                         */
96                                        result = false;
97                                        //Something on this variation didn't match the current selection, so we don't care about any of it's attributes.
98                                    }
99                                }
100                            }
101                        }
102
103                        /**
104                         After checking this attribute against this variation's attributes
105                         we either have an attribute which should be enabled or not.
106
107                         If the result is false we know that something on this variation did not match the currently selected attribute values.
108
109                         **/
110                        if (result) {
111                            if (maybe_available_attribute_value === "") {
112                                for (var av in this.variations_current[attribute]) {
113                                    this.variations_current[attribute][av] = 1;
114                                }
115
116                            } else {
117                                this.variations_current[attribute][maybe_available_attribute_value] = 1;
118                            }
119                        }
120
121                    }
122                }
123            }
124
125            this.recalc_needed = false;
126        };
127
128        this.get_current = function () {
129            if (this.recalc_needed) {
130                this.update_current();
131            }
132
133            return this.variations_current;
134        };
135
136        this.reset_selected = function () {
137            this.recalc_needed = true;
138            this.variations_selected = {};
139        }
140
141        this.set_selected = function (key, value) {
142            this.recalc_needed = true;
143            this.variations_selected[key] = value;
144        };
145
146        this.get_selected = function () {
147            return this.variations_selected;
148        }
149    }
150
151    $.fn.wc_swatches_form = function () {
152        var $form = this;
153        var $product_id = parseInt($form.data('product_id'), 10);
154        var calculator = null;
155        var $use_ajax = false;
156        var $swatches_xhr = null;
157
158        var checked = false;
159
160        $form.on('bind_calculator', function () {
161
162            var $product_variations = $form.data('product_variations');
163            $use_ajax = $product_variations === false;
164
165            if ($use_ajax) {
166                $form.block({message: null, overlayCSS: {background: '#fff', opacity: 0.6}});
167            }
168
169            var attribute_keys = {};
170
171            //Set the default label.
172            $form.find('.select-option.selected').each(function (index, el) {
173                var $this = $(this);
174
175                //Get the wrapper select div
176                var $option_wrapper = $this.closest('div.select').eq(0);
177                var $label = $option_wrapper.parent().find('.swatch-label').eq(0);
178                var $wc_select_box = $option_wrapper.find('select').first();
179
180                // Decode entities
181                var attr_val = $('<div/>').html($this.data('value')).text();
182
183                // Add slashes
184                attr_val = attr_val.replace(/'/g, '\\\'');
185                attr_val = attr_val.replace(/"/g, '\\\"');
186
187                if ($label) {
188                    $label.html($wc_select_box.children("[value='" + attr_val + "']").eq(0).text());
189                }
190
191            });
192
193            $form.find('.variations select').each(function (index, el) {
194                var $current_attr_select = $(el);
195                var current_attribute_name = $current_attr_select.data('attribute_name') || $current_attr_select.attr('name');
196
197                attribute_keys[current_attribute_name] = [];
198
199                //Build out a list of all available attributes and their values.
200                var current_options = '';
201                current_options = $current_attr_select.find('option:gt(0)').get();
202
203                if (current_options.length) {
204                    for (var i = 0; i < current_options.length; i++) {
205                        var option = current_options[i];
206                        attribute_keys[current_attribute_name].push($(option).val());
207                    }
208                }
209            });
210
211            if ($use_ajax) {
212                if ($swatches_xhr) {
213                    $swatches_xhr.abort();
214                }
215
216                var data = {
217                    product_id: $product_id,
218                    action: 'get_product_variations'
219                };
220
221                $swatches_xhr = $.ajax({
222                    url: wc_swatches_params.ajax_url,
223                    type: 'POST',
224                    data: data,
225                    success: function (response) {
226                        calculator = new variation_calculator(attribute_keys, response.data, null, null);
227                        $form.unblock();
228                    }
229                });
230            } else {
231                calculator = new variation_calculator(attribute_keys, $product_variations, null, null);
232            }
233
234            $form.trigger('woocommerce_variation_has_changed');
235        });
236
237        $form
238        // On clicking the reset variation button
239            .on('click', '.reset_variations', function () {
240                $form.find('.swatch-label').html("&nbsp;");
241                $form.find('.select-option').removeClass('selected');
242                $form.find('.radio-option').prop('checked', false);
243                return false;
244            }).on('reset_data', function (e) {
245
246            if (calculator == null) {
247                return;
248            }
249
250            var current_options = calculator.get_current();
251
252            if (!checked) {
253
254                //Grey out or show valid options.
255                $form.find('div.select').each(function (index, element) {
256                    var $wc_select_box = $(element).find('select').first();
257
258                    var attribute_name = $wc_select_box.data('attribute_name') || $wc_select_box.attr('name');
259                    var avaiable_options = current_options[attribute_name];
260
261                    $(element).find('div.select-option').each(function (index, option) {
262                        if (!avaiable_options[$(option).data('value')]) {
263                            $(option).removeClass('selected');
264                            $(option).addClass('disabled', 'disabled');
265                        } else {
266                            $(option).removeClass('disabled');
267                        }
268                    });
269
270                    $(element).find('input.radio-option').each(function (index, option) {
271                        if (!avaiable_options[$(option).val()]) {
272                            $(option).attr('disabled', 'disabled');
273                            $(option).parent().addClass('disabled', 'disabled');
274                        } else {
275                            $(option).removeAttr('disabled');
276                            $(option).parent().removeClass('disabled');
277                        }
278                    });
279                });
280
281                checked = true;
282            }
283        })
284            .on('click', '.select-option', function (e) {
285                e.preventDefault();
286
287                var $this = $(this);
288
289                //Get the wrapper select div
290                var $option_wrapper = $this.closest('div.select').eq(0);
291                var $label = $option_wrapper.parent().find('.swatch-label').eq(0);
292
293                if ($this.hasClass('disabled')) {
294                    return false;
295                } else if ($this.hasClass('selected')) {
296                    $this.removeClass('selected');
297                    var $wc_select_box = $option_wrapper.find('select').first();
298                    $wc_select_box.children('option:eq(0)').prop("selected", "selected").change();
299                    if ($label) {
300                        $label.html("&nbsp;");
301                    }
302                } else {
303
304                    $option_wrapper.find('.select-option').removeClass('selected');
305                    //Set the option to selected.
306                    $this.addClass('selected');
307
308                    //Select the option.
309                    var wc_select_box_id = $option_wrapper.data('selectid');
310                    var $wc_select_box = $option_wrapper.find('select').first();
311
312                    // Decode entities
313                    var attr_val = $('<div/>').html($this.data('value')).text();
314
315                    // Add slashes
316                    attr_val = attr_val.replace(/'/g, '\\\'');
317                    attr_val = attr_val.replace(/"/g, '\\\"');
318
319                    $wc_select_box.trigger('focusin').children("[value='" + attr_val + "']").prop("selected", "selected").change();
320                    if ($label) {
321                        $label.html($wc_select_box.children("[value='" + attr_val + "']").eq(0).text());
322                    }
323                }
324            })
325            .on('change', '.radio-option', function (e) {
326
327                var $this = $(this);
328
329                //Get the wrapper select div
330                var $option_wrapper = $this.closest('div.select').eq(0);
331
332                //Select the option.
333                var $wc_select_box = $option_wrapper.find('select').first();
334
335                // Decode entities
336                var attr_val = $('<div/>').html($this.val()).text();
337
338                // Add slashes
339                attr_val = attr_val.replace(/'/g, '\\\'');
340                attr_val = attr_val.replace(/"/g, '\\\"');
341
342                $wc_select_box.trigger('focusin').children("[value='" + attr_val + "']").prop("selected", "selected").change();
343
344
345            })
346            .on('woocommerce_variation_has_changed', function () {
347                if (calculator === null) {
348                    return;
349                }
350
351                $form.find('.variations select').each(function () {
352                    var attribute_name = $(this).data('attribute_name') || $(this).attr('name');
353                    calculator.set_selected(attribute_name, $(this).val());
354                });
355
356                var current_options = calculator.get_current();
357
358                //Grey out or show valid options.
359                $form.find('div.select').each(function (index, element) {
360                    var $wc_select_box = $(element).find('select').first();
361
362                    var attribute_name = $wc_select_box.data('attribute_name') || $wc_select_box.attr('name');
363                    var avaiable_options = current_options[attribute_name];
364
365                    $(element).find('div.select-option').each(function (index, option) {
366                        if (!avaiable_options[$(option).data('value')
366]) {
367                            $(option).addClass('disabled', 'disabled');
368                        } else {
369                            $(option).removeClass('disabled');
370                        }
371                    });
372
373                    $(element).find('input.radio-option').each(function (index, option) {
374                        if (!avaiable_options[$(option).val()]) {
375                            $(option).attr('disabled', 'disabled');
376                            $(option).parent().addClass('disabled', 'disabled');
377                        } else {
378                            $(option).removeAttr('disabled');
379                            $(option).parent().removeClass('disabled');
380                        }
381                    });
382                });
383
384                if ($use_ajax) {
385                    //Manage a regular  default select list.
386                    // WooCommerce core does not do this if it's using AJAX for it's processing.
387                    $form.find('.wc-default-select').each(function (index, element) {
388                        var $wc_select_box = $(element);
389
390                        var attribute_name = $wc_select_box.data('attribute_name') || $wc_select_box.attr('name');
391                        var avaiable_options = current_options[attribute_name];
392
393                        $wc_select_box.find('option:gt(0)').removeClass('attached');
394                        $wc_select_box.find('option:gt(0)').removeClass('enabled');
395                        $wc_select_box.find('option:gt(0)').removeAttr('disabled');
396
397                        //Disable all options
398                        $wc_select_box.find('option:gt(0)').each(function (optindex, option_element) {
399                            if (!avaiable_options[$(option_element).val()]) {
400                                $(option_element).addClass('disabled', 'disabled');
401                            } else {
402                                $(option_element).addClass('attached');
403                                $(option_element).addClass('enabled');
404                            }
405                        });
406
407                        $wc_select_box.find('option:gt(0):not(.enabled)').attr('disabled', 'disabled');
408
409                    });
410                }
411            })
412
413    };
414
415    var forms = [];
416
417    $(document).on('wc_variation_form', function (e) {
418        var $form = $(e.target);
419        forms.push($form);
420
421        if (!$form.data('has_swatches_form') || $form.hasClass('summary_content')) {
422            if ($form.find('.swatch-control').length) {
423                $form.data('has_swatches_form', true);
424
425                $form.wc_swatches_form();
426                $form.trigger('bind_calculator');
427
428                $form.on('reload_product_variations', function () {
429                    for (var i = 0; i < forms.length; i++) {
430
431
432                        forms[i].trigger('woocommerce_variation_has_changed');
433                        forms[i].trigger('bind_calculator');
434                        forms[i].trigger('woocommerce_variation_has_changed');
435
436
437                    }
438                });
439
440                 $form.trigger('check_variations');
441            }
442        }
443    });
444
445
446})(jQuery, window, document);

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.