PageSourceSearch

https://filmotecadecastillayleon.es/wp-content/plugins/woocommerce/assets/js/frontend/add-to-cart-variation.js

js filmotecadecastillayleon.es collected 2026-09-24 10:04:18 UTC 28,465 bytes, 818 lines download raw bytes

1/*global wc_add_to_cart_variation_params */
2;(function ( $, window, document, undefined ) {
3	/**
4	 * VariationForm class which handles variation forms and attributes.
5	 */
6	var VariationForm = function( $form ) {
7		var self = this;
8
9		self.$form                = $form;
10		self.$attributeFields     = $form.find( '.variations select' );
11		self.$singleVariation     = $form.find( '.single_variation' );
12		self.$singleVariationWrap = $form.find( '.single_variation_wrap' );
13		self.$resetVariations     = $form.find( '.reset_variations' );
14		self.$product             = $form.closest( '.product' );
15		self.variationData        = $form.data( 'product_variations' );
16		self.useAjax              = false === self.variationData;
17		self.xhr                  = false;
18		self.loading              = true;
19
20		// Initial state.
21		self.$singleVariationWrap.show();
22		self.$form.off( '.wc-variation-form' );
23
24		// Methods.
25		self.getChosenAttributes    = self.getChosenAttributes.bind( self );
26		self.findMatchingVariations = self.findMatchingVariations.bind( self );
27		self.isMatch                = self.isMatch.bind( self );
28		self.toggleResetLink        = self.toggleResetLink.bind( self );
29
30		// Events.
31		$form.on( 'click.wc-variation-form', '.reset_variations', { variationForm: self }, self.onReset );
32		$form.on( 'reload_product_variations', { variationForm: self }, self.onReload );
33		$form.on( 'hide_variation', { variationForm: self }, self.onHide );
34		$form.on( 'show_variation', { variationForm: self }, self.onShow );
35		$form.on( 'click', '.single_add_to_cart_button', { variationForm: self }, self.onAddToCart );
36		$form.on( 'reset_data', { variationForm: self }, self.onResetDisplayedVariation );
37		$form.on( 'reset_image', { variationForm: self }, self.onResetImage );
38		$form.on( 'change.wc-variation-form', '.variations select', { variationForm: self }, self.onChange );
39		$form.on( 'found_variation.wc-variation-form', { variationForm: self }, self.onFoundVariation );
40		$form.on( 'check_variations.wc-variation-form', { variationForm: self }, self.onFindVariation );
41		$form.on( 'update_variation_values.wc-variation-form', { variationForm: self }, self.onUpdateAttributes );
42
43		// Init after gallery.
44		setTimeout( function() {
45			$form.trigger( 'check_variations' );
46			$form.trigger( 'wc_variation_form', self );
47			self.loading = false;
48		}, 100 );
49	};
50
51	/**
52	 * Reset all fields.
53	 */
54	VariationForm.prototype.onReset = function( event ) {
55		event.preventDefault();
56		event.data.variationForm.$attributeFields.val( '' ).change();
57		event.data.variationForm.$form.trigger( 'reset_data' );
58	};
59
60	/**
61	 * Reload variation data from the DOM.
62	 */
63	VariationForm.prototype.onReload = function( event ) {
64		var form           = event.data.variationForm;
65		form.variationData = form.$form.data( 'product_variations' );
66		form.useAjax       = false === form.variationData;
67		form.$form.trigger( 'check_variations' );
68	};
69
70	/**
71	 * When a variation is hidden.
72	 */
73	VariationForm.prototype.onHide = function( event ) {
74		event.preventDefault();
75		event.data.variationForm.$form
76			.find( '.single_add_to_cart_button' )
77			.removeClass( 'wc-variation-is-unavailable' )
78			.addClass( 'disabled wc-variation-selection-needed' );
79		event.data.variationForm.$form
80			.find( '.woocommerce-variation-add-to-cart' )
81			.removeClass( 'woocommerce-variation-add-to-cart-enabled' )
82			.addClass( 'woocommerce-variation-add-to-cart-disabled' );
83	};
84
85	/**
86	 * When a variation is shown.
87	 */
88	VariationForm.prototype.onShow = function( event, variation, purchasable ) {
89		event.preventDefault();
90		if ( purchasable ) {
91			event.data.variationForm.$form
92				.find( '.single_add_to_cart_button' )
93				.removeClass( 'disabled wc-variation-selection-needed wc-variation-is-unavailable' );
94			event.data.variationForm.$form
95				.find( '.woocommerce-variation-add-to-cart' )
96				.removeClass( 'woocommerce-variation-add-to-cart-disabled' )
97				.addClass( 'woocommerce-variation-add-to-cart-enabled' );
98		} else {
99			event.data.variationForm.$form
100				.find( '.single_add_to_cart_button' )
101				.removeClass( 'wc-variation-selection-needed' )
102				.addClass( 'disabled wc-variation-is-unavailable' );
103			event.data.variationForm.$form
104				.find( '.woocommerce-variation-add-to-cart' )
105				.removeClass( 'woocommerce-variation-add-to-cart-enabled' )
106				.addClass( 'woocommerce-variation-add-to-cart-disabled' );
107		}
108
109		// If present, the media element library needs initialized on the variation description.
110		if ( wp.mediaelement ) {
111			event.data.variationForm.$form.find( '.wp-audio-shortcode, .wp-video-shortcode' )
112				.not( '.mejs-container' )
113				.filter(
114					function () {
115						return ! $( this ).parent().hasClass( 'mejs-mediaelement' );
116					}
117				)
118				.mediaelementplayer( wp.mediaelement.settings );
119		}
120	};
121
122	/**
123	 * When the cart button is pressed.
124	 */
125	VariationForm.prototype.onAddToCart = function( event ) {
126		if ( $( this ).is('.disabled') ) {
127			event.preventDefault();
128
129			if ( $( this ).is('.wc-variation-is-unavailable') ) {
130				window.alert( wc_add_to_cart_variation_params.i18n_unavailable_text );
131			} else if ( $( this ).is('.wc-variation-selection-needed') ) {
132				window.alert( wc_add_to_cart_variation_params.i18n_make_a_selection_text );
133			}
134		}
135	};
136
137	/**
138	 * When displayed variation data is reset.
139	 */
140	VariationForm.prototype.onResetDisplayedVariation = function( event ) {
141		var form = event.data.variationForm;
142		form.$product.find( '.product_meta' ).find( '.sku' ).wc_reset_content();
143		form.$product
144			.find( '.product_weight, .woocommerce-product-attributes-item--weight .woocommerce-product-attributes-item__value' )
145			.wc_reset_content();
146		form.$product
147			.find( '.product_dimensions, .woocommerce-product-attributes-item--dimensions .woocommerce-product-attributes-item__value' )
148			.wc_reset_content();
149		form.$form.trigger( 'reset_image' );
150		form.$singleVariation.slideUp( 200 ).trigger( 'hide_variation' );
151	};
152
153	/**
154	 * When the product image is reset.
155	 */
156	VariationForm.prototype.onResetImage = function( event ) {
157		event.data.variationForm.$form.wc_variations_image_update( false );
158	};
159
160	/**
161	 * Looks for matching variations for current selected attributes.
162	 */
163	VariationForm.prototype.onFindVariation = function( event, chosenAttributes ) {
164		var form              = event.data.variationForm,
165			attributes        = 'undefined' !== typeof chosenAttributes ? chosenAttributes : form.getChosenAttributes(),
166			currentAttributes = attributes.data;
167
168		if ( attributes.count && attributes.count === attributes.chosenCount ) {
169			if ( form.useAjax ) {
170				if ( form.xhr ) {
171					form.xhr.abort();
172				}
173				form.$form.block( { message: null, overlayCSS: { background: '#fff', opacity: 0.6 } } );
174				currentAttributes.product_id  = parseInt( form.$form.data( 'product_id' ), 10 );
175				currentAttributes.custom_data = form.$form.data( 'custom_data' );
176				form.xhr                      = $.ajax( {
177					url: wc_add_to_cart_variation_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'get_variation' ),
178					type: 'POST',
179					data: currentAttributes,
180					success: function( variation ) {
181						if ( variation ) {
182							form.$form.trigger( 'found_variation', [ variation ] );
183						} else {
184							form.$form.trigger( 'reset_data' );
185							attributes.chosenCount = 0;
186
187							if ( ! form.loading ) {
188								form.$form
189									.find( '.single_variation' )
190									.after(
191										'<p class="wc-no-matching-variations woocommerce-info">' +
192										wc_add_to_cart_variation_params.i18n_no_matching_variations_text +
193										'</p>'
194									);
195								form.$form.find( '.wc-no-matching-variations' ).slideDown( 200 );
196							}
197						}
198					},
199					complete: function() {
200						form.$form.unblock();
201					}
202				} );
203			} else {
204				form.$form.trigger( 'update_variation_values' );
205
206				var matching_variations = form.findMatchingVariations( form.variationData, currentAttributes ),
207					variation           = matching_variations.shift();
208
209				if ( variation ) {
210					form.$form.trigger( 'found_variation', [ variation ] );
211				} else {
212					form.$form.trigger( 'reset_data' );
213					attributes.chosenCount = 0;
214
215					if ( ! form.loading ) {
216						form.$form
217							.find( '.single_variation' )
218							.after(
219								'<p class="wc-no-matching-variations woocommerce-info">' +
220								wc_add_to_cart_variation_params.i18n_no_matching_variations_text +
221								'</p>'
222							);
223						form.$form.find( '.wc-no-matching-variations' ).slideDown( 200 );
224					}
225				}
226			}
227		} else {
228			form.$form.trigger( 'update_variation_values' );
229			form.$form.trigger( 'reset_data' );
230		}
231
232		// Show reset link.
233		form.toggleResetLink( attributes.chosenCount > 0 );
234	};
235
236	/**
237	 * Triggered when a variation has been found which matches all attributes.
238	 */
239	VariationForm.prototype.onFoundVariation = function( event, variation ) {
240		var form           = event.data.variationForm,
241			$sku           = form.$product.find( '.product_meta' ).find( '.sku' ),
242			$weight        = form.$product.find(
243				'.product_weight, .woocommerce-product-attributes-item--weight .woocommerce-product-attributes-item__value'
244			),
245			$dimensions    = form.$product.find(
246				'.product_dimensions, .woocommerce-product-attributes-item--dimensions .woocommerce-product-attributes-item__value'
247			),
248			$qty           = form.$singleVariationWrap.find( '.quantity' ),
249			purchasable    = true,
250			variation_id   = '',
251			template       = false,
252			$template_html = '';
253
254		if ( variation.sku ) {
255			$sku.wc_set_content( variation.sku );
256		} else {
257			$sku.wc_reset_content();
258		}
259
260		if ( variation.weight ) {
261			$weight.wc_set_content( variation.weight_html );
262		} else {
263			$weight.wc_reset_content();
264		}
265
266		if ( variation.dimensions ) {
267			// Decode HTML entities.
268			$dimensions.wc_set_content( $.parseHTML( variation.dimensions_html )[0].data );
269		} else {
270			$dimensions.wc_reset_content();
271		}
272
273		form.$form.wc_variations_image_update( variation );
274
275		if ( ! variation.variation_is_visible ) {
276			template = wp_template( 'unavailable-variation-template' );
277		} else {
278			template     = wp_template( 'variation-template' );
279			variation_id = variation.variation_id;
280		}
281
282		$template_html = template( {
283			variation: variation
284		} );
285		$template_html = $template_html.replace( '/*<![CDATA[*/', '' );
286		$template_html = $template_html.replace( '/*]]>*/', '' );
287
288		form.$singleVariation.html( $template_html );
289		form.$form.find( 'input[name="variation_id"], input.variation_id' ).val( variation.variation_id ).change();
290
291		// Hide or show qty input
292		if ( variation.is_sold_individually === 'yes' ) {
293			$qty.find( 'input.qty' ).val( '1' ).attr( 'min', '1' ).attr( 'max', '' ).change();
294			$qty.hide();
295		} else {
296
297			var $qty_input = $qty.find( 'input.qty' ),
298				qty_val    = parseFloat( $qty_input.val() );
299
300			if ( isNaN( qty_val ) ) {
301				qty_val = variation.min_qty;
302			} else {
303				qty_val = qty_val > parseFloat( variation.max_qty ) ? variation.max_qty : qty_val;
304				qty_val = qty_val < parseFloat( variation.min_qty ) ? variation.min_qty : qty_val;
305			}
306
307			$qty_input.attr( 'min', variation.min_qty ).attr( 'max', variation.max_qty ).val( qty_val ).change();
308			$qty.show();
309		}
310
311		// Enable or disable the add to cart button
312		if ( ! variation.is_purchasable || ! variation.is_in_stock || ! variation.variation_is_visible ) {
313			purchasable = false;
314		}
315
316		// Reveal
317		if ( $.trim( form.$singleVariation.text() ) ) {
318			form.$singleVariation.slideDown( 200 ).trigger( 'show_variation', [ variation, purchasable ] );
319		} else {
320			form.$singleVariation.show().trigger( 'show_variation', [ variation, purchasable ] );
321		}
322	};
323
324	/**
325	 * Triggered when an attribute field changes.
326	 */
327	VariationForm.prototype.onChange = function( event ) {
328		var form = event.data.variationForm;
329
330		form.$form.find( 'input[name="variation_id"], input.variation_id' ).val( '' ).change();
331		form.$form.find( '.wc-no-matching-variations' ).remove();
332
333		if ( form.useAjax ) {
334			form.$form.trigger( 'check_variations' );
335		} else {
336			form.$form.trigger( 'woocommerce_variation_select_change' );
337			form.$form.trigger( 'check_variations' );
338		}
339
340		// Custom event for when variation selection has been changed
341		form.$form.trigger( 'woocommerce_variation_has_changed' );
342	};
343
344	/**
345	 * Escape quotes in a string.
346	 * @param {string} string
347	 * @return {string}
348	 */
349	VariationForm.prototype.addSlashes = function( string ) {
350		string = string.replace( /'/g, '\\\'' );
351		string = string.replace( /"/g, '\\\"' );
352		return string;
353	};
354
355	/**
356	 * Updates attributes in the DOM to show valid values.
357	 */
358	VariationForm.prototype.onUpdateAttributes = function( event ) {
359		var form              = event.data.variationForm,
360			attributes        = form.getChosenAttributes(),
361			currentAttributes = attributes.data;
362
363		if ( form.useAjax ) {
364			return;
365		}
366
367		// Loop through selects and disable/enable options based on selections.
368		form.$attributeFields.each( function( index, el ) {
369			var current_attr_select     = $( el ),
370				current_attr_name       = current_attr_select.data( 'attribute_name' ) || current_attr_select.attr( 'name' ),
371				show_option_none        = $( el ).data( 'show_option_none' ),
372				option_gt_filter        = ':gt(0)',
373				attached_options_count  = 0,
374				new_attr_select         = $( '<select/>' ),
375				selected_attr_val       = current_attr_select.val() || '',
376				selected_attr_val_valid = true;
377
378			// Reference options set at first.
379			if ( ! current_attr_select.data( 'attribute_html' ) ) {
380				var refSelect = current_attr_select.clone();
381
382				refSelect.find( 'option' ).removeAttr( 'disabled attached' ).removeAttr( 'selected' );
383
384				// Legacy data attribute.
385				current_attr_select.data(
386					'attribute_options',
387					refSelect.find( 'option' + option_gt_filter ).get()
388				);
389				current_attr_select.data( 'attribute_html', refSelect.html() );
390			}
391
392			new_attr_select.html( current_attr_select.data( 'attribute_html' ) );
393
394			// The attribute of this select field should not be taken into account when calculating its matching variations:
395			// The constraints of this attribute are shaped by the values of the other attributes.
396			var checkAttributes = $.extend( true, {}, currentAttributes );
397
398			checkAttributes[ current_attr_name ] = '';
399
400			var variations = form.findMatchingVariations( form.variationData, checkAttributes );
401
402			// Loop through variations.
403			for ( var num in variations ) {
404				if ( typeof( variations[ num ] ) !== 'undefined' ) {
405					var variationAttributes = variations[ num ].attributes;
406
407					for ( var attr_name in variationAttributes ) {
408						if ( variationAttributes.hasOwnProperty( attr_name ) ) {
409							var attr_val         = variationAttributes[ attr_name ],
410								variation_active = '';
411
412							if ( attr_name === current_attr_name ) {
413								if ( variations[ num ].variation_is_active ) {
414									variation_active = 'enabled';
415								}
416
417								if ( attr_val ) {
418									// Decode entities.
419									attr_val = $( '<div/>' ).html( attr_val ).text();
420
421									// Attach to matching options by value. This is done to compare
422									// TEXT values rather than any HTML entities.
423									var $option_elements = new_attr_select.find( 'option' );
424									if ( $option_elements.length ) {
425										for (var i = 0, len = $option_elements.length; i < len; i++) {
426											var $option_element = $( $option_elements[i] ),
427												option_value = $option_element.val();
428
429											if ( attr_val === option_value ) {
430												$option_element.addClass( 'attached ' + variation_active );
431												break;
432											}
433										}
434									}
435								} else {
436									// Attach all apart from placeholder.
437									new_attr_select.find( 'option:gt(0)' ).addClass( 'attached ' + variation_active );
438								}
439							}
440						}
441					}
442				}
443			}
444
445			// Count available options.
446			attached_options_count = new_attr_select.find( 'option.attached' ).length;
447
448			// Check if current selection is in attached options.
449			if ( selected_attr_val ) {
450				selected_attr_val_valid = false;
451
452				if ( 0 !== attached_options_count ) {
453					new_attr_select.find( 'option.attached.enabled' ).each( function() {
454						var option_value = $( this ).val();
455
456						if ( selected_attr_val === option_value ) {
457							selected_attr_val_valid = true;
458							return false; // break.
459						}
460					});
461				}
462			}
463
464			// Detach the placeholder if:
465			// - Valid options exist.
466			// - The current selection is non-empty.
467			// - The current selection is valid.
468			// - Placeholders are not set to be permanently visible.
469			if ( attached_options_count > 0 && selected_attr_val && selected_attr_val_valid && ( 'no' === show_option_none ) ) {
470				new_attr_select.find( 'option:first' ).remove();
471				option_gt_filter = '';
472			}
473
474			// Detach unattached.
475			new_attr_select.find( 'option' + option_gt_filter + ':not(.attached)' ).remove();
476
477			// Finally, copy to DOM and set value.
478			current_attr_select.html( new_attr_select.html() );
479			current_attr_select.find( 'option' + option_gt_filter + ':not(.enabled)' ).prop( 'disabled', true );
480
481			// Choose selected value.
482			if ( selected_attr_val ) {
483				// If the previously selected value is no longer available, fall back to the placeholder (it's going to be there).
484				if ( selected_attr_val_valid ) {
485					current_attr_select.val( selected_attr_val );
486				} else {
487					current_attr_select.val( '' ).change();
488				}
489			} else {
490				current_attr_select.val( '' ); // No change event to prevent infinite loop.
491			}
492		});
493
494		// Custom event for when variations have been updated.
495		form.$form.trigger( 'woocommerce_update_variation_values' );
496	};
497
498	/**
499	 * Get chosen attributes from form.
500	 * @return array
501	 */
502	VariationForm.prototype.getChosenAttributes = function() {
503		var data   = {};
504		var count  = 0;
505		var chosen = 0;
506
507		this.$attributeFields.each( function() {
508			var attribute_name = $( this ).data( 'attribute_name' ) || $( this ).attr( 'name' );
509			var value          = $( this ).val() || '';
510
511			if ( value.length > 0 ) {
512				chosen ++;
513			}
514
515			count ++;
516			data[ attribute_name ] = value;
517		});
518
519		return {
520			'count'      : count,
521			'chosenCount': chosen,
522			'data'       : data
523		};
524	};
525
526	/**
527	 * Find matching variations for attributes.
528	 */
529	VariationForm.prototype.findMatchingVariations = function( variations, attributes ) {
530		var matching = [];
531		for ( var i = 0; i < variations.length; i++ ) {
532			var variation = variations[i];
533
534			if ( this.isMatch( variation.attributes, attributes ) ) {
535				matching.push( variation );
536			}
537		}
538		return matching;
539	};
540
541	/**
542	 * See if attributes match.
543	 * @return {Boolean}
544	 */
545	VariationForm.prototype.isMatch = function( variation_attributes, attributes ) {
546		var match = true;
547		for ( var attr_name in variation_attributes ) {
548			if ( variation_attributes.hasOwnProperty( attr_name ) ) {
549				var val1 = variation_attributes[ attr_name ];
550				var val2 = attributes[ attr_name ];
551				if ( val1 !== undefined && val2 !== undefined && val1.length !== 0 && val2.length !== 0 && val1 !== val2 ) {
552					match = false;
553				}
554			}
555		}
556		return match;
557	};
558
559	/**
560	 * Show or hide the reset link.
561	 */
562	VariationForm.prototype.toggleResetLink = function( on ) {
563		if ( on ) {
564			if ( this.$resetVariations.css( 'visibility' ) === 'hidden' ) {
565				this.$resetVariations.css( 'visibility', 'visible' ).hide().fadeIn();
566			}
567		} else {
568			this.$resetVariations.css( 'visibility', 'hidden' );
569		}
570	};
571
572	/**
573	 * Function to call wc_variation_form on jquery selector.
574	 */
575	$.fn.wc_variation_form = function() {
576		new VariationForm( this );
577		return this;
578	};
579
580	/**
581	 * Stores the default text for an element so it can be reset later
582	 */
583	$.fn.wc_set_content = function( content ) {
584		if ( undefined === this.attr( 'data-o_content' ) ) {
585			this.attr( 'data-o_content', this.text() );
586		}
587		this.text( content );
588	};
589
590	/**
591	 * Stores the default text for an element so it can be reset later
592	 */
593	$.fn.wc_reset_content = function() {
594		if ( undefined !== this.attr( 'data-o_content' ) ) {
595			this.text( this.attr( 'data-o_content' ) );
596		}
597	};
598
599	/**
600	 * Stores a default attribute for an element so it can be reset later
601	 */
602	$.fn.wc_set_variation_attr = function( attr, value ) {
603		if ( undefined === this.attr( 'data-o_' + attr ) ) {
604			this.attr( 'data-o_' + attr, ( ! this.attr( attr ) ) ? '' : this.attr( attr ) );
605		}
606		if ( false === value ) {
607			this.removeAttr( attr );
608		} else {
609			this.attr( attr, value );
610		}
611	};
612
613	/**
614	 * Reset a default attribute for an element so it can be reset later
615	 */
616	$.fn.wc_reset_variation_attr = function( attr ) {
617		if ( undefined !== this.attr( 'data-o_' + attr ) ) {
618			this.attr( attr, this.attr( 'data-o_' + attr ) );
619		}
620	};
621
622	/**
623	 * Reset the slide position if the variation has a different image than the current one
624	 */
625	$.fn.wc_maybe_trigger_slide_position_reset = function( variation ) {
626		var $form                = $( this ),
627			$product             = $form.closest( '.product' ),
628			$product_gallery     = $product.find( '.images' ),
629			reset_slide_position = false,
630			new_image_id         = ( variation && variation.image_id ) ? variation.image_id : '';
631
632		if ( $form.attr( 'current-image' ) !== new_image_id ) {
633			reset_slide_position = true;
634		}
635
636		$form.attr( 'current-image', new_image_id );
637
638		if ( reset_slide_position ) {
639			$product_gallery.trigger( 'woocommerce_gallery_reset_slide_position' );
640		}
641	};
642
643	/**
644	 * Sets product images for the chosen variation
645	 */
646	$.fn.wc_variations_image_update = function( variation ) {
647		var $form             = this,
648			$product          = $form.closest( '.product' ),
649			$product_gallery  = $product.find( '.images' ),
650			$gallery_nav      = $product.find( '.flex-control-nav' ),
651			$gallery_img      = $gallery_nav.find( 'li:eq(0) img' ),
652			$product_img_wrap = $product_gallery
653				.find( '.woocommerce-product-gallery__image, .woocommerce-product-gallery__image--placeholder' )
654				.eq( 0 ),
655			$product_img      = $product_img_wrap.find( '.wp-post-image' ),
656			$product_link     = $product_img_wrap.find( 'a' ).eq( 0 );
657
658		if ( variation && variation.image && variation.image.src && variation.image.src.length > 1 ) {
659			// See if the gallery has an image with the same original src as the image we want to switch to.
660			var galleryHasImage = $gallery_nav.find( 'li img[data-o_src="' + variation.image.gallery_thumbnail_src + '"]' ).length > 0;
661
662			// If the gallery has the image, reset the images. We'll scroll to the correct one.
663			if ( galleryHasImage ) {
664				$form.wc_variations_image_reset();
665			}
666
667			// See if gallery has a matching image we can slide to.
668			var slideToImage = $gallery_nav.find( 'li img[src="' + variation.image.gallery_thumbnail_src + '"]' );
669
670			if ( slideToImage.length > 0 ) {
671				slideToImage.trigger( 'click' );
672				$form.attr( 'current-image', variation.image_id );
673				window.setTimeout( function() {
674					$( window ).trigger( 'resize' );
675					$product_gallery.trigger( 'woocommerce_gallery_init_zoom' );
676				}, 20 );
677				return;
678			}
679
680			$product_img.wc_set_variation_attr( 'src', variation.image.src );
681			$product_img.wc_set_variation_attr( 'height', variation.image.src_h );
682			$product_img.wc_set_variation_attr( 'width', variation.image.src_w );
683			$product_img.wc_set_variation_attr( 'srcset', variation.image.srcset );
684			$product_img.wc_set_variation_attr( 'sizes', variation.image.sizes );
685			$product_img.wc_set_variation_attr( 'title', variation.image.title );
686			$product_img.wc_set_variation_attr( 'data-caption', variation.image.caption );
687			$product_img.wc_set_variation_attr( 'alt', variation.image.alt );
688			$product_img.wc_set_variation_attr( 'data-src', variation.image.full_src );
689			$product_img.wc_set_variation_attr( 'data-large_image', variation.image.full_src );
690			$product_img.wc_set_variation_attr( 'data-large_image_width', variation.image.full_src_w );
691			$product_img.wc_set_variation_attr( 'data-large_image_height', variation.image.full_src_h );
692			$product_img_wrap.wc_set_variation_attr( 'data-thumb', variation.image.src );
693			$gallery_img.wc_set_variation_attr( 'src', variation.image.gallery_thumbnail_src );
694			$product_link.wc_set_variation_attr( 'href', variation.image.full_src );
695		} else {
696			$form.wc_variations_image_reset();
697		}
698
699		window.setTimeout( function() {
700			$( window ).trigger( 'resize' );
701			$form.wc_maybe_trigger_slide_position_reset( variation );
702			$product_gallery.trigger( 'woocommerce_gallery_init_zoom' );
703		}, 20 );
704	};
705
706	/**
707	 * Reset main image to defaults.
708	 */
709	$.fn.wc_variations_image_reset = function() {
710		var $form             = this,
711			$product          = $form.closest( '.product' ),
712			$product_gallery  = $product.find( '.images' ),
713			$gallery_nav      = $product.find( '.flex-control-nav' ),
714			$gallery_img      = $gallery_nav.find( 'li:eq(0) img' ),
715			$product_img_wrap = $product_gallery
716				.find( '.woocommerce-product-gallery__image, .woocommerce-product-gallery__image--placeholder' )
717				.eq( 0 ),
718			$product_img      = $product_img_wrap.find( '.wp-post-image' ),
719			$product_link     = $product_img_wrap.find( 'a' ).eq( 0 );
720
721		$product_img.wc_reset_variation_attr( 'src' );
722		$product_img.wc_reset_variation_attr( 'width' );
723		$product_img.wc_reset_variation_attr( 'height' );
724		$product_img.wc_reset_variation_attr( 'srcset' );
725		$product_img.wc_reset_variation_attr( 'sizes' );
726		$product_img.wc_reset_variation_attr( 'title' );
727		$product_img.wc_reset_variation_attr( 'data-caption' );
728		$product_img.wc_reset_variation_attr( 'alt' );
729		$product_img.wc_reset_variation_attr( 'data-src' );
730		$product_img.wc_reset_variation_attr( 'data-large_image' );
731		$product_img.wc_reset_variation_attr( 'data-large_image_width' );
732		$product_img.wc_reset_variation_attr( 'data-large_image_height' );
733		$product_img_wrap.wc_reset_variation_attr( 'data-thumb' );
734		$gallery_img.wc_reset_variation_attr( 'src' );
735		$product_link.wc_reset_variation_attr( 'href' );
736	};
737
738	$(function() {
739		if ( typeof wc_add_to_cart_variation_params !== 'undefined' ) {
740			$( '.variations_form' ).each( function() {
741				$( this ).wc_variation_form();
742			});
743		}
744	});
745
746	/**
747	 * Matches inline variation objects to chosen attributes
748	 * @deprecated 2.6.9
749	 * @type {Object}
750	 */
751	var wc_variation_form_matcher = {
752		find_matching_variations: function( product_variations, settings ) {
753			var matching = [];
754			for ( var i = 0; i < product_variations.length; i++ ) {
755				var variation    = product_variations[i];
756
757				if ( wc_variation_form_matcher.variations_match( variation.attributes, settings ) ) {
758					matching.push( variation );
759				}
760			}
761			return matching;
762		},
763		variations_match: function( attrs1, attrs2 ) {
764			var match = true;
765			for ( var attr_name in attrs1 ) {
766				if ( attrs1.hasOwnProperty( attr_name ) ) {
767					var val1 = attrs1[ attr_name ];
768					var val2 = attrs2[ attr_name ];
769					if ( val1 !== undefined && val2 !== undefined && val1.length !== 0 && val2.length !== 0 && val1 !== val2 ) {
770						match = false;
771					}
772				}
773			}
774			return match;
775		}
776	};
777
778	/**
779	 * Avoids using wp.template where possible in order to be CSP compliant.
780	 * wp.template uses internally eval().
781	 * @param {string} templateId
782	 * @return {Function}
783	 */
784	var wp_template = function( templateId ) {
785		var html = document.getElementById( 'tmpl-' + templateId ).textContent;
786		var hard = false;
787		// any <# #> interpolate (evaluate).
788		hard = hard || /<#\s?data\./.test( html );
789		// any data that is NOT data.variation.
790		hard = hard || /{{{?\s?data\.(?!variation\.).+}}}?/.test( html );
791		// any data access deeper than 1 level e.g.
792		// data.variation.object.item
793		// data.variation.object['item']
794		// data.variation.array[0]
795		hard = hard || /{{{?\s?data\.variation\.[\w-]*[^\s}]/.test ( html );
796		if ( hard ) {
797			return wp.template( templateId );
798		}
799		return function template ( data ) {
800			var variation = data.variation || {};
801			return html.replace( /({{{?)\s?data\.variation\.([\w-]*)\s?(}}}?)/g, function( _, open, key, close ) {
802				// Error in the format, ignore.
803				if ( open.length !== close.length ) {
804					return '';
805				}
806				var replacement = variation[ key ] || '';
807				// {{{ }}} => interpolate (unescaped).
808				// {{  }}  => interpolate (escaped).
809				// https://codex.wordpress.org/Javascript_Reference/wp.template
810				if ( open.length === 2 ) {
811					return window.escape( replacement );
812				}
813				return replacement;
814			});
815		};
816	};
817
818})( 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.