PageSourceSearch

https://slash-32.com/wp-content/plugins/variation-swatches-woo/assets/js/swatches.js?ver=1.0.14

js slash-32.com collected 2026-10-01 15:19:46 UTC 16,476 bytes, 593 lines download raw bytes

1( function ( $ ) {
2	const removeAttrClass = cfvsw_swatches_settings.remove_attr_class;
3	const addRemoveWithCommonClass = `${ removeAttrClass } cfvsw-swatches-out-of-stock`;
4	const addRemoveDisableClass = removeAttrClass + '-disable';
5	const addRemoveDisableClassCommon = `${ addRemoveDisableClass } cfvsw-swatches-disabled`;
6
7	// Disable out of stock attr.
8	const SW = {
9		init: () => {
10			if ( cfvsw_swatches_settings.disable_out_of_stock ) {
11				SW.firstTime();
12				SW.Events();
13			}
14		},
15		firstTime: () => {
16			const getVariationTable = $( 'table.variations' ).not(
17				'.cfvsw-variation-disable-logic'
18			);
19			getVariationTable.addClass( 'cfvsw-variation-disable-logic' );
20			getVariationTable.each( function () {
21				const table = $( this );
22				const getForm = table.closest(
23					'[data-product_id][data-product_variations]'
24				);
25				const getFormData = getForm.data( 'product_variations' );
26				SW.swatchesOptions( getForm, getFormData );
27			} );
28		},
29		chooseOption() {
30			const option = $( this );
31			const getForm = option.closest(
32				'[data-product_id][data-product_variations]'
33			);
34			getForm
35				.find( '.disable-to-select' )
36				.removeClass( 'disable-to-select' );
37			const td = option.closest( 'td' );
38			const checkTdSelected = td
39				.find( '.cfvsw-hidden-select select' )
40				.val();
41			if ( '' !== checkTdSelected ) {
42				td.addClass( 'disable-to-select' );
43			}
44			const getFormData = getForm.data( 'product_variations' );
45			SW.swatchesOptions( getForm, getFormData );
46		},
47		getSelectedOptions: ( getForm ) => {
48			const getSelectedSwatches = getForm.find(
49				'.cfvsw-hidden-select select'
50			);
51			const selected = {};
52			getSelectedSwatches.each( function () {
53				const select = $( this );
54				const getValue = select.val();
55				const getAttrName = select.attr( 'data-attribute_name' );
56				if ( '' !== getValue && '' !== getAttrName ) {
57					selected[ getAttrName ] = getValue;
58				}
59			} );
60			return selected;
61		},
62		swatchesOptions: ( getForm, getFormData ) => {
63			const getTdAvoidCurrent = getForm
64				.find( 'td' )
65				.not( '.disable-to-select' );
66			const getAllSelect = getTdAvoidCurrent.find(
67				'.cfvsw-swatches-container[swatches-attr]'
68			);
69			if ( ! getAllSelect.length ) {
70				return;
71			}
72			const getSelectedOptions = SW.getSelectedOptions( getForm );
73			const findToRemoveClass = getTdAvoidCurrent.find(
74				`.${ addRemoveDisableClass }`
75			);
76			if ( findToRemoveClass.length ) {
77				findToRemoveClass.removeClass( addRemoveDisableClassCommon );
78			}
79			getAllSelect.each( function () {
80				const select = $( this );
81				const getAttrName = select.attr( 'swatches-attr' );
82				if ( '' !== getAttrName ) {
83					const findOptions = select.find( '.cfvsw-swatches-option' );
84					findOptions.each( function () {
85						const optValue = $( this );
86						const currentTermSlug = optValue.attr( 'data-slug' );
87
88						if ( currentTermSlug && '' !== currentTermSlug ) {
89							const hasStock = SW.checkOptionAvail(
90								getAttrName,
91								currentTermSlug,
92								getSelectedOptions,
93								getFormData
94							);
95							if ( ! hasStock ) {
96								optValue.addClass(
97									addRemoveDisableClassCommon
98								);
99							}
100						}
101					} );
102				}
103			} );
104		},
105		checkOptionAvail: (
106			getAttrName,
107			currentTermSlug,
108			getSelectedOptions,
109			getFormData
110		) => {
111			let hasThisSwatch;
112			for ( let index = 0; index < getFormData.length; index++ ) {
113				const productVariations = getFormData[ index ];
114				const { attributes, is_in_stock } = productVariations;
115				const passedInRaw = SW.checkInPreRawData(
116					getSelectedOptions,
117					attributes,
118					getAttrName,
119					currentTermSlug,
120					is_in_stock
121				);
122				if ( passedInRaw ) {
123					hasThisSwatch = is_in_stock;
124					break;
125				}
126			}
127			return hasThisSwatch;
128		},
129		checkInPreRawData: (
130			getSelectedOptions,
131			attributes,
132			getAttrName,
133			currentTermSlug,
134			is_in_stock
135		) => {
136			let hasThisSwatch = false;
137			// If getSelectedOptions values have.
138			const copySelected = { ...getSelectedOptions };
139			const selectedKeys = Object.keys( getSelectedOptions );
140			const getCurrentIndex = selectedKeys.indexOf( getAttrName );
141			const currentObj = {};
142			currentObj[ getAttrName ] = currentTermSlug;
143			if ( getCurrentIndex >= 0 ) {
144				selectedKeys.splice( getCurrentIndex, 1 );
145				delete copySelected[ getAttrName ];
146			}
147			hasThisSwatch = SW.checkInRawData(
148				attributes,
149				copySelected,
150				currentObj,
151				is_in_stock
152			);
153			return hasThisSwatch;
154		},
155		checkInRawData: ( attribute, selected, currentObj, is_in_stock ) => {
156			const cloneAttr = { ...attribute };
157			const selectedCurrent = { ...selected, ...currentObj };
158			let checkAndAvail = true;
159			for ( const checkIsAvail in selectedCurrent ) {
160				const value = selectedCurrent[ checkIsAvail ];
161				const attrValue = attribute[ checkIsAvail ];
162				if ( '' === attrValue ) {
163					delete cloneAttr[ checkIsAvail ];
164					continue;
165				}
166				if ( value === attrValue ) {
167					delete cloneAttr[ checkIsAvail ];
168					continue;
169				}
170				checkAndAvail = false;
171			}
172
173			if ( is_in_stock ) {
174				return checkAndAvail;
175			}
176			// Check when out of stock
177			for ( const cloneKey in cloneAttr ) {
178				const cloneValue = cloneAttr[ cloneKey ];
179				if ( '' !== cloneValue ) {
180					checkAndAvail = false;
181				}
182			}
183			return checkAndAvail;
184		},
185		Events: () => {
186			$( document ).on(
187				'click',
188				'.cfvsw-swatches-container .cfvsw-swatches-option[data-slug]',
189				SW.chooseOption
190			);
191
192			// Adding a compatibility of Load More Products for WooCommerce Plugin's Ajax call for loading the products on shop page.
193			$( document ).on(
194				'berocket_ajax_products_infinite_loaded',
195				function () {
196					SW.firstTime();
197				}
198			);
199		},
200	};
201
202	$( document ).on( 'click', '.cfvsw-swatches-option', function () {
203		const swatchesOption = $( this );
204		if (
205			swatchesOption.hasClass( 'cfvsw-swatches-disabled' ) ||
206			swatchesOption.hasClass( 'cfvsw-swatches-out-of-stock' )
207		) {
208			return;
209		}
210		onClickSwatchesOption( swatchesOption );
211		addVariationFunctionality();
212	} );
213
214	$( 'body' ).on(
215		'click',
216		'.cfvsw_ajax_add_to_cart.cfvsw_variation_found',
217		function ( e ) {
218			e.preventDefault();
219			triggerAddToCart( $( this ) );
220		}
221	);
222
223	function onClickSwatchesOption( swatch ) {
224		if ( swatch.hasClass( 'cfvsw-selected-swatch' ) ) {
225			swatch.removeClass( 'cfvsw-selected-swatch' );
226			resetPrice( swatch );
227			resetThumbnail( swatch );
228			resetButtonData( swatch );
229		} else {
230			const parent = swatch.parent();
231			parent.find( '.cfvsw-swatches-option' ).each( function () {
232				$( this ).removeClass( 'cfvsw-selected-swatch' );
233			} );
234
235			swatch.addClass( 'cfvsw-selected-swatch' );
236		}
237
238		updateSelectOption( swatch );
239		if ( cfvsw_swatches_settings.html_design !== 'inline' ) {
240			updateTitle( swatch );
241		}
242	}
243
244	function updateSelectOption( swatch ) {
245		const value = swatch.hasClass( 'cfvsw-selected-swatch' )
246			? swatch.data( 'slug' )
247			: '';
248		const select = swatch
249			.closest( '.cfvsw-swatches-container' )
250			.prev()
251			.find( 'select' );
252		select.val( value ).change();
253	}
254
255	function updateTitle( swatch ) {
256		const label = swatch.closest( 'tr' ).children( '.label' );
257		label.find( '.cfvsw-selected-label' ).remove();
258
259		if ( ! swatch.hasClass( 'cfvsw-selected-swatch' ) ) {
260			return;
261		}
262
263		label
264			.children( 'label' )
265			.append( '<span class="cfvsw-selected-label"></span>' );
266		label
267			.children( 'label' )
268			.children( '.cfvsw-selected-label' )
269			.html( swatch.data( 'title' ) );
270	}
271
272	function triggerAddToCart( variant ) {
273		if ( variant.is( '.wc-variation-is-unavailable' ) ) {
274			return window.alert( cfvsw_swatches_settings.unavailable_text );
275		}
276		const productId = variant.data( 'product_id' );
277		let variationId = variant.attr( 'data-variation_id' );
278		variationId = parseInt( variationId );
279		if (
280			isNaN( productId ) ||
281			productId === 0 ||
282			isNaN( variationId ) ||
283			variationId === 0
284		) {
285			return true;
286		}
287		let variation = variant.attr( 'data-selected_variant' );
288		variation = JSON.parse( variation );
289		const data = {
290			action: 'cfvsw_ajax_add_to_cart',
291			security: cfvsw_swatches_settings.ajax_add_to_cart_nonce,
292			product_id: productId,
293			variation_id: variationId,
294			variation,
295		};
296		$( document.body ).trigger( 'adding_to_cart', [ variant, data ] );
297		variant.removeClass( 'added' ).addClass( 'loading' );
298		// Ajax add to cart request
299		$.ajax( {
300			type: 'POST',
301			url: cfvsw_swatches_settings.ajax_url,
302			data,
303			dataType: 'json',
304			success( response ) {
305				if ( ! response ) {
306					return;
307				}
308
309				if ( response.error && response.product_url ) {
310					window.location = response.product_url;
311					return;
312				}
313
314				// Trigger event so themes can refresh other areas.
315				$( document.body ).trigger( 'added_to_cart', [
316					response.fragments,
317					response.cart_hash,
318					variant,
319				] );
320				$( document.body ).trigger( 'update_checkout' );
321
322				variant.removeClass( 'loading' ).addClass( 'added' );
323			},
324			error( errorThrown ) {
325				variant.removeClass( 'loading' );
326				console.log( errorThrown );
327			},
328		} );
329	}
330
331	$( document ).on( 'change', '.cfvsw-hidden-select select', function () {
332		setTimeout( () => {
333			updateSwatchesAvailability();
334		}, 1 );
335	} );
336
337	$( '.reset_variations' ).on( 'click', function () {
338		resetSwatches( $( this ) );
339	} );
340
341	// Tooltip.
342	$( document ).on(
343		{
344			mouseenter() {
345				const addToTooltip = $( this );
346				const tooltip = addToTooltip.data( 'tooltip' );
347				if (
348					'' === tooltip ||
349					'undefined' === typeof tooltip ||
350					addToTooltip.hasClass( 'cfvsw-label-option' )
351				) {
352					return;
353				}
354
355				if ( addToTooltip.children( '.cfvsw-tooltip' ).length === 0 ) {
356					addToTooltip.prepend(
357						`<div class="cfvsw-tooltip"><span class="cfvsw-tooltip-label">${ tooltip }</span></div>`
358					);
359					$( '.cfvsw-tooltip' ).fadeIn( 500 );
360					const swatchHeight = addToTooltip
361						.children( '.cfvsw-swatch-inner' )
362						.innerHeight();
363					$( '.cfvsw-tooltip' ).css( {
364						bottom: swatchHeight,
365					} );
366					if (
367						cfvsw_swatches_settings.tooltip_image &&
368						addToTooltip.hasClass( 'cfvsw-image-option' )
369					) {
370						$( '.cfvsw-tooltip' ).prepend(
371							"<span class='cfvsw-tooltip-preview'></span>"
372						);
373						const preview = addToTooltip
374							.children( '.cfvsw-swatch-inner' )
375							.css( 'backgroundImage' );
376						$( '.cfvsw-tooltip' ).css( {
377							bottom: swatchHeight - 30,
378							padding: '2px',
379						} );
380						$( '.cfvsw-tooltip-preview' ).css( {
381							backgroundImage: preview,
382							backgroundSize: 'cover',
383						} );
384					}
385				}
386			},
387			mouseleave() {
388				$( '.cfvsw-tooltip' ).remove();
389			},
390		},
391		'.cfvsw-swatches-option'
392	);
393
394	$( document ).on( 'ready', function () {
395		setTimeout( () => {
396			setSwatchesSelection();
397		}, 1 );
398		$( '.woocommerce-widget-layered-nav-list' ).each( function () {
399			if ( $( this ).find( '.cfvsw-swatches-container' ).length ) {
400				$( this ).addClass( 'cfvsw-filters' );
401			}
402		} );
403	} );
404
405	$( '.cfvsw-shop-variations' ).on( 'click', function ( e ) {
406		e.preventDefault();
407	} );
408
409	$( '.cfvsw-shop-variations .cfvsw-more-link' ).on( 'click', function ( e ) {
410		window.location = e.target.href;
411	} );
412
413	function updateSwatchesAvailability() {
414		$( '.cfvsw-hidden-select select' ).each( function () {
415			const availableOptions = [];
416			$( this )
417				.children( 'option' )
418				.each( function () {
419					if ( '' !== $( this ).val() ) {
420						availableOptions.push( $( this ).val() );
421					}
422				} );
423			$( this )
424				.parent()
425				.next()
426				.find( '.cfvsw-swatches-option' )
427				.each( function () {
428					if (
429						-1 ===
430						$.inArray(
431							$( this ).attr( 'data-slug' ),
432							availableOptions
433						)
434					) {
435						$( this ).addClass( addRemoveWithCommonClass );
436					} else {
437						$( this ).removeClass( addRemoveWithCommonClass );
438					}
439				} );
440		} );
441	}
442
443	function setSwatchesSelection() {
444		$( '.cfvsw-hidden-select select' ).each( function () {
445			const selected = $( this ).val();
446			$( this )
447				.parent()
448				.next()
449				.find( `[data-slug='${ selected }']` )
450				.trigger( 'click' );
451		} );
452	}
453
454	function resetSwatches( resetButton ) {
455		$( '.cfvsw-swatches-option' ).each( function () {
456			$( this ).removeClass( 'cfvsw-selected-swatch' );
457		} );
458		$( '.cfvsw-selected-label' ).remove();
459
460		if ( cfvsw_swatches_settings.disable_out_of_stock ) {
461			const table = resetButton.closest( 'table' );
462			const findDisabledAttr = table.find(
463				`.${ addRemoveDisableClass }`
464			);
465			const findDisableSelect = table.find( '.disable-to-select' );
466			if ( findDisableSelect.length ) {
467				findDisableSelect.removeClass( 'disable-to-select' );
468			}
469			if ( findDisabledAttr ) {
470				findDisabledAttr.removeClass( addRemoveDisableClassCommon );
471			}
472			setTimeout( () => {
473				SW.firstTime();
474			}, 20 );
475		}
476	}
477
478	function addVariationFunctionality() {
479		$( '.cfvsw_variations_form:not(.variation-function-added)' ).each(
480			function () {
481				const thisForm = $( this );
482				thisForm.addClass( 'variation-function-added' );
483				thisForm.wc_variation_form();
484				thisForm.on( 'found_variation', function ( e, variation ) {
485					updateThumbnail( thisForm, variation.image );
486					if ( thisForm.attr( 'data-cfvsw-catalog' ) ) {
487						return;
488					}
489					updatePrice( thisForm, variation );
490					updatebuttonData( thisForm, variation );
491				} );
492			}
493		);
494	}
495
496	$( window ).on( 'load', function () {
497		addVariationFunctionality();
498	} );
499
500	function updateThumbnail( swatch, imageData ) {
501		const listItem = swatch.closest( 'li' );
502		const thumbnail = listItem.find( 'img:first' );
503		if ( 0 === listItem.find( '.cfvsw-original-thumbnail' ).length ) {
504			const originalThumbnail = thumbnail.clone();
505			thumbnail.after( '<span class="cfvsw-original-thumbnail"></span>' );
506			listItem
507				.find( '.cfvsw-original-thumbnail' )
508				.html( originalThumbnail );
509		}
510		thumbnail.attr( 'src', imageData.thumb_src );
511		thumbnail.attr( 'srcset', '' );
512	}
513
514	function resetThumbnail( swatch ) {
515		const listItem = swatch.closest( 'li' );
516		if ( listItem.find( '.cfvsw-original-thumbnail' ).length ) {
517			const thumbnail = listItem.find( 'img:first' );
518			thumbnail.replaceWith(
519				listItem.find( '.cfvsw-original-thumbnail' ).html()
520			);
521			listItem.find( '.cfvsw-original-thumbnail' ).remove();
522		}
523	}
524
525	function updatePrice( swatch, variation ) {
526		if ( 0 === variation.price_html.length ) {
527			return;
528		}
529		if ( swatch.parents( 'li' ).find( '.cfvsw-original-price' ).length ) {
530			const price = swatch.parents( 'li' ).find( '.price' );
531			price.replaceWith( variation.price_html );
532		} else {
533			const price = swatch.parents( 'li' ).find( '.price' );
534			price.after( variation.price_html );
535			price.removeClass( 'price' ).addClass( 'cfvsw-original-price' );
536		}
537	}
538
539	function resetPrice( swatch ) {
540		if ( swatch.parents( 'li' ).find( '.cfvsw-original-price' ).length ) {
541			swatch.parents( 'li' ).find( '.price' ).remove();
542			swatch
543				.parents( 'li' )
544				.find( '.cfvsw-original-price' )
545				.removeClass( 'cfvsw-original-price' )
546				.addClass( 'price' );
547		}
548	}
549
550	function updatebuttonData( variant, variation ) {
551		const select = variant.find( '.variations select' );
552		const data = {};
553		const button = variant
554			.parents( 'li' )
555			.find( '.cfvsw_ajax_add_to_cart' );
556
557		select.each( function () {
558			const attributeName =
559				$( this ).data( 'attribute_name' ) || $( this ).attr( 'name' );
560			const value = $( this ).val() || '';
561			data[ attributeName ] = value;
562		} );
563
564		button.html( button.data( 'add_to_cart_text' ) );
565		button.addClass( 'cfvsw_variation_found' );
566		button.attr( 'data-variation_id', variation.variation_id );
567		button.attr( 'data-selected_variant', JSON.stringify( data ) );
568	}
569
570	function resetButtonData( variant ) {
571		const button = variant
572			.parents( 'li' )
573			.find( '.cfvsw_ajax_add_to_cart' );
574		button.html( button.data( 'select_options_text' ) );
575		button.removeClass( 'cfvsw_variation_found' );
576		button.attr( 'data-variation_id', '' );
577		button.attr( 'data-selected_variant', '' );
578	}
579
580	SW.init();
581	document.addEventListener( 'astraInfinitePaginationLoaded', function () {
582		SW.firstTime();
583		addVariationFunctionality();
584	} );
585
586	// Add custom trigger to load swatches.
587
588	// document.dispatchEvent( new CustomEvent("cfvswVariationLoad", { detail: {} }) ); To load variation trigger we need to trigger this.
589	document.addEventListener( 'cfvswVariationLoad', function () {
590		SW.firstTime();
591		addVariationFunctionality();
592	} );
593} )( jQuery );

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.