PageSourceSearch

https://softext.co.uk/wp-content/plugins/woocommerce-tm-extra-product-options/assets/js/tm-epo.js?ver=7.6.1

js softext.co.uk collected 2026-10-06 17:53:59 UTC 507,286 bytes, 14,268 lines download raw bytes

1( function( window, document, $ ) {
2	'use strict';
3
4	var tcAPI = {};
5	var TMEPOJS = window.TMEPOJS;
6	var wp = window.wp;
7	var TMEPOQTRANSLATEXJS = window.TMEPOQTRANSLATEXJS;
8	var noUiSlider = window.noUiSlider;
9	var ClipboardEvent = window.ClipboardEvent;
10	var DataTransfer = window.DataTransfer;
11	var lateVariationEvent = [];
12	var latecpflogicactions = [];
13	var tmLazyloadContainer = false;
14	var variationsFormIsLoaded = false;
15	var jBody = $( 'body' );
16	var jWindow = $( window );
17	var jDocument = $( document );
18	var errorObject;
19	var FloatingTotalsBox;
20	var currentAjaxButton;
21	var currentAddToCartButton;
22	var errorContainer = $( window );
23	var tcmexp = window.tcmexp;
24	var _ = window._;
25	var priceCache = false;
26
27	var getLocalInputDecimalSeparator = function() {
28		if ( TMEPOJS.tm_epo_global_input_decimal_separator === '' ) {
29			return TMEPOJS.currency_format_decimal_sep;
30		}
31		return $.epoAPI.locale.getSystemDecimalSeparator();
32	};
33
34	var getLocalDecimalSeparator = function() {
35		if ( TMEPOJS.tm_epo_global_displayed_decimal_separator === '' ) {
36			return TMEPOJS.currency_format_decimal_sep;
37		}
38		return $.epoAPI.locale.getSystemDecimalSeparator();
39	};
40
41	var getLocalThousandSeparator = function() {
42		if ( TMEPOJS.tm_epo_global_displayed_decimal_separator === '' ) {
43			return TMEPOJS.currency_format_thousand_sep;
44		}
45		return $.epoAPI.locale.getSystemDecimalSeparator();
46	};
47
48	var getEpoDelay = function() {
49		if ( TMEPOJS.tm_epo_start_animation_delay ) {
50			return TMEPOJS.tm_epo_start_animation_delay;
51		} else if ( window.tc_epo_delay ) {
52			return window.tc_epo_delay;
53		}
54		return 500;
55	};
56
57	var getEpoAnimationDelay = function() {
58		if ( TMEPOJS.tm_epo_animation_delay ) {
59			return TMEPOJS.tm_epo_start_animation_delay;
60		} else if ( window.tc_epo_animation_delay ) {
61			return window.tc_epo_animation_delay;
62		}
63		return 500;
64	};
65
66	var originalVal = $.fn.val;
67
68	if ( ! TMEPOJS || ! wp ) {
69		return;
70	}
71
72	// Trigger plugin events when other plugins use val.
73	$.fn.val = function() {
74		var result = originalVal.apply( this, arguments );
75		if ( arguments.length > 0 ) {
76			if ( $( this ).is( '.input-text.qty' ) ) {
77				$( this ).trigger( 'change.cpf' );
78			}
79		}
80		return result;
81	};
82
83	// Set update event for Lazy Load XT
84	if ( TMEPOJS.tm_epo_no_lazy_load === 'no' && $.lazyLoadXT ) {
85		$.extend( $.lazyLoadXT, {
86			autoInit: false,
87			updateEvent: $.lazyLoadXT.updateEvent + ' tmlazy'
88		} );
89	}
90
91	tcAPI.localInputDecimalSeparator = getLocalInputDecimalSeparator();
92	tcAPI.localDecimalSeparator = getLocalDecimalSeparator();
93	tcAPI.localThousandSeparator = getLocalThousandSeparator();
94	tcAPI.epoDelay = getEpoDelay();
95	tcAPI.epoAnimationDelay = getEpoAnimationDelay();
96	tcAPI.getElementFromFieldCache = [];
97	tcAPI.epoSelector = '.tc-extra-product-options';
98	tcAPI.associatedEpoSelector = '.tc-extra-product-options-inline';
99	tcAPI.associatedEpoCart = '.tc-epo-element-product-container-cart';
100	tcAPI.addToCartSelector = "input[name='add-to-cart']";
101	tcAPI.tcAddToCartSelector = 'input.tc-add-to-cart';
102	tcAPI.qtySelector = "input.qty,input[name='quantity'],select.qty,.drop-down-button #qty,.plus-minus-button #qty,.slider-input #amount";
103	tcAPI.associateQtySelector = 'input.tm-qty-alt';
104	tcAPI.addToCartButtonSelector = '.add_to_cart_button, .single_add_to_cart_button';
105	tcAPI.compositeSelector = '.bto_item,.component';
106	tcAPI.nativeProductPriceSelector = TMEPOJS.tm_epo_global_product_price_selector || '.woocommerce .product p.price, .wc-block-components-product-price';
107	tcAPI.associatedNativeProductPriceSelector = '.product-price .associated-price';
108	tcAPI.templateEngine = $.epoAPI.applyFilter( 'tc_adjust_templateEngine', {
109		plain_price: wp.template( 'tc-plain-price' ),
110		suffix: wp.template( 'tc-suffix' ),
111		main_suffix: wp.template( 'tc-main-suffix' ),
112		price: wp.template( 'tc-price' ),
113		price_m: wp.template( 'tc-price-m' ),
114		sale_price: wp.template( 'tc-sale-price' ),
115		sale_price_m10: wp.template( 'tc-sale-price-m10' ),
116		sale_price_m01: wp.template( 'tc-sale-price-m01' ),
117		sale_price_m11: wp.template( 'tc-sale-price-m11' ),
118		tc_chars_remanining: wp.template( 'tc-chars-remanining' ),
119		tc_final_totals: wp.template( 'tc-final-totals' ),
120		tc_floating_box: wp.template( 'tc-floating-box' ),
121		tc_floating_box_nks: wp.template( 'tc-floating-box-nks' ),
122		tc_formatted_price: wp.template( 'tc-formatted-price' ),
123		tc_formatted_sale_price: wp.template( 'tc-formatted-sale-price' ),
124		tc_lightbox: wp.template( 'tc-lightbox' ),
125		tc_lightbox_zoom: wp.template( 'tc-lightbox-zoom' ),
126		tc_section_pop_link: wp.template( 'tc-section-pop-link' ),
127		tc_upload_messages: wp.template( 'tc-upload-messages' )
128	} );
129
130	// make API available to 3rd party plugins
131	$.tcAPI = function() {
132		return tcAPI;
133	};
134	// method for accessing internal api variables
135	$.tcAPIGet = function( name ) {
136		return tcAPI[ name ];
137	};
138
139	// method for setting  internal api variables
140	$.tcAPISet = function( name, value ) {
141		tcAPI[ name ] = value;
142	};
143
144	if ( $.tc_validator ) {
145		$.extend( $.tc_validator.messages, {
146			required: TMEPOJS.tm_epo_global_validator_messages.required,
147			email: TMEPOJS.tm_epo_global_validator_messages.email,
148			url: TMEPOJS.tm_epo_global_validator_messages.url,
149			number: TMEPOJS.tm_epo_global_validator_messages.number,
150			digits: TMEPOJS.tm_epo_global_validator_messages.digits,
151			maxlengthsingle: $.tc_validator.format( TMEPOJS.tm_epo_global_validator_messages.maxlengthsingle ),
152			maxlength: $.tc_validator.format( TMEPOJS.tm_epo_global_validator_messages.maxlength ),
153			minlengthsingle: $.tc_validator.format( TMEPOJS.tm_epo_global_validator_messages.minlengthsingle ),
154			minlength: $.tc_validator.format( TMEPOJS.tm_epo_global_validator_messages.minlength ),
155			max: $.tc_validator.format( TMEPOJS.tm_epo_global_validator_messages.max ),
156			min: $.tc_validator.format( TMEPOJS.tm_epo_global_validator_messages.min ),
157			step: $.tc_validator.format( TMEPOJS.tm_epo_global_validator_messages.step ),
158			lettersonly: $.tc_validator.format( TMEPOJS.tm_epo_global_validator_messages.lettersonly ),
159			lettersspaceonly: $.tc_validator.format( TMEPOJS.tm_epo_global_validator_messages.lettersspaceonly ),
160			alphanumeric: $.tc_validator.format( TMEPOJS.tm_epo_global_validator_messages.alphanumeric ),
161			alphanumericunicode: $.tc_validator.format( TMEPOJS.tm_epo_global_validator_messages.alphanumericunicode ),
162			alphanumericunicodespace: $.tc_validator.format( TMEPOJS.tm_epo_global_validator_messages.alphanumericunicodespace ),
163			repeaterminrows: $.tc_validator.format( TMEPOJS.tm_epo_global_validator_messages.repeaterminrows ),
164			repeatermaxrows: $.tc_validator.format( TMEPOJS.tm_epo_global_validator_messages.repeatermaxrows )
165		} );
166
167		/*
168		ASCII Digits
169		\u0030-\u0039
170
171		Latin Alphabet
172		\u0041-\u005A\u0061-\u007A
173
174		Latin-1 Supplement
175		\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF
176
177		Latin Extended-A
178		\u0100-\u0148\u014A-\u017F
179
180		Latin Extended-B
181		\u0180-\u01BF\u01C4-\u024F
182
183		Latin Extended Additional
184		\u1E02-\u1EF3
185
186		Greek and Coptic
187		\u0370-\u03FF
188
189		Cyrillic
190		\u0400-\u04FF\u0500-\u052F
191
192		Japanese Hiragana
193		\u3040-\u309f
194		Japanese Katakana
195		\u30a0-\u30ff
196		Japanese Kanji (common & uncommon)
197		\u4e00-\u9faf
198		Japanese Kanji (rare)
199		\u3400-\u4dbf
200
201		Arabic
202		\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF\uFB50-\uFDFF\uFE70-\uFEFF\u10E60-\u10E7F\u1EC70-\u1ECBF\u1ED00-\u1ED4F\u1EE00-\u1EEFF
203
204		\u0600-\u06ff
205		\u0600-\u06FF
206
207		Armenian
208		\u0530-\u1058F
209
210		\u0030-\u0039\u0041-\u005A\u0061-\u007A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u0148\u014A-\u017F\u0180-\u01BF\u01C4-\u024F\u1E02-\u1EF3\u0370-\u03FF\u0400-\u04FF\u0500-\u052F\u3040-\u309f\u30a0-\u30ff\u4e00-\u9faf\u3400-\u4dbf\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF\uFB50-\uFDFF\uFE70-\uFEFF\u10E60-\u10E7F\u1EC70-\u1ECBF\u1ED00-\u1ED4F\u1EE00-\u1EEFF\u0530-\u1058F
211
212		*/
213
214		$.tc_validator.addMethod(
215			'alphanumeric',
216			function( value, element ) {
217				return this.optional( element ) || /^[a-zA-Z0-9.-]+$/i.test( value );
218			},
219			$.tc_validator.messages.alphanumeric
220		);
221
222		$.tc_validator.addMethod(
223			'lettersonly',
224			function( value, element ) {
225				return this.optional( element ) || /^[a-z]+$/i.test( value );
226			},
227			$.tc_validator.messages.lettersonly
228		);
229
230		$.tc_validator.addMethod(
231			'lettersspaceonly',
232			function( value, element ) {
233				return this.optional( element ) || /^[a-z,\u0020]+$/i.test( value );
234			},
235			$.tc_validator.messages.lettersspaceonly
236		);
237
238		$.tc_validator.addMethod(
239			'alphanumericunicode',
240			function( value, element ) {
241				return (
242					this.optional( element ) ||
243					/^[\u0030-\u0039\u0041-\u005A\u0061-\u007A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u0148\u014A-\u017F\u0180-\u01BF\u01C4-\u024F\u1E02-\u1EF3\u0370-\u03FF\u0400-\u04FF\u0500-\u052F\u3040-\u309f\u30a0-\u30ff\u4e00-\u9faf\u3400-\u4dbf\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF\uFB50-\uFDFF\uFE70-\uFEFF\u10E60-\u10E7F\u1EC70-\u1ECBF\u1ED00-\u1ED4F\u1EE00-\u1EEFF\u0530-\u1058F]+$/i.test(
244						value
245					)
246				);
247			},
248			$.tc_validator.messages.alphanumericunicode
249		);
250
251		$.tc_validator.addMethod(
252			'alphanumericunicodespace',
253			function( value, element ) {
254				return (
255					this.optional( element ) ||
256					/^[\u0030-\u0039\u0041-\u005A\u0061-\u007A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u0148\u014A-\u017F\u0180-\u01BF\u01C4-\u024F\u1E02-\u1EF3\u0370-\u03FF\u0400-\u04FF\u0500-\u052F\u3040-\u309f\u30a0-\u30ff\u4e00-\u9faf\u3400-\u4dbf\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF\uFB50-\uFDFF\uFE70-\uFEFF\u10E60-\u10E7F\u1EC70-\u1ECBF\u1ED00-\u1ED4F\u1EE00-\u1EEFF\u0530-\u1058F,\u0020]+$/i.test(
257						value
258					)
259				);
260			},
261			$.tc_validator.messages.alphanumericunicodespace
262		);
263		$.tc_validator.addMethod(
264			'repeaterminrows',
265			function( value, element, param ) {
266				return $.epoAPI.math.toInt( $( element ).closest( '.tc-element-inner-wrap' ).find( '.tc-repeater-element' ).length ) >= $.epoAPI.math.toInt( param );
267			},
268			$.tc_validator.messages.repeaterminrows
269		);
270		$.tc_validator.addMethod(
271			'repeatermaxrows',
272			function( value, element, param ) {
273				return $.epoAPI.math.toInt( $( element ).closest( '.tc-element-inner-wrap' ).find( '.tc-repeater-element' ).length ) <= $.epoAPI.math.toInt( param );
274			},
275			$.tc_validator.messages.repeatermaxrows
276		);
277		$.tc_validator.addMethod(
278			'product_element_radio_qty',
279			function( value, element ) {
280				var qty = $( element ).closest( '.tm-element-ul-product' ).find( 'input.tc-epo-field-product.tm
280cp-radio:checked' ).closest( '.tc-epo-element-product-holder' ).find( '.tm-qty' ).first().val();
281				return qty > 0;
282			},
283			$.tc_validator.messages.required
284		);
285		$.tc_validator.addMethod(
286			'product_element_select_qty',
287			function( value, element ) {
288				var qty = $( element ).closest( '.tm-element-ul-product' ).find( 'select.tc-epo-field-product.tmcp-select' ).closest( '.tc-epo-element-product-holder' ).find( '.tm-qty' ).first().val();
289				return qty > 0;
290			},
291			$.tc_validator.messages.required
292		);
293	}
294
295	$.epoAPI.util.unformat = function( o ) {
296		var a = $.epoAPI.math.unformat( o, tcAPI.localInputDecimalSeparator );
297		var n = parseFloat( a );
298
299		if ( ! Number.isFinite( n ) ) {
300			return a;
301		}
302		return n;
303	};
304
305	if ( ! $.tmType ) {
306		$.tmType = function( obj ) {
307			return Object.prototype.toString
308				.call( obj )
309				.match( /\s([a-zA-Z]+)/ )[ 1 ]
310				.toLowerCase();
311		};
312	}
313
314	if ( ! $.is_on_screen ) {
315		$.fn.is_on_screen = function() {
316			// we don't use jWindow because we want the current window object
317			var win = $( window );
318			var scroll = $.epoAPI.dom.scroll();
319			var bounds = this.offset();
320			var viewport = {
321				top: scroll.top,
322				left: scroll.left
323			};
324
325			viewport.right = viewport.left + win.width();
326			viewport.bottom = viewport.top + win.height();
327			bounds.right = bounds.left + this.outerWidth();
328			bounds.bottom = bounds.top + this.outerHeight();
329
330			return ! ( viewport.right < bounds.left || viewport.left > bounds.right || viewport.bottom < bounds.top || viewport.top > bounds.bottom );
331		};
332	}
333
334	if ( ! $().tmtoggle ) {
335		$.fn.tmtoggle = function() {
336			var elements = this;
337			var is_one_open_for_accordion = false;
338			var init_done = 0;
339
340			if ( elements.length === 0 ) {
341				return;
342			}
343
344			if ( window.tc_accordion_offset === undefined ) {
345				window.tc_accordion_offset = -100;
346			}
347
348			elements.toArray().forEach( function( t ) {
349				var headers;
350				var wrap;
351				var wraps;
352
353				t = $( t );
354
355				if ( ! t.data( 'tm-toggle-init' ) ) {
356					t.data( 'tm-toggle-init', 1 );
357					headers = t.find( '.tm-toggle' );
358					wrap = t.find( '.tm-collapse-wrap' );
359					wraps = $( '.tm-collapse.tmaccordion' );
360					if ( wraps.closest( '.tc-epo-element-product-holder' ).length > 0 ) {
361						wraps = wraps.closest( '.tc-epo-element-product-holder' ).find( '.tm-collapse.tmaccordion' ).find( '.tm-toggle' );
362					} else {
363						wraps = $( '.tm-collapse.tmaccordion' ).not( '.tc-epo-element-product-holder .tm-collapse.tmaccordion' ).find( '.tm-toggle' );
364					}
365					if ( headers.length === 0 || wrap.length === 0 ) {
366						return;
367					}
368
369					if ( wrap.is( '.closed' ) ) {
370						$( wrap ).removeClass( 'closed open' ).addClass( 'closed' ).hide();
371						$( headers ).find( '.tm-arrow' ).removeClass( 'tcfa-angle-down tcfa-angle-up' ).addClass( 'tcfa-angle-down' );
372						$( headers ).removeClass( 'toggle-header-open toggle-header-closed' ).addClass( 'toggle-header-closed' );
373						$( headers ).attr( 'aria-expanded', false );
374					} else {
375						$( wrap ).removeClass( 'closed open' ).addClass( 'open' ).show();
376						$( headers ).find( '.tm-arrow' ).removeClass( 'tcfa-angle-down tcfa-angle-up' ).addClass( 'tcfa-angle-up' );
377						$( headers ).removeClass( 'toggle-header-open toggle-header-closed' ).addClass( 'toggle-header-open' );
378						$( headers ).attr( 'aria-expanded', true );
379						is_one_open_for_accordion = true;
380					}
381
382					headers.toArray().forEach( function( header ) {
383						header = $( header );
384						header.on( 'closewrap.tmtoggle', function() {
385							if ( t.is( '.tmaccordion' ) && $( wrap ).is( '.closed' ) ) {
386								return;
387							}
388							$( wrap ).removeClass( 'closed open' ).addClass( 'closed' );
389							$( this ).find( '.tm-arrow' ).removeClass( 'tcfa-angle-down tcfa-angle-up' ).addClass( 'tcfa-angle-down' );
390							$( this ).removeClass( 'toggle-header-open toggle-header-closed' ).addClass( 'toggle-header-closed' );
391							$( this ).attr( 'aria-expanded', false );
392							$( wrap ).removeClass( 'tm-animated fadein' );
393							if ( t.is( '.tmaccordion' ) ) {
394								$( wrap ).animate( { height: 'toggle' }, 100, function() {
395									$( wrap ).hide();
396								} );
397							} else {
398								$( wrap ).animate( { height: 'toggle' }, 100, function() {
399									$( wrap ).hide();
400								} );
401							}
402							jWindow.trigger( 'tmlazy' );
403						} );
404
405						header.on( 'openwrap.tmtoggle', function( e, data ) {
406							if ( t.is( '.tmaccordion' ) ) {
407								$( wraps ).not( $( this ) ).trigger( 'closewrap.tmtoggle' );
408							}
409							$( wrap ).removeClass( 'closed open' ).addClass( 'open' );
410							$( this ).find( '.tm-arrow' ).removeClass( 'tcfa-angle-down tcfa-angle-up' ).addClass( 'tcfa-angle-up' );
411							$( this ).removeClass( 'toggle-header-open toggle-header-closed' ).addClass( 'toggle-header-open' );
412							$( this ).attr( 'aria-expanded', true );
413							$( wrap ).show().removeClass( 'tm-animated fadein' ).addClass( 'tm-animated fadein' );
414							setTimeout( function() {
415								jWindow.trigger( 'tmlazy' );
416							}, 200 );
417							setTimeout( function() {
418								if ( data === undefined && init_done && t.is( '.tmaccordion' ) && ! t.is_on_screen() ) {
419									jWindow.tcScrollTo( header, 10, window.tc_accordion_offset );
420								}
421							}, 110 );
422						} );
423
424						header.on( 'click.tmtoggle keydown.tmtoggle', function( e ) {
425							// If it's a keydown event, only trigger if the Enter key was pressed
426							if ( e.type === 'keydown' && e.key !== 'Enter' ) {
427								return; // Ignore all other keypresses
428							}
429							e.preventDefault();
430							if ( $( wrap ).is( '.closed' ) ) {
431								$( this ).trigger( 'openwrap.tmtoggle' );
432							} else {
433								$( this ).trigger( 'closewrap.tmtoggle' );
434							}
435						} );
436
437						header
438							.find( '.tm-qty' )
439							.closest( '.cpf-element' )
440							.find( '.tm-epo-field' )
441							.on( 'change.cpf', function() {
442								header.trigger( 'openwrap.tmtoggle' );
443							} );
444					} );
445				}
446			} );
447			if ( undefined === window.tc_accordion_closed_on_page_load && ! is_one_open_for_accordion && elements.filter( '.tmaccordion' ).length > 0 ) {
448				elements.filter( '.tmaccordion' ).first().find( '.tm-toggle' ).trigger( 'openwrap.tmtoggle', { nomove: 1 } );
449			}
450			init_done = 1;
451			return elements;
452		};
453	}
454
455	if ( ! $().tmpoplink ) {
456		$.fn.tmpoplink = function( options ) {
457			var elements = this;
458			var floatbox_template;
459			var settings = {
460				classname: 'flasho tc-wrapper cart-popup'
461			};
462
463			if ( elements.length === 0 ) {
464				return;
465			}
466			if ( options ) {
467				settings = $.extend( {}, settings, options );
468			}
469
470			floatbox_template = function( data ) {
471				return $.epoAPI.template.html( wp.template( 'tc-cart-options-popup' ), {
472					title: data.title,
473					id: data.id,
474					html: data.html,
475					close: TMEPOJS.i18n_close
476				} );
477			};
478
479			return elements.toArray().forEach( function( t ) {
480				var id;
481				var title;
482				var html;
483				var $_html;
484
485				t = $( t );
486				if ( t.is( '.tc-poplink' ) ) {
487					return;
488				}
489				t.addClass( 'tc-poplink' );
490				id = t.attr( 'href' );
491				title = t.attr( 'data-title' );
492				html = $( id ).html();
493				if ( ! title ) {
494					title = TMEPOJS.i18n_addition_options;
495				}
496				$_html = floatbox_template( {
497					id: 'tc-floatbox-content',
498					html: html,
499					title: title
500				} );
501
502				t.on( 'click.tmpoplink', function( e ) {
503					$.tcFloatBox( {
504						fps: 1,
505						ismodal: false,
506						width: '80%',
507						height: '80%',
508						classname: settings.classname,
509						data: $_html
510					} );
511
512					e.preventDefault();
513				} );
514			} );
515		};
516	}
517
518	function readableFileSize( a, b, c, d, e ) {
519		b = Math;
520		c = b.log;
521		d = 1024;
522		e = c( a ) / c( d ) | 0; //eslint-disable-line no-bitwise
523
524		return ( ( a / b.pow( d, e ) ).toFixed( e ? 2 : 0 ) ) + ' ' + ( e ? 'KMGTPEZY'[ --e ] + 'B' : 'bytes' );
525	}
526
527	function toggleState( thisProductContainerWrap, disabled ) {
528		thisProductContainerWrap.toArray().forEach( function( setter ) {
529			setter = $( setter );
530			setter.find( ':input' ).prop( 'disabled', function( i, v ) {
531				var state = $( this ).data( 'tc-state' );
532				if ( state === undefined ) {
533					$( this ).data( 'tc-state', v );
534					return disabled;
535				}
536				if ( state === false ) {
537					return disabled;
538				}
539				return state;
540			} );
541		} );
542	}
543	// Function to calculate tax amount
544	function calculateTaxAmount( priceWithTax, _cart ) {
545		var taxable;
546		var tax_rate;
547		var pricesIncludeTax;
548		var tax_display_mode;
549		var current_variation;
550		var priceWithoutTax;
551		var taxAmount = 0;
552
553		if ( _cart ) {
554			taxable = _cart.attr( 'data-taxable' );
555			tax_rate = _cart.attr( 'data-tax-rate' );
556			pricesIncludeTax = _cart.attr( 'data-prices-include-tax' ) || TMEPOJS.prices_include_tax;
557			tax_display_mode = _cart.attr( 'data-tax-display-mode' );
558			if ( _cart.data( 'current_variation' ) !== undefined ) {
559				current_variation = _cart.data( 'current_variation' );
560			}
561
562			if ( current_variation !== undefined ) {
563				current_variation = _cart.data( 'current_variation' );
564				taxable = current_variation.tc_is_taxable;
565				tax_rate = current_variation.tc_tax_rate;
566			}
567		}
568
569		if ( taxable ) {
570			tax_rate = parseFloat( tax_rate / 100 );
571
572			if ( pricesIncludeTax === '1' ) {
573				if ( tax_display_mode === 'incl' ) {
574					priceWithTax = parseFloat( priceWithTax );
575
576					// Calculate price without tax
577					priceWithoutTax = priceWithTax / ( 1 + tax_rate );
578
579					// Calculate tax amount
580					taxAmount = priceWithTax - priceWithoutTax;
581				} else {
582					// Calculate price without tax
583					priceWithoutTax = priceWithTax;
584
585					// Calculate tax amount
586					taxAmount = priceWithTax * tax_rate;
587				}
588			} else if ( tax_display_mode === 'incl' ) {
589				// Calculate price without tax
590				priceWithoutTax = priceWithTax / ( 1 + tax_rate );
591
592				// Calculate tax amount
593				taxAmount = priceWithTax - priceWithoutTax;
594			}
595
596			taxAmount = $.epoAPI.math.toFloat( taxAmount );
597		}
598
599		return taxAmount;
600	}
601	// Taxes setup
602	function get_price_including_tax( price, _cart, element, force, variation, pricetype, doubleforce ) {
603		var taxable;
604		var tax_rate;
605		var prices_include_tax;
606		var is_vat_exempt;
607		var non_base_location_prices;
608		var taxes_of_one;
609		var base_taxes_of_one;
610		var modded_taxes_of_one;
611		var current_variation;
612
613		if ( ! Number.isFinite( parseFloat( price ) ) ) {
614			price = 0;
615		}
616		price = price * 10000;
617		if ( _cart ) {
618			taxable = _cart.attr( 'data-taxable' );
619			tax_rate = _cart.attr( 'data-tax-rate' );
620			prices_include_tax = _cart.attr( 'data-prices-include-tax' ) || TMEPOJS.prices_include_tax;
621			is_vat_exempt = _cart.attr( 'data-is-vat-exempt' );
622			non_base_location_prices = _cart.attr( 'data-non-base-location-prices' );
623			taxes_of_one = _cart.attr( 'data-taxes-of-one' );
624			base_taxes_of_one = _cart.attr( 'data-base-taxes-of-one' );
625			modded_taxes_of_one = _cart.attr( 'data-modded-taxes-of-one' );
626
627			if ( _cart.data( 'current_variation' ) !== undefined ) {
628				current_variation = _cart.data( 'current_variation' );
629			} else if ( variation !== undefined ) {
630				current_variation = variation;
631			}
632
633			if ( current_variation !== undefined ) {
634				current_variation = _cart.data( 'current_variation' );
635				taxable = current_variation.tc_is_taxable;
636				tax_rate = current_variation.tc_tax_rate;
637				non_base_location_prices = current_variation.tc_non_base_location_prices;
638				taxes_of_one = current_variation.tc_taxes_of_one;
639				base_taxes_of_one = current_variation.tc_base_taxes_of_one;
640				modded_taxes_of_one = current_variation.tc_modded_taxes_of_one;
641			}
642
643			if ( element ) {
644				if ( element.data( 'tax-obj' ) ) {
645					tax_rate = element.data( 'tax-obj' );
646					if ( tax_rate.has_fee === 'no' ) {
647						taxable = false;
648					} else if ( tax_rate.has_fee === 'yes' ) {
649						taxable = true;
650					}
651					if ( base_taxes_of_one === '' || base_taxes_of_one === undefined ) {
652						base_taxes_of_one = tax_rate / 100;
653					}
654					if ( tax_rate.base_taxes_of_one !== undefined ) {
655						base_taxes_of_one = tax_rate.base_taxes_of_one;
656					}
657					tax_rate = tax_rate.tax_rate;
658					taxes_of_one = tax_rate / 100;
659				}
660			}
661			if ( taxable ) {
662				if ( prices_include_tax === '1' && ! force ) {
663					if ( is_vat_exempt === '1' ) {
664						if ( non_base_location_prices === '1' ) {
665							price = parseFloat( price ) - ( taxes_of_one * price );
666						} else {
667							price = parseFloat( price ) - ( base_taxes_of_one * price );
668						}
669					} else if ( non_base_location_prices === '1' ) {
670						price = parseFloat( price ) - ( base_taxes_of_one * price ) + ( modded_taxes_of_one * price );
671					}
672				} else if ( element || current_variation === undefined || doubleforce ) {
673					price = parseFloat( price ) + ( parseFloat( price ) * taxes_of_one );
674				}
675			}
676		}
677		price = price / 10000;
678
679		return price;
680	}
681
682	function get_price_excluding_tax( price, _cart, element, force, variation, pricetype, doubleforce ) {
683		var taxable;
684		var tax_rate;
685		var taxes_of_one;
686		var base_taxes_of_one;
687		var prices_include_tax;
688		var current_variation;
689		var tax_display_mode;
690
691		if ( ! Number.isFinite( parseFloat( price ) ) ) {
692			price = 0;
693		}
694		price = price * 10000;
695
696		if ( _cart ) {
697			tax_display_mode = _cart.attr( 'data-tax-display-mode' );
698
699			taxable = _cart.attr( 'data-taxable' );
700			tax_rate = _cart.attr( 'data-tax-rate' );
701			taxes_of_one = _cart.attr( 'data-taxes-of-one' );
702			base_taxes_of_one = _cart.attr( 'data-base-taxes-of-one' );
703			prices_include_tax = _cart.attr( 'data-prices-include-tax' );
704
705			if ( _cart.data( 'current_variation' ) !== undefined ) {
706				current_variation = _cart.data( 'current_variation' );
707			} else if ( variation !== undefined ) {
708				current_variation = variation;
709			}
710			if ( current_variation !== undefined ) {
711				taxable = current_variation.tc_is_taxable;
712				tax_rate = current_variation.tc_tax_rate;
713				taxes_of_one = current_variation.tc_taxes_of_one;
714				base_taxes_of_one = current_variation.tc_base_taxes_of_one;
715			}
716
717			if ( element ) {
718				if ( element.data( 'tax-obj' ) ) {
719					tax_rate = element.data( 'tax-obj' );
720					if ( tax_rate.has_fee === 'no' ) {
721						taxable = false;
722					} else if ( tax_rate.has_fee === 'yes' ) {
723						taxable = true;
724					}
725					if ( base_taxes_of_one === '' || base_taxes_of_one === undefined ) {
726						base_taxes_of_one = tax_rate / 100;
727					}
728					if ( tax_rate.base_taxes_of_one !== undefined ) {
729						base_taxes_of_one = tax_rate.base_taxes_of_one;
730					}
731					tax_rate = tax_rate.tax_rate;
732				}
733			}
734
735			if ( taxable ) {
736				if ( prices_include_tax === '1' || force ) {
737					if ( tax_display_mode === 'incl' ) {
738						// This should never run on this function
739					} else if ( element || current_variation === undefined || force || doubleforce ) {
740						if ( base_taxes_of_one === taxes_of_one ) {
741							price = parseFloat( price ) - parseFloat( taxes_of_one * price );
742						} else {
743							price = price * ( 1 - parseFloat( base_taxes_of_one ) );
744						}
745					}
746				}
747			}
748		}
749		price = price / 10000;
750
751		return price;
752	}
753
754	function tm_set_tax_price( value, _cart, element, pricetype, force, variation, doubleforce ) {
755		var tax_display_mode;
756
757		if ( ! Number.isFinite( parseFloat( value ) ) ) {
758			value = 0;
759		}
760		if ( _cart ) {
761			tax_display_mode = _cart.attr( 'data-tax-display-mode' ) || TMEPOJS.tax_display_mode;
762			if ( tax_display_mode === 'incl' ) {
763				value = get_price_including_tax( value, _cart, element, force, variation, pricetype, doubleforce );
764			} else {
765				value = get_price_excluding_tax( value, _cart, element, force, variation, pricetype, doubleforce );
766			}
767		}
768		return value;
769	}
770
771	// Return a formatted currency value
772	function formatPrice( value, args ) {
773		var data;
774		if ( ! args ) {
775			args = {};
776		}
777		data = $.extend( {
778			symbol: '',
779			format: '',
780			decimal: tcAPI.localDecimalSeparator,
781			thousand: tcAPI.localThousandSeparator,
782			precision: TMEPOJS.currency_format_num_decimals
783		}, args );
784
785		if ( TMEPOJS.tm_epo_trim_zeros === 'yes' ) {
786			if ( ( ( value % 1 ).toString() !== '0' ) === false ) {
787				data.precision = 0;
788			}
789		}
790
791		return $.epoAPI.applyFilter( 'tc_formatPrice', $.epoAPI.math.format( value, data ), data, value );
792	}
793
794	// Return a formatted currency value
795	function tm_set_price_( value, sign ) {
796		return (
797			sign +
798			formatPrice( value, { symbol: TMEPOJS.currency_format_symbol, format: TMEPOJS.currency_format } )
799		);
800	}
801
802	// Return a formatted currency value
803	function tm_set_price( value, _cart, notax, element, pricetype ) {
804		var val;
805		var sign = TMEPOJS.option_plus_sign + ' ';
806
807		if ( ! notax ) {
808			value = tm_set_tax_price( value, _cart, element, pricetype );
809		}
810
811		val = Math.abs( value );
812
813		if ( TMEPOJS.tm_epo_global_options_price_sign === 'minus' ) {
814			sign = '';
815		}
816		if ( value < 0 ) {
817			sign = TMEPOJS.option_minus_sign + ' ';
818		}
819
820		return tm_set_price_( val, sign );
821	}
822
823	// Return a price currency value without any formatting
824	function tm_get_price( value, _cart, notax, element, pricetype, force ) {
825		if ( ! notax ) {
826			value = tm_set_tax_price( value, _cart, element, pricetype, force );
827		}
828
829		return value;
830	}
831
832	// FloatingTotalsBox plugin
833	FloatingTotalsBox = function( this_epo_totals_container, is_quickview, main_cart ) {
834		this.this_epo_totals_container = this_epo_totals_container;
835		this.is_quickview = is_quickview;
836		this.main_cart = main_cart;
837
838		if ( ! is_quickview && TMEPOJS.floating_totals_box && TMEPOJS.floating_totals_box !== 'disable' && main_cart && this_epo_totals_container.length ) {
839			this.init();
840			return this;
841		}
842
843		return false;
844	};
845
846	FloatingTotalsBox.prototype = {
847		constructor: FloatingTotalsBox,
848
849		onUpdate: function() {
850			var tm_epo_totals_html = this.this_epo_totals_container.data( 'tm-html' );
851			var tm_floating_box_data = this.this_epo_totals_container.data( 'tm-floating-box-data' );
852			var values_obj = [];
853			var floatingBoxHtml;
854			var floatingBoxaddToCartButton;
855			var len;
856			var i;
857			var row;
858			var tempDiv;
859			var j;
860			var spans;
861			var container;
862
863			if ( tm_floating_box_data && tm_floating_box_data.length ) {
864				len = tm_floating_box_data.length;
865				for ( i = 0; i < len; i++ ) {
866					row = tm_floating_box_data[ i ];
867					// Ensure title and value are properly set
868					row.title = row.title ? String( row.title ) : '&nbsp;';
869					row.value = row.value ? String( row.value ) : '&nbsp;';
870
871					// Sanitize title by removing spans
872					if ( row.title !== '&nbsp;' ) {
873						tempDiv = document.createElement( 'div' );
874						tempDiv.innerHTML = row.title;
875						spans = tempDiv.querySelectorAll( 'span' );
876						for ( j = 0; j < spans.length; j++ ) {
877							spans[ j ].remove();
878						}
879						row.title = tempDiv.innerHTML;
880					}
881
882					// Handle "is_nks" logic
883					if ( this.is_nks ) {
884						if ( row.label_show !== '' ) {
885							row.title = '';
886						}
887						if ( row.value_show !== '' ) {
888							row.value = '';
889						}
890					}
891
892					// Auto-hide price if zero
893					if ( TMEPOJS.tm_epo_auto_hide_price_if_zero === 'yes' && $.epoAPI.util.isEmpty( row.price ) === true ) {
894						row.price = '';
895					} else {
896						row.price = tm_set_price( row.price, this.this_epo_totals_container, true );
897					}
898
899					// Push processed data into values_obj
900					values_obj.push( {
901						label_show: row.label_show,
902						value_show: row.value_show,
903						title: row.title,
904						value: row.value,
905						quantity: row.quantity,
906						price: row.price
907					} );
908				}
909			}
910
911			if ( ( ( tm_epo_totals_html && tm_epo_totals_html === '' ) && ( ! tm_floating_box_data || ! tm_floating_box_data.length ) ) || ! ( ( tm_epo_totals_html && tm_epo_totals_html !== '' ) || this.is_nks ) ) {
912				tm_epo_totals_html = '';
913				this.floatingBox.hide();
914			}
915
916			floatingBoxHtml = $.epoAPI.template.html( this.engineTemplate, {
917				html_before: TMEPOJS.floating_totals_box_html_before,
918				html_after: TMEPOJS.floating_totals_box_html_after,
919				option_label: TMEPOJS.i18n_option_label,
920				option_value: TMEPOJS.i18n_option_value,
921				option_qty: TMEPOJS.i18n_option_qty,
922				option_price: TMEPOJS.i18n_option_price,
923				values: values_obj,
924				totals: tm_epo_totals_html
925			} );
926
927			this.floatingBox.html( floatingBoxHtml );
928			this.onUpdateScroll();
929
930			if ( TMEPOJS.tm_epo_no_lazy_load !== 'yes' ) {
931				this.floatingBox.addClass( 'lazyxt' );
932				container = this.floatingBox.find( 'img.tmlazy' );
933				container.lazyLoadXT();
934				container.on( 'lazyshow', function() {
935					jWindow.trigger( 'lazyLoadXToncomplete' );
936				} );
937			}
938
939			if ( TMEPOJS.floating_totals_box_add_button === 'yes' ) {
940				floatingBoxaddToCartButton = this.main_cart.find( tcAPI.addToCartButtonSelector ).first();
941				floatingBoxaddToCartButton
942					.tcClone()
943					.addClass( 'tc-add-to-cart-button' )
944					.on( 'click', function() {
945						floatingBoxaddToCartButton.trigger( 'click' );
946					} )
947					.appendTo( this.floatingBox );
948			}
949		},
950
951		onUpdateScroll: function() {
952			if ( TMEPOJS.floating_totals_box_visibility === 'always' ) {
953				if ( ( this.floatingBox.children().length === 0 || this.floatingBox.text().trim() === '' ) && ! this.is_nks_alt ) {
954					this.floatingBox.hide();
955				} else {
956					this.floatingBox.show();
957				}
958				return;
959			}
960			if ( TMEPOJS.floating_totals_box_visibility === 'hideafterscroll' ) {
961				if ( jWindow.scrollTop() > $.epoAPI.math.toFloat( TMEPOJS.floating_totals_box_pixels ) && ! this.is_nks_alt ) {
962					if ( ! this.floatingBox.is( ':hidden' ) ) {
963						if ( this.is_nks === false ) {
964							this.floatingBox.fadeOut();
965						} else {
966							this.floatingBox.hide();
967						}
968					}
969				} else if ( this.floatingBox.is( ':hidden' ) || this.is_nks_alt ) {
970					if ( ! ( this.floatingBox.children().length === 0 || this.floatingBox.text().trim() === '' ) || this.is_nks_alt ) {
971						if ( this.is_nks === false ) {
972							this.floatingBox.fadeIn();
973						} else {
974							this.floatingBox.show();
975						}
976					}
977				}
978			}
979
980			if ( TMEPOJS.floating_totals_box_visibility === 'afterscroll' ) {
981				if ( jWindow.scrollTop() >
981 $.epoAPI.math.toFloat( TMEPOJS.floating_totals_box_pixels ) || this.is_nks_alt ) {
982					if ( ( this.floatingBox.is( ':hidden' ) && ! ( this.floatingBox.children().length === 0 || this.floatingBox.text().trim() === '' ) ) || this.is_nks_alt ) {
983						if ( this.is_nks === false ) {
984							this.floatingBox.fadeIn();
985						} else {
986							this.floatingBox.show();
987						}
988					} else if ( ! this.floatingBox.is( ':hidden' ) && ( this.floatingBox.children().length === 0 || this.floatingBox.text().trim() === '' ) ) {
989						if ( this.is_nks === false ) {
990							this.floatingBox.fadeOut();
991						} else {
992							this.floatingBox.hide();
993						}
994					}
995				} else if ( ! this.floatingBox.is( ':hidden' ) ) {
996					if ( this.is_nks === false ) {
997						this.floatingBox.fadeOut();
998					} else {
999						this.floatingBox.hide();
1000					}
1001				}
1002			}
1003		},
1004
1005		addEvents: function() {
1006			this.onUpdate();
1007
1008			this.main_cart.on( 'tm-epo-after-update', this.onUpdate.bind( this ) );
1009			this.main_cart.on( 'tm-epo-short-update', this.onUpdate.bind( this ) );
1010
1011			if ( this.is_nks === false ) {
1012				jWindow.on( 'scroll', this.onUpdateScroll.bind( this ) );
1013			}
1014		},
1015
1016		init: function() {
1017			this.floatingBox = $( '<div class="tm-floating-box ' + TMEPOJS.floating_totals_box + '"></div>' );
1018			this.nks_selector = $( '.tm-floating-box-nks' ).first();
1019			this.alt_selector = $( '.tm-floating-box-alt' ).first();
1020			this.engineTemplate = tcAPI.templateEngine.tc_floating_box;
1021			this.is_nks = false;
1022			this.is_nks_alt = false;
1023
1024			if ( this.nks_selector.length > 0 ) {
1025				this.is_nks = true;
1026				this.floatingBox.removeClass( 'top left right bottom' ).appendTo( this.nks_selector ).show();
1027			} else if ( this.alt_selector.length > 0 ) {
1028				this.floatingBox.removeClass( 'top left right bottom' ).appendTo( this.alt_selector ).hide();
1029			} else {
1030				this.floatingBox.appendTo( 'body' ).hide();
1031			}
1032
1033			if ( this.nks_selector.length > 0 || this.alt_selector.length > 0 ) {
1034				this.is_nks_alt = true;
1035				this.engineTemplate = tcAPI.templateEngine.tc_floating_box_nks;
1036			}
1037
1038			this.addEvents();
1039		}
1040	};
1041
1042	$.tcFloatingTotalsBox = function( this_epo_totals_container, is_quickview, main_cart ) {
1043		var data = false;
1044
1045		if ( this_epo_totals_container && this_epo_totals_container.length && this_epo_totals_container.data( 'tcfloatingtotalsbox' ) === undefined ) {
1046			data = new FloatingTotalsBox( this_epo_totals_container, is_quickview, main_cart );
1047			this_epo_totals_container.data( 'tcfloatingtotalsbox', data );
1048		}
1049
1050		return data;
1051	};
1052
1053	$.tc_product_image = {};
1054	$.tc_product_image_store = {};
1055
1056	// replace obj1 values with obj2 values
1057	$.tc_replace_object_values = function( obj1, obj2 ) {
1058		Object.keys( obj1 ).forEach( function( x ) {
1059			Object.keys( obj1[ x ] ).forEach( function( attr ) {
1060				if ( undefined !== obj2[ x ] && undefined !== obj2[ x ][ attr ] && Object.prototype.hasOwnProperty.call( obj2[ x ], attr ) ) {
1061					obj1[ x ][ attr ] = obj2[ x ][ attr ];
1062				}
1063			} );
1064		} );
1065		return obj1;
1066	};
1067	// copy obj2 values to obj1
1068	$.tc_maybe_copy_object_values = function( obj1, obj2 ) {
1069		Object.keys( obj2 ).forEach( function( x ) {
1070			Object.keys( obj2[ x ] ).forEach( function( attr ) {
1071				if ( undefined !== obj2[ x ] && Object.prototype.hasOwnProperty.call( obj2[ x ], attr ) && undefined !== obj2[ x ][ attr ] && ( undefined === obj1[ x ] || undefined === obj1[ x ][ attr ] ) ) {
1072					if ( undefined === obj1[ x ] ) {
1073						obj1[ x ] = {};
1074					}
1075					obj1[ x ][ attr ] = obj2[ x ][ attr ];
1076				}
1077			} );
1078		} );
1079		return obj1;
1080	};
1081
1082	$.tc_pre_populate_store = function() {
1083		var obj = {};
1084
1085		obj[ 0 ] = {};
1086		obj[ 1 ] = {};
1087		obj[ 2 ] = {};
1088		obj[ 3 ] = {};
1089
1090		obj[ 0 ].src = '';
1091		obj[ 0 ].srcset = '';
1092		obj[ 0 ].sizes = '';
1093		obj[ 0 ].title = '';
1094		obj[ 0 ].alt = '';
1095		obj[ 0 ][ 'data-src' ] = '';
1096		obj[ 0 ][ 'data-large_image' ] = '';
1097		obj[ 0 ][ 'data-large_image_width' ] = '';
1098		obj[ 0 ][ 'data-large_image_height' ] = '';
1099		obj[ 1 ][ 'data-thumb' ] = '';
1100		obj[ 2 ].src = '';
1101		obj[ 3 ].href = '';
1102		obj[ 3 ].title = '';
1103
1104		return obj;
1105	};
1106
1107	$.tc_populate_store = function( img, product_element ) {
1108		var $gallery_img = product_element.find( '.flex-control-nav li:eq(0) img' );
1109		var $gallery_wrapper = product_element.find( '.woocommerce-product-gallery__wrapper ' );
1110		var $product_img_wrap = $gallery_wrapper.find( '.woocommerce-product-gallery__image, .woocommerce-product-gallery__image--placeholder' ).eq( 0 );
1111		var $product_img = img;
1112		var $product_link = img.closest( 'a' );
1113		var obj = {};
1114
1115		obj[ 0 ] = {};
1116		obj[ 1 ] = {};
1117		obj[ 2 ] = {};
1118		obj[ 3 ] = {};
1119
1120		obj[ 0 ].src = $product_img.attr( 'src' );
1121		obj[ 0 ].srcset = $product_img.attr( 'srcset' );
1122		obj[ 0 ].sizes = $product_img.attr( 'sizes' );
1123		obj[ 0 ].title = $product_img.attr( 'title' );
1124		obj[ 0 ].alt = $product_img.attr( 'alt' );
1125		obj[ 0 ][ 'data-src' ] = $product_img.attr( 'data-src' );
1126		obj[ 0 ][ 'data-large_image' ] = $product_img.attr( 'data-large_image' );
1127		obj[ 0 ][ 'data-large_image_width' ] = $product_img.attr( 'data-large_image_width' );
1128		obj[ 0 ][ 'data-large_image_height' ] = $product_img.attr( 'data-large_image_height' );
1129		obj[ 1 ][ 'data-thumb' ] = $product_img_wrap.attr( 'data-thumb' );
1130		obj[ 2 ].src = $gallery_img.attr( 'src' );
1131		obj[ 3 ].href = $product_link.attr( 'href' );
1132		obj[ 3 ].title = $product_link.attr( 'title' );
1133
1134		return obj;
1135	};
1136
1137	$.tc_maybe_copy_object_values_from_img = function( obj1, img, product_element ) {
1138		var $gallery_img = product_element.find( '.flex-control-nav li:eq(0) img' );
1139		var $gallery_wrapper = product_element.find( '.woocommerce-product-gallery__wrapper' );
1140		var $product_img_wrap = $gallery_wrapper.find( '.woocommerce-product-gallery__image, .woocommerce-product-gallery__image--placeholder' ).eq( 0 );
1141		var $product_img = img;
1142		var $product_link = img.closest( 'a' );
1143
1144		var all = [ $product_img, $product_img_wrap, $gallery_img, $product_link ];
1145		var attrs_all = [
1146			[ 'src', 'srcset', 'sizes', 'title', 'alt', 'data-src', 'data-large_image', 'data-large_image_width', 'data-large_image_height', 'large-image' ],
1147			[ 'data-thumb' ],
1148			[ 'src' ],
1149			[ 'href', 'title' ]
1150		];
1151		var i;
1152		var item;
1153		var attrs;
1154		var attr;
1155		var j;
1156
1157		for ( i = 0; i < all.length; i++ ) {
1158			item = all[ i ];
1159
1160			if ( item && item[ 0 ] ) {
1161				attrs = item[ 0 ].attributes;
1162
1163				for ( j = 0; j < attrs.length; j++ ) {
1164					attr = attrs[ j ];
1165
1166					if ( attr.specified && attrs_all[ i ].indexOf( attr.name ) !== -1 ) {
1167						if ( obj1[ i ] === undefined || ( obj1[ i ] !== undefined && obj1[ i ][ attr.name ] === undefined ) ) {
1168							if ( undefined === obj1[ i ] ) {
1169								obj1[ i ] = {};
1170							}
1171							obj1[ i ][ attr.name ] = attr.value;
1172						}
1173					}
1174				}
1175			}
1176		}
1177
1178		return obj1;
1179	};
1180
1181	// Stores a default attribute for an element so it can be reset later
1182	$.fn.tc_set_attr = function( attr, value, id ) {
1183		if ( undefined === id ) {
1184			id = 0;
1185		}
1186		if ( undefined === $.tc_product_image[ id ] || ( undefined !== $.tc_product_image[ id ] && undefined === $.tc_product_image[ id ][ attr ] ) ) {
1187			if ( undefined === $.tc_product_image[ id ] ) {
1188				$.tc_product_image[ id ] = {};
1189			}
1190			$.tc_product_image[ id ][ attr ] = '';
1191			if ( this.attr( attr ) ) {
1192				$.tc_product_image[ id ][ attr ] = this.attr( attr );
1193			}
1194		}
1195		if ( false === value ) {
1196			this.removeAttr( attr );
1197		} else {
1198			this.attr( attr, value );
1199		}
1200	};
1201
1202	// Reset a default attribute for an element so it can be reset later
1203	$.fn.tc_reset_attr = function( attr, id ) {
1204		if ( undefined === id ) {
1205			id = 0;
1206		}
1207		if ( undefined === $.tc_product_image[ id ] ) {
1208			return;
1209		}
1210		if ( undefined !== $.tc_product_image[ id ][ attr ] ) {
1211			this.attr( attr, $.tc_product_image[ id ][ attr ] );
1212		}
1213		delete $.tc_product_image[ id ][ attr ];
1214	};
1215
1216	$.fn.tc_update_attr = function( attr, id ) {
1217		if ( undefined === id ) {
1218			id = 0;
1219		}
1220		if ( undefined !== $.tc_product_image[ id ] ) {
1221			$.tc_product_image[ id ][ attr ] = this.attr( attr );
1222		}
1223	};
1224
1225	$.fn.tc_image_update = function( dom, image ) {
1226		var element = $( dom );
1227		var $form = this;
1228		var $image = $( image );
1229		var epo_object = $form.data( 'epo_object' );
1230		var image_info;
1231		var $product_img;
1232		var product_element = epo_object.main_product.closest( '#product-' + epo_object.product_id );
1233		var $product_element = product_element;
1234		var $product_img_thumb;
1235		var $product_link;
1236		var use_image_info;
1237
1238		if ( product_element.length <= 0 ) {
1239			$product_element = epo_object.main_product.closest( '.post-' + epo_object.product_id );
1240		}
1241
1242		$product_img_thumb = $product_element.find( '.flex-control-nav li:eq(0) img' );
1243
1244		if ( element.is( 'select' ) ) {
1245			element = element.children( 'option:selected' );
1246		}
1247		image_info = element.data( 'image-variations' );
1248
1249		if ( TMEPOJS.tm_epo_global_product_image_selector !== '' ) {
1250			$product_img = $( TMEPOJS.tm_epo_global_product_image_selector );
1251		} else {
1252			$product_img = $product_element.find( 'a.woocommerce-main-image img, img.woocommerce-main-image,a img' ).not( '.thumbnails img,.product_list_widget img,img.emoji,a.woocommerce-product-gallery__trigger img' ).first();
1253		}
1254		$product_link = $product_img.closest( 'a' );
1255
1256		if ( $product_img.length > 1 ) {
1257			$product_img = $product_img.first();
1258		}
1259
1260		if ( element && image_info && $image.length > 0 ) {
1261			$image.removeAttr( 'data-o_src' ).removeAttr( 'data-o_title' ).removeAttr( 'data-o_alt' ).removeAttr( 'data-o_srcset' ).removeAttr( 'data-o_sizes' ).removeAttr( 'srcset' ).removeAttr( 'sizes' );
1262
1263			use_image_info = image_info.imagep;
1264			if ( ! image_info.imagep.image_link ) {
1265				use_image_info = image_info.image;
1266			}
1267
1268			$image.attr( 'title', use_image_info.image_title );
1269			$image.attr( 'alt', use_image_info.image_alt );
1270			if ( use_image_info.image_srcset ) {
1271				$image.attr( 'srcset', use_image_info.image_srcset );
1272			}
1273			if ( use_image_info.image_sizes ) {
1274				$image.attr( 'sizes', use_image_info.image_sizes );
1275			}
1276
1277			$product_img.tc_set_attr( 'title', use_image_info.image_title );
1278			$product_img.tc_set_attr( 'alt', use_image_info.image_alt );
1279
1280			$product_img.tc_set_attr( 'data-large-image', use_image_info.image_link );
1281			if ( $product_img.data.wc27_zoom_target ) {
1282				$product_img.data.wc27_zoom_target.tc_set_attr( 'data-thumb', use_image_info.image_link );
1283				$product_img_thumb.tc_set_attr( 'src', use_image_info.image_link );
1284				if ( use_image_info.image_srcset ) {
1285					$product_img_thumb.tc_set_attr( 'srcset', use_image_info.image_srcset );
1286				}
1287				if ( use_image_info.image_sizes ) {
1288					$product_img_thumb.tc_set_attr( 'sizes', use_image_info.image_sizes );
1289				}
1290			}
1291
1292			$product_link.tc_set_attr( 'href', use_image_info.image_link );
1293			$product_link.tc_set_attr( 'title', use_image_info.image_caption );
1294		} else {
1295			$product_img.tc_reset_attr( 'title' );
1296			$product_img.tc_reset_attr( 'alt' );
1297
1298			$product_img.tc_reset_attr( 'data-large-image' );
1299			if ( $product_img.data.wc27_zoom_target ) {
1300				$product_img.data.wc27_zoom_target.tc_reset_attr( 'data-thumb' );
1301				$product_img_thumb.tc_reset_attr( 'src' );
1302				$product_img_thumb.tc_reset_attr( 'srcset' );
1303				$product_img_thumb.tc_reset_attr( 'sizes' );
1304			}
1305
1306			$product_link.tc_reset_attr( 'href' );
1307			$product_link.tc_reset_attr( 'title' );
1308		}
1309	};
1310
1311	// variations checker
1312	$.fn.tm_find_matching_variations = function( product_variations, settings ) {
1313		var matching = [];
1314		var i;
1315		var variation;
1316
1317		if ( product_variations ) {
1318			for ( i = 0; i < product_variations.length; i += 1 ) {
1319				variation = product_variations[ i ];
1320
1321				if ( $.fn.tm_variations_match( variation.attributes, settings ) ) {
1322					matching.push( variation );
1323				}
1324			}
1325		}
1326
1327		return matching;
1328	};
1329
1330	$.fn.tm_variations_match = function( attrs1, attrs2 ) {
1331		var match = true;
1332		var val1;
1333		var val2;
1334
1335		Object.keys( attrs1 ).forEach( function( x ) {
1336			if ( Object.prototype.hasOwnProperty.call( attrs1, x ) ) {
1337				val1 = attrs1[ x ];
1338				val2 = attrs2[ x ];
1339
1340				if ( val1 !== undefined && val2 !== undefined && val1.length !== 0 && val2.length !== 0 && val1 !== val2 ) {
1341					match = false;
1342				}
1343			}
1344		} );
1345
1346		return match;
1347	};
1348
1349	function get_element_from_field( element, ckey ) {
1350		var $element = $( element );
1351		var data_uniqid;
1352		var the_epo_id;
1353		var _class;
1354		var epoContainer;
1355
1356		if ( $element.length === 0 ) {
1357			return;
1358		}
1359
1360		if ( $element.is( '.cpf-section' ) ) {
1361			return element.find( '.tm-epo-field' );
1362		}
1363		data_uniqid = $element.attr( 'data-uniqid' );
1364		epoContainer = $element.closest( tcAPI.epoSelector );
1365		the_epo_id = epoContainer.attr( 'data-epo-id' );
1366
1367		if ( ! epoContainer.is( '.reactivate' ) && tcAPI.getElementFromFieldCache && tcAPI.getElementFromFieldCache[ the_epo_id ] && tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ] && tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ][ ckey ] ) {
1368			return tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ][ ckey ];
1369		}
1370		_class = $element
1371			.attr( 'class' )
1372			.split( ' ' )
1373			.map( function( cls ) {
1374				if ( cls.indexOf( 'cpf-type-', 0 ) !== -1 ) {
1375					return cls;
1376				}
1377				return null;
1378			} )
1379			.filter( function( v ) {
1380				if ( v !== null && v !== undefined ) {
1381					return v;
1382				}
1383				return null;
1384			} );
1385
1386		if ( _class.length > 0 ) {
1387			_class = _class[ 0 ];
1388			if ( _class === 'cpf-type-product' ) {
1389				if ( $element.is( '.cpf-type-product-mode-product' ) || $element.is( '.cpf-type-product-checkbox' ) || $element.is( '.cpf-type-product-thumbnailmultiple' ) || $element.is( '.cpf-type-product-custombundle' ) ) {
1390					_class = 'cpf-type-checkbox';
1391				} else if ( $element.is( '.cpf-type-product-dropdown' ) ) {
1392					_class = 'cpf-type-select';
1393				} else {
1394					_class = 'cpf-type-radio';
1395				}
1396			}
1397			if ( tcAPI.getElementFromFieldCache[ the_epo_id ] === undefined ) {
1398				tcAPI.getElementFromFieldCache[ the_epo_id ] = [];
1399			}
1400			if ( tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ] === undefined ) {
1401				tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ] = [];
1402			}
1403			switch ( _class ) {
1404				case 'cpf-type-radio':
1405					tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ][ ckey ] = $element.find( '.tm-epo-field.tmcp-radio' );
1406					return tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ][ ckey ];
1407
1408				case 'cpf-type-checkbox':
1409					tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ][ ckey ] = $element.find( '.tm-epo-field.tmcp-checkbox' );
1410					return tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ][ ckey ];
1411
1412				case 'cpf-type-select':
1413					tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ][ ckey ] = $element.find( '.tm-epo-field.tmcp-select' );
1414					return tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ][ ckey ];
1415
1416				case 'cpf-type-selectmultiple':
1417					tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ][ ckey ] = $element.find( '.tm-epo-field.tmcp-selectmultiple' );
1418					return tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ][ ckey ];
1419
1420				case 'cpf-type-textarea':
1421					tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ][ ckey ] = $element.find( '.tm-epo-field.tmcp-textarea' );
1422					return tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ][ ckey ];
1423
1424				case 'cpf-type-textfield':
1425					tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ][ ckey ] = $element.find( '.tm-epo-field.tmcp-textfield' );
1426					return tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ][ ckey ];
1427
1428				case 'cpf-type-color':
1429					tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ][ ckey ] = $element.find( '.tm-epo-field.tm-color-picker' );
1430					return tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ][ ckey ];
1431
1432				case 'cpf-type-range':
1433					tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ][ ckey ] = $element.find( '.tm-epo-field.tmcp-range' );
1434					return tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ][ ckey ];
1435
1436				case 'cpf-type-date':
1437					tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ][ ckey ] = $element.find( '.tm-epo-field.tmcp-date' );
1438					return tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ][ ckey ];
1439
1440				case 'cpf-type-time':
1441					tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ][ ckey ] = $element.find( '.tm-epo-field.tmcp-time' );
1442					return tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ][ ckey ];
1443
1444				case 'cpf-type-variations':
1445					tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ][ ckey ] = $element.closest( '.cpf-section' ).find( '.tm-epo-field.tm-epo-variation-element' );
1446					return tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ][ ckey ];
1447			}
1448		}
1449	}
1450
1451	// tc-lightbox
1452	if ( ! $().tclightbox ) {
1453		$.fn.tclightbox = function() {
1454			var elements = this;
1455
1456			if ( elements.length === 0 ) {
1457				return;
1458			}
1459
1460			return elements.toArray().forEach( function( lb ) {
1461				var $this = $( lb );
1462				var _imgsrc;
1463				var _label;
1464				var _input;
1465				var tclightboxwrap;
1466				var _img_button;
1467				var preload_img;
1468				var addButtonEvent;
1469
1470				if ( $this.is( '.tcinit' ) ) {
1471					return;
1472				}
1473				_imgsrc = $this.attr( 'src' ) || $this.attr( 'data-original' );
1474				_label = $this.closest( 'label' );
1475				_input = _label.closest( '.tmcp-field-wrap' ).find( ".tm-epo-field[id='" + _label.attr( 'for' ) + "']" );
1476				_imgsrc = $this.attr( 'data-large_image' ) || _input.attr( 'data-imagel' ) || _input.attr( 'data-imagep' ) || _input.attr( 'data-image' ) || _imgsrc;
1477
1478				if ( ! _imgsrc ) {
1479					return;
1480				}
1481
1482				$this.addClass( 'tcinit' ).before( $.epoAPI.template.html( tcAPI.templateEngine.tc_lightbox, {} ) );
1483				tclightboxwrap = $this.prev();
1484
1485				$this.wrap( "<div class='tc-lightbox-image-wrap'/>" );
1486				$this.after( tclightboxwrap );
1487
1488				_img_button = tclightboxwrap.find( '.tc-lightbox-button' );
1489
1490				addButtonEvent = function() {
1491					_img_button.addClass( 'tcinit' ).on( 'click.tclightbox', function( buttonevent ) {
1492						var size;
1493						var _img;
1494
1495						if ( $( '.tc-closing.tc-lightbox' ).length > 0 ) {
1496							return;
1497						}
1498
1499						size = $.epoAPI.dom.size();
1500						_img = $( '<img>' )
1501							.addClass( 'tc-lightbox-img' )
1502							.attr( 'src', _imgsrc )
1503							.css( 'maxHeight', size.visibleHeight + 'px' )
1504							.css( 'maxWidth', size.visibleWidth + 'px' );
1505
1506						$.tcFloatBox( {
1507							fps: 1,
1508							ismodal: false,
1509							width: 'auto',
1510							height: 'auto',
1511							classname: 'flasho tc-lightbox',
1512							animateIn: 'tc-lightbox-zoomin',
1513							animateOut: 'tc-lightbox-zoomout',
1514							data: $.epoAPI.template.html( tcAPI.templateEngine.tc_lightbox_zoom, { img: _img[ 0 ].outerHTML } ),
1515							zIndex: 102001,
1516							cancelClass: '.tc-lightbox-img, .tc-lightbox-button-close',
1517							unique: true
1518						} );
1519
1520						buttonevent.preventDefault();
1521					} );
1522				};
1523				if ( TMEPOJS.tm_epo_preload_lightbox_image === 'yes' ) {
1524					preload_img = new Image();
1525					preload_img.src = _imgsrc;
1526					preload_img.onload = function() {
1527						addButtonEvent();
1528					};
1529				} else {
1530					addButtonEvent();
1531				}
1532			} );
1533		};
1534	}
1535
1536	// Start Section popup
1537	if ( ! $().tmsectionpoplink ) {
1538		$.fn.tmsectionpoplink = function() {
1539			var elements = this;
1540
1541			if ( elements.length === 0 ) {
1542				return;
1543			}
1544
1545			return elements.toArray().forEach( function( pl ) {
1546				var $this = $( pl );
1547				var id;
1548				var title;
1549				var section;
1550				var clicked;
1551				var cancelfunc;
1552				var cancelpop;
1553
1554				if ( $this.data( 'tmsectionpoplink' ) ) {
1555					return;
1556				}
1557
1558				$this.data( 'tmsectionpoplink', true );
1559				id = $this.attr( 'data-sectionid' );
1560				title = TMEPOJS.i18n_addition_options;
1561				section = $this.closest( ".cpf-section[data-uniqid='" + id + "']" );
1562				clicked = false;
1563				cancelfunc = function() {
1564					var pop = $( '#tm-section-pop-up' );
1565					pop.parents().removeClass( 'noanimated' );
1566
1567					pop.after( section );
1568					pop.remove();
1569
1570					section.find( '.tm-section-link' ).show();
1571					section.find( '.tm-section-pop' ).hide();
1572				};
1573				cancelpop = function( e ) {
1574					if ( e.target === $( '.flasho' )[ 0 ] || $( e.target ).closest( '.flasho' ).length ) {
1575						return;
1576					}
1577
1578					cancelfunc();
1579				};
1580
1581				if ( $this.attr( 'data-title' ) ) {
1582					title = $this.attr( 'data-title' );
1583				}
1584
1585				$this.on( 'click.tmsectionpoplink', function( e ) {
1586					var pop;
1587
1588					e.preventDefault();
1589					clicked = false;
1590
1591					section.before(
1592						$.epoAPI.template.html( tcAPI.templateEngine.tc_section_pop_link, {
1593							title: title,
1594							close: TMEPOJS.i18n_close
1595						} )
1596					);
1597
1598					pop = $( '#tm-section-pop-up' );
1599
1600					pop.on( 'click', cancelpop );
1601
1602					pop.find( '.float-editbox' ).prepend( section );
1603
1604					section.find( '.tm-section-link' ).hide();
1605					section.find( '.tm-section-pop' ).show();
1606
1607					pop.parents().addClass( 'noanimated' );
1608
1609					pop.find( '.floatbox-cancel' ).on( 'click', function() {
1610						if ( clicked ) {
1611							return;
1612						}
1613						clicked = true;
1614						cancelfunc();
1615					} );
1616					jWindow.trigger( 'tmlazy' );
1617					jWindow.trigger( 'tmsectionpoplink' );
1618				} );
1619			} );
1620		};
1621	} // End Section popup
1622
1623	function getVariationIdSelector( currentCart ) {
1624		var variationIdSelector = "input[name^='variation_id']";
1625
1626		if ( currentCart.find( 'input.variation_id' ).length > 0 ) {
1627			variationIdSelector = 'input.variation_id';
1628		} else {
1629			variationIdSelector = 'input.product-variation-id';
1630		}
1631
1632		return variationIdSelector;
1633	}
1634
1635	function getVariationIdElement( currentCart, not ) {
1636		var variationIdSelector = getVariationIdSelector( currentCart );
1637		var variationIdElement = currentCart.find( variationIdSelector );
1638
1639		if ( currentCart.is( '.tc-epo-element-product-container-cart' ) ) {
1640			variationIdElement = currentCart.closest( '.tc-epo-element-product-li-container' ).find( variationIdSelector );
1641		} else {
1642			variationIdElement = currentCart.find( variationIdSelector ).not( '.tc-epo-element-product-container-variation-id ' + variationIdSelector );
1643		}
1644		if ( not ) {
1645			variationIdElement = variationIdElement.not( not );
1646		}
1647
1648		return variationIdElement;
1649	}
1650
1651	function getCurrentVariation( currentCart ) {
1652		var field_div;
1653		var newCart;
1654
1655		if ( currentCart.is( '.tc-epo-element-product-container-cart' ) ) {
1656			field_div = currentCart.closest( '.cpf-element' );
1657			if ( field_div.is( '.cpf-type-product-thumbnailmultiple' ) || field_div.is( '.cpf-type-product-checkbox' ) || field_div.is( '.cpf-type-product-custombundle' ) ) {
1658				newCart = currentCart.closest( '.tc-epo-element-product-holder' ).find( '.tc-epo-element-product-container-variation-id' );
1659			} else if ( field_div.is( '.cpf-type-product-thumbnail' ) || field_div.is( '.cpf-type-product-radio' ) || field_div.is( '.cpf-type-product-dropdown' ) || field_div.is( '.cpf-type-product-single' ) ) {
1660				newCart = field_div.find( '.tc-epo-element-product-container-variation-id' );
1661			}
1662			if ( newCart && newCart.length ) {
1663				currentCart = newCart;
1664			}
1665		}
1666		return currentCart.find( getVariationIdSelector( currentCart ) ).val() || 0;
1667	}
1668
1669	function getQtyElement( currentCart ) {
1670		var qty = currentCart.find( tcAPI.qtySelector ).last();
1671		if ( qty.length === 0 ) {
1672			qty = currentCart.find( tcAPI.associateQtySelector ).last();
1673		}
1674		qty = $.epoAPI.applyFilter( 'tc_getQtyElement', qty, currentCart );
1675		return qty;
1676	}
1677
1678	function getCurrentQty( currentCart ) {
1679		return $.epoAPI.applyFilter( 'tc_getCurrentQty', $.epoAPI.math.toFloat( getQtyElement( currentCart ).val() ), currentCart );
1680	}
1681
1682	function add_variation_event( name, selector, func ) {
1683		lateVariationEvent[ lateVariationEvent.length ] = {
1684			name: name,
1685			selector: selector,
1686			func: func
1687		};
1688	}
1689
1690	function field_is_active( field, nochecks, single, simpleCheck ) {
1691		var ret = true;
1692		var insideProductCheck = false;
1693		var productElement;
1694		field = $( field );
1695		productElement = field.filter( '.tc-epo-field-product' );
1696		if ( productElement.length && productElement.data( 'islogicinit' ) === undefined ) {
1697			insideProductCheck = true;
1698		}
1699		field.toArray().forEach( function( element ) {
1700			if ( ! ret && field.has( '.tc-epo-field-product' ).length ) {
1701				if ( insideProductCheck || productElement.is( '.tcdisabled' ) ) {
1702					if ( simpleCheck ) {
1703						field_check_active_simple( element );
1704					} else {
1705						field_check_active( element, nochecks, single, simpleCheck );
1706					}
1707				}
1708			} else if ( simpleCheck ) {
1709				ret = field_check_active_simple( element );
1710			} else {
1711				ret = field_check_active( element, nochecks, single, simpleCheck ) && ret;
1712			}
1713		} );
1714
1715		return ret;
1716	}
1717
1718	function field_check_active_simple( field ) {
1719		var hideElement;
1720		var isInsideProductElement;
1721		var productElementActive;
1722		var productElementSectionActive;
1723		var section;
1724
1725		field = $( field );
1726		if ( field.is( '.cpf-element' ) ) {
1727			hideElement = field;
1728			field = field.find( '.tmcp-field, .tmcp-fee-field' );
1729		} else {
1730			hideElement = field.closest( '.cpf-element' );
1731		}
1732
1733		section = hideElement.closest( '.cpf-section' );
1734
1735		isInsideProductElement = ! field.is( '.tc-epo-field-product' ) && hideElement.closest( '.cpf-type-product' );
1736
1737		if ( isInsideProductElement.length ) {
1738			productElementActive = isInsideProductElement.data( 'isactive' );
1739			isInsideProductElement = isInsideProductElement.closest( '.cpf-section' );
1740			productElementSectionActive = isInsideProductElement.data( 'isactive' );
1741		}
1742		if ( productElementActive !== false && productElementSectionActive !== false && hideElement.data( 'isactive' ) !== false && section.data( 'isactive' ) !== false ) {
1743			return true;
1744		}
1745
1746		return false;
1747	}
1748
1749	function field_check_active( field, nochecks, single ) {
1750		var hideElement;
1751		var singleField;
1752		var ul;
1753		var isInsideProductElement;
1754		var productElementActive;
1755		var productElementSectionActive;
1756		var productElementQty;
1757		var section;
1758		var disableElements;
1759		var sectionLi;
1760		var allSectionsDisabled;
1761		var tabSlide;
1762		var epoFields;
1763
1764		field = $( field );
1765		if ( field.is( '.cpf-element' ) ) {
1766			hideElement = field;
1767			field = field.find( '.tmcp-field, .tmcp-fee-field' );
1768		} else {
1769			hideElement = field.closest( '.cpf-element' );
1770		}
1771
1772		section = hideElement.closest( '.cpf-section' );
1773		sectionLi = section.closest( '.tm-extra-product-options-field' );
1774
1775		if ( single ) {
1776			ul = field.closest( '.tmcp-ul-wrap' );
1777		} else {
1778			ul = hideElement;
1779		}
1780
1781		if ( field.is( '.tc-epo-field-product' ) && field.data( 'islogicinit' ) === undefined ) {
1782			field.data( 'islogicinit', 1 );
1783		}
1784
1785		if ( ! field.is( '.tc-force-disabled' ) ) {
1786			isInsideProductElement = ! field.is( '.tc-epo-field-product' ) && hideElement.closest( '.cpf-type-product' );
1787
1788			if ( isInsideProductElement.length ) {
1789				productElementQty = isInsideProductElement.find( tcAPI.associateQtySelector );
1790				if ( productElementQty.length ) {
1791					if ( $.epoAPI.math.toFloat( productElementQty.val() ) > 0 ) {
1792						field.removeClass( 'ignore' );
1793						productElementQty.removeClass( 'ignore' );
1794					} else {
1795						field.addClass( 'ignore' );
1796						productElementQty.addClass( 'ignore' );
1797					}
1798				}
1799				productElementActive = isInsideProductElement.data( 'isactive' );
1800				isInsideProductElement = isInsideProductElement.closest( '.cpf-section' );
1801				productElementSectionActive = isInsideProductElement.data( 'isactive' );
1802			}
1803			if ( productElementActive !== false && productElementSectionActive !== false && hideElement.data( 'isactive' ) !== false && section.data( 'isactive' ) !== false ) {
1804				singleField = field.first();
1805				field.prop( 'disabled', false );
1806				if ( field.data( 'tc-state' ) !== undefined ) {
1807					field.data( 'tc-state', false );
1808				}
1809
1810				if ( TMEPOJS.tm_epo_show_only_active_quantities !== 'yes' ) {
1811					if ( singleField.is( ':radio, .cpf-type-radio' ) || singleField.is( ':checkbox, .cpf-type-checkbox' ) ) {
1812						field.filter( ':checked' ).closest( '.tmcp-field-wrap' ).find( '.tm-qty, .tc-qty-button' ).prop( 'disabled', false );
1813						field.not( ':checked' ).closest( '.tmcp-field-wrap' ).find( '.tm-qty, .tc-qty-button' ).prop( 'disabled', true );
1814					} else if ( singleField.is( 'select, .cpf-type-select, .cpf-type-selectmultiple' ) ) {
1815						if ( singleField.val() ) {
1816							ul.find( '.tm-qty, .tc-qty-button' ).prop( 'disabled', false );
1817						} else {
1818							ul.find( '.tm-qty, .tc-qty-button' ).prop( 'disabled', true );
1819						}
1820					} else if ( singleField.val() ) {
1821						ul.find( '.tm-qty, .tc-qty-button' ).prop( 'disabled', false );
1822					} else {
1823						ul.find( '.tm-qty, .tc-qty-button' ).prop( 'disabled', true );
1824					}
1825				} else if ( ! nochecks ) {
1826					hideElement.find( '.tm-quantity' ).trigger( 'showhide.cpfcustom' );
1827				}
1828
1829				if ( ! singleField.is( '.cpf-element' ) ) {
1830					field.removeClass( 'tcdisabled' ).addClass( 'tcenabled' );
1831
1832					if ( field.is( '.tmcp-upload' ) ) {
1833						if ( field.next( '.tmcp-upload-hidden' ).length ) {
1834							field.next( '.tmcp-upload-hidden' ).removeClass( 'tcdisabled' ).addClass( 'tcenabled' ).prop( 'disabled', false );
1835						}
1836					}
1837				}
1838
1839				hideElement.removeClass( 'tc-container-disabled' ).addClass( 'tc-container-enabled' );
1840				hideElement.find( '.product-variation-id, .tc-epo-field-product-counter' ).prop( 'disabled', false );
1841
1842				field.trigger( {
1843					type: 'tm-field-is-active',
1844					field: field,
1845					value: true
1846				} );
1847				section.removeClass( 'section-disabled' );
1848				sectionLi.removeClass( 'tc-hidden' );
1849
1850				hideElement.closest( '.owl-item' ).removeClass( 'tc-hidden-visibility' );
1851
1852				return true;
1853			}
1854		}
1855
1856		if ( ! field.is( '.cpf-element' ) ) {
1857			field.prop( 'disabled', true ).removeClass( 'tcenabled' ).addClass( 'tcdisabled' );
1858			if ( field.data( 'tc-state' ) !== undefined ) {
1859				field.data( 'tc-state', true );
1860			}
1861			hideElement.find( '.tm-qty, .tc-qty-button' ).prop( 'disabled', true );
1862			if ( field.is( '.tmcp-upload' ) ) {
1863				if ( field.next( '.tmcp-upload-hidden' ).length ) {
1864					field.next( '.tmcp-upload-hidden' ).removeClass( 'tcenabled' ).addClass( 'tcdisabled' ).prop( 'disabled', true );
1865				}
1866			}
1867		}
1868
1869		if ( field.is( '.tc-force-disabled' ) ) {
1870			epoFields = hideElement.find( '.tmcp-field, .tmcp-fee-field' );
1871			if ( epoFields.length !== epoFields.filter( '.tc-force-disabled' ).length ) {
1872				return false;
1873			}
1874		}
1875
1876		hideElement.removeClass( 'tc-container-enabled' ).addClass( 'tc-container-disabled' );
1877		hideElement.find( '.product-variation-id, .tc-epo-field-product-counter' ).prop( 'disabled', true );
1878
1879		field.trigger( {
1880			type: 'tm-field-is-active',
1881			field: field,
1882			value: false
1883		} );
1884
1885		disableElements = section.find( '.cpf-element.tc-container-enabled' ).length === 0;
1886		if ( disableElements ) {
1887			section.addClass( 'section-disabled' );
1888			allSectionsDisabled = sectionLi.children( '.cpf-section' ).filter( function() {
1889				return ! $( this ).hasClass( 'section-disabled' );
1890			} ).length === 0;
1891			if ( allSectionsDisabled ) {
1892				sectionLi.addClass( 'tc-hidden' );
1893			}
1894		}
1895
1896		tabSlide = hideElement.closest( '.tc-tab-slide' ).find( '.cpf-element.tc-container-enabled' ).length === 0;
1897		if ( tabSlide ) {
1898			hideElement.closest( '.owl-item' ).addClass( 'tc-hidden-visibility' );
1899		}
1900
1901		return false;
1902	}
1903
1904	function tm_variation_check_match( element, val2, operator ) {
1905		var $element = $( element );
1906		var epoId = $element.attr( 'data-epo_id' ) || $element.attr( 'data-epo-id' );
1907		var productId = $element.attr( 'data-product_id' ) || $element.attr( 'data-product-id' );
1908
1909		var variationsForm = $( '.variations_form[data-epo_id="' + epoId + '"][data-product_id="' + productId + '"]' );
1910		var val1;
1911		var variationIdSelector = 'input[name^="variation_id"]';
1912		var $variationId;
1913
1914		variationsForm = $.epoAPI.applyFilter( 'tm_variation_check_match_variationsForm', variationsForm, epoId, productId, $element );
1915		if ( $element.attr( 'data-product_type' ) === 'variation' ) {
1916			variationsForm = $element;
1917			$variationId = productId;
1918		}
1919		if ( variationsForm.length === 0 && $element.is( '.cpf-type-variations' ) && ! epoId && ! productId ) {
1920			variationsForm = $element.closest( '.tc-epo-element-product-container' );
1921			if ( variationsForm.length ) {
1922				productId = variationsForm.attr( 'data-product_id' );
1923				$variationId = productId;
1924			}
1925		}
1926
1927		if ( variationsForm.length === 0 ) {
1928			return false;
1929		}
1930
1931		if ( ! $variationId ) {
1932			$variationId = variationsForm.find( variationIdSelector );
1933
1934			if ( $variationId.length === 0 ) {
1935				variationIdSelector = 'input.variation_id';
1936
1937				$variationId = variationsForm.find( variationIdSelector );
1938
1939				if ( $variationId.length === 0 ) {
1940					$variationId = variationsForm.closest( '.tc-epo-element-product-li-container' ).find( '.product-variation-id' );
1941				}
1942			}
1943			if ( $variationId.length ) {
1944				$variationId = $variationId.val();
1945			} else {
1946				$variationId = 0;
1947			}
1948		}
1949
1950		if ( element !== null && val2 !== null && element !== undefined && val2 !== undefined && element !== false && val2 !== false ) {
1951			if ( val2 ) {
1952				val2 = parseInt( val2, 10 );
1953			} else {
1954				val2 = -1;
1955			}
1956		}
1957
1958		val1 = parseInt( $variationId, 10 );
1959
1960		if ( ! Number.isFinite( val1 ) ) {
1961			val1 = 0;
1962		}
1963		if ( ! Number.isFinite( val2 ) ) {
1964			val2 = 0;
1965		}
1966
1967		switch ( operator ) {
1968			case 'is':
1969				return val1 !== '' && val1 === val2;
1970
1971			case 'isnot':
1972				return val1 !== '' && val1 !== val2;
1973
1974			case 'isempty':
1975				return val1 === '' || val1 === 0;
1976
1977			case 'isnotempty':
1978				return val1 !== '' && val1 !== 0;
1979
1980			case 'startswith':
1981				return val1.toString().startsWith( val2 );
1982
1983			case 'endswith':
1984				return val1.toString().endsWith( val2 );
1985
1986			case 'greaterthan':
1987				return parseFloat( val1 ) > parseFloat( val2 );
1988
1989			case 'lessthan':
1990				return parseFloat( val1 ) < parseFloat( val2 );
1991
1992			case 'greaterthanequal':
1993				return parseFloat( val1 ) >= parseFloat( val2 );
1994
1995			case 'lessthanequal':
1996				return parseFloat( val1 ) <= parseFloat( val2 );
1997		}
1998		return false;
1999	}
2000
2001	function tm_variationattributes_check_match( element, rule ) {
2002		var $element = $( element );
2003		var val2 = rule.value;
2004		var operator = rule.operator;
2005		var epoId = $element.attr( 'data-epo_id' ) || $element.attr( 'data-epo-id' );
2006		var productId = $element.attr( 'data-product_id' ) || $element.attr( 'data-product-id' );
2007
2008		var variationsForm = $( '.variations_form[data-epo_id="' + epoId + '"][data-product_id="' + productId + '"]' );
2009		var val1;
2010		var $att;
2011
2012		variationsForm = $.epoAPI.applyFilter( 'tm_variation_check_match_variationsForm', variationsForm, epoId, productId, $element );
2013		if ( $element.attr( 'data-product_type' ) === 'variation' ) {
2014			variationsForm = $element;
2015		}
2016		if ( variationsForm.length === 0 && $element.is( '.cpf-type-variations' ) && ! epoId && ! productId ) {
2017			variationsForm = $element.closest( '.tc-epo-element-product-container' );
2018			if ( variationsForm.length ) {
2019				productId = variationsForm.attr( 'data-product_id' );
2020			}
2021		}
2022
2023		if ( variationsForm.length === 0 ) {
2024			return false;
2025		}
2026
2027		$att = variationsForm.find( '[name="attribute_' + rule.taxonomy + '"]' );
2028
2029		if ( ! $att.length ) {
2030			return false;
2031		}
2032
2033		val1 = $att.find( 'option:selected' ).attr( 'value' );
2034
2035		switch ( operator ) {
2036			case 'is':
2037				return val1 !== '' && val1 === val2;
2038
2039			case 'isnot':
2040				return val1 !== '' && val1 !== val2;
2041
2042			case 'isempty':
2043				return val1 === '' || val1 === 0;
2044
2045			case 'isnotempty':
2046				return val1 !== '' && val1 !== 0;
2047
2048			case 'startswith':
2049				return val1.toString().startsWith( val2 );
2050
2051			case 'endswith':
2052				return val1.toString().endsWith( val2 );
2053		}
2054		return false;
2055	}
2056
2057	function tm_check_match( val1, val2, operator ) {
2058		if ( val1 !== null && val2 !== null ) {
2059			val1 = encodeURIComponent( val1 );
2060			if ( $.qtranxj_split ) {
2061				//backwards compatible
2062				val2 = encodeURIComponent( $.qtranxj_split( decodeURIComponent( val2 ) )[ TMEPOQTRANSLATEXJS.language ] );
2063			} else {
2064				//backwards compatible
2065				val2 = encodeURIComponent( decodeURIComponent( val2 ) );
2066			}
2067
2068			if ( val1 ) {
2069				val1 = val1.toLowerCase();
2070			} else {
2071				val1 = '';
2072			}
2073			if ( val2 ) {
2074				val2 = val2.toLowerCase();
2075			} else {
2076				val2 = '';
2077			}
2078		} else {
2079			return false;
2080		}
2081
2082		val1 = val1.toString();
2083		val2 = val2.toString();
2084
2085		switch ( operator ) {
2086			case 'is':
2087				return val1 !== null && val1 === val2;
2088
2089			case 'isnot':
2090				return val1 !== null && val1 !== val2;
2091
2092			case 'isempty':
2093				return ! ( val1 !== 'undefined' && val1 !== undefined && val1 !== '' );
2094
2095			case 'isnotempty':
2096				return val1 !== 'undefined' && val1 !== undefined && val1 !== '';
2097
2098			case 'startswith':
2099				return val1.startsWith( val2 );
2100
2101			case 'endswith':
2102				return val1.endsWith( val2 );
2103
2104			case 'greaterthan':
2105				return parseFloat( val1 ) > parseFloat( val2 );
2106
2107			case 'lessthan':
2108				return parseFloat( val1 ) < parseFloat( val2 );
2109
2110			case 'greaterthanequal':
2111				return parseFloat( val1 ) >= parseFloat( val2 );
2112
2113			case 'lessthanequal':
2114				return parseFloat( val1 ) <= parseFloat( val2 );
2115		}
2116
2117		return false;
2118	}
2119
2120	function tm_check_section_match( elements, operator ) {
2121		var any_checked;
2122		var val;
2123		var all_elements = elements.find( '.cpf-element' );
2124		var radio_checked;
2125		var checkbox_checked;
2126		var noSplit = false;
2127
2128		if ( elements.is( '.tc-hidden' ) ) {
2129			if ( operator === 'isnotempty' ) {
2130				return false;
2131			} else if ( operator === 'isempty' ) {
2132				return true;
2133			}
2134		}
2135
2136		if ( operator === 'isnotempty' ) {
2137			any_checked = false;
2138		} else if ( operator === 'isempty' ) {
2139			any_checked = true;
2140		}
2141
2142		$( all_elements ).toArray().forEach( function( element ) {
2143			var _class;
2144			var elementToCheck = '';
2145
2146			element = $( element );
2147			if ( element.is( '.cpf-type-product' ) ) {
2148				elementToCheck = ':not(' + tcAPI.associatedEpoSelector + ' .tm-epo-field)';
2149			}
2150			if ( field_is_active( element, undefined, undefined, true ) ) {
2151				_class = element
2152					.attr( 'class' )
2153					.split( ' ' )
2154					.map( function( cls ) {
2155						if ( cls.indexOf( 'cpf-type-', 0 ) !== -1 ) {
2156							return cls;
2157						}
2158						return null;
2159					} )
2160					.filter( function( v ) {
2161						if ( v !== null && v !== undefined ) {
2162							return v;
2163						}
2164						return null;
2165					} );
2166
2167				if ( _class.length > 0 ) {
2168					_class = _class[ 0 ];
2169					if ( _class === 'cpf-type-product' ) {
2170						noSplit = true;
2171						if ( element.is( '.cpf-type-product-mode-product' ) || element.is( '.cpf-type-product-checkbox' ) || element.is( '.cpf-type-product-thumbnailmultiple' ) || element.is( '.cpf-type-product-custombundle' ) ) {
2172							_class = 'cpf-type-checkbox';
2173						} else if ( element.is( '.cpf-type-product-dropdown' ) ) {
2174							_class = 'cpf-type-select';
2175						} else {
2176							_class = 'cpf-type-radio';
2177						}
2178					}
2179					switch ( _class ) {
2180						case 'cpf-type-radio':
2181							radio_checked = element.find( 'input.tm-epo-field.tmcp-radio:checked' + elementToCheck );
2182							if ( operator === 'isnotempty' ) {
2183								any_checked = any_checked || radio_checked.length > 0;
2184								if ( radio_checked.length > 0 ) {
2185									val = radio_checked.length;
2186								}
2187							} else if ( operator === 'isempty' ) {
2188								any_checked = any_checked && radio_checked.length === 0;
2189							}
2190							break;
2191
2192						case 'cpf-type-checkbox':
2193							checkbox_checked = element.find( 'input.tm-epo-field.tmcp-checkbox:checked' + elementToCheck );
2194							if ( operator === 'isnotempty' ) {
2195								any_checked = any_checked || checkbox_checked.length > 0;
2196								if ( checkbox_checked.length > 0 ) {
2197									val = checkbox_checked.length;
2198								}
2199							} else if ( operator === 'isempty' ) {
2200								any_checked = any_checked && checkbox_checked.length === 0;
2201							}
2202							break;
2203
2204						case 'cpf-type-select':
2205							val = element.find( 'select.tm-epo-field.tmcp-select' + elementToCheck ).val();
2206							if ( val && ! noSplit ) {
2207								val = val.slice( 0, val.lastIndexOf( '_' ) );
2208							}
2209							break;
2210
2211						case 'cpf-type-selectmultiple':
2212							val = element.find( 'select.tm-epo-field.tmcp-selectmultiple' + elementToCheck ).val();
2213							if ( val && ! noSplit ) {
2214								val.forEach( function( option, i ) {
2215									val[ i ] = option.slice( 0, option.lastIndexOf( '_' ) );
2216								} );
2217							}
2218							break;
2219
2220						default:
2221							val = element.find( '.tm-epo-field' + elementToCheck ).val();
2222							break;
2223					}
2224					if ( Array.isArray( val ) ) {
2225						if ( operator === 'isnotempty' ) {
2226							any_checked = any_checked || val.some( function( item ) {
2227								return tm_check_match( item, '', operator );
2228							} );
2229						} else if ( operator === 'isempty' ) {
2230							any_checked = any_checked && val.every( function( item ) {
2231								return tm_check_match( item, '', operator );
2232							} );
2233						}
2234					} else if ( operator === 'isnotempty' ) {
2235						any_checked = any_checked || tm_check_match( val, '', operator );
2236					} else if ( operator === 'isempty' ) {
2237						any_checked = any_checked && tm_check_match( val, '', operator );
2238					}
2239				} else {
2240					any_checked = false;
2241				}
2242			}
2243		} );
2244
2245		return any_checked;
2246	}
2247
2248	function tm_check_field_match( f ) {
2249		var element = f.element;
2250		var operator = f.rule.operator;
2251		var value = f.rule.value;
2252		var type = f.type;
2253		var val;
2254		var radio_checked;
2255		var checkbox_checked;
2256		var ret;
2257		var _class;
2258		var noSplit = false;
2259		var elementToCheck = '';
2260
2261		if ( type === 'quantity' ) {
2262			return tm_check_match( element.val(), value, operator );
2263		}
2264		if ( type === 'productid' ) {
2265			return tm_check_match( element, value, operator );
2266		}
2267		if ( type === 'variation' ) {
2268			return tm_variation_check_match( element, value, operator );
2269		}
2270		if ( type === 'variationattributes' ) {
2271			return tm_variationattributes_check_match( element, f.rule );
2272		}
2273		element = $( f.element );
2274
2275		if ( ! element.length ) {
2276			return false;
2277		}
2278		if ( element.is( '.cpf-section' ) ) {
2279			return tm_check_section_match( element, operator );
2280		}
2281		if ( element.is( '.cpf-type-product' ) ) {
2282			elementToCheck = ':not(' + tcAPI.associatedEpoSelector + ' .tm-epo-field)';
2283		}
2284		_class = element
2285			.attr( 'class' )
2286			.split( ' ' )
2287			.map( function( cls ) {
2288				if ( cls.indexOf( 'cpf-type-', 0 ) !== -1 ) {
2289					return cls;
2290				}
2291				return null;
2292			} )
2293			.filter( function( v ) {
2294				if ( v !== null && v !== undefined ) {
2295					return v;
2296				}
2297				return null;
2298			} );
2299
2300		if ( _class.length > 0 ) {
2301			_class = _class[ 0 ];
2302			if ( _class === 'cpf-type-product' ) {
2303				noSplit = true;
2304				if ( element.is( '.cpf-type-product-mode-product' ) || element.is( '.cpf-type-product-checkbox' ) || element.is( '.cpf-type-product-thumbnailmultiple' ) || element.is( '.cpf-type-product-custombundle' ) ) {
2305					_class = 'cpf-type-checkbox';
2306				} else if ( element.is( '.cpf-type-product-dropdown' ) ) {
2307					_class = 'cpf-type-select';
2308				} else {
2309					_class = 'cpf-type-radio';
2310				}
2311			}
2312			switch ( _class ) {
2313				case 'cpf-type-radio':
2314					radio_checked = element.find( 'input.tm-epo-field.tmcp-radio:checked' + elementToCheck );
2315
2316					if ( operator === 'is' || operator === 'isnot' ) {
2317						if ( radio_checked.length === 0 && operator === 'is' ) {
2318							return false;
2319						}
2320						if ( radio_checked.length === 0 && operator === 'isnot' ) {
2321							return true;
2322						}
2323					}
2324					if ( operator === 'isnotempty' ) {
2325						return radio_checked.length > 0;
2326					}
2327					if ( operator === 'isempty' ) {
2328						return radio_checked.length === 0;
2329					}
2330					val = element.find( 'input.tm-epo-field.tmcp-radio:checked' + elementToCheck ).val();
2331					if ( val && ! noSplit ) {
2332						val = val.slice( 0, val.lastIndexOf( '_' ) );
2333					}
2334					break;
2335				case 'cpf-type-checkbox':
2336					checkbox_checked = element.find( 'input.tm-epo-field.tmcp-checkbox:checked' + elementToCheck );
2337
2338					if ( operator === 'is' || operator === 'isnot' ) {
2339						if ( checkbox_checked.length === 0 && operator === 'is' ) {
2340							return false;
2341						}
2342						if ( checkbox_checked.length === 0 && operator === 'isnot' ) {
2343							return true;
2344						}
2345						ret = false;
2346						checkbox_checked.toArray().forEach( function( el ) {
2347							val = $( el ).val();
2348							if ( val && ! noSplit ) {
2349								val = val.slice( 0, val.lastIndexOf( '_' ) );
2350							}
2351							if ( tm_check_match( val, value, operator ) ) {
2352								ret = true;
2353							} else if ( operator === 'isnot' ) {
2354								ret = false;
2355								return false;
2356							}
2357						} );
2358						return ret;
2359					}
2360					if ( operator === 'isnotempty' ) {
2361						return checkbox_checked.length > 0;
2362					}
2363					if ( operator === 'isempty' ) {
2364						return checkbox_checked.length === 0;
2365					}
2366					break;
2367				case 'cpf-type-select':
2368					val = element.find( 'select.tm-epo-field.tmcp-select' + elementToCheck ).val();
2369					if ( val && ! noSplit ) {
2370						val = val.slice( 0, val.lastIndexOf( '_' ) );
2371					}
2372					break;
2373				case 'cpf-type-selectmultiple':
2374					val = element.find( 'select.tm-epo-field.tmcp-selectmultiple' + elementToCheck ).val();
2375					if ( val && ! noSplit ) {
2376						val.forEach( function( option, i ) {
2377							val[ i ] = option.slice( 0, option.lastIndexOf( '_' ) );
2378						} );
2379					}
2380					break;
2381				case 'cpf-type-variations':
2382					return tm_variation_check_match( element, value, operator );
2383
2384				default:
2385					val = element.find( '.tm-epo-field' + elementToCheck ).val();
2386					break;
2387			}
2388			if ( Array.isArray( val ) ) {
2389				return val.some( function( item ) {
2390					return tm_check_match( item, value, operator );
2391				} );
2392			}
2393			return tm_check_match( val, value, operator );
2394		}
2395		return false;
2396	}
2397
2398	function tm_check_rules( o, theevent ) {
2399		o.toArray().forEach( function( oel ) {
2400			var $this = $( oel );
2401			var matches = $this.data( 'matches' );
2402			var toggle = $this.data( 'toggle' );
2403			var fields = $this.data( 'fields' );
2404			var checked = [];
2405			var show = toggle !== 'show';
2406			var ifield;
2407			var i;
2408			var field;
2409			var ii;
2410			var im;
2411			var sectionFields;
2412			var isInSectionRepeater;
2413
2414			if ( ! fields ) {
2415				return;
2416			}
2417
2418			sectionFields = $this.closest( '.tc-section-fields' );
2419			isInSectionRepeater = sectionFields.is( '.tc-repeater-section' );
2420
2421			for ( i = 0; i < fields.length; i++ ) {
2422				ifield = fields[ i ];
2423				if ( Array.isArray( ifield ) ) {
2424					checked[ i ] = 0;
2425					for ( ii = 0; ii < ifield.length; ii++ ) {
2426						field = ifield[ ii ];
2427						if ( isInSectionRepeater ) {
2428							field.element = sectionFields.find( '[data-uniqid="' + field.element.attr( 'data-uniqid' ) + '"' );
2429						}
2430						if ( theevent !== 'cpflogic' || field_is_active( $( field.element ), undefined, undefined, true ) ) {
2431							if ( tm_check_field_match( field ) ) {
2432								checked[ i ] = ( checked[ i ] || 0 ) + 1;
2433							}
2434						}
2435					}
2436				}
2437			}
2438
2439			for ( im = 0; im < matches.length; im++ ) {
2440				if ( parseInt( checked[ im ], 10 ) === parseInt( matches[ im ], 10 ) ) {
2441					show = ! show;
2442					break;
2443				}
2444			}
2445
2446			if ( show ) {
2447				if ( theevent === 'cpflogic' && ! $this.data( 'did_initial_activation' ) ) {
2448					latecpflogicactions.push( function() {
2449						var enabledEpos = $this.find( '.tm-epo-field.tcenabled' );
2450						enabledEpos.toArray().forEach( function( el ) {
2451							el = $( el );
2452							if ( ! el.data( 'initial_activation' ) && ! $this.closest( '.cpf-section' ).is( '.tc-hidden' ) && field_is_active( el ) ) {
2453								el.trigger( 'tc_element_epo_rules' );
2454								el.data( 'initial_activation', 1 );
2455							}
2456						} );
2457						if ( ( $this.is( '.cpf-element' ) && enabledEpos.length ) || $this.is( '.cpf-section' ) ) {
2458							$this.data( 'did_initial_activation', 1 );
2459						}
2460					} );
2461				}
2462				$this.removeClass( 'tc-hidden' );
2463			} else {
2464				$this.addClass( 'tc-hidden' );
2465			}
2466
2467			$this.data( 'isactive', show ).trigger( 'tc-logic' );
2468		} );
2469	}
2470
2471	function run_cpfdependson( obj ) {
2472		var iscpfdependson;
2473		var last_activate_field = [];
2474		var epo_object;
2475
2476		if ( ! $( obj ).length ) {
2477			obj = 'body';
2478		}
2479		obj = $( obj );
2480		iscpfdependson = obj.find( '.iscpfdependson' );
2481		iscpfdependson.toArray().forEach( function( elements ) {
2482			$( elements ).toArray().forEach( function( el ) {
2483				tm_check_rules( $( el ) );
2484			} );
2485		} );
2486		iscpfdependson.toArray().forEach( function( elements ) {
2487			$( elements ).toArray().forEach( function( el ) {
2488				tm_check_rules( $( el ), 'cpflogic' );
2489			} );
2490		} );
2491		iscpfdependson.toArray().forEach( function( elements ) {
2492			$( elements ).toArray().forEach( function( o ) {
2493				o = $( o );
2494				if ( o.is( '.cpf-section' ) ) {
2495					o = o.find( '.cpf-element' );
2496				}
2497				o.toArray().forEach( function( theelement ) {
2498					var $theelement = $( theelement );
2499					var $theelementepos = $theelement.find( '.tm-epo-field' );
2500					var len = $theelementepos.length;
2501					if ( len > 0 ) {
2502						field_is_active( $theelementepos );
2503					} else {
2504						field_is_active( $theelement );
2505					}
2506				} );
2507			} );
2508		} );
2509		latecpflogicactions.forEach( function( func ) {
2510			func();
2511		} );
2512		latecpflogicactions = [];
2513		if ( $().selectric ) {
2514			$( '.tm-extra-product-options select' ).selectric( 'refresh' );
2515		}
2516		setTimeout( function() {
2517			$( '.tm-owl-slider' ).toArray().forEach( function( slider ) {
2518				$( slider ).trigger( 'refresh.owl.carousel' );
2519			} );
2520		}, 200 );
2521
2522		obj.find( '.tm-product-image:checked,select.tm-product-image' ).toArray().forEach( function( t ) {
2523			t = $( t );
2524			if ( field_is_active( t ) && t.val() !== '' ) {
2525				last_activate_field.push( t );
2526			}
2527		} );
2528		if ( last_activate_field.length ) {
2529			last_activate_field[ last_activate_field.length - 1 ].trigger( 'tm_trigger_product_image' );
2530		} else {
2531			epo_object = obj.data( 'epo_object' );
2532			if ( epo_object ) {
2533				epo_object.main_product.trigger( 'tm_restore_product_image' );
2534			}
2535		}
2536
2537		jWindow.trigger( 'cpflogicrun' );
2538		jWindow.trigger( 'tmlazy' );
2539		jWindow.trigger( 'cpflogicdone' );
2540	}
2541
2542	// Start Conditional logic
2543	if ( ! $().cpfdependson ) {
2544		$.fn.cpfdependson = function( fields, toggle, refresh, epoObject ) {
2545			var elements = this;
2546			var matches = [];
2547			var $this_epo_container = null;
2548			var get_element;
2549			var $element;
2550			var $pid1;
2551			var $epo_id1;
2552			var _events;
2553			var $container;
2554			var i;
2555			var ii;
2556			var iii;
2557			var e;
2558			var ifield;
2559			var field;
2560			var $this;
2561			var show;
2562			var sectionFields;
2563			var isInSectionRepeater;
2564
2565			if ( ! elements.length || typeof fields !== 'object' ) {
2566				return;
2567			}
2568
2569			if ( ! toggle ) {
2570				toggle = 'show';
2571			}
2572
2573			sectionFields = elements.first().closest( '.tc-section-fields' );
2574			isInSectionRepeater = sectionFields.is( '.tc-repeater-section' );
2575
2576			// Initialize the matches array
2577			for ( i = 0; i < fields.length; i++ ) {
2578				matches[ i ] = 0;
2579				ifield = fields[ i ];
2580
2581				if ( Array.isArray( ifield ) ) {
2582					for ( ii = 0; ii < ifield.length; ii++ ) {
2583						field = ifield[ ii ];
2584						if ( typeof field !== 'object' ) {
2585							continue;
2586						}
2587						if ( isInSectionRepeater ) {
2588							field.element = sectionFields.find( '[data-uniqid="' + field.element.attr( 'data-uniqid' ) + '"' );
2589						}
2590
2591						if ( field.type === 'quantity' ) {
2592							if ( ! field.element.data( 'didcpflogic' ) ) {
2593								_events = 'change.cpflogic input.cpflogic';
2594								field.element.off( _events ).on( _events, function() {
2595									run_cpfdependson( epoObject.this_epo_container );
2596								} ).data( 'didcpflogic', 1 );
2597							}
2598						} else if ( field.type === 'variation' || field.type === 'variationattributes' ) {
2599							add_variation_event( 'found_variation.tmlogic', false, function() {
2600								run_cpfdependson( field.element );
2601								jWindow.trigger( 'tm-do-epo-update' );
2602							} );
2603
2604							add_variation_event( 'hide_variation.tmlogic', false, function() {
2605								run_cpfdependson( field.element );
2606								jWindow.trigger( 'tm-do-epo-update' );
2607							} );
2608						} else {
2609							get_element = get_element_from_field( field.element, isInSectionRepeater ? sectionFields.index() : 0 );
2610							if ( get_element && get_element.length > 0 ) {
2611								for ( iii = 0; iii < get_element.length; iii++ ) {
2612									if ( ! get_element[ iii ] ) {
2613										continue;
2614									}
2615									$element = $( get_element[ iii ] );
2616
2617									if ( $element.length === 0 ) {
2618										continue;
2619									}
2620
2621									_events = 'change.cpflogic';
2622
2623									// this essentially only works for the plugin so we use
2624									// cache and not recalcualte each time
2625									if ( ! $this_epo_container || $this_epo_container.closest( tcAPI.associatedEpoSelector ).length ) {
2626										$container = $element.closest( tcAPI.epoSelector );
2627										$pid1 = '.tm-product-id-' + $container.attr( 'data-product-id' );
2628										$epo_id1 = "[data-epo-id='" + $container.attr( 'data-epo-id' ) + "']";
2629										$this_epo_container = $( tcAPI.epoSelector + $pid1 + $epo_id1 );
2630									}
2631
2632									if ( ! $element.data( 'tmhaslogicevents' ) || refresh ) {
2633										/* For variation elements we must only add the event once,
2634										* otherwise if the variable product is on a product element
2635										* it will generate multiple events and slow down the site
2636										*/
2637										if ( ! $element.data( 'tmhaslogicevents' ) && $element.is( '.tm-epo-variation-element' ) ) {
2638											// associated product event prefixes are added later
2639											add_variation_event( 'found_variation.tmlogic', false, function() {
2640												run_cpfdependson( $this_epo_container );
2641												jWindow.trigger( 'tm-do-epo-update' );
2642											} );
2643
2644											add_variation_event( 'hide_variation.tmlogic', false, function() {
2645												run_cpfdependson( $this_epo_container );
2646												jWindow.trigger( 'tm-do-epo-update' );
2647											} );
2648										} else {
2649											if ( $element.is( ':text, textarea' ) ) {
2650												_events = 'change.cpflogic input.cpflogic';
2651											}
2652											if ( $element.is( ':input[type="number"]' ) ) {
2653												_events = 'change.cpflogic input.cpflogic keypress.cpflogic';
2654											}
2655
2656											$element.off( _events ).on( _events, function() {
2657												run_cpfdependson( $this_epo_container );
2658											} );
2659										}
2660
2661										$element.data( 'tmhaslogicevents', 1 );
2662									}
2663								}
2664							}
2665						}
2666
2667						matches[ i ]++;
2668					}
2669				}
2670			}
2671
2672			// Loop through all elements and apply visibility toggling
2673			for ( e = 0; e < elements.length; e++ ) {
2674				$this = $( elements[ e ] );
2675				show = toggle === 'hide';
2676
2677				$this.data( {
2678					matches: matches,
2679					toggle: toggle,
2680					fields: fields,
2681					isactive: show
2682				} );
2683
2684				if ( show ) {
2685					$this.removeClass( 'tc-hidden' );
2686				} else {
2687					$this.addClass( 'tc-hidden' );
2688				}
2689			}
2690
2691			elements.addClass( 'iscpfdependson is-epo-depend' ).data( 'iscpfdependson', 1 );
2692			return elements;
2693		};
2694
2695		$.fn.run_cpfdependson = function() {
2696			run_cpfdependson();
2697		};
2698	}
2699
2700	$.tcepo = {
2701		formSubmitEvents: {},
2702
2703		oneOptionIsSelected: {},
2704
2705		initialActivation: {},
2706
2707		// Holds the active precentage of total current price type fields
2708		lateFieldsPrices: {},
2709
2710		errorObject: {},
2711
2712		showHideTotal: {}
2713	};
2714
2715	function validate_logic( l ) {
2716		return typeof l === 'object' && 'toggle' in l && 'rules' in l && l.rules.length > 0;
2717	}
2718
2719	function convert_rules( rules ) {
2720		if ( rules.what ) {
2721			if ( rules.what === 'all' ) {
2722				rules.rules = [ rules.rules ];
2723			} else if ( rules.what === 'any' ) {
2724				rules.rules = rules.rules.reduce( function( accumulator, elrule ) {
2725					accumulator.push( [ elrule ] );
2726					return accumulator;
2727				}, [] );
2728			}
2729			delete rules.what;
2730		}
2731		return rules;
2732	}
2733
2734	function getLogicType( section, element ) {
2735		var type = 'element';
2736		if ( section === 'product-properties' ) {
2737			switch ( String( element ) ) {
2738				case '0':
2739					type = 'quantity';
2740					break;
2741				case '1':
2742					type = 'productid';
2743					break;
2744				case '2':
2745					type = 'variation';
2746					break;
2747				case '3':
2748					type = 'variationattributes';
2749					break;
2750			}
2751		}
2752
2753		return type;
2754	}
2755
2756	// The following loops are required for the logic to work on composite products that have custom variations
2757	function cpf_section_logic( epoObject ) {
2758		var obj = epoObject.this_epo_container;
2759		var root_element = $( obj );
2760		var all_sections = root_element.find( '.cpf-section' ).not( '.cpf-type-product .cpf-section' );
2761		var search_obj;
2762		var cpf_section;
2763		var sect;
2764		var logic;
2765		var haslogic;
2766		var fields;
2767		var section;
2768		var element;
2769		var type;
2770		var obj_section;
2771		var obj_element;
2772		var closestProductElement;
2773		var selector = '[data-haslogic="1"]';
2774
2775		if ( root_element.is( '.cpf-section' ) ) {
2776			search_obj = false;
2777		} else {
2778			search_obj = all_sections;
2779		}
2780
2781		if ( ! epoObject.is_associated ) {
2782			selector = '[data-haslogic="1"]:not(".cpf-type-product .cpf-section")';
2783		}
2784
2785		root_element.toArray().forEach( function( obj_el ) {
2786			if ( $( obj_el ).is( '.cpf-section' ) ) {
2787				cpf_section = $( obj_el );
2788			} else {
2789				cpf_section = $( obj_el ).find( '.cpf-section' );
2790			}
2791
2792			cpf_section.filter( selector ).toArray().forEach( function( el ) {
2793				var irule;
2794				var rule;
2795				var i;
2796				var ii;
2797				sect = $( el );
2798				logic = sect.data( 'logic' );
2799				// backwards compatibility conversion.
2800				logic = convert_rules( logic );
2801				haslogic = parseInt( sect.data( 'haslogic' ), 10 );
2802				fields = [];
2803				closestProductElement = sect.parent().closest( '.cpf-type-product' );
2804
2805				if ( haslogic === 1 && validate_logic( logic ) ) {
2806					for ( i = 0; i < logic.rules.length; i++ ) {
2807						irule = logic.rules[ i ];
2808						if ( ! irule || ! Array.isArray( irule ) ) {
2809							continue;
2810						}
2811						fields[ i ] = [];
2812						for ( ii = 0; ii < irule.length; ii++ ) {
2813							rule = irule[ ii ];
2814							section = rule.section;
2815							element = rule.element;
2816							type = getLogicType( section, element );
2817
2818							if ( type === 'quantity' ) {
2819								if ( closestProductElement.length ) {
2820									obj_element = epoObject.main_cart.find( tcAPI.associateQtySelector );
2821								} else {
2822									obj_element = epoObject.main_cart.find( epoObject.qtySelector );
2823								}
2824							} else if ( type === 'productid' ) {
2825								obj_element = epoObject.product_id;
2826							} else if ( type === 'variation' || type === 'variationattributes' ) {
2827								if ( closestProductElement.length ) {
2828									obj_element = closestProductElement.find( '.tc-epo-element-product-container' );
2829									if ( ! obj_element.length ) {
2830										obj_element = closestProductElement.closest( '.tc-epo-element-product-container' );
2831									}
2832								} else {
2833									obj_element = root_element;
2834								}
2835							} else if ( search_obj ) {
2836								if ( closestProductElement.length ) {
2837									obj_section = root_element.find( '.cpf-section' ).filter( "[data-uniqid='" + section + "']" );
2838									if ( element !== section ) {
2839										obj_element = obj_section.find( '.cpf-element' ).eq( element );
2840									} else {
2841										obj_element = obj_section;
2842									}
2843								} else {
2844									obj_section = search_obj.filter( "[data-uniqid='" + section + "']" );
2845									if ( element !== section ) {
2846										obj_element = obj_section.find( '.cpf-element:not(.cpf-element .cpf-element)' ).eq( element );
2847									} else {
2848										obj_element = obj_section;
2849									}
2850								}
2851							} else if ( element !== section ) {
2852								obj_element = root_element.find( '.cpf-element' ).eq( element );
2853							} else {
2854								obj_section = root_element.find( '.cpf-section' ).filter( "[data-uniqid='" + section + "']" );
2855								obj_element = obj_section;
2856							}
2857
2858							fields[ i ].push( {
2859								element: obj_element,
2860								rule: rule,
2861								type: type
2862							} );
2863						}
2864					}
2865					if ( ! sect.data( 'iscpfdependson' ) ) {
2866						sect.data( 'cpfdependson-fields', fields );
2867						sect.cpfdependson( fields, logic.toggle, false, epoObject );
2868					} else {
2869						sect.cpfdependson( sect.data( 'cpfdependson-fields' ), logic.toggle, true, epoObject );
2870					}
2871				}
2872			} );
2873		} );
2874	}
2875
2876	function cpf_element_logic( epoObject ) {
2877		var obj = epoObject.this_epo_container;
2878		var root_element = $( obj );
2879		var all_sections = root_element.find( '.cpf-section' ).not( '.cpf-type-product .cpf-section' );
2880		var search_obj;
2881		var current_element;
2882		var logic;
2883		var haslogic;
2884		var section;
2885		var element;
2886		var type;
2887		var obj_section;
2888		var obj_element;
2889		var closestProductElement;
2890		var isInProductElement = false;
2891		var selector = '.cpf-element[data-haslogic="1"]';
2892
2893		if ( root_element.parent().is( tcAPI.associatedEpoSelector ) ) {
2894			all_sections = root_element.find( '.cpf-section' );
2895			isInProductElement = true;
2896		}
2897		if ( root_element.is( '.cpf-section' ) ) {
2898			search_obj = false;
2899		} else {
2900			search_obj = all_sections;
2901		}
2902
2903		if ( ! epoObject.is_associated ) {
2904			selector = '.cpf-element[data-haslogic="1"]:not(".cpf-type-product .cpf-element")';
2905		}
2906
2907		root_element.find( selector ).toArray().forEach( function( el ) {
2908			var fields = [];
2909			var irule;
2910			var rule;
2911			var i;
2912			var ii;
2913
2914			current_element = $( el );
2915			logic = current_element.data( 'logic' );
2916			// backwards compatibility conversion.
2917			logic = convert_rules( logic );
2918
2919			haslogic = parseInt( current_element.data( 'haslogic' ), 10 );
2920
2921			if ( isInProductElement ) {
2922				closestProductElement = root_element;
2923			} else {
2924				closestProductElement = current_element.parent().closest( '.cpf-type-product' );
2925			}
2926
2927			if ( haslogic === 1 && validate_logic( logic ) ) {
2928				for ( i = 0; i < logic.rules.length; i++ ) {
2929					irule = logic.rules[ i ];
2930					if ( ! irule || ! Array.isArray( irule ) ) {
2931						continue;
2932					}
2933					fields[ i ] = [];
2934					for ( ii = 0; ii < irule.length; ii++ ) {
2935						rule = irule[ ii ];
2936						section = rule.section;
2937						element = rule.element;
2938						type = getLogicType( section, element );
2939
2940						if ( type === 'quantity' ) {
2941							if ( closestProductElement.length ) {
2942								obj_element = epoObject.main_cart.find( tcAPI.associateQtySelector );
2943							} else {
2944								obj_element = epoObject.main_cart.find( epoObject.qtySelector );
2945							}
2946						} else if ( type === 'productid' ) {
2947							obj_element = epoObject.product_id;
2948						} else if ( type === 'variation' || type === 'variationattributes' ) {
2949							if ( closestProductElement.length ) {
2950								obj_element = closestProductElement.find( '.tc-epo-element-product-container' );
2951								if ( ! obj_element.length ) {
2952									obj_element = closestProductElement.closest( '.tc-epo-element-product-container' );
2953								}
2954							} else {
2955								obj_element = root_element;
2956							}
2957						} else if ( search_obj ) {
2958							if ( closestProductElement.length ) {
2959								obj_section = root_element.find( '.cpf-section' ).filter( "[data-uniqid='" + section + "']" );
2960								if ( element !== section ) {
2961									obj_element = obj_section.find( '.cpf-element' ).eq( element );
2962								} else {
2963									obj_element = obj_section;
2964								}
2965							} else {
2966								obj_section = search_obj.filter( "[data-uniqid='" + section + "']" );
2967								if ( element !== section ) {
2968									obj_element = obj_section.find( '.cpf-element:not(.cpf-element .cpf-element)' ).eq( element );
2969								} else {
2970									obj_element = obj_section;
2971								}
2972							}
2973						} else if ( element !== section ) {
2974							obj_element = root_element.find( '.cpf-element' ).eq( element );
2975						} else {
2976							obj_section = root_element.find( '.cpf-section' ).filter( "[data-uniqid='" + section + "']" );
2977							obj_element = obj_section;
2978						}
2979
2980						fields[ i ].push( {
2981							element: obj_element,
2982							rule: rule,
2983							type: type
2984						} );
2985					}
2986				}
2987
2988				if ( ! current_element.data( 'iscpfdependson' ) ) {
2989					current_element.data( 'cpfdependson-fields', fields );
2990					current_element.cpfdependson( fields, logic.toggle, false, epoObject );
2991				} else {
2992					current_element.cpfdependson( current_element.data( 'cpfdependson-fields' ), logic.toggle, true, epoObject );
2993				}
2994			}
2995		} );
2996	} // End Conditional logic
2997
2998	// Return price value without tax
2999	function tm_set_price_without_tax( value, _cart, force ) {
3000		var taxable;
3001		var tax_rate;
3002		var tax_display_mode;
3003		var prices_include_tax;
3004
3005		if ( _cart ) {
3006			taxable = _cart.attr( 'data-taxable' );
3007			tax_rate = _cart.attr( 'data-tax-rate' );
3008			tax_display_mode = _cart.attr( 'data-tax-display-mode' );
3009			prices_include_tax = _cart.attr( 'data-prices-include-tax' );
3010
3011			if ( force || ( taxable && tax_display_mode === 'incl' && prices_include_tax !== '1' ) ) {
3012				value = parseFloat( value ) / ( 1 + ( tax_rate / 100 ) );
3013			}
3014		}
3015
3016		return value;
3017	}
3018
3019	// Return price with tax
3020	function tm_set_price_with_tax( value, _cart, force ) {
3021		var taxable;
3022		var tax_rate;
3023		var tax_display_mode;
3024		var prices_include_tax;
3025
3026		if ( _cart ) {
3027			taxable = _cart.attr( 'data-taxable' );
3028			tax_rate = _cart.attr( 'data-tax-rate' );
3029			tax_display_mode = _cart.attr( 'data-tax-display-mode' );
3030			prices_include_tax = _cart.attr( 'data-prices-include-tax' );
3031			if ( force || ( taxable && tax_display_mode !== 'incl' && prices_include_tax === '1' ) ) {
3032				value = parseFloat( value ) * ( 1 + ( tax_rate / 100 ) );
3033			}
3034		}
3035
3036		return value;
3037	}
3038
3039	// Return  price
3040	function tm_set_backend_price( value, _cart, variation ) {
3041		var taxable;
3042		var tax_display_mode;
3043		var prices_include_tax;
3044
3045		if ( _cart ) {
3046			taxable = _cart.attr( 'data-taxable' );
3047			tax_display_mode = _cart.attr( 'data-tax-display-mode' );
3048			prices_include_tax = _cart.attr( 'data-prices-include-tax' );
3049			if ( taxable ) {
3050				if ( variation && variation.tc_tax_rate && String( variation.tc_tax_rate ) === '0' ) {
3051					return value;
3052				}
3053				if ( prices_include_tax === '1' ) {
3054					if ( tax_display_mode === 'incl' ) {
3055						// if we are not in the base tax
3056						if ( variation.tc_base_taxes_of_one !== variation.tc_modded_taxes_of_one ) {
3057							value = parseFloat( ( ( 1 - variation.tc_taxes_of_one ) * value ) * ( 1 / ( 1 - variation.tc_base_taxes_of_one ) ) );
3058						}
3059					} else {
3060						value = tm_set_price_with_tax( value, _cart );
3061					}
3062				} else if ( prices_include_tax !== '1' && tax_display_mode === 'incl' ) {
3063					value = tm_set_price_without_tax( value, _cart );
3064				}
3065			}
3066		}
3067
3068		return value;
3069	}
3070
3071	// Return a formatted currency value
3072	function tm_set_price_totals( value, _cart, notax, element ) {
3073		var sign = '';
3074		var val;
3075
3076		if ( ! notax ) {
3077			value = tm_set_tax_price( value, _cart, element, undefined, true );
3078		}
3079		val = Math.abs( value );
3080
3081		if ( value < 0 ) {
3082			sign = TMEPOJS.minus_sign + ' ';
3083		}
3084
3085		return tm_set_price_( val, sign );
3086	}
3087
3088	function replace_suffixes( value, rawValue, tc_totals_ob, totalsHolder ) {
3089		if ( totalsHolder.attr( 'data-tax-display-mode' ) === 'excl' ) {
3090			tc_totals_ob[ value ] = tc_totals_ob[ value ].replaceAll( '{price_excluding_tax}', tm_set_price_totals( tc_totals_ob[ rawValue ], totalsHolder, true ) );
3091			tc_totals_ob[ value ] = tc_totals_ob[ value ].replaceAll( '{price_including_tax}', tm_set_price_totals( tm_set_price_with_tax( tc_totals_ob[ rawValue ], totalsHolder, true ), totalsHolder, true ) );
3092		} else {
3093			tc_totals_ob[ value ] = tc_totals_ob[ value ].replaceAll( '{price_including_tax}', tm_set_price_totals( tc_totals_ob[ rawValue ], totalsHolder, true ) );
3094			tc_totals_ob[ value ] = tc_totals_ob[ value ].replaceAll( '{price_excluding_tax}', tm_set_price_totals( tm_set_price_without_tax( tc_totals_ob[ rawValue ], totalsHolder, true ), totalsHolder, true ) );
3095		}
3096		return tc_totals_ob;
3097	}
3098
3099	function replace_suffixes_in_html( html, price, totalsHolder ) {
3100		if ( totalsHolder.attr( 'data-tax-display-mode' ) === 'excl' ) {
3101			html = html.replaceAll( '{price_excluding_tax}', tm_set_price_totals( price, totalsHolder, true ) );
3102			html = html.replaceAll( '{price_including_tax}', tm_set_price_totals( tm_set_price_with_tax( price, totalsHolder, true ), totalsHolder, true ) );
3103		} else {
3104			html = html.replaceAll( '{price_including_tax}', tm_set_price_totals( price, totalsHolder, true ) );
3105			html = html.replaceAll( '{price_excluding_tax}', tm_set_price_totals( tm_set_price_without_tax( price, totalsHolder, true ), totalsHolder, true ) );
3106		}
3107		return html;
3108	}
3109
3110	function tm_force_update_price( epoObject, obj, price, formatted_price, original_price, useFormattedPrice ) {
3111		tm_update_price( {
3112			epoObject: epoObject,
3113			obj: obj,
3114			price: price,
3115			formatted_price: formatted_price,
3116			original_price: original_price,
3117			force: true,
3118			useFormattedPrice: useFormattedPrice
3119		} );
3120	}
3121
3122	function tm_update_price( priceobj ) {
3123		var $obj;
3124		var w;
3125		var $ba_amount;
3126		var f;
3127		var pw;
3128		var price;
3129		var formatted_price;
3130		var original_price;
3131		var force;
3132		var useFormattedPrice;
3133		var template;
3134		var templatePrice;
3135		var html;
3136		var totalsHolder;
3137		var sign;
3138
3139		$obj = $( priceobj.obj );
3140
3141		if ( $obj.length === 0 ) {
3142			return;
3143		}
3144
3145		w = $obj.closest( '.tmcp-field-wrap' );
3146		pw = $obj.closest( '.tc-price-wrap' );
3147		f = w.find( '.tm-epo-field' );
3148
3149		price = priceobj.price || 0;
3150		formatted_price = priceobj.formatted_price || '';
3151		original_price = priceobj.original_price || '';
3152		force = priceobj.force || false;
3153		useFormattedPrice = priceobj.useFormattedPrice || false;
3154		totalsHolder = priceobj.epoObject.this_epo_totals_container;
3155
3156		if ( ! force && f.attr( 'data-no-price-change' ) === '1' && f.data( 'price-changed' ) ) {
3157			return;
3158		}
3159
3160		price = $.epoAPI.applyFilter( 'tc_adjust_update_price_price', price ); //number
3161		formatted_price = $.epoAPI.applyFilter( 'tc_adjust_update_price_formatted_price', formatted_price, price ); //formatted
3162		original_price = $.epoAPI.applyFilter( 'tc_adjust_update_price_original_price', original_price ); //number
3163
3164		if ( ! Number.isFinite( parseFloat( original_price ) ) ) {
3165			original_price = 0;
3166		}
3167		if ( ! Number.isFinite( parseFloat( price ) ) ) {
3168			price = 0;
3169		}
3170
3171		$ba_amount = w.find( '.before-amount,.after-amount' );
3172
3173		if ( ( TMEPOJS.tm_epo_auto_hide_price_if_zero === 'yes' && ( $.epoAPI.util.isEmpty( price ) === false || ( TMEPOJS.tm_epo_no_hide_price_if_original_not_zero === 'yes' && $.epoAPI.util.isEmpty( price ) === true && $.epoAPI.util.isEmpty( original_price ) === false ) ) ) || TMEPOJS.tm_epo_auto_hide_price_if_zero !== 'yes' ) {
3174			if ( ( $.epoAPI.util.isEmpty( price ) === true && f.attr( 'data-no-price' ) === '1' ) || ( ! force && f.length > 0 && ( f.attr( 'data-no-price' ) === '1' || ( f.attr( 'data-type' ) === 'variable' && ! f.data( 'price' ) ) ) ) ) {
3175				pw.addClass( 'tm-hidden' );
3176				$obj.addClass( 'tm-hidden' );
3177				$obj.empty();
3178				$ba_amount.addClass( 'tm-hidden' );
3179			} else {
3180				if ( original_price && original_price !== undefined && parseFloat( original_price ) !== parseFloat( price ) ) {
3181					if ( useFormattedPrice ) {
3182						template = tcAPI.templateEngine.plain_price;
3183						templatePrice = { price: formatted_price };
3184					} else {
3185						if ( price < 0 && ! original_price < 0 ) {
3186							template = tcAPI.templateEngine.sale_price_m10;
3187							price = Math.abs( price );
3188						} else if ( ! price < 0 && original_price < 0 ) {
3189							template = tcAPI.templateEngine.sale_price_m01;
3190							original_price = Math.abs( original_price );
3191						} else if ( price < 0 && original_price < 0 ) {
3192							template = tcAPI.templateEngine.sale_price_m11;
3193							price = Math.abs( price );
3194							original_price = Math.abs( original_price );
3195						} else {
3196							template = tcAPI.templateEngine.sale_price;
3197						}
3198						templatePrice = { price: formatPrice( original_price ), sale_price: formatPrice( price ) };
3199					}
3200				} else if ( useFormattedPrice ) {
3201					template = tcAPI.templateEngine.plain_price;
3202					templatePrice = { price: formatted_price };
3203				} else {
3204					template = tcAPI.templateEngine.price;
3205					if ( price < 0 ) {
3206						template = tcAPI.templateEngine.price_m;
3207						price = Math.abs( price );
3208					}
3209					templatePrice = { price: formatPrice( price ) };
3210				}
3211				html = $.epoAPI.util.decodeHTML( $.epoAPI.template.html( template, templatePrice ) );
3212				html = replace_suffixes_in_html( html, price, totalsHolder );
3213				html = $.epoAPI.applyFilter( 'tc_adjust_update_price_formatted_price_html', html );
3214				sign = '';
3215				if ( ! useFormattedPrice && price > 0 && TMEPOJS.tm_epo_global_options_price_sign !== 'minus' ) {
3216					sign = TMEPOJS.option_plus_sign + ' ';
3217				}
3218				$obj.html( sign + html );
3219				pw.removeClass( 'tm-hidden' );
3220				$obj.removeClass( 'tm-hidden' );
3221				$ba_amount.removeClass( 'tm-hidden' );
3222			}
3223		} else {
3224			pw.addClass( 'tm-hidden' );
3225			$obj.addClass( 'tm-hidden' );
3226			$obj.empty();
3227			$ba_amount.addClass( 'tm-hidden' );
3228		}
3229	}
3230
3231	function get_variation_current_settings( form, epoObject ) {
3232		var current_settings = {};
3233
3234		if ( epoObject.thisForm ) {
3235			form = epoObject.thisForm;
3236		}
3237
3238		form.find( '.variations select, .tc-epo-variable-product-selector' ).toArray().forEac
3238h( function( el ) {
3239			var attribute_name;
3240			var value;
3241			el = $( el );
3242
3243			// Get attribute name from data-attribute_name, or from input name
3244			// if it doesn't exist
3245			if ( typeof el.data( 'attribute_name' ) !== 'undefined' ) {
3246				attribute_name = el.data( 'attribute_name' );
3247			} else {
3248				attribute_name = el.attr( 'name' );
3249			}
3250
3251			// Encode entities
3252			value = el.val();
3253
3254			// Add to settings array
3255			current_settings[ attribute_name ] = value;
3256		} );
3257
3258		return current_settings;
3259	}
3260
3261	function do_tm_custom_variations_update( form, all_variations, epoObject ) {
3262		var check_if_all_are_not_set = [];
3263		var formSettings = get_variation_current_settings( form, epoObject );
3264		var redo_check = true;
3265		var variationId = form.find( getVariationIdSelector( form ) ).val();
3266		var ii;
3267
3268		variationId = ( variationId !== '0' && variationId !== '' ) || form.find( '.cpf-type-variations' ).find( '.tm-epo-variation-element:checked' ).length > 0 || form.find( '.cpf-type-variations' ).find( '.tm-epo-variation-element option[value!=""]:selected' );
3269
3270		if ( ! variationId ) {
3271			return;
3272		}
3273		form.find( '.cpf-type-variations' ).toArray().forEach( function( el, i ) {
3274			var t = $( el ).find( '.tm-epo-variation-element' );
3275			var id;
3276			var v;
3277			var exists = false;
3278
3279			check_if_all_are_not_set[ i ] = true;
3280
3281			if ( t.is( 'select' ) ) {
3282				id = $.epoAPI.dom.id( t.attr( 'data-tm-for-variation' ) );
3283				v = t.val();
3284				if ( v ) {
3285					check_if_all_are_not_set[ i ] = false;
3286				}
3287				t.children( 'option' ).toArray().forEach( function( o ) {
3288					exists = false;
3289					form.find( "[data-attribute_name='attribute_" + id + "']" )
3290						.children( 'option' )
3291						.toArray().forEach( function( att ) {
3292							if ( $( att ).attr( 'value' ) === $( o ).attr( 'value' ) ) {
3293								exists = true;
3294								return false;
3295							}
3296						} );
3297					if ( ! exists ) {
3298						$( o ).prop( 'disabled', true ).hide();
3299					} else {
3300						$( o ).prop( 'disabled', false ).show();
3301					}
3302				} );
3303			} else {
3304				t.toArray().forEach( function( oe ) {
3305					var o = $( oe );
3306					var li = o.closest( 'li' );
3307					var input = li.find( '.tm-epo-variation-element' );
3308					var this_settings = $.extend( true, {}, formSettings );
3309					var matching_variations;
3310					var variation;
3311					var is_in_stock;
3312
3313					id = o.attr( 'data-tm-for-variation' );
3314					v = o.val();
3315					if ( o.is( ':checked' ) ) {
3316						check_if_all_are_not_set[ i ] = false;
3317					}
3318
3319					this_settings[ 'attribute_' + id ] = v;
3320
3321					matching_variations = $.fn.tm_find_matching_variations( all_variations, this_settings );
3322					variation = matching_variations.shift();
3323
3324					is_in_stock = variation && 'is_in_stock' in variation && variation.is_in_stock;
3325
3326					if ( ! is_in_stock ) {
3327						if ( ! input.is( ':checked' ) && ! is_in_stock ) {
3328							li.addClass( 'pointereventsoff' );
3329						} else {
3330							li.removeClass( 'pointereventsoff' );
3331						}
3332
3333						o.attr( 'disabled', 'disabled' ).addClass( 'tm-disabled' );
3334
3335						input.attr( 'disabled', 'disabled' );
3336						input.attr( 'data-tm-disabled', 'disabled' );
3337
3338						li.addClass( 'tm-attribute-disabled' ).fadeTo( 'fast', 0.5 );
3339					} else {
3340						o.prop( 'disabled', false ).removeClass( 'tm-disabled' );
3341						li.removeClass( 'pointereventsoff tm-attribute-disabled' ).fadeTo( 'fast', 1, function() {
3342							$( this ).css( 'opacity', '' );
3343						} );
3344						input.prop( 'disabled', false );
3345						input.removeAttr( 'data-tm-disabled' );
3346					}
3347				} );
3348			}
3349		} );
3350
3351		if ( check_if_all_are_not_set ) {
3352			check_if_all_are_not_set.shift();
3353
3354			for ( ii = 0; ii < check_if_all_are_not_set.length; ii++ ) {
3355				if ( check_if_all_are_not_set[ ii ] === false ) {
3356					redo_check = false;
3357					break;
3358				}
3359			}
3360
3361			if ( redo_check ) {
3362				form.find( '.cpf-type-variations' )
3363					.first()
3364					.toArray().forEach( function( el ) {
3365						var t;
3366						var li;
3367						var input;
3368
3369						t = $( el ).find( '.tm-epo-variation-element' );
3370
3371						if ( ! t.is( 'select' ) ) {
3372							t.toArray().forEach( function( o ) {
3373								o = $( o );
3374								li = o.closest( 'li' );
3375								input = li.find( '.tm-epo-variation-element' );
3376								o.prop( 'disabled', false ).removeClass( 'tm-disabled' );
3377								li.removeClass( 'tm-attribute-disabled' ).stop().css( 'opacity', '' );
3378								input.prop( 'disabled', false );
3379								input.removeAttr( 'data-tm-disabled' );
3380							} );
3381						}
3382					} );
3383			}
3384		}
3385	}
3386
3387	function tm_custom_variations_update( form, epoObject ) {
3388		var data;
3389		var all_variations = form.data( 'product_variations' );
3390		var product_id = parseInt( form.data( 'product_id' ), 10 );
3391		var globalVariationObject = form.data( 'globalVariationObject' ) || false;
3392
3393		if ( TMEPOJS.skipCustomVariationsUpdate ) {
3394			return;
3395		}
3396
3397		if ( ! product_id ) {
3398			product_id = form.data( 'tc_product_id' );
3399		}
3400
3401		if ( ! product_id && form.is( tcAPI.compositeSelector ) ) {
3402			data = form.find( '.component_options' ).data( 'options_data' );
3403			product_id = data[ 0 ].option_id;
3404			if ( ! all_variations ) {
3405				all_variations = form.find( '.details.component_data' ).data( 'product_variations' );
3406			}
3407		}
3408
3409		if ( ! epoObject.is_associated ) {
3410			// Fallback to window property if not set - backwards compat
3411			if ( ! all_variations && window.product_variations && window.product_variations.product_id ) {
3412				all_variations = window.product_variations.product_id;
3413			}
3414			if ( ! all_variations && window.product_variations ) {
3415				all_variations = window.product_variations;
3416			}
3417			if ( ! all_variations && window[ 'product_variations_' + product_id ] ) {
3418				all_variations = window[ 'product_variations_' + product_id ];
3419			}
3420		}
3421
3422		if ( ! all_variations ) {
3423			if ( ! globalVariationObject ) {
3424				data = {
3425					action: 'woocommerce_tm_get_variations_array',
3426					post_id: product_id
3427				};
3428				$.post(
3429					TMEPOJS.ajax_url,
3430					data,
3431					function( response ) {
3432						globalVariationObject = response;
3433						form.data( 'globalVariationObject', response );
3434						do_tm_custom_variations_update( form, globalVariationObject.variations, epoObject );
3435					},
3436					'json'
3437				);
3438			} else {
3439				do_tm_custom_variations_update( form, globalVariationObject.variations, epoObject );
3440			}
3441
3442			return;
3443		}
3444		// may need 2.4 check for woocommerce_ajax_variation_threshold
3445		do_tm_custom_variations_update( form, all_variations, epoObject );
3446	}
3447
3448	function tm_fix_stock( cart, html ) {
3449		var custom_variations;
3450		var section;
3451
3452		if ( html === undefined ) {
3453			return false;
3454		}
3455		cart = $( cart );
3456		custom_variations = cart.find( '.tm-epo-variation-element' ).first();
3457		section = custom_variations.closest( '.tm-epo-variation-section' );
3458
3459		if ( custom_variations.length ) {
3460			section.find( '.tm-stock' ).remove();
3461			section.append( '<div class="tm-stock">' + html + '</div>' );
3462			return true;
3463		}
3464		cart.find( '.tm-stock' ).remove();
3465		cart.find( '.variations' ).after( '<div class="tm-stock">' + html + '</div>' );
3466		return true;
3467	}
3468
3469	function fix_stock( $this, form ) {
3470		var stock;
3471
3472		if ( TMEPOJS.tm_epo_global_move_out_of_stock === 'no' ) {
3473			return;
3474		}
3475		stock = $this.find( '.woocommerce-variation-availability' ).last();
3476		if ( ! stock.length ) {
3477			stock = $this.find( '.stock' ).last();
3478		}
3479
3480		if ( stock.length ) {
3481			form.find( '.tm-stock' ).remove();
3482			if ( tm_fix_stock( form, stock.prop( 'outerHTML' ) ) ) {
3483				stock.remove();
3484			}
3485		} else {
3486			form.find( '.tm-stock' ).remove();
3487		}
3488	}
3489
3490	function get_main_input_id( main_product, product, id ) {
3491		var selector = '';
3492		var inputid;
3493
3494		if ( id ) {
3495			selector = selector + "[value='" + id + "']";
3496		}
3497		if ( ! product ) {
3498			product = main_product;
3499		}
3500		inputid = product.find( tcAPI.addToCartSelector + selector );
3501		if ( inputid.length === 0 ) {
3502			inputid = product.find( tcAPI.tcAddToCartSelector + selector );
3503		}
3504		return inputid.last();
3505	}
3506
3507	function get_main_form( main_product, product, selector, id ) {
3508		if ( ! selector ) {
3509			selector = 'form';
3510		}
3511		return get_main_input_id( main_product, product, id ).closest( selector );
3512	}
3513
3514	function get_main_cart( main_product, product, selector, id ) {
3515		return get_main_form( main_product, product, selector, id );
3516	}
3517
3518	function tm_get_native_prices_block( obj ) {
3519		var selector = $.epoAPI.applyFilter( 'tcGetNativePricesBlockSelector', '.single_variation .price', obj );
3520
3521		return $( obj ).find( selector ).not( '.tc-price' );
3522	}
3523
3524	// URL replacement setup
3525	function tm_set_url_fields() {
3526		jDocument.on( 'click.cpfurl change.cpfurl tmredirect', '.tc-url-container .tmcp-radio, .tc-url-container .tmcp-radio+label', function( e ) {
3527			var data_url = $( this ).attr( 'data-url' );
3528			if ( data_url ) {
3529				if ( window.location !== data_url ) {
3530					e.preventDefault();
3531					window.location = data_url;
3532				}
3533			}
3534		} );
3535		jDocument.on( 'change.cpfurl tmredirect', '.tc-url-container .tmcp-select', function( e ) {
3536			var data_url = $( this ).children( 'option:selected' ).attr( 'data-url' );
3537			if ( data_url ) {
3538				if ( window.location !== data_url ) {
3539					e.preventDefault();
3540					window.location = data_url;
3541				}
3542			}
3543		} );
3544	}
3545
3546	function tm_floating_totals( this_epo_totals_container, is_quickview, main_cart ) {
3547		$.tcFloatingTotalsBox( this_epo_totals_container, is_quickview, main_cart );
3548	}
3549
3550	function tm_show_hide_add_to_cart_button( main_product, currentEpoObject ) {
3551		var button;
3552		var qty;
3553		var showHideCart = currentEpoObject.showHideCart;
3554
3555		if ( ! currentEpoObject.is_associated && showHideCart !== undefined ) {
3556			if ( TMEPOJS.tm_epo_hide_add_cart_button === 'yes' || TMEPOJS.tm_epo_hide_all_add_cart_button === 'yes' || TMEPOJS.tm_epo_hide_required_add_cart_button === 'yes' ) {
3557				button = main_product.find( tcAPI.addToCartButtonSelector ).first();
3558				qty = main_product.find( tcAPI.qtySelector ).first();
3559
3560				if ( showHideCart ) {
3561					button.removeClass( 'tc-hide-add-to-cart-button' );
3562					qty.removeClass( 'tc-hide-add-to-cart-button' );
3563				} else {
3564					button.addClass( 'tc-hide-add-to-cart-button' );
3565					qty.addClass( 'tc-hide-add-to-cart-button' );
3566				}
3567
3568				jWindow.trigger( 'epoShowHideCart', {
3569					main_product: main_product,
3570					currentEpoObject: currentEpoObject,
3571					showHideCart: showHideCart,
3572					button: button,
3573					qty: qty
3574				} );
3575			}
3576		}
3577	}
3578
3579	function addShowHidetoEpoObject( currentEpoObject, epoEventId, epoObject ) {
3580		var has_epo;
3581		var this_epo_container;
3582		var epos;
3583		var allElementsAreSelected;
3584		var showHideCart = true;
3585		var showHideTotal = true;
3586		var one_option_is_selected = $.tcepo.oneOptionIsSelected[ epoEventId ];
3587
3588		if ( currentEpoObject.is_associated ) {
3589			currentEpoObject = $.epoAPI.applyFilter( 'tc_currentEpoObject_associated', currentEpoObject, epoEventId, epoObject );
3590			return currentEpoObject;
3591		}
3592
3593		if ( typeof epoObject === 'object' ) {
3594			has_epo = epoObject.has_epo;
3595			this_epo_container = epoObject.this_epo_container;
3596			has_epo = has_epo && ( this_epo_container.find( '.tmcp-fee-field' ).length || this_epo_container.find( '.tmcp-field' ).not( '.cpf-type-variations .tmcp-field' ).length );
3597		} else {
3598			has_epo = epoObject;
3599		}
3600
3601		currentEpoObject.showHideCart = undefined;
3602		currentEpoObject.showHideTotal = undefined;
3603
3604		if ( has_epo && ( TMEPOJS.tm_epo_hide_add_cart_button === 'yes' || TMEPOJS.tm_epo_hide_all_add_cart_button === 'yes' || TMEPOJS.tm_epo_hide_required_add_cart_button === 'yes' || TMEPOJS.tm_epo_hide_totals_until_any === 'yes' || TMEPOJS.tm_epo_hide_totals_until_all_required === 'yes' || TMEPOJS.tm_epo_hide_totals_until_all === 'yes' ) ) {
3605			// Hide cart button until an element is chosen
3606			if ( TMEPOJS.tm_epo_hide_add_cart_button === 'yes' ) {
3607				showHideCart = one_option_is_selected;
3608			}
3609
3610			// Hide Final total box until an element is chosen
3611			if ( TMEPOJS.tm_epo_hide_totals_until_any === 'yes' ) {
3612				showHideTotal = one_option_is_selected;
3613			}
3614
3615			// Hide until all required elements are chosen
3616			if ( TMEPOJS.tm_epo_hide_required_add_cart_button === 'yes' || TMEPOJS.tm_epo_hide_totals_until_all_required === 'yes' ) {
3617				epos = currentEpoObject.this_epo_container.find( '.cpf-element' ).not( '.cpf-type-variations' ).filter( '.tc-container-enabled.tc-is-required' );
3618				allElementsAreSelected = checkFullSelection( epos );
3619				if ( TMEPOJS.tm_epo_hide_required_add_cart_button === 'yes' ) {
3620					showHideCart = allElementsAreSelected;
3621				}
3622				if ( TMEPOJS.tm_epo_hide_totals_until_all_required === 'yes' ) {
3623					showHideTotal = allElementsAreSelected;
3624				}
3625			}
3626
3627			// Hide until all elements are chosen
3628			if ( TMEPOJS.tm_epo_hide_all_add_cart_button === 'yes' || TMEPOJS.tm_epo_hide_totals_until_all === 'yes' ) {
3629				epos = currentEpoObject.this_epo_container.find( '.cpf-element' ).not( '.cpf-type-variations' ).filter( '.tc-container-enabled' );
3630				allElementsAreSelected = checkFullSelection( epos );
3631				if ( TMEPOJS.tm_epo_hide_all_add_cart_button === 'yes' ) {
3632					showHideCart = allElementsAreSelected;
3633				}
3634				if ( TMEPOJS.tm_epo_hide_totals_until_all === 'yes' ) {
3635					showHideTotal = allElementsAreSelected;
3636				}
3637			}
3638
3639			currentEpoObject.showHideCart = showHideCart;
3640			currentEpoObject.showHideTotal = showHideTotal;
3641			$.tcepo.showHideTotal[ epoEventId ] = showHideTotal;
3642		}
3643
3644		currentEpoObject = $.epoAPI.applyFilter( 'tc_currentEpoObject', currentEpoObject, epoEventId, epoObject );
3645
3646		return currentEpoObject;
3647	}
3648
3649	function checkFullSelection( epos, mode ) {
3650		var funcCallback = function( element ) {
3651			var elementToCheck = '';
3652			var _class;
3653			var noSplit = false;
3654			var radio_checked;
3655			var checkbox_checked;
3656			var val;
3657
3658			element = $( element );
3659			if ( element.is( '.cpf-type-product' ) ) {
3660				elementToCheck = ':not(' + tcAPI.associatedEpoSelector + ' .tm-epo-field)';
3661			}
3662			_class = element
3663				.attr( 'class' )
3664				.split( ' ' )
3665				.map( function( cls ) {
3666					if ( cls.indexOf( 'cpf-type-', 0 ) !== -1 ) {
3667						return cls;
3668					}
3669					return null;
3670				} )
3671				.filter( function( v ) {
3672					if ( v !== null && v !== undefined ) {
3673						return v;
3674					}
3675					return null;
3676				} );
3677
3678			if ( _class.length > 0 ) {
3679				_class = _class[ 0 ];
3680				if ( _class === 'cpf-type-product' ) {
3681					noSplit = true;
3682					if ( element.is( '.cpf-type-product-mode-product' ) || element.is( '.cpf-type-product-checkbox' ) || element.is( '.cpf-type-product-thumbnailmultiple' ) || element.is( '.cpf-type-product-custombundle' ) ) {
3683						_class = 'cpf-type-checkbox';
3684					} else if ( element.is( '.cpf-type-product-dropdown' ) ) {
3685						_class = 'cpf-type-select';
3686					} else {
3687						_class = 'cpf-type-radio';
3688					}
3689				}
3690				switch ( _class ) {
3691					case 'cpf-type-radio':
3692						radio_checked = element.find( 'input.tm-epo-field.tmcp-radio:checked' + elementToCheck );
3693						return radio_checked.length > 0;
3694
3695					case 'cpf-type-checkbox':
3696						checkbox_checked = element.find( 'input.tm-epo-field.tmcp-checkbox:checked' + elementToCheck );
3697						return checkbox_checked.length > 0;
3698
3699					case 'cpf-type-select':
3700						val = element.find( 'select.tm-epo-field.tmcp-select' + elementToCheck ).val();
3701						if ( val && ! noSplit ) {
3702							val = val.slice( 0, val.lastIndexOf( '_' ) );
3703						}
3704						break;
3705
3706					case 'cpf-type-selectmultiple':
3707						val = element.find( 'select.tm-epo-field.tmcp-selectmultiple' + elementToCheck ).val();
3708						if ( val && ! noSplit ) {
3709							val.forEach( function( option, i ) {
3710								val[ i ] = option.slice( 0, option.lastIndexOf( '_' ) );
3711							} );
3712						}
3713						break;
3714
3715					default:
3716						val = element.find( '.tm-epo-field' + elementToCheck ).val();
3717						break;
3718				}
3719				if ( Array.isArray( val ) ) {
3720					return val.some( function( item ) {
3721						return item !== '';
3722					} );
3723				}
3724				return val !== '';
3725			}
3726			return false;
3727		};
3728		if ( mode === 'some' ) {
3729			return epos.toArray().some( funcCallback );
3730		}
3731		return epos.toArray().every( funcCallback );
3732	}
3733
3734	function goto_error_item( item, epoEventId ) {
3735		var el = $.tcepo.errorObject[ epoEventId ] || item;
3736		var elsection;
3737		var elsectionlink;
3738		var cpfElement;
3739		var productSection;
3740		var pos;
3741
3742		if ( el ) {
3743			if ( TMEPOJS.tm_epo_disable_error_scroll !== 'yes' ) {
3744				elsection = el.closest( '.cpf-section' );
3745				elsectionlink = elsection.find( '.tm-section-link' );
3746				cpfElement = el.closest( '.cpf-element' );
3747				productSection = el.closest( '.cpf-type-product' ).closest( '.cpf-section' );
3748
3749				if ( productSection.length && productSection.find( '.tm-toggle' ).length ) {
3750					productSection.find( '.tm-toggle' ).trigger( 'openwrap.tmtoggle' );
3751				}
3752
3753				if ( elsection.find( '.tm-toggle' ).length ) {
3754					elsection.find( '.tm-toggle' ).trigger( 'openwrap.tmtoggle' );
3755				}
3756				if ( window.tc_validation_offset === undefined ) {
3757					window.tc_validation_offset = -100;
3758				}
3759				if ( elsection.is( '.section_popup' ) ) {
3760					errorContainer.tcScrollTo( elsectionlink, 300, window.tc_validation_offset );
3761					elsectionlink.trigger( 'click.tmsectionpoplink' );
3762				} else if ( elsection.is( '.tm-owl-slider-section' ) ) {
3763					pos = el.closest( '.owl-item' ).index();
3764					elsection.find( '.tcowl-carousel' ).trigger( 'to.owl.carousel', [ pos, 100 ] );
3765					setTimeout( function() {
3766						elsection.find( '.tcowl-carousel' ).trigger( 'refresh.owl.carousel' );
3767
3768						if ( cpfElement.length > 0 ) {
3769							errorContainer.tcScrollTo( cpfElement, 300, window.tc_validation_offset );
3770						}
3771					}, 200 );
3772				} else if ( elsection.is( '.tc-tabs-section' ) ) {
3773					pos = el.closest( '.tc-tab-slide' ).index();
3774					el.closest( '.tc-tabs' ).find( '.tc-tab-headers .tc-tab-header .tab-header[data-id="tc-tab-slide' + pos + '"]' ).trigger( 'click.tmtabs' );
3775					setTimeout( function() {
3776						if ( cpfElement.length > 0 ) {
3777							errorContainer.tcScrollTo( cpfElement, 300, window.tc_validation_offset );
3778						}
3779					}, 200 );
3780				} else if ( cpfElement.length > 0 ) {
3781					errorContainer.tcScrollTo( cpfElement, 300, window.tc_validation_offset );
3782				}
3783			}
3784
3785			if ( ! item ) {
3786				$.tcepo.errorObject[ epoEventId ] = false;
3787			}
3788		}
3789	}
3790
3791	function tm_limit_c_selection( field, prevent ) {
3792		var allowed = parseInt( field.attr( 'data-limit' ), 10 );
3793		var checked = false;
3794		var val;
3795		var q;
3796
3797		if ( allowed > 0 ) {
3798			checked = 0;
3799			field
3800				.closest( '.tm-extra-product-options-checkbox' )
3801				.find( "input.tm-epo-field[type='checkbox']:checked" )
3802				.toArray().forEach( function( cb ) {
3803					cb = $( cb );
3804					q = cb.closest( 'li.tmcp-field-wrap' ).find( 'input.tm-qty' );
3805					if ( q.length > 0 ) {
3806						val = parseInt( q.val(), 10 );
3807						if ( val <= 0 ) {
3808							val = 1;
3809						}
3810						checked = parseInt( checked, 10 ) + val;
3811					} else {
3812						checked = parseInt( checked, 10 ) + 1;
3813					}
3814				} );
3815			if ( checked > allowed ) {
3816				if ( prevent ) {
3817					field.prop( 'checked', '' ).trigger( 'change' );
3818				}
3819				return false;
3820			}
3821		}
3822		return true;
3823	}
3824
3825	function tm_exact_c_selection( field, prevent ) {
3826		var allowed = parseInt( field.attr( 'data-exactlimit' ), 10 );
3827		var checked = false;
3828		var val;
3829		var q;
3830
3831		if ( allowed > 0 ) {
3832			checked = 0;
3833			field
3834				.closest( '.tm-extra-product-options-checkbox' )
3835				.find( "input.tm-epo-field[type='checkbox']:checked" )
3836				.toArray().forEach( function( cb ) {
3837					cb = $( cb );
3838					q = cb.closest( 'li.tmcp-field-wrap' ).find( 'input.tm-qty' );
3839					if ( q.length > 0 ) {
3840						val = parseInt( q.val(), 10 );
3841						if ( val <= 0 ) {
3842							val = 1;
3843						}
3844						checked = parseInt( checked, 10 ) + val;
3845					} else {
3846						checked = parseInt( checked, 10 ) + 1;
3847					}
3848				} );
3849			if ( checked > allowed ) {
3850				if ( prevent ) {
3851					field.prop( 'checked', '' ).trigger( 'change' );
3852				}
3853				return false;
3854			}
3855		}
3856		return true;
3857	}
3858
3859	function tm_limit_cont( fields, main_product, epoEventId ) {
3860		var checkall = true;
3861		var first_error_obj = false;
3862		var limit;
3863		var eln;
3864		var checked;
3865		var val;
3866		var q;
3867		var ew;
3868		var em;
3869		var message;
3870
3871		fields.toArray().forEach( function( field ) {
3872			field = $( field );
3873			limit = field.find( "[type='checkbox'][data-limit]" );
3874			if ( limit.length && field_is_active( limit ) ) {
3875				eln = parseInt( limit.attr( 'data-limit' ), 10 );
3876				checked = 0;
3877				field.find( "input.tm-epo-field[type='checkbox']:checked" ).toArray().forEach( function( cb ) {
3878					cb = $( cb );
3879					q = cb.closest( 'li.tmcp-field-wrap' ).find( 'input.tm-qty' );
3880					if ( q.length > 0 ) {
3881						val = parseInt( q.val(), 10 );
3882						if ( val <= 0 ) {
3883							val = 1;
3884						}
3885						checked = parseInt( checked, 10 ) + val;
3886					} else {
3887						checked = parseInt( checked, 10 ) + 1;
3888					}
3889				} );
3890				ew = field.closest( '.cpf-element' );
3891				em = ew.find( 'div.tm-error-min' );
3892
3893				if ( eln < checked ) {
3894					checkall = false;
3895					first_error_obj = field;
3896					if ( eln === 1 ) {
3897						message = TMEPOJS.tm_epo_global_validator_messages.epolimitsingle.replaceAll( '{0}', eln );
3898					} else {
3899						message = TMEPOJS.tm_epo_global_validator_messages.epolimit.replaceAll( '{0}', eln );
3900					}
3901					if ( em.length ) {
3902						em.remove();
3903					}
3904					if ( TMEPOJS.tm_epo_global_error_label_placement === 'before' ) {
3905						field.closest( '.tc-element-container' ).before( '<div class="tm-error-min tm-error tc-cell tcwidth tcwidth-100">' + message + '</div>' );
3906					} else {
3907						field.closest( '.tc-element-container' ).after( '<div class="tm-error-min tm-error tc-cell tcwidth tcwidth-100">' + message + '</div>' );
3908					}
3909					main_product.find( tcAPI.addToCartButtonSelector ).first().removeClass( 'disabled loading fpd-disabled' ).prop( 'disabled', false );
3910				} else {
3911					em.remove();
3912				}
3913			}
3914		} );
3915		if ( first_error_obj ) {
3916			$.tcepo.errorObject[ epoEventId ] = first_error_obj;
3917		}
3918		return checkall;
3919	}
3920
3921	function tm_check_limit_cont( limit_cont, main_product, epoEventId ) {
3922		$.tcepo.formSubmitEvents[ epoEventId ][ $.tcepo.formSubmitEvents[ epoEventId ].length ] = {
3923			trigger: function() {
3924				return tm_limit_cont( limit_cont, main_product, epoEventId );
3925			},
3926			on_true: function() {
3927				return true;
3928			},
3929			on_false: function() {
3930				goto_error_item( $( limit_cont ).find( '.tm-epo-field' ).first(), epoEventId );
3931				return true;
3932			}
3933		};
3934	}
3935
3936	function tm_exactlimit_cont( fields, main_product, epoEventId ) {
3937		var checkall = true;
3938		var first_error_obj = false;
3939		var exactlimit;
3940		var eln;
3941		var checked;
3942		var val;
3943		var q;
3944		var ew;
3945		var em;
3946		var message;
3947
3948		fields.toArray().forEach( function( field ) {
3949			field = $( field );
3950			exactlimit = field.find( "[type='checkbox'][data-exactlimit]" );
3951			if ( exactlimit.length && field_is_active( exactlimit ) ) {
3952				eln = parseInt( exactlimit.attr( 'data-exactlimit' ), 10 );
3953				checked = 0;
3954				field.find( "input.tm-epo-field[type='checkbox']:checked" ).toArray().forEach( function( cb ) {
3955					cb = $( cb );
3956					q = cb.closest( 'li.tmcp-field-wrap' ).find( 'input.tm-qty' );
3957					if ( q.length > 0 ) {
3958						val = parseInt( q.val(), 10 );
3959						if ( val <= 0 ) {
3960							val = 1;
3961						}
3962						checked = parseInt( checked, 10 ) + val;
3963					} else {
3964						checked = parseInt( checked, 10 ) + 1;
3965					}
3966				} );
3967				ew = field.closest( '.cpf-element' );
3968				em = ew.find( 'div.tm-error-min' );
3969
3970				if ( eln !== checked ) {
3971					checkall = false;
3972					first_error_obj = field;
3973					if ( eln === 1 ) {
3974						message = TMEPOJS.tm_epo_global_validator_messages.epoexactsingle.replaceAll( '{0}', eln );
3975					} else {
3976						message = TMEPOJS.tm_epo_global_validator_messages.epoexact.replaceAll( '{0}', eln );
3977					}
3978					if ( em.length ) {
3979						em.remove();
3980					}
3981					if ( TMEPOJS.tm_epo_global_error_label_placement === 'before' ) {
3982						field.closest( '.tc-element-container' ).before( '<div class="tm-error-min tm-error tc-cell tcwidth tcwidth-100">' + message + '</div>' );
3983					} else {
3984						field.closest( '.tc-element-container' ).after( '<div class="tm-error-min tm-error tc-cell tcwidth tcwidth-100">' + message + '</div>' );
3985					}
3986					main_product.find( tcAPI.addToCartButtonSelector ).first().removeClass( 'disabled loading fpd-disabled' ).prop( 'disabled', false );
3987				} else {
3988					em.remove();
3989				}
3990			}
3991		} );
3992		if ( first_error_obj ) {
3993			$.tcepo.errorObject[ epoEventId ] = first_error_obj;
3994		}
3995		return checkall;
3996	}
3997
3998	function tm_check_exactlimit_cont( exactlimit_cont, main_product, epoEventId ) {
3999		$.tcepo.formSubmitEvents[ epoEventId ][ $.tcepo.formSubmitEvents[ epoEventId ].length ] = {
4000			trigger: function() {
4001				return tm_exactlimit_cont( exactlimit_cont, main_product, epoEventId );
4002			},
4003			on_true: function() {
4004				return true;
4005			},
4006			on_false: function() {
4007				goto_error_item( $( exactlimit_cont ).find( '.tm-epo-field' ).first(), epoEventId );
4008				return true;
4009			}
4010		};
4011	}
4012
4013	function tm_minimumlimit_cont( fields, epoEventId ) {
4014		var checkall = true;
4015		var first_error_obj = false;
4016		var eln;
4017		var checked;
4018		var val;
4019		var q;
4020		var ew;
4021		var em;
4022		var message;
4023
4024		fields.toArray().forEach( function( field ) {
4025			var minimumlimit;
4026
4027			field = $( field );
4028			minimumlimit = field.find( "[type='checkbox'][data-minimumlimit]" );
4029
4030			if ( minimumlimit.length && field_is_active( minimumlimit ) ) {
4031				eln = parseInt( minimumlimit.attr( 'data-minimumlimit' ), 10 );
4032				checked = 0;
4033				field.find( "input.tm-epo-field[type='checkbox']:checked" ).toArray().forEach( function( cb ) {
4034					cb = $( cb );
4035					q = cb.closest( 'li.tmcp-field-wrap' ).find( 'input.tm-qty' );
4036					if ( q.length > 0 ) {
4037						val = parseInt( q.val(), 10 );
4038						if ( val <= 0 ) {
4039							val = 1;
4040						}
4041						checked = parseInt( checked, 10 ) + val;
4042					} else {
4043						checked = parseInt( checked, 10 ) + 1;
4044					}
4045				} );
4046				ew = field.closest( '.cpf-element' );
4047				em = ew.find( 'div.tm-error-min' );
4048				if ( eln > checked ) {
4049					checkall = false;
4050					first_error_obj = field;
4051					if ( eln === 1 ) {
4052						message = TMEPOJS.tm_epo_global_validator_messages.epominsingle.replaceAll( '{0}', eln );
4053					} else {
4054						message = TMEPOJS.tm_epo_global_validator_messages.epomin.replaceAll( '{0}', eln );
4055					}
4056					if ( em.length ) {
4057						em.remove();
4058					}
4059					if ( TMEPOJS.tm_epo_global_error_label_placement === 'before' ) {
4060						field.closest( '.tc-element-container' ).before( '<div class="tm-error-min tm-error tc-cell tcwidth tcwidth-100">' + message + '</div>' );
4061					} else {
4062						field.closest( '.tc-element-container' ).after( '<div class="tm-error-min tm-error tc-cell tcwidth tcwidth-100">' + message + '</div>' );
4063					}
4064				} else {
4065					em.remove();
4066				}
4067			}
4068		} );
4069
4070		if ( first_error_obj ) {
4071			$.tcepo.errorObject[ epoEventId ] = first_error_obj;
4072		}
4073
4074		return checkall;
4075	}
4076
4077	function tm_check_minimumlimit_cont( minimumlimit_cont, epoEventId ) {
4078		$.tcepo.formSubmitEvents[ epoEventId ][ $.tcepo.formSubmitEvents[ epoEventId ].length ] = {
4079			trigger: function() {
4080				return tm_minimumlimit_cont( minimumlimit_cont, epoEventId );
4081			},
4082			on_true: function() {
4083				return true;
4084			},
4085			on_false: function() {
4086				goto_error_item( false, epoEventId );
4087				return true;
4088			}
4089		};
4090	}
4091
4092	function cleanPrice( price ) {
4093		if ( price === null ) {
4094			return 0;
4095		}
4096
4097		if ( typeof price === 'object' ) {
4098			price = price[ 0 ];
4099		}
4100
4101		if ( ! Number.isFinite( parseFloat( price ) ) ) {
4102			price = 0;
4103		}
4104
4105		return price;
4106	}
4107
4108	function tm_apply_dpd( price, totals, apply, force ) {
4109		price = cleanPrice( price );
4110
4111		if ( apply ) {
4112			price = $.epoAPI.applyFilter( 'tc_apply_dpd', price, totals, apply, force );
4113		}
4114
4115		return price;
4116	}
4117
4118	function tm_calculate_product_regular_price( totals, allowfalse ) {
4119		var price = 0;
4120
4121		if ( totals.length > 0 ) {
4122			price = totals.data( 'regular-price' );
4123		}
4124
4125		price = $.epoAPI.applyFilter( 'tc_calculate_product_regular_price', price, totals );
4126
4127		if ( allowfalse && price === false ) {
4128			return false;
4129		}
4130		price = parseFloat( price );
4131
4132		if ( ! Number.isFinite( price ) ) {
4133			price = 0;
4134		}
4135
4136		return price;
4137	}
4138
4139	function tm_calculate_product_price( totals, allowfalse ) {
4140		var price = 0;
4141
4142		if ( totals.length > 0 ) {
4143			price = totals.data( 'price' );
4144		}
4145
4146		price = $.epoAPI.applyFilter( 'tc_calculate_product_price', price, totals );
4147
4148		if ( allowfalse && price === false ) {
4149			return false;
4150		}
4151		price = parseFloat( price );
4152
4153		if ( ! Number.isFinite( price ) ) {
4154			price = 0;
4155		}
4156
4157		return price;
4158	}
4159
4160	function calculateMathPrice( price, thisElement, epoObject, noevents, useOriginalPrice, funcTotal, cumulativeTotal, mathskip ) {
4161		var formula = price.toString();
4162		var val = 0;
4163		var matches;
4164		var match;
4165		var elementWrap;
4166		var allElements;
4167		var element;
4168		var reg;
4169		var elementPrice = 0;
4170		var pos;
4171		var type;
4172		var id;
4173		var thisVal;
4174		var thisValForced;
4175		var thisElementId = thisElement.closest( '.cpf-element' ).attr( 'data-uniqid' );
4176		var thisElementWrap = thisElement.closest( '.tmcp-ul-wrap' );
4177		var totalsHolder_tc_totals_ob = epoObject.this_epo_totals_container.data( 'totalsHolder_tc_totals_ob' );
4178		var thisElementIndex = thisElementWrap.find( '.tmcp-field, .tmcp-fee-field, .tmcp-sub-fee-field' ).filter( ':checked' ).index( thisElement );
4179		var thisElementIndexForced = thisElementWrap.find( '.tmcp-field, .tmcp-fee-field, .tmcp-sub-fee-field' ).index( thisElement );
4180		var this_epo_container = epoObject.is_associated ? epoObject.this_epo_container : epoObject.this_epo_container.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector );
4181		var constants = $.epoAPI.util.parseJSON( TMEPOJS.tm_epo_math ) || {};
4182		var productPrice;
4183		var dynamicProductPrice;
4184		var __price;
4185		var __price_type;
4186
4187		if ( thisElementIndex === -1 && ! thisElement.is( '.tmcp-checkbox, .tmcp-radio' ) ) {
4188			thisElementIndex = 0;
4189		}
4190		if ( thisElementIndexForced === -1 && ! thisElement.is( '.tmcp-checkbox, .tmcp-radio' ) ) {
4191			thisElementIndexForced = 0;
4192		}
4193
4194		if ( ! thisElement.is( '.tcdisabled' ) && ! noevents && ! thisElement.data( 'addedtcEpoBeforeOptionPriceCalculation' ) ) {
4195			jWindow.on( 'tcEpoBeforeOptionPriceCalculation.math' + thisElementId, function() {
4196				tm_element_epo_rules( epoObject, thisElement, undefined, undefined, undefined, true );
4197			} );
4198			jWindow.on( 'tcEpoAfterNormalOptionPriceCalculation.math' + thisElementId, function() {
4199				thisElement.data( 'fetchOptionPrices', false );
4200				thisElement.data( 'fetchOptionPrices-forced', false );
4201				thisElement.data( 'fetchOptionPrices-fee', false );
4202				thisElement.data( 'fetchOptionPrices-fee-forced', false );
4203				thisElement.data( 'fetchOptionPrices-sub-fee', false );
4204				thisElement.data( 'fetchOptionPrices-sub-fee-forced', false );
4205			} );
4206			thisElement.data( 'addedtcEpoBeforeOptionPriceCalculation', 1 );
4207		}
4208
4209		if ( thisElement.is( '.tmcp-field' ) ) {
4210			if ( thisElement.data( 'fetchOptionPrices' ) ) {
4211				thisVal = thisElement.data( 'fetchOptionPrices' );
4212				thisValForced = thisElement.data( 'fetchOptionPrices-forced' );
4213			} else {
4214				thisVal = fetchOptionPrices( epoObject, thisElementWrap, '.tmcp-field', 0, 0, [], true, undefined, undefined, undefined, undefined, undefined, true );
4215				thisValForced = fetchOptionPrices( epoObject, thisElementWrap, '.tmcp-field', 0, 0, [], true, true, undefined, undefined, undefined, undefined, true );
4216				thisElement.data( 'fetchOptionPrices', thisVal );
4217				thisElement.data( 'fetchOptionPrices-forced', thisValForced );
4218			}
4219		} else if ( thisElement.is( '.tmcp-fee-field' ) ) {
4220			if ( thisElement.data( 'fetchOptionPrices-fee' ) ) {
4221				thisVal = thisElement.data( 'fetchOptionPrices-fee' );
4222				thisValForced = thisElement.data( 'fetchOptionPrices-fee-forced' );
4223			} else {
4224				thisVal = fetchOptionPrices( epoObject, thisElementWrap, '.tmcp-fee-field', 0, 0, [], true, undefined, undefined, undefined, undefined, undefined, true );
4225				thisValForced = fetchOptionPrices( epoObject, thisElementWrap, '.tmcp-fee-field', 0, 0, [], true, true, undefined, undefined, undefined, undefined, true );
4226				thisElement.data( 'fetchOptionPrices-fee', thisVal );
4227				thisElement.data( 'fetchOptionPrices-fee-forced', thisValForced );
4228			}
4229		} else if ( thisElement.is( '.tmcp-sub-fee-field' ) ) {
4230			if ( thisElement.data( 'fetchOptionPrices-sub-fee' ) ) {
4231				thisVal = thisElement.data( 'fetchOptionPrices-sub-fee' );
4232				thisValForced = thisElement.data( 'fetchOptionPrices-sub-fee-forced' );
4233			} else {
4234				thisVal = fetchOptionPrices( epoObject, thisElementWrap, '.tmcp-sub-fee-field', 0, 0, [], true, undefined, undefined, undefined, undefined, undefined, true );
4235				thisValForced = fetchOptionPrices( epoObject, thisElementWrap, '.tmcp-sub-fee-field', 0, 0, [], true, true, undefined, undefined, undefined, undefined, true );
4236				thisElement.data( 'fetchOptionPrices-sub-fee', thisVal );
4237				thisElement.data( 'fetchOptionPrices-sub-fee-forced', thisValForced );
4238			}
4239		}
4240
4241		Object.keys( constants ).forEach( function( key ) {
4242			var name;
4243			var value;
4244
4245			if ( constants[ key ].name !== '' && constants[ key ].value !== '' ) {
4246				name = constants[ key ].name;
4247				value = constants[ key ].value;
4248				if ( name.startsWith( '{' ) ) {
4249					formula = formula.replaceAll( name, value );
4250				} else if ( constants[ key ].name.isNumeric() ) {
4251					formula = formula.replaceAll( '{' + name + '}', value );
4252				} else {
4253					name = '{' + name + '}';
4254					if ( value.startsWith( '{' ) ) {
4255						formula = formula.replaceAll( name, value );
4256					} else {
4257						formula = formula.replaceAll( name, $.epoAPI.math.unformat( value.replace( ',', '.' ) ) );
4258					}
4259				}
4260			}
4261		} );
4262
4263		if ( totalsHolder_tc_totals_ob !== undefined ) {
4264			// product quantity
4265			formula = formula.replaceAll( '{quantity}', $.epoAPI.math.unformat( totalsHolder_tc_totals_ob.qty ) );
4266			// original product price
4267			if ( useOriginalPrice && totalsHolder_tc_totals_ob.original_product_price !== undefined ) {
4268				productPrice = $.epoAPI.math.unformat( totalsHolder_tc_totals_ob.original_product_price );
4269			} else {
4270				productPrice = $.epoAPI.math.unformat( totalsHolder_tc_totals_ob.product_price );
4271			}
4272			if ( totalsHolder_tc_totals_ob.dynamic_product_price !== undefined ) {
4273				dynamicProductPrice = $.epoAPI.math.unformat( totalsHolder_tc_totals_ob.dynamic_product_price );
4274			} else {
4275				dynamicProductPrice = 0;
4276			}
4277		} else {
4278			// product quantity
4279			formula = formula.replaceAll( '{quantity}', 0 );
4280			// original product price
4281			productPrice = 0;
4282			dynamicProductPrice = 0;
4283		}
4284
4285		productPrice = $.epoAPI.math.toFloat( productPrice );
4286
4287		formula = formula.replaceAll( '{product_price}', productPrice );
4288		formula = formula.replaceAll( '{dynamic_product_price}', dynamicProductPrice );
4289
4290		if ( ! funcTotal ) {
4291			funcTotal = 0;
4292		}
4293		funcTotal = $.epoAPI.math.toFloat( funcTotal );
4294
4295		if ( ! cumulativeTotal ) {
4296			cumulativeTotal = 0;
4297		}
4298		cumulativeTotal = $.epoAPI.math.toFloat( cumulativeTotal );
4299
4300		formula = formula.replaceAll( '{options_total}', funcTotal );
4301		formula = formula.replaceAll( '{product_price_plus_options_total}', productPrice + funcTotal );
4302		formula = formula.replaceAll( '{cumulative_total}', cumulativeTotal );
4303		formula = formula.replaceAll( '{product_price_plus_cumulative_total}', productPrice + cumulativeTotal );
4304
4305		if ( thisValForced.floatingBoxData !== undefined && thisValForced.floatingBoxData[ thisElementIndexForced ] !== undefined ) {
4306			// the option/element value to float
4307			if ( thisValForced.floatingBoxData[ thisElementIndexForced ].input_type === 'number' || thisValForced.floatingBoxData[ thisElementIndexForced ].input_type === 'hidden' ) {
4308				formula = formula
4309					.replaceAll( '{this.value}', $.epoAPI.math.toFloat( $.epoAPI.math.unformat( thisValForced.floatingBoxData[ thisElementIndexForced ].valueText ) ) );
4310			} else {
4311				formula = formula
4312					.replaceAll( '{this.value}', $.epoAPI.math.toFloat( $.epoAPI.math.unformat( thisValForced.floatingBoxData[ thisElementIndexForced ].valueText, tcAPI.localDecimalSeparator ) ) );
4313			}
4314			// the option/element raw value
4315			formula = formula.replaceAll( '{this.rawvalue}', thisValForced.floatingBoxData[ thisElementIndexForced ].valueText );
4316			// the option/element raw value
4317			formula = formula.replaceAll( '{this.text}', thisValForced.floatingBoxData[ thisElementIndexForced ].valueText );
4318			// the option/element value length
4319			formula = formula
4320				.replaceAll( '{this.value.length}', thisValForced.floatingBoxData[ thisElementIndexForced ].valueText.length );
4321		} else {
4322			formula = formula
4323				// the option/element value to float
4324				.replaceAll( '{this.value}', 0 )
4325				// the option/element raw value
4326				.replaceAll( '{this.rawvalue}', '' )
4327				// the option/element raw value
4328				.replaceAll( '{this.text}', '' )
4329				// the option/element value length
4330				.replaceAll( '{this.value.length}', 0 );
4331		}
4332
4333		formula = formula
4334			// the number of options the user has selected
4335			.replaceAll( '{this.count}', thisVal.floatingBoxData.length )
4336			// the total option quantity of this element
4337			.replaceAll(
4338				'{this.count.quantity}',
4339				thisVal.floatingBoxData
4340					.map( function( x ) {
4341						return x.quantity;
4342					} )
4343					.reduce( function( acc, thisval ) {
4344						return $.epoAPI.math.toFloat( acc ) + $.epoAPI.math.toFloat
4344( thisval );
4345					}, 0 )
4346			)
4347			// the option quantity of this element
4348			.replaceAll( '{this.quantity}', thisElement.data( 'tm-quantity' ) );
4349
4350		if ( formula.match( /\{(\s)*?field\.([^}]*)}/ ) ) {
4351			matches = formula.match( /\{(\s)*?field\.([^}]*)}/g );
4352			matches.forEach( function( field ) {
4353				match = field.match( /\{(\s)*?field\.([^}]*)}/ );
4354				if ( undefined !== match[ 2 ] && 'string' === typeof match[ 2 ] ) {
4355					pos = match[ 2 ].lastIndexOf( '.' );
4356					if ( pos !== -1 ) {
4357						id = match[ 2 ].substring( 0, pos );
4358						type = match[ 2 ].substring( pos + 1 );
4359
4360						if ( $.inArray( type, [ 'price', 'value', 'value.length', 'rawvalue', 'text', 'text.length', 'quantity', 'count', 'count.quantity' ] ) !== -1 ) {
4361							elementWrap = this_epo_container.find( "[data-uniqid='" + $.epoAPI.util.escapeSelector( id ) + "']" );
4362							if ( elementWrap.length ) {
4363								allElements = elementWrap.find( '.tmcp-field, .tmcp-fee-field, .tmcp-sub-fee-field' );
4364								element = allElements.first();
4365
4366								if ( ! thisElement.is( '.tcdisabled' ) && ! noevents && ! thisElement.data( 'addedfieldtcEpoBeforeOptionPriceCalculation' ) ) {
4367									jWindow.on( 'tcEpoBeforeOptionPriceCalculation.math' + thisElementId, function() {
4368										tm_element_epo_rules( epoObject, thisElement, undefined, undefined, undefined, true );
4369										thisElement.trigger( 'tm-math-select-change-html-all' );
4370									} );
4371									thisElement.data( 'addedfieldtcEpoBeforeOptionPriceCalculation', 1 );
4372								}
4373								val = 0;
4374								switch ( type ) {
4375									case 'text':
4376									case 'rawvalue':
4377										val = '';
4378										break;
4379								}
4380
4381								if ( elementWrap.is( '.tc-container-enabled' ) ) {
4382									if ( ! mathskip ) {
4383										allElements.toArray().forEach( function( singleElement ) {
4384											singleElement = $( singleElement );
4385											// For now we only recalculate dynamic elements
4386											if ( thisElement.attr( 'id' ) !== singleElement.attr( 'id' ) && ( thisElement.is( '.tmcp-dynamic' ) || singleElement.is( '.tmcp-dynamic' ) ) ) {
4387												tm_element_epo_rules( epoObject, singleElement, undefined, undefined, undefined, true, undefined, undefined, true );
4388											}
4389											if ( ! noevents && ! singleElement.data( 'addedmathevent' ) ) {
4390												singleElement.on( 'input.mathevent', function() {
4391													if ( ! thisElement.is( '.tcdisabled' ) ) {
4392														thisElement.trigger( 'change.cpf', { calculateMathPrice: 1 } );
4393													}
4394												} );
4395												singleElement.data( 'addedmathevent', 1 );
4396											}
4397										} );
4398									}
4399									if ( element.is( '.tmcp-field' ) ) {
4400										val = fetchOptionPrices( epoObject, elementWrap, '.tmcp-field', 0, 0, [], true, undefined, undefined, true, undefined, undefined, true );
4401									} else if ( element.is( '.tmcp-fee-field' ) ) {
4402										val = fetchOptionPrices( epoObject, elementWrap, '.tmcp-fee-field', 0, 0, [], true, undefined, undefined, true, undefined, undefined, true );
4403									} else if ( element.is( '.tmcp-sub-fee-field' ) ) {
4404										val = fetchOptionPrices( epoObject, elementWrap, '.tmcp-sub-fee-field', 0, 0, [], true, undefined, undefined, true, undefined, undefined, true );
4405									}
4406
4407									switch ( type ) {
4408										// element price
4409										case 'price':
4410											val = val.total;
4411											if ( thisElement.is( '.tmcp-dynamic' ) ) {
4412												__price = get_type( epoObject, element, 'price' );
4413												__price_type = get_type( epoObject, element, 'price_type' );
4414												if ( 'math' === __price_type && __price.includes( '{dynamic_product_price}' ) ) {
4415													val = 0;
4416												}
4417											}
4418											break;
4419
4420										// element value
4421										case 'value':
4422										case 'text':
4423										case 'rawvalue':
4424											if ( val.floatingBoxData ) {
4425												val = val.floatingBoxData
4426													.map( function( x ) {
4427														if ( x.input_type === 'number' || x.input_type === 'hidden' ) {
4428															if ( type === 'text' || type === 'rawvalue' ) {
4429																return x.valueText;
4430															}
4431															return $.epoAPI.math.unformat( x.valueText );
4432														}
4433														if ( type === 'text' || type === 'rawvalue' ) {
4434															return x.valueText;
4435														}
4436														return $.epoAPI.math.unformat( x.valueText, tcAPI.localIn
4436putDecimalSeparator );
4437													} )
4438													.reduce( function( acc, thisval ) {
4439														if ( type === 'text' || type === 'rawvalue' ) {
4440															return acc + thisval;
4441														}
4442														return $.epoAPI.math.toFloat( acc ) + $.epoAPI.math.toFloat( thisval );
4443													}, ( type === 'text' || type === 'rawvalue' ) ? '' : 0 );
4444
4445												if ( type === 'text' || type === 'rawvalue' ) {
4446													if ( val === '' ) {
4447														val = "''";
4448													} else if ( ! val.toString().isNumeric() ) {
4449														val = "'" + val.replaceAll( "'", "\\'" ) + "'";
4450													}
4451												}
4452											}
4453											break;
4454
4455										// element value length
4456										case 'value.length':
4457										case 'text.length':
4458											if ( val.floatingBoxData ) {
4459												val = val.floatingBoxData
4460													.map( function( x ) {
4461														return x.valueText;
4462													} )
4463													.reduce( function( acc, thisval ) {
4464														return $.epoAPI.math.toFloat( acc ) + thisval.length;
4465													}, 0 );
4466											}
4467											break;
4468
4469										// element quantity
4470										// the total option quantity of this element
4471										case 'quantity':
4472										case 'count.quantity':
4473											if ( val.floatingBoxData ) {
4474												val = val.floatingBoxData
4475													.map( function( x ) {
4476														return x.quantity;
4477													} )
4478													.reduce( function( acc, thisval ) {
4479														return $.epoAPI.math.toFloat( acc ) + $.epoAPI.math.toFloat( thisval );
4480													}, 0 );
4481											}
4482											break;
4483
4484										// number of element options the user has selected
4485										case 'count':
4486											if ( val.floatingBoxData ) {
4487												val = val.floatingBoxData.length;
4488											}
4489											break;
4490									}
4491									if ( type !== 'text' && type !== 'rawvalue' ) {
4492										val = $.epoAPI.math.toFloat( val );
4493										if ( ! Number.isFinite( val ) ) {
4494											val = 0;
4495										}
4496									}
4497								}
4498							} else {
4499								val = 0;
4500								switch ( type ) {
4501									case 'text':
4502									case 'rawvalue':
4503										val = '';
4504										break;
4505								}
4506							}
4507							reg = new RegExp( match[ 0 ] );
4508							if ( type === 'text' || type === 'rawvalue' ) {
4509								formula = val === '' ? formula.replace( reg, "''" ) : formula.replace( reg, val );
4510							} else {
4511								formula = ! Number.isFinite( val ) ? formula.replace( reg, "'" + val.replace( "'", "\\'" ) + "'" ) : formula.replace( reg, val );
4512							}
4513						}
4514					}
4515				}
4516			} );
4517		}
4518
4519		try {
4520			elementPrice = tcmexp.evaluate( formula );
4521		} catch ( e ) {
4522			elementPrice = 0;
4523		}
4524
4525		return elementPrice;
4526	}
4527
4528	function get_type( epoObject, obj, type ) {
4529		var element = $( obj );
4530		var setter = element;
4531		var cart;
4532		var current_variation;
4533		var rules;
4534		var rulestype;
4535		var _rulestype;
4536		var pricetype;
4537		var variation_id_selector;
4538		var _tmcpulwrap;
4539		var price;
4540		var _rules;
4541
4542		cart = epoObject.main_cart;
4543		variation_id_selector = "input[name^='variation_id']";
4544		if ( cart.find( 'input.variation_id' ).length > 0 ) {
4545			variation_id_selector = 'input.variation_id';
4546		}
4547		current_variation = cart.find( variation_id_selector ).val();
4548		// Get current woocommerce variation
4549		if ( ! current_variation ) {
4550			current_variation = 0;
4551		}
4552
4553		if ( element.is( 'select' ) ) {
4554			setter = element.find( 'option:selected' );
4555		}
4556
4557		rules = $.epoAPI.util.parseJSON( setter.attr( 'data-rules' ) );
4558		rulestype = $.epoAPI.util.parseJSON( setter.attr( 'data-rulestype' ) );
4559
4560		pricetype = '';
4561		if ( typeof rules === 'object' ) {
4562			if ( current_variation in rules ) {
4563				price = rules[ current_variation ];
4564			} else {
4565				_rules = $.epoAPI.util.parseJSON( element.closest( '.tmcp-ul-wrap' ).attr( 'data-rules' ) );
4566
4567				if ( typeof _rules === 'object' ) {
4568					if ( current_variation in _rules ) {
4569						price = _rules[ current_variation ];
4570					} else {
4571						price = rules[ 0 ];
4572					}
4573				} else {
4574					price = rules[ 0 ];
4575				}
4576			}
4577			if ( typeof rulestype === 'object' ) {
4578				if ( current_variation in rulestype ) {
4579					pricetype = rulestype[ current_variation ];
4580				} else {
4581					_rulestype = $.epoAPI.util.parseJSON( element.closest( '.tmcp-ul-wrap' ).attr( 'data-rulestype' ) );
4582					if ( typeof _rulestype === 'object' ) {
4583						if ( current_variation in _rulestype ) {
4584							pricetype = _rulestype[ current_variation ];
4585						} else {
4586							pricetype = rulestype[ 0 ];
4587						}
4588					} else {
4589						pricetype = rulestype[ 0 ];
4590					}
4591				}
4592			} else {
4593				rulestype = $.epoAPI.util.parseJSON( element.closest( '.tmcp-ul-wrap' ).attr( 'data-rulestype' ) );
4594				if ( typeof rulestype === 'object' ) {
4595					if ( current_variation in rulestype ) {
4596						pricetype = rulestype[ current_variation ];
4597					} else {
4598						pricetype = rulestype[ 0 ];
4599					}
4600				}
4601			}
4602		} else {
4603			_tmcpulwrap = element.closest( '.tmcp-ul-wrap' );
4604			rules = $.epoAPI.util.parseJSON( _tmcpulwrap.attr( 'data-rules' ) );
4605
4606			if ( typeof rules === 'object' ) {
4607				if ( current_variation in rules ) {
4608					price = rules[ current_variation ];
4609				} else {
4610					price = rules[ 0 ];
4611				}
4612				if ( typeof rulestype === 'object' ) {
4613					if ( current_variation in rulestype ) {
4614						pricetype = rulestype[ current_variation ];
4615					} else {
4616						_rulestype = $.epoAPI.util.parseJSON( _tmcpulwrap.attr( 'data-rulestype' ) );
4617						if ( typeof _rulestype === 'object' ) {
4618							if ( current_variation in _rulestype ) {
4619								pricetype = _rulestype[ current_variation ];
4620							} else {
4621								pricetype = rulestype[ 0 ];
4622							}
4623						} else {
4624							pricetype = rulestype[ 0 ];
4625						}
4626					}
4627				} else {
4628					rulestype = $.epoAPI.util.parseJSON( _tmcpulwrap.attr( 'data-rulestype' ) );
4629					if ( typeof rulestype === 'object' ) {
4630						if ( current_variation in rulestype ) {
4631							pricetype = rulestype[ current_variation ];
4632						} else {
4633							pricetype = rulestype[ 0 ];
4634						}
4635					}
4636				}
4637			}
4638		}
4639
4640		if ( typeof price === 'object' ) {
4641			price = price[ 0 ];
4642		}
4643
4644		if ( typeof pricetype === 'object' ) {
4645			pricetype = pricetype[ 0 ];
4646		}
4647		if ( element.is( '.tmcp-fee-field' ) ) {
4648			if ( $.inArray( pricetype, [ 'fee', 'stepfee', 'currentstepfee' ] ) !== -1 ) {
4649				pricetype = '';
4650			}
4651		}
4652
4653		if ( type === 'price' ) {
4654			return price;
4655		}
4656
4657		return pricetype;
4658	}
4659
4660	function wordLength( str ) {
4661		var regex = new RegExp( /[\p{L}\d!@#$%^&*()_+=\{[\}\]|\\"':;?/>.<,-]+/, 'gu' );
4662		var m;
4663		var len = 0;
4664
4665		while ( ( m = regex.exec( str ) ) !== null ) {
4666			// This is necessary to avoid infinite loops with zero-width matches
4667			if ( m.index === regex.lastIndex ) {
4668				regex.lastIndex++;
4669			}
4670			len = len + m.length;
4671		}
4672		return len;
4673	}
4674
4675	function tm_calculate_price_by_type( pricetype, price, original_price, setter, product_price, product_original_price, epoTotalsContainer, apply_dpd, funcTotal, cumulativeTotal, mathskip, manthnoevent, cart, element, epoObject, bundleid, epoEventId, is_range_field ) {
4676		var undiscounted_price;
4677		var freechars, textlength, cart_total, min_value;
4678		var mathopc = false;
4679		var setterValue = setter.val();
4680
4681		switch ( pricetype ) {
4682			case '':
4683				undiscounted_price = price;
4684				price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd );
4685				// original_price No change
4686				break;
4687			case 'fixednon':
4688				freechars = parseInt( setter.attr( 'data-freechars' ), 10 );
4689				if ( ! Number.isFinite( freechars ) ) {
4690					freechars = 0;
4691				}
4692				textlength = setterValue.length - freechars;
4693				if ( textlength <= 0 ) {
4694					price = 0;
4695				}
4696				undiscounted_price = price;
4697				price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd );
4698				break;
4699			case 'math':
4700				if ( price !== original_price ) {
4701					mathopc = true;
4702				} else {
4703					mathopc = false;
4704				}
4705				if ( mathopc ) {
4706					original_price = calculateMathPrice( original_price, element, epoObject, true, true, funcTotal, cumulativeTotal, mathskip );
4707				}
4708				price = calculateMathPrice( price, element, epoObject, manthnoevent, $.epoAPI.applyFilter( 'tc_use_undiscounted_price', undefined, element, cart, epoTotalsContainer ), funcTotal, cumulativeTotal, mathskip );
4709				if ( ! mathopc ) {
4710					original_price = price;
4711				}
4712				undiscounted_price = price;
4713				price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd );
4714				// original_price No other change
4715				break;
4716			case 'percent_cart_total':
4717				cart_total = parseFloat( TMEPOJS.cart_total );
4718
4719				if ( ! Number.isFinite( cart_total ) ) {
4720					cart_total = 0;
4721				}
4722				undiscounted_price = ( price / 100 ) * cart_total;
4723				price = ( tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) / 100 ) * cart_total;
4724				original_price = ( tm_apply_dpd( original_price, epoTotalsContainer, apply_dpd ) / 100 ) * cart_total;
4725				break;
4726
4727			case 'percent':
4728				undiscounted_price = ( price / 100 ) * product_price;
4729				price = ( tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) / 100 ) * product_price;
4730				original_price = ( original_price / 100 ) * product_original_price;
4731				break;
4732			case 'percentcurrenttotal':
4733				$.tcepo.lateFieldsPrices[ epoEventId ].push( {
4734					setter: setter,
4735					price: price,
4736					original_price: original_price,
4737					bundleid: bundleid,
4738					pricetype: pricetype
4739				} );
4740				setter.data( 'tm-price-for-late', price ).data( 'tm-original-price-for-late', original_price ).data( 'islate', 1 ).addClass( 'tm-epo-late-field' );
4741				undiscounted_price = 0;
4742				price = 0;
4743				original_price = 0;
4744				break;
4745			case 'fixedcurrenttotal':
4746				price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd );
4747				$.tcepo.lateFieldsPrices[ epoEventId ].push( {
4748					setter: setter,
4749					price: price,
4750					original_price: original_price,
4751					bundleid: bundleid,
4752					pricetype: pricetype
4753				} );
4754				setter.data( 'tm-price-for-late', price ).data( 'tm-original-price-for-late', original_price ).data( 'islate', 1 ).addClass( 'tm-epo-late-field' );
4755				undiscounted_price = 0;
4756				price = 0;
4757				original_price = 0;
4758				break;
4759			case 'word':
4760				undiscounted_price = price * wordLength( setterValue );
4761				price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) * wordLength( setterValue );
4762				original_price = original_price * wordLength( setterValue );
4763				break;
4764			case 'wordpercent':
4765				undiscounted_price = ( price / 100 ) * product_price * wordLength( setterValue );
4766				price = ( tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) / 100 ) * product_price * wordLength( setterValue );
4767				original_price = ( original_price / 100 ) * product_original_price * wordLength( setterValue );
4768				break;
4769			case 'wordnon':
4770				freechars = parseInt( setter.attr( 'data-freechars' ), 10 );
4771				if ( ! Number.isFinite( freechars ) ) {
4772					freechars = 0;
4773				}
4774				textlength = wordLength( setterValue ) - freechars;
4775				if ( textlength < 0 ) {
4776					textlength = 0;
4777				}
4778				undiscounted_price = price * textlength;
4779				price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) * textlength;
4780				original_price = original_price * textlength;
4781				break;
4782			case 'wordpercentnon':
4783				freechars = parseInt( setter.attr( 'data-freechars' ), 10 );
4784				if ( ! Number.isFinite( freechars ) ) {
4785					freechars = 0;
4786				}
4787				textlength = wordLength( setterValue ) - freechars;
4788				if ( textlength < 0 ) {
4789					textlength = 0;
4790				}
4791				undiscounted_price = ( price / 100 ) * product_price * textlength;
4792				price = ( tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) / 100 ) * product_price * textlength;
4793				original_price = ( original_price / 100 ) * product_original_price * textlength;
4794				break;
4795
4796			case 'char':
4797				undiscounted_price = price * setterValue.length;
4798				price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) * setterValue.length;
4799				original_price = original_price * setterValue.length;
4800				break;
4801			case 'charpercent':
4802				undiscounted_price = ( price / 100 ) * product_price * setterValue.length;
4803				price = ( tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) / 100 ) * product_price * setterValue.length;
4804				original_price = ( original_price / 100 ) * product_original_price * setterValue.length;
4805				break;
4806			case 'charnospaces':
4807				undiscounted_price = price * setterValue.replace( /\s/g, '' ).length;
4808				price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) * setterValue.replace( /\s/g, '' ).length;
4809				original_price = original_price * setterValue.replace( /\s/g, '' ).length;
4810				break;
4811			case 'charnofirst':
4812				textlength = setterValue.length - 1;
4813				if ( textlength < 0 ) {
4814					textlength = 0;
4815				}
4816				undiscounted_price = price * textlength;
4817				price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) * textlength;
4818				original_price = original_price * textlength;
4819				break;
4820
4821			case 'charnon':
4822				freechars = parseInt( setter.attr( 'data-freechars' ), 10 );
4823				if ( ! Number.isFinite( freechars ) ) {
4824					freechars = 0;
4825				}
4826				textlength = setterValue.length - freechars;
4827				if ( textlength < 0 ) {
4828					textlength = 0;
4829				}
4830				undiscounted_price = price * textlength;
4831				price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) * textlength;
4832				original_price = original_price * textlength;
4833				break;
4834			case 'charpercentnon':
4835				freechars = parseInt( setter.attr( 'data-freechars' ), 10 );
4836				if ( ! Number.isFinite( freechars ) ) {
4837					freechars = 0;
4838				}
4839				textlength = setterValue.length - freechars;
4840				if ( textlength < 0 ) {
4841					textlength = 0;
4842				}
4843				undiscounted_price = ( price / 100 ) * product_price * textlength;
4844				price = ( tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) / 100 ) * product_price * textlength;
4845				original_price = ( original_price / 100 ) * product_original_price * textlength;
4846				break;
4847			case 'charnonnospaces':
4848				freechars = parseInt( setter.attr( 'data-freechars' ), 10 );
4849				if ( ! Number.isFinite( freechars ) ) {
4850					freechars = 0;
4851				}
4852				textlength = setterValue.replace( /\s/g, '' ).length - freechars;
4853				if ( textlength < 0 ) {
4854					textlength = 0;
4855				}
4856				undiscounted_price = price * textlength;
4857				price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) * textlength;
4858				original_price = original_price * textlength;
4859				break;
4860			case 'charpercentnonnospaces':
4861				freechars = parseInt( setter.attr( 'data-freechars' ), 10 );
4862				if ( ! Number.isFinite( freechars ) ) {
4863					freechars = 0;
4864				}
4865				textlength = setterValue.replace( /\s/g, '' ).length - freechars;
4866				if ( textlength < 0 ) {
4867					textlength = 0;
4868				}
4869				undiscounted_price = ( price / 100 ) * product_price * textlength;
4870				price = ( tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) / 100 ) * product_price * textlength;
4871				original_price = ( original_price / 100 ) * product_original_price * textlength;
4872				break;
4873
4874			case 'charpercentnofirst':
4875				textlength = setterValue.length - 1;
4876				if ( textlength < 0 ) {
4877					textlength = 0;
4878				}
4879				undiscounted_price = ( price / 100 ) * product_price * textlength;
4880				price = ( tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) / 100 ) * product_price * textlength;
4881				original_price = ( original_price / 100 ) * product_original_price * textlength;
4882				break;
4883			case 'step':
4884				if ( is_range_field ) {
4885					undiscounted_price = price * setterValue;
4886					price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) * setterValue;
4887					original_price = original_price * $.epoAPI.math.toFloat( setterValue );
4888				} else {
4889					undiscounted_price = price * $.epoAPI.math.toFloat( setterValue );
4890					price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) * $.epoAPI.math.toFloat( setterValue );
4891					original_price = original_price * $.epoAPI.math.toFloat( setterValue );
4892				}
4893				break;
4894			case 'currentstep':
4895				if ( is_range_field ) {
4896					undiscounted_price = setterValue;
4897					price = tm_apply_dpd( setterValue, epoTotalsContainer, apply_dpd );
4898					original_price = tm_apply_dpd( setterValue, epoTotalsContainer, apply_dpd );
4899				} else {
4900					undiscounted_price = $.epoAPI.math.toFloat( setterValue );
4901					price = tm_apply_dpd( $.epoAPI.math.toFloat( setterValue ), epoTotalsContainer, apply_dpd );
4902					original_price = tm_apply_dpd( $.epoAPI.math.toFloat( setterValue ), epoTotalsContainer, apply_dpd );
4903				}
4904				break;
4905			case 'intervalstep':
4906				if ( is_range_field ) {
4907					min_value = parseFloat( $( '.tm-range-picker[data-field-id="' + setter.attr( 'id' ) + '"]' ).attr( 'data-min' ) );
4908					undiscounted_price = price * ( setterValue - min_value );
4909					price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) * ( setterValue - min_value );
4910					original_price = original_price * ( setterValue - min_value );
4911				}
4912				break;
4913			case 'row':
4914				undiscounted_price = price * ( ( setterValue.match( /(\r\n|\n|\r)/gm ) || [] ).length + 1 );
4915				price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) * ( ( setterValue.match( /(\r\n|\n|\r)/gm ) || [] ).length + 1 );
4916				original_price = original_price * ( ( setterValue.match( /(\r\n|\n|\r)/gm ) || [] ).length + 1 );
4917				break;
4918		}
4919
4920		return {
4921			price: price,
4922			original_price: original_price,
4923			undiscounted_price: undiscounted_price
4924		};
4925	}
4926
4927	// Set field price rules
4928	function tm_element_epo_rules( epoObject, obj, args, setter_override, noremove, manthnoevent, funcTotal, cumulativeTotal, mathskip ) {
4929		var element = obj instanceof $ ? obj : $( obj );
4930		var setterall = element;
4931		var cart;
4932		var current_variation;
4933		var bundleid;
4934		var epoTotalsContainer;
4935		var apply_dpd;
4936		var product_price;
4937		var product_original_price;
4938		var is_range_field = element.is( '.tmcp-range' );
4939		var rules;
4940		var rulestype;
4941		var original_rules;
4942		var _rules;
4943		var _rulestype;
4944		var _original_rules;
4945		var pricetype;
4946		var price;
4947		var original_price;
4948		var raw_price;
4949		var raw_original_price;
4950		var formatted_price = '';
4951		var main_product = epoObject.main_product;
4952		var epoEventId = epoObject.epoEventId;
4953		var variation_id_selector;
4954		var _tmcpulwrap;
4955		var per_product_pricing = true;
4956		var addedPrice = 0;
4957		var originalAddedPrice = 0;
4958		var undiscounted_raw_price;
4959		var undiscounted_raw_original_price;
4960		var undiscounted_price;
4961		var undiscounted_original_price;
4962		var isFilled;
4963		var useFormattedPrice = false;
4964		var priceResult;
4965
4966		if ( element.data( 'associated_price_set' ) ) {
4967			return;
4968		}
4969
4970		if ( ! args ) {
4971			cart = epoObject.main_cart;
4972			if ( cart.data( 'per_product_pricing' ) !== undefined ) {
4973				per_product_pricing = cart.data( 'per_product_pricing' );
4974			}
4975			variation_id_selector = "input[name^='variation_id']";
4976			if ( cart.find( 'input.variation_id' ).length > 0 ) {
4977				variation_id_selector = 'input.variation_id';
4978			}
4979			current_variation = cart.find( variation_id_selector ).val();
4980
4981			bundleid = $.epoAPI.applyFilter( 'tc_get_bundleid', cart.attr( 'data-product_id' ), cart, epoObject );
4982
4983			// Get current woocommerce variation
4984			if ( ! current_variation ) {
4985				current_variation = 0;
4986			}
4987
4988			epoTotalsContainer = $.epoAPI.applyFilter( 'tc_get_totals_container', epoObject.this_epo_totals_container, element, main_product, bundleid );
4989			product_price = tm_calculate_product_price( epoTotalsContainer );
4990			product_original_price = tm_calculate_product_regular_price( epoTotalsContainer );
4991			apply_dpd = epoTotalsContainer.data( 'fields-price-rules' );
4992		} else {
4993			cart = args.cart;
4994			current_variation = args.current_variation;
4995
4996			bundleid = args.bundleid;
4997			epoTotalsContainer = args.epoTotalsContainer;
4998			product_price = args.product_price;
4999			product_original_price = args.product_original_price;
5000			apply_dpd = args.apply_dpd;
5001			per_product_pricing = args.per_product_pricing;
5002		}
5003		product_price = $.epoAPI.applyFilter( 'tc_alter_product_price', product_price, element, cart, epoTotalsContainer, bundleid );
5004		product_original_price = $.epoAPI.applyFilter( 'tc_alter_product_original_price', product_original_price, element, cart, epoTotalsContainer );
5005
5006		if ( product_price === false || ! per_product_pricing ) {
5007			return;
5008		}
5009
5010		if ( element.is( 'select' ) ) {
5011			setterall = element.find( 'option:selected' );
5012		}
5013		if ( setter_override ) {
5014			setterall = setter_override;
5015		}
5016
5017		setterall.toArray().forEach( function( setter ) {
5018			setter = $( setter );
5019
5020			rules = $.epoAPI.util.parseJSON( setter.attr( 'data-rules' ) );
5021			rulestype = $.epoAPI.util.parseJSON( setter.attr( 'data-rulestype' ) );
5022			original_rules = $.epoAPI.util.parseJSON( setter.attr( 'data-original-rules' ) );
5023			if ( element.is( '.tmcp-dynamic' ) ) {
5024				rules = $.epoAPI.util.parseJSON( setter.attr( 'data-formula' ) );
5025				original_rules = $.epoAPI.util.parseJSON( setter.attr( 'data-formula' ) );
5026				rulestype = $.epoAPI.util.parseJSON( setter.attr( 'data-calculation-type' ) );
5027			}
5028			if ( original_rules === undefined ) {
5029				original_rules = rules;
5030			}
5031
5032			pricetype = '';
5033			if ( typeof rules === 'object' ) {
5034				if ( current_variation in rules ) {
5035					price = rules[ current_variation ];
5036					original_price = original_rules[ current_variation ];
5037				} else {
5038					_rules = $.epoAPI.util.parseJSON( element.closest( '.tmcp-ul-wrap' ).attr( 'data-rules' ) );
5039					_original_rules = element.closest( '.tmcp-ul-wrap' ).data( 'original-rules' );
5040
5041					if ( typeof _rules === 'object' ) {
5042						if ( current_variation in _rules ) {
5043							price = _rules[ current_variation ];
5044						} else {
5045							price = rules[ 0 ];
5046						}
5047					} else {
5048						price = rules[ 0 ];
5049					}
5050
5051					if ( typeof _original_rules === 'object' ) {
5052						if ( current_variation in _original_rules ) {
5053							original_price = _original_rules[ current_variation ];
5054						} else {
5055							original_price = original_rules[ 0 ];
5056						}
5057					} else {
5058						original_price = original_rules[ 0 ];
5059					}
5060				}
5061
5062				if ( typeof rulestype === 'object' ) {
5063					if ( current_variation in rulestype ) {
5064						pricetype = rulestype[ current_variation ];
5065					} else {
5066						_rulestype = $.epoAPI.util.parseJSON( element.closest( '.tmcp-ul-wrap' ).attr( 'data-rulestype' ) );
5067						if ( typeof _rulestype === 'object' ) {
5068							if ( current_variation in _rulestype ) {
5069								pricetype = _rulestype[ current_variation ];
5070							} else {
5071								pricetype = rulestype[ 0 ];
5072							}
5073						} else {
5074							pricetype = rulestype[ 0 ];
5075						}
5076					}
5077				} else {
5078					rulestype = $.epoAPI.util.parseJSON( element.closest( '.tmcp-ul-wrap' ).attr( 'data-rulestype' ) );
5079					if ( typeof rulestype === 'object' ) {
5080						if ( current_variation in rulestype ) {
5081							pricetype = rulestype[ current_variation ];
5082						} else {
5083							pricetype = rulestype[ 0 ];
5084						}
5085					}
5086				}
5087			} else {
5088				_tmcpulwrap = element.closest( '.tmcp-ul-wrap' );
5089				rules = $.epoAPI.util.parseJSON( _tmcpulwrap.attr( 'data-rules' ) );
5090				original_rules = $.epoAPI.util.parseJSON( _tmcpulwrap.attr( 'data-original-rules' ) );
5091
5092				if ( typeof rules === 'object' ) {
5093					if ( current_variation in rules ) {
5094						price = rules[ current_variation ];
5095					} else {
5096						price = rules[ 0 ];
5097					}
5098					if ( typeof original_rules === 'object' ) {
5099						if ( current_variation in original_rules ) {
5100							original_price = original_rules[ current_variation ];
5101						} else {
5102							original_price = original_rules[ 0 ];
5103						}
5104					} else {
5105						original_price = price;
5106					}
5107
5108					if ( typeof rulestype === 'object' ) {
5109						if ( current_variation in rulestype ) {
5110							pricetype = rulestype[ current_variation ];
5111						} else {
5112							_rulestype = $.epoAPI.util.parseJSON( _tmcpulwrap.attr( 'data-rulestype' ) );
5113							if ( typeof _rulestype === 'object' ) {
5114								if ( current_variation in _rulestype ) {
5115									pricetype = _rulestype[ current_variation ];
5116								} else {
5117									pricetype = rulestype[ 0 ];
5118								}
5119							} else {
5120								pricetype = rulestype[ 0 ];
5121							}
5122						}
5123					} else {
5124						rulestype = $.epoAPI.util.parseJSON( _tmcpulwrap.attr( 'data-rulestype' ) );
5125						if ( typeof rulestype === 'object' ) {
5126							if ( current_variation in rulestype ) {
5127								pricetype = rulestype[ current_variation ];
5128							} else {
5129								pricetype = rulestype[ 0 ];
5130							}
5131						}
5132					}
5133				}
5134			}
5135
5136			if ( typeof pricetype === 'object' ) {
5137				pricetype = pricetype[ 0 ];
5138			}
5139			if ( element.is( '.tmcp-fee-field' ) ) {
5140				if ( $.inArray( pricetype, [ 'fee', 'stepfee', 'currentstepfee' ] ) !== -1 ) {
5141					pricetype = '';
5142				}
5143				apply_dpd = 0;
5144			}
5145
5146			if ( noremove === undefined ) {
5147				if ( element.is( 'select' ) ) {
5148					element.find( 'option' ).removeClass( 'tm-epo-late-field' ).removeData( 'tm-price-for-late islate' );
5149				} else {
5150					setter.removeClass( 'tm-epo-late-field' ).removeData( 'tm-price-for-late islate' );
5151				}
5152			}
5153			if ( pricetype !== 'math' ) {
5154				price = cleanPrice( price );
5155				original_price = cleanPrice( original_price );
5156			} else if ( typeof price === 'object' ) {
5157				price = price[ 0 ];
5158			}
5159
5160			undiscounted_raw_price = price;
5161			undiscounted_raw_original_price = original_price;
5162
5163			priceResult = tm_calculate_price_by_type(
5164				pricetype, price, original_price, setter,
5165				product_price, product_original_price,
5166				epoTotalsContainer, apply_dpd,
5167				funcTotal, cumulativeTotal, mathskip,
5168				manthnoevent, cart, element, epoObject,
5169				bundleid, epoEventId, is_range_field
5170			);
5171			price = priceResult.price;
5172			original_price = priceResult.original_price;
5173			undiscounted_price = priceResult.undiscounted_price;
5174
5175			raw_price = price;
5176			raw_original_price = original_price;
5177
5178			undiscounted_original_price = original_price;
5179			undiscounted_raw_price = undiscounted_price;
5180			undiscounted_raw_original_price = undiscounted_original_price;
5181
5182			if ( element.data( 'tm-quantity' ) ) {
5183				undiscounted_price = undiscounted_price * parseFloat( element.data( 'tm-quantity' ) );
5184				undiscounted_original_price = undiscounted_original_price * parseFloat( element.data( 'tm-quantity' ) );
5185				undiscounted_raw_price = undiscounted_raw_price * parseFloat( element.data( 'tm-quantity' ) );
5186				undiscounted_raw_original_price = undiscounted_raw_original_price * parseFloat( element.data( 'tm-quantity' ) );
5187
5188				price = price * parseFloat( element.data( 'tm-quantity' ) );
5189				original_price = original_price * parseFloat( element.data( 'tm-quantity' ) );
5190				raw_price = raw_price * parseFloat( element.data( 'tm-quantity' ) );
5191				raw_original_price = raw_original_price * parseFloat( element.data( 'tm-quantity' ) );
5192			}
5193
5194			addedPrice = addedPrice + parseFloat( price );
5195			originalAddedPrice = originalAddedPrice + parseFloat( original_price );
5196
5197			element.data( 'price_set', 1 );
5198			setter.data( 'price_set', 1 );
5199
5200			setter.data( 'undiscounted_raw_price', undiscounted_raw_price );
5201			setter.data( 'undiscounted_raw_original_price', undiscounted_raw_original_price );
5202			setter.data( 'undiscounted_price', tm_set_tax_price( undiscounted_price, epoTotalsContainer, setter, pricetype ) );
5203			setter.data( 'undiscounted_original_price', tm_set_tax_price( undiscounted_original_price, epoTotalsContainer, setter, pricetype ) );
5204
5205			setter.data( 'raw_price', raw_price );
5206			setter.data( 'raw_original_price', raw_original_price );
5207			setter.data( 'price', tm_set_tax_price( price, epoTotalsContainer, setter, pricetype ) );
5208			setter.data( 'original_price', tm_set_tax_price( original_price, epoTotalsContainer, setter, pricetype ) );
5209
5210			if ( ! setter_override ) {
5211				if ( element.is( '.tc-epo-field-product' ) ) {
5212					isFilled = false;
5213					if ( element.is( 'select' ) ) {
5214						if ( element.val() !== '' ) {
5215							isFilled = true;
5216						}
5217					} else if ( ( element.is( ':checkbox' ) || element.is( ':radio' ) ) ) {
5218						if ( element.is( ':checked' ) ) {
5219							isFilled = true;
5220						}
5221					} else if ( element.val() !== '' ) {
5222						isFilled = true;
5223					}
5224
5225					if ( ! isFilled ) {
5226						formatted_price = setter.data( 'price-html' );
5227						useFormattedPrice = true;
5228					}
5229				}
5230				tm_update_price( {
5231					epoObject: epoObject,
5232					obj: setter.closest( '.tmcp-field-wrap' ).find( '.tc-price' ),
5233					price: tm_get_price( addedPrice, epoTotalsContainer, false, setter, pricetype ),
5234					formatted_price: formatted_price,
5235					original_price: tm_get_price( originalAddedPrice, epoTotalsContainer, false, setter, pricetype ),
5236					force: false,
5237					useFormattedPrice: useFormattedPrice
5238				} );
5239				element.data( 'price-changed', 1 );
5240			}
5241		} );
5242	}
5243
5244	function tm_epo_rules( epoObject, theCart ) {
5245		var all_carts;
5246		var variation_id_selector;
5247		var per_product_pricing = true;
5248		var current_variation;
5249		var bundleid;
5250		var epoContainer;
5251		var epoTotalsContainer;
5252		var apply_dpd;
5253		var rules;
5254		var original_rules;
5255		var price;
5256		var original_price;
5257		var product_price;
5258		var product_original_price;
5259		var all_fields;
5260		var active_fields;
5261		var args;
5262		var main_product = epoObject.main_product;
5263		var epoEventId = epoObject.epoEventId;
5264		var this_epo_container = epoObject.this_epo_container;
5265		var this_epo_totals_container = epoObject.this_epo_totals_container;
5266
5267		if ( ! theCart ) {
5268			all_carts = main_product.find( '.cart' );
5269		} else {
5270			all_carts = theCart;
5271		}
5272		if ( all_carts.length <= 0 ) {
5273			return;
5274		}
5275
5276		$.tcepo.lateFieldsPrices[ epoEventId ] = [];
5277
5278		all_carts.toArray().forEach( function( cart ) {
5279			cart = $( cart );
5280			variation_id_selector = "input[name^='variation_id']";
5281			if ( cart.find( 'input.variation_id' ).length > 0 ) {
5282				variation_id_selector = 'input.variation_id';
5283			}
5284
5285			if ( cart.data( 'per_product_pricing' ) !== undefined ) {
5286				per_product_pricing = cart.data( 'per_product_pricing' );
5287			}
5288
5289			current_variation = cart.find( variation_id_selector ).val();
5290			bundleid = $.epoAPI.applyFilter( 'tc_get_bundleid', cart.attr( 'data-product_id' ), cart, epoObject );
5291
5292			// get current woocommerce variation
5293			if ( ! current_variation ) {
5294				current_variation = 0;
5295			}
5296
5297			epoContainer = $.epoAPI.applyFilter( 'tc_get_epo_container', this_epo_container, cart, main_product, bundleid );
5298			epoTotalsContainer = $.epoAPI.applyFilter( 'tc_get_totals_container', this_epo_totals_container, cart, main_product, bundleid );
5299
5300			// WooCommerce Dynamic Pricing & Discounts
5301			apply_dpd = epoTotalsContainer.data( 'fields-price-rules' );
5302
5303			// set initial prices for all fields
5304			if ( ! epoContainer.data( 'tm_rules_init_done' ) ) {
5305				if ( epoTotalsContainer.data( 'force-quantity' ) ) {
5306					cart.find( tcAPI.qtySelector ).val( epoTotalsContainer.data( 'force-quantity' ) );
5307				}
5308				epoContainer.toArray().forEach( function( el ) {
5309					$( el ).closest( '.tmcp-field-wrap' ).find( '.tm-epo-field' ).data( 'tm-quantity', $( el ).val() );
5310				} );
5311
5312				epoContainer
5313					.find( '.tmcp-attributes, .tmcp-elements' )
5314					.toArray()
5315					.forEach( function( element ) {
5316						element = $( element );
5317						rules = $.epoAPI.util.parseJSON( element.attr( 'data-rules' ) );
5318						original_rules = $.epoAPI.util.parseJSON( element.attr( 'data-original-rules' ) );
5319
5320						// if rule doesn't exit then init an empty rule
5321						if ( typeof rules !== 'object' ) {
5322							rules = {
5323								0: '0'
5324							};
5325						}
5326						if ( typeof original_rules !== 'object' ) {
5327							original_rules = {
5328								0: '0'
5329							};
5330						}
5331						if ( typeof rules === 'object' ) {
5332							// we skip price validation test so that every field has at least a price of 0
5333							price = tm_apply_dpd( rules[ $.epoAPI.math.toFloat( current_variation ) ], epoTotalsContainer, apply_dpd );
5334							original_price = tm_apply_dpd( original_rules[ $.epoAPI.math.toFloat( current_variation ) ], epoTotalsContainer, apply_dpd );
5335
5336							element
5337								.find( '.tmcp-field, .tmcp-fee-field ' )
5338								.toArray()
5339								.forEach( function( el ) {
5340									el = $( el );
5341									if ( per_product_pricing ) {
5342										if ( el.attr( 'data-no-price' ) === '1' ) {
5343											price = 0;
5344											original_price = 0;
5345										}
5346										el.data( 'raw_price', price );
5347										el.data( 'raw_original_price', original_price );
5348
5349										el.data( 'price', tm_set_tax_price( price, epoTotalsContainer, el ) );
5350										el.data( 'original_price', tm_set_tax_price( original_price, epoTotalsContainer, el ) );
5351
5352										tm_update_price( {
5353											epoObject: epoObject,
5354											obj: el.closest( '.tmcp-field-wrap' ).find( '.tc-price' ),
5355											price: tm_get_price( price, epoTotalsContainer ),
5356											original_price: tm_get_price( original_price, epoTotalsContainer ),
5357											force: false,
5358											useFormattedPrice: false
5359										} );
5360									} else {
5361										el.data( 'price', 0 );
5362										el.data( 'original_price', 0 );
5363										el.closest( '.tmcp-field-wrap' ).find( '.amount' ).empty();
5364									}
5365								} );
5366						}
5367					} );
5368				epoContainer.data( 'tm_rules_init_done', 1 );
5369			}
5370
5371			// skip specific field rules if per_product_pricing is false
5372			if ( ! per_product_pricing ) {
5373				return true;
5374			}
5375
5376			product_price = tm_calculate_product_price( epoTotalsContainer );
5377			product_original_price = tm_calculate_product_regular_price( epoTotalsContainer );
5378
5379			args = {
5380				cart: cart,
5381				current_variation: current_variation,
5382				bundleid: bundleid,
5383				epoTotalsContainer: epoTotalsContainer,
5384				product_price: product_price,
5385				product_original_price: product_original_price,
5386				apply_dpd: apply_dpd,
5387				per_product_pricing: per_product_pricing
5388			};
5389
5390			all_fields = epoContainer.find( '.tmcp-field,.tmcp-sub-fee-field,.tmcp-fee-field' );
5391			if ( ! epoObject.is_associated ) {
5392				all_fields = all_fields.not( tcAPI.associatedEpoSelector + ' ' + '.tmcp-field,' + tcAPI.associatedEpoSelector + ' ' + '.tmcp-sub-fee-field,' + tcAPI.associatedEpoSelector + ' ' + '.tmcp-fee-field' );
5393			}
5394			active_fields = all_fields.filter( '.tcenabled' );
5395
5396			// note: find a better way if any
5397			if ( ! $.tcepo.initialActivation[ epoEventId ] || ( active_fields.length === 0 && all_fields.length > 0 ) ) {
5398				all_fields.toArray().forEach( function( el ) {
5399					field_is_active( $( el ) );
5400				} );
5401				epoContainer.find( '.cpf-type-divider,.cpf-type-header' ).toArray().forEach( function( el ) {
5402					field_is_active( $( el ) );
5403				} );
5404
5405				$.tcepo.initialActivation[ epoEventId ] = true;
5406			}
5407
5408			//  apply specific field rules
5409			all_fields.filter( '.tcenabled' ).toArray().forEach( function( element ) {
5410				tm_element_epo_rules( epoObject, element, args );
5411			} );
5412
5413			all_fields.toArray().forEach( function( element ) {
5414				$( element ).on( 'tc_element_epo_rules', function() {
5415					tm_element_epo_rules( epoObject, element, args );
5416				} );
5417			} );
5418		} );
5419	}
5420
5421	function add_late_fields_prices( epoObject, currentProductPrice, originalProductPrice, options_total, original_options_total, bid, _cart, applydpd ) {
5422		var total = 0;
5423		var originalTotal = 0;
5424		var totalFees = 0;
5425		var originalTotalFees = 0;
5426		var price;
5427		var originalPrice;
5428		var priceType;
5429		var setter;
5430		var id;
5431		var hidden;
5432		var bundleid;
5433		var realSetter;
5434		var productId;
5435		var epoId;
5436		var epoEventId = epoObject.epoEventId;
5437		var taxPrice;
5438		var taxOriginalPrice;
5439		var hiddenName;
5440		var productPrice;
5441		var oProductPrice;
5442		var apply_dpd;
5443
5444		if ( applydpd !== undefined ) {
5445			apply_dpd = applydpd;
5446		} else {
5447			apply_dpd = epoObject.this_epo_totals_container.data( 'fields-price-rules' );
5448		}
5449		productPrice = currentProductPrice;
5450		oProductPrice = originalProductPrice;
5451
5452		$.tcepo.lateFieldsPrices[ epoEventId ].forEach( function( field ) {
5453			price = field.price;
5454			originalPrice = field.original_price;
5455			priceType = field.pricetype;
5456			setter = field.setter;
5457			bundleid = field.bundleid;
5458			realSetter = setter;
5459
5460			if ( priceType === 'percentcurrenttotal' ) {
5461				hiddenName = '_hidden';
5462			} else {
5463				hiddenName = '_hiddenfixed';
5464			}
5465
5466			if ( setter.is( 'option' ) ) {
5467				realSetter = setter.closest( 'select' );
5468			}
5469
5470			productPrice = parseFloat( $.epoAPI.applyFilter( 'tc_alter_product_price', productPrice, realSetter, _cart, epoObject.this_epo_totals_container, bid ) );
5471			oProductPrice = parseFloat( $.epoAPI.applyFilter( 'tc_alter_original_product_price', oProductPrice, realSetter, _cart, epoObject.this_epo_totals_container, bid ) );
5472
5473			id = $.epoAPI.dom.id( realSetter.attr( 'name' ) );
5474			productId = $( '.tc-totals-form.tm-totals-form-' + _cart.attr( 'data-cart-id' ) ).attr( 'data-product-id' );
5475			epoId = $( '.tc-totals-form.tm-totals-form-' + _cart.attr( 'data-cart-id' ) ).attr( 'data-epo-id' );
5476			//workaround to support composite products
5477			hidden = $( tcAPI.epoSelector + '.tm-product-id-' + productId + "[data-epo-id='" + epoId + "']" ).find( '#' + id + hiddenName );
5478
5479			if ( bundleid === bid ) {
5480				if ( priceType === 'percentcurrenttotal' ) {
5481					price = ( parseFloat( price ) / 100 ) * ( tm_apply_dpd( parseFloat( productPrice ), epoObject.this_epo_totals_container, apply_dpd ) + parseFloat( options_total ) );
5482					originalPrice = ( parseFloat( originalPrice ) / 100 ) * ( parseFloat( oProductPrice ) + parseFloat( original_options_total ) );
5483				} else if ( priceType === 'fixedcurrenttotal' ) {
5484					price = parseFloat( price ) + parseFloat( options_total );
5485					originalPrice = parseFloat( originalPrice ) + parseFloat( original_options_total );
5486				}
5487				if ( realSetter.data( 'tm-quantity' ) ) {
5488					price = price * parseFloat( realSetter.data( 'tm-quantity' ) );
5489					originalPrice = originalPrice * parseFloat( realSetter.data( 'tm-quantity' ) );
5490				}
5491
5492				if ( setter.data( 'isset' ) === 1 && field_is_active( setter ) ) {
5493					if ( realSetter.is( '.tmcp-field' ) ) {
5494						total = total + price;
5495						originalTotal = originalTotal + originalPrice;
5496					} else if ( realSetter.is( '.tmcp-fee-field' ) ) {
5497						totalFees = totalFees + price;
5498						originalTotalFees = originalTotalFees + originalPrice;
5499					}
5500				}
5501
5502				taxPrice = tm_set_tax_price( price, _cart, setter );
5503				taxOriginalPrice = tm_set_tax_price( originalPrice, _cart, setter );
5504
5505				setter.data( 'price', taxPrice );
5506				setter.data( 'pricew', taxPrice );
5507				setter.data( 'original_price', taxOriginalPrice );
5508				setter.data( 'original_pricew', taxOriginalPrice );
5509
5510				tm_update_price( {
5511					epoObject: epoObject,
5512					obj: setter.closest( '.tmcp-field-wrap' ).find( '.tc-price' ),
5513					price: tm_get_price( taxPrice, _cart, false, setter ),
5514					original_price: tm_get_price( taxOriginalPrice, _cart, false, setter ),
5515					force: false,
5516					useFormattedPrice: false
5517				} );
5518
5519				if ( hidden.length === 0 ) {
5520					realSetter.before( '<input type="hidden" id="' + id + hiddenName + '" name="' + id + hiddenName + '" value="' + tm_set_price_without_tax( price, _cart ) + '">' );
5521				}
5522				if ( setter.is( '.tm-epo-field.tmcp-radio' ) || setter.is( '.tm-epo-field.tmcp-checkbox' ) ) {
5523					if ( setter.is( ':checked' ) ) {
5524						hidden.val( tm_set_price_without_tax( price, _cart ) );
5525					}
5526				} else {
5527					hidden.val( tm_set_price_without_tax( price, _cart ) );
5528				}
5529			} else if ( setter.data( 'pricew' ) !== undefined ) {
5530				// Prices are already taxed
5531				tm_update_price( {
5532					epoObject: epoObject,
5533					obj: setter.closest( '.tmcp-field-wrap' ).find( '.tc-price' ),
5534					price: setter.data( 'pricew' ),
5535					original_price: ( setter.data( 'original_pricew' ) !== undefined ? setter.data( 'original_pricew' ) : setter.data( 'pricew' ) ),
5536					force: false,
5537					useFormattedPrice: false
5538				} );
5539			}
5540		} );
5541
5542		return {
5543			normal: [ total, originalTotal ],
5544			fees: [ totalFees, originalTotalFees ]
5545		};
5546	}
5547
5548	function tm_lazyload() {
5549		var container;
5550
5551		if ( TMEPOJS.tm_epo_no_lazy_load === 'yes' ) {
5552			return;
5553		}
5554
5555		if ( tmLazyloadContainer ) {
5556			container = $( tmLazyloadContainer ).find( 'img.tmlazy' );
5557		} else {
5558			container = $( tcAPI.epoSelector + ' img.tmlazy, .tc-styled-variations img.tmlazy' );
5559		}
5560
5561		container.lazyLoadXT();
5562		container.on( 'lazyshow', function() {
5563			jWindow.trigger( 'lazyLoadXToncomplete' );
5564		} );
5565	}
5566
5567	function tm_css_styles( obj ) {
5568		var $cart;
5569		var sliderSection;
5570
5571		if ( ! obj ) {
5572			return;
5573		}
5574
5575		$cart = $( '.cart' );
5576
5577		sliderSection = obj.find( '.tm-owl-slider-section' );
5578		if ( ! sliderSection.length ) {
5579			sliderSection = obj;
5580			if ( ! sliderSection.is( '.tc-repeater-section' ) ) {
5581				sliderSection = false;
5582			}
5583		}
5584
5585		if ( sliderSection ) {
5586			sliderSection.toArray().forEach( function( slider ) {
5587				slider = $( slider );
5588
5589				slider.find( '.tc-slider-content' ).addClass( 'tm-owl-slider' );
5590
5591				slider = slider.find( '.tm-owl-slider' );
5592				if ( slider.length ) {
5593					slider
5594						.addClass( 'tcowl-carousel-show' )
5595						.addClass( 'tcowl-carousel' )
5596						.on( 'changed.owl.carousel', function() {
5597							$cart.css( 'display', 'block' ).addClass( 'slider-setup' );
5598						} )
5599						.tmowlCarousel( Object.assign( {
5600							rtl: TMEPOJS.isRTL === '1',
5601							dots: false,
5602							nav: true,
5603							items: 1,
5604							autoHeight: true,
5605							mouseDrag: false,
5606							touchDrag: true,
5607							navText: [ TMEPOJS.i18n_prev_text, TMEPOJS.i18n_next_text ],
5608							navClass: [ 'owl-prev button', 'owl-next button' ],
5609							navElement: 'a',
5610							loop: false,
5611							navRewind: false
5612						}, window.tmowlCarouselSettings || {} ) );
5613
5614					slider.removeClass( 'tcowl-carousel-show' );
5615				}
5616			} );
5617		}
5618
5619		if ( $.fn.tcTabs ) {
5620			obj.find( '.tc-tabs' ).tcTabs( {
5621				headers: 'tc-tab-headers',
5622				header: 'tab-header',
5623				dataopenattribute: 'data-tab',
5624				sortabletabs: false
5625			} );
5626		}
5627	}
5628
5629	function repeaterAdd( el, elementInnerWrap ) {
5630		var cpf = elementInnerWrap.closest( '.cpf-element' );
5631		var maxRows = cpf.data( 'repeater-max-rows' );
5632		var minRows = cpf.data( 'repeater-min-rows' ) || 1;
5633		var repeater = elementInnerWrap.find( '.tc-repeater-element' );
5634		var rows = repeater.length;
5635		var repeaterLast = repeater.last();
5636		var repeaterLastUL = repeaterLast.find( '.tmcp-ul-wrap' );
5637		var clone;
5638		var cloneUl;
5639		var index = el.data( 'tc-repeater-init' );
5640
5641		if ( maxRows ) {
5642			if ( rows >= maxRows ) {
5643				return false;
5644			}
5645		}
5646
5647		if ( rows + 1 >= maxRows && el.is( '.tc-repeater-add' ) ) {
5648			el.closest( '.tc-repeater-wrap' ).addClass( 'tc-hidden' );
5649		}
5650
5651		if ( repeaterLastUL.is( '.tm-element-ul-date, .tm-element-ul-time' ) ) {
5652			repeaterLastUL.find( '.tm-epo-field' ).tm_datepicker( 'destroy' );
5653			repeaterLastUL.find( '.tmcp-date-select' ).off();
5654		}
5655		if ( repeaterLastUL.is( '.tm-element-ul-color' ) ) {
5656			repeaterLastUL.find( '.tm-epo-field' ).spectrum( 'destroy' );
5657		}
5658
5659		clone = repeaterLast.tcClone( true );
5660
5661		clone.find( '.tm-epo-field' ).attr( 'id', function( i, value ) {
5662			return value.replace( /\_\d+$/g, '' ) + '_' + index;
5663		} );
5664		clone.find( '[data-for]' ).attr( 'data-for', function( i, value ) {
5665			return value.replace( /\_\d+$/g, '' ) + '_' + index;
5666		} );
5667		clone.find( '[for]:not(:has(.tmcp-date-select))' ).attr( 'for', function( i, value ) {
5668			return value.replace( /\_\d+$/g, '' ) + '_' + index;
5669		} );
5670		clone.find( '[data-field-id]' ).attr( 'data-field-id', function( i, value ) {
5671			return value.replace( /\_\d+$/g, '' ) + '_' + index;
5672		} );
5673		clone.find( '[data-tm-date]' ).attr( 'data-tm-date', function( i, value ) {
5674			return value.replace( /\_\d+$/g, '' ) + '_' + index;
5675		} );
5676		clone.find( '.tmcp-date-select' ).attr( 'id', function( i, value ) {
5677			return $( this ).attr( 'data-tm-date' ) + '_' + value.substring( value.lastIndexOf( '_' ) + 1 );
5678		} );
5679		clone.find( '[for]:has(.tmcp-date-select)' ).attr( 'for', function( i, value ) {
5680			return $( this ).find( '.tmcp-date-select' ).attr( 'data-tm-date' ) + '_' + value.substring( value.lastIndexOf( '_' ) + 1 );
5681		} );
5682		clone.find( '.tm-epo-field' ).attr( 'name', function( i, value ) {
5683			return value.replace( /\[\d+\]/g, '[' + index + ']' );
5684		} );
5685		clone.find( '.tm-qty' ).attr( 'name', function( i, value ) {
5686			return value.replace( /\[\d+\]/g, '[' + index + ']' );
5687		} );
5688		clone.find( '.tmcp-date-select' ).attr( 'name', function( i, value ) {
5689			return value.replace( /\[\d+\]/g, '[' + index + ']' );
5690		} );
5691
5692		cloneUl = clone.find( '.tmcp-ul-wrap' );
5693
5694		if ( rows >= minRows && elementInnerWrap.find( '.tc-repeater-element' ).length >= 1 ) {
5695			elementInnerWrap.find( '.tc-repeater-delete' ).removeClass( 'tc-hidden' );
5696			clone.find( '.tc-repeater-delete' ).removeClass( 'tc-hidden' );
5697		}
5698
5699		if ( cloneUl.is( '.tm-element-ul-checkbox' ) ) {
5700			clone.find( 'li.tmcp-field-wrap' ).removeClass( 'tc-active' );
5701			clone
5702				.find( '.tm-epo-field.tmcp-checkbox' )
5703				.prop( 'checked', false );
5704			clone
5705				.find( '.tm-epo-field.tmcp-checkbox' )
5706				.filter( function( i, x ) {
5707					return $.inArray( $( x ).val(), el.data( 'repeater-init-value' ) ) !== -1;
5708				} )
5709				.prop( 'checked', true )
5710				.closest( 'li.tmcp-field-wrap' ).addClass( 'tc-active' );
5711		} else if ( cloneUl.is( '.tm-element-ul-radio' ) ) {
5712			clone.find( 'li.tmcp-field-wrap' ).removeClass( 'tc-active' );
5713			clone
5714				.find( '.tm-epo-field.tmcp-radio' )
5715				.filter( function( i, x ) {
5716					return $( x ).val() === el.data( 'repeater-init-value' );
5717				} )
5718				.prop( 'checked', true )
5719				.closest( 'li.tmcp-field-wrap' ).addClass( 'tc-active' );
5720		} else {
5721			clone.find( '.tm-epo-field' ).val( el.data( 'repeater-init-value' ) );
5722		}
5723
5724		if ( ! cloneUl.is( '.tm-element-ul-checkbox' ) && ! cloneUl.is( '.tm-element-ul-radio' ) ) {
5725			clone.find( '.tm-epo-field' ).val( el.data( 'repeater-init-value' ) );
5726		}
5727
5728		if ( cloneUl.is( '.tm-element-ul-upload' ) ) {
5729			clone.find( '.tc-upload-preview' ).remove();
5730			clone.find( '.tm-filename' ).remove();
5731		}
5732
5733		clone.find( '.tc-element-qty' ).toArray().forEach( function( elc ) {
5734			var qelc = $( elc );
5735			var defaultValue = qelc.attr( 'data-default-value' );
5736			qelc.val( defaultValue ).trigger( 'change' );
5737		} );
5738
5739		el.data( 'tc-repeater-init', el.data( 'tc-repeater-init' ) + 1 );
5740
5741		return [ clone, repeaterLast, repeaterLastUL ];
5742	}
5743
5744	function repeaterAddAfter( epoObject, clone, repeaterLastUL, doevents ) {
5745		var cloneUl = clone.find( '.tmcp-ul-wrap' );
5746
5747		if ( cloneUl.is( '.tm-element-ul-range' ) ) {
5748			clone.find( '.tm-range-picker' ).removeData( 'tc-picker-init' ).attr( 'class', 'tm-range-picker' ).html( '' );
5749			setRangePickers( clone );
5750		}
5751		if ( cloneUl.is( '.tm-element-ul-date, .tm-element-ul-time' ) ) {
5752			tm_set_datepicker( repeaterLastUL );
5753			tm_set_datepicker( cloneUl );
5754		}
5755		if ( cloneUl.is( '.tm-element-ul-color' ) ) {
5756			tm_set_color_pickers( repeaterLastUL );
5757			tm_set_color_pickers( cloneUl );
5758		}
5759		clone.find( '.tm-tooltip' ).removeData( 'tctooltip' ).removeData( 'tm-has-tm-tip' );
5760		$.tcToolTip( clone.find( '.tm-tooltip' ) );
5761
5762		//  apply specific field rules
5763		clone.find( '.tm-epo-field' )
5764			.removeData( 'addedtcEpoBeforeOptionPriceCalculation' )
5765			.toArray().forEach( function( elc ) {
5766				elc = $( elc );
5767				field_is_active( elc, false, true );
5768				if ( elc.is( '.tcenabled' ) ) {
5769					tm_element_epo_rules( epoObject, elc );
5770				}
5771				elc.on( 'tc_element_epo_rules', function() {
5772					tm_element_epo_rules( epoObject, elc );
5773				} );
5774			} );
5775		if ( ! doevents ) {
5776			return;
5777		}
5778		if ( cloneUl.is( '.tm-element-ul-checkbox' ) ) {
5779			clone
5780				.find( '.tm-epo-field.tmcp-checkbox' )
5781				.filter( ':checked' )
5782				.trigger( 'change.cpf' );
5783		} else if ( cloneUl.is( '.tm-element-ul-radio' ) ) {
5784			clone
5785				.find( '.tm-epo-field.tmcp-radio' )
5786				.filter( ':checked' )
5787				.trigger( 'change.cpf' );
5788		} else {
5789			clone.find( '.tm-epo-field' ).trigger( 'change.cpf' );
5790		}
5791	}
5792
5793	function repeaterDelete( elementInnerWrap, repeaterElement, repeaterObj, $this ) {
5794		var cpf = elementInnerWrap.closest( '.cpf-element' );
5795		var minRows = cpf.data( 'repeater-min-rows' );
5796		var rows = elementInnerWrap.find( '.tc-repeater-element' ).length;
5797		var repeaterElementIndex = repeaterElement.index();
5798		var message;
5799
5800		if ( minRows ) {
5801			if ( rows <= minRows ) {
5802				if ( $.tc_validator && $this ) {
5803					message = '<div class="tm-error-repeater tm-error tc-cell tcwidth tcwidth-100">' + $.tc_validator.messages.repeaterminrows( minRows ) + '</div>';
5804					$this.tcToolTip( { tip: message, onetime: true, trigger: true, tipclass: 'tc-error' } );
5805				}
5806				return false;
5807			}
5808		}
5809		if ( rows === 1 ) {
5810			return;
5811		}
5812		if ( rows === 2 || ( rows - 1 ) <= minRows ) {
5813			elementInnerWrap.find( '.tc-repeater-delete' ).addClass( 'tc-hidden' );
5814		}
5815		if ( repeaterObj.is( '.tc-repeater-add' ) ) {
5816			repeaterObj.closest( '.tc-repeater-wrap' ).removeClass( 'tc-hidden' );
5817		}
5818		repeaterElement.remove();
5819		repeaterObj.data( 'tc-repeater-init', repeaterObj.data( 'tc-repeater-init' ) - 1 );
5820		if ( repeaterElementIndex + 1 === rows ) {
5821			return;
5822		}
5823		elementInnerWrap.find( '.tc-repeater-element' )
5824			.toArray()
5825			.forEach( function( clone, index ) {
5826				clone = $( clone );
5827				clone.find( '.tm-epo-field' ).attr( 'id', function( i, value ) {
5828					return value.replace( /\_\d+$/g, '' ) + ( ( index !== 0 ) ? '_' + index : '' );
5829				} );
5830				clone.find( '[data-for]' ).attr( 'data-for', function( i, value ) {
5831					return value.replace( /\_\d+$/g, '' ) + ( ( index !== 0 ) ? '_' + index : '' );
5832				} );
5833				clone.find( '[for]:not(:has(.tmcp-date-select))' ).attr( 'for', function( i, value ) {
5834					return value.replace( /\_\d+$/g, '' ) + ( ( index !== 0 ) ? '_' + index : '' );
5835				} );
5836				clone.find( '[data-field-id]' ).attr( 'data-field-id', function( i, value ) {
5837					return value.replace( /\_\d+$/g, '' ) + ( ( index !== 0 ) ? '_' + index : '' );
5838				} );
5839				clone.find( '[data-tm-date]' ).attr( 'data-tm-date', function( i, value ) {
5840					return value.replace( /\_\d+$/g, '' ) + ( ( index !== 0 ) ? '_' + index : '' );
5841				} );
5842				clone.find( '.tmcp-date-select' ).attr( 'id', function( i, value ) {
5843					return $( this ).attr( 'data-tm-date' ) + '_' + value.substring( value.lastIndexOf( '_' ) + 1 );
5844				} );
5845				clone.find( '[for]:has(.tmcp-date-select)' ).attr( 'for', function( i, value ) {
5846					return $( this ).find( '.tmcp-date-select' ).attr( 'data-tm-date' ) + '_' + value.substring( value.lastIndexOf( '_' ) + 1 );
5847				} );
5848				clone.find( '.tm-epo-field' ).attr( 'name', function( i, value ) {
5849					return value.replace( /\[\d+\]/g, '[' + index + ']' );
5850				} );
5851				clone.find( '.tm-qty' ).attr( 'name', function( i, value ) {
5852					return value.replace( /\[\d+\]/g, '[' + index + ']' );
5853				} );
5854				clone.find( '.tmcp-date-select' ).attr( 'name', function( i, value ) {
5855					return value.replace( /\[\d+\]/g, '[' + index + ']' );
5856				} );
5857			} );
5858	}
5859
5860	function repeaterDeleteSection( elementInnerWrap, repeaterElement, repeaterObj, $this ) {
5861		var cpf = elementInnerWrap.closest( '.cpf-section' );
5862		var minRows = cpf.data( 'repeater-min-rows' );
5863		var rows = elementInnerWrap.find( '.tc-repeater-section' ).length;
5864		var repeaterElementIndex = repeaterElement.index();
5865		var message;
5866
5867		if ( minRows ) {
5868			if ( rows <= minRows ) {
5869				if ( $.tc_validator && $this ) {
5870					message = '<div class="tm-error-repeater tm-error tc-cell tcwidth tcwidth-100">' + $.tc_validator.messages.repeaterminrows( minRows ) + '</div>';
5871					$this.tcToolTip( { tip: message, onetime: true, trigger: true, tipclass: 'tc-error' } );
5872				}
5873				return false;
5874			}
5875		}
5876		if ( rows === 1 ) {
5877			return;
5878		}
5879		if ( rows === 2 || ( rows - 1 ) <= minRows ) {
5880			elementInnerWrap.find( '.tc-repeater-section-delete' ).addClass( 'tc-hidden' );
5881			elementInnerWrap.find( '.tc-repeater-section' ).removeClass( 'has-delete' );
5882			cpf.find( '.tcowl-carousel' ).trigger( 'refresh.owl.carousel' );
5883		}
5884		if ( repeaterObj.is( '.tc-section-repeater-add' ) ) {
5885			repeaterObj.closest( '.tc-repeater-wrap' ).removeClass( 'tc-hidden' );
5886		}
5887		repeaterElement.remove();
5888		repeaterObj.data( 'tc-repeater-init', repeaterObj.data( 'tc-repeater-init' ) - 1 );
5889		if ( repeaterElementIndex + 1 === rows ) {
5890			return;
5891		}
5892		elementInnerWrap.find( '.tc-repeater-section' )
5893			.toArray()
5894			.forEach( function( clone, index ) {
5895				clone = $( clone );
5896
5897				clone.find( '.tm-epo-field' ).attr( 'id', function( i, value ) {
5898					return value.replace( /\_\d+$/g, '' ) + ( ( index !== 0 ) ? '_' + index : '' );
5899				} );
5900				clone.find( '[data-for]' ).attr( 'data-for', function( i, value ) {
5901					return value.replace( /\_\d+$/g, '' ) + ( ( index !== 0 ) ? '_' + index : '' );
5902				} );
5903				clone.find( '[for]:not(:has(.tmcp-date-select))' ).attr( 'for', function( i, value ) {
5904					return value.replace( /\_\d+$/g, '' ) + ( ( index !== 0 ) ? '_' + index : '' );
5905				} );
5906				clone.find( '[data-field-id]' ).attr( 'data-field-id', function( i, value ) {
5907					return value.replace( /\_\d+$/g, '' ) + ( ( index !== 0 ) ? '_' + index : '' );
5908				} );
5909				clone.find( '[data-tm-date]' ).attr( 'data-tm-date', function( i, value ) {
5910					return value.replace( /\_\d+$/g, '' ) + ( ( index !== 0 ) ? '_' + index : '' );
5911				} );
5912				clone.find( '.tmcp-date-select' ).attr( 'id', function( i, value ) {
5913					return $( this ).attr( 'data-tm-date' ) + '_' + value.substring( value.lastIndexOf( '_' ) + 1 );
5914				} );
5915				clone.find( '[for]:has(.tmcp-date-select)' ).attr( 'for', function( i, value ) {
5916					return $( this ).find( '.tmcp-date-select' ).attr( 'data-tm-date' ) + '_' + value.substring( value.lastIndexOf( '_' ) + 1 );
5917				} );
5918				clone.find( '.tm-epo-field' ).attr( 'name', function( i, value ) {
5919					return value.replace( /\[\d+\]/g, '[' + index + ']' );
5920				} );
5921				clone.find( '.tm-qty' ).attr( 'name', function( i, value ) {
5922					return value.replace( /\[\d+\]/g, '[' + index + ']' );
5923				} );
5924				clone.find( '.tmcp-date-select' ).attr( 'name', function( i, value ) {
5925					return value.replace( /\[\d+\]/g, '[' + index + ']' );
5926				} );
5927			} );
5928	}
5929
5930	function repeaterAddSection( el, elementInnerWrap ) {
5931		var cpf = elementInnerWrap.closest( '.cpf-section' );
5932		var maxRows = cpf.data( 'repeater-max-rows' );
5933		var minRows = cpf.data( 'repeater-min-rows' ) || 1;
5934		var repeater = elementInnerWrap.find( '.tc-repeater-section' );
5935		var rows = repeater.length;
5936		var repeaterLast = repeater.last();
5937		var repeaterLastUL = repeaterLast.find( '.tmcp-ul-wrap' );
5938		var clone;
5939		var cloneUl;
5940		var index = el.data( 'tc-repeater-init' );
5941		var repeaterInitValue = el.data( 'repeater-init-value' );
5942
5943		if ( maxRows ) {
5944			if ( rows >= maxRows ) {
5945				return false;
5946			}
5947		}
5948
5949		if ( rows + 1 >= maxRows && el.is( '.tc-repeater-add' ) ) {
5950			el.closest( '.tc-repeater-wrap' ).addClass( 'tc-hidden' );
5951		}
5952
5953		repeaterLastUL.toArray().forEach( function( field ) {
5954			var rlul = $( field );
5955			if ( rlul.is( '.tm-element-ul-date, .tm-element-ul-time' ) ) {
5956				rlul.find( '.tm-epo-field' ).tm_datepicker( 'destroy' );
5957				rlul.find( '.tmcp-date-select' ).off();
5958			}
5959			if ( rlul.is( '.tm-element-ul-color' ) ) {
5960				rlul.find( '.tm-epo-field' ).spectrum( 'destroy' );
5961			}
5962		} );
5963
5964		clone = repeaterLast.tcClone( true );
5965
5966		clone.find( '.tm-epo-field' ).attr( 'id', function( i, value ) {
5967			return value.replace( /\_\d+$/g, '' ) + '_' + index;
5968		} );
5969		clone.find( '[data-for]' ).attr( 'data-for', function( i, value ) {
5970			return value.replace( /\_\d+$/g, '' ) + '_' + index;
5971		} );
5972		clone.find( '[for]:not(:has(.tmcp-date-select))' ).attr( 'for', function( i, value ) {
5973			return value.replace( /\_\d+$/g, '' ) + '_' + index;
5974		} );
5975		clone.find( '[data-field-id]' ).attr( 'data-field-id', function( i, value ) {
5976			return value.replace( /\_\d+$/g, '' ) + '_' + index;
5977		} );
5978		clone.find( '[data-tm-date]' ).attr( 'data-tm-date', function( i, value ) {
5979			return value.replace( /\_\d+$/g, '' ) + '_' + index;
5980		} );
5981		clone.find( '.tmcp-date-select' ).attr( 'id', function( i, value ) {
5982			return $( this ).attr( 'data-tm-date' ) + '_' + value.substring( value.lastIndexOf( '_' ) + 1 );
5983		} );
5984		clone.find( '[for]:has(.tmcp-date-select)' ).attr( 'for', function( i, value ) {
5985			return $( this ).find( '.tmcp-date-select' ).attr( 'data-tm-date' ) + '_' + value.substring( value.lastIndexOf( '_' ) + 1 );
5986		} );
5987		clone.find( '.tm-epo-field' ).attr( 'name', function( i, value ) {
5988			return value.replace( /\[\d+\]/g, '[' + index + ']' );
5989		} );
5990		clone.find( '.tm-qty' ).attr( 'name', function( i, value ) {
5991			return value.replace( /\[\d+\]/g, '[' + index + ']' );
5992		} );
5993		clone.find( '.tmcp-date-select' ).attr( 'name', function( i, value ) {
5994			return value.replace( /\[\d+\]/g, '[' + index + ']' );
5995		} );
5996
5997		cloneUl = clone.find( '.tmcp-ul-wrap' );
5998
5999		if ( rows >= minRows && elementInnerWrap.find( '.tc-repeater-section' ).length >= 1 ) {
6000			elementInnerWrap.find( '.tc-repeater-section-delete' ).removeClass( 'tc-hidden' );
6001			clone.find( '.tc-repeater-section-delete' ).removeClass( 'tc-hidden' );
6002			repeater.addClass( 'has-delete' );
6003			clone.addClass( 'has-delete' );
6004			cpf.find( '.tcowl-carousel' ).trigger( 'refresh.owl.carousel' );
6005		}
6006
6007		cloneUl.toArray().forEach( function( field ) {
6008			var cUl = $( field );
6009			if ( cUl.is( '.tm-element-ul-checkbox' ) ) {
6010				cUl.find( 'li.tmcp-field-wrap' ).removeClass( 'tc-active' );
6011				cUl
6012					.find( '.tm-epo-field.tmcp-checkbox' )
6013					.prop( 'checked', false );
6014				cUl
6015					.find( '.tm-epo-field.tmcp-checkbox' )
6016					.filter( function( i, x ) {
6017						var $field = $( x );
6018						var fieldId = $field.attr( 'id' ).replace( /_(\d+)$/, '' );
6019						return $.inArray( $field.val(), repeaterInitValue[ fieldId ] ) !== -1;
6020					} )
6021					.prop( 'checked', true )
6022					.closest( 'li.tmcp-field-wrap' ).addClass( 'tc-active' );
6023			} else if ( cUl.is( '.tm-element-ul-radio' ) ) {
6024				cUl.find( 'li.tmcp-field-wrap' ).removeClass( 'tc-active' );
6025				cUl
6026					.find( '.tm-epo-field.tmcp-radio' )
6027					.filter( function( i, x ) {
6028						var $field = $( x );
6029						var fieldId = $field.attr( 'id' ).replace( /_(\d+)$/, '' );
6030						return $field.val() === repeaterInitValue[ fieldId ];
6031					} )
6032					.prop( 'checked', true )
6033					.closest( 'li.tmcp-field-wrap' ).addClass( 'tc-active' );
6034			} else {
6035				cUl.find( '.tm-epo-field' ).each( function() {
6036					var $field = $( this );
6037					var fieldId = $field.attr( 'id' ).replace( /_(\d+)$/, '' );
6038					if ( repeaterInitValue.hasOwnProperty( fieldId ) ) {
6039						$field.val( repeaterInitValue[ fieldId ] );
6040					}
6041				} );
6042			}
6043
6044			if ( ! cUl.is( '.tm-element-ul-checkbox' ) && ! cUl.is( '.tm-element-ul-radio' ) ) {
6045				cUl.find( '.tm-epo-field' ).each( function() {
6046					var $field = $( this );
6047					var fieldId = $field.attr( 'id' ).replace( /_(\d+)$/, '' );
6048					if ( repeaterInitValue.hasOwnProperty( fieldId ) ) {
6049						$field.val( repeaterInitValue[ fieldId ] );
6050					}
6051				} );
6052			}
6053
6054			if ( cUl.is( '.tm-element-ul-upload' ) ) {
6055				cUl.find( '.tc-upload-preview' ).remove();
6056				cUl.find( '.tm-filename' ).remove();
6057			}
6058		} );
6059
6060		clone.find( '.tc-element-qty' ).toArray().forEach( function( elc ) {
6061			var qelc = $( elc );
6062			var defaultValue = qelc.attr( 'data-default-value' );
6063			qelc.val( defaultValue ).trigger( 'change' );
6064		} );
6065
6066		el.data( 'tc-repeater-init', el.data( 'tc-repeater-init' ) + 1 );
6067
6068		return [ clone, repeaterLast, repeaterLastUL ];
6069	}
6070
6071	function repeaterAddSectionAfter( epoObject, clone, repeaterLastUL, doevents ) {
6072		var cloneUl = clone.find( '.tmcp-ul-wrap' );
6073		var doDate;
6074		var doColor;
6075		cloneUl.toArray().forEach( function( field ) {
6076			var cUL = $( field );
6077			if ( cUL.is( '.tm-element-ul-range' ) ) {
6078				cUL.find( '.tm-range-picker' ).removeData( 'tc-picker-init' ).attr( 'class', 'tm-range-picker' ).html( '' );
6079				setRangePickers( cUL );
6080			}
6081			if ( cUL.is( '.tm-element-ul-date, .tm-element-ul-time' ) ) {
6082				doDate = true;
6083				tm_set_datepicker( cUL );
6084			}
6085			if ( cUL.is( '.tm-element-ul-color' ) ) {
6086				doColor = true;
6087				tm_set_color_pickers( cUL );
6088			}
6089			if ( doevents ) {
6090				if ( cUL.is( '.tm-element-ul-checkbox' ) ) {
6091					cUL
6092						.find( '.tm-epo-field.tmcp-checkbox' )
6093						.filter( ':checked' )
6094						.trigger( 'change.cpf' );
6095				} else if ( cUL.is( '.tm-element-ul-radio' ) ) {
6096					cUL
6097						.find( '.tm-epo-field.tmcp-radio' )
6098						.filter( ':checked' )
6099						.trigger( 'change.cpf' );
6100				} else {
6101					cUL.find( '.tm-epo-field' ).trigger( 'change.cpf' );
6102				}
6103			}
6104		} );
6105		if ( doDate ) {
6106			tm_set_datepicker( repeaterLastUL );
6107		}
6108		if ( doColor ) {
6109			tm_set_color_pickers( repeaterLastUL );
6110		}
6111
6112		clone.find( '.tm-tooltip' ).removeData( 'tctooltip' ).removeData( 'tm-has-tm-tip' );
6113		$.tcToolTip( clone.find( '.tm-tooltip' ) );
6114
6115		//  apply specific field rules
6116		clone.find( '.tm-epo-field' )
6117			.removeData( 'addedtcEpoBeforeOptionPriceCalculation' )
6118			.toArray().forEach( function( elc ) {
6119				elc = $( elc );
6120				field_is_active( elc, false, true );
6121				if ( elc.is( '.tcenabled' ) ) {
6122					tm_element_epo_rules( epoObject, elc );
6123				}
6124				elc.on( 'tc_element_epo_rules', function() {
6125					tm_element_epo_rules( epoObject, elc );
6126				} );
6127			} );
6128		clone.find( '.tc-tabs' ).removeData( 'tctabs' );
6129		clone.find( '.tcowl-carousel' ).removeData( 'owl.carousel' );
6130		clone.find( '.owl-nav, .owl-dots' ).remove();
6131		tm_css_styles( clone );
6132	}
6133
6134	function tm_set_repeaters( obj, epoObject ) {
6135		var currentCart;
6136		var qtyElement;
6137		var quantityRepeaters;
6138		var sectionQuantityRepeaters;
6139		if ( ! obj ) {
6140			return;
6141		}
6142		obj = $( obj );
6143
6144		if ( obj.length ) {
6145			currentCart = epoObject.main_cart;
6146			qtyElement = getQtyElement( currentCart );
6147			qtyElement = $.epoAPI.applyFilter( 'qtyElementForRepeaterQuantity', qtyElement, {
6148				epo: epoObject,
6149				currentCart: currentCart,
6150				obj: obj,
6151				qtyElement: qtyElement
6152			} );
6153			quantityRepeaters = obj.find( '.tc-repeater-quantity' );
6154			quantityRepeaters
6155				.toArray()
6156				.forEach( function( repeater, qx ) {
6157					var el = $( repeater );
6158					var tmEpoField;
6159					var repeaterElement;
6160					var length;
6161					var elementInnerWrap;
6162					var maxRows = el.data( 'repeater-max-rows' );
6163
6164					if ( el.data( 'tc-repeater-init' ) ) {
6165						return;
6166					}
6167					repeaterElement = el.find( '.tc-repeater-element' );
6168					length = repeaterElement.length;
6169					tmEpoField = repeaterElement.first().find( '.tm-epo-field' );
6170					if ( tmEpoField.is( ':checkbox' ) ) {
6171						el.data( 'repeater-init-value',
6172							tmEpoField.filter( ':checked' ).toArray().map( function( x ) {
6173								return $( x ).val();
6174							} ) );
6175					} else if ( tmEpoField.is( ':radio' ) ) {
6176						el.data( 'repeater-init-value', tmEpoField.filter( ':checked' ).val() );
6177					} else {
6178						el.data( 'repeater-init-value', tmEpoField.val() );
6179					}
6180					el.data( 'tc-repeater-init', length );
6181					el.data( 'tc-repeater-name', tmEpoField.attr( 'name' ) );
6182
6183					if ( qtyElement.length ) {
6184						elementInnerWrap = el.find( '.tc-element-inner-wrap' );
6185						qtyElement
6186							.off( 'change.r' + qx + 'cpf input.r' + qx + 'cpf' )
6187							.on( 'change.r' + qx + 'cpf input.r' + qx + 'cpf', function( event ) {
6188								var field = $( this );
6189								var prevValue = field.data( 'epopreviousvalue' );
6190								var value = $.epoAPI.applyFilter( 'qtyElementForRepeaterQuantityValue', field.val(), {
6191									epo: epoObject,
6192									currentCart: currentCart,
6193									obj: obj,
6194									qtyElement: qtyElement,
6195									field: field
6196								} );
6197								var difference = value - prevValue;
6198								var thisRepeaterElement;
6199								var i;
6200								var ele;
6201								var cloned;
6202								var repeaterLastUL;
6203								var fieldprevval;
6204								if ( prevValue === undefined ) {
6205									prevValue = value - 1;
6206									difference = value - prevValue;
6207								}
6208								if ( event.isTrigger !== undefined ) {
6209									prevValue = el.find( '.tc-element-inner-wrap' ).find( '.tc-repeater-element' ).length;
6210									difference = value - prevValue;
6211								}
6212								if ( maxRows && difference > maxRows ) {
6213									difference = maxRows - 1;
6214								}
6215								if ( difference === 0 ) {
6216									return;
6217								}
6218								fieldprevval = $.epoAPI.applyFilter( 'qtyElementForRepeaterQuantity_epopreviousvalue', field.val(), {
6219									epo: epoObject,
6220									currentCart: currentCart,
6221									obj: obj,
6222									qtyElement: qtyElement,
6223									field: field
6224								} );
6225								if ( fieldprevval <= 0 ) {
6226									fieldprevval = 1;
6227								}
6228								if ( qx === quantityRepeaters.length ) {
6229									field.data( 'epopreviousvalue', fieldprevval );
6230								}
6231								if ( difference > 0 ) {
6232									thisRepeaterElement = elementInnerWrap.find( '.tc-repeater-element' ).eq( value - 1 );
6233									if ( thisRepeaterElement.length ) {
6234										return;
6235									}
6236									for ( i = 0; i < difference; i++ ) {
6237										cloned = repeaterAdd( el, elementInnerWrap );
6238										if ( cloned ) {
6239											if ( ele ) {
6240												ele = ele.add( cloned[ 0 ] );
6241											} else {
6242												ele = cloned[ 0 ];
6243											}
6244											if ( i === 0 ) {
6245												repeaterLastUL = cloned[ 2 ];
6246											}
6247										}
6248									}
6249									if ( ele ) {
6250										ele.appendTo( elementInnerWrap.find( '.tc-element-container' ) );
6251										repeaterAddAfter( epoObject, ele, repeaterLastUL );
6252									}
6253								} else {
6254									for ( i = value - difference; i > value; i -= 1 ) {
6255										thisRepeaterElement = elementInnerWrap.find( '.tc-repeater-element' ).eq( i - 1 );
6256										repeaterDelete( elementInnerWrap, thisRepeaterElement, el );
6257									}
6258								}
6259								currentCart.trigger( {
6260									type: 'tm-epo-update',
6261									norules: 2
6262								} );
6263							} );
6264						qtyElement.data( 'epopreviousvalue', $.epoAPI.applyFilter( 'qtyElementForRepeaterQuantityValue', qtyElement.val(), {
6265							epo: epoObject,
6266							currentCart: currentCart,
6267							obj: obj,
6268							qtyElement: qtyElement,
6269							field: qtyElement
6270						} ) ).trigger( 'change' );
6271					}
6272				} );
6273
6274			obj.find( '.tc-repeater-add' )
6275				.toArray()
6276				.forEach( function( repeater ) {
6277					var el = $( repeater );
6278					var tmEpoField;
6279					var elementInnerWrap;
6280					var repeaterElement;
6281					var length;
6282					if ( el.data( 'tc-repeater-init' ) ) {
6283						return;
6284					}
6285					elementInnerWrap = el.closest( '.tc-element-inner-wrap' );
6286					repeaterElement = elementInnerWrap.find( '.tc-repeater-element' );
6287					length = repeaterElement.length;
6288					tmEpoField = repeaterElement.first().find( '.tm-epo-field' );
6289					if ( elementInnerWrap.find( '.tc-repeater-element' ).length > 1 ) {
6290						elementInnerWrap.find( '.tc-repeater-delete' ).removeClass( 'tc-hidden' );
6291					}
6292					if ( tmEpoField.is( ':checkbox' ) ) {
6293						el.data( 'repeater-init-value',
6294							tmEpoField.filter( ':checked' ).toArray().map( function( x ) {
6295								return $( x ).val();
6296							} ) );
6297					} else if ( tmEpoField.is( ':radio' ) ) {
6298						el.data( 'repeater-init-value', tmEpoField.filter( ':checked' ).val() );
6299					} else {
6300						el.data( 'repeater-init-value', tmEpoField.val() );
6301					}
6302					el.data( 'tc-repeater-init', length );
6303					el.data( 'tc-repeater-name', tmEpoField.attr( 'name' ) );
6304
6305					el.on( 'click.repeater', function() {
6306						var ele = repeaterAdd( el, elementInnerWrap );
6307						if ( ele ) {
6308							ele[ 0 ].appendTo( elementInnerWrap.find( '.tc-element-container' ) );
6309							repeaterAddAfter( epoObject, ele[ 0 ], ele[ 2 ], true );
6310						}
6311					} );
6312				} );
6313
6314			obj.find( '.tc-repeater-delete .delete' ).on( 'click', function() {
6315				var $this = $( this );
6316				var elementInnerWrap = $this.closest( '.tc-element-inner-wrap' );
6317				var repeaterElement = $this.closest( '.tc-repeater-element' );
6318				repeaterDelete( elementInnerWrap, repeaterElement, elementInnerWrap.find( '.tc-repeater-add' ), $this );
6319				epoObject.form.trigger( {
6320					type: 'tm-epo-update',
6321					norules: 2
6322				} );
6323			} );
6324
6325			obj.find( '.tc-section-repeater-add' )
6326				.toArray()
6327				.forEach( function( repeater ) {
6328					var el = $( repeater );
6329					var tmEpoField;
6330					var elementInnerWrap;
6331					var repeaterElement;
6332					var length;
6333					var fieldData = [];
6334					if ( el.data( 'tc-repeater-init' ) ) {
6335						return;
6336					}
6337					elementInnerWrap = el.closest( '.tc-section-inner-wrap' );
6338					repeaterElement = elementInnerWrap.find( '.tc-repeater-section' );
6339					length = repeaterElement.length;
6340					tmEpoField = elementInnerWrap.find( '.sections_repeater' );
6341					if ( elementInnerWrap.find( '.tc-repeater-section' ).length > 1 ) {
6342						elementInnerWrap.find( '.tc-section-repeater-delete' ).removeClass( 'tc-hidden' );
6343					}
6344					repeaterElement.first().find( '.tm-epo-field' )
6345						.toArray()
6346						.forEach( function( field ) {
6347							var epofield = $( field );
6348							var id = epofield.attr( 'id' );
6349							if ( epofield.is( ':checkbox' ) ) {
6350								fieldData[ id ] = epofield.filter( ':checked' ).toArray().map( function( x ) {
6351									return $( x ).val();
6352								} );
6353							} else if ( epofield.is( ':radio' ) ) {
6354								fieldData[ id ] = epofield.filter( ':checked' ).val();
6355							} else {
6356								fieldData[ id ] = epofield.val();
6357							}
6358						} );
6359					el.data( 'repeater-init-value', fieldData );
6360
6361					el.data( 'tc-repeater-init', length );
6362					el.data( 'tc-repeater-name', tmEpoField.attr( 'name' ) );
6363
6364					el.on( 'click.repeater', function() {
6365						var ele = repeaterAddSection( el, elementInnerWrap );
6366						if ( ele ) {
6367							ele[ 1 ].after( ele[ 0 ] );
6368							repeaterAddSectionAfter( epoObject, ele[ 0 ], ele[ 2 ], true );
6369							tmEpoField.val( function( i, currentValue ) {
6370								return currentValue ? parseInt( currentValue, 10 ) + 1 : 2;
6371							} );
6372						}
6373					} );
6374				} );
6375
6376			sectionQuantityRepeaters = obj.find( '.tc-section-repeater-quantity' );
6377			sectionQuantityRepeaters
6378				.toArray()
6379				.forEach( function( repeater, qx ) {
6380					var el = $( repeater );
6381					var tmEpoField;
6382					var elementInnerWrap;
6383					var repeaterElement;
6384					var length;
6385					var fieldData = [];
6386					var maxRows = el.closest( '.cpf-section' ).data( 'repeater-max-rows' );
6387					if ( el.data( 'tc-repeater-init' ) ) {
6388						return;
6389					}
6390					elementInnerWrap = el.find( '.tc-section-inner-wrap' );
6391					repeaterElement = elementInnerWrap.find( '.tc-repeater-section' );
6392					length = repeaterElement.length;
6393					tmEpoField = elementInnerWrap.find( '.sections_repeater' );
6394					repeaterElement.first().find( '.tm-epo-field' )
6395						.toArray()
6396						.forEach( function( field ) {
6397							var epofield = $( field );
6398							var id = epofield.attr( 'id' );
6399							if ( epofield.is( ':checkbox' ) ) {
6400								fieldData[ id ] = epofield.filter( ':checked' ).toArray().map( function( x ) {
6401									return $( x ).val();
6402								} );
6403							} else if ( epofield.is( ':radio' ) ) {
6404								fieldData[ id ] = epofield.filter( ':checked' ).val();
6405							} else {
6406								fieldData[ id ] = epofield.val();
6407							}
6408						} );
6409					el.data( 'repeater-init-value', fieldData );
6410
6411					el.data( 'tc-repeater-init', length );
6412					el.data( 'tc-repeater-name', tmEpoField.attr( 'name' ) );
6413
6414					if ( qtyElement.length ) {
6415						qtyElement
6416							.off( 'change.rs' + qx + 'cpf input.rs' + qx + 'cpf' )
6417							.on( 'change.rs' + qx + 'cpf input.rs' + qx + 'cpf', function( event ) {
6418								var field = $( this );
6419								var prevValue = field.data( 'epopreviousvalue' + qx );
6420								var value = $.epoAPI.applyFilter( 'qtyElementForRepeaterQuantityValue', field.val(), {
6421									epo: epoObject,
6422									currentCart: currentCart,
6423									obj: obj,
6424									qtyElement: qtyElement,
6425									field: field
6426								} );
6427								var difference = value - prevValue;
6428								var thisRepeaterElement;
6429								var i;
6430								var ele;
6431								var cloned;
6432								var repeaterLastUL;
6433								var fieldprevval;
6434								var firstcloned;
6435								if ( prevValue === undefined ) {
6436									prevValue = value - 1;
6437									difference = value - prevValue;
6438								}
6439								if ( event.isTrigger !== undefined ) {
6440									prevValue = el.find( '.tc-section-inner-wrap' ).find( '.tc-repeater-section' ).length;
6441									difference = value - prevValue;
6442								}
6443								if ( maxRows && difference > maxRows ) {
6444									difference = maxRows - 1;
6445								}
6446								if ( difference === 0 ) {
6447									return;
6448								}
6449								fieldprevval = $.epoAPI.applyFilter( 'qtyElementForRepeaterQuantity_epopreviousvalue', field.val(), {
6450									epo: epoObject,
6451									currentCart: currentCart,
6452									obj: obj,
6453									qtyElement: qtyElement,
6454									field: field
6455								} );
6456								if ( fieldprevval <= 0 ) {
6457									fieldprevval = 1;
6458								}
6459								if ( qx === quantityRepeaters.length ) {
6460									field.data( 'epopreviousvalue' + qx, fieldprevval );
6461								}
6462								if ( difference > 0 ) {
6463									thisRepeaterElement = elementInnerWrap.find( '.tc-repeater-section' ).eq( value - 1 );
6464									if ( thisRepeaterElement.length ) {
6465										return;
6466									}
6467									for ( i = 0; i < difference; i++ ) {
6468										cloned = repeaterAddSection( el, elementInnerWrap );
6469										if ( cloned ) {
6470											if ( ! firstcloned ) {
6471												firstcloned = cloned;
6472											}
6473											if ( ele ) {
6474												ele = ele.add( cloned[ 0 ] );
6475											} else {
6476												ele = cloned[ 0 ];
6477											}
6478											if ( i === 0 ) {
6479												repeaterLastUL = cloned[ 2 ];
6480											}
6481										}
6482									}
6483									if ( ele ) {
6484										tmEpoField.val( function( ii, currentValue ) {
6485											return currentValue ? parseInt( currentValue, 10 ) + parseInt( difference, 10 ) : 2;
6486										} );
6487										
6487firstcloned[ 1 ].after( ele );
6488										repeaterAddSectionAfter( epoObject, ele, repeaterLastUL );
6489									}
6490								} else {
6491									for ( i = value - difference; i > value; i -= 1 ) {
6492										thisRepeaterElement = elementInnerWrap.find( '.tc-repeater-section' ).eq( i - 1 );
6493										repeaterDeleteSection( elementInnerWrap, thisRepeaterElement, el );
6494									}
6495									tmEpoField.val( elementInnerWrap.find( '.tc-repeater-section' ).length );
6496								}
6497								currentCart.trigger( {
6498									type: 'tm-epo-update',
6499									norules: 2
6500								} );
6501							} );
6502						qtyElement.data( 'epopreviousvalue' + qx, $.epoAPI.applyFilter( 'qtyElementForRepeaterQuantityValue', qtyElement.val(), {
6503							epo: epoObject,
6504							currentCart: currentCart,
6505							obj: obj,
6506							qtyElement: qtyElement,
6507							field: qtyElement
6508						} ) ).trigger( 'change' );
6509					}
6510				} );
6511
6512			obj.find( '.tc-repeater-section-delete .delete' ).on( 'click', function() {
6513				var $this = $( this );
6514				var elementInnerWrap = $this.closest( '.tc-section-inner-wrap' );
6515				var repeaterElement = $this.closest( '.tc-repeater-section' );
6516				var tmEpoField;
6517				tmEpoField = elementInnerWrap.find( '.sections_repeater' );
6518				repeaterDeleteSection( elementInnerWrap, repeaterElement, elementInnerWrap.find( '.tc-section-repeater-add' ), $this );
6519				tmEpoField.val( function( ii, currentValue ) {
6520					return currentValue ? parseInt( currentValue, 10 ) - 1 : 2;
6521				} );
6522				epoObject.form.trigger( {
6523					type: 'tm-epo-update',
6524					norules: 2
6525				} );
6526			} );
6527		}
6528	}
6529
6530	function tm_set_color_pickers( obj ) {
6531		if ( ! obj ) {
6532			return;
6533		}
6534		obj = $( obj ).find( '.tm-color-picker' );
6535		if ( obj.length ) {
6536			obj.spectrum( {
6537				type: 'color',
6538				theme: 'epo',
6539				showButtons: true,
6540				allowEmpty: true,
6541				showInitial: true,
6542				showInput: true,
6543				clickoutFiresChange: false,
6544				chooseText: TMEPOJS.closeText,
6545				cancelText: TMEPOJS.i18n_cancel,
6546				clearText: ''
6547			} );
6548			obj.spectrum( 'enable' );
6549		}
6550	}
6551
6552	function tm_set_lightbox( obj ) {
6553		if ( ! obj ) {
6554			return;
6555		}
6556		if ( $( obj ).length ) {
6557			// document ready
6558			$( function() {
6559				$( obj ).tclightbox();
6560			} );
6561		}
6562	}
6563
6564	function has_active_changes_product_image( field ) {
6565		var uic = field.closest( '.tmcp-field-wrap' ).find( 'label img' );
6566		var src = $( uic ).first().attr( 'data-original' );
6567
6568		if ( field.is( 'select.tm-product-image' ) ) {
6569			field = field.children( 'option:selected' );
6570		}
6571
6572		if ( ! src ) {
6573			src = $( uic ).first().attr( 'src' );
6574		}
6575		if ( ! src ) {
6576			src = field.attr( 'data-image' );
6577		}
6578		if ( field.attr( 'data-imagep' ) ) {
6579			src = field.attr( 'data-imagep' );
6580		}
6581		if ( src ) {
6582			return true;
6583		}
6584
6585		return false;
6586	}
6587
6588	function tm_set_upload_fields( epoObject ) {
6589		var field;
6590		var dT;
6591		var name;
6592		var file;
6593		var selector = epoObject.is_associated
6594			? epoObject.this_epo_container.find( '.tm-epo-field.tmcp-upload' )
6595			: epoObject.this_epo_container.find( '.tm-epo-field.tmcp-upload' ).not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector + ' .tm-epo-field.tmcp-upload' );
6596
6597		try {
6598			selector
6599				.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector + ' .tm-epo-field.tmcp-upload' )
6600				.toArray()
6601				.forEach( function( el ) {
6602					var dataFiles;
6603					var dataFilename;
6604					file = [];
6605					field = $( el );
6606					if ( field.attr( 'data-file' ) === '' ) {
6607						return false;
6608					}
6609					dataFiles = field.attr( 'data-file' ).split( '|' );
6610					if ( dataFiles.length === 0 ) {
6611						return false;
6612					}
6613					if ( ClipboardEvent || DataTransfer ) {
6614						dT = new ClipboardEvent( '' ).clipboardData || new DataTransfer();
6615					}
6616					dataFiles.forEach( function( dataFile ) {
6617						dataFilename = $.epoAPI.util.basename( dataFile );
6618						if ( ClipboardEvent || DataTransfer ) {
6619							dT.items.add( new File( [ dataFile ], dataFilename ) );
6620						}
6621						file.push( dataFile );
6622					} );
6623					if ( dT ) {
6624						el.files = dT.files;
6625					}
6626					file = file.join( '|' );
6627					name = field.attr( 'name' );
6628					field.trigger( 'tcupload' );
6629					field.after( '<input type="hidden" class="tmcp-upload-hidden" name="' + name + '" value="' + file + '">' );
6630					field.removeAttr( 'data-file' );
6631				} );
6632		} catch ( err ) {
6633			window.console.log( err );
6634			$( '.tm-epo-field.tmcp-upload' ).not( '.tm-multiple-file-upload' ).addClass( 'tc-nodt' );
6635			errorObject = err;
6636		}
6637	}
6638
6639	function tm_set_upload_rules( epoObject ) {
6640		var epoEventId = epoObject.epoEventId;
6641		var this_epo_container = epoObject.this_epo_container;
6642
6643		if ( TMEPOJS.tm_epo_upload_popup === 'yes' ) {
6644			$.tcepo.formSubmitEvents[ epoEventId ][ $.tcepo.formSubmitEvents[ epoEventId ].length ] = {
6645				trigger: function() {
6646					return true;
6647				},
6648				on_true: function() {
6649					var upload_fields = this_epo_container.data( 'num_uploads' );
6650					var thisPopup;
6651					var ajaxSuccessFunc;
6652					if ( upload_fields && Object.keys( upload_fields ).length ) {
6653						thisPopup = $.tcFloatBox( {
6654							fps: 1,
6655							ismodal: true,
6656							width: '50%',
6657							height: '300px',
6658							classname: 'flasho tc-wrapper',
6659							data: $.epoAPI.template.html( tcAPI.templateEngine.tc_upload_messages, {
6660								files: upload_fields,
6661								title: TMEPOJS.i18n_uploading_files,
6662								message: TMEPOJS.i18n_uploading_message
6663							} )
6664						} );
6665						ajaxSuccessFunc = function() {
6666							thisPopup.destroy();
6667							jDocument.off( 'ajaxSuccess', ajaxSuccessFunc );
6668						};
6669						jDocument.on( 'ajaxSuccess', ajaxSuccessFunc );
6670					}
6671
6672					return true;
6673				},
6674				on_false: function() {
6675					return true;
6676				}
6677			};
6678		}
6679	}
6680
6681	function tm_set_expanables() {
6682		var obj = $( '.tc-expand' );
6683		obj.toArray().forEach( function( o ) {
6684			var el = $( o );
6685			var max = parseInt( el.attr( 'data-max-items' ), 10 );
6686			var ul = el.find( '.tmcp-ul-wrap' );
6687			var gap = ul.css( 'gap' ) || ul.css( 'row-gap' );
6688			var lis = ul.find( '> li' );
6689			var lisMax = lis.slice( 0, max );
6690			var height;
6691			var totalHeight;
6692			if ( lisMax.length ) {
6693				totalHeight = lis.toArray()
6694					.reduce( function( sum, element ) {
6695						return sum + $( element ).outerHeight( true );
6696					}, 0 );
6697				totalHeight = 'calc(100px + ' + totalHeight + 'px + (' + gap + ' * (' + max + ' - 1) ) )';
6698				height = lisMax.toArray()
6699					.reduce( function( sum, element ) {
6700						return sum + $( element ).outerHeight( true );
6701					}, 0 );
6702				height = 'calc(' + height + 'px + (' + gap + ' * (' + max + ' - 1) ) )';
6703				ul.css( 'max-height', height );
6704				ul.after( $( '<button type="button" data-height="' + height + '" data-total-height="' + totalHeight + '" class="button load-more-button">Load more</button>' ) );
6705			}
6706		} );
6707		jDocument.on( 'click.txexpand', '.load-more-button', function() {
6708			var b = $( this );
6709			var h;
6710			if ( b.is( '.expanded' ) ) {
6711				b.removeClass( 'expanded' );
6712			} else {
6713				b.addClass( 'expanded' );
6714			}
6715			h = b.is( '.expanded' ) ? $( this ).attr( 'data-total-height' ) : $( this ).attr( 'data-height' );
6716			b.prev().css( 'max-height', h );
6717		} );
6718	}
6719
6720	function tm_set_checkboxes_rules( epoObject ) {
6721		var this_epo_container = epoObject.this_epo_container;
6722		var main_product = epoObject.main_product;
6723		var epoEventId = epoObject.epoEventId;
6724		var limit_cont = this_epo_container.find( '.tm-limit' );
6725		var exactlimit_cont = this_epo_container.find( '.tm-exactlimit' );
6726		var minimumlimit_cont = this_epo_container.find( '.tm-minimumlimit' );
6727
6728		// Limit checkbox selection
6729		this_epo_container.on( 'change.cpflimit', 'input.tm-epo-field.tmcp-checkbox', function() {
6730			var $this = $( this );
6731			tm_limit_c_selection( $this, true );
6732			tm_exact_c_selection( $this, true );
6733		} );
6734		if ( limit_cont.length ) {
6735			tm_check_limit_cont( limit_cont, main_product, epoEventId );
6736		}
6737
6738		// Exact value checkbox check (Todo:check for isvisible)
6739		if ( exactlimit_cont.length ) {
6740			tm_check_exactlimit_cont( exactlimit_cont, main_product, epoEventId );
6741		}
6742
6743		// Minimum number checkbox check (Todo:check for isvisible)
6744		if ( minimumlimit_cont.length ) {
6745			tm_check_minimumlimit_cont( minimumlimit_cont, epoEventId );
6746		}
6747	}
6748
6749	function tm_set_radiobutton_rules() {
6750		// Find all elements with data-tm-sync attribute
6751		var $elements = $( '[data-tm-sync]' );
6752		// Group by the attribute value
6753		var groups = {};
6754
6755		if ( ! $elements.length ) {
6756			return;
6757		}
6758
6759		$elements.each( function() {
6760			var syncKey = $( this ).data( 'tm-sync' );
6761
6762			// If no value, skip or handle separately
6763			if ( ! syncKey ) {
6764				return;
6765			}
6766
6767			if ( ! groups[ syncKey ] ) {
6768				groups[ syncKey ] = [];
6769			}
6770
6771			groups[ syncKey ].push( this );
6772		} );
6773
6774		$.each( groups, function( syncKey, elements ) {
6775			var selector = 'input.tmcp-radio:not(.tc-force-disabled)';
6776			$( elements ).off( 'change.sync', selector ).on( 'change.sync', selector, function() {
6777				var $clickedRadio = $( this );
6778				var $currentUl = $clickedRadio.closest( '[data-tm-sync]' );
6779				var radioIndex = $currentUl.find( selector ).index( $clickedRadio );
6780
6781				// Sync to all other sync-div containers
6782				$( elements ).not( $currentUl ).each( function() {
6783					var $otherDiv = $( this );
6784					var $targetRadio = $otherDiv.find( selector ).eq( radioIndex );
6785					var $lis = $otherDiv.find( '.tmcp-field-wrap' );
6786					var $li = $targetRadio.closest( '.tmcp-field-wrap' );
6787
6788					if ( $targetRadio.length ) {
6789						// Uncheck all radios in this div first
6790						$otherDiv.find( selector ).prop( 'checked', false );
6791						// Check the radio at the same index
6792						$targetRadio.prop( 'checked', true );
6793						$lis.removeClass( 'tc-active' );
6794						$li.addClass( 'tc-active' );
6795					}
6796				} );
6797			} );
6798		} );
6799	}
6800
6801	function tm_theme_specific_actions( epoObject ) {
6802		var this_epo_container = epoObject.this_epo_container;
6803		var theme_name = TMEPOJS.theme_name;
6804		var all_epo_selects;
6805		var blaszok_selects;
6806
6807		if ( theme_name ) {
6808			theme_name = theme_name.toLowerCase();
6809			all_epo_selects = this_epo_container.find( 'select' );
6810
6811			switch ( theme_name ) {
6812				case 'flatsome':
6813				case 'flatsome-child':
6814				case 'flatsome child':
6815					all_epo_selects.wrap( '<div class="custom select-wrapper"/>' );
6816					break;
6817
6818				case 'avada':
6819				case 'avada-child':
6820				case 'avada child':
6821					all_epo_selects.wrap( '<div class="avada-select-parent tm-select-parent"></div>' );
6822					$( '<div class="select-arrow">&#xe61f;</div>' ).appendTo( this_epo_container.find( '.tm-select-parent' ) );
6823					if ( window.calc_select_arrow_dimensions ) {
6824						window.calc_select_arrow_dimensions();
6825						jWindow.on( 'tmsectionpoplink cpflogicdone', function() {
6826							window.calc_select_arrow_dimensions();
6827						} );
6828					} else if ( window.calcSelectArrowDimensions ) {
6829						window.calcSelectArrowDimensions();
6830						jWindow.on( 'tmsectionpoplink cpflogicdone', function() {
6831							window.calcSelectArrowDimensions();
6832						} );
6833					}
6834					break;
6835
6836				case 'bazar':
6837				case 'bazar-child':
6838				case 'bazar child':
6839					all_epo_selects.wrap( '<div class="tm-select-wrapper select-wrapper"/>' );
6840					break;
6841
6842				case 'blaszok':
6843				case 'blaszok-child':
6844				case 'blaszok child':
6845					blaszok_selects = function() {
6846						setTimeout( function() {
6847							$( '.tm-extra-product-options select' )
6848								.not( '.hasCustomSelect' )
6849								.filter( ':visible' )
6850								.toArray().forEach( function( el ) {
6851									el = $( el );
6852									if ( ! el.is( '.mpcthSelect' ) ) {
6853										el.width( el.outerWidth() );
6854										el.customSelect( { customClass: 'mpcthSelect' } );
6855									}
6856								} );
6857						}, 100 );
6858					};
6859					jWindow.on( 'cpflogicrun', function() {
6860						blaszok_selects();
6861					} );
6862					jWindow.on( 'epo_options_visible', function() {
6863						blaszok_selects();
6864					} );
6865
6866					break;
6867
6868				case 'handmade':
6869				case 'handmade child theme':
6870					$( '.tm-owl-slider.tcowl-carousel' ).addClass( 'manual' );
6871					break;
6872			}
6873
6874			jWindow.trigger( 'tm-theme-specific-actions', {
6875				epo: {
6876					theme_name: theme_name,
6877					all_epo_selects: all_epo_selects
6878				}
6879			} );
6880		}
6881
6882		// Fix added +/- quantity button on most themes.
6883		jDocument.off( 'click.cpf', '.quantity:not(.buttons_added) .minus, .quantity:not(.buttons_added) .plus' ).on( 'click.cpf', '.quantity:not(.buttons_added) .minus, .quantity:not(.buttons_added) .plus', function() {
6884			$( this ).closest( '.quantity' ).find( tcAPI.qtySelector ).trigger( 'change.cpf' );
6885		} );
6886	}
6887
6888	function tm_custom_variations( epoObject, form, item_id, $main_product, $epo_holder ) {
6889		var epoEventId = epoObject.epoEventId;
6890		var variation_id_selector = "input[name^='variation_id']";
6891		var tm_epo_variation_section;
6892		var li_variations;
6893		var composite_load_test;
6894		var form_event;
6895		var type;
6896		var name;
6897		var selector;
6898		var func;
6899		var i;
6900		var eventName = epoObject.is_associated ? 'tc_variation_form.tmlogic' : 'wc_variation_form.tmlogic';
6901		var eventNamePrefix = epoObject.is_associated ? 'tc_' : '';
6902		var variationsForm = epoObject.variations_form;
6903		var variationsTable = epoObject.is_associated ? variationsForm.find( '.tc-epo-element-variations' ) : variationsForm.find( '.variations' );
6904		var resetSelector = epoObject.is_associated ? '.tc-epo-element-variable-reset-variations' : '.reset_variations';
6905
6906		variationsForm.attr( 'data-epo_id', epoObject.epo_id );
6907
6908		if ( form.find( 'input.variation_id' ).length > 0 ) {
6909			variation_id_selector = 'input.variation_id';
6910		}
6911		if ( $epo_holder.find( '.tm-epo-variation-element' ).length || $epo_holder.data( 'tm-epo-variation-element' ) ) {
6912			tm_epo_variation_section = $epo_holder.find( '.tm-epo-variation-section' ).first();
6913			tm_epo_variation_section.find( '.cpf-type-variations' ).attr( 'data-epo_id', epoObject.epo_id ).attr( 'data-product_id', variationsForm.attr( 'data-product_id' ) );
6914
6915			$epo_holder.data( 'tm-epo-variation-element', tm_epo_variation_section.find( '.tm-epo-variation-element' ) );
6916
6917			if ( item_id && item_id !== 'main' && ! epoObject.is_associated ) {
6918				// on composite
6919
6920				variationsForm = epoObject.form;
6921				variationsTable = variationsForm.find( '.composite_component[data-item_id="' + item_id + '"]' ).find( '.variations' );
6922				variationsForm.attr( 'data-epo_id', epoObject.epo_id );
6923
6924				if ( variationsTable.length === 0 ) {
6925					return;
6926				}
6927
6928				li_variations = tm_epo_variation_section.closest( 'li.tm-extra-product-options-field' );
6929				if ( ! tm_epo_variation_section.is( '.tm-hidden' ) ) {
6930					variationsTable.hide();
6931				}
6932
6933				variationsTable.after( tm_epo_variation_section.addClass( 'tm-extra-product-options nopadding' ) );
6934				if ( li_variations.children().length === 0 || li_variations.text().trim() === '' ) {
6935					li_variations.remove();
6936				}
6937
6938				if ( ! tm_epo_variation_section.is( '.section_popup' ) ) {
6939					tm_epo_variation_section.removeClass( 'tc-cell' );
6940					tm_epo_variation_section.wrap( "<div class='tc-styled-variations'></div>" );
6941				} else {
6942					tm_epo_variation_section.wrap( "<div class='tc-styled-variations tc-row'></div>" );
6943				}
6944
6945				composite_load_test = false;
6946				form.off( eventName ).on( eventName, function() {
6947					composite_load_test = true;
6948					variationsForm.on( 'click.tmlogic', '.reset_variations', function() {
6949						tm_epo_variation_section.find( 'select.tm-epo-variation-element' ).val( '' ).children( 'option' ).prop( 'disabled', false ).show();
6950						tm_epo_variation_section.find( '.tm-epo-variation-element' ).prop( 'disabled', false ).removeClass( 'tm-disabled' ).prop( 'checked', false ).closest( 'li' ).show();
6951						jWindow.trigger( 'tmlazy' );
6952						tm_epo_variation_section.find( '.tm-epo-variation-element' ).trigger( 'tm_trigger_product_image' );
6953						tm_epo_variation_section.find( 'li' ).removeClass( 'tc-active tm-attribute-disabled' ).css( 'opacity', '' );
6954					} );
6955
6956					// Disable option fields that are unavaiable for current set of attributes
6957					form.off( 'woocommerce_update_variation_values_tmlogic' ).on( 'woocommerce_update_variation_values_tmlogic', function() {
6958						tm_custom_variations_update( form, epoObject );
6959					} );
6960					for ( i = 0; i < lateVariationEvent.length; i += 1 ) {
6961						form_event = lateVariationEvent[ i ];
6962						type = typeof form_event;
6963						if ( type === 'object' ) {
6964							name = typeof form_event.name === 'string' || false;
6965							selector = typeof form_event.selector === 'string' || false;
6966							func = typeof form_event.func === 'function' || false;
6967							if ( name && func ) {
6968								if ( selector === "input[name='variation_id']" ) {
6969									selector = variation_id_selector;
6970								}
6971								if ( form_event.selector ) {
6972									form.data( 'tm-styled-variations', 1 )
6973										.off( eventNamePrefix + form_event.name + i, selector )
6974										.on( eventNamePrefix + form_event.name + i, selector, form_event.func );
6975								} else {
6976									form.data( 'tm-styled-variations', 1 )
6977										.off( eventNamePrefix + form_event.name + i )
6978										.on( eventNamePrefix + form_event.name + i, form_event.func );
6979								}
6980							}
6981						}
6982					}
6983					lateVariationEvent = [];
6984					tm_epo_variation_section.find( '.tm-epo-variation-element:not(.tm-hidden .tm-epo-variation-element)' ).last().trigger( 'tm_epo_variation_element_change' );
6985				} );
6986				// document ready
6987				$( function() {
6988					if ( composite_load_test === false ) {
6989						form.trigger( eventName );
6990					}
6991				} );
6992			} else {
6993				if ( tm_epo_variation_section.length ) {
6994					if ( ! tm_epo_variation_section.is( '.tm-hidden' ) ) {
6995						variationsTable.hide();
6996					}
6997
6998					li_variations = tm_epo_variation_section.closest( 'li.tm-extra-product-options-field' );
6999
7000					variationsTable.after( tm_epo_variation_section.addClass( 'tm-extra-product-options nopadding' ) );
7001
7002					if ( li_variations.children().length === 0 || li_variations.text().trim() === '' ) {
7003						li_variations.remove();
7004					}
7005
7006					if ( ! tm_epo_variation_section.is( '.section_popup' ) ) {
7007						tm_epo_variation_section.removeClass( 'tc-cell' );
7008						tm_epo_variation_section.wrap( "<div class='tc-styled-variations'></div>" );
7009					} else {
7010						tm_epo_variation_section.wrap( "<div class='tc-styled-variations tc-row'></div>" );
7011					}
7012
7013					variationsForm.off( 'click.tmlogic', resetSelector ).on( 'click.tmlogic', resetSelector, function() {
7014						tm_epo_variation_section.find( 'select.tm-epo-variation-element' ).val( '' ).children( 'option' ).prop( 'disabled', false ).show();
7015						tm_epo_variation_section.find( '.tm-epo-variation-element' ).prop( 'disabled', false ).removeClass( 'tm-disabled' ).prop( 'checked', false ).closest( 'li' ).show();
7016						jWindow.trigger( 'tmlazy' );
7017						tm_epo_variation_section.find( '.tm-epo-variation-element' ).trigger( 'tm_trigger_product_image' );
7018						tm_epo_variation_section.find( 'li' ).removeClass( 'tc-active tm-attribute-disabled' ).css( 'opacity', '' );
7019					} );
7020				}
7021
7022				// Disable option fields that are unavaiable for current set of attributes
7023				variationsForm.off( 'woocommerce_update_variation_values_tmlogic' ).on( 'woocommerce_update_variation_values_tmlogic', function() {
7024					tm_custom_variations_update( variationsForm, epoObject );
7025				} );
7026
7027				for ( i = 0; i < lateVariationEvent.length; i += 1 ) {
7028					form_event = lateVariationEvent[ i ];
7029					type = typeof form_event;
7030					if ( type === 'object' ) {
7031						name = typeof form_event.name === 'string' || false;
7032						selector = typeof form_event.selector === 'string' || false;
7033						func = typeof form_event.func === 'function' || false;
7034						if ( name && func ) {
7035							if ( selector === "input[name='variation_id']" ) {
7036								selector = variation_id_selector;
7037							}
7038							if ( form_event.selector ) {
7039								variationsForm
7040									.data( 'tm-styled-variations', 1 )
7041									.off( eventNamePrefix + form_event.name + i, selector )
7042									.on( eventNamePrefix + form_event.name + i, selector, form_event.func );
7043							} else {
7044								variationsForm
7045									.data( 'tm-styled-variations', 1 )
7046									.off( eventNamePrefix + form_event.name + i )
7047									.on( eventNamePrefix + form_event.name + i, form_event.func );
7048							}
7049						}
7050					}
7051				}
7052				lateVariationEvent = [];
7053				tm_epo_variation_section.find( '.tm-epo-variation-element:not(.tm-hidden .tm-epo-variation-element)' ).last().trigger( 'tm_epo_variation_element_change' );
7054			}
7055
7056			// global event for custom variations
7057			$.tcepo.formSubmitEvents[ epoEventId ][ $.tcepo.formSubmitEvents[ epoEventId ].length ] = {
7058				trigger: function() {
7059					return true;
7060				},
7061				on_true: function() {
7062					tm_epo_variation_section.find( '.tm-epo-variation-element' ).attr( 'disabled', 'disabled' );
7063					return true;
7064				},
7065				on_false: function() {
7066					tm_epo_variation_section.find( '.tm-epo-variation-element' ).prop( 'disabled', false );
7067				}
7068			};
7069
7070			$( document.body ).on( 'added_to_cart', function() {
7071				tm_epo_variation_section.find( '.tm-epo-variation-element' ).prop( 'disabled', false );
7072			} );
7073		}
7074	}
7075
7076	function repopulate_backup_image_atts( img, product_element ) {
7077		var $gallery_img = product_element.find( '.flex-control-nav li:eq(0) img' );
7078		var $gallery_wrapper = product_element.find( '.woocommerce-product-gallery__wrapper ' );
7079		var $product_img_wrap = $gallery_wrapper.find( '.woocommerce-product-gallery__image, .woocommerce-product-gallery__image--placeholder' ).eq( 0 );
7080		var $product_img = img;
7081		var $product_link = img.closest( 'a' );
7082
7083		$product_img.attr( 'data-o_' + 'src', $.tc_product_image_store[ 0 ].src );
7084		$product_img.attr( 'data-o_' + 'srcset', $.tc_product_image_store[ 0 ].srcset );
7085		$product_img.attr( 'data-o_' + 'sizes', $.tc_product_image_store[ 0 ].sizes );
7086		$product_img.attr( 'data-o_' + 'title', $.tc_product_image_store[ 0 ].title );
7087		$product_img.attr( 'data-o_' + 'alt', $.tc_product_image_store[ 0 ].alt );
7088		$product_img.attr( 'data-o_' + 'data-src', $.tc_product_image_store[ 0 ][ 'data-src' ] );
7089		$product_img.attr( 'data-o_' + 'data-large_image', $.tc_product_image_store[ 0 ][ 'data-large_image' ] );
7090		$product_img.attr( 'data-o_' + 'data-large_image_width', $.tc_product_image_store[ 0 ][ 'data-large_image_width' ] );
7091		$product_img.attr( 'data-o_' + 'data-large_image_height', $.tc_product_image_store[ 0 ][ 'data-large_image_height' ] );
7092		$product_img_wrap.attr( 'data-o_' + 'data-thumb', $.tc_product_image_store[ 1 ][ 'data-thumb' ] );
7093		if ( $.tc_product_image_store[ 2 ] ) {
7094			$gallery_img.attr( 'data-o_' + 'src', $.tc_product_image_store[ 2 ].src );
7095		}
7096
7097		$product_link.attr( 'data-o_' + 'href', $.tc_product_image_store[ 3 ].href );
7098		$product_link.attr( 'data-o_' + 'title', $.tc_product_image_store[ 3 ].title );
7099	}
7100
7101	function reset_saved_image( img, product_element ) {
7102		var $gallery_img = product_element.find( '.flex-control-nav li:eq(0) img' );
7103		var $gallery_wrapper = product_element.find( '.woocommerce-product-gallery__wrapper ' );
7104		var $product_img_wrap = $gallery_wrapper.find( '.woocommerce-product-gallery__image, .woocommerce-product-gallery__image--placeholder' ).eq( 0 );
7105		var $product_img = img;
7106		var $product_link = img.closest( 'a' );
7107
7108		// backup current product image attributes
7109		if ( ! $.isEmptyObject( $.tc_product_image ) ) {
7110			$.tc_product_image_store = $.tc_pre_populate_store();
7111			$.tc_product_image_store = $.tc_maybe_copy_object_values( $.tc_product_image_store, $.tc_product_image );
7112		} else {
7113			$.tc_product_image_store = $.tc_populate_store( img, product_element );
7114		}
7115
7116		$product_img.tc_update_attr( 'src', 0 );
7117		$product_img.tc_update_attr( 'srcset', 0 );
7118		$product_img.tc_update_attr( 'sizes', 0 );
7119		$product_img.tc_update_attr( 'title', 0 );
7120		$product_img.tc_update_attr( 'alt', 0 );
7121		$product_img.tc_update_attr( 'data-src', 0 );
7122		$product_img.tc_update_attr( 'data-large_image', 0 );
7123		$product_img.tc_update_attr( 'data-large_image_width', 0 );
7124		$product_img.tc_update_attr( 'data-large_image_height', 0 );
7125		$product_img_wrap.tc_update_attr( 'data-thumb', 1 );
7126		$gallery_img.tc_update_attr( 'src', 2 );
7127
7128		$product_link.tc_update_attr( 'href', 3 );
7129		$product_link.tc_update_attr( 'title', 3 );
7130	}
7131
7132	function image_update( data, img, product_element ) {
7133		var $gallery_img = product_element.find( '.flex-control-nav li:eq(0) img' );
7134		var $gallery_wrapper = product_element.find( '.woocommerce-product-gallery__wrapper ' );
7135		var $product_img_wrap = $gallery_wrapper.find( '.woocommerce-product-gallery__image, .woocommerce-product-gallery__image--placeholder' ).eq( 0 );
7136		var $product_img = img;
7137		var $product_link = img.closest( 'a' );
7138		var $img_zoom = $product_link.next( '.zoomImg' );
7139
7140		if ( data && data.image_link && data.image_link && data.image_link.length > 1 ) {
7141			if ( data.full_src === null || data.full_src === '' ) {
7142				data.full_src = data.image_link;
7143			}
7144			if ( data.full_src_w === null || data.full_src_w === '' ) {
7145				data.full_src_w = $product_img.attr( 'data-large_image_width' );
7146			}
7147			if ( data.full_src_h === null || data.full_src_h === '' ) {
7148				data.full_src_h = $product_img.attr( 'data-large_image_height' );
7149			}
7150			if ( $product_img.length ) {
7151				if ( ! data.image_srcset ) {
7152					data.image_sizes = false;
7153				}
7154				if ( ! data.image_sizes ) {
7155					data.image_srcset = false;
7156				}
7157				$product_img.tc_set_attr( 'src', data.image_link, 0 );
7158				$product_img.tc_set_attr( 'srcset', data.image_srcset, 0 );
7159				$product_img.tc_set_attr( 'sizes', data.image_sizes, 0 );
7160				$product_img.tc_set_attr( 'title', data.image_title, 0 );
7161				$product_img.tc_set_attr( 'alt', data.image_alt, 0 );
7162				$product_img.tc_set_attr( 'data-src', data.full_src, 0 );
7163				$product_img.tc_set_attr( 'data-large_image', data.full_src, 0 );
7164				$product_img.tc_set_attr( 'data-large_image_width', data.full_src_w, 0 );
7165				$product_img.tc_set_attr( 'data-large_image_height', data.full_src_h, 0 );
7166				$product_img_wrap.tc_set_attr( 'data-thumb', data.image_link, 1 );
7167			}
7168			if ( $gallery_img.length ) {
7169				$gallery_img.tc_set_attr( 'src', data.image_link, 2 );
7170				$gallery_img.tc_set_attr( 'srcset', data.image_srcset, 2 );
7171				$gallery_img.tc_set_attr( 'sizes', data.image_sizes, 2 );
7172			}
7173			if ( $product_link.length ) {
7174				$product_link.tc_set_attr( 'href', data.full_src, 3 );
7175				$product_link.tc_set_attr( 'title', data.image_caption, 3 );
7176			}
7177			if ( $img_zoom.length ) {
7178				$img_zoom.tc_set_attr( 'src', data.full_src, 4 );
7179			}
7180		} else {
7181			if ( $product_img.length ) {
7182				$product_img.tc_reset_attr( 'src', 0 );
7183				$product_img.tc_reset_attr( 'srcset', 0 );
7184				$product_img.tc_reset_attr( 'sizes', 0 );
7185				$product_img.tc_reset_attr( 'title', 0 );
7186				$product_img.tc_reset_attr( 'alt', 0 );
7187				$product_img.tc_reset_attr( 'data-src', 0 );
7188				$product_img.tc_reset_attr( 'data-large_image', 0 );
7189				$product_img.tc_reset_attr( 'data-large_image_width', 0 );
7190				$product_img.tc_reset_attr( 'data-large_image_height', 0 );
7191				$product_img_wrap.tc_reset_attr( 'data-thumb', 1 );
7192			}
7193			if ( $gallery_img.length ) {
7194				$gallery_img.tc_reset_attr( 'src', 2 );
7195				$gallery_img.tc_reset_attr( 'srcset', 2 );
7196				$gallery_img.tc_reset_attr( 'sizes', 2 );
7197			}
7198			if ( $product_link.length ) {
7199				$product_link.tc_reset_attr( 'href', 3 );
7200				$product_link.tc_reset_attr( 'title', 3 );
7201			}
7202			if ( $img_zoom.length ) {
7203				$img_zoom.tc_reset_attr( 'src', 4 );
7204			}
7205		}
7206	}
7207
7208	function get_main_product_image( epoObject, product_element ) {
7209		var img;
7210
7211		if ( epoObject.is_associated ) {
7212			img = product_element.find( '.tc-product-image .wp-post-image' ).first();
7213		} else if ( TMEPOJS.tm_epo_global_product_image_selector !== '' ) {
7214			img = $( TMEPOJS.tm_epo_global_product_image_selector );
7215		} else {
7216			img = product_element.find( '.woocommerce-product-gallery__image:not(.clone), .woocommerce-product-gallery__image--placeholder:not(.clone)' ).eq( 0 ).find( '.wp-post-image' ).first();
7217			if ( img.length === 0 ) {
7218				img = product_element.find( 'a.woocommerce-main-image img, img.woocommerce-main-image,a img' ).not( '.thumbnails img,.product_list_widget img' ).first();
7219			}
7220			if ( img.length === 0 ) {
7221				img = product_element.find( 'img.wp-post-image' ).not( '.thumbnails img,.product_list_widget img' ).first();
7222			}
7223			if ( img.length === 0 ) {
7224				img = product_element.find( '.elementor-widget-wd_single_product_gallery img.wp-post-image' ).first();
7225			}
7226			if ( img.length === 0 ) {
7227				img = product_element.find( '.elementor-widget-ae-post-image .wp-post-image' ).first();
7228			}
7229			if ( img.length === 0 ) {
7230				img = $( '.woocommerce div.product div.images' ).not( '.thumbnails img,.product_list_widget img' ).first();
7231			}
7232		}
7233
7234		if ( $( img ).length > 1 ) {
7235			img = $( img ).first();
7236		}
7237
7238		return img;
7239	}
7240
7241	function get_product_element( epoObject ) {
7242		var main_product;
7243		var product_id;
7244		var product_element;
7245
7246		if ( epoObject.is_associated ) {
7247			return epoObject.main_product.closest( '.tc-epo-element-product-container' );
7248		}
7249
7250		main_product = epoObject.main_product;
7251		product_id = epoObject.product_id;
7252		product_element = main_product.closest( '#product-' + product_id );
7253
7254		if ( product_element.length <= 0 ) {
7255			product_element = main_product.closest( '.post-' + product_id );
7256		}
7257
7258		return product_element;
7259	}
7260
7261	function gallery_compatibility_actions( gallery_type, clone_image, preload_img, visible, event_data, $form, product_element ) {
7262		var gallery;
7263		var _elements;
7264		var ge;
7265		var galleryWidth;
7266		var zoomEnabled;
7267		var image;
7268		var zoom_options;
7269
7270		for ( gallery in gallery_type ) {
7271			if ( Object.prototype.hasOwnProperty.call( gallery_type, gallery ) ) {
7272				gallery = gallery_type[ gallery ];
7273
7274				if ( gallery.enabled ) {
7275					switch ( gallery.type ) {
7276						case 'yith':
7277							if ( ! clone_image ) {
7278								if ( ! visible ) {
7279									gallery.yith_wcmg_zoom.attr( 'href', gallery._yith_wcmg_default_zoom );
7280								} else {
7281									gallery.yith_wcmg_zoom.attr( 'href', gallery.yith_wcmg_default_zoom );
7282								}
7283								if ( gallery.element.data( 'yith_magnifier' ) ) {
7284									gallery.element.yith_magnifier( 'destroy' );
7285								}
7286
7287								gallery.element.yith_magnifier( window.yith_magnifier_options );
7288							} else {
7289								clone_image.attr( 'srcset', preload_img ).attr( 'src-orig', preload_img );
7290
7291								if ( gallery.element.data( 'yith_magnifier' ) ) {
7292									gallery.element.yith_magnifier( 'destroy' );
7293								}
7294								_elements = {
7295									elements: {
7296										zoom: $( '.yith_magnifier_zoom' ),
7297										zoomImage: clone_image,
7298										gallery: $( '.yith_magnifier_gallery li a' )
7299									}
7300								};
7301
7302								gallery.element.yith_magnifier( $.extend( true, {}, window.yith_magnifier_options, _elements ) );
7303							}
7304							break;
7305						case 'iosslider':
7306							setTimeout(
7307								function( g ) {
7308									g.element.iosSlider( 'update' );
7309								}.bind( null, gallery ),
7310								150
7311							);
7312							break;
7313						case 'flexslider':
7314							jWindow.trigger( 'resize' );
7315							break;
7316						case 'elevatezoom':
7317							gallery.element.each(
7318								function( g, j ) {
7319									var elevateZoom = j( this ).data( 'elevateZoom' );
7320									if ( typeof elevateZoom !== 'undefined' ) {
7321										elevateZoom.swaptheimage( g, g );
7322									}
7323								}.bind( null, preload_img, $ )
7324							);
7325							break;
7326						case 'easyzoom':
7327							gallery.element.swap( null, preload_img );
7328							break;
7329						case 'easyzoom-flatsome':
7330							gallery.element.swap( preload_img, preload_img );
7331							break;
7332						case 'woocommerce':
7333							if ( clone_image ) {
7334								gallery.element.flexslider( 0 );
7335								gallery.element.trigger( 'woocommerce_gallery_reset_slide_position' );
7336								ge = gallery.element;
7337								window.setTimeout(
7338									function( g, w ) {
7339										g.trigger( 'woocommerce_gallery_init_zoom' );
7340										w.trigger( 'resize' );
7341									}.bind( null, ge, jWindow ),
7342									10
7343								);
7344							}
7345							break;
7346						case 'zoom':
7347							if ( product_element ) {
7348								galleryWidth = product_element.find( '.woocommerce-product-gallery--with-images' ).width();
7349								zoomEnabled = false;
7350
7351								image = gallery.element.find( 'img.wp-post-image' );
7352								if ( image.attr( 'data-large_image_width' ) > galleryWidth ) {
7353									zoomEnabled = true;
7354								}
7355
7356								if ( zoomEnabled ) {
7357									zoom_options = {
7358										touch: false
7359									};
7360									if ( 'ontouchstart' in window ) {
7361										zoom_options.on = 'click';
7362									}
7363
7364									gallery.element.trigger( 'zoom.destroy' );
7365									gallery.element.zoom( zoom_options );
7366								} else {
7367									gallery.element.trigger( 'zoom.destroy' );
7368								}
7369							}
7370							break;
7371					}
7372				}
7373			}
7374		}
7375
7376		jWindow.trigger( 'tm_gallery_compatibility_actions', {
7377			event_data: event_data,
7378			product_element: product_element,
7379			form: $form
7380		} );
7381	}
7382
7383	function get_gallery_type( epoObject, img, product_element ) {
7384		// YITH WooCommerce Zoom Magnifier
7385		var is_yith_wcmg;
7386		var yith_wcmg;
7387		var yith_wcmg_zoom;
7388		var yith_wcmg_default_zoom;
7389		var _yith_wcmg_default_zoom;
7390		var yith_wcmg_default_image;
7391
7392		// iosslider - Touch Enabled, Responsive jQuery Horizontal Content
7393		// Slider/Carousel/Image Gallery Plugin
7394		var is_iosSlider;
7395		var is_iosSlider_element;
7396
7397		// ThemeFusion flexslider
7398		var is_flexslider;
7399		var is_flexslider_element;
7400
7401		// elevateZoom A Jquery Image Zoom Plugin
7402		var is_elevateZoom;
7403		var is_elevateZoom_obj;
7404
7405		// EasyZoom jQuery image zoom plugin
7406		var is_easyzoom;
7407		var is_easyzoom_element;
7408
7409		// new flatsome easyzoom
7410		var is_easyzoom_flatsome;
7411		var is_easyzoom_flatsome_element;
7412
7413		// WooCommerce 2.7x gallery
7414		var is_wc27_gallery;
7415		var is_wc27_gallery_element;
7416		var wc27_zoom_target;
7417		var wc_single_product_params;
7418		var zoom_target_temp;
7419
7420		// fn.zoom
7421		var is_zoom_enabled;
7422		var zoom_images;
7423		var gallery;
7424
7425		if ( epoObject.is_associated ) {
7426			return {};
7427		}
7428
7429		// YITH WooCommerce Zoom Magnifier
7430		is_yith_wcmg = false;
7431		yith_wcmg = $( '.images' );
7432		yith_wcmg_zoom = $( '.yith_magnifier_zoom' );
7433		yith_wcmg_default_zoom = yith_wcmg.find( '.yith_magnifier_zoom' ).first().attr( 'href' );
7434		_yith_wcmg_default_zoom = yith_wcmg_default_zoom;
7435		yith_wcmg_default_image = yith_wcmg.find( '.yith_magnifier_zoom img' ).first().attr( 'src' );
7436
7437		// iosslider - Touch Enabled, Responsive jQuery Horizontal Content
7438		// Slider/Carousel/Image Gallery Plugin
7439		is_iosSlider = false;
7440		is_iosSlider_element = $( '.iosSlider.product-gallery-slider,.iosSlider.product-slider' );
7441
7442		// ThemeFusion flexslider
7443		is_flexslider = false;
7444		is_flexslider_element = product_element.find( '.images .fusion-flexslider' );
7445
7446		// elevateZoom A Jquery Image Zoom Plugin
7447		is_elevateZoom = img.data( 'elevateZoom' ) || false;
7448		is_elevateZoom_obj = product_element.find( 'div.product-images .woocommerce-main-image' );
7449
7450		// EasyZoom jQuery image zoom plugin
7451		is_easyzoom = false;
7452		is_easyzoom_element = product_element.find( '.images .easyzoom' );
7453
7454		// new flatsome easyzoom
7455		is_easyzoom_flatsome = false;
7456		is_easyzoom_flatsome_element = product_element.find( '.images .easyzoom' );
7457
7458		// WooCommerce 2.7x gallery
7459		is_wc27_gallery = false;
7460		is_wc27_gallery_element = product_element.find( '.woocommerce-product-gallery' );
7461		wc27_zoom_target = false;
7462		wc_single_product_params = window.wc_single_product_params;
7463
7464		// fn.zoom
7465		is_zoom_enabled = typeof $.fn.zoom === 'function' && wc_single_product_params && wc_single_product_params.zoom_enabled;
7466		zoom_images = false;
7467
7468		if ( window.yith_magnifier_options && yith_wcmg.data( 'yith_magnifier' ) ) {
7469			is_yith_wcmg = true;
7470		}
7471
7472		if ( is_iosSlider_element.length && is_iosSlider_element.iosSlider ) {
7473			is_iosSlider = true;
7474		}
7475
7476		if ( is_flexslider_element.length && is_flexslider_element.flexslider ) {
7477			is_flexslider = true;
7478		}
7479
7480		if ( is_easyzoom_element.length && is_easyzoom_element.filter( '.images .easyzoom.first' ).data( 'easyZoom' ) ) {
7481			is_easyzoom_element = is_easyzoom_element.filter( '.images .easyzoom.first' ).data( 'easyZoom' );
7482			is_easyzoom = true;
7483		}
7484
7485		if ( ! is_easyzoom ) {
7486			is_easyzoom_flatsome_element = product_element.find( '.images .has-image-zoom .slide' );
7487			if ( is_easyzoom_flatsome_element.length && is_easyzoom_flatsome_element.filter( '.images .has-image-zoom .slide.first' ).data( 'easyZoom' ) ) {
7488				is_easyzoom_flatsome_element = is_easyzoom_flatsome_element.filter( '.images .has-image-zoom .slide.first' ).data( 'easyZoom' );
7489				is_easyzoom_flatsome = true;
7490			}
7491		}
7492
7493		if ( document.readyState === 'complete' ) {
7494			setTimeout( function() {
7495				if ( is_easyzoom_element.length && is_easyzoom_element.data( 'easyZoom' ) ) {
7496					is_easyzoom_element = is_easyzoom_element.data( 'easyZoom' );
7497					is_easyzoom = true;
7498				}
7499				if ( is_easyzoom_flatsome_element.length && is_easyzoom_flatsome_element.data( 'easyZoom' ) ) {
7500					is_easyzoom_flatsome_element = is_easyzoom_flatsome_element.data( 'easyZoom' );
7501					is_easyzoom_flatsome = true;
7502				}
7503			}, 150 );
7504		} else {
7505			jWindow.on( 'load', function() {
7506				setTimeout( function() {
7507					if ( is_easyzoom_element.length && is_easyzoom_element.data( 'easyZoom' ) ) {
7508						is_easyzoom_element = is_easyzoom_element.data( 'easyZoom' );
7509						is_easyzoom = true;
7510					}
7511					if ( is_easyzoom_flatsome_element.length && is_easyzoom_flatsome_element.data( 'easyZoom' ) ) {
7512						is_easyzoom_flatsome_element = is_easyzoom_flatsome_element.data( 'easyZoom' );
7513						is_easyzoom_flatsome = true;
7514					}
7515				}, 150 );
7516			} );
7517		}
7518
7519		if ( is_wc27_gallery_element.length && is_wc27_gallery_element.data( 'flexslider' ) ) {
7520			is_wc27_gallery = true;
7521
7522			if ( typeof $.fn.zoom === 'function' && wc_single_product_params && wc_single_product_params.zoom_enabled ) {
7523				zoom_target_temp = img.closest( '.woocommerce-product-gallery__image' );
7524				// Ommiting the following condition:
7525				// && img.width() > $( '.woocommerce-product-gallery' ).width()
7526				if ( zoom_target_temp.length > 0 ) {
7527					wc27_zoom_target = zoom_target_temp;
7528					img.data.wc27_zoom_target = wc27_zoom_target;
7529				}
7530			}
7531		}
7532
7533		if ( ! is_wc27_gallery && is_zoom_enabled ) {
7534			zoom_images = product_element.find( '.woocommerce-product-gallery .woocommerce-product-gallery__image' );
7535		}
7536
7537		gallery = {
7538			is_yith_wcmg: {
7539				type: 'yith',
7540				enabled: is_yith_wcmg,
7541				element: yith_wcmg,
7542				yith_wcmg_zoom: yith_wcmg_zoom,
7543				_yith_wcmg_default_zoom: _yith_wcmg_default_zoom,
7544				yith_wcmg_default_image: yith_wcmg_default_image
7545			},
7546			is_iosSlider: {
7547				type: 'iosslider',
7548				enabled: is_iosSlider,
7549				element: is_iosSlider_element
7550			},
7551			is_flexslider: {
7552				type: 'flexslider',
7553				enabled: is_flexslider,
7554				element: is_flexslider_element
7555			},
7556			is_elevateZoom: {
7557				type: 'elevatezoom',
7558				enabled: is_elevateZoom,
7559				element: is_elevateZoom_obj
7560			},
7561			is_easyzoom: {
7562				type: 'easyzoom',
7563				enabled: is_easyzoom,
7564				element: is_easyzoom_element
7565			},
7566			is_easyzoom_flatsome: {
7567				type: 'easyzoom-flatsome',
7568				enabled: is_easyzoom_flatsome,
7569				element: is_easyzoom_flatsome_element
7570			},
7571			is_wc27_gallery: {
7572				type: 'woocommerce',
7573				enabled: is_wc27_gallery,
7574				element: is_wc27_gallery_element
7575			},
7576			is_zoom_enabled: {
7577				type: 'zoom',
7578				enabled: ! is_wc27_gallery && is_zoom_enabled,
7579				element: zoom_images
7580			}
7581		};
7582
7583		return gallery;
7584	}
7585
7586	function tm_product_image_self( epoObject ) {
7587		var this_epo_container = epoObject.is_associated ? epoObject.this_epo_container : epoObject.this_epo_container.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector );
7588		var variationsForm = epoObject.variations_form;
7589		var main_product = epoObject.main_product;
7590		var $form = epoObject.form;
7591		var img;
7592		var gallery_type;
7593		var product_element = get_product_element( epoObject );
7594		var last_active_field = [];
7595		var el;
7596		var el_current;
7597		var imp;
7598		var selector;
7599		var eventNamePrefix = epoObject.is_associated ? 'tc_' : '';
7600		// This currently has a limitation that it doesn't work if there is variation active onload.
7601		var main_tc_product_image_store;
7602
7603		img = get_main_product_image( epoObject, product_element );
7604		gallery_type = get_gallery_type( epoObject, img, product_element );
7605
7606		if ( $( img ).length > 0 ) {
7607			$form.on( eventNamePrefix + 'reset_image.tcpi', function() {
7608				setTimeout( function() {
7609					if ( TMEPOJS.tm_epo_global_image_recalculate === 'yes' ) {
7610						img = get_main_product_image( epoObject, product_element );
7611						$.tc_product_image_store = main_tc_product_image_store;
7612					}
7613					// restore product image atts from backup
7614					$.tc_product_image = $.tc_replace_object_values( $.tc_product_image, $.tc_product_image_store );
7615
7616					last_active_field = [];
7617
7618					$( this_epo_container.find( '.tm-product-image:checked,select.tm-product-image' ) )
7619						.add( variationsForm.find( '.tm-epo-variation-section' ).first().find( '.tm-product-image:checked,select.tm-product-image' ) )
7620						.toArray().forEach( function( pi ) {
7621							pi = $( pi );
7622							if ( field_is_active( pi ) && pi.val() !== '' ) {
7623								last_active_field.push( pi );
7624							}
7625						} );
7626					if ( last_active_field.length ) {
7627						last_active_field[ last_active_field.length - 1 ].trigger( 'tm_trigger_product_image' );
7628					} else {
7629						$.tc_product_image_store = $.tc_populate_store( img, product_element );
7630					}
7631				}, window.tc_epo_product_image_change_delay || 0 );
7632			} );
7633
7634			$form.on( eventNamePrefix + 'found_variation.tcpi', function() {
7635				setTimeout( function() {
7636					if ( TMEPOJS.tm_epo_global_image_recalculate === 'yes' ) {
7637						img = get_main_product_image( epoObject, product_element );
7638					}
7639					reset_saved_image( img, product_element );
7640
7641					last_active_field = [];
7642					$( this_epo_container.find( '.tm-product-image:checked,select.tm-product-image' ) )
7643						.add( variationsForm.find( '.tm-epo-variation-section' ).first().find( '.tm-product-image:checked,select.tm-product-image' ) )
7644						.toArray().forEach( function( pi ) {
7645							pi = $( pi );
7646							if ( field_is_active( pi ) && pi.val() !== '' ) {
7647								last_active_field.push( pi );
7648							}
7649						} );
7650					if ( last_active_field.length ) {
7651						repopulate_backup_image_atts( img, product_element );
7652						last_active_field[ last_active_field.length - 1 ].trigger( 'tm_trigger_product_image' );
7653					}
7654				}, window.tc_epo_product_image_change_delay || 0 );
7655			} );
7656
7657			$.tc_product_image_store = $.tc_maybe_copy_object_values_from_img( $.tc_product_image_store, img, product_element );
7658			main_tc_product_image_store = $.epoAPI.util.deepCopyArray( $.tc_product_image_store );
7659
7660			main_product.off( 'tm_change_product_image' ).on( 'tm_change_product_image', function( evt, event_data ) {
7661				var data;
7662				evt.stopImmediatePropagation();
7663
7664				el = event_data.element;
7665				el_current = event_data.element_current;
7666				if ( el && el_current ) {
7667					imp = el.data( 'imagep' );
7668					selector = '';
7669					if ( imp !== '' ) {
7670						selector = 'imagep';
7671					} else if ( el.data( 'changes-product-image' ) === 'images' ) {
7672						selector = 'image';
7673					}
7674					data = event_data.element_current.data( 'image-variations' );
7675
7676					if ( data ) {
7677						data = data[ selector ];
7678					}
7679
7680					if ( data === undefined ) {
7681						// Enter the following if you want to restore the original product image
7682						// main_product.trigger( 'tm_restore_product_image', event_data );
7683						return;
7684					}
7685
7686					last_active_field = [];
7687					$( this_epo_container.find( '.tm-product-image:checked,select.tm-product-image' ) )
7688						.add( variationsForm.find( '.tm-epo-variation-section' ).first().find( '.tm-product-image:checked,select.tm-product-image' ) )
7689						.toArray().forEach( function( pi ) {
7690							pi = $( pi );
7691							if ( pi.is( 'option' ) ) {
7692								pi = pi.closest( 'select' );
7693							}
7694							if ( pi.val() !== '' && field_is_active( pi ) ) {
7695								last_active_field.push( pi );
7696							}
7697						} );
7698
7699					if ( last_active_field.length ) {
7700						if ( ! last_active_field[ last_active_field.length - 1 ].is( el ) ) {
7701							return;
7702						}
7703					}
7704
7705					setTimeout( function() {
7706						if ( TMEPOJS.tm_epo_global_image_recalculate === 'yes' ) {
7707							img = get_main_product_image( epoObject, product_element );
7708						}
7709						image_update( data, img, product_element );
7710						gallery_compatibility_actions( gallery_type, img, data.image_link, false, event_data, $form, product_element );
7711					}, window.tc_epo_product_image_change_delay || 0 );
7712				}
7713			} );
7714
7715			main_product.off( 'tm_restore_product_image' ).on( 'tm_restore_product_image', function( evt, event_data ) {
7716				evt.stopImmediatePropagation();
7717
7718				el = event_data ? event_data.element : false;
7719				last_active_field = [];
7720
7721				if ( el ) {
7722					$( this_epo_container.find( '.tm-product-image:checked,select.tm-product-image' ) )
7723						.add( variationsForm.find( '.tm-epo-variation-section' ).first().find( '.tm-product-image:checked,select.tm-product-image' ) )
7724						.toArray().forEach( function( pi ) {
7725							pi = $( pi );
7726							if ( field_is_active( pi ) && pi.val() !== '' ) {
7727								last_active_field.push( pi );
7728							}
7729						} );
7730					if ( last_active_field.length ) {
7731						if ( ! last_active_field[ last_active_field.length - 1 ].is( el ) ) {
7732							last_active_field[ last_active_field.length - 1 ].trigger( 'tm_trigger_product_image' );
7733							return;
7734						}
7735					}
7736				}
7737
7738				setTimeout( function() {
7739					if ( TMEPOJS.tm_epo_global_image_recalculate === 'yes' ) {
7740						img = get_main_product_image( epoObject, product_element );
7741					}
7742					image_update( false, img, product_element );
7743					gallery_compatibility_actions( gallery_type, false, img.attr( 'src' ), false, event_data, $form, product_element );
7744				}, window.tc_epo_product_image_change_delay || 0 );
7745			} );
7746
7747			last_active_field = [];
7748			$( this_epo_container.find( '.tm-product-image:checked,select.tm-product-image' ) )
7749				.add( variationsForm.find( '.tm-epo-variation-section' ).first().find( '.tm-product-image:checked,select.tm-product-image' ) )
7750				.toArray().forEach( function( pi ) {
7751					pi = $( pi );
7752					if ( field_is_active( pi ) && pi.val() !== '' ) {
7753						last_active_field.push( pi );
7754					}
7755				} );
7756			if ( last_active_field.length ) {
7757				last_active_field[ last_active_field.length - 1 ].trigger( 'tm_trigger_product_image' );
7758			}
7759		}
7760
7761		jWindow.trigger( 'tm_product_image_loaded' );
7762	}
7763
7764	function tm_product_image_inline( epoObject ) {
7765		var this_epo_container = epoObject.is_associated ? epoObject.this_epo_container : epoObject.this_epo_container.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector );
7766		var main_product = epoObject.main_product;
7767		var product_id = epoObject.product_id;
7768		var $form = epoObject.form;
7769		var img;
7770		var product_element = get_product_element( epoObject );
7771		var gallery_type;
7772		var a;
7773		var img_src_original;
7774		var img_width;
7775		var img_height;
7776		var last_active_field = [];
7777
7778		img = get_main_product_image( epoObject, product_element );
7779
7780		gallery_type = get_gallery_type( epoObject, img, product_element );
7781
7782		if ( $( img ).length > 0 ) {
7783			img.data( 'tm-current-image', false );
7784			a = img.closest( 'a' );
7785			img_src_original = img.attr( 'src' );
7786			img_width = img.width();
7787			img_height = img.height();
7788
7789			main_product.off( 'tm_change_product_image' ).on( 'tm_change_product_image', function( evt, e ) {
7790				setTimeout( function() {
7791					var variation_element_section;
7792					var is_variation_element;
7793					var $this_epo_container;
7794					var tm_last_visible_image_element;
7795					var last_activate_field = [];
7796					var tm_current_image_element_id;
7797					var can_show_image;
7798					var $main_product;
7799					var $current_product_element;
7800					var preload_width;
7801					var preload_height;
7802					var current_cloned_image;
7803					var preloader;
7804					var clone_image;
7805					var preload_img;
7806					var preload_img_onerror;
7807
7808					if ( TMEPOJS.tm_epo_global_image_recalculate === 'yes' ) {
7809						img = get_main_product_image( epoObject, product_element );
7810					}
7811
7812					variation_element_section = e.element.closest( '.cpf-section' );
7813					is_variation_element = variation_element_section.is( '.tm-epo-variation-section' );
7814					$this_epo_container = e.epo_holder;
7815					if ( is_variation_element ) {
7816						$this_epo_container = variation_element_section;
7817					}
7818					tm_last_visible_image_element = $this_epo_container.find( '.tm-product-image:checked,select.tm-product-image' );
7819					last_activate_field = [];
7820					tm_current_image_element_id = e.element.attr( 'id' );
7821					can_show_image = true;
7822					$main_product = e.main_product;
7823					$current_product_element = $main_product.closest( '#product-' + product_id );
7824					preload_width = img_width;
7825					preload_height = img_height;
7826					preloader = $( "<div class='blockUI blockOverlay tm-preloader-img'></div>" );
7827
7828					if ( $current_product_element.length <= 0 ) {
7829						$current_product_element = $main_product.closest( '.post-' + product_id );
7830					}
7831
7832					current_cloned_image = $current_product_element.find( '#' + tm_current_image_element_id + '_tmimage' );
7833					if ( current_cloned_image.length === 0 ) {
7834						current_cloned_image = img;
7835					}
7836
7837					preload_img_onerror = function() {
7838						preloader.remove();
7839						$form.tc_image_update( false );
7840						img.data( 'tm-current-image', false );
7841						$current_product_element.find( '.tm-clone-product-image' ).hide();
7842						img.show();
7843					};
7844
7845					if ( e.src === current_cloned_image.attr( 'src' ) && current_cloned_image.is( ':visible' ) ) {
7846						return;
7847					}
7848
7849					if ( e.src === false ) {
7850						preload_img_onerror();
7851						return;
7852					}
7853
7854					preloader.css( {
7855						width: preload_width,
7856						height: preload_height
7857					} );
7858
7859					// Get last active field
7860					tm_last_visible_image_element.toArray().forEach( function( ie ) {
7861						ie = $( ie );
7862						if (
7863							field_is_active( ie ) &&
7864							has_active_changes_product_image( ie ) &&
7865							tm_check_field_match( {
7866								element: ie.closest( '.cpf-element' ),
7867								rule: {
7868									operator: 'isnotempty',
7869									value: ''
7870								},
7871								type: 'element'
7872							} )
7873						) {
7874							last_activate_field.push( ie );
7875						}
7876					} );
7877					// Get last active image
7878					if ( last_activate_field.length ) {
7879						tm_last_visible_image_element = last_activate_field[ last_activate_field.length - 1 ];
7880					}
7881
7882					if ( tm_last_visible_image_element.attr( 'id' ) !== e.element.attr( 'id' ) ) {
7883						can_show_image = false;
7884					}
7885
7886					clone_image = img.tcClone();
7887					preload_img = new Image();
7888					clone_image.removeAttr( 'data-o_src' ).removeAttr( 'data-o_title' ).removeAttr( 'data-o_alt' ).removeAttr( 'data-o_srcset' ).removeAttr( 'data-o_sizes' ).removeAttr( 'srcset' ).removeAttr( 'sizes' );
7889
7890					if ( can_show_image ) {
7891						img.before( preloader );
7892					}
7893
7894					gallery_type.is_yith_wcmg.yith_wcmg_default_zoom = gallery_type.is_yith_wcmg.element.find( '.yith_magnifier_zoom' ).first().attr( 'href' );
7895					gallery_type.is_yith_wcmg.yith_wcmg_default_image = gallery_type.is_yith_wcmg.element.find( '.yith_magnifier_zoom img' ).first().attr( 'src' );
7896
7897					preload_img.onerror = function() {
7898						preload_img_onerror();
7899					};
7900
7901					preload_img.onload = function() {
7902						if ( 'naturalHeight' in this ) {
7903							if ( this.naturalHeight + this.naturalWidth === 0 ) {
7904								this.onerror();
7905								return;
7906							}
7907						} else if ( this.width + this.height === 0 ) {
7908							this.onerror();
7909							return;
7910						}
7911						$current_product_element.find( '#' + tm_current_image_element_id + '_tmimage' ).remove();
7912						$current_product_element.find( '.tm-clone-product-image' ).hide();
7913						clone_image.prop( 'src', preload_img.src ).hide();
7914
7915						img.hide().after( clone_image );
7916
7917						clone_image.css( 'opacity', 0 ).show();
7918
7919						gallery_compatibility_actions( gallery_type, clone_image, preload_img.src );
7920
7921						preloader.animate(
7922							{
7923								opacity: 0
7924							},
7925							750,
7926							'easeOutExpo',
7927							function() {
7928								preloader.remove();
7929							}
7930						);
7931						clone_image.animate(
7932							{
7933								opacity: 1
7934							},
7935							window.tc_epo_image_animation_delay || 1500,
7936							'easeOutExpo',
7937							function() {}
7938						);
7939
7940						jWindow.trigger( 'tm_change_product_image_loaded', {
7941							src: e.src,
7942							element: e.element,
7943							main_product: e.main_product,
7944							epo_holder: e.epo_holder
7945						} );
7946					};
7947
7948					clone_image
7949						.attr( 'id', tm_current_image_element_id + '_tmimage' )
7950						.addClass( 'tm-clone-product-image' )
7951						.hide();
7952
7953					if ( clone_image.attr( 'src-orig' ) ) {
7954						clone_image.attr( 'src-orig', e.src );
7955					}
7956
7957					if ( can_show_image ) {
7958						preload_img.src = e.src;
7959
7960						$form.tc_image_update( e.element, clone_image );
7961
7962						img.data( 'tm-current-image', tm_current_image_element_id );
7963
7964						jWindow.trigger( 'tm_change_product_image_show', {
7965							src: e.src,
7966							element: e.element,
7967							main_product: e.main_product,
7968							epo_holder: e.epo_holder
7969						} );
7970					} else {
7971						clone_image.prop( 'src', e.src ).hide();
7972						img.after( clone_image );
7973					}
7974
7975					jWindow.trigger( 'tm_change_product_image_end', {
7976						src: e.src,
7977						element: e.element,
7978						main_product: e.main_product,
7979						epo_holder: e.epo_holder
7980					} );
7981				}, window.tc_epo_product_image_change_delay || 0 );
7982			} );
7983
7984			main_product.off( 'tm_restore_product_image' ).on( 'tm_restore_product_image', function( evt, e ) {
7985				setTimeout( function() {
7986					var tm_current_image_element_id;
7987					var $main_product;
7988					var $current_product_element;
7989					var variation_element_section;
7990					var is_variation_element;
7991					var current_element;
7992					var current_image_replacement;
7993					var found;
7994					var is_it_visible;
7995					var len;
7996					var el_to_check;
7997					var imgSrc;
7998					var $this_epo_container;
7999					var i;
8000
8001					if ( ! e || ! e.element ) {
8002						return false;
8003					}
8004					if ( TMEPOJS.tm_epo_global_image_recalculate === 'yes' ) {
8005						img = get_main_product_image( epoObject, product_element );
8006					}
8007
8008					jWindow.trigger( 'tm_restore_product_image_pre', {
8009						element: e.element,
8010						main_product: e.main_product,
8011						epo_holder: e.epo_holder
8012					} );
8013					tm_current_image_element_id = e.element.attr( 'id' );
8014					$main_product = e.main_product;
8015					$current_product_element = $main_product.closest( '#product-' + product_id );
8016					variation_element_section = e.element.closest( '.cpf-section' );
8017					is_variation_element = variation_element_section.is( '.tm-epo-variation-section' );
8018					found = false;
8019					imgSrc = img_src_original;
8020					$this_epo_container = e.epo_holder;
8021					if ( is_variation_element ) {
8022						$this_epo_container = variation_element_section;
8023					}
8024
8025					if ( $current_product_element.length <= 0 ) {
8026						$current_product_element = $main_product.closest( '.post-' + product_id );
8027					}
8028
8029					is_it_visible = $current_product_element.find( '#' + tm_current_image_element_id + '_tmimage' ).is( ':visible' );
8030
8031					$current_product_element.find( '#' + tm_current_image_element_id + '_tmimage' ).remove();
8032
8033					if ( $current_product_element.find( '.tm-clone-product-image' ).length === 0 ) {
8034						img.show();
8035						img.data( 'tm-current-image', false );
8036						$form.tc_image_update( false );
8037					} else {
8038						if ( ! is_it_visible ) {
8039							jWindow.trigger( 'tm_restore_product_image_loaded_exit', {
8040								element: e.element,
8041								main_product: e.main_product,
8042								epo_holder: e.epo_holder
8043							} );
8044							return;
8045						}
8046
8047						len = $current_product_element.find( '.tm-clone-product-image' ).length;
8048						tm_current_image_element_id = img.data( 'tm-current-image' );
8049
8050						for ( i = len - 1; i >= 0; i -= 1 ) {
8051							current_image_replacement = $current_product_element.find( '.tm-clone-product-image' ).eq( i );
8052							current_element = current_image_replacement.attr( 'id' ).replace( '_tmimage', '' );
8053							el_to_check = $this_epo_container.find( "[id='" + current_element + "']" );
8054
8055							if ( el_to_check.is( ':checked' ) && el_to_check.closest( '.cpf-element' ).is( ':visible' ) ) {
8056								$current_product_element.find( '.tm-clone-product-image' ).eq( i ).show();
8057								a.attr( 'href', $current_product_element.find( '.tm-clone-product-image' ).eq( i ).prop( 'src' ) );
8058								img.data( 'tm-current-image', current_element );
8059								found = true;
8060								break;
8061							} else {
8062								$current_product_element.find( '.tm-clone-product-image' ).eq( i ).hide();
8063							}
8064						}
8065						if ( ! found ) {
8066							img.show();
8067							img.data( 'tm-current-image', false );
8068							$form.tc_image_update( false );
8069						} else {
8070							$current_product_element.find( '#' + tm_current_image_element_id + '_tmimage' ).remove();
8071						}
8072					}
8073
8074					if ( found ) {
8075						imgSrc = current_image_replacement.attr( 'src' );
8076					}
8077
8078					gallery_compatibility_actions( gallery_type, false, imgSrc, $current_product_element.find( '.tm-clone-product-image' ).filter( ':visible' ).length );
8079
8080					jWindow.trigger( 'tm_restore_product_image_loaded', {
8081						element: e.element,
8082						main_product: e.main_product,
8083						epo_holder: e.epo_holder
8084					} );
8085				}, window.tc_epo_product_image_change_delay || 0 );
8086			} );
8087
8088			main_product.off( 'tm_attempt_product_image' ).on( 'tm_attempt_product_image', function( evt, e ) {
8089				setTimeout( function() {
8090					var $main_product;
8091					var $current_product_element;
8092					var variation_element_section;
8093					var is_variation_element;
8094					var $this_epo_container;
8095					var tm_last_visible_image_element;
8096					var last_activate_field;
8097					var tm_last_visible_image_element_id;
8098					var current_image_replacement;
8099					var current_element;
8100					var found;
8101					var tm_current_image_element_id;
8102					var len;
8103					var imgSrc;
8104					var el_to_check;
8105					var tmcie_id;
8106					var i;
8107
8108					if ( TMEPOJS.tm_epo_global_image_recalculate === 'yes' ) {
8109						img = get_main_product_image( epoObject, product_element );
8110					}
8111
8112					$main_product = e.main_product;
8113					$current_product_element = $main_product.closest( '#product-' + product_id );
8114					if ( e.element ) {
8115						variation_element_section = e.element.closest( '.cpf-section' );
8116					} else {
8117						variation_element_section = $( $main_product.find( '.tm-epo-variation-section' ).first(), e.epo_holder );
8118					}
8119					is_variation_element = variation_element_section.is( '.tm-epo-variation-section' );
8120					$this_epo_container = e.epo_holder;
8121					if ( is_variation_element ) {
8122						$this_epo_container = variation_element_section;
8123					}
8124					tm_last_visible_image_element = $this_epo_container.find( '.tm-product-image:checked,select.tm-product-image' );
8125					last_activate_field = [];
8126					tm_last_visible_image_element_id = '';
8127					found = false;
8128					tm_current_image_element_id = img.data( 'tm-current-image' );
8129					imgSrc = img_src_original;
8130
8131					if ( $current_product_element.length <= 0 ) {
8132						$current_product_element = $main_product.closest( '.post-' + product_id );
8133					}
8134
8135					$this_epo_container = $main_product.find( '.tm-epo-variation-section' ).first().add( e.epo_holder );
8136					tm_last_visible_image_element = $this_epo_container.find( '.tm-product-image:checked,select.tm-product-image' );
8137
8138					tm_last_visible_image_element.toArray().forEach( function( ie ) {
8139						ie = $( ie );
8140						if (
8141							field_is_active( ie ) &&
8142							has_active_changes_product_image( ie ) &&
8143							tm_check_field_match( {
8144								element: ie.closest( '.cpf-element' ),
8145								rule: {
8146									operator: 'isnotempty',
8147									value: ''
8148								},
8149								type: 'element'
8150							} )
8151						) {
8152							last_activate_field.push( ie );
8153						}
8154					} );
8155
8156					if ( last_activate_field.length ) {
8157						tm_last_visible_image_element = last_activate_field[ last_activate_field.length - 1 ];
8158						tm_last_visible_image_element_id = tm_last_visible_image_element.attr( 'id' );
8159					}
8160
8161					if ( last_activate_field.length && tm_last_visible_image_element.length && ( ! tm_current_image_element_id || tm_last_visible_image_element_id !== tm_current_image_element_id ) ) {
8162						tm_last_visible_image_element.last().trigger( 'tm_trigger_product_image' );
8163						return;
8164					}
8165
8166					tmcie_id = $this_epo_container.find( "[id='" + tm_current_image_element_id + "']" ).closest( '.cpf-element' );
8167					if ( ! tm_current_image_element_id || ( tmcie_id.data( 'isactive' ) !== false && tmcie_id.closest( '.cpf-section' ).data( 'isactive' ) !== false ) ) {
8168						return;
8169					}
8170
8171					$current_product_element.find( '#' + tm_current_image_element_id + '_tmimage' ).remove();
8172					len = $current_product_element.find( '.tm-clone-product-image' ).length;
8173
8174					if ( len === 0 ) {
8175						img.show();
8176						img.data( 'tm-current-image', false );
8177						$form.tc_image_update( false );
8178					} else {
8179						for ( i = len - 1; i >= 0; i -= 1 ) {
8180							current_image_replacement = $current_product_element.find( '.tm-clone-product-image' ).eq( i );
8181							current_element = current_image_replacement.attr( 'id' ).replace( '_tmimage', '' );
8182							el_to_check = $this_epo_container.find( "[id='" + current_element + "']" );
8183
8184							if ( el_to_check.is( ':checked' ) && el_to_check.closest( '.cpf-element' ).is( ':visible' ) ) {
8185								$current_product_element.find( '.tm-clone-product-image' ).eq( i ).show();
8186								a.attr( 'href', $current_product_element.find( '.tm-clone-product-image' ).eq( i ).prop( 'src' ) );
8187								img.data( 'tm-current-image', current_element );
8188								found = true;
8189								break;
8190							} else {
8191								$current_product_element.find( '.tm-clone-product-image' ).eq( i ).hide();
8192							}
8193						}
8194
8195						if ( ! found ) {
8196							img.show();
8197							img.data( 'tm-current-image', false );
8198							$form.tc_image_update( false );
8199						}
8200					}
8201
8202					if ( found ) {
8203						imgSrc = current_image_replacement.attr( 'src' );
8204					}
8205
8206					gallery_compatibility_actions( gallery_type, false, imgSrc, $current_product_element.find( '.tm-clone-product-image' ).filter( ':visible' ).length );
8207				}, window.tc_epo_product_image_change_delay || 0 );
8208			} );
8209
8210			$( this_epo_container.find( '.tm-product-image:checked,select.tm-product-image' ) )
8211				.add( main_product.find( '.tm-epo-variation-section' ).first().find( '.tm-product-image:checked,select.tm-product-image' ) )
8212				.toArray().forEach( function( pi ) {
8213					pi = $( pi );
8214					if ( field_is_active( pi ) && pi.val() !== '' ) {
8215						last_active_field.push( pi );
8216					}
8217				} );
8218			if ( last_active_field.length ) {
8219				last_active_field[ last_active_field.length - 1 ].trigger( 'tm_trigger_product_image' );
8220			}
8221		}
8222
8223		jWindow.trigger( 'tm_product_image_loaded' );
8224	}
8225
8226	function tm_product_image( epoObject ) {
8227		var galleryImages;
8228		setTimeout( function() {
8229			if ( TMEPOJS.tm_epo_global_product_image_mode === 'inline' ) {
8230				tm_product_image_inline( epoObject );
8231			} else {
8232				tm_product_image_self( epoObject );
8233			}
8234
8235			if ( $.fn.wc_product_gallery ) {
8236				galleryImages = epoObject.this_epo_container;
8237				if ( epoObject.is_associated ) {
8238					galleryImages = epoObject.main_product;
8239				}
8240				galleryImages.find( '.cpf-type-product-custombundle .tc-associated-product-image' ).tclightbox();
8241			}
8242		}, window.tc_epo_product_image_setup_delay || 0 );
8243	}
8244
8245	function tc_compatibility( epoObject ) {
8246		jWindow.trigger( 'tm-epo-compatibility', {
8247			epo: epoObject
8248		} );
8249	}
8250
8251	// Range picker setup
8252	function setRangePickers( obj ) {
8253		if ( ! noUiSlider ) {
8254			return;
8255		}
8256		obj.find( '.tm-range-picker' )
8257			.toArray()
8258			.forEach( function( picker ) {
8259				var el = $( picker );
8260				var $decimals = el.attr( 'data-step' ).split( '.' );
8261				var $tmfid = obj.find( '#' + $.epoAPI.dom.id( el.attr( 'data-field-id' ) ) );
8262				var $min = parseFloat( el.attr( 'data-min' ) );
8263				var $max = parseFloat( el.attr( 'data-max' ) );
8264				var $start = parseFloat( el.attr( 'data-start' ) );
8265				var $step = parseFloat( el.attr( 'data-step' ) );
8266				var $show_picker_value = el.attr( 'data-show-picker-value' );
8267				var $show_label = el.closest( 'li' ).find( '.tm-show-picker-value' );
8268				var $noofpips = parseFloat( el.attr( 'data-noofpips' ) );
8269				var $pips = null;
8270				var $tmh;
8271
8272				if ( el.data( 'tc-picker-init' ) ) {
8273					return;
8274				}
8275				el.data( 'tc-picker-init', 1 );
8276
8277				if ( $decimals.length === 1 ) {
8278					$decimals = 0;
8279				} else {
8280					$decimals = $decimals[ 1 ].length;
8281				}
8282				if ( ! Number.isFinite( $min ) ) {
8283					$min = 0;
8284				}
8285				if ( ! Number.isFinite( $max ) ) {
8286					$max = 0;
8287				}
8288				if ( $max <= $min ) {
8289					$max = parseFloat( $max ) + 1;
8290				}
8291				$start = $.epoAPI.math.unformat( $start, tcAPI.localDecimalSeparator );
8292				if ( ! Number.isFinite( $start ) ) {
8293					$start = 0;
8294				}
8295				$start = formatPrice( $start, { precision: $decimals } );
8296				if ( ! Number.isFinite( $step ) ) {
8297					$step = 0;
8298				}
8299				if ( ! Number.isFinite( $noofpips ) ) {
8300					$noofpips = 10;
8301				}
8302				if ( $noofpips < 2 ) {
8303					$noofpips = 2;
8304				}
8305
8306				if ( el.attr( 'data-pips' ) === 'yes' ) {
8307					$pips = {
8308						mode: 'count',
8309						values: $noofpips,
8310						filter: function( value, type ) {
8311							value = parseFloat( $.epoAPI.math.toFixed( value, $decimals ) );
8312
8313							if ( $step <= 0 ) {
8314								return 0;
8315							}
8316
8317							if ( type === 1 ) {
8318								if ( ! Number.isInteger( value ) ) {
8319									return 2;
8320								}
8321							}
8322
8323							return type;
8324						},
8325						format: {
8326							from: function( value ) {
8327								return $.epoAPI.math.unformat( value, tcAPI.localInputDecimalSeparator );
8328							},
8329							to: function( value ) {
8330								return formatPrice( value, { precision: $decimals } );
8331							}
8332						},
8333						density: 2
8334					};
8335				}
8336
8337				noUiSlider.create( el.get( 0 ), {
8338					direction: TMEPOJS.text_direction,
8339					start: $start,
8340					step: $step,
8341					connect: 'lower',
8342					// Configure tapping, or make the selected range dragable.
8343					behaviour: 'tap',
8344					// Full number format support.
8345					format: {
8346						from: function( value ) {
8347							return $.epoAPI.math.unformat( value, tcAPI.localDecimalSeparator );
8348						},
8349						to: function( value ) {
8350							return formatPrice( value, { precision: $decimals } );
8351						}
8352					},
8353					// Support for non-linear ranges by adding intervals.
8354					range: {
8355						min: [ $min ],
8356						max: [ $max ]
8357					},
8358					pips: $pips,
8359					tooltips: {
8360						from: function( value ) {
8361							return $.epoAPI.math.unformat( value, tcAPI.localInputDecimalSeparator );
8362						},
8363						to: function( value ) {
8364							return formatPrice( value, { precision: $decimals } );
8365						}
8366					}
8367				} );
8368
8369				$tmh = el.find( '.noui-handle-lower' );
8370				el.get( 0 ).noUiSlider.on( 'slide', function() {
8371					$tmfid.trigger( 'change.cpf' );
8372				} );
8373				el.get( 0 ).noUiSlider.on( 'update', function( values, handle ) {
8374					values[ handle ] = $.epoAPI.math.unformat( values[ handle ], tcAPI.localDecimalSeparator );
8375					handle = 0; //fixes rtl issue.
8376					if ( $show_picker_value !== 'left' && $show_picker_value !== 'right' ) {
8377						$tmh.attr(
8378							'title',
8379							formatPrice( values[ handle ], { precision: $decimals } )
8380						);
8381					}
8382					$tmfid.val( values[ handle ] ).trigger( 'change' );
8383					if ( $show_picker_value !== '' ) {
8384						$show_label.html(
8385							formatPrice( values[ handle ], { precision: $decimals } )
8386						);
8387					}
8388				} );
8389
8390				if ( $show_picker_value !== '' ) {
8391					$show_label.html( $start );
8392				}
8393
8394				if ( $show_picker_value !== 'left' && $show_picker_value !== 'right' ) {
8395					$tmh.attr( 'title', $start );
8396					el.addClass( 'noui-show-tooltip' );
8397				}
8398			} );
8399	}
8400
8401	// Range picker event setup
8402	function setRangePickersEvents() {
8403		if ( ! noUiSlider || jDocument.data( 'setRangePickersEvents' ) ) {
8404			return;
8405		}
8406		jDocument.on( 'click', '.tm-show-picker-value', function() {
8407			var $this = $( this );
8408			var li = $this.closest( '.tmcp-field-wrap' );
8409			var value = li.find( '.tmcp-range' ).val();
8410			var edit;
8411			var html5Slider = $this.closest( '.tmcp-field-wrap' ).find( '.tm-range-picker' );
8412
8413			$this.addClass( 'tc-hidden' ).after( $( '<input type="number" class="tm-show-picker-value-edit">' ) );
8414			edit = li.find( '.tm-show-picker-value-edit' );
8415			edit.focus().val( value ).wrap( '<div class="tm-show-picker-value-edit-wrap"></div>' );
8416			edit.attr( 'step', html5Slider.attr( 'data-step' ) );
8417			edit.attr( 'min', html5Slider.attr( 'data-min' ) );
8418			edit.attr( 'max', html5Slider.attr( 'data-max' ) );
8419			$( '.tm-show-picker-value-edit' ).focus().on( 'focusout', function() {
8420				$this = li.find( '.tm-show-picker-value-edit' );
8421				$this.closest( '.tmcp-field-wrap' ).find( '.tm-show-picker-value' ).removeClass( 'tc-hidden' );
8422				$this.closest( '.tm-show-picker-value-edit-wrap' ).remove();
8423			} );
8424		} );
8425		jDocument.on( 'change input', '.tm-show-picker-value-edit', function() {
8426			var $this = $( this );
8427			var html5Slider = $this.closest( '.tmcp-field-wrap' ).find( '.tm-range-picker' );
8428			var $decimals = html5Slider.attr( 'data-step' ).split( '.' );
8429			var value = $this.val();
8430			if ( $decimals.length === 1 ) {
8431				$decimals = 0;
8432			} else {
8433				$decimals = $decimals[ 1 ].length;
8434			}
8435
8436			html5Slider.get( 0 ).noUiSlider.set( [ formatPrice( value, { precision: $decimals } ), null ] );
8437		} );
8438		jDocument.on( 'keydown', '.tm-show-picker-value-edit', function( event ) {
8439			var key;
8440
8441			key = event.which;
8442			if ( key === 13 ) {
8443				event.preventDefault();
8444			}
8445		} );
8446		jDocument.data( 'setRangePickersEvents', 1 );
8447	}
8448
8449	function validate_date_with_options( date, inputElement ) {
8450		var input = $( inputElement );
8451		var inst = $.tm_datepicker._getInst( input[ 0 ] );
8452		var enabled_only_dates = input.data( 'tc-enabled_only_dates' );
8453		var disabled_weekdays = input.data( 'tc-disabled_weekdays' );
8454		var disabled_months = input.data( 'tc-disabled_months' );
8455		var disabled_dates = input.data( 'tc-disabled_dates' );
8456		var format = input.data( 'tc-format' );
8457		var day = date.getDay();
8458		var month = date.getDay() + 1;
8459		var string;
8460
8461		if ( ! $.tm_datepicker._isInRange( inst, date ) ) {
8462			return false;
8463		}
8464		if ( enabled_only_dates !== '' ) {
8465			string = $.tm_datepicker.formatDate( format, date );
8466			return enabled_only_dates.indexOf( string ) !== -1;
8467		}
8468		if ( disabled_weekdays.indexOf( day.toString() ) !== -1 ) {
8469			return false;
8470		}
8471		if ( disabled_months.indexOf( month.toString() ) !== -1 ) {
8472			return false;
8473		}
8474		if ( disabled_dates !== '' ) {
8475			string = $.tm_datepicker.formatDate( format, date );
8476			return disabled_dates.indexOf( string ) === -1;
8477		}
8478		return true;
8479	}
8480
8481	function correctDate( days ) {
8482		var sign, testDate, count, added, noOfDaysToAdd;
8483		if ( days.toString().isNumeric() ) {
8484			sign = days === 0 ? days : ( days > 0 ? 1 : -1 );
8485			if ( sign !== 0 ) {
8486				testDate = new Date();
8487				count = 1;
8488				added = false;
8489				noOfDaysToAdd = Math.abs( days );
8490				while ( count <= noOfDaysToAdd ) {
8491					if ( added === false ) {
8492						added = 0;
8493					}
8494					testDate.setDate( testDate.getDate() + ( 1 * sign ) );
8495					added++;
8496					if ( testDate.getDay() !== 0 && testDate.getDay() !== 6 ) {
8497						count++;
8498					}
8499				}
8500				if ( added !== false ) {
8501					days = added * sign;
8502				}
8503			}
8504		}
8505		return days;
8506	}
8507	// Date and time picker setup
8508	function tm_set_datepicker( obj ) {
8509		var inputIds;
8510		var elem;
8511		var timepickerSelector = '.tm-epo-timepicker';
8512
8513		if ( ! $.tm_datepicker ) {
8514			return;
8515		}
8516
8517		inputIds = $( 'input' )
8518			.map( function() {
8519				return this.id;
8520			} )
8521			.get()
8522			.join( ' ' );
8523
8524		elem = document.createElement( 'input' );
8525		elem.setAttribute( 'type', 'date' );
8526
8527		if ( elem.type === 'text' ) {
8528			timepickerSelector = '.tm-epo-system-timepicker';
8529		}
8530
8531		obj.find( timepickerSelector )
8532			.toArray()
8533			.forEach( function( el ) {
8534				var field = $( el );
8535				var _mintime = null;
8536				var _maxtime = null;
8537				var format = field.attr( 'data-time-format' ).trim();
8538				var date_theme = field.attr( 'data-time-theme' ).trim();
8539				var date_theme_size = field.attr( 'data-time-theme-size' ).trim();
8540				var date_theme_position = field.attr( 'data-time-theme-position' ).trim();
8541				var data_translation_hour = field.attr( 'data-tranlation-hour' ).trim();
8542				var data_translation_minute = field.attr( 'data-tranlation-minute' ).trim();
8543				var data_translation_second = field.attr( 'data-tranlation-second' ).trim();
8544
8545				field.attr( 'type', 'text' );
8546
8547				if ( field.attr( 'data-min-time' ).trim() !== '' ) {
8548					_mintime = field.attr( 'data-min-time' ).trim();
8549				}
8550				if ( field.attr( 'data-max-time' ).trim() !== '' ) {
8551					_maxtime = field.attr( 'data-max-time' ).trim();
8552				}
8553
8554				if ( field.attr( 'data-custom-time-format' ).trim() !== '' ) {
8555					format = field.attr( 'data-custom-time-format' ).trim();
8556				}
8557				if ( ! data_translation_hour ) {
8558					data_translation_hour = TMEPOJS.hourText;
8559				}
8560				if ( ! data_translation_minute ) {
8561					data_translation_minute = TMEPOJS.minuteText;
8562				}
8563				if ( ! data_translation_second ) {
8564					data_translation_second = TMEPOJS.secondText;
8565				}
8566
8567				field.tm_timepicker( Object.assign( {
8568					isRTL: TMEPOJS.isRTL,
8569					hourText: data_translation_hour,
8570					minuteText: data_translation_minute,
8571					secondText: data_translation_second,
8572					timeFormat: format,
8573					minTime: _mintime,
8574					maxTime: _maxtime,
8575					closeText: TMEPOJS.closeText,
8576					showOn: 'both',
8577					buttonText: '',
8578
8579					beforeShow: function( input, inst ) {
8580						$( inst.dpDiv )
8581							.removeClass( inputIds )
8582							.removeClass( 'tm-ui-skin-epo tm-ui-skin-epo-black tm-datepicker-medium tm-datepicker-small tm-datepicker-large tm-datepicker-normal tm-datepicker-top tm-datepicker-bottom' )
8583							.addClass( this.id + ' tm-bsbb-all tm-ui-skin-' + date_theme + ' tm-timepicker tm-datepicker tm-datepicker-' + date_theme_position + ' tm-datepicker-' + date_theme_size )
8584							.appendTo( 'body' );
8585
8586						jDocument.off( 'click', '.tm-ui-dp-overlay' ).on( 'click', '.tm-ui-dp-overlay', function() {
8587							field.tm_timepicker( 'hide' );
8588						} );
8589						jBody.addClass( 'tm-static' );
8590						field.prop( 'readonly', true );
8591
8592						jWindow.trigger( {
8593							type: 'tm-timepicker-beforeShow',
8594							input: input,
8595							inst: inst
8596						} );
8597					},
8598					onClose: function() {
8599						jBody.removeClass( 'tm-static' );
8600						field.prop( 'readonly', false );
8601						field.trigger( 'change' );
8602					}
8603				}, window.tmTimepickerSettings || window.timepicker_settings || {} ) );
8604				$( '#ui-tm-datepicker-div' ).hide();
8605			} );
8606
8607		obj.find( '.tm-epo-datepicker' )
8608			.toArray()
8609			.forEach( function( el ) {
8610				var field = $( el );
8611				var startDate = parseInt( field.attr( 'data-start-year' ).trim(), 10 );
8612				var endDate = parseInt( field.attr( 'data-end-year' ).trim(), 10 );
8613				var minDate = field.attr( 'data-min-date' ).trim();
8614				var maxDate = field.attr( 'data-max-date' ).trim();
8615				var disabled_dates = field.attr( 'data-disabled-dates' ).trim();
8616				var enabled_only_dates = field.attr( 'data-enabled-only-dates' ).trim();
8617				var exlude_disabled = field.attr( 'data-exlude-disabled' ).trim();
8618				var disabled_weekdays = field.attr( 'data-disabled-weekdays' ).trim().split( ',' );
8619				var disabled_months = field.attr( 'data-disabled-months' ).trim().split( ',' );
8620				var format = field.attr( 'data-date-format' ).trim();
8621				var show = field.attr( 'data-date-showon' ).trim();
8622				var default_date = field.attr( 'data-date-defaultdate' ).trim();
8623				var date_theme = field.attr( 'data-date-theme' ).trim();
8624				var date_theme_size = field.attr( 'data-date-theme-size' ).trim();
8625				var date_theme_position = field.attr( 'data-date-theme-position' ).trim();
8626				var $split;
8627				var $index;
8628				var $split2;
8629				var $index2;
8630
8631				if ( disabled_dates !== '' ) {
8632					$split = disabled_dates.split( ',' );
8633					$index = disabled_dates.indexOf( ',' );
8634
8635					if ( $index !== -1 && $split.length > 0 ) {
8636						disabled_dates = $split;
8637					}
8638				}
8639				if ( enabled_only_dates !== '' ) {
8640					$split2 = enabled_only_dates.split( ',' );
8641					$index2 = enabled_only_dates.indexOf( ',' );
8642
8643					if ( $index2 !== -1 && $split2.length > 0 ) {
8644						enabled_only_dates = $split2;
8645					}
8646				}
8647
8648				if ( minDate === '' ) {
8649					if ( startDate === '' ) {
8650						minDate = null;
8651					} else {
8652						minDate = new Date( startDate, 1 - 1, 1 );
8653					}
8654				} else if ( exlude_disabled ) {
8655					minDate = correctDate( minDate );
8656				}
8657				if ( maxDate === '' ) {
8658					if ( endDate === '' ) {
8659						maxDate = null;
8660					} else {
8661						maxDate = new Date( endDate, 12 - 1, 31 );
8662					}
8663				} else if ( exlude_disabled ) {
8664					maxDate = correctDate( maxDate );
8665				}
8666
8667				field.data( 'tc-enabled_only_dates', enabled_only_dates );
8668				field.data( 'tc-disabled_weekdays', disabled_weekdays );
8669				field.data( 'tc-disabled_months', disabled_months );
8670				field.data( 'tc-disabled_dates', disabled_dates );
8671				field.data( 'tc-format', format );
8672
8673				field.tm_datepicker( Object.assign( {
8674					monthNames: TMEPOJS.monthNames,
8675					monthNamesShort: TMEPOJS.monthNamesShort,
8676					dayNames: TMEPOJS.dayNames,
8677					dayNamesShort: TMEPOJS.dayNamesShort,
8678					dayNamesMin: TMEPOJS.dayNamesMin,
8679					isRTL: TMEPOJS.isRTL,
8680					showOtherMonths: true,
8681					selectOtherMonths: true,
8682					showOn: show,
8683					defaultDate: default_date,
8684					buttonText: '',
8685					showButtonPanel: true,
8686					firstDay: TMEPOJS.first_day,
8687					closeText: TMEPOJS.closeText,
8688					currentText: TMEPOJS.currentText,
8689					dateFormat: format,
8690					minDate: minDate,
8691					maxDate: maxDate,
8692					onSelect: function() {
8693						var input = $( this );
8694						var id = '#' + $.epoAPI.dom.id( input.attr( 'id' ) );
8695						var date = input.tm_datepicker( 'getDate' );
8696						var day = '';
8697						var month = '';
8698						var year = '';
8699						var day_field = obj.find( id + '_day' );
8700						var month_field = obj.find( id + '_month' );
8701						var year_field = obj.find( id + '_year' );
8702						var string;
8703						var ld;
8704
8705						if ( date ) {
8706							day = date.getDate();
8707							month = date.getMonth() + 1;
8708							year = date.getFullYear();
8709							string = $.tm_datepicker.formatDate( format, date );
8710							if (
8711								disabled_months.indexOf( month.toString() ) !== -1 ||
8712								disabled_weekdays.indexOf( date.getDay().toString() ) !== -1 ||
8713								disabled_dates.indexOf( string ) !== -1 ||
8714								( enabled_only_dates !== '' && enabled_only_dates.indexOf( string ) === -1 )
8715							) {
8716								ld = input.data( 'tm-last-date' );
8717								if ( input.data( 'tm-last-date' ) ) {
8718									ld = input.data( 'tm-last-date' );
8719								} else {
8720									ld = '';
8721								}
8722								input.val( ld );
8723								input.tm_datepicker( 'setDate', ld );
8724								if ( ld ) {
8725									date = input.tm_datepicker( 'getDate' );
8726									day = date.getDate();
8727									month = date.getMonth() + 1;
8728									year = date.getFullYear();
8729								} else {
8730									day = '';
8731									month = '';
8732									year = '';
8733								}
8734							}
8735						}
8736
8737						day_field.val( day );
8738						month_field.val( month );
8739						year_field.val( year );
8740
8741						input.data( 'tm-last-date', input.val() );
8742						input.tm_datepicker( 'hide' );
8743					},
8744					beforeShow: function( input, inst ) {
8745						$( inst.dpDiv )
8746							.removeClass( inputIds )
8747							.removeClass( 'tm-datepicker-normal tm-datepicker-top tm-datepicker-bottom' )
8748							.addClass( this.id + ' tm-bsbb-all tm-ui-skin-' + date_theme + ' tm-datepicker tm-datepicker-' + date_theme_position + ' tm-datepicker-' + date_theme_size )
8749							.appendTo( 'body' );
8750
8751						jDocument.off( 'click', '.tm-ui-dp-overlay' ).on( 'click', '.tm-ui-dp-overlay', function() {
8752							field.tm_datepicker( 'hide' );
8753						} );
8754						jDocument.off( 'click', '.ui-tm-datepicker-current' ).on( 'click', '.ui-tm-datepicker-current', function() {
8755							var tempDate = new Date(),
8756								today = $.tm_datepicker._daylightSavingAdjust( new Date( tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate() ) );
8757							var day = today.getDay();
8758							var month = today.getMonth() + 1;
8759							var id = '#' + inst.id.replace( /\\\\/g, '\\' );
8760							var check = false;
8761							var string;
8762							var date = field.tm_datepicker( 'getDate' );
8763
8764							if ( enabled_only_dates !== '' ) {
8765								string = $.tm_datepicker.formatDate( format, date );
8766								check = enabled_only_dates.indexOf( string ) !== -1;
8767							} else if ( disabled_months.indexOf( month.toString() ) !== -1 || disabled_weekdays.indexOf( day.toString() ) !== -1 ) {
8768								check = false;
8769							} else {
8770								if ( disabled_dates !== '' ) {
8771									string = $.tm_datepicker.formatDate( format, date );
8772									return [ disabled_dates.indexOf( string ) === -1, '' ];
8773								}
8774								check = true;
8775							}
8776							if ( check ) {
8777								$.tm_datepicker._setDate( inst, today );
8778								$.tm_datepicker._gotoToday( id );
8779							}
8780						} );
8781						jBody.addClass( 'tm-static' );
8782
8783						jWindow.trigger( {
8784							type: 'tm-datepicker-beforeShow',
8785							input: input,
8786							inst: inst
8787						} );
8788					},
8789					onClose: function() {
8790						jBody.removeClass( 'tm-static' );
8791						field.trigger( 'change' );
8792					},
8793					beforeShowDay: function( date ) {
8794						var day = date.getDay();
8795						var month = date.getMonth() + 1;
8796						var string;
8797
8798						if ( enabled_only_dates !== '' ) {
8799							string = $.tm_datepicker.formatDate( format, date );
8800							return [ enabled_only_dates.indexOf( string ) !== -1, '' ];
8801						}
8802						if ( disabled_months.indexOf( month.toString() ) !== -1 || disabled_weekdays.indexOf( day.toString() ) !== -1 ) {
8803							return [ false, '' ];
8804						}
8805						if ( disabled_dates !== '' ) {
8806							string = $.tm_datepicker.formatDate( format, date );
8807							return [ disabled_dates.indexOf( string ) === -1, '' ];
8808						}
8809						return [ true, '' ];
8810					}
8811				}, window.tmDatepickerSettings || {} ) );
8812
8813				$( '#ui-tm-datepicker-div' ).hide();
8814			} );
8815
8816		obj.find( '.tmcp-date-select' )
8817			.on( 'change.cpf', function() {
8818				var id = '#' + $.epoAPI.dom.id( $( this ).attr( 'data-tm-date' ) );
8819				var input = obj.find( id );
8820				var format = input.attr( 'data-date-format' );
8821				var day = obj.find( id + '_day' ).val();
8822				var month = obj.find( id + '_month' ).val();
8823				var year = obj.find( id + '_year' ).val();
8824				var dateFormat = $.tm_datepicker.formatDate( format, new Date( year, parseInt( month, 10 ) - 1, day ) );
8825
8826				if ( day > 0 && month > 0 && year > 0 ) {
8827					input.tm_datepicker( 'setDate', dateFormat );
8828					input.trigger( 'change' );
8829				} else {
8830					input.val( '' );
8831					input.trigger( 'change.cpf' );
8832				}
8833			} )
8834			.on( 'focus.cpf', function() {
8835				var id = '#' + $.epoAPI.dom.id( $( this ).attr( 'data-tm-date' ) );
8836				var input = obj.find( id );
8837				var day_select = obj.find( id + '_day' );
8838				var month_select = obj.find( id + '_month' );
8839				var year_select = obj.find( id + '_year' );
8840				var day = day_select.val();
8841				var month = month_select.val();
8842				var year = year_select.val();
8843				var _select = $( this );
8844
8845				if ( ( year !== '' && month !== '' && day !== '' ) || ( year !== '' && month !== '' && day === '' ) || ( day !== '' && year !== '' && month === '' ) || ( day !== '' && month !== '' && year === '' ) ) {
8846					_select
8847						.find( 'option' )
8848						.toArray()
8849						.forEach( function( element ) {
8850							var option = $( element );
8851							var val = option.val();
8852							var date_string = year + '-' + month + '-' + day;
8853							var d;
8854
8855							if ( _select.is( '.tmcp-date-day' ) ) {
8856								if ( year === '' || month === '' ) {
8857									return;
8858								}
8859								date_string = year + '-' + month + '-' + val;
8860							} else if ( _select.is( '.tmcp-date-month' ) ) {
8861								if ( year === '' || day === '' ) {
8862									return;
8863								}
8864								date_string = year + '-' + val + '-' + day;
8865							} else if ( _select.is( '.tmcp-date-year' ) ) {
8866								if ( day === '' || month === '' ) {
8867									return;
8868								}
8869								date_string = val + '-' + month + '-' + day;
8870							}
8871
8872							if ( val !== '' ) {
8873								try {
8874									d = $.tm_datepicker.parseDate( 'yy-mm-dd', date_string );
8875									if ( d ) {
8876										if ( validate_date_with_options( d, input ) ) {
8877											option.prop( 'disabled', false );
8878										} else {
8879											option.prop( 'disabled', true );
8880										}
8881									}
8882								} catch ( err ) {
8883									window.console.log( err );
8884
8885									option.prop( 'disabled', true );
8886									errorObject = err;
8887								}
8888							}
8889						} );
8890				} else {
8891					day_select.find( 'option' ).prop( 'disabled', false );
8892					month_select.find( 'option' ).prop( 'disabled', false );
8893					year_select.find( 'option' ).prop( 'disabled', false );
8894				}
8895			} );
8896
8897		jWindow.on( 'resizestart', function() {
8898			var activeElement = $( document.activeElement );
8899
8900			if ( activeElement.is( '.hasDatepicker' ) ) {
8901				activeElement.data( 'resizestarted', true );
8902
8903				// we don't use jWindow here because we want the current window width
8904				if ( $( window ).width() < 768 ) {
8905					activeElement.data( 'resizewidth', true );
8906					return;
8907				}
8908				activeElement.tm_datepicker( 'hide' );
8909			}
8910		} );
8911		jWindow.on( 'resizestop', function() {
8912			var activeElement = $( document.activeElement );
8913
8914			if ( activeElement.is( '.hasDatepicker' ) && activeElement.data( 'resizestarted' ) ) {
8915				if ( activeElement.data( 'resizewidth' ) ) {
8916					activeElement.tm_datepicker( 'hide' );
8917				}
8918				activeElement.tm_datepicker( 'show' );
8919			}
8920			activeElement.data( 'resizestarted', false );
8921			activeElement.data( 'resizewidth', false );
8922		} );
8923	}
8924
8925	function apply_submit_events( epoObject ) {
8926		var epoEventId = epoObject.epoEventId;
8927		var main_product = epoObject.main_product;
8928		var type;
8929		var form_is_submit = ! $.tcepo.formSubmitEvents[ epoEventId ].some( function( form_event ) {
8930			return typeof form_event && ( typeof form_event.trigger === 'function' || false ) && ! form_event.trigger();
8931		} );
8932
8933		$.tcepo.formSubmitEvents[ epoEventId ].forEach( function( form_event ) {
8934			type = typeof form_event;
8935			if ( type === 'object' ) {
8936				if ( form_is_submit ) {
8937					form_event.on_true();
8938				} else {
8939					form_event.on_false();
8940				}
8941			}
8942		} );
8943
8944		if ( ! form_is_submit ) {
8945			setTimeout( function() {
8946				main_product.find( tcAPI.addToCartButtonSelector ).first().removeClass( 'disabled' ).removeClass( 'loading' ).prop( 'disabled', false ).removeClass( 'fpd-disabled' );
8947			}, 100 );
8948		}
8949
8950		jWindow.trigger( 'tm-apply-submit-events', {
8951			epo: {
8952				form_is_submit: form_is_submit
8953			}
8954		} );
8955
8956		return form_is_submit;
8957	}
8958
8959	function tm_apply_validation( epoObject ) {
8960		var form = epoObject.form;
8961		var this_epo_container = epoObject.this_epo_container;
8962		var main_product = epoObject.main_product;
8963		var epoEventId = epoObject.epoEventId;
8964		var validation_rules;
8965		var has_rules;
8966
8967		if ( TMEPOJS.tm_epo_global_enable_validation === 'yes' ) {
8968			validation_rules = {};
8969
8970			this_epo_container
8971				.find( '.tmcp-ul-wrap' )
8972				.toArray()
8973				.forEach( function( tmcpulwrap ) {
8974					var field;
8975					var field_name;
8976					var subFieldName;
8977					var subRule;
8978					var productField;
8979
8980					tmcpulwrap = $( tmcpulwrap );
8981					has_rules = tmcpulwrap.data( 'tm-validation' );
8982					if ( has_rules && $.tmType( has_rules ) === 'object' ) {
8983						field = tmcpulwrap.find( '.tm-epo-field' );
8984						field_name = field.first().attr( 'name' );
8985						if ( tmcpulwrap.is( '.tm-extra-product-options-radio.tm-element-ul-radio' ) ) {
8986							field_name = field.last().attr( 'name' );
8987							validation_rules[ field_name ] = has_rules;
8988						} else if ( tmcpulwrap.is( '.tm-extra-product-options-checkbox.tm-element-ul-checkbox' ) ) {
8989							field.toArray().forEach( function( fname ) {
8990								if ( 'required' in has_rules ) {
8991									has_rules.required = function( elem ) {
8992										var len = tmcpulwrap.find( 'input.tm-epo-field.tmcp-checkbox:checked' ).length;
8993										if ( len === 0 ) {
8994											if ( field.last().attr( 'name' ) === $( elem ).attr( 'name' ) ) {
8995												return true;
8996											}
8997											return false;
8998										}
8999										return len <= 0;
9000									};
9001								}
9002								validation_rules[ $( fname ).attr( 'name' ) ] = has_rules;
9003							} );
9004						} else if ( tmcpulwrap.is( '.tm-extra-product-options-product.tm-element-ul-product' ) ) {
9005							field = field.filter( '.tc-epo-field-product' );
9006							if ( field.is( ':checkbox' ) ) {
9007								field.toArray().forEach( function( fname ) {
9008									if ( 'required' in has_rules ) {
9009										productField = $( fname );
9010										if ( productField.is( ':checkbox' ) ) {
9011											has_rules.required = function( elem ) {
9012												var checkedFields = tmcpulwrap.find( 'input.tm-epo-field.tmcp-checkbox:checked' );
9013												var len = checkedFields.length;
9014												var qtyCheck;
9015												if ( len === 0 ) {
9016													if ( field.last().attr( 'name' ) === $( elem ).attr( 'name' ) ) {
9017														return true;
9018													}
9019													return false;
9020												}
9021												qtyCheck = checkedFields.map( function() {
9022													return $( this );
9023												} ).get().some( function( element ) {
9024													return element.closest( '.tc-epo-element-product-holder' ).find( '.tm-qty' ).first().val() <= 0;
9025												} );
9026												if ( len > 0 ) {
9027													return qtyCheck;
9028												}
9029												return len <= 0;
9030											};
9031											if ( productField.attr( 'data-type' ) === 'variable' ) {
9032												subFieldName = productField.closest( '.tc-epo-element-product-holder' ).find( '.product-variation-id' ).first().attr( 'name' );
9033												subRule = {
9034													required: function( elem ) {
9035														var element = $( elem );
9036														var holder = element.closest( '.tc-epo-element-product-holder' );
9037														var checkbox = holder.find( '.tc-epo-field-product' );
9038
9039														if ( field_is_active( checkbox, true ) && checkbox.is( ':checked' ) ) {
9040															return true;
9041														}
9042														return false;
9043													}
9044												};
9045												validation_rules[ subFieldName ] = subRule;
9046											}
9047										}
9048									}
9049									validation_rules[ productField.attr( 'name' ) ] = has_rules;
9050								} );
9051							} else if ( field.is( ':radio' ) ) {
9052								has_rules.product_element_radio_qty = true;
9053								validation_rules[ field.attr( 'name' ) ] = has_rules;
9054								subFieldName = field.closest( '.tc-element-container' ).find( '.product-variation-id' ).first().attr( 'name' );
9055								subRule = {
9056									required: function( elem ) {
9057										var element = $( elem );
9058										var holder = element.closest( '.tc-element-container' );
9059										var radiobutton = holder.find( '.tc-epo-field-product:checked' );
9060
9061										if ( radiobutton.length && radiobutton.attr( 'data-type' ) === 'variable' && field_is_active( radiobutton, true ) && radiobutton.is( ':checked' ) ) {
9062											return true;
9063										}
9064										return false;
9065									}
9066								};
9067								validation_rules[ subFieldName ] = subRule;
9068							} else if ( field.is( 'select' ) ) {
9069								has_rules.product_element_select_qty = true;
9070								validation_rules[ field.attr( 'name' ) ] = has_rules;
9071								subFieldName = field.closest( '.tc-element-container' ).find( '.product-variation-id' ).first().attr( 'name' );
9072								subRule = {
9073									required: function( elem ) {
9074										var element = $( elem );
9075										var holder = element.closest( '.tc-element-container' );
9076										var select = holder.find( '.tc-epo-field-product' );
9077
9078										if ( select.length && select.children( ':selected' ).attr( 'data-type' ) === 'variable' && field_is_active( select, true ) ) {
9079											return true;
9080										}
9081										return false;
9082									}
9083								};
9084								validation_rules[ subFieldName ] = subRule;
9085							}
9086						} else {
9087							validation_rules[ field_name ] = has_rules;
9088						}
9089					}
9090				} );
9091
9092			form.removeData( 'tc_validator' );
9093			form.tc_validate( {
9094				focusInvalid: false,
9095				ignore:
9096					tcAPI.qtySelector +
9097					',.tcdisabled,.tmcp-upload-hidden,#wc_bookings_field_duration,input.tm-qty:hidden[type="number"],input.input-text.qty,.ignore,.variations select,.tc-epo-variable-product-selector,.tm-extra-product-options-variations input,.tm-extra-product-options-variations select,input:not(' + tcAPI.epoSelector + ' input),select:not(' + tcAPI.epoSelector + ' select)',
9098				rules: validation_rules,
9099				errorClass: 'tm-error',
9100				validClass: 'tm-valid',
9101				errorElement: 'label',
9102				errorPlacement: function( error, element ) {
9103					error.addClass( 'tc-cell tcwidth tcwidth-100' );
9104					if ( TMEPOJS.tm_epo_global_error_label_placement === 'before' ) {
9105						element.closest( '.tc-element-container' ).before( error );
9106					} else {
9107						element.closest( '.tc-element-container' ).after( error );
9108					}
9109					return false;
9110				},
9111				invalidHandler: function( event, validator ) {
9112					jWindow.trigger( 'tm-invalidHandler', {
9113						epo: {
9114							validator: validator
9115						}
9116					} );
9117					setTimeout( function() {
9118						if ( ! main_product.find( tcAPI.addToCartButtonSelector ).first().is( '.disabled' ) ) {
9119							main_product.find( tcAPI.addToCartButtonSelector ).first().removeClass( 'loading' ).prop( 'disabled', false ).removeClass( 'fpd-disabled' );
9120							main_product.find( tcAPI.addToCartButtonSelector ).first().removeClass( 'disabled' ).removeClass( 'loading' ).prop( 'disabled', false ).removeClass( 'fpd-disabled' );
9121						}
9122					}, 100 );
9123					if ( validator.errorList && validator.errorList[ 0 ] && validator.errorList[ 0 ].element ) {
9124						goto_error_item( $( validator.errorList[ 0 ].element ), epoEventId );
9125					}
9126				},
9127				submitHandler: function() {
9128					var ajaxSuccessFunc;
9129					if ( ! epoObject.is_quickview ) {
9130						main_product.find( tcAPI.addToCartButtonSelector ).first().addClass( 'disabled' );
9131						ajaxSuccessFunc = function() {
9132							main_product.find( tcAPI.addToCartButtonSelector ).first().removeClass( 'disabled' );
9133							jDocument.off( 'ajaxSuccess', ajaxSuccessFunc );
9134						};
9135						jDocument.on( 'ajaxSuccess', ajaxSuccessFunc );
9136					}
9137					return apply_submit_events( epoObject );
9138				}
9139			} );
9140
9141			// This should handle most ajax based add to cart solutions
9142			form.find( tcAPI.addToCartButtonSelector ).on( 'click', function( e ) {
9143				if ( ! form.tc_validate().form() ) {
9144					e.preventDefault();
9145					e.stopImmediatePropagation();
9146				}
9147			} );
9148
9149			return true;
9150		}
9151		return false;
9152	}
9153
9154	function tm_form_submit_event( epoObject ) {
9155		var form = epoObject.form;
9156		var epoEventId = epoObject.epoEventId;
9157
9158		jWindow.trigger( 'tm-from-submit', {
9159			epo: epoObject,
9160			functions: {
9161				tm_apply_validation: tm_apply_validation,
9162				apply_submit_events: apply_submit_events
9163			}
9164		} );
9165		if ( ! tm_apply_validation( epoObject ) && $.tcepo.formSubmitEvents[ epoEventId ].length ) {
9166			form.on( 'submit', function() {
9167				apply_submit_events( epoObject );
9168			} );
9169		}
9170
9171		jWindow.on( 'tc_apply_validation', function() {
9172			return tm_apply_validation( epoObject );
9173		} );
9174	}
9175
9176	function found_variation_tmepo( dataObject ) {
9177		var epoHolder = dataObject.epoHolder;
9178		var totalsHolder = dataObject.totalsHolder;
9179		var totalsHolderContainer = dataObject.totalsHolderContainer;
9180		var currentCart = dataObject.currentCart;
9181		var variationForm = dataObject.variationForm;
9182		var variation = dataObject.variation;
9183		var variations = totalsHolder.data( 'variations' );
9184		var product_price;
9185
9186		totalsHolder.data( 'current_variation', variation );
9187
9188		/**
9189		 * Currency converters that don't allow multi currency checkout will fail the following if statement
9190		 *
9191		 * if (variation.display_price!=undefined) {
9192		 *     product_price = variation.display_price;
9193		 *     totalsHolder.data('price', product_price);
9194		 * } else ...
9195		 *
9196		 */
9197		// This needs to be the first check as the next one
9198		// fails for taxed products as it displays the backend price only.
9199		if ( variation && 'display_price' in variation && ! totalsHolder.data( 'tm-epo-is-woocs' ) ) {
9200			product_price = variation.display_price;
9201
9202			totalsHolder.data( 'priceIsWithDiscount', '1' );
9203			// Fancy product Designer
9204			totalsHolder.removeData( 'tcprice' );
9205		} else if ( variations && variation && variation.variation_id && variations[ variation.variation_id ] !== undefined ) {
9206			product_price = variations[ variation.variation_id ];
9207
9208			// Fancy product Designer
9209			totalsHolder.removeData( 'tcprice' );
9210		} else if ( variation && $( variation.price_html ).find( '.amount:last' ).length ) {
9211			product_price = $( variation.price_html ).find( '.amount:last' ).text();
9212			product_price = product_price.replace( TMEPOJS.currency_format_thousand_sep, '' );
9213			product_price = product_price.replace( TMEPOJS.currency_format_decimal_sep, '.' );
9214			product_price = product_price.replace( /[^0-9.]/g, '' );
9215			product_price = parseFloat( product_price );
9216
9217			// Fancy product Designer
9218			totalsHolder.removeData( 'tcprice' );
9219		}
9220
9221		product_price = tm_set_backend_price( product_price, totalsHolder, variation );
9222		totalsHolder.data( 'price', product_price );
9223
9224		totalsHolderContainer.find( '.cpf-product-price' ).val( product_price );
9225
9226		setTimeout( function() {
9227			epoHolder.find( 'select.tm-epo-field' ).trigger( 'tm-select-change-html-all-math' );
9228		}, 100 );
9229
9230		// This must be run every time to get correct results for percent price types
9231		// if set norules then discount will not auto work upon chosing a variation
9232		if ( ! variationForm.data( 'tm-styled-variations' ) ) {
9233			currentCart.trigger( {
9234				type: 'tm-epo-update'
9235			} );
9236		}
9237	}
9238
9239	function fetchOptionPrices( epoObject, epoHolder, selector, total, original_total, floatingBoxData, showTotal, forced, setPriceTax, useUndiscountedPrice, mathTotal, cumulative, nopriceCac
9239heSelector, cartQty ) {
9240		var obj;
9241		var noDpd;
9242		var priceArray;
9243		var priceCacheSelector = 'none';
9244		var total_taxed;
9245		var original_total_taxed;
9246		var vat_total = 0;
9247		var currentTotalsContainer;
9248		var epoinline;
9249		var funcTotal;
9250		var cumulativeTotal;
9251
9252		if ( ! nopriceCacheSelector ) {
9253			priceCacheSelector = epoHolder.attr( 'class' ) + epoHolder.attr( 'data-uniqid' ) + selector + epoObject.is_associated + setPriceTax + forced + setPriceTax + useUndiscountedPrice || 'none';
9254		}
9255
9256		if ( priceCacheSelector !== 'none' && priceCache !== true && priceCache !== false && priceCache[ priceCacheSelector ] !== undefined ) {
9257			return priceCache[ priceCacheSelector ];
9258		}
9259
9260		noDpd = useUndiscountedPrice ? 'undiscounted_' : '';
9261		obj = epoHolder.find( selector );
9262		if ( epoObject.is_associated === false ) {
9263			obj = obj.not( tcAPI.associatedEpoSelector + ' ' + selector + ',.cpf-type-variations ' + selector );
9264		}
9265		if ( ! forced ) {
9266			obj = obj.filter( '.tcenabled' );
9267		}
9268
9269		if ( ! total ) {
9270			total = 0;
9271		}
9272		if ( ! original_total ) {
9273			original_total = 0;
9274		}
9275
9276		funcTotal = total;
9277		cumulativeTotal = total;
9278
9279		total_taxed = total;
9280		original_total_taxed = original_total;
9281
9282		if ( ! floatingBoxData ) {
9283			floatingBoxData = [];
9284		}
9285
9286		currentTotalsContainer = epoObject.this_epo_totals_container;
9287
9288		if ( obj.length ) {
9289			obj.toArray().forEach( function( tmcpfield ) {
9290				var field = $( tmcpfield );
9291				var _value = '';
9292				var fieldval;
9293				var field_div = field.closest( '.cpf-element' );
9294				var field_wrap = field.closest( '.tmcp-field-wrap' );
9295				var field_label_show = field_div.attr( 'data-fblabelshow' );
9296				var field_value_show = field_div.attr( 'data-fbvalueshow' );
9297				var field_title = '';
9298				var option_quantity = field_wrap.find( '.tm-qty' ).val();
9299				var option_price;
9300				var option_price_taxed;
9301				var option_original_price;
9302				var option_original_price_taxed;
9303				var liw;
9304				var cri;
9305				var tl;
9306				var options;
9307				var forrangepicker;
9308				var $decimals;
9309				var _valueText = '';
9310				var setter;
9311				var dofloatingBoxData = false;
9312
9313				if ( selector === '.tc-epo-field-product' ) {
9314					if ( field_div.is( '.cpf-type-product-thumbnailmultiple' ) || field_div.is( '.cpf-type-product-checkbox' ) || field_div.is( '.cpf-type-product-custombundle' ) ) {
9315						epoinline = field.closest( '.tc-epo-element-product-holder' ).find( tcAPI.associatedEpoSelector );
9316					} else if ( field_div.is( '.cpf-type-product-thumbnail' ) || field_div.is( '.cpf-type-product-radio' ) || field_div.is( '.cpf-type-product-dropdown' ) ) {
9317						epoinline = field_div.find( '.tc-epo-element-product-container[data-product_id="' + field.val() + '"]' ).find( tcAPI.associatedEpoSelector );
9318					} else if ( field_div.is( '.cpf-type-product-single' ) ) {
9319						epoinline = field_div.find( tcAPI.associatedEpoSelector );
9320					}
9321					currentTotalsContainer = $( '.tc-epo-totals' + '.tm-product-id-' + epoinline.attr( 'data-product-id' ) + '[data-epo-id="' + epoinline.attr( 'data-epo-id' ) + '"]' );
9322				}
9323
9324				if ( currentTotalsContainer.length ) {
9325					if ( field_label_show === '' ) {
9326						field_title = field_div.find( '.tc-epo-element-label-text' ).html();
9327					}
9328
9329					if ( option_quantity === undefined ) {
9330						option_quantity = '';
9331					}
9332					if ( mathTotal ) {
9333						tm_element_epo_rules( epoObject, field, undefined, undefined, undefined, undefined, funcTotal, cumulativeTotal );
9334					}
9335					if ( field.is( ':checkbox, :radio, :input' ) ) {
9336						option_price = 0;
9337						option_price_taxed = 0;
9338						option_original_price = 0;
9339						option_original_price_taxed = 0;
9340						if ( field.is( '.tmcp-checkbox, .tmcp-radio' ) ) {
9341							if ( forced || field.is( ':checked' ) ) {
9342								option_price = field.data( noDpd + 'raw_price' );
9343								option_price_taxed = field.data( noDpd + 'price' );
9344								option_original_price = field.data( noDpd + 'raw_original_price' );
9345								option_original_price_taxed = field.data( noDpd + 'original_price' );
9346								showTotal = true;
9347								field.data( 'isset', 1 );
9348								liw = field.closest( 'li.tmcp-field-wrap' );
9349								cri = liw.find( '.tc-image' );
9350								_value = '';
9351								_valueText = '';
9352
9353								tl = field.closest( 'li.tmcp-field-wrap' ).find( '.tc-label-text' );
9354								if ( tl.length ) {
9355									_value = tl.html();
9356									_valueText = _value;
9357								}
9358
9359								if ( cri.length ) {
9360									cri = cri.closest( '.tc-label-wrap' ).clone().addClass( 'tc-img-floating' );
9361									cri.find( '.tc-label, .tc-epo-style-wrapper, .tc-input-wrap' ).remove();
9362									_value = cri[ 0 ].outerHTML + '<span class="tc-label-text">' + _value + '</span>';
9363								}
9364								dofloatingBoxData = true;
9365							} else {
9366								field.data( 'isset', 0 );
9367							}
9368						} else if ( field.is( '.tmcp-select' ) ) {
9369							setter = field.find( 'option:selected' );
9370							option_price = setter.data( noDpd + 'raw_price' );
9371							option_price_taxed = setter.data( noDpd + 'price' );
9372							option_original_price = setter.data( noDpd + 'raw_original_price' );
9373							option_original_price_taxed = setter.data( noDpd + 'original_price' );
9374
9375							options = field.children( 'option:selected' );
9376							if ( ! ( options.val() === '' && options.attr( 'data-rulestype' ) === '' ) ) {
9377								showTotal = true;
9378							}
9379
9380							field.find( 'option' ).data( 'isset', 0 );
9381							setter.data( 'isset', 1 );
9382
9383							if ( ! ( setter.val() === '' && setter.attr( 'data-rulestype' ) === '' ) ) {
9384								_value = setter.attr( 'data-text' );
9385								dofloatingBoxData = true;
9386								_valueText = _value;
9387							}
9388						} else if ( field.is( '.tmcp-selectmultiple' ) ) {
9389							setter = field.find( 'option:selected' );
9390							setter.toArray().forEach( function( setterel ) {
9391								setterel = $( setterel );
9392								option_price = option_price + $.epoAPI.math.toFloat( setterel.data( noDpd + 'raw_price' ) );
9393								option_price_taxed = option_price_taxed + $.epoAPI.math.toFloat( setterel.data( noDpd + 'price' ) );
9394								option_original_price = option_original_price + $.epoAPI.math.toFloat( setterel.data( noDpd + 'raw_original_price' ) );
9395								option_original_price_taxed = option_original_price_taxed + $.epoAPI.math.toFloat( setterel.data( noDpd + 'original_price' ) );
9396
9397								options = field.children( 'option:selected' );
9398								if ( ! ( options.val() === '' && options.attr( 'data-rulestype' ) === '' ) ) {
9399									showTotal = true;
9400								}
9401
9402								field.find( 'option' ).data( 'isset', 0 );
9403								setterel.data( 'isset', 1 );
9404
9405								if ( ! ( setterel.val() === '' && setterel.attr( 'data-rulestype' ) === '' ) ) {
9406									_value = setterel.attr( 'data-text' );
9407									dofloatingBoxData = true;
9408									_valueText = _value;
9409								}
9410							} );
9411						} else {
9412							fieldval = field.val();
9413							if ( field.is( "[type='file']" ) ) {
9414								fieldval = fieldval.replace( 'C:\\fakepath\\', '' );
9415							}
9416							if ( fieldval ) {
9417								if ( field.is( '.tmcp-range' ) && fieldval === '0' ) {
9418									field.data( 'isset', 0 );
9419								} else {
9420									option_price = field.data( noDpd + 'raw_price' );
9421									option_price_taxed = field.data( noDpd + 'price' );
9422									option_original_price = field.data( noDpd + 'raw_original_price' );
9423									option_original_price_taxed = field.data( noDpd + 'original_price' );
9424									showTotal = true;
9425									field.data( 'isset', 1 );
9426
9427									_value = fieldval;
9428									if ( field.is( '.tmcp-range' ) ) {
9429										forrangepicker = field.closest( '.tmcp-field-wrap' ).find( '.tm-range-picker' );
9430										$decimals = forrangepicker.attr( 'data-step' ).split( '.' );
9431										if ( $decimals.length === 1 ) {
9432											$decimals = 0;
9433										} else {
9434											$decimals = $decimals[ 1 ].length;
9435										}
9436										_value = formatPrice( _value, { precision: $decimals } );
9437									}
9438									dofloatingBoxData = true;
9439									if ( field.is( '.tmcp-dynamic' ) ) {
9440										field_label_show = 'hidden';
9441										field_value_show = 'hidden';
9442									}
9443									_valueText = fieldval;
9444								}
9445							} else {
9446								field.data( 'isset', 0 );
9447							}
9448						}
9449						if ( ! option_price ) {
9450							option_price = 0;
9451						}
9452						if ( ! option_original_price ) {
9453							option_original_price = 0;
9454						}
9455						if ( ! option_price_taxed ) {
9456							option_price_taxed = 0;
9457						}
9458						if ( ! option_original_price_taxed ) {
9459							option_original_price_taxed = 0;
9460						}
9461						if ( dofloatingBoxData ) {
9462							floatingBoxData.push( {
9463								title: field_title,
9464								value: _value,
9465								valueText: _valueText,
9466								price: option_price_taxed,
9467								original_price: option_original_price_taxed,
9468								quantity: option_quantity,
9469								label_show: field_label_show,
9470								value_show: field_value_show,
9471								input_type: field.attr( 'type' )
9472							} );
9473						}
9474						if ( undefined !== cartQty && cartQty > 0 && field.is( '.tc-is-dnmpbq' ) ) {
9475							option_price = option_price / cartQty;
9476						}
9477
9478						option_price_taxed = tm_set_tax_price( option_price, currentTotalsContainer, field, undefined, undefined, undefined, true );
9479						option_original_price_taxed = tm_set_tax_price( option_original_price, currentTotalsContainer, field, undefined, undefined, undefined, true );
9480
9481						if ( setPriceTax ) {
9482							option_price = option_price_taxed;
9483							option_original_price = option_original_price_taxed;
9484						}
9485
9486						total = $.epoAPI.math.toFloat( total ) + $.epoAPI.math.toFloat( option_price );
9487						total = $.epoAPI.math.toFloat( $.epoAPI.math.round( total, 10 ) );
9488						original_total = $.epoAPI.math.toFloat( original_total ) + $.epoAPI.math.toFloat( option_original_price );
9489						original_total = $.epoAPI.math.toFloat( $.epoAPI.math.round( original_total, 10 ) );
9490
9491						total_taxed = $.epoAPI.math.toFloat( total_taxed ) + $.epoAPI.math.toFloat( option_price_taxed );
9492						total_taxed = $.epoAPI.math.toFloat( $.epoAPI.math.round( total_taxed, 10 ) );
9493						vat_total = vat_total + $.epoAPI.math.toFloat( calculateTaxAmount( option_price_taxed, currentTotalsContainer ) );
9494						original_total_taxed = $.epoAPI.math.toFloat( original_total_taxed ) + $.epoAPI.math.toFloat( option_original_price_taxed );
9495						original_total_taxed = $.epoAPI.math.toFloat( $.epoAPI.math.round( original_total_taxed, 10 ) );
9496
9497						if ( cumulative ) {
9498							cumulativeTotal = total;
9499						}
9500					}
9501				}
9502			} );
9503		}
9504		priceArray = {
9505			total: total,
9506			original_total: original_total,
9507			total_taxed: total_taxed,
9508			original_total_taxed: original_total_taxed,
9509			vat_total: vat_total,
9510			floatingBoxData: floatingBoxData,
9511			showTotal: showTotal,
9512			elementsLength: obj.length
9513		};
9514
9515		if ( priceCache === true ) {
9516			priceCache = {};
9517			priceCache[ priceCacheSelector ] = priceArray;
9518		} else if ( priceCache !== true && priceCache !== false ) {
9519			priceCache[ priceCacheSelector ] = priceArray;
9520		}
9521
9522		return priceArray;
9523	}
9524
9525	function show_product_html( thisEpoObject, thisMainProduct, thisVariableProductContainer, type, $this, currentCart, variableProductContainers, isTrigger, qtyalt ) {
9526		var epoObjectCopy = $.extend( true, {}, thisEpoObject );
9527		var item_tm_extra_product_options = thisVariableProductContainer.find( tcAPI.associatedEpoSelector );
9528		var item = thisVariableProductContainer;
9529		var newEpoObject;
9530		var showOnly = true;
9531
9532		$this.removeData( 'triggeredforced' );
9533
9534		if ( item.closest( '.cpf-element' ).is( '.tc-hidden' ) ) {
9535			return;
9536		}
9537
9538		variableProductContainers.addClass( 'tm-hidden' );
9539		if ( variableProductContainers.length ) {
9540			toggleState( variableProductContainers, true );
9541		}
9542
9543		if ( type === 'variable' ) {
9544			if ( ! thisVariableProductContainer.is( '.tc-init-variations' ) ) {
9545				thisVariableProductContainer.addClass( 'variations_form' );
9546				setTimeout( function() {
9547					newEpoObject = tm_init_epo( item, false, item_tm_extra_product_options.attr( 'data-product-id' ), item_tm_extra_product_options.attr( 'data-epo-id' ), $this, epoObjectCopy );
9548					thisVariableProductContainer.addClass( 'tc-init-variations' );
9549					thisVariableProductContainer.tc_product_variation_form( $this, currentCart, variableProductContainers, newEpoObject );
9550				}, 40 );
9551				showOnly = false;
9552			} else {
9553				thisVariableProductContainer.trigger( 'refresh.tc-variation-form' );
9554			}
9555		} else if ( ! thisVariableProductContainer.is( '.tc-init-product' ) ) {
9556			thisVariableProductContainer.addClass( 'tc-init-product' );
9557			variableProductContainers.find( '.tc-epo-element-variable-product' ).removeClass( 'variations_form' );
9558			variableProductContainers.find( '.tc-epo-element-variations' ).removeClass( 'variations' );
9559
9560			setTimeout( function() {
9561				tm_init_epo( item, false, item_tm_extra_product_options.attr( 'data-product-id' ), item_tm_extra_product_options.attr( 'data-epo-id' ), $this, epoObjectCopy );
9562			}, 20 );
9563			showOnly = false;
9564		}
9565
9566		setTimeout( function() {
9567			if ( variableProductContainers.length ) {
9568				toggleState( thisVariableProductContainer, false );
9569			}
9570			thisVariableProductContainer
9571				.find( ':checkbox:checked, :radio:checked' )
9572				.toArray().forEach( function( vpc ) {
9573					$( vpc ).closest( '.tmcp-field-wrap' ).addClass( 'tc-active' );
9574				} );
9575		}, 10 );
9576		setTimeout( function() {
9577			if ( qtyalt.length ) {
9578				qtyalt.trigger( 'change' );
9579			}
9580			if ( thisVariableProductContainer.find( tcAPI.epoSelector ).length === 0 ) {
9581				thisVariableProductContainer.addClass( 'no-epo' );
9582			}
9583			thisVariableProductContainer.removeClass( 'tm-hidden' );
9584			if ( showOnly ) {
9585				jWindow.trigger( 'cpflogicdone' );
9586				thisVariableProductContainer.find( '.tm-quantity' ).trigger( 'showhide.cpfcustom' );
9587			}
9588			if ( isTrigger === undefined && TMEPOJS.tm_epo_global_product_element_scroll === 'yes' ) {
9589				jWindow.tcScrollTo( thisVariableProductContainer, 200, $.epoAPI.math.toFloat
9589( TMEPOJS.tm_epo_global_product_element_scroll_offset ) );
9590			}
9591			jWindow.trigger( 'show_product_html', {
9592				thisEpoObject: thisEpoObject,
9593				thisMainProduct: thisMainProduct,
9594				thisVariableProductContainer: thisVariableProductContainer,
9595				type: type,
9596				this: $this,
9597				currentCart: currentCart,
9598				variableProductContainers: variableProductContainers,
9599				isTrigger: isTrigger,
9600				qtyalt: qtyalt
9601			} );
9602		}, 210 );
9603	}
9604
9605	function setQtyData( qtyElement, value ) {
9606		var data = qtyElement.data();
9607		if ( value === undefined ) {
9608			value = qtyElement.val();
9609		}
9610		if ( data ) {
9611			Object.keys( data ).filter( function( key ) {
9612				return key.indexOf( 'epopreviousvalue' ) === 0;
9613			} ).forEach( function( key ) {
9614				qtyElement.data( key, value );
9615			} );
9616		}
9617	}
9618
9619	function epoEventHandlers( epoObject, cartContainer, alternativeCart ) {
9620		// if cartContainer & alternativeCart is defined we are on a non default product (eg. composite product)
9621		var product_id = epoObject.product_id;
9622		var main_product = epoObject.main_product;
9623		var main_cart = epoObject.main_cart;
9624		var this_epo_container = epoObject.this_epo_container;
9625		var this_totals_container = epoObject.this_totals_container;
9626		var this_epo_totals_container = epoObject.this_epo_totals_container;
9627		var epoEventId = epoObject.epoEventId;
9628		var main_epo_inside_form = epoObject.main_epo_inside_form;
9629		var epo_id_selector = epoObject.epo_id_selector;
9630		var epo_id = epoObject.epo_id;
9631		var product_id_selector = epoObject.product_id_selector;
9632		var itemId = 'main';
9633		var epoHolder;
9634		var totalsHolderContainer;
9635		var totalsHolder;
9636		var currentCart;
9637		var variation_id_selector;
9638		var this_product_type;
9639		var variationForm;
9640		var qtyElement;
9641		var finalTotalBoxMode;
9642		var finalTotalBoxShowFinal;
9643		var finalTotalBoxShowOptions;
9644		var eventName = epoObject.is_associated ? 'tc-variation-form' : 'wc-variation-form';
9645		var eventNamePrefix = epoObject.is_associated ? 'tc_' : '';
9646		var epoVariationSection;
9647		var thismaxlength;
9648		var epoFieldAll;
9649		var selectSelector;
9650		var epoFieldText;
9651		var epoResetRadio;
9652		var epoFieldUpload;
9653		var epoFieldHasClearButton;
9654		var tmQty;
9655		var tmQuantity;
9656
9657		// Non default product (eg. composite product)
9658		if ( alternativeCart && cartContainer ) {
9659			itemId = $.epoAPI.applyFilter( 'tc_get_item_id', cartContainer.attr( 'data-item_id' ), cartContainer );
9660			epoHolder = main_product.find( '.tm-extra-product-options.tm-cart-' + itemId );
9661			totalsHolderContainer = main_product.find( '.tm-totals-form-' + itemId );
9662			totalsHolder = main_product.find( '.tm-epo-totals.tm-cart-' + itemId );
9663			variationForm = cartContainer.find( '.variations_form' ).first();
9664		// Default product
9665		} else {
9666			if ( ! main_cart || main_cart.length === 0 ) {
9667				if ( this_epo_container.is( '.tc-shortcode' ) ) {
9668					main_cart = main_product;
9669				} else {
9670					main_cart = get_main_cart( main_product, main_product, 'form', product_id );
9671				}
9672			}
9673			cartContainer = main_cart.parent();
9674			epoHolder = this_epo_container;
9675			totalsHolderContainer = this_totals_container;
9676			totalsHolder = this_epo_totals_container;
9677			variationForm = epoObject.variations_form;
9678		}
9679
9680		if ( epoObject.is_associated ) {
9681			itemId = epoHolder.attr( 'data-cart-id' );
9682		}
9683
9684		currentCart = alternativeCart || main_cart;
9685		totalsHolder.data( 'tm_for_cart', currentCart );
9686
9687		variation_id_selector = getVariationIdSelector( currentCart );
9688		qtyElement = getQtyElement( currentCart );
9689
9690		totalsHolder.data( 'variationIdElement', getVariationIdElement( currentCart, '.wceb_picker_wrap ' + variation_id_selector ) );
9691		totalsHolder.data( 'qty_element', qtyElement );
9692
9693		this_product_type = totalsHolder.data( 'type' );
9694
9695		variationForm.data( 'tc_product_id', product_id );
9696
9697		finalTotalBoxMode = totalsHolder.attr( 'data-tm-epo-final-total-box' );
9698		finalTotalBoxShowFinal = totalsHolder.attr( 'data-tm-epo-show-final-total' );
9699		finalTotalBoxShowOptions = totalsHolder.attr( 'data-tm-epo-show-options-total' );
9700
9701		jWindow.trigger( 'epoEventHandlersStart', {
9702			epo: epoObject,
9703			cart: currentCart,
9704			alternativeCart: alternativeCart,
9705			cartContainer: cartContainer,
9706			totalsHolderContainer: totalsHolderContainer,
9707			totalsHolder: totalsHolder,
9708			epoHolder: epoHolder
9709		} );
9710
9711		jWindow.on( 'epoCalculateRules', function( event, dataObject ) {
9712			if ( event && dataObject && dataObject.currentCart ) {
9713				tm_epo_rules( epoObject, dataObject.currentCart );
9714			}
9715		} );
9716
9717		if ( currentCart.is( 'form' ) ) {
9718			currentCart.on( 'reset', function() {
9719				var form = $( this );
9720				setTimeout( function() {
9721					$( form.data( 'epo_id_selector' ) ).find( '.tm-epo-field' ).trigger( 'change' );
9722				}, 1 );
9723			} );
9724		}
9725
9726		tm_epo_rules( epoObject, currentCart );
9727
9728		epoFieldAll = epoHolder.find( '.tm-epo-field' );
9729		if ( ! epoObject.is_associated ) {
9730			epoFieldAll = epoFieldAll.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector + ' .tm-epo-field' );
9731		}
9732
9733		epoFieldText = epoHolder.find( '.tm-epo-field.tmcp-textarea,.tm-epo-field.tmcp-textfield' );
9734		if ( ! epoObject.is_associated ) {
9735			epoFieldText = epoFieldText.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector + ' .tm-epo-field' );
9736		}
9737
9738		epoResetRadio = epoHolder.find( '.tm-epo-reset-radio' );
9739		if ( ! epoObject.is_associated ) {
9740			epoResetRadio = epoResetRadio.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector + ' .tm-epo-reset-radio' );
9741		}
9742
9743		epoFieldUpload = epoHolder.find( '.tm-epo-field.tmcp-upload' );
9744		if ( ! epoObject.is_associated ) {
9745			epoFieldUpload = epoFieldUpload.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector + ' .tm-epo-field.tmcp-upload' );
9746		}
9747
9748		epoFieldHasClearButton = epoHolder.find( '.tm-has-clearbutton .tm-epo-field' );
9749		if ( ! epoObject.is_associated ) {
9750			epoFieldHasClearButton = epoFieldHasClearButton.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector + ' .tm-has-clearbutton .tm-epo-field' );
9751		}
9752
9753		tmQty = epoHolder.find( '.tm-quantity .tm-qty' );
9754		if ( ! epoObject.is_associated ) {
9755			tmQty = tmQty.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector + ' .tm-quantity .tm-qty' );
9756		}
9757
9758		tmQuantity = epoHolder.find( '.tm-quantity' );
9759		if ( ! epoObject.is_associated ) {
9760			tmQuantity = tmQuantity.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector + ' .tm-quantity' );
9761		}
9762
9763		selectSelector = epoHolder.find( 'select.tm-epo-field' );
9764		if ( ! epoObject.is_associated ) {
9765			selectSelector = selectSelector.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector + ' select.tm-epo-field' );
9766		}
9767		// update price amount for select elements
9768		selectSelector
9769			.off( 'tm-select-change-html' )
9770			.on( 'tm-select-change-html', function() {
9771				var field = $( this );
9772				var e_tip;
9773				var e_description;
9774				var sign;
9775				var formatted_price;
9776
9777				if ( field.is( '.tc-epo-field-product' ) || field.is( '.tmcp-selectmultiple' ) ) {
9778					return;
9779				}
9780
9781				if ( main_cart && main_cart.data( 'per_product_pricing' ) !== undefined && ! main_cart.data( 'per_product_pricing' ) ) {
9782					return;
9783				}
9784
9785				formatted_price = tm_set_price( field.find( 'option:selected' ).data( 'price' ), totalsHolder, true, field );
9786				e_tip = field.closest( '.tmcp-field-wrap' ).find( '.tc-tooltip' );
9787				e_description = field.closest( '.tmcp-field-wrap' ).find( '.tc-inline-description' );
9788
9789				// Prices are already taxed
9790				tm_update_price( {
9791					epoObject: epoObject,
9792					obj: field.closest( '.tmcp-field-wrap' ).find( '.tc-price' ),
9793					price: field.find( 'option:selected' ).data( 'price' ),
9794					original_price: field.find( 'option:selected' ).data( 'original_price' ),
9795					force: false,
9796					useFormattedPrice: false
9797				} );
9798
9799				if ( e_tip.length > 0 ) {
9800					e_tip.attr( 'data-tm-tooltip-html', field.find( 'option:selected' ).attr( 'data-tm-tooltip-html' ) ).trigger( 'tc-tooltip-html-changed' );
9801				}
9802
9803				if ( e_description.length > 0 ) {
9804					if ( field.find( 'option:selected' ).attr( 'data-tm-tooltip-html' ) ) {
9805						e_description.html( field.find( 'option:selected' ).attr( 'data-tm-tooltip-html' ) );
9806					} else {
9807						e_description.html( '' );
9808					}
9809				}
9810
9811				if (
9812					( field.find( 'option:selected' ).attr( 'data-hide-amount' ) === '0' || TMEPOJS.tm_epo_show_price_inside_option_hidden_even === 'yes' ) &&
9813					TMEPOJS.tm_epo_show_price_inside_option === 'yes' &&
9814					field.find( 'option:selected' ).attr( 'data-text' ) &&
9815					( field.find( 'option:selected' ).data( 'price' ) || ( TMEPOJS.tm_epo_no_hide_price_if_original_not_zero === 'yes' && field.find( 'option:selected' ).data( 'original_price' ) ) )
9816				) {
9817					if (
9818						( TMEPOJS.tm_epo_auto_hide_price_if_zero === 'yes' && $.epoAPI.util.isEmpty( field.find( 'option:selected' ).data( 'price' ) ) === false ) ||
9819						( TMEPOJS.tm_epo_auto_hide_price_if_zero !== 'yes' && field.find( 'option:selected' ).attr( 'data-
9819price' ) !== '' )
9820					) {
9821						sign = '';
9822						field.find( 'option:selected' ).html( field.find( 'option:selected' ).attr( 'data-text' ) + ' (' + sign + formatted_price + ')' );
9823					} else {
9824						field.find( 'option:selected' ).html( field.find( 'option:selected' ).attr( 'data-text' ) );
9825					}
9826				}
9827
9828				if ( field.val() === '' ) {
9829					e_tip.addClass( 'tm-hidden' );
9830				} else if ( field.find( 'option:selected' ).attr( 'data-tm-tooltip-html' ) ) {
9831					e_tip.removeClass( 'tm-hidden' );
9832				} else {
9833					e_tip.addClass( 'tm-hidden' );
9834				}
9835			} )
9836			.off( 'tm-math-select-change-html-all tm-select-change-html-all tm-select-change-html-all-math' )
9837			.on( 'tm-math-select-change-html-all tm-select-change-html-all tm-select-change-html-all-math', function( event ) {
9838				var field = $( this );
9839				var e_tip;
9840				var e_description;
9841				var divider;
9842				var thisformatted_price;
9843
9844				if ( field.is( '.tc-epo-field-product' ) ) {
9845					return;
9846				}
9847
9848				e_tip = field.closest( '.tmcp-field-wrap' ).find( '.tc-tooltip' );
9849				e_description = field.closest( '.tmcp-field-wrap' ).find( '.tc-inline-description' );
9850
9851				if ( e_tip.length > 0 ) {
9852					e_tip.attr( 'data-tm-tooltip-html', field.find( 'option:selected' ).attr( 'data-tm-tooltip-html' ) ).trigger( 'tc-tooltip-html-changed' );
9853				}
9854
9855				if ( field.val() === '' ) {
9856					e_tip.addClass( 'tm-hidden' );
9857				} else if ( field.find( 'option:selected' ).attr( 'data-tm-tooltip-html' ) ) {
9858					e_tip.removeClass( 'tm-hidden' );
9859				} else {
9860					e_tip.addClass( 'tm-hidden' );
9861				}
9862
9863				if ( e_description.length > 0 ) {
9864					if ( field.find( 'option:selected' ).attr( 'data-tm-tooltip-html' ) ) {
9865						e_description.html( field.find( 'option:selected' ).attr( 'data-tm-tooltip-html' ) );
9866					} else {
9867						e_description.html( '' );
9868					}
9869				}
9870
9871				if ( main_cart && main_cart.data( 'per_product_pricing' ) !== undefined && ! main_cart.data( 'per_product_pricing' ) ) {
9872					return;
9873				}
9874
9875				if ( TMEPOJS.tm_epo_show_price_inside_option === 'yes' ) {
9876					field.find( 'option' ).toArray().forEach( function( thisoption ) {
9877						thisoption = $( thisoption );
9878						if ( ! thisoption.val() ) {
9879							return true;
9880						}
9881
9882						if ( event.type === 'tm-select-change-html-all' ) {
9883							thisoption.removeClass( 'tm-epo-late-field' ).removeData( 'tm-price-for-late islate' );
9884							tm_element_epo_rules( epoObject, field, undefined, thisoption, 1 );
9885						} else if ( event.type === 'tm-math-select-change-html-all' ) {
9886							tm_element_epo_rules( epoObject, field, undefined, thisoption, 1, true );
9887						} else if ( event.type === 'tm-select-change-html-all-math' ) {
9888							thisoption.removeClass( 'tm-epo-late-field' ).removeData( 'tm-price-for-late islate' );
9889							tm_element_epo_rules( epoObject, field, undefined, thisoption, 1, true );
9890						}
9891						divider = 1;
9892
9893						if ( TMEPOJS.tm_epo_multiply_price_inside_option !== 'yes' ) {
9894							divider = field.data( 'tm-quantity' );
9895						}
9896
9897						if ( ! divider ) {
9898							divider = 1;
9899						}
9900
9901						if ( ( TMEPOJS.tm_epo_auto_hide_price_if_zero === 'yes' && $.epoAPI.util.isEmpty( thisoption.data( 'price' ) ) === false ) || ( TMEPOJS.tm_epo_auto_hide_price_if_zero !== 'yes' && thisoption.attr( 'data-price' ) !== '' ) ) {
9902							thisformatted_price = tm_set_price( thisoption.data( 'price' ) / divider, totalsHolder, true, field );
9903
9904							if ( ( thisoption.attr( 'data-hide-amount' ) === '0' || TMEPOJS.tm_epo_show_price_inside_option_hidden_even === 'yes' ) && thisoption.attr( 'data-text' ) ) {
9905								thisoption.html( thisoption.attr( 'data-text' ) + ' (' + thisformatted_price + ')' );
9906							}
9907						} else {
9908							thisoption.html( thisoption.attr( 'data-text' ) );
9909						}
9910					} );
9911				}
9912			} )
9913			.off( 'tm-select-price-update-html-all' )
9914			.on( 'tm-select-price-update-html-all', function() {
9915				var field = $( this );
9916				var divider;
9917				var thisformatted_price;
9918
9919				if ( field.is( '.tc-epo-field-product' ) ) {
9920					return;
9921				}
9922
9923				if ( main_cart && main_cart.data( 'per_product_pricing' ) !== undefined && ! main_cart.data( 'per_product_pricing' ) ) {
9924					return;
9925				}
9926
9927				if ( TMEPOJS.tm_epo_show_price_inside_option === 'yes' ) {
9928					field.find( 'option' ).toArray().forEach( function( thisoption ) {
9929						thisoption = $( thisoption );
9930						if ( ! thisoption.val() ) {
9931							return true;
9932						}
9933
9934						divider = 1;
9935
9936						if ( TMEPOJS.tm_epo_multiply_price_inside_option !== 'yes' ) {
9937							divider = field.data( 'tm-quantity' );
9938						}
9939
9940						if ( ! divider ) {
9941							divider = 1;
9942						}
9943
9944						if ( ( TMEPOJS.tm_epo_auto_hide_price_if_zero === 'yes' && $.epoAPI.util.isEmpty( thisoption.data( 'price' ) ) === false ) || ( TMEPOJS.tm_epo_auto_hide_price_if_zero !== 'yes' && thisoption.attr( 'data-price' ) !== '' ) ) {
9945							thisformatted_price = tm_set_price( thisoption.data( 'price' ) / divider, totalsHolder, true, field );
9946
9947							if ( ( thisoption.attr( 'data-hide-amount' ) === '0' || TMEPOJS.tm_epo_show_price_inside_option_hidden_even === 'yes' ) && thisoption.attr( 'data-text' ) ) {
9948								thisoption.html( thisoption.attr( 'data-text' ) + ' (' + thisformatted_price + ')' );
9949							}
9950						} else {
9951							thisoption.html( thisoption.attr( 'data-text' ) );
9952						}
9953					} );
9954				}
9955			} )
9956			.off( 'tm-select-change' )
9957			.on( 'tm-select-change', function() {
9958				var field = $( this );
9959				var thisElementId = field.closest( '.cpf-element' ).attr( 'data-uniqid' );
9960
9961				if ( field.is( '.tc-epo-field-product' ) ) {
9962					return;
9963				}
9964
9965				if ( main_cart && main_cart.data( 'per_product_pricing' ) !== undefined && ! main_cart.data( 'per_product_pricing' ) ) {
9966					return;
9967				}
9968
9969				field.removeData( 'addedtcEpoBeforeOptionPriceCalculation' );
9970				field.removeData( 'addedfieldtcEpoBeforeOptionPriceCalculation' );
9971				jWindow.off( 'tcEpoBeforeOptionPriceCalculation.math' + thisElementId );
9972				jWindow.off( 'tcEpoAfterNormalOptionPriceCalculation.math' + thisElementId );
9973
9974				field.trigger( 'tm-select-change-html' );
9975				field.trigger( 'tm-select-change-html-all' );
9976
9977				currentCart.trigger( {
9978					type: 'tm-epo-update',
9979					norules: 1,
9980					element: field
9981				} );
9982			} ).trigger( 'tm-select-change-html-all' );
9983
9984		// Element quantity selector
9985		tmQty
9986			.off( 'focus.cpf' )
9987			.on( 'focus.cpf', function() {
9988				var qtyField = $( this );
9989				var field = qtyField.closest( '.tmcp-field-wrap' ).find( '.tm-epo-field' );
9990				var currentVal = parseFloat( qtyField.val() );
9991				var max = parseFloat( qtyField.attr( 'max' ) );
9992				var min = parseFloat( qtyField.attr( 'min' ) );
9993				var step = qtyField.attr( 'step' );
9994				var check1 = tm_limit_c_selection( field, false );
9995				var check2 = tm_exact_c_selection( field, false );
9996				var check3 = true;
9997
9998				// Format values
9999				if ( ! currentVal || currentVal === '' || currentVal === 'NaN' ) {
10000					currentVal = 0;
10001				}
10002				if ( max === '' || max === 'NaN' ) {
10003					max = '';
10004				}
10005				if ( min === '' || min === 'NaN' ) {
10006					min = 0;
10007				}
10008				if ( step === 'any' || step === '' || step === undefined || parseFloat( step ) === 'NaN' ) {
10009					step = 1;
10010				}
10011
10012				if ( currentVal < min || currentVal > max ) {
10013					check3 = false;
10014				}
10015
10016				if ( check1 && check2 && check3 ) {
10017					setQtyData( qtyField, currentVal );
10018				} else {
10019					setQtyData( qtyField, min );
10020				}
10021			} )
10022			.off( 'change.cpf' )
10023			.on( 'change.cpf', function( event, data ) {
10024				var qtyField = $( this );
10025				var field = qtyField.closest( '.tmcp-field-wrap' ).find( '.tm-epo-field' );
10026				var currentVal = parseFloat( qtyField.val() );
10027				var max = parseFloat( qtyField.attr( 'max' ) );
10028				var min = parseFloat( qtyField.attr( 'min' ) );
10029				var step = qtyField.attr( 'step' );
10030				var check1 = tm_limit_c_selection( field, false );
10031				var check2 = tm_exact_c_selection( field, false );
10032				var check3 = true;
10033
10034				// Format values
10035				if ( ! currentVal || currentVal === '' || currentVal === 'NaN' ) {
10036					currentVal = 0;
10037				}
10038				if ( max === '' || max === 'NaN' ) {
10039					max = '';
10040				}
10041				if ( min === '' || min === 'NaN' ) {
10042					min = 0;
10043				}
10044				if ( step === 'any' || step === '' || step === undefined || parseFloat( step ) === 'NaN' ) {
10045					step = 1;
10046				}
10047
10048				if ( currentVal < min || currentVal > max ) {
10049					check3 = false;
10050				}
10051
10052				if ( check1 && check2 && check3 ) {
10053					if ( ! epoObject.noEpoUpdate ) {
10054						field.data( 'tm-quantity', qtyField.val() ).trigger( 'change', data );
10055					} else {
10056						field.data( 'tm-quantity', qtyField.val() ).trigger( 'change.cpf', data ).trigger( 'change.cpfproduct', data );
10057					}
10058					field.trigger( 'tm-select-change-html-all' );
10059				} else if ( qtyField.data( 'epopreviousvalue' ) ) {
10060					qtyField.val( qtyField.data( 'epopreviousvalue' ) );
10061				} else {
10062					qtyField.val( min );
10063				}
10064
10065				qtyField.trigger( 'cpf-changed' );
10066			} )
10067			.off( 'tmaddquantity' )
10068			.on( 'tmaddquantity', function() {
10069				var qtyField = $( this );
10070				var field = qtyField.closest( '.tmcp-field-wrap' ).find( '.tm-epo-field' );
10071
10072				field.data( 'tm-quantity', qtyField.val() );
10073			} );
10074
10075		// Insert characters remaining for text-areas and text-fields
10076		thismaxlength = epoHolder.find( '.tmcp-textfield.tm-epo-field[maxlength],textarea.tm-epo-field[maxlength]' );
10077		if ( ! epoObject.is_associated ) {
10078			thismaxlength = thismaxlength.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector + ' .tm-epo-field' );
10079		}
10080
10081		thismaxlength.toArray().forEach( function( field ) {
10082			var innerWrap;
10083			var html;
10084			field = $( field );
10085			if ( field.data( 'tcmaxlength' ) ) {
10086				return;
10087			}
10088			field.data( 'tcmaxlength', 1 );
10089			innerWrap = field.closest( '.tmcp-field-wrap-inner' );
10090			html = $.epoAPI.template.html( tcAPI.templateEngine.tc_chars_remanining, {
10091				maxlength: field.attr( 'maxlength' ),
10092				characters_remaining: TMEPOJS.i18n_characters_remaining
10093			} );
10094			innerWrap.append( $( html ) );
10095		} );
10096		thismaxlength
10097			.off( 'change.tc_maxlen input.tc_maxlen' )
10098			.on( 'change.tc_maxlen input.tc_maxlen', function() {
10099				var field = $( this );
10100
10101				field
10102					.closest( '.tmcp-field-wrap' )
10103					.find( '.tc-chars-remanining' )
10104					.html( parseInt( field.attr( 'maxlength' ), 10 ) - parseInt( field.val().length, 10 ) );
10105			} );
10106
10107		// Change product image event
10108		epoFieldAll
10109			.off( 'tm_trigger_product_image' )
10110			.on( 'tm_trigger_product_image', function() {
10111				var field = $( this );
10112				var currentElement;
10113				var uic;
10114				var variation_element_section;
10115				var is_variation_element;
10116				var src;
10117
10118				if ( field.is( '.tm-product-image:checkbox, .tm-product-image:radio, select.tm-product-image' ) ) {
10119					uic = field.closest( '.tmcp-field-wrap' ).find( 'label img' );
10120					variation_element_section = field.closest( '.cpf-section' );
10121					is_variation_element = variation_element_section.is( '.tm-epo-variation-section' );
10122
10123					currentElement = field;
10124					if ( field.is( 'select.tm-product-image' ) ) {
10125						currentElement = field.children( 'option:selected' );
10126					}
10127					if (
10128						$( uic ).length > 0 ||
10129						( is_variation_element && currentElement.attr( 'data-image' ) !== undefined ) ||
10130						( currentElement.attr( 'data-image' ) !== undefined && currentElement.attr( 'data-image' ) !== '' ) ||
10131						( currentElement.attr( 'data-imagep' ) !== undefined && currentElement.attr( 'data-imagep' ) !== '' )
10132					) {
10133						if ( field.is( ':checked' ) || ( field.is( 'select.tm-product-image' ) && field.val() !== '' && ( field.find( 'option:selected' ).attr( 'data-rules' ) !== '' || field.is( '.tm-epo-variation-element' ) ) ) ) {
10134							src = $( uic ).first().attr( 'data-original' );
10135
10136							if ( ! src && ! is_variation_element ) {
10137								src = $( uic ).first().attr( 'src' );
10138							}
10139							if ( ! src ) {
10140								src = currentElement.attr( 'data-image' );
10141							}
10142							if ( currentElement.attr( 'data-imagep' ) ) {
10143								src = currentElement.attr( 'data-imagep' );
10144							}
10145							if ( src ) {
10146								main_product.trigger( 'tm_change_product_image', {
10147									src: src,
10148									element: field,
10149									element_current: currentElement,
10150									main_product: main_product,
10151									epo_holder: epoHolder
10152								} );
10153							} else {
10154								main_product.trigger( 'tm_change_product_image', {
10155									src: false,
10156									element: field,
10157									element_current: currentElement,
10158									main_product: main_product,
10159									epo_holder: epoHolder
10160								} );
10161							}
10162						} else {
10163							main_product.trigger( 'tm_restore_product_image', {
10164								element: field,
10165								element_current: currentElement,
10166								main_product: main_product,
10167								epo_holder: epoHolder
10168							} );
10169						}
10170					} else {
10171						main_product.trigger( 'tm_restore_product_image', {
10172							element: field,
10173							element_current: currentElement,
10174							main_product: main_product,
10175							epo_holder: epoHolder
10176						} );
10177					}
10178				} else {
10179					main_product.trigger( 'tm_attempt_product_image', {
10180						element: field,
10181						element_current: currentElement,
10182						main_product: main_product,
10183						epo_holder: epoHolder
10184					} );
10185				}
10186			} );
10187
10188		tmQuantity
10189			.off( 'showhide.cpfcustom' )
10190			.on( 'showhide.cpfcustom', function() {
10191				var quantity_selector = $( this );
10192				var field = quantity_selector.closest( '.tmcp-field-wrap' ).find( '.tm-epo-field' );
10193				var show = false;
10194				var tmqty;
10195				var tmqtyval;
10196				var tmqtymin;
10197				var radios;
10198				var tmqtybuttons;
10199
10200				if ( ! field.is( '.tm-epo-variation-element' ) ) {
10201					if ( field.is( 'select' ) ) {
10202						if ( field.val() !== '' ) {
10203							show = true;
10204						}
10205					} else if ( field.is( ':checkbox' ) ) {
10206						if ( field.is( ':checked' ) ) {
10207							show = true;
10208						}
10209					} else if ( field.is( ':radio' ) ) {
10210						if ( field.is( ':checked' ) ) {
10211							show = true;
10212							if ( TMEPOJS.tm_epo_show_only_active_quantities === 'yes' ) {
10213								radios = field.closest( '.tc-element-inner-wrap' ).find( '.tm-epo-field.tmcp-radio' );
10214								radios.toArray().forEach( function( rd ) {
10215									$( rd ).closest( '.tmcp-field-wrap' ).find( '.tm-quantity' ).hide();
10216								} );
10217							}
10218						}
10219					} else if ( field.val() ) {
10220						show = true;
10221					}
10222
10223					tmqty = quantity_selector.find( '.tm-qty' );
10224					tmqtybuttons = quantity_selector.find( '.tc-qty-button' );
10225					tmqtyval = tmqty.val();
10226					tmqtymin = tmqty.attr( 'min' ) || '';
10227
10228					if ( show ) {
10229						if ( TMEPOJS.tm_epo_show_only_active_quantities === 'yes' ) {
10230							quantity_selector.show();
10231						}
10232
10233						tmqty.removeClass( 'ignore' ).prop( 'disabled', false );
10234						tmqtybuttons.prop( 'disabled', false );
10235					} else {
10236						if ( TMEPOJS.tm_epo_show_only_active_quantities === 'yes' ) {
10237							quantity_selector.hide();
10238							if ( ! tmqtyval ) {
10239								tmqty.val( tmqtymin );
10240							}
10241						}
10242
10243						tmqty.addClass( 'ignore' ).prop( 'disabled', true );
10244						tmqtybuttons.prop( 'disabled', true );
10245					}
10246
10247					if ( epoHolder.is( '.tc-show' ) ) {
10248						setTimeout( function() {
10249							quantity_selector.closest( '.tcowl-carousel' ).trigger( 'refresh.owl.carousel' );
10250						}, 200 );
10251					}
10252				}
10253			} );
10254
10255		epoFieldAll
10256			.off( 'change.cpfcustom' )
10257			.on( 'change.cpfcustom', function() {
10258				$( this ).closest( '.tmcp-field-wrap' ).find( '.tm-quantity' ).trigger( 'showhide.cpfcustom' );
10259			} );
10260
10261		epoFieldAll
10262			.off( 'change.cpf' )
10263			.on( 'change.cpf', function( event, data ) {
10264				var field = $( this );
10265				var is_li = field.closest( '.tmcp-field-wrap' );
10266				var is_ul = field.closest( '.tmcp-ul-wrap' );
10267				var is_replace;
10268				var connector = is_ul.attr( 'data-tm-connector' );
10269
10270				if ( field.is( ':checkbox, :radio' ) ) {
10271					if ( field.is( ':radio' ) ) {
10272						if ( ! data ) {
10273							if ( connector !== undefined ) {
10274								$( '[data-tm-connector="' + connector + '"]' ).find( '.tmcp-field-wrap' ).removeClass( 'tc-active' ).find( '.tm-epo-reset-radio' ).addClass( 'tm-hidden' );
10275							} else {
10276								is_ul.find( '.tmcp-field-wrap' ).removeClass( 'tc-active' );
10277							}
10278						}
10279						if ( connector !== undefined ) {
10280							$( '[data-tm-connector="' + connector + '"]' ).find( '.tmcp-field-wrap' ).removeClass( 'tc-active' ).find( '.tm-epo-reset-radio' ).addClass( 'tm-hidden' );
10281						}
10282					}
10283					if ( field.is( ':checked' ) ) {
10284						is_li.addClass( 'tc-active' );
10285					} else {
10286						is_li.removeClass( 'tc-active' );
10287					}
10288				}
10289
10290				if ( ! field.is( '.tm-epo-variation-element' ) ) {
10291					if ( field.is( '.use_images:checkbox, .use_images:radio' ) && field.attr( 'data-imagec' ) ) {
10292						is_replace = is_li.find( '.radio-image,.checkbox-image' ).first();
10293						if ( is_replace.length > 0 ) {
10294							if ( field.is( ':checked' ) ) {
10295								is_replace.prop( 'src', field.attr( 'data-imagec' ) );
10296							} else {
10297								is_replace.prop( 'src', field.attr( 'data-image' ) );
10298							}
10299						}
10300					}
10301
10302					if ( field.is( '.use_images:radio' ) && ! data ) {
10303						field
10304							.closest( '.cpf-type-radio' )
10305							.find( '.use_images:radio' )
10306							.not( field )
10307							.toArray().forEach( function( r ) {
10308								r = $( r );
10309								r.closest( '.tmcp-field-wrap' ).find( '.radio-image' ).first().prop( 'src', r.attr( 'data-image' ) );
10310							} );
10311					}
10312
10313					if ( field.is( '.tmcp-range' ) ) {
10314						field.trigger( 'change.cpflogic' );
10315					}
10316					if ( field.is( 'select' ) ) {
10317						field.trigger( 'tm-select-change' );
10318					} else {
10319						if ( field.is( '.tmcp-radio' ) ) {
10320							field
10321								.closest( '.cpf-element' )
10322								.find( '.tm-quantity .tm-qty' )
10323								.toArray().forEach( function( tmqty ) {
10324									tmqty = $( tmqty );
10325									if ( ! tmqty.closest( 'li.tmcp-field-wrap' ).find( '.tmcp-radio' ).is( ':checked' ) ) {
10326										tmqty.attr( 'disabled', 'disabled' );
10327									} else {
10328										tmqty.prop( 'disabled', false );
10329									}
10330								} );
10331						}
10332						priceCache = true;
10333						currentCart.trigger( {
10334							type: 'tm-epo-update',
10335							norules: 1,
10336							element: field
10337						} );
10338						priceCache = false;
10339					}
10340				}
10341
10342				field.trigger( 'tm_trigger_product_image' );
10343
10344				if ( epoHolder.is( '.tc-show' ) ) {
10345					setTimeout( function() {
10346						$( '.tm-owl-slider' ).toArray().forEach( function( slider ) {
10347							$( slider ).trigger( 'refresh.owl.carousel' );
10348						} );
10349					}, 200 );
10350				}
10351				main_product.trigger( 'tm_attempt_product_image', {
10352					element: field,
10353					main_product: main_product,
10354					epo_holder: epoHolder
10355				} );
10356			} );
10357
10358		epoFieldAll.filter( '.tm-epo-field:text,input.tm-epo-field[type="number"],textarea.tm-epo-field' )
10359			.off( 'input.cpf' )
10360			.on( 'input.cpf', function() {
10361				$( this ).trigger( 'change.cpf', { autoload: 1 } );
10362			} );
10363
10364		epoFieldAll
10365			.filter( ':checkbox:checked, :radio:checked' )
10366			.toArray().forEach( function( cb ) {
10367				$( cb )
10368					.closest( '.tmcp-field-wrap' )
10369					.addClass( 'tc-active' )
10370					.trigger( 'change.cpf', { autoload: 1 } );
10371			} );
10372
10373		epoFieldHasClearButton
10374			.off( 'change.cpfclearbutton' )
10375			.on( 'change.cpfclearbutton cpfclearbutton', function() {
10376				var field = $( this );
10377				var radioResetElement;
10378				var fieldWrap = field.closest( '.tmcp-field-wrap' );
10379				var fieldSearch;
10380
10381				if ( field.is( ':checked' ) ) {
10382					fieldSearch = field.closest( '.tc-element-inner-wrap' );
10383
10384					if ( fieldSearch.find( '.tc-epo-element-product-li-container' ).length ) {
10385						fieldSearch = fieldSearch.find( '.tmcp-ul-wrap' ).first().children( '.tmcp-field-wrap' ).not( '.tc-epo-element-product-li-container' );
10386					}
10387
10388					radioResetElement = fieldSearch.find( '.tm-epo-reset-radio' );
10389					if ( ! radioResetElement.length ) {
10390						radioResetElement = field.closest( '.tc-element-inner-wrap' ).find( '.tm-epo-reset-radio' ).first();
10391					}
10392					radioResetElement.removeClass( 'tm-hidden' );
10393
10394					fieldWrap.append( radioResetElement );
10395				}
10396			} );
10397
10398		epoResetRadio
10399			.off( 'click.cpf' )
10400			.on( 'click.cpf', function() {
10401				var radioResetElement = $( this );
10402				var fieldContainer = radioResetElement.closest( '.tc-element-inner-wrap' );
10403				var checkedRadios = fieldContainer.find( '.tm-epo-field.tmcp-radio:checked' );
10404
10405				if ( checkedRadios.length ) {
10406					checkedRadios.prop( 'checked', false );
10407					checkedRadios.trigger( 'change', { forced: 1 } );
10408				}
10409
10410				radioResetElement.addClass( 'tm-hidden' );
10411			} );
10412
10413		if ( _ && _.debounce ) {
10414			epoFieldText.on( 'keyup',
10415				_.debounce( function() {
10416					var $this = $( this );
10417					var mainform = currentCart;
10418					if ( epoObject.is_associated ) {
10419						mainform = epoObject.mainEpoObject.form;
10420					}
10421
10422					if ( TMEPOJS.tm_epo_global_enable_validation === 'yes' && $.tc_validator && $this.closest( '.tmcp-ul-wrap' ).data( 'tm-validation' ) && $this.tc_rules() ) {
10423						mainform.tc_validate().element( $this );
10424					}
10425					$this.trigger( 'change.cpf' );
10426					$this.closest( '.tmcp-field-wrap' ).find( '.tm-quantity' ).trigger( 'showhide.cpfcustom' );
10427				}, 10 )
10428			);
10429		}
10430
10431		epoFieldUpload
10432			.off( 'change.cpfv tcupload' )
10433			.on( 'change.cpfv tcupload', function() {
10434				var field = $( this );
10435				var label = field.closest( 'label' );
10436				var li = field.closest( '.tmcp-field-wrap' );
10437				var cpfUploadContainer = li.find( '.cpf-upload-container' );
10438				var name = li.find( '.tm-filename' );
10439				var val = field.val().replace( 'C:\\fakepath\\', '' );
10440				var valHidden = [];
10441				var num_uploads;
10442				var windowURL = window.URL || window.webkitURL;
10443				var files;
10444				var image;
10445				var uploadPreview = li.find( '.tc-upload-preview' );
10446				var addImage;
10447				var uniqid;
10448
10449				if ( cpfUploadContainer.length && name.length <= 0 ) {
10450					name = $( '<span class="tm-filename"></span>' );
10451					label.after( name );
10452				}
10453				if ( val === undefined || val === 'undefined' ) {
10454					val = '';
10455				}
10456
10457				field.next( '.tmcp-upload-hidden' ).remove();
10458
10459				valHidden = field.attr( 'data-file' );
10460				valHidden = valHidden ? valHidden.split( '|' ) : [];
10461				if ( this.files ) {
10462					files = Array.from( this.files );
10463				} else if ( valHidden.length > 0 ) {
10464					files = valHidden;
10465				}
10466
10467				if ( files.length > 1 ) {
10468					name.html( '' + files.length + ' ' + ( files.length === 1 ? TMEPOJS.i18n_file : TMEPOJS.i18n_files ) );
10469				} else if ( files.length === 1 ) {
10470					name.html( val );
10471				} else {
10472					name.empty();
10473				}
10474				if ( ! uploadPreview.length ) {
10475					uploadPreview = $( '<div class="tc-upload-preview tc-hidden"></div>' );
10476					li.append( uploadPreview );
10477				}
10478
10479				uploadPreview.empty();
10480
10481				num_uploads = epoHolder.data( 'num_uploads' );
10482				if ( ! num_uploads ) {
10483					num_uploads = [];
10484				}
10485				uniqid = field.closest( '.cpf-element' ).attr( 'data-uniqid' );
10486				if ( ! num_uploads[ uniqid ] ) {
10487					num_uploads[ uniqid ] = [];
10488				}
10489
10490				if ( ( val || files.length > 0 ) && windowURL && windowURL.createObjectURL ) {
10491					if ( TMEPOJS.tm_epo_upload_inline_image_preview === 'yes' ) {
10492						if ( files.length > 1 ) {
10493							uploadPreview.addClass( 'multiple' );
10494						} else {
10495							uploadPreview.removeClass( 'multiple' );
10496						}
10497						uploadPreview.removeClass( 'tc-hidden' );
10498					}
10499					addImage = function( dataFile, src, i, fileHolder, ext ) {
10500						var size = field[ 0 ].files && field[ 0 ].files[ i ] && field[ 0 ].files[ i ].size ? field[ 0 ].files[ i ].size : 0;
10501						var imageHTML = '<div class="tc-upload-image">';
10502						if ( src ) {
10503							imageHTML = imageHTML + '<img src="' + src + '">';
10504						} else {
10505							imageHTML = imageHTML + '<div class="tc-file-ext-overlay"></div>';
10506						}
10507						imageHTML = imageHTML + '<div class="tc-file-name">' + dataFile.name + '</div>';
10508						if ( ClipboardEvent || DataTransfer ) {
10509							imageHTML = imageHTML + '<button type="button" class="tc-upload-remove"><svg width="26" height="26" viewBox="0 0 26 26" xmlns="http://www.w3.org/2000/svg"><path d="M11.586 13l-2.293 2.293a1 1 0 0 0 1.414 1.414L13 14.414l2.293 2.293a1 1 0 0 0 1.414-1.414L14.414 13l2.293-2.293a1 1 0 0 0-1.414-1.414L13 11.586l-2.293-2.293a1 1 0 0 0-1.414 1.414L11.586 13z" fill="currentColor" fill-rule="nonzero"/></svg></button>';
10510						}
10511						if ( ext ) {
10512							imageHTML = imageHTML + '<div class="tc-file-ext">' + ext + '</div>';
10513						}
10514						imageHTML = imageHTML + '<div class="tc-file-size">' + readableFileSize( size ) + '</div>';
10515						imageHTML = imageHTML + '</div>';
10516						fileHolder.append( imageHTML );
10517					};
10518
10519					files.forEach( function( dataFile, i ) {
10520						var fileHolder;
10521						if ( TMEPOJS.tm_epo_upload_inline_image_preview === 'yes' ) {
10522							fileHolder = $( '<div class="tc-upload-file"></div>' );
10523							uploadPreview.append( fileHolder );
10524							image = new Image();
10525							image.onload = function() {
10526								addImage( dataFile, this.src, i, fileHolder );
10527							};
10528							image.onerror = function() {
10529								addImage( dataFile, false, i, fileHolder, dataFile.name.split( '.' ).pop() );
10530							};
10531							if ( valHidden.length > 0 ) {
10532								image.src = valHidden[ i ];
10533							} else {
10534								image.src = windowURL.createObjectURL( dataFile );
10535								windowURL.revokeObjectURL( dataFile );
10536							}
10537						}
10538						num_uploads[ uniqid ].push( dataFile.name );
10539					} );
10540					epoHolder.data( 'num_uploads', num_uploads );
10541				} else {
10542					delete num_uploads[ uniqid ];
10543				}
10544				if ( num_uploads[ uniqid ] && num_uploads[ uniqid ].length === 0 ) {
10545					delete num_uploads[ uniqid ];
10546				}
10547			} );
10548
10549		jDocument.on( 'click', '.tc-upload-remove', function() {
10550			var $this = $( this );
10551			var val;
10552			var cpfElement;
10553			var input;
10554			var fileWrap;
10555			var li;
10556			var uploadPreview;
10557			var name;
10558			var index;
10559			var files;
10560			var dT;
10561			var num_uploads;
10562			var uniqid;
10563			var uploadHidden;
10564			var dataFiles;
10565
10566			if ( ClipboardEvent || DataTransfer ) {
10567				cpfElement = $this.closest( '.cpf-element' );
10568				input = cpfElement.find( '.tm-epo-field' );
10569				fileWrap = $this.closest( '.tc-upload-file' );
10570				li = $this.closest( '.tmcp-field-wrap' );
10571				uploadPreview = li.find( '.tc-upload-preview' );
10572				name = li.find( '.tm-filename' );
10573				index = fileWrap.index();
10574				val = input.val().replace( 'C:\\fakepath\\', '' );
10575				if ( val === undefined || val === 'undefined' ) {
10576					val = '';
10577				}
10578
10579				files = Array.from( input[ 0 ].files );
10580				files.splice( index, 1 );
10581				dT = new ClipboardEvent( '' ).clipboardData || new DataTransfer();
10582
10583				files.forEach( function( dataFile ) {
10584					dT.items.add( dataFile );
10585				} );
10586
10587				if ( files.length > 1 ) {
10588					uploadPreview.addClass( 'multiple' );
10589				} else {
10590					uploadPreview.removeClass( 'multiple' );
10591				}
10592
10593				input[ 0 ].files = dT.files;
10594				fileWrap.remove();
10595				if ( dT.files.length > 1 ) {
10596					name.html( '' + dT.files.length + ' ' + ( dT.files.length === 1 ? TMEPOJS.i18n_file : TMEPOJS.i18n_files ) );
10597				} else if ( dT.files.length === 1 ) {
10598					name.html( val );
10599				} else {
10600					name.empty();
10601				}
10602
10603				num_uploads = epoHolder.data( 'num_uploads' );
10604				if ( ! num_uploads ) {
10605					num_uploads = [];
10606				}
10607				uniqid = cpfElement.closest( '.cpf-element' ).attr( 'data-uniqid' );
10608				if ( ! num_uploads[ uniqid ] ) {
10609					num_uploads[ uniqid ] = [];
10610				}
10611
10612				num_uploads[ uniqid ].splice( index, 1 );
10613				if ( num_uploads[ uniqid ].length === 0 ) {
10614					delete num_uploads[ uniqid ];
10615					input.val( '' );
10616				}
10617
10618				uploadHidden = input.next( '.tmcp-upload-hidden' );
10619				if ( uploadHidden.length ) {
10620					dataFiles = uploadHidden.val().split( '|' );
10621					if ( dataFiles.length > 0 ) {
10622						dataFiles.splice( index, 1 );
10623					}
10624					if ( dataFiles.length === 0 ) {
10625						uploadHidden.remove();
10626					} else {
10627						uploadHidden.val( dataFiles.join( '|' ) );
10628					}
10629				}
10630
10631				epoHolder.data( 'num_uploads', num_uploads );
10632			}
10633		} );
10634
10635		qtyElement
10636			.off( 'change.cpf input.cpf' )
10637			.on( 'change.cpf input.cpf', function() {
10638				var field = $( this );
10639
10640				currentCart.trigger( 'tm-epo-check-dpd' );
10641				setQtyData( field );
10642				// It is required than when you update the product quantity
10643				// to recalculate the option price to accommodate price types
10644				// that depend on quantity
10645				currentCart.trigger( {
10646					type: 'tm-epo-update',
10647					norules: 2
10648				} );
10649			} );
10650		setQtyData( qtyElement );
10651		// Support for math formula on associated products when they are initially hidden
10652		epoHolder
10653			.find( '.cpf-type-product' )
10654			.off( 'tc-logic' )
10655			.on( 'tc-logic', function() {
10656				var $this = $( this );
10657				if ( $this.find( '.tc-init' ).length ) {
10658					return;
10659				}
10660				if ( $this.data( 'isactive' ) && ! $this.data( 'donetclogic' ) ) {
10661					$this.data( 'donetclogic', true );
10662					$this.find( '.tc-epo-field-product' ).trigger( 'change.cpfproduct', { forced: 3 } );
10663				}
10664			} );
10665
10666		// Product element checkbox required status fix
10667		epoHolder
10668			.find( '.cpf-type-product .tc-epo-field-product.tc-epo-field-product-checkbox' )
10669			.off( 'change.cpfrequired' )
10670			.on( 'change.cpfrequired', function() {
10671				var $this = $( this );
10672				var cpfElement = $this.closest( '.cpf-element' );
10673				var checkboxes;
10674				var checkboxesChecked;
10675				var checkboxesNotChecked;
10676				if ( cpfElement.is( '.tc-is-required' ) ) {
10677					checkboxes = cpfElement.find( '.tmcp-field.tc-epo-field-product-checkbox' );
10678					checkboxesNotChecked = checkboxes.not( ':checked' );
10679					checkboxesChecked = cpfElement.find( '.tmcp-field.tc-epo-field-product-checkbox:checked' );
10680
10681					if ( checkboxesChecked.length > 0 ) {
10682						checkboxesNotChecked.prop( 'required', false );
10683						checkboxesChecked.prop( 'required', true );
10684					} else {
10685						checkboxes.attr( 'required', true );
10686						checkboxes.prop( 'required', true );
10687					}
10688				}
10689			} );
10690
10691		// Product element variable product support
10692		epoHolder
10693			.find( '.cpf-type-product .tc-epo-field-product' )
10694			.off( 'change.cpfproduct' )
10695			.on( 'change.cpfproduct', function( e, data ) {
10696				var $this = $( this );
10697				var value;
10698				var type;
10699				var selected;
10700				var variableProductContainers;
10701				var thisVariableProductContainer;
10702				var elementContainer = $this.closest( '.cpf-element' );
10703				var productContainerWraps = elementContainer.find( '.tc-epo-element-product-container-wrap' );
10704				var thisProductContainerWrap = $this.closest( '.tmcp-field-wrap' ).find( '.tc-epo-element-product-container-wrap' );
10705				var hasProductContainerWrap = thisProductContainerWrap.length > 0;
10706				var postData;
10707				var skip = false;
10708				var isTrigger = 1000;
10709				var qtyalt;
10710				var associatedSetter = $this;
10711				var associatedElement;
10712				var isFilled;
10713				var productPrice;
10714				var originalProductPrice;
10715				var epoField = elementContainer.find( '.tm-epo-field' ).not( '.tc-epo-element-product-li-container .tm-epo-field' );
10716				var checked = epoField.filter( ':checked' );
10717				var qty;
10718				var counter = $this.attr( 'data-counter' );
10719
10720				if ( false === elementContainer.data( 'isactive' ) ) {
10721					return;
10722				}
10723				if ( data && data.forced === 2 ) {
10724					return;
10725				}
10726
10727				if ( e.isTrigger !== undefined && $this.data( 'triggeredonce' ) && ! ( data && data.forced ) ) {
10728					return;
10729				}
10730
10731				if ( $this.data( 'triggeredforced' ) === 3 ) {
10732					return;
10733				}
10734
10735				$this.data( 'triggeredonce', 1 );
10736
10737				if ( ! $this.is( ':checkbox' ) ) {
10738					isTrigger = e.isTrigger;
10739				}
10740
10741				if ( epoField.is( ':radio' ) ) {
10742					if ( checked.length > 0 ) {
10743						qty = checked.closest( '.tmcp-field-wrap' ).find( 'input.tm-qty' );
10744					}
10745				} else if ( epoField.is( ':checkbox' ) ) {
10746					if ( checked.length > 0 ) {
10747						qty = $this.closest( '.tmcp-field-wrap' ).find( 'input.tm-qty' );
10748					}
10749				} else {
10750					qty = epoField.closest( '.tmcp-field-wrap' ).find( 'input.tm-qty' );
10751				}
10752
10753				if ( $this.is( ':checkbox' ) ) {
10754					if ( $this.is( '.tc-epo-field-product-hidden' ) ) {
10755						if ( $this.is( ':checked' ) ) {
10756							productContainerWraps.addClass( 'tc-active-product' );
10757						} else {
10758							productContainerWraps.removeClass( 'tc-active-product' );
10759						}
10760
10761						value = $this.val();
10762						type = $this.attr( 'data-type' );
10763						elementContainer.find( '.tc-epo-element-product-li-container:not(.tc-hidden-container .tc-epo-element-product-li-container)' ).removeClass( 'tm-hidden' );
10764					} else {
10765						if ( ! $this.is( ':checked' ) ) {
10766							if ( hasProductContainerWrap ) {
10767								thisProductContainerWrap.addClass( 'tm-hidden' );
10768							}
10769							if ( ! ( data && data.forced ) ) {
10770								return;
10771							}
10772							skip = true;
10773						} else if ( hasProductContainerWrap ) {
10774							thisProductContainerWrap.removeClass( 'tm-hidden' );
10775						}
10776						if ( ! skip ) {
10777							value = $this.val();
10778							type = $this.attr( 'data-type' );
10779							elementContainer.find( '.tc-epo-element-product-li-container:not(.tc-hidden-container .tc-epo-element-product-li-container)' ).removeClass( 'tm-hidden' );
10780						}
10781					}
10782				} else if ( $this.is( ':radio' ) ) {
10783					if ( ! $this.is( ':checked' ) ) {
10784						if ( hasProductContainerWrap ) {
10785							thisProductContainerWrap.addClass( 'tm-hidden' );
10786						}
10787						if ( ! ( data && data.forced ) ) {
10788							return;
10789						}
10790						skip = true;
10791					} else if ( hasProductContainerWrap ) {
10792						productContainerWraps.addClass( 'tm-hidden' );
10793						thisProductContainerWrap.removeClass( 'tm-hidden' );
10794					}
10795					if ( ! skip ) {
10796						value = $this.val();
10797						type = $this.attr( 'data-type' );
10798						elementContainer.find( '.tc-epo-element-product-li-container:not(.tc-hidden-container .tc-epo-element-product-li-container)' ).removeClass( 'tm-hidden' );
10799					}
10800				} else if ( $this.is( 'select' ) ) {
10801					selected = $this.children( ':selected' );
10802					associatedSetter = selected;
10803					counter = selected.index();
10804					if ( $this.children( ':first' ).val() === '' ) {
10805						counter--;
10806					}
10807					value = $this.val();
10808					type = selected.attr( 'data-type' );
10809					elementContainer.find( '.tc-epo-element-product-li-container:not(.tc-hidden-container .tc-epo-element-product-li-container)' ).removeClass( 'tm-hidden' );
10810				}
10811
10812				if ( $this.is( '.tc-epo-field-product-checkbox' ) ) {
10813					variableProductContainers = thisProductContainerWrap.find( '.tc-epo-element-product-container' );
10814				} else {
10815					variableProductContainers = elementContainer.find( '.tc-epo-element-product-container' );
10816				}
10817
10818				thisVariableProductContainer = variableProductContainers.filter( '[data-product_id="' + value + '"]' );
10819
10820				qtyalt = thisVariableProductContainer.find( tcAPI.associateQtySelector );
10821
10822				if ( productContainerWraps.html() !== '' && qty && qty.length > 0 && qtyalt.length === 0 ) {
10823					qty.val( 0 );
10824				}
10825				if ( $this.is( ':checkbox' ) ) {
10826					if ( $this.is( '.tc-epo-field-product-hidden' ) ) {
10827						if ( $this.is( ':checked' ) ) {
10828							if ( qtyalt.val() === '0' ) {
10829								if ( qtyalt.attr( 'min' ) !== '0' ) {
10830									qtyalt.val( qtyalt.attr( 'min' ) ).trigger( 'change' );
10831								}
10832							}
10833						} else {
10834							qtyalt.val( 0 );
10835							qtyalt.closest( '.tm-quantity-alt' ).removeClass( 'tm-hidden' );
10836							if ( data.forced !== 1 ) {
10837								qtyalt.closest( '.tm-quantity-alt' ).find( '.single_add_to_cart_product' ).trigger( 'cpfqtybutton' );
10838							}
10839							productContainerWraps.find( tcAPI.associatedEpoCart ).trigger( 'tm-epo-update' );
10840						}
10841					}
10842				} else if ( $this.is( ':radio' ) ) {
10843					if ( $this.val() && ! $this.data( 'set_initial' ) ) {
10844						if ( qtyalt.val() === '0' ) {
10845							if ( qtyalt.attr( 'min' ) !== '0' ) {
10846								qtyalt.val( qtyalt.attr( 'min' ) ).trigger( 'change' );
10847							}
10848							$this.data( 'set_initial', 1 );
10849						}
10850					}
10851				} else if ( $this.is( 'select' ) ) {
10852					if ( $this.val() && ! $this.data( 'set_initial' ) ) {
10853						if ( qtyalt.val() === '0' ) {
10854							if ( qtyalt.attr( 'min' ) !== '0' ) {
10855								qtyalt.val( qtyalt.attr( 'min' ) ).trigger( 'change' );
10856							}
10857							$this.data( 'set_initial', 1 );
10858						}
10859					}
10860				} else {
10861					return;
10862				}
10863
10864				if ( ! value ) {
10865					variableProductContainers.addClass( 'tm-hidden' );
10866					productPrice = $.epoAPI.util.parseJSON( associatedSetter.attr( 'data-rules' ) );
10867					productPrice = productPrice[ 0 ] || 0;
10868					originalProductPrice = $.epoAPI.util.parseJSON( associatedSetter.attr( 'data-original-rules' ) );
10869					originalProductPrice = originalProductPrice || 0;
10870					if ( associatedSetter.is( '.tcenabled' ) ) {
10871						associatedSetter.data( 'associated_price_set', 1 );
10872					}
10873					associatedSetter.data( 'price_set', 1 );
10874					associatedSetter.data( 'raw_price', productPrice );
10875					associatedSetter.data( 'raw_original_price', originalProductPrice );
10876					associatedSetter.data( 'price', productPrice );
10877					associatedSetter.data( 'original_price', originalProductPrice );
10878
10879					associatedElement = associatedSetter;
10880					if ( associatedElement.is( 'option' ) ) {
10881						associatedElement = associatedSetter.closest( 'select' );
10882					}
10883					isFilled = false;
10884					if ( associatedElement.is( '.tc-epo-field-product' ) ) {
10885						if ( associatedElement.is( 'select' ) ) {
10886							if ( associatedElement.val() !== '' ) {
10887								isFilled = true;
10888							}
10889						} else if ( ( associatedElement.is( ':checkbox' ) || associatedElement.is( ':radio' ) ) ) {
10890							if ( associatedElement.is( ':checked' ) ) {
10891								isFilled = true;
10892							}
10893						} else if ( associatedElement.val() !== '' ) {
10894							isFilled = true;
10895						}
10896					}
10897					tm_force_update_price(
10898						epoObject,
10899						associatedSetter
10900							.closest( '.tmcp-field-wrap' )
10901							.find( '.tc-price' )
10902							.not( tcAPI.associatedEpoSelector + ' .tc-price' ),
10903						productPrice,
10904						isFilled ? tm_set_price_totals( productPrice ) : associatedSetter.data( 'price-html' ),
10905						originalProductPrice,
10906						! isFilled
10907					);
10908
10909					qtyElement.trigger( 'change.cpf' );
10910
10911					return;
10912				}
10913
10914				if ( thisVariableProductContainer.length === 0 ) {
10915					if ( data && data.forced === 3 ) {
10916						$this.data( 'triggeredforced', 3 );
10917					}
10918					// parent_id is used for customization purposes.
10919					postData = {
10920						action: 'wc_epo_get_associated_product_html',
10921						product_id: value,
10922						parent_id: epoHolder.attr( 'data-product-id' ),
10923						mode: elementContainer.attr( 'data-mode' ),
10924						layout_mode: elementContainer.attr( 'data-product-layout-mode' ),
10925						uniqid: elementContainer.attr( 'data-uniqid' ),
10926						name: $this.attr( 'name' ),
10927						counter: counter,
10928						quantity_min: elementContainer.attr( 'data-quantity-min' ),
10929						quantity_max: elementContainer.attr( 'data-quantity-max' ),
10930						priced_individually: elementContainer.attr( 'data-priced-individually' ),
10931						discount: elementContainer.attr( 'data-discount' ),
10932						discount_type: elementContainer.attr( 'data-discount-type' ),
10933						discount_exclude_addons: elementContainer.attr( 'data-discount-exclude-
10933addons' ),
10934						show_image: elementContainer.attr( 'data-show-image' ),
10935						show_title: elementContainer.attr( 'data-show-title' ),
10936						show_title_link: elementContainer.attr( 'data-show-title-link' ),
10937						show_price: elementContainer.attr( 'data-show-price' ),
10938						show_description: elementContainer.attr( 'data-show-description' ),
10939						show_meta: elementContainer.attr( 'data-show-meta' ),
10940						disable_epo: elementContainer.attr( 'data-disable-epo' )
10941					};
10942
10943					elementContainer.block( { message: null, overlayCSS: { background: '#fff', opacity: 0.6 } } );
10944					$.ajax( {
10945						url: TMEPOJS.ajax_url,
10946						type: 'POST',
10947						data: postData,
10948						dataType: 'json',
10949						success: function( response ) {
10950							if ( response.result === 200 ) {
10951								thisVariableProductContainer = $( response.html );
10952								if ( hasProductContainerWrap ) {
10953									$this.closest( '.tmcp-field-wrap' ).find( '.tc-epo-element-product-container-wrap' ).empty().append( thisVariableProductContainer );
10954								} else {
10955									elementContainer.find( '.tc-epo-element-product-container-wrap' ).append( thisVariableProductContainer );
10956								}
10957								show_product_html( epoObject, main_product, thisVariableProductContainer, type, $this, currentCart, variableProductContainers, isTrigger, qtyalt );
10958								thisVariableProductContainer.find( tcAPI.associateQtySelector ).trigger( 'change' );
10959								jWindow.trigger( 'tc_apply_validation' );
10960							}
10961						},
10962						complete: function() {
10963							elementContainer.unblock();
10964						}
10965					} );
10966				} else {
10967					show_product_html( epoObject, main_product, thisVariableProductContainer, type, $this, currentCart, variableProductContainers, isTrigger, qtyalt );
10968					thisVariableProductContainer.find( tcAPI.associateQtySelector ).trigger( 'change' );
10969				}
10970			} );
10971
10972		jDocument
10973			.off( 'click.cpfqtybutton cpfqtybutton', '.cpf-type-product .single_add_to_cart_product' )
10974			.on( 'click.cpfqtybutton cpfqtybutton', '.cpf-type-product .single_add_to_cart_product', function() {
10975				var $this = $( this );
10976				var qtyalt = $this.closest( '.tm-quantity-alt' ).find( tcAPI.associateQtySelector );
10977				var isAdd = $this.is( '.alt' );
10978				var productContainerWraps = $this.closest( '.cpf-element' ).find( '.tc-epo-element-product-container-wrap' );
10979				var qtyMin;
10980				var qtyMax;
10981
10982				if ( $this.data( 'inittriggeredonce' ) ) {
10983					qtyMin = $.epoAPI.math.toInt( qtyalt.attr( 'data-min' ) );
10984					qtyMax = $.epoAPI.math.toInt( qtyalt.attr( 'data-max' ) );
10985					if ( isAdd ) {
10986						productContainerWraps.addClass( 'tc-active-product' );
10987						qtyalt.attr( 'min', qtyMin );
10988						if ( qtyMax ) {
10989							qtyalt.attr( 'max', qtyMax );
10990						}
10991						if ( qtyalt.val() === '0' ) {
10992							if ( qtyalt.attr( 'min' ) === '0' ) {
10993								qtyalt.val( 1 ).trigger( 'change' );
10994							} else {
10995								qtyalt.val( qtyalt.attr( 'min' ) ).trigger( 'change' );
10996							}
10997						}
10998						$this.removeClass( 'alt' ).text( $this.attr( 'data-remove' ) );
10999					} else {
11000						productContainerWraps.removeClass( 'tc-active-product' );
11001						qtyalt.val( 0 ).trigger( 'change' );
11002						qtyalt.closest( '.tm-quantity-alt' ).removeClass( 'tm-hidden' );
11003						$this.addClass( 'alt' ).text( $this.attr( 'data-add' ) );
11004					}
11005				}
11006
11007				$this.data( 'inittriggeredonce', 1 );
11008
11009				productContainerWraps.find( tcAPI.associatedEpoCart ).trigger( 'tm-epo-update' );
11010			} );
11011
11012		jDocument
11013			.off( 'change.cpfqtyalt input.cpfqtyalt', '.cpf-type-product ' + tcAPI.associateQtySelector )
11014			.on( 'change.cpfqtyalt input.cpfqtyalt', '.cpf-type-product ' + tcAPI.associateQtySelector, function() {
11015				var $this = $( this );
11016				var epoField = $this.closest( '.cpf-element' ).find( '.tm-epo-field' ).not( '.tc-epo-element-product-li-container .tm-epo-field' );
11017				var addButton = $this.closest( '.tm-quantity-alt' ).find( '.single_add_to_cart_product' );
11018				var checked = epoField.filter( ':checked' );
11019				var qty;
11020				var qtyMin;
11021				var qtyMax;
11022				var associatedEpoCart;
11023
11024				qtyMin = $.epoAPI.math.toInt( $this.attr( 'min' ) );
11025				qtyMax = $.epoAPI.math.toInt( $this.attr( 'max' ) );
11026
11027				if ( epoField.is( '.tc-epo-field-product-hidden' ) && epoField.is( ':checkbox' ) ) {
11028					if ( checked.length === 0 && $this.val() !== '0' ) {
11029						epoField.prop( 'checked', true ).trigger( 'change' );
11030						checked = epoField.filter( ':checked' );
11031					} else if ( $this.val() === '0' && checked.length ) {
11032						epoField.prop( 'checked', false ).trigger( 'change' );
11033					}
11034				}
11035
11036				if ( epoField.is( ':radio' ) ) {
11037					if ( checked.length === 0 ) {
11038						return;
11039					}
11040					qty = checked.closest( '.tmcp-field-wrap' ).find( 'input.tm-qty' ).not( '.tc-element-qty' );
11041				} else if ( epoField.is( ':checkbox' ) ) {
11042					if ( checked.length === 0 ) {
11043						return;
11044					}
11045					qty = $this.closest( '.tmcp-field-wrap' ).find( 'input.tm-qty' ).not( '.tc-element-qty' );
11046				} else {
11047					qty = epoField.closest( '.tmcp-field-wrap' ).find( 'input.tm-qty' ).not( '.tc-element-qty' );
11048				}
11049
11050				if ( qty.length === 0 ) {
11051					return;
11052				}
11053
11054				qty.attr( 'min', qtyMin );
11055				if ( qtyMax ) {
11056					qty.attr( 'max', qtyMax );
11057				}
11058				associatedEpoCart = $this.closest( '.tc-epo-element-product-container' ).find( tcAPI.associatedEpoCart );
11059				associatedEpoCart.trigger( 'tm-epo-update' );
11060
11061				qty.val( $this.val() );
11062
11063				if ( $.epoAPI.math.toFloat( $this.val() ) > 0 ) {
11064					associatedEpoCart.find( '.tm-epo-field.tcenabled' ).removeClass( 'ignore' );
11065					$this.removeClass( 'ignore' );
11066				} else {
11067					associatedEpoCart.find( '.tm-epo-field.tcenabled' ).addClass( 'ignore' );
11068					$this.addClass( 'ignore' );
11069				}
11070				epoField.trigger( 'change.cpfproduct', { forced: 2 } );
11071				if ( addButton.data( 'inittriggeredonce' ) ) {
11072					if ( $this.val() === '0' ) {
11073						addButton.removeClass( 'alt' );
11074					} else {
11075						addButton.addClass( 'alt' );
11076					}
11077				}
11078				addButton.trigger( 'cpfqtybutton' );
11079			} );
11080
11081		jDocument
11082			.off( 'click.cbsmel' )
11083			.on( 'click.cbsmel', '.tc-choice-button-selector', function( e ) {
11084				var $field = $( this ).closest( '.tmcp-field-wrap' ).find( '.tm-epo-field' );
11085				e.stopPropagation();
11086				if ( $field.length ) {
11087					$field.trigger( 'click' );
11088				}
11089			} );
11090
11091		// Global update event
11092		currentCart.off( 'tm-epo-update' ).on( 'tm-epo-update', function( event ) {
11093			var cart = $( this );
11094			var bundleid;
11095			var productPrice = false;
11096			var rawProductPrice = 0;
11097			var productRegularPrice = false;
11098			var rawProductRegularPrice = 0;
11099			var total = 0;
11100			var original_total = 0;
11101			var showTotal = false;
11102			var cartQty;
11103			var elementQty = 1;
11104			var priceOverrideMode;
11105			var perProductPricing = true;
11106			var floatingBoxData = [];
11107			var currentVariation;
11108			var cart_fee_options_total = 0;
11109			var cart_fee_options_original_total = 0;
11110			var _total;
11111			var _original_total;
11112			var late_total_price;
11113			var tc_totals_ob = {};
11114			var formatted_options_total;
11115			var formatted_options_original_total;
11116			var formatted_fees_total;
11117			var formatted_fees_original_total;
11118			var formatted_final_total;
11119			var formatted_final_original_total;
11120			var extraFee = 0;
11121			var raw_extraFee = 0;
11122			var product_total_price;
11123			var product_total_original_price;
11124			var calculateFinalProductPrice;
11125			var total_plus_fee;
11126			var original_total_plus_fee;
11127			var product_total_price_without_options;
11128			var unit_price;
11129			var unit_original_price;
11130			var formatted_unit_price;
11131			var formatted_unit_original_price;
11132			var html;
11133			var show_options_total = false;
11134			var show_vat_options_total = false;
11135			var show_fees_total = false;
11136			var formatted_extra_fee = '';
11137			var show_extra_fee = false;
11138			var show_final_total = false;
11139			var hide_native_price;
11140			var update_native_html;
11141			var _fprice;
11142			var _f_regular_price;
11143			var customerPriceFormat;
11144			var currentEpoObject;
11145			var raw_total;
11146			var raw__total;
11147			var raw_original_total;
11148			var raw__original_total;
11149			var raw_cart_fee_options_total;
11150			var raw_cart_fee_options_original_total;
11151			var raw_total_plus_fee;
11152			var raw_original_total_plus_fee;
11153			var raw_product_total_price_without_options;
11154			var raw_product_total_price;
11155			var raw_product_total_original_price;
11156			var fetch;
11157			var customer_price_format_wrap_start = '';
11158			var customer_price_format_wrap_end = '';
11159			var associatedSetter;
11160			var associatedPrice;
11161			var associatedRawPrice;
11162			var associatedOriginalPrice;
11163			var associatedRawOriginalPrice;
11164			var associatedFormattedPrice;
11165			var nativeProductPriceSelector;
11166			var elementsLength;
11167			var productFieldSyncVatTotal = 0;
11168			var productFieldSyncTotal = 0;
11169			var productFieldSyncOriginalTotal = 0;
11170			var productFieldSyncTotalTaxed = 0;
11171			var productFieldSyncOriginalTotalTaxed = 0;
11172			var totalProductField = 0;
11173			var originalTotalProductField = 0;
11174			var totalProductFieldTaxed = 0;
11175			var originalTotalProductFieldTaxed = 0;
11176			var _ftotal;
11177			var _foriginal_total;
11178			var totalsHolder_tc_totals_ob;
11179			var temp;
11180			var vat_options_total;
11181			var vat_options_total_plus_fee;
11182			var formatted_vat_options_total;
11183			var formatted_vat_options_total_plus_fee;
11184			var vat_total;
11185			var formatted_vat_total;
11186			var vat_product_base;
11187			var formatted_vat_product_base;
11188			var pricesIncludeTax;
11189			var dynamicCheck;
11190			var dynamicProductPrice = 0;
11191
11192			if ( event.epoObject ) {
11193				currentEpoObject = $.extend( true, {}, event.epoObject );
11194			} else {
11195				currentEpoObject = $.extend( true, {}, epoObject );
11196			}
11197
11198			if ( ! currentEpoObject ) {
11199				return;
11200			}
11201
11202			if ( currentEpoObject.noEpoUpdate ) {
11203				return;
11204			}
11205
11206			jWindow.trigger( 'tcEpoUpdateStart', {
11207				epo: currentEpoObject,
11208				alternativeCart: currentEpoObject,
11209				this_product_type: this_product_type,
11210				cart: cart,
11211				totalsHolder: totalsHolder,
11212				fetchOptionPrices: fetchOptionPrices,
11213				epoHolder: epoHolder
11214			} );
11215
11216			bundleid = $.epoAPI.applyFilter( 'tc_get_bundleid', cart.attr( 'data-
11216product_id' ), cart, currentEpoObject );
11217			priceOverrideMode = totalsHolder.attr( 'data-price-override' );
11218			cartQty = getCurrentQty( cart );
11219			currentVariation = getCurrentVariation( cart );
11220
11221			if ( currentEpoObject.associated_connect && currentEpoObject.associated_connect.length === 1 ) {
11222				cartQty = parseFloat(
11223					currentEpoObject.main_product
11224						.find( tcAPI.associateQtySelector )
11225						.not( tcAPI.associatedEpoSelector + ' ' + tcAPI.qtySelector )
11226						.last()
11227						.val()
11228				);
11229			}
11230
11231			event.stopImmediatePropagation();
11232
11233			productPrice = $.epoAPI.applyFilter( 'tcGetCurrentProductPrice', tm_calculate_product_price( totalsHolder, true ), currentCart, totalsHolder );
11234
11235			rawProductPrice = productPrice;
11236
11237			productRegularPrice = $.epoAPI.applyFilter( 'tcGetCurrentProductRegularPrice', tm_calculate_product_regular_price( totalsHolder, true ), currentCart, totalsHolder );
11238
11239			rawProductRegularPrice = productRegularPrice;
11240
11241			productPrice = $.epoAPI.applyFilter( 'tcCalculateCurrentProductPrice', productPrice, {
11242				epo: currentEpoObject,
11243				alternativeCart: alternativeCart,
11244				cart: cart,
11245				main_product: main_product
11246			} );
11247
11248			if ( ! Number.isFinite( cartQty ) || totalsHolder.attr( 'data-is-sold-individually' ) || getQtyElement( cart ).length === 0 ) {
11249				cartQty = 1;
11250			}
11251			if ( TMEPOJS.tm_epo_total_price_as_unit_price === 'yes' ) {
11252				cartQty = 1;
11253			}
11254
11255			// needed for inital math calculation
11256			totalsHolder_tc_totals_ob = {
11257				qty: cartQty,
11258				product_price: rawProductPrice,
11259				original_product_price: rawProductRegularPrice
11260			};
11261			totalsHolder.data( 'totalsHolder_tc_totals_ob', totalsHolder_tc_totals_ob );
11262
11263			if ( ! event.norules ) {
11264				tm_epo_rules( currentEpoObject, cart );
11265			} else if ( event.norules ) {
11266				if ( event.norules === 1 ) {
11267					tm_element_epo_rules( currentEpoObject, event.element );
11268				}
11269				$.tcepo.lateFieldsPrices[ epoEventId ] = [];
11270
11271				epoHolder
11272					.find( '.tm-epo-late-field' )
11273					.toArray()
11274					.forEach( function( setter ) {
11275						setter = $( setter );
11276						setter.data( 'price', 0 );
11277						$.tcepo.lateFieldsPrices[ epoEventId ].push( {
11278							setter: setter,
11279							price: setter.data( 'tm-price-for-late' ),
11280							original_price: setter.data( 'tm-original-price-for-late' ),
11281							bundleid: bundleid,
11282							pricetype: get_type( currentEpoObject, setter, 'price_type' )
11283						} );
11284					} );
11285			}
11286
11287			// Check for dynamic elements.
11288			dynamicCheck = epoHolder.find( '.tmcp-dynamic.dynamic-product-price:not(.tc-is-math-special, .tc-is-math-cumulative)' );
11289			if ( currentEpoObject.is_associated === false ) {
11290				dynamicCheck = dynamicCheck.not( tcAPI.associatedEpoSelector + ' ' + '.tmcp-dynamic.dynamic-product-price:not(.tc-is-math-special, .tc-is-math-cumulative)' );
11291			}
11292			dynamicCheck = dynamicCheck.filter( '.tcenabled' );
11293			if ( dynamicCheck.length > 0 ) {
11294				fetch = fetchOptionPrices( currentEpoObject, epoHolder, '.tmcp-dynamic.dynamic-product-price:not(.tc-is-math-special, .tc-is-math-cumulative)', 0, 0, floatingBoxData, showTotal, undefined, undefined, undefined, true, undefined, undefined, cartQty );
11295				productPrice = fetch.total;
11296				dynamicProductPrice = productPrice;
11297				rawProductRegularPrice = fetch.original_total;
11298				rawProductPrice = dynamicProductPrice;
11299				productRegularPrice = dynamicProductPrice;
11300				totalsHolderContainer.find( '.cpf-dynamic-product-price' ).val( dynamicProductPrice );
11301				totalsHolder_tc_totals_ob.dynamic_product_price = dynamicProductPrice;
11302				totalsHolder.data( 'totalsHolder_tc_totals_ob', totalsHolder_tc_totals_ob );
11303			}
11304
11305			if ( currentEpoObject.associated_connect && currentEpoObject.associated_connect.length === 1 ) {
11306				associatedSetter = currentEpoObject.associated_connect;
11307				if ( currentEpoObject.associated_connect.is( 'select' ) ) {
11308					associatedSetter = currentEpoObject.associated_connect.find( 'option:selected' );
11309				}
11310			}
11311
11312			// No reason to continue if the product price is invalid
11313			if ( productPrice === false ) {
11314				totalsHolder.data( 'tm-floating-box-data', [] );
11315				totalsHolder.empty();
11316				if ( currentEpoObject.associated_connect && currentEpoObject.associated_connect.length === 1 ) {
11317					tm_force_update_price(
11318						epoObject,
11319						associatedSetter
11320							.closest( '.tmcp-field-wrap' )
11321							.find( '.tc-price' )
11322							.not( tcAPI.associatedEpoSelector + ' .tc-price' ),
11323						0,
11324						'',
11325						0
11326					);
11327				}
11328				main_cart.trigger( 'tm-epo-short-update', {
11329					container: cartContainer
11330				} );
11331				return;
11332			}
11333
11334			elementQty = $.epoAPI.applyFilter( 'tcAlterElementQty', elementQty, {
11335				epo: currentEpoObject,
11336				alternativeCart: alternativeCart,
11337				currentCart: currentCart,
11338				main_product: main_product
11339			} );
11340
11341			if ( currentCart.data( 'per_product_pricing' ) !== undefined ) {
11342				perProductPricing = currentCart.data( 'per_product_pricing' );
11343			}
11344
11345			perProductPricing = $.epoAPI.applyFilter( 'tcCalculatePerProductPricing', perProductPricing, {
11346				epo: currentEpoObject,
11347				alternativeCart: alternativeCart,
11348				cart: cart,
11349				main_product: main_product
11350			} );
11351
11352			if ( main_epo_inside_form && TMEPOJS.tm_epo_totals_box_placement === 'woocommerce_before_add_to_cart_button' ) {
11353				if ( ( this_product_type === 'variable' || this_product_type === 'variable-subscription' ) && ! totalsHolder.data( 'moved_inside' ) ) {
11354					totalsHolder.data( 'moved_inside', 1 );
11355				}
11356			}
11357
11358			jWindow.trigger( 'tcEpoBeforeOptionPriceCalculation', {
11359				epo: currentEpoObject,
11360				alternativeCart: currentEpoObject,
11361				this_product_type: this_product_type,
11362				cart: cart,
11363				totalsHolder: totalsHolder,
11364				fetchOptionPrices: fetchOptionPrices,
11365				epoHolder: epoHolder,
11366				total: total,
11367				original_total: original_total,
11368				floatingBoxData: floatingBoxData,
11369				showTotal: showTotal,
11370				cart_fee_options_total: cart_fee_options_total,
11371				cart_fee_options_original_total: cart_fee_options_original_total
11372			} );
11373
11374			if ( ! currentEpoObject.associated_connect && ! event.noassociated ) {
11375				if ( TMEPOJS.tm_epo_global_product_element_quantity_sync === 'yes' && ! cart.is( $.tcAPI().associatedEpoCart ) ) {
11376					cart.find( $.tcAPI().associatedEpoCart ).filter( ':visible' ).toArray().forEac
11376h( function( acart ) {
11377						$( acart ).trigger( {
11378							type: 'tm-epo-update',
11379							noassociated: 1
11380						} );
11381					} );
11382				}
11383			}
11384
11385			fetch = fetchOptionPrices( currentEpoObject, epoHolder, '.tmcp-field:not(.tmcp-dynamic,.tc-epo-field-product, .tc-is-math-special, .tc-is-math-cumulative)', total, original_total, floatingBoxData, showTotal, undefined, undefined, undefined, undefined, undefined, undefined, cartQty );
11386			total = fetch.total;
11387			original_total = fetch.original_total;
11388			floatingBoxData = fetch.floatingBoxData;
11389			showTotal = fetch.showTotal;
11390			elementsLength = fetch.elementsLength;
11391
11392			fetch = fetchOptionPrices( currentEpoObject, epoHolder, '.tc-epo-field-product', productFieldSyncTotal, productFieldSyncOriginalTotal, floatingBoxData, showTotal, undefined, undefined, undefined, undefined, undefined, undefined, cartQty );
11393			productFieldSyncTotal = fetch.total;
11394			productFieldSyncOriginalTotal = fetch.original_total;
11395			productFieldSyncTotalTaxed = fetch.total_taxed;
11396			productFieldSyncOriginalTotalTaxed = fetch.original_total_taxed;
11397			productFieldSyncVatTotal = fetch.vat_total;
11398			floatingBoxData = fetch.floatingBoxData;
11399			showTotal = fetch.showTotal;
11400			elementsLength = elementsLength + fetch.elementsLength;
11401
11402			totalsHolder.data( 'tm-floating-box-data', floatingBoxData );
11403
11404			fetch = fetchOptionPrices( currentEpoObject, epoHolder, '.tmcp-fee-field', cart_fee_options_total, cart_fee_options_original_total, floatingBoxData, showTotal, false, true, undefined, undefined, undefined, undefined, cartQty );
11405			cart_fee_options_total = fetch.total;
11406			cart_fee_options_original_total = fetch.original_total;
11407			floatingBoxData = fetch.floatingBoxData;
11408			showTotal = fetch.showTotal;
11409			elementsLength = elementsLength + fetch.elementsLength;
11410
11411			jWindow.trigger( 'tcEpoAfterNormalOptionPriceCalculation', {
11412				epo: currentEpoObject,
11413				alternativeCart: currentEpoObject,
11414				this_product_type: this_product_type,
11415				cart: cart,
11416				totalsHolder: totalsHolder,
11417				fetchOptionPrices: fetchOptionPrices,
11418				epoHolder: epoHolder,
11419				total: total,
11420				original_total: original_total,
11421				floatingBoxData: floatingBoxData,
11422				showTotal: showTotal,
11423				cart_fee_options_total: cart_fee_options_total,
11424				cart_fee_options_original_total: cart_fee_options_original_total
11425			} );
11426
11427			// Original price + options price type requires this here.
11428			_total = total;
11429			_original_total = original_total;
11430
11431			late_total_price = add_late_fields_prices( currentEpoObject, parseFloat( productPrice ), parseFloat( rawProductRegularPrice ), parseFloat( _total + productFieldSyncTotal ), parseFloat( _original_total + productFieldSyncOriginalTotal ), bundleid, totalsHolder );
11432
11433			fetch = fetchOptionPrices( currentEpoObject, epoHolder, '.tmcp-field.tc-is-math-special:not(.tmcp-dynamic)', total, original_total, floatingBoxData, showTotal, undefined, undefined, undefined, true, undefined, undefined, cartQty );
11434			total = fetch.total;
11435			original_total = fetch.original_total;
11436			floatingBoxData = fetch.floatingBoxData;
11437			showTotal = fetch.showTotal;
11438			elementsLength = elementsLength + fetch.elementsLength;
11439
11440			_total = total;
11441			_original_total = original_total;
11442
11443			_total = _total + late_total_price.normal[ 0 ];
11444			_original_total = _original_total + late_total_price.normal[ 1 ];
11445
11446			cart_fee_options_total = cart_fee_options_total + late_total_price.fees[ 0 ];
11447			cart_fee_options_original_total = cart_fee_options_original_total + late_total_price.fees[ 1 ];
11448
11449			total = _total;
11450			original_total = _original_total;
11451			fetch = fetchOptionPrices( currentEpoObject, epoHolder, '.tmcp-field.tc-is-math-cumulative:not(.tmcp-dynamic)', total, original_total, floatingBoxData, showTotal, undefined, undefined, undefined, true, true, undefined, cartQty );
11452			total = fetch.total;
11453			original_total = fetch.original_total;
11454			floatingBoxData = fetch.floatingBoxData;
11455			showTotal = fetch.showTotal;
11456			elementsLength = elementsLength + fetch.elementsLength;
11457
11458			_total = total;
11459			_original_total = original_total;
11460
11461			// Check for dynamic elements.
11462			dynamicCheck = epoHolder.find( '.tmcp-dynamic.dynamic-product-price.tc-is-math-special' );
11463			if ( currentEpoObject.is_associated === false ) {
11464				dynamicCheck = dynamicCheck.not( tcAPI.associatedEpoSelector + ' ' + '.tmcp-dynamic.dynamic-product-price.tc-is-math-special' );
11465			}
11466			dynamicCheck = dynamicCheck.filter( '.tcenabled' );
11467			if ( dynamicCheck.length > 0 ) {
11468				fetch = fetchOptionPrices( currentEpoObject, epoHolder, '.tmcp-field.tmcp-dynamic.dynamic-product-price.tc-is-math-special', dynamicProductPrice + total, dynamicProductPrice + original_total, floatingBoxData, showTotal, undefined, undefined, undefined, true, undefined, undefined, cartQty );
11469				dynamicProductPrice = $.epoAPI.math.toFloat( fetch.total ) - $.epoAPI.math.toFloat( total );
11470				productPrice = dynamicProductPrice;
11471				rawProductRegularPrice = $.epoAPI.math.toFloat( fetch.original_total ) - $.epoAPI.math.toFloat( original_total );
11472				rawProductPrice = dynamicProductPrice;
11473				productRegularPrice = dynamicProductPrice;
11474				totalsHolderContainer.find( '.cpf-dynamic-product-price' ).val( dynamicProductPrice );
11475				totalsHolder_tc_totals_ob.dynamic_product_price = dynamicProductPrice;
11476				totalsHolder.data( 'totalsHolder_tc_totals_ob', totalsHolder_tc_totals_ob );
11477			}
11478
11479			dynamicCheck = epoHolder.find( '.tmcp-dynamic.dynamic-product-price.tc-is-math-cumulative' );
11480			if ( currentEpoObject.is_associated === false ) {
11481				dynamicCheck = dynamicCheck.not( tcAPI.associatedEpoSelector + ' ' + '.tmcp-dynamic.dynamic-product-price.tc-is-math-cumulative' );
11482			}
11483			dynamicCheck = dynamicCheck.filter( '.tcenabled' );
11484			if ( dynamicCheck.length > 0 ) {
11485				fetch = fetchOptionPrices( currentEpoObject, epoHolder, '.tmcp-field.tmcp-dynamic.dynamic-product-price.tc-is-math-cumulative', dynamicProductPrice + total, dynamicProductPrice + original_total, floatingBoxData, showTotal, undefined, undefined, undefined, true, undefined, undefined, cartQty );
11486				dynamicProductPrice = $.epoAPI.math.toFloat( fetch.total ) - $.epoAPI.math.toFloat( total );
11487				productPrice = dynamicProductPrice;
11488				rawProductRegularPrice = $.epoAPI.math.toFloat( fetch.original_total ) - $.epoAPI.math.toFloat( original_total );
11489				rawProductPrice = dynamicProductPrice;
11490				productRegularPrice = dynamicProductPrice;
11491				totalsHolderContainer.find( '.cpf-dynamic-product-price' ).val( dynamicProductPrice );
11492				totalsHolder_tc_totals_ob.dynamic_product_price = dynamicProductPrice;
11493				totalsHolder.data( 'totalsHolder_tc_totals_ob', totalsHolder_tc_totals_ob );
11494			}
11495
11496			// Check if there are any dynamic product price elements
11497			dynamicCheck = epoHolder.find( '.tmcp-dynamic.dynamic-product-price' );
11498			if ( currentEpoObject.is_associated === false ) {
11499				dynamicCheck = dynamicCheck.not( tcAPI.associatedEpoSelector + ' ' + '.tmcp-dynamic.dynamic-product-price' );
11500			}
11501			dynamicCheck = dynamicCheck.filter( '.tcenabled' );
11502			if ( ! dynamicCheck.length > 0 ) {
11503				totalsHolderContainer.find( '.cpf-dynamic-product-price' ).val( '' );
11504			}
11505
11506			// Dynamic Calculation
11507			dynamicProductPrice = 0;
11508			dynamicCheck = epoHolder.find( '.tmcp-dynamic.calculation:not(.tc-is-math-special, .tc-is-math-cumulative)' );
11509			if ( currentEpoObject.is_associated === false ) {
11510				dynamicCheck = dynamicCheck.not( tcAPI.associatedEpoSelector + ' ' + '.tmcp-dynamic.calculation:not(.tc-is-math-special, .tc-is-math-cumulative)' );
11511			}
11512			dynamicCheck = dynamicCheck.filter( '.tcenabled' );
11513			if ( dynamicCheck.length > 0 ) {
11514				dynamicCheck.toArray().forEach( function( setter ) {
11515					var f;
11516					var ulWrap;
11517					var setterVal;
11518					setter = $( setter );
11519					ulWrap = setter.closest( '.tmcp-ul-wrap' );
11520					f = fetchOptionPrices( epoObject, ulWrap, '.tmcp-dynamic.calculation:not(.tc-is-math-special, .tc-is-math-cumulative)', dynamicProductPrice, dynamicProductPrice, [], true, true, undefined, undefined, undefined, true, undefined, undefined, cartQty );
11521					setterVal = f.total;
11522					if ( setter.is( '.result-as-price' ) ) {
11523						setterVal = tm_set_price_totals( setterVal, totalsHolder, true );
11524					}
11525					ulWrap.find( '.tc-result' ).html( setterVal );
11526				} );
11527			}
11528
11529			dynamicCheck = epoHolder.find( '.tmcp-dynamic.calculation.tc-is-math-special' );
11530			if ( currentEpoObject.is_associated === false ) {
11531				dynamicCheck = dynamicCheck.not( tcAPI.associatedEpoSelector + ' ' + '.tmcp-dynamic.calculation.tc-is-math-special' );
11532			}
11533			dynamicCheck = dynamicCheck.filter( '.tcenabled' );
11534			if ( dynamicCheck.length > 0 ) {
11535				dynamicCheck.toArray().forEach( function( setter ) {
11536					var f;
11537					var ulWrap;
11538					var setterVal;
11539					setter = $( setter );
11540					ulWrap = setter.closest( '.tmcp-ul-wrap' );
11541					f = fetchOptionPrices( epoObject, ulWrap, '.tmcp-field.tmcp-dynamic.calculation.tc-is-math-special', dynamicProductPrice + total, dynamicProductPrice + original_total, [], true, true, undefined, undefined, true );
11542					setterVal = $.epoAPI.math.toFloat( f.total ) - $.epoAPI.math.toFloat( total );
11543					if ( setter.is( '.result-as-price' ) ) {
11544						setterVal = tm_set_price_totals( setterVal, totalsHolder, true );
11545					}
11546					ulWrap.find( '.tc-result' ).html( setterVal );
11547				} );
11548			}
11549
11550			dynamicCheck = epoHolder.find( '.tmcp-dynamic.calculation.tc-is-math-cumulative' );
11551			if ( currentEpoObject.is_associated === false ) {
11552				dynamicCheck = dynamicCheck.not( tcAPI.associatedEpoSelector + ' ' + '.tmcp-dynamic.calculation.tc-is-math-cumulative' );
11553			}
11554			dynamicCheck = dynamicCheck.filter( '.tcenabled' );
11555			if ( dynamicCheck.length > 0 ) {
11556				dynamicCheck.toArray().forEach( function( setter ) {
11557					var f;
11558					var ulWrap;
11559					var setterVal;
11560					setter = $( setter );
11561					ulWrap = setter.closest( '.tmcp-ul-wrap' );
11562					f = fetchOptionPrices( epoObject, ulWrap, '.tmcp-field.tmcp-dynamic.calculation.tc-is-math-cumulative', dynamicProductPrice + total, dynamicProductPrice + original_total, [], true, true, undefined, undefined, true, undefined, undefined, undefined, cartQty );
11563					setterVal = $.epoAPI.math.toFloat( f.total ) - $.epoAPI.math.toFloat( total );
11564					if ( setter.is( '.result-as-price' ) ) {
11565						setterVal = tm_set_price_totals( setterVal, totalsHolder, true );
11566					}
11567					ulWrap.find( '.tc-result' ).html( setterVal );
11568				} );
11569			}
11570
11571			// Dynamic Weight
11572			dynamicProductPrice = 0;
11573			dynamicCheck = epoHolder.find( '.tmcp-dynamic.change-product-weight:not(.tc-is-math-special, .tc-is-math-cumulative)' );
11574			if ( currentEpoObject.is_associated === false ) {
11575				dynamicCheck = dynamicCheck.not( tcAPI.associatedEpoSelector + ' ' + '.tmcp-dynamic.change-product-weight:not(.tc-is-math-special, .tc-is-math-cumulative)' );
11576			}
11577			dynamicCheck = dynamicCheck.filter( '.tcenabled' );
11578			if ( dynamicCheck.length > 0 ) {
11579				dynamicCheck.toArray().forEach( function( setter ) {
11580					var f;
11581					var ulWrap;
11582					setter = $( setter );
11583					ulWrap = setter.closest( '.tmcp-ul-wrap' );
11584					f = fetchOptionPrices( epoObject, ulWrap, '.tmcp-dynamic.change-product-weight:not(.tc-is-math-special, .tc-is-math-cumulative)', dynamicProductPrice, dynamicProductPrice, [], true, true, undefined, undefined, undefined, undefined, undefined, undefined, cartQty );
11585					ulWrap.find( '.tc-result' ).html( f.total );
11586				} );
11587			}
11588
11589			dynamicCheck = epoHolder.find( '.tmcp-dynamic.change-product-weight.tc-is-math-special' );
11590			if ( currentEpoObject.is_associated === false ) {
11591				dynamicCheck = dynamicCheck.not( tcAPI.associatedEpoSelector + ' ' + '.tmcp-dynamic.change-product-weight.tc-is-math-special' );
11592			}
11593			dynamicCheck = dynamicCheck.filter( '.tcenabled' );
11594			if ( dynamicCheck.length > 0 ) {
11595				dynamicCheck.toArray().forEach( function( setter ) {
11596					var f;
11597					var ulWrap;
11598					setter = $( setter );
11599					ulWrap = setter.closest( '.tmcp-ul-wrap' );
11600					f = fetchOptionPrices( epoObject, ulWrap, '.tmcp-field.tmcp-dynamic.change-product-weight.tc-is-math-special', dynamicProductPrice + total, dynamicProductPrice + original_total, [], true, true, undefined, undefined, true, undefined, undefined, undefined, cartQty );
11601					ulWrap.find( '.tc-result' ).html( $.epoAPI.math.toFloat( f.total ) - $.epoAPI.math.toFloat( total ) );
11602				} );
11603			}
11604
11605			dynamicCheck = epoHolder.find( '.tmcp-dynamic.change-product-weight.tc-is-math-cumulative' );
11606			if ( currentEpoObject.is_associated === false ) {
11607				dynamicCheck = dynamicCheck.not( tcAPI.associatedEpoSelector + ' ' + '.tmcp-dynamic.change-product-weight.tc-is-math-cumulative' );
11608			}
11609			dynamicCheck = dynamicCheck.filter( '.tcenabled' );
11610			if ( dynamicCheck.length > 0 ) {
11611				dynamicCheck.toArray().forEach( function( setter ) {
11612					var f;
11613					var ulWrap;
11614					setter = $( setter );
11615					ulWrap = setter.closest( '.tmcp-ul-wrap' );
11616					f = fetchOptionPrices( epoObject, ulWrap, '.tmcp-field.tmcp-dynamic.change-product-weight.tc-is-math-cumulative', dynamicProductPrice + total, dynamicProductPrice + original_total, [], true, true, undefined, undefined, true, undefined, undefined, undefined, cartQty );
11617					ulWrap.find( '.tc-result' ).html( $.epoAPI.math.toFloat( f.total ) - $.epoAPI.math.toFloat( total ) );
11618				} );
11619			}
11620
11621			// Check for dynamic override elements
11622			dynamicProductPrice = 0;
11623			dynamicCheck = epoHolder.find( '.tmcp-dynamic.override-product-price:not(.tc-is-math-special, .tc-is-math-cumulative)' );
11624			if ( currentEpoObject.is_associated === false ) {
11625				dynamicCheck = dynamicCheck.not( tcAPI.associatedEpoSelector + ' ' + '.tmcp-dynamic.override-product-price:not(.tc-is-math-special, .tc-is-math-cumulative)' );
11626			}
11627			dynamicCheck = dynamicCheck.filter( '.tcenabled' );
11628			if ( dynamicCheck.length > 0 ) {
11629				fetch = fetchOptionPrices( currentEpoObject, epoHolder, '.tmcp-dynamic.override-product-price:not(.tc-is-math-special, .tc-is-math-cumulative)', dynamicProductPrice, dynamicProductPrice, floatingBoxData, showTotal, undefined, undefined, undefined, undefined, undefined, undefined, cartQty );
11630				dynamicProductPrice = fetch.total;
11631				productPrice = dynamicProductPrice;
11632				rawProductRegularPrice = fetch.original_total;
11633				rawProductPrice = dynamicProductPrice;
11634				productRegularPrice = dynamicProductPrice;
11635				_total = dynamicProductPrice;
11636				_original_total = dynamicProductPrice;
11637				totalsHolderContainer.find( '.cpf-override-product-price' ).val( dynamicProductPrice );
11638				totalsHolder_tc_totals_ob.override_product_price = dynamicProductPrice;
11639				totalsHolder.data( 'totalsHolder_tc_totals_ob', totalsHolder_tc_totals_ob );
11640			}
11641
11642			dynamicCheck = epoHolder.find( '.tmcp-dynamic.override-product-price.tc-is-math-special' );
11643			if ( currentEpoObject.is_associated === false ) {
11644				dynamicCheck = dynamicCheck.not( tcAPI.associatedEpoSelector + ' ' + '.tmcp-dynamic.override-product-price.tc-is-math-special' );
11645			}
11646			dynamicCheck = dynamicCheck.filter( '.tcenabled' );
11647			if ( dynamicCheck.length > 0 ) {
11648				fetch = fetchOptionPrices( currentEpoObject, epoHolder, '.tmcp-field.tmcp-dynamic.override-product-price.tc-is-math-special', dynamicProductPrice + total, dynamicProductPrice + original_total, floatingBoxData, showTotal, undefined, undefined, undefined, true, undefined, undefined, cartQty );
11649				dynamicProductPrice = $.epoAPI.math.toFloat( fetch.total ) - $.epoAPI.math.toFloat( total );
11650				productPrice = dynamicProductPrice;
11651				rawProductRegularPrice = $.epoAPI.math.toFloat( fetch.original_total ) - $.epoAPI.math.toFloat( original_total );
11652				rawProductPrice = dynamicProductPrice;
11653				productRegularPrice = dynamicProductPrice;
11654				_total = dynamicProductPrice;
11655				_original_total = dynamicProductPrice;
11656				totalsHolderContainer.find( '.cpf-override-product-price' ).val( dynamicProductPrice );
11657				totalsHolder_tc_totals_ob.override_product_price = dynamicProductPrice;
11658				totalsHolder.data( 'totalsHolder_tc_totals_ob', totalsHolder_tc_totals_ob );
11659			}
11660
11661			dynamicCheck = epoHolder.find( '.tmcp-dynamic.override-product-price.tc-is-math-cumulative' );
11662			if ( currentEpoObject.is_associated === false ) {
11663				dynamicCheck = dynamicCheck.not( tcAPI.associatedEpoSelector + ' ' + '.tmcp-dynamic.override-product-price.tc-is-math-cumulative' );
11664			}
11665			dynamicCheck = dynamicCheck.filter( '.tcenabled' );
11666			if ( dynamicCheck.length > 0 ) {
11667				fetch = fetchOptionPrices( currentEpoObject, epoHolder, '.tmcp-field.tmcp-dynamic.override-product-price.tc-is-math-cumulative', dynamicProductPrice + total, dynamicProductPrice + original_total, floatingBoxData, showTotal, undefined, undefined, undefined, true, undefined, undefined, cartQty );
11668				dynamicProductPrice = $.epoAPI.math.toFloat( fetch.total ) - $.epoAPI.math.toFloat( total );
11669				productPrice = dynamicProductPrice;
11670				rawProductRegularPrice = $.epoAPI.math.toFloat( fetch.original_total ) - $.epoAPI.math.toFloat( original_total );
11671				rawProductPrice = dynamicProductPrice;
11672				productRegularPrice = dynamicProductPrice;
11673				_total = dynamicProductPrice;
11674				_original_total = dynamicProductPrice;
11675				totalsHolderContainer.find( '.cpf-override-product-price' ).val( dynamicProductPrice );
11676				totalsHolder_tc_totals_ob.override_product_price = dynamicProductPrice;
11677				totalsHolder.data( 'totalsHolder_tc_totals_ob', totalsHolder_tc_totals_ob );
11678			}
11679
11680			// Check if there are any dynamic override elements
11681			dynamicCheck = epoHolder.find( '.tmcp-dynamic.override-product-price' );
11682			if ( currentEpoObject.is_associated === false ) {
11683				dynamicCheck = dynamicCheck.not( tcAPI.associatedEpoSelector + ' ' + '.tmcp-dynamic.override-product-price' );
11684			}
11685			dynamicCheck = dynamicCheck.filter( '.tcenabled' );
11686			if ( ! dynamicCheck.length > 0 ) {
11687				totalsHolderContainer.find( '.cpf-override-product-price' ).val( '' );
11688			} else {
11689				_total = 0;
11690				_original_total = 0;
11691			}
11692
11693			jWindow.trigger( 'tcEpoAfterOptionPriceCalculation', {
11694				epo: currentEpoObject,
11695				alternativeCart: currentEpoObject,
11696				this_product_type: this_product_type,
11697				cart: cart,
11698				totalsHolder: totalsHolder,
11699				fetchOptionPrices: fetchOptionPrices,
11700				epoHolder: epoHolder,
11701				total: total,
11702				original_total: original_total,
11703				floatingBoxData: floatingBoxData,
11704				showTotal: showTotal,
11705				cart_fee_options_total: cart_fee_options_total,
11706				cart_fee_options_original_total: cart_fee_options_original_total
11707			} );
11708
11709			setTimeout( function() {
11710				epoHolder.find( 'select.tm-epo-field' ).trigger( 'tm-select-price-update-html-all' );
11711			}, 1 );
11712
11713			$.tcepo.oneOptionIsSelected[ epoEventId ] = showTotal;
11714			currentEpoObject = addShowHidetoEpoObject( currentEpoObject, epoEventId, elementsLength );
11715			tm_show_hide_add_to_cart_button( main_product, currentEpoObject );
11716
11717			if ( cart_fee_options_total > 0 ) {
11718				showTotal = true;
11719			}
11720
11721			if ( alternativeCart && ! perProductPricing ) {
11722				showTotal = false;
11723			}
11724
11725			if (
11726				finalTotalBoxMode === 'enable' ||
11727				finalTotalBoxMode === 'hideifoptionsiszero' ||
11728				finalTotalBoxMode === 'hideiftotaliszero'
11729			) {
11730				showTotal = true;
11731			}
11732
11733			if ( cartQty > 1 ) {
11734				showTotal = true;
11735			}
11736			if ( ( this_product_type === 'variable' || this_product_type === 'variable-subscription' ) && ! $.epoAPI.math.toFloat( currentVariation ) ) {
11737				showTotal = false;
11738			}
11739
11740			if ( finalTotalBoxMode === 'disable' ) {
11741				showTotal = false;
11742			}
11743			if ( TMEPOJS.tm_epo_change_variation_price === 'yes' || TMEPOJS.tm_epo_change_original_price === 'yes' ) {
11744				showTotal = true;
11745			}
11746
11747			if ( currentEpoObject.is_associated && ! perProductPricing ) {
11748				showTotal = false;
11749			}
11750
11751			product_total_price = parseFloat( productPrice * cartQty );
11752
11753			if ( TMEPOJS.extraFee ) {
11754				extraFee = parseFloat( TMEPOJS.extraFee );
11755				if ( ! Number.isFinite( extraFee ) ) {
11756					extraFee = 0;
11757				}
11758			}
11759
11760			calculateFinalProductPrice = $.epoAPI.applyFilter( 'tcCalculateFinalProductPrice', false, {
11761				alternativeCart: alternativeCart,
11762				product_price: productPrice,
11763				product_total_price: product_total_price,
11764				v_product_price: rawProductPrice,
11765				tm_set_tax_price: tm_set_tax_price,
11766				main_product: main_product,
11767				totalsHolder: totalsHolder,
11768				cartQty: cartQty
11769			} );
11770
11771			if (
11772				calculateFinalProductPrice !== false &&
11773				typeof calculateFinalProductPrice === 'object' &&
11774				Object.prototype.hasOwnProperty.call( calculateFinalProductPrice, 'productPrice' ) &&
11775				Object.prototype.hasOwnProperty.call( calculateFinalProductPrice, 'productTotalPrice' )
11776			) {
11777				productPrice = calculateFinalProductPrice.productPrice;
11778				product_total_price = calculateFinalProductPrice.productTotalPrice;
11779			}
11780
11781			_total = $.epoAPI.applyFilter( 'tc_adjust_options_price_per_unit', _total, product_total_price );
11782			total = parseFloat( _total * cartQty * elementQty );
11783			total = $.epoAPI.applyFilter( 'tc_adjust_options_total_price', total, cartQty, elementQty, _total, totalsHolder );
11784			if ( TMEPOJS.tm_epo_global_product_element_quantity_sync === 'no' ) {
11785				totalProductField = parseFloat( productFieldSyncTotal );
11786				totalProductFieldTaxed = parseFloat( productFieldSyncTotalTaxed );
11787			} else {
11788				totalProductField = parseFloat( productFieldSyncTotal * cartQty * elementQty );
11789				totalProductFieldTaxed = parseFloat( productFieldSyncTotalTaxed * cartQty * elementQty );
11790			}
11791			totalProductField = $.epoAPI.applyFilter( 'tc_adjust_options_productfield_total_price', totalProductField, cartQty, elementQty, _total, totalsHolder );
11792			totalProductFieldTaxed = $.epoAPI.applyFilter( 'tc_adjust_options_productfield_total_price_taxed', totalProductFieldTaxed, cartQty, elementQty, _total, totalsHolder );
11793
11794			_original_total = $.epoAPI.applyFilter( 'tc_adjust_options_price_per_unit', _original_total, product_total_price );
11795			original_total = parseFloat( _original_total * cartQty * elementQty );
11796			original_total = $.epoAPI.applyFilter( 'tc_adjust_options_original_total_price', original_total, cartQty, elementQty, _original_total, totalsHolder );
11797			if ( TMEPOJS.tm_epo_global_product_element_quantity_sync === 'no' ) {
11798				originalTotalProductField = parseFloat( productFieldSyncOriginalTotal );
11799				originalTotalProductFieldTaxed = parseFloat( productFieldSyncOriginalTotalTaxed );
11800			} else {
11801				originalTotalProductField = parseFloat( productFieldSyncOriginalTotal * cartQty * elementQty );
11802				originalTotalProductFieldTaxed = parseFloat( productFieldSyncOriginalTotalTaxed * cartQty * elementQty );
11803			}
11804			originalTotalProductField = $.epoAPI.applyFilter( 'tc_adjust_options_productfield_original_total_price', originalTotalProductField, cartQty, elementQty, _original_total, totalsHolder );
11805			originalTotalProductFieldTaxed = $.epoAPI.applyFilter( 'tc_adjust_options_productfield_original_total_price_taxed', originalTotalProductFieldTaxed, cartQty, elementQty, _original_total, totalsHolder );
11806
11807			if ( priceOverrideMode === '1' && parseFloat( total ) > 0 ) {
11808				productPrice = 0;
11809				rawProductPrice = 0;
11810				product_total_price = 0;
11811			}
11812
11813			product_total_price = $.epoAPI.applyFilter( 'tc_adjust_product_total_price_without_options', product_total_price );
11814
11815			total = $.epoAPI.applyFilter( 'tcAdjustTotal', total, {
11816				epo: currentEpoObject,
11817				totalsHolder: totalsHolder,
11818				cart: cart,
11819				main_product: main_product
11820			} );
11821			totalProductField = $.epoAPI.applyFilter( 'tcAdjustProductFieldTotal', totalProductField, {
11822				epo: currentEpoObject,
11823				totalsHolder: totalsHolder,
11824				cart: cart,
11825				main_product: main_product
11826			} );
11827			totalProductFieldTaxed = $.epoAPI.applyFilter( 'tcAdjustProductFieldTotalTaxed', totalProductFieldTaxed, {
11828				epo: currentEpoObject,
11829				totalsHolder: totalsHolder,
11830				cart: cart,
11831				main_product: main_product
11832			} );
11833			original_total = $.epoAPI.applyFilter( 'tcAdjustOriginalTotal', original_total, {
11834				epo: currentEpoObject,
11835				totalsHolder: totalsHolder,
11836				cart: cart,
11837				main_product: main_product
11838			} );
11839			originalTotalProductField = $.epoAPI.applyFilter( 'tcAdjustProductFieldOriginalTotal', originalTotalProductField, {
11840				epo: currentEpoObject,
11841				totalsHolder: totalsHolder,
11842				cart: cart,
11843				main_product: main_product
11844			} );
11845			originalTotalProductFieldTaxed = $.epoAPI.applyFilter( 'tcAdjustProductFieldOriginalTotalTaxed', originalTotalProductFieldTaxed, {
11846				epo: currentEpoObject,
11847				totalsHolder: totalsHolder,
11848				cart: cart,
11849				main_product: main_product
11850			} );
11851
11852			total = parseFloat( $.epoAPI.applyFilter( 'tc_adjust_total', total, totalsHolder ) );
11853			cart_fee_options_total = parseFloat( $.epoAPI.applyFilter( 'tc_adjust_totals_fee', cart_fee_options_total, totalsHolder ) );
11854			original_total = parseFloat( $.epoAPI.applyFilter( 'tc_adjust_original_total', original_total, totalsHolder ) );
11855			cart_fee_options_original_total = parseFloat( $.epoAPI.applyFilter( 'tc_adjust_original_total_fee', cart_fee_options_original_total, totalsHolder ) );
11856			raw_extraFee = extraFee;
11857
11858			total_plus_fee = total + cart_fee_options_total;
11859			original_total_plus_fee = original_total + cart_fee_options_original_total;
11860
11861			raw_total = total;
11862			raw__total = _total;
11863
11864			raw_cart_fee_options_total = cart_fee_options_total;
11865			raw_total_plus_fee = total_plus_fee;
11866
11867			raw_original_total = original_total;
11868			raw__original_total = _original_total;
11869
11870			raw_cart_fee_options_original_total = cart_fee_options_original_total;
11871			raw_original_total_plus_fee = original_total_plus_fee;
11872
11873			raw_product_total_price_without_options = product_total_price;
11874			raw_product_total_price = parseFloat( product_total_price + total_plus_fee + raw_extraFee );
11875			raw_product_total_original_price = parseFloat( rawProductRegularPrice + original_total_plus_fee + raw_extraFee );
11876
11877			productPrice = tm_set_tax_price( productPrice, totalsHolder, undefined, undefined, undefined, undefined, true );
11878			productRegularPrice = tm_set_tax_price( productRegularPrice, totalsHolder, undefined, undefined, undefined, undefined, true );
11879			product_total_price = tm_set_tax_price( product_total_price, totalsHolder, undefined, undefined, undefined, undefined, true );
11880
11881			total = tm_set_tax_price( total, totalsHolder, undefined, undefined, undefined, undefined, true );
11882			_total = tm_set_tax_price( _total, totalsHolder, undefined, undefined, undefined, undefined, true );
11883
11884			total_plus_fee = parseFloat( cart_fee_options_total ) + parseFloat( total );
11885
11886			original_total = tm_set_tax_price( original_total, totalsHolder, undefined, undefined, undefined, undefined, true );
11887			_original_total = tm_set_tax_price( _original_total, totalsHolder, undefined, undefined, undefined, undefined, true );
11888
11889			original_total_plus_fee = parseFloat( cart_fee_options_original_total ) + parseFloat( original_total );
11890
11891			extraFee = tm_set_tax_price( extraFee, totalsHolder, undefined, undefined, undefined, undefined, true );
11892
11893			// Calculate product price
11894			product_total_price_without_options = product_total_price;
11895			product_total_price = $.epoAPI.applyFilter( 'tc_adjust_product_total_price', parseFloat( product_total_price + total_plus_fee + extraFee ), product_total_price_without_options, total_plus_fee, extraFee, total, cart_fee_options_total, totalsHolder );
11896			product_total_original_price = $.epoAPI.applyFilter( 'tc_adjust_product_total_original_price', parseFloat( product_total_price_without_options + original_total_plus_fee + extraFee ), product_total_price_without_options, original_total_plus_fee, extraFee, original_total, cart_fee_options_original_total, totalsHolder );
11897
11898			// Calculate vat options total
11899			pricesIncludeTax = totalsHolder.attr( 'data-prices-include-tax' ) || TMEPOJS.prices_include_tax;
11900			if ( pricesIncludeTax === '1' ) {
11901				vat_options_total = productFieldSyncVatTotal + parseFloat( calculateTaxAmount( total, totalsHolder ) );
11902				vat_options_total_plus_fee = productFieldSyncVatTotal + parseFloat( calculateTaxAmount( total_plus_fee, totalsHolder ) );
11903				vat_total = productFieldSyncVatTotal + parseFloat( calculateTaxAmount( product_total_price, totalsHolder ) );
11904				vat_product_base = parseFloat( calculateTaxAmount( product_total_price_without_options, totalsHolder ) );
11905			} else {
11906				vat_options_total = productFieldSyncVatTotal + parseFloat( total - raw_total );
11907				vat_options_total_plus_fee = productFieldSyncVatTotal + parseFloat( total_plus_fee - raw_total_plus_fee );
11908				vat_total = productFieldSyncVatTotal + parseFloat( product_total_price - raw_product_total_price );
11909				vat_product_base = parseFloat( product_total_price_without_options - raw_product_total_price_without_options );
11910			}
11911
11912			raw_total = raw_total + totalProductField;
11913			raw__total = raw__total + totalProductField;
11914			raw_total_plus_fee = raw_total_plus_fee + totalProductField;
11915			raw_original_total = raw_original_total + originalTotalProductField;
11916			raw__original_total = raw__original_total + originalTotalProductField;
11917			raw_original_total_plus_fee = raw_original_total_plus_fee + originalTotalProductField;
11918			raw_product_total_price = raw_product_total_price + totalProductField;
11919			raw_product_total_original_price = raw_product_total_original_price + originalTotalProductField;
11920			total = total + totalProductFieldTaxed;
11921			_total = _total + totalProductFieldTaxed;
11922			total_plus_fee = total_plus_fee + totalProductFieldTaxed;
11923			original_total = original_total + originalTotalProductFieldTaxed;
11924			_original_total = _original_total + originalTotalProductFieldTaxed;
11925			original_total_plus_fee = original_total_plus_fee + originalTotalProductFieldTaxed;
11926			product_total_price = product_total_price + totalProductFieldTaxed;
11927			product_total_original_price = product_total_original_price + originalTotalProductFieldTaxed;
11928
11929			// Calculate unit price
11930			unit_price = parseFloat( productPrice + parseFloat( _total ) );
11931			unit_original_price = parseFloat( productPrice + parseFloat( _original_total ) );
11932			if ( TMEPOJS.tm_epo_fees_on_unit_price === 'yes' ) {
11933				unit_price = parseFloat( productPrice + parseFloat( _total ) + parseFloat( parseFloat( cart_fee_options_total ) / cartQty ) );
11934				unit_original_price = parseFloat( productPrice + parseFloat( _original_total ) + parseFloat( parseFloat( cart_fee_options_original_total ) / cartQty ) );
11935			}
11936
11937			// Format unit price
11938			formatted_unit_price = tm_set_price_totals( unit_price, totalsHolder, true );
11939			formatted_unit_original_price = tm_set_price_totals( unit_original_price, totalsHolder, true );
11940
11941			// Format extra fee
11942			if ( extraFee ) {
11943				show_extra_fee = true;
11944				formatted_extra_fee = tm_set_price_totals( extraFee, totalsHolder, true );
11945			}
11946
11947			// Format final total
11948			formatted_final_total = tm_set_price_totals( product_total_price, totalsHolder, true );
11949			formatted_final_original_total = tm_set_price_totals( product_total_original_price, totalsHolder, true );
11950
11951			// Format options total
11952			formatted_options_total = tm_set_price_totals( total, totalsHolder, true );
11953
11954			// Format fees total
11955			formatted_fees_total = tm_set_price_totals( cart_fee_options_total, totalsHolder, true );
11956
11957			// Format options original total
11958			formatted_options_original_total = tm_set_price_totals( original_total, totalsHolder, true );
11959
11960			// Format fees original total
11961			formatted_fees_original_total = tm_set_price_totals( cart_fee_options_original_total, totalsHolder, true );
11962
11963			// Format vat options total
11964			formatted_vat_options_total = tm_set_price_totals( vat_options_total );
11965			formatted_vat_options_total_plus_fee = tm_set_price_totals( vat_options_total_plus_fee );
11966			formatted_vat_total = tm_set_price_totals( vat_total );
11967			formatted_vat_product_base = tm_set_price_totals( vat_product_base );
11968
11969			// Backwards compatibility
11970			formatted_unit_price = $.epoAPI.applyFilter( 'tc_adjust_formatted_unit_price', formatted_unit_price, productPrice, _total, cart_fee_options_total, cartQty );
11971			formatted_options_total = $.epoAPI.applyFilter( 'tc_adjust_formatted_options_total', formatted_options_total, total, _total, cartQty );
11972			formatted_fees_total = $.epoAPI.applyFilter( 'tc_adjust_formatted_fees_total', formatted_fees_total, cart_fee_options_total );
11973			formatted_final_total = $.epoAPI.applyFilter( 'tc_adjust_formatted_final_total', formatted_final_total, product_total_price, product_total_price_without_options, total_plus_fee, extraFee, cartQty );
11974
11975			formatted_unit_price = $.epoAPI.applyFilter( 'tcAdjustFormattedUnitPrice', formatted_unit_price, {
11976				epo: currentEpoObject,
11977				totalsHolder: totalsHolder,
11978				event: event,
11979				unit_price: unit_price,
11980				productPrice: productPrice,
11981				_total: _total,
11982				total_plcart_fee_options_totals_fee: cart_fee_options_total,
11983				cartQty: cartQty
11984			} );
11985			formatted_unit_original_price = $.epoAPI.applyFilter( 'tcAdjustFormattedUnitOriginalPrice', formatted_unit_original_price, {
11986				epo: currentEpoObject,
11987				totalsHolder: totalsHolder,
11988				event: event,
11989				unit_original_price: unit_original_price,
11990				productPrice: productPrice,
11991				_original_total: _original_total,
11992				total_plcart_fee_options_totals_fee: cart_fee_options_total,
11993				cartQty: cartQty
11994			} );
11995			formatted_options_total = $.epoAPI.applyFilter( 'tcAdjustFormattedOptionsTotal', formatted_options_total, {
11996				epo: currentEpoObject,
11997				totalsHolder: totalsHolder,
11998				event: event,
11999				total: total,
12000				_total: _total,
12001				total_plus_fee: total_plus_fee,
12002				extraFee: extraFee,
12003				cartQty: cartQty
12004			} );
12005			formatted_options_original_total = $.epoAPI.applyFilter( 'tcAdjustFormattedOptionsOriginalTotal', formatted_options_original_total, {
12006				epo: currentEpoObject,
12007				totalsHolder: totalsHolder,
12008				event: event,
12009				original_total: original_total,
12010				_original_total: _original_total,
12011				original_total_plus_fee: original_total_plus_fee,
12012				extraFee: extraFee,
12013				cartQty: cartQty
12014			} );
12015			formatted_fees_total = $.epoAPI.applyFilter( 'tcAdjustFormattedFeesTotal', formatted_fees_total, {
12016				epo: currentEpoObject,
12017				totalsHolder: totalsHolder,
12018				event: event,
12019				cart_fee_options_total: cart_fee_options_total,
12020				extraFee: extraFee,
12021				cartQty: cartQty
12022			} );
12023			formatted_fees_original_total = $.epoAPI.applyFilter( 'tcAdjustFormattedFeesOriginalTotal', formatted_fees_original_total, {
12024				epo: currentEpoObject,
12025				totalsHolder: totalsHolder,
12026				event: event,
12027				cart_fee_options_original_total: cart_fee_options_original_total,
12028				extraFee: extraFee,
12029				cartQty: cartQty
12030			} );
12031			formatted_final_total = $.epoAPI.applyFilter( 'tcAdjustFormattedFinalTotal', formatted_final_total, {
12032				epo: currentEpoObject,
12033				totalsHolder: totalsHolder,
12034				event: event,
12035				product_total_price: product_total_price,
12036				product_total_price_without_options: product_total_price_without_options,
12037				total_plus_fee: total_plus_fee,
12038				extraFee: extraFee,
12039				cartQty: cartQty
12040			} );
12041			formatted_final_original_total = $.epoAPI.applyFilter( 'tcAdjustFormattedFinalOriginalTotal', formatted_final_original_total, {
12042				epo: currentEpoObject,
12043				totalsHolder: totalsHolder,
12044				event: event,
12045				product_total_original_price: product_total_original_price,
12046				product_total_price_without_options: product_total_price_without_options,
12047				original_total_plus_fee: original_total_plus_fee,
12048				extraFee: extraFee,
12049				cartQty: cartQty
12050			} );
12051
12052			if ( ( total > 0 && finalTotalBoxShowOptions === 'showtgz' ) || finalTotalBoxShowOptions === 'show' ) {
12053				show_options_total = true;
12054				if ( TMEPOJS.tm_epo_enable_vat_options_total === 'yes' ) {
12055					show_vat_options_total = true;
12056				}
12057			}
12058			if ( cart_fee_options_total !== 0 ) {
12059				show_fees_total = true;
12060			}
12061
12062			if ( formatted_final_total && finalTotalBoxShowFinal === 'show' ) {
12063				show_final_total = true;
12064			}
12065
12066			tc_totals_ob = {
12067				qty: cartQty,
12068				product_price: productPrice,
12069				raw_product_price: rawProductPrice,
12070				product_regular_price: productRegularPrice,
12071				raw_product_regular_price: rawProductRegularPrice,
12072				formatted_product_price: tm_set_price_totals( parseFloat( productPrice ) * cartQty ),
12073
12074				late_total_prices: late_total_price,
12075				late_total_price: tm_set_tax_price( late_total_price[ 0 ], totalsHolder ),
12076				late_total_original_price: tm_set_tax_price( late_total_price[ 1 ], totalsHolder ),
12077
12078				raw_options_price_per_unit: raw__total,
12079				raw_options_total_price: raw_total,
12080				raw_cart_fee_options_total_price: raw_cart_fee_options_total,
12081				raw_total_plus_fee: raw_total_plus_fee,
12082
12083				raw_options_original_price_per_unit: raw__original_total,
12084				raw_options_original_total_price: raw_original_total,
12085				raw_cart_fee_options_original_total_price: raw_cart_fee_options_original_total,
12086				raw_original_total_plus_fee: raw_original_total_plus_fee,
12087
12088				raw_product_total_price: raw_product_total_price,
12089				raw_product_total_original_price: raw_product_total_original_price,
12090				raw_product_total_price_without_options: raw_product_total_price_without_options,
12091
12092				options_price_per_unit: _total,
12093				options_total_price: total,
12094				cart_fee_options_total_price: cart_fee_options_total,
12095				total_plus_fee: total_plus_fee,
12096
12097				options_original_price_per_unit: _original_total,
12098				options_original_total_price: original_total,
12099				cart_fee_options_total_original_price: cart_fee_options_original_total,
12100				original_total_plus_fee: original_total_plus_fee,
12101
12102				vat_options_total: vat_options_total,
12103				vat_options_total_plus_fee: vat_options_total_plus_fee,
12104				formatted_vat_options_total: formatted_vat_options_total,
12105				formatted_vat_options_total_plus_fee: formatted_vat_options_total_plus_fee,
12106				vat_total: vat_total,
12107				formatted_vat_total: formatted_vat_total,
12108				vat_product_base: vat_product_base,
12109				formatted_vat_product_base: formatted_vat_product_base,
12110
12111				product_total_price: product_total_price,
12112				product_total_original_price: product_total_original_price,
12113				product_total_price_without_options: product_total_price_without_options,
12114
12115				product_unit_price: unit_price,
12116				product_unit_original_price: unit_original_price,
12117				formatted_unit_price: formatted_unit_price,
12118				formatted_options_total: formatted_options_total,
12119				formatted_fees_total: formatted_fees_total,
12120				formatted_final_total: formatted_final_total,
12121
12122				formatted_unit_original_price: formatted_unit_original_price,
12123				formatted_options_original_total: formatted_options_original_total,
12124				formatted_fees_original_total: formatted_fees_original_total,
12125				formatted_final_original_total: formatted_final_original_total,
12126
12127				formatted_extra_fee: formatted_extra_fee,
12128
12129				show_options_total: show_options_total,
12130				show_fees_total: show_fees_total,
12131				show_extra_fee: show_extra_fee,
12132				show_final_total: show_final_total,
12133				show_options_vat: show_vat_options_total,
12134
12135				show_unit_price: TMEPOJS.tm_epo_show_unit_price === 'yes',
12136				unit_price: currentEpoObject.is_associated ? TMEPOJS.i18n_item_unit_price : TMEPOJS.i18n_unit_price,
12137				options_total: currentEpoObject.is_associated ? TMEPOJS.i18n_item_options_total : TMEPOJS.i18n_options_total,
12138				options_vat_total: currentEpoObject.is_associated ? TMEPOJS.i18n_item_vat_options_total : TMEPOJS.i18n_vat_options_total,
12139				final_total: currentEpoObject.is_associated ? TMEPOJS.i18n_item_final_total : TMEPOJS.i18n_final_total,
12140				fees_total: TMEPOJS.i18n_fees_total,
12141				extra_fee: TMEPOJS.i18n_extra_fee,
12142
12143				totals_box_before_unit_price: TMEPOJS.totals_box_before_unit_price,
12144				totals_box_after_unit_price: TMEPOJS.totals_box_after_unit_price,
12145				totals_box_before_vat_options_totals_price: TMEPOJS.totals_box_before_vat_options_totals_price,
12146				totals_box_after_vat_options_totals_price: TMEPOJS.totals_box_after_vat_options_totals_price,
12147				totals_box_before_options_totals_price: TMEPOJS.totals_box_before_options_totals_price,
12148				totals_box_after_options_totals_price: TMEPOJS.totals_box_after_options_totals_price,
12149				totals_box_before_fee_totals_price: TMEPOJS.totals_box_before_fee_totals_price,
12150				totals_box_after_fee_totals_price: TMEPOJS.totals_box_after_fee_totals_price,
12151				totals_box_before_extra_fee_price: TMEPOJS.totals_box_before_extra_fee_price,
12152				totals_box_after_extra_fee_price: TMEPOJS.totals_box_after_extra_fee_price,
12153				totals_box_before_final_totals_price: TMEPOJS.totals_box_before_final_totals_price,
12154				totals_box_after_final_totals_price: TMEPOJS.totals_box_after_final_totals_price
12155			};
12156
12157			if ( TMEPOJS.customer_price_format ) {
12158				customer_price_format_wrap_start = TMEPOJS.customer_price_format_wrap_start;
12159				customer_price_format_wrap_end = TMEPOJS.customer_price_format_wrap_end;
12160				customerPriceFormat = TMEPOJS.customer_price_format;
12161			}
12162
12163			if ( formatted_options_total && total >= 0 ) {
12164				_ftotal = formatPrice( total );
12165				_foriginal_total = formatPrice( original_total );
12166				if ( customerPriceFormat ) {
12167					_ftotal = customerPriceFormat.replaceAll( '__PRICE__', _ftotal ).replaceAll( '__CODE__', TMEPOJS.current_currency );
12168					if ( ! totalsHolder.data( 'is-on-sale' ) ) {
12169						_foriginal_total = customerPriceFormat.replaceAll( '__PRICE__', _foriginal_total ).replaceAll( '__CODE__', TMEPOJS.current_currency );
12170					}
12171				}
12172				_ftotal = $.epoAPI.applyFilter( 'tcFilterFormattedFTotal', _ftotal, {
12173					epo: currentEpoObject,
12174					totalsHolder: totalsHolder,
12175					event: event,
12176					total: total,
12177					_total: _total,
12178					total_plus_fee: total_plus_fee,
12179					extraFee: extraFee,
12180					cartQty: cartQty
12181				} );
12182				_foriginal_total = $.epoAPI.applyFilter( 'tcFilterFormattedFOriginalTotal', _foriginal_total, {
12183					epo: currentEpoObject,
12184					totalsHolder: totalsHolder,
12185					event: event,
12186					original_total: original_total,
12187					total: original_total,
12188					_total: _total,
12189					total_plus_fee: total_plus_fee,
12190					extraFee: extraFee,
12191					cartQty: cartQty
12192				} );
12193				if ( TMEPOJS.tm_epo_enable_original_final_total === 'yes' && total !== original_total ) {
12194					tc_totals_ob.formatted_options_total = $.epoAPI.util.decodeHTML(
12195						$.epoAPI.template.html( tcAPI.templateEngine.tc_formatted_sale_price, {
12196							price: _foriginal_total,
12197							sale_price: _ftotal,
12198							customer_price_format_wrap_start: customer_price_format_wrap_start,
12199							customer_price_format_wrap_end: customer_price_format_wrap_end
12200						} )
12201					);
12202					tc_totals_ob._foriginal_total = _foriginal_total;
12203					tc_totals_ob._ftotal = _ftotal;
12204				} else {
12205					tc_totals_ob.formatted_options_total = $.epoAPI.util.decodeHTML(
12206						$.epoAPI.util.decodeHTML(
12207							$.epoAPI.template.html( tcAPI.templateEngine.tc_formatted_price, {
12208								price: _ftotal,
12209								customer_price_format_wrap_start: customer_price_format_wrap_start,
12210								customer_price_format_wrap_end: customer_price_format_wrap_end
12211							} )
12212						)
12213					);
12214				}
12215			}
12216
12217			if ( formatted_final_total && product_total_price >= 0 ) {
12218				_fprice = formatPrice( product_total_price );
12219				if ( priceOverrideMode === '1' && parseFloat( total ) > 0 ) {
12220					_f_regular_price = parseFloat( raw_original_total + extraFee );
12221				} else {
12222					_f_regular_price = parseFloat( parseFloat( rawProductRegularPrice * cartQty ) + raw_original_total );
12223				}
12224				if ( customerPriceFormat ) {
12225					_fprice = customerPriceFormat.replaceAll( '__PRICE__', _fprice ).replaceAll( '__CODE__', TMEPOJS.current_currency );
12226					if ( ! totalsHolder.data( 'is-on-sale' ) ) {
12227						_f_regular_price = customerPriceFormat.replaceAll( '__PRICE__', _f_regular_price ).replaceAll( '__CODE__', TMEPOJS.current_currency );
12228					}
12229				}
12230
12231				_fprice = $.epoAPI.applyFilter( 'tc_adjust_native_price', _fprice, product_total_price );
12232				_f_regular_price = tm_set_tax_price( _f_regular_price, totalsHolder, undefined, undefined, undefined, undefined, true ) + parseFloat( cart_fee_options_original_total ) + parseFloat( extraFee );
12233				_f_regular_price = formatPrice( _f_regular_price );
12234				_f_regular_price = $.epoAPI.applyFilter( 'tc_adjust_native_regular_price', _f_regular_price, product_total_price );
12235
12236				if ( TMEPOJS.tm_epo_enable_original_final_total =
12236== 'yes' && ( ( totalsHolder.data( 'is-on-sale' ) && priceOverrideMode !== '1' ) || _f_regular_price !== _fprice ) ) {
12237					tc_totals_ob.formatted_final_total = $.epoAPI.util.decodeHTML(
12238						$.epoAPI.template.html( tcAPI.templateEngine.tc_formatted_sale_price, {
12239							price: _f_regular_price,
12240							sale_price: _fprice,
12241							customer_price_format_wrap_start: customer_price_format_wrap_start,
12242							customer_price_format_wrap_end: customer_price_format_wrap_end
12243						} )
12244					);
12245				} else {
12246					tc_totals_ob.formatted_final_total = $.epoAPI.util.decodeHTML(
12247						$.epoAPI.util.decodeHTML(
12248							$.epoAPI.template.html( tcAPI.templateEngine.tc_formatted_price, {
12249								price: _fprice,
12250								customer_price_format_wrap_start: customer_price_format_wrap_start,
12251								customer_price_format_wrap_end: customer_price_format_wrap_end
12252							} )
12253						)
12254					);
12255				}
12256				tc_totals_ob._f_regular_price = _f_regular_price;
12257				tc_totals_ob._fprice = _fprice;
12258			}
12259
12260			// Add the suffix.
12261			tc_totals_ob.formatted_unit_price = tc_totals_ob.formatted_unit_price + $.epoAPI.util.decodeHTML(
12262				$.epoAPI.util.decodeHTML(
12263					$.epoAPI.template.html( tcAPI.templateEngine.suffix )
12264				)
12265			);
12266
12267			tc_totals_ob.formatted_options_total = tc_totals_ob.formatted_options_total + $.epoAPI.util.decodeHTML(
12268				$.epoAPI.util.decodeHTML(
12269					$.epoAPI.template.html( tcAPI.templateEngine.suffix )
12270				)
12271			);
12272
12273			tc_totals_ob.formatted_final_total = tc_totals_ob.formatted_final_total + $.epoAPI.util.decodeHTML(
12274				$.epoAPI.util.decodeHTML(
12275					$.epoAPI.template.html( tcAPI.templateEngine.suffix )
12276				)
12277			);
12278
12279			tc_totals_ob = replace_suffixes( 'formatted_fees_original_total', 'cart_fee_options_total_original_price', tc_totals_ob, totalsHolder );
12280			tc_totals_ob = replace_suffixes( 'formatted_fees_total', 'cart_fee_options_total_price', tc_totals_ob, totalsHolder );
12281			tc_totals_ob = replace_suffixes( 'formatted_final_original_total', 'product_total_original_price', tc_totals_ob, totalsHolder );
12282			tc_totals_ob = replace_suffixes( 'formatted_final_total', 'product_total_price', tc_totals_ob, totalsHolder );
12283			tc_totals_ob = replace_suffixes( 'formatted_options_original_total', 'options_original_total_price', tc_totals_ob, totalsHolder );
12284			tc_totals_ob = replace_suffixes( 'formatted_options_total', 'options_total_price', tc_totals_ob, totalsHolder );
12285			tc_totals_ob = replace_suffixes( 'formatted_unit_original_price', 'product_unit_original_price', tc_totals_ob, totalsHolder );
12286			tc_totals_ob = replace_suffixes( 'formatted_unit_price', 'product_unit_price', tc_totals_ob, totalsHolder );
12287
12288			if ( $.tcepo.showHideTotal !== undefined && $.tcepo.showHideTotal[ epoEventId ] !== undefined ) {
12289				showTotal = $.tcepo.showHideTotal[ epoEventId ];
12290			}
12291
12292			tc_totals_ob = $.epoAPI.applyFilter( 'tc_adjust_tc_totals_ob', tc_totals_ob, {
12293				epo_object: currentEpoObject,
12294				showTotal: showTotal,
12295				epoHolder: epoHolder,
12296				totalsHolder: totalsHolder,
12297				replace_suffixes: replace_suffixes,
12298				replace_suffixes_in_html: replace_suffixes_in_html,
12299				tm_set_tax_price: tm_set_tax_price,
12300				tm_set_price: tm_set_price,
12301				tm_set_price_totals: tm_set_price_totals,
12302				product_total_price: product_total_price,
12303				product_price: productPrice,
12304				qty: cartQty
12305			} );
12306
12307			if ( tc_totals_ob.showTotal !== undefined ) {
12308				showTotal = tc_totals_ob.showTotal;
12309			}
12310
12311			currentEpoObject.tc_totals_ob = tc_totals_ob;
12312
12313			showTotal = $.epoAPI.applyFilter( 'tcFinalTotalsBoxVisibility', showTotal, {
12314				epo: currentEpoObject,
12315				alternativeCart: alternativeCart,
12316				cart: cart,
12317				main_product: main_product,
12318				totalsHolder: totalsHolder,
12319				this_epo_totals_container: this_epo_totals_container
12320			} );
12321
12322			html = $.epoAPI.template.html( tcAPI.templateEngine.tc_final_totals, tc_totals_ob );
12323
12324			totalsHolder.data( 'tm-html', html );
12325			totalsHolder.data( 'tc_totals_ob', tc_totals_ob );
12326
12327			if ( currentEpoObject.associated_connect && currentEpoObject.associated_connect.length === 1 ) {
12328				if ( currentEpoObject.associated_connect.attr( 'data-no-price' ) === '1' ) {
12329					associatedPrice = 0;
12330					associatedRawPrice = 0;
12331					associatedOriginalPrice = 0;
12332					associatedRawOriginalPrice = 0;
12333					associatedFormattedPrice = '';
12334					tm_force_update_price(
12335						epoObject,
12336						associatedSetter
12337							.closest( '.tmcp-field-wrap' )
12338							.find( '.tc-price' )
12339							.not( tcAPI.associatedEpoSelector + ' .tc-price' ),
12340						associatedPrice,
12341						associatedFormattedPrice,
12342						associatedOriginalPrice
12343					);
12344				} else {
12345					associatedPrice = tc_totals_ob.product_price + tc_totals_ob.options_price_per_unit + ( tc_totals_ob.cart_fee_options_total_price / tc_totals_ob.qty );
12346					associatedRawPrice = tc_totals_ob.raw_product_price + tc_totals_ob.raw_options_price_per_unit + ( tc_totals_ob.raw_cart_fee_options_total_price / tc_totals_ob.qty );
12347					associatedOriginalPrice = tc_totals_ob.product_regular_price + tc_totals_ob.options_original_price_per_unit + ( tc_totals_ob.cart_fee_options_total_original_price / tc_totals_ob.qty );
12348					associatedRawOriginalPrice = tc_totals_ob.raw_product_regular_price + tc_totals_ob.raw_options_original_price_per_unit + ( tc_totals_ob.raw_cart_fee_options_original_total_price / tc_totals_ob.qty );
12349
12350					associatedFormattedPrice = tm_set_price( associatedPrice, currentEpoObject.this_epo_totals_container, false, associatedSetter );
12351
12352					// Mainly used to update the price of the associated element when the associated product is variable.
12353					tm_force_update_price(
12354						epoObject,
12355						associatedSetter
12356							.closest( '.tmcp-field-wrap' )
12357							.find( '.tc-price' )
12358							.not( tcAPI.associatedEpoSelector + ' .tc-price' ),
12359						associatedPrice,
12360						associatedFormattedPrice,
12361						associatedOriginalPrice
12362					);
12363
12364					currentEpoObject.associated_connect.data( 'tm-quantity', tc_totals_ob.qty );
12365
12366					if ( currentEpoObject.associated_connect.data( 'tm-quantity' ) ) {
12367						associatedPrice = associatedPrice * parseFloat( currentEpoObject.associated_connect.data( 'tm-quantity' ) );
12368						associatedRawPrice = associatedRawPrice * parseFloat( currentEpoObject.associated_connect.data( 'tm-quantity' ) );
12369						associatedOriginalPrice = associatedOriginalPrice * parseFloat( currentEpoObject.associated_connect.data( 'tm-quantity' ) );
12370						associatedRawOriginalPrice = associatedRawOriginalPrice * parseFloat( currentEpoObject.associated_connect.data( 'tm-quantity' ) );
12371					}
12372
12373					associatedFormattedPrice = tm_set_price( associatedPrice, currentEpoObject.this_epo_totals_container, false, associatedSetter );
12374				}
12375
12376				currentEpoObject.associated_connect.data( 'price_set', 1 );
12377				if ( associatedSetter.is( '.tcenabled' ) ) {
12378					associatedSetter.data( 'associated_price_set', 1 );
12379				}
12380				associatedSetter.data( 'price_set', 1 );
12381				associatedSetter.data( 'raw_price', associatedRawPrice );
12382				associatedSetter.data( 'raw_original_price', associatedRawOriginalPrice );
12383				associatedSetter.data( 'price', tm_set_tax_price( associatedPrice, currentEpoObject.this_epo_totals_container, associatedSetter ) );
12384				associatedSetter.data( 'original_price', tm_set_tax_price( associatedOriginalPrice, currentEpoObject.this_epo_totals_container, associatedSetter ) );
12385
12386				currentEpoObject.associated_connect.data( 'price-changed', 1 );
12387
12388				setTimeout( function() {
12389					if ( ! ( currentEpoObject.associated_connect && event.noassociated ) ) {
12390						currentEpoObject.mainEpoObject.main_cart.trigger( {
12391							type: 'tm-epo-update',
12392							norules: 2
12393						} );
12394					}
12395				}, 20 );
12396			}
12397
12398			jWindow.trigger( 'tcEpoAfterCalculateTotals', {
12399				epo: currentEpoObject,
12400				alternativeCart: alternativeCart,
12401				this_product_type: this_product_type,
12402				cart: cart,
12403				bundleid: bundleid,
12404				totalsObject: tc_totals_ob,
12405				main_product: main_product,
12406				per_product_pricing: perProductPricing,
12407				event: event
12408			} );
12409
12410			hide_native_price = $.epoAPI.applyFilter( 'hide_native_price', true );
12411
12412			if ( cartQty > 0 ) {
12413				// hide native prices
12414				if ( TMEPOJS.tm_epo_change_variation_price === 'yes' ) {
12415					if ( hide_native_price === true && finalTotalBoxMode !== 'disable' ) {
12416						tm_get_native_prices_block( cart ).hide();
12417					} else {
12418						tm_get_native_prices_block( cart ).show();
12419					}
12420				}
12421
12422				if ( ! showTotal ||
12423					finalTotalBoxMode === 'disable' ||
12424					( finalTotalBoxMode === 'hideiftotaliszero' && product_total_price === 0 ) ||
12425					( finalTotalBoxMode === 'hideifoptionsiszero' && total_plus_fee === 0 )
12426				) {
12427					html = '';
12428					totalsHolder.html( html );
12429					totalsHolder.data( 'tm-floating-box-data', [] );
12430				} else {
12431					totalsHolder.html( html );
12432
12433					jWindow.trigger( 'tc-totals-container', {
12434						epo: tc_totals_ob,
12435						totals_holder: totalsHolder,
12436						data: {
12437							epo_object: currentEpoObject,
12438							tm_set_price: tm_set_price,
12439							tm_set_price_totals: tm_set_price_totals,
12440							product_total_price: product_total_price,
12441							product_price: productPrice,
12442							qty: cartQty
12443						},
12444						tm_epo_js: TMEPOJS
12445					} );
12446				}
12447
12448				if ( formatted_final_total && product_total_price >= 0 ) {
12449					if ( TMEPOJS.tm_epo_change_variation_price === 'yes' ) {
12450						setTimeout( function() {
12451							update_native_html = tm_get_native_prices_block( cart );
12452							if ( totalsHolder.data( 'is-on-sale' ) ) {
12453								temp = $.epoAPI.util.decodeHTML(
12454									$.epoAPI.template.html( tcAPI.templateEngine.tc_formatted_sale_price, {
12455										price: _f_regular_price,
12456										sale_price: _fprice,
12457										customer_price_format_wrap_start: customer_price_format_wrap_start,
12458										customer_price_format_wrap_end: customer_price_format_wrap_end,
12459										before_price_text: TMEPOJS.variation_price_before_price_text,
12460										after_price_text: TMEPOJS.variation_price_after_price_text
12461									} )
12462								);
12463								temp = temp + $.epoAPI.util.decodeHTML(
12464									$.epoAPI.util.decodeHTML(
12465										$.epoAPI.template.html( tcAPI.templateEngine.main_suffix )
12466									)
12467								);
12468								temp = {
12469									formatted: temp,
12470									raw: tc_totals_ob.product_total_price
12471								};
12472								temp = replace_suffixes( 'formatted', 'raw', temp, totalsHolder );
12473								temp = temp.formatted;
12474								update_native_html
12475									.html( temp )
12476									.show();
12477							} else {
12478								temp = $.epoAPI.util.decodeHTML(
12479									$.epoAPI.template.html( tcAPI.templateEngine.tc_formatted_price, {
12480										price: _fprice,
12481										customer_price_format_wrap_start: customer_price_format_wrap_start,
12482										customer_price_format_wrap_end: customer_price_format_wrap_end,
12483										before_price_text: TMEPOJS.variation_price_before_price_text,
12484										after_price_text: TMEPOJS.variation_price_after_price_text
12485									} )
12486								);
12487								temp = temp + $.epoAPI.util.decodeHTML(
12488									$.epoAPI.util.decodeHTML(
12489										$.epoAPI.template.html( tcAPI.templateEngine.main_suffix )
12490									)
12491								);
12492								temp = {
12493									formatted: temp,
12494									raw: tc_totals_ob.product_total_price
12495								};
12496								temp = replace_suffixes( 'formatted', 'raw', temp, totalsHolder );
12497								temp = temp.formatted;
12498								update_native_html
12499									.html( temp )
12500									.show();
12501							}
12502						}, 310 ); // WooCommerce uses 300ms timeout for changing the price.
12503					}
12504
12505					if ( TMEPOJS.tm_epo_change_original_price === 'yes' ) {
12506						if ( ! alternativeCart || main_product.find( '.cpf-bto-price' ).length === 0 ) {
12507							if ( currentEpoObject.associated_connect ) {
12508								nativeProductPriceSelector = currentEpoObject.main_product.find( tcAPI.associatedNativeProductPriceSelector );
12509							} else {
12510								// shop/archive pages.
12511								nativeProductPriceSelector = currentEpoObject.main_product.find( tcAPI.nativeProductPriceSelector );
12512								// product page.
12513								if ( nativeProductPriceSelector.length === 0 ) {
12514									nativeProductPriceSelector = $( tcAPI.nativeProductPriceSelector );
12515								}
12516							}
12517
12518							if ( nativeProductPriceSelector.length === 0 && main_product.is( '.tc-after-shop-loop' ) ) {
12519								nativeProductPriceSelector = main_product.closest( '.product' ).find( '.price' ).not( '.tc-after-shop-loop .price' );
12520							}
12521							if ( nativeProductPriceSelector.data( 'tc-original-html' ) === undefined ) {
12522								nativeProductPriceSelector.data( 'tc-original-html', nativeProductPriceSelector.html() );
12523							}
12524							if ( product_total_price > 0 ) {
12525								if ( totalsHolder.data( 'is-on-sale' ) ) {
12526									temp = $.epoAPI.util.decodeHTML(
12527										$.epoAPI.template.html( tcAPI.templateEngine.tc_formatted_sale_price, {
12528											price: _f_regular_price,
12529											sale_price: _fprice,
12530											customer_price_format_wrap_start: customer_price_format_wrap_start,
12531											customer_price_format_wrap_end: customer_price_format_wrap_end,
12532											before_price_text: TMEPOJS.product_price_before_price_text,
12533											after_price_text: TMEPOJS.product_price_after_price_text
12534										} )
12535									);
12536									temp = temp + $.epoAPI.util.decodeHTML(
12537										$.epoAPI.util.decodeHTML(
12538											$.epoAPI.template.html( tcAPI.templateEngine.main_suffix )
12539										)
12540									);
12541									temp = {
12542										formatted: temp,
12543										raw: tc_totals_ob.product_total_price
12544									};
12545									temp = replace_suffixes( 'formatted', 'raw', temp, totalsHolder );
12546									temp = temp.formatted;
12547									nativeProductPriceSelector
12548										.html( temp )
12549										.show();
12550								} else {
12551									temp = $.epoAPI.util.decodeHTML(
12552										$.epoAPI.template.html( tcAPI.templateEngine.tc_formatted_price, {
12553											price: _fprice,
12554											customer_price_format_wrap_start: customer_price_format_wrap_start,
12555											customer_price_format_wrap_end: customer_price_format_wrap_end,
12556											before_price_text: TMEPOJS.product_price_before_price_text,
12557											after_price_text: TMEPOJS.product_price_after_price_text
12558										} )
12559									);
12560									temp = temp + $.epoAPI.util.decodeHTML(
12561										$.epoAPI.util.decodeHTML(
12562											$.epoAPI.template.html( tcAPI.templateEngine.main_suffix )
12563										)
12564									);
12565									temp = {
12566										formatted: temp,
12567										raw: tc_totals_ob.product_total_price
12568									};
12569									temp = replace_suffixes( 'formatted', 'raw', temp, totalsHolder );
12570									temp = temp.formatted;
12571									nativeProductPriceSelector
12572										.html( temp )
12573										.show();
12574								}
12575							} else if ( this_product_type && this_product_type !== 'composite' ) {
12576								if ( currentEpoObject.associated_connect ) {
12577									if ( currentEpoObject.variations_form.length ) {
12578										temp = currentEpoObject.this_epo_totals_container.data( 'variationIdElement' );
12579										if ( temp.length > 0 ) {
12580											temp = parseFloat( temp.val() );
12581											if ( ! ( ! temp || temp === 0 ) ) {
12582												nativeProductPriceSelector.html( $.epoAPI.util.decodeHTML( TMEPOJS.assoc_current_free_text ) );
12583											}
12584										}
12585									} else {
12586										nativeProductPriceSelector.html( $.epoAPI.util.decodeHTML( TMEPOJS.assoc_current_free_text ) );
12587									}
12588								} else {
12589									nativeProductPriceSelector.html( $.epoAPI.util.decodeHTML( TMEPOJS.current_free_text ) );
12590								}
12591							}
12592						}
12593
12594						jWindow.trigger( 'tcEpoMaybeChangePriceHtml', {
12595							epo: currentEpoObject,
12596							alternativeCart: alternativeCart,
12597							this_product_type: this_product_type,
12598							cart: cart,
12599							bundleid: bundleid,
12600							totalsObject: tc_totals_ob,
12601							main_product: main_product,
12602							nativePrice: _fprice
12603						} );
12604					}
12605				}
12606
12607				if ( alternativeCart ) {
12608					main_cart.trigger( {
12609						type: 'tm-epo-update',
12610						norules: 1
12611					} );
12612				} else {
12613					this_epo_totals_container.data( 'is_active', true );
12614				}
12615			} else {
12616				if ( currentEpoObject.associated_connect ) {
12617					nativeProductPriceSelector = currentEpoObject.main_product.find( tcAPI.associatedNativeProductPriceSelector );
12618					nativeProductPriceSelector.html( nativeProductPriceSelector.data( 'tc-original-html' ) );
12619				}
12620
12621				tm_get_native_prices_block( cart ).toArray().forEach( function( npb ) {
12622					var $npb = $( npb );
12623					if ( ! $npb.data( 'tm-original-html' ) ) {
12624						$npb.data( 'tm-original-html', $npb.html() );
12625					} else {
12626						$npb.html( $npb.data( 'tm-original-html' ) );
12627					}
12628				} );
12629
12630				if ( rawProductPrice === 0 && TMEPOJS.tm_epo_remove_free_price_label === 'yes' ) {
12631					tm_get_native_prices_block( cart ).hide();
12632				} else if ( TMEPOJS.tm_epo_change_variation_price === 'yes' && ! ( hide_native_price === true && finalTotalBoxMode !== 'disable' ) ) {
12633					tm_get_native_prices_block( cart ).show();
12634				}
12635
12636				totalsHolder.empty();
12637
12638				if ( alternativeCart ) {
12639					main_cart.trigger( {
12640						type: 'tm-epo-update',
12641						norules: 1
12642					} );
12643				}
12644			}
12645
12646			main_cart.trigger( 'tm-epo-after-update', {
12647				container: cartContainer
12648			} );
12649
12650			jWindow.trigger( 'tc-epo-after-update', {
12651				epo: tc_totals_ob,
12652				totals_holder: totalsHolder,
12653				data: {
12654					epo_object: currentEpoObject,
12655					add_late_fields_prices: add_late_fields_prices,
12656					tm_set_price: tm_set_price,
12657					tm_set_price_totals: tm_set_price_totals,
12658					product_total_price: product_total_price,
12659					replace_suffixes_in_html: replace_suffixes_in_html,
12660					product_price: productPrice,
12661					qty: cartQty,
12662					bundleid: bundleid,
12663					currentCart: currentCart
12664				},
12665				tm_epo_js: TMEPOJS
12666			} );
12667		} );
12668
12669		if ( this_product_type === 'variable' || this_product_type === 'variable-subscription' ) {
12670			epoVariationSection = epoHolder.find( '.tm-epo-variation-section' ).first();
12671
12672			// Custom variation events
12673			epoVariationSection
12674				.find( '.tm-epo-reset-variation' )
12675				.off( 'click.cpfv' )
12676				.on( 'click.cpfv', function() {
12677					var field = $( this );
12678					var id = $.epoAPI.dom.id( field.attr( 'data-tm-for-variation' ) );
12679					var section = field.closest( '.cpf-type-variations' );
12680					var inputs = field.closest( '.cpf-element' ).find( '.tm-epo-variation-element' );
12681					var lis = field.closest( '.cpf-element' ).find( '.tmcp-field-wrap' );
12682
12683					inputs.prop( 'checked', false );
12684					lis.removeClass( 'tc-active' );
12685					variationForm
12686						.find( "[data-attribute_name='attribute_" + id + "']" )
12687						.val( '' )
12688						.trigger( 'change' );
12689					variationForm.find( "[data-attribute_name='attribute_" + id + "']" ).trigger( 'focusin' );
12690
12691					main_product
12692						.find( '.cpf-type-variations' )
12693						.not( section )
12694						.toArray().forEach( function( el ) {
12695							variationForm.find( "[data-attribute_name='attribute_" + $.epoAPI.dom.id( $( el ).find( '.tm-epo-variation-element' ).first().attr( 'data-tm-for-variation' ) ) + "']" ).trigger( 'focusin' );
12696						} );
12697					field.trigger( 'blur' );
12698					variationForm.trigger( 'woocommerce_update_variation_values_tmlogic' );
12699				} );
12700
12701			epoVariationSection
12702				.find( 'input.tm-epo-variation-element,input.tm-epo-variation-element + span' )
12703				.off( 'mouseup.cpfv' )
12704				.on( 'mouseup.cpfv', function() {
12705					var field = $( this );
12706					var id;
12707
12708					if ( field.is( 'span' ) ) {
12709						field = field.prev( 'input' );
12710					}
12711					if ( field.attr( 'disabled' ) ) {
12712						variationForm.find( '.reset_variations' ).trigger( 'click' );
12713					}
12714					id = $.epoAPI.dom.id( field.attr( 'data-tm-for-variation' ) );
12715					variationForm.find( "[data-attribute_name='attribute_" + id + "']" ).trigger( 'focusin' );
12716				} );
12717
12718			epoVariationSection
12719				.off( 'click.' + eventName + '.tmepo', '.reset_variations, .tc-epo-element-variable-reset-variations' )
12720				.on( 'click.' + eventName + '.tmepo', '.reset_variations, .tc-epo-element-variable-reset-variations', { _epoObject: epoObject }, function( event ) {
12721					var _nativeProductPriceSelector;
12722					if ( TMEPOJS.tm_epo_change_original_price === 'yes' ) {
12723						if ( ! alternativeCart || main_product.find( '.cpf-bto-price' ).length === 0 ) {
12724							if ( event.data._epoObject.associated_connect ) {
12725								_nativeProductPriceSelector = event.data._epoObject.main_product.find( tcAPI.associatedNativeProductPriceSelector );
12726							} else {
12727								_nativeProductPriceSelector = $( tcAPI.nativeProductPriceSelector );
12728							}
12729							if ( _nativeProductPriceSelector.data( 'tc-original-html' ) ) {
12730								_nativeProductPriceSelector.html( _nativeProductPriceSelector.data( 'tc-original-html' ) );
12731							}
12732						}
12733					}
12734					variationForm.find( '.variations .reset_variations, .tc-epo-element-variable-reset-variations' ).first().trigger( 'click' );
12735				} );
12736
12737			epoVariationSection
12738				.find( '.tm-epo-variation-element' )
12739				.off( 'change.cpfv tm_epo_variation_element_change' )
12740				.on( 'change.cpfv tm_epo_variation_element_change', function( e ) {
12741					var field = $( this );
12742					var id = $.epoAPI.dom.id( field.attr( 'data-tm-for-variation' ) );
12743					var value = field.val();
12744					var section = field.closest( '.cpf-type-variations' );
12745					var nativeSelect = variationForm.find( "[data-attribute_name='attribute_" + id + "']" );
12746					var exists;
12747
12748					if ( field.closest( '.tm-epo-variation-section' ).is( '.tm-hidden' ) ) {
12749						return;
12750					}
12751
12752					if ( ! ( e && e.type && e.type === 'tm_epo_variation_element_change' ) ) {
12753						exists = false;
12754						nativeSelect.each( function() {
12755							if ( this.value === value ) {
12756								exists = true;
12757								return false;
12758							}
12759						} );
12760						if ( ! exists ) {
12761							nativeSelect.trigger( 'focusin' );
12762						}
12763						nativeSelect.val( value ).trigger( 'change' );
12764					}
12765
12766					if ( ! value ) {
12767						nativeSelect.trigger( 'focusin' );
12768					}
12769
12770					main_product
12771						.find( '.cpf-type-variations' )
12772						.not( section )
12773						.toArray().forEach( function( vr ) {
12774							variationForm.find( '#' + $.epoAPI.dom.id( $( vr ).find( '.tm-epo-variation-element' ).first().attr( 'data-tm-for-variation' ) ) ).trigger( 'focusin' );
12775						} );
12776
12777					field.trigger( 'blur' );
12778					variationForm.trigger( 'woocommerce_update_variation_values_tmlogic' );
12779				} )
12780				.off( 'focusin.cpfv' )
12781				.on( 'focusin.cpfv', function() {
12782					var field = $( this );
12783					var id;
12784
12785					if ( ! field.is( 'select' ) ) {
12786						return;
12787					}
12788
12789					id = $.epoAPI.dom.id( field.attr( 'data-tm-for-variation' ) );
12790					variationForm.find( "[data-attribute_name='attribute_" + id + "']" ).trigger( 'focusin' );
12791					variationForm.trigger( 'woocommerce_update_variation_values_tmlogic' );
12792				} );
12793
12794			variationForm.off( eventNamePrefix + 'found_variation.tmepo tm_fix_stock', '.single_variation_wrap' ).on( eventNamePrefix + 'found_variation.tmepo tm_fix_stock', '.single_variation_wrap', function() {
12795				fix_stock( $( this ), cartContainer );
12796			} );
12797
12798			// update prices when a variation is found
12799			variationForm
12800				.off( eventNamePrefix + 'found_variation.tmepo' )
12801				.on( eventNamePrefix + 'found_variation.tmepo', function( event, variation ) {
12802					var form = $( this );
12803
12804					totalsHolder.data( 'is-on-sale', variation.tc_is_on_sale );
12805					totalsHolder.data( 'regular-price', tm_set_backend_price( variation.display_regular_price, totalsHolder, variation ) );
12806
12807					jWindow.trigger( 'tm-epo-found-variation', {
12808						epo: epoObject,
12809						totalsHolder: totalsHolder,
12810						totalsHolderContainer: totalsHolderContainer,
12811						currentCart: currentCart,
12812						variationForm: form,
12813						variation: variation
12814					} );
12815
12816					found_variation_tmepo( {
12817						epoHolder: epoHolder,
12818						totalsHolder: totalsHolder,
12819						totalsHolderContainer: totalsHolderContainer,
12820						currentCart: currentCart,
12821						variationForm: form,
12822						variation: variation
12823					} );
12824
12825					fix_stock( form, cartContainer );
12826				} )
12827				.off( eventNamePrefix + 'hide_variation.tmepo' )
12828				.on( eventNamePrefix + 'hide_variation.tmepo', { _epoObject: epoObject }, function( event ) {
12829					var _nativeProductPriceSelector;
12830					if ( TMEPOJS.tm_epo_change_original_price === 'yes' ) {
12831						if ( ! alternativeCart || main_product.find( '.cpf-bto-price' ).length === 0 ) {
12832							if ( event.data._epoObject.associated_connect ) {
12833								_nativeProductPriceSelector = event.data._epoObject.main_product.find( tcAPI.associatedNativeProductPriceSelector );
12834							} else {
12835								_nativeProductPriceSelector = $( tcAPI.nativeProductPriceSelector );
12836							}
12837							if ( _nativeProductPriceSelector.data( 'tc-original-html' ) ) {
12838								_nativeProductPriceSelector.html( _nativeProductPriceSelector.data( 'tc-original-html' ) );
12839							}
12840						}
12841					}
12842					totalsHolder.data( 'price', false );
12843					// Fancy product Designer
12844					totalsHolder.removeData( 'tcprice' );
12845					currentCart.trigger( {
12846						type: 'tm-epo-update',
12847						norules: 2
12848					} );
12849				} )
12850				.off( eventNamePrefix + 'check_variations.tmepo' )
12851				.on( eventNamePrefix + 'check_variations.tmepo', function() {
12852					var data = {};
12853					var chosen = 0;
12854					var reset = epoVariationSection.find( '.reset_variations' );
12855
12856					variationForm.find( '.variations select, .tc-epo-variable-product-selector' ).toArray().forEach( function( sl ) {
12857						var $this = $( sl );
12858						var attribute_name = $this.data( 'attribute_name' ) || $this.attr( 'name' );
12859						var value = $this.val() || '';
12860
12861						if ( value.length > 0 ) {
12862							chosen++;
12863						}
12864
12865						data[ attribute_name ] = value;
12866					} );
12867
12868					if ( chosen > 0 ) {
12869						if ( reset.css( 'visibility' ) === 'hidden' ) {
12870							reset.css( 'visibility', 'visible' ).hide().fadeIn();
12871						}
12872					} else {
12873						reset.css( 'visibility', 'hidden' );
12874					}
12875				} )
12876				.trigger( eventNamePrefix + 'check_variations' );
12877
12878			tm_custom_variations( epoObject, cartContainer, itemId, main_product, epoHolder );
12879		}
12880
12881		selectSelector.trigger( 'tm-select-change-html' );
12882		tmQty.trigger( 'change.cpf', { init: 1 } );
12883		tmQuantity.trigger( 'showhide.cpfcustom' );
12884		epoFieldHasClearButton.filter( ':checked' ).trigger( 'cpfclearbutton' );
12885
12886		jWindow.on( 'tm-do-epo-update', function() {
12887			// This must be run every time to get correct results for percent price types
12888			// if set norules then discount will not auto work upon chosing a variation
12889			currentCart.trigger( {
12890				type: 'tm-epo-update'
12891				//"norules": 2
12892			} );
12893		} );
12894
12895		jWindow.trigger( 'tm-epo-init-events', {
12896			epo: {
12897				epo_id: epo_id,
12898				form: epoObject.form,
12899				currentCart: currentCart,
12900				cart_container: cartContainer,
12901				epo_holder: epoHolder,
12902				totals_holder_container: totalsHolderContainer,
12903				totals_holder: totalsHolder,
12904				main_cart: main_cart,
12905				main_epo_inside_form: main_epo_inside_form,
12906				product_id_selector: product_id_selector,
12907				epo_id_selector: epo_id_selector,
12908				product_id: product_id,
12909				this_epo_container: this_epo_container,
12910				this_totals_container: this_totals_container,
12911				this_epo_totals_container: this_epo_totals_container
12912			}
12913		} );
12914
12915		jWindow.trigger( 'epoEventHandlers', {
12916			epo: epoObject,
12917			currentCart: currentCart,
12918			cartContainer: cartContainer,
12919			qtyElement: qtyElement,
12920			epoHolder: epoHolder,
12921			totalsHolderContainer: totalsHolderContainer,
12922			totalsHolder: totalsHolder,
12923			variationForm: variationForm,
12924			variation_id_selector: variation_id_selector,
12925			main_epo_inside_form: main_epo_inside_form,
12926			this_product_type: this_product_type,
12927			get_price_excluding_tax: get_price_excluding_tax,
12928			get_price_including_tax: get_price_including_tax
12929		} );
12930
12931		// show final totals
12932		if ( finalTotalBoxMode !== 'disable' ) {
12933			totalsHolderContainer.addClass( 'tc-show' );
12934		}
12935
12936		// show extra options
12937		jWindow.trigger( 'epo_options_before_visible' );
12938
12939		if ( TMEPOJS.tm_epo_progressive_display === 'yes' ) {
12940			setTimeout( function() {
12941				epoHolder
12942					.css( 'opacity', 0 )
12943					.addClass( 'tc-show' )
12944					.animate(
12945						{
12946							opacity: 1
12947						},
12948						tcAPI.epoAnimationDelay,
12949						'easeOutExpo',
12950						function() {
12951							jWindow.trigger( 'epo_options_visible' );
12952							jWindow.trigger( 'tmlazy' );
12953						}
12954					);
12955			}, tcAPI.epoDelay );
12956		} else {
12957			epoHolder.addClass( 'tc-show' );
12958			jWindow.trigger( 'epo_options_visible' );
12959			jWindow.trigger( 'tmlazy' );
12960		}
12961
12962		main_product.addClass( 'tc-init' );
12963	}
12964
12965	function run_wc_variation_form_cpf( epoObject ) {
12966		var form = epoObject.variations_form;
12967		var cart = epoObject.main_cart;
12968		var this_epo_container = epoObject.this_epo_container;
12969		var eventName = epoObject.is_associated ? 'tc_variation_form.cpf' : 'wc_variation_form.cpf';
12970		var run = function() {
12971			if ( form.data( 'epo_loaded' ) ) {
12972				return;
12973			}
12974
12975			// Start Condition Logic
12976			cpf_section_logic( epoObject );
12977			cpf_element_logic( epoObject );
12978
12979			jWindow.on( 'epoEventHandlers', function() {
12980				run_cpfdependson( this_epo_container );
12981				tm_lazyload();
12982			} );
12983
12984			// Init field price rules
12985			$.tcepo.lateFieldsPrices[ epoObject.epoEventId ] = [];
12986
12987			epoEventHandlers( epoObject );
12988			tm_set_upload_fields( epoObject );
12989			tm_product_image( epoObject );
12990
12991			jWindow.trigger( 'epo-after-init-in-timeout', { epo: epoObject } );
12992			epoObject.noEpoUpdate = false;
12993			cart.trigger( 'tm-epo-check-dpd' );
12994			cart.trigger( {
12995				type: 'tm-epo-update',
12996				rules: 'init'
12997			} );
12998
12999			form.data( 'epo_loaded', true );
13000		};
13001
13002		form.off( eventName ).on( eventName, function() {
13003			run();
13004		} );
13005
13006		setTimeout( function() {
13007			form.trigger( eventName );
13008		}, window.tcVariationDelayCheck || 2000 );
13009
13010		if ( variationsFormIsLoaded ) {
13011			form.trigger( eventName );
13012		}
13013
13014		jWindow.trigger( 'epo-after-init', { epo: epoObject } );
13015	}
13016
13017	function detect_variation_swatches_interval( epoObject ) {
13018		var $id = requestAnimationFrame( function() {
13019			detect_variation_swatches_interval( epoObject );
13020		} );
13021		var obj = epoObject.variations_form;
13022		var bound = obj.data( 'bound' );
13023		var eventName = epoObject.is_associated ? 'tc_variation_form.cpf' : 'wc_variation_form.cpf';
13024
13025		if ( bound ) {
13026			cancelAnimationFrame( $id );
13027			run_wc_variation_form_cpf( epoObject );
13028			obj.trigger( eventName );
13029		}
13030	}
13031
13032	function manualInitEPO( epoObject, item, itemCart, itemEpoContainer, main_product ) {
13033		var epoObjectOriginal = $.extend( true, {}, epoObject );
13034		var product_id = itemEpoContainer.attr( 'data-product-id' );
13035		var epo_id = itemEpoContainer.attr( 'data-epo-id' );
13036		var product_id_selector = '.tm-product-id-' + product_id;
13037		var epo_id_selector = "[data-epo-id='" + epo_id + "']";
13038		var epoEventId = 'p' + product_id + 'e' + epo_id;
13039		var this_epo_container = $( tcAPI.epoSelector + product_id_selector + epo_id_selector );
13040		var this_totals_container = $( '.tc-totals-form' + product_id_selector + epo_id_selector );
13041		var this_epo_totals_container = $( '.tc-epo-totals' + product_id_selector + epo_id_selector );
13042
13043		epoObject.isManual = true;
13044
13045		$.tcepo.formSubmitEvents[ epoEventId ] = [];
13046		$.tcepo.errorObject[ epoEventId ] = false;
13047		$.tcepo.initialActivation[ epoEventId ] = false;
13048
13049		epoObject.product_id = product_id;
13050		epoObject.product_id_selector = product_id_selector;
13051		epoObject.epo_id = epo_id;
13052		epoObject.epo_id_selector = epo_id_selector;
13053		epoObject.epoEventId = epoEventId;
13054		epoObject.noEpoUpdate = true;
13055		epoObject.thisForm = item;
13056		epoObject.this_epo_container = this_epo_container;
13057		epoObject.this_totals_container = this_totals_container;
13058		epoObject.this_epo_totals_container = this_epo_totals_container;
13059
13060		tm_lazyload();
13061		main_product.find( '.tm-collapse' ).tmtoggle();
13062		main_product.find( '.tm-section-link' ).tmsectionpoplink();
13063
13064		tm_set_datepicker( item );
13065		setRangePickers( item );
13066		setRangePickersEvents();
13067		tm_set_repeaters( item, epoObject );
13068		tm_css_styles( item );
13069		tm_set_color_pickers( itemEpoContainer );
13070		tm_set_lightbox( itemEpoContainer.find( '.tc-lightbox-image' ).not( '.tm-extra-product-options-variations .radio-image' ) );
13071
13072		// Start Condition Logic
13073		cpf_section_logic( epoObject );
13074		cpf_element_logic( epoObject );
13075		run_cpfdependson( itemEpoContainer );
13076
13077		$.tcToolTip( item.find( '.tm-tooltip' ) );
13078		epoEventHandlers( epoObject, item, itemCart );
13079
13080		epoObject.noEpoUpdate = false;
13081
13082		itemCart.trigger( {
13083			type: 'tm-epo-update',
13084			norules: 2
13085		} );
13086		setTimeout( function() {
13087			epoObject.main_cart.trigger( {
13088				type: 'tm-epo-update',
13089				epoObject: epoObjectOriginal,
13090				norules: 1
13091			} );
13092		}, 200 );
13093		fix_stock( itemCart, item );
13094	}
13095
13096	function tm_init_epo( main_product, is_quickview, product_id, epo_id, associated_connect, mainEpoObject, reactivate ) {
13097		// Holds the main cart when using Composite Products
13098		var main_cart = false;
13099		var main_epo_inside_form = false;
13100		var main_totals_inside_form = false;
13101		var epoEventId;
13102		var has_epo = typeof product_id !== 'undefined';
13103		var not_has_epo = false;
13104		var add_to_cart_field;
13105		var product_id_selector;
13106		var epo_id_selector;
13107		var this_epo_container;
13108		var this_totals_container;
13109		var this_epo_totals_container;
13110		var epo_object;
13111		var variations_form;
13112		var detect_variation_swatches = $( '.variation_form_section .variations-table' ).length > 0;
13113		var is_associated = false;
13114
13115		main_product = $( main_product );
13116
13117		if ( main_product.is( '.tc-init' ) && ! reactivate ) {
13118			return true;
13119		}
13120
13121		if ( is_quickview ) {
13122			errorContainer = main_product;
13123		} else {
13124			errorContainer = $( window );
13125		}
13126
13127		jWindow.trigger( 'tm-epo-init-start' );
13128
13129		if ( ! has_epo ) {
13130			if ( main_product.is( '.product' ) ) {
13131				not_has_epo = true;
13132				has_epo = jBody.find( tcAPI.epoSelector ).length;
13133			}
13134		}
13135
13136		// return if product has no extra options and the totals box is not enabled for all products
13137		if ( ! has_epo && TMEPOJS.tm_epo_enable_final_total_box_all === 'no' && ! main_product.is( '.tm-no-options-composite' ) ) {
13138			jWindow.trigger( 'tm-epo-init-end-no-options' );
13139			return;
13140		}
13141
13142		// set the main_product variable again for products that have no extra options
13143		if ( not_has_epo ) {
13144			jWindow.trigger( 'tm-epo-init-no-options' );
13145			if ( main_product.is( '.product' ) && ! ( main_product.is( '.tm-no-options-pxq' ) || main_product.is( '.tm-no-options-composite' ) ) ) {
13146				main_product = jBody;
13147			}
13148		}
13149
13150		if ( ! product_id ) {
13151			add_to_cart_field = main_product.find( tcAPI.addToCartSelector ).last();
13152			if ( add_to_cart_field.length > 0 ) {
13153				product_id = add_to_cart_field.val();
13154			} else {
13155				add_to_cart_field = $( '.tc-totals-form.tm-totals-form-main' );
13156				product_id = add_to_cart_field.attr( 'data-product-id' );
13157			}
13158			if ( ! product_id ) {
13159				product_id = '';
13160			}
13161		}
13162
13163		if ( ! epo_id ) {
13164			epo_id = parseInt( main_product.find( 'input.tm-epo-counter' ).last().val(), 10 );
13165
13166			if ( ! Number.isFinite( epo_id ) ) {
13167				epo_id = '';
13168			}
13169		}
13170
13171		product_id_selector = '.tm-product-id-' + product_id;
13172		epo_id_selector = "[data-epo-id='" + epo_id + "']";
13173		this_epo_container = $( tcAPI.epoSelector + product_id_selector + epo_id_selector );
13174		this_totals_container = $( '.tc-totals-form' + product_id_selector + epo_id_selector );
13175		this_epo_totals_container = $( '.tc-epo-totals' + product_id_selector + epo_id_selector );
13176		variations_form = main_product.find( '.variations_form' ).not( '.composite_component .variations_form' ).first();
13177		epoEventId = 'p' + product_id + 'e' + epo_id;
13178
13179		if ( variations_form && variations_form.attr( 'data-product_id' ) ) {
13180			if ( variations_form.attr( 'data-product_id' ) !== product_id ) {
13181				variations_form = main_product.find( ".variations_form[data-product_id='" + product_id + "']" );
13182			}
13183		}
13184
13185		main_cart = get_main_cart( main_product, main_product, 'form', product_id );
13186		if ( main_cart.length === 0 ) {
13187			if ( main_product.is( '.tc-shortcode-wrap' ) ) {
13188				main_cart = get_main_cart( this_totals_container, this_totals_container, '.tc-totals-form', product_id );
13189			} else if ( main_product.is( '.tc-epo-element-product-container' ) ) {
13190				main_cart = main_product.find( tcAPI.associatedEpoCart );
13191				// should never be 0
13192				if ( main_cart.length === 0 ) {
13193					main_cart = this_epo_container.parent( tcAPI.associatedEpoSelector );
13194					if ( main_cart.length === 0 ) {
13195						main_cart = main_product.find( '.tc-epo-element-product-container-right' );
13196					}
13197				}
13198				is_associated = true;
13199			}
13200		}
13201
13202		if ( is_associated && variations_form.length === 0 && main_product.is( '.variations_form' ) ) {
13203			variations_form = main_product;
13204		}
13205
13206		$.tcepo.formSubmitEvents[ epoEventId ] = [];
13207		$.tcepo.errorObject[ epoEventId ] = false;
13208		$.tcepo.initialActivation[ epoEventId ] = false;
13209
13210		if ( main_cart.find( tcAPI.epoSelector ).length > 0 ) {
13211			main_epo_inside_form = true;
13212		}
13213		if ( main_cart.find( '.tc-totals-form' ).length > 0 ) {
13214			main_totals_inside_form = true;
13215		}
13216
13217		if ( ! main_totals_inside_form ) {
13218			$.tcepo.formSubmitEvents[ epoEventId ][ $.tcepo.formSubmitEvents[ epoEventId ].length ] = {
13219				trigger: function() {
13220					return true;
13221				},
13222				on_true: function() {
13223					// hidden fields see totals.php
13224					var epos_hidden = $( '.tc-totals-form.tm-product-id-' + product_id + "[data-epo-id='" + epo_id + "']" ).tcClone();
13225					var formepo = $( '<div class="tm-hidden tm-formepo-normal"></div>' );
13226
13227					main_cart.find( '.tm-formepo-normal' ).remove();
13228					formepo.append( epos_hidden );
13229					main_cart.append( formepo );
13230					return true;
13231				},
13232				on_false: function() {
13233					setTimeout( function() {
13234						$( '.tm-formepo-normal' ).remove();
13235					}, 100 );
13236				}
13237			};
13238		}
13239		if ( ! main_epo_inside_form ) {
13240			$.tcepo.formSubmitEvents[ epoEventId ][ $.tcepo.formSubmitEvents[ epoEventId ].length ] = {
13241				trigger: function() {
13242					return true;
13243				},
13244				on_true: function() {
13245					// visible fields
13246					var epos = $( tcAPI.epoSelector + '.tm-product-id-' + product_id + "[data-epo-id='" + epo_id + "']" )
13247						.tcClone()
13248						.addClass( 'formepo' );
13249					var formepo = $( '<div class="tm-hidden tm-formepo"></div>' );
13250
13251					main_cart.find( '.tm-formepo' ).remove();
13252					formepo.append( epos );
13253
13254					main_cart.append( formepo );
13255					return true;
13256				},
13257				on_false: function() {
13258					setTimeout( function() {
13259						$( '.tm-formepo' ).remove();
13260					}, 100 );
13261				}
13262			};
13263		}
13264
13265		epo_object = {
13266			main_product: main_product,
13267			main_cart: main_cart,
13268			epo_id: epo_id,
13269			form: get_main_form( main_product ),
13270			main_epo_inside_form: main_epo_inside_form,
13271			product_id_selector: product_id_selector,
13272			epo_id_selector: epo_id_selector,
13273			product_id: product_id,
13274			this_epo_container: this_epo_container,
13275			this_totals_container: this_totals_container,
13276			this_epo_totals_container: this_epo_totals_container,
13277			qtySelector: tcAPI.qtySelector,
13278			manualInitEPO: manualInitEPO,
13279			epoEventId: epoEventId,
13280			variations_form: variations_form,
13281			has_epo: has_epo,
13282			is_quickview: is_quickview,
13283			is_associated: is_associated,
13284			is_epo_shortcode: this_epo_container.is( '.tc-shortcode' ),
13285			mainEpoObject: mainEpoObject,
13286			associated_connect: associated_connect,
13287			noEpoUpdate: true
13288		};
13289
13290		$( epo_object.form ).data( 'epo_object', epo_object );
13291		this_epo_container.data( 'epo_object', epo_object );
13292
13293		main_cart.data( 'product_id', product_id ).data( 'epo_id', epo_id ).data( 'product_id_selector', product_id_selector ).data( 'epo_id_selector', epo_id_selector );
13294
13295		// tm_set_expanables();
13296		tm_set_checkboxes_rules( epo_object );
13297		tm_set_radiobutton_rules();
13298		tm_set_upload_rules( epo_object );
13299		tm_set_datepicker( this_epo_container );
13300		setRangePickers( this_epo_container );
13301		setRangePickersEvents();
13302		tm_set_repeaters( this_epo_container, epo_object );
13303		tm_set_url_fields();
13304
13305		$.tcToolTip( this_epo_container.find( '.tm-tooltip' ) );
13306
13307		this_epo_container.find( '.tm-collapse' ).tmtoggle();
13308		this_epo_container.find( '.tm-section-link' ).tmsectionpoplink();
13309
13310		if ( reactivate ) {
13311			this_epo_container.addClass( 'reactivate' );
13312		}
13313
13314		if ( variations_form.length > 0 ) {
13315			if ( reactivate ) {
13316				variations_form.data( 'epo_loaded', false );
13317			}
13318			this_epo_totals_container.data( 'price', false );
13319			if ( detect_variation_swatches ) {
13320				detect_variation_swatches_interval( epo_object );
13321			} else {
13322				run_wc_variation_form_cpf( epo_object );
13323			}
13324		} else {
13325			setTimeout( function() {
13326				// Start Condition Logic
13327				cpf_section_logic( epo_object );
13328				cpf_element_logic( epo_object );
13329
13330				jWindow.on( 'epoEventHandlers', function() {
13331					run_cpfdependson( this_epo_container );
13332					tm_lazyload();
13333				} );
13334
13335				// Init field price rules
13336				$.tcepo.lateFieldsPrices[ epoEventId ] = [];
13337				epoEventHandlers( epo_object );
13338				tm_set_upload_fields( epo_object );
13339				tm_product_image( epo_object );
13340
13341				jWindow.trigger( 'epo-after-init-in-timeout', { epo: epo_object } );
13342				main_cart.trigger( 'tm-epo-check-dpd' );
13343				epo_object.noEpoUpdate = false;
13344				main_cart.trigger( {
13345					type: 'tm-epo-update',
13346					rules: 'init'
13347				} );
13348			}, 20 );
13349			jWindow.trigger( 'epo-after-init', { epo: epo_object } );
13350		}
13351
13352		tm_css_styles( this_epo_container );
13353		tm_set_color_pickers( this_epo_container );
13354		tm_set_lightbox( this_epo_container.find( '.tc-lightbox-image' ).not( '.tm-extra-product-options-variations .radio-image' ) );
13355		tm_theme_specific_actions( epo_object );
13356		tc_compatibility( epo_object );
13357
13358		if ( ! is_associated ) {
13359			tm_floating_totals( this_epo_totals_container, is_quickview, main_cart );
13360			tm_form_submit_event( epo_object );
13361			epo_object = addShowHidetoEpoObject( epo_object, epoEventId, epo_object );
13362			tm_show_hide_add_to_cart_button( main_product, epo_object );
13363		}
13364
13365		jWindow.trigger( 'tm-epo-init-end', {
13366			epo: epo_object,
13367			replace_suffixes_in_html: replace_suffixes_in_html
13368		} );
13369
13370		return epo_object;
13371	}
13372
13373	function manual_init( container, reactivate ) {
13374		var $this = $( container );
13375		var product_id = $this.attr( 'data-product-id' );
13376		var epo_id = $this.attr( 'data-epo-id' );
13377		var quickview_floating = false;
13378		var testForm = $this.parent();
13379		if ( ! testForm.is( 'form' ) ) {
13380			testForm = $this.closest( 'form' );
13381			if ( ! testForm.is( 'form' ) ) {
13382				testForm = $this.parent();
13383			}
13384		}
13385		testForm = testForm.parent();
13386
13387		tm_init_epo( testForm, quickview_floating, product_id, epo_id, undefined, undefined, reactivate );
13388	}
13389
13390	function init_epo_plugin() {
13391		var epo_container;
13392		var epo_options_container;
13393
13394		if ( TMEPOJS.tm_epo_no_lazy_load === 'no' ) {
13395			$.extend( $.lazyLoadXT, {
13396				autoInit: false,
13397				selector: 'img.tmlazy',
13398				srcAttr: 'data-original',
13399				visibleOnly: false,
13400				updateEvent: $.lazyLoadXT.updateEvent + ' tmlazy'
13401			} );
13402		}
13403		/*
13404		 * tm-no-options-pxq = product has not options but the "Enable Final total box for all products" is on
13405		 * tm-no-options-composite = product is a composite product with no options but at least one of its bundles have options
13406		 */
13407		epo_container = $( '.tm-no-options-pxq, .tm-no-options-composite' );
13408
13409		if ( epo_container.length > 0 ) {
13410			// Special cases
13411			// -------------
13412			// Price x Quantity display (.tm-no-options-pxq) & composite
13413			// without option but a component has extra options
13414			// (.tm-no-options-composite)
13415
13416			epo_container.addClass( 'initializing' );
13417
13418			epo_container.toArray().forEach( function( product_wrap ) {
13419				var inputepoid;
13420				product_wrap = $( product_wrap );
13421				inputepoid = product_wrap.find( 'input.tm-epo-counter' );
13422				if ( inputepoid.length > 1 ) {
13423					inputepoid.toArray().forEach( function( ec ) {
13424						var currentepoid = $( ec );
13425						var currentcart = currentepoid.closest( '.cart' );
13426						var currentcartparent = currentcart.parent();
13427						if ( currentcartparent.is( 'form' ) ) {
13428							currentcartparent = currentcartparent.parent();
13429						}
13430
13431						if ( ! currentcartparent.is( '.initializing' ) ) {
13432							tm_init_epo( currentcartparent, false, undefined, parseInt( currentepoid.val(), 10 ) );
13433						}
13434					} );
13435				} else {
13436					tm_init_epo( product_wrap, false );
13437				}
13438				epo_container.removeClass( 'initializing' );
13439			} );
13440		}
13441
13442		// The setTimeout is used for compatibility with
13443		// skeleton screen mode that some themes have
13444
13445		setTimeout( function() {
13446			try {
13447				// new main way of calling tm_init_epo
13448				// -----------------------------------
13449				// Normal product pages
13450
13451				epo_options_container = $( tcAPI.epoSelector ).not( tcAPI.associatedEpoSelector + ' ' + tcAPI.epoSelector + ', .tm-no-options-pxq, .tm-no-options-composite, .wc-product-table ' + tcAPI.epoSelector );
13452
13453				if ( epo_options_container.length > 0 ) {
13454					epo_container.addClass( 'initializing' );
13455					epo_options_container.toArray().forEach( function( ec ) {
13456						var $this = $( ec );
13457						var product_id = $this.attr( 'data-product-id' );
13458						var epo_id = $this.attr( 'data-epo-id' );
13459						var quickview_floating = false;
13460						var jProductWrap;
13461						var addInputs = false;
13462						var inputepoid;
13463
13464						// First check if we are in a loop.
13465						jProductWrap = $this.closest( '.tc-after-shop-loop.tm-has-options' );
13466
13467						if ( jProductWrap.length === 0 ) {
13468							// Check based on plugin add to cart selector.
13469							jProductWrap = $( tcAPI.tcAddToCartSelector + "[data-epo-id='" + epo_id + "'][value='" + product_id + "']" )
13470								.closest( 'form,.cart' )
13471								.first()
13472								.parent();
13473							// Check based on native add to cart selector.
13474							if ( jProductWrap.length === 0 ) {
13475								jProductWrap = $( tcAPI.addToCartSelector + "[value='" + product_id + "']" )
13476									.closest( 'form,.cart' )
13477									.first()
13478									.parent();
13479								if ( jProductWrap.length === 0 ) {
13480									// Check if we are in a shortcode
13481									jProductWrap = $this.closest( 'form,.cart' ).first().parent( '.tm-has-options' );
13482									if ( jProductWrap.length === 0 ) {
13483										if ( $this.is( '.tc-shortcode' ) ) {
13484											jProductWrap = $this.wrap( '<div class="tc-shortcode-wrap tc-wrap-' + epo_id + '"></div>' );
13485											jProductWrap = $this.parent();
13486										}
13487										if ( jProductWrap.length > 0 ) {
13488											addInputs = true;
13489										}
13490									}
13491								}
13492							}
13493						} else {
13494							addInputs = true;
13495						}
13496
13497						if ( jProductWrap.length > 0 ) {
13498							if ( addInputs ) {
13499								// in shop (variation logic will not work here)
13500								quickview_floating = true;
13501								$this
13502									.closest( 'form,.cart' )
13503									.first()
13504									.append( $( '<input name="add-to-cart" value="' + product_id + '" type="hidden">' ) );
13505								$this.closest( 'form,.cart' ).first().append( $( '<input type="hidden" value="" class="variation_id" name="variation_id">' ) );
13506							}
13507
13508							if ( jProductWrap.is( 'form' ) ) {
13509								jProductWrap = jProductWrap.parent();
13510							}
13511
13512							inputepoid = jProductWrap.find( 'input.tm-epo-counter' );
13513							if ( inputepoid.length > 1 ) {
13514								inputepoid.toArray().forEach( function( c ) {
13515									var currentepoid = $( c );
13516									var currentcart = currentepoid.closest( '.cart' );
13517									var currentcartparent = currentcart.parent();
13518									if ( currentcartparent.is( 'form' ) ) {
13519										currentcartparent = currentcartparent.parent();
13520									}
13521
13522									if ( ! currentcartparent.is( '.initializing' ) ) {
13523										tm_init_epo( currentcartparent, quickview_floating, product_id, parseInt( currentepoid.val(), 10 ) );
13524									}
13525								} );
13526							} else {
13527								tm_init_epo( jProductWrap, quickview_floating, product_id, epo_id );
13528							}
13529						}
13530					} );
13531					epo_container.removeClass( 'initializing' );
13532				}
13533			} catch ( err ) {
13534				window.console.log( err );
13535				errorObject = err;
13536			}
13537		}, 1 );
13538	}
13539
13540	$.tcepo.tm_init_epo = function( main_product, is_quickview, product_id, epo_id ) {
13541		tm_init_epo( main_product, is_quickview, product_id, epo_id );
13542	};
13543
13544	$.tcepo.tmLazyloadContainer = function( container ) {
13545		tmLazyloadContainer = container;
13546	};
13547
13548	jWindow.on( 'tc_manual_init', function( evt, container ) {
13549		var reactivate;
13550		if ( 'container' in container && 'reactivate' in container ) {
13551			reactivate = container.reactivate;
13552			container = container.container;
13553		}
13554		manual_init( container, reactivate );
13555	} );
13556
13557	function tcAjaxAddToCart( $this ) {
13558		var _pid;
13559		var epos;
13560		var _cpf_product_price;
13561		var _dynamic_product_price;
13562		var _override_product_price;
13563		var form_prefix;
13564		var epoid;
13565		var obj;
13566		var data;
13567		var tcTotalsForm;
13568
13569		currentAjaxButton = $this;
13570		_pid = currentAjaxButton.attr( 'data-product_id' );
13571		if ( undefined === _pid ) {
13572			_pid = currentAjaxButton.val();
13573		}
13574
13575		if ( undefined !== _pid ) {
13576			epoid = currentAjaxButton.closest( '.cart' ).find( '.tm-epo-counter' ).val();
13577			if ( ! epoid ) {
13578				epoid = currentAjaxButton.attr( 'data-epo-id' );
13579				if ( ! epoid ) {
13580					return;
13581				}
13582			}
13583			if ( currentAjaxButton.closest( '.tm-has-options' ).length !== 1 && currentAjaxButton.attr( 'data-epo-id' ) === undefined ) {
13584				return;
13585			}
13586
13587			obj = {};
13588
13589			epos = $( tcAPI.epoSelector + '.tm-product-id-' + _pid + '[data-epo-id="' + epoid + '"]' );
13590
13591			if ( epos.length > 1 ) {
13592				if ( epos.filter( '.formepo' ) ) {
13593					epos = epos.filter( '.formepo' );
13594				} else {
13595					epos = epos.first();
13596				}
13597			}
13598
13599			if ( epos.length === 1 ) {
13600				tcTotalsForm = $( '.tc-totals-form.tm-product-id-' + _pid + '[data-epo-id="' + epoid + '"]' );
13601				_cpf_product_price = tcTotalsForm.find( '.cpf-product-price' ).val();
13602				_dynamic_product_price = tcTotalsForm.find( '.cpf-dynamic-product-price' ).val();
13603				_override_product_price = tcTotalsForm.find( '.cpf-override-product-price' ).val();
13604				form_prefix = tcTotalsForm.find( '.tc_form_prefix' ).val();
13605
13606				obj = $.extend( obj, {
13607					tcajax: 1,
13608					tcaddtocart: _pid,
13609					cpf_product_price: _cpf_product_price,
13610					dynamic_product_price: _dynamic_product_price,
13611					override_product_price: _override_product_price
13612				} );
13613				if ( form_prefix ) {
13614					obj.tc_form_prefix = form_prefix;
13615				}
13616			}
13617
13618			data = currentAjaxButton.data();
13619			TMEPOJS.ajaxbuttondata = $.epoAPI.util.deepCopyArray( data );
13620			TMEPOJS.ajaxbutton = currentAjaxButton;
13621
13622			currentAjaxButton.removeData();
13623			currentAjaxButton.data( $.extend( data, epos.tcSerializeObject(), obj ) );
13624
13625			TMEPOJS.ajaxdata = {
13626				epos: epos,
13627				_pid: _pid,
13628				data: data
13629			};
13630		}
13631	}
13632
13633	function ajaxAddToCartFunctions() {
13634		// Betheme ajax add to cart.
13635		$( document ).on( 'click.tcajax', 'body.mfn-ajax-add-to-cart .single_add_to_cart_button:not(.disabled)', function() {
13636			var formepo;
13637			var $this = $( this );
13638			tcAjaxAddToCart( $this );
13639			TMEPOJS.ajaxdata.cart = $this.closest( '.cart' );
13640			TMEPOJS.ajaxdata.cart.find( '.tm-formepo' ).remove();
13641			formepo = $( "<div class='tm-hidden tm-formepo'></div>" );
13642			formepo.append( TMEPOJS.ajaxdata.epos.tcClone().addClass( 'formepo' ) );
13643			$this.after( formepo );
13644		} );
13645
13646		jBody.on( 'click.tcajax', '.ajax_add_to_cart', function() {
13647			tcAjaxAddToCart( $( this ) );
13648			if ( undefined !== TMEPOJS.ajaxdata ) {
13649				delete TMEPOJS.ajaxdata;
13650			}
13651		} );
13652
13653		jBody.on( 'click.tcajax', '.single_add_to_cart_button', function() {
13654			currentAddToCartButton = $( this );
13655		} );
13656
13657		$( document.body ).on( 'added_to_cart', function() {
13658			if ( TMEPOJS.ajaxbuttondata && TMEPOJS.ajaxbutton instanceof $ ) {
13659				TMEPOJS.ajaxbutton.removeData();
13660				TMEPOJS.ajaxbutton.data( TMEPOJS.ajaxbuttondata );
13661			}
13662		} );
13663	}
13664
13665	// This needs to run here to register our event handlers before WooCommerce.
13666	ajaxAddToCartFunctions();
13667
13668	// document ready
13669	$( function() {
13670		tcAPI = $.epoAPI.applyFilter( 'tc_api', tcAPI );
13671
13672		jWindow.on( 'lazyLoadXToncomplete', function() {
13673			$( '.tm-owl-slider' ).toArray().forEach( function( slider ) {
13674				$( slider ).trigger( 'refresh.owl.carousel' );
13675			} );
13676		} );
13677
13678		jWindow.on( 'tc_init_epo_plugin', function( evt ) {
13679			init_epo_plugin( evt );
13680		} );
13681
13682		jWindow.on( 'tcShowLastError', function() {
13683			window.console.log( errorObject );
13684		} );
13685
13686		$.ajaxPrefilter( function( options, originalOptions ) {
13687			var found = false;
13688			var hashes;
13689			var hash;
13690			var i;
13691			var params;
13692			var $thisbutton;
13693			var _data;
13694			var _urldata;
13695			var _pid;
13696			var epos;
13697			var _cpf_product_price;
13698			var _dynamic_product_price;
13699			var _override_product_price;
13700			var form_prefix;
13701			var obj;
13702			var oldData;
13703			var formData;
13704			var can_be_added = false;
13705			var associativeArray = {};
13706			var tcTotalsForm;
13707
13708			if ( TMEPOJS.tm_epo_enable_in_shop === 'yes' ) {
13709				hashes = options.url.split( '?' );
13710
13711				if ( hashes && hashes.length >= 1 ) {
13712					hashes = hashes[ 1 ];
13713					if ( hashes ) {
13714						hash = hashes.split( '&' );
13715						for ( i = 0; i < hash.length; i += 1 ) {
13716							params = hash[ i ].split( '=' );
13717							if ( params.length >= 1 ) {
13718								if ( params[ 0 ] && params[ 1 ] && params[ 0 ] === 'wc-ajax' && params[ 1 ] === 'add_to_cart' ) {
13719									found = true;
13720								}
13721							}
13722						}
13723						if ( found ) {
13724							options.originalsuccess = options.success;
13725							options.success = function( response ) {
13726								if ( response && response.error && response.product_url ) {
13727									if ( currentAjaxButton && currentAjaxButton.length === 1 ) {
13728										$thisbutton = currentAjaxButton;
13729									}
13730									$thisbutton = $( ".ajax_add_to_cart[data-product_id='" + originalOptions.data.product_id + "']" );
13731									$thisbutton.removeClass( 'added' );
13732									$thisbutton.removeClass( 'loading' );
13733								} else {
13734									options.originalsuccess.call( null, response );
13735								}
13736							};
13737						}
13738					}
13739				}
13740			}
13741
13742			if ( FormData && originalOptions.data ) {
13743				_data = originalOptions.data;
13744				if ( typeof originalOptions.data === 'string' ) {
13745					_data = $.epoAPI.util.parseParams( originalOptions.data );
13746				}
13747				if ( typeof _data[ 0 ] === 'object' ) {
13748					_data.forEach( function( item ) {
13749						associativeArray[ item.name ] = item.value;
13750					} );
13751					_data = associativeArray;
13752				}
13753
13754				_urldata = [];
13755				if ( originalOptions.url && originalOptions.url.indexOf ) {
13756					_urldata = $.epoAPI.util.parseParams( originalOptions.url.slice( originalOptions.url.indexOf( '?' ) + 1 ) );
13757				}
13758
13759				if ( 'quantity' in _data && _data.tcaddtocart && ( _data.product_id || _data[ 'add-to-cart' ] || _urldata.product_id || _urldata[ 'add-to-cart' ] ) ) {
13760					can_be_added = true;
13761					_pid = _data.tcaddtocart;
13762				} else if ( Array.isArray( _data ) ) {
13763					can_be_added = _data.some( function( item ) {
13764						return item.name === 'quantity';
13765					} ) && _data.some( function( item ) {
13766						return item.name === 'add-to-cart';
13767					} ) && _data.some( function( item ) {
13768						return item.name === 'tcaddtocart';
13769					} );
13770					_pid = _data.find( function( item ) {
13771						return item.name === 'tcaddtocart';
13772					} );
13773					if ( _pid ) {
13774						_pid = _pid.value;
13775					} else {
13776						_pid = false;
13777					}
13778				}
13779
13780				if ( ! _pid ) {
13781					if ( 'qty' in _data && _data.tcaddtocart ) {
13782						can_be_added = true;
13783						_pid = _data.tcaddtocart;
13784					}
13785				}
13786
13787				if ( can_be_added ) {
13788					if ( currentAjaxButton && currentAjaxButton.length === 1 && currentAjaxButton.closest( '.tm-has-options' ).length === 1 ) {
13789						epos = currentAjaxButton.closest( '.tm-has-options' ).find( tcAPI.epoSelector + '.tm-product-id-' + _pid );
13790					} else {
13791						epos = $( tcAPI.epoSelector + '.tm-product-id-' + _pid );
13792					}
13793
13794					if ( epos.length > 1 ) {
13795						if ( epos.filter( '.formepo' ) ) {
13796							epos = epos.filter( '.formepo' );
13797						} else {
13798							epos = epos.first();
13799						}
13800					}
13801					if ( epos.length === 1 ) {
13802						tcTotalsForm = $( '.tc-totals-form.tm-product-id-' + _pid );
13803						_cpf_product_price = tcTotalsForm.find( '.cpf-product-price' ).val();
13804						_dynamic_product_price = tcTotalsForm.find( '.cpf-dynamic-product-price' ).val();
13805						_override_product_price = tcTotalsForm.find( '.cpf-override-product-price' ).val();
13806						form_prefix = tcTotalsForm.find( '.tc_form_prefix' ).val();
13807						obj = {
13808							tcajax: 1,
13809							tcaddtocart: _pid,
13810							cpf_product_price: _cpf_product_price,
13811							dynamic_product_price: _dynamic_product_price,
13812							override_product_price: _override_product_price
13813						};
13814						if ( form_prefix ) {
13815							obj.tc_form_prefix = form_prefix;
13816						}
13817
13818						oldData = $.epoAPI.util.parseParams( options.data, true );
13819						oldData = $.extend( oldData, epos.tcSerializeObject(), obj );
13820						formData = new FormData();
13821
13822						Object.keys( oldData ).forEach( function( key ) {
13823							if ( key ) {
13824								formData.append( key, oldData[ key ] );
13825							}
13826						} );
13827
13828						epos.find( ':file' )
13829							.toArray()
13830							.forEach( function( el ) {
13831								for ( i = 0; i < $( el )[ 0 ].files.length; i++ ) {
13832									if ( ! el.multiple ) {
13833										formData.delete( $( el ).attr( 'name' ) );
13834									}
13835									formData.append( $( el ).attr( 'name' ), $( el )[ 0 ].files[ i ] );
13836								}
13837							} );
13838
13839						options.data = formData;
13840						options.contentType = false;
13841						options.cache = false;
13842						options.processData = false;
13843					}
13844				}
13845			}
13846		} );
13847
13848		jDocument.ajaxSuccess( function( event, request, settings ) {
13849			// quickview plugins
13850			var qv_container = TMEPOJS.quickview_array || 'null';
13851			var fromaddons = TMEPOJS.quickview_container || 'null';
13852			var added = {};
13853			var selectors;
13854			var container;
13855			var product_id;
13856			var epo_id;
13857			var noProductCheck;
13858			var testContainer;
13859			var parsedUrl;
13860			var time = 1;
13861			var detectContainer;
13862			var requestContainer;
13863
13864			if ( undefined !== TMEPOJS.ajaxdata ) {
13865				TMEPOJS.ajaxdata.cart.find( '.tm-formepo' ).remove();
13866				delete TMEPOJS.ajaxdata;
13867			}
13868
13869			parsedUrl = $.epoAPI.util.parseParams( settings.data );
13870			if ( parsedUrl.action === 'wc_epo_get_associated_product_html' ) {
13871				return;
13872			}
13873
13874			$( '.tm-formepo-normal' ).remove();
13875			$( '.tm-formepo' ).remove();
13876
13877			//fix for menu cart pop up
13878			$( '.tm-cart-link' ).tmpoplink();
13879
13880			qv_container = $.epoAPI.util.parseJSON( qv_container );
13881
13882			fromaddons = $.epoAPI.util.parseJSON( fromaddons );
13883
13884			for ( selectors in fromaddons ) {
13885				if ( Object.prototype.hasOwnProperty.call( fromaddons, selectors ) ) {
13886					added[ fromaddons[ selectors ][ 0 ] ] = $( fromaddons[ selectors ][ 1 ] );
13887				}
13888			}
13889
13890			$.extend( qv_container, added );
13891
13892			detectContainer = function() {
13893				var keyfound = false;
13894				Object.keys( qv_container ).forEach( function( key ) {
13895					if ( $( qv_container[ key ] ).length ) {
13896						keyfound = key;
13897					}
13898				} );
13899				return keyfound;
13900			};
13901			requestContainer = function( times ) {
13902				var id = requestAnimationFrame( function() {
13903					setTimeout( function() {
13904						requestContainer( times - 1 );
13905					}, 200 );
13906				} );
13907				var key = detectContainer();
13908				var epoContainer;
13909				var initepo;
13910
13911				if ( key || 0 === times ) {
13912					cancelAnimationFrame( id );
13913					if ( key ) {
13914						noProductCheck = false;
13915						container = $( qv_container[ key ] );
13916						if ( container.length > 1 && currentAddToCartButton && currentAddToCartButton.length ) {
13917							container = currentAddToCartButton.closest( qv_container[ key ] );
13918						}
13919						if ( container.length > 1 && ( key !== 'quickview_pro' && key !== 'us_list_item_popup_content' ) ) {
13920							return true;
13921						}
13922
13923						if ( key === 'woothemes_quick_view' && container.is( '.fusion-woocommerce-quick-view-container' ) ) {
13924							return true;
13925						}
13926
13927						if ( key === 'fusion_quick_view_load' && container.find( tcAPI.epoSelector ).length === 0 ) {
13928							return true;
13929						}
13930
13931						if ( key === 'woodmart_quick_shop' ) {
13932							parsedUrl = $.epoAPI.util.parseParams( settings.url );
13933							if ( parsedUrl.action === 'woodmart_quick_shop' ) {
13934								testContainer = $( $.epoAPI.util.escapeSelector( qv_container[ key ] + '.post-' + parsedUrl.id ) );
13935								if ( testContainer.length ) {
13936									container = testContainer;
13937									noProductCheck = true;
13938								}
13939							}
13940						}
13941						if ( key === 'woodmart_quick_view' ) {
13942							parsedUrl = $.epoAPI.util.parseParams( settings.url );
13943							if ( parsedUrl.action === 'woodmart_quick_view' ) {
13944								testContainer = $( $.epoAPI.util.escapeSelector( qv_container[ key ] + '.post-' + parsedUrl.id ) );
13945								if ( testContainer.length ) {
13946									container = testContainer;
13947									noProductCheck = true;
13948								}
13949							}
13950						}
13951
13952						if ( key === 'quickview_pro' ) {
13953							parsedUrl = settings.url.split( '/' );
13954							if ( parsedUrl.length ) {
13955								testContainer = $( $.epoAPI.util.escapeSelector( qv_container[ key ] + ' .post-' + parsedUrl[ parsedUrl.length - 1 ] ) );
13956								if ( testContainer.length ) {
13957									container = testContainer;
13958									noProductCheck = true;
13959								}
13960							}
13961						}
13962
13963						if ( key === 'us_list_item_popup_content' || key === 'exwoofood_booking_info' || key === 'wqv_popup_content' || key === 'wp_food' || key === 'jet_popup_get_content' ) {
13964							noProductCheck = true;
13965						}
13966
13967						if ( key === 'woofood' && settings.data ) {
13968							parsedUrl = $.epoAPI.util.parseParams( settings.data );
13969							if ( parsedUrl.action === 'woofood_quickview_ajax' ) {
13970								testContainer = testContainer = container.find( 'form' ).parent();
13971								if ( testContainer.length ) {
13972									container = testContainer;
13973									noProductCheck = true;
13974								}
13975							}
13976						}
13977
13978						if ( container.find( '.product' ).length === 0 && container.is( '.product' ) ) {
13979							noProductCheck = true;
13980						}
13981
13982						if ( ( container.find( '.product' ).length > 0 || noProductCheck ) ) {
13983							container.removeClass( 'tc-init' );
13984
13985							if (
13986								key === 'fusion_quick_view_load' ||
13987								key === 'jet_popup_get_content' ||
13988								key === 'wp_food' ||
13989								key === 'woodmart_quick_shop' ||
13990								key === 'woodmart_quick_view' ||
13991								key === 'lightboxpro' ||
13992								key === 'jckqv_quick_view' ||
13993								key === 'yith_quick_view' ||
13994								key === 'theme_flatsome_quick_view'
13995							) {
13996								variationsFormIsLoaded = true;
13997							}
13998							tmLazyloadContainer = container;
13999							if ( tmLazyloadContainer.length > 1 ) {
14000								while ( tmLazyloadContainer.length > 1 ) {
14001									tmLazyloadContainer = tmLazyloadContainer.filter( function() {
14002										return $( this ).find( tcAPI.epoSelector ).length > 0;
14003									} );
14004									if ( tmLazyloadContainer.length === 0 ) {
14005										break;
14006									}
14007								}
14008								if ( tmLazyloadContainer.length === 0 ) {
14009									setTimeout( function() {
14010										requestContainer( 10 );
14011									}, 1000 );
14012
14013									return true;
14014								}
14015							}
14016
14017							epoContainer = tmLazyloadContainer.find( tcAPI.epoSelector );
14018							if ( epoContainer.length === 0 ) {
14019								delete qv_container[ key ];
14020								requestContainer( 10 );
14021								return true;
14022							}
14023
14024							if ( key === 'fusion_quick_view_load' ) {
14025								time = 1400;
14026							}
14027
14028							initepo = function( redo ) {
14029								setTimeout( function() {
14030									product_id = epoContainer.attr( 'data-product-id' );
14031									epo_id = epoContainer.attr( 'data-epo-id' );
14032									if ( key === 'woodmart_quick_shop' ) {
14033										container.addClass( 'has-options' );
14034									}
14035
14036									// Reset element cache
14037									tcAPI.getElementFromFieldCache = [];
14038									tm_init_epo( tmLazyloadContainer, true, product_id, epo_id, undefined, undefined, redo );
14039									jWindow.trigger( 'tmlazy' );
14040									jWindow.trigger( 'tm_epo_loaded_quickview' );
14041									if ( $.jMaskGlobals ) {
14042										tmLazyloadContainer.find( $.jMaskGlobals.maskElements ).toArray().forEach( function( t ) {
14043											t = $( t );
14044
14045											if ( t.attr( 'data-mask' ) ) {
14046												t.mask( t.attr( 'data-mask' ) );
14047											}
14048										} );
14049									}
14050								}, time );
14051							};
14052
14053							initepo();
14054
14055							if ( key === 'minimog_product_quick_view' ) {
14056								$( '.minimog-product' ).on( 'click', '.quick-view-btn', function( evt ) {
14057									var $button = $( this );
14058									var productID = $button.data( 'pid' );
14059									var $template = jBody.children( '#' + 'modal-quick-view-product-' + productID );
14060									evt.preventDefault();
14061									evt.stopPropagation();
14062									if ( $button.hasClass( 'loading' ) ) {
14063										return;
14064									}
14065									if ( ! $.fn.MinimogModal ) {
14066										return;
14067									}
14068									if ( $template.length > 0 ) {
14069										tmLazyloadContainer = $( '.modal-quick-view-popup' );
14070										initepo( true );
14071									}
14072								} );
14073							}
14074						}
14075					}
14076				}
14077			};
14078			requestContainer( 10 );
14079		} );
14080
14081		init_epo_plugin();
14082
14083		$( '.tm-cart-link' ).tmpoplink();
14084		jBody.on( 'updated_checkout wc_fragments_loaded wc_fragments_refreshed wc_fragment_refresh', function() {
14085			$( '.tm-cart-link' ).tmpoplink();
14086		} );
14087
14088		jWindow.trigger( 'tmlazy' );
14089
14090		jWindow.trigger( 'tm_epo_loaded' );
14091	} );
14092
14093	function associated_table_item() {
14094		$( '.tc-associated-table-product td.product-name' ).toArray().forEach( function( el ) {
14095			el = $( el );
14096			if ( el.find( '.product-name' ).length === 0 ) {
14097				el.wrapInner( $( '<div class="tc-associated-table-product-indent"></div>' ) );
14098			}
14099		} );
14100	}
14101
14102	// Associated product cart indent
14103	jBody.on( 'updated_checkout updated_cart_totals', function() {
14104		associated_table_item();
14105	} );
14106
14107	associated_table_item();
14108
14109	// document ready
14110	$( function() {
14111		// Remove accept attribute from upload buttons when in Facebook or Instagram internral browser
14112		var ua = navigator.userAgent || navigator.vendor || window.opera;
14113		ua = ( ua.indexOf( 'FBAN' ) > -1 ) || ( ua.indexOf( 'FBAV' ) > -1 ) || ( ua.indexOf( 'Instagram' ) > -1 );
14114		if ( ua ) {
14115			$( '.tmcp-upload' ).removeAttr( 'accept' );
14116		}
14117
14118		// Fix several custom quantity buttons on themes
14119		jDocument.on( 'click', '.quantity .jckqv-qty-spinner, .quantity .ui-spinner-button', function() {
14120			$( this ).closest( '.quantity' ).find( tcAPI.qtySelector ).trigger( 'change' );
14121		} );
14122
14123		// Quantity selector buttons
14124		$( document ).on( 'click', '.tm-quantity .tc-qty-button, .tm-quantity-alt .tc-qty-button', function() {
14125			var qty = $( this ).closest( '.tm-quantity, .tm-quantity-alt' ).find( '.tm-qty, .tm-qty-alt' );
14126			var val = parseFloat( qty.val() );
14127			var max = parseFloat( qty.attr( 'max' ) );
14128			var min = parseFloat( qty.attr( 'min' ) );
14129			var step = parseFloat( qty.attr( 'step' ) );
14130			if ( isNaN( step ) ) {
14131				step = 1;
14132			}
14133
14134			// Change the value if plus or minus
14135			if ( $( this ).is( '.plus' ) ) {
14136				if ( ! isNaN( max ) && ( max <= val ) ) {
14137					qty.val( max );
14138				} else {
14139					qty.val( val + step );
14140				}
14141			} else if ( ! isNaN( min ) && ( min >= val ) ) {
14142				qty.val( min );
14143			} else if ( val > 0 ) {
14144				qty.val( val - step );
14145			}
14146
14147			$( this ).closest( '.tm-quantity, .tm-quantity-alt' ).find( 'input.tm-qty, input.tm-qty-alt' ).trigger( 'change' );
14148		} );
14149
14150		// bulk variations forms plugin
14151		$( '#wholesale_form' ).on( 'submit', function() {
14152			var _product_id = $( 'form.cart' ).find( tcAPI.addToCartSelector ).val();
14153			// visible fields
14154			var epos = $( tcAPI.epoSelector + ".tm-cart-main[data-product-id='" + _product_id + "']" ).tcClone();
14155			// hidden fields see totals.php
14156			var epos_hidden = $( ".tm-totals-form-main[data-product-id='" + _product_id + "']" ).tcClone();
14157			var formepo = $( "<div class='tm-hidden tm-formepo'></div>" );
14158
14159			formepo.append( epos );
14160			formepo.append( epos_hidden );
14161			$( this ).append( formepo );
14162			return true;
14163		} );
14164
14165		// Disable quote button if option validation fails
14166		jDocument.on( 'click', '#add_to_quote', function( e ) {
14167			var form;
14168			var epo_id;
14169			var epos;
14170
14171			if ( TMEPOJS && TMEPOJS.tm_epo_global_enable_validation === 'yes' ) {
14172				form = $( this ).parents( 'form' );
14173				epo_id = parseInt( form.find( '.tm-epo-counter' ).val(), 10 );
14174				epos = $( tcAPI.epoSelector + "[data-epo-id='" + epo_id + "']" );
14175
14176				// not validated
14177				if ( TMEPOJS.tm_epo_global_enable_validation === 'yes' && $.tc_validator && form.length > 0 && epos.length > 0 && ! form.tc_validate().form() ) {
14178					e.stopImmediatePropagation();
14179				}
14180			}
14181		} );
14182
14183		// PayPal for WooCommerce (PayPal Express Checkout button fix)
14184		$( '.single_add_to_cart_button.paypal_checkout_button' ).on( 'click', function( event ) {
14185			// this is the selector used by the paypal checkout plugin
14186			var form = $( '.cart' );
14187			var validator;
14188
14189			if ( form.data( 'tc_validator' ) ) {
14190				validator = form.data( 'tc_validator' );
14191				if ( validator.errorList ) {
14192					event.stopImmediatePropagation();
14193				}
14194			}
14195		} );
14196
14197		$( '.wc-product-table' ).on( 'init.wcpt', function( event, table ) {
14198			table.$table.find( tcAPI.epoSelector ).addClass( 'hidden' );
14199			table.$table.find( 'thead tr' ).append( '<th>&nbsp;</th>' );
14200			setTimeout( function() {
14201				table.$table.find( '.cart:not(.cart_group)' ).toArray().forEach( function( c ) {
14202					var epo = $( c ).find( tcAPI.epoSelector );
14203					var tr = epo.closest( 'tr' );
14204
14205					$( "<td class='wc-product-table-epo'></td>" ).appendTo( tr ).append( epo );
14206					$( window ).trigger( 'tc_manual_init', epo );
14207					epo.removeClass( 'hidden' );
14208				} );
14209			}, 500 );
14210		} );
14211
14212		// Generate product link.
14213		$( '.generate-product-link' ).on( 'click', function( e ) {
14214			var url = new URL( window.location.href );
14215			var params = url.searchParams;
14216			var newUrl;
14217			var processedRadios = {};
14218
14219			e.preventDefault();
14220
14221			/* Build the query-string from the fields inside #myFormDiv */
14222			$( tcAPI.epoSelector + ':visible' ).find( '.tm-epo-field:enabled' ).each( function() {
14223				var name = this.name;
14224				var value;
14225				var checkedRadio;
14226				if ( this.type === 'radio' ) {
14227					if ( processedRadios[ name ] ) {
14228						return;
14229					}
14230					processedRadios[ name ] = true;
14231
14232					// Find the checked radio in this group
14233					checkedRadio = $( tcAPI.epoSelector + ':visible' )
14234						.find( '.tm-epo-field[name="' + name + '"]:checked' );
14235
14236					value = checkedRadio.length ? checkedRadio.val() : '';
14237				} else if ( this.type === 'checkbox' ) {
14238					value = this.checked ? this.value : '';
14239				} else {
14240					value = $( this ).val();
14241				}
14242
14243				if ( name && value !== '' ) {
14244					params.set( name, value );
14245				}
14246				if ( value === '' ) {
14247					params.delete( name );
14248				}
14249			} );
14250
14251			/* Remove empty values we just stored above */
14252			for ( const [ key, val ] of params.entries() ) {
14253				if ( val === '' ) {
14254					params.delete( key );
14255				}
14256			}
14257
14258			/* Update the browser URL without reloading the page */
14259			newUrl = url.toString();
14260			history.replaceState( null, null, newUrl );
14261			navigator.clipboard.writeText( newUrl ).then( function() {
14262				window.alert( 'Link copied to clipboard:\n' + newUrl );
14263			} ).catch( function( err ) {
14264				window.console.error( 'Could not copy: ', err );
14265			} );
14266		} );
14267	} );
14268}( window, document, window.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.