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 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(" "); 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.