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 159 $form.on('bind_calculator', function () { 160 161 var $product_variations = $form.data('product_variations'); 162 $use_ajax = $product_variations === false; 163 164 if ($use_ajax) { 165 $form.block({message: null, overlayCSS: {background: '#fff', opacity: 0.6}}); 166 } 167 168 var attribute_keys = {}; 169 170 //Set the default label. 171 $form.find('.select-option.selected').each(function (index, el) { 172 var $this = $(this); 173 174 //Get the wrapper select div 175 var $option_wrapper = $this.closest('div.select').eq(0); 176 var $label = $option_wrapper.parent().find('.swatch-label').eq(0); 177 var $wc_select_box = $option_wrapper.find('select').first(); 178 179 // Decode entities 180 var attr_val = $('<div/>').html($this.data('value')).text(); 181 182 // Add slashes 183 attr_val = attr_val.replace(/'/g, '\\\''); 184 attr_val = attr_val.replace(/"/g, '\\\"'); 185 186 if ($label) { 187 $label.html($wc_select_box.children("[value='" + attr_val + "']").eq(0).text()); 188 } 189 190 }); 191 192 $form.find('.variations select').each(function (index, el) { 193 var $current_attr_select = $(el); 194 var current_attribute_name = $current_attr_select.data('attribute_name') || $current_attr_select.attr('name'); 195 196 attribute_keys[current_attribute_name] = []; 197 198 //Build out a list of all available attributes and their values. 199 var current_options = ''; 200 current_options = $current_attr_select.find('option:gt(0)').get(); 201 202 if (current_options.length) { 203 for (var i = 0; i < current_options.length; i++) { 204 var option = current_options[i]; 205 attribute_keys[current_attribute_name].push($(option).val()); 206 } 207 } 208 }); 209 210 if ($use_ajax) { 211 if ($swatches_xhr) { 212 $swatches_xhr.abort(); 213 } 214 215 var data = { 216 product_id: $product_id, 217 action: 'get_product_variations' 218 }; 219 220 $swatches_xhr = $.ajax({ 221 url: wc_swatches_params.ajax_url, 222 type: 'POST', 223 data: data, 224 success: function (response) { 225 calculator = new variation_calculator(attribute_keys, response.data, null, null); 226 $form.unblock(); 227 } 228 }); 229 } else { 230 calculator = new variation_calculator(attribute_keys, $product_variations, null, null); 231 } 232 233 $form.trigger('woocommerce_variation_has_changed'); 234 }); 235 236 $form 237 // On clicking the reset variation button 238 .on('click', '.reset_variations', function () { 239 $form.find('.swatch-label').html(" "); 240 $form.find('.select-option').removeClass('selected'); 241 $form.find('.radio-option').prop('checked', false); 242 return false;
243 }) 244 .on('click', '.select-option', function (e) { 245 e.preventDefault(); 246 247 var $this = $(this); 248 249 //Get the wrapper select div 250 var $option_wrapper = $this.closest('div.select').eq(0); 251 var $label = $option_wrapper.parent().find('.swatch-label').eq(0); 252 253 if ($this.hasClass('disabled')) { 254 return false; 255 } else if ($this.hasClass('selected')) { 256 $this.removeClass('selected'); 257 var $wc_select_box = $option_wrapper.find('select').first(); 258 $wc_select_box.children('option:eq(0)').prop("selected", "selected").change(); 259 if ($label) { 260 $label.html(" "); 261 } 262 } else { 263 264 $option_wrapper.find('.select-option').removeClass('selected'); 265 //Set the option to selected. 266 $this.addClass('selected'); 267 268 //Select the option. 269 var wc_select_box_id = $option_wrapper.data('selectid'); 270 var $wc_select_box = $option_wrapper.find('select').first(); 271 272 // Decode entities 273 var attr_val = $('<div/>').html($this.data('value')).text(); 274 275 // Add slashes 276 attr_val = attr_val.replace(/'/g, '\\\''); 277 attr_val = attr_val.replace(/"/g, '\\\"'); 278 279 $wc_select_box.trigger('focusin').children("[value='" + attr_val + "']").prop("selected", "selected").change(); 280 if ($label) { 281 $label.html($wc_select_box.children("[value='" + attr_val + "']").eq(0).text()); 282 } 283 } 284 }) 285 .on('change', '.radio-option', function (e) { 286 287 var $this = $(this); 288 289 //Get the wrapper select div 290 var $option_wrapper = $this.closest('div.select').eq(0); 291 292 //Select the option. 293 var $wc_select_box = $option_wrapper.find('select').first(); 294 295 // Decode entities 296 var attr_val = $('<div/>').html($this.val()).text(); 297 298 // Add slashes 299 attr_val = attr_val.replace(/'/g, '\\\''); 300 attr_val = attr_val.replace(/"/g, '\\\"'); 301 302 $wc_select_box.trigger('focusin').children("[value='" + attr_val + "']").prop("selected", "selected").change(); 303 304 305 }) 306 .on('woocommerce_variation_has_changed', function () { 307 if (calculator === null) { 308 return; 309 } 310 311 $form.find('.variations select').each(function () { 312 var attribute_name = $(this).data('attribute_name') || $(this).attr('name'); 313 calculator.set_selected(attribute_name, $(this).val()); 314 }); 315 316 var current_options = calculator.get_current(); 317 318 //Grey out or show valid options. 319 $form.find('div.select').each(function (index, element) { 320 var $wc_select_box = $(element).find('select').first(); 321 322 var attribute_name = $wc_select_box.data('attribute_name') || $wc_select_box.attr('name'); 323 var avaiable_options = current_options[attribute_name]; 324 325 $(element).find('div.select-option').each(function (index, option) { 326 if (!avaiable_options[$(option).data('value')]) { 327 $(option).addClass('disabled', 'disabled'); 328 } else { 329 $(option).removeClass('disabled'); 330 } 331 }); 332 333 $(element).find('input.radio-option').each(function (index, option) { 334 if (!avaiable_options[$(option).val()]) { 335 $(option).attr('disabled', 'disabled'); 336 $(option).parent().addClass('disabled', 'disabled'); 337 } else { 338 $(option).removeAttr('disabled'); 339 $(option).parent().removeClass('disabled'); 340 } 341 }); 342 }); 343 344 if ($use_ajax) { 345 //Manage a regular default select list. 346 // WooCommerce core does not do this if it's using AJAX for it's processing. 347 $form.find('.wc-default-select').each(function (index, element) { 348 var $wc_select_box = $(element); 349 350 var attribute_name = $wc_select_box.data('attribute_name') || $wc_select_box.attr('name'); 351 var avaiable_options = current_options[attribute_name]; 352 353 $wc_select_box.find('option:gt(0)').removeClass('attached'); 354 $wc_select_box.find('option:gt(0)').removeClass('enabled'); 355 $wc_select_box.find('option:gt(0)').removeAttr('disabled'); 356 357 //Disable all options 358 $wc_select_box.find('option:gt(0)').each(function (optindex, option_element) { 359 if (!avaiable_options[$(option_element).val()]) { 360 $(option_element).addClass('disabled', 'disabled'); 361 } else { 362 $(option_element).addClass('attached'); 363 $(option_element).addClass('enabled'); 364 } 365 }); 366 367 $wc_select_box.find('option:gt(0):not(.enabled)').attr('disabled', 'disabled'); 368 369 }); 370 } 371 }); 372 }; 373 374 var forms = []; 375 376 $(document).on('wc_variation_form', function (e) { 377 var $form = $(e.target); 378 forms.push($form); 379 380 if ( !$form.data('has_swatches_form') || $form.hasClass('summary_content') ) { 381 if ($form.find('.swatch-control').length) { 382 $form.data('has_swatches_form', true); 383 384 $form.wc_swatches_form(); 385 $form.trigger('bind_calculator'); 386 387 $form.on('reload_product_variations', function () { 388 for (var i = 0; i < forms.length; i++) { 389 390 391 forms[i].trigger('woocommerce_variation_has_changed'); 392 forms[i].trigger('bind_calculator'); 393 forms[i].trigger('woocommerce_variation_has_changed'); 394 395 396 } 397 }) 398 } 399 } 400 }); 401 402 403})(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.