PageSourceSearch

https://whisperoutdoor.com/wp-content/plugins/woocommerce-tm-extra…/assets/js/tm-epo.js?ver=6.3.2

js whisperoutdoor.com collected 2026-10-08 16:00:55 UTC 413,315 bytes, 11,948 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 errorContainer = $( window );
22	var tcmexp = window.tcmexp;
23	var _ = window._;
24	var priceCache = false;
25
26	var getLocalInputDecimalSeparator = function() {
27		if ( TMEPOJS.tm_epo_global_input_decimal_separator === '' ) {
28			return TMEPOJS.currency_format_decimal_sep;
29		}
30		return $.epoAPI.locale.getSystemDecimalSeparator();
31	};
32
33	var getLocalDecimalSeparator = function() {
34		if ( TMEPOJS.tm_epo_global_displayed_decimal_separator === '' ) {
35			return TMEPOJS.currency_format_decimal_sep;
36		}
37		return $.epoAPI.locale.getSystemDecimalSeparator();
38	};
39
40	var getLocalThousandSeparator = function() {
41		if ( TMEPOJS.tm_epo_global_displayed_decimal_separator === '' ) {
42			return TMEPOJS.currency_format_thousand_sep;
43		}
44		return $.epoAPI.locale.getSystemDecimalSeparator();
45	};
46
47	var getEpoDelay = function() {
48		if ( TMEPOJS.tm_epo_start_animation_delay ) {
49			return TMEPOJS.tm_epo_start_animation_delay;
50		} else if ( window.tc_epo_delay ) {
51			return window.tc_epo_delay;
52		}
53		return 500;
54	};
55
56	var getEpoAnimationDelay = function() {
57		if ( TMEPOJS.tm_epo_animation_delay ) {
58			return TMEPOJS.tm_epo_start_animation_delay;
59		} else if ( window.tc_epo_animation_delay ) {
60			return window.tc_epo_animation_delay;
61		}
62		return 500;
63	};
64
65	var originalVal = $.fn.val;
66
67	if ( ! TMEPOJS || ! wp ) {
68		return;
69	}
70
71	// Trigger plugin events when other plugins use val.
72	$.fn.val = function() {
73		var result = originalVal.apply( this, arguments );
74		if ( arguments.length > 0 ) {
75			if ( $( this ).is( '.input-text.qty' ) ) {
76				$( this ).trigger( 'change.cpf' );
77			}
78		}
79		return result;
80	};
81
82	// Set update event for Lazy Load XT
83	if ( TMEPOJS.tm_epo_no_lazy_load === 'no' && $.lazyLoadXT ) {
84		$.extend( $.lazyLoadXT, {
85			autoInit: false,
86			updateEvent: $.lazyLoadXT.updateEvent + ' tmlazy'
87		} );
88	}
89
90	tcAPI.localInputDecimalSeparator = getLocalInputDecimalSeparator();
91	tcAPI.localDecimalSeparator = getLocalDecimalSeparator();
92	tcAPI.localThousandSeparator = getLocalThousandSeparator();
93	tcAPI.epoDelay = getEpoDelay();
94	tcAPI.epoAnimationDelay = getEpoAnimationDelay();
95	tcAPI.getElementFromFieldCache = [];
96	tcAPI.epoSelector = '.tc-extra-product-options';
97	tcAPI.associatedEpoSelector = '.tc-extra-product-options-inline';
98	tcAPI.associatedEpoCart = '.tc-epo-element-product-container-cart';
99	tcAPI.addToCartSelector = "input[name='add-to-cart']";
100	tcAPI.tcAddToCartSelector = 'input.tc-add-to-cart';
101	tcAPI.qtySelector = "input.qty,input[name='quantity'],select.qty,.drop-down-button #qty,.plus-minus-button #qty,.slider-input #amount";
102	tcAPI.associateQtySelector = 'input.tm-qty-alt';
103	tcAPI.addToCartButtonSelector = '.add_to_cart_button, .single_add_to_cart_button';
104	tcAPI.compositeSelector = '.bto_item,.component';
105	tcAPI.nativeProductPriceSelector = '.woocommerce .product p.price';
106	tcAPI.associatedNativeProductPriceSelector = '.product-price span.price';
107	tcAPI.templateEngine = $.epoAPI.applyFilter( 'tc_adjust_templateEngine', {
108		price: wp.template( 'tc-price' ),
109		sale_price: wp.template( 'tc-sale-price' ),
110		tc_chars_remanining: wp.template( 'tc-chars-remanining' ),
111		tc_final_totals: wp.template( 'tc-final-totals' ),
112		tc_floating_box: wp.template( 'tc-floating-box' ),
113		tc_floating_box_nks: wp.template( 'tc-floating-box-nks' ),
114		tc_formatted_price: wp.template( 'tc-formatted-price' ),
115		tc_formatted_sale_price: wp.template( 'tc-formatted-sale-price' ),
116		tc_lightbox: wp.template( 'tc-lightbox' ),
117		tc_lightbox_zoom: wp.template( 'tc-lightbox-zoom' ),
118		tc_section_pop_link: wp.template( 'tc-section-pop-link' ),
119		tc_upload_messages: wp.template( 'tc-upload-messages' )
120	} );
121
122	// make API available to 3rd party plugins
123	$.tcAPI = function() {
124		return tcAPI;
125	};
126	// method for accessing internal api variables
127	$.tcAPIGet = function( name ) {
128		return tcAPI[ name ];
129	};
130
131	// method for setting  internal api variables
132	$.tcAPISet = function( name, value ) {
133		tcAPI[ name ] = value;
134	};
135
136	if ( $.tc_validator ) {
137		$.extend( $.tc_validator.messages, {
138			required: TMEPOJS.tm_epo_global_validator_messages.required,
139			email: TMEPOJS.tm_epo_global_validator_messages.email,
140			url: TMEPOJS.tm_epo_global_validator_messages.url,
141			number: TMEPOJS.tm_epo_global_validator_messages.number,
142			digits: TMEPOJS.tm_epo_global_validator_messages.digits,
143			maxlengthsingle: $.tc_validator.format( TMEPOJS.tm_epo_global_validator_messages.maxlengthsingle ),
144			maxlength: $.tc_validator.format( TMEPOJS.tm_epo_global_validator_messages.maxlength ),
145			minlengthsingle: $.tc_validator.format( TMEPOJS.tm_epo_global_validator_messages.minlengthsingle ),
146			minlength: $.tc_validator.format( TMEPOJS.tm_epo_global_validator_messages.minlength ),
147			max: $.tc_validator.format( TMEPOJS.tm_epo_global_validator_messages.max ),
148			min: $.tc_validator.format( TMEPOJS.tm_epo_global_validator_messages.min ),
149			step: $.tc_validator.format( TMEPOJS.tm_epo_global_validator_messages.step ),
150			lettersonly: $.tc_validator.format( TMEPOJS.tm_epo_global_validator_messages.lettersonly ),
151			lettersspaceonly: $.tc_validator.format( TMEPOJS.tm_epo_global_validator_messages.lettersspaceonly ),
152			alphanumeric: $.tc_validator.format( TMEPOJS.tm_epo_global_validator_messages.alphanumeric ),
153			alphanumericunicode: $.tc_validator.format( TMEPOJS.tm_epo_global_validator_messages.alphanumericunicode ),
154			alphanumericunicodespace: $.tc_validator.format( TMEPOJS.tm_epo_global_validator_messages.alphanumericunicodespace ),
155			repeaterminrows: $.tc_validator.format( TMEPOJS.tm_epo_global_validator_messages.repeaterminrows ),
156			repeatermaxrows: $.tc_validator.format( TMEPOJS.tm_epo_global_validator_messages.repeatermaxrows )
157		} );
158
159		/*
160		ASCII Digits
161		\u0030-\u0039
162
163		Latin Alphabet
164		\u0041-\u005A\u0061-\u007A
165
166		Latin-1 Supplement
167		\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF
168
169		Latin Extended-A
170		\u0100-\u0148\u014A-\u017F
171
172		Latin Extended-B
173		\u0180-\u01BF\u01C4-\u024F
174
175		Latin Extended Additional
176		\u1E02-\u1EF3
177
178		Greek and Coptic
179		\u0370-\u03FF
180
181		Cyrillic
182		\u0400-\u04FF\u0500-\u052F
183
184		Japanese Hiragana
185		\u3040-\u309f
186		Japanese Katakana
187		\u30a0-\u30ff
188		Japanese Kanji (common & uncommon)
189		\u4e00-\u9faf
190		Japanese Kanji (rare)
191		\u3400-\u4dbf
192
193		Arabic
194		\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF\uFB50-\uFDFF\uFE70-\uFEFF\u10E60-\u10E7F\u1EC70-\u1ECBF\u1ED00-\u1ED4F\u1EE00-\u1EEFF
195
196		\u0600-\u06ff
197		\u0600-\u06FF
198
199		Armenian
200		\u0530-\u1058F
201
202		\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
203
204		*/
205
206		$.tc_validator.addMethod(
207			'alphanumeric',
208			function( value, element ) {
209				return this.optional( element ) || /^[a-zA-Z0-9.-]+$/i.test( value );
210			},
211			$.tc_validator.messages.alphanumeric
212		);
213
214		$.tc_validator.addMethod(
215			'lettersonly',
216			function( value, element ) {
217				return this.optional( element ) || /^[a-z]+$/i.test( value );
218			},
219			$.tc_validator.messages.lettersonly
220		);
221
222		$.tc_validator.addMethod(
223			'lettersspaceonly',
224			function( value, element ) {
225				return this.optional( element ) || /^[a-z,\u0020]+$/i.test( value );
226			},
227			$.tc_validator.messages.lettersspaceonly
228		);
229
230		$.tc_validator.addMethod(
231			'alphanumericunicode',
232			function( value, element ) {
233				return (
234					this.optional( element ) ||
235					/^[\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(
236						value
237					)
238				);
239			},
240			$.tc_validator.messages.alphanumericunicode
241		);
242
243		$.tc_validator.addMethod(
244			'alphanumericunicodespace',
245			function( value, element ) {
246				return (
247					this.optional( element ) ||
248					/^[\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(
249						value
250					)
251				);
252			},
253			$.tc_validator.messages.alphanumericunicodespace
254		);
255		$.tc_validator.addMethod(
256			'repeaterminrows',
257			function( value, element, param ) {
258				return $.epoAPI.math.toInt( $( element ).closest( '.tc-element-inner-wrap' ).find( '.tc-repeater-element' ).length ) >= $.epoAPI.math.toInt( param );
259			},
260			$.tc_validator.messages.repeaterminrows
261		);
262		$.tc_validator.addMethod(
263			'repeatermaxrows',
264			function( value, element, param ) {
265				return $.epoAPI.math.toInt( $( element ).closest( '.tc-element-inner-wrap' ).find( '.tc-repeater-element' ).length ) <= $.epoAPI.math.toInt( param );
266			},
267			$.tc_validator.messages.repeatermaxrows
268		);
269		$.tc_validator.addMethod(
270			'product_element_radio_qty',
271			function( value, element ) {
272				var qty = $( element ).closest( '.tm-element-ul-product' ).find( 'input.tc-epo-field-product.tm
272cp-radio:checked' ).closest( '.tc-epo-element-product-holder' ).find( '.tm-qty' ).first().val();
273				return qty > 0;
274			},
275			$.tc_validator.messages.required
276		);
277		$.tc_validator.addMethod(
278			'product_element_select_qty',
279			function( value, element ) {
280				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();
281				return qty > 0;
282			},
283			$.tc_validator.messages.required
284		);
285	}
286
287	$.epoAPI.util.escapeSelector = ( function() {
288		/* original escape string
289		 *  /([!"#$%&'()*+,./:;<=>?@[\]^`{|}~])/g;
290		 */
291		var selectorEscape = /([!"$%&'()*+,/:;<=>?@[\]^`{|}~])/g;
292		return function( selector ) {
293			return selector.replace( selectorEscape, '\\$1' );
294		};
295	}() );
296
297	$.epoAPI.util.unformat = function( o ) {
298		var a = $.epoAPI.math.unformat( o, tcAPI.localInputDecimalSeparator );
299		var n = parseFloat( a );
300
301		if ( ! Number.isFinite( n ) ) {
302			return a;
303		}
304		return n;
305	};
306
307	$.epoAPI.util.parseParams = function( string, decode ) {
308		if ( typeof string !== 'string' || string.split === undefined ) {
309			return [];
310		}
311		return string
312			.split( '&' )
313			.map( function( value ) {
314				var obj = {};
315
316				if ( decode === true ) {
317					value = decodeURIComponent( value.replace( /\+/g, '%20' ) );
318				}
319
320				value = value.split( '=' ).map( function( v ) {
321					var a = v.split( '?' );
322
323					if ( a.length > 1 ) {
324						return a[ 1 ];
325					}
326					return v;
327				} );
328
329				if ( value.length > 1 ) {
330					obj[ value[ 0 ] ] = value[ 1 ];
331				}
332
333				return obj;
334			} )
335			.filter( function( n ) {
336				return n !== null;
337			} )
338			.reduce( function( current, next ) {
339				return Object.assign( {}, current, next );
340			}, {} );
341	};
342
343	if ( ! $.tmempty ) {
344		$.tmempty = function( obj ) {
345			var emptyValues = [ undefined, null, false, 0, '', '0' ];
346			var isEmptyValue =
347				emptyValues.filter( function( item ) {
348					return obj === item;
349				} ).length === 1;
350			var isEmptyObject = false;
351
352			if ( typeof obj === 'object' ) {
353				isEmptyObject =
354					Object.keys( obj ).filter( function( key ) {
355						return Object.prototype.hasOwnProperty.call( obj, key );
356					} ).length === 0;
357				return isEmptyObject;
358			}
359
360			return isEmptyValue || isEmptyObject;
361		};
362	}
363
364	if ( ! $.tmType ) {
365		$.tmType = function( obj ) {
366			return Object.prototype.toString
367				.call( obj )
368				.match( /\s([a-zA-Z]+)/ )[ 1 ]
369				.toLowerCase();
370		};
371	}
372
373	if ( ! $.is_on_screen ) {
374		$.fn.is_on_screen = function() {
375			// we don't use jWindow because we want the current window object
376			var win = $( window );
377			var scroll = $.epoAPI.dom.scroll();
378			var bounds = this.offset();
379			var viewport = {
380				top: scroll.top,
381				left: scroll.left
382			};
383
384			viewport.right = viewport.left + win.width();
385			viewport.bottom = viewport.top + win.height();
386			bounds.right = bounds.left + this.outerWidth();
387			bounds.bottom = bounds.top + this.outerHeight();
388
389			return ! ( viewport.right < bounds.left || viewport.left > bounds.right || viewport.bottom < bounds.top || viewport.top > bounds.bottom );
390		};
391	}
392
393	if ( ! $().tmtoggle ) {
394		$.fn.tmtoggle = function() {
395			var elements = this;
396			var is_one_open_for_accordion = false;
397			var init_done = 0;
398
399			if ( elements.length === 0 ) {
400				return;
401			}
402
403			if ( window.tc_accordion_offset === undefined ) {
404				window.tc_accordion_offset = -100;
405			}
406
407			elements.each( function() {
408				var t = $( this );
409				var headers;
410				var wrap;
411				var wraps;
412
413				if ( ! t.data( 'tm-toggle-init' ) ) {
414					t.data( 'tm-toggle-init', 1 );
415					headers = t.find( '.tm-toggle' );
416					wrap = t.find( '.tm-collapse-wrap' );
417					wraps = $( '.tm-collapse.tmaccordion' ).find( '.tm-toggle' );
418					if ( headers.length === 0 || wrap.length === 0 ) {
419						return;
420					}
421
422					if ( wrap.is( '.closed' ) ) {
423						$( wrap ).removeClass( 'closed open' ).addClass( 'closed' ).hide();
424						$( headers ).find( '.tm-arrow' ).removeClass( 'tcfa-angle-down tcfa-angle-up' ).addClass( 'tcfa-angle-down' );
425						$( headers ).removeClass( 'toggle-header-open toggle-header-closed' ).addClass( 'toggle-header-closed' );
426					} else {
427						$( wrap ).removeClass( 'closed open' ).addClass( 'open' ).show();
428						$( headers ).find( '.tm-arrow' ).removeClass( 'tcfa-angle-down tcfa-angle-up' ).addClass( 'tcfa-angle-up' );
429						$( headers ).removeClass( 'toggle-header-open toggle-header-closed' ).addClass( 'toggle-header-open' );
430						is_one_open_for_accordion = true;
431					}
432
433					headers.each( function( i, header ) {
434						$( header ).on( 'closewrap.tmtoggle', function() {
435							if ( t.is( '.tmaccordion' ) && $( wrap ).is( '.closed' ) ) {
436								return;
437							}
438							$( wrap ).removeClass( 'closed open' ).addClass( 'closed' );
439							$( this ).find( '.tm-arrow' ).removeClass( 'tcfa-angle-down tcfa-angle-up' ).addClass( 'tcfa-angle-down' );
440							$( this ).removeClass( 'toggle-header-open toggle-header-closed' ).addClass( 'toggle-header-closed' );
441							$( wrap ).removeClass( 'tm-animated fadein' );
442							if ( t.is( '.tmaccordion' ) ) {
443								$( wrap ).animate( { height: 'toggle' }, 100, function() {
444									$( wrap ).hide();
445								} );
446							} else {
447								$( wrap ).animate( { height: 'toggle' }, 100, function() {
448									$( wrap ).hide();
449								} );
450							}
451							jWindow.trigger( 'tmlazy' );
452						} );
453
454						$( header ).on( 'openwrap.tmtoggle', function() {
455							if ( t.is( '.tmaccordion' ) ) {
456								$( wraps ).not( $( this ) ).trigger( 'closewrap.tmtoggle' );
457							}
458							$( wrap ).removeClass( 'closed open' ).addClass( 'open' );
459							$( this ).find( '.tm-arrow' ).removeClass( 'tcfa-angle-down tcfa-angle-up' ).addClass( 'tcfa-angle-up' );
460							$( this ).removeClass( 'toggle-header-open toggle-header-closed' ).addClass( 'toggle-header-open' );
461							$( wrap ).show().removeClass( 'tm-animated fadein' ).addClass( 'tm-animated fadein' );
462							setTimeout( function() {
463								jWindow.trigger( 'tmlazy' );
464							}, 200 );
465							setTimeout( function() {
466								if ( init_done && t.is( '.tmaccordion' ) && ! t.is_on_screen() ) {
467									jWindow.tcScrollTo( $( header ), 10, window.tc_accordion_offset );
468								}
469							}, 110 );
470						} );
471
472						$( header ).on( 'click.tmtoggle', function( e ) {
473							e.preventDefault();
474							if ( $( wrap ).is( '.closed' ) ) {
475								$( this ).trigger( 'openwrap.tmtoggle' );
476							} else {
477								$( this ).trigger( 'closewrap.tmtoggle' );
478							}
479						} );
480
481						$( header )
482							.find( '.tm-qty' )
483							.closest( '.cpf-element' )
484							.find( '.tm-epo-field' )
485							.on( 'change.cpf', function() {
486								$( header ).trigger( 'openwrap.tmtoggle' );
487							} );
488					} );
489				}
490			} );
491			if ( undefined === window.tc_accordion_closed_on_page_load && ! is_one_open_for_accordion && elements.filter( '.tmaccordion' ).length > 0 ) {
492				elements.filter( '.tmaccordion' ).first().find( '.tm-toggle' ).trigger( 'openwrap.tmtoggle' );
493			}
494			init_done = 1;
495			return elements;
496		};
497	}
498
499	if ( ! $().tmpoplink ) {
500		$.fn.tmpoplink = function() {
501			var elements = this;
502			var floatbox_template;
503
504			if ( elements.length === 0 ) {
505				return;
506			}
507
508			floatbox_template = function( data ) {
509				return $.epoAPI.template.html( wp.template( 'tc-cart-options-popup' ), {
510					title: data.title,
511					id: data.id,
512					html: data.html,
513					close: TMEPOJS.i18n_close
514				} );
515			};
516
517			return elements.each( function() {
518				var t = $( this );
519				var id;
520				var title;
521				var html;
522				var $_html;
523
524				if ( t.is( '.tc-poplink' ) ) {
525					return;
526				}
527				t.addClass( 'tc-poplink' );
528				id = $( this ).attr( 'href' );
529				title = $( this ).attr( 'data-title' );
530				html = $( id ).html();
531				if ( ! title ) {
532					title = TMEPOJS.i18n_addition_options;
533				}
534				$_html = floatbox_template( {
535					id: 'tc-floatbox-content',
536					html: html,
537					title: title
538				} );
539
540				t.on( 'click.tmpoplink', function( e ) {
541					$.tcFloatBox( {
542						fps: 1,
543						ismodal: false,
544						refresh: 100,
545						width: '80%',
546						height: '80%',
547						classname: 'flasho tc-wrapper',
548						data: $_html
549					} );
550
551					e.preventDefault();
552				} );
553			} );
554		};
555	}
556
557	function readableFileSize( a, b, c, d, e ) {
558		b = Math;
559		c = b.log;
560		d = 1024;
561		e = c( a ) / c( d ) | 0; //eslint-disable-line no-bitwise
562
563		return ( ( a / b.pow( d, e ) ).toFixed( e ? 2 : 0 ) ) + ' ' + ( e ? 'KMGTPEZY'[ --e ] + 'B' : 'bytes' );
564	}
565
566	function toggleState( thisProductContainerWrap, disabled ) {
567		thisProductContainerWrap.toArray().forEach( function( setter ) {
568			setter = $( setter );
569			setter.find( ':input' ).prop( 'disabled', function( i, v ) {
570				var state = $( this ).data( 'tc-state' );
571				if ( state === undefined ) {
572					$( this ).data( 'tc-state', v );
573					return disabled;
574				}
575				if ( state === false ) {
576					return disabled;
577				}
578				return state;
579			} );
580		} );
581	}
582
583	// Taxes setup
584	function get_price_including_tax( price, _cart, element, force, variation, pricetype, doubleforce ) {
585		var taxable;
586		var tax_rate;
587		var prices_include_tax;
588		var is_vat_exempt;
589		var non_base_location_prices;
590		var taxes_of_one;
591		var base_taxes_of_one;
592		var modded_taxes_of_one;
593		var current_variation;
594
595		if ( ! Number.isFinite( parseFloat( price ) ) ) {
596			price = 0;
597		}
598		price = price * 10000;
599		if ( _cart ) {
600			taxable = _cart.attr( 'data-taxable' );
601			tax_rate = _cart.attr( 'data-tax-rate' );
602			prices_include_tax = _cart.attr( 'data-prices-include-tax' ) || TMEPOJS.prices_include_tax;
603			is_vat_exempt = _cart.attr( 'data-is-vat-exempt' );
604			non_base_location_prices = _cart.attr( 'data-non-base-location-prices' );
605			taxes_of_one = _cart.attr( 'data-taxes-of-one' );
606			base_taxes_of_one = _cart.attr( 'data-base-taxes-of-one' );
607			modded_taxes_of_one = _cart.attr( 'data-modded-taxes-of-one' );
608
609			if ( _cart.data( 'current_variation' ) !== undefined ) {
610				current_variation = _cart.data( 'current_variation' );
611			} else if ( variation !== undefined ) {
612				current_variation = variation;
613			}
614
615			if ( current_variation !== undefined ) {
616				current_variation = _cart.data( 'current_variation' );
617				taxable = current_variation.tc_is_taxable;
618				tax_rate = current_variation.tc_tax_rate;
619				non_base_location_prices = current_variation.tc_non_base_location_prices;
620				taxes_of_one = current_variation.tc_taxes_of_one;
621				base_taxes_of_one = current_variation.tc_base_taxes_of_one;
622				modded_taxes_of_one = current_variation.tc_modded_taxes_of_one;
623			}
624
625			if ( element ) {
626				if ( element.data( 'tax-obj' ) ) {
627					tax_rate = element.data( 'tax-obj' );
628					if ( tax_rate.has_fee === 'no' ) {
629						taxable = false;
630					} else if ( tax_rate.has_fee === 'yes' ) {
631						taxable = true;
632					}
633					tax_rate = tax_rate.tax_rate;
634					taxes_of_one = tax_rate / 100;
635					base_taxes_of_one = tax_rate / 100;
636				}
637			}
638			if ( taxable ) {
639				if ( prices_include_tax === '1' && ! force ) {
640					if ( is_vat_exempt === '1' ) {
641						if ( non_base_location_prices === '1' ) {
642							price = parseFloat( price ) - ( taxes_of_one * price );
643						} else {
644							price = parseFloat( price ) - ( base_taxes_of_one * price );
645						}
646					} else if ( non_base_location_prices === '1' ) {
647						price = parseFloat( price ) - ( base_taxes_of_one * price ) + ( modded_taxes_of_one * price );
648					}
649				} else if ( element || current_variation === undefined || doubleforce ) {
650					price = parseFloat( price ) + ( parseFloat( price ) * taxes_of_one );
651				}
652			}
653		}
654		price = price / 10000;
655
656		return price;
657	}
658
659	function get_price_excluding_tax( price, _cart, element, force, variation, pricetype, doubleforce ) {
660		var taxable;
661		var tax_rate;
662		var taxes_of_one;
663		var prices_include_tax;
664		var current_variation;
665		var tax_display_mode;
666
667		if ( ! Number.isFinite( parseFloat( price ) ) ) {
668			price = 0;
669		}
670		price = price * 10000;
671
672		if ( _cart ) {
673			tax_display_mode = _cart.attr( 'data-tax-display-mode' );
674
675			taxable = _cart.attr( 'data-taxable' );
676			tax_rate = _cart.attr( 'data-tax-rate' );
677			taxes_of_one = _cart.attr( 'data-taxes-of-one' );
678			prices_include_tax = _cart.attr( 'data-prices-include-tax' );
679
680			if ( _cart.data( 'current_variation' ) !== undefined ) {
681				current_variation = _cart.data( 'current_variation' );
682			} else if ( variation !== undefined ) {
683				current_variation = variation;
684			}
685			if ( current_variation !== undefined ) {
686				taxable = current_variation.tc_is_taxable;
687				tax_rate = current_variation.tc_tax_rate;
688				taxes_of_one = current_variation.tc_taxes_of_one;
689			}
690
691			if ( element ) {
692				if ( element.data( 'tax-obj' ) ) {
693					tax_rate = element.data( 'tax-obj' );
694					if ( tax_rate.has_fee === 'no' ) {
695						taxable = false;
696					} else if ( tax_rate.has_fee === 'yes' ) {
697						taxable = true;
698					}
699					tax_rate = tax_rate.tax_rate;
700				}
701			}
702
703			if ( taxable ) {
704				if ( prices_include_tax === '1' || force ) {
705					if ( tax_display_mode === 'incl' ) {
706						// This should never run on this function
707					} else if ( element || current_variation === undefined || force || doubleforce ) {
708						price = parseFloat( price ) - parseFloat( taxes_of_one * price );
709					}
710				}
711			}
712		}
713		price = price / 10000;
714
715		return price;
716	}
717
718	function tm_set_tax_price( value, _cart, element, pricetype, force, variation, doubleforce ) {
719		var tax_display_mode;
720
721		if ( ! Number.isFinite( parseFloat( value ) ) ) {
722			value = 0;
723		}
724		if ( _cart ) {
725			tax_display_mode = _cart.attr( 'data-tax-display-mode' ) || TMEPOJS.tax_display_mode;
726			if ( tax_display_mode === 'incl' ) {
727				value = get_price_including_tax( value, _cart, element, force, variation, pricetype, doubleforce );
728			} else {
729				value = get_price_excluding_tax( value, _cart, element, force, variation, pricetype, doubleforce );
730			}
731		}
732		return value;
733	}
734
735	// Return a formatted currency value
736	function formatPrice( value, args ) {
737		var data;
738		if ( ! args ) {
739			args = {};
740		}
741		data = $.extend( {
742			symbol: '',
743			format: '',
744			decimal: tcAPI.localDecimalSeparator,
745			thousand: tcAPI.localThousandSeparator,
746			precision: TMEPOJS.currency_format_num_decimals
747		}, args );
748
749		if ( TMEPOJS.tm_epo_trim_zeros === 'yes' ) {
750			if ( ( ( value % 1 ).toString() !== '0' ) === false ) {
751				data.precision = 0;
752			}
753		}
754
755		return $.epoAPI.applyFilter( 'tc_formatPrice', $.epoAPI.math.format( value, data ), data, value );
756	}
757
758	// Return a formatted currency value
759	function tm_set_price_( value, sign, inc_tax_string ) {
760		return (
761			sign +
762			formatPrice( value, { symbol: TMEPOJS.currency_format_symbol, format: TMEPOJS.currency_format } ) +
763			inc_tax_string
764		);
765	}
766
767	// Return a formatted currency value
768	function tm_set_price( value, _cart, notax, taxstring, element, pricetype ) {
769		var inc_tax_string = '';
770		var val;
771		var sign = TMEPOJS.option_plus_sign + ' ';
772
773		if ( ! notax ) {
774			value = tm_set_tax_price( value, _cart, element, pricetype );
775		}
776
777		val = Math.abs( value );
778
779		if ( TMEPOJS.tm_epo_global_options_price_sign === 'minus' ) {
780			sign = '';
781		}
782		if ( value < 0 ) {
783			sign = TMEPOJS.option_minus_sign + ' ';
784		}
785
786		if ( _cart && taxstring ) {
787			inc_tax_string = _cart.attr( 'data-tax-string' );
788		}
789		if ( inc_tax_string === undefined ) {
790			inc_tax_string = '';
791		}
792
793		return tm_set_price_( val, sign, inc_tax_string );
794	}
795
796	// FloatingTotalsBox plugin
797	FloatingTotalsBox = function( this_epo_totals_container, is_quickview, main_cart ) {
798		this.this_epo_totals_container = this_epo_totals_container;
799		this.is_quickview = is_quickview;
800		this.main_cart = main_cart;
801
802		if ( ! is_quickview && TMEPOJS.floating_totals_box && TMEPOJS.floating_totals_box !== 'disable' && main_cart && this_epo_totals_container.length ) {
803			this.init();
804			return this;
805		}
806
807		return false;
808	};
809
810	FloatingTotalsBox.prototype = {
811		constructor: FloatingTotalsBox,
812
813		onUpdate: function() {
814			var tm_epo_totals_html = this.this_epo_totals_container.data( 'tm-html' );
815			var tm_floating_box_data = this.this_epo_totals_container.data( 'tm-floating-box-data' );
816			var values_obj = [];
817			var floatingBoxHtml;
818			var floatingBoxaddToCartButton;
819
820			if ( tm_floating_box_data && tm_floating_box_data.length ) {
821				$.each( tm_floating_box_data, function( i, row ) {
822					if ( row.title === '' ) {
823						row.title = '&nbsp;';
824					}
825					if ( row.value === '' ) {
826						row.value = '&nbsp;';
827					}
828					if ( ! row.title ) {
829						row.title = '&nbsp;';
830					} else {
831						row.title = $( '<div>' + row.title + '</div>' );
832						row.title.find( 'span' ).remove();
833						row.title = row.title.html();
834					}
835
836					if ( this.is_nks ) {
837						if ( row.label_show !== '' ) {
838							row.title = '';
839						}
840						if ( row.value_show !== '' ) {
841							row.value = '';
842						}
843					}
844
845					if ( TMEPOJS.tm_epo_auto_hide_price_if_zero === 'yes' && $.tmempty( row.price ) === true ) {
846						row.price = '';
847					} else {
848						row.price = tm_set_price( row.price, this.this_epo_totals_container, true, false );
849					}
850
851					values_obj.push( {
852						label_show: row.label_show,
853						value_show: row.value_show,
854						title: row.title,
855						value: row.value,
856						quantity: row.quantity,
857						price: row.price
858					} );
859				} );
860			}
861
862			if ( ! ( ( tm_epo_totals_html && tm_epo_totals_html !== '' ) || this.is_nks ) ) {
863				tm_epo_totals_html = '';
864				this.floatingBox.hide();
865			}
866			if ( values_obj && ! values_obj.length ) {
867				values_obj.push( {
868					label_show: 'hidden',
869					value_show: 'hidden',
870					title: '',
871					value: '',
872					quantity: 0,
873					price: 0
874				} );
875			}
876
877			floatingBoxHtml = $.epoAPI.template.html( this.engineTemplate, {
878				html_before: TMEPOJS.floating_totals_box_html_before,
879				html_after: TMEPOJS.floating_totals_box_html_after,
880				option_label: TMEPOJS.i18n_option_label,
881				option_value: TMEPOJS.i18n_option_value,
882				option_qty: TMEPOJS.i18n_option_qty,
883				option_price: TMEPOJS.i18n_option_price,
884				values: values_obj,
885				totals: tm_epo_totals_html
886			} );
887
888			this.floatingBox.html( floatingBoxHtml );
889			this.onUpdateScroll();
890
891			if ( TMEPOJS.floating_totals_box_add_button === 'yes' ) {
892				floatingBoxaddToCartButton = this.main_cart.find( tcAPI.addToCartButtonSelector ).first();
893				floatingBoxaddToCartButton
894					.tcClone()
895					.addClass( 'tc-add-to-cart-button' )
896					.on( 'click', function() {
897						floatingBoxaddToCartButton.trigger( 'click' );
898					} )
899					.appendTo( this.floatingBox );
900			}
901		},
902
903		onUpdateScroll: function() {
904			if ( TMEPOJS.floating_totals_box_visibility === 'always' ) {
905				this.floatingBox.show();
906				return;
907			}
908			if ( TMEPOJS.floating_totals_box_visibility === 'hideafterscroll' ) {
909				if ( jWindow.scrollTop() >
909 $.epoAPI.math.toFloat( TMEPOJS.floating_totals_box_pixels ) && ! this.is_nks_alt ) {
910					if ( ! this.floatingBox.is( ':hidden' ) ) {
911						if ( this.is_nks === false ) {
912							this.floatingBox.fadeOut();
913						} else {
914							this.floatingBox.hide();
915						}
916					}
917				} else if ( this.floatingBox.is( ':hidden' ) || this.is_nks_alt ) {
918					if ( ! this.floatingBox.is( ':empty' ) || this.is_nks_alt ) {
919						if ( this.is_nks === false ) {
920							this.floatingBox.fadeIn();
921						} else {
922							this.floatingBox.show();
923						}
924					}
925				}
926			}
927
928			if ( TMEPOJS.floating_totals_box_visibility === 'afterscroll' ) {
929				if ( jWindow.scrollTop() > $.epoAPI.math.toFloat( TMEPOJS.floating_totals_box_pixels ) || this.is_nks_alt ) {
930					if ( ( this.floatingBox.is( ':hidden' ) && ! this.floatingBox.is( ':empty' ) ) || this.is_nks_alt ) {
931						if ( this.is_nks === false ) {
932							this.floatingBox.fadeIn();
933						} else {
934							this.floatingBox.show();
935						}
936					} else if ( ! this.floatingBox.is( ':hidden' ) && this.floatingBox.is( ':empty' ) ) {
937						if ( this.is_nks === false ) {
938							this.floatingBox.fadeOut();
939						} else {
940							this.floatingBox.hide();
941						}
942					}
943				} else if ( ! this.floatingBox.is( ':hidden' ) ) {
944					if ( this.is_nks === false ) {
945						this.floatingBox.fadeOut();
946					} else {
947						this.floatingBox.hide();
948					}
949				}
950			}
951		},
952
953		addEvents: function() {
954			this.onUpdate();
955
956			this.main_cart.on( 'tm-epo-after-update', this.onUpdate.bind( this ) );
957
958			if ( this.is_nks === false ) {
959				jWindow.on( 'scroll', this.onUpdateScroll.bind( this ) );
960			}
961		},
962
963		init: function() {
964			this.floatingBox = $( '<div class="tm-floating-box ' + TMEPOJS.floating_totals_box + '"></div>' );
965			this.nks_selector = $( '.tm-floating-box-nks' ).first();
966			this.alt_selector = $( '.tm-floating-box-alt' ).first();
967			this.engineTemplate = tcAPI.templateEngine.tc_floating_box;
968			this.is_nks = false;
969			this.is_nks_alt = false;
970
971			if ( this.nks_selector.length > 0 ) {
972				this.is_nks = true;
973				this.floatingBox.removeClass( 'top left right bottom' ).appendTo( this.nks_selector ).show();
974			} else if ( this.alt_selector.length > 0 ) {
975				this.floatingBox.removeClass( 'top left right bottom' ).appendTo( this.alt_selector ).hide();
976			} else {
977				this.floatingBox.appendTo( 'body' ).hide();
978			}
979
980			if ( this.nks_selector.length > 0 || this.alt_selector.length > 0 ) {
981				this.is_nks_alt = true;
982				this.engineTemplate = tcAPI.templateEngine.tc_floating_box_nks;
983			}
984
985			this.addEvents();
986		}
987	};
988
989	$.tcFloatingTotalsBox = function( this_epo_totals_container, is_quickview, main_cart ) {
990		var data = false;
991
992		if ( this_epo_totals_container && this_epo_totals_container.length && this_epo_totals_container.data( 'tcfloatingtotalsbox' ) === undefined ) {
993			data = new FloatingTotalsBox( this_epo_totals_container, is_quickview, main_cart );
994			this_epo_totals_container.data( 'tcfloatingtotalsbox', data );
995		}
996
997		return data;
998	};
999
1000	$.tc_product_image = {};
1001	$.tc_product_image_store = {};
1002
1003	// replace obj1 values with obj2 values
1004	$.tc_replace_object_values = function( obj1, obj2 ) {
1005		Object.keys( obj1 ).forEach( function( x ) {
1006			Object.keys( obj1[ x ] ).forEach( function( attr ) {
1007				if ( undefined !== obj2[ x ] && undefined !== obj2[ x ][ attr ] && Object.prototype.hasOwnProperty.call( obj2[ x ], attr ) ) {
1008					obj1[ x ][ attr ] = obj2[ x ][ attr ];
1009				}
1010			} );
1011		} );
1012		return obj1;
1013	};
1014	// copy obj2 values to obj1
1015	$.tc_maybe_copy_object_values = function( obj1, obj2 ) {
1016		Object.keys( obj2 ).forEach( function( x ) {
1017			Object.keys( obj2[ x ] ).forEach( function( attr ) {
1018				if ( undefined !== obj2[ x ] && Object.prototype.hasOwnProperty.call( obj2[ x ], attr ) && undefined !== obj2[ x ][ attr ] && ( undefined === obj1[ x ] || undefined === obj1[ x ][ attr ] ) ) {
1019					if ( undefined === obj1[ x ] ) {
1020						obj1[ x ] = {};
1021					}
1022					obj1[ x ][ attr ] = obj2[ x ][ attr ];
1023				}
1024			} );
1025		} );
1026		return obj1;
1027	};
1028
1029	$.tc_pre_populate_store = function() {
1030		var obj = {};
1031
1032		obj[ 0 ] = {};
1033		obj[ 1 ] = {};
1034		obj[ 2 ] = {};
1035		obj[ 3 ] = {};
1036
1037		obj[ 0 ].src = '';
1038		obj[ 0 ].srcset = '';
1039		obj[ 0 ].sizes = '';
1040		obj[ 0 ].title = '';
1041		obj[ 0 ].alt = '';
1042		obj[ 0 ][ 'data-src' ] = '';
1043		obj[ 0 ][ 'data-large_image' ] = '';
1044		obj[ 0 ][ 'data-large_image_width' ] = '';
1045		obj[ 0 ][ 'data-large_image_height' ] = '';
1046		obj[ 1 ][ 'data-thumb' ] = '';
1047		obj[ 2 ].src = '';
1048		obj[ 3 ].href = '';
1049		obj[ 3 ].title = '';
1050
1051		return obj;
1052	};
1053
1054	$.tc_populate_store = function( img, product_element ) {
1055		var $gallery_img = product_element.find( '.flex-control-nav li:eq(0) img' );
1056		var $gallery_wrapper = product_element.find( '.woocommerce-product-gallery__wrapper ' );
1057		var $product_img_wrap = $gallery_wrapper.find( '.woocommerce-product-gallery__image, .woocommerce-product-gallery__image--placeholder' ).eq( 0 );
1058		var $product_img = img;
1059		var $product_link = img.closest( 'a' );
1060		var obj = {};
1061
1062		obj[ 0 ] = {};
1063		obj[ 1 ] = {};
1064		obj[ 2 ] = {};
1065		obj[ 3 ] = {};
1066
1067		obj[ 0 ].src = $product_img.attr( 'src' );
1068		obj[ 0 ].srcset = $product_img.attr( 'srcset' );
1069		obj[ 0 ].sizes = $product_img.attr( 'sizes' );
1070		obj[ 0 ].title = $product_img.attr( 'title' );
1071		obj[ 0 ].alt = $product_img.attr( 'alt' );
1072		obj[ 0 ][ 'data-src' ] = $product_img.attr( 'data-src' );
1073		obj[ 0 ][ 'data-large_image' ] = $product_img.attr( 'data-large_image' );
1074		obj[ 0 ][ 'data-large_image_width' ] = $product_img.attr( 'data-large_image_width' );
1075		obj[ 0 ][ 'data-large_image_height' ] = $product_img.attr( 'data-large_image_height' );
1076		obj[ 1 ][ 'data-thumb' ] = $product_img_wrap.attr( 'data-thumb' );
1077		obj[ 2 ].src = $gallery_img.attr( 'src' );
1078		obj[ 3 ].href = $product_link.attr( 'href' );
1079		obj[ 3 ].title = $product_link.attr( 'title' );
1080
1081		return obj;
1082	};
1083
1084	$.tc_maybe_copy_object_values_from_img = function( obj1, img, product_element ) {
1085		var $gallery_img = product_element.find( '.flex-control-nav li:eq(0) img' );
1086		var $gallery_wrapper = product_element.find( '.woocommerce-product-gallery__wrapper ' );
1087		var $product_img_wrap = $gallery_wrapper.find( '.woocommerce-product-gallery__image, .woocommerce-product-gallery__image--placeholder' ).eq( 0 );
1088		var $product_img = img;
1089		var $product_link = img.closest( 'a' );
1090		var attrs;
1091		var attr;
1092		var attrs_product_img = [ 'src', 'srcset', 'sizes', 'title', 'alt', 'data-src', 'data-large_image', 'data-large_image_width', 'data-large_image_height', 'large-image' ];
1093		var attrs_product_img_wrap = [ 'data-thumb' ];
1094		var attrs_gallery_img = [ 'src' ];
1095		var attrs_product_link = [ 'href', 'title' ];
1096		var all = [ $product_img, $product_img_wrap, $gallery_img, $product_link ];
1097		var attrs_all = [ attrs_product_img, attrs_product_img_wrap, attrs_gallery_img, attrs_product_link ];
1098		all.forEach( function( item, index ) {
1099			if ( undefined !== item && undefined !== item[ 0 ] ) {
1100				attrs = item[ 0 ].attributes;
1101
1102				$.each( attrs, function() {
1103					if ( this.specified ) {
1104						attr = this.name;
1105
1106						if ( $.inArray( attr, attrs_all[ index ] ) !== -1 && ( undefined === obj1[ index ] || ( undefined !== obj1[ index ] && undefined === obj1[ index ][ attr ] ) ) ) {
1107							if ( undefined === obj1[ index ] ) {
1108								obj1[ index ] = {};
1109							}
1110							obj1[ index ][ attr ] = this.value;
1111						}
1112					}
1113				} );
1114			}
1115		} );
1116
1117		return obj1;
1118	};
1119
1120	// Stores a default attribute for an element so it can be reset later
1121	$.fn.tc_set_attr = function( attr, value, id ) {
1122		if ( undefined === id ) {
1123			id = 0;
1124		}
1125		if ( undefined === $.tc_product_image[ id ] || ( undefined !== $.tc_product_image[ id ] && undefined === $.tc_product_image[ id ][ attr ] ) ) {
1126			if ( undefined === $.tc_product_image[ id ] ) {
1127				$.tc_product_image[ id ] = {};
1128			}
1129			$.tc_product_image[ id ][ attr ] = '';
1130			if ( this.attr( attr ) ) {
1131				$.tc_product_image[ id ][ attr ] = this.attr( attr );
1132			}
1133		}
1134		if ( false === value ) {
1135			this.removeAttr( attr );
1136		} else {
1137			this.attr( attr, value );
1138		}
1139	};
1140
1141	// Reset a default attribute for an element so it can be reset later
1142	$.fn.tc_reset_attr = function( attr, id ) {
1143		if ( undefined === id ) {
1144			id = 0;
1145		}
1146		if ( undefined === $.tc_product_image[ id ] ) {
1147			return;
1148		}
1149		if ( undefined !== $.tc_product_image[ id ][ attr ] ) {
1150			this.attr( attr, $.tc_product_image[ id ][ attr ] );
1151		}
1152		delete $.tc_product_image[ id ][ attr ];
1153	};
1154
1155	$.fn.tc_update_attr = function( attr, id ) {
1156		if ( undefined === id ) {
1157			id = 0;
1158		}
1159		if ( undefined !== $.tc_product_image[ id ] ) {
1160			$.tc_product_image[ id ][ attr ] = this.attr( attr );
1161		}
1162	};
1163
1164	$.fn.tc_image_update = function( dom, image ) {
1165		var element = $( dom );
1166		var $form = this;
1167		var $image = $( image );
1168		var epo_object = $form.data( 'epo_object' );
1169		var image_info;
1170		var $product_img;
1171		var product_element = epo_object.main_product.closest( '#product-' + epo_object.product_id );
1172		var $product_element = product_element;
1173		var $product_link;
1174		var use_image_info;
1175
1176		if ( product_element.length <= 0 ) {
1177			$product_element = epo_object.main_product.closest( '.post-' + epo_object.product_id );
1178		}
1179
1180		if ( element.is( 'select' ) ) {
1181			element = element.children( 'option:selected' );
1182		}
1183		image_info = element.data( 'image-variations' );
1184
1185		if ( TMEPOJS.tm_epo_global_product_image_selector !== '' ) {
1186			$product_img = $( TMEPOJS.tm_epo_global_product_image_selector );
1187		} else {
1188			$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();
1189		}
1190		$product_link = $product_img.closest( 'a' );
1191
1192		if ( $product_img.length > 1 ) {
1193			$product_img = $product_img.first();
1194		}
1195
1196		if ( element && image_info && $image.length > 0 ) {
1197			$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' );
1198
1199			use_image_info = image_info.imagep;
1200			if ( ! image_info.imagep.image_link ) {
1201				use_image_info = image_info.image;
1202			}
1203
1204			$image.attr( 'title', use_image_info.image_title );
1205			$image.attr( 'alt', use_image_info.image_alt );
1206			if ( use_image_info.image_srcset ) {
1207				$image.attr( 'srcset', use_image_info.image_srcset );
1208			}
1209			if ( use_image_info.image_sizes ) {
1210				$image.attr( 'sizes', use_image_info.image_sizes );
1211			}
1212
1213			$product_img.tc_set_attr( 'title', use_image_info.image_title );
1214			$product_img.tc_set_attr( 'alt', use_image_info.image_alt );
1215
1216			$product_img.tc_set_attr( 'data-large-image', use_image_info.image_link );
1217			if ( $product_img.data.wc27_zoom_target ) {
1218				$product_img.data.wc27_zoom_target.tc_set_attr( 'data-thumb', use_image_info.image_link );
1219				$product_element.find( '.flex-control-nav li:eq(0) img' ).tc_set_attr( 'src', use_image_info.image_link );
1220			}
1221
1222			$product_link.tc_set_attr( 'href', use_image_info.image_link );
1223			$product_link.tc_set_attr( 'title', use_image_info.image_caption );
1224		} else {
1225			$product_img.tc_reset_attr( 'title' );
1226			$product_img.tc_reset_attr( 'alt' );
1227
1228			$product_img.tc_reset_attr( 'data-large-image' );
1229			if ( $product_img.data.wc27_zoom_target ) {
1230				$product_img.data.wc27_zoom_target.tc_reset_attr( 'data-thumb' );
1231				$product_element.find( '.flex-control-nav li:eq(0) img' ).tc_reset_attr( 'src' );
1232			}
1233
1234			$product_link.tc_reset_attr( 'href' );
1235			$product_link.tc_reset_attr( 'title' );
1236		}
1237	};
1238
1239	// variations checker
1240	$.fn.tm_find_matching_variations = function( product_variations, settings ) {
1241		var matching = [];
1242		var i;
1243		var variation;
1244
1245		if ( product_variations ) {
1246			for ( i = 0; i < product_variations.length; i += 1 ) {
1247				variation = product_variations[ i ];
1248
1249				if ( $.fn.tm_variations_match( variation.attributes, settings ) ) {
1250					matching.push( variation );
1251				}
1252			}
1253		}
1254
1255		return matching;
1256	};
1257
1258	$.fn.tm_variations_match = function( attrs1, attrs2 ) {
1259		var match = true;
1260		var val1;
1261		var val2;
1262
1263		Object.keys( attrs1 ).forEach( function( x ) {
1264			if ( Object.prototype.hasOwnProperty.call( attrs1, x ) ) {
1265				val1 = attrs1[ x ];
1266				val2 = attrs2[ x ];
1267
1268				if ( val1 !== undefined && val2 !== undefined && val1.length !== 0 && val2.length !== 0 && val1 !== val2 ) {
1269					match = false;
1270				}
1271			}
1272		} );
1273
1274		return match;
1275	};
1276
1277	function get_element_from_field( element ) {
1278		var $element = $( element );
1279		var data_uniqid;
1280		var the_epo_id;
1281		var _class;
1282		var epoContainer;
1283
1284		if ( $element.length === 0 ) {
1285			return;
1286		}
1287
1288		if ( $element.is( '.cpf-section' ) ) {
1289			return element.find( '.tm-epo-field' );
1290		}
1291		data_uniqid = $element.attr( 'data-uniqid' );
1292		epoContainer = $element.closest( '.tc-extra-product-options' );
1293		the_epo_id = epoContainer.attr( 'data-epo-id' );
1294
1295		if ( ! epoContainer.is( '.reactivate' ) && tcAPI.getElementFromFieldCache && tcAPI.getElementFromFieldCache[ the_epo_id ] && tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ] ) {
1296			return tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ];
1297		}
1298		_class = $element
1299			.attr( 'class' )
1300			.split( ' ' )
1301			.map( function( cls ) {
1302				if ( cls.indexOf( 'cpf-type-', 0 ) !== -1 ) {
1303					return cls;
1304				}
1305				return null;
1306			} )
1307			.filter( function( v ) {
1308				if ( v !== null && v !== undefined ) {
1309					return v;
1310				}
1311				return null;
1312			} );
1313
1314		if ( _class.length > 0 ) {
1315			_class = _class[ 0 ];
1316			if ( _class === 'cpf-type-product' ) {
1317				if ( $element.is( '.cpf-type-product-mode-product' ) || $element.is( '.cpf-type-product-checkbox' ) || $element.is( '.cpf-type-product-thumbnailmultiple' ) ) {
1318					_class = 'cpf-type-checkbox';
1319				} else if ( $element.is( '.cpf-type-product-dropdown' ) ) {
1320					_class = 'cpf-type-select';
1321				} else {
1322					_class = 'cpf-type-radio';
1323				}
1324			}
1325			switch ( _class ) {
1326				case 'cpf-type-radio':
1327					tcAPI.getElementFromFieldCache[ the_epo_id ] = [];
1328					tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ] = $element.find( '.tm-epo-field.tmcp-radio' );
1329					return tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ];
1330
1331				case 'cpf-type-checkbox':
1332					tcAPI.getElementFromFieldCache[ the_epo_id ] = [];
1333					tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ] = $element.find( '.tm-epo-field.tmcp-checkbox' );
1334					return tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ];
1335
1336				case 'cpf-type-select':
1337					tcAPI.getElementFromFieldCache[ the_epo_id ] = [];
1338					tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ] = $element.find( '.tm-epo-field.tmcp-select' );
1339					return tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ];
1340
1341				case 'cpf-type-selectmultiple':
1342					tcAPI.getElementFromFieldCache[ the_epo_id ] = [];
1343					tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ] = $element.find( '.tm-epo-field.tmcp-selectmultiple' );
1344					return tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ];
1345
1346				case 'cpf-type-textarea':
1347					tcAPI.getElementFromFieldCache[ the_epo_id ] = [];
1348					tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ] = $element.find( '.tm-epo-field.tmcp-textarea' );
1349					return tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ];
1350
1351				case 'cpf-type-textfield':
1352					tcAPI.getElementFromFieldCache[ the_epo_id ] = [];
1353					tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ] = $element.find( '.tm-epo-field.tmcp-textfield' );
1354					return tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ];
1355
1356				case 'cpf-type-color':
1357					tcAPI.getElementFromFieldCache[ the_epo_id ] = [];
1358					tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ] = $element.find( '.tm-epo-field.tm-color-picker' );
1359					return tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ];
1360
1361				case 'cpf-type-range':
1362					tcAPI.getElementFromFieldCache[ the_epo_id ] = [];
1363					tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ] = $element.find( '.tm-epo-field.tmcp-range' );
1364					return tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ];
1365
1366				case 'cpf-type-date':
1367					tcAPI.getElementFromFieldCache[ the_epo_id ] = [];
1368					tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ] = $element.find( '.tm-epo-field.tmcp-date' );
1369					return tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ];
1370
1371				case 'cpf-type-time':
1372					tcAPI.getElementFromFieldCache[ the_epo_id ] = [];
1373					tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ] = $element.find( '.tm-epo-field.tmcp-time' );
1374					return tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ];
1375
1376				case 'cpf-type-variations':
1377					tcAPI.getElementFromFieldCache[ the_epo_id ] = [];
1378					tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ] = $element.closest( '.cpf-section' ).find( '.tm-epo-field.tm-epo-variation-element' );
1379					return tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ];
1380			}
1381		}
1382	}
1383
1384	// tc-lightbox
1385	if ( ! $().tclightbox ) {
1386		$.fn.tclightbox = function() {
1387			var elements = this;
1388
1389			if ( elements.length === 0 ) {
1390				return;
1391			}
1392
1393			return elements.each( function() {
1394				var $this = $( this );
1395				var _imgsrc;
1396				var _label;
1397				var _input;
1398				var tclightboxwrap;
1399				var _img_button;
1400				var preload_img;
1401				var addButtonEvent;
1402
1403				if ( $this.is( '.tcinit' ) ) {
1404					return;
1405				}
1406				_imgsrc = $this.attr( 'src' ) || $this.attr( 'data-original' );
1407				_label = $this.closest( 'label' );
1408				_input = _label.closest( '.tmcp-field-wrap' ).find( ".tm-epo-field[id='" + _label.attr( 'for' ) + "']" );
1409				_imgsrc = _input.attr( 'data-imagel' ) || _input.attr( 'data-imagep' ) || _input.attr( 'data-image' ) || _imgsrc;
1410
1411				if ( ! _imgsrc ) {
1412					return;
1413				}
1414
1415				$this.addClass( 'tcinit' ).before( $.epoAPI.template.html( tcAPI.templateEngine.tc_lightbox, {} ) );
1416				tclightboxwrap = $this.prev();
1417
1418				$this.wrap( "<div class='tc-lightbox-image-wrap'/>" );
1419				$this.after( tclightboxwrap );
1420
1421				_img_button = tclightboxwrap.find( '.tc-lightbox-button' );
1422
1423				addButtonEvent = function() {
1424					_img_button.addClass( 'tcinit' ).on( 'click.tclightbox', function( buttonevent ) {
1425						var size;
1426						var _img;
1427
1428						if ( $( '.tc-closing.tc-lightbox' ).length > 0 ) {
1429							return;
1430						}
1431
1432						size = $.epoAPI.dom.size();
1433						_img = $( '<img>' )
1434							.addClass( 'tc-lightbox-img' )
1435							.attr( 'src', _imgsrc )
1436							.css( 'maxHeight', size.visibleHeight + 'px' )
1437							.css( 'maxWidth', size.visibleWidth + 'px' );
1438
1439						$.tcFloatBox( {
1440							fps: 1,
1441							ismodal: false,
1442							refresh: 'fixed',
1443							width: 'auto',
1444							height: 'auto',
1445							top: '0%',
1446							left: '0%',
1447							classname: 'flasho tc-lightbox',
1448							animateIn: 'tc-lightbox-zoomin',
1449							animateOut: 'tc-lightbox-zoomout',
1450							data: $.epoAPI.template.html( tcAPI.templateEngine.tc_lightbox_zoom, { img: _img[ 0 ].outerHTML } ),
1451							zIndex: 102001,
1452							cancelClass: '.tc-lightbox-img, .tc-lightbox-button-close',
1453							unique: true
1454						} );
1455
1456						buttonevent.preventDefault();
1457					} );
1458				};
1459				if ( TMEPOJS.tm_epo_preload_lightbox_image === 'yes' ) {
1460					preload_img = new Image();
1461					preload_img.src = _imgsrc;
1462					preload_img.onload = function() {
1463						addButtonEvent();
1464					};
1465				} else {
1466					addButtonEvent();
1467				}
1468			} );
1469		};
1470	}
1471
1472	// Start Section popup
1473	if ( ! $().tmsectionpoplink ) {
1474		$.fn.tmsectionpoplink = function() {
1475			var elements = this;
1476
1477			if ( elements.length === 0 ) {
1478				return;
1479			}
1480
1481			return elements.each( function() {
1482				var $this = $( this );
1483				var id;
1484				var title;
1485				var section;
1486				var clicked;
1487				var _ovl;
1488				var cancelfunc;
1489
1490				if ( $this.data( 'tmsectionpoplink' ) ) {
1491					return;
1492				}
1493
1494				$this.data( 'tmsectionpoplink', true );
1495				id = $this.attr( 'data-sectionid' );
1496				title = TMEPOJS.i18n_addition_options;
1497				section = $this.closest( ".cpf-section[data-uniqid='" + id + "']" );
1498				clicked = false;
1499				_ovl = $( '<div class="fl-overlay"></div>' ).css( {
1500					zIndex: parseInt( $this.zIndex, 10 ) - 1,
1501					opacity: 0.8
1502				} );
1503				cancelfunc = function() {
1504					var pop = $( '#tm-section-pop-up' );
1505					pop.parents().removeClass( 'noanimated' );
1506
1507					_ovl.unbind().remove();
1508					pop.after( section );
1509					pop.remove();
1510
1511					section.find( '.tm-section-link' ).show();
1512					section.find( '.tm-section-pop' ).hide();
1513				};
1514
1515				if ( $this.attr( 'data-title' ) ) {
1516					title = $this.attr( 'data-title' );
1517				}
1518
1519				$this.on( 'click.tmsectionpoplink', function( e ) {
1520					var pop;
1521
1522					e.preventDefault();
1523					clicked = false;
1524					_ovl.appendTo( 'body' ).on( 'click', cancelfunc );
1525
1526					section.before(
1527						$.epoAPI.template.html( tcAPI.templateEngine.tc_section_pop_link, {
1528							title: title,
1529							close: TMEPOJS.i18n_close
1530						} )
1531					);
1532
1533					pop = $( '#tm-section-pop-up' );
1534
1535					pop.find( '.float-editbox' ).prepend( section );
1536
1537					section.find( '.tm-section-link' ).hide();
1538					section.find( '.tm-section-pop' ).show();
1539
1540					pop.parents().addClass( 'noanimated' );
1541
1542					pop.find( '.floatbox-cancel' ).on( 'click', function() {
1543						if ( clicked ) {
1544							return;
1545						}
1546						clicked = true;
1547						cancelfunc();
1548					} );
1549					jWindow.trigger( 'tmlazy' );
1550					jWindow.trigger( 'tmsectionpoplink' );
1551				} );
1552			} );
1553		};
1554	} // End Section popup
1555
1556	function getVariationIdSelector( currentCart ) {
1557		var variationIdSelector = "input[name^='variation_id']";
1558
1559		if ( currentCart.find( 'input.variation_id' ).length > 0 ) {
1560			variationIdSelector = 'input.variation_id';
1561		} else {
1562			variationIdSelector = 'input.product-variation-id';
1563		}
1564
1565		return variationIdSelector;
1566	}
1567
1568	function getVariationIdElement( currentCart, not ) {
1569		var variationIdSelector = getVariationIdSelector( currentCart );
1570		var variationIdElement = currentCart.find( variationIdSelector );
1571
1572		if ( currentCart.is( '.tc-epo-element-product-container-cart' ) ) {
1573			variationIdElement = currentCart.closest( '.tc-epo-element-product-li-container' ).find( variationIdSelector );
1574		} else {
1575			variationIdElement = currentCart.find( variationIdSelector );
1576		}
1577		if ( not ) {
1578			variationIdElement = variationIdElement.not( not );
1579		}
1580
1581		return variationIdElement;
1582	}
1583
1584	function getCurrentVariation( currentCart ) {
1585		return currentCart.find( getVariationIdSelector( currentCart ) ).val() || 0;
1586	}
1587
1588	function getQtyElement( currentCart ) {
1589		var qty = currentCart.find( tcAPI.qtySelector ).last();
1590		if ( qty.length === 0 ) {
1591			qty = currentCart.find( tcAPI.associateQtySelector ).last();
1592		}
1593		qty = $.epoAPI.applyFilter( 'tc_getQtyElement', qty, currentCart );
1594		return qty;
1595	}
1596
1597	function getCurrentQty( currentCart ) {
1598		return $.epoAPI.applyFilter( 'tc_getCurrentQty', $.epoAPI.math.toFloat( getQtyElement( currentCart ).val() ), currentCart );
1599	}
1600
1601	function add_variation_event( name, selector, func ) {
1602		lateVariationEvent[ lateVariationEvent.length ] = {
1603			name: name,
1604			selector: selector,
1605			func: func
1606		};
1607	}
1608
1609	function field_is_active( field, nochecks, single ) {
1610		var ret = true;
1611		var insideProductCheck = false;
1612		var productElement;
1613		field = $( field );
1614		productElement = field.filter( '.tc-epo-field-product' );
1615		if ( productElement.length && productElement.data( 'islogicinit' ) === undefined ) {
1616			insideProductCheck = true;
1617		}
1618		field.each( function( j, element ) {
1619			if ( ! ret && field.has( '.tc-epo-field-product' ).length ) {
1620				if ( insideProductCheck || productElement.is( '.tcdisabled' ) ) {
1621					field_check_active( element, nochecks, single );
1622				}
1623			} else {
1624				ret = field_check_active( element, nochecks, single ) && ret;
1625			}
1626		} );
1627
1628		return ret;
1629	}
1630
1631	function field_check_active( field, nochecks, single ) {
1632		var hideElement;
1633		var singleField;
1634		var ul;
1635		var isInsideProductElement;
1636		var productElementActive;
1637		var productElementSectionActive;
1638		var productElementQty;
1639
1640		field = $( field );
1641		if ( field.is( '.cpf-element' ) ) {
1642			hideElement = field;
1643			field = field.find( '.tmcp-field, .tmcp-fee-field' );
1644		} else {
1645			hideElement = field.closest( '.cpf-element' );
1646		}
1647
1648		if ( single ) {
1649			ul = field.closest( '.tmcp-ul-wrap' );
1650		} else {
1651			ul = hideElement;
1652		}
1653
1654		if ( field.is( '.tc-epo-field-product' ) && field.data( 'islogicinit' ) === undefined ) {
1655			field.data( 'islogicinit', 1 );
1656		}
1657
1658		isInsideProductElement = ! field.is( '.tc-epo-field-product' ) && hideElement.closest( '.cpf-type-product' );
1659
1660		if ( isInsideProductElement.length ) {
1661			productElementQty = isInsideProductElement.find( tcAPI.associateQtySelector );
1662			if ( productElementQty.length ) {
1663				if ( $.epoAPI.math.toFloat( productElementQty.val() ) > 0 ) {
1664					field.removeClass( 'ignore' );
1665					productElementQty.removeClass( 'ignore' );
1666				} else {
1667					field.addClass( 'ignore' );
1668					productElementQty.addClass( 'ignore' );
1669				}
1670			}
1671			productElementActive = isInsideProductElement.data( 'isactive' );
1672			isInsideProductElement = isInsideProductElement.closest( '.cpf-section' );
1673			productElementSectionActive = isInsideProductElement.data( 'isactive' );
1674		}
1675		if ( productElementActive !== false && productElementSectionActive !== false && hideElement.data( 'isactive' ) !== false && hideElement.closest( '.cpf-section' ).data( 'isactive' ) !== false ) {
1676			singleField = field.first();
1677			field.prop( 'disabled', false );
1678			if ( field.data( 'tc-state' ) !== undefined ) {
1679				field.data( 'tc-state', false );
1680			}
1681
1682			if ( TMEPOJS.tm_epo_show_only_active_quantities !== 'yes' ) {
1683				if ( singleField.is( ':radio, .cpf-type-radio' ) || singleField.is( ':checkbox, .cpf-type-checkbox' ) ) {
1684					field.filter( ':checked' ).closest( '.tmcp-field-wrap' ).find( '.tm-qty' ).prop( 'disabled', false );
1685					field.not( ':checked' ).closest( '.tmcp-field-wrap' ).find( '.tm-qty' ).prop( 'disabled', true );
1686				} else if ( singleField.is( 'select, .cpf-type-select, .cpf-type-selectmultiple' ) ) {
1687					if ( singleField.val() ) {
1688						ul.find( '.tm-qty' ).prop( 'disabled', false );
1689					} else {
1690						ul.find( '.tm-qty' ).prop( 'disabled', true );
1691					}
1692				} else if ( singleField.val() ) {
1693					ul.find( '.tm-qty' ).prop( 'disabled', false );
1694				} else {
1695					ul.find( '.tm-qty' ).prop( 'disabled', true );
1696				}
1697			} else if ( ! nochecks ) {
1698				hideElement.find( '.tm-quantity' ).trigger( 'showhide.cpfcustom' );
1699			}
1700
1701			if ( ! singleField.is( '.cpf-element' ) ) {
1702				field.removeClass( 'tcdisabled' ).addClass( 'tcenabled' );
1703
1704				if ( field.is( '.tmcp-upload' ) ) {
1705					if ( field.next( '.tmcp-upload-hidden' ).length ) {
1706						field.next( '.tmcp-upload-hidden' ).removeClass( 'tcdisabled' ).addClass( 'tcenabled' ).prop( 'disabled', false );
1707					}
1708				}
1709			}
1710
1711			hideElement.removeClass( 'tc-container-disabled' ).addClass( 'tc-container-enabled' );
1712
1713			field.trigger( {
1714				type: 'tm-field-is-active',
1715				field: field,
1716				value: true
1717			} );
1718
1719			return true;
1720		}
1721
1722		if ( ! field.is( '.cpf-element' ) ) {
1723			field.prop( 'disabled', true ).removeClass( 'tcenabled' ).addClass( 'tcdisabled' );
1724			if ( field.data( 'tc-state' ) !== undefined ) {
1725				field.data( 'tc-state', true );
1726			}
1727			hideElement.find( '.tm-qty' ).prop( 'disabled', true );
1728			if ( field.is( '.tmcp-upload' ) ) {
1729				if ( field.next( '.tmcp-upload-hidden' ).length ) {
1730					field.next( '.tmcp-upload-hidden' ).removeClass( 'tcenabled' ).addClass( 'tcdisabled' ).prop( 'disabled', true );
1731				}
1732			}
1733		}
1734
1735		hideElement.removeClass( 'tc-container-enabled' ).addClass( 'tc-container-disabled' );
1736
1737		field.trigger( {
1738			type: 'tm-field-is-active',
1739			field: field,
1740			value: false
1741		} );
1742
1743		return false;
1744	}
1745
1746	function tm_variation_check_match( element, val2, operator ) {
1747		var $element = $( element );
1748		var epoId = $element.attr( 'data-epo_id' );
1749		var productId = $element.attr( 'data-product_id' );
1750
1751		var variationsForm = $( ".variations_form[data-epo_id='" + epoId + "'][data-product_id='" + productId + "']" );
1752		var val1;
1753		var variationIdSelector = "input[name^='variation_id']";
1754		var $variationId;
1755
1756		variationsForm = $.epoAPI.applyFilter( 'tm_variation_check_match_variationsForm', variationsForm, epoId, productId, $element );
1757
1758		if ( variationsForm.length === 0 ) {
1759			return false;
1760		}
1761
1762		$variationId = variationsForm.find( variationIdSelector );
1763
1764		if ( $variationId.length === 0 ) {
1765			variationIdSelector = 'input.variation_id';
1766
1767			$variationId = variationsForm.find( variationIdSelector );
1768
1769			if ( $variationId.length === 0 ) {
1770				$variationId = variationsForm.closest( '.tc-epo-element-product-li-container' ).find( '.product-variation-id' );
1771			}
1772		}
1773
1774		if ( element !== null && val2 !== null && element !== undefined && val2 !== undefined && element !== false && val2 !== false ) {
1775			if ( val2 ) {
1776				val2 = parseInt( val2, 10 );
1777			} else {
1778				val2 = -1;
1779			}
1780		}
1781
1782		val1 = parseInt( $variationId.val(), 10 );
1783
1784		if ( ! Number.isFinite( val1 ) ) {
1785			val1 = '';
1786		}
1787		if ( ! Number.isFinite( val2 ) ) {
1788			val2 = '';
1789		}
1790
1791		switch ( operator ) {
1792			case 'is':
1793				return val1 !== '' && val1 === val2;
1794
1795			case 'isnot':
1796				return val1 !== '' && val1 !== val2;
1797
1798			case 'isempty':
1799				return val1 === '' || val1 === 0;
1800
1801			case 'isnotempty':
1802				return val1 !== '' && val1 !== 0;
1803
1804			case 'startswith':
1805				return val1.toString().startsWith( val2 );
1806
1807			case 'endswith':
1808				return val1.toString().endsWith( val2 );
1809
1810			case 'greaterthan':
1811				return parseFloat( val1 ) > parseFloat( val2 );
1812
1813			case 'lessthan':
1814				return parseFloat( val1 ) < parseFloat( val2 );
1815
1816			case 'greaterthanequal':
1817				return parseFloat( val1 ) >= parseFloat( val2 );
1818
1819			case 'lessthanequal':
1820				return parseFloat( val1 ) <= parseFloat( val2 );
1821		}
1822		return false;
1823	}
1824
1825	function tm_check_match( val1, val2, operator ) {
1826		if ( val1 !== null && val2 !== null ) {
1827			val1 = encodeURIComponent( val1 );
1828			if ( $.qtranxj_split ) {
1829				//backwards compatible
1830				val2 = encodeURIComponent( $.qtranxj_split( decodeURIComponent( val2 ) )[ TMEPOQTRANSLATEXJS.language ] );
1831			} else {
1832				//backwards compatible
1833				val2 = encodeURIComponent( decodeURIComponent( val2 ) );
1834			}
1835
1836			if ( val1 ) {
1837				val1 = val1.toLowerCase();
1838			} else {
1839				val1 = '';
1840			}
1841			if ( val2 ) {
1842				val2 = val2.toLowerCase();
1843			} else {
1844				val2 = '';
1845			}
1846		} else {
1847			return false;
1848		}
1849
1850		val1 = val1.toString();
1851		val2 = val2.toString();
1852
1853		switch ( operator ) {
1854			case 'is':
1855				return val1 !== null && val1 === val2;
1856
1857			case 'isnot':
1858				return val1 !== null && val1 !== val2;
1859
1860			case 'isempty':
1861				return ! ( val1 !== 'undefined' && val1 !== undefined && val1 !== '' );
1862
1863			case 'isnotempty':
1864				return val1 !== 'undefined' && val1 !== undefined && val1 !== '';
1865
1866			case 'startswith':
1867				return val1.startsWith( val2 );
1868
1869			case 'endswith':
1870				return val1.endsWith( val2 );
1871
1872			case 'greaterthan':
1873				return parseFloat( val1 ) > parseFloat( val2 );
1874
1875			case 'lessthan':
1876				return parseFloat( val1 ) < parseFloat( val2 );
1877
1878			case 'greaterthanequal':
1879				return parseFloat( val1 ) >= parseFloat( val2 );
1880
1881			case 'lessthanequal':
1882				return parseFloat( val1 ) <= parseFloat( val2 );
1883		}
1884
1885		return false;
1886	}
1887
1888	function tm_check_section_match( elements, operator ) {
1889		var all_checked = true;
1890		var val;
1891		var all_elements = elements.find( '.cpf-element' );
1892		var radio_checked;
1893		var checkbox_checked;
1894		var noSplit = false;
1895
1896		if ( elements.is( '.tc-hidden' ) ) {
1897			if ( operator === 'isnotempty' ) {
1898				return false;
1899			} else if ( operator === 'isempty' ) {
1900				return true;
1901			}
1902		}
1903
1904		$( all_elements ).each( function( j, element ) {
1905			var _class;
1906			var elementToCheck = '';
1907
1908			element = $( element );
1909			if ( element.is( '.cpf-type-product' ) ) {
1910				elementToCheck = ':not(.tc-extra-product-options-inline .tm-epo-field)';
1911			}
1912			if ( field_is_active( element ) ) {
1913				_class = element
1914					.attr( 'class' )
1915					.split( ' ' )
1916					.map( function( cls ) {
1917						if ( cls.indexOf( 'cpf-type-', 0 ) !== -1 ) {
1918							return cls;
1919						}
1920						return null;
1921					} )
1922					.filter( function( v ) {
1923						if ( v !== null && v !== undefined ) {
1924							return v;
1925						}
1926						return null;
1927					} );
1928
1929				if ( _class.length > 0 ) {
1930					_class = _class[ 0 ];
1931					if ( _class === 'cpf-type-product' ) {
1932						noSplit = true;
1933						if ( element.is( '.cpf-type-product-mode-product' ) || element.is( '.cpf-type-product-checkbox' ) || element.is( '.cpf-type-product-thumbnailmultiple' ) ) {
1934							_class = 'cpf-type-checkbox';
1935						} else if ( element.is( '.cpf-type-product-dropdown' ) ) {
1936							_class = 'cpf-type-select';
1937						} else {
1938							_class = 'cpf-type-radio';
1939						}
1940					}
1941					switch ( _class ) {
1942						case 'cpf-type-radio':
1943							radio_checked = element.find( 'input.tm-epo-field.tmcp-radio:checked' + elementToCheck );
1944							if ( operator === 'isnotempty' ) {
1945								all_checked = all_checked && radio_checked.length > 0;
1946								if ( radio_checked.length > 0 ) {
1947									val = radio_checked.length;
1948								}
1949							} else if ( operator === 'isempty' ) {
1950								all_checked = all_checked && radio_checked.length === 0;
1951							}
1952							break;
1953
1954						case 'cpf-type-checkbox':
1955							checkbox_checked = element.find( 'input.tm-epo-field.tmcp-checkbox:checked' + elementToCheck );
1956							if ( operator === 'isnotempty' ) {
1957								all_checked = all_checked && checkbox_checked.length > 0;
1958								if ( checkbox_checked.length > 0 ) {
1959									val = checkbox_checked.length;
1960								}
1961							} else if ( operator === 'isempty' ) {
1962								all_checked = all_checked && checkbox_checked.length === 0;
1963							}
1964							break;
1965
1966						case 'cpf-type-select':
1967							val = element.find( 'select.tm-epo-field.tmcp-select' + elementToCheck ).val();
1968							if ( val && ! noSplit ) {
1969								val = val.slice( 0, val.lastIndexOf( '_' ) );
1970							}
1971							break;
1972
1973						case 'cpf-type-selectmultiple':
1974							val = element.find( 'select.tm-epo-field.tmcp-selectmultiple' + elementToCheck ).val();
1975							if ( val && ! noSplit ) {
1976								val.forEach( function( option, i ) {
1977									val[ i ] = option.slice( 0, option.lastIndexOf( '_' ) );
1978								} );
1979							}
1980							break;
1981
1982						default:
1983							val = element.find( '.tm-epo-field' + elementToCheck ).val();
1984							break;
1985					}
1986					if ( Array.isArray( val ) ) {
1987						all_checked = all_checked && val.some( function( item ) {
1988							return tm_check_match( item, '', operator );
1989						} );
1990					} else {
1991						all_checked = all_checked && tm_check_match( val, '', operator );
1992					}
1993				} else {
1994					all_checked = all_checked && false;
1995				}
1996			}
1997		} );
1998
1999		return all_checked;
2000	}
2001
2002	function tm_check_field_match( f ) {
2003		var element = $( f.element );
2004		var operator = f.operator;
2005		var value = f.value;
2006		var val;
2007		var radio_checked;
2008		var checkbox_checked;
2009		var ret;
2010		var _class;
2011		var noSplit = false;
2012		var elementToCheck = '';
2013
2014		if ( ! element.length ) {
2015			return false;
2016		}
2017		if ( element.is( '.cpf-section' ) ) {
2018			return tm_check_section_match( element, operator );
2019		}
2020		if ( element.is( '.cpf-type-product' ) ) {
2021			elementToCheck = ':not(.tc-extra-product-options-inline .tm-epo-field)';
2022		}
2023		_class = element
2024			.attr( 'class' )
2025			.split( ' ' )
2026			.map( function( cls ) {
2027				if ( cls.indexOf( 'cpf-type-', 0 ) !== -1 ) {
2028					return cls;
2029				}
2030				return null;
2031			} )
2032			.filter( function( v ) {
2033				if ( v !== null && v !== undefined ) {
2034					return v;
2035				}
2036				return null;
2037			} );
2038
2039		if ( _class.length > 0 ) {
2040			_class = _class[ 0 ];
2041			if ( _class === 'cpf-type-product' ) {
2042				noSplit = true;
2043				if ( element.is( '.cpf-type-product-mode-product' ) || element.is( '.cpf-type-product-checkbox' ) || element.is( '.cpf-type-product-thumbnailmultiple' ) ) {
2044					_class = 'cpf-type-checkbox';
2045				} else if ( element.is( '.cpf-type-product-dropdown' ) ) {
2046					_class = 'cpf-type-select';
2047				} else {
2048					_class = 'cpf-type-radio';
2049				}
2050			}
2051			switch ( _class ) {
2052				case 'cpf-type-radio':
2053					radio_checked = element.find( 'input.tm-epo-field.tmcp-radio:checked' + elementToCheck );
2054
2055					if ( operator === 'is' || operator === 'isnot' ) {
2056						if ( radio_checked.length === 0 ) {
2057							return false;
2058						}
2059						val = element.find( 'input.tm-epo-field.tmcp-radio:checked' + elementToCheck ).val();
2060						if ( val && ! noSplit ) {
2061							val = val.slice( 0, val.lastIndexOf( '_' ) );
2062						}
2063					}
2064					if ( operator === 'isnotempty' ) {
2065						return radio_checked.length > 0;
2066					}
2067					if ( operator === 'isempty' ) {
2068						return radio_checked.length === 0;
2069					}
2070					break;
2071				case 'cpf-type-checkbox':
2072					checkbox_checked = element.find( 'input.tm-epo-field.tmcp-checkbox:checked' + elementToCheck );
2073
2074					if ( operator === 'is' || operator === 'isnot' ) {
2075						if ( checkbox_checked.length === 0 ) {
2076							return false;
2077						}
2078						ret = false;
2079						checkbox_checked.each( function( i, el ) {
2080							val = $( el ).val();
2081							if ( val && ! noSplit ) {
2082								val = val.slice( 0, val.lastIndexOf( '_' ) );
2083							}
2084							if ( tm_check_match( val, value, operator ) ) {
2085								ret = true;
2086							} else if ( operator === 'isnot' ) {
2087								ret = false;
2088								return false;
2089							}
2090						} );
2091						return ret;
2092					}
2093					if ( operator === 'isnotempty' ) {
2094						return checkbox_checked.length > 0;
2095					}
2096					if ( operator === 'isempty' ) {
2097						return checkbox_checked.length === 0;
2098					}
2099					break;
2100
2101				case 'cpf-type-select':
2102					val = element.find( 'select.tm-epo-field.tmcp-select' + elementToCheck ).val();
2103					if ( val && ! noSplit ) {
2104						val = val.slice( 0, val.lastIndexOf( '_' ) );
2105					}
2106					break;
2107
2108				case 'cpf-type-selectmultiple':
2109					val = element.find( 'select.tm-epo-field.tmcp-selectmultiple' + elementToCheck ).val();
2110					if ( val && ! noSplit ) {
2111						val.forEach( function( option, i ) {
2112							val[ i ] = option.slice( 0, option.lastIndexOf( '_' ) );
2113						} );
2114					}
2115					break;
2116
2117				case 'cpf-type-variations':
2118					return tm_variation_check_match( element, value, operator );
2119
2120				default:
2121					val = element.find( '.tm-epo-field' + elementToCheck ).val();
2122					break;
2123			}
2124			if ( Array.isArray( val ) ) {
2125				return val.some( function( item ) {
2126					return tm_check_match( item, value, operator );
2127				} );
2128			}
2129			return tm_check_match( val, value, operator );
2130		}
2131		return false;
2132	}
2133
2134	function tm_check_rules( o, theevent ) {
2135		o.each( function() {
2136			var $this = $( this );
2137			var matches = parseInt( $this.data( 'matches' ), 10 );
2138			var toggle = $this.data( 'toggle' );
2139			var what = $this.data( 'what' );
2140			var fields = $this.data( 'fields' );
2141			var checked = 0;
2142			var show = false;
2143
2144			switch ( toggle ) {
2145				case 'show':
2146					show = false;
2147					break;
2148				case 'hide':
2149					show = true;
2150					break;
2151			}
2152
2153			$.each( fields, function( i, field ) {
2154				var fia = true;
2155
2156				if ( theevent === 'cpflogic' ) {
2157					fia = field_is_active( $( field.element ) );
2158				}
2159				if ( fia && tm_check_field_match( field ) ) {
2160					checked = parseInt( checked, 10 ) + 1;
2161				}
2162			} );
2163
2164			if ( what === 'all' ) {
2165				if ( matches === checked ) {
2166					show = ! show;
2167				}
2168			} else if ( checked > 0 ) {
2169				show = ! show;
2170			}
2171			if ( show ) {
2172				if ( theevent === 'cpflogic' && ! $this.data( 'did_initial_activation' ) ) {
2173					latecpflogicactions.push( function() {
2174						var enabledEpos = $this.find( '.tm-epo-field.tcenabled' );
2175						enabledEpos.each( function( i, el ) {
2176							el = $( el );
2177							if ( ! el.data( 'initial_activation' ) && ! $this.closest( '.cpf-section' ).is( '.tc-hidden' ) && field_is_active( el ) ) {
2178								el.trigger( 'tc_element_epo_rules' );
2179								el.data( 'initial_activation', 1 );
2180							}
2181						} );
2182						if ( ( $this.is( '.cpf-element' ) && enabledEpos.length ) || $this.is( '.cpf-section' ) ) {
2183							$this.data( 'did_initial_activation', 1 );
2184						}
2185					} );
2186				}
2187
2188				$this.removeClass( 'tc-hidden' );
2189			} else {
2190				$this.addClass( 'tc-hidden' );
2191			}
2192			$this.data( 'isactive', show );
2193			$this.trigger( 'tc-logic' );
2194		} );
2195	}
2196
2197	function run_cpfdependson( obj ) {
2198		var iscpfdependson;
2199		var last_activate_field = [];
2200
2201		if ( ! $( obj ).length ) {
2202			obj = 'body';
2203		}
2204		obj = $( obj );
2205		iscpfdependson = obj.find( '.iscpfdependson' );
2206		iscpfdependson.each( function( i, elements ) {
2207			$( elements ).each( function( j, el ) {
2208				tm_check_rules( $( el ) );
2209			} );
2210		} );
2211		iscpfdependson.each( function( i, elements ) {
2212			$( elements ).each( function( j, el ) {
2213				tm_check_rules( $( el ), 'cpflogic' );
2214			} );
2215		} );
2216		iscpfdependson.each( function( i, elements ) {
2217			$( elements ).each( function( j, o ) {
2218				o = $( o );
2219				if ( o.is( '.cpf-section' ) ) {
2220					o = o.find( '.cpf-element' );
2221				}
2222				o.each( function( theindex, theelement ) {
2223					field_is_active( $( theelement ).find( '.tm-epo-field' ) );
2224				} );
2225			} );
2226		} );
2227		latecpflogicactions.forEach( function( func ) {
2228			func();
2229		} );
2230		latecpflogicactions = [];
2231		if ( $().selectric ) {
2232			$( '.tm-extra-product-options select' ).selectric( 'refresh' );
2233		}
2234		setTimeout( function() {
2235			$( '.tm-owl-slider' ).each( function() {
2236				$( this ).trigger( 'refresh.owl.carousel' );
2237			} );
2238		}, 200 );
2239
2240		obj.find( '.tm-product-image:checked,select.tm-product-image' ).each( function() {
2241			var t = $( this );
2242			if ( field_is_active( t ) && t.val() !== '' ) {
2243				last_activate_field.push( t );
2244			}
2245		} );
2246		if ( last_activate_field.length ) {
2247			last_activate_field[ last_activate_field.length - 1 ].trigger( 'tm_trigger_product_image' );
2248		}
2249
2250		jWindow.trigger( 'cpflogicrun' );
2251		jWindow.trigger( 'tmlazy' );
2252		jWindow.trigger( 'cpflogicdone' );
2253	}
2254
2255	// Start Conditional logic
2256	if ( ! $().cpfdependson ) {
2257		$.fn.cpfdependson = function( fields, toggle, what, refresh ) {
2258			var elements = this;
2259			var matches = 0;
2260
2261			if ( elements.length === 0 || typeof fields !== 'object' ) {
2262				return;
2263			}
2264
2265			if ( ! toggle ) {
2266				toggle = 'show';
2267			}
2268			if ( ! what ) {
2269				what = 'all';
2270			}
2271
2272			$.each( fields, function( i, field ) {
2273				var get_element;
2274				var $this_epo_container;
2275
2276				if ( typeof fields !== 'object' ) {
2277					return true;
2278				}
2279
2280				get_element = get_element_from_field( field.element );
2281
2282				if ( get_element && get_element.length > 0 ) {
2283					get_element.each( function( ii, element ) {
2284						var $element = $( element );
2285						var $pid1;
2286						var $epo_id1;
2287						var _events = 'change.cpflogic';
2288
2289						// this essentially only works for the plugin so we use
2290						// cache and not recalcualte each time
2291						if ( ! $this_epo_container || $this_epo_container.closest( '.tc-extra-product-options-inline' ).length ) {
2292							$pid1 = '.tm-product-id-' + $element.closest( '.tc-extra-product-options' ).attr( 'data-product-id' );
2293							$epo_id1 = "[data-epo-id='" + $element.closest( '.tc-extra-product-options' ).attr( 'data-epo-id' ) + "']";
2294							$this_epo_container = $( '.tc-extra-product-options' + $pid1 + $epo_id1 );
2295						}
2296
2297						if ( element && $element.length > 0 && ( ! $element.data( 'tmhaslogicevents' ) || refresh ) ) {
2298							if ( $element.is( '.tm-epo-variation-element' ) ) {
2299								// associated product event prefixes are added later
2300								add_variation_event( 'found_variation.tmlogic', false, function() {
2301									run_cpfdependson( $this_epo_container );
2302									jWindow.trigger( 'tm-do-epo-update' );
2303								} );
2304								add_variation_event( 'hide_variation.tmlogic', false, function() {
2305									run_cpfdependson( $this_epo_container );
2306									jWindow.trigger( 'tm-do-epo-update' );
2307								} );
2308							} else {
2309								if ( $element.is( ':text' ) || $element.is( 'textarea' ) ) {
2310									_events = 'change.cpflogic input.cpflogic';
2311								}
2312								$element.off( _events ).on( _events, function() {
2313									run_cpfdependson( $this_epo_container );
2314								} );
2315							}
2316							$element.data( 'tmhaslogicevents', 1 );
2317						}
2318					} );
2319
2320					matches = parseInt( matches, 10 ) + 1;
2321				}
2322			} );
2323
2324			elements.each( function() {
2325				var $this = $( this );
2326				var show = false;
2327
2328				$this.data( 'matches', matches ).data( 'toggle', toggle ).data( 'what', what ).data( 'fields', fields );
2329
2330				switch ( toggle ) {
2331					case 'show':
2332						show = false;
2333						break;
2334					case 'hide':
2335						show = true;
2336						break;
2337				}
2338				if ( show ) {
2339					$this.removeClass( 'tc-hidden' );
2340				} else {
2341					$this.addClass( 'tc-hidden' );
2342				}
2343
2344				$this.data( 'isactive', show );
2345			} );
2346
2347			elements.addClass( 'iscpfdependson is-epo-depend' ).data( 'iscpfdependson', 1 );
2348			return elements;
2349		};
2350
2351		$.fn.run_cpfdependson = function() {
2352			run_cpfdependson();
2353		};
2354	}
2355
2356	$.tcepo = {
2357		formSubmitEvents: {},
2358
2359		oneOptionIsSelected: {},
2360
2361		initialActivation: {},
2362
2363		// Holds the active precentage of total current price type fields
2364		lateFieldsPrices: {},
2365
2366		errorObject: {}
2367	};
2368
2369	function validate_logic( l ) {
2370		return typeof l === 'object' && 'toggle' in l && 'what' in l && 'rules' in l && l.rules.length > 0;
2371	}
2372
2373	// The following loops are required for the logic to work on composite products that have custom variations
2374	function cpf_section_logic( obj ) {
2375		var root_element = $( obj );
2376		var all_sections = root_element.find( '.cpf-section' );
2377		var search_obj;
2378		var cpf_section;
2379		var sect;
2380		var logic;
2381		var haslogic;
2382		var fields;
2383		var section;
2384		var element;
2385		var operator;
2386		var value;
2387		var obj_section;
2388		var obj_element;
2389		var closestProductElement;
2390
2391		if ( root_element.is( '.cpf-section' ) ) {
2392			search_obj = false;
2393		} else {
2394			search_obj = all_sections;
2395		}
2396
2397		root_element.each( function( j, obj_el ) {
2398			if ( $( obj_el ).is( '.cpf-section' ) ) {
2399				cpf_section = $( obj_el );
2400			} else {
2401				cpf_section = $( obj_el ).find( '.cpf-section' );
2402			}
2403
2404			cpf_section.filter( '[data-haslogic="1"]' ).each( function( index, el ) {
2405				sect = $( el );
2406				logic = sect.data( 'logic' );
2407				haslogic = parseInt( sect.data( 'haslogic' ), 10 );
2408				fields = [];
2409				closestProductElement = sect.parent().closest( '.cpf-type-product' );
2410
2411				if ( haslogic === 1 && validate_logic( logic ) ) {
2412					$.each( logic.rules, function( i, rule ) {
2413						if ( rule ) {
2414							section = rule.section;
2415							element = rule.element;
2416							operator = rule.operator;
2417							value = rule.value;
2418
2419							if ( search_obj ) {
2420								if ( closestProductElement.length ) {
2421									obj_section = closestProductElement.find( '.cpf-section' ).filter( "[data-uniqid='" + section + "']" );
2422									if ( element !== section ) {
2423										obj_element = obj_section.find( '.cpf-element' ).eq( element );
2424									} else {
2425										obj_element = obj_section;
2426									}
2427								} else {
2428									obj_section = search_obj.filter( "[data-uniqid='" + section + "']" );
2429									if ( element !== section ) {
2430										obj_element = obj_section.find( '.cpf-element:not(.cpf-element .cpf-element)' ).eq( element );
2431									} else {
2432										obj_element = obj_section;
2433									}
2434								}
2435							} else if ( element !== section ) {
2436								obj_element = root_element.find( '.cpf-element' ).eq( element );
2437							} else {
2438								obj_element = obj_section;
2439							}
2440
2441							fields.push( {
2442								element: obj_element,
2443								operator: operator,
2444								value: value
2445							} );
2446						}
2447					} );
2448					if ( ! sect.data( 'iscpfdependson' ) ) {
2449						sect.data( 'cpfdependson-fields', fields );
2450						sect.cpfdependson( fields, logic.toggle, logic.what );
2451					} else {
2452						sect.cpfdependson( sect.data( 'cpfdependson-fields' ), logic.toggle, logic.what, true );
2453					}
2454				}
2455			} );
2456		} );
2457	}
2458
2459	function cpf_element_logic( obj ) {
2460		var root_element = $( obj );
2461		var all_sections = root_element.find( '.cpf-section' ).not( '.cpf-type-product .cpf-section' );
2462		var search_obj;
2463		var current_element;
2464		var logic;
2465		var haslogic;
2466		var section;
2467		var element;
2468		var operator;
2469		var value;
2470		var obj_section;
2471		var obj_element;
2472		var closestProductElement;
2473
2474		if ( root_element.is( '.cpf-section' ) ) {
2475			search_obj = false;
2476		} else {
2477			search_obj = all_sections;
2478		}
2479
2480		root_element.find( '.cpf-element[data-haslogic="1"]' ).each( function( index, el ) {
2481			var fields = [];
2482
2483			current_element = $( el );
2484			logic = current_element.data( 'logic' );
2485			haslogic = parseInt( current_element.data( 'haslogic' ), 10 );
2486
2487			closestProductElement = current_element.parent().closest( '.cpf-type-product' );
2488
2489			if ( haslogic === 1 && validate_logic( logic ) ) {
2490				$.each( logic.rules, function( i, rule ) {
2491					if ( rule ) {
2492						section = rule.section;
2493						element = rule.element;
2494						operator = rule.operator;
2495						value = rule.value;
2496
2497						if ( search_obj ) {
2498							if ( closestProductElement.length ) {
2499								obj_section = closestProductElement.find( '.cpf-section' ).filter( "[data-uniqid='" + section + "']" );
2500								if ( element !== section ) {
2501									obj_element = obj_section.find( '.cpf-element' ).eq( element );
2502								} else {
2503									obj_element = obj_section;
2504								}
2505							} else {
2506								obj_section = search_obj.filter( "[data-uniqid='" + section + "']" );
2507								if ( element !== section ) {
2508									obj_element = obj_section.find( '.cpf-element:not(.cpf-element .cpf-element)' ).eq( element );
2509								} else {
2510									obj_element = obj_section;
2511								}
2512							}
2513						} else if ( element !== section ) {
2514							obj_element = root_element.find( '.cpf-element' ).eq( element );
2515						} else {
2516							obj_element = obj_section;
2517						}
2518
2519						fields.push( {
2520							element: obj_element,
2521							operator: operator,
2522							value: value
2523						} );
2524					}
2525				} );
2526
2527				if ( ! current_element.data( 'iscpfdependson' ) ) {
2528					current_element.data( 'cpfdependson-fields', fields );
2529					current_element.cpfdependson( fields, logic.toggle, logic.what );
2530				} else {
2531					current_element.cpfdependson( current_element.data( 'cpfdependson-fields' ), logic.toggle, logic.what, true );
2532				}
2533			}
2534		} );
2535	} // End Conditional logic
2536
2537	// Return price value without tax
2538	function tm_set_price_without_tax( value, _cart, force ) {
2539		var taxable;
2540		var tax_rate;
2541		var tax_display_mode;
2542		var prices_include_tax;
2543
2544		if ( _cart ) {
2545			taxable = _cart.attr( 'data-taxable' );
2546			tax_rate = _cart.attr( 'data-tax-rate' );
2547			tax_display_mode = _cart.attr( 'data-tax-display-mode' );
2548			prices_include_tax = _cart.attr( 'data-prices-include-tax' );
2549
2550			if ( force || ( taxable && tax_display_mode === 'incl' && prices_include_tax !== '1' ) ) {
2551				value = parseFloat( value ) / ( 1 + ( tax_rate / 100 ) );
2552			}
2553		}
2554
2555		return value;
2556	}
2557
2558	// Return price with tax
2559	function tm_set_price_with_tax( value, _cart, force ) {
2560		var taxable;
2561		var tax_rate;
2562		var tax_display_mode;
2563		var prices_include_tax;
2564
2565		if ( _cart ) {
2566			taxable = _cart.attr( 'data-taxable' );
2567			tax_rate = _cart.attr( 'data-tax-rate' );
2568			tax_display_mode = _cart.attr( 'data-tax-display-mode' );
2569			prices_include_tax = _cart.attr( 'data-prices-include-tax' );
2570			if ( force || ( taxable && tax_display_mode !== 'incl' && prices_include_tax === '1' ) ) {
2571				value = parseFloat( value ) * ( 1 + ( tax_rate / 100 ) );
2572			}
2573		}
2574
2575		return value;
2576	}
2577
2578	// Return  price
2579	function tm_set_backend_price( value, _cart, variation ) {
2580		var taxable;
2581		var tax_display_mode;
2582		var prices_include_tax;
2583
2584		if ( _cart ) {
2585			taxable = _cart.attr( 'data-taxable' );
2586			tax_display_mode = _cart.attr( 'data-tax-display-mode' );
2587			prices_include_tax = _cart.attr( 'data-prices-include-tax' );
2588			if ( taxable ) {
2589				if ( variation && variation.tc_tax_rate && String( variation.tc_tax_rate ) === '0' ) {
2590					return value;
2591				}
2592				if ( prices_include_tax === '1' ) {
2593					if ( tax_display_mode !== 'incl' ) {
2594						value = tm_set_price_with_tax( value, _cart );
2595					}
2596				} else if ( prices_include_tax !== '1' && tax_display_mode === 'incl' ) {
2597					value = tm_set_price_without_tax( value, _cart );
2598				}
2599			}
2600		}
2601
2602		return value;
2603	}
2604
2605	// Return a formatted currency value
2606	function tm_set_price_totals( value, _cart, notax, taxstring, element ) {
2607		var inc_tax_string = '';
2608		var sign = '';
2609		var val;
2610
2611		if ( ! notax ) {
2612			value = tm_set_tax_price( value, _cart, element, undefined, true );
2613		}
2614		val = Math.abs( value );
2615		if ( _cart && taxstring ) {
2616			inc_tax_string = _cart.attr( 'data-tax-string' );
2617		}
2618		if ( inc_tax_string === undefined ) {
2619			inc_tax_string = '';
2620		}
2621
2622		if ( value < 0 ) {
2623			sign = TMEPOJS.minus_sign + ' ';
2624		}
2625
2626		return tm_set_price_( val, sign, inc_tax_string );
2627	}
2628
2629	function replace_suffixes( value, rawValue, tc_totals_ob, totalsHolder ) {
2630		if ( totalsHolder.attr( 'data-tax-display-mode' ) === 'excl' ) {
2631			tc_totals_ob[ value ] = tc_totals_ob[ value ].replace( /{price_excluding_tax}/g, tm_set_price_totals( tc_totals_ob[ rawValue ], totalsHolder, true, false ) );
2632			tc_totals_ob[ value ] = tc_totals_ob[ value ].replace( /{price_including_tax}/g, tm_set_price_totals( tm_set_price_with_tax( tc_totals_ob[ rawValue ], totalsHolder, true ), totalsHolder, true, false ) );
2633		} else {
2634			tc_totals_ob[ value ] = tc_totals_ob[ value ].replace( /{price_including_tax}/g, tm_set_price_totals( tc_totals_ob[ rawValue ], totalsHolder, true, false ) );
2635			tc_totals_ob[ value ] = tc_totals_ob[ value ].replace( /{price_excluding_tax}/g, tm_set_price_totals( tm_set_price_without_tax( tc_totals_ob[ rawValue ], totalsHolder, true ), totalsHolder, true, false ) );
2636		}
2637		return tc_totals_ob;
2638	}
2639
2640	function tm_force_update_price( obj, price, formated_price, original_price, original_formated_price ) {
2641		tm_update_price( obj, price, formated_price, original_price, original_formated_price, true );
2642	}
2643
2644	function tm_update_price( obj, price, formated_price, original_price, original_formated_price, force ) {
2645		var $obj = $( obj );
2646		var w;
2647		var $ba_amount;
2648		var priceobj;
2649		var f;
2650		var pw;
2651
2652		if ( $obj.length === 0 ) {
2653			return;
2654		}
2655
2656		w = $obj.closest( '.tmcp-field-wrap' );
2657		pw = $obj.closest( '.tc-price-wrap' );
2658		f = w.find( '.tm-epo-field' );
2659
2660		if ( ! force && f.attr( 'data-no-price-change' ) === '1' && f.data( 'price-changed' ) ) {
2661			return;
2662		}
2663
2664		price = $.epoAPI.applyFilter( 'tc_adjust_update_price_price', price ); //number
2665		formated_price = $.epoAPI.applyFilter( 'tc_adjust_update_price_formated_price', formated_price, price ); //formatted
2666		original_price = $.epoAPI.applyFilter( 'tc_adjust_update_price_original_price', original_price ); //number
2667		original_formated_price = $.epoAPI.applyFilter( 'tc_adjust_update_price_original_formated_price', original_formated_price, original_price ); //formatted
2668
2669		if ( ! Number.isFinite( parseFloat( original_price ) ) ) {
2670			original_price = 0;
2671		}
2672		if ( ! Number.isFinite( parseFloat( price ) ) ) {
2673			price = 0;
2674		}
2675
2676		$ba_amount = w.find( '.before-amount,.after-amount' );
2677		priceobj = {
2678			price: formated_price,
2679			original_price: original_formated_price
2680		};
2681
2682		if ( ( TMEPOJS.tm_epo_auto_hide_price_if_zero === 'yes' && $.tmempty( price ) === false ) || TMEPOJS.tm_epo_auto_hide_price_if_zero !== 'yes' ) {
2683			if ( ( $.tmempty( 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' ) ) || ( f.is( '.tmcp-select' ) && ! f.children( 'option:selected' ).data( 'price' ) ) ) ) ) {
2684				pw.addClass( 'tm-hidden' );
2685				$obj.addClass( 'tm-hidden' );
2686				$obj.empty();
2687				$ba_amount.addClass( 'tm-hidden' );
2688			} else {
2689				if ( original_price && original_price !== undefined && parseFloat( original_price ) !== parseFloat( price ) ) {
2690					$obj.html( $.epoAPI.template.html( tcAPI.templateEngine.sale_price, { price: priceobj } ) );
2691				} else {
2692					$obj.html( $.epoAPI.template.html( tcAPI.templateEngine.price, { price: priceobj } ) );
2693				}
2694				pw.removeClass( 'tm-hidden' );
2695				$obj.removeClass( 'tm-hidden' );
2696				$ba_amount.removeClass( 'tm-hidden' );
2697			}
2698		} else {
2699			pw.addClass( 'tm-hidden' );
2700			$obj.addClass( 'tm-hidden' );
2701			$obj.empty();
2702			$ba_amount.addClass( 'tm-hidden' );
2703		}
2704	}
2705
2706	function get_variation_current_settings( form, epoObject ) {
2707		var current_settings = {};
2708
2709		if ( epoObject.thisForm ) {
2710			form = epoObject.thisForm;
2711		}
2712
2713		form.find( '.variations select, .tc-epo-variable-product-selector' ).each( function() {
2714			var attribute_name;
2715			var value;
2716
2717			// Get attribute name from data-attribute_name, or from input name
2718			// if it doesn't exist
2719			if ( typeof $( this ).data( 'attribute_name' ) !== 'undefined' ) {
2720				attribute_name = $( this ).data( 'attribute_name' );
2721			} else {
2722				attribute_name = $( this ).attr( 'name' );
2723			}
2724
2725			// Encode entities
2726			value = $( this ).val();
2727
2728			// Add to settings array
2729			current_settings[ attribute_name ] = value;
2730		} );
2731
2732		return current_settings;
2733	}
2734
2735	function do_tm_custom_variations_update( form, all_variations, epoObject ) {
2736		var check_if_all_are_not_set = [];
2737		var formSettings = get_variation_current_settings( form, epoObject );
2738		var redo_check = true;
2739		var variationId = form.find( getVariationIdSelector( form ) ).val();
2740		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' );
2741
2742		if ( ! variationId ) {
2743			return;
2744		}
2745		form.find( '.cpf-type-variations' ).each( function( i, el ) {
2746			var t = $( el ).find( '.tm-epo-variation-element' );
2747			var id;
2748			var v;
2749			var exists = false;
2750
2751			check_if_all_are_not_set[ i ] = true;
2752
2753			if ( t.is( 'select' ) ) {
2754				id = $.epoAPI.dom.id( t.attr( 'data-tm-for-variation' ) );
2755				v = t.val();
2756				if ( v ) {
2757					check_if_all_are_not_set[ i ] = false;
2758				}
2759				t.children( 'option' ).each( function( x, o ) {
2760					exists = false;
2761					form.find( "[data-attribute_name='attribute_" + id + "']" )
2762						.children( 'option' )
2763						.each( function() {
2764							if ( $( this ).attr( 'value' ) === $( o ).attr( 'value' ) ) {
2765								exists = true;
2766								return false;
2767							}
2768						} );
2769					if ( ! exists ) {
2770						$( o ).prop( 'disabled', true ).hide();
2771					} else {
2772						$( o ).prop( 'disabled', false ).show();
2773					}
2774				} );
2775			} else {
2776				t.each( function( x, oe ) {
2777					var o = $( oe );
2778					var li = o.closest( 'li' );
2779					var input = li.find( '.tm-epo-variation-element' );
2780					var this_settings = $.extend( true, {}, formSettings );
2781					var matching_variations;
2782					var variation;
2783					var is_in_stock;
2784
2785					id = o.attr( 'data-tm-for-variation' );
2786					v = o.val();
2787					if ( o.is( ':checked' ) ) {
2788						check_if_all_are_not_set[ i ] = false;
2789					}
2790
2791					this_settings[ 'attribute_' + id ] = v;
2792
2793					matching_variations = $.fn.tm_find_matching_variations( all_variations, this_settings );
2794					variation = matching_variations.shift();
2795
2796					is_in_stock = variation && 'is_in_stock' in variation && variation.is_in_stock;
2797
2798					if ( ! is_in_stock ) {
2799						if ( ! input.is( ':checked' ) && ! is_in_stock ) {
2800							li.addClass( 'pointereventsoff' );
2801						} else {
2802							li.removeClass( 'pointereventsoff' );
2803						}
2804
2805						o.attr( 'disabled', 'disabled' ).addClass( 'tm-disabled' );
2806
2807						input.attr( 'disabled', 'disabled' );
2808						input.attr( 'data-tm-disabled', 'disabled' );
2809
2810						li.addClass( 'tm-attribute-disabled' ).fadeTo( 'fast', 0.5 );
2811					} else {
2812						o.prop( 'disabled', false ).removeClass( 'tm-disabled' );
2813						li.removeClass( 'pointereventsoff tm-attribute-disabled' ).fadeTo( 'fast', 1, function() {
2814							$( this ).css( 'opacity', '' );
2815						} );
2816						input.prop( 'disabled', false );
2817						input.removeAttr( 'data-tm-disabled' );
2818					}
2819				} );
2820			}
2821		} );
2822
2823		if ( check_if_all_are_not_set ) {
2824			check_if_all_are_not_set.shift();
2825
2826			$.each( check_if_all_are_not_set, function( i, el ) {
2827				if ( el === false ) {
2828					redo_check = false;
2829					return false;
2830				}
2831			} );
2832			if ( redo_check ) {
2833				form.find( '.cpf-type-variations' )
2834					.first()
2835					.each( function( i, el ) {
2836						var t;
2837						var li;
2838						var input;
2839
2840						t = $( el ).find( '.tm-epo-variation-element' );
2841
2842						if ( ! t.is( 'select' ) ) {
2843							t.each( function( x, o ) {
2844								o = $( o );
2845								li = o.closest( 'li' );
2846								input = li.find( '.tm-epo-variation-element' );
2847								o.prop( 'disabled', false ).removeClass( 'tm-disabled' );
2848								li.removeClass( 'tm-attribute-disabled' ).stop().css( 'opacity', '' );
2849								input.prop( 'disabled', false );
2850								input.removeAttr( 'data-tm-disabled' );
2851							} );
2852						}
2853					} );
2854			}
2855		}
2856	}
2857
2858	function tm_custom_variations_update( form, epoObject ) {
2859		var data;
2860		var all_variations = form.data( 'product_variations' );
2861		var product_id = parseInt( form.data( 'product_id' ), 10 );
2862		var globalVariationObject = form.data( 'globalVariationObject' ) || false;
2863
2864		if ( ! product_id ) {
2865			product_id = form.data( 'tc_product_id' );
2866		}
2867
2868		if ( ! product_id && form.is( tcAPI.compositeSelector ) ) {
2869			data = form.find( '.component_options' ).data( 'options_data' );
2870			product_id = data[ 0 ].option_id;
2871			if ( ! all_variations ) {
2872				all_variations = form.find( '.details.component_data' ).data( 'product_variations' );
2873			}
2874		}
2875
2876		if ( ! epoObject.is_associated ) {
2877			// Fallback to window property if not set - backwards compat
2878			if ( ! all_variations && window.product_variations && window.product_variations.product_id ) {
2879				all_variations = window.product_variations.product_id;
2880			}
2881			if ( ! all_variations && window.product_variations ) {
2882				all_variations = window.product_variations;
2883			}
2884			if ( ! all_variations && window[ 'product_variations_' + product_id ] ) {
2885				all_variations = window[ 'product_variations_' + product_id ];
2886			}
2887		}
2888
2889		if ( ! all_variations ) {
2890			if ( ! globalVariationObject ) {
2891				data = {
2892					action: 'woocommerce_tm_get_variations_array',
2893					post_id: product_id
2894				};
2895				$.post(
2896					TMEPOJS.ajax_url,
2897					data,
2898					function( response ) {
2899						globalVariationObject = response;
2900						form.data( 'globalVariationObject', response );
2901						do_tm_custom_variations_update( form, globalVariationObject.variations, epoObject );
2902					},
2903					'json'
2904				);
2905			} else {
2906				do_tm_custom_variations_update( form, globalVariationObject.variations, epoObject );
2907			}
2908
2909			return;
2910		}
2911		// may need 2.4 check for woocommerce_ajax_variation_threshold
2912		do_tm_custom_variations_update( form, all_variations, epoObject );
2913	}
2914
2915	function tm_fix_stock( cart, html ) {
2916		var custom_variations;
2917		var section;
2918
2919		if ( html === undefined ) {
2920			return false;
2921		}
2922		cart = $( cart );
2923		custom_variations = cart.find( '.tm-epo-variation-element' ).first();
2924		section = custom_variations.closest( '.tm-epo-variation-section' );
2925
2926		if ( custom_variations.length ) {
2927			section.find( '.tm-stock' ).remove();
2928			section.append( '<div class="tm-stock">' + html + '</div>' );
2929			return true;
2930		}
2931		cart.find( '.tm-stock' ).remove();
2932		cart.find( '.variations' ).after( '<div class="tm-stock">' + html + '</div>' );
2933		return true;
2934	}
2935
2936	function tm_fix_stock_tmepo( $this, form ) {
2937		var stock;
2938
2939		if ( TMEPOJS.tm_epo_global_move_out_of_stock === 'no' ) {
2940			return;
2941		}
2942		stock = $this.find( '.woocommerce-variation-availability' ).last();
2943		if ( ! stock.length ) {
2944			stock = $this.find( '.stock' ).last();
2945		}
2946
2947		if ( stock.length ) {
2948			form.find( '.tm-stock' ).remove();
2949			if ( tm_fix_stock( form, stock.prop( 'outerHTML' ) ) ) {
2950				stock.remove();
2951			}
2952		} else {
2953			form.find( '.tm-stock' ).remove();
2954		}
2955	}
2956
2957	function get_main_input_id( main_product, product, id ) {
2958		var selector = '';
2959		var inputid;
2960
2961		if ( id ) {
2962			selector = selector + "[value='" + id + "']";
2963		}
2964		if ( ! product ) {
2965			product = main_product;
2966		}
2967		inputid = product.find( tcAPI.addToCartSelector + selector );
2968		if ( inputid.length === 0 ) {
2969			inputid = product.find( tcAPI.tcAddToCartSelector + selector );
2970		}
2971		return inputid.last();
2972	}
2973
2974	function get_main_form( main_product, product, selector, id ) {
2975		if ( ! selector ) {
2976			selector = 'form';
2977		}
2978		return get_main_input_id( main_product, product, id ).closest( selector );
2979	}
2980
2981	function get_main_cart( main_product, product, selector, id ) {
2982		return get_main_form( main_product, product, selector, id );
2983	}
2984
2985	function tm_get_native_prices_block( obj ) {
2986		var selector = $.epoAPI.applyFilter( 'tcGetNativePricesBlockSelector', '.single_variation .price', obj );
2987
2988		return $( obj ).find( selector ).not( '.tc-price' );
2989	}
2990
2991	// URL replacement setup
2992	function tm_set_url_fields() {
2993		jDocument.on( 'click.cpfurl change.cpfurl tmredirect', '.tc-url-container .tmcp-radio, .tc-url-container .tmcp-radio+label', function( e ) {
2994			var data_url = $( this ).attr( 'data-url' );
2995			if ( data_url ) {
2996				if ( window.location !== data_url ) {
2997					e.preventDefault();
2998					window.location = data_url;
2999				}
3000			}
3001		} );
3002		jDocument.on( 'change.cpfurl tmredirect', '.tc-url-container .tmcp-select', function( e ) {
3003			var data_url = $( this ).children( 'option:selected' ).attr( 'data-url' );
3004			if ( data_url ) {
3005				if ( window.location !== data_url ) {
3006					e.preventDefault();
3007					window.location = data_url;
3008				}
3009			}
3010		} );
3011	}
3012
3013	function tm_floating_totals( this_epo_totals_container, is_quickview, main_cart ) {
3014		$.tcFloatingTotalsBox( this_epo_totals_container, is_quickview, main_cart );
3015	}
3016
3017	function tm_show_hide_add_to_cart_button( main_product, epoObject, one_option_is_selected, currentEpoObject ) {
3018		var button;
3019		var qty;
3020		var has_epo;
3021		var this_epo_container;
3022		var epos;
3023		var allElementsAreSelected;
3024		var showHide = true;
3025
3026		if ( typeof epoObject === 'object' ) {
3027			has_epo = epoObject.has_epo;
3028			this_epo_container = epoObject.this_epo_container;
3029			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 );
3030		} else {
3031			has_epo = epoObject;
3032		}
3033
3034		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' ) ) {
3035			button = main_product.find( tcAPI.addToCartButtonSelector ).first();
3036			qty = main_product.find( tcAPI.qtySelector ).first();
3037
3038			// Hide cart button until an elements is chosen
3039			if ( TMEPOJS.tm_epo_hide_add_cart_button === 'yes' ) {
3040				showHide = one_option_is_selected;
3041				if ( one_option_is_selected ) {
3042					button.removeClass( 'tc-hide-add-to-cart-button' );
3043					qty.removeClass( 'tc-hide-add-to-cart-button' );
3044				} else {
3045					button.addClass( 'tc-hide-add-to-cart-button' );
3046					qty.addClass( 'tc-hide-add-to-cart-button' );
3047				}
3048			}
3049
3050			// Hide cart button until all elements are chosen
3051			if ( TMEPOJS.tm_epo_hide_required_add_cart_button === 'yes' ) {
3052				epos = currentEpoObject.this_epo_container.find( '.cpf-element' ).not( '.cpf-type-variations' ).filter( '.tc-container-enabled.tc-is-required' );
3053				allElementsAreSelected = epos.toArray().every( function( element ) {
3054					var elementToCheck = '';
3055					var _class;
3056					var noSplit = false;
3057					var radio_checked;
3058					var checkbox_checked;
3059					var val;
3060
3061					element = $( element );
3062					if ( element.is( '.cpf-type-product' ) ) {
3063						elementToCheck = ':not(.tc-extra-product-options-inline .tm-epo-field)';
3064					}
3065					_class = element
3066						.attr( 'class' )
3067						.split( ' ' )
3068						.map( function( cls ) {
3069							if ( cls.indexOf( 'cpf-type-', 0 ) !== -1 ) {
3070								return cls;
3071							}
3072							return null;
3073						} )
3074						.filter( function( v ) {
3075							if ( v !== null && v !== undefined ) {
3076								return v;
3077							}
3078							return null;
3079						} );
3080
3081					if ( _class.length > 0 ) {
3082						_class = _class[ 0 ];
3083						if ( _class === 'cpf-type-product' ) {
3084							noSplit = true;
3085							if ( element.is( '.cpf-type-product-mode-product' ) || element.is( '.cpf-type-product-checkbox' ) || element.is( '.cpf-type-product-thumbnailmultiple' ) ) {
3086								_class = 'cpf-type-checkbox';
3087							} else if ( element.is( '.cpf-type-product-dropdown' ) ) {
3088								_class = 'cpf-type-select';
3089							} else {
3090								_class = 'cpf-type-radio';
3091							}
3092						}
3093						switch ( _class ) {
3094							case 'cpf-type-radio':
3095								radio_checked = element.find( 'input.tm-epo-field.tmcp-radio:checked' + elementToCheck );
3096								return radio_checked.length > 0;
3097
3098							case 'cpf-type-checkbox':
3099								checkbox_checked = element.find( 'input.tm-epo-field.tmcp-checkbox:checked' + elementToCheck );
3100								return checkbox_checked.length > 0;
3101
3102							case 'cpf-type-select':
3103								val = element.find( 'select.tm-epo-field.tmcp-select' + elementToCheck ).val();
3104								if ( val && ! noSplit ) {
3105									val = val.slice( 0, val.lastIndexOf( '_' ) );
3106								}
3107								break;
3108
3109							case 'cpf-type-selectmultiple':
3110								val = element.find( 'select.tm-epo-field.tmcp-selectmultiple' + elementToCheck ).val();
3111								if ( val && ! noSplit ) {
3112									val.forEach( function( option, i ) {
3113										val[ i ] = option.slice( 0, option.lastIndexOf( '_' ) );
3114									} );
3115								}
3116								break;
3117
3118							default:
3119								val = element.find( '.tm-epo-field' + elementToCheck ).val();
3120								break;
3121						}
3122						if ( Array.isArray( val ) ) {
3123							return val.some( function( item ) {
3124								return item !== '';
3125							} );
3126						}
3127						return val !== '';
3128					}
3129					return false;
3130				} );
3131				showHide = allElementsAreSelected;
3132			}
3133
3134			// Hide cart button until all elements are chosen
3135			if ( TMEPOJS.tm_epo_hide_all_add_cart_button === 'yes' ) {
3136				epos = currentEpoObject.this_epo_container.find( '.cpf-element' ).not( '.cpf-type-variations' ).filter( '.tc-container-enabled' );
3137				allElementsAreSelected = epos.toArray().every( function( element ) {
3138					var elementToCheck = '';
3139					var _class;
3140					var noSplit = false;
3141					var radio_checked;
3142					var checkbox_checked;
3143					var val;
3144
3145					element = $( element );
3146					if ( element.is( '.cpf-type-product' ) ) {
3147						elementToCheck = ':not(.tc-extra-product-options-inline .tm-epo-field)';
3148					}
3149					_class = element
3150						.attr( 'class' )
3151						.split( ' ' )
3152						.map( function( cls ) {
3153							if ( cls.indexOf( 'cpf-type-', 0 ) !== -1 ) {
3154								return cls;
3155							}
3156							return null;
3157						} )
3158						.filter( function( v ) {
3159							if ( v !== null && v !== undefined ) {
3160								return v;
3161							}
3162							return null;
3163						} );
3164
3165					if ( _class.length > 0 ) {
3166						_class = _class[ 0 ];
3167						if ( _class === 'cpf-type-product' ) {
3168							noSplit = true;
3169							if ( element.is( '.cpf-type-product-mode-product' ) || element.is( '.cpf-type-product-checkbox' ) || element.is( '.cpf-type-product-thumbnailmultiple' ) ) {
3170								_class = 'cpf-type-checkbox';
3171							} else if ( element.is( '.cpf-type-product-dropdown' ) ) {
3172								_class = 'cpf-type-select';
3173							} else {
3174								_class = 'cpf-type-radio';
3175							}
3176						}
3177						switch ( _class ) {
3178							case 'cpf-type-radio':
3179								radio_checked = element.find( 'input.tm-epo-field.tmcp-radio:checked' + elementToCheck );
3180								return radio_checked.length > 0;
3181
3182							case 'cpf-type-checkbox':
3183								checkbox_checked = element.find( 'input.tm-epo-field.tmcp-checkbox:checked' + elementToCheck );
3184								return checkbox_checked.length > 0;
3185
3186							case 'cpf-type-select':
3187								val = element.find( 'select.tm-epo-field.tmcp-select' + elementToCheck ).val();
3188								if ( val && ! noSplit ) {
3189									val = val.slice( 0, val.lastIndexOf( '_' ) );
3190								}
3191								break;
3192
3193							case 'cpf-type-selectmultiple':
3194								val = element.find( 'select.tm-epo-field.tmcp-selectmultiple' + elementToCheck ).val();
3195								if ( val && ! noSplit ) {
3196									val.forEach( function( option, i ) {
3197										val[ i ] = option.slice( 0, option.lastIndexOf( '_' ) );
3198									} );
3199								}
3200								break;
3201
3202							default:
3203								val = element.find( '.tm-epo-field' + elementToCheck ).val();
3204								break;
3205						}
3206						if ( Array.isArray( val ) ) {
3207							return val.some( function( item ) {
3208								return item !== '';
3209							} );
3210						}
3211						return val !== '';
3212					}
3213					return false;
3214				} );
3215				showHide = allElementsAreSelected;
3216			}
3217
3218			if ( showHide ) {
3219				button.removeClass( 'tc-hide-add-to-cart-button' );
3220				qty.removeClass( 'tc-hide-add-to-cart-button' );
3221			} else {
3222				button.addClass( 'tc-hide-add-to-cart-button' );
3223				qty.addClass( 'tc-hide-add-to-cart-button' );
3224			}
3225		}
3226	}
3227
3228	function goto_error_item( item, epoEventId ) {
3229		var el = $.tcepo.errorObject[ epoEventId ] || item;
3230		var elsection;
3231		var elsectionlink;
3232		var cpfElement;
3233		var pos;
3234
3235		if ( el ) {
3236			if ( TMEPOJS.tm_epo_disable_error_scroll !== 'yes' ) {
3237				elsection = el.closest( '.cpf-section' );
3238				elsectionlink = elsection.find( '.tm-section-link' );
3239				cpfElement = el.closest( '.cpf-element' );
3240
3241				if ( elsection.find( '.tm-toggle' ).length ) {
3242					elsection.find( '.tm-toggle' ).trigger( 'openwrap.tmtoggle' );
3243				}
3244				if ( window.tc_validation_offset === undefined ) {
3245					window.tc_validation_offset = -100;
3246				}
3247				if ( elsection.is( '.section_popup' ) ) {
3248					errorContainer.tcScrollTo( elsectionlink, 300, window.tc_validation_offset );
3249					elsectionlink.trigger( 'click.tmsectionpoplink' );
3250				} else if ( elsection.is( '.tm-owl-slider-section' ) ) {
3251					pos = el.closest( '.owl-item' ).index();
3252					elsection.find( '.tcowl-carousel' ).trigger( 'to.owl.carousel', [ pos, 100 ] );
3253					setTimeout( function() {
3254						elsection.find( '.tcowl-carousel' ).trigger( 'refresh.owl.carousel' );
3255
3256						if ( cpfElement.length > 0 ) {
3257							errorContainer.tcScrollTo( cpfElement, 300, window.tc_validation_offset );
3258						}
3259					}, 200 );
3260				} else if ( cpfElement.length > 0 ) {
3261					errorContainer.tcScrollTo( cpfElement, 300, window.tc_validation_offset );
3262				}
3263			}
3264
3265			if ( ! item ) {
3266				$.tcepo.errorObject[ epoEventId ] = false;
3267			}
3268		}
3269	}
3270
3271	function tm_limit_c_selection( field, prevent ) {
3272		var allowed = parseInt( field.attr( 'data-limit' ), 10 );
3273		var checked = false;
3274		var val;
3275		var t;
3276		var q;
3277
3278		if ( allowed > 0 ) {
3279			checked = 0;
3280			field
3281				.closest( '.tm-extra-product-options-checkbox' )
3282				.find( "input.tm-epo-field[type='checkbox']:checked" )
3283				.each( function() {
3284					t = $( this );
3285					q = t.closest( 'li.tmcp-field-wrap' ).find( 'input.tm-qty' );
3286					if ( q.length > 0 ) {
3287						val = parseInt( q.val(), 10 );
3288						if ( val <= 0 ) {
3289							val = 1;
3290						}
3291						checked = parseInt( checked, 10 ) + val;
3292					} else {
3293						checked = parseInt( checked, 10 ) + 1;
3294					}
3295				} );
3296			if ( checked > allowed ) {
3297				if ( prevent ) {
3298					field.prop( 'checked', '' ).trigger( 'change' );
3299				}
3300				return false;
3301			}
3302		}
3303		return true;
3304	}
3305
3306	function tm_exact_c_selection( field, prevent ) {
3307		var allowed = parseInt( field.attr( 'data-exactlimit' ), 10 );
3308		var checked = false;
3309		var val;
3310		var t;
3311		var q;
3312
3313		if ( allowed > 0 ) {
3314			checked = 0;
3315			field
3316				.closest( '.tm-extra-product-options-checkbox' )
3317				.find( "input.tm-epo-field[type='checkbox']:checked" )
3318				.each( function() {
3319					t = $( this );
3320					q = t.closest( 'li.tmcp-field-wrap' ).find( 'input.tm-qty' );
3321					if ( q.length > 0 ) {
3322						val = parseInt( q.val(), 10 );
3323						if ( val <= 0 ) {
3324							val = 1;
3325						}
3326						checked = parseInt( checked, 10 ) + val;
3327					} else {
3328						checked = parseInt( checked, 10 ) + 1;
3329					}
3330				} );
3331			if ( checked > allowed ) {
3332				if ( prevent ) {
3333					field.prop( 'checked', '' ).trigger( 'change' );
3334				}
3335				return false;
3336			}
3337		}
3338		return true;
3339	}
3340
3341	function tm_limit_cont( fields, main_product, epoEventId ) {
3342		var checkall = true;
3343		var first_error_obj = false;
3344		var limit;
3345		var eln;
3346		var checked;
3347		var t;
3348		var val;
3349		var q;
3350		var ew;
3351		var em;
3352		var message;
3353		var field;
3354
3355		fields.each( function() {
3356			field = $( this );
3357			limit = field.find( "[type='checkbox'][data-limit]" );
3358			if ( limit.length && field_is_active( limit ) ) {
3359				eln = parseInt( limit.attr( 'data-limit' ), 10 );
3360				checked = 0;
3361				field.find( "input.tm-epo-field[type='checkbox']:checked" ).each( function() {
3362					t = $( this );
3363					q = t.closest( 'li.tmcp-field-wrap' ).find( 'input.tm-qty' );
3364					if ( q.length > 0 ) {
3365						val = parseInt( q.val(), 10 );
3366						if ( val <= 0 ) {
3367							val = 1;
3368						}
3369						checked = parseInt( checked, 10 ) + val;
3370					} else {
3371						checked = parseInt( checked, 10 ) + 1;
3372					}
3373				} );
3374				ew = field.closest( '.cpf-element' );
3375				em = ew.find( 'div.tm-error-min' );
3376
3377				if ( eln < checked ) {
3378					checkall = false;
3379					first_error_obj = field;
3380					if ( eln === 1 ) {
3381						message = TMEPOJS.tm_epo_global_validator_messages.epolimitsingle.replace( '{0}', eln );
3382					} else {
3383						message = TMEPOJS.tm_epo_global_validator_messages.epolimit.replace( '{0}', eln );
3384					}
3385					if ( em.length ) {
3386						em.remove();
3387					}
3388					if ( TMEPOJS.tm_epo_global_error_label_placement === 'before' ) {
3389						field.closest( '.tc-element-container' ).before( '<div class="tm-error-min tm-error tc-cell tcwidth-100">' + message + '</div>' );
3390					} else {
3391						field.closest( '.tc-element-container' ).after( '<div class="tm-error-min tm-error tc-cell tcwidth-100">' + message + '</div>' );
3392					}
3393					main_product.find( tcAPI.addToCartButtonSelector ).first().removeClass( 'disabled loading fpd-disabled' ).prop( 'disabled', false );
3394				} else {
3395					em.remove();
3396				}
3397			}
3398		} );
3399		if ( first_error_obj ) {
3400			$.tcepo.errorObject[ epoEventId ] = first_error_obj;
3401		}
3402		return checkall;
3403	}
3404
3405	function tm_check_limit_cont( limit_cont, main_product, epoEventId ) {
3406		$.tcepo.formSubmitEvents[ epoEventId ][ $.tcepo.formSubmitEvents[ epoEventId ].length ] = {
3407			trigger: function() {
3408				return tm_limit_cont( limit_cont, main_product, epoEventId );
3409			},
3410			on_true: function() {
3411				return true;
3412			},
3413			on_false: function() {
3414				goto_error_item( $( limit_cont ).find( '.tm-epo-field' ).first(), epoEventId );
3415				return true;
3416			}
3417		};
3418	}
3419
3420	function tm_exactlimit_cont( fields, main_product, epoEventId ) {
3421		var checkall = true;
3422		var first_error_obj = false;
3423		var exactlimit;
3424		var eln;
3425		var checked;
3426		var t;
3427		var val;
3428		var q;
3429		var ew;
3430		var em;
3431		var message;
3432		var field;
3433
3434		fields.each( function() {
3435			field = $( this );
3436			exactlimit = field.find( "[type='checkbox'][data-exactlimit]" );
3437			if ( exactlimit.length && field_is_active( exactlimit ) ) {
3438				eln = parseInt( exactlimit.attr( 'data-exactlimit' ), 10 );
3439				checked = 0;
3440				field.find( "input.tm-epo-field[type='checkbox']:checked" ).each( function() {
3441					t = $( this );
3442					q = t.closest( 'li.tmcp-field-wrap' ).find( 'input.tm-qty' );
3443					if ( q.length > 0 ) {
3444						val = parseInt( q.val(), 10 );
3445						if ( val <= 0 ) {
3446							val = 1;
3447						}
3448						checked = parseInt( checked, 10 ) + val;
3449					} else {
3450						checked = parseInt( checked, 10 ) + 1;
3451					}
3452				} );
3453				ew = field.closest( '.cpf-element' );
3454				em = ew.find( 'div.tm-error-min' );
3455
3456				if ( eln !== checked ) {
3457					checkall = false;
3458					first_error_obj = field;
3459					if ( eln === 1 ) {
3460						message = TMEPOJS.tm_epo_global_validator_messages.epoexactsingle.replace( '{0}', eln );
3461					} else {
3462						message = TMEPOJS.tm_epo_global_validator_messages.epoexact.replace( '{0}', eln );
3463					}
3464					if ( em.length ) {
3465						em.remove();
3466					}
3467					if ( TMEPOJS.tm_epo_global_error_label_placement === 'before' ) {
3468						field.closest( '.tc-element-container' ).before( '<div class="tm-error-min tm-error tc-cell tcwidth-100">' + message + '</div>' );
3469					} else {
3470						field.closest( '.tc-element-container' ).after( '<div class="tm-error-min tm-error tc-cell tcwidth-100">' + message + '</div>' );
3471					}
3472					main_product.find( tcAPI.addToCartButtonSelector ).first().removeClass( 'disabled loading fpd-disabled' ).prop( 'disabled', false );
3473				} else {
3474					em.remove();
3475				}
3476			}
3477		} );
3478		if ( first_error_obj ) {
3479			$.tcepo.errorObject[ epoEventId ] = first_error_obj;
3480		}
3481		return checkall;
3482	}
3483
3484	function tm_check_exactlimit_cont( exactlimit_cont, main_product, epoEventId ) {
3485		$.tcepo.formSubmitEvents[ epoEventId ][ $.tcepo.formSubmitEvents[ epoEventId ].length ] = {
3486			trigger: function() {
3487				return tm_exactlimit_cont( exactlimit_cont, main_product, epoEventId );
3488			},
3489			on_true: function() {
3490				return true;
3491			},
3492			on_false: function() {
3493				goto_error_item( $( exactlimit_cont ).find( '.tm-epo-field' ).first(), epoEventId );
3494				return true;
3495			}
3496		};
3497	}
3498
3499	function tm_minimumlimit_cont( fields, epoEventId ) {
3500		var checkall = true;
3501		var first_error_obj = false;
3502		var eln;
3503		var checked;
3504		var t;
3505		var val;
3506		var q;
3507		var ew;
3508		var em;
3509		var message;
3510		var field;
3511
3512		fields.each( function() {
3513			var minimumlimit;
3514
3515			field = $( this );
3516			minimumlimit = field.find( "[type='checkbox'][data-minimumlimit]" );
3517
3518			if ( minimumlimit.length && field_is_active( minimumlimit ) ) {
3519				eln = parseInt( minimumlimit.attr( 'data-minimumlimit' ), 10 );
3520				checked = 0;
3521				field.find( "input.tm-epo-field[type='checkbox']:checked" ).each( function() {
3522					t = $( this );
3523					q = t.closest( 'li.tmcp-field-wrap' ).find( 'input.tm-qty' );
3524					if ( q.length > 0 ) {
3525						val = parseInt( q.val(), 10 );
3526						if ( val <= 0 ) {
3527							val = 1;
3528						}
3529						checked = parseInt( checked, 10 ) + val;
3530					} else {
3531						checked = parseInt( checked, 10 ) + 1;
3532					}
3533				} );
3534				ew = field.closest( '.cpf-element' );
3535				em = ew.find( 'div.tm-error-min' );
3536				if ( eln > checked ) {
3537					checkall = false;
3538					first_error_obj = field;
3539					if ( eln === 1 ) {
3540						message = TMEPOJS.tm_epo_global_validator_messages.epominsingle.replace( '{0}', eln );
3541					} else {
3542						message = TMEPOJS.tm_epo_global_validator_messages.epomin.replace( '{0}', eln );
3543					}
3544					if ( em.length ) {
3545						em.remove();
3546					}
3547					if ( TMEPOJS.tm_epo_global_error_label_placement === 'before' ) {
3548						field.closest( '.tc-element-container' ).before( '<div class="tm-error-min tm-error tc-cell tcwidth-100">' + message + '</div>' );
3549					} else {
3550						field.closest( '.tc-element-container' ).after( '<div class="tm-error-min tm-error tc-cell tcwidth-100">' + message + '</div>' );
3551					}
3552				} else {
3553					em.remove();
3554				}
3555			}
3556		} );
3557
3558		if ( first_error_obj ) {
3559			$.tcepo.errorObject[ epoEventId ] = first_error_obj;
3560		}
3561
3562		return checkall;
3563	}
3564
3565	function tm_check_minimumlimit_cont( minimumlimit_cont, epoEventId ) {
3566		$.tcepo.formSubmitEvents[ epoEventId ][ $.tcepo.formSubmitEvents[ epoEventId ].length ] = {
3567			trigger: function() {
3568				return tm_minimumlimit_cont( minimumlimit_cont, epoEventId );
3569			},
3570			on_true: function() {
3571				return true;
3572			},
3573			on_false: function() {
3574				goto_error_item( false, epoEventId );
3575				return true;
3576			}
3577		};
3578	}
3579
3580	function cleanPrice( price ) {
3581		if ( price === null ) {
3582			return 0;
3583		}
3584
3585		if ( typeof price === 'object' ) {
3586			price = price[ 0 ];
3587		}
3588
3589		if ( ! Number.isFinite( parseFloat( price ) ) ) {
3590			price = 0;
3591		}
3592
3593		return price;
3594	}
3595
3596	function tm_apply_dpd( price, totals, apply, force ) {
3597		price = cleanPrice( price );
3598
3599		if ( apply ) {
3600			price = $.epoAPI.applyFilter( 'tc_apply_dpd', price, totals, apply, force );
3601		}
3602
3603		return price;
3604	}
3605
3606	function tm_calculate_product_regular_price( totals, allowfalse ) {
3607		var price = 0;
3608
3609		if ( totals.length > 0 ) {
3610			price = totals.data( 'regular-price' );
3611		}
3612
3613		price = $.epoAPI.applyFilter( 'tc_calculate_product_regular_price', price, totals );
3614
3615		if ( allowfalse && price === false ) {
3616			return false;
3617		}
3618		price = parseFloat( price );
3619
3620		if ( ! Number.isFinite( price ) ) {
3621			price = 0;
3622		}
3623
3624		return price;
3625	}
3626
3627	function tm_calculate_product_price( totals, allowfalse ) {
3628		var price = 0;
3629
3630		if ( totals.length > 0 ) {
3631			price = totals.data( 'price' );
3632		}
3633
3634		price = $.epoAPI.applyFilter( 'tc_calculate_product_price', price, totals );
3635
3636		if ( allowfalse && price === false ) {
3637			return false;
3638		}
3639		price = parseFloat( price );
3640
3641		if ( ! Number.isFinite( price ) ) {
3642			price = 0;
3643		}
3644
3645		return price;
3646	}
3647
3648	function calculateMathPrice( price, thisElement, epoObject, noevents, useOriginalPrice ) {
3649		var formula = price.toString();
3650		var val = 0;
3651		var matches;
3652		var match;
3653		var elementWrap;
3654		var element;
3655		var reg;
3656		var elementPrice = 0;
3657		var pos;
3658		var type;
3659		var id;
3660		var thisVal;
3661		var thisValForced;
3662		var thisElementId = thisElement.closest( '.cpf-element' ).attr( 'data-uniqid' );
3663		var thisElementWrap = thisElement.closest( '.tmcp-ul-wrap' );
3664		var totalsHolder_tc_totals_ob = epoObject.this_epo_totals_container.data( 'totalsHolder_tc_totals_ob' );
3665		var thisElementIndex = thisElementWrap.find( '.tmcp-field, .tmcp-fee-field' ).filter( ':checked' ).index( thisElement );
3666		var thisElementIndexForced = thisElementWrap.find( '.tmcp-field, .tmcp-fee-field' ).index( thisElement );
3667		var this_epo_container = epoObject.is_associated ? epoObject.this_epo_container : epoObject.this_epo_container.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector );
3668		var constants = $.epoAPI.util.parseJSON( TMEPOJS.tm_epo_math ) || {};
3669
3670		if ( thisElementIndex === -1 && ! thisElement.is( '.tmcp-checkbox, .tmcp-radio' ) ) {
3671			thisElementIndex = 0;
3672		}
3673
3674		if ( ! thisElement.is( '.tcdisabled' ) && ! noevents && ! thisElement.data( 'addedtcEpoBeforeOptionPriceCalculation' ) ) {
3675			jWindow.on( 'tcEpoBeforeOptionPriceCalculation.math' + thisElementId, function() {
3676				tm_element_epo_rules( epoObject, thisElement, undefined, undefined, undefined, true );
3677			} );
3678			jWindow.on( 'tcEpoAfterOptionPriceCalculation.math' + thisElementId, function() {
3679				thisElement.data( 'fetchOptionPrices', false );
3680				thisElement.data( 'fetchOptionPrices-forced', false );
3681				thisElement.data( 'fetchOptionPrices-fee', false );
3682				thisElement.data( 'fetchOptionPrices-fee-forced', false );
3683				thisElement.data( 'fetchOptionPrices-sub-fee', false );
3684				thisElement.data( 'fetchOptionPrices-sub-fee-forced', false );
3685			} );
3686			thisElement.data( 'addedtcEpoBeforeOptionPriceCalculation', 1 );
3687		}
3688
3689		if ( thisElement.is( '.tmcp-field' ) ) {
3690			if ( thisElement.data( 'fetchOptionPrices' ) ) {
3691				thisVal = thisElement.data( 'fetchOptionPrices' );
3692				thisValForced = thisElement.data( 'fetchOptionPrices-forced' );
3693			} else {
3694				thisVal = fetchOptionPrices( epoObject, thisElementWrap, '.tmcp-field', 0, 0, [], true );
3695				thisValForced = fetchOptionPrices( epoObject, thisElementWrap, '.tmcp-field', 0, 0, [], true, true );
3696				thisElement.data( 'fetchOptionPrices', thisVal );
3697				thisElement.data( 'fetchOptionPrices-forced', thisValForced );
3698			}
3699		} else if ( thisElement.is( '.tmcp-fee-field' ) ) {
3700			if ( thisElement.data( 'fetchOptionPrices-fee' ) ) {
3701				thisVal = thisElement.data( 'fetchOptionPrices-fee' );
3702				thisValForced = thisElement.data( 'fetchOptionPrices-fee-forced' );
3703			} else {
3704				thisVal = fetchOptionPrices( epoObject, thisElementWrap, '.tmcp-fee-field', 0, 0, [], true );
3705				thisValForced = fetchOptionPrices( epoObject, thisElementWrap, '.tmcp-fee-field', 0, 0, [], true, true );
3706				thisElement.data( 'fetchOptionPrices-fee', thisVal );
3707				thisElement.data( 'fetchOptionPrices-fee-forced', thisValForced );
3708			}
3709		} else if ( thisElement.is( '.tmcp-sub-fee-field' ) ) {
3710			if ( thisElement.data( 'fetchOptionPrices-sub-fee' ) ) {
3711				thisVal = thisElement.data( 'fetchOptionPrices-sub-fee' );
3712				thisValForced = thisElement.data( 'fetchOptionPrices-sub-fee-forced' );
3713			} else {
3714				thisVal = fetchOptionPrices( epoObject, thisElementWrap, '.tmcp-sub-fee-field', 0, 0, [], true );
3715				thisValForced = fetchOptionPrices( epoObject, thisElementWrap, '.tmcp-sub-fee-field', 0, 0, [], true, true );
3716				thisElement.data( 'fetchOptionPrices-sub-fee', thisVal );
3717				thisElement.data( 'fetchOptionPrices-sub-fee-forced', thisValForced );
3718			}
3719		}
3720
3721		Object.keys( constants ).forEach( function( key ) {
3722			var name;
3723			var value;
3724
3725			if ( constants[ key ].name !== '' && constants[ key ].value !== '' ) {
3726				name = constants[ key ].name;
3727				value = constants[ key ].value;
3728				if ( constants[ key ].name.isNumeric() ) {
3729					formula = formula.replace( '{' + name + '}', value );
3730				} else {
3731					name = new RegExp( '{' + name + '}', 'g' );
3732					if ( value.startsWith( '{' ) ) {
3733						formula = formula.replace( name, value );
3734					} else {
3735						formula = formula.replace( name, $.epoAPI.math.unformat( value.replace( ',', '.' ) ) );
3736					}
3737				}
3738			}
3739		} );
3740
3741		if ( totalsHolder_tc_totals_ob !== undefined ) {
3742			// product quantity
3743			formula = formula.replace( /{quantity}/g, $.epoAPI.math.unformat( totalsHolder_tc_totals_ob.qty ) );
3744			// original product price
3745			if ( useOriginalPrice && totalsHolder_tc_totals_ob.original_product_price !== undefined ) {
3746				formula = formula.replace( /{product_price}/g, $.epoAPI.math.unformat( totalsHolder_tc_totals_ob.original_product_price ) );
3747			} else {
3748				formula = formula.replace( /{product_price}/g, $.epoAPI.math.unformat( totalsHolder_tc_totals_ob.product_price ) );
3749			}
3750		} else {
3751			// product quantity
3752			formula = formula.replace( /{quantity}/g, 0 );
3753			// original product price
3754			formula = formula.replace( /{product_price}/g, 0 );
3755		}
3756
3757		if ( thisValForced.floatingBoxData !== undefined && thisValForced.floatingBoxData[ thisElementIndexF
3757orced ] !== undefined ) {
3758			// the option/element value to float
3759			if ( thisValForced.floatingBoxData[ thisElementIndexForced ].input_type === 'number' ) {
3760				formula = formula
3761					.replace( /{this.value}/g, $.epoAPI.math.toFloat( $.epoAPI.math.unformat( thisValForced.floatingBoxData[ thisElementIndexForced ].valueText ) ) );
3762			} else {
3763				formula = formula
3764					.replace( /{this.value}/g, $.epoAPI.math.toFloat( $.epoAPI.math.unformat( thisValForced.floatingBoxData[ thisElementIndexForced ].valueText, tcAPI.localDecimalSeparator ) ) );
3765			}
3766			// the option/element raw value
3767			if ( thisValForced.floatingBoxData[ thisElementIndexForced ].input_type === 'number' ) {
3768				formula = formula
3769					.replace( /{this.rawvalue}/g, $.epoAPI.math.unformat( thisValForced.floatingBoxData[ thisElementIndexForced ].valueText ) );
3770			} else {
3771				formula = formula
3772					.replace( /{this.rawvalue}/g, $.epoAPI.math.unformat( thisValForced.floatingBoxData[ thisElementIndexForced ].valueText, tcAPI.localDecimalSeparator ) );
3773			}
3774			// the option/element raw value
3775			if ( thisValForced.floatingBoxData[ thisElementIndexForced ].input_type === 'number' ) {
3776				formula = formula
3777					.replace( /{this.text}/g, $.epoAPI.math.unformat( thisValForced.floatingBoxData[ thisElementIndexForced ].valueText ) );
3778			} else {
3779				formula = formula
3780					.replace( /{this.text}/g, $.epoAPI.math.unformat( thisValForced.floatingBoxData[ thisElementIndexForced ].valueText, tcAPI.localDecimalSeparator ) );
3781			}
3782			// the option/element value length
3783			formula = formula
3784				.replace( /{this.value.length}/g, thisValForced.floatingBoxData[ thisElementIndexForced ].valueText.length );
3785		} else {
3786			formula = formula
3787				// the option/element value to float
3788				.replace( /{this.value}/g, 0 )
3789				// the option/element raw value
3790				.replace( /{this.rawvalue}/g, '' )
3791				// the option/element raw value
3792				.replace( /{this.text}/g, '' )
3793				// the option/element value length
3794				.replace( /{this.value.length}/g, 0 );
3795		}
3796
3797		formula = formula
3798			// the number of options the user has selected
3799			.replace( /{this.count}/g, thisVal.floatingBoxData.length )
3800			// the total option quantity of this element
3801			.replace(
3802				/{this.count.quantity}/g,
3803				thisVal.floatingBoxData
3804					.map( function( x ) {
3805						return x.quantity;
3806					} )
3807					.reduce( function( acc, thisval ) {
3808						return $.epoAPI.math.toFloat( acc ) + $.epoAPI.math.toFloat( thisval );
3809					}, 0 )
3810			)
3811			// the option quantity of this element
3812			.replace( /{this.quantity}/g, thisElement.data( 'tm-quantity' ) );
3813
3814		if ( formula.match( /\{(\s)*?field\.([^}]*)}/ ) ) {
3815			matches = formula.match( /\{(\s)*?field\.([^}]*)}/g );
3816			matches.forEach( function( field ) {
3817				match = field.match( /\{(\s)*?field\.([^}]*)}/ );
3818				if ( undefined !== match[ 2 ] && 'string' === typeof match[ 2 ] ) {
3819					pos = match[ 2 ].indexOf( '.', match[ 2 ].indexOf( '.' ) + 1 );
3820					if ( pos !== -1 ) {
3821						id = match[ 2 ].substring( 0, pos );
3822						type = match[ 2 ].substring( pos + 1 );
3823
3824						if ( $.inArray( type, [ 'price', 'value', 'value.length', 'rawvalue', 'text', 'text.length', 'quantity', 'count', 'count.quantity' ] ) !== -1 ) {
3825							elementWrap = this_epo_container.find( "[data-uniqid='" + $.epoAPI.util.escapeSelector( id ) + "']" );
3826							if ( elementWrap.length ) {
3827								element = elementWrap.find( '.tmcp-field, .tmcp-fee-field' );
3828
3829								if ( ! thisElement.is( '.tcdisabled' ) && ! noevents && ! thisElement.data( 'addedfieldtcEpoBeforeOptionPriceCalculation' ) ) {
3830									jWindow.on( 'tcEpoBeforeOptionPriceCalculation.math' + thisElementId, function() {
3831										tm_element_epo_rules( epoObject, thisElement, undefined, undefined, undefined, true );
3832										thisElement.trigger( 'tm-math-select-change-html-all' );
3833									} );
3834									thisElement.data( 'addedfieldtcEpoBeforeOptionPriceCalculation', 1 );
3835								}
3836
3837								element = element.first();
3838								val = 0;
3839
3840								if ( elementWrap.is( '.tc-container-enabled' ) ) {
3841									if ( element.is( '.tmcp-field' ) ) {
3842										val = fetchOptionPrices( epoObject, elementWrap, '.tmcp-field', 0, 0, [], true, undefined, undefined, true );
3843									} else if ( element.is( '.tmcp-fee-field' ) ) {
3844										val = fetchOptionPrices( epoObject, elementWrap, '.tmcp-fee-field', 0, 0, [], true, undefined, undefined, true );
3845									}
3846
3847									switch ( type ) {
3848										// element price
3849										case 'price':
3850											val = val.total;
3851											break;
3852
3853										// element value
3854										case 'value':
3855										case 'text':
3856										case 'rawvalue':
3857											if ( val.floatingBoxData ) {
3858												val = val.floatingBoxData
3859													.map( function( x ) {
3860														if ( x.input_type === 'number' ) {
3861															if ( type === 'text' || type === 'rawvalue' ) {
3862																return x.valueText;
3863															}
3864															return $.epoAPI.math.unformat( x.valueText );
3865														}
3866														if ( type === 'text' || type === 'rawvalue' ) {
3867															return x.valueText;
3868														}
3869														return $.epoAPI.math.unformat( x.valueText, tcAPI.localIn
3869putDecimalSeparator );
3870													} )
3871													.reduce( function( acc, thisval ) {
3872														if ( type === 'text' || type === 'rawvalue' ) {
3873															return acc + thisval;
3874														}
3875														return $.epoAPI.math.toFloat( acc ) + $.epoAPI.math.toFloat( thisval );
3876													}, ( type === 'text' || type === 'rawvalue' ) ? '' : 0 );
3877
3878												if ( type === 'text' || type === 'rawvalue' ) {
3879													if ( val === '' ) {
3880														val = "''";
3881													} else if ( ! val.toString().isNumeric() ) {
3882														val = "'" + val + "'";
3883													}
3884												}
3885											}
3886											break;
3887
3888										// element value length
3889										case 'value.length':
3890										case 'text.length':
3891											if ( val.floatingBoxData ) {
3892												val = val.floatingBoxData
3893													.map( function( x ) {
3894														return x.valueText;
3895													} )
3896													.reduce( function( acc, thisval ) {
3897														return $.epoAPI.math.toFloat( acc ) + thisval.length;
3898													}, 0 );
3899											}
3900											break;
3901
3902										// element quantity
3903										// the total option quantity of this element
3904										case 'quantity':
3905										case 'count.quantity':
3906											if ( val.floatingBoxData ) {
3907												val = val.floatingBoxData
3908													.map( function( x ) {
3909														return x.quantity;
3910													} )
3911													.reduce( function( acc, thisval ) {
3912														return $.epoAPI.math.toFloat( acc ) + $.epoAPI.math.toFloat( thisval );
3913													}, 0 );
3914											}
3915											break;
3916
3917										// number of element options the user has selected
3918										case 'count':
3919											if ( val.floatingBoxData ) {
3920												val = val.floatingBoxData.length;
3921											}
3922											break;
3923									}
3924									if ( type !== 'text' && type !== 'rawvalue' ) {
3925										val = $.epoAPI.math.toFloat( val );
3926										if ( ! Number.isFinite( val ) ) {
3927											val = 0;
3928										}
3929									}
3930								}
3931							} else {
3932								val = 0;
3933							}
3934							reg = new RegExp( match[ 0 ] );
3935							if ( type === 'text' || type === 'rawvalue' ) {
3936								formula = formula.replace( reg, val );
3937							} else {
3938								formula = ! Number.isFinite( val ) ? formula.replace( reg, "'" + val + "'" ) : formula.replace( reg, val );
3939							}
3940						}
3941					}
3942				}
3943			} );
3944		}
3945
3946		try {
3947			elementPrice = tcmexp.evaluate( formula );
3948		} catch ( e ) {
3949			elementPrice = 0;
3950		}
3951
3952		return elementPrice;
3953	}
3954
3955	// Set field price rules
3956	function get_price_type( epoObject, obj ) {
3957		var element = $( obj );
3958		var setter = element;
3959		var cart;
3960		var current_variation;
3961		var rules;
3962		var rulestype;
3963		var _rulestype;
3964		var pricetype;
3965		var variation_id_selector;
3966		var _tmcpulwrap;
3967
3968		cart = epoObject.main_cart;
3969		variation_id_selector = "input[name^='variation_id']";
3970		if ( cart.find( 'input.variation_id' ).length > 0 ) {
3971			variation_id_selector = 'input.variation_id';
3972		}
3973		current_variation = cart.find( variation_id_selector ).val();
3974		// Get current woocommerce variation
3975		if ( ! current_variation ) {
3976			current_variation = 0;
3977		}
3978
3979		if ( element.is( 'select' ) ) {
3980			setter = element.find( 'option:selected' );
3981		}
3982
3983		rules = $.epoAPI.util.parseJSON( setter.attr( 'data-rules' ) );
3984		rulestype = $.epoAPI.util.parseJSON( setter.attr( 'data-rulestype' ) );
3985
3986		pricetype = '';
3987		if ( typeof rules === 'object' ) {
3988			if ( typeof rulestype === 'object' ) {
3989				if ( current_variation in rulestype ) {
3990					pricetype = rulestype[ current_variation ];
3991				} else {
3992					_rulestype = $.epoAPI.util.parseJSON( element.closest( '.tmcp-ul-wrap' ).attr( 'data-rulestype' ) );
3993					if ( typeof _rulestype === 'object' ) {
3994						if ( current_variation in _rulestype ) {
3995							pricetype = _rulestype[ current_variation ];
3996						} else {
3997							pricetype = rulestype[ 0 ];
3998						}
3999					} else {
4000						pricetype = rulestype[ 0 ];
4001					}
4002				}
4003			} else {
4004				rulestype = $.epoAPI.util.parseJSON( element.closest( '.tmcp-ul-wrap' ).attr( 'data-ulestype' ) );
4005				if ( typeof rulestype === 'object' ) {
4006					if ( current_variation in rulestype ) {
4007						pricetype = rulestype[ current_variation ];
4008					} else {
4009						pricetype = rulestype[ 0 ];
4010					}
4011				}
4012			}
4013		} else {
4014			_tmcpulwrap = element.closest( '.tmcp-ul-wrap' );
4015			rules = $.epoAPI.util.parseJSON( _tmcpulwrap.attr( 'data-rules' ) );
4016
4017			if ( typeof rules === 'object' ) {
4018				if ( typeof rulestype === 'object' ) {
4019					if ( current_variation in rulestype ) {
4020						pricetype = rulestype[ current_variation ];
4021					} else {
4022						_rulestype = $.epoAPI.util.parseJSON( _tmcpulwrap.attr( 'data-rulestype' ) );
4023						if ( typeof _rulestype === 'object' ) {
4024							if ( current_variation in _rulestype ) {
4025								pricetype = _rulestype[ current_variation ];
4026							} else {
4027								pricetype = rulestype[ 0 ];
4028							}
4029						} else {
4030							pricetype = rulestype[ 0 ];
4031						}
4032					}
4033				} else {
4034					rulestype = $.epoAPI.util.parseJSON( _tmcpulwrap.attr( 'data-rulestype' ) );
4035					if ( typeof rulestype === 'object' ) {
4036						if ( current_variation in rulestype ) {
4037							pricetype = rulestype[ current_variation ];
4038						} else {
4039							pricetype = rulestype[ 0 ];
4040						}
4041					}
4042				}
4043			}
4044		}
4045
4046		if ( typeof pricetype === 'object' ) {
4047			pricetype = pricetype[ 0 ];
4048		}
4049		if ( element.is( '.tmcp-fee-field' ) ) {
4050			if ( $.inArray( pricetype, [ 'fee', 'stepfee', 'currentstepfee' ] ) !== -1 ) {
4051				pricetype = '';
4052			}
4053		}
4054
4055		return pricetype;
4056	}
4057
4058	function wordLength( str ) {
4059		var regex = new RegExp( /[\p{L}\d!@#$%^&*()_+=\{[\}\]|\\"':;?/>.<,-]+/, 'gu' );
4060		var m;
4061		var len = 0;
4062
4063		while ( ( m = regex.exec( str ) ) !== null ) {
4064			// This is necessary to avoid infinite loops with zero-width matches
4065			if ( m.index === regex.lastIndex ) {
4066				regex.lastIndex++;
4067			}
4068			len = len + m.length;
4069		}
4070		return len;
4071	}
4072
4073	// Set field price rules
4074	function tm_element_epo_rules( epoObject, obj, args, setter_override, noremove, manthnoevent ) {
4075		var element = $( obj );
4076		var setterall = element;
4077		var cart;
4078		var current_variation;
4079		var bundleid;
4080		var epoTotalsContainer;
4081		var apply_dpd;
4082		var product_price;
4083		var product_original_price;
4084		var is_range_field = element.is( '.tmcp-range' );
4085		var rules;
4086		var rulestype;
4087		var original_rules;
4088		var _rules;
4089		var _rulestype;
4090		var _original_rules;
4091		var pricetype;
4092		var price;
4093		var original_price;
4094		var raw_price;
4095		var raw_original_price;
4096		var formatted_price;
4097		var original_formatted_price;
4098		var textlength;
4099		var freechars;
4100		var min_value;
4101		var main_product = epoObject.main_product;
4102		var epoEventId = epoObject.epoEventId;
4103		var variation_id_selector;
4104		var _tmcpulwrap;
4105		var cart_total;
4106		var per_product_pricing = true;
4107		var addedPrice = 0;
4108		var originalAddedPrice = 0;
4109		var undiscounted_raw_price;
4110		var undiscounted_raw_original_price;
4111		var undiscounted_price;
4112		var undiscounted_original_price;
4113		var isFilled;
4114
4115		if ( element.data( 'associated_price_set' ) ) {
4116			return;
4117		}
4118
4119		if ( ! args ) {
4120			cart = epoObject.main_cart;
4121			if ( cart.data( 'per_product_pricing' ) !== undefined ) {
4122				per_product_pricing = cart.data( 'per_product_pricing' );
4123			}
4124			variation_id_selector = "input[name^='variation_id']";
4125			if ( cart.find( 'input.variation_id' ).length > 0 ) {
4126				variation_id_selector = 'input.variation_id';
4127			}
4128			current_variation = cart.find( variation_id_selector ).val();
4129
4130			bundleid = $.epoAPI.applyFilter( 'tc_get_bundleid', cart.attr( 'data-product_id' ), cart, epoObject );
4131
4132			// Get current woocommerce variation
4133			if ( ! current_variation ) {
4134				current_variation = 0;
4135			}
4136
4137			epoTotalsContainer = $.epoAPI.applyFilter( 'tc_get_totals_container', epoObject.this_epo_totals_container, element, main_product, bundleid );
4138			product_price = tm_calculate_product_price( epoTotalsContainer );
4139			product_original_price = tm_calculate_product_regular_price( epoTotalsContainer );
4140			apply_dpd = epoTotalsContainer.data( 'fields-price-rules' );
4141		} else {
4142			cart = args.cart;
4143			current_variation = args.current_variation;
4144
4145			bundleid = args.bundleid;
4146			epoTotalsContainer = args.epoTotalsContainer;
4147			product_price = args.product_price;
4148			product_original_price = args.product_original_price;
4149			apply_dpd = args.apply_dpd;
4150			per_product_pricing = args.per_product_pricing;
4151		}
4152		product_price = $.epoAPI.applyFilter( 'tc_alter_product_price', product_price, element, cart, epoTotalsContainer, bundleid );
4153		product_original_price = $.epoAPI.applyFilter( 'tc_alter_product_original_price', product_original_price, element, cart, epoTotalsContainer );
4154
4155		if ( product_price === false || ! per_product_pricing ) {
4156			return;
4157		}
4158
4159		if ( element.is( 'select' ) ) {
4160			setterall = element.find( 'option:selected' );
4161		}
4162		if ( setter_override ) {
4163			setterall = setter_override;
4164		}
4165
4166		setterall.toArray().forEach( function( setter ) {
4167			setter = $( setter );
4168
4169			rules = $.epoAPI.util.parseJSON( setter.attr( 'data-rules' ) );
4170			rulestype = $.epoAPI.util.parseJSON( setter.attr( 'data-rulestype' ) );
4171			original_rules = $.epoAPI.util.parseJSON( setter.attr( 'data-original-rules' ) );
4172
4173			if ( original_rules === undefined ) {
4174				original_rules = rules;
4175			}
4176
4177			pricetype = '';
4178			if ( typeof rules === 'object' ) {
4179				if ( current_variation in rules ) {
4180					price = rules[ current_variation ];
4181					original_price = original_rules[ current_variation ];
4182				} else {
4183					_rules = $.epoAPI.util.parseJSON( element.closest( '.tmcp-ul-wrap' ).attr( 'data-rules' ) );
4184					_original_rules = element.closest( '.tmcp-ul-wrap' ).data( 'original-rules' );
4185
4186					if ( typeof _rules === 'object' ) {
4187						if ( current_variation in _rules ) {
4188							price = _rules[ current_variation ];
4189						} else {
4190							price = rules[ 0 ];
4191						}
4192					} else {
4193						price = rules[ 0 ];
4194					}
4195
4196					if ( typeof _original_rules === 'object' ) {
4197						if ( current_variation in _original_rules ) {
4198							original_price = _original_rules[ current_variation ];
4199						} else {
4200							original_price = original_rules[ 0 ];
4201						}
4202					} else {
4203						original_price = original_rules[ 0 ];
4204					}
4205				}
4206
4207				if ( typeof rulestype === 'object' ) {
4208					if ( current_variation in rulestype ) {
4209						pricetype = rulestype[ current_variation ];
4210					} else {
4211						_rulestype = $.epoAPI.util.parseJSON( element.closest( '.tmcp-ul-wrap' ).attr( 'data-rulestype' ) );
4212						if ( typeof _rulestype === 'object' ) {
4213							if ( current_variation in _rulestype ) {
4214								pricetype = _rulestype[ current_variation ];
4215							} else {
4216								pricetype = rulestype[ 0 ];
4217							}
4218						} else {
4219							pricetype = rulestype[ 0 ];
4220						}
4221					}
4222				} else {
4223					rulestype = $.epoAPI.util.parseJSON( element.closest( '.tmcp-ul-wrap' ).attr( 'data-ulestype' ) );
4224					if ( typeof rulestype === 'object' ) {
4225						if ( current_variation in rulestype ) {
4226							pricetype = rulestype[ current_variation ];
4227						} else {
4228							pricetype = rulestype[ 0 ];
4229						}
4230					}
4231				}
4232			} else {
4233				_tmcpulwrap = element.closest( '.tmcp-ul-wrap' );
4234				rules = $.epoAPI.util.parseJSON( _tmcpulwrap.attr( 'data-rules' ) );
4235				original_rules = $.epoAPI.util.parseJSON( _tmcpulwrap.attr( 'data-original-rules' ) );
4236
4237				if ( typeof rules === 'object' ) {
4238					if ( current_variation in rules ) {
4239						price = rules[ current_variation ];
4240					} else {
4241						price = rules[ 0 ];
4242					}
4243					if ( typeof original_rules === 'object' ) {
4244						if ( current_variation in original_rules ) {
4245							original_price = original_rules[ current_variation ];
4246						} else {
4247							original_price = original_rules[ 0 ];
4248						}
4249					} else {
4250						original_price = price;
4251					}
4252
4253					if ( typeof rulestype === 'object' ) {
4254						if ( current_variation in rulestype ) {
4255							pricetype = rulestype[ current_variation ];
4256						} else {
4257							_rulestype = $.epoAPI.util.parseJSON( _tmcpulwrap.attr( 'data-rulestype' ) );
4258							if ( typeof _rulestype === 'object' ) {
4259								if ( current_variation in _rulestype ) {
4260									pricetype = _rulestype[ current_variation ];
4261								} else {
4262									pricetype = rulestype[ 0 ];
4263								}
4264							} else {
4265								pricetype = rulestype[ 0 ];
4266							}
4267						}
4268					} else {
4269						rulestype = $.epoAPI.util.parseJSON( _tmcpulwrap.attr( 'data-rulestype' ) );
4270						if ( typeof rulestype === 'object' ) {
4271							if ( current_variation in rulestype ) {
4272								pricetype = rulestype[ current_variation ];
4273							} else {
4274								pricetype = rulestype[ 0 ];
4275							}
4276						}
4277					}
4278				}
4279			}
4280
4281			if ( typeof pricetype === 'object' ) {
4282				pricetype = pricetype[ 0 ];
4283			}
4284			if ( element.is( '.tmcp-fee-field' ) ) {
4285				if ( $.inArray( pricetype, [ 'fee', 'stepfee', 'currentstepfee' ] ) !== -1 ) {
4286					pricetype = '';
4287				}
4288				apply_dpd = 0;
4289			}
4290
4291			if ( noremove === undefined ) {
4292				if ( element.is( 'select' ) ) {
4293					element.find( 'option' ).removeClass( 'tm-epo-late-field' ).removeData( 'tm-price-for-late islate' );
4294				} else {
4295					setter.removeClass( 'tm-epo-late-field' ).removeData( 'tm-price-for-late islate' );
4296				}
4297			}
4298			if ( pricetype !== 'math' ) {
4299				price = cleanPrice( price );
4300				original_price = cleanPrice( original_price );
4301			}
4302
4303			undiscounted_raw_price = price;
4304			undiscounted_raw_original_price = original_price;
4305
4306			switch ( pricetype ) {
4307				case '':
4308					undiscounted_price = price;
4309					price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd );
4310					// original_price No change
4311					break;
4312				case 'math':
4313					price = calculateMathPrice( price, element, epoObject, manthnoevent, $.epoAPI.applyFilter( 'tc_use_undiscounted_price', undefined, element, cart, epoTotalsContainer ) );
4314					undiscounted_price = price;
4315					price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd );
4316					original_price = calculateMathPrice( original_price, element, epoObject, true, true );
4317					// original_price No other change
4318					break;
4319				case 'percent_cart_total':
4320					cart_total = parseFloat( TMEPOJS.cart_total );
4321
4322					if ( ! Number.isFinite( cart_total ) ) {
4323						cart_total = 0;
4324					}
4325					undiscounted_price = ( price / 100 ) * cart_total;
4326					price = ( tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) / 100 ) * cart_total;
4327					original_price = ( tm_apply_dpd( original_price, epoTotalsContainer, apply_dpd ) / 100 ) * cart_total;
4328					break;
4329
4330				case 'percent':
4331					undiscounted_price = ( price / 100 ) * product_price;
4332					price = ( tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) / 100 ) * product_price;
4333					original_price = ( original_price / 100 ) * product_original_price;
4334					break;
4335				case 'percentcurrenttotal':
4336					$.tcepo.lateFieldsPrices[ epoEventId ].push( {
4337						setter: setter,
4338						price: price,
4339						original_price: original_price,
4340						bundleid: bundleid,
4341						pricetype: pricetype
4342					} );
4343					setter.data( 'tm-price-for-late', price ).data( 'tm-original-price-for-late', original_price ).data( 'islate', 1 ).addClass( 'tm-epo-late-field' );
4344					undiscounted_price = 0;
4345					price = 0;
4346					original_price = 0;
4347					break;
4348				case 'fixedcurrenttotal':
4349					price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd );
4350					$.tcepo.lateFieldsPrices[ epoEventId ].push( {
4351						setter: setter,
4352						price: price,
4353						original_price: original_price,
4354						bundleid: bundleid,
4355						pricetype: pricetype
4356					} );
4357					setter.data( 'tm-price-for-late', price ).data( 'tm-original-price-for-late', original_price ).data( 'islate', 1 ).addClass( 'tm-epo-late-field' );
4358					undiscounted_price = 0;
4359					price = 0;
4360					original_price = 0;
4361					break;
4362				case 'word':
4363					undiscounted_price = price * wordLength( setter.val() );
4364					price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) * wordLength( setter.val() );
4365					original_price = original_price * wordLength( setter.val() );
4366					break;
4367				case 'wordpercent':
4368					undiscounted_price = ( price / 100 ) * product_price * wordLength( setter.val() );
4369					price = ( tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) / 100 ) * product_price * wordLength( setter.val() );
4370					original_price = ( original_price / 100 ) * product_original_price * wordLength( setter.val() );
4371					break;
4372				case 'wordnon':
4373					freechars = parseInt( setter.attr( 'data-freechars' ), 10 );
4374					if ( ! Number.isFinite( freechars ) ) {
4375						freechars = 0;
4376					}
4377					textlength = wordLength( setter.val() ) - freechars;
4378					if ( textlength < 0 ) {
4379						textlength = 0;
4380					}
4381					undiscounted_price = price * textlength;
4382					price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) * textlength;
4383					original_price = original_price * textlength;
4384					break;
4385				case 'wordpercentnon':
4386					freechars = parseInt( setter.attr( 'data-freechars' ), 10 );
4387					if ( ! Number.isFinite( freechars ) ) {
4388						freechars = 0;
4389					}
4390					textlength = wordLength( setter.val() ) - freechars;
4391					if ( textlength < 0 ) {
4392						textlength = 0;
4393					}
4394					undiscounted_price = ( price / 100 ) * product_price * textlength;
4395					price = ( tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) / 100 ) * product_price * textlength;
4396					original_price = ( original_price / 100 ) * product_original_price * textlength;
4397					break;
4398
4399				case 'char':
4400					undiscounted_price = price * setter.val().length;
4401					price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) * setter.val().length;
4402					original_price = original_price * setter.val().length;
4403					break;
4404				case 'charpercent':
4405					undiscounted_price = ( price / 100 ) * product_price * setter.val().length;
4406					price = ( tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) / 100 ) * product_price * setter.val().length;
4407					original_price = ( original_price / 100 ) * product_original_price * setter.val().length;
4408					break;
4409				case 'charnospaces':
4410					undiscounted_price = price * setter.val().replace( /\s/g, '' ).length;
4411					price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) * setter.val().replace( /\s/g, '' ).length;
4412					original_price = original_price * setter.val().replace( /\s/g, '' ).length;
4413					break;
4414				case 'charnofirst':
4415					textlength = setter.val().length - 1;
4416					if ( textlength < 0 ) {
4417						textlength = 0;
4418					}
4419					undiscounted_price = price * textlength;
4420					price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) * textlength;
4421					original_price = original_price * textlength;
4422					break;
4423
4424				case 'charnon':
4425					freechars = parseInt( setter.attr( 'data-freechars' ), 10 );
4426					if ( ! Number.isFinite( freechars ) ) {
4427						freechars = 0;
4428					}
4429					textlength = setter.val().length - freechars;
4430					if ( textlength < 0 ) {
4431						textlength = 0;
4432					}
4433					undiscounted_price = price * textlength;
4434					price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) * textlength;
4435					original_price = original_price * textlength;
4436					break;
4437				case 'charpercentnon':
4438					freechars = parseInt( setter.attr( 'data-freechars' ), 10 );
4439					if ( ! Number.isFinite( freechars ) ) {
4440						freechars = 0;
4441					}
4442					textlength = setter.val().length - freechars;
4443					if ( textlength < 0 ) {
4444						textlength = 0;
4445					}
4446					undiscounted_price = ( price / 100 ) * product_price * textlength;
4447					price = ( tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) / 100 ) * product_price * textlength;
4448					original_price = ( original_price / 100 ) * product_original_price * textlength;
4449					break;
4450				case 'charnonnospaces':
4451					freechars = parseInt( setter.attr( 'data-freechars' ), 10 );
4452					if ( ! Number.isFinite( freechars ) ) {
4453						freechars = 0;
4454					}
4455					textlength = setter.val().replace( /\s/g, '' ).length - freechars;
4456					if ( textlength < 0 ) {
4457						textlength = 0;
4458					}
4459					undiscounted_price = price * textlength;
4460					price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) * textlength;
4461					original_price = original_price * textlength;
4462					break;
4463				case 'charpercentnonnospaces':
4464					freechars = parseInt( setter.attr( 'data-freechars' ), 10 );
4465					if ( ! Number.isFinite( freechars ) ) {
4466						freechars = 0;
4467					}
4468					textlength = setter.val().replace( /\s/g, '' ).length - freechars;
4469					if ( textlength < 0 ) {
4470						textlength = 0;
4471					}
4472					undiscounted_price = ( price / 100 ) * product_price * textlength;
4473					price = ( tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) / 100 ) * product_price * textlength;
4474					original_price = ( original_price / 100 ) * product_original_price * textlength;
4475					break;
4476
4477				case 'charpercentnofirst':
4478					textlength = setter.val().length - 1;
4479					if ( textlength < 0 ) {
4480						textlength = 0;
4481					}
4482					undiscounted_price = ( price / 100 ) * product_price * textlength;
4483					price = ( tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) / 100 ) * product_price * textlength;
4484					original_price = ( original_price / 100 ) * product_original_price * textlength;
4485					break;
4486				case 'step':
4487					if ( is_range_field ) {
4488						undiscounted_price = price * setter.val();
4489						price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) * setter.val();
4490						original_price = original_price * $.epoAPI.math.toFloat( setter.val() );
4491					} else {
4492						undiscounted_price = price * $.epoAPI.math.toFloat( setter.val() );
4493						price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) * $.epoAPI.math.toFloat( setter.val() );
4494						original_price = original_price * $.epoAPI.math.toFloat( setter.val() );
4495					}
4496					break;
4497				case 'currentstep':
4498					if ( is_range_field ) {
4499						undiscounted_price = setter.val();
4500						price = tm_apply_dpd( setter.val(), epoTotalsContainer, apply_dpd );
4501						original_price = tm_apply_dpd( setter.val(), epoTotalsContainer, apply_dpd );
4502					} else {
4503						undiscounted_price = $.epoAPI.math.toFloat( setter.val() );
4504						price = tm_apply_dpd( $.epoAPI.math.toFloat( setter.val() ), epoTotalsContainer, apply_dpd );
4505						original_price = tm_apply_dpd( $.epoAPI.math.toFloat( setter.val() ), epoTotalsContainer, apply_dpd );
4506					}
4507					break;
4508				case 'intervalstep':
4509					if ( is_range_field ) {
4510						min_value = parseFloat( $( '.tm-range-picker[data-field-id="' + setter.attr( 'id' ) + '"]' ).attr( 'data-min' ) );
4511						undiscounted_price = price * ( setter.val() - min_value );
4512						price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) * ( setter.val() - min_value );
4513						original_price = original_price * ( setter.val() - min_value );
4514					}
4515					break;
4516				case 'row':
4517					undiscounted_price = price * ( ( setter.val().match( /(\r\n|\n|\r)/gm ) || [] ).length + 1 );
4518					price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) * ( ( setter.val().match( /(\r\n|\n|\r)/gm ) || [] ).length + 1 );
4519					original_price = original_price * ( ( setter.val().match( /(\r\n|\n|\r)/gm ) || [] ).length + 1 );
4520					break;
4521			}
4522
4523			raw_price = price;
4524			raw_original_price = original_price;
4525
4526			undiscounted_original_price = original_price;
4527			undiscounted_raw_price = undiscounted_price;
4528			undiscounted_raw_original_price = undiscounted_original_price;
4529
4530			if ( element.data( 'tm-quantity' ) ) {
4531				undiscounted_price = undiscounted_price * parseFloat( element.data( 'tm-quantity' ) );
4532				undiscounted_original_price = undiscounted_original_price * parseFloat( element.data( 'tm-quantity' ) );
4533				undiscounted_raw_price = undiscounted_raw_price * parseFloat( element.data( 'tm-quantity' ) );
4534				undiscounted_raw_original_price = undiscounted_raw_original_price * parseFloat( element.data( 'tm-quantity' ) );
4535
4536				price = price * parseFloat( element.data( 'tm-quantity' ) );
4537				original_price = original_price * parseFloat( element.data( 'tm-quantity' ) );
4538				raw_price = raw_price * parseFloat( element.data( 'tm-quantity' ) );
4539				raw_original_price = raw_original_price * parseFloat( element.data( 'tm-quantity' ) );
4540			}
4541
4542			addedPrice = addedPrice + parseFloat( price );
4543			originalAddedPrice = originalAddedPrice + parseFloat( original_price );
4544
4545			formatted_price = tm_set_price( addedPrice, epoTotalsContainer, false, false, setter, pricetype );
4546			original_formatted_price = tm_set_price( originalAddedPrice, epoTotalsContainer, false, false, setter, pricetype );
4547
4548			element.data( 'price_set', 1 );
4549			setter.data( 'price_set', 1 );
4550
4551			setter.data( 'undiscounted_raw_price', undiscounted_raw_price );
4552			setter.data( 'undiscounted_raw_original_price', undiscounted_raw_original_price );
4553			setter.data( 'undiscounted_price', tm_set_tax_price( undiscounted_price, epoTotalsContainer, setter, pricetype ) );
4554			setter.data( 'undiscounted_original_price', tm_set_tax_price( undiscounted_original_price, epoTotalsContainer, setter, pricetype ) );
4555
4556			setter.data( 'raw_price', raw_price );
4557			setter.data( 'raw_original_price', raw_original_price );
4558			setter.data( 'price', tm_set_tax_price( price, epoTotalsContainer, setter, pricetype ) );
4559			setter.data( 'original_price', tm_set_tax_price( original_price, epoTotalsContainer, setter, pricetype ) );
4560
4561			if ( ! setter_override ) {
4562				if ( element.is( '.tc-epo-field-product' ) ) {
4563					isFilled = false;
4564					if ( element.is( 'select' ) ) {
4565						if ( element.val() !== '' ) {
4566							isFilled = true;
4567						}
4568					} else if ( ( element.is( ':checkbox' ) || element.is( ':radio' ) ) ) {
4569						if ( element.is( ':checked' ) ) {
4570							isFilled = true;
4571						}
4572					} else if ( element.val() !== '' ) {
4573						isFilled = true;
4574					}
4575
4576					if ( ! isFilled ) {
4577						formatted_price = setter.data( 'price-html' );
4578						original_formatted_price = '';
4579					}
4580				}
4581				tm_update_price( setter.closest( '.tmcp-field-wrap' ).find( '.tc-price' ), addedPrice, formatted_price, originalAddedPrice, original_formatted_price );
4582				element.data( 'price-changed', 1 );
4583			}
4584		} );
4585	}
4586
4587	function tm_epo_rules( epoObject, theCart ) {
4588		var all_carts;
4589		var variation_id_selector;
4590		var per_product_pricing = true;
4591		var current_variation;
4592		var bundleid;
4593		var epoContainer;
4594		var epoTotalsContainer;
4595		var apply_dpd;
4596		var rules;
4597		var original_rules;
4598		var price;
4599		var formatted_price;
4600		var original_price;
4601		var original_formatted_price;
4602		var product_price;
4603		var product_original_price;
4604		var all_fields;
4605		var active_fields;
4606		var args;
4607		var main_product = epoObject.main_product;
4608		var epoEventId = epoObject.epoEventId;
4609		var this_epo_container = epoObject.this_epo_container;
4610		var this_epo_totals_container = epoObject.this_epo_totals_container;
4611
4612		if ( ! theCart ) {
4613			all_carts = main_product.find( '.cart' );
4614		} else {
4615			all_carts = theCart;
4616		}
4617		if ( all_carts.length <= 0 ) {
4618			return;
4619		}
4620
4621		$.tcepo.lateFieldsPrices[ epoEventId ] = [];
4622
4623		all_carts.toArray().forEach( function( cart ) {
4624			cart = $( cart );
4625			variation_id_selector = "input[name^='variation_id']";
4626			if ( cart.find( 'input.variation_id' ).length > 0 ) {
4627				variation_id_selector = 'input.variation_id';
4628			}
4629
4630			if ( cart.data( 'per_product_pricing' ) !== undefined ) {
4631				per_product_pricing = cart.data( 'per_product_pricing' );
4632			}
4633
4634			current_variation = cart.find( variation_id_selector ).val();
4635			bundleid = $.epoAPI.applyFilter( 'tc_get_bundleid', cart.attr( 'data-product_id' ), cart, epoObject );
4636
4637			// get current woocommerce variation
4638			if ( ! current_variation ) {
4639				current_variation = 0;
4640			}
4641
4642			epoContainer = $.epoAPI.applyFilter( 'tc_get_epo_container', this_epo_container, cart, main_product, bundleid );
4643			epoTotalsContainer = $.epoAPI.applyFilter( 'tc_get_totals_container', this_epo_totals_container, cart, main_product, bundleid );
4644
4645			// WooCommerce Dynamic Pricing & Discounts
4646			apply_dpd = epoTotalsContainer.data( 'fields-price-rules' );
4647
4648			// set initial prices for all fields
4649			if ( ! epoContainer.data( 'tm_rules_init_done' ) ) {
4650				if ( epoTotalsContainer.data( 'force-quantity' ) ) {
4651					cart.find( tcAPI.qtySelector ).val( epoTotalsContainer.data( 'force-quantity' ) );
4652				}
4653				epoContainer.toArray().forEach( function( el ) {
4654					$( el ).closest( '.tmcp-field-wrap' ).find( '.tm-epo-field' ).data( 'tm-quantity', $( el ).val() );
4655				} );
4656
4657				epoContainer
4658					.find( '.tmcp-attributes, .tmcp-elements' )
4659					.toArray()
4660					.forEach( function( element ) {
4661						element = $( element );
4662						rules = $.epoAPI.util.parseJSON( element.attr( 'data-rules' ) );
4663						original_rules = $.epoAPI.util.parseJSON( element.attr( 'data-original-rules' ) );
4664
4665						// if rule doesn't exit then init an empty rule
4666						if ( typeof rules !== 'object' ) {
4667							rules = {
4668								0: '0'
4669							};
4670						}
4671						if ( typeof original_rules !== 'object' ) {
4672							original_rules = {
4673								0: '0'
4674							};
4675						}
4676						if ( typeof rules === 'object' ) {
4677							// we skip price validation test so that every field has at least a price of 0
4678							price = tm_apply_dpd( rules[ $.epoAPI.math.toFloat( current_variation ) ], epoTotalsContainer, apply_dpd );
4679							formatted_price = tm_set_price( price, epoTotalsContainer );
4680							original_price = tm_apply_dpd( original_rules[ $.epoAPI.math.toFloat( current_variation ) ], epoTotalsContainer, apply_dpd );
4681							original_formatted_price = tm_set_price( original_price, epoTotalsContainer );
4682
4683							element
4684								.find( '.tmcp-field, .tmcp-fee-field ' )
4685								.toArray()
4686								.forEach( function( el ) {
4687									el = $( el );
4688									if ( per_product_pricing ) {
4689										if ( el.attr( 'data-no-price' ) === '1' ) {
4690											price = 0;
4691											original_price = 0;
4692										}
4693										el.data( 'raw_price', price );
4694										el.data( 'raw_original_price', original_price );
4695
4696										el.data( 'price', tm_set_tax_price( price, epoTotalsContainer, el ) );
4697										el.data( 'original_price', tm_set_tax_price( original_price, epoTotalsContainer, el ) );
4698
4699										tm_update_price( el.closest( '.tmcp-field-wrap' ).find( '.tc-price' ), price, formatted_price, original_price, original_formatted_price );
4700									} else {
4701										el.data( 'price', 0 );
4702										el.data( 'original_price', 0 );
4703										el.closest( '.tmcp-field-wrap' ).find( '.amount' ).empty();
4704									}
4705								} );
4706						}
4707					} );
4708				epoContainer.data( 'tm_rules_init_done', 1 );
4709			}
4710
4711			// skip specific field rules if per_product_pricing is false
4712			if ( ! per_product_pricing ) {
4713				return true;
4714			}
4715
4716			product_price = tm_calculate_product_price( epoTotalsContainer );
4717			product_original_price = tm_calculate_product_regular_price( epoTotalsContainer );
4718
4719			args = {
4720				cart: cart,
4721				current_variation: current_variation,
4722				bundleid: bundleid,
4723				epoTotalsContainer: epoTotalsContainer,
4724				product_price: product_price,
4725				product_original_price: product_original_price,
4726				apply_dpd: apply_dpd,
4727				per_product_pricing: per_product_pricing
4728			};
4729
4730			all_fields = epoContainer.find( '.tmcp-field,.tmcp-sub-fee-field,.tmcp-fee-field' );
4731			if ( ! epoObject.is_associated ) {
4732				all_fields = all_fields.not( tcAPI.associatedEpoSelector + ' ' + '.tmcp-field,' + tcAPI.associatedEpoSelector + ' ' + '.tmcp-sub-fee-field,' + tcAPI.associatedEpoSelector + ' ' + '.tmcp-fee-field' );
4733			}
4734			active_fields = all_fields.filter( '.tcenabled' );
4735
4736			// note: find a better way if any
4737			if ( ! $.tcepo.initialActivation[ epoEventId ] || ( active_fields.length === 0 && all_fields.length > 0 ) ) {
4738				all_fields.each( function() {
4739					field_is_active( $( this ) );
4740				} );
4741
4742				$.tcepo.initialActivation[ epoEventId ] = true;
4743			}
4744
4745			//  apply specific field rules
4746			all_fields.filter( '.tcenabled' ).each( function( index, element ) {
4747				tm_element_epo_rules( epoObject, element, args );
4748			} );
4749
4750			all_fields.each( function( index, element ) {
4751				$( element ).on( 'tc_element_epo_rules', function() {
4752					tm_element_epo_rules( epoObject, element, args );
4753				} );
4754			} );
4755		} );
4756	}
4757
4758	function add_late_fields_prices( epoObject, currentProductPrice, originalProductPrice, options_total, original_options_total, bid, _cart, applydpd ) {
4759		var total = 0;
4760		var originalTotal = 0;
4761		var price;
4762		var originalPrice;
4763		var priceType;
4764		var setter;
4765		var id;
4766		var hidden;
4767		var bundleid;
4768		var realSetter;
4769		var productId;
4770		var epoId;
4771		var formattedPrice;
4772		var originalFormattedPrice;
4773		var epoEventId = epoObject.epoEventId;
4774		var taxPrice;
4775		var taxOriginalPrice;
4776		var hiddenName;
4777		var productPrice;
4778		var oProductPrice;
4779		var apply_dpd;
4780
4781		if ( applydpd !== undefined ) {
4782			apply_dpd = applydpd;
4783		} else {
4784			apply_dpd = epoObject.this_epo_totals_container.data( 'fields-price-rules' );
4785		}
4786		productPrice = currentProductPrice;
4787		oProductPrice = originalProductPrice;
4788
4789		$.tcepo.lateFieldsPrices[ epoEventId ].forEach( function( field ) {
4790			price = field.price;
4791			originalPrice = field.original_price;
4792			priceType = field.pricetype;
4793			setter = field.setter;
4794			bundleid = field.bundleid;
4795			realSetter = setter;
4796
4797			if ( priceType === 'percentcurrenttotal' ) {
4798				hiddenName = '_hidden';
4799			} else {
4800				hiddenName = '_hiddenfixed';
4801			}
4802
4803			if ( setter.is( 'option' ) ) {
4804				realSetter = setter.closest( 'select' );
4805			}
4806
4807			productPrice = parseFloat( $.epoAPI.applyFilter( 'tc_alter_product_price', productPrice, realSetter, _cart, epoObject.this_epo_totals_container, bid ) );
4808			oProductPrice = parseFloat( $.epoAPI.applyFilter( 'tc_alter_original_product_price', oProductPrice, realSetter, _cart, epoObject.this_epo_totals_container, bid ) );
4809
4810			id = $.epoAPI.dom.id( realSetter.attr( 'name' ) );
4811			productId = $( '.tc-totals-form.tm-totals-form-' + _cart.attr( 'data-cart-id' ) ).attr( 'data-product-id' );
4812			epoId = $( '.tc-totals-form.tm-totals-form-' + _cart.attr( 'data-cart-id' ) ).attr( 'data-epo-id' );
4813			//workaround to support composite products
4814			hidden = $( '.tc-extra-product-options.tm-product-id-' + productId + "[data-epo-id='" + epoId + "']" ).find( '#' + id + hiddenName );
4815
4816			if ( bundleid === bid ) {
4817				if ( priceType === 'percentcurrenttotal' ) {
4818					price = ( parseFloat( price ) / 100 ) * ( tm_apply_dpd( parseFloat( productPrice ), epoObject.this_epo_totals_container, apply_dpd ) + parseFloat( options_total ) );
4819					originalPrice = ( parseFloat( originalPrice ) / 100 ) * ( parseFloat( oProductPrice ) + parseFloat( original_options_total ) );
4820				} else if ( priceType === 'fixedcurrenttotal' ) {
4821					price = parseFloat( price ) + parseFloat( options_total );
4822					originalPrice = parseFloat( originalPrice ) + parseFloat( original_options_total );
4823				}
4824				if ( realSetter.data( 'tm-quantity' ) ) {
4825					price = price * parseFloat( realSetter.data( 'tm-quantity' ) );
4826					originalPrice = originalPrice * parseFloat( realSetter.data( 'tm-quantity' ) );
4827				}
4828
4829				if ( setter.data( 'isset' ) === 1 && field_is_active( setter ) ) {
4830					total = total + price;
4831					originalTotal = originalTotal + originalPrice;
4832				}
4833
4834				taxPrice = tm_set_tax_price( price, _cart, setter );
4835				taxOriginalPrice = tm_set_tax_price( originalPrice, _cart, setter );
4836
4837				formattedPrice = tm_set_price( price, _cart, false, false, setter );
4838				originalFormattedPrice = tm_set_price( originalPrice, _cart, false, false, setter );
4839				setter.data( 'price', taxPrice );
4840				setter.data( 'pricew', taxPrice );
4841				setter.data( 'original_price', taxOriginalPrice );
4842				setter.data( 'original_pricew', taxOriginalPrice );
4843
4844				tm_update_price( setter.closest( '.tmcp-field-wrap' ).find( '.tc-price' ), taxPr
4844ice, formattedPrice, taxOriginalPrice, originalFormattedPrice );
4845
4846				if ( hidden.length === 0 ) {
4847					realSetter.before( '<input type="hidden" id="' + id + hiddenName + '" name="' + id + hiddenName + '" value="' + tm_set_price_without_tax( price, _cart ) + '">' );
4848				}
4849				if ( setter.is( '.tm-epo-field.tmcp-radio' ) ) {
4850					if ( setter.is( ':checked' ) ) {
4851						hidden.val( tm_set_price_without_tax( price, _cart ) );
4852					}
4853				} else {
4854					hidden.val( tm_set_price_without_tax( price, _cart ) );
4855				}
4856			} else if ( setter.data( 'pricew' ) !== undefined ) {
4857				formattedPrice = tm_set_price( setter.data( 'pricew' ), _cart, true, false, setter );
4858				originalFormattedPrice = '';
4859
4860				if ( setter.data( 'original_pricew' ) !== undefined ) {
4861					originalFormattedPrice = tm_set_price( setter.data( 'original_pricew' ), _cart, true, false, setter );
4862				}
4863
4864				tm_update_price( setter.closest( '.tmcp-field-wrap' ).find( '.tc-price' ), setter.data( 'pricew' ), formattedPrice, setter.data( 'original_pricew' ), originalFormattedPrice );
4865			}
4866		} );
4867
4868		return [ total, originalTotal ];
4869	}
4870
4871	function tm_lazyload() {
4872		var container;
4873
4874		if ( TMEPOJS.tm_epo_no_lazy_load === 'yes' ) {
4875			return;
4876		}
4877
4878		if ( tmLazyloadContainer ) {
4879			container = $( tmLazyloadContainer ).find( 'img.tmlazy' );
4880		} else {
4881			container = $( '.tc-extra-product-options img.tmlazy' );
4882		}
4883
4884		container.lazyLoadXT();
4885		container.on( 'lazyshow', function() {
4886			jWindow.trigger( 'lazyLoadXToncomplete' );
4887		} );
4888	}
4889
4890	function tm_css_styles( obj ) {
4891		var slider;
4892		var display;
4893
4894		if ( ! obj ) {
4895			return;
4896		}
4897
4898		obj.find( '.tm-owl-slider-section' ).each( function() {
4899			slider = $( this );
4900
4901			slider.find( '.tc-slider-content' ).addClass( 'tm-owl-slider tc-container' );
4902
4903			slider = slider.find( '.tm-owl-slider' );
4904			display = slider.css( 'display' );
4905
4906			slider
4907				.show()
4908				.addClass( 'tcowl-carousel' )
4909				.tmowlCarousel( {
4910					rtl: TMEPOJS.isRTL === '1',
4911					dots: false,
4912					nav: true,
4913					items: 1,
4914					autoHeight: true,
4915					mouseDrag: false,
4916					touchDrag: true,
4917					//navigation:true,
4918					navText: [ TMEPOJS.i18n_prev_text, TMEPOJS.i18n_next_text ],
4919					navClass: [ 'owl-prev button', 'owl-next button' ],
4920					navElement: 'a',
4921					loop: false,
4922					navRewind: false
4923				} );
4924
4925			slider.css( 'display', display );
4926		} );
4927
4928		if ( $.fn.tcTabs ) {
4929			obj.find( '.tc-tabs' ).tcTabs( {
4930				headers: 'tc-tab-headers',
4931				header: 'tab-header',
4932				dataopenattribute: 'data-tab',
4933				sortabletabs: false
4934			} );
4935		}
4936	}
4937
4938	function repeaterAdd( el, elementInnerWrap ) {
4939		var cpf = elementInnerWrap.closest( '.cpf-element' );
4940		var maxRows = cpf.data( 'repeater-max-rows' );
4941		var repeater = elementInnerWrap.find( '.tc-repeater-element' );
4942		var rows = repeater.length;
4943		var repeaterLast = repeater.last();
4944		var repeaterLastUL = repeater.last().find( '.tmcp-ul-wrap' );
4945		var clone;
4946		var cloneUl;
4947		var originalId = el.data( 'tc-repeater-id' );
4948		var index = el.data( 'tc-repeater-init' );
4949
4950		if ( maxRows ) {
4951			if ( rows >= maxRows ) {
4952				return false;
4953			}
4954		}
4955
4956		if ( rows + 1 >= maxRows && el.is( '.tc-repeater-add' ) ) {
4957			el.closest( '.tc-repeater-wrap' ).addClass( 'tc-hidden' );
4958		}
4959
4960		if ( repeaterLastUL.is( '.tm-element-ul-date, .tm-element-ul-time' ) ) {
4961			repeaterLastUL.find( '.tm-epo-field' ).tm_datepicker( 'destroy' );
4962			repeaterLastUL.find( '.tmcp-date-select' ).off();
4963		}
4964		if ( repeaterLastUL.is( '.tm-element-ul-color' ) ) {
4965			repeaterLastUL.find( '.tm-epo-field' ).spectrum( 'destroy' );
4966		}
4967
4968		clone = repeaterLast.tcClone( true );
4969
4970		clone.find( '.tm-epo-field' ).attr( 'id', function( i, value ) {
4971			return value.replace( /\_\d+$/g, '' ) + '_' + index;
4972		} );
4973		clone.find( '[data-for]' ).attr( 'data-for', function( i, value ) {
4974			return value.replace( /\_\d+$/g, '' ) + '_' + index;
4975		} );
4976		clone.find( '[for]' ).attr( 'for', function( i, value ) {
4977			return value.replace( /\_\d+$/g, '' ) + '_' + index;
4978		} );
4979		clone.find( '[data-field-id]' ).attr( 'data-field-id', function( i, value ) {
4980			return value.replace( /\_\d+$/g, '' ) + '_' + index;
4981		} );
4982		clone.find( '[data-tm-date]' ).attr( 'data-tm-date', function() {
4983			return originalId + '_' + index;
4984		} );
4985		clone.find( '.tm-epo-field' ).attr( 'name', function( i, value ) {
4986			return value.replace( /\[\d+\]/g, '[' + index + ']' );
4987		} );
4988		clone.find( '.tm-qty' ).attr( 'name', function( i, value ) {
4989			return value.replace( /\[\d+\]/g, '[' + index + ']' );
4990		} );
4991		clone.find( '.tmcp-date-select' ).attr( 'name', function( i, value ) {
4992			return value.replace( /\[\d+\]/g, '[' + index + ']' );
4993		} );
4994		clone.find( '.tmcp-date-select' ).attr( 'id', function( i, value ) {
4995			return originalId + '_' + index + '_' + value.substring( value.lastIndexOf( '_' ) + 1 );
4996		} );
4997
4998		cloneUl = clone.find( '.tmcp-ul-wrap' );
4999
5000		if ( elementInnerWrap.find( '.tc-repeater-element' ).length > 0 ) {
5001			elementInnerWrap.find( '.tc-repeater-delete' ).removeClass( 'tc-hidden' );
5002			clone.find( '.tc-repeater-delete' ).removeClass( 'tc-hidden' );
5003		}
5004
5005		if ( cloneUl.is( '.tm-element-ul-checkbox' ) ) {
5006			clone.find( 'li.tmcp-field-wrap' ).removeClass( 'tc-active' );
5007			clone
5008				.find( '.tm-epo-field.tmcp-checkbox' )
5009				.prop( 'checked', false );
5010			clone
5011				.find( '.tm-epo-field.tmcp-checkbox' )
5012				.filter( function( i, x ) {
5013					return $.inArray( $( x ).val(), el.data( 'repeater-init-value' ) ) !== -1;
5014				} )
5015				.prop( 'checked', true )
5016				.closest( 'li.tmcp-field-wrap' ).addClass( 'tc-active' );
5017		} else if ( cloneUl.is( '.tm-element-ul-radio' ) ) {
5018			clone.find( 'li.tmcp-field-wrap' ).removeClass( 'tc-active' );
5019			clone
5020				.find( '.tm-epo-field.tmcp-radio' )
5021				.filter( function( i, x ) {
5022					return $( x ).val() === el.data( 'repeater-init-value' );
5023				} )
5024				.prop( 'checked', true )
5025				.closest( 'li.tmcp-field-wrap' ).addClass( 'tc-active' );
5026		} else {
5027			clone.find( '.tm-epo-field' ).val( el.data( 'repeater-init-value' ) );
5028		}
5029
5030		if ( ! cloneUl.is( '.tm-element-ul-checkbox' ) && ! cloneUl.is( '.tm-element-ul-radio' ) ) {
5031			clone.find( '.tm-epo-field' ).val( el.data( 'repeater-init-value' ) );
5032		}
5033
5034		el.data( 'tc-repeater-init', el.data( 'tc-repeater-init' ) + 1 );
5035
5036		return [ clone, repeaterLast, repeaterLastUL ];
5037	}
5038
5039	function repeaterAddAfter( epoObject, clone, repeaterLast, repeaterLastUL, doevents ) {
5040		var cloneUl = clone.find( '.tmcp-ul-wrap' );
5041
5042		if ( cloneUl.is( '.tm-element-ul-range' ) ) {
5043			clone.find( '.tm-range-picker' ).removeData( 'tc-picker-init' ).attr( 'class', 'tm-range-picker' ).html( '' );
5044			setRangePickers( clone );
5045		}
5046		if ( cloneUl.is( '.tm-element-ul-date, .tm-element-ul-time' ) ) {
5047			tm_set_datepicker( repeaterLastUL );
5048			tm_set_datepicker( cloneUl );
5049		}
5050		if ( cloneUl.is( '.tm-element-ul-color' ) ) {
5051			tm_set_color_pickers( repeaterLastUL );
5052			tm_set_color_pickers( cloneUl );
5053		}
5054		clone.find( '.tm-tooltip' ).removeData( 'tctooltip' ).removeData( 'tm-has-tm-tip' );
5055		$.tcToolTip( clone.find( '.tm-tooltip' ) );
5056
5057		//  apply specific field rules
5058		clone.find( '.tm-epo-field' )
5059			.removeData( 'addedtcEpoBeforeOptionPriceCalculation' )
5060			.each( function( y, elc ) {
5061				var element = $( elc );
5062				field_is_active( element, false, true );
5063				if ( element.is( '.tcenabled' ) ) {
5064					tm_element_epo_rules( epoObject, element );
5065				}
5066				element.on( 'tc_element_epo_rules', function() {
5067					tm_element_epo_rules( epoObject, element );
5068				} );
5069			} );
5070		if ( ! doevents ) {
5071			return;
5072		}
5073		if ( cloneUl.is( '.tm-element-ul-checkbox' ) ) {
5074			clone
5075				.find( '.tm-epo-field.tmcp-checkbox' )
5076				.filter( ':checked' )
5077				.trigger( 'change.cpf' );
5078		} else if ( cloneUl.is( '.tm-element-ul-radio' ) ) {
5079			clone
5080				.find( '.tm-epo-field.tmcp-radio' )
5081				.filter( ':checked' )
5082				.trigger( 'change.cpf' );
5083		} else {
5084			clone.find( '.tm-epo-field' ).trigger( 'change.cpf' );
5085		}
5086	}
5087
5088	function repeaterDelete( elementInnerWrap, repeaterElement, repeaterObj, $this ) {
5089		var cpf = elementInnerWrap.closest( '.cpf-element' );
5090		var minRows = cpf.data( 'repeater-min-rows' );
5091		var rows = elementInnerWrap.find( '.tc-repeater-element' ).length;
5092		var repeaterElementIndex = repeaterElement.index();
5093		var message;
5094
5095		if ( minRows ) {
5096			if ( rows <= minRows ) {
5097				if ( $this ) {
5098					message = '<div class="tm-error-repeater tm-error tc-cell tcwidth-100">' + $.tc_validator.messages.repeaterminrows( minRows ) + '</div>';
5099					$this.tcToolTip( { tip: message, onetime: true, trigger: true, tipclass: 'tc-error' } );
5100				}
5101				return false;
5102			}
5103		}
5104		if ( rows === 1 ) {
5105			return;
5106		}
5107		if ( rows === 2 ) {
5108			elementInnerWrap.find( '.tc-repeater-delete' ).addClass( 'tc-hidden' );
5109		}
5110		if ( repeaterObj.is( '.tc-repeater-add' ) ) {
5111			repeaterObj.closest( '.tc-repeater-wrap' ).removeClass( 'tc-hidden' );
5112		}
5113		repeaterElement.remove();
5114		repeaterObj.data( 'tc-repeater-init', repeaterObj.data( 'tc-repeater-init' ) - 1 );
5115		if ( repeaterElementIndex + 1 === rows ) {
5116			return;
5117		}
5118		elementInnerWrap.find( '.tc-repeater-element' )
5119			.toArray()
5120			.forEach( function( clone, index ) {
5121				clone = $( clone );
5122				clone.find( '.tm-epo-field' ).attr( 'id', function( i, value ) {
5123					return value.replace( /\_\d+$/g, '' ) + ( ( index !== 0 ) ? '_' + index : '' );
5124				} );
5125				clone.find( '[data-for]' ).attr( 'data-for', function( i, value ) {
5126					return value.replace( /\_\d+$/g, '' ) + ( ( index !== 0 ) ? '_' + index : '' );
5127				} );
5128				clone.find( '[for]' ).attr( 'for', function( i, value ) {
5129					return value.replace( /\_\d+$/g, '' ) + ( ( index !== 0 ) ? '_' + index : '' );
5130				} );
5131				clone.find( '[data-field-id]' ).attr( 'data-field-id', function( i, value ) {
5132					return value.replace( /\_\d+$/g, '' ) + ( ( index !== 0 ) ? '_' + index : '' );
5133				} );
5134				clone.find( '[data-tm-date]' ).attr( 'data-tm-date', function( i, value ) {
5135					return value.replace( /\_\d+$/g, '' ) + ( ( index !== 0 ) ? '_' + index : '' );
5136				} );
5137				clone.find( '.tm-epo-field' ).attr( 'name', function( i, value ) {
5138					return value.replace( /\[\d+\]/g, '[' + index + ']' );
5139				} );
5140				clone.find( '.tm-qty' ).attr( 'name', function( i, value ) {
5141					return value.replace( /\[\d+\]/g, '[' + index + ']' );
5142				} );
5143				clone.find( '.tmcp-date-select' ).attr( 'name', function( i, value ) {
5144					return value.replace( /\[\d+\]/g, '[' + index + ']' );
5145				} );
5146			} );
5147	}
5148
5149	function tm_set_repeaters( obj, epoObject ) {
5150		var currentCart;
5151		var qtyElement;
5152		if ( ! obj ) {
5153			return;
5154		}
5155		obj = $( obj );
5156
5157		if ( obj.length ) {
5158			currentCart = epoObject.main_cart;
5159			qtyElement = getQtyElement( currentCart );
5160			qtyElement = $.epoAPI.applyFilter( 'qtyElementForRepeaterQuantity', qtyElement, {
5161				epo: epoObject,
5162				currentCart: currentCart,
5163				obj: obj,
5164				qtyElement: qtyElement
5165			} );
5166			obj.find( '.tc-repeater-quantity' )
5167				.toArray()
5168				.forEach( function( repeater, qx ) {
5169					var el = $( repeater );
5170					var tmEpoField;
5171					var repeaterElement;
5172					var length;
5173
5174					if ( el.data( 'tc-repeater-init' ) ) {
5175						return;
5176					}
5177					repeaterElement = el.find( '.tc-repeater-element' );
5178					length = repeaterElement.length;
5179					tmEpoField = repeaterElement.first().find( '.tm-epo-field' );
5180					if ( tmEpoField.is( ':checkbox' ) ) {
5181						el.data( 'repeater-init-value',
5182							tmEpoField.filter( ':checked' ).toArray().map( function( x ) {
5183								return $( x ).val();
5184							} ) );
5185					} else if ( tmEpoField.is( ':radio' ) ) {
5186						el.data( 'repeater-init-value', tmEpoField.filter( ':checked' ).val() );
5187					} else {
5188						el.data( 'repeater-init-value', tmEpoField.val() );
5189					}
5190					el.data( 'tc-repeater-init', length );
5191					el.data( 'tc-repeater-id', tmEpoField.attr( 'id' ) );
5192					el.data( 'tc-repeater-name', tmEpoField.attr( 'name' ) );
5193
5194					if ( qtyElement.length ) {
5195						qtyElement
5196							.off( 'change.r' + qx + 'cpf input.r' + qx + 'cpf' )
5197							.on( 'change.r' + qx + 'cpf input.r' + qx + 'cpf', function( event ) {
5198								var field = $( this );
5199								var prevValue = field.data( 'tm-prev-value' );
5200								var value = $.epoAPI.applyFilter( 'qtyElementForRepeaterQuantityValue', field.val(), {
5201									epo: epoObject,
5202									currentCart: currentCart,
5203									obj: obj,
5204									qtyElement: qtyElement,
5205									field: field
5206								} );
5207								var difference = value - prevValue;
5208								var elementInnerWrap;
5209								var thisRepeaterElement;
5210								var i;
5211								var ele;
5212								var cloned;
5213								var repeaterLast;
5214								var repeaterLastUL;
5215								if ( prevValue === undefined ) {
5216									prevValue = value - 1;
5217									difference = value - prevValue;
5218								}
5219								if ( event.isTrigger !== undefined ) {
5220									prevValue = el.find( '.tc-element-inner-wrap' ).find( '.tc-repeater-element' ).length;
5221									difference = value - prevValue;
5222								}
5223								if ( difference === 0 ) {
5224									return;
5225								}
5226								elementInnerWrap = el.find( '.tc-element-inner-wrap' );
5227								field.data( 'tm-prev-value', $.epoAPI.applyFilter( 'qtyElementForRepeaterQuantity_tm-prev-value', field.val(), {
5228									epo: epoObject,
5229									currentCart: currentCart,
5230									obj: obj,
5231									qtyElement: qtyElement,
5232									field: field
5233								} ) );
5234								if ( difference > 0 ) {
5235									thisRepeaterElement = elementInnerWrap.find( '.tc-repeater-element' ).eq( value - 1 );
5236									if ( thisRepeaterElement.length ) {
5237										return;
5238									}
5239									for ( i = 0; i < difference; i++ ) {
5240										cloned = repeaterAdd( el, elementInnerWrap );
5241										if ( cloned ) {
5242											if ( ele ) {
5243												ele = ele.add( cloned[ 0 ] );
5244											} else {
5245												ele = cloned[ 0 ];
5246											}
5247											if ( i === 0 ) {
5248												repeaterLast = cloned[ 1 ];
5249												repeaterLastUL = cloned[ 2 ];
5250											}
5251										}
5252									}
5253									if ( ele ) {
5254										ele.appendTo( elementInnerWrap.find( '.tc-element-container' ) );
5255										repeaterAddAfter( epoObject, ele, repeaterLast, repeaterLastUL );
5256									}
5257								} else {
5258									for ( i = value - difference; i > value; i -= 1 ) {
5259										thisRepeaterElement = elementInnerWrap.find( '.tc-repeater-element' ).eq( i - 1 );
5260										repeaterDelete( elementInnerWrap, thisRepeaterElement, el );
5261									}
5262								}
5263								currentCart.trigger( {
5264									type: 'tm-epo-update',
5265									norules: 2
5266								} );
5267							} );
5268					}
5269				} );
5270
5271			obj.find( '.tc-repeater-add' )
5272				.toArray()
5273				.forEach( function( repeater ) {
5274					var el = $( repeater );
5275					var tmEpoField;
5276					var elementInnerWrap;
5277					var repeaterElement;
5278					var length;
5279					if ( el.data( 'tc-repeater-init' ) ) {
5280						return;
5281					}
5282					elementInnerWrap = el.closest( '.tc-element-inner-wrap' );
5283					repeaterElement = elementInnerWrap.find( '.tc-repeater-element' );
5284					length = repeaterElement.length;
5285					tmEpoField = repeaterElement.first().find( '.tm-epo-field' );
5286					if ( elementInnerWrap.find( '.tc-repeater-element' ).length > 1 ) {
5287						elementInnerWrap.find( '.tc-repeater-delete' ).removeClass( 'tc-hidden' );
5288					}
5289					if ( tmEpoField.is( ':checkbox' ) ) {
5290						el.data( 'repeater-init-value',
5291							tmEpoField.filter( ':checked' ).toArray().map( function( x ) {
5292								return $( x ).val();
5293							} ) );
5294					} else if ( tmEpoField.is( ':radio' ) ) {
5295						el.data( 'repeater-init-value', tmEpoField.filter( ':checked' ).val() );
5296					} else {
5297						el.data( 'repeater-init-value', tmEpoField.val() );
5298					}
5299					el.data( 'tc-repeater-init', length );
5300					el.data( 'tc-repeater-id', tmEpoField.attr( 'id' ) );
5301					el.data( 'tc-repeater-name', tmEpoField.attr( 'name' ) );
5302
5303					el.on( 'click.repeater', function() {
5304						var ele = repeaterAdd( el, elementInnerWrap );
5305						if ( ele ) {
5306							ele[ 0 ].appendTo( elementInnerWrap.find( '.tc-element-container' ) );
5307							repeaterAddAfter( epoObject, ele[ 0 ], ele[ 1 ], ele[ 2 ], true );
5308						}
5309					} );
5310				} );
5311
5312			obj.find( '.tc-repeater-delete .delete' ).on( 'click', function() {
5313				var $this = $( this );
5314				var elementInnerWrap = $this.closest( '.tc-element-inner-wrap' );
5315				var repeaterElement = $this.closest( '.tc-repeater-element' );
5316				repeaterDelete( elementInnerWrap, repeaterElement, elementInnerWrap.find( '.tc-repeater-add' ), $this );
5317			} );
5318		}
5319	}
5320
5321	function tm_set_color_pickers( obj ) {
5322		if ( ! obj ) {
5323			return;
5324		}
5325		obj = $( obj ).find( '.tm-color-picker' );
5326		if ( obj.length ) {
5327			obj.spectrum( {
5328				type: 'color',
5329				theme: 'epo',
5330				showButtons: true,
5331				allowEmpty: true,
5332				showInitial: true,
5333				showInput: true,
5334				clickoutFiresChange: false,
5335				chooseText: TMEPOJS.closeText,
5336				cancelText: TMEPOJS.i18n_cancel
5337			} );
5338			obj.spectrum( 'enable' );
5339		}
5340	}
5341
5342	function tm_set_lightbox( obj ) {
5343		if ( ! obj ) {
5344			return;
5345		}
5346		if ( $( obj ).length ) {
5347			// document ready
5348			$( function() {
5349				$( obj ).tclightbox();
5350			} );
5351		}
5352	}
5353
5354	function has_active_changes_product_image( field ) {
5355		var uic = field.closest( '.tmcp-field-wrap' ).find( 'label img' );
5356		var src = $( uic ).first().attr( 'data-original' );
5357
5358		if ( field.is( 'select.tm-product-image' ) ) {
5359			field = field.children( 'option:selected' );
5360		}
5361
5362		if ( ! src ) {
5363			src = $( uic ).first().attr( 'src' );
5364		}
5365		if ( ! src ) {
5366			src = field.attr( 'data-image' );
5367		}
5368		if ( field.attr( 'data-imagep' ) ) {
5369			src = field.attr( 'data-imagep' );
5370		}
5371		if ( src ) {
5372			return true;
5373		}
5374
5375		return false;
5376	}
5377
5378	function tm_set_upload_fields( epoObject ) {
5379		var field;
5380		var dT;
5381		var name;
5382		var file;
5383		var selector = epoObject.is_associated
5384			? epoObject.this_epo_container.find( '.tm-epo-field.tmcp-upload' )
5385			: epoObject.this_epo_container.find( '.tm-epo-field.tmcp-upload' ).not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector + ' .tm-epo-field.tmcp-upload' );
5386
5387		try {
5388			selector
5389				.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector + ' .tm-epo-field.tmcp-upload' )
5390				.toArray()
5391				.forEach( function( el ) {
5392					var dataFiles;
5393					var dataFilename;
5394					file = [];
5395					field = $( el );
5396					if ( field.attr( 'data-file' ) === '' ) {
5397						return false;
5398					}
5399					dataFiles = field.attr( 'data-file' ).split( '|' );
5400					if ( dataFiles.length === 0 ) {
5401						return false;
5402					}
5403					if ( ClipboardEvent || DataTransfer ) {
5404						dT = new ClipboardEvent( '' ).clipboardData || new DataTransfer();
5405					}
5406					dataFiles.forEach( function( dataFile ) {
5407						dataFilename = $.epoAPI.util.basename( dataFile );
5408						if ( ClipboardEvent || DataTransfer ) {
5409							dT.items.add( new File( [ dataFile ], dataFilename ) );
5410						}
5411						file.push( dataFile );
5412					} );
5413					if ( dT ) {
5414						el.files = dT.files;
5415					}
5416					file = file.join( '|' );
5417					name = field.attr( 'name' );
5418					field.trigger( 'tcupload' );
5419					field.after( '<input type="hidden" class="tmcp-upload-hidden" name="' + name + '" value="' + file + '">' );
5420					field.removeAttr( 'data-file' );
5421				} );
5422		} catch ( err ) {
5423			window.console.log( err );
5424			$( '.tm-epo-field.tmcp-upload' ).not( '.tm-multiple-file-upload' ).addClass( 'tc-nodt' );
5425			errorObject = err;
5426		}
5427	}
5428
5429	function tm_set_upload_rules( epoObject ) {
5430		var epoEventId = epoObject.epoEventId;
5431		var this_epo_container = epoObject.this_epo_container;
5432
5433		if ( TMEPOJS.tm_epo_upload_popup === 'yes' ) {
5434			$.tcepo.formSubmitEvents[ epoEventId ][ $.tcepo.formSubmitEvents[ epoEventId ].length ] = {
5435				trigger: function() {
5436					return true;
5437				},
5438				on_true: function() {
5439					var upload_fields = this_epo_container.data( 'num_uploads' );
5440					var thisPopup;
5441					var ajaxSuccessFunc;
5442					if ( upload_fields && Object.keys( upload_fields ).length ) {
5443						thisPopup = $.tcFloatBox( {
5444							fps: 1,
5445							ismodal: true,
5446							refresh: 'fixed',
5447							width: '50%',
5448							height: '300px',
5449							classname: 'flasho tc-wrapper',
5450							data: $.epoAPI.template.html( tcAPI.templateEngine.tc_upload_messages, {
5451								files: upload_fields,
5452								title: TMEPOJS.i18n_uploading_files,
5453								message: TMEPOJS.i18n_uploading_message
5454							} )
5455						} );
5456						ajaxSuccessFunc = function() {
5457							thisPopup.destroy();
5458							jDocument.off( 'ajaxSuccess', ajaxSuccessFunc );
5459						};
5460						jDocument.on( 'ajaxSuccess', ajaxSuccessFunc );
5461					}
5462
5463					return true;
5464				},
5465				on_false: function() {
5466					return true;
5467				}
5468			};
5469		}
5470	}
5471
5472	function tm_set_checkboxes_rules( epoObject ) {
5473		var this_epo_container = epoObject.this_epo_container;
5474		var main_product = epoObject.main_product;
5475		var epoEventId = epoObject.epoEventId;
5476		var limit_cont = this_epo_container.find( '.tm-limit' );
5477		var exactlimit_cont = this_epo_container.find( '.tm-exactlimit' );
5478		var minimumlimit_cont = this_epo_container.find( '.tm-minimumlimit' );
5479
5480		// Limit checkbox selection
5481		this_epo_container.on( 'change.cpflimit', 'input.tm-epo-field.tmcp-checkbox', function() {
5482			var $this = $( this );
5483			tm_limit_c_selection( $this, true );
5484			tm_exact_c_selection( $this, true );
5485		} );
5486		if ( limit_cont.length ) {
5487			tm_check_limit_cont( limit_cont, main_product, epoEventId );
5488		}
5489
5490		// Exact value checkbox check (Todo:check for isvisible)
5491		if ( exactlimit_cont.length ) {
5492			tm_check_exactlimit_cont( exactlimit_cont, main_product, epoEventId );
5493		}
5494
5495		// Minimum number checkbox check (Todo:check for isvisible)
5496		if ( minimumlimit_cont.length ) {
5497			tm_check_minimumlimit_cont( minimumlimit_cont, epoEventId );
5498		}
5499	}
5500
5501	function tm_theme_specific_actions( epoObject ) {
5502		var this_epo_container = epoObject.this_epo_container;
5503		var theme_name = TMEPOJS.theme_name;
5504		var all_epo_selects;
5505		var blaszok_selects;
5506
5507		if ( theme_name ) {
5508			theme_name = theme_name.toLowerCase();
5509			all_epo_selects = this_epo_container.find( 'select' );
5510
5511			switch ( theme_name ) {
5512				case 'flatsome':
5513				case 'flatsome-child':
5514				case 'flatsome child':
5515					all_epo_selects.wrap( '<div class="custom select-wrapper"/>' );
5516					break;
5517
5518				case 'avada':
5519				case 'avada-child':
5520				case 'avada child':
5521					all_epo_selects.wrap( '<div class="avada-select-parent tm-select-parent"></div>' );
5522					$( '<div class="select-arrow">&#xe61f;</div>' ).appendTo( this_epo_container.find( '.tm-select-parent' ) );
5523					if ( window.calc_select_arrow_dimensions ) {
5524						window.calc_select_arrow_dimensions();
5525						jWindow.on( 'tmsectionpoplink cpflogicdone', function() {
5526							window.calc_select_arrow_dimensions();
5527						} );
5528					} else if ( window.calcSelectArrowDimensions ) {
5529						window.calcSelectArrowDimensions();
5530						jWindow.on( 'tmsectionpoplink cpflogicdone', function() {
5531							window.calcSelectArrowDimensions();
5532						} );
5533					}
5534					break;
5535
5536				case 'bazar':
5537				case 'bazar-child':
5538				case 'bazar child':
5539					all_epo_selects.wrap( '<div class="tm-select-wrapper select-wrapper"/>' );
5540					break;
5541
5542				case 'blaszok':
5543				case 'blaszok-child':
5544				case 'blaszok child':
5545					blaszok_selects = function() {
5546						setTimeout( function() {
5547							$( '.tm-extra-product-options select' )
5548								.not( '.hasCustomSelect' )
5549								.filter( ':visible' )
5550								.each( function() {
5551									if ( ! $( this ).is( '.mpcthSelect' ) ) {
5552										$( this ).width( $( this ).outerWidth() );
5553										$( this ).customSelect( { customClass: 'mpcthSelect' } );
5554									}
5555								} );
5556						}, 100 );
5557					};
5558					jWindow.on( 'cpflogicrun', function() {
5559						blaszok_selects();
5560					} );
5561					jWindow.on( 'epo_options_visible', function() {
5562						blaszok_selects();
5563					} );
5564
5565					break;
5566
5567				case 'handmade':
5568				case 'handmade child theme':
5569					$( '.tm-owl-slider.tcowl-carousel' ).addClass( 'manual' );
5570					break;
5571			}
5572
5573			jWindow.trigger( 'tm-theme-specific-actions', {
5574				epo: {
5575					theme_name: theme_name,
5576					all_epo_selects: all_epo_selects
5577				}
5578			} );
5579		}
5580
5581		// Fix added +/- quantity button on most themes.
5582		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() {
5583			$( this ).closest( '.quantity' ).find( tcAPI.qtySelector ).trigger( 'change.cpf' );
5584		} );
5585	}
5586
5587	function tm_custom_variations( epoObject, form, item_id, $main_product, $epo_holder ) {
5588		var epoEventId = epoObject.epoEventId;
5589		var variation_id_selector = "input[name^='variation_id']";
5590		var tm_epo_variation_section;
5591		var li_variations;
5592		var composite_load_test;
5593		var form_event;
5594		var type;
5595		var name;
5596		var selector;
5597		var func;
5598		var i;
5599		var eventName = epoObject.is_associated ? 'tc_variation_form.tmlogic' : 'wc_variation_form.tmlogic';
5600		var eventNamePrefix = epoObject.is_associated ? 'tc_' : '';
5601		var variationsForm = epoObject.variations_form;
5602		var variationsTable = epoObject.is_associated ? variationsForm.find( '.tc-epo-element-variations' ) : variationsForm.find( '.variations' );
5603		var resetSelector = epoObject.is_associated ? '.tc-epo-element-variable-reset-variations' : '.reset_variations';
5604
5605		variationsForm.attr( 'data-epo_id', epoObject.epo_id );
5606
5607		if ( form.find( 'input.variation_id' ).length > 0 ) {
5608			variation_id_selector = 'input.variation_id';
5609		}
5610		if ( $epo_holder.find( '.tm-epo-variation-element' ).length || $epo_holder.data( 'tm-epo-variation-element' ) ) {
5611			tm_epo_variation_section = $epo_holder.find( '.tm-epo-variation-section' ).first();
5612			tm_epo_variation_section.find( '.cpf-type-variations' ).attr( 'data-epo_id', epoObject.epo_id ).attr( 'data-product_id', variationsForm.attr( 'data-product_id' ) );
5613
5614			$epo_holder.data( 'tm-epo-variation-element', tm_epo_variation_section.find( '.tm-epo-variation-element' ) );
5615
5616			if ( item_id && item_id !== 'main' && ! epoObject.is_associated ) {
5617				// on composite
5618
5619				variationsForm = epoObject.form;
5620				variationsTable = variationsForm.find( '.composite_component[data-item_id="' + item_id + '"]' ).find( '.variations' );
5621				variationsForm.attr( 'data-epo_id', epoObject.epo_id );
5622
5623				if ( variationsTable.length === 0 ) {
5624					return;
5625				}
5626
5627				li_variations = tm_epo_variation_section.closest( 'li.tm-extra-product-options-field' );
5628				if ( ! tm_epo_variation_section.is( '.tm-hidden' ) ) {
5629					variationsTable.hide();
5630				}
5631
5632				variationsTable.after( tm_epo_variation_section.addClass( 'tm-extra-product-options nopadding' ) );
5633				if ( li_variations.is( ':empty' ) ) {
5634					li_variations.hide();
5635				}
5636
5637				if ( ! tm_epo_variation_section.is( '.section_popup' ) ) {
5638					tm_epo_variation_section.removeClass( 'tc-cell' );
5639					tm_epo_variation_section.wrap( "<div class='tc-styled-variations'></div>" );
5640				} else {
5641					tm_epo_variation_section.wrap( "<div class='tc-styled-variations tc-row'></div>" );
5642				}
5643
5644				composite_load_test = false;
5645				form.off( eventName ).on( eventName, function() {
5646					composite_load_test = true;
5647					variationsForm.on( 'click.tmlogic', '.reset_variations', function() {
5648						tm_epo_variation_section.find( 'select.tm-epo-variation-element' ).val( '' ).children( 'option' ).prop( 'disabled', false ).show();
5649						tm_epo_variation_section.find( '.tm-epo-variation-element' ).prop( 'disabled', false ).removeClass( 'tm-disabled' ).prop( 'checked', false ).closest( 'li' ).show();
5650						jWindow.trigger( 'tmlazy' );
5651						tm_epo_variation_section.find( '.tm-epo-variation-element' ).trigger( 'tm_trigger_product_image' );
5652						tm_epo_variation_section.find( 'li' ).removeClass( 'tc-active tm-attribute-disabled' ).css( 'opacity', '' );
5653					} );
5654
5655					// Disable option fields that are unavaiable for current set of attributes
5656					form.off( 'woocommerce_update_variation_values_tmlogic' ).on( 'woocommerce_update_variation_values_tmlogic', function() {
5657						tm_custom_variations_update( form, epoObject );
5658					} );
5659					for ( i = 0; i < lateVariationEvent.length; i += 1 ) {
5660						form_event = lateVariationEvent[ i ];
5661						type = typeof form_event;
5662						if ( type === 'object' ) {
5663							name = typeof form_event.name === 'string' || false;
5664							selector = typeof form_event.selector === 'string' || false;
5665							func = typeof form_event.func === 'function' || false;
5666							if ( name && func ) {
5667								if ( selector === "input[name='variation_id']" ) {
5668									selector = variation_id_selector;
5669								}
5670								if ( form_event.selector ) {
5671									form.data( 'tm-styled-variations', 1 )
5672										.off( eventNamePrefix + form_event.name + i, selector )
5673										.on( eventNamePrefix + form_event.name + i, selector, form_event.func );
5674								} else {
5675									form.data( 'tm-styled-variations', 1 )
5676										.off( eventNamePrefix + form_event.name + i )
5677										.on( eventNamePrefix + form_event.name + i, form_event.func );
5678								}
5679							}
5680						}
5681					}
5682					lateVariationEvent = [];
5683					tm_epo_variation_section.find( '.tm-epo-variation-element:not(.tm-hidden .tm-epo-variation-element)' ).last().trigger( 'tm_epo_variation_element_change' );
5684				} );
5685				// document ready
5686				$( function() {
5687					if ( composite_load_test === false ) {
5688						form.trigger( eventName );
5689					}
5690				} );
5691			} else {
5692				if ( tm_epo_variation_section.length ) {
5693					if ( ! tm_epo_variation_section.is( '.tm-hidden' ) ) {
5694						variationsTable.hide();
5695					}
5696
5697					li_variations = tm_epo_variation_section.closest( 'li.tm-extra-product-options-field' );
5698
5699					variationsTable.after( tm_epo_variation_section.addClass( 'tm-extra-product-options nopadding' ) );
5700					if ( li_variations.is( ':empty' ) ) {
5701						li_variations.hide();
5702					}
5703
5704					if ( ! tm_epo_variation_section.is( '.section_popup' ) ) {
5705						tm_epo_variation_section.removeClass( 'tc-cell' );
5706						tm_epo_variation_section.wrap( "<div class='tc-styled-variations'></div>" );
5707					} else {
5708						tm_epo_variation_section.wrap( "<div class='tc-styled-variations tc-row'></div>" );
5709					}
5710
5711					variationsForm.off( 'click.tmlogic', resetSelector ).on( 'click.tmlogic', resetSelector, function() {
5712						tm_epo_variation_section.find( 'select.tm-epo-variation-element' ).val( '' ).children( 'option' ).prop( 'disabled', false ).show();
5713						tm_epo_variation_section.find( '.tm-epo-variation-element' ).prop( 'disabled', false ).removeClass( 'tm-disabled' ).prop( 'checked', false ).closest( 'li' ).show();
5714						jWindow.trigger( 'tmlazy' );
5715						tm_epo_variation_section.find( '.tm-epo-variation-element' ).trigger( 'tm_trigger_product_image' );
5716						tm_epo_variation_section.find( 'li' ).removeClass( 'tc-active tm-attribute-disabled' ).css( 'opacity', '' );
5717					} );
5718				}
5719
5720				// Disable option fields that are unavaiable for current set of attributes
5721				variationsForm.off( 'woocommerce_update_variation_values_tmlogic' ).on( 'woocommerce_update_variation_values_tmlogic', function() {
5722					tm_custom_variations_update( variationsForm, epoObject );
5723				} );
5724
5725				for ( i = 0; i < lateVariationEvent.length; i += 1 ) {
5726					form_event = lateVariationEvent[ i ];
5727					type = typeof form_event;
5728					if ( type === 'object' ) {
5729						name = typeof form_event.name === 'string' || false;
5730						selector = typeof form_event.selector === 'string' || false;
5731						func = typeof form_event.func === 'function' || false;
5732						if ( name && func ) {
5733							if ( selector === "input[name='variation_id']" ) {
5734								selector = variation_id_selector;
5735							}
5736							if ( form_event.selector ) {
5737								variationsForm
5738									.data( 'tm-styled-variations', 1 )
5739									.off( eventNamePrefix + form_event.name + i, selector )
5740									.on( eventNamePrefix + form_event.name + i, selector, form_event.func );
5741							} else {
5742								variationsForm
5743									.data( 'tm-styled-variations', 1 )
5744									.off( eventNamePrefix + form_event.name + i )
5745									.on( eventNamePrefix + form_event.name + i, form_event.func );
5746							}
5747						}
5748					}
5749				}
5750				lateVariationEvent = [];
5751				tm_epo_variation_section.find( '.tm-epo-variation-element:not(.tm-hidden .tm-epo-variation-element)' ).last().trigger( 'tm_epo_variation_element_change' );
5752			}
5753
5754			// global event for custom variations
5755			$.tcepo.formSubmitEvents[ epoEventId ][ $.tcepo.formSubmitEvents[ epoEventId ].length ] = {
5756				trigger: function() {
5757					return true;
5758				},
5759				on_true: function() {
5760					tm_epo_variation_section.find( '.tm-epo-variation-element' ).attr( 'disabled', 'disabled' );
5761					return true;
5762				},
5763				on_false: function() {
5764					tm_epo_variation_section.find( '.tm-epo-variation-element' ).prop( 'disabled', false );
5765				}
5766			};
5767
5768			$( document.body ).on( 'added_to_cart', function() {
5769				tm_epo_variation_section.find( '.tm-epo-variation-element' ).prop( 'disabled', false );
5770			} );
5771		}
5772	}
5773
5774	function repopulate_backup_image_atts( img, product_element ) {
5775		var $gallery_img = product_element.find( '.flex-control-nav li:eq(0) img' );
5776		var $gallery_wrapper = product_element.find( '.woocommerce-product-gallery__wrapper ' );
5777		var $product_img_wrap = $gallery_wrapper.find( '.woocommerce-product-gallery__image, .woocommerce-product-gallery__image--placeholder' ).eq( 0 );
5778		var $product_img = img;
5779		var $product_link = img.closest( 'a' );
5780
5781		$product_img.attr( 'data-o_' + 'src', $.tc_product_image_store[ 0 ].src );
5782		$product_img.attr( 'data-o_' + 'srcset', $.tc_product_image_store[ 0 ].srcset );
5783		$product_img.attr( 'data-o_' + 'sizes', $.tc_product_image_store[ 0 ].sizes );
5784		$product_img.attr( 'data-o_' + 'title', $.tc_product_image_store[ 0 ].title );
5785		$product_img.attr( 'data-o_' + 'alt', $.tc_product_image_store[ 0 ].alt );
5786		$product_img.attr( 'data-o_' + 'data-src', $.tc_product_image_store[ 0 ][ 'data-src' ] );
5787		$product_img.attr( 'data-o_' + 'data-large_image', $.tc_product_image_store[ 0 ][ 'data-large_image' ] );
5788		$product_img.attr( 'data-o_' + 'data-large_image_width', $.tc_product_image_store[ 0 ][ 'data-large_image_width' ] );
5789		$product_img.attr( 'data-o_' + 'data-large_image_height', $.tc_product_image_store[ 0 ][ 'data-large_image_height' ] );
5790		$product_img_wrap.attr( 'data-o_' + 'data-thumb', $.tc_product_image_store[ 1 ][ 'data-thumb' ] );
5791		if ( $.tc_product_image_store[ 2 ] ) {
5792			$gallery_img.attr( 'data-o_' + 'src', $.tc_product_image_store[ 2 ].src );
5793		}
5794
5795		$product_link.attr( 'data-o_' + 'href', $.tc_product_image_store[ 3 ].href );
5796		$product_link.attr( 'data-o_' + 'title', $.tc_product_image_store[ 3 ].title );
5797	}
5798
5799	function reset_saved_image( img, product_element ) {
5800		var $gallery_img = product_element.find( '.flex-control-nav li:eq(0) img' );
5801		var $gallery_wrapper = product_element.find( '.woocommerce-product-gallery__wrapper ' );
5802		var $product_img_wrap = $gallery_wrapper.find( '.woocommerce-product-gallery__image, .woocommerce-product-gallery__image--placeholder' ).eq( 0 );
5803		var $product_img = img;
5804		var $product_link = img.closest( 'a' );
5805
5806		// backup current product image attributes
5807		if ( ! $.isEmptyObject( $.tc_product_image ) ) {
5808			$.tc_product_image_store = $.tc_pre_populate_store();
5809			$.tc_product_image_store = $.tc_maybe_copy_object_values( $.tc_product_image_store, $.tc_product_image );
5810		} else {
5811			$.tc_product_image_store = $.tc_populate_store( img, product_element );
5812		}
5813
5814		$product_img.tc_update_attr( 'src', 0 );
5815		$product_img.tc_update_attr( 'srcset', 0 );
5816		$product_img.tc_update_attr( 'sizes', 0 );
5817		$product_img.tc_update_attr( 'title', 0 );
5818		$product_img.tc_update_attr( 'alt', 0 );
5819		$product_img.tc_update_attr( 'data-src', 0 );
5820		$product_img.tc_update_attr( 'data-large_image', 0 );
5821		$product_img.tc_update_attr( 'data-large_image_width', 0 );
5822		$product_img.tc_update_attr( 'data-large_image_height', 0 );
5823		$product_img_wrap.tc_update_attr( 'data-thumb', 1 );
5824		$gallery_img.tc_update_attr( 'src', 2 );
5825
5826		$product_link.tc_update_attr( 'href', 3 );
5827		$product_link.tc_update_attr( 'title', 3 );
5828	}
5829
5830	function image_update( data, img, product_element ) {
5831		var $gallery_img = product_element.find( '.flex-control-nav li:eq(0) img' );
5832		var $gallery_wrapper = product_element.find( '.woocommerce-product-gallery__wrapper ' );
5833		var $product_img_wrap = $gallery_wrapper.find( '.woocommerce-product-gallery__image, .woocommerce-product-gallery__image--placeholder' ).eq( 0 );
5834		var $product_img = img;
5835		var $product_link = img.closest( 'a' );
5836
5837		if ( data && data.image_link && data.image_link && data.image_link.length > 1 ) {
5838			if ( data.full_src === null || data.full_src === '' ) {
5839				data.full_src = data.image_link;
5840			}
5841			if ( data.full_src_w === null || data.full_src_w === '' ) {
5842				data.full_src_w = $product_img.attr( 'data-large_image_width' );
5843			}
5844			if ( data.full_src_h === null || data.full_src_h === '' ) {
5845				data.full_src_h = $product_img.attr( 'data-large_image_height' );
5846			}
5847			if ( $product_img.length ) {
5848				if ( ! data.image_srcset ) {
5849					data.image_sizes = false;
5850				}
5851				if ( ! data.image_sizes ) {
5852					data.image_srcset = false;
5853				}
5854				$product_img.tc_set_attr( 'src', data.image_link, 0 );
5855				$product_img.tc_set_attr( 'srcset', data.image_srcset, 0 );
5856				$product_img.tc_set_attr( 'sizes', data.image_sizes, 0 );
5857				$product_img.tc_set_attr( 'title', data.image_title, 0 );
5858				$product_img.tc_set_attr( 'alt', data.image_alt, 0 );
5859				$product_img.tc_set_attr( 'data-src', data.full_src, 0 );
5860				$product_img.tc_set_attr( 'data-large_image', data.full_src, 0 );
5861				$product_img.tc_set_attr( 'data-large_image_width', data.full_src_w, 0 );
5862				$product_img.tc_set_attr( 'data-large_image_height', data.full_src_h, 0 );
5863				$product_img_wrap.tc_set_attr( 'data-thumb', data.image_link, 1 );
5864			}
5865			if ( $gallery_img.length ) {
5866				$gallery_img.tc_set_attr( 'src', data.image_link, 2 );
5867			}
5868			if ( $product_link.length ) {
5869				$product_link.tc_set_attr( 'href', data.full_src, 3 );
5870				$product_link.tc_set_attr( 'title', data.image_caption, 3 );
5871			}
5872		} else {
5873			if ( $product_img.length ) {
5874				$product_img.tc_reset_attr( 'src', 0 );
5875				$product_img.tc_reset_attr( 'srcset', 0 );
5876				$product_img.tc_reset_attr( 'sizes', 0 );
5877				$product_img.tc_reset_attr( 'title', 0 );
5878				$product_img.tc_reset_attr( 'alt', 0 );
5879				$product_img.tc_reset_attr( 'data-src', 0 );
5880				$product_img.tc_reset_attr( 'data-large_image', 0 );
5881				$product_img.tc_reset_attr( 'data-large_image_width', 0 );
5882				$product_img.tc_reset_attr( 'data-large_image_height', 0 );
5883				$product_img_wrap.tc_reset_attr( 'data-thumb', 1 );
5884			}
5885			if ( $gallery_img.length ) {
5886				$gallery_img.tc_reset_attr( 'src', 2 );
5887			}
5888			if ( $product_link.length ) {
5889				$product_link.tc_reset_attr( 'href', 3 );
5890				$product_link.tc_reset_attr( 'title', 3 );
5891			}
5892		}
5893	}
5894
5895	function get_main_product_image( epoObject, product_element ) {
5896		var img;
5897
5898		if ( epoObject.is_associated ) {
5899			img = product_element.find( '.tc-product-image .wp-post-image' ).first();
5900		} else if ( TMEPOJS.tm_epo_global_product_image_selector !== '' ) {
5901			img = $( TMEPOJS.tm_epo_global_product_image_selector );
5902		} else {
5903			img = product_element.find( '.woocommerce-product-gallery__image:not(.clone), .woocommerce-product-gallery__image--placeholder:not(.clone)' ).eq( 0 ).find( '.wp-post-image' ).first();
5904			if ( img.length === 0 ) {
5905				img = product_element.find( 'a.woocommerce-main-image img, img.woocommerce-main-image,a img' ).not( '.thumbnails img,.product_list_widget img' ).first();
5906			}
5907			if ( img.length === 0 ) {
5908				img = product_element.find( 'img.wp-post-image' ).not( '.thumbnails img,.product_list_widget img' ).first();
5909			}
5910			if ( img.length === 0 ) {
5911				img = product_element.find( '.elementor-widget-wd_single_product_gallery img.wp-post-image' ).first();
5912			}
5913			if ( img.length === 0 ) {
5914				img = product_element.find( '.elementor-widget-ae-post-image .wp-post-image' ).first();
5915			}
5916			if ( img.length === 0 ) {
5917				img = $( '.woocommerce div.product div.images' ).not( '.thumbnails img,.product_list_widget img' ).first();
5918			}
5919		}
5920
5921		if ( $( img ).length > 1 ) {
5922			img = $( img ).first();
5923		}
5924
5925		return img;
5926	}
5927
5928	function get_product_element( epoObject ) {
5929		var main_product;
5930		var product_id;
5931		var product_element;
5932
5933		if ( epoObject.is_associated ) {
5934			return epoObject.main_product.closest( '.tc-epo-element-product-container' );
5935		}
5936
5937		main_product = epoObject.main_product;
5938		product_id = epoObject.product_id;
5939		product_element = main_product.closest( '#product-' + product_id );
5940
5941		if ( product_element.length <= 0 ) {
5942			product_element = main_product.closest( '.post-' + product_id );
5943		}
5944
5945		return product_element;
5946	}
5947
5948	function gallery_compatibility_actions( gallery_type, clone_image, preload_img, visible, event_data, $form, product_element ) {
5949		var gallery;
5950		var _elements;
5951		var ge;
5952		var galleryWidth;
5953		var zoomEnabled;
5954		var image;
5955		var zoom_options;
5956
5957		for ( gallery in gallery_type ) {
5958			if ( Object.prototype.hasOwnProperty.call( gallery_type, gallery ) ) {
5959				gallery = gallery_type[ gallery ];
5960
5961				if ( gallery.enabled ) {
5962					switch ( gallery.type ) {
5963						case 'yith':
5964							if ( ! clone_image ) {
5965								if ( ! visible ) {
5966									gallery.yith_wcmg_zoom.attr( 'href', gallery._yith_wcmg_default_zoom );
5967								} else {
5968									gallery.yith_wcmg_zoom.attr( 'href', gallery.yith_wcmg_default_zoom );
5969								}
5970								if ( gallery.element.data( 'yith_magnifier' ) ) {
5971									gallery.element.yith_magnifier( 'destroy' );
5972								}
5973
5974								gallery.element.yith_magnifier( window.yith_magnifier_options );
5975							} else {
5976								clone_image.attr( 'srcset', preload_img ).attr( 'src-orig', preload_img );
5977
5978								if ( gallery.element.data( 'yith_magnifier' ) ) {
5979									gallery.element.yith_magnifier( 'destroy' );
5980								}
5981								_elements = {
5982									elements: {
5983										zoom: $( '.yith_magnifier_zoom' ),
5984										zoomImage: clone_image,
5985										gallery: $( '.yith_magnifier_gallery li a' )
5986									}
5987								};
5988
5989								gallery.element.yith_magnifier( $.extend( true, {}, window.yith_magnifier_options, _elements ) );
5990							}
5991							break;
5992						case 'iosslider':
5993							setTimeout(
5994								function( g ) {
5995									g.element.iosSlider( 'update' );
5996								}.bind( null, gallery ),
5997								150
5998							);
5999							break;
6000						case 'flexslider':
6001							jWindow.trigger( 'resize' );
6002							break;
6003						case 'elevatezoom':
6004							gallery.element.each(
6005								function( g, j ) {
6006									var elevateZoom = j( this ).data( 'elevateZoom' );
6007									if ( typeof elevateZoom !== 'undefined' ) {
6008										elevateZoom.swaptheimage( g, g );
6009									}
6010								}.bind( null, preload_img, $ )
6011							);
6012							break;
6013						case 'easyzoom':
6014							gallery.element.swap( null, preload_img );
6015							break;
6016						case 'easyzoom-flatsome':
6017							gallery.element.swap( preload_img, preload_img );
6018							break;
6019						case 'woocommerce':
6020							gallery.element.flexslider( 0 );
6021							ge = gallery.element;
6022							window.setTimeout(
6023								function( g, w ) {
6024									g.trigger( 'woocommerce_gallery_init_zoom' );
6025									w.trigger( 'resize' );
6026								}.bind( null, ge, jWindow ),
6027								10
6028							);
6029							break;
6030						case 'zoom':
6031							if ( product_element ) {
6032								galleryWidth = product_element.find( '.woocommerce-product-gallery--with-images' ).width();
6033								zoomEnabled = false;
6034
6035								image = gallery.element.find( 'img.wp-post-image' );
6036								if ( image.attr( 'data-large_image_width' ) > galleryWidth ) {
6037									zoomEnabled = true;
6038								}
6039
6040								if ( zoomEnabled ) {
6041									zoom_options = {
6042										touch: false
6043									};
6044									if ( 'ontouchstart' in window ) {
6045										zoom_options.on = 'click';
6046									}
6047
6048									gallery.element.trigger( 'zoom.destroy' );
6049									gallery.element.zoom( zoom_options );
6050								} else {
6051									gallery.element.trigger( 'zoom.destroy' );
6052								}
6053							}
6054							break;
6055					}
6056				}
6057			}
6058		}
6059
6060		jWindow.trigger( 'tm_gallery_compatibility_actions', {
6061			event_data: event_data,
6062			product_element: product_element,
6063			form: $form
6064		} );
6065	}
6066
6067	function get_gallery_type( epoObject, img, product_element ) {
6068		// YITH WooCommerce Zoom Magnifier
6069		var is_yith_wcmg;
6070		var yith_wcmg;
6071		var yith_wcmg_zoom;
6072		var yith_wcmg_default_zoom;
6073		var _yith_wcmg_default_zoom;
6074		var yith_wcmg_default_image;
6075
6076		// iosslider - Touch Enabled, Responsive jQuery Horizontal Content
6077		// Slider/Carousel/Image Gallery Plugin
6078		var is_iosSlider;
6079		var is_iosSlider_element;
6080
6081		// ThemeFusion flexslider
6082		var is_flexslider;
6083		var is_flexslider_element;
6084
6085		// elevateZoom A Jquery Image Zoom Plugin
6086		var is_elevateZoom;
6087		var is_elevateZoom_obj;
6088
6089		// EasyZoom jQuery image zoom plugin
6090		var is_easyzoom;
6091		var is_easyzoom_element;
6092
6093		// new flatsome easyzoom
6094		var is_easyzoom_flatsome;
6095		var is_easyzoom_flatsome_element;
6096
6097		// WooCommerce 2.7x gallery
6098		var is_wc27_gallery;
6099		var is_wc27_gallery_element;
6100		var wc27_zoom_target;
6101		var wc_single_product_params;
6102		var zoom_target_temp;
6103
6104		// fn.zoom
6105		var is_zoom_enabled;
6106		var zoom_images;
6107		var gallery;
6108
6109		if ( epoObject.is_associated ) {
6110			return {};
6111		}
6112
6113		// YITH WooCommerce Zoom Magnifier
6114		is_yith_wcmg = false;
6115		yith_wcmg = $( '.images' );
6116		yith_wcmg_zoom = $( '.yith_magnifier_zoom' );
6117		yith_wcmg_default_zoom = yith_wcmg.find( '.yith_magnifier_zoom' ).first().attr( 'href' );
6118		_yith_wcmg_default_zoom = yith_wcmg_default_zoom;
6119		yith_wcmg_default_image = yith_wcmg.find( '.yith_magnifier_zoom img' ).first().attr( 'src' );
6120
6121		// iosslider - Touch Enabled, Responsive jQuery Horizontal Content
6122		// Slider/Carousel/Image Gallery Plugin
6123		is_iosSlider = false;
6124		is_iosSlider_element = $( '.iosSlider.product-gallery-slider,.iosSlider.product-slider' );
6125
6126		// ThemeFusion flexslider
6127		is_flexslider = false;
6128		is_flexslider_element = product_element.find( '.images .fusion-flexslider' );
6129
6130		// elevateZoom A Jquery Image Zoom Plugin
6131		is_elevateZoom = img.data( 'elevateZoom' ) || false;
6132		is_elevateZoom_obj = product_element.find( 'div.product-images .woocommerce-main-image' );
6133
6134		// EasyZoom jQuery image zoom plugin
6135		is_easyzoom = false;
6136		is_easyzoom_element = product_element.find( '.images .easyzoom' );
6137
6138		// new flatsome easyzoom
6139		is_easyzoom_flatsome = false;
6140		is_easyzoom_flatsome_element = product_element.find( '.images .easyzoom' );
6141
6142		// WooCommerce 2.7x gallery
6143		is_wc27_gallery = false;
6144		is_wc27_gallery_element = product_element.find( '.woocommerce-product-gallery' );
6145		wc27_zoom_target = false;
6146		wc_single_product_params = window.wc_single_product_params;
6147
6148		// fn.zoom
6149		is_zoom_enabled = typeof $.fn.zoom === 'function' && wc_single_product_params && wc_single_product_params.zoom_enabled;
6150		zoom_images = false;
6151
6152		if ( window.yith_magnifier_options && yith_wcmg.data( 'yith_magnifier' ) ) {
6153			is_yith_wcmg = true;
6154		}
6155
6156		if ( is_iosSlider_element.length && is_iosSlider_element.iosSlider ) {
6157			is_iosSlider = true;
6158		}
6159
6160		if ( is_flexslider_element.length && is_flexslider_element.flexslider ) {
6161			is_flexslider = true;
6162		}
6163
6164		if ( is_easyzoom_element.length && is_easyzoom_element.filter( '.images .easyzoom.first' ).data( 'easyZoom' ) ) {
6165			is_easyzoom_element = is_easyzoom_element.filter( '.images .easyzoom.first' ).data( 'easyZoom' );
6166			is_easyzoom = true;
6167		}
6168
6169		if ( ! is_easyzoom ) {
6170			is_easyzoom_flatsome_element = product_element.find( '.images .has-image-zoom .slide' );
6171			if ( is_easyzoom_flatsome_element.length && is_easyzoom_flatsome_element.filter( '.images .has-image-zoom .slide.first' ).data( 'easyZoom' ) ) {
6172				is_easyzoom_flatsome_element = is_easyzoom_flatsome_element.filter( '.images .has-image-zoom .slide.first' ).data( 'easyZoom' );
6173				is_easyzoom_flatsome = true;
6174			}
6175		}
6176
6177		if ( document.readyState === 'complete' ) {
6178			setTimeout( function() {
6179				if ( is_easyzoom_element.length && is_easyzoom_element.data( 'easyZoom' ) ) {
6180					is_easyzoom_element = is_easyzoom_element.data( 'easyZoom' );
6181					is_easyzoom = true;
6182				}
6183				if ( is_easyzoom_flatsome_element.length && is_easyzoom_flatsome_element.data( 'easyZoom' ) ) {
6184					is_easyzoom_flatsome_element = is_easyzoom_flatsome_element.data( 'easyZoom' );
6185					is_easyzoom_flatsome = true;
6186				}
6187			}, 150 );
6188		} else {
6189			jWindow.on( 'load', function() {
6190				setTimeout( function() {
6191					if ( is_easyzoom_element.length && is_easyzoom_element.data( 'easyZoom' ) ) {
6192						is_easyzoom_element = is_easyzoom_element.data( 'easyZoom' );
6193						is_easyzoom = true;
6194					}
6195					if ( is_easyzoom_flatsome_element.length && is_easyzoom_flatsome_element.data( 'easyZoom' ) ) {
6196						is_easyzoom_flatsome_element = is_easyzoom_flatsome_element.data( 'easyZoom' );
6197						is_easyzoom_flatsome = true;
6198					}
6199				}, 150 );
6200			} );
6201		}
6202
6203		if ( is_wc27_gallery_element.length && is_wc27_gallery_element.data( 'flexslider' ) ) {
6204			is_wc27_gallery = true;
6205
6206			if ( typeof $.fn.zoom === 'function' && wc_single_product_params && wc_single_product_params.zoom_enabled ) {
6207				zoom_target_temp = img.closest( '.woocommerce-product-gallery__image' );
6208
6209				if ( zoom_target_temp.length > 0 && img.width() > $( '.woocommerce-product-gallery' ).width() ) {
6210					wc27_zoom_target = zoom_target_temp;
6211					img.data.wc27_zoom_target = wc27_zoom_target;
6212				}
6213			}
6214		}
6215
6216		if ( ! is_wc27_gallery && is_zoom_enabled ) {
6217			zoom_images = product_element.find( '.woocommerce-product-gallery__image' );
6218		}
6219
6220		gallery = {
6221			is_yith_wcmg: {
6222				type: 'yith',
6223				enabled: is_yith_wcmg,
6224				element: yith_wcmg,
6225				yith_wcmg_zoom: yith_wcmg_zoom,
6226				_yith_wcmg_default_zoom: _yith_wcmg_default_zoom,
6227				yith_wcmg_default_image: yith_wcmg_default_image
6228			},
6229			is_iosSlider: {
6230				type: 'iosslider',
6231				enabled: is_iosSlider,
6232				element: is_iosSlider_element
6233			},
6234			is_flexslider: {
6235				type: 'flexslider',
6236				enabled: is_flexslider,
6237				element: is_flexslider_element
6238			},
6239			is_elevateZoom: {
6240				type: 'elevatezoom',
6241				enabled: is_elevateZoom,
6242				element: is_elevateZoom_obj
6243			},
6244			is_easyzoom: {
6245				type: 'easyzoom',
6246				enabled: is_easyzoom,
6247				element: is_easyzoom_element
6248			},
6249			is_easyzoom_flatsome: {
6250				type: 'easyzoom-flatsome',
6251				enabled: is_easyzoom_flatsome,
6252				element: is_easyzoom_flatsome_element
6253			},
6254			is_wc27_gallery: {
6255				type: 'woocommerce',
6256				enabled: is_wc27_gallery,
6257				element: is_wc27_gallery_element
6258			},
6259			is_zoom_enabled: {
6260				type: 'zoom',
6261				enabled: ! is_wc27_gallery && is_zoom_enabled,
6262				element: zoom_images
6263			}
6264		};
6265
6266		return gallery;
6267	}
6268
6269	function tm_product_image_self( epoObject ) {
6270		var this_epo_container = epoObject.is_associated ? epoObject.this_epo_container : epoObject.this_epo_container.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector );
6271		var variationsForm = epoObject.variations_form;
6272		var main_product = epoObject.main_product;
6273		var $form = epoObject.form;
6274		var img;
6275		var gallery_type;
6276		var product_element = get_product_element( epoObject );
6277		var last_active_field = [];
6278		var t;
6279		var el;
6280		var el_current;
6281		var imp;
6282		var selector;
6283		var data;
6284		var eventNamePrefix = epoObject.is_associated ? 'tc_' : '';
6285
6286		img = get_main_product_image( epoObject, product_element );
6287		gallery_type = get_gallery_type( epoObject, img, product_element );
6288
6289		if ( $( img ).length > 0 ) {
6290			$form.on( eventNamePrefix + 'reset_image.tcpi', function() {
6291				// restore product image atts from backup
6292				$.tc_product_image = $.tc_replace_object_values( $.tc_product_image, $.tc_product_image_store );
6293
6294				last_active_field = [];
6295
6296				$( this_epo_container.find( '.tm-product-image:checked,select.tm-product-image' ) )
6297					.add( variationsForm.find( '.tm-epo-variation-section' ).first().find( '.tm-product-image:checked,select.tm-product-image' ) )
6298					.each( function() {
6299						t = $( this );
6300						if ( field_is_active( t ) && t.val() !== '' ) {
6301							last_active_field.push( t );
6302						}
6303					} );
6304				if ( last_active_field.length ) {
6305					last_active_field[ last_active_field.length - 1 ].trigger( 'tm_trigger_product_image' );
6306				} else {
6307					$.tc_product_image_store = $.tc_populate_store( img, product_element );
6308				}
6309			} );
6310
6311			$form.on( eventNamePrefix + 'found_variation.tcpi', function() {
6312				reset_saved_image( img, product_element );
6313
6314				last_active_field = [];
6315				$( this_epo_container.find( '.tm-product-image:checked,select.tm-product-image' ) )
6316					.add( variationsForm.find( '.tm-epo-variation-section' ).first().find( '.tm-product-image:checked,select.tm-product-image' ) )
6317					.each( function() {
6318						t = $( this );
6319						if ( field_is_active( t ) && t.val() !== '' ) {
6320							last_active_field.push( t );
6321						}
6322					} );
6323				if ( last_active_field.length ) {
6324					repopulate_backup_image_atts( img, product_element );
6325					last_active_field[ last_active_field.length - 1 ].trigger( 'tm_trigger_product_image' );
6326				}
6327			} );
6328
6329			$.tc_product_image_store = $.tc_maybe_copy_object_values_from_img( $.tc_product_image_store, img, product_element );
6330
6331			main_product.off( 'tm_change_product_image' ).on( 'tm_change_product_image', function( evt, event_data ) {
6332				evt.stopImmediatePropagation();
6333
6334				el = event_data.element;
6335				el_current = event_data.element_current;
6336				if ( el && el_current ) {
6337					imp = el.data( 'imagep' );
6338					selector = '';
6339					if ( imp !== '' ) {
6340						selector = 'imagep';
6341					} else if ( el.data( 'changes-product-image' ) === 'images' ) {
6342						selector = 'image';
6343					}
6344					data = event_data.element_current.data( 'image-variations' );
6345
6346					if ( data ) {
6347						data = data[ selector ];
6348					}
6349
6350					if ( data === undefined ) {
6351						// Enter the following if you want to restore the original product image
6352						// main_product.trigger( 'tm_restore_product_image', event_data );
6353						return;
6354					}
6355
6356					last_active_field = [];
6357					$( this_epo_container.find( '.tm-product-image:checked,select.tm-product-image' ) )
6358						.add( variationsForm.find( '.tm-epo-variation-section' ).first().find( '.tm-product-image:checked,select.tm-product-image' ) )
6359						.each( function() {
6360							t = $( this );
6361							if ( t.is( 'option' ) ) {
6362								t = t.closest( 'select' );
6363							}
6364							if ( field_is_active( t ) && t.val() !== '' ) {
6365								last_active_field.push( t );
6366							}
6367						} );
6368
6369					if ( last_active_field.length ) {
6370						if ( ! last_active_field[ last_active_field.length - 1 ].is( el ) ) {
6371							return;
6372						}
6373					}
6374
6375					image_update( data, img, product_element );
6376
6377					gallery_compatibility_actions( gallery_type, img, data.image_link, false, event_data, $form, product_element );
6378				}
6379			} );
6380
6381			main_product.off( 'tm_restore_product_image' ).on( 'tm_restore_product_image', function( evt, event_data ) {
6382				evt.stopImmediatePropagation();
6383
6384				el = event_data.element;
6385				last_active_field = [];
6386
6387				if ( el ) {
6388					$( this_epo_container.find( '.tm-product-image:checked,select.tm-product-image' ) )
6389						.add( variationsForm.find( '.tm-epo-variation-section' ).first().find( '.tm-product-image:checked,select.tm-product-image' ) )
6390						.each( function() {
6391							t = $( this );
6392							if ( field_is_active( t ) && t.val() !== '' ) {
6393								last_active_field.push( t );
6394							}
6395						} );
6396					if ( last_active_field.length ) {
6397						if ( ! last_active_field[ last_active_field.length - 1 ].is( el ) ) {
6398							last_active_field[ last_active_field.length - 1 ].trigger( 'tm_trigger_product_image' );
6399							return;
6400						}
6401					}
6402				}
6403
6404				image_update( false, img, product_element );
6405				gallery_compatibility_actions( gallery_type, false, img.attr( 'src' ), false, event_data, $form, product_element );
6406			} );
6407
6408			last_active_field = [];
6409			$( this_epo_container.find( '.tm-product-image:checked,select.tm-product-image' ) )
6410				.add( variationsForm.find( '.tm-epo-variation-section' ).first().find( '.tm-product-image:checked,select.tm-product-image' ) )
6411				.each( function() {
6412					t = $( this );
6413					if ( field_is_active( t ) && t.val() !== '' ) {
6414						last_active_field.push( t );
6415					}
6416				} );
6417			if ( last_active_field.length ) {
6418				last_active_field[ last_active_field.length - 1 ].trigger( 'tm_trigger_product_image' );
6419			}
6420		}
6421
6422		jWindow.trigger( 'tm_product_image_loaded' );
6423	}
6424
6425	function tm_product_image_inline( epoObject ) {
6426		var this_epo_container = epoObject.is_associated ? epoObject.this_epo_container : epoObject.this_epo_container.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector );
6427		var main_product = epoObject.main_product;
6428		var product_id = epoObject.product_id;
6429		var $form = epoObject.form;
6430		var img;
6431		var product_element = get_product_element( epoObject );
6432		var gallery_type;
6433		var a;
6434		var img_src_original;
6435		var img_width;
6436		var img_height;
6437		var last_active_field = [];
6438		var t;
6439
6440		img = get_main_product_image( epoObject, product_element );
6441
6442		gallery_type = get_gallery_type( epoObject, img, product_element );
6443
6444		if ( $( img ).length > 0 ) {
6445			img.data( 'tm-current-image', false );
6446			a = img.closest( 'a' );
6447			img_src_original = img.attr( 'src' );
6448			img_width = img.width();
6449			img_height = img.height();
6450
6451			main_product.off( 'tm_change_product_image' ).on( 'tm_change_product_image', function( evt, e ) {
6452				var variation_element_section;
6453				var is_variation_element;
6454				var $this_epo_container;
6455				var tm_last_visible_image_element;
6456				var last_activate_field = [];
6457				var tm_current_image_element_id;
6458				var can_show_image;
6459				var $main_product;
6460				var $current_product_element;
6461				var preload_width;
6462				var preload_height;
6463				var current_cloned_image;
6464				var preloader;
6465				var clone_image;
6466				var preload_img;
6467				var preload_img_onerror;
6468
6469				variation_element_section = e.element.closest( '.cpf-section' );
6470				is_variation_element = variation_element_section.is( '.tm-epo-variation-section' );
6471				$this_epo_container = e.epo_holder;
6472				if ( is_variation_element ) {
6473					$this_epo_container = variation_element_section;
6474				}
6475				tm_last_visible_image_element = $this_epo_container.find( '.tm-product-image:checked,select.tm-product-image' );
6476				last_activate_field = [];
6477				tm_current_image_element_id = e.element.attr( 'id' );
6478				can_show_image = true;
6479				$main_product = e.main_product;
6480				$current_product_element = $main_product.closest( '#product-' + product_id );
6481				preload_width = img_width;
6482				preload_height = img_height;
6483				preloader = $( "<div class='blockUI blockOverlay tm-preloader-img'></div>" );
6484
6485				if ( $current_product_element.length <= 0 ) {
6486					$current_product_element = $main_product.closest( '.post-' + product_id );
6487				}
6488
6489				current_cloned_image = $current_product_element.find( '#' + tm_current_image_element_id + '_tmimage' );
6490				if ( current_cloned_image.length === 0 ) {
6491					current_cloned_image = img;
6492				}
6493
6494				preload_img_onerror = function() {
6495					preloader.remove();
6496					$form.tc_image_update( false );
6497					img.data( 'tm-current-image', false );
6498					$current_product_element.find( '.tm-clone-product-image' ).hide();
6499					img.show();
6500				};
6501
6502				if ( e.src === current_cloned_image.attr( 'src' ) && current_cloned_image.is( ':visible' ) ) {
6503					return;
6504				}
6505
6506				if ( e.src === false ) {
6507					preload_img_onerror();
6508					return;
6509				}
6510
6511				preloader.css( {
6512					width: preload_width,
6513					height: preload_height
6514				} );
6515
6516				// Get last active field
6517				tm_last_visible_image_element.each( function() {
6518					t = $( this );
6519					if (
6520						field_is_active( t ) &&
6521						has_active_changes_product_image( t ) &&
6522						tm_check_field_match( {
6523							element: t.closest( '.cpf-element' ),
6524							operator: 'isnotempty',
6525							value: ''
6526						} )
6527					) {
6528						last_activate_field.push( t );
6529					}
6530				} );
6531				// Get last active image
6532				if ( last_activate_field.length ) {
6533					tm_last_visible_image_element = last_activate_field[ last_activate_field.length - 1 ];
6534				}
6535
6536				if ( tm_last_visible_image_element.attr( 'id' ) !== e.element.attr( 'id' ) ) {
6537					can_show_image = false;
6538				}
6539
6540				clone_image = img.tcClone();
6541				preload_img = new Image();
6542				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' );
6543
6544				if ( can_show_image ) {
6545					img.before( preloader );
6546				}
6547
6548				gallery_type.is_yith_wcmg.yith_wcmg_default_zoom = gallery_type.is_yith_wcmg.element.find( '.yith_magnifier_zoom' ).first().attr( 'href' );
6549				gallery_type.is_yith_wcmg.yith_wcmg_default_image = gallery_type.is_yith_wcmg.element.find( '.yith_magnifier_zoom img' ).first().attr( 'src' );
6550
6551				preload_img.onerror = function() {
6552					preload_img_onerror();
6553				};
6554
6555				preload_img.onload = function() {
6556					if ( 'naturalHeight' in this ) {
6557						if ( this.naturalHeight + this.naturalWidth === 0 ) {
6558							this.onerror();
6559							return;
6560						}
6561					} else if ( this.width + this.height === 0 ) {
6562						this.onerror();
6563						return;
6564					}
6565					$current_product_element.find( '#' + tm_current_image_element_id + '_tmimage' ).remove();
6566					$current_product_element.find( '.tm-clone-product-image' ).hide();
6567					clone_image.prop( 'src', preload_img.src ).hide();
6568
6569					img.hide().after( clone_image );
6570
6571					clone_image.css( 'opacity', 0 ).show();
6572
6573					gallery_compatibility_actions( gallery_type, clone_image, preload_img.src );
6574
6575					preloader.animate(
6576						{
6577							opacity: 0
6578						},
6579						750,
6580						'easeOutExpo',
6581						function() {
6582							preloader.remove();
6583						}
6584					);
6585					clone_image.animate(
6586						{
6587							opacity: 1
6588						},
6589						window.tc_epo_image_animation_delay || 1500,
6590						'easeOutExpo',
6591						function() {}
6592					);
6593
6594					jWindow.trigger( 'tm_change_product_image_loaded', {
6595						src: e.src,
6596						element: e.element,
6597						main_product: e.main_product,
6598						epo_holder: e.epo_holder
6599					} );
6600				};
6601
6602				clone_image
6603					.attr( 'id', tm_current_image_element_id + '_tmimage' )
6604					.addClass( 'tm-clone-product-image' )
6605					.hide();
6606
6607				if ( clone_image.attr( 'src-orig' ) ) {
6608					clone_image.attr( 'src-orig', e.src );
6609				}
6610
6611				if ( can_show_image ) {
6612					preload_img.src = e.src;
6613
6614					$form.tc_image_update( e.element, clone_image );
6615
6616					img.data( 'tm-current-image', tm_current_image_element_id );
6617
6618					jWindow.trigger( 'tm_change_product_image_show', {
6619						src: e.src,
6620						element: e.element,
6621						main_product: e.main_product,
6622						epo_holder: e.epo_holder
6623					} );
6624				} else {
6625					clone_image.prop( 'src', e.src ).hide();
6626					img.after( clone_image );
6627				}
6628
6629				jWindow.trigger( 'tm_change_product_image_end', {
6630					src: e.src,
6631					element: e.element,
6632					main_product: e.main_product,
6633					epo_holder: e.epo_holder
6634				} );
6635			} );
6636
6637			main_product.off( 'tm_restore_product_image' ).on( 'tm_restore_product_image', function( evt, e ) {
6638				var tm_current_image_element_id;
6639				var $main_product;
6640				var $current_product_element;
6641				var variation_element_section;
6642				var is_variation_element;
6643				var current_element;
6644				var current_image_replacement;
6645				var found;
6646				var is_it_visible;
6647				var len;
6648				var el_to_check;
6649				var imgSrc;
6650				var $this_epo_container;
6651				var i;
6652
6653				jWindow.trigger( 'tm_restore_product_image_pre', {
6654					element: e.element,
6655					main_product: e.main_product,
6656					epo_holder: e.epo_holder
6657				} );
6658				tm_current_image_element_id = e.element.attr( 'id' );
6659				$main_product = e.main_product;
6660				$current_product_element = $main_product.closest( '#product-' + product_id );
6661				variation_element_section = e.element.closest( '.cpf-section' );
6662				is_variation_element = variation_element_section.is( '.tm-epo-variation-section' );
6663				found = false;
6664				imgSrc = img_src_original;
6665				$this_epo_container = e.epo_holder;
6666				if ( is_variation_element ) {
6667					$this_epo_container = variation_element_section;
6668				}
6669
6670				if ( $current_product_element.length <= 0 ) {
6671					$current_product_element = $main_product.closest( '.post-' + product_id );
6672				}
6673
6674				is_it_visible = $current_product_element.find( '#' + tm_current_image_element_id + '_tmimage' ).is( ':visible' );
6675
6676				$current_product_element.find( '#' + tm_current_image_element_id + '_tmimage' ).remove();
6677
6678				if ( $current_product_element.find( '.tm-clone-product-image' ).length === 0 ) {
6679					img.show();
6680					img.data( 'tm-current-image', false );
6681					$form.tc_image_update( false );
6682				} else {
6683					if ( ! is_it_visible ) {
6684						jWindow.trigger( 'tm_restore_product_image_loaded_exit', {
6685							element: e.element,
6686							main_product: e.main_product,
6687							epo_holder: e.epo_holder
6688						} );
6689						return;
6690					}
6691
6692					len = $current_product_element.find( '.tm-clone-product-image' ).length;
6693					tm_current_image_element_id = img.data( 'tm-current-image' );
6694
6695					for ( i = len - 1; i >= 0; i -= 1 ) {
6696						current_image_replacement = $current_product_element.find( '.tm-clone-product-image' ).eq( i );
6697						current_element = current_image_replacement.attr( 'id' ).replace( '_tmimage', '' );
6698						el_to_check = $this_epo_container.find( "[id='" + current_element + "']" );
6699
6700						if ( el_to_check.is( ':checked' ) && el_to_check.closest( '.cpf-element' ).is( ':visible' ) ) {
6701							$current_product_element.find( '.tm-clone-product-image' ).eq( i ).show();
6702							a.attr( 'href', $current_product_element.find( '.tm-clone-product-image' ).eq( i ).prop( 'src' ) );
6703							img.data( 'tm-current-image', current_element );
6704							found = true;
6705							break;
6706						} else {
6707							$current_product_element.find( '.tm-clone-product-image' ).eq( i ).hide();
6708						}
6709					}
6710					if ( ! found ) {
6711						img.show();
6712						img.data( 'tm-current-image', false );
6713						$form.tc_image_update( false );
6714					} else {
6715						$current_product_element.find( '#' + tm_current_image_element_id + '_tmimage' ).remove();
6716					}
6717				}
6718
6719				if ( found ) {
6720					imgSrc = current_image_replacement.attr( 'src' );
6721				}
6722
6723				gallery_compatibility_actions( gallery_type, false, imgSrc, $current_product_element.find( '.tm-clone-product-image' ).filter( ':visible' ).length );
6724
6725				jWindow.trigger( 'tm_restore_product_image_loaded', {
6726					element: e.element,
6727					main_product: e.main_product,
6728					epo_holder: e.epo_holder
6729				} );
6730			} );
6731
6732			main_product.off( 'tm_attempt_product_image' ).on( 'tm_attempt_product_image', function( evt, e ) {
6733				var $main_product;
6734				var $current_product_element;
6735				var variation_element_section;
6736				var is_variation_element;
6737				var $this_epo_container;
6738				var tm_last_visible_image_element;
6739				var last_activate_field;
6740				var tm_last_visible_image_element_id;
6741				var current_image_replacement;
6742				var current_element;
6743				var found;
6744				var tm_current_image_element_id;
6745				var len;
6746				var imgSrc;
6747				var el_to_check;
6748				var tmcie_id;
6749				var i;
6750
6751				$main_product = e.main_product;
6752				$current_product_element = $main_product.closest( '#product-' + product_id );
6753				if ( e.element ) {
6754					variation_element_section = e.element.closest( '.cpf-section' );
6755				} else {
6756					variation_element_section = $( $main_product.find( '.tm-epo-variation-section' ).first(), e.epo_holder );
6757				}
6758				is_variation_element = variation_element_section.is( '.tm-epo-variation-section' );
6759				$this_epo_container = e.epo_holder;
6760				if ( is_variation_element ) {
6761					$this_epo_container = variation_element_section;
6762				}
6763				tm_last_visible_image_element = $this_epo_container.find( '.tm-product-image:checked,select.tm-product-image' );
6764				last_activate_field = [];
6765				tm_last_visible_image_element_id = '';
6766				found = false;
6767				tm_current_image_element_id = img.data( 'tm-current-image' );
6768				imgSrc = img_src_original;
6769
6770				if ( $current_product_element.length <= 0 ) {
6771					$current_product_element = $main_product.closest( '.post-' + product_id );
6772				}
6773
6774				$this_epo_container = $main_product.find( '.tm-epo-variation-section' ).first().add( e.epo_holder );
6775				tm_last_visible_image_element = $this_epo_container.find( '.tm-product-image:checked,select.tm-product-image' );
6776
6777				tm_last_visible_image_element.each( function() {
6778					t = $( this );
6779					if (
6780						field_is_active( t ) &&
6781						has_active_changes_product_image( t ) &&
6782						tm_check_field_match( {
6783							element: t.closest( '.cpf-element' ),
6784							operator: 'isnotempty',
6785							value: ''
6786						} )
6787					) {
6788						last_activate_field.push( t );
6789					}
6790				} );
6791
6792				if ( last_activate_field.length ) {
6793					tm_last_visible_image_element = last_activate_field[ last_activate_field.length - 1 ];
6794					tm_last_visible_image_element_id = tm_last_visible_image_element.attr( 'id' );
6795				}
6796
6797				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 ) ) {
6798					tm_last_visible_image_element.last().trigger( 'tm_trigger_product_image' );
6799					return;
6800				}
6801
6802				tmcie_id = $this_epo_container.find( "[id='" + tm_current_image_element_id + "']" ).closest( '.cpf-element' );
6803				if ( ! tm_current_image_element_id || ( tmcie_id.data( 'isactive' ) !== false && tmcie_id.closest( '.cpf-section' ).data( 'isactive' ) !== false ) ) {
6804					return;
6805				}
6806
6807				$current_product_element.find( '#' + tm_current_image_element_id + '_tmimage' ).remove();
6808				len = $current_product_element.find( '.tm-clone-product-image' ).length;
6809
6810				if ( len === 0 ) {
6811					img.show();
6812					img.data( 'tm-current-image', false );
6813					$form.tc_image_update( false );
6814				} else {
6815					for ( i = len - 1; i >= 0; i -= 1 ) {
6816						current_image_replacement = $current_product_element.find( '.tm-clone-product-image' ).eq( i );
6817						current_element = current_image_replacement.attr( 'id' ).replace( '_tmimage', '' );
6818						el_to_check = $this_epo_container.find( "[id='" + current_element + "']" );
6819
6820						if ( el_to_check.is( ':checked' ) && el_to_check.closest( '.cpf-element' ).is( ':visible' ) ) {
6821							$current_product_element.find( '.tm-clone-product-image' ).eq( i ).show();
6822							a.attr( 'href', $current_product_element.find( '.tm-clone-product-image' ).eq( i ).prop( 'src' ) );
6823							img.data( 'tm-current-image', current_element );
6824							found = true;
6825							break;
6826						} else {
6827							$current_product_element.find( '.tm-clone-product-image' ).eq( i ).hide();
6828						}
6829					}
6830
6831					if ( ! found ) {
6832						img.show();
6833						img.data( 'tm-current-image', false );
6834						$form.tc_image_update( false );
6835					}
6836				}
6837
6838				if ( found ) {
6839					imgSrc = current_image_replacement.attr( 'src' );
6840				}
6841
6842				gallery_compatibility_actions( gallery_type, false, imgSrc, $current_product_element.find( '.tm-clone-product-image' ).filter( ':visible' ).length );
6843			} );
6844
6845			$( this_epo_container.find( '.tm-product-image:checked,select.tm-product-image' ) )
6846				.add( main_product.find( '.tm-epo-variation-section' ).first().find( '.tm-product-image:checked,select.tm-product-image' ) )
6847				.each( function() {
6848					t = $( this );
6849					if ( field_is_active( t ) && t.val() !== '' ) {
6850						last_active_field.push( t );
6851					}
6852				} );
6853			if ( last_active_field.length ) {
6854				last_active_field[ last_active_field.length - 1 ].trigger( 'tm_trigger_product_image' );
6855			}
6856		}
6857
6858		jWindow.trigger( 'tm_product_image_loaded' );
6859	}
6860
6861	function tm_product_image( epoObject ) {
6862		setTimeout( function() {
6863			if ( TMEPOJS.tm_epo_global_product_image_mode === 'inline' ) {
6864				tm_product_image_inline( epoObject );
6865			} else {
6866				tm_product_image_self( epoObject );
6867			}
6868		}, window.tc_epo_product_image_setup_delay || 0 );
6869	}
6870
6871	function tc_compatibility( epoObject ) {
6872		jWindow.trigger( 'tm-epo-compatibility', {
6873			epo: epoObject
6874		} );
6875	}
6876
6877	// Range picker setup
6878	function setRangePickers( obj ) {
6879		if ( ! noUiSlider ) {
6880			return;
6881		}
6882		obj.find( '.tm-range-picker' )
6883			.toArray()
6884			.forEach( function( picker ) {
6885				var el = $( picker );
6886				var $decimals = el.attr( 'data-step' ).split( '.' );
6887				var $tmfid = obj.find( '#' + $.epoAPI.dom.id( el.attr( 'data-field-id' ) ) );
6888				var $min = parseFloat( el.attr( 'data-min' ) );
6889				var $max = parseFloat( el.attr( 'data-max' ) );
6890				var $start = parseFloat( el.attr( 'data-start' ) );
6891				var $step = parseFloat( el.attr( 'data-step' ) );
6892				var $show_picker_value = el.attr( 'data-show-picker-value' );
6893				var $show_label = el.closest( 'li' ).find( '.tm-show-picker-value' );
6894				var $noofpips = parseFloat( el.attr( 'data-noofpips' ) );
6895				var $pips = null;
6896				var $tmh;
6897
6898				if ( el.data( 'tc-picker-init' ) ) {
6899					return;
6900				}
6901				el.data( 'tc-picker-init', 1 );
6902
6903				if ( $decimals.length === 1 ) {
6904					$decimals = 0;
6905				} else {
6906					$decimals = $decimals[ 1 ].length;
6907				}
6908				if ( ! Number.isFinite( $min ) ) {
6909					$min = 0;
6910				}
6911				if ( ! Number.isFinite( $max ) ) {
6912					$max = 0;
6913				}
6914				if ( $max <= $min ) {
6915					$max = parseFloat( $max ) + 1;
6916				}
6917				$start = $.epoAPI.math.unformat( $start, tcAPI.localDecimalSeparator );
6918				if ( ! Number.isFinite( $start ) ) {
6919					$start = 0;
6920				}
6921				$start = formatPrice( $start, { precision: $decimals } );
6922				if ( ! Number.isFinite( $step ) ) {
6923					$step = 0;
6924				}
6925				if ( ! Number.isFinite( $noofpips ) ) {
6926					$noofpips = 10;
6927				}
6928				if ( $noofpips < 2 ) {
6929					$noofpips = 2;
6930				}
6931
6932				if ( el.attr( 'data-pips' ) === 'yes' ) {
6933					$pips = {
6934						mode: 'count',
6935						values: $noofpips,
6936						filter: function( value, type ) {
6937							value = parseFloat( $.epoAPI.math.toFixed( value, $decimals ) );
6938
6939							if ( $step <= 0 ) {
6940								return 0;
6941							}
6942
6943							if ( type === 1 ) {
6944								if ( ! Number.isInteger( value ) ) {
6945									return 2;
6946								}
6947							}
6948
6949							return type;
6950						},
6951						format: {
6952							from: function( value ) {
6953								return $.epoAPI.math.unformat( value, tcAPI.localInputDecimalSeparator );
6954							},
6955							to: function( value ) {
6956								return formatPrice( value, { precision: $decimals } );
6957							}
6958						},
6959						density: 2
6960					};
6961				}
6962
6963				noUiSlider.create( el.get( 0 ), {
6964					direction: TMEPOJS.text_direction,
6965					start: $start,
6966					step: $step,
6967					connect: 'lower',
6968					// Configure tapping, or make the selected range dragable.
6969					behaviour: 'tap',
6970					// Full number format support.
6971					format: {
6972						from: function( value ) {
6973							return $.epoAPI.math.unformat( value, tcAPI.localDecimalSeparator );
6974						},
6975						to: function( value ) {
6976							return formatPrice( value, { precision: $decimals } );
6977						}
6978					},
6979					// Support for non-linear ranges by adding intervals.
6980					range: {
6981						min: [ $min ],
6982						max: [ $max ]
6983					},
6984					pips: $pips,
6985					tooltips: {
6986						from: function( value ) {
6987							return $.epoAPI.math.unformat( value, tcAPI.localInputDecimalSeparator );
6988						},
6989						to: function( value ) {
6990							return formatPrice( value, { precision: $decimals } );
6991						}
6992					}
6993				} );
6994
6995				$tmh = el.find( '.noui-handle-lower' );
6996				el.get( 0 ).noUiSlider.on( 'slide', function() {
6997					$tmh.trigger( 'tmmovetooltip' );
6998					$tmfid.trigger( 'change.cpf' );
6999				} );
7000				el.get( 0 ).noUiSlider.on( 'update', function( values, handle ) {
7001					values[ handle ] = $.epoAPI.math.unformat( values[ handle ], tcAPI.localDecimalSeparator );
7002					handle = 0; //fixes rtl issue.
7003					if ( $show_picker_value !== 'left' && $show_picker_value !== 'right' ) {
7004						$tmh.attr(
7005							'title',
7006							formatPrice( values[ handle ], { precision: $decimals } )
7007						);
7008					}
7009					$tmfid.val( values[ handle ] ).trigger( 'change' );
7010					if ( $show_picker_value !== '' ) {
7011						$show_label.html(
7012							formatPrice( values[ handle ], { precision: $decimals } )
7013						);
7014					}
7015				} );
7016
7017				if ( $show_picker_value !== '' ) {
7018					$show_label.html( $start );
7019				}
7020
7021				if ( $show_picker_value !== 'left' && $show_picker_value !== 'right' ) {
7022					$tmh.attr( 'title', $start );
7023					el.addClass( 'noui-show-tooltip' );
7024				}
7025			} );
7026	}
7027
7028	// Range picker event setup
7029	function setRangePickersEvents() {
7030		if ( ! noUiSlider || jDocument.data( 'setRangePickersEvents' ) ) {
7031			return;
7032		}
7033		jDocument.on( 'click', '.tm-show-picker-value', function() {
7034			var $this = $( this );
7035			var li = $this.closest( '.tmcp-field-wrap' );
7036			var value = li.find( '.tmcp-range' ).val();
7037			var edit;
7038			var html5Slider = $this.closest( '.tmcp-field-wrap' ).find( '.tm-range-picker' );
7039
7040			$this.addClass( 'tc-hidden' ).after( $( '<input type="number" class="tm-show-picker-value-edit">' ) );
7041			edit = li.find( '.tm-show-picker-value-edit' );
7042			edit.focus().val( value ).wrap( '<div class="tm-show-picker-value-edit-wrap"></div>' );
7043			edit.attr( 'step', html5Slider.attr( 'data-step' ) );
7044			edit.attr( 'min', html5Slider.attr( 'data-min' ) );
7045			edit.attr( 'max', html5Slider.attr( 'data-max' ) );
7046			jDocument.data( 'range-picker-edit', li.find( '.tm-show-picker-value-edit' ) );
7047		} );
7048		jDocument.on( 'change input', '.tm-show-picker-value-edit', function() {
7049			var $this = $( this );
7050			var html5Slider = $this.closest( '.tmcp-field-wrap' ).find( '.tm-range-picker' );
7051			var $decimals = html5Slider.attr( 'data-step' ).split( '.' );
7052			var value = $this.val();
7053			if ( $decimals.length === 1 ) {
7054				$decimals = 0;
7055			} else {
7056				$decimals = $decimals[ 1 ].length;
7057			}
7058
7059			html5Slider.get( 0 ).noUiSlider.set( [ formatPrice( value, { precision: $decimals } ), null ] );
7060		} );
7061		jDocument.on( 'keydown', '.tm-show-picker-value-edit', function( event ) {
7062			var key;
7063
7064			if ( window.event ) {
7065				key = window.event.keyCode;
7066			} else {
7067				key = event.which;
7068			}
7069			if ( key === 13 ) {
7070				event.preventDefault();
7071			}
7072		} );
7073		jDocument.on( 'click', function( event ) {
7074			var $this;
7075
7076			if ( ! jDocument.data( 'range-picker-edit' ) || $( event.target ).is( '.tm-show-picker-value' ) ) {
7077				return;
7078			}
7079
7080			if ( $( event.target ).closest( '.tm-show-picker-value-edit-wrap' ).length === 0 ) {
7081				$this = jDocument.data( 'range-picker-edit' );
7082				$this.closest( '.tmcp-field-wrap' ).find( '.tm-show-picker-value' ).data( 'has-edit', 0 ).removeClass( 'tc-hidden' );
7083				$this.closest( '.tm-show-picker-value-edit-wrap' ).remove();
7084				jDocument.removeData( 'range-picker-edit' );
7085			}
7086		} );
7087		jDocument.data( 'setRangePickersEvents', 1 );
7088	}
7089
7090	function validate_date_with_options( date, inputElement ) {
7091		var input = $( inputElement );
7092		var inst = $.tm_datepicker._getInst( input[ 0 ] );
7093		var enabled_only_dates = input.data( 'tc-enabled_only_dates' );
7094		var disabled_weekdays = input.data( 'tc-disabled_weekdays' );
7095		var disabled_months = input.data( 'tc-disabled_months' );
7096		var disabled_dates = input.data( 'tc-disabled_dates' );
7097		var format = input.data( 'tc-format' );
7098		var day = date.getDay();
7099		var month = date.getDay() + 1;
7100		var string;
7101
7102		if ( ! $.tm_datepicker._isInRange( inst, date ) ) {
7103			return false;
7104		}
7105		if ( enabled_only_dates !== '' ) {
7106			string = $.tm_datepicker.formatDate( format, date );
7107			return enabled_only_dates.indexOf( string ) !== -1;
7108		}
7109		if ( disabled_weekdays.indexOf( day.toString() ) !== -1 ) {
7110			return false;
7111		}
7112		if ( disabled_months.indexOf( month.toString() ) !== -1 ) {
7113			return false;
7114		}
7115		if ( disabled_dates !== '' ) {
7116			string = $.tm_datepicker.formatDate( format, date );
7117			return disabled_dates.indexOf( string ) === -1;
7118		}
7119		return true;
7120	}
7121
7122	function correctDate( days ) {
7123		var sign, testDate, count, added, noOfDaysToAdd;
7124		if ( days.toString().isNumeric() ) {
7125			sign = days === 0 ? days : ( days > 0 ? 1 : -1 );
7126			if ( sign !== 0 ) {
7127				testDate = new Date();
7128				count = 1;
7129				added = false;
7130				noOfDaysToAdd = Math.abs( days );
7131				while ( count <= noOfDaysToAdd ) {
7132					if ( added === false ) {
7133						added = 0;
7134					}
7135					testDate.setDate( testDate.getDate() + ( 1 * sign ) );
7136					added++;
7137					if ( testDate.getDay() !== 0 && testDate.getDay() !== 6 ) {
7138						count++;
7139					}
7140				}
7141				if ( added !== false ) {
7142					days = added * sign;
7143				}
7144			}
7145		}
7146		return days;
7147	}
7148	// Date and time picker setup
7149	function tm_set_datepicker( obj ) {
7150		var inputIds;
7151		var elem;
7152		var timepickerSelector = '.tm-epo-timepicker';
7153
7154		if ( ! $.tm_datepicker ) {
7155			return;
7156		}
7157
7158		inputIds = $( 'input' )
7159			.map( function() {
7160				return this.id;
7161			} )
7162			.get()
7163			.join( ' ' );
7164
7165		elem = document.createElement( 'input' );
7166		elem.setAttribute( 'type', 'date' );
7167
7168		if ( elem.type === 'text' ) {
7169			timepickerSelector = '.tm-epo-system-timepicker';
7170		}
7171
7172		obj.find( timepickerSelector )
7173			.toArray()
7174			.forEach( function( el ) {
7175				var field = $( el );
7176				var _mintime = null;
7177				var _maxtime = null;
7178				var format = field.attr( 'data-time-format' ).trim();
7179				var date_theme = field.attr( 'data-time-theme' ).trim();
7180				var date_theme_size = field.attr( 'data-time-theme-size' ).trim();
7181				var date_theme_position = field.attr( 'data-time-theme-position' ).trim();
7182				var data_tranlation_hour = field.attr( 'data-tranlation-hour' ).trim();
7183				var data_tranlation_minute = field.attr( 'data-tranlation-minute' ).trim();
7184				var data_tranlation_second = field.attr( 'data-tranlation-second' ).trim();
7185
7186				field.attr( 'type', 'text' );
7187
7188				if ( field.attr( 'data-min-time' ).trim() !== '' ) {
7189					_mintime = field.attr( 'data-min-time' ).trim();
7190				}
7191				if ( field.attr( 'data-max-time' ).trim() !== '' ) {
7192					_maxtime = field.attr( 'data-max-time' ).trim();
7193				}
7194
7195				if ( field.attr( 'data-custom-time-format' ).trim() !== '' ) {
7196					format = field.attr( 'data-custom-time-format' ).trim();
7197				}
7198				if ( ! data_tranlation_hour ) {
7199					data_tranlation_hour = TMEPOJS.hourText;
7200				}
7201				if ( ! data_tranlation_minute ) {
7202					data_tranlation_minute = TMEPOJS.minuteText;
7203				}
7204				if ( ! data_tranlation_second ) {
7205					data_tranlation_second = TMEPOJS.secondText;
7206				}
7207
7208				field.tm_timepicker( Object.assign( {
7209					isRTL: TMEPOJS.isRTL,
7210					hourText: data_tranlation_hour,
7211					minuteText: data_tranlation_minute,
7212					secondText: data_tranlation_second,
7213					timeFormat: format,
7214					minTime: _mintime,
7215					maxTime: _maxtime,
7216					closeText: TMEPOJS.closeText,
7217					showOn: 'both',
7218					buttonText: '',
7219
7220					beforeShow: function( input, inst ) {
7221						$( inst.dpDiv )
7222							.removeClass( inputIds )
7223							.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' )
7224							.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 )
7225							.appendTo( 'body' );
7226
7227						jDocument.off( 'click', '.tm-ui-dp-overlay' ).on( 'click', '.tm-ui-dp-overlay', function() {
7228							field.tm_timepicker( 'hide' );
7229						} );
7230						jBody.addClass( 'tm-static' );
7231						field.prop( 'readonly', true );
7232
7233						jWindow.trigger( {
7234							type: 'tm-timepicker-beforeShow',
7235							input: input,
7236							inst: inst
7237						} );
7238					},
7239					onClose: function() {
7240						jBody.removeClass( 'tm-static' );
7241						field.prop( 'readonly', false );
7242						field.trigger( 'change' );
7243					}
7244				}, window.timepicker_settings || {} ) );
7245				$( '#ui-tm-datepicker-div' ).hide();
7246			} );
7247
7248		obj.find( '.tm-epo-datepicker' )
7249			.toArray()
7250			.forEach( function( el ) {
7251				var field = $( el );
7252				var startDate = parseInt( field.attr( 'data-start-year' ).trim(), 10 );
7253				var endDate = parseInt( field.attr( 'data-end-year' ).trim(), 10 );
7254				var minDate = field.attr( 'data-min-date' ).trim();
7255				var maxDate = field.attr( 'data-max-date' ).trim();
7256				var disabled_dates = field.attr( 'data-disabled-dates' ).trim();
7257				var enabled_only_dates = field.attr( 'data-enabled-only-dates' ).trim();
7258				var exlude_disabled = field.attr( 'data-exlude-disabled' ).trim();
7259				var disabled_weekdays = field.attr( 'data-disabled-weekdays' ).trim().split( ',' );
7260				var disabled_months = field.attr( 'data-disabled-months' ).trim().split( ',' );
7261				var format = field.attr( 'data-date-format' ).trim();
7262				var show = field.attr( 'data-date-showon' ).trim();
7263				var default_date = field.attr( 'data-date-defaultdate' ).trim();
7264				var date_theme = field.attr( 'data-date-theme' ).trim();
7265				var date_theme_size = field.attr( 'data-date-theme-size' ).trim();
7266				var date_theme_position = field.attr( 'data-date-theme-position' ).trim();
7267				var $split;
7268				var $index;
7269				var $split2;
7270				var $index2;
7271
7272				if ( disabled_dates !== '' ) {
7273					$split = disabled_dates.split( ',' );
7274					$index = disabled_dates.indexOf( ',' );
7275
7276					if ( $index !== -1 && $split.length > 0 ) {
7277						disabled_dates = $split;
7278					}
7279				}
7280				if ( enabled_only_dates !== '' ) {
7281					$split2 = enabled_only_dates.split( ',' );
7282					$index2 = enabled_only_dates.indexOf( ',' );
7283
7284					if ( $index2 !== -1 && $split2.length > 0 ) {
7285						enabled_only_dates = $split2;
7286					}
7287				}
7288
7289				if ( minDate === '' ) {
7290					if ( startDate === '' ) {
7291						minDate = null;
7292					} else {
7293						minDate = new Date( startDate, 1 - 1, 1 );
7294					}
7295				} else if ( exlude_disabled ) {
7296					minDate = correctDate( minDate );
7297				}
7298				if ( maxDate === '' ) {
7299					if ( endDate === '' ) {
7300						maxDate = null;
7301					} else {
7302						maxDate = new Date( endDate, 12 - 1, 31 );
7303					}
7304				} else if ( exlude_disabled ) {
7305					maxDate = correctDate( maxDate );
7306				}
7307
7308				field.data( 'tc-enabled_only_dates', enabled_only_dates );
7309				field.data( 'tc-disabled_weekdays', disabled_weekdays );
7310				field.data( 'tc-disabled_months', disabled_months );
7311				field.data( 'tc-disabled_dates', disabled_dates );
7312				field.data( 'tc-format', format );
7313
7314				field.tm_datepicker( {
7315					monthNames: TMEPOJS.monthNames,
7316					monthNamesShort: TMEPOJS.monthNamesShort,
7317					dayNames: TMEPOJS.dayNames,
7318					dayNamesShort: TMEPOJS.dayNamesShort,
7319					dayNamesMin: TMEPOJS.dayNamesMin,
7320					isRTL: TMEPOJS.isRTL,
7321					showOtherMonths: true,
7322					selectOtherMonths: true,
7323					showOn: show,
7324					defaultDate: default_date,
7325					buttonText: '',
7326					showButtonPanel: true,
7327					firstDay: TMEPOJS.first_day,
7328					closeText: TMEPOJS.closeText,
7329					currentText: TMEPOJS.currentText,
7330					dateFormat: format,
7331					minDate: minDate,
7332					maxDate: maxDate,
7333					onSelect: function() {
7334						var input = $( this );
7335						var id = '#' + $.epoAPI.dom.id( input.attr( 'id' ) );
7336						var date = input.tm_datepicker( 'getDate' );
7337						var day = '';
7338						var month = '';
7339						var year = '';
7340						var day_field = obj.find( id + '_day' );
7341						var month_field = obj.find( id + '_month' );
7342						var year_field = obj.find( id + '_year' );
7343						var string;
7344						var ld;
7345
7346						if ( date ) {
7347							day = date.getDate();
7348							month = date.getMonth() + 1;
7349							year = date.getFullYear();
7350							string = $.tm_datepicker.formatDate( format, date );
7351							if (
7352								disabled_months.indexOf( month.toString() ) !== -1 ||
7353								disabled_weekdays.indexOf( date.getDay().toString() ) !== -1 ||
7354								disabled_dates.indexOf( string ) !== -1 ||
7355								( enabled_only_dates !== '' && enabled_only_dates.indexOf( string ) === -1 )
7356							) {
7357								ld = input.data( 'tm-last-date' );
7358								if ( input.data( 'tm-last-date' ) ) {
7359									ld = input.data( 'tm-last-date' );
7360								} else {
7361									ld = '';
7362								}
7363								input.val( ld );
7364								input.tm_datepicker( 'setDate', ld );
7365								if ( ld ) {
7366									date = input.tm_datepicker( 'getDate' );
7367									day = date.getDate();
7368									month = date.getMonth() + 1;
7369									year = date.getFullYear();
7370								} else {
7371									day = '';
7372									month = '';
7373									year = '';
7374								}
7375							}
7376						}
7377
7378						day_field.val( day );
7379						month_field.val( month );
7380						year_field.val( year );
7381
7382						input.data( 'tm-last-date', input.val() );
7383					},
7384					beforeShow: function( input, inst ) {
7385						$( inst.dpDiv )
7386							.removeClass( inputIds )
7387							.removeClass( 'tm-datepicker-normal tm-datepicker-top tm-datepicker-bottom' )
7388							.addClass( this.id + ' tm-bsbb-all tm-ui-skin-' + date_theme + ' tm-datepicker tm-datepicker-' + date_theme_position + ' tm-datepicker-' + date_theme_size )
7389							.appendTo( 'body' );
7390
7391						jDocument.off( 'click', '.tm-ui-dp-overlay' ).on( 'click', '.tm-ui-dp-overlay', function() {
7392							field.tm_datepicker( 'hide' );
7393						} );
7394						jDocument.off( 'click', '.ui-tm-datepicker-current' ).on( 'click', '.ui-tm-datepicker-current', function() {
7395							var tempDate = new Date(),
7396								today = $.tm_datepicker._daylightSavingAdjust( new Date( tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate() ) );
7397							var day = today.getDay();
7398							var month = today.getMonth() + 1;
7399							var id = '#' + inst.id.replace( /\\\\/g, '\\' );
7400							var check = false;
7401							var string;
7402							var date = field.tm_datepicker( 'getDate' );
7403
7404							if ( enabled_only_dates !== '' ) {
7405								string = $.tm_datepicker.formatDate( format, date );
7406								check = enabled_only_dates.indexOf( string ) !== -1;
7407							} else if ( disabled_months.indexOf( month.toString() ) !== -1 || disabled_weekdays.indexOf( day.toString() ) !== -1 ) {
7408								check = false;
7409							} else {
7410								if ( disabled_dates !== '' ) {
7411									string = $.tm_datepicker.formatDate( format, date );
7412									return [ disabled_dates.indexOf( string ) === -1, '' ];
7413								}
7414								check = true;
7415							}
7416							if ( check ) {
7417								$.tm_datepicker._setDate( inst, today );
7418								$.tm_datepicker._gotoToday( id );
7419							}
7420						} );
7421						jBody.addClass( 'tm-static' );
7422						field.prop( 'readonly', true );
7423
7424						jWindow.trigger( {
7425							type: 'tm-datepicker-beforeShow',
7426							input: input,
7427							inst: inst
7428						} );
7429					},
7430					onClose: function() {
7431						jBody.removeClass( 'tm-static' );
7432						field.prop( 'readonly', false );
7433						field.trigger( 'change' );
7434					},
7435					beforeShowDay: function( date ) {
7436						var day = date.getDay();
7437						var month = date.getMonth() + 1;
7438						var string;
7439
7440						if ( enabled_only_dates !== '' ) {
7441							string = $.tm_datepicker.formatDate( format, date );
7442							return [ enabled_only_dates.indexOf( string ) !== -1, '' ];
7443						}
7444						if ( disabled_months.indexOf( month.toString() ) !== -1 || disabled_weekdays.indexOf( day.toString() ) !== -1 ) {
7445							return [ false, '' ];
7446						}
7447						if ( disabled_dates !== '' ) {
7448							string = $.tm_datepicker.formatDate( format, date );
7449							return [ disabled_dates.indexOf( string ) === -1, '' ];
7450						}
7451						return [ true, '' ];
7452					}
7453				} );
7454
7455				$( '#ui-tm-datepicker-div' ).hide();
7456			} );
7457
7458		obj.find( '.tmcp-date-select' )
7459			.on( 'change.cpf', function() {
7460				var id = '#' + $.epoAPI.dom.id( $( this ).attr( 'data-tm-date' ) );
7461				var input = obj.find( id );
7462				var format = input.attr( 'data-date-format' );
7463				var day = obj.find( id + '_day' ).val();
7464				var month = obj.find( id + '_month' ).val();
7465				var year = obj.find( id + '_year' ).val();
7466				var dateFormat = $.tm_datepicker.formatDate( format, new Date( year, parseInt( month, 10 ) - 1, day ) );
7467
7468				if ( day > 0 && month > 0 && year > 0 ) {
7469					input.tm_datepicker( 'setDate', dateFormat );
7470					input.trigger( 'change' );
7471				} else {
7472					input.val( '' );
7473					input.trigger( 'change.cpf' );
7474				}
7475			} )
7476			.on( 'focus.cpf', function() {
7477				var id = '#' + $.epoAPI.dom.id( $( this ).attr( 'data-tm-date' ) );
7478				var input = obj.find( id );
7479				var day_select = obj.find( id + '_day' );
7480				var month_select = obj.find( id + '_month' );
7481				var year_select = obj.find( id + '_year' );
7482				var day = day_select.val();
7483				var month = month_select.val();
7484				var year = year_select.val();
7485				var _select = $( this );
7486
7487				if ( ( year !== '' && month !== '' && day !== '' ) || ( year !== '' && month !== '' && day === '' ) || ( day !== '' && year !== '' && month === '' ) || ( day !== '' && month !== '' && year === '' ) ) {
7488					_select
7489						.find( 'option' )
7490						.toArray()
7491						.forEach( function( element ) {
7492							var option = $( element );
7493							var val = option.val();
7494							var date_string = year + '-' + month + '-' + day;
7495							var d;
7496
7497							if ( _select.is( '.tmcp-date-day' ) ) {
7498								if ( year === '' || month === '' ) {
7499									return;
7500								}
7501								date_string = year + '-' + month + '-' + val;
7502							} else if ( _select.is( '.tmcp-date-month' ) ) {
7503								if ( year === '' || day === '' ) {
7504									return;
7505								}
7506								date_string = year + '-' + val + '-' + day;
7507							} else if ( _select.is( '.tmcp-date-year' ) ) {
7508								if ( day === '' || month === '' ) {
7509									return;
7510								}
7511								date_string = val + '-' + month + '-' + day;
7512							}
7513
7514							if ( val !== '' ) {
7515								try {
7516									d = $.tm_datepicker.parseDate( 'yy-mm-dd', date_string );
7517									if ( d ) {
7518										if ( validate_date_with_options( d, input ) ) {
7519											option.prop( 'disabled', false );
7520										} else {
7521											option.prop( 'disabled', true );
7522										}
7523									}
7524								} catch ( err ) {
7525									window.console.log( err );
7526
7527									option.prop( 'disabled', true );
7528									errorObject = err;
7529								}
7530							}
7531						} );
7532				} else {
7533					day_select.find( 'option' ).prop( 'disabled', false );
7534					month_select.find( 'option' ).prop( 'disabled', false );
7535					year_select.find( 'option' ).prop( 'disabled', false );
7536				}
7537			} );
7538
7539		jWindow.on( 'resizestart', function() {
7540			var activeElement = $( document.activeElement );
7541
7542			if ( activeElement.is( '.hasDatepicker' ) ) {
7543				activeElement.data( 'resizestarted', true );
7544
7545				// we don't use jWindow here because we want the current window width
7546				if ( $( window ).width() < 768 ) {
7547					activeElement.data( 'resizewidth', true );
7548					return;
7549				}
7550				activeElement.tm_datepicker( 'hide' );
7551			}
7552		} );
7553		jWindow.on( 'resizestop', function() {
7554			var activeElement = $( document.activeElement );
7555
7556			if ( activeElement.is( '.hasDatepicker' ) && activeElement.data( 'resizestarted' ) ) {
7557				if ( activeElement.data( 'resizewidth' ) ) {
7558					activeElement.tm_datepicker( 'hide' );
7559				}
7560				activeElement.tm_datepicker( 'show' );
7561			}
7562			activeElement.data( 'resizestarted', false );
7563			activeElement.data( 'resizewidth', false );
7564		} );
7565	}
7566
7567	function apply_submit_events( epoObject ) {
7568		var epoEventId = epoObject.epoEventId;
7569		var main_product = epoObject.main_product;
7570		var type;
7571		var form_is_submit = ! $.tcepo.formSubmitEvents[ epoEventId ].some( function( form_event ) {
7572			return typeof form_event && ( typeof form_event.trigger === 'function' || false ) && ! form_event.trigger();
7573		} );
7574
7575		$.tcepo.formSubmitEvents[ epoEventId ].forEach( function( form_event ) {
7576			type = typeof form_event;
7577			if ( type === 'object' ) {
7578				if ( form_is_submit ) {
7579					form_event.on_true();
7580				} else {
7581					form_event.on_false();
7582				}
7583			}
7584		} );
7585
7586		if ( ! form_is_submit ) {
7587			setTimeout( function() {
7588				main_product.find( tcAPI.addToCartButtonSelector ).first().removeClass( 'disabled' ).removeClass( 'loading' ).prop( 'disabled', false ).removeClass( 'fpd-disabled' );
7589			}, 100 );
7590		}
7591
7592		jWindow.trigger( 'tm-apply-submit-events', {
7593			epo: {
7594				form_is_submit: form_is_submit
7595			}
7596		} );
7597
7598		return form_is_submit;
7599	}
7600
7601	function tm_apply_validation( epoObject ) {
7602		var form = epoObject.form;
7603		var this_epo_container = epoObject.this_epo_container;
7604		var main_product = epoObject.main_product;
7605		var epoEventId = epoObject.epoEventId;
7606		var validation_rules;
7607		var has_rules;
7608
7609		if ( TMEPOJS.tm_epo_global_enable_validation === 'yes' ) {
7610			validation_rules = {};
7611
7612			this_epo_container
7613				.find( '.tmcp-ul-wrap' )
7614				.toArray()
7615				.forEach( function( tmcpulwrap ) {
7616					var field;
7617					var field_name;
7618					var subFieldName;
7619					var subRule;
7620					var productField;
7621
7622					tmcpulwrap = $( tmcpulwrap );
7623					has_rules = tmcpulwrap.data( 'tm-validation' );
7624					if ( has_rules && $.tmType( has_rules ) === 'object' ) {
7625						field = tmcpulwrap.find( '.tm-epo-field' );
7626						field_name = field.first().attr( 'name' );
7627						if ( tmcpulwrap.is( '.tm-extra-product-options-radio.tm-element-ul-radio' ) ) {
7628							field_name = field.last().attr( 'name' );
7629							validation_rules[ field_name ] = has_rules;
7630						} else if ( tmcpulwrap.is( '.tm-extra-product-options-checkbox.tm-element-ul-checkbox' ) ) {
7631							field.each( function( f, fname ) {
7632								if ( 'required' in has_rules ) {
7633									has_rules.required = function( elem ) {
7634										var len = tmcpulwrap.find( 'input.tm-epo-field.tmcp-checkbox:checked' ).length;
7635										if ( len === 0 ) {
7636											if ( field.last().attr( 'name' ) === $( elem ).attr( 'name' ) ) {
7637												return true;
7638											}
7639											return false;
7640										}
7641										return len <= 0;
7642									};
7643								}
7644								validation_rules[ $( fname ).attr( 'name' ) ] = has_rules;
7645							} );
7646						} else if ( tmcpulwrap.is( '.tm-extra-product-options-product.tm-element-ul-product' ) ) {
7647							if ( field.is( ':checkbox' ) ) {
7648								field.each( function( f, fname ) {
7649									if ( 'required' in has_rules ) {
7650										productField = $( fname );
7651										if ( productField.is( ':checkbox' ) ) {
7652											has_rules.required = function( elem ) {
7653												var checkedFields = tmcpulwrap.find( 'input.tm-epo-field.tmcp-checkbox:checked' );
7654												var len = checkedFields.length;
7655												var qtyCheck;
7656												if ( len === 0 ) {
7657													if ( field.last().attr( 'name' ) === $( elem ).attr( 'name' ) ) {
7658														return true;
7659													}
7660													return false;
7661												}
7662												qtyCheck = checkedFields.map( function() {
7663													return $( this );
7664												} ).get().some( function( element ) {
7665													return element.closest( '.tc-epo-element-product-holder' ).find( '.tm-qty' ).first().val() <= 0;
7666												} );
7667												if ( len > 0 ) {
7668													return qtyCheck;
7669												}
7670												return len <= 0;
7671											};
7672											if ( productField.attr( 'data-type' ) === 'variable' ) {
7673												subFieldName = productField.closest( '.tc-epo-element-product-holder' ).find( '.product-variation-id' ).first().attr( 'name' );
7674												subRule = {
7675													required: function( elem ) {
7676														var element = $( elem );
7677														var holder = element.closest( '.tc-epo-element-product-holder' );
7678														var checkbox = holder.find( '.tc-epo-field-product' );
7679
7680														if ( field_is_active( checkbox, true ) && checkbox.is( ':checked' ) ) {
7681															return true;
7682														}
7683														return false;
7684													}
7685												};
7686												validation_rules[ subFieldName ] = subRule;
7687											}
7688										}
7689									}
7690									validation_rules[ productField.attr( 'name' ) ] = has_rules;
7691								} );
7692							} else if ( field.is( ':radio' ) ) {
7693								has_rules.product_element_radio_qty = true;
7694								validation_rules[ field.attr( 'name' ) ] = has_rules;
7695								subFieldName = field.closest( '.tc-element-container' ).find( '.product-variation-id' ).first().attr( 'name' );
7696								subRule = {
7697									required: function( elem ) {
7698										var element = $( elem );
7699										var holder = element.closest( '.tc-element-container' );
7700										var radiobutton = holder.find( '.tc-epo-field-product:checked' );
7701
7702										if ( radiobutton.length && radiobutton.attr( 'data-type' ) === 'variable' && field_is_active( radiobutton, true ) && radiobutton.is( ':checked' ) ) {
7703											return true;
7704										}
7705										return false;
7706									}
7707								};
7708								validation_rules[ subFieldName ] = subRule;
7709							} else if ( field.is( 'select' ) ) {
7710								has_rules.product_element_select_qty = true;
7711								validation_rules[ field.attr( 'name' ) ] = has_rules;
7712								subFieldName = field.closest( '.tc-element-container' ).find( '.product-variation-id' ).first().attr( 'name' );
7713								subRule = {
7714									required: function( elem ) {
7715										var element = $( elem );
7716										var holder = element.closest( '.tc-element-container' );
7717										var select = holder.find( '.tc-epo-field-product' );
7718
7719										if ( select.length && select.children( ':selected' ).attr( 'data-type' ) === 'variable' && field_is_active( select, true ) ) {
7720											return true;
7721										}
7722										return false;
7723									}
7724								};
7725								validation_rules[ subFieldName ] = subRule;
7726							}
7727						} else {
7728							validation_rules[ field_name ] = has_rules;
7729						}
7730					}
7731				} );
7732
7733			form.removeData( 'tc_validator' );
7734			form.tc_validate( {
7735				focusInvalid: false,
7736				ignore:
7737					tcAPI.qtySelector +
7738					",.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(.tc-extra-product-options input),select:not(.tc-extra-product-options select)",
7739				rules: validation_rules,
7740				errorClass: 'tm-error',
7741				validClass: 'tm-valid',
7742				errorElement: 'label',
7743				errorPlacement: function( error, element ) {
7744					error.addClass( 'tc-cell tcwidth-100' );
7745					if ( TMEPOJS.tm_epo_global_error_label_placement === 'before' ) {
7746						element.closest( '.tc-element-container' ).before( error );
7747					} else {
7748						element.closest( '.tc-element-container' ).after( error );
7749					}
7750					return false;
7751				},
7752				invalidHandler: function( event, validator ) {
7753					jWindow.trigger( 'tm-invalidHandler', {
7754						epo: {
7755							validator: validator
7756						}
7757					} );
7758					setTimeout( function() {
7759						if ( ! main_product.find( tcAPI.addToCartButtonSelector ).first().is( '.disabled' ) ) {
7760							main_product.find( tcAPI.addToCartButtonSelector ).first().removeClass( 'loading' ).prop( 'disabled', false ).removeClass( 'fpd-disabled' );
7761							main_product.find( tcAPI.addToCartButtonSelector ).first().removeClass( 'disabled' ).removeClass( 'loading' ).prop( 'disabled', false ).removeClass( 'fpd-disabled' );
7762						}
7763					}, 100 );
7764					if ( validator.errorList && validator.errorList[ 0 ] && validator.errorList[ 0 ].element ) {
7765						goto_error_item( $( validator.errorList[ 0 ].element ), epoEventId );
7766					}
7767				},
7768				submitHandler: function() {
7769					var ajaxSuccessFunc;
7770					if ( ! epoObject.is_quickview ) {
7771						main_product.find( tcAPI.addToCartButtonSelector ).first().addClass( 'disabled' );
7772						ajaxSuccessFunc = function() {
7773							main_product.find( tcAPI.addToCartButtonSelector ).first().removeClass( 'disabled' );
7774							jDocument.off( 'ajaxSuccess', ajaxSuccessFunc );
7775						};
7776						jDocument.on( 'ajaxSuccess', ajaxSuccessFunc );
7777					}
7778					return apply_submit_events( epoObject );
7779				}
7780			} );
7781
7782			// This should handle most ajax based add to cart solutions
7783			form.find( tcAPI.addToCartButtonSelector ).on( 'click', function( e ) {
7784				if ( ! form.tc_validate().form() ) {
7785					e.preventDefault();
7786					e.stopImmediatePropagation();
7787				}
7788			} );
7789
7790			return true;
7791		}
7792		return false;
7793	}
7794
7795	function tm_form_submit_event( epoObject ) {
7796		var form = epoObject.form;
7797		var epoEventId = epoObject.epoEventId;
7798
7799		jWindow.trigger( 'tm-from-submit', {
7800			epo: epoObject,
7801			functions: {
7802				tm_apply_validation: tm_apply_validation,
7803				apply_submit_events: apply_submit_events
7804			}
7805		} );
7806		if ( ! tm_apply_validation( epoObject ) && $.tcepo.formSubmitEvents[ epoEventId ].length ) {
7807			form.on( 'submit', function() {
7808				apply_submit_events( epoObject );
7809			} );
7810		}
7811	}
7812
7813	function found_variation_tmepo( dataObject ) {
7814		var epoHolder = dataObject.epoHolder;
7815		var totalsHolder = dataObject.totalsHolder;
7816		var totalsHolderContainer = dataObject.totalsHolderContainer;
7817		var currentCart = dataObject.currentCart;
7818		var variationForm = dataObject.variationForm;
7819		var variation = dataObject.variation;
7820		var variations = totalsHolder.data( 'variations' );
7821		var product_price;
7822
7823		totalsHolder.data( 'current_variation', variation );
7824
7825		/**
7826		 * Currency converters that don't allow multi currency checkout will fail the following if statement
7827		 *
7828		 * if (variation.display_price!=undefined) {
7829		 *     product_price = variation.display_price;
7830		 *     totalsHolder.data('price', product_price);
7831		 * } else ...
7832		 *
7833		 */
7834		// This needs to be the first check as the next one
7835		// fails for taxed products as it displays the backend price only.
7836		if ( variation && 'display_price' in variation && ! totalsHolder.data( 'tm-epo-is-woocs' ) ) {
7837			product_price = variation.display_price;
7838
7839			totalsHolder.data( 'priceIsWithDiscount', '1' );
7840			// Fancy product Designer
7841			totalsHolder.removeData( 'tcprice' );
7842		} else if ( variations && variation && variation.variation_id && variations[ variation.variation_id ] !== undefined ) {
7843			product_price = variations[ variation.variation_id ];
7844
7845			// Fancy product Designer
7846			totalsHolder.removeData( 'tcprice' );
7847		} else if ( variation && $( variation.price_html ).find( '.amount:last' ).length ) {
7848			product_price = $( variation.price_html ).find( '.amount:last' ).text();
7849			product_price = product_price.replace( TMEPOJS.currency_format_thousand_sep, '' );
7850			product_price = product_price.replace( TMEPOJS.currency_format_decimal_sep, '.' );
7851			product_price = product_price.replace( /[^0-9.]/g, '' );
7852			product_price = parseFloat( product_price );
7853
7854			// Fancy product Designer
7855			totalsHolder.removeData( 'tcprice' );
7856		}
7857
7858		product_price = tm_set_backend_price( product_price, totalsHolder, variation );
7859		totalsHolder.data( 'price', product_price );
7860
7861		totalsHolderContainer.find( '.cpf-product-price' ).val( product_price );
7862
7863		setTimeout( function() {
7864			epoHolder.find( 'select.tm-epo-field' ).trigger( 'tm-select-change-html-all-math' );
7865		}, 100 );
7866
7867		// This must be run every time to get correct results for percent price types
7868		// if set norules then discount will not auto work upon chosing a variation
7869		if ( ! variationForm.data( 'tm-styled-variations' ) ) {
7870			currentCart.trigger( {
7871				type: 'tm-epo-update'
7872			} );
7873		}
7874	}
7875
7876	function fetchOptionPrices( epoObject, epoHolder, selector, total, original_total, floatingBoxData, showTotal, forced, setPriceTax, useUndiscountedPrice ) {
7877		var obj;
7878		var noDpd;
7879		var priceArray;
7880		var priceCacheSelector = epoHolder.attr( 'class' ) + epoHolder.attr( 'data-uniqid' ) + selector + epoObject.is_associated + setPriceTax + forced + setPriceTax + useUndiscountedPrice || 'none';
7881
7882		if ( priceCacheSelector !== 'none' && priceCache !== true && priceCache !== false && priceCache[ priceCacheSelector ] !== undefined ) {
7883			return priceCache[ priceCacheSelector ];
7884		}
7885
7886		noDpd = useUndiscountedPrice ? 'undiscounted_' : '';
7887		obj = epoHolder.find( selector );
7888		if ( epoObject.is_associated === false ) {
7889			obj = obj.not( tcAPI.associatedEpoSelector + ' ' + selector );
7890		}
7891		if ( ! forced ) {
7892			obj = obj.filter( '.tcenabled' );
7893		}
7894
7895		if ( ! total ) {
7896			total = 0;
7897		}
7898		if ( ! original_total ) {
7899			original_total = 0;
7900		}
7901		if ( ! floatingBoxData ) {
7902			floatingBoxData = [];
7903		}
7904
7905		obj.toArray().forEach( function( tmcpfield ) {
7906			var field = $( tmcpfield );
7907			var _value = '';
7908			var fieldval;
7909			var field_div = field.closest( '.cpf-element' );
7910			var field_wrap = field.closest( '.tmcp-field-wrap' );
7911			var field_label_show = field_div.attr( 'data-fblabelshow' );
7912			var field_value_show = field_div.attr( 'data-fbvalueshow' );
7913			var field_title = '';
7914			var option_quantity = field_wrap.find( '.tm-qty' ).val();
7915			var option_price;
7916			var option_price_taxed;
7917			var option_original_price;
7918			var option_original_price_taxed;
7919			var liw;
7920			var cri;
7921			var tl;
7922			var options;
7923			var forrangepicker;
7924			var $decimals;
7925			var _valueText = '';
7926			var setter;
7927			var dofloatingBoxData = false;
7928
7929			if ( field_label_show === '' ) {
7930				field_title = field_div.find( '.tc-epo-label' ).html();
7931			}
7932
7933			if ( option_quantity === undefined ) {
7934				option_quantity = '';
7935			}
7936			if ( field.is( ':checkbox, :radio, :input' ) ) {
7937				option_price = 0;
7938				option_price_taxed = 0;
7939				option_original_price = 0;
7940				option_original_price_taxed = 0;
7941				if ( field.is( '.tmcp-checkbox, .tmcp-radio' ) ) {
7942					if ( forced || field.is( ':checked' ) ) {
7943						option_price = field.data( noDpd + 'raw_price' );
7944						option_price_taxed = field.data( noDpd + 'price' );
7945						option_original_price = field.data( noDpd + 'raw_original_price' );
7946						option_original_price_taxed = field.data( noDpd + 'original_price' );
7947						showTotal = true;
7948						field.data( 'isset', 1 );
7949						liw = field.closest( 'li.tmcp-field-wrap' );
7950						cri = liw.find( '.checkbox-image,.radio-image' );
7951						_value = '';
7952						_valueText = '';
7953
7954						tl = field.closest( 'li.tmcp-field-wrap' ).find( '.tm-label' );
7955						if ( tl.length ) {
7956							_value = tl.html();
7957							_valueText = _value;
7958						}
7959
7960						if ( cri.length ) {
7961							if ( field.closest( '.tmcp-ul-wrap' ).is( '.tc-colors-container' ) ) {
7962								_value = _value + cri.closest( '.tc-label-wrap' ).clone().addClass( 'tc-img-floating' )[ 0 ].outerHTML;
7963							} else {
7964								_value = _value + cri.clone().addClass( 'tc-img-floating' )[ 0 ].outerHTML;
7965							}
7966						}
7967
7968						if ( field.closest( '.tmcp-ul-wrap' ).is( '.tc-images-container' ) ) {
7969							_value = liw.find( '.tc-label' ).first().html();
7970							_valueText = _value;
7971							if ( cri.length ) {
7972								_value = _value + '<img class="tc-img-floating" src="' + field.attr( 'data-image' ) + '">';
7973							}
7974						}
7975						dofloatingBoxData = true;
7976					} else {
7977						field.data( 'isset', 0 );
7978					}
7979				} else if ( field.is( '.tmcp-select' ) ) {
7980					setter = field.find( 'option:selected' );
7981					option_price = setter.data( noDpd + 'raw_price' );
7982					option_price_taxed = setter.data( noDpd + 'price' );
7983					option_original_price = setter.data( noDpd + 'raw_original_price' );
7984					option_original_price_taxed = setter.data( noDpd + 'original_price' );
7985
7986					options = field.children( 'option:selected' );
7987					if ( ! ( options.val() === '' && options.attr( 'data-rulestype' ) === '' ) ) {
7988						showTotal = true;
7989					}
7990
7991					field.find( 'option' ).data( 'isset', 0 );
7992					setter.data( 'isset', 1 );
7993
7994					if ( ! ( setter.val() === '' && setter.attr( 'data-rulestype' ) === '' ) ) {
7995						_value = setter.attr( 'data-text' );
7996						dofloatingBoxData = true;
7997						_valueText = _value;
7998					}
7999				} else if ( field.is( '.tmcp-selectmultiple' ) ) {
8000					setter = field.find( 'option:selected' );
8001					setter.toArray().forEach( function( setterel ) {
8002						setterel = $( setterel );
8003						option_price = option_price + $.epoAPI.math.toFloat( setterel.data( noDpd + 'raw_price' ) );
8004						option_price_taxed = option_price_taxed + $.epoAPI.math.toFloat( setterel.data( noDpd + 'price' ) );
8005						option_original_price = option_original_price + $.epoAPI.math.toFloat( setterel.data( noDpd + 'raw_original_price' ) );
8006						option_original_price_taxed = option_original_price_taxed + $.epoAPI.math.toFloat( setterel.data( noDpd + 'original_price' ) );
8007
8008						options = field.children( 'option:selected' );
8009						if ( ! ( options.val() === '' && options.attr( 'data-rulestype' ) === '' ) ) {
8010							showTotal = true;
8011						}
8012
8013						field.find( 'option' ).data( 'isset', 0 );
8014						setterel.data( 'isset', 1 );
8015
8016						if ( ! ( setterel.val() === '' && setterel.attr( 'data-rulestype' ) === '' ) ) {
8017							_value = setterel.attr( 'data-text' );
8018							dofloatingBoxData = true;
8019							_valueText = _value;
8020						}
8021					} );
8022				} else {
8023					fieldval = field.val();
8024					if ( field.is( "[type='file']" ) ) {
8025						fieldval = fieldval.replace( 'C:\\fakepath\\', '' );
8026					}
8027					if ( fieldval ) {
8028						if ( field.is( '.tmcp-range' ) && fieldval === '0' ) {
8029							field.data( 'isset', 0 );
8030						} else {
8031							option_price = field.data( noDpd + 'raw_price' );
8032							option_price_taxed = field.data( noDpd + 'price' );
8033							option_original_price = field.data( noDpd + 'raw_original_price' );
8034							option_original_price_taxed = field.data( noDpd + 'original_price' );
8035							showTotal = true;
8036							field.data( 'isset', 1 );
8037
8038							_value = fieldval;
8039							if ( field.is( '.tmcp-range' ) ) {
8040								forrangepicker = field.closest( '.tmcp-field-wrap' ).find( '.tm-range-picker' );
8041								$decimals = forrangepicker.attr( 'data-step' ).split( '.' );
8042								if ( $decimals.length === 1 ) {
8043									$decimals = 0;
8044								} else {
8045									$decimals = $decimals[ 1 ].length;
8046								}
8047								_value = formatPrice( _value, { precision: $decimals } );
8048							}
8049							dofloatingBoxData = true;
8050							_valueText = fieldval;
8051						}
8052					} else {
8053						field.data( 'isset', 0 );
8054					}
8055				}
8056				if ( ! option_price ) {
8057					option_price = 0;
8058				}
8059				if ( ! option_original_price ) {
8060					option_original_price = 0;
8061				}
8062				if ( ! option_price_taxed ) {
8063					option_price_taxed = 0;
8064				}
8065				if ( ! option_original_price_taxed ) {
8066					option_original_price_taxed = 0;
8067				}
8068				if ( dofloatingBoxData ) {
8069					floatingBoxData.push( {
8070						title: field_title,
8071						value: _value,
8072						valueText: _valueText,
8073						price: option_price_taxed,
8074						original_price: option_original_price_taxed,
8075						quantity: option_quantity,
8076						label_show: field_label_show,
8077						value_show: field_value_show,
8078						input_type: field.attr( 'type' )
8079					} );
8080				}
8081				if ( setPriceTax ) {
8082					option_price = tm_set_tax_price( option_price, epoObject.this_epo_totals_container, field, undefined, undefined, undefined, true );
8083					option_original_price = tm_set_tax_price( option_original_price, epoObject.this_epo_totals_container, field, undefined, undefined, undefined, true );
8084				}
8085				total = $.epoAPI.math.toFloat( total ) + $.epoAPI.math.toFloat( option_price );
8086				total = $.epoAPI.math.toFloat( $.epoAPI.math.round( total, 10 ) );
8087				original_total = $.epoAPI.math.toFloat( original_total ) + $.epoAPI.math.toFloat( option_original_price );
8088				original_total = $.epoAPI.math.toFloat( $.epoAPI.math.round( original_total, 10 ) );
8089			}
8090		} );
8091
8092		priceArray = {
8093			total: total,
8094			original_total: original_total,
8095			floatingBoxData: floatingBoxData,
8096			showTotal: showTotal,
8097			elementsLength: obj.length
8098		};
8099
8100		if ( priceCache === true ) {
8101			priceCache = {};
8102			priceCache[ priceCacheSelector ] = priceArray;
8103		} else if ( priceCache !== true && priceCache !== false ) {
8104			priceCache[ priceCacheSelector ] = priceArray;
8105		}
8106
8107		return priceArray;
8108	}
8109
8110	function show_product_html( thisEpoObject, thisMainProduct, thisVariableProductContainer, type, $this, currentCart, variableProductContainers, isTrigger, qtyalt ) {
8111		var epoObjectCopy = $.extend( true, {}, thisEpoObject );
8112		var item_tm_extra_product_options = thisVariableProductContainer.find( tcAPI.associatedEpoSelector );
8113		var item = thisVariableProductContainer;
8114		var newEpoObject;
8115		var showOnly = true;
8116
8117		if ( item.closest( '.cpf-element' ).is( '.tc-hidden' ) ) {
8118			return;
8119		}
8120
8121		variableProductContainers.addClass( 'tm-hidden' );
8122		if ( variableProductContainers.length ) {
8123			toggleState( variableProductContainers, true );
8124		}
8125
8126		if ( type === 'variable' ) {
8127			if ( ! thisVariableProductContainer.is( '.tc-init-variations' ) ) {
8128				thisVariableProductContainer.addClass( 'variations_form' );
8129				setTimeout( function() {
8130					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 );
8131					thisVariableProductContainer.addClass( 'tc-init-variations' );
8132					thisVariableProductContainer.tc_product_variation_form( $this, currentCart, variableProductContainers, newEpoObject );
8133				}, 40 );
8134				showOnly = false;
8135			} else {
8136				thisVariableProductContainer.trigger( 'refresh.tc-variation-form' );
8137			}
8138		} else if ( ! thisVariableProductContainer.is( '.tc-init-product' ) ) {
8139			thisVariableProductContainer.addClass( 'tc-init-product' );
8140			variableProductContainers.find( '.tc-epo-element-variable-product' ).removeClass( 'variations_form' );
8141			variableProductContainers.find( '.tc-epo-element-variations' ).removeClass( 'variations' );
8142
8143			setTimeout( function() {
8144				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 );
8145			}, 20 );
8146			showOnly = false;
8147		}
8148
8149		setTimeout( function() {
8150			if ( variableProductContainers.length ) {
8151				toggleState( thisVariableProductContainer, false );
8152			}
8153		}, 200 );
8154		setTimeout( function() {
8155			if ( qtyalt.length ) {
8156				qtyalt.trigger( 'change' );
8157			}
8158			thisVariableProductContainer.removeClass( 'tm-hidden' );
8159			if ( showOnly ) {
8160				jWindow.trigger( 'cpflogicdone' );
8161				thisVariableProductContainer.find( '.tm-quantity' ).trigger( 'showhide.cpfcustom' );
8162			}
8163			if ( isTrigger === undefined && TMEPOJS.tm_epo_global_product_element_scroll === 'yes' ) {
8164				jWindow.tcScrollTo( thisVariableProductContainer, 200, $.epoAPI.math.toFloat( TMEPOJS.tm_epo_global_product_element_scroll_offset ) );
8165			}
8166		}, 210 );
8167	}
8168
8169	function epoEventHandlers( epoObject, cartContainer, alternativeCart ) {
8170		// if cartContainer & alternativeCart is defined we are on a non default product (eg. composite product)
8171		var product_id = epoObject.product_id;
8172		var main_product = epoObject.main_product;
8173		var main_cart = epoObject.main_cart;
8174		var this_epo_container = epoObject.this_epo_container;
8175		var this_totals_container = epoObject.this_totals_container;
8176		var this_epo_totals_container = epoObject.this_epo_totals_container;
8177		var epoEventId = epoObject.epoEventId;
8178		var main_epo_inside_form = epoObject.main_epo_inside_form;
8179		var epo_id_selector = epoObject.epo_id_selector;
8180		var epo_id = epoObject.epo_id;
8181		var product_id_selector = epoObject.product_id_selector;
8182		var itemId = 'main';
8183		var epoHolder;
8184		var totalsHolderContainer;
8185		var totalsHolder;
8186		var currentCart;
8187		var variation_id_selector;
8188		var this_product_type;
8189		var variationForm;
8190		var qtyElement;
8191		var finalTotalBoxMode;
8192		var eventName = epoObject.is_associated ? 'tc-variation-form' : 'wc-variation-form';
8193		var eventNamePrefix = epoObject.is_associated ? 'tc_' : '';
8194		var epoVariationSection;
8195		var thismaxlength;
8196		var epoFieldAll;
8197		var selectSelector;
8198		var epoFieldText;
8199		var epoResetRadio;
8200		var epoFieldUpload;
8201		var epoFieldHasClearButton;
8202		var tmQty;
8203		var tmQuantity;
8204
8205		// Non default product (eg. composite product)
8206		if ( alternativeCart && cartContainer ) {
8207			itemId = $.epoAPI.applyFilter( 'tc_get_item_id', cartContainer.attr( 'data-item_id' ), cartContainer );
8208			epoHolder = main_product.find( '.tm-extra-product-options.tm-cart-' + itemId );
8209			totalsHolderContainer = main_product.find( '.tm-totals-form-' + itemId );
8210			totalsHolder = main_product.find( '.tm-epo-totals.tm-cart-' + itemId );
8211			variationForm = cartContainer.find( '.variations_form' ).first();
8212		// Default product
8213		} else {
8214			if ( ! main_cart || main_cart.length === 0 ) {
8215				if ( this_epo_container.is( '.tc-shortcode' ) ) {
8216					main_cart = main_product;
8217				} else {
8218					main_cart = get_main_cart( main_product, main_product, 'form', product_id );
8219				}
8220			}
8221			cartContainer = main_cart.parent();
8222			epoHolder = this_epo_container;
8223			totalsHolderContainer = this_totals_container;
8224			totalsHolder = this_epo_totals_container;
8225			variationForm = epoObject.variations_form;
8226		}
8227
8228		if ( epoObject.is_associated ) {
8229			itemId = epoHolder.attr( 'data-cart-id' );
8230		}
8231
8232		currentCart = alternativeCart || main_cart;
8233		totalsHolder.data( 'tm_for_cart', currentCart );
8234
8235		variation_id_selector = getVariationIdSelector( currentCart );
8236		qtyElement = getQtyElement( currentCart );
8237
8238		totalsHolder.data( 'variationIdElement', getVariationIdElement( currentCart, '.wceb_picker_wrap ' + variation_id_selector ) );
8239		totalsHolder.data( 'qty_element', qtyElement );
8240
8241		this_product_type = totalsHolder.data( 'type' );
8242
8243		variationForm.data( 'tc_product_id', product_id );
8244
8245		finalTotalBoxMode = totalsHolder.attr( 'data-tm-epo-final-total-box' );
8246
8247		jWindow.on( 'epoCalculateRules', function( event, dataObject ) {
8248			if ( event && dataObject && dataObject.currentCart ) {
8249				tm_epo_rules( epoObject, dataObject.currentCart );
8250			}
8251		} );
8252
8253		if ( currentCart.is( 'form' ) ) {
8254			currentCart.on( 'reset', function() {
8255				var form = $( this );
8256				setTimeout( function() {
8257					$( form.data( 'epo_id_selector' ) ).find( '.tm-epo-field' ).trigger( 'change' );
8258				}, 1 );
8259			} );
8260		}
8261
8262		tm_epo_rules( epoObject, currentCart );
8263
8264		epoFieldAll = epoHolder.find( '.tm-epo-field' );
8265		if ( ! epoObject.is_associated ) {
8266			epoFieldAll = epoFieldAll.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector + ' .tm-epo-field' );
8267		}
8268
8269		epoFieldText = epoHolder.find( '.tm-epo-field.tmcp-textarea,.tm-epo-field.tmcp-textfield' );
8270		if ( ! epoObject.is_associated ) {
8271			epoFieldText = epoFieldText.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector + ' .tm-epo-field' );
8272		}
8273
8274		epoResetRadio = epoHolder.find( '.tm-epo-reset-radio' );
8275		if ( ! epoObject.is_associated ) {
8276			epoResetRadio = epoResetRadio.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector + ' .tm-epo-reset-radio' );
8277		}
8278
8279		epoFieldUpload = epoHolder.find( '.tm-epo-field.tmcp-upload' );
8280		if ( ! epoObject.is_associated ) {
8281			epoFieldUpload = epoFieldUpload.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector + ' .tm-epo-field.tmcp-upload' );
8282		}
8283
8284		epoFieldHasClearButton = epoHolder.find( '.tm-has-clearbutton .tm-epo-field' );
8285		if ( ! epoObject.is_associated ) {
8286			epoFieldHasClearButton = epoFieldHasClearButton.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector + ' .tm-has-clearbutton .tm-epo-field' );
8287		}
8288
8289		tmQty = epoHolder.find( '.tm-quantity .tm-qty' );
8290		if ( ! epoObject.is_associated ) {
8291			tmQty = tmQty.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector + ' .tm-quantity .tm-qty' );
8292		}
8293
8294		tmQuantity = epoHolder.find( '.tm-quantity' );
8295		if ( ! epoObject.is_associated ) {
8296			tmQuantity = tmQuantity.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector + ' .tm-quantity' );
8297		}
8298
8299		selectSelector = epoHolder.find( 'select.tm-epo-field' );
8300		if ( ! epoObject.is_associated ) {
8301			selectSelector = selectSelector.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector + ' select.tm-epo-field' );
8302		}
8303		// update price amount for select elements
8304		selectSelector
8305			.off( 'tm-select-change-html' )
8306			.on( 'tm-select-change-html', function() {
8307				var field = $( this );
8308				var formatted_price;
8309				var original_formatted_price;
8310				var e_tip;
8311				var e_description;
8312				var sign;
8313
8314				if ( field.is( '.tc-epo-field-product' ) || field.is( '.tmcp-selectmultiple' ) ) {
8315					return;
8316				}
8317
8318				if ( main_cart && main_cart.data( 'per_product_pricing' ) !== undefined && ! main_cart.data( 'per_product_pricing' ) ) {
8319					return;
8320				}
8321
8322				formatted_price = tm_set_price( field.find( 'option:selected' ).data( 'price' ), totalsHolder, true, false, field );
8323				original_formatted_price = tm_set_price( field.find( 'option:selected' ).data( 'original_price' ), totalsHolder, true, false, field );
8324				e_tip = field.closest( '.tmcp-field-wrap' ).find( '.tc-tooltip' );
8325				e_description = field.closest( '.tmcp-field-wrap' ).find( '.tc-inline-description' );
8326
8327				tm_update_price( field.closest( '.tmcp-field-wrap' ).find( '.tc-price' ), field.find( 'option:selected' ).data( 'price' ), formatted_price, field.find( 'option:selected' ).data( 'original_price' ), original_formatted_price );
8328
8329				if ( e_tip.length > 0 ) {
8330					e_tip.attr( 'data-tm-tooltip-html', field.find( 'option:selected' ).attr( 'data-tm-tooltip-html' ) ).trigger( 'tc-tooltip-html-changed' );
8331				}
8332
8333				if ( e_description.length > 0 ) {
8334					if ( field.find( 'option:selected' ).attr( 'data-tm-tooltip-html' ) ) {
8335						e_description.html( field.find( 'option:selected' ).attr( 'data-tm-tooltip-html' ) );
8336					} else {
8337						e_description.html( '' );
8338					}
8339				}
8340
8341				if (
8342					( field.find( 'option:selected' ).attr( 'data-hide-amount' ) === '0' || TMEPOJS.tm_epo_show_price_inside_option_hidden_even === 'yes' ) &&
8343					TMEPOJS.tm_epo_show_price_inside_option === 'yes' &&
8344					field.find( 'option:selected' ).attr( 'data-text' )
8345				) {
8346					if (
8347						( TMEPOJS.tm_epo_auto_hide_price_if_zero === 'yes' && $.tmempty( field.find( 'option:selected' ).data( 'price' ) ) === false ) ||
8348						( TMEPOJS.tm_epo_auto_hide_price_if_zero !== 'yes' && field.find( 'option:selected' ).attr( 'data-
8348price' ) !== '' )
8349					) {
8350						sign = '';
8351						field.find( 'option:selected' ).html( field.find( 'option:selected' ).attr( 'data-text' ) + ' (' + sign + formatted_price + ')' );
8352					}
8353				}
8354
8355				if ( field.val() === '' ) {
8356					e_tip.addClass( 'tm-hidden' );
8357				} else if ( field.find( 'option:selected' ).attr( 'data-tm-tooltip-html' ) ) {
8358					e_tip.removeClass( 'tm-hidden' );
8359				} else {
8360					e_tip.addClass( 'tm-hidden' );
8361				}
8362			} )
8363			.off( 'tm-math-select-change-html-all tm-select-change-html-all tm-select-change-html-all-math' )
8364			.on( 'tm-math-select-change-html-all tm-select-change-html-all tm-select-change-html-all-math', function( event ) {
8365				var field = $( this );
8366				var e_tip;
8367				var e_description;
8368				var thisoption;
8369				var divider;
8370				var thisformatted_price;
8371
8372				if ( field.is( '.tc-epo-field-product' ) ) {
8373					return;
8374				}
8375
8376				e_tip = field.closest( '.tmcp-field-wrap' ).find( '.tc-tooltip' );
8377				e_description = field.closest( '.tmcp-field-wrap' ).find( '.tc-inline-description' );
8378
8379				if ( e_tip.length > 0 ) {
8380					e_tip.attr( 'data-tm-tooltip-html', field.find( 'option:selected' ).attr( 'data-tm-tooltip-html' ) ).trigger( 'tc-tooltip-html-changed' );
8381				}
8382
8383				if ( field.val() === '' ) {
8384					e_tip.addClass( 'tm-hidden' );
8385				} else if ( field.find( 'option:selected' ).attr( 'data-tm-tooltip-html' ) ) {
8386					e_tip.removeClass( 'tm-hidden' );
8387				} else {
8388					e_tip.addClass( 'tm-hidden' );
8389				}
8390
8391				if ( e_description.length > 0 ) {
8392					if ( field.find( 'option:selected' ).attr( 'data-tm-tooltip-html' ) ) {
8393						e_description.html( field.find( 'option:selected' ).attr( 'data-tm-tooltip-html' ) );
8394					} else {
8395						e_description.html( '' );
8396					}
8397				}
8398
8399				if ( main_cart && main_cart.data( 'per_product_pricing' ) !== undefined && ! main_cart.data( 'per_product_pricing' ) ) {
8400					return;
8401				}
8402
8403				if ( TMEPOJS.tm_epo_show_price_inside_option === 'yes' ) {
8404					field.find( 'option' ).each( function() {
8405						thisoption = $( this );
8406						if ( ! thisoption.val() ) {
8407							return true;
8408						}
8409
8410						if ( event.type === 'tm-select-change-html-all' ) {
8411							thisoption.removeClass( 'tm-epo-late-field' ).removeData( 'tm-price-for-late islate' );
8412							tm_element_epo_rules( epoObject, field, undefined, thisoption, 1 );
8413						} else if ( event.type === 'tm-math-select-change-html-all' ) {
8414							tm_element_epo_rules( epoObject, field, undefined, thisoption, 1, true );
8415						} else if ( event.type === 'tm-select-change-html-all-math' ) {
8416							thisoption.removeClass( 'tm-epo-late-field' ).removeData( 'tm-price-for-late islate' );
8417							tm_element_epo_rules( epoObject, field, undefined, thisoption, 1, true );
8418						}
8419						divider = 1;
8420
8421						if ( TMEPOJS.tm_epo_multiply_price_inside_option !== 'yes' ) {
8422							divider = field.data( 'tm-quantity' );
8423						}
8424
8425						if ( ! divider ) {
8426							divider = 1;
8427						}
8428
8429						thisformatted_price = tm_set_price( thisoption.data( 'price' ) / divider, totalsHolder, true, false, field );
8430
8431						if ( ( thisoption.attr( 'data-hide-amount' ) === '0' || TMEPOJS.tm_epo_show_price_inside_option_hidden_even === 'yes' ) && thisoption.attr( 'data-text' ) ) {
8432							if ( ( TMEPOJS.tm_epo_auto_hide_price_if_zero === 'yes' && $.tmempty( thisoption.data( 'price' ) ) === false ) || ( TMEPOJS.tm_epo_auto_hide_price_if_zero !== 'yes' && thisoption.attr( 'data-price' ) !== '' ) ) {
8433								thisoption.html( thisoption.attr( 'data-text' ) + ' (' + thisformatted_price + ')' );
8434							}
8435						}
8436					} );
8437				}
8438			} )
8439			.off( 'tm-select-change' )
8440			.on( 'tm-select-change', function() {
8441				var field = $( this );
8442				var thisElementId = field.closest( '.cpf-element' ).attr( 'data-uniqid' );
8443
8444				if ( field.is( '.tc-epo-field-product' ) ) {
8445					return;
8446				}
8447
8448				if ( main_cart && main_cart.data( 'per_product_pricing' ) !== undefined && ! main_cart.data( 'per_product_pricing' ) ) {
8449					return;
8450				}
8451
8452				field.removeData( 'addedtcEpoBeforeOptionPriceCalculation' );
8453				field.removeData( 'addedfieldtcEpoBeforeOptionPriceCalculation' );
8454				jWindow.off( 'tcEpoBeforeOptionPriceCalculation.math' + thisElementId );
8455				jWindow.off( 'tcEpoAfterOptionPriceCalculation.math' + thisElementId );
8456
8457				field.trigger( 'tm-select-change-html' );
8458				field.trigger( 'tm-select-change-html-all' );
8459
8460				currentCart.trigger( {
8461					type: 'tm-epo-update',
8462					norules: 1,
8463					element: field
8464				} );
8465			} ).trigger( 'tm-select-change-html-all' );
8466
8467		// Element quantity selector
8468		tmQty
8469			.off( 'focus.cpf' )
8470			.on( 'focus.cpf', function() {
8471				var qtyField = $( this );
8472				var field = qtyField.closest( '.tmcp-field-wrap' ).find( '.tm-epo-field' );
8473				var currentVal = parseFloat( qtyField.val() );
8474				var max = parseFloat( qtyField.attr( 'max' ) );
8475				var min = parseFloat( qtyField.attr( 'min' ) );
8476				var step = qtyField.attr( 'step' );
8477				var check1 = tm_limit_c_selection( field, false );
8478				var check2 = tm_exact_c_selection( field, false );
8479				var check3 = true;
8480
8481				// Format values
8482				if ( ! currentVal || currentVal === '' || currentVal === 'NaN' ) {
8483					currentVal = 0;
8484				}
8485				if ( max === '' || max === 'NaN' ) {
8486					max = '';
8487				}
8488				if ( min === '' || min === 'NaN' ) {
8489					min = 0;
8490				}
8491				if ( step === 'any' || step === '' || step === undefined || parseFloat( step ) 
8491=== 'NaN' ) {
8492					step = 1;
8493				}
8494
8495				if ( currentVal < min || currentVal > max ) {
8496					check3 = false;
8497				}
8498
8499				if ( check1 && check2 && check3 ) {
8500					qtyField.data( 'tm-prev-value', currentVal );
8501				} else {
8502					qtyField.data( 'tm-prev-value', min );
8503				}
8504			} )
8505			.off( 'change.cpf' )
8506			.on( 'change.cpf', function( event, data ) {
8507				var qtyField = $( this );
8508				var field = qtyField.closest( '.tmcp-field-wrap' ).find( '.tm-epo-field' );
8509				var currentVal = parseFloat( qtyField.val() );
8510				var max = parseFloat( qtyField.attr( 'max' ) );
8511				var min = parseFloat( qtyField.attr( 'min' ) );
8512				var step = qtyField.attr( 'step' );
8513				var check1 = tm_limit_c_selection( field, false );
8514				var check2 = tm_exact_c_selection( field, false );
8515				var check3 = true;
8516
8517				// Format values
8518				if ( ! currentVal || currentVal === '' || currentVal === 'NaN' ) {
8519					currentVal = 0;
8520				}
8521				if ( max === '' || max === 'NaN' ) {
8522					max = '';
8523				}
8524				if ( min === '' || min === 'NaN' ) {
8525					min = 0;
8526				}
8527				if ( step === 'any' || step === '' || step === undefined || parseFloat( step ) === 'NaN' ) {
8528					step = 1;
8529				}
8530
8531				if ( currentVal < min || currentVal > max ) {
8532					check3 = false;
8533				}
8534
8535				if ( check1 && check2 && check3 ) {
8536					if ( ! epoObject.noEpoUpdate ) {
8537						field.data( 'tm-quantity', qtyField.val() ).trigger( 'change', data );
8538					} else {
8539						field.data( 'tm-quantity', qtyField.val() ).trigger( 'change.cpf', data ).trigger( 'change.cpfproduct', data );
8540					}
8541					field.trigger( 'tm-select-change-html-all' );
8542				} else if ( qtyField.data( 'tm-prev-value' ) ) {
8543					qtyField.val( qtyField.data( 'tm-prev-value' ) );
8544				} else {
8545					qtyField.val( min );
8546				}
8547
8548				qtyField.trigger( 'cpf-changed' );
8549			} )
8550			.off( 'tmaddquantity' )
8551			.on( 'tmaddquantity', function() {
8552				var qtyField = $( this );
8553				var field = qtyField.closest( '.tmcp-field-wrap' ).find( '.tm-epo-field' );
8554
8555				field.data( 'tm-quantity', qtyField.val() );
8556			} );
8557
8558		// Insert characters remaining for text-areas and text-fields
8559		thismaxlength = epoHolder.find( '.tmcp-textfield.tm-epo-field[maxlength],textarea.tm-epo-field[maxlength]' );
8560		if ( ! epoObject.is_associated ) {
8561			thismaxlength = thismaxlength.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector + ' .tm-epo-field' );
8562		}
8563
8564		thismaxlength.each( function() {
8565			var field = $( this );
8566			var html = $.epoAPI.template.html( tcAPI.templateEngine.tc_chars_remanining, {
8567				maxlength: field.attr( 'maxlength' ),
8568				characters_remaining: TMEPOJS.i18n_characters_remaining
8569			} );
8570
8571			field.after( $( html ) );
8572		} );
8573		thismaxlength
8574			.off( 'change.tc_maxlen input.tc_maxlen' )
8575			.on( 'change.tc_maxlen input.tc_maxlen', function() {
8576				var field = $( this );
8577
8578				field
8579					.closest( '.tmcp-field-wrap' )
8580					.find( '.tc-chars-remanining' )
8581					.html( parseInt( field.attr( 'maxlength' ), 10 ) - parseInt( field.val().length, 10 ) );
8582			} );
8583
8584		// Change product image event
8585		epoFieldAll
8586			.off( 'tm_trigger_product_image' )
8587			.on( 'tm_trigger_product_image', function() {
8588				var field = $( this );
8589				var currentElement;
8590				var uic;
8591				var variation_element_section;
8592				var is_variation_element;
8593				var src;
8594
8595				if ( field.is( '.tm-product-image:checkbox, .tm-product-image:radio, select.tm-product-image' ) ) {
8596					uic = field.closest( '.tmcp-field-wrap' ).find( 'label img' );
8597					variation_element_section = field.closest( '.cpf-section' );
8598					is_variation_element = variation_element_section.is( '.tm-epo-variation-section' );
8599
8600					currentElement = field;
8601					if ( field.is( 'select.tm-product-image' ) ) {
8602						currentElement = field.children( 'option:selected' );
8603					}
8604					if (
8605						$( uic ).length > 0 ||
8606						( is_variation_element && currentElement.attr( 'data-image' ) !== undefined ) ||
8607						( currentElement.attr( 'data-image' ) !== undefined && currentElement.attr( 'data-image' ) !== '' ) ||
8608						( currentElement.attr( 'data-imagep' ) !== undefined && currentElement.attr( 'data-imagep' ) !== '' )
8609					) {
8610						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' ) ) ) ) {
8611							src = $( uic ).first().attr( 'data-original' );
8612
8613							if ( ! src && ! is_variation_element ) {
8614								src = $( uic ).first().attr( 'src' );
8615							}
8616							if ( ! src ) {
8617								src = currentElement.attr( 'data-image' );
8618							}
8619							if ( currentElement.attr( 'data-imagep' ) ) {
8620								src = currentElement.attr( 'data-imagep' );
8621							}
8622							if ( src ) {
8623								main_product.trigger( 'tm_change_product_image', {
8624									src: src,
8625									element: field,
8626									element_current: currentElement,
8627									main_product: main_product,
8628									epo_holder: epoHolder
8629								} );
8630							} else {
8631								main_product.trigger( 'tm_change_product_image', {
8632									src: false,
8633									element: field,
8634									element_current: currentElement,
8635									main_product: main_product,
8636									epo_holder: epoHolder
8637								} );
8638							}
8639						} else {
8640							main_product.trigger( 'tm_restore_product_image', {
8641								element: field,
8642								element_current: currentElement,
8643								main_product: main_product,
8644								epo_holder: epoHolder
8645							} );
8646						}
8647					} else {
8648						main_product.trigger( 'tm_restore_product_image', {
8649							element: field,
8650							element_current: currentElement,
8651							main_product: main_product,
8652							epo_holder: epoHolder
8653						} );
8654					}
8655				} else {
8656					main_product.trigger( 'tm_attempt_product_image', {
8657						element: field,
8658						element_current: currentElement,
8659						main_product: main_product,
8660						epo_holder: epoHolder
8661					} );
8662				}
8663			} );
8664
8665		tmQuantity
8666			.off( 'showhide.cpfcustom' )
8667			.on( 'showhide.cpfcustom', function() {
8668				var quantity_selector = $( this );
8669				var field = quantity_selector.closest( '.tmcp-field-wrap' ).find( '.tm-epo-field' );
8670				var show = false;
8671				var tmqty;
8672				var tmqtyval;
8673				var tmqtymin;
8674				var radios;
8675
8676				if ( ! field.is( '.tm-epo-variation-element' ) ) {
8677					if ( field.is( 'select' ) ) {
8678						if ( field.val() !== '' ) {
8679							show = true;
8680						}
8681					} else if ( field.is( ':checkbox' ) ) {
8682						if ( field.is( ':checked' ) ) {
8683							show = true;
8684						}
8685					} else if ( field.is( ':radio' ) ) {
8686						if ( field.is( ':checked' ) ) {
8687							show = true;
8688							if ( TMEPOJS.tm_epo_show_only_active_quantities === 'yes' ) {
8689								radios = field.closest( '.tc-element-inner-wrap' ).find( '.tm-epo-field.tmcp-radio' );
8690								radios.each( function() {
8691									$( this ).closest( '.tmcp-field-wrap' ).find( '.tm-quantity' ).hide();
8692								} );
8693							}
8694						}
8695					} else if ( field.val() ) {
8696						show = true;
8697					}
8698
8699					tmqty = quantity_selector.find( '.tm-qty' );
8700					tmqtyval = tmqty.val();
8701					tmqtymin = tmqty.attr( 'min' ) || '';
8702
8703					if ( show ) {
8704						if ( TMEPOJS.tm_epo_show_only_active_quantities === 'yes' ) {
8705							quantity_selector.show();
8706						}
8707
8708						tmqty.removeClass( 'ignore' ).prop( 'disabled', false );
8709					} else {
8710						if ( TMEPOJS.tm_epo_show_only_active_quantities === 'yes' ) {
8711							quantity_selector.hide();
8712							if ( ! tmqtyval ) {
8713								tmqty.val( tmqtymin );
8714							}
8715						}
8716
8717						tmqty.addClass( 'ignore' ).prop( 'disabled', true );
8718					}
8719
8720					setTimeout( function() {
8721						quantity_selector.closest( '.tcowl-carousel' ).trigger( 'refresh.owl.carousel' );
8722					}, 200 );
8723				}
8724			} );
8725
8726		epoFieldAll
8727			.off( 'change.cpfcustom' )
8728			.on( 'change.cpfcustom', function() {
8729				$( this ).closest( '.tmcp-field-wrap' ).find( '.tm-quantity' ).trigger( 'showhide.cpfcustom' );
8730			} );
8731
8732		epoFieldAll
8733			.off( 'change.cpf' )
8734			.on( 'change.cpf', function( event, data ) {
8735				var field = $( this );
8736				var is_li = field.closest( '.tmcp-field-wrap' );
8737				var is_ul = field.closest( '.tmcp-ul-wrap' );
8738				var is_replace;
8739				var connector = is_ul.attr( 'data-tm-connector' );
8740
8741				if ( field.is( ':checkbox, :radio' ) ) {
8742					if ( field.is( ':radio' ) ) {
8743						if ( ! data ) {
8744							if ( connector !== undefined ) {
8745								$( '[data-tm-connector="' + connector + '"]' ).find( '.tmcp-field-wrap' ).removeClass( 'tc-active' );
8746							} else {
8747								is_ul.find( '.tmcp-field-wrap' ).removeClass( 'tc-active' );
8748							}
8749						}
8750						if ( connector !== undefined ) {
8751							$( '[data-tm-connector="' + connector + '"]' ).find( '.tmcp-field-wrap' ).removeClass( 'tc-active' );
8752						}
8753					}
8754					if ( field.is( ':checked' ) ) {
8755						is_li.addClass( 'tc-active' );
8756					} else {
8757						is_li.removeClass( 'tc-active' );
8758					}
8759				}
8760
8761				if ( ! field.is( '.tm-epo-variation-element' ) ) {
8762					if ( field.is( '.use_images:checkbox, .use_images:radio' ) && field.attr( 'data-imagec' ) ) {
8763						is_replace = is_li.find( '.radio-image,.checkbox-image' ).first();
8764						if ( is_replace.length > 0 ) {
8765							if ( field.is( ':checked' ) ) {
8766								is_replace.prop( 'src', field.attr( 'data-imagec' ) );
8767							} else {
8768								is_replace.prop( 'src', field.attr( 'data-image' ) );
8769							}
8770						}
8771					}
8772
8773					if ( field.is( '.use_images:radio' ) ) {
8774						field
8775							.closest( '.cpf-type-radio' )
8776							.find( '.use_images:radio' )
8777							.not( field )
8778							.each( function() {
8779								var r = $( this );
8780								r.closest( '.tmcp-field-wrap' ).find( '.radio-image' ).first().prop( 'src', r.attr( 'data-image' ) );
8781							} );
8782					}
8783
8784					if ( field.is( '.tmcp-range' ) ) {
8785						field.trigger( 'change.cpflogic' );
8786					}
8787					if ( field.is( 'select' ) ) {
8788						field.trigger( 'tm-select-change' );
8789					} else {
8790						if ( field.is( '.tmcp-radio' ) ) {
8791							field
8792								.closest( '.cpf-element' )
8793								.find( '.tm-quantity .tm-qty' )
8794								.each( function() {
8795									if ( ! $( this ).closest( 'li.tmcp-field-wrap' ).find( '.tmcp-radio' ).is( ':checked' ) ) {
8796										$( this ).attr( 'disabled', 'disabled' );
8797									} else {
8798										$( this ).prop( 'disabled', false );
8799									}
8800								} );
8801						}
8802
8803						priceCache = true;
8804						currentCart.trigger( {
8805							type: 'tm-epo-update',
8806							norules: 1,
8807							element: field
8808						} );
8809						priceCache = false;
8810					}
8811				}
8812
8813				field.trigger( 'tm_trigger_product_image' );
8814				setTimeout( function() {
8815					$( '.tm-owl-slider' ).each( function() {
8816						$( this ).trigger( 'refresh.owl.carousel' );
8817					} );
8818				}, 200 );
8819				main_product.trigger( 'tm_attempt_product_image', {
8820					element: field,
8821					main_product: main_product,
8822					epo_holder: epoHolder
8823				} );
8824			} );
8825
8826		epoFieldAll
8827			.filter( ':checkbox:checked, :radio:checked' )
8828			.each( function() {
8829				$( this ).closest( '.tmcp-field-wrap' ).addClass( 'tc-active' );
8830				$( this ).trigger( 'change.cpf' );
8831			} );
8832
8833		epoFieldHasClearButton
8834			.off( 'change.cpfclearbutton' )
8835			.on( 'change.cpfclearbutton cpfclearbutton', function() {
8836				var field = $( this );
8837				var radioResetElement;
8838				var fieldWrap = field.closest( '.tmcp-field-wrap' );
8839				var fieldSearch;
8840
8841				if ( field.is( ':checked' ) ) {
8842					fieldSearch = field.closest( '.tc-element-inner-wrap' );
8843
8844					if ( fieldSearch.find( '.tc-epo-element-product-li-container' ).length ) {
8845						fieldSearch = fieldSearch.find( '.tmcp-ul-wrap' ).first().children( '.tmcp-field-wrap' ).not( '.tc-epo-element-product-li-container' );
8846					}
8847
8848					radioResetElement = fieldSearch.find( '.tm-epo-reset-radio' );
8849					if ( ! radioResetElement.length ) {
8850						radioResetElement = field.closest( '.tc-element-inner-wrap' ).find( '.tm-epo-reset-radio' ).first();
8851					}
8852					radioResetElement.removeClass( 'tm-hidden' );
8853
8854					fieldWrap.append( radioResetElement );
8855				}
8856			} );
8857
8858		epoResetRadio
8859			.off( 'click.cpf' )
8860			.on( 'click.cpf', function() {
8861				var radioResetElement = $( this );
8862				var fieldContainer = radioResetElement.closest( '.tc-element-inner-wrap' );
8863				var checkedRadios = fieldContainer.find( '.tm-epo-field.tmcp-radio:checked' );
8864
8865				if ( checkedRadios.length ) {
8866					checkedRadios.prop( 'checked', false );
8867					checkedRadios.trigger( 'change', { forced: 1 } );
8868				}
8869
8870				radioResetElement.addClass( 'tm-hidden' );
8871			} );
8872
8873		if ( _ && _.debounce ) {
8874			epoFieldText.on( 'keyup',
8875				_.debounce( function() {
8876					var $this = $( this );
8877
8878					if ( TMEPOJS.tm_epo_global_enable_validation === 'yes' && $.tc_validator && $this.closest( '.tmcp-ul-wrap' ).data( 'tm-validation' ) && $this.tc_rules() ) {
8879						currentCart.tc_validate().element( $this );
8880					}
8881					$this.trigger( 'change.cpf' );
8882					$this.closest( '.tmcp-field-wrap' ).find( '.tm-quantity' ).trigger( 'showhide.cpfcustom' );
8883				}, 10 )
8884			);
8885		}
8886
8887		epoFieldUpload
8888			.off( 'change.cpfv tcupload' )
8889			.on( 'change.cpfv tcupload', function() {
8890				var field = $( this );
8891				var label = field.closest( 'label' );
8892				var li = field.closest( '.tmcp-field-wrap' );
8893				var cpfUploadContainer = li.find( '.cpf-upload-container' );
8894				var name = li.find( '.tm-filename' );
8895				var val = field.val().replace( 'C:\\fakepath\\', '' );
8896				var valHidden = [];
8897				var num_uploads;
8898				var windowURL = window.URL || window.webkitURL;
8899				var files;
8900				var image;
8901				var uploadPreview = li.find( '.tc-upload-preview' );
8902				var addImage;
8903				var uniqid;
8904
8905				if ( cpfUploadContainer.length && name.length <= 0 ) {
8906					name = $( '<span class="tm-filename"></span>' );
8907					label.after( name );
8908				}
8909				if ( val === undefined || val === 'undefined' ) {
8910					val = '';
8911				}
8912
8913				field.next( '.tmcp-upload-hidden' ).remove();
8914
8915				valHidden = field.attr( 'data-file' );
8916				valHidden = valHidden ? valHidden.split( '|' ) : [];
8917				if ( this.files ) {
8918					files = Array.from( this.files );
8919				} else if ( valHidden.length > 0 ) {
8920					files = valHidden;
8921				}
8922
8923				if ( files.length > 1 ) {
8924					name.html( '' + files.length + ' ' + ( files.length === 1 ? TMEPOJS.i18n_file : TMEPOJS.i18n_files ) );
8925				} else if ( files.length === 1 ) {
8926					name.html( val );
8927				} else {
8928					name.empty();
8929				}
8930				if ( ! uploadPreview.length ) {
8931					uploadPreview = $( '<div class="tc-upload-preview tc-hidden"></div>' );
8932					li.append( uploadPreview );
8933				}
8934
8935				uploadPreview.empty();
8936
8937				num_uploads = epoHolder.data( 'num_uploads' );
8938				if ( ! num_uploads ) {
8939					num_uploads = [];
8940				}
8941				uniqid = field.closest( '.cpf-element' ).attr( 'data-uniqid' );
8942				if ( ! num_uploads[ uniqid ] ) {
8943					num_uploads[ uniqid ] = [];
8944				}
8945
8946				if ( ( val || files.length > 0 ) && windowURL && windowURL.createObjectURL ) {
8947					if ( TMEPOJS.tm_epo_upload_inline_image_preview === 'yes' ) {
8948						if ( files.length > 1 ) {
8949							uploadPreview.addClass( 'multiple' );
8950						} else {
8951							uploadPreview.removeClass( 'multiple' );
8952						}
8953						uploadPreview.removeClass( 'tc-hidden' );
8954					}
8955					addImage = function( dataFile, src, i, fileHolder, ext ) {
8956						var size = field[ 0 ].files && field[ 0 ].files[ i ] && field[ 0 ].files[ i ].size ? field[ 0 ].files[ i ].size : 0;
8957						var imageHTML = '<div class="tc-upload-image">';
8958						if ( src ) {
8959							imageHTML = imageHTML + '<img src="' + src + '">';
8960						} else {
8961							imageHTML = imageHTML + '<div class="tc-file-ext-overlay"></div>';
8962						}
8963						imageHTML = imageHTML + '<div class="tc-file-name">' + dataFile.name + '</div>';
8964						if ( ClipboardEvent || DataTransfer ) {
8965							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>';
8966						}
8967						if ( ext ) {
8968							imageHTML = imageHTML + '<div class="tc-file-ext">' + ext + '</div>';
8969						}
8970						imageHTML = imageHTML + '<div class="tc-file-size">' + readableFileSize( size ) + '</div>';
8971						imageHTML = imageHTML + '</div>';
8972						fileHolder.append( imageHTML );
8973					};
8974
8975					files.forEach( function( dataFile, i ) {
8976						var fileHolder;
8977						if ( TMEPOJS.tm_epo_upload_inline_image_preview === 'yes' ) {
8978							fileHolder = $( '<div class="tc-upload-file"></div>' );
8979							uploadPreview.append( fileHolder );
8980							image = new Image();
8981							image.onload = function() {
8982								addImage( dataFile, this.src, i, fileHolder );
8983							};
8984							image.onerror = function() {
8985								addImage( dataFile, false, i, fileHolder, dataFile.name.split( '.' ).pop() );
8986							};
8987							if ( valHidden.length > 0 ) {
8988								image.src = valHidden[ i ];
8989							} else {
8990								image.src = windowURL.createObjectURL( dataFile );
8991								windowURL.revokeObjectURL( dataFile );
8992							}
8993						}
8994						num_uploads[ uniqid ].push( dataFile.name );
8995					} );
8996					epoHolder.data( 'num_uploads', num_uploads );
8997				} else {
8998					delete num_uploads[ uniqid ];
8999				}
9000				if ( num_uploads[ uniqid ] && num_uploads[ uniqid ].length === 0 ) {
9001					delete num_uploads[ uniqid ];
9002				}
9003			} );
9004
9005		jDocument.on( 'click', '.tc-upload-remove', function() {
9006			var $this = $( this );
9007			var val;
9008			var cpfElement;
9009			var input;
9010			var fileWrap;
9011			var li;
9012			var uploadPreview;
9013			var name;
9014			var index;
9015			var files;
9016			var dT;
9017			var num_uploads;
9018			var uniqid;
9019			var uploadHidden;
9020			var dataFiles;
9021
9022			if ( ClipboardEvent || DataTransfer ) {
9023				cpfElement = $this.closest( '.cpf-element' );
9024				input = cpfElement.find( '.tm-epo-field' );
9025				fileWrap = $this.closest( '.tc-upload-file' );
9026				li = $this.closest( '.tmcp-field-wrap' );
9027				uploadPreview = li.find( '.tc-upload-preview' );
9028				name = li.find( '.tm-filename' );
9029				index = fileWrap.index();
9030				val = input.val().replace( 'C:\\fakepath\\', '' );
9031				if ( val === undefined || val === 'undefined' ) {
9032					val = '';
9033				}
9034
9035				files = Array.from( input[ 0 ].files );
9036				files.splice( index, 1 );
9037				dT = new ClipboardEvent( '' ).clipboardData || new DataTransfer();
9038
9039				files.forEach( function( dataFile ) {
9040					dT.items.add( dataFile );
9041				} );
9042
9043				if ( files.length > 1 ) {
9044					uploadPreview.addClass( 'multiple' );
9045				} else {
9046					uploadPreview.removeClass( 'multiple' );
9047				}
9048
9049				input[ 0 ].files = dT.files;
9050				fileWrap.remove();
9051				if ( dT.files.length > 1 ) {
9052					name.html( '' + dT.files.length + ' ' + ( dT.files.length === 1 ? TMEPOJS.i18n_file : TMEPOJS.i18n_files ) );
9053				} else if ( dT.files.length === 1 ) {
9054					name.html( val );
9055				} else {
9056					name.empty();
9057				}
9058
9059				num_uploads = epoHolder.data( 'num_uploads' );
9060				if ( ! num_uploads ) {
9061					num_uploads = [];
9062				}
9063				uniqid = cpfElement.closest( '.cpf-element' ).attr( 'data-uniqid' );
9064				if ( ! num_uploads[ uniqid ] ) {
9065					num_uploads[ uniqid ] = [];
9066				}
9067
9068				num_uploads[ uniqid ].splice( index, 1 );
9069				if ( num_uploads[ uniqid ].length === 0 ) {
9070					delete num_uploads[ uniqid ];
9071					input.val( '' );
9072				}
9073
9074				uploadHidden = input.next( '.tmcp-upload-hidden' );
9075				if ( uploadHidden.length ) {
9076					dataFiles = uploadHidden.val().split( '|' );
9077					if ( dataFiles.length > 0 ) {
9078						dataFiles.splice( index, 1 );
9079					}
9080					if ( dataFiles.length === 0 ) {
9081						uploadHidden.remove();
9082					} else {
9083						uploadHidden.val( dataFiles.join( '|' ) );
9084					}
9085				}
9086
9087				epoHolder.data( 'num_uploads', num_uploads );
9088			}
9089		} );
9090
9091		qtyElement
9092			.off( 'change.cpf input.cpf' )
9093			.on( 'change.cpf input.cpf', function() {
9094				var field = $( this );
9095
9096				currentCart.trigger( 'tm-epo-check-dpd' );
9097				field.data( 'tm-prev-value', field.val() );
9098				// It is required than when you update the product quantity
9099				// to recalculate the option price to accommodate price types
9100				// that depend on quantity
9101				currentCart.trigger( {
9102					type: 'tm-epo-update',
9103					norules: 2
9104				} );
9105			} )
9106			.data( 'tm-prev-value', qtyElement.val() );
9107
9108		// Support math formula on associated product when they are initially hidden
9109		epoHolder
9110			.find( '.cpf-type-product' )
9111			.off( 'tc-logic' )
9112			.on( 'tc-logic', function() {
9113				var $this = $( this );
9114				if ( $this.find( '.tc-init' ).lengh ) {
9115					return;
9116				}
9117				if ( $this.data( 'isactive' ) && ! $this.data( 'donetclogic' ) ) {
9118					$this.data( 'donetclogic', true );
9119					$this.find( '.tc-epo-field-product' ).trigger( 'change.cpfproduct', { forced: 1 } );
9120				}
9121			} );
9122
9123		// Product element checkbox requires status fix
9124		epoHolder
9125			.find( '.cpf-type-product .tc-epo-field-product.tc-epo-field-product-checkbox' )
9126			.off( 'change.cpfrequired' )
9127			.on( 'change.cpfrequired', function() {
9128				var $this = $( this );
9129				var cpfElement = $this.closest( '.cpf-element' );
9130				var checkboxes;
9131				var checkboxesChecked;
9132				var checkboxesNotChecked;
9133				if ( cpfElement.is( '.tc-is-required' ) ) {
9134					checkboxes = cpfElement.find( '.tmcp-field.tc-epo-field-product-checkbox' );
9135					checkboxesNotChecked = checkboxes.not( ':checked' );
9136					checkboxesChecked = cpfElement.find( '.tmcp-field.tc-epo-field-product-checkbox:checked' );
9137
9138					if ( checkboxesChecked.length > 0 ) {
9139						checkboxesNotChecked.removeAttr( 'required' );
9140						checkboxesNotChecked.prop( 'required', false );
9141						checkboxesChecked.attr( 'required', true );
9142						checkboxesChecked.prop( 'required', true );
9143					} else {
9144						checkboxes.attr( 'required', true );
9145						checkboxes.prop( 'required', true );
9146					}
9147				}
9148			} );
9149
9150		// Product element variable product support
9151		epoHolder
9152			.find( '.cpf-type-product .tc-epo-field-product' )
9153			.off( 'change.cpfproduct' )
9154			.on( 'change.cpfproduct', function( e, data ) {
9155				var $this = $( this );
9156				var value;
9157				var type;
9158				var selected;
9159				var variableProductContainers;
9160				var thisVariableProductContainer;
9161				var elementContainer = $this.closest( '.cpf-element' );
9162				var productContainerWraps = elementContainer.find( '.tc-epo-element-product-container-wrap' );
9163				var thisProductContainerWrap = $this.closest( '.tmcp-field-wrap' ).find( '.tc-epo-element-product-container-wrap' );
9164				var hasProductContainerWrap = thisProductContainerWrap.length > 0;
9165				var postData;
9166				var skip = false;
9167				var isTrigger = 1000;
9168				var qtyalt;
9169				var associatedSetter = $this;
9170				var associatedElement;
9171				var isFilled;
9172				var productPrice;
9173				var originalProductPrice;
9174				var epoField = elementContainer.find( '.tm-epo-field' ).not( '.tc-epo-element-product-li-container .tm-epo-field' );
9175				var checked = epoField.filter( ':checked' );
9176				var qty;
9177				var counter = $this.attr( 'data-counter' );
9178
9179				if ( false === elementContainer.data( 'isactive' ) ) {
9180					return;
9181				}
9182				if ( data && data.forced === 2 ) {
9183					return;
9184				}
9185
9186				if ( e.isTrigger !== undefined && $this.data( 'triggeredonce' ) && ! ( data && data.forced ) ) {
9187					return;
9188				}
9189
9190				$this.data( 'triggeredonce', 1 );
9191
9192				if ( ! $this.is( ':checkbox' ) ) {
9193					isTrigger = e.isTrigger;
9194				}
9195
9196				if ( epoField.is( ':radio' ) || epoField.is( ':checkbox' ) ) {
9197					if ( checked.length > 0 ) {
9198						qty = checked.closest( '.tmcp-field-wrap' ).find( 'input.tm-qty' );
9199					}
9200				} else {
9201					qty = epoField.closest( '.tmcp-field-wrap' ).find( 'input.tm-qty' );
9202				}
9203
9204				if ( $this.is( ':checkbox' ) ) {
9205					if ( $this.is( '.tc-epo-field-product-hidden' ) ) {
9206						if ( $this.is( ':checked' ) ) {
9207							productContainerWraps.addClass( 'tc-active-product' );
9208						} else {
9209							productContainerWraps.removeClass( 'tc-active-product' );
9210						}
9211
9212						value = $this.val();
9213						type = $this.attr( 'data-type' );
9214						elementContainer.find( '.tc-epo-element-product-li-container' ).removeClass( 'tm-hidden' );
9215					} else {
9216						if ( ! $this.is( ':checked' ) ) {
9217							if ( hasProductContainerWrap ) {
9218								thisProductContainerWrap.addClass( 'tm-hidden' );
9219							}
9220							if ( ! ( data && data.forced ) ) {
9221								return;
9222							}
9223							skip = true;
9224						} else if ( hasProductContainerWrap ) {
9225							thisProductContainerWrap.removeClass( 'tm-hidden' );
9226						}
9227						if ( ! skip ) {
9228							value = $this.val();
9229							type = $this.attr( 'data-type' );
9230							elementContainer.find( '.tc-epo-element-product-li-container' ).removeClass( 'tm-hidden' );
9231						}
9232					}
9233				} else if ( $this.is( ':radio' ) ) {
9234					if ( ! $this.is( ':checked' ) ) {
9235						if ( hasProductContainerWrap ) {
9236							thisProductContainerWrap.addClass( 'tm-hidden' );
9237						}
9238						if ( ! ( data && data.forced ) ) {
9239							return;
9240						}
9241						skip = true;
9242					} else if ( hasProductContainerWrap ) {
9243						productContainerWraps.addClass( 'tm-hidden' );
9244						thisProductContainerWrap.removeClass( 'tm-hidden' );
9245					}
9246					if ( ! skip ) {
9247						value = $this.val();
9248						type = $this.attr( 'data-type' );
9249						elementContainer.find( '.tc-epo-element-product-li-container' ).removeClass( 'tm-hidden' );
9250					}
9251				} else if ( $this.is( 'select' ) ) {
9252					selected = $this.children( ':selected' );
9253					associatedSetter = selected;
9254					counter = selected.index();
9255					if ( $this.children( ':first' ).val() === '' ) {
9256						counter--;
9257					}
9258					value = $this.val();
9259					type = selected.attr( 'data-type' );
9260					elementContainer.find( '.tc-epo-element-product-li-container' ).removeClass( 'tm-hidden' );
9261				}
9262
9263				if ( $this.is( '.tc-epo-field-product-checkbox' ) ) {
9264					variableProductContainers = thisProductContainerWrap.find( '.tc-epo-element-product-container' );
9265				} else {
9266					variableProductContainers = elementContainer.find( '.tc-epo-element-product-container' );
9267				}
9268
9269				thisVariableProductContainer = variableProductContainers.filter( '[data-product_id="' + value + '"]' );
9270
9271				qtyalt = thisVariableProductContainer.find( tcAPI.associateQtySelector );
9272
9273				if ( productContainerWraps.html() !== '' && qty && qty.length > 0 && qtyalt.length === 0 ) {
9274					qty.val( 0 );
9275				}
9276				if ( $this.is( ':checkbox' ) ) {
9277					if ( $this.is( '.tc-epo-field-product-hidden' ) ) {
9278						if ( $this.is( ':checked' ) ) {
9279							if ( qtyalt.val() === '0' ) {
9280								if ( qtyalt.attr( 'min' ) === '0' ) {
9281									qtyalt.val( 1 ).trigger( 'change' );
9282								} else {
9283									qtyalt.val( qtyalt.attr( 'min' ) ).trigger( 'change' );
9284								}
9285							}
9286						} else {
9287							qtyalt.val( 0 );
9288							qtyalt.closest( '.tm-quantity-alt' ).removeClass( 'tm-hidden' );
9289							if ( data.forced !== 1 ) {
9290								qtyalt.closest( '.tm-quantity-alt' ).find( '.single_add_to_cart_product' ).trigger( 'cpfqtybutton' );
9291							}
9292							productContainerWraps.find( tcAPI.associatedEpoCart ).trigger( 'tm-epo-update' );
9293						}
9294					}
9295				} else if ( $this.is( ':radio' ) ) {
9296					if ( $this.val() && ! $this.data( 'set_initial' ) ) {
9297						if ( qtyalt.val() === '0' ) {
9298							if ( qtyalt.attr( 'min' ) === '0' ) {
9299								qtyalt.val( 1 ).trigger( 'change' );
9300							} else {
9301								qtyalt.val( qtyalt.attr( 'min' ) ).trigger( 'change' );
9302							}
9303							$this.data( 'set_initial', 1 );
9304						}
9305					}
9306				} else if ( $this.is( 'select' ) ) {
9307					if ( $this.val() && ! $this.data( 'set_initial' ) ) {
9308						if ( qtyalt.val() === '0' ) {
9309							if ( qtyalt.attr( 'min' ) === '0' ) {
9310								// qtyalt.val( 1 ).trigger( 'change' );
9311							} else {
9312								qtyalt.val( qtyalt.attr( 'min' ) ).trigger( 'change' );
9313							}
9314							$this.data( 'set_initial', 1 );
9315						}
9316					}
9317				} else {
9318					return;
9319				}
9320
9321				if ( ! value ) {
9322					variableProductContainers.addClass( 'tm-hidden' );
9323					productPrice = $.epoAPI.util.parseJSON( associatedSetter.attr( 'data-rules' ) );
9324					productPrice = productPrice[ 0 ] || 0;
9325					originalProductPrice = $.epoAPI.util.parseJSON( associatedSetter.attr( 'data-original-rules' ) );
9326					originalProductPrice = originalProductPrice || 0;
9327					if ( associatedSetter.is( '.tcenabled' ) ) {
9328						associatedSetter.data( 'associated_price_set', 1 );
9329					}
9330					associatedSetter.data( 'price_set', 1 );
9331					associatedSetter.data( 'raw_price', productPrice );
9332					associatedSetter.data( 'raw_original_price', originalProductPrice );
9333					associatedSetter.data( 'price', productPrice );
9334					associatedSetter.data( 'original_price', originalProductPrice );
9335
9336					associatedElement = associatedSetter;
9337					if ( associatedElement.is( 'option' ) ) {
9338						associatedElement = associatedSetter.closest( 'select' );
9339					}
9340					isFilled = false;
9341					if ( associatedElement.is( '.tc-epo-field-product' ) ) {
9342						if ( associatedElement.is( 'select' ) ) {
9343							if ( associatedElement.val() !== '' ) {
9344								isFilled = true;
9345							}
9346						} else if ( ( associatedElement.is( ':checkbox' ) || associatedElement.is( ':radio' ) ) ) {
9347							if ( associatedElement.is( ':checked' ) ) {
9348								isFilled = true;
9349							}
9350						} else if ( associatedElement.val() !== '' ) {
9351							isFilled = true;
9352						}
9353					}
9354					tm_force_update_price(
9355						associatedSetter
9356							.closest( '.tmcp-field-wrap' )
9357							.find( '.tc-price' )
9358							.not( tcAPI.associatedEpoSelector + ' .tc-price' ),
9359						productPrice,
9360						isFilled ? tm_set_price_totals( productPrice ) : associatedSetter.data( 'price-html' ),
9361						originalProductPrice,
9362						isFilled ? tm_set_price_totals( originalProductPrice ) : ''
9363					);
9364
9365					qtyElement.trigger( 'change.cpf' );
9366
9367					return;
9368				}
9369
9370				if ( thisVariableProductContainer.length === 0 ) {
9371					// parent_id is used for customization purposes.
9372					postData = {
9373						action: 'wc_epo_get_associated_product_html',
9374						product_id: value,
9375						parent_id: epoHolder.attr( 'data-product-id' ),
9376						mode: elementContainer.attr( 'data-mode' ),
9377						layout_mode: elementContainer.attr( 'data-product-layout-mode' ),
9378						uniqid: elementContainer.attr( 'data-uniqid' ),
9379						name: $this.attr( 'name' ),
9380						counter: counter,
9381						quantity_min: elementContainer.attr( 'data-quantity-min' ),
9382						quantity_max: elementContainer.attr( 'data-quantity-max' ),
9383						priced_individually: elementContainer.attr( 'data-priced-individually' ),
9384						discount: elementContainer.attr( 'data-discount' ),
9385						discount_type: elementContainer.attr( 'data-discount-type' ),
9386						discount_exclude_addons: elementContainer.attr( 'data-discount-exclude-addons' ),
9387						show_image: elementContainer.attr( 'data-show-image' ),
9388						show_title: elementContainer.attr( 'data-show-title' ),
9389						show_price: elementContainer.attr( 'data-show-price' ),
9390						show_description: elementContainer.attr( 'data-show-description' ),
9391						show_meta: elementContainer.attr( 'data-show-meta' ),
9392						disable_epo: elementContainer.attr( 'data-disable-epo' )
9393					};
9394
9395					elementContainer.block( { message: null, overlayCSS: { background: '#fff', opacity: 0.6 } } );
9396					$.ajax( {
9397						url: TMEPOJS.ajax_url,
9398						type: 'POST',
9399						data: postData,
9400						dataType: 'json',
9401						success: function( response ) {
9402							if ( response.result === 200 ) {
9403								thisVariableProductContainer = $( response.html );
9404								if ( hasProductContainerWrap ) {
9405									$this.closest( '.tmcp-field-wrap' ).find( '.tc-epo-element-product-container-wrap' ).empty().append( thisVariableProductContainer );
9406								} else {
9407									elementContainer.find( '.tc-epo-element-product-container-wrap' ).append( thisVariableProductContainer );
9408								}
9409								show_product_html( epoObject, main_product, thisVariableProductContainer, type, $this, currentCart, variableProductContainers, isTrigger, qtyalt );
9410								thisVariableProductContainer.find( tcAPI.associateQtySelector ).trigger( 'change' );
9411							}
9412						},
9413						complete: function() {
9414							elementContainer.unblock();
9415						}
9416					} );
9417				} else {
9418					show_product_html( epoObject, main_product, thisVariableProductContainer, type, $this, currentCart, variableProductContainers, isTrigger, qtyalt );
9419					thisVariableProductContainer.find( tcAPI.associateQtySelector ).trigger( 'change' );
9420				}
9421			} );
9422
9423		jDocument
9424			.off( 'click.cpfqtybutton cpfqtybutton', '.cpf-type-product .single_add_to_cart_product' )
9425			.on( 'click.cpfqtybutton cpfqtybutton', '.cpf-type-product .single_add_to_cart_product', function() {
9426				var $this = $( this );
9427				var qtyalt = $this.closest( '.tm-quantity-alt' ).find( tcAPI.associateQtySelector );
9428				var isAdd = $this.is( '.alt' );
9429				var productContainerWraps = $this.closest( '.cpf-element' ).find( '.tc-epo-element-product-container-wrap' );
9430				var qtyMin;
9431				var qtyMax;
9432
9433				if ( $this.data( 'inittriggeredonce' ) ) {
9434					qtyMin = $.epoAPI.math.toInt( qtyalt.attr( 'data-min' ) );
9435					qtyMax = $.epoAPI.math.toInt( qtyalt.attr( 'data-max' ) );
9436					if ( isAdd ) {
9437						productContainerWraps.addClass( 'tc-active-product' );
9438						qtyalt.attr( 'min', qtyMin );
9439						if ( qtyMax ) {
9440							qtyalt.attr( 'max', qtyMax );
9441						}
9442						if ( qtyalt.val() === '0' ) {
9443							if ( qtyalt.attr( 'min' ) === '0' ) {
9444								qtyalt.val( 1 ).trigger( 'change' );
9445							} else {
9446								qtyalt.val( qtyalt.attr( 'min' ) ).trigger( 'change' );
9447							}
9448						}
9449						$this.removeClass( 'alt' ).text( $this.attr( 'data-remove' ) );
9450					} else {
9451						productContainerWraps.removeClass( 'tc-active-product' );
9452						qtyalt.val( 0 ).trigger( 'change' );
9453						qtyalt.closest( '.tm-quantity-alt' ).removeClass( 'tm-hidden' );
9454						$this.addClass( 'alt' ).text( $this.attr( 'data-add' ) );
9455					}
9456				}
9457
9458				$this.data( 'inittriggeredonce', 1 );
9459
9460				productContainerWraps.find( tcAPI.associatedEpoCart ).trigger( 'tm-epo-update' );
9461			} );
9462
9463		jDocument
9464			.off( 'change.cpfqtyalt', '.cpf-type-product ' + tcAPI.associateQtySelector )
9465			.on( 'change.cpfqtyalt', '.cpf-type-product ' + tcAPI.associateQtySelector, function() {
9466				var $this = $( this );
9467				var epoField = $this.closest( '.cpf-element' ).find( '.tm-epo-field' ).not( '.tc-epo-element-product-li-container .tm-epo-field' );
9468				var addButton = $this.closest( '.tm-quantity-alt' ).find( '.single_add_to_cart_product' );
9469				var checked = epoField.filter( ':checked' );
9470				var qty;
9471				var qtyMin;
9472				var qtyMax;
9473				var associatedEpoCart;
9474
9475				qtyMin = $.epoAPI.math.toInt( $this.attr( 'min' ) );
9476				qtyMax = $.epoAPI.math.toInt( $this.attr( 'max' ) );
9477
9478				if ( epoField.is( '.tc-epo-field-product-hidden' ) && epoField.is( ':checkbox' ) ) {
9479					if ( checked.length === 0 && $this.val() !== '0' ) {
9480						epoField.prop( 'checked', true ).trigger( 'change' );
9481						checked = epoField.filter( ':checked' );
9482					} else if ( $this.val() === '0' && checked.length ) {
9483						epoField.prop( 'checked', false ).trigger( 'change' );
9484					}
9485				}
9486
9487				if ( epoField.is( ':radio' ) || epoField.is( ':checkbox' ) ) {
9488					if ( checked.length === 0 ) {
9489						return;
9490					}
9491					qty = checked.closest( '.tmcp-field-wrap' ).find( 'input.tm-qty' ).not( '.tc-element-qty' );
9492				} else {
9493					qty = epoField.closest( '.tmcp-field-wrap' ).find( 'input.tm-qty' ).not( '.tc-element-qty' );
9494				}
9495
9496				if ( qty.length === 0 ) {
9497					return;
9498				}
9499
9500				qty.attr( 'min', qtyMin );
9501				if ( qtyMax ) {
9502					qty.attr( 'max', qtyMax );
9503				}
9504				associatedEpoCart = $this.closest( '.tc-epo-element-product-container' ).find( tcAPI.associatedEpoCart );
9505				associatedEpoCart.trigger( 'tm-epo-update' );
9506
9507				qty.val( $this.val() );
9508
9509				if ( $.epoAPI.math.toFloat( $this.val() ) > 0 ) {
9510					associatedEpoCart.find( '.tm-epo-field.tcenabled' ).removeClass( 'ignore' );
9511					$this.removeClass( 'ignore' );
9512				} else {
9513					associatedEpoCart.find( '.tm-epo-field.tcenabled' ).addClass( 'ignore' );
9514					$this.addClass( 'ignore' );
9515				}
9516				epoField.trigger( 'change.cpfproduct', { forced: 2 } );
9517				if ( addButton.data( 'inittriggeredonce' ) ) {
9518					if ( $this.val() === '0' ) {
9519						addButton.removeClass( 'alt' );
9520					} else {
9521						addButton.addClass( 'alt' );
9522					}
9523				}
9524				addButton.trigger( 'cpfqtybutton' );
9525			} );
9526
9527		// Global update event
9528		currentCart.off( 'tm-epo-update' ).on( 'tm-epo-update', function( event ) {
9529			var cart = $( this );
9530			var bundleid;
9531			var productPrice = false;
9532			var rawProductPrice = 0;
9533			var productRegularPrice = false;
9534			var rawProductRegularPrice = 0;
9535			var total = 0;
9536			var original_total = 0;
9537			var showTotal = false;
9538			var cartQty;
9539			var elementQty = 1;
9540			var priceOverrideMode;
9541			var perProductPricing = true;
9542			var floatingBoxData = [];
9543			var currentVariation;
9544			var cart_fee_options_total = 0;
9545			var cart_fee_options_original_total = 0;
9546			var _total;
9547			var _original_total;
9548			var late_total_price;
9549			var tc_totals_ob = {};
9550			var formatted_options_total;
9551			var formatted_options_original_total;
9552			var formatted_fees_total;
9553			var formatted_fees_original_total;
9554			var formatted_final_total;
9555			var formatted_final_original_total;
9556			var extraFee = 0;
9557			var product_total_price;
9558			var product_total_original_price;
9559			var calculateFinalProductPrice;
9560			var total_plus_fee;
9561			var original_total_plus_fee;
9562			var product_total_price_without_options;
9563			var unit_price;
9564			var unit_original_price;
9565			var formatted_unit_price;
9566			var formatted_unit_original_price;
9567			var html;
9568			var show_options_total = false;
9569			var show_vat_options_total = false;
9570			var show_fees_total = false;
9571			var formatted_extra_fee = '';
9572			var show_extra_fee = false;
9573			var show_final_total = false;
9574			var hide_native_price;
9575			var update_native_html;
9576			var _fprice;
9577			var _f_regular_price;
9578			var customerPriceFormat;
9579			var currentEpoObject;
9580			var raw_total;
9581			var raw__total;
9582			var raw_original_total;
9583			var raw__original_total;
9584			var raw_cart_fee_options_total;
9585			var raw_cart_fee_options_original_total;
9586			var raw_total_plus_fee;
9587			var raw_original_total_plus_fee;
9588			var raw_product_total_price_without_options;
9589			var raw_product_total_price;
9590			var raw_product_total_original_price;
9591			var fetch;
9592			var customer_price_format_wrap_start = '';
9593			var customer_price_format_wrap_end = '';
9594			var associatedSetter;
9595			var associatedPrice;
9596			var associatedRawPrice;
9597			var associatedOriginalPrice;
9598			var associatedRawOriginalPrice;
9599			var associatedFormattedPrice;
9600			var associatedFormattedOriginalPrice;
9601			var nativeProductPriceSelector;
9602			var elementsLength;
9603			var noSyncTotal = 0;
9604			var noSyncOriginalTotal = 0;
9605			var _ftotal;
9606			var _foriginal_total;
9607			var totalsHolder_tc_totals_ob;
9608			var temp;
9609			var vat_options_total;
9610			var vat_options_total_plus_fee;
9611			var formatted_vat_options_total;
9612			var formatted_vat_options_total_plus_fee;
9613			var vat_total;
9614			var formatted_vat_total;
9615			var vat_product_base;
9616			var formatted_vat_product_base;
9617			var pricesIncludeTax;
9618
9619			if ( event.epoObject ) {
9620				currentEpoObject = $.extend( true, {}, event.epoObject );
9621			} else {
9622				currentEpoObject = $.extend( true, {}, epoObject );
9623			}
9624
9625			if ( ! currentEpoObject ) {
9626				return;
9627			}
9628
9629			if ( currentEpoObject.noEpoUpdate ) {
9630				return;
9631			}
9632
9633			jWindow.trigger( 'tcEpoUpdateStart', {
9634				epo: currentEpoObject,
9635				alternativeCart: currentEpoObject,
9636				this_product_type: this_product_type,
9637				cart: cart,
9638				totalsHolder: totalsHolder,
9639				fetchOptionPrices: fetchOptionPrices,
9640				epoHolder: epoHolder
9641			} );
9642
9643			bundleid = $.epoAPI.applyFilter( 'tc_get_bundleid', cart.attr( 'data-product_id' ), cart, currentEpoObject );
9644			priceOverrideMode = totalsHolder.attr( 'data-price-override' );
9645			cartQty = getCurrentQty( cart );
9646			currentVariation = getCurrentVariation( cart );
9647
9648			if ( currentEpoObject.associated_connect && currentEpoObject.associated_connect.length === 1 ) {
9649				cartQty = parseFloat(
9650					currentEpoObject.main_product
9651						.find( tcAPI.associateQtySelector )
9652						.not( tcAPI.associatedEpoSelector + ' ' + tcAPI.qtySelector )
9653						.last()
9654						.val()
9655				);
9656			}
9657
9658			event.stopImmediatePropagation();
9659
9660			productPrice = $.epoAPI.applyFilter( 'tcGetCurrentProductPrice', tm_calculate_product_price( totalsHolder, true ), currentCart, totalsHolder );
9661
9662			rawProductPrice = productPrice;
9663
9664			productRegularPrice = $.epoAPI.applyFilter( 'tcGetCurrentProductRegularPrice', tm_calculate_product_regular_price( totalsHolder, true ), currentCart, totalsHolder );
9665
9666			rawProductRegularPrice = productRegularPrice;
9667
9668			productPrice = $.epoAPI.applyFilter( 'tcCalculateCurrentProductPrice', productPrice, {
9669				epo: currentEpoObject,
9670				alternativeCart: alternativeCart,
9671				cart: cart,
9672				main_product: main_product
9673			} );
9674
9675			if ( ! Number.isFinite( cartQty ) ) {
9676				if ( totalsHolder.attr( 'data-is-sold-individually' ) || getQtyElement( cart ).length === 0 ) {
9677					cartQty = 1;
9678				}
9679			}
9680
9681			// needed for inital math calculation
9682			totalsHolder_tc_totals_ob = {
9683				qty: cartQty,
9684				product_price: rawProductPrice,
9685				original_product_price: rawProductRegularPrice
9686			};
9687			totalsHolder.data( 'totalsHolder_tc_totals_ob', totalsHolder_tc_totals_ob );
9688
9689			if ( ! event.norules ) {
9690				tm_epo_rules( currentEpoObject, cart );
9691			} else if ( event.norules ) {
9692				if ( event.norules === 1 ) {
9693					tm_element_epo_rules( currentEpoObject, event.element );
9694				}
9695				$.tcepo.lateFieldsPrices[ epoEventId ] = [];
9696
9697				epoHolder
9698					.find( '.tm-epo-late-field' )
9699					.toArray()
9700					.forEach( function( setter ) {
9701						setter = $( setter );
9702						setter.data( 'price', 0 );
9703						$.tcepo.lateFieldsPrices[ epoEventId ].push( {
9704							setter: setter,
9705							price: setter.data( 'tm-price-for-late' ),
9706							original_price: setter.data( 'tm-original-price-for-late' ),
9707							bundleid: bundleid,
9708							pricetype: get_price_type( currentEpoObject, setter )
9709						} );
9710					} );
9711			}
9712
9713			if ( currentEpoObject.associated_connect && currentEpoObject.associated_connect.length === 1 ) {
9714				associatedSetter = currentEpoObject.associated_connect;
9715				if ( currentEpoObject.associated_connect.is( 'select' ) ) {
9716					associatedSetter = currentEpoObject.associated_connect.find( 'option:selected' );
9717				}
9718			}
9719
9720			// No reason to continue if the product price is invalid
9721			if ( productPrice === false ) {
9722				totalsHolder.empty();
9723				if ( currentEpoObject.associated_connect && currentEpoObject.associated_connect.length === 1 ) {
9724					tm_force_update_price(
9725						associatedSetter
9726							.closest( '.tmcp-field-wrap' )
9727							.find( '.tc-price' )
9728							.not( tcAPI.associatedEpoSelector + ' .tc-price' ),
9729						0,
9730						'',
9731						0,
9732						''
9733					);
9734				}
9735				return;
9736			}
9737
9738			elementQty = $.epoAPI.applyFilter( 'tcAlterElementQty', elementQty, {
9739				epo: currentEpoObject,
9740				alternativeCart: alternativeCart,
9741				currentCart: currentCart,
9742				main_product: main_product
9743			} );
9744
9745			if ( currentCart.data( 'per_product_pricing' ) !== undefined ) {
9746				perProductPricing = currentCart.data( 'per_product_pricing' );
9747			}
9748
9749			perProductPricing = $.epoAPI.applyFilter( 'tcCalculatePerProductPricing', perProductPricing, {
9750				epo: currentEpoObject,
9751				alternativeCart: alternativeCart,
9752				cart: cart,
9753				main_product: main_product
9754			} );
9755
9756			if ( main_epo_inside_form && TMEPOJS.tm_epo_totals_box_placement === 'woocommerce_before_add_to_cart_button' ) {
9757				if ( ( this_product_type === 'variable' || this_product_type === 'variable-subscription' ) && ! totalsHolder.data( 'moved_inside' ) ) {
9758					totalsHolder.data( 'moved_inside', 1 );
9759				}
9760			}
9761
9762			jWindow.trigger( 'tcEpoBeforeOptionPriceCalculation', {
9763				epo: currentEpoObject,
9764				alternativeCart: currentEpoObject,
9765				this_product_type: this_product_type,
9766				cart: cart,
9767				totalsHolder: totalsHolder,
9768				fetchOptionPrices: fetchOptionPrices,
9769				epoHolder: epoHolder,
9770				total: total,
9771				original_total: original_total,
9772				floatingBoxData: floatingBoxData,
9773				showTotal: showTotal,
9774				cart_fee_options_total: cart_fee_options_total,
9775				cart_fee_options_original_total: cart_fee_options_original_total
9776			} );
9777
9778			if ( ! currentEpoObject.associated_connect && ! event.noassociated ) {
9779				if ( TMEPOJS.tm_epo_global_product_element_quantity_sync === 'yes' && ! cart.is( $.tcAPI().associatedEpoCart ) ) {
9780					cart.find( $.tcAPI().associatedEpoCart ).filter( ':visible' ).toArray().forEach( function( acart ) {
9781						$( acart ).trigger( {
9782							type: 'tm-epo-update',
9783							noassociated: 1
9784						} );
9785					} );
9786				}
9787			}
9788
9789			if ( TMEPOJS.tm_epo_global_product_element_quantity_sync === 'no' ) {
9790				fetch = fetchOptionPrices( currentEpoObject, epoHolder, '.tmcp-field:not(.tc-epo-field-product)', total, original_total, floatingBoxData, showTotal );
9791				total = fetch.total;
9792				original_total = fetch.original_total;
9793				floatingBoxData = fetch.floatingBoxData;
9794				showTotal = fetch.showTotal;
9795				elementsLength = fetch.elementsLength;
9796
9797				fetch = fetchOptionPrices( currentEpoObject, epoHolder, '.tc-epo-field-product', noSyncTotal, 0, floatingBoxData, showTotal );
9798				noSyncTotal = fetch.total;
9799				noSyncOriginalTotal = fetch.original_total;
9800				floatingBoxData = fetch.floatingBoxData;
9801				showTotal = showTotal && fetch.showTotal;
9802				elementsLength = elementsLength + fetch.elementsLength;
9803
9804				totalsHolder.data( 'tm-floating-box-data', floatingBoxData );
9805			} else {
9806				fetch = fetchOptionPrices( currentEpoObject, epoHolder, '.tmcp-field', total, original_total, floatingBoxData, showTotal );
9807				total = fetch.total;
9808				original_total = fetch.original_total;
9809				floatingBoxData = fetch.floatingBoxData;
9810				showTotal = fetch.showTotal;
9811				elementsLength = fetch.elementsLength;
9812
9813				totalsHolder.data( 'tm-floating-box-data', floatingBoxData );
9814			}
9815
9816			fetch = fetchOptionPrices( currentEpoObject, epoHolder, '.tmcp-fee-field', cart_fee_options_total, cart_fee_options_original_total, floatingBoxData, showTotal, false, true );
9817			cart_fee_options_total = fetch.total;
9818			cart_fee_options_original_total = fetch.original_total;
9819			floatingBoxData = fetch.floatingBoxData;
9820			showTotal = fetch.showTotal;
9821			elementsLength = elementsLength + fetch.elementsLength;
9822
9823			jWindow.trigger( 'tcEpoAfterOptionPriceCalculation', {
9824				epo: currentEpoObject,
9825				alternativeCart: currentEpoObject,
9826				this_product_type: this_product_type,
9827				cart: cart,
9828				totalsHolder: totalsHolder,
9829				fetchOptionPrices: fetchOptionPrices,
9830				epoHolder: epoHolder,
9831				total: total,
9832				original_total: original_total,
9833				floatingBoxData: floatingBoxData,
9834				showTotal: showTotal,
9835				cart_fee_options_total: cart_fee_options_total,
9836				cart_fee_options_original_total: cart_fee_options_original_total
9837			} );
9838
9839			$.tcepo.oneOptionIsSelected[ epoEventId ] = showTotal;
9840			tm_show_hide_add_to_cart_button( main_product, elementsLength, $.tcepo.oneOptionIsSelected[ epoEventId ], currentEpoObject );
9841
9842			showTotal = $.epoAPI.applyFilter( 'tcFinalTotalsBoxVisibility', showTotal, {
9843				epo: currentEpoObject,
9844				alternativeCart: alternativeCart,
9845				cart: cart,
9846				main_product: main_product,
9847				totalsHolder: totalsHolder,
9848				this_epo_totals_container: this_epo_totals_container
9849			} );
9850
9851			if ( cart_fee_options_total > 0 ) {
9852				showTotal = true;
9853			}
9854
9855			if ( alternativeCart && ! perProductPricing ) {
9856				showTotal = false;
9857			}
9858
9859			if (
9860				finalTotalBoxMode === 'pxq' ||
9861				finalTotalBoxMode === 'hide' ||
9862				finalTotalBoxMode === 'normal' ||
9863				finalTotalBoxMode === 'options' ||
9864				finalTotalBoxMode === 'final' ||
9865				finalTotalBoxMode === 'hideoptionsifzero' ||
9866				finalTotalBoxMode === 'hideiftotaliszero' ||
9867				finalTotalBoxMode === 'optionsiftotalnotzero'
9868			) {
9869				showTotal = true;
9870			}
9871
9872			if ( cartQty > 1 ) {
9873				showTotal = true;
9874			}
9875			if ( ( this_product_type === 'variable' || this_product_type === 'variable-subscription' ) && ! $.epoAPI.math.toFloat( currentVariation ) ) {
9876				showTotal = false;
9877			}
9878
9879			// Original price + options price type requires this here.
9880			_total = total;
9881			_original_total = original_total;
9882
9883			late_total_price = add_late_fields_prices( currentEpoObject, parseFloat( productPrice ), parseFloat( rawProductRegularPrice ), parseFloat( _total + noSyncTotal ), parseFloat( _original_total + noSyncOriginalTotal ), bundleid, totalsHolder );
9884
9885			if ( finalTotalBoxMode === 'disable' ) {
9886				showTotal = false;
9887			}
9888			if ( finalTotalBoxMode === 'disable_change' || TMEPOJS.tm_epo_change_variation_price === 'yes' || TMEPOJS.tm_epo_change_original_price === 'yes' ) {
9889				showTotal = true;
9890			}
9891
9892			if ( currentEpoObject.is_associated && ! perProductPricing ) {
9893				showTotal = false;
9894			}
9895
9896			if ( TMEPOJS.tm_epo_total_price_as_unit_price === 'yes' ) {
9897				cartQty = 1;
9898			}
9899
9900			product_total_price = parseFloat( productPrice * cartQty );
9901
9902			if ( TMEPOJS.extraFee ) {
9903				extraFee = parseFloat( TMEPOJS.extraFee );
9904				if ( ! Number.isFinite( extraFee ) ) {
9905					extraFee = 0;
9906				}
9907			}
9908
9909			calculateFinalProductPrice = $.epoAPI.applyFilter( 'tcCalculateFinalProductPrice', false, {
9910				alternativeCart: alternativeCart,
9911				product_price: productPrice,
9912				product_total_price: product_total_price,
9913				v_product_price: rawProductPrice,
9914				tm_set_tax_price: tm_set_tax_price,
9915				main_product: main_product,
9916				totalsHolder: totalsHolder,
9917				cartQty: cartQty
9918			} );
9919
9920			if (
9921				calculateFinalProductPrice !== false &&
9922				typeof calculateFinalProductPrice === 'object' &&
9923				Object.prototype.hasOwnProperty.call( calculateFinalProductPrice, 'productPrice' ) &&
9924				Object.prototype.hasOwnProperty.call( calculateFinalProductPrice, 'productTotalPrice' )
9925			) {
9926				productPrice = calculateFinalProductPrice.productPrice;
9927				product_total_price = calculateFinalProductPrice.productTotalPrice;
9928			}
9929
9930			_total = _total + late_total_price[ 0 ];
9931			_total = $.epoAPI.applyFilter( 'tc_adjust_options_price_per_unit', _total, product_total_price );
9932			total = parseFloat( _total * cartQty * elementQty );
9933			total = total + noSyncTotal;
9934			total = $.epoAPI.applyFilter( 'tc_adjust_options_total_price', total, cartQty, elementQty, _total, noSyncTotal, totalsHolder );
9935
9936			_original_total = _original_total + late_total_price[ 1 ];
9937			_original_total = $.epoAPI.applyFilter( 'tc_adjust_options_price_per_unit', _original_total, product_total_price );
9938			original_total = parseFloat( _original_total * cartQty * elementQty );
9939			original_total = original_total + noSyncOriginalTotal;
9940			original_total = $.epoAPI.applyFilter( 'tc_adjust_options_original_total_price', original_total, cartQty, elementQty, _original_total, noSyncOriginalTotal, totalsHolder );
9941
9942			if ( priceOverrideMode === '1' && parseFloat( total ) > 0 ) {
9943				productPrice = 0;
9944				rawProductPrice = 0;
9945				product_total_price = 0;
9946			}
9947
9948			product_total_price = $.epoAPI.applyFilter( 'tc_adjust_product_total_price_without_options', product_total_price );
9949
9950			total = $.epoAPI.applyFilter( 'tcAdjustTotal', total, {
9951				epo: currentEpoObject,
9952				totalsHolder: totalsHolder,
9953				cart: cart,
9954				main_product: main_product
9955			} );
9956			original_total = $.epoAPI.applyFilter( 'tcAdjustOriginalTotal', original_total, {
9957				epo: currentEpoObject,
9958				totalsHolder: totalsHolder,
9959				cart: cart,
9960				main_product: main_product
9961			} );
9962
9963			total = parseFloat( $.epoAPI.applyFilter( 'tc_adjust_total', total, totalsHolder ) );
9964			cart_fee_options_total = parseFloat( $.epoAPI.applyFilter( 'tc_adjust_totals_fee', cart_fee_options_total, totalsHolder ) );
9965			original_total = parseFloat( $.epoAPI.applyFilter( 'tc_adjust_total', original_total, totalsHolder ) );
9966			cart_fee_options_original_total = parseFloat( $.epoAPI.applyFilter( 'tc_adjust_totals_fee', cart_fee_options_original_total, totalsHolder ) );
9967
9968			total_plus_fee = total + cart_fee_options_total;
9969			original_total_plus_fee = original_total + cart_fee_options_original_total;
9970
9971			raw_total = total;
9972			raw__total = _total;
9973			raw_cart_fee_options_total = cart_fee_options_total;
9974			raw_total_plus_fee = total_plus_fee;
9975
9976			raw_original_total = original_total;
9977			raw__original_total = _original_total;
9978			raw_cart_fee_options_original_total = cart_fee_options_original_total;
9979			raw_original_total_plus_fee = original_total_plus_fee;
9980
9981			raw_product_total_price_without_options = product_total_price;
9982			raw_product_total_price = parseFloat( product_total_price + total_plus_fee + extraFee );
9983			raw_product_total_original_price = parseFloat( rawProductRegularPrice + original_total_plus_fee + extraFee );
9984
9985			productPrice = tm_set_tax_price( productPrice, totalsHolder, undefined, undefined, undefined, undefined, true );
9986			productRegularPrice = tm_set_tax_price( productRegularPrice, totalsHolder, undefined, undefined, undefined, undefined, true );
9987			product_total_price = tm_set_tax_price( product_total_price, totalsHolder, undefined, undefined, undefined, undefined, true );
9988			total = tm_set_tax_price( total, totalsHolder, undefined, undefined, undefined, undefined, true );
9989			_total = tm_set_tax_price( _total, totalsHolder, undefined, undefined, undefined, undefined, true );
9990
9991			total_plus_fee = parseFloat( cart_fee_options_total ) + parseFloat( tm_set_tax_price( raw_total, totalsHolder, undefined, undefined, undefined, undefined, true ) );
9992			original_total = tm_set_tax_price( original_total, totalsHolder, undefined, undefined, undefined, undefined, true );
9993			_original_total = tm_set_tax_price( _original_total, totalsHolder, undefined, undefined, undefined, undefined, true );
9994			cart_fee_options_original_total = tm_set_tax_price( cart_fee_options_original_total, totalsHolder, undefined, undefined, undefined, undefined, true );
9995			original_total_plus_fee = parseFloat( cart_fee_options_original_total ) + parseFloat( original_total );
9996			extraFee = tm_set_tax_price( extraFee, totalsHolder, undefined, undefined, undefined, undefined, true );
9997
9998			formatted_options_total = tm_set_price_totals( total, totalsHolder, true, true );
9999			formatted_fees_total = tm_set_price_totals( cart_fee_options_total, totalsHolder, true, true );
10000			formatted_options_original_total = tm_set_price_totals( original_total, totalsHolder, true, true );
10001			formatted_fees_original_total = tm_set_price_totals( cart_fee_options_original_total, totalsHolder, true, true );
10002
10003			product_total_price_without_options = product_total_price;
10004			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 );
10005			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 );
10006
10007			formatted_final_total = tm_set_price_totals( product_total_price, totalsHolder, true, true );
10008			formatted_final_original_total = tm_set_price_totals( product_total_original_price, totalsHolder, true, true );
10009			unit_price = parseFloat( productPrice + parseFloat( _total ) );
10010			unit_original_price = parseFloat( productPrice + parseFloat( _original_total ) );
10011			if ( TMEPOJS.tm_epo_fees_on_unit_price === 'yes' ) {
10012				unit_price = parseFloat( productPrice + parseFloat( _total ) + parseFloat( parseFloat( cart_fee_options_total ) / cartQty ) );
10013				unit_original_price = parseFloat( productPrice + parseFloat( _original_total ) + parseFloat( parseFloat( cart_fee_options_original_total ) / cartQty ) );
10014			}
10015			formatted_unit_price = tm_set_price_totals( parseFloat( productPrice + parseFloat( _total ) + parseFloat( parseFloat( cart_fee_options_total ) / cartQty ) ), totalsHolder, true, true );
10016			formatted_unit_original_price = tm_set_price_totals( parseFloat( productPrice + parseFloat( _original_total ) + parseFloat( parseFloat( cart_fee_options_original_total ) / cartQty ) ), totalsHolder, true, true );
10017
10018			if ( finalTotalBoxMode !== 'pxq' && finalTotalBoxMode !== 'final' && finalTotalBoxMode !== 'hide' && ! ( total_plus_fee === 0 && finalTotalBoxMode === 'hideoptionsifzero' ) ) {
10019				if ( ! ( total === 0 && finalTotalBoxMode === 'hideoptionsifzero' ) || finalTotalBoxMode === 'options' ) {
10020					show_options_total = true;
10021					if ( TMEPOJS.tm_epo_enable_vat_options_total === 'yes' ) {
10022						show_vat_options_total = true;
10023					}
10024				}
10025				if ( cart_fee_options_total !== 0 ) {
10026					show_fees_total = true;
10027				}
10028			}
10029			if ( extraFee ) {
10030				show_extra_fee = true;
10031				formatted_extra_fee = tm_set_price_totals( extraFee, totalsHolder, true, true );
10032			}
10033			if ( formatted_final_total && finalTotalBoxMode !== 'options' && finalTotalBoxMode !== 'optionsiftotalnotzero' ) {
10034				show_final_total = true;
10035			}
10036
10037			pricesIncludeTax = totalsHolder.attr( 'data-prices-include-tax' ) || TMEPOJS.prices_include_tax;
10038			if ( pricesIncludeTax === '1' ) {
10039				vat_options_total = parseFloat( get_price_including_tax( total, totalsHolder, undefined, true, undefined, undefined, true ) - raw_total );
10040				vat_options_total_plus_fee = parseFloat( get_price_including_tax( original_total_plus_fee, totalsHolder, undefined, true, undefined, undefined, true ) - raw_total_plus_fee );
10041				vat_total = parseFloat( get_price_including_tax( product_total_price, totalsHolder, undefined, true, undefined, undefined, true ) - raw_product_total_price );
10042				vat_product_base = parseFloat( get_price_including_tax( product_total_price_without_options, totalsHolder, undefined, true, undefined, undefined, true ) - raw_product_total_price_without_options );
10043			} else {
10044				vat_options_total = parseFloat( total - raw_total );
10045				vat_options_total_plus_fee = parseFloat( original_total_plus_fee - raw_total_plus_fee );
10046				vat_total = parseFloat( product_total_price - raw_product_total_price );
10047				vat_product_base = parseFloat( product_total_price_without_options - raw_product_total_price_without_options );
10048			}
10049			formatted_vat_options_total = tm_set_price_totals( vat_options_total );
10050			formatted_vat_options_total_plus_fee = tm_set_price_totals( vat_options_total_plus_fee );
10051			formatted_vat_total = tm_set_price_totals( vat_total );
10052			formatted_vat_product_base = tm_set_price_totals( vat_product_base );
10053
10054			// Backwards compatibility
10055			formatted_unit_price = $.epoAPI.applyFilter( 'tc_adjust_formatted_unit_price', formatted_unit_price, productPrice, _total, cart_fee_options_total, cartQty );
10056			formatted_options_total = $.epoAPI.applyFilter( 'tc_adjust_formatted_options_total', formatted_options_total, total, _total, cartQty );
10057			formatted_fees_total = $.epoAPI.applyFilter( 'tc_adjust_formatted_fees_total', formatted_fees_total, cart_fee_options_total );
10058			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 );
10059
10060			formatted_unit_price = $.epoAPI.applyFilter( 'tcAdjustFormattedUnitPrice', formatted_unit_price, {
10061				epo: currentEpoObject,
10062				totalsHolder: totalsHolder,
10063				event: event,
10064				unit_price: unit_price,
10065				productPrice: productPrice,
10066				_total: _total,
10067				total_plcart_fee_options_totals_fee: cart_fee_options_total,
10068				cartQty: cartQty
10069			} );
10070			formatted_unit_original_price = $.epoAPI.applyFilter( 'tcAdjustFormattedUnitOriginalPrice', formatted_unit_original_price, {
10071				epo: currentEpoObject,
10072				totalsHolder: totalsHolder,
10073				event: event,
10074				unit_original_price: unit_original_price,
10075				productPrice: productPrice,
10076				_original_total: _original_total,
10077				total_plcart_fee_options_totals_fee: cart_fee_options_total,
10078				cartQty: cartQty
10079			} );
10080
10081			formatted_options_total = $.epoAPI.applyFilter( 'tcAdjustFormattedOptionsTotal', formatted_options_total, {
10082				epo: currentEpoObject,
10083				totalsHolder: totalsHolder,
10084				event: event,
10085				total: total,
10086				_total: _total,
10087				total_plus_fee: total_plus_fee,
10088				extraFee: extraFee,
10089				cartQty: cartQty
10090			} );
10091			formatted_options_original_total = $.epoAPI.applyFilter( 'tcAdjustFormattedOptionsOriginalTotal', formatted_options_original_total, {
10092				epo: currentEpoObject,
10093				totalsHolder: totalsHolder,
10094				event: event,
10095				original_total: original_total,
10096				_original_total: _original_total,
10097				original_total_plus_fee: original_total_plus_fee,
10098				extraFee: extraFee,
10099				cartQty: cartQty
10100			} );
10101
10102			formatted_fees_total = $.epoAPI.applyFilter( 'tcAdjustFormattedFeesTotal', formatted_fees_total, {
10103				epo: currentEpoObject,
10104				totalsHolder: totalsHolder,
10105				event: event,
10106				cart_fee_options_total: cart_fee_options_total,
10107				extraFee: extraFee,
10108				cartQty: cartQty
10109			} );
10110			formatted_fees_original_total = $.epoAPI.applyFilter( 'tcAdjustFormattedFeesOriginalTotal', formatted_fees_original_total, {
10111				epo: currentEpoObject,
10112				totalsHolder: totalsHolder,
10113				event: event,
10114				cart_fee_options_original_total: cart_fee_options_original_total,
10115				extraFee: extraFee,
10116				cartQty: cartQty
10117			} );
10118
10119			formatted_final_total = $.epoAPI.applyFilter( 'tcAdjustFormattedFinalTotal', formatted_final_total, {
10120				epo: currentEpoObject,
10121				totalsHolder: totalsHolder,
10122				event: event,
10123				product_total_price: product_total_price,
10124				product_total_price_without_options: product_total_price_without_options,
10125				total_plus_fee: total_plus_fee,
10126				extraFee: extraFee,
10127				cartQty: cartQty
10128			} );
10129			formatted_final_original_total = $.epoAPI.applyFilter( 'tcAdjustFormattedFinalOriginalTotal', formatted_final_original_total, {
10130				epo: currentEpoObject,
10131				totalsHolder: totalsHolder,
10132				event: event,
10133				product_total_original_price: product_total_original_price,
10134				product_total_price_without_options: product_total_price_without_options,
10135				original_total_plus_fee: original_total_plus_fee,
10136				extraFee: extraFee,
10137				cartQty: cartQty
10138			} );
10139
10140			tc_totals_ob = {
10141				qty: cartQty,
10142				product_price: productPrice,
10143				raw_product_price: rawProductPrice,
10144				product_regular_price: productRegularPrice,
10145				raw_product_regular_price: rawProductRegularPrice,
10146
10147				late_total_prices: late_total_price,
10148				late_total_price: tm_set_tax_price( late_total_price[ 0 ], totalsHolder ),
10149				late_total_original_price: tm_set_tax_price( late_total_price[ 1 ], totalsHolder ),
10150
10151				raw_options_price_per_unit: raw__total,
10152				raw_options_total_price: raw_total,
10153				raw_cart_fee_options_total_price: raw_cart_fee_options_total,
10154				raw_total_plus_fee: raw_total_plus_fee,
10155
10156				raw_options_original_price_per_unit: raw__original_total,
10157				raw_options_original_total_price: raw_original_total,
10158				raw_cart_fee_options_original_total_price: raw_cart_fee_options_original_total,
10159				raw_original_total_plus_fee: raw_original_total_plus_fee,
10160
10161				raw_product_total_price: raw_product_total_price,
10162				raw_product_total_original_price: raw_product_total_original_price,
10163				raw_product_total_price_without_options: raw_product_total_price_without_options,
10164
10165				options_price_per_unit: _total,
10166				options_total_price: total,
10167				cart_fee_options_total_price: cart_fee_options_total,
10168				total_plus_fee: total_plus_fee,
10169
10170				options_original_price_per_unit: _original_total,
10171				options_original_total_price: original_total,
10172				cart_fee_options_total_original_price: cart_fee_options_original_total,
10173				original_total_plus_fee: original_total_plus_fee,
10174
10175				vat_options_total: vat_options_total,
10176				vat_options_total_plus_fee: vat_options_total_plus_fee,
10177				formatted_vat_options_total: formatted_vat_options_total,
10178				formatted_vat_options_total_plus_fee: formatted_vat_options_total_plus_fee,
10179				vat_total: vat_total,
10180				formatted_vat_total: formatted_vat_total,
10181				vat_product_base: vat_product_base,
10182				formatted_vat_product_base: formatted_vat_product_base,
10183
10184				product_total_price: product_total_price,
10185				product_total_original_price: product_total_original_price,
10186				product_total_price_without_options: product_total_price_without_options,
10187
10188				product_unit_price: unit_price,
10189				product_unit_original_price: unit_original_price,
10190				formatted_unit_price: formatted_unit_price,
10191				formatted_options_total: formatted_options_total,
10192				formatted_fees_total: formatted_fees_total,
10193				formatted_final_total: formatted_final_total,
10194
10195				formatted_unit_original_price: formatted_unit_original_price,
10196				formatted_options_original_total: formatted_options_original_total,
10197				formatted_fees_original_total: formatted_fees_original_total,
10198				formatted_final_original_total: formatted_final_original_total,
10199
10200				formatted_extra_fee: formatted_extra_fee,
10201
10202				show_options_total: show_options_total,
10203				show_fees_total: show_fees_total,
10204				show_extra_fee: show_extra_fee,
10205				show_final_total: show_final_total,
10206				show_options_vat: show_vat_options_total,
10207
10208				unit_price: TMEPOJS.i18n_unit_price,
10209				show_unit_price: TMEPOJS.tm_epo_show_unit_price === 'yes',
10210				options_total: TMEPOJS.i18n_options_total,
10211				fees_total: TMEPOJS.i18n_fees_total,
10212				extra_fee: TMEPOJS.i18n_extra_fee,
10213				final_total: TMEPOJS.i18n_final_total,
10214				options_vat_total: TMEPOJS.i18n_vat_options_total
10215			};
10216
10217			if ( formatted_options_total && total > 0 ) {
10218				_ftotal = formatPrice( total );
10219				_foriginal_total = formatPrice( original_total );
10220				_ftotal = $.epoAPI.applyFilter( 'tcFilterFormattedFTotal', _ftotal, {
10221					epo: currentEpoObject,
10222					totalsHolder: totalsHolder,
10223					event: event,
10224					total: total,
10225					_total: _total,
10226					total_plus_fee: total_plus_fee,
10227					extraFee: extraFee,
10228					cartQty: cartQty
10229				} );
10230				_foriginal_total = $.epoAPI.applyFilter( 'tcFilterFormattedFOriginalTotal', _foriginal_total, {
10231					epo: currentEpoObject,
10232					totalsHolder: totalsHolder,
10233					event: event,
10234					original_total: original_total,
10235					total: original_total,
10236					_total: _total,
10237					total_plus_fee: total_plus_fee,
10238					extraFee: extraFee,
10239					cartQty: cartQty
10240				} );
10241				if ( TMEPOJS.tm_epo_enable_original_final_total === 'yes' && total !== original_total ) {
10242					tc_totals_ob.formatted_options_total = $.epoAPI.util.decodeHTML(
10243						$.epoAPI.template.html( tcAPI.templateEngine.tc_formatted_sale_price, {
10244							price: _foriginal_total,
10245							sale_price: _ftotal,
10246							customer_price_format_wrap_start: customer_price_format_wrap_start,
10247							customer_price_format_wrap_end: customer_price_format_wrap_end
10248						} )
10249					);
10250					tc_totals_ob._foriginal_total = _foriginal_total;
10251					tc_totals_ob._ftotal = _ftotal;
10252				} else {
10253					tc_totals_ob.formatted_options_total = $.epoAPI.util.decodeHTML(
10254						$.epoAPI.util.decodeHTML(
10255							$.epoAPI.template.html( tcAPI.templateEngine.tc_formatted_price, {
10256								price: _ftotal,
10257								customer_price_format_wrap_start: customer_price_format_wrap_start,
10258								customer_price_format_wrap_end: customer_price_format_wrap_end
10259							} )
10260						)
10261					);
10262				}
10263			}
10264
10265			if ( formatted_final_total && product_total_price >= 0 ) {
10266				_fprice = formatPrice( product_total_price );
10267
10268				if ( priceOverrideMode === '1' && parseFloat( raw_original_total_plus_fee + extraFee ) > 0 ) {
10269					_f_regular_price = parseFloat( raw_original_total_plus_fee + extraFee );
10270				} else {
10271					_f_regular_price = parseFloat( parseFloat( rawProductRegularPrice * cartQty ) + raw_original_total_plus_fee + extraFee );
10272				}
10273
10274				if ( TMEPOJS.customer_price_format ) {
10275					customer_price_format_wrap_start = TMEPOJS.customer_price_format_wrap_start;
10276					customer_price_format_wrap_end = TMEPOJS.customer_price_format_wrap_end;
10277					customerPriceFormat = TMEPOJS.customer_price_format;
10278					_fprice = customerPriceFormat.replace( '__PRICE__', _fprice ).replace( '__CODE__', TMEPOJS.current_currency );
10279					if ( ! totalsHolder.data( 'is-on-sale' ) ) {
10280						_f_regular_price = customerPriceFormat.replace( '__PRICE__', _f_regular_price ).replace( '__CODE__', TMEPOJS.current_currency );
10281					}
10282				}
10283
10284				_fprice = $.epoAPI.applyFilter( 'tc_adjust_native_price', _fprice, product_total_price );
10285				_f_regular_price = tm_set_tax_price( _f_regular_price, totalsHolder, undefined, undefined, undefined, undefined, true );
10286				_f_regular_price = formatPrice( _f_regular_price );
10287				_f_regular_price = $.epoAPI.applyFilter( 'tc_adjust_native_regular_price', _f_regular_price, product_total_price );
10288
10289				if ( TMEPOJS.tm_epo_enable_original_final_total === 'yes' && ( totalsHolder.data( 'is-on-sale' ) || _f_regular_price !== _fprice ) ) {
10290					tc_totals_ob.formatted_final_total = $.epoAPI.util.decodeHTML(
10291						$.epoAPI.template.html( tcAPI.templateEngine.tc_formatted_sale_price, {
10292							price: _f_regular_price,
10293							sale_price: _fprice,
10294							customer_price_format_wrap_start: customer_price_format_wrap_start,
10295							customer_price_format_wrap_end: customer_price_format_wrap_end
10296						} )
10297					);
10298				} else {
10299					tc_totals_ob.formatted_final_total = $.epoAPI.util.decodeHTML(
10300						$.epoAPI.util.decodeHTML(
10301							$.epoAPI.template.html( tcAPI.templateEngine.tc_formatted_price, {
10302								price: _fprice,
10303								customer_price_format_wrap_start: customer_price_format_wrap_start,
10304								customer_price_format_wrap_end: customer_price_format_wrap_end
10305							} )
10306						)
10307					);
10308				}
10309				tc_totals_ob._f_regular_price = _f_regular_price;
10310				tc_totals_ob._fprice = _fprice;
10311			}
10312
10313			tc_totals_ob = $.epoAPI.applyFilter( 'tc_adjust_tc_totals_ob', tc_totals_ob, {
10314				epo_object: currentEpoObject,
10315				showTotal: showTotal,
10316				epoHolder: epoHolder,
10317				totalsHolder: totalsHolder,
10318				tm_set_price: tm_set_price,
10319				tm_set_price_totals: tm_set_price_totals,
10320				product_total_price: product_total_price,
10321				product_price: productPrice,
10322				qty: cartQty
10323			} );
10324
10325			tc_totals_ob = replace_suffixes( 'formatted_fees_original_total', 'cart_fee_options_total_original_price', tc_totals_ob, totalsHolder );
10326			tc_totals_ob = replace_suffixes( 'formatted_fees_total', 'cart_fee_options_total_price', tc_totals_ob, totalsHolder );
10327			tc_totals_ob = replace_suffixes( 'formatted_final_original_total', 'product_total_original_price', tc_totals_ob, totalsHolder );
10328			tc_totals_ob = replace_suffixes( 'formatted_final_total', 'product_total_price', tc_totals_ob, totalsHolder );
10329			tc_totals_ob = replace_suffixes( 'formatted_options_original_total', 'options_original_total_price', tc_totals_ob, totalsHolder );
10330			tc_totals_ob = replace_suffixes( 'formatted_options_total', 'options_total_price', tc_totals_ob, totalsHolder );
10331			tc_totals_ob = replace_suffixes( 'formatted_unit_original_price', 'product_unit_original_price', tc_totals_ob, totalsHolder );
10332			tc_totals_ob = replace_suffixes( 'formatted_unit_price', 'product_unit_price', tc_totals_ob, totalsHolder );
10333
10334			currentEpoObject.tc_totals_ob = tc_totals_ob;
10335
10336			if ( tc_totals_ob.showTotal !== undefined ) {
10337				showTotal = tc_totals_ob.showTotal;
10338			}
10339
10340			html = $.epoAPI.template.html( tcAPI.templateEngine.tc_final_totals, tc_totals_ob );
10341
10342			totalsHolder.data( 'tm-html', html );
10343			totalsHolder.data( 'tc_totals_ob', tc_totals_ob );
10344
10345			if ( currentEpoObject.associated_connect && currentEpoObject.associated_connect.length === 1 ) {
10346				if ( currentEpoObject.associated_connect.attr( 'data-no-price' ) === '1' ) {
10347					associatedPrice = 0;
10348					associatedRawPrice = 0;
10349					associatedOriginalPrice = 0;
10350					associatedRawOriginalPrice = 0;
10351					associatedFormattedPrice = '';
10352					associatedFormattedOriginalPrice = '';
10353					tm_force_update_price(
10354						associatedSetter
10355							.closest( '.tmcp-field-wrap' )
10356							.find( '.tc-price' )
10357							.not( tcAPI.associatedEpoSelector + ' .tc-price' ),
10358						associatedPrice,
10359						associatedFormattedPrice,
10360						associatedOriginalPrice,
10361						associatedFormattedOriginalPrice
10362					);
10363				} else {
10364					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 );
10365					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 );
10366					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 );
10367					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 );
10368
10369					associatedFormattedPrice = tm_set_price( associatedPrice, currentEpoObject.this_epo_totals_containe, false, false, associatedSetter );
10370					associatedFormattedOriginalPrice = tm_set_price( associatedOriginalPrice, currentEpoObject.this_epo_totals_containe, false, false, associatedSetter );
10371
10372					// Mainly used to update the price of the associated element when the associated product is variable.
10373					tm_force_update_price(
10374						associatedSetter
10375							.closest( '.tmcp-field-wrap' )
10376							.find( '.tc-price' )
10377							.not( tcAPI.associatedEpoSelector + ' .tc-price' ),
10378						associatedPrice,
10379						associatedFormattedPrice,
10380						associatedOriginalPrice,
10381						associatedFormattedOriginalPrice
10382					);
10383
10384					currentEpoObject.associate
10384d_connect.data( 'tm-quantity', tc_totals_ob.qty );
10385
10386					if ( currentEpoObject.associated_connect.data( 'tm-quantity' ) ) {
10387						associatedPrice = associatedPrice * parseFloat( currentEpoObject.associated_connect.data( 'tm-quantity' ) );
10388						associatedRawPrice = associatedRawPrice * parseFloat( currentEpoObject.associated_connect.data( 'tm-quantity' ) );
10389						associatedOriginalPrice = associatedOriginalPrice * parseFloat( currentEpoObject.associated_connect.data( 'tm-quantity' ) );
10390						associatedRawOriginalPrice = associatedRawOriginalPrice * parseFloat( currentEpoObject.associated_connect.data( 'tm-quantity' ) );
10391					}
10392
10393					associatedFormattedPrice = tm_set_price( associatedPrice, currentEpoObject.this_epo_totals_containe, false, false, associatedSetter );
10394					associatedFormattedOriginalPrice = tm_set_price( associatedOriginalPrice, currentEpoObject.this_epo_totals_containe, false, false, associatedSetter );
10395				}
10396
10397				currentEpoObject.associated_connect.data( 'price_set', 1 );
10398				if ( associatedSetter.is( '.tcenabled' ) ) {
10399					associatedSetter.data( 'associated_price_set', 1 );
10400				}
10401				associatedSetter.data( 'price_set', 1 );
10402				associatedSetter.data( 'raw_price', associatedRawPrice );
10403				associatedSetter.data( 'raw_original_price', associatedRawOriginalPrice );
10404				associatedSetter.data( 'price', tm_set_tax_price( associatedPrice, currentEpoObject.this_epo_totals_containe, associatedSetter ) );
10405				associatedSetter.data( 'original_price', tm_set_tax_price( associatedOriginalPrice, currentEpoObject.this_epo_totals_containe, associatedSetter ) );
10406
10407				currentEpoObject.associated_connect.data( 'price-changed', 1 );
10408
10409				setTimeout( function() {
10410					if ( ! ( currentEpoObject.associated_connect && event.noassociated ) ) {
10411						currentEpoObject.mainEpoObject.main_cart.trigger( {
10412							type: 'tm-epo-update',
10413							norules: 2
10414						} );
10415					}
10416				}, 20 );
10417			}
10418
10419			jWindow.trigger( 'tcEpoAfterCalculateTotals', {
10420				epo: currentEpoObject,
10421				alternativeCart: alternativeCart,
10422				this_product_type: this_product_type,
10423				cart: cart,
10424				bundleid: bundleid,
10425				totalsObject: tc_totals_ob,
10426				main_product: main_product,
10427				per_product_pricing: perProductPricing
10428			} );
10429
10430			hide_native_price = $.epoAPI.applyFilter( 'hide_native_price', true );
10431
10432			if ( showTotal && cartQty > 0 ) {
10433				// hide native prices
10434				if ( finalTotalBoxMode === 'disable_change' || TMEPOJS.tm_epo_change_variation_price === 'yes' ) {
10435					if ( hide_native_price === true && finalTotalBoxMode !== 'disable' && finalTotalBoxMode !== 'disable_change' ) {
10436						tm_get_native_prices_block( cart ).hide();
10437					} else {
10438						tm_get_native_prices_block( cart ).show();
10439					}
10440				}
10441
10442				if (
10443					finalTotalBoxMode === 'disable' ||
10444					finalTotalBoxMode === 'disable_change' ||
10445					( finalTotalBoxMode === 'hideiftotaliszero' && product_total_price === 0 ) ||
10446					( ( finalTotalBoxMode === 'hideifoptionsiszero' || finalTotalBoxMode === 'optionsiftotalnotzero' ) && total_plus_fee === 0 ) ||
10447					finalTotalBoxMode === 'hide'
10448				) {
10449					html = '';
10450					totalsHolder.html( html );
10451				} else {
10452					totalsHolder.html( html );
10453
10454					jWindow.trigger( 'tc-totals-container', {
10455						epo: tc_totals_ob,
10456						totals_holder: totalsHolder,
10457						data: {
10458							epo_object: currentEpoObject,
10459							tm_set_price: tm_set_price,
10460							tm_set_price_totals: tm_set_price_totals,
10461							product_total_price: product_total_price,
10462							product_price: productPrice,
10463							qty: cartQty
10464						},
10465						tm_epo_js: TMEPOJS
10466					} );
10467				}
10468
10469				if ( formatted_final_total && product_total_price >= 0 ) {
10470					update_native_html = tm_get_native_prices_block( cart );
10471
10472					if ( finalTotalBoxMode === 'disable_change' || TMEPOJS.tm_epo_change_variation_price === 'yes' ) {
10473						if ( totalsHolder.data( 'is-on-sale' ) ) {
10474							temp = $.epoAPI.util.decodeHTML(
10475								$.epoAPI.template.html( tcAPI.templateEngine.tc_formatted_sale_price, {
10476									price: _f_regular_price,
10477									sale_price: _fprice,
10478									customer_price_format_wrap_start: customer_price_format_wrap_start,
10479									customer_price_format_wrap_end: customer_price_format_wrap_end
10480								} )
10481							);
10482							temp = {
10483								formatted: temp,
10484								raw: tc_totals_ob.product_total_price
10485							};
10486							temp = replace_suffixes( 'formatted', 'raw', temp, totalsHolder );
10487							temp = temp.formatted;
10488							update_native_html
10489								.html( temp )
10490								.show();
10491						} else {
10492							temp = $.epoAPI.util.decodeHTML(
10493								$.epoAPI.template.html( tcAPI.templateEngine.tc_formatted_price, {
10494									price: _fprice,
10495									customer_price_format_wrap_start: customer_price_format_wrap_start,
10496									customer_price_format_wrap_end: customer_price_format_wrap_end
10497								} )
10498							);
10499							temp = {
10500								formatted: temp,
10501								raw: tc_totals_ob.product_total_price
10502							};
10503							temp = replace_suffixes( 'formatted', 'raw', temp, totalsHolder );
10504							temp = temp.formatted;
10505							update_native_html
10506								.html( temp )
10507								.show();
10508						}
10509					}
10510
10511					if ( finalTotalBoxMode === 'disable_change' || TMEPOJS.tm_epo_change_original_price === 'yes' ) {
10512						if ( ! alternativeCart || main_product.find( '.cpf-bto-price' ).length === 0 ) {
10513							if ( currentEpoObject.associated_connect ) {
10514								nativeProductPriceSelector = currentEpoObject.main_product.find( tcAPI.associatedNativeProductPriceSelector );
10515							} else {
10516								nativeProductPriceSelector = $( tcAPI.nativeProductPriceSelector );
10517							}
10518
10519							if ( nativeProductPriceSelector.length === 0 && main_product.is( '.tc-after-shop-loop' ) ) {
10520								nativeProductPriceSelector = main_product.closest( '.product' ).find( '.price' );
10521							}
10522							if ( nativeProductPriceSelector.data( 'tc-original-html' ) === undefined ) {
10523								nativeProductPriceSelector.data( 'tc-original-html', nativeProductPriceSelector.html() );
10524							}
10525							if ( product_total_price > 0 ) {
10526								if ( totalsHolder.data( 'is-on-sale' ) ) {
10527									temp = $.epoAPI.util.decodeHTML(
10528										$.epoAPI.template.html( tcAPI.templateEngine.tc_formatted_sale_price, {
10529											price: _f_regular_price,
10530											sale_price: _fprice,
10531											customer_price_format_wrap_start: customer_price_format_wrap_start,
10532											customer_price_format_wrap_end: customer_price_format_wrap_end
10533										} )
10534									);
10535									temp = {
10536										formatted: temp,
10537										raw: tc_totals_ob.product_total_price
10538									};
10539									temp = replace_suffixes( 'formatted', 'raw', temp, totalsHolder );
10540									temp = temp.formatted;
10541									nativeProductPriceSelector
10542										.html( temp )
10543										.show();
10544								} else {
10545									temp = $.epoAPI.util.decodeHTML(
10546										$.epoAPI.template.html( tcAPI.templateEngine.tc_formatted_price, {
10547											price: _fprice,
10548											customer_price_format_wrap_start: customer_price_format_wrap_start,
10549											customer_price_format_wrap_end: customer_price_format_wrap_end
10550										} )
10551									);
10552									temp = {
10553										formatted: temp,
10554										raw: tc_totals_ob.product_total_price
10555									};
10556									temp = replace_suffixes( 'formatted', 'raw', temp, totalsHolder );
10557									temp = temp.formatted;
10558									nativeProductPriceSelector
10559										.html( temp )
10560										.show();
10561								}
10562							} else if ( this_product_type && this_product_type !== 'composite' ) {
10563								if ( currentEpoObject.associated_connect ) {
10564									if ( currentEpoObject.variations_form.length ) {
10565										temp = currentEpoObject.this_epo_totals_container.data( 'variationIdElement' );
10566										if ( temp.length > 0 ) {
10567											temp = parseFloat( temp.val() );
10568											if ( ! ( ! temp || temp === 0 ) ) {
10569												nativeProductPriceSelector.html( $.epoAPI.util.decodeHTML( TMEPOJS.assoc_current_free_text ) );
10570											}
10571										}
10572									} else {
10573										nativeProductPriceSelector.html( $.epoAPI.util.decodeHTML( TMEPOJS.assoc_current_free_text ) );
10574									}
10575								} else {
10576									nativeProductPriceSelector.html( $.epoAPI.util.decodeHTML( TMEPOJS.current_free_text ) );
10577								}
10578							}
10579						}
10580
10581						jWindow.trigger( 'tcEpoMaybeChangePriceHtml', {
10582							epo: currentEpoObject,
10583							alternativeCart: alternativeCart,
10584							this_product_type: this_product_type,
10585							cart: cart,
10586							bundleid: bundleid,
10587							totalsObject: tc_totals_ob,
10588							main_product: main_product,
10589							nativePrice: _fprice
10590						} );
10591					}
10592				}
10593
10594				if ( alternativeCart ) {
10595					main_cart.trigger( {
10596						type: 'tm-epo-update',
10597						norules: 1
10598					} );
10599				} else {
10600					this_epo_totals_container.data( 'is_active', true );
10601				}
10602			} else {
10603				if ( currentEpoObject.associated_connect ) {
10604					nativeProductPriceSelector = currentEpoObject.main_product.find( tcAPI.associatedNativeProductPriceSelector );
10605					nativeProductPriceSelector.html( nativeProductPriceSelector.data( 'tc-original-html' ) );
10606				}
10607
10608				tm_get_native_prices_block( cart ).each( function() {
10609					var $npb = $( this );
10610					if ( ! $npb.data( 'tm-original-html' ) ) {
10611						$npb.data( 'tm-original-html', $npb.html() );
10612					} else {
10613						$npb.html( $npb.data( 'tm-original-html' ) );
10614					}
10615				} );
10616
10617				if ( rawProductPrice === 0 && TMEPOJS.tm_epo_remove_free_price_label === 'yes' ) {
10618					tm_get_native_prices_block( cart ).hide();
10619				} else if ( ( finalTotalBoxMode === 'disable_change' || TMEPOJS.tm_epo_change_variation_price === 'yes' ) && ! ( hide_native_price === true && finalTotalBoxMode !== 'disable' && finalTotalBoxMode !== 'disable_change' ) ) {
10620					tm_get_native_prices_block( cart ).show();
10621				}
10622
10623				totalsHolder.empty();
10624
10625				if ( alternativeCart ) {
10626					main_cart.trigger( {
10627						type: 'tm-epo-update',
10628						norules: 1
10629					} );
10630				}
10631			}
10632
10633			main_cart.trigger( 'tm-epo-after-update', {
10634				container: cartContainer
10635			} );
10636
10637			jWindow.trigger( 'tc-epo-after-update', {
10638				epo: tc_totals_ob,
10639				totals_holder: totalsHolder,
10640				data: {
10641					epo_object: currentEpoObject,
10642					add_late_fields_prices: add_late_fields_prices,
10643					tm_set_price: tm_set_price,
10644					tm_set_price_totals: tm_set_price_totals,
10645					product_total_price: product_total_price,
10646					product_price: productPrice,
10647					qty: cartQty,
10648					bundleid: bundleid,
10649					currentCart: currentCart
10650				},
10651				tm_epo_js: TMEPOJS
10652			} );
10653		} );
10654
10655		if ( this_product_type === 'variable' || this_product_type === 'variable-subscription' ) {
10656			epoVariationSection = epoHolder.find( '.tm-epo-variation-section' ).first();
10657
10658			// Custom variation events
10659			epoVariationSection
10660				.find( '.tm-epo-reset-variation' )
10661				.off( 'click.cpfv' )
10662				.on( 'click.cpfv', function() {
10663					var field = $( this );
10664					var id = $.epoAPI.dom.id( field.attr( 'data-tm-for-variation' ) );
10665					var section = field.closest( '.cpf-type-variations' );
10666					var inputs = field.closest( '.cpf-element' ).find( '.tm-epo-variation-element' );
10667					var lis = field.closest( '.cpf-element' ).find( '.tmcp-field-wrap' );
10668
10669					inputs.prop( 'checked', false );
10670					lis.removeClass( 'tc-active' );
10671					variationForm
10672						.find( "[data-attribute_name='attribute_" + id + "']" )
10673						.val( '' )
10674						.trigger( 'change' );
10675					variationForm.find( "[data-attribute_name='attribute_" + id + "']" ).trigger( 'focusin' );
10676
10677					main_product
10678						.find( '.cpf-type-variations' )
10679						.not( section )
10680						.each( function( i, el ) {
10681							variationForm.find( "[data-attribute_name='attribute_" + $.epoAPI.dom.id( $( el ).find( '.tm-epo-variation-element' ).first().attr( 'data-tm-for-variation' ) ) + "']" ).trigger( 'focusin' );
10682						} );
10683					field.trigger( 'blur' );
10684					variationForm.trigger( 'woocommerce_update_variation_values_tmlogic' );
10685				} );
10686
10687			epoVariationSection
10688				.find( 'input.tm-epo-variation-element,input.tm-epo-variation-element + span' )
10689				.off( 'mouseup.cpfv' )
10690				.on( 'mouseup.cpfv', function() {
10691					var field = $( this );
10692					var id;
10693
10694					if ( field.is( 'span' ) ) {
10695						field = field.prev( 'input' );
10696					}
10697					if ( field.attr( 'disabled' ) ) {
10698						variationForm.find( '.reset_variations' ).trigger( 'click' );
10699					}
10700					id = $.epoAPI.dom.id( field.attr( 'data-tm-for-variation' ) );
10701					variationForm.find( "[data-attribute_name='attribute_" + id + "']" ).trigger( 'focusin' );
10702				} );
10703
10704			epoVariationSection
10705				.off( 'click.' + eventName + '.tmepo', '.reset_variations, .tc-epo-element-variable-reset-variations' )
10706				.on( 'click.' + eventName + '.tmepo', '.reset_variations, .tc-epo-element-variable-reset-variations', { _epoObject: epoObject }, function( event ) {
10707					var _nativeProductPriceSelector;
10708					if ( finalTotalBoxMode === 'disable_change' || TMEPOJS.tm_epo_change_original_price === 'yes' ) {
10709						if ( ! alternativeCart || main_product.find( '.cpf-bto-price' ).length === 0 ) {
10710							if ( event.data._epoObject.associated_connect ) {
10711								_nativeProductPriceSelector = event.data._epoObject.main_product.find( tcAPI.associatedNativeProductPriceSelector );
10712							} else {
10713								_nativeProductPriceSelector = $( tcAPI.nativeProductPriceSelector );
10714							}
10715							if ( _nativeProductPriceSelector.data( 'tc-original-html' ) ) {
10716								_nativeProductPriceSelector.html( _nativeProductPriceSelector.data( 'tc-original-html' ) );
10717							}
10718						}
10719					}
10720					variationForm.find( '.variations .reset_variations, .tc-epo-element-variable-reset-variations' ).first().trigger( 'click' );
10721				} );
10722
10723			epoVariationSection
10724				.find( '.tm-epo-variation-element' )
10725				.off( 'change.cpfv tm_epo_variation_element_change' )
10726				.on( 'change.cpfv tm_epo_variation_element_change', function( e ) {
10727					var field = $( this );
10728					var id = $.epoAPI.dom.id( field.attr( 'data-tm-for-variation' ) );
10729					var value = field.val();
10730					var section = field.closest( '.cpf-type-variations' );
10731					var nativeSelect = variationForm.find( "[data-attribute_name='attribute_" + id + "']" );
10732					var exists;
10733
10734					if ( field.closest( '.tm-epo-variation-section' ).is( '.tm-hidden' ) ) {
10735						return;
10736					}
10737
10738					if ( ! ( e && e.type && e.type === 'tm_epo_variation_element_change' ) ) {
10739						exists = false;
10740						nativeSelect.each( function() {
10741							if ( this.value === value ) {
10742								exists = true;
10743								return false;
10744							}
10745						} );
10746						if ( ! exists ) {
10747							nativeSelect.trigger( 'focusin' );
10748						}
10749						nativeSelect.val( value ).trigger( 'change' );
10750					}
10751
10752					if ( ! value ) {
10753						nativeSelect.trigger( 'focusin' );
10754					}
10755
10756					main_product
10757						.find( '.cpf-type-variations' )
10758						.not( section )
10759						.each( function() {
10760							variationForm.find( '#' + $.epoAPI.dom.id( $( this ).find( '.tm-epo-variation-element' ).first().attr( 'data-tm-for-variation' ) ) ).trigger( 'focusin' );
10761						} );
10762
10763					field.trigger( 'blur' );
10764					variationForm.trigger( 'woocommerce_update_variation_values_tmlogic' );
10765				} )
10766				.off( 'focusin.cpfv' )
10767				.on( 'focusin.cpfv', function() {
10768					var field = $( this );
10769					var id;
10770
10771					if ( ! field.is( 'select' ) ) {
10772						return;
10773					}
10774
10775					id = $.epoAPI.dom.id( field.attr( 'data-tm-for-variation' ) );
10776					variationForm.find( "[data-attribute_name='attribute_" + id + "']" ).trigger( 'focusin' );
10777					variationForm.trigger( 'woocommerce_update_variation_values_tmlogic' );
10778				} );
10779
10780			variationForm.off( eventNamePrefix + 'found_variation.tmepo tm_fix_stock', '.single_variation_wrap' ).on( eventNamePrefix + 'found_variation.tmepo tm_fix_stock', '.single_variation_wrap', function() {
10781				tm_fix_stock_tmepo( $( this ), cartContainer );
10782			} );
10783
10784			// update prices when a variation is found
10785			variationForm
10786				.off( eventNamePrefix + 'found_variation.tmepo' )
10787				.on( eventNamePrefix + 'found_variation.tmepo', function( event, variation ) {
10788					var form = $( this );
10789
10790					totalsHolder.data( 'is-on-sale', variation.tc_is_on_sale );
10791					totalsHolder.data( 'regular-price', tm_set_backend_price( variation.display_regular_price, totalsHolder, variation ) );
10792
10793					jWindow.trigger( 'tm-epo-found-variation', {
10794						epo: epoObject,
10795						totalsHolder: totalsHolder,
10796						totalsHolderContainer: totalsHolderContainer,
10797						currentCart: currentCart,
10798						variationForm: form,
10799						variation: variation
10800					} );
10801
10802					found_variation_tmepo( {
10803						epoHolder: epoHolder,
10804						totalsHolder: totalsHolder,
10805						totalsHolderContainer: totalsHolderContainer,
10806						currentCart: currentCart,
10807						variationForm: form,
10808						variation: variation
10809					} );
10810
10811					tm_fix_stock_tmepo( form, cartContainer );
10812				} )
10813				.off( eventNamePrefix + 'hide_variation.tmepo' )
10814				.on( eventNamePrefix + 'hide_variation.tmepo', { _epoObject: epoObject }, function( event ) {
10815					var _nativeProductPriceSelector;
10816					if ( finalTotalBoxMode === 'disable_change' || TMEPOJS.tm_epo_change_original_price === 'yes' ) {
10817						if ( ! alternativeCart || main_product.find( '.cpf-bto-price' ).length === 0 ) {
10818							if ( event.data._epoObject.associated_connect ) {
10819								_nativeProductPriceSelector = event.data._epoObject.main_product.find( tcAPI.associatedNativeProductPriceSelector );
10820							} else {
10821								_nativeProductPriceSelector = $( tcAPI.nativeProductPriceSelector );
10822							}
10823							if ( _nativeProductPriceSelector.data( 'tc-original-html' ) ) {
10824								_nativeProductPriceSelector.html( _nativeProductPriceSelector.data( 'tc-original-html' ) );
10825							}
10826						}
10827					}
10828					totalsHolder.data( 'price', false );
10829					// Fancy product Designer
10830					totalsHolder.removeData( 'tcprice' );
10831					currentCart.trigger( {
10832						type: 'tm-epo-update',
10833						norules: 2
10834					} );
10835				} )
10836				.off( eventNamePrefix + 'check_variations.tmepo' )
10837				.on( eventNamePrefix + 'check_variations.tmepo', function() {
10838					var data = {};
10839					var chosen = 0;
10840					var reset = epoVariationSection.find( '.reset_variations' );
10841
10842					variationForm.find( '.variations select, .tc-epo-variable-product-selector' ).each( function() {
10843						var attribute_name = $( this ).data( 'attribute_name' ) || $( this ).attr( 'name' );
10844						var value = $( this ).val() || '';
10845
10846						if ( value.length > 0 ) {
10847							chosen++;
10848						}
10849
10850						data[ attribute_name ] = value;
10851					} );
10852
10853					if ( chosen > 0 ) {
10854						if ( reset.css( 'visibility' ) === 'hidden' ) {
10855							reset.css( 'visibility', 'visible' ).hide().fadeIn();
10856						}
10857					} else {
10858						reset.css( 'visibility', 'hidden' );
10859					}
10860				} )
10861				.trigger( eventNamePrefix + 'check_variations' );
10862
10863			tm_custom_variations( epoObject, cartContainer, itemId, main_product, epoHolder );
10864		}
10865
10866		selectSelector.trigger( 'tm-select-change-html' );
10867		tmQty.trigger( 'change.cpf', { init: 1 } );
10868		tmQuantity.trigger( 'showhide.cpfcustom' );
10869		epoFieldHasClearButton.filter( ':checked' ).trigger( 'cpfclearbutton' );
10870
10871		jWindow.on( 'tm-do-epo-update', function() {
10872			// This must be run every time to get correct results for percent price types
10873			// if set norules then discount will not auto work upon chosing a variation
10874			currentCart.trigger( {
10875				type: 'tm-epo-update'
10876				//"norules": 2
10877			} );
10878		} );
10879
10880		jWindow.trigger( 'tm-epo-init-events', {
10881			epo: {
10882				epo_id: epo_id,
10883				form: epoObject.form,
10884				currentCart: currentCart,
10885				cart_container: cartContainer,
10886				epo_holder: epoHolder,
10887				totals_holder_container: totalsHolderContainer,
10888				totals_holder: totalsHolder,
10889				main_cart: main_cart,
10890				main_epo_inside_form: main_epo_inside_form,
10891				product_id_selector: product_id_selector,
10892				epo_id_selector: epo_id_selector,
10893				product_id: product_id,
10894				this_epo_container: this_epo_container,
10895				this_totals_container: this_totals_container,
10896				this_epo_totals_container: this_epo_totals_container
10897			}
10898		} );
10899
10900		jWindow.trigger( 'epoEventHandlers', {
10901			epo: epoObject,
10902			currentCart: currentCart,
10903			cartContainer: cartContainer,
10904			qtyElement: qtyElement,
10905			epoHolder: epoHolder,
10906			totalsHolderContainer: totalsHolderContainer,
10907			totalsHolder: totalsHolder,
10908			variationForm: variationForm,
10909			variation_id_selector: variation_id_selector,
10910			main_epo_inside_form: main_epo_inside_form,
10911			this_product_type: this_product_type,
10912			get_price_excluding_tax: get_price_excluding_tax,
10913			get_price_including_tax: get_price_including_tax
10914		} );
10915
10916		// show final totals
10917		if ( finalTotalBoxMode !== 'disable' && finalTotalBoxMode !== 'disable_change' && finalTotalBoxMode !== 'hide' ) {
10918			totalsHolderContainer.addClass( 'tc-show' );
10919		}
10920
10921		// show extra options
10922		jWindow.trigger( 'epo_options_before_visible' );
10923
10924		if ( TMEPOJS.tm_epo_progressive_display === 'yes' ) {
10925			setTimeout( function() {
10926				epoHolder
10927					.css( 'opacity', 0 )
10928					.addClass( 'tc-show' )
10929					.animate(
10930						{
10931							opacity: 1
10932						},
10933						tcAPI.epoAnimationDelay,
10934						'easeOutExpo',
10935						function() {
10936							jWindow.trigger( 'epo_options_visible' );
10937							jWindow.trigger( 'tmlazy' );
10938						}
10939					);
10940			}, tcAPI.epoDelay );
10941		} else {
10942			epoHolder.addClass( 'tc-show' );
10943			jWindow.trigger( 'epo_options_visible' );
10944			jWindow.trigger( 'tmlazy' );
10945		}
10946
10947		main_product.addClass( 'tc-init' );
10948	}
10949
10950	function run_wc_variation_form_cpf( epoObject ) {
10951		var form = epoObject.variations_form;
10952		var cart = epoObject.main_cart;
10953		var this_epo_container = epoObject.this_epo_container;
10954		var eventName = epoObject.is_associated ? 'tc_variation_form.cpf' : 'wc_variation_form.cpf';
10955
10956		form.off( eventName ).on( eventName, function() {
10957			if ( form.data( 'epo_loaded' ) ) {
10958				return;
10959			}
10960
10961			// Start Condition Logic
10962			cpf_section_logic( this_epo_container );
10963			cpf_element_logic( this_epo_container );
10964
10965			// Init field price rules
10966			$.tcepo.lateFieldsPrices[ epoObject.epoEventId ] = [];
10967
10968			epoEventHandlers( epoObject );
10969			tm_set_upload_fields( epoObject );
10970			tm_product_image( epoObject );
10971
10972			epoObject.noEpoUpdate = false;
10973
10974			setTimeout( function() {
10975				run_cpfdependson( this_epo_container );
10976				cart.trigger( {
10977					type: 'tm-epo-update',
10978					rules: 'init'
10979				} );
10980			}, 10 );
10981
10982			form.data( 'epo_loaded', true );
10983		} );
10984
10985		if ( variationsFormIsLoaded ) {
10986			form.trigger( eventName );
10987		}
10988
10989		jWindow.trigger( 'epo-after-init', { epo: epoObject } );
10990	}
10991
10992	function detect_variation_swatches_interval( epoObject ) {
10993		var $id = requestAnimationFrame( function() {
10994			detect_variation_swatches_interval( epoObject );
10995		} );
10996		var obj = epoObject.variations_form;
10997		var bound = obj.data( 'bound' );
10998		var eventName = epoObject.is_associated ? 'tc_variation_form.cpf' : 'wc_variation_form.cpf';
10999
11000		if ( bound ) {
11001			cancelAnimationFrame( $id );
11002			run_wc_variation_form_cpf( epoObject );
11003			obj.trigger( eventName );
11004		}
11005	}
11006
11007	function manualInitEPO( epoObject, item, itemCart, itemEpoContainer, main_product ) {
11008		var epoObjectOriginal = $.extend( true, {}, epoObject );
11009		var product_id = itemEpoContainer.attr( 'data-product-id' );
11010		var epo_id = itemEpoContainer.attr( 'data-epo-id' );
11011		var product_id_selector = '.tm-product-id-' + product_id;
11012		var epo_id_selector = "[data-epo-id='" + epo_id + "']";
11013		var epoEventId = 'p' + product_id + 'e' + epo_id;
11014		var this_epo_container = $( '.tc-extra-product-options' + product_id_selector + epo_id_selector );
11015		var this_totals_container = $( '.tc-totals-form' + product_id_selector + epo_id_selector );
11016		var this_epo_totals_container = $( '.tc-epo-totals' + product_id_selector + epo_id_selector );
11017
11018		epoObject.isManual = true;
11019
11020		$.tcepo.formSubmitEvents[ epoEventId ] = [];
11021		$.tcepo.errorObject[ epoEventId ] = false;
11022		$.tcepo.initialActivation[ epoEventId ] = false;
11023
11024		epoObject.product_id = product_id;
11025		epoObject.product_id_selector = product_id_selector;
11026		epoObject.epo_id = epo_id;
11027		epoObject.epo_id_selector = epo_id_selector;
11028		epoObject.epoEventId = epoEventId;
11029		epoObject.noEpoUpdate = true;
11030		epoObject.thisForm = item;
11031		epoObject.this_epo_container = this_epo_container;
11032		epoObject.this_totals_container = this_totals_container;
11033		epoObject.this_epo_totals_container = this_epo_totals_container;
11034
11035		tm_lazyload();
11036		main_product.find( '.tm-collapse' ).tmtoggle();
11037		main_product.find( '.tm-section-link' ).tmsectionpoplink();
11038
11039		tm_set_datepicker( item );
11040		setRangePickers( item );
11041		setRangePickersEvents();
11042		tm_set_repeaters( item, epoObject );
11043		tm_css_styles( item );
11044		tm_set_color_pickers( itemEpoContainer );
11045		tm_set_lightbox( itemEpoContainer.find( '.tc-lightbox-image' ).not( '.tm-extra-product-options-variations .radio-image' ) );
11046
11047		// Start Condition Logic
11048		cpf_section_logic( itemEpoContainer );
11049		cpf_element_logic( itemEpoContainer );
11050		run_cpfdependson( itemEpoContainer );
11051
11052		$.tcToolTip( item.find( '.tm-tooltip' ) );
11053		epoEventHandlers( epoObject, item, itemCart );
11054
11055		epoObject.noEpoUpdate = false;
11056
11057		itemCart.trigger( {
11058			type: 'tm-epo-update',
11059			norules: 2
11060		} );
11061		setTimeout( function() {
11062			epoObject.main_cart.trigger( {
11063				type: 'tm-epo-update',
11064				epoObject: epoObjectOriginal,
11065				norules: 1
11066			} );
11067		}, 200 );
11068		tm_fix_stock_tmepo( itemCart, item );
11069	}
11070
11071	function tm_init_epo( main_product, is_quickview, product_id, epo_id, associated_connect, mainEpoObject, reactivate ) {
11072		// Holds the main cart when using Composite Products
11073		var main_cart = false;
11074		var main_epo_inside_form = false;
11075		var main_totals_inside_form = false;
11076		var epoEventId;
11077		var has_epo = typeof product_id !== 'undefined';
11078		var not_has_epo = false;
11079		var add_to_cart_field;
11080		var product_id_selector;
11081		var epo_id_selector;
11082		var this_epo_container;
11083		var this_totals_container;
11084		var this_epo_totals_container;
11085		var epo_object;
11086		var variations_form;
11087		var detect_variation_swatches = $( '.variation_form_section .variations-table' ).length > 0;
11088		var is_associated = false;
11089
11090		main_product = $( main_product );
11091
11092		if ( main_product.is( '.tc-init' ) && ! reactivate ) {
11093			return true;
11094		}
11095
11096		if ( is_quickview ) {
11097			errorContainer = main_product;
11098		} else {
11099			errorContainer = $( window );
11100		}
11101
11102		jWindow.trigger( 'tm-epo-init-start' );
11103
11104		if ( ! has_epo ) {
11105			if ( main_product.is( '.product' ) ) {
11106				not_has_epo = true;
11107				has_epo = jBody.find( tcAPI.epoSelector ).length;
11108			}
11109		}
11110
11111		// return if product has no extra options and the totals box is not enabled for all products
11112		if ( ! has_epo && TMEPOJS.tm_epo_enable_final_total_box_all === 'no' && ! main_product.is( '.tm-no-options-composite' ) ) {
11113			jWindow.trigger( 'tm-epo-init-end-no-options' );
11114			return;
11115		}
11116
11117		// set the main_product variable again for products that have no extra options
11118		if ( not_has_epo ) {
11119			jWindow.trigger( 'tm-epo-init-no-options' );
11120			if ( main_product.is( '.product' ) && ! ( main_product.is( '.tm-no-options-pxq' ) || main_product.is( '.tm-no-options-composite' ) ) ) {
11121				main_product = jBody;
11122			}
11123		}
11124
11125		if ( ! product_id ) {
11126			add_to_cart_field = main_product.find( tcAPI.addToCartSelector ).last();
11127			if ( add_to_cart_field.length > 0 ) {
11128				product_id = add_to_cart_field.val();
11129			} else {
11130				add_to_cart_field = $( '.tc-totals-form.tm-totals-form-main' );
11131				product_id = add_to_cart_field.attr( 'data-product-id' );
11132			}
11133			if ( ! product_id ) {
11134				product_id = '';
11135			}
11136		}
11137
11138		if ( ! epo_id ) {
11139			epo_id = parseInt( main_product.find( 'input.tm-epo-counter' ).last().val(), 10 );
11140
11141			if ( ! Number.isFinite( epo_id ) ) {
11142				epo_id = '';
11143			}
11144		}
11145
11146		product_id_selector = '.tm-product-id-' + product_id;
11147		epo_id_selector = "[data-epo-id='" + epo_id + "']";
11148		this_epo_container = $( '.tc-extra-product-options' + product_id_selector + epo_id_selector );
11149		this_totals_container = $( '.tc-totals-form' + product_id_selector + epo_id_selector );
11150		this_epo_totals_container = $( '.tc-epo-totals' + product_id_selector + epo_id_selector );
11151		variations_form = main_product.find( '.variations_form' ).not( '.composite_component .variations_form' ).first();
11152		epoEventId = 'p' + product_id + 'e' + epo_id;
11153
11154		if ( variations_form && variations_form.attr( 'data-product_id' ) ) {
11155			if ( variations_form.attr( 'data-product_id' ) !== product_id ) {
11156				variations_form = main_product.find( ".variations_form[data-product_id='" + product_id + "']" );
11157			}
11158		}
11159
11160		main_cart = get_main_cart( main_product, main_product, 'form', product_id );
11161		if ( main_cart.length === 0 ) {
11162			if ( main_product.is( '.tc-shortcode-wrap' ) ) {
11163				main_cart = get_main_cart( this_totals_container, this_totals_container, '.tc-totals-form', product_id );
11164			} else if ( main_product.is( '.tc-epo-element-product-container' ) ) {
11165				main_cart = main_product.find( tcAPI.associatedEpoCart );
11166				// should never be 0
11167				if ( main_cart.length === 0 ) {
11168					main_cart = this_epo_container.parent( tcAPI.associatedEpoSelector );
11169					if ( main_cart.length === 0 ) {
11170						main_cart = main_product.find( '.tc-epo-element-product-container-right' );
11171					}
11172				}
11173				is_associated = true;
11174			}
11175		}
11176
11177		if ( is_associated && variations_form.length === 0 && main_product.is( '.variations_form' ) ) {
11178			variations_form = main_product;
11179		}
11180
11181		$.tcepo.formSubmitEvents[ epoEventId ] = [];
11182		$.tcepo.errorObject[ epoEventId ] = false;
11183		$.tcepo.initialActivation[ epoEventId ] = false;
11184
11185		if ( main_cart.find( tcAPI.epoSelector ).length > 0 ) {
11186			main_epo_inside_form = true;
11187		}
11188		if ( main_cart.find( '.tc-totals-form' ).length > 0 ) {
11189			main_totals_inside_form = true;
11190		}
11191
11192		if ( ! main_totals_inside_form ) {
11193			$.tcepo.formSubmitEvents[ epoEventId ][ $.tcepo.formSubmitEvents[ epoEventId ].length ] = {
11194				trigger: function() {
11195					return true;
11196				},
11197				on_true: function() {
11198					// hidden fields see totals.php
11199					var epos_hidden = $( '.tc-totals-form.tm-product-id-' + product_id + "[data-epo-id='" + epo_id + "']" ).tcClone();
11200					var formepo = $( '<div class="tm-hidden tm-formepo-normal"></div>' );
11201
11202					main_cart.find( '.tm-formepo-normal' ).remove();
11203					formepo.append( epos_hidden );
11204					main_cart.append( formepo );
11205					return true;
11206				},
11207				on_false: function() {
11208					setTimeout( function() {
11209						$( '.tm-formepo-normal' ).remove();
11210					}, 100 );
11211				}
11212			};
11213		}
11214		if ( ! main_epo_inside_form ) {
11215			$.tcepo.formSubmitEvents[ epoEventId ][ $.tcepo.formSubmitEvents[ epoEventId ].length ] = {
11216				trigger: function() {
11217					return true;
11218				},
11219				on_true: function() {
11220					// visible fields
11221					var epos = $( tcAPI.epoSelector + '.tm-product-id-' + product_id + "[data-epo-id='" + epo_id + "']" )
11222						.tcClone()
11223						.addClass( 'formepo' );
11224					var formepo = $( '<div class="tm-hidden tm-formepo"></div>' );
11225
11226					main_cart.find( '.tm-formepo' ).remove();
11227					formepo.append( epos );
11228
11229					main_cart.append( formepo );
11230					return true;
11231				},
11232				on_false: function() {
11233					setTimeout( function() {
11234						$( '.tm-formepo' ).remove();
11235					}, 100 );
11236				}
11237			};
11238		}
11239
11240		epo_object = {
11241			main_product: main_product,
11242			main_cart: main_cart,
11243			epo_id: epo_id,
11244			form: get_main_form( main_product ),
11245			main_epo_inside_form: main_epo_inside_form,
11246			product_id_selector: product_id_selector,
11247			epo_id_selector: epo_id_selector,
11248			product_id: product_id,
11249			this_epo_container: this_epo_container,
11250			this_totals_container: this_totals_container,
11251			this_epo_totals_container: this_epo_totals_container,
11252			qtySelector: tcAPI.qtySelector,
11253			manualInitEPO: manualInitEPO,
11254			epoEventId: epoEventId,
11255			variations_form: variations_form,
11256			has_epo: has_epo,
11257			is_quickview: is_quickview,
11258			is_associated: is_associated,
11259			is_epo_shortcode: this_epo_container.is( '.tc-shortcode' ),
11260			mainEpoObject: mainEpoObject,
11261			associated_connect: associated_connect,
11262			noEpoUpdate: true
11263		};
11264
11265		$( epo_object.form ).data( 'epo_object', epo_object );
11266
11267		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 );
11268
11269		tm_set_checkboxes_rules( epo_object );
11270		tm_set_upload_rules( epo_object );
11271		tm_set_datepicker( this_epo_container );
11272		setRangePickers( this_epo_container );
11273		setRangePickersEvents();
11274		tm_set_repeaters( this_epo_container, epo_object );
11275		tm_set_url_fields();
11276
11277		$.tcToolTip( this_epo_container.find( '.tm-tooltip' ) );
11278
11279		this_epo_container.find( '.tm-collapse' ).tmtoggle();
11280		this_epo_container.find( '.tm-section-link' ).tmsectionpoplink();
11281
11282		if ( reactivate ) {
11283			this_epo_container.addClass( 'reactivate' );
11284		}
11285
11286		if ( variations_form.length > 0 ) {
11287			if ( reactivate ) {
11288				variations_form.data( 'epo_loaded', false );
11289			}
11290			this_epo_totals_container.data( 'price', false );
11291			if ( detect_variation_swatches ) {
11292				detect_variation_swatches_interval( epo_object );
11293			} else {
11294				run_wc_variation_form_cpf( epo_object );
11295			}
11296		} else {
11297			setTimeout( function() {
11298				// Start Condition Logic
11299				cpf_section_logic( this_epo_container );
11300				cpf_element_logic( this_epo_container );
11301				run_cpfdependson( this_epo_container );
11302
11303				// Init field price rules
11304				$.tcepo.lateFieldsPrices[ epoEventId ] = [];
11305				epoEventHandlers( epo_object );
11306				tm_set_upload_fields( epo_object );
11307				tm_product_image( epo_object );
11308
11309				jWindow.trigger( 'epo-after-init-in-timeout', { epo: epo_object } );
11310
11311				main_cart.trigger( 'tm-epo-check-dpd' );
11312				epo_object.noEpoUpdate = false;
11313				main_cart.trigger( {
11314					type: 'tm-epo-update',
11315					rules: 'init'
11316				} );
11317			}, 20 );
11318			jWindow.trigger( 'epo-after-init', { epo: epo_object } );
11319		}
11320
11321		tm_lazyload();
11322
11323		tm_css_styles( this_epo_container );
11324		tm_set_color_pickers( this_epo_container );
11325		tm_set_lightbox( this_epo_container.find( '.tc-lightbox-image' ).not( '.tm-extra-product-options-variations .radio-image' ) );
11326		tm_theme_specific_actions( epo_object );
11327		tc_compatibility( epo_object );
11328
11329		if ( ! is_associated ) {
11330			tm_floating_totals( this_epo_totals_container, is_quickview, main_cart );
11331			tm_form_submit_event( epo_object );
11332			tm_show_hide_add_to_cart_button( main_product, epo_object, $.tcepo.oneOptionIsSelected[ epoEventId ], epo_object );
11333		}
11334
11335		jWindow.trigger( 'tm-epo-init-end', { epo: epo_object } );
11336
11337		return epo_object;
11338	}
11339
11340	function manual_init( container, reactivate ) {
11341		var $this = $( container );
11342		var product_id = $this.attr( 'data-product-id' );
11343		var epo_id = $this.attr( 'data-epo-id' );
11344		var quickview_floating = false;
11345		var testForm = $this.parent();
11346		if ( ! testForm.is( 'form' ) ) {
11347			testForm = $this.closest( 'form' );
11348			if ( ! testForm.is( 'form' ) ) {
11349				testForm = $this.parent();
11350			}
11351		}
11352		testForm = testForm.parent();
11353
11354		tm_init_epo( testForm, quickview_floating, product_id, epo_id, undefined, undefined, reactivate );
11355	}
11356
11357	function init_epo_plugin() {
11358		var epo_container;
11359		var epo_options_container;
11360
11361		if ( TMEPOJS.tm_epo_no_lazy_load === 'no' ) {
11362			$.extend( $.lazyLoadXT, {
11363				autoInit: false,
11364				selector: 'img.tmlazy',
11365				srcAttr: 'data-original',
11366				visibleOnly: false,
11367				updateEvent: $.lazyLoadXT.updateEvent + ' tmlazy'
11368			} );
11369		}
11370		/*
11371		 * tm-no-options-pxq = product has not options but the "Enable Final total box for all products" is on
11372		 * tm-no-options-composite = product is a composite product with no options but at least one of its bundles have options
11373		 */
11374		epo_container = $( '.tm-no-options-pxq, .tm-no-options-composite' );
11375
11376		if ( epo_container.length > 0 ) {
11377			// Special cases
11378			// -------------
11379			// Price x Quantity display (.tm-no-options-pxq) & composite
11380			// without option but a component has extra options
11381			// (.tm-no-options-composite)
11382
11383			epo_container.each( function( loop_index, product_wrap ) {
11384				tm_init_epo( $( product_wrap ), false );
11385			} );
11386		}
11387
11388		// The setTimeout is used for compatibility with
11389		// skeleton screen mode that some themes have
11390
11391		setTimeout( function() {
11392			try {
11393				// new main way of calling tm_init_epo
11394				// -----------------------------------
11395				// Normal product pages
11396
11397				epo_options_container = $( tcAPI.epoSelector ).not( tcAPI.associatedEpoSelector + ' ' + tcAPI.epoSelector + ', .tm-no-options-pxq, .tm-no-options-composite, .wc-product-table ' + tcAPI.epoSelector );
11398
11399				if ( epo_options_container.length > 0 ) {
11400					epo_options_container.each( function() {
11401						var $this = $( this );
11402						var product_id = $this.attr( 'data-product-id' );
11403						var epo_id = $this.attr( 'data-epo-id' );
11404						var quickview_floating = false;
11405						var jProductWrap;
11406						var addInputs = false;
11407
11408						// First check if we are in a loop.
11409						jProductWrap = $this.closest( '.tc-after-shop-loop.tm-has-options' );
11410
11411						if ( jProductWrap.length === 0 ) {
11412							// Check based on plugin add to cart selector.
11413							jProductWrap = $( tcAPI.tcAddToCartSelector + "[data-epo-id='" + epo_id + "'][value='" + product_id + "']" )
11414								.closest( 'form,.cart' )
11415								.first()
11416								.parent();
11417							// Check based on native add to cart selector.
11418							if ( jProductWrap.length === 0 ) {
11419								jProductWrap = $( tcAPI.addToCartSelector + "[value='" + product_id + "']" )
11420									.closest( 'form,.cart' )
11421									.first()
11422									.parent();
11423								if ( jProductWrap.length === 0 ) {
11424									// Check if we are in a shortcode
11425									jProductWrap = $this.closest( 'form,.cart' ).first().parent( '.tm-has-options' );
11426									if ( jProductWrap.length === 0 ) {
11427										if ( $this.is( '.tc-shortcode' ) ) {
11428											jProductWrap = $this.wrap( '<div class="tc-shortcode-wrap tc-wrap-' + epo_id + '"></div>' );
11429											jProductWrap = $this.parent();
11430										}
11431										if ( jProductWrap.length > 0 ) {
11432											addInputs = true;
11433										}
11434									}
11435								}
11436							}
11437						} else {
11438							addInputs = true;
11439						}
11440
11441						if ( jProductWrap.length > 0 ) {
11442							if ( addInputs ) {
11443								// in shop (variation logic will not work here)
11444								quickview_floating = true;
11445								$this
11446									.closest( 'form,.cart' )
11447									.first()
11448									.append( $( '<input name="add-to-cart" value="' + product_id + '" type="hidden">' ) );
11449								$this.closest( 'form,.cart' ).first().append( $( '<input type="hidden" value="" class="variation_id" name="variation_id">' ) );
11450							}
11451
11452							if ( jProductWrap.is( 'form' ) ) {
11453								jProductWrap = jProductWrap.parent();
11454							}
11455
11456							tm_init_epo( jProductWrap, quickview_floating, product_id, epo_id );
11457						}
11458					} );
11459				}
11460			} catch ( err ) {
11461				window.console.log( err );
11462				errorObject = err;
11463			}
11464		}, 1 );
11465	}
11466
11467	$.tcepo.tm_init_epo = function( main_product, is_quickview, product_id, epo_id ) {
11468		tm_init_epo( main_product, is_quickview, product_id, epo_id );
11469	};
11470
11471	$.tcepo.tmLazyloadContainer = function( container ) {
11472		tmLazyloadContainer = container;
11473	};
11474
11475	jWindow.on( 'tc_manual_init', function( evt, container ) {
11476		var reactivate;
11477		if ( 'container' in container && 'reactivate' in container ) {
11478			reactivate = container.reactivate;
11479			container = container.container;
11480		}
11481		manual_init( container, reactivate );
11482	} );
11483
11484	// document ready
11485	$( function() {
11486		tcAPI = $.epoAPI.applyFilter( 'tc_api', tcAPI );
11487
11488		jWindow.on( 'lazyLoadXToncomplete', function() {
11489			$( '.tm-owl-slider' ).each( function() {
11490				$( this ).trigger( 'refresh.owl.carousel' );
11491			} );
11492		} );
11493
11494		jWindow.on( 'tc_init_epo_plugin', function( evt ) {
11495			init_epo_plugin( evt );
11496		} );
11497
11498		jWindow.on( 'tcShowLastError', function() {
11499			window.console.log( errorObject );
11500		} );
11501
11502		jBody.on( 'adding_to_cart', function( e, button, data ) {
11503			window.console.log( data );
11504		} );
11505
11506		jBody.on( 'click.tcajax', '.ajax_add_to_cart', function() {
11507			var _pid;
11508			var epos;
11509			var _cpf_product_price;
11510			var form_prefix;
11511			var epoid;
11512			var obj;
11513			var data;
11514			currentAjaxButton = $( this );
11515
11516			if ( undefined !== currentAjaxButton.attr( 'data-product_id' ) ) {
11517				epoid = currentAjaxButton.closest( '.cart' ).find( '.tm-epo-counter' ).val();
11518				if ( ! epoid ) {
11519					return;
11520				}
11521				if ( currentAjaxButton.closest( '.tm-has-options' ).length !== 1 ) {
11522					return;
11523				}
11524
11525				_pid = currentAjaxButton.attr( 'data-product_id' );
11526				obj = {};
11527
11528				epos = $( '.tc-extra-product-options.tm-product-id-' + _pid + '[data-epo-id="' + epoid + '"]' );
11529
11530				if ( epos.length > 1 ) {
11531					if ( epos.filter( '.formepo' ) ) {
11532						epos = epos.filter( '.formepo' );
11533					} else {
11534						epos = epos.first();
11535					}
11536				}
11537
11538				if ( epos.length === 1 ) {
11539					_cpf_product_price = $( '.tc-totals-form.tm-product-id-' + _pid + '[data-epo-id="' + epoid + '"]' )
11540						.find( '.cpf-product-price' )
11541						.val();
11542					form_prefix = $( '.tc-totals-form.tm-product-id-' + _pid + '[data-epo-id="' + epoid + '"]' )
11543						.find( '.tc_form_prefix' )
11544						.val();
11545
11546					obj = $.extend( obj, {
11547						tcajax: 1,
11548						tcaddtocart: _pid,
11549						cpf_product_price: _cpf_product_price
11550					} );
11551					if ( form_prefix ) {
11552						obj.tc_form_prefix = form_prefix;
11553					}
11554				}
11555				data = currentAjaxButton.data();
11556				data = $.extend( data, epos.tcSerializeObject(), obj );
11557
11558				currentAjaxButton.removeData();
11559				currentAjaxButton.data( data );
11560			}
11561		} );
11562
11563		$.ajaxPrefilter( function( options, originalOptions ) {
11564			var found = false;
11565			var hashes;
11566			var hash;
11567			var i;
11568			var params;
11569			var $thisbutton;
11570			var _data;
11571			var _urldata;
11572			var _pid;
11573			var epos;
11574			var _cpf_product_price;
11575			var form_prefix;
11576			var obj;
11577			var oldData;
11578			var formData;
11579
11580			if ( TMEPOJS.tm_epo_enable_in_shop === 'yes' ) {
11581				hashes = options.url.split( '?' );
11582
11583				if ( hashes && hashes.length >= 1 ) {
11584					hashes = hashes[ 1 ];
11585					if ( hashes ) {
11586						hash = hashes.split( '&' );
11587						for ( i = 0; i < hash.length; i += 1 ) {
11588							params = hash[ i ].split( '=' );
11589							if ( params.length >= 1 ) {
11590								if ( params[ 0 ] && params[ 1 ] && params[ 0 ] === 'wc-ajax' && params[ 1 ] === 'add_to_cart' ) {
11591									found = true;
11592								}
11593							}
11594						}
11595						if ( found ) {
11596							options.originalsuccess = options.success;
11597							options.success = function( response ) {
11598								if ( response && response.error && response.product_url ) {
11599									if ( currentAjaxButton && currentAjaxButton.length === 1 ) {
11600										$thisbutton = currentAjaxButton;
11601									}
11602									$thisbutton = $( ".ajax_add_to_cart[data-product_id='" + originalOptions.data.product_id + "']" );
11603									$thisbutton.removeClass( 'added' );
11604									$thisbutton.removeClass( 'loading' );
11605								} else {
11606									options.originalsuccess.call( null, response );
11607								}
11608							};
11609						}
11610					}
11611				}
11612			}
11613
11614			if ( FormData && originalOptions.data ) {
11615				_data = originalOptions.data;
11616				if ( typeof originalOptions.data === 'string' ) {
11617					_data = $.epoAPI.util.parseParams( originalOptions.data );
11618				}
11619				_urldata = [];
11620				if ( originalOptions.url && originalOptions.url.indexOf ) {
11621					_urldata = $.epoAPI.util.parseParams( originalOptions.url.slice( originalOptions.url.indexOf( '?' ) + 1 ) );
11622				}
11623
11624				if ( 'quantity' in _data && ( _data.product_id || _data[ 'add-to-cart' ] || _urldata.product_id || _urldata[ 'add-to-cart' ] || _data.tcaddtocart ) ) {
11625					_pid = _data.product_id || _data[ 'add-to-cart' ] || _urldata.product_id || _urldata[ 'add-to-cart' ] || _data.tcaddtocart;
11626					if ( currentAjaxButton && currentAjaxButton.length === 1 && currentAjaxButton.closest( '.tm-has-options' ).length === 1 ) {
11627						epos = currentAjaxButton.closest( '.tm-has-options' ).find( '.tc-extra-product-options.tm-product-id-' + _pid );
11628					} else {
11629						epos = $( '.tc-extra-product-options.tm-product-id-' + _pid );
11630					}
11631
11632					if ( epos.length > 1 ) {
11633						if ( epos.filter( '.formepo' ) ) {
11634							epos = epos.filter( '.formepo' );
11635						} else {
11636							epos = epos.first();
11637						}
11638					}
11639					if ( epos.length === 1 ) {
11640						_cpf_product_price = $( '.tc-totals-form.tm-product-id-' + _pid )
11641							.find( '.cpf-product-price' )
11642							.val();
11643						form_prefix = $( '.tc-totals-form.tm-product-id-' + _pid )
11644							.find( '.tc_form_prefix' )
11645							.val();
11646						obj = {
11647							tcajax: 1,
11648							tcaddtocart: _pid,
11649							cpf_product_price: _cpf_product_price
11650						};
11651						if ( form_prefix ) {
11652							obj.tc_form_prefix = form_prefix;
11653						}
11654
11655						options.data = $.epoAPI.util.parseParams( options.data, true );
11656						options.data = $.extend( options.data, epos.tcSerializeObject(), obj );
11657						oldData = options.data;
11658						formData = new FormData();
11659
11660						Object.keys( oldData ).forEach( function( key ) {
11661							formData.append( key, oldData[ key ] );
11662						} );
11663
11664						epos.find( ':file' )
11665							.toArray()
11666							.forEach( function( el ) {
11667								for ( i = 0; i < $( el )[ 0 ].files.length; i++ ) {
11668									formData.append( $( el ).attr( 'name' ), $( el )[ 0 ].files[ i ] );
11669								}
11670							} );
11671
11672						options.data = formData;
11673						options.contentType = false;
11674						options.cache = false;
11675						options.processData = false;
11676					}
11677				}
11678			}
11679		} );
11680
11681		jDocument.ajaxSuccess( function( event, request, settings ) {
11682			// quickview plugins
11683			var qv_container = TMEPOJS.quickview_array || 'null';
11684			var fromaddons = TMEPOJS.quickview_container || 'null';
11685			var added = {};
11686			var selectors;
11687			var container;
11688			var product_id;
11689			var epo_id;
11690			var noProductCheck;
11691			var testContainer;
11692			var parsedUrl;
11693			var time = 1;
11694			var detectContainer;
11695			var requestContainer;
11696
11697			parsedUrl = $.epoAPI.util.parseParams( settings.data );
11698			if ( parsedUrl.action === 'wc_epo_get_associated_product_html' ) {
11699				return;
11700			}
11701
11702			$( '.tm-formepo-normal' ).remove();
11703			$( '.tm-formepo' ).remove();
11704
11705			//fix for menu cart pop up
11706			$( '.tm-cart-link' ).tmpoplink();
11707
11708			qv_container = $.epoAPI.util.parseJSON( qv_container );
11709
11710			fromaddons = $.epoAPI.util.parseJSON( fromaddons );
11711
11712			for ( selectors in fromaddons ) {
11713				if ( Object.prototype.hasOwnProperty.call( fromaddons, selectors ) ) {
11714					added[ fromaddons[ selectors ][ 0 ] ] = $( fromaddons[ selectors ][ 1 ] );
11715				}
11716			}
11717
11718			$.extend( qv_container, added );
11719
11720			detectContainer = function() {
11721				var keyfound = false;
11722				Object.keys( qv_container ).forEach( function( key ) {
11723					if ( $( qv_container[ key ] ).length ) {
11724						keyfound = key;
11725					}
11726				} );
11727				return keyfound;
11728			};
11729			requestContainer = function( times ) {
11730				var id = requestAnimationFrame( function() {
11731					setTimeout( function() {
11732						requestContainer( times - 1 );
11733					}, 200 );
11734				} );
11735				var key = detectContainer();
11736				var epoContainer;
11737
11738				if ( key || 0 === times ) {
11739					cancelAnimationFrame( id );
11740					if ( key ) {
11741						noProductCheck = false;
11742						container = $( qv_container[ key ] );
11743
11744						if ( key === 'woothemes_quick_view' && container.is( '.fusion-woocommerce-quick-view-container' ) ) {
11745							return true;
11746						}
11747
11748						if ( key === 'fusion_quick_view_load' && container.find( tcAPI.epoSelector ).length === 0 ) {
11749							return true;
11750						}
11751
11752						if ( key === 'woodmart_quick_shop' ) {
11753							parsedUrl = $.epoAPI.util.parseParams( settings.url );
11754							if ( parsedUrl.action === 'woodmart_quick_shop' ) {
11755								testContainer = $( $.epoAPI.util.escapeSelector( qv_container[ key ] + '.post-' + parsedUrl.id ) );
11756								if ( testContainer.length ) {
11757									container = testContainer;
11758									noProductCheck = true;
11759								}
11760							}
11761						}
11762						if ( key === 'woodmart_quick_view' ) {
11763							parsedUrl = $.epoAPI.util.parseParams( settings.url );
11764							if ( parsedUrl.action === 'woodmart_quick_view' ) {
11765								testContainer = $( $.epoAPI.util.escapeSelector( qv_container[ key ] + '.post-' + parsedUrl.id ) );
11766								if ( testContainer.length ) {
11767									container = testContainer;
11768									noProductCheck = true;
11769								}
11770							}
11771						}
11772
11773						if ( key === 'quickview_pro' ) {
11774							parsedUrl = settings.url.split( '/' );
11775							if ( parsedUrl.length ) {
11776								testContainer = $( $.epoAPI.util.escapeSelector( qv_container[ key ] + ' .post-' + parsedUrl[ parsedUrl.length - 1 ] ) );
11777								if ( testContainer.length ) {
11778									container = testContainer;
11779									noProductCheck = true;
11780								}
11781							}
11782						}
11783
11784						if ( key === 'exwoofood_booking_info' || key === 'wqv_popup_content' || key === 'wp_food' || key === 'jet_popup_get_content' ) {
11785							noProductCheck = true;
11786						}
11787
11788						if ( key === 'woofood' && settings.data ) {
11789							parsedUrl = $.epoAPI.util.parseParams( settings.data );
11790							if ( parsedUrl.action === 'woofood_quickview_ajax' ) {
11791								testContainer = testContainer = container.find( 'form' ).parent();
11792								if ( testContainer.length ) {
11793									container = testContainer;
11794									noProductCheck = true;
11795								}
11796							}
11797						}
11798
11799						if ( container.find( '.product' ).length === 0 && container.is( '.product' ) ) {
11800							noProductCheck = true;
11801						}
11802
11803						if ( ( container.find( '.product' ).length > 0 || noProductCheck ) ) {
11804							container.removeClass( 'tc-init' );
11805
11806							if (
11807								key === 'fusion_quick_view_load' ||
11808								key === 'jet_popup_get_content' ||
11809								key === 'wp_food' ||
11810								key === 'woodmart_quick_shop' ||
11811								key === 'woodmart_quick_view' ||
11812								key === 'lightboxpro' ||
11813								key === 'jckqv_quick_view' ||
11814								key === 'yith_quick_view' ||
11815								key === 'theme_flatsome'
11816							) {
11817								variationsFormIsLoaded = true;
11818							}
11819							tmLazyloadContainer = container;
11820							epoContainer = tmLazyloadContainer.find( tcAPI.epoSelector );
11821							if ( epoContainer.length === 0 ) {
11822								delete qv_container[ key ];
11823								requestContainer( 10 );
11824								return true;
11825							}
11826
11827							if ( key === 'fusion_quick_view_load' ) {
11828								time = 1400;
11829							}
11830
11831							setTimeout( function() {
11832								product_id = epoContainer.attr( 'data-product-id' );
11833								epo_id = epoContainer.attr( 'data-epo-id' );
11834								if ( key === 'woodmart_quick_shop' ) {
11835									container.addClass( 'has-options' );
11836								}
11837
11838								// Reset element cache
11839								tcAPI.getElementFromFieldCache = [];
11840								tm_init_epo( tmLazyloadContainer, true, product_id, epo_id );
11841								jWindow.trigger( 'tmlazy' );
11842								jWindow.trigger( 'tm_epo_loaded_quickview' );
11843								if ( $.jMaskGlobals ) {
11844									tmLazyloadContainer.find( $.jMaskGlobals.maskElements ).each( function() {
11845										var t = $( this );
11846
11847										if ( t.attr( 'data-mask' ) ) {
11848											t.mask( t.attr( 'data-mask' ) );
11849										}
11850									} );
11851								}
11852							}, time );
11853						}
11854					}
11855				}
11856			};
11857			requestContainer( 10 );
11858		} );
11859
11860		init_epo_plugin();
11861
11862		$( '.tm-cart-link' ).tmpoplink();
11863		jBody.on( 'updated_checkout', function() {
11864			$( '.tm-cart-link' ).tmpoplink();
11865		} );
11866
11867		jWindow.trigger( 'tmlazy' );
11868
11869		jWindow.trigger( 'tm_epo_loaded' );
11870	} );
11871
11872	// document ready
11873	$( function() {
11874		// Remove accept attribute from upload buttons when in Facebook or Instagram internral browser
11875		var ua = navigator.userAgent || navigator.vendor || window.opera;
11876		ua = ( ua.indexOf( 'FBAN' ) > -1 ) || ( ua.indexOf( 'FBAV' ) > -1 ) || ( ua.indexOf( 'Instagram' ) > -1 );
11877		if ( ua ) {
11878			$( '.tmcp-upload' ).removeAttr( 'accept' );
11879		}
11880
11881		// Fix several custom quantity buttons on themes
11882		jDocument.on( 'click', '.quantity .jckqv-qty-spinner, .quantity .ui-spinner-button', function() {
11883			$( this ).closest( '.quantity' ).find( tcAPI.qtySelector ).trigger( 'change' );
11884		} );
11885
11886		// bulk variations forms plugin
11887		$( '#wholesale_form' ).on( 'submit', function() {
11888			var _product_id = $( 'form.cart' ).find( tcAPI.addToCartSelector ).val();
11889			// visible fields
11890			var epos = $( tcAPI.epoSelector + ".tm-cart-main[data-product-id='" + _product_id + "']" ).tcClone();
11891			// hidden fields see totals.php
11892			var epos_hidden = $( ".tm-totals-form-main[data-product-id='" + _product_id + "']" ).tcClone();
11893			var formepo = $( "<div class='tm-hidden tm-formepo'></div>" );
11894
11895			formepo.append( epos );
11896			formepo.append( epos_hidden );
11897			$( this ).append( formepo );
11898			return true;
11899		} );
11900
11901		// Disable quote button if option validation fails
11902		jDocument.on( 'click', '#add_to_quote', function( e ) {
11903			var form;
11904			var epo_id;
11905			var epos;
11906
11907			if ( TMEPOJS && TMEPOJS.tm_epo_global_enable_validation === 'yes' ) {
11908				form = $( this ).parents( 'form' );
11909				epo_id = parseInt( form.find( '.tm-epo-counter' ).val(), 10 );
11910				epos = $( tcAPI.epoSelector + "[data-epo-id='" + epo_id + "']" );
11911
11912				//not validated
11913				if ( TMEPOJS.tm_epo_global_enable_validation === 'yes' && $.tc_validator && form.length > 0 && epos.length > 0 && ! form.tc_validate().form() ) {
11914					e.stopImmediatePropagation();
11915				}
11916			}
11917		} );
11918
11919		// PayPal for WooCommerce (PayPal Express Checkout button fix)
11920		$( '.single_add_to_cart_button.paypal_checkout_button' ).on( 'click', function( event ) {
11921			// this is the selector used by the paypal checkout plugin
11922			var form = $( '.cart' );
11923			var validator;
11924
11925			if ( form.data( 'tc_validator' ) ) {
11926				validator = form.data( 'tc_validator' );
11927				if ( validator.errorList ) {
11928					event.stopImmediatePropagation();
11929				}
11930			}
11931		} );
11932
11933		$( '.wc-product-table' ).on( 'init.wcpt', function( event, table ) {
11934			table.$table.find( tcAPI.epoSelector ).addClass( 'hidden' );
11935			table.$table.find( 'thead tr' ).append( '<th>&nbsp;</th>' );
11936			setTimeout( function() {
11937				table.$table.find( '.cart:not(.cart_group)' ).each( function() {
11938					var epo = $( this ).find( tcAPI.epoSelector );
11939					var tr = epo.closest( 'tr' );
11940
11941					$( "<td class='wc-product-table-epo'></td>" ).appendTo( tr ).append( epo );
11942					$( window ).trigger( 'tc_manual_init', epo );
11943					epo.removeClass( 'hidden' );
11944				} );
11945			}, 500 );
11946		} );
11947	} );
11948}( 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.