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(" "); 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 var current_options = calculator.get_current(); 247 248 if (!checked) { 249 250 //Grey out or show valid options. 251 $form.find('div.select').each(function (index, element) { 252 var $wc_select_box = $(element).find('select').first(); 253 254 var attribute_name = $wc_select_box.data('attribute_name') || $wc_select_box.attr('name'); 255 var avaiable_options = current_options[attribute_name]; 256 257 $(element).find('div.select-option').each(function (index, option) { 258 if (!avaiable_options[$(option).data('value')]) { 259 $(option).removeClass('selected'); 260 $(option).addClass('disabled', 'disabled'); 261 } else { 262 $(option).removeClass('disabled'); 263 } 264 }); 265 266 $(element).find('input.radio-option').each(function (index, option) { 267 if (!avaiable_options[$(option).val()]) { 268 $(option).attr('disabled', 'disabled'); 269 $(option).parent().addClass('disabled', 'disabled'); 270 } else { 271 $(option).removeAttr('disabled'); 272 $(option).parent().removeClass('disabled'); 273 } 274 }); 275 }); 276 277 checked = true; 278 } 279 }) 280 .on('click', '.select-option', function (e) { 281 e.preventDefault(); 282 283 var $this = $(this); 284 285 //Get the wrapper select div 286 var $option_wrapper = $this.closest('div.select').eq(0); 287 var $label = $option_wrapper.parent().find('.swatch-label').eq(0); 288 289 if ($this.hasClass('disabled')) { 290 return false; 291 } else if ($this.hasClass('selected')) { 292 $this.removeClass('selected'); 293 var $wc_select_box = $option_wrapper.find('select').first(); 294 $wc_select_box.children('option:eq(0)').prop("selected", "selected").change(); 295 if ($label) { 296 $label.html(" "); 297 } 298 } else { 299 300 $option_wrapper.find('.select-option').removeClass('selected'); 301 //Set the option to selected. 302 $this.addClass('selected'); 303 304 //Select the option. 305 var wc_select_box_id = $option_wrapper.data('selectid'); 306 var $wc_select_box = $option_wrapper.find('select').first(); 307 308 // Decode entities 309 var attr_val = $('<div/>').html($this.data('value')).text(); 310 311 // Add slashes 312 attr_val = attr_val.replace(/'/g, '\\\''); 313 attr_val = attr_val.replace(/"/g, '\\\"'); 314 315 $wc_select_box.trigger('focusin').children("[value='" + attr_val + "']").prop("selected", "selected").change(); 316 if ($label) { 317 $label.html($wc_select_box.children("[value='" + attr_val + "']").eq(0).text()); 318 } 319 } 320 }) 321 .on('change', '.radio-option', function (e) { 322 323 var $this = $(this); 324 325 //Get the wrapper select div 326 var $option_wrapper = $this.closest('div.select').eq(0); 327 328 //Select the option. 329 var $wc_select_box = $option_wrapper.find('select').first(); 330 331 // Decode entities 332 var attr_val = $('<div/>').html($this.val()).text(); 333 334 // Add slashes 335 attr_val = attr_val.replace(/'/g, '\\\''); 336 attr_val = attr_val.replace(/"/g, '\\\"'); 337 338 $wc_select_box.trigger('focusin').children("[value='" + attr_val + "']").prop("selected", "selected").change(); 339 340 341 }) 342 .on('woocommerce_variation_has_changed', function () { 343 if (calculator === null) { 344 return; 345 } 346 347 $form.find('.variations select').each(function () { 348 var attribute_name = $(this).data('attribute_name') || $(this).attr('name'); 349 calculator.set_selected(attribute_name, $(this).val()); 350 }); 351 352 var current_options = calculator.get_current(); 353 354 //Grey out or show valid options. 355 $form.find('div.select').each(function (index, element) { 356 var $wc_select_box = $(element).find('select').first(); 357 358 var attribute_name = $wc_select_box.data('attribute_name') || $wc_select_box.attr('name'); 359 var avaiable_options = current_options[attribute_name]; 360 361 $(element).find('div.select-option').each(function (index, option) { 362 if (!avaiable_options[$(option).data('value')
362]) { 363 $(option).addClass('disabled', 'disabled'); 364 } else { 365 $(option).removeClass('disabled'); 366 } 367 }); 368 369 $(element).find('input.radio-option').each(function (index, option) { 370 if (!avaiable_options[$(option).val()]) { 371 $(option).attr('disabled', 'disabled'); 372 $(option).parent().addClass('disabled', 'disabled'); 373 } else { 374 $(option).removeAttr('disabled'); 375 $(option).parent().removeClass('disabled'); 376 } 377 }); 378 }); 379 380 if ($use_ajax) { 381 //Manage a regular default select list. 382 // WooCommerce core does not do this if it's using AJAX for it's processing. 383 $form.find('.wc-default-select').each(function (index, element) { 384 var $wc_select_box = $(element); 385 386 var attribute_name = $wc_select_box.data('attribute_name') || $wc_select_box.attr('name'); 387 var avaiable_options = current_options[attribute_name]; 388 389 $wc_select_box.find('option:gt(0)').removeClass('attached'); 390 $wc_select_box.find('option:gt(0)').removeClass('enabled'); 391 $wc_select_box.find('option:gt(0)').removeAttr('disabled'); 392 393 //Disable all options 394 $wc_select_box.find('option:gt(0)').each(function (optindex, option_element) { 395 if (!avaiable_options[$(option_element).val()]) { 396 $(option_element).addClass('disabled', 'disabled'); 397 } else { 398 $(option_element).addClass('attached'); 399 $(option_element).addClass('enabled'); 400 } 401 }); 402 403 $wc_select_box.find('option:gt(0):not(.enabled)').attr('disabled', 'disabled'); 404 405 }); 406 } 407 }) 408 409 }; 410 411 var forms = []; 412 413 $(document).on('wc_variation_form', function (e) { 414 var $form = $(e.target); 415 forms.push($form); 416 417 if (!$form.data('has_swatches_form') || $form.hasClass('summary_content')) { 418 if ($form.find('.swatch-control').length) { 419 $form.data('has_swatches_form', true); 420 421 $form.wc_swatches_form(); 422 $form.trigger('bind_calculator'); 423 424 $form.on('reload_product_variations', function () { 425 for (var i = 0; i < forms.length; i++) { 426 427 428 forms[i].trigger('woocommerce_variation_has_changed'); 429 forms[i].trigger('bind_calculator'); 430 forms[i].trigger('woocommerce_variation_has_changed'); 431 432 433 } 434 }); 435 436 $form.trigger('check_variations'); 437 } 438 } 439 }); 440 441 442})(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.