PageSourceSearch

https://www.inkablelabel.com/wp-content/plugins/woocommerce-tm-ext…/assets/js/tm-epo.js?ver=6.4.4

js inkablelabel.com collected 2026-10-09 22:50:09 UTC 452,172 bytes, 12,867 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 .associated-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( e, data ) {
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 ( data === undefined && 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', { nomove: 1 } );
493			}
494			init_done = 1;
495			return elements;
496		};
497	}
498
499	if ( ! $().tmpoplink ) {
500		$.fn.tmpoplink = function( options ) {
501			var elements = this;
502			var floatbox_template;
503			var settings = {
504				classname: 'flasho tc-wrapper cart-popup'
505			};
506
507			if ( elements.length === 0 ) {
508				return;
509			}
510			if ( options ) {
511				settings = $.extend( {}, settings, options );
512			}
513
514			floatbox_template = function( data ) {
515				return $.epoAPI.template.html( wp.template( 'tc-cart-options-popup' ), {
516					title: data.title,
517					id: data.id,
518					html: data.html,
519					close: TMEPOJS.i18n_close
520				} );
521			};
522
523			return elements.each( function() {
524				var t = $( this );
525				var id;
526				var title;
527				var html;
528				var $_html;
529
530				if ( t.is( '.tc-poplink' ) ) {
531					return;
532				}
533				t.addClass( 'tc-poplink' );
534				id = $( this ).attr( 'href' );
535				title = $( this ).attr( 'data-title' );
536				html = $( id ).html();
537				if ( ! title ) {
538					title = TMEPOJS.i18n_addition_options;
539				}
540				$_html = floatbox_template( {
541					id: 'tc-floatbox-content',
542					html: html,
543					title: title
544				} );
545
546				t.on( 'click.tmpoplink', function( e ) {
547					$.tcFloatBox( {
548						fps: 1,
549						ismodal: false,
550						refresh: 100,
551						width: '80%',
552						height: '80%',
553						classname: settings.classname,
554						data: $_html
555					} );
556
557					e.preventDefault();
558				} );
559			} );
560		};
561	}
562
563	function readableFileSize( a, b, c, d, e ) {
564		b = Math;
565		c = b.log;
566		d = 1024;
567		e = c( a ) / c( d ) | 0; //eslint-disable-line no-bitwise
568
569		return ( ( a / b.pow( d, e ) ).toFixed( e ? 2 : 0 ) ) + ' ' + ( e ? 'KMGTPEZY'[ --e ] + 'B' : 'bytes' );
570	}
571
572	function toggleState( thisProductContainerWrap, disabled ) {
573		thisProductContainerWrap.toArray().forEach( function( setter ) {
574			setter = $( setter );
575			setter.find( ':input' ).prop( 'disabled', function( i, v ) {
576				var state = $( this ).data( 'tc-state' );
577				if ( state === undefined ) {
578					$( this ).data( 'tc-state', v );
579					return disabled;
580				}
581				if ( state === false ) {
582					return disabled;
583				}
584				return state;
585			} );
586		} );
587	}
588	// Function to calculate tax amount
589	function calculateTaxAmount( priceWithTax, _cart ) {
590		var taxable;
591		var tax_rate;
592		var pricesIncludeTax;
593		var tax_display_mode;
594		var current_variation;
595		var priceWithoutTax;
596		var taxAmount = 0;
597
598		if ( _cart ) {
599			taxable = _cart.attr( 'data-taxable' );
600			tax_rate = _cart.attr( 'data-tax-rate' );
601			pricesIncludeTax = _cart.attr( 'data-prices-include-tax' ) || TMEPOJS.prices_include_tax;
602			tax_display_mode = _cart.attr( 'data-tax-display-mode' );
603			if ( _cart.data( 'current_variation' ) !== undefined ) {
604				current_variation = _cart.data( 'current_variation' );
605			}
606
607			if ( current_variation !== undefined ) {
608				current_variation = _cart.data( 'current_variation' );
609				taxable = current_variation.tc_is_taxable;
610				tax_rate = current_variation.tc_tax_rate;
611			}
612		}
613
614		if ( taxable ) {
615			tax_rate = parseFloat( tax_rate / 100 );
616
617			if ( pricesIncludeTax === '1' ) {
618				if ( tax_display_mode === 'incl' ) {
619					priceWithTax = parseFloat( priceWithTax );
620
621					// Calculate price without tax
622					priceWithoutTax = priceWithTax / ( 1 + tax_rate );
623
624					// Calculate tax amount
625					taxAmount = priceWithTax - priceWithoutTax;
626				} else {
627					// Calculate price without tax
628					priceWithoutTax = priceWithTax;
629
630					// Calculate tax amount
631					taxAmount = priceWithTax * tax_rate;
632				}
633			} else if ( tax_display_mode === 'incl' ) {
634				// Calculate price without tax
635				priceWithoutTax = priceWithTax / ( 1 + tax_rate );
636
637				// Calculate tax amount
638				taxAmount = priceWithTax - priceWithoutTax;
639			}
640
641			taxAmount = $.epoAPI.math.toFloat( taxAmount );
642		}
643
644		return taxAmount;
645	}
646	// Taxes setup
647	function get_price_including_tax( price, _cart, element, force, variation, pricetype, doubleforce ) {
648		var taxable;
649		var tax_rate;
650		var prices_include_tax;
651		var is_vat_exempt;
652		var non_base_location_prices;
653		var taxes_of_one;
654		var base_taxes_of_one;
655		var modded_taxes_of_one;
656		var current_variation;
657
658		if ( ! Number.isFinite( parseFloat( price ) ) ) {
659			price = 0;
660		}
661		price = price * 10000;
662		if ( _cart ) {
663			taxable = _cart.attr( 'data-taxable' );
664			tax_rate = _cart.attr( 'data-tax-rate' );
665			prices_include_tax = _cart.attr( 'data-prices-include-tax' ) || TMEPOJS.prices_include_tax;
666			is_vat_exempt = _cart.attr( 'data-is-vat-exempt' );
667			non_base_location_prices = _cart.attr( 'data-non-base-location-prices' );
668			taxes_of_one = _cart.attr( 'data-taxes-of-one' );
669			base_taxes_of_one = _cart.attr( 'data-base-taxes-of-one' );
670			modded_taxes_of_one = _cart.attr( 'data-modded-taxes-of-one' );
671
672			if ( _cart.data( 'current_variation' ) !== undefined ) {
673				current_variation = _cart.data( 'current_variation' );
674			} else if ( variation !== undefined ) {
675				current_variation = variation;
676			}
677
678			if ( current_variation !== undefined ) {
679				current_variation = _cart.data( 'current_variation' );
680				taxable = current_variation.tc_is_taxable;
681				tax_rate = current_variation.tc_tax_rate;
682				non_base_location_prices = current_variation.tc_non_base_location_prices;
683				taxes_of_one = current_variation.tc_taxes_of_one;
684				base_taxes_of_one = current_variation.tc_base_taxes_of_one;
685				modded_taxes_of_one = current_variation.tc_modded_taxes_of_one;
686			}
687
688			if ( element ) {
689				if ( element.data( 'tax-obj' ) ) {
690					tax_rate = element.data( 'tax-obj' );
691					if ( tax_rate.has_fee === 'no' ) {
692						taxable = false;
693					} else if ( tax_rate.has_fee === 'yes' ) {
694						taxable = true;
695					}
696					tax_rate = tax_rate.tax_rate;
697					taxes_of_one = tax_rate / 100;
698					base_taxes_of_one = tax_rate / 100;
699				}
700			}
701			if ( taxable ) {
702				if ( prices_include_tax === '1' && ! force ) {
703					if ( is_vat_exempt === '1' ) {
704						if ( non_base_location_prices === '1' ) {
705							price = parseFloat( price ) - ( taxes_of_one * price );
706						} else {
707							price = parseFloat( price ) - ( base_taxes_of_one * price );
708						}
709					} else if ( non_base_location_prices === '1' ) {
710						price = parseFloat( price ) - ( base_taxes_of_one * price ) + ( modded_taxes_of_one * price );
711					}
712				} else if ( element || current_variation === undefined || doubleforce ) {
713					price = parseFloat( price ) + ( parseFloat( price ) * taxes_of_one );
714				}
715			}
716		}
717		price = price / 10000;
718
719		return price;
720	}
721
722	function get_price_excluding_tax( price, _cart, element, force, variation, pricetype, doubleforce ) {
723		var taxable;
724		var tax_rate;
725		var taxes_of_one;
726		var base_taxes_of_one;
727		var prices_include_tax;
728		var current_variation;
729		var tax_display_mode;
730
731		if ( ! Number.isFinite( parseFloat( price ) ) ) {
732			price = 0;
733		}
734		price = price * 10000;
735
736		if ( _cart ) {
737			tax_display_mode = _cart.attr( 'data-tax-display-mode' );
738
739			taxable = _cart.attr( 'data-taxable' );
740			tax_rate = _cart.attr( 'data-tax-rate' );
741			taxes_of_one = _cart.attr( 'data-taxes-of-one' );
742			base_taxes_of_one = _cart.attr( 'data-base-taxes-of-one' );
743			prices_include_tax = _cart.attr( 'data-prices-include-tax' );
744
745			if ( _cart.data( 'current_variation' ) !== undefined ) {
746				current_variation = _cart.data( 'current_variation' );
747			} else if ( variation !== undefined ) {
748				current_variation = variation;
749			}
750			if ( current_variation !== undefined ) {
751				taxable = current_variation.tc_is_taxable;
752				tax_rate = current_variation.tc_tax_rate;
753				taxes_of_one = current_variation.tc_taxes_of_one;
754				base_taxes_of_one = current_variation.tc_base_taxes_of_one;
755			}
756
757			if ( element ) {
758				if ( element.data( 'tax-obj' ) ) {
759					tax_rate = element.data( 'tax-obj' );
760					if ( tax_rate.has_fee === 'no' ) {
761						taxable = false;
762					} else if ( tax_rate.has_fee === 'yes' ) {
763						taxable = true;
764					}
765					tax_rate = tax_rate.tax_rate;
766					base_taxes_of_one = tax_rate / 100;
767				}
768			}
769
770			if ( taxable ) {
771				if ( prices_include_tax === '1' || force ) {
772					if ( tax_display_mode === 'incl' ) {
773						// This should never run on this function
774					} else if ( element || current_variation === undefined || force || doubleforce ) {
775						if ( base_taxes_of_one === taxes_of_one ) {
776							price = parseFloat( price ) - parseFloat( taxes_of_one * price );
777						} else {
778							price = price * ( 1 - parseFloat( base_taxes_of_one ) );
779						}
780					}
781				}
782			}
783		}
784		price = price / 10000;
785
786		return price;
787	}
788
789	function tm_set_tax_price( value, _cart, element, pricetype, force, variation, doubleforce ) {
790		var tax_display_mode;
791
792		if ( ! Number.isFinite( parseFloat( value ) ) ) {
793			value = 0;
794		}
795		if ( _cart ) {
796			tax_display_mode = _cart.attr( 'data-tax-display-mode' ) || TMEPOJS.tax_display_mode;
797			if ( tax_display_mode === 'incl' ) {
798				value = get_price_including_tax( value, _cart, element, force, variation, pricetype, doubleforce );
799			} else {
800				value = get_price_excluding_tax( value, _cart, element, force, variation, pricetype, doubleforce );
801			}
802		}
803		return value;
804	}
805
806	// Return a formatted currency value
807	function formatPrice( value, args ) {
808		var data;
809		if ( ! args ) {
810			args = {};
811		}
812		data = $.extend( {
813			symbol: '',
814			format: '',
815			decimal: tcAPI.localDecimalSeparator,
816			thousand: tcAPI.localThousandSeparator,
817			precision: TMEPOJS.currency_format_num_decimals
818		}, args );
819
820		if ( TMEPOJS.tm_epo_trim_zeros === 'yes' ) {
821			if ( ( ( value % 1 ).toString() !== '0' ) === false ) {
822				data.precision = 0;
823			}
824		}
825
826		return $.epoAPI.applyFilter( 'tc_formatPrice', $.epoAPI.math.format( value, data ), data, value );
827	}
828
829	// Return a formatted currency value
830	function tm_set_price_( value, sign, inc_tax_string ) {
831		return (
832			sign +
833			formatPrice( value, { symbol: TMEPOJS.currency_format_symbol, format: TMEPOJS.currency_format } ) +
834			inc_tax_string
835		);
836	}
837
838	// Return a formatted currency value
839	function tm_set_price( value, _cart, notax, taxstring, element, pricetype ) {
840		var inc_tax_string = '';
841		var val;
842		var sign = TMEPOJS.option_plus_sign + ' ';
843
844		if ( ! notax ) {
845			value = tm_set_tax_price( value, _cart, element, pricetype );
846		}
847
848		val = Math.abs( value );
849
850		if ( TMEPOJS.tm_epo_global_options_price_sign === 'minus' ) {
851			sign = '';
852		}
853		if ( value < 0 ) {
854			sign = TMEPOJS.option_minus_sign + ' ';
855		}
856
857		if ( _cart && taxstring ) {
858			inc_tax_string = _cart.attr( 'data-tax-string' );
859		}
860		if ( inc_tax_string === undefined ) {
861			inc_tax_string = '';
862		}
863
864		return tm_set_price_( val, sign, inc_tax_string );
865	}
866
867	// FloatingTotalsBox plugin
868	FloatingTotalsBox = function( this_epo_totals_container, is_quickview, main_cart ) {
869		this.this_epo_totals_container = this_epo_totals_container;
870		this.is_quickview = is_quickview;
871		this.main_cart = main_cart;
872
873		if ( ! is_quickview && TMEPOJS.floating_totals_box && TMEPOJS.floating_totals_box !== 'disable' && main_cart && this_epo_totals_container.length ) {
874			this.init();
875			return this;
876		}
877
878		return false;
879	};
880
881	FloatingTotalsBox.prototype = {
882		constructor: FloatingTotalsBox,
883
884		onUpdate: function() {
885			var tm_epo_totals_html = this.this_epo_totals_container.data( 'tm-html' );
886			var tm_floating_box_data = this.this_epo_totals_container.data( 'tm-floating-box-data' );
887			var values_obj = [];
888			var floatingBoxHtml;
889			var floatingBoxaddToCartButton;
890
891			if ( tm_floating_box_data && tm_floating_box_data.length ) {
892				$.each( tm_floating_box_data, function( i, row ) {
893					if ( row.title === '' ) {
894						row.title = '&nbsp;';
895					}
896					if ( row.value === '' ) {
897						row.value = '&nbsp;';
898					}
899					if ( ! row.title ) {
900						row.title = '&nbsp;';
901					} else {
902						row.title = $( '<div>' + row.title + '</div>' );
903						row.title.find( 'span' ).remove();
904						row.title = row.title.html();
905					}
906
907					if ( this.is_nks ) {
908						if ( row.label_show !== '' ) {
909							row.title = '';
910						}
911						if ( row.value_show !== '' ) {
912							row.value = '';
913						}
914					}
915
916					if ( TMEPOJS.tm_epo_auto_hide_price_if_zero === 'yes' && $.tmempty( row.price ) === true ) {
917						row.price = '';
918					} else {
919						row.price = tm_set_price( row.price, this.this_epo_totals_container, true, false );
920					}
921
922					values_obj.push( {
923						label_show: row.label_show,
924						value_show: row.value_show,
925						title: row.title,
926						value: row.value,
927						quantity: row.quantity,
928						price: row.price
929					} );
930				} );
931			}
932
933			if ( ( ( tm_epo_totals_html && tm_epo_totals_html === '' ) && ( ! tm_floating_box_data || ! tm_floating_box_data.length ) ) || ! ( ( tm_epo_totals_html && tm_epo_totals_html !== '' ) || this.is_nks ) ) {
934				tm_epo_totals_html = '';
935				this.floatingBox.hide();
936			}
937
938			floatingBoxHtml = $.epoAPI.template.html( this.engineTemplate, {
939				html_before: TMEPOJS.floating_totals_box_html_before,
940				html_after: TMEPOJS.floating_totals_box_html_after,
941				option_label: TMEPOJS.i18n_option_label,
942				option_value: TMEPOJS.i18n_option_value,
943				option_qty: TMEPOJS.i18n_option_qty,
944				option_price: TMEPOJS.i18n_option_price,
945				values: values_obj,
946				totals: tm_epo_totals_html
947			} );
948
949			this.floatingBox.html( floatingBoxHtml );
950			this.onUpdateScroll();
951
952			if ( TMEPOJS.floating_totals_box_add_button === 'yes' ) {
953				floatingBoxaddToCartButton = this.main_cart.find( tcAPI.addToCartButtonSelector ).first();
954				floatingBoxaddToCartButton
955					.tcClone()
956					.addClass( 'tc-add-to-cart-button' )
957					.on( 'click', function() {
958						floatingBoxaddToCartButton.trigger( 'click' );
959					} )
960					.appendTo( this.floatingBox );
961			}
962		},
963
964		onUpdateScroll: function() {
965			if ( TMEPOJS.floating_totals_box_visibility === 'always' ) {
966				if ( this.floatingBox.is( ':empty' ) && ! this.is_nks_alt ) {
967					this.floatingBox.hide();
968				} else {
969					this.floatingBox.show();
970				}
971				return;
972			}
973			if ( TMEPOJS.floating_totals_box_visibility === 'hideafterscroll' ) {
974				if ( jWindow.scrollTop() >
974 $.epoAPI.math.toFloat( TMEPOJS.floating_totals_box_pixels ) && ! this.is_nks_alt ) {
975					if ( ! this.floatingBox.is( ':hidden' ) ) {
976						if ( this.is_nks === false ) {
977							this.floatingBox.fadeOut();
978						} else {
979							this.floatingBox.hide();
980						}
981					}
982				} else if ( this.floatingBox.is( ':hidden' ) || this.is_nks_alt ) {
983					if ( ! this.floatingBox.is( ':empty' ) || this.is_nks_alt ) {
984						if ( this.is_nks === false ) {
985							this.floatingBox.fadeIn();
986						} else {
987							this.floatingBox.show();
988						}
989					}
990				}
991			}
992
993			if ( TMEPOJS.floating_totals_box_visibility === 'afterscroll' ) {
994				if ( jWindow.scrollTop() > $.epoAPI.math.toFloat( TMEPOJS.floating_totals_box_pixels ) || this.is_nks_alt ) {
995					if ( ( this.floatingBox.is( ':hidden' ) && ! this.floatingBox.is( ':empty' ) ) || this.is_nks_alt ) {
996						if ( this.is_nks === false ) {
997							this.floatingBox.fadeIn();
998						} else {
999							this.floatingBox.show();
1000						}
1001					} else if ( ! this.floatingBox.is( ':hidden' ) && this.floatingBox.is( ':empty' ) ) {
1002						if ( this.is_nks === false ) {
1003							this.floatingBox.fadeOut();
1004						} else {
1005							this.floatingBox.hide();
1006						}
1007					}
1008				} else if ( ! this.floatingBox.is( ':hidden' ) ) {
1009					if ( this.is_nks === false ) {
1010						this.floatingBox.fadeOut();
1011					} else {
1012						this.floatingBox.hide();
1013					}
1014				}
1015			}
1016		},
1017
1018		addEvents: function() {
1019			this.onUpdate();
1020
1021			this.main_cart.on( 'tm-epo-after-update', this.onUpdate.bind( this ) );
1022			this.main_cart.on( 'tm-epo-short-update', this.onUpdate.bind( this ) );
1023
1024			if ( this.is_nks === false ) {
1025				jWindow.on( 'scroll', this.onUpdateScroll.bind( this ) );
1026			}
1027		},
1028
1029		init: function() {
1030			this.floatingBox = $( '<div class="tm-floating-box ' + TMEPOJS.floating_totals_box + '"></div>' );
1031			this.nks_selector = $( '.tm-floating-box-nks' ).first();
1032			this.alt_selector = $( '.tm-floating-box-alt' ).first();
1033			this.engineTemplate = tcAPI.templateEngine.tc_floating_box;
1034			this.is_nks = false;
1035			this.is_nks_alt = false;
1036
1037			if ( this.nks_selector.length > 0 ) {
1038				this.is_nks = true;
1039				this.floatingBox.removeClass( 'top left right bottom' ).appendTo( this.nks_selector ).show();
1040			} else if ( this.alt_selector.length > 0 ) {
1041				this.floatingBox.removeClass( 'top left right bottom' ).appendTo( this.alt_selector ).hide();
1042			} else {
1043				this.floatingBox.appendTo( 'body' ).hide();
1044			}
1045
1046			if ( this.nks_selector.length > 0 || this.alt_selector.length > 0 ) {
1047				this.is_nks_alt = true;
1048				this.engineTemplate = tcAPI.templateEngine.tc_floating_box_nks;
1049			}
1050
1051			this.addEvents();
1052		}
1053	};
1054
1055	$.tcFloatingTotalsBox = function( this_epo_totals_container, is_quickview, main_cart ) {
1056		var data = false;
1057
1058		if ( this_epo_totals_container && this_epo_totals_container.length && this_epo_totals_container.data( 'tcfloatingtotalsbox' ) === undefined ) {
1059			data = new FloatingTotalsBox( this_epo_totals_container, is_quickview, main_cart );
1060			this_epo_totals_container.data( 'tcfloatingtotalsbox', data );
1061		}
1062
1063		return data;
1064	};
1065
1066	$.tc_product_image = {};
1067	$.tc_product_image_store = {};
1068
1069	// replace obj1 values with obj2 values
1070	$.tc_replace_object_values = function( obj1, obj2 ) {
1071		Object.keys( obj1 ).forEach( function( x ) {
1072			Object.keys( obj1[ x ] ).forEach( function( attr ) {
1073				if ( undefined !== obj2[ x ] && undefined !== obj2[ x ][ attr ] && Object.prototype.hasOwnProperty.call( obj2[ x ], attr ) ) {
1074					obj1[ x ][ attr ] = obj2[ x ][ attr ];
1075				}
1076			} );
1077		} );
1078		return obj1;
1079	};
1080	// copy obj2 values to obj1
1081	$.tc_maybe_copy_object_values = function( obj1, obj2 ) {
1082		Object.keys( obj2 ).forEach( function( x ) {
1083			Object.keys( obj2[ x ] ).forEach( function( attr ) {
1084				if ( undefined !== obj2[ x ] && Object.prototype.hasOwnProperty.call( obj2[ x ], attr ) && undefined !== obj2[ x ][ attr ] && ( undefined === obj1[ x ] || undefined === obj1[ x ][ attr ] ) ) {
1085					if ( undefined === obj1[ x ] ) {
1086						obj1[ x ] = {};
1087					}
1088					obj1[ x ][ attr ] = obj2[ x ][ attr ];
1089				}
1090			} );
1091		} );
1092		return obj1;
1093	};
1094
1095	$.tc_pre_populate_store = function() {
1096		var obj = {};
1097
1098		obj[ 0 ] = {};
1099		obj[ 1 ] = {};
1100		obj[ 2 ] = {};
1101		obj[ 3 ] = {};
1102
1103		obj[ 0 ].src = '';
1104		obj[ 0 ].srcset = '';
1105		obj[ 0 ].sizes = '';
1106		obj[ 0 ].title = '';
1107		obj[ 0 ].alt = '';
1108		obj[ 0 ][ 'data-src' ] = '';
1109		obj[ 0 ][ 'data-large_image' ] = '';
1110		obj[ 0 ][ 'data-large_image_width' ] = '';
1111		obj[ 0 ][ 'data-large_image_height' ] = '';
1112		obj[ 1 ][ 'data-thumb' ] = '';
1113		obj[ 2 ].src = '';
1114		obj[ 3 ].href = '';
1115		obj[ 3 ].title = '';
1116
1117		return obj;
1118	};
1119
1120	$.tc_populate_store = function( img, product_element ) {
1121		var $gallery_img = product_element.find( '.flex-control-nav li:eq(0) img' );
1122		var $gallery_wrapper = product_element.find( '.woocommerce-product-gallery__wrapper ' );
1123		var $product_img_wrap = $gallery_wrapper.find( '.woocommerce-product-gallery__image, .woocommerce-product-gallery__image--placeholder' ).eq( 0 );
1124		var $product_img = img;
1125		var $product_link = img.closest( 'a' );
1126		var obj = {};
1127
1128		obj[ 0 ] = {};
1129		obj[ 1 ] = {};
1130		obj[ 2 ] = {};
1131		obj[ 3 ] = {};
1132
1133		obj[ 0 ].src = $product_img.attr( 'src' );
1134		obj[ 0 ].srcset = $product_img.attr( 'srcset' );
1135		obj[ 0 ].sizes = $product_img.attr( 'sizes' );
1136		obj[ 0 ].title = $product_img.attr( 'title' );
1137		obj[ 0 ].alt = $product_img.attr( 'alt' );
1138		obj[ 0 ][ 'data-src' ] = $product_img.attr( 'data-src' );
1139		obj[ 0 ][ 'data-large_image' ] = $product_img.attr( 'data-large_image' );
1140		obj[ 0 ][ 'data-large_image_width' ] = $product_img.attr( 'data-large_image_width' );
1141		obj[ 0 ][ 'data-large_image_height' ] = $product_img.attr( 'data-large_image_height' );
1142		obj[ 1 ][ 'data-thumb' ] = $product_img_wrap.attr( 'data-thumb' );
1143		obj[ 2 ].src = $gallery_img.attr( 'src' );
1144		obj[ 3 ].href = $product_link.attr( 'href' );
1145		obj[ 3 ].title = $product_link.attr( 'title' );
1146
1147		return obj;
1148	};
1149
1150	$.tc_maybe_copy_object_values_from_img = function( obj1, img, product_element ) {
1151		var $gallery_img = product_element.find( '.flex-control-nav li:eq(0) img' );
1152		var $gallery_wrapper = product_element.find( '.woocommerce-product-gallery__wrapper ' );
1153		var $product_img_wrap = $gallery_wrapper.find( '.woocommerce-product-gallery__image, .woocommerce-product-gallery__image--placeholder' ).eq( 0 );
1154		var $product_img = img;
1155		var $product_link = img.closest( 'a' );
1156		var attrs;
1157		var attr;
1158		var attrs_product_img = [ 'src', 'srcset', 'sizes', 'title', 'alt', 'data-src', 'data-large_image', 'data-large_image_width', 'data-large_image_height', 'large-image' ];
1159		var attrs_product_img_wrap = [ 'data-thumb' ];
1160		var attrs_gallery_img = [ 'src' ];
1161		var attrs_product_link = [ 'href', 'title' ];
1162		var all = [ $product_img, $product_img_wrap, $gallery_img, $product_link ];
1163		var attrs_all = [ attrs_product_img, attrs_product_img_wrap, attrs_gallery_img, attrs_product_link ];
1164		all.forEach( function( item, index ) {
1165			if ( undefined !== item && undefined !== item[ 0 ] ) {
1166				attrs = item[ 0 ].attributes;
1167
1168				$.each( attrs, function() {
1169					if ( this.specified ) {
1170						attr = this.name;
1171
1172						if ( $.inArray( attr, attrs_all[ index ] ) !== -1 && ( undefined === obj1[ index ] || ( undefined !== obj1[ index ] && undefined === obj1[ index ][ attr ] ) ) ) {
1173							if ( undefined === obj1[ index ] ) {
1174								obj1[ index ] = {};
1175							}
1176							obj1[ index ][ attr ] = this.value;
1177						}
1178					}
1179				} );
1180			}
1181		} );
1182
1183		return obj1;
1184	};
1185
1186	// Stores a default attribute for an element so it can be reset later
1187	$.fn.tc_set_attr = function( attr, value, id ) {
1188		if ( undefined === id ) {
1189			id = 0;
1190		}
1191		if ( undefined === $.tc_product_image[ id ] || ( undefined !== $.tc_product_image[ id ] && undefined === $.tc_product_image[ id ][ attr ] ) ) {
1192			if ( undefined === $.tc_product_image[ id ] ) {
1193				$.tc_product_image[ id ] = {};
1194			}
1195			$.tc_product_image[ id ][ attr ] = '';
1196			if ( this.attr( attr ) ) {
1197				$.tc_product_image[ id ][ attr ] = this.attr( attr );
1198			}
1199		}
1200		if ( false === value ) {
1201			this.removeAttr( attr );
1202		} else {
1203			this.attr( attr, value );
1204		}
1205	};
1206
1207	// Reset a default attribute for an element so it can be reset later
1208	$.fn.tc_reset_attr = function( attr, id ) {
1209		if ( undefined === id ) {
1210			id = 0;
1211		}
1212		if ( undefined === $.tc_product_image[ id ] ) {
1213			return;
1214		}
1215		if ( undefined !== $.tc_product_image[ id ][ attr ] ) {
1216			this.attr( attr, $.tc_product_image[ id ][ attr ] );
1217		}
1218		delete $.tc_product_image[ id ][ attr ];
1219	};
1220
1221	$.fn.tc_update_attr = function( attr, id ) {
1222		if ( undefined === id ) {
1223			id = 0;
1224		}
1225		if ( undefined !== $.tc_product_image[ id ] ) {
1226			$.tc_product_image[ id ][ attr ] = this.attr( attr );
1227		}
1228	};
1229
1230	$.fn.tc_image_update = function( dom, image ) {
1231		var element = $( dom );
1232		var $form = this;
1233		var $image = $( image );
1234		var epo_object = $form.data( 'epo_object' );
1235		var image_info;
1236		var $product_img;
1237		var product_element = epo_object.main_product.closest( '#product-' + epo_object.product_id );
1238		var $product_element = product_element;
1239		var $product_link;
1240		var use_image_info;
1241
1242		if ( product_element.length <= 0 ) {
1243			$product_element = epo_object.main_product.closest( '.post-' + epo_object.product_id );
1244		}
1245
1246		if ( element.is( 'select' ) ) {
1247			element = element.children( 'option:selected' );
1248		}
1249		image_info = element.data( 'image-variations' );
1250
1251		if ( TMEPOJS.tm_epo_global_product_image_selector !== '' ) {
1252			$product_img = $( TMEPOJS.tm_epo_global_product_image_selector );
1253		} else {
1254			$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();
1255		}
1256		$product_link = $product_img.closest( 'a' );
1257
1258		if ( $product_img.length > 1 ) {
1259			$product_img = $product_img.first();
1260		}
1261
1262		if ( element && image_info && $image.length > 0 ) {
1263			$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' );
1264
1265			use_image_info = image_info.imagep;
1266			if ( ! image_info.imagep.image_link ) {
1267				use_image_info = image_info.image;
1268			}
1269
1270			$image.attr( 'title', use_image_info.image_title );
1271			$image.attr( 'alt', use_image_info.image_alt );
1272			if ( use_image_info.image_srcset ) {
1273				$image.attr( 'srcset', use_image_info.image_srcset );
1274			}
1275			if ( use_image_info.image_sizes ) {
1276				$image.attr( 'sizes', use_image_info.image_sizes );
1277			}
1278
1279			$product_img.tc_set_attr( 'title', use_image_info.image_title );
1280			$product_img.tc_set_attr( 'alt', use_image_info.image_alt );
1281
1282			$product_img.tc_set_attr( 'data-large-image', use_image_info.image_link );
1283			if ( $product_img.data.wc27_zoom_target ) {
1284				$product_img.data.wc27_zoom_target.tc_set_attr( 'data-thumb', use_image_info.image_link );
1285				$product_element.find( '.flex-control-nav li:eq(0) img' ).tc_set_attr( 'src', use_image_info.image_link );
1286			}
1287
1288			$product_link.tc_set_attr( 'href', use_image_info.image_link );
1289			$product_link.tc_set_attr( 'title', use_image_info.image_caption );
1290		} else {
1291			$product_img.tc_reset_attr( 'title' );
1292			$product_img.tc_reset_attr( 'alt' );
1293
1294			$product_img.tc_reset_attr( 'data-large-image' );
1295			if ( $product_img.data.wc27_zoom_target ) {
1296				$product_img.data.wc27_zoom_target.tc_reset_attr( 'data-thumb' );
1297				$product_element.find( '.flex-control-nav li:eq(0) img' ).tc_reset_attr( 'src' );
1298			}
1299
1300			$product_link.tc_reset_attr( 'href' );
1301			$product_link.tc_reset_attr( 'title' );
1302		}
1303	};
1304
1305	// variations checker
1306	$.fn.tm_find_matching_variations = function( product_variations, settings ) {
1307		var matching = [];
1308		var i;
1309		var variation;
1310
1311		if ( product_variations ) {
1312			for ( i = 0; i < product_variations.length; i += 1 ) {
1313				variation = product_variations[ i ];
1314
1315				if ( $.fn.tm_variations_match( variation.attributes, settings ) ) {
1316					matching.push( variation );
1317				}
1318			}
1319		}
1320
1321		return matching;
1322	};
1323
1324	$.fn.tm_variations_match = function( attrs1, attrs2 ) {
1325		var match = true;
1326		var val1;
1327		var val2;
1328
1329		Object.keys( attrs1 ).forEach( function( x ) {
1330			if ( Object.prototype.hasOwnProperty.call( attrs1, x ) ) {
1331				val1 = attrs1[ x ];
1332				val2 = attrs2[ x ];
1333
1334				if ( val1 !== undefined && val2 !== undefined && val1.length !== 0 && val2.length !== 0 && val1 !== val2 ) {
1335					match = false;
1336				}
1337			}
1338		} );
1339
1340		return match;
1341	};
1342
1343	function get_element_from_field( element ) {
1344		var $element = $( element );
1345		var data_uniqid;
1346		var the_epo_id;
1347		var _class;
1348		var epoContainer;
1349
1350		if ( $element.length === 0 ) {
1351			return;
1352		}
1353
1354		if ( $element.is( '.cpf-section' ) ) {
1355			return element.find( '.tm-epo-field' );
1356		}
1357		data_uniqid = $element.attr( 'data-uniqid' );
1358		epoContainer = $element.closest( '.tc-extra-product-options' );
1359		the_epo_id = epoContainer.attr( 'data-epo-id' );
1360
1361		if ( ! epoContainer.is( '.reactivate' ) && tcAPI.getElementFromFieldCache && tcAPI.getElementFromFieldCache[ the_epo_id ] && tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ] ) {
1362			return tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ];
1363		}
1364		_class = $element
1365			.attr( 'class' )
1366			.split( ' ' )
1367			.map( function( cls ) {
1368				if ( cls.indexOf( 'cpf-type-', 0 ) !== -1 ) {
1369					return cls;
1370				}
1371				return null;
1372			} )
1373			.filter( function( v ) {
1374				if ( v !== null && v !== undefined ) {
1375					return v;
1376				}
1377				return null;
1378			} );
1379
1380		if ( _class.length > 0 ) {
1381			_class = _class[ 0 ];
1382			if ( _class === 'cpf-type-product' ) {
1383				if ( $element.is( '.cpf-type-product-mode-product' ) || $element.is( '.cpf-type-product-checkbox' ) || $element.is( '.cpf-type-product-thumbnailmultiple' ) ) {
1384					_class = 'cpf-type-checkbox';
1385				} else if ( $element.is( '.cpf-type-product-dropdown' ) ) {
1386					_class = 'cpf-type-select';
1387				} else {
1388					_class = 'cpf-type-radio';
1389				}
1390			}
1391			switch ( _class ) {
1392				case 'cpf-type-radio':
1393					tcAPI.getElementFromFieldCache[ the_epo_id ] = [];
1394					tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ] = $element.find( '.tm-epo-field.tmcp-radio' );
1395					return tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ];
1396
1397				case 'cpf-type-checkbox':
1398					tcAPI.getElementFromFieldCache[ the_epo_id ] = [];
1399					tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ] = $element.find( '.tm-epo-field.tmcp-checkbox' );
1400					return tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ];
1401
1402				case 'cpf-type-select':
1403					tcAPI.getElementFromFieldCache[ the_epo_id ] = [];
1404					tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ] = $element.find( '.tm-epo-field.tmcp-select' );
1405					return tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ];
1406
1407				case 'cpf-type-selectmultiple':
1408					tcAPI.getElementFromFieldCache[ the_epo_id ] = [];
1409					tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ] = $element.find( '.tm-epo-field.tmcp-selectmultiple' );
1410					return tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ];
1411
1412				case 'cpf-type-textarea':
1413					tcAPI.getElementFromFieldCache[ the_epo_id ] = [];
1414					tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ] = $element.find( '.tm-epo-field.tmcp-textarea' );
1415					return tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ];
1416
1417				case 'cpf-type-textfield':
1418					tcAPI.getElementFromFieldCache[ the_epo_id ] = [];
1419					tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ] = $element.find( '.tm-epo-field.tmcp-textfield' );
1420					return tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ];
1421
1422				case 'cpf-type-color':
1423					tcAPI.getElementFromFieldCache[ the_epo_id ] = [];
1424					tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ] = $element.find( '.tm-epo-field.tm-color-picker' );
1425					return tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ];
1426
1427				case 'cpf-type-range':
1428					tcAPI.getElementFromFieldCache[ the_epo_id ] = [];
1429					tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ] = $element.find( '.tm-epo-field.tmcp-range' );
1430					return tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ];
1431
1432				case 'cpf-type-date':
1433					tcAPI.getElementFromFieldCache[ the_epo_id ] = [];
1434					tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ] = $element.find( '.tm-epo-field.tmcp-date' );
1435					return tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ];
1436
1437				case 'cpf-type-time':
1438					tcAPI.getElementFromFieldCache[ the_epo_id ] = [];
1439					tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ] = $element.find( '.tm-epo-field.tmcp-time' );
1440					return tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ];
1441
1442				case 'cpf-type-variations':
1443					tcAPI.getElementFromFieldCache[ the_epo_id ] = [];
1444					tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ] = $element.closest( '.cpf-section' ).find( '.tm-epo-field.tm-epo-variation-element' );
1445					return tcAPI.getElementFromFieldCache[ the_epo_id ][ data_uniqid ];
1446			}
1447		}
1448	}
1449
1450	// tc-lightbox
1451	if ( ! $().tclightbox ) {
1452		$.fn.tclightbox = function() {
1453			var elements = this;
1454
1455			if ( elements.length === 0 ) {
1456				return;
1457			}
1458
1459			return elements.each( function() {
1460				var $this = $( this );
1461				var _imgsrc;
1462				var _label;
1463				var _input;
1464				var tclightboxwrap;
1465				var _img_button;
1466				var preload_img;
1467				var addButtonEvent;
1468
1469				if ( $this.is( '.tcinit' ) ) {
1470					return;
1471				}
1472				_imgsrc = $this.attr( 'src' ) || $this.attr( 'data-original' );
1473				_label = $this.closest( 'label' );
1474				_input = _label.closest( '.tmcp-field-wrap' ).find( ".tm-epo-field[id='" + _label.attr( 'for' ) + "']" );
1475				_imgsrc = _input.attr( 'data-imagel' ) || _input.attr( 'data-imagep' ) || _input.attr( 'data-image' ) || _imgsrc;
1476
1477				if ( ! _imgsrc ) {
1478					return;
1479				}
1480
1481				$this.addClass( 'tcinit' ).before( $.epoAPI.template.html( tcAPI.templateEngine.tc_lightbox, {} ) );
1482				tclightboxwrap = $this.prev();
1483
1484				$this.wrap( "<div class='tc-lightbox-image-wrap'/>" );
1485				$this.after( tclightboxwrap );
1486
1487				_img_button = tclightboxwrap.find( '.tc-lightbox-button' );
1488
1489				addButtonEvent = function() {
1490					_img_button.addClass( 'tcinit' ).on( 'click.tclightbox', function( buttonevent ) {
1491						var size;
1492						var _img;
1493
1494						if ( $( '.tc-closing.tc-lightbox' ).length > 0 ) {
1495							return;
1496						}
1497
1498						size = $.epoAPI.dom.size();
1499						_img = $( '<img>' )
1500							.addClass( 'tc-lightbox-img' )
1501							.attr( 'src', _imgsrc )
1502							.css( 'maxHeight', size.visibleHeight + 'px' )
1503							.css( 'maxWidth', size.visibleWidth + 'px' );
1504
1505						$.tcFloatBox( {
1506							fps: 1,
1507							ismodal: false,
1508							refresh: 'fixed',
1509							width: 'auto',
1510							height: 'auto',
1511							top: '0%',
1512							left: '0%',
1513							classname: 'flasho tc-lightbox',
1514							animateIn: 'tc-lightbox-zoomin',
1515							animateOut: 'tc-lightbox-zoomout',
1516							data: $.epoAPI.template.html( tcAPI.templateEngine.tc_lightbox_zoom, { img: _img[ 0 ].outerHTML } ),
1517							zIndex: 102001,
1518							cancelClass: '.tc-lightbox-img, .tc-lightbox-button-close',
1519							unique: true
1520						} );
1521
1522						buttonevent.preventDefault();
1523					} );
1524				};
1525				if ( TMEPOJS.tm_epo_preload_lightbox_image === 'yes' ) {
1526					preload_img = new Image();
1527					preload_img.src = _imgsrc;
1528					preload_img.onload = function() {
1529						addButtonEvent();
1530					};
1531				} else {
1532					addButtonEvent();
1533				}
1534			} );
1535		};
1536	}
1537
1538	// Start Section popup
1539	if ( ! $().tmsectionpoplink ) {
1540		$.fn.tmsectionpoplink = function() {
1541			var elements = this;
1542
1543			if ( elements.length === 0 ) {
1544				return;
1545			}
1546
1547			return elements.each( function() {
1548				var $this = $( this );
1549				var id;
1550				var title;
1551				var section;
1552				var clicked;
1553				var _ovl;
1554				var cancelfunc;
1555
1556				if ( $this.data( 'tmsectionpoplink' ) ) {
1557					return;
1558				}
1559
1560				$this.data( 'tmsectionpoplink', true );
1561				id = $this.attr( 'data-sectionid' );
1562				title = TMEPOJS.i18n_addition_options;
1563				section = $this.closest( ".cpf-section[data-uniqid='" + id + "']" );
1564				clicked = false;
1565				_ovl = $( '<div class="fl-overlay"></div>' ).css( {
1566					zIndex: parseInt( $this.zIndex, 10 ) - 1,
1567					opacity: 0.8
1568				} );
1569				cancelfunc = function() {
1570					var pop = $( '#tm-section-pop-up' );
1571					pop.parents().removeClass( 'noanimated' );
1572
1573					_ovl.unbind().remove();
1574					pop.after( section );
1575					pop.remove();
1576
1577					section.find( '.tm-section-link' ).show();
1578					section.find( '.tm-section-pop' ).hide();
1579				};
1580
1581				if ( $this.attr( 'data-title' ) ) {
1582					title = $this.attr( 'data-title' );
1583				}
1584
1585				$this.on( 'click.tmsectionpoplink', function( e ) {
1586					var pop;
1587
1588					e.preventDefault();
1589					clicked = false;
1590					_ovl.appendTo( 'body' ).on( 'click', cancelfunc );
1591
1592					section.before(
1593						$.epoAPI.template.html( tcAPI.templateEngine.tc_section_pop_link, {
1594							title: title,
1595							close: TMEPOJS.i18n_close
1596						} )
1597					);
1598
1599					pop = $( '#tm-section-pop-up' );
1600
1601					pop.find( '.float-editbox' ).prepend( section );
1602
1603					section.find( '.tm-section-link' ).hide();
1604					section.find( '.tm-section-pop' ).show();
1605
1606					pop.parents().addClass( 'noanimated' );
1607
1608					pop.find( '.floatbox-cancel' ).on( 'click', function() {
1609						if ( clicked ) {
1610							return;
1611						}
1612						clicked = true;
1613						cancelfunc();
1614					} );
1615					jWindow.trigger( 'tmlazy' );
1616					jWindow.trigger( 'tmsectionpoplink' );
1617				} );
1618			} );
1619		};
1620	} // End Section popup
1621
1622	function getVariationIdSelector( currentCart ) {
1623		var variationIdSelector = "input[name^='variation_id']";
1624
1625		if ( currentCart.find( 'input.variation_id' ).length > 0 ) {
1626			variationIdSelector = 'input.variation_id';
1627		} else {
1628			variationIdSelector = 'input.product-variation-id';
1629		}
1630
1631		return variationIdSelector;
1632	}
1633
1634	function getVariationIdElement( currentCart, not ) {
1635		var variationIdSelector = getVariationIdSelector( currentCart );
1636		var variationIdElement = currentCart.find( variationIdSelector );
1637
1638		if ( currentCart.is( '.tc-epo-element-product-container-cart' ) ) {
1639			variationIdElement = currentCart.closest( '.tc-epo-element-product-li-container' ).find( variationIdSelector );
1640		} else {
1641			variationIdElement = currentCart.find( variationIdSelector ).not( '.tc-epo-element-product-container-variation-id ' + variationIdSelector );
1642		}
1643		if ( not ) {
1644			variationIdElement = variationIdElement.not( not );
1645		}
1646
1647		return variationIdElement;
1648	}
1649
1650	function getCurrentVariation( currentCart ) {
1651		var field_div;
1652		var newCart;
1653
1654		if ( currentCart.is( '.tc-epo-element-product-container-cart' ) ) {
1655			field_div = currentCart.closest( '.cpf-element' );
1656			if ( field_div.is( '.cpf-type-product-thumbnailmultiple' ) || field_div.is( '.cpf-type-product-checkbox' ) ) {
1657				newCart = currentCart.closest( '.tc-epo-element-product-holder' ).find( '.tc-epo-element-product-container-variation-id' );
1658			} else if ( field_div.is( '.cpf-type-product-thumbnail' ) || field_div.is( '.cpf-type-product-radio' ) || field_div.is( '.cpf-type-product-dropdown' ) || field_div.is( '.cpf-type-product-single' ) ) {
1659				newCart = field_div.find( '.tc-epo-element-product-container-variation-id' );
1660			}
1661			if ( newCart && newCart.length ) {
1662				currentCart = newCart;
1663			}
1664		}
1665		return currentCart.find( getVariationIdSelector( currentCart ) ).val() || 0;
1666	}
1667
1668	function getQtyElement( currentCart ) {
1669		var qty = currentCart.find( tcAPI.qtySelector ).last();
1670		if ( qty.length === 0 ) {
1671			qty = currentCart.find( tcAPI.associateQtySelector ).last();
1672		}
1673		qty = $.epoAPI.applyFilter( 'tc_getQtyElement', qty, currentCart );
1674		return qty;
1675	}
1676
1677	function getCurrentQty( currentCart ) {
1678		return $.epoAPI.applyFilter( 'tc_getCurrentQty', $.epoAPI.math.toFloat( getQtyElement( currentCart ).val() ), currentCart );
1679	}
1680
1681	function add_variation_event( name, selector, func ) {
1682		lateVariationEvent[ lateVariationEvent.length ] = {
1683			name: name,
1684			selector: selector,
1685			func: func
1686		};
1687	}
1688
1689	function field_is_active( field, nochecks, single ) {
1690		var ret = true;
1691		var insideProductCheck = false;
1692		var productElement;
1693		field = $( field );
1694		productElement = field.filter( '.tc-epo-field-product' );
1695		if ( productElement.length && productElement.data( 'islogicinit' ) === undefined ) {
1696			insideProductCheck = true;
1697		}
1698		field.each( function( j, element ) {
1699			if ( ! ret && field.has( '.tc-epo-field-product' ).length ) {
1700				if ( insideProductCheck || productElement.is( '.tcdisabled' ) ) {
1701					field_check_active( element, nochecks, single );
1702				}
1703			} else {
1704				ret = field_check_active( element, nochecks, single ) && ret;
1705			}
1706		} );
1707
1708		return ret;
1709	}
1710
1711	function field_check_active( field, nochecks, single ) {
1712		var hideElement;
1713		var singleField;
1714		var ul;
1715		var isInsideProductElement;
1716		var productElementActive;
1717		var productElementSectionActive;
1718		var productElementQty;
1719		var section;
1720		var elements;
1721		var disableElements;
1722		var sectionLi;
1723		var allSectionsDisabled;
1724
1725		field = $( field );
1726		if ( field.is( '.cpf-element' ) ) {
1727			hideElement = field;
1728			field = field.find( '.tmcp-field, .tmcp-fee-field' );
1729		} else {
1730			hideElement = field.closest( '.cpf-element' );
1731		}
1732
1733		section = hideElement.closest( '.cpf-section' );
1734		sectionLi = section.closest( '.tm-extra-product-options-field' );
1735
1736		if ( single ) {
1737			ul = field.closest( '.tmcp-ul-wrap' );
1738		} else {
1739			ul = hideElement;
1740		}
1741
1742		if ( field.is( '.tc-epo-field-product' ) && field.data( 'islogicinit' ) === undefined ) {
1743			field.data( 'islogicinit', 1 );
1744		}
1745
1746		isInsideProductElement = ! field.is( '.tc-epo-field-product' ) && hideElement.closest( '.cpf-type-product' );
1747
1748		if ( isInsideProductElement.length ) {
1749			productElementQty = isInsideProductElement.find( tcAPI.associateQtySelector );
1750			if ( productElementQty.length ) {
1751				if ( $.epoAPI.math.toFloat( productElementQty.val() ) > 0 ) {
1752					field.removeClass( 'ignore' );
1753					productElementQty.removeClass( 'ignore' );
1754				} else {
1755					field.addClass( 'ignore' );
1756					productElementQty.addClass( 'ignore' );
1757				}
1758			}
1759			productElementActive = isInsideProductElement.data( 'isactive' );
1760			isInsideProductElement = isInsideProductElement.closest( '.cpf-section' );
1761			productElementSectionActive = isInsideProductElement.data( 'isactive' );
1762		}
1763		if ( productElementActive !== false && productElementSectionActive !== false && hideElement.data( 'isactive' ) !== false && section.data( 'isactive' ) !== false ) {
1764			singleField = field.first();
1765			field.prop( 'disabled', false );
1766			if ( field.data( 'tc-state' ) !== undefined ) {
1767				field.data( 'tc-state', false );
1768			}
1769
1770			if ( TMEPOJS.tm_epo_show_only_active_quantities !== 'yes' ) {
1771				if ( singleField.is( ':radio, .cpf-type-radio' ) || singleField.is( ':checkbox, .cpf-type-checkbox' ) ) {
1772					field.filter( ':checked' ).closest( '.tmcp-field-wrap' ).find( '.tm-qty' ).prop( 'disabled', false );
1773					field.not( ':checked' ).closest( '.tmcp-field-wrap' ).find( '.tm-qty' ).prop( 'disabled', true );
1774				} else if ( singleField.is( 'select, .cpf-type-select, .cpf-type-selectmultiple' ) ) {
1775					if ( singleField.val() ) {
1776						ul.find( '.tm-qty' ).prop( 'disabled', false );
1777					} else {
1778						ul.find( '.tm-qty' ).prop( 'disabled', true );
1779					}
1780				} else if ( singleField.val() ) {
1781					ul.find( '.tm-qty' ).prop( 'disabled', false );
1782				} else {
1783					ul.find( '.tm-qty' ).prop( 'disabled', true );
1784				}
1785			} else if ( ! nochecks ) {
1786				hideElement.find( '.tm-quantity' ).trigger( 'showhide.cpfcustom' );
1787			}
1788
1789			if ( ! singleField.is( '.cpf-element' ) ) {
1790				field.removeClass( 'tcdisabled' ).addClass( 'tcenabled' );
1791
1792				if ( field.is( '.tmcp-upload' ) ) {
1793					if ( field.next( '.tmcp-upload-hidden' ).length ) {
1794						field.next( '.tmcp-upload-hidden' ).removeClass( 'tcdisabled' ).addClass( 'tcenabled' ).prop( 'disabled', false );
1795					}
1796				}
1797			}
1798
1799			hideElement.removeClass( 'tc-container-disabled' ).addClass( 'tc-container-enabled' );
1800
1801			field.trigger( {
1802				type: 'tm-field-is-active',
1803				field: field,
1804				value: true
1805			} );
1806			section.removeClass( 'section-disabled' );
1807			sectionLi.removeClass( 'tc-hidden' );
1808
1809			return true;
1810		}
1811
1812		if ( ! field.is( '.cpf-element' ) ) {
1813			field.prop( 'disabled', true ).removeClass( 'tcenabled' ).addClass( 'tcdisabled' );
1814			if ( field.data( 'tc-state' ) !== undefined ) {
1815				field.data( 'tc-state', true );
1816			}
1817			hideElement.find( '.tm-qty' ).prop( 'disabled', true );
1818			if ( field.is( '.tmcp-upload' ) ) {
1819				if ( field.next( '.tmcp-upload-hidden' ).length ) {
1820					field.next( '.tmcp-upload-hidden' ).removeClass( 'tcenabled' ).addClass( 'tcdisabled' ).prop( 'disabled', true );
1821				}
1822			}
1823		}
1824
1825		hideElement.removeClass( 'tc-container-enabled' ).addClass( 'tc-container-disabled' );
1826
1827		field.trigger( {
1828			type: 'tm-field-is-active',
1829			field: field,
1830			value: false
1831		} );
1832
1833		elements = section.find( '.cpf-element' ).length;
1834		disableElements = section.find( '.cpf-element.tc-container-disabled' ).length;
1835
1836		if ( elements === disableElements ) {
1837			section.addClass( 'section-disabled' );
1838			allSectionsDisabled = sectionLi.children( '.cpf-section' ).filter( function() {
1839				return ! $( this ).hasClass( 'section-disabled' );
1840			} ).length === 0;
1841			if ( allSectionsDisabled ) {
1842				sectionLi.addClass( 'tc-hidden' );
1843			}
1844		}
1845
1846		return false;
1847	}
1848
1849	function tm_variation_check_match( element, val2, operator ) {
1850		var $element = $( element );
1851		var epoId = $element.attr( 'data-epo_id' );
1852		var productId = $element.attr( 'data-product_id' );
1853
1854		var variationsForm = $( ".variations_form[data-epo_id='" + epoId + "'][data-product_id='" + productId + "']" );
1855		var val1;
1856		var variationIdSelector = "input[name^='variation_id']";
1857		var $variationId;
1858
1859		variationsForm = $.epoAPI.applyFilter( 'tm_variation_check_match_variationsForm', variationsForm, epoId, productId, $element );
1860
1861		if ( variationsForm.length === 0 ) {
1862			return false;
1863		}
1864
1865		$variationId = variationsForm.find( variationIdSelector );
1866
1867		if ( $variationId.length === 0 ) {
1868			variationIdSelector = 'input.variation_id';
1869
1870			$variationId = variationsForm.find( variationIdSelector );
1871
1872			if ( $variationId.length === 0 ) {
1873				$variationId = variationsForm.closest( '.tc-epo-element-product-li-container' ).find( '.product-variation-id' );
1874			}
1875		}
1876
1877		if ( element !== null && val2 !== null && element !== undefined && val2 !== undefined && element !== false && val2 !== false ) {
1878			if ( val2 ) {
1879				val2 = parseInt( val2, 10 );
1880			} else {
1881				val2 = -1;
1882			}
1883		}
1884
1885		val1 = parseInt( $variationId.val(), 10 );
1886
1887		if ( ! Number.isFinite( val1 ) ) {
1888			val1 = 0;
1889		}
1890		if ( ! Number.isFinite( val2 ) ) {
1891			val2 = 0;
1892		}
1893
1894		switch ( operator ) {
1895			case 'is':
1896				return val1 !== '' && val1 === val2;
1897
1898			case 'isnot':
1899				return val1 !== '' && val1 !== val2;
1900
1901			case 'isempty':
1902				return val1 === '' || val1 === 0;
1903
1904			case 'isnotempty':
1905				return val1 !== '' && val1 !== 0;
1906
1907			case 'startswith':
1908				return val1.toString().startsWith( val2 );
1909
1910			case 'endswith':
1911				return val1.toString().endsWith( val2 );
1912
1913			case 'greaterthan':
1914				return parseFloat( val1 ) > parseFloat( val2 );
1915
1916			case 'lessthan':
1917				return parseFloat( val1 ) < parseFloat( val2 );
1918
1919			case 'greaterthanequal':
1920				return parseFloat( val1 ) >= parseFloat( val2 );
1921
1922			case 'lessthanequal':
1923				return parseFloat( val1 ) <= parseFloat( val2 );
1924		}
1925		return false;
1926	}
1927
1928	function tm_check_match( val1, val2, operator ) {
1929		if ( val1 !== null && val2 !== null ) {
1930			val1 = encodeURIComponent( val1 );
1931			if ( $.qtranxj_split ) {
1932				//backwards compatible
1933				val2 = encodeURIComponent( $.qtranxj_split( decodeURIComponent( val2 ) )[ TMEPOQTRANSLATEXJS.language ] );
1934			} else {
1935				//backwards compatible
1936				val2 = encodeURIComponent( decodeURIComponent( val2 ) );
1937			}
1938
1939			if ( val1 ) {
1940				val1 = val1.toLowerCase();
1941			} else {
1942				val1 = '';
1943			}
1944			if ( val2 ) {
1945				val2 = val2.toLowerCase();
1946			} else {
1947				val2 = '';
1948			}
1949		} else {
1950			return false;
1951		}
1952
1953		val1 = val1.toString();
1954		val2 = val2.toString();
1955
1956		switch ( operator ) {
1957			case 'is':
1958				return val1 !== null && val1 === val2;
1959
1960			case 'isnot':
1961				return val1 !== null && val1 !== val2;
1962
1963			case 'isempty':
1964				return ! ( val1 !== 'undefined' && val1 !== undefined && val1 !== '' );
1965
1966			case 'isnotempty':
1967				return val1 !== 'undefined' && val1 !== undefined && val1 !== '';
1968
1969			case 'startswith':
1970				return val1.startsWith( val2 );
1971
1972			case 'endswith':
1973				return val1.endsWith( val2 );
1974
1975			case 'greaterthan':
1976				return parseFloat( val1 ) > parseFloat( val2 );
1977
1978			case 'lessthan':
1979				return parseFloat( val1 ) < parseFloat( val2 );
1980
1981			case 'greaterthanequal':
1982				return parseFloat( val1 ) >= parseFloat( val2 );
1983
1984			case 'lessthanequal':
1985				return parseFloat( val1 ) <= parseFloat( val2 );
1986		}
1987
1988		return false;
1989	}
1990
1991	function tm_check_section_match( elements, operator ) {
1992		var any_checked;
1993		var val;
1994		var all_elements = elements.find( '.cpf-element' );
1995		var radio_checked;
1996		var checkbox_checked;
1997		var noSplit = false;
1998
1999		if ( elements.is( '.tc-hidden' ) ) {
2000			if ( operator === 'isnotempty' ) {
2001				return false;
2002			} else if ( operator === 'isempty' ) {
2003				return true;
2004			}
2005		}
2006
2007		if ( operator === 'isnotempty' ) {
2008			any_checked = false;
2009		} else if ( operator === 'isempty' ) {
2010			any_checked = true;
2011		}
2012
2013		$( all_elements ).each( function( j, element ) {
2014			var _class;
2015			var elementToCheck = '';
2016
2017			element = $( element );
2018			if ( element.is( '.cpf-type-product' ) ) {
2019				elementToCheck = ':not(.tc-extra-product-options-inline .tm-epo-field)';
2020			}
2021			if ( field_is_active( element ) ) {
2022				_class = element
2023					.attr( 'class' )
2024					.split( ' ' )
2025					.map( function( cls ) {
2026						if ( cls.indexOf( 'cpf-type-', 0 ) !== -1 ) {
2027							return cls;
2028						}
2029						return null;
2030					} )
2031					.filter( function( v ) {
2032						if ( v !== null && v !== undefined ) {
2033							return v;
2034						}
2035						return null;
2036					} );
2037
2038				if ( _class.length > 0 ) {
2039					_class = _class[ 0 ];
2040					if ( _class === 'cpf-type-product' ) {
2041						noSplit = true;
2042						if ( element.is( '.cpf-type-product-mode-product' ) || element.is( '.cpf-type-product-checkbox' ) || element.is( '.cpf-type-product-thumbnailmultiple' ) ) {
2043							_class = 'cpf-type-checkbox';
2044						} else if ( element.is( '.cpf-type-product-dropdown' ) ) {
2045							_class = 'cpf-type-select';
2046						} else {
2047							_class = 'cpf-type-radio';
2048						}
2049					}
2050					switch ( _class ) {
2051						case 'cpf-type-radio':
2052							radio_checked = element.find( 'input.tm-epo-field.tmcp-radio:checked' + elementToCheck );
2053							if ( operator === 'isnotempty' ) {
2054								any_checked = any_checked || radio_checked.length > 0;
2055								if ( radio_checked.length > 0 ) {
2056									val = radio_checked.length;
2057								}
2058							} else if ( operator === 'isempty' ) {
2059								any_checked = any_checked && radio_checked.length === 0;
2060							}
2061							break;
2062
2063						case 'cpf-type-checkbox':
2064							checkbox_checked = element.find( 'input.tm-epo-field.tmcp-checkbox:checked' + elementToCheck );
2065							if ( operator === 'isnotempty' ) {
2066								any_checked = any_checked || checkbox_checked.length > 0;
2067								if ( checkbox_checked.length > 0 ) {
2068									val = checkbox_checked.length;
2069								}
2070							} else if ( operator === 'isempty' ) {
2071								any_checked = any_checked && checkbox_checked.length === 0;
2072							}
2073							break;
2074
2075						case 'cpf-type-select':
2076							val = element.find( 'select.tm-epo-field.tmcp-select' + elementToCheck ).val();
2077							if ( val && ! noSplit ) {
2078								val = val.slice( 0, val.lastIndexOf( '_' ) );
2079							}
2080							break;
2081
2082						case 'cpf-type-selectmultiple':
2083							val = element.find( 'select.tm-epo-field.tmcp-selectmultiple' + elementToCheck ).val();
2084							if ( val && ! noSplit ) {
2085								val.forEach( function( option, i ) {
2086									val[ i ] = option.slice( 0, option.lastIndexOf( '_' ) );
2087								} );
2088							}
2089							break;
2090
2091						default:
2092							val = element.find( '.tm-epo-field' + elementToCheck ).val();
2093							break;
2094					}
2095					if ( Array.isArray( val ) ) {
2096						if ( operator === 'isnotempty' ) {
2097							any_checked = any_checked || val.some( function( item ) {
2098								return tm_check_match( item, '', operator );
2099							} );
2100						} else if ( operator === 'isempty' ) {
2101							any_checked = any_checked && val.every( function( item ) {
2102								return tm_check_match( item, '', operator );
2103							} );
2104						}
2105					} else if ( operator === 'isnotempty' ) {
2106						any_checked = any_checked || tm_check_match( val, '', operator );
2107					} else if ( operator === 'isempty' ) {
2108						any_checked = any_checked && tm_check_match( val, '', operator );
2109					}
2110				} else {
2111					any_checked = false;
2112				}
2113			}
2114		} );
2115
2116		return any_checked;
2117	}
2118
2119	function tm_check_field_match( f ) {
2120		var element = $( f.element );
2121		var operator = f.operator;
2122		var value = f.value;
2123		var val;
2124		var radio_checked;
2125		var checkbox_checked;
2126		var ret;
2127		var _class;
2128		var noSplit = false;
2129		var elementToCheck = '';
2130
2131		if ( ! element.length ) {
2132			return false;
2133		}
2134		if ( element.is( '.cpf-section' ) ) {
2135			return tm_check_section_match( element, operator );
2136		}
2137		if ( element.is( '.cpf-type-product' ) ) {
2138			elementToCheck = ':not(.tc-extra-product-options-inline .tm-epo-field)';
2139		}
2140		_class = element
2141			.attr( 'class' )
2142			.split( ' ' )
2143			.map( function( cls ) {
2144				if ( cls.indexOf( 'cpf-type-', 0 ) !== -1 ) {
2145					return cls;
2146				}
2147				return null;
2148			} )
2149			.filter( function( v ) {
2150				if ( v !== null && v !== undefined ) {
2151					return v;
2152				}
2153				return null;
2154			} );
2155
2156		if ( _class.length > 0 ) {
2157			_class = _class[ 0 ];
2158			if ( _class === 'cpf-type-product' ) {
2159				noSplit = true;
2160				if ( element.is( '.cpf-type-product-mode-product' ) || element.is( '.cpf-type-product-checkbox' ) || element.is( '.cpf-type-product-thumbnailmultiple' ) ) {
2161					_class = 'cpf-type-checkbox';
2162				} else if ( element.is( '.cpf-type-product-dropdown' ) ) {
2163					_class = 'cpf-type-select';
2164				} else {
2165					_class = 'cpf-type-radio';
2166				}
2167			}
2168			switch ( _class ) {
2169				case 'cpf-type-radio':
2170					radio_checked = element.find( 'input.tm-epo-field.tmcp-radio:checked' + elementToCheck );
2171
2172					if ( operator === 'is' || operator === 'isnot' ) {
2173						if ( radio_checked.length === 0 && operator === 'is' ) {
2174							return false;
2175						}
2176						if ( radio_checked.length === 0 && operator === 'isnot' ) {
2177							return true;
2178						}
2179					}
2180					if ( operator === 'isnotempty' ) {
2181						return radio_checked.length > 0;
2182					}
2183					if ( operator === 'isempty' ) {
2184						return radio_checked.length === 0;
2185					}
2186					val = element.find( 'input.tm-epo-field.tmcp-radio:checked' + elementToCheck ).val();
2187					if ( val && ! noSplit ) {
2188						val = val.slice( 0, val.lastIndexOf( '_' ) );
2189					}
2190					break;
2191				case 'cpf-type-checkbox':
2192					checkbox_checked = element.find( 'input.tm-epo-field.tmcp-checkbox:checked' + elementToCheck );
2193
2194					if ( operator === 'is' || operator === 'isnot' ) {
2195						if ( checkbox_checked.length === 0 && operator === 'is' ) {
2196							return false;
2197						}
2198						if ( checkbox_checked.length === 0 && operator === 'isnot' ) {
2199							return true;
2200						}
2201						ret = false;
2202						checkbox_checked.each( function( i, el ) {
2203							val = $( el ).val();
2204							if ( val && ! noSplit ) {
2205								val = val.slice( 0, val.lastIndexOf( '_' ) );
2206							}
2207							if ( tm_check_match( val, value, operator ) ) {
2208								ret = true;
2209							} else if ( operator === 'isnot' ) {
2210								ret = false;
2211								return false;
2212							}
2213						} );
2214						return ret;
2215					}
2216					if ( operator === 'isnotempty' ) {
2217						return checkbox_checked.length > 0;
2218					}
2219					if ( operator === 'isempty' ) {
2220						return checkbox_checked.length === 0;
2221					}
2222					break;
2223
2224				case 'cpf-type-select':
2225					val = element.find( 'select.tm-epo-field.tmcp-select' + elementToCheck ).val();
2226					if ( val && ! noSplit ) {
2227						val = val.slice( 0, val.lastIndexOf( '_' ) );
2228					}
2229					break;
2230
2231				case 'cpf-type-selectmultiple':
2232					val = element.find( 'select.tm-epo-field.tmcp-selectmultiple' + elementToCheck ).val();
2233					if ( val && ! noSplit ) {
2234						val.forEach( function( option, i ) {
2235							val[ i ] = option.slice( 0, option.lastIndexOf( '_' ) );
2236						} );
2237					}
2238					break;
2239
2240				case 'cpf-type-variations':
2241					return tm_variation_check_match( element, value, operator );
2242
2243				default:
2244					val = element.find( '.tm-epo-field' + elementToCheck ).val();
2245					break;
2246			}
2247			if ( Array.isArray( val ) ) {
2248				return val.some( function( item ) {
2249					return tm_check_match( item, value, operator );
2250				} );
2251			}
2252			return tm_check_match( val, value, operator );
2253		}
2254		return false;
2255	}
2256
2257	function tm_check_rules( o, theevent ) {
2258		o.each( function() {
2259			var $this = $( this );
2260			var matches = $this.data( 'matches' );
2261			var toggle = $this.data( 'toggle' );
2262			var fields = $this.data( 'fields' );
2263			var checked = [];
2264			var show = false;
2265
2266			switch ( toggle ) {
2267				case 'show':
2268					show = false;
2269					break;
2270				case 'hide':
2271					show = true;
2272					break;
2273			}
2274
2275			$.each( fields, function( i, ifield ) {
2276				if ( Array.isArray( ifield ) ) {
2277					checked[ i ] = 0;
2278					$.each( ifield, function( ii, field ) {
2279						var fia = true;
2280
2281						if ( theevent === 'cpflogic' ) {
2282							fia = field_is_active( $( field.element ) );
2283						}
2284						if ( fia && tm_check_field_match( field ) ) {
2285							checked[ i ] = parseInt( checked[ i ], 10 ) + 1;
2286						}
2287					} );
2288				}
2289			} );
2290
2291			$.each( matches, function( im, match ) {
2292				var checkim = parseInt( checked[ im ], 10 );
2293				match = parseInt( match, 10 );
2294
2295				if ( checkim > 0 && match === checkim ) {
2296					show = ! show;
2297					return false;
2298				}
2299			} );
2300
2301			if ( show ) {
2302				if ( theevent === 'cpflogic' && ! $this.data( 'did_initial_activation' ) ) {
2303					latecpflogicactions.push( function() {
2304						var enabledEpos = $this.find( '.tm-epo-field.tcenabled' );
2305						enabledEpos.each( function( i, el ) {
2306							el = $( el );
2307							if ( ! el.data( 'initial_activation' ) && ! $this.closest( '.cpf-section' ).is( '.tc-hidden' ) && field_is_active( el ) ) {
2308								el.trigger( 'tc_element_epo_rules' );
2309								el.data( 'initial_activation', 1 );
2310							}
2311						} );
2312						if ( ( $this.is( '.cpf-element' ) && enabledEpos.length ) || $this.is( '.cpf-section' ) ) {
2313							$this.data( 'did_initial_activation', 1 );
2314						}
2315					} );
2316				}
2317
2318				$this.removeClass( 'tc-hidden' );
2319			} else {
2320				$this.addClass( 'tc-hidden' );
2321			}
2322			$this.data( 'isactive', show );
2323			$this.trigger( 'tc-logic' );
2324		} );
2325	}
2326
2327	function run_cpfdependson( obj ) {
2328		var iscpfdependson;
2329		var last_activate_field = [];
2330		var epo_object;
2331
2332		if ( ! $( obj ).length ) {
2333			obj = 'body';
2334		}
2335		obj = $( obj );
2336		iscpfdependson = obj.find( '.iscpfdependson' );
2337		iscpfdependson.each( function( i, elements ) {
2338			$( elements ).each( function( j, el ) {
2339				tm_check_rules( $( el ) );
2340			} );
2341		} );
2342		iscpfdependson.each( function( i, elements ) {
2343			$( elements ).each( function( j, el ) {
2344				tm_check_rules( $( el ), 'cpflogic' );
2345			} );
2346		} );
2347		iscpfdependson.each( function( i, elements ) {
2348			$( elements ).each( function( j, o ) {
2349				o = $( o );
2350				if ( o.is( '.cpf-section' ) ) {
2351					o = o.find( '.cpf-element' );
2352				}
2353				o.each( function( theindex, theelement ) {
2354					field_is_active( $( theelement ).find( '.tm-epo-field' ) );
2355				} );
2356			} );
2357		} );
2358		latecpflogicactions.forEach( function( func ) {
2359			func();
2360		} );
2361		latecpflogicactions = [];
2362		if ( $().selectric ) {
2363			$( '.tm-extra-product-options select' ).selectric( 'refresh' );
2364		}
2365		setTimeout( function() {
2366			$( '.tm-owl-slider' ).each( function() {
2367				$( this ).trigger( 'refresh.owl.carousel' );
2368			} );
2369		}, 200 );
2370
2371		obj.find( '.tm-product-image:checked,select.tm-product-image' ).each( function() {
2372			var t = $( this );
2373			if ( field_is_active( t ) && t.val() !== '' ) {
2374				last_activate_field.push( t );
2375			}
2376		} );
2377		if ( last_activate_field.length ) {
2378			last_activate_field[ last_activate_field.length - 1 ].trigger( 'tm_trigger_product_image' );
2379		} else {
2380			epo_object = obj.data( 'epo_object' );
2381			if ( epo_object ) {
2382				epo_object.main_product.trigger( 'tm_restore_product_image' );
2383			}
2384		}
2385
2386		jWindow.trigger( 'cpflogicrun' );
2387		jWindow.trigger( 'tmlazy' );
2388		jWindow.trigger( 'cpflogicdone' );
2389	}
2390
2391	// Start Conditional logic
2392	if ( ! $().cpfdependson ) {
2393		$.fn.cpfdependson = function( fields, toggle, refresh ) {
2394			var elements = this;
2395			var matches = [];
2396
2397			if ( elements.length === 0 || typeof fields !== 'object' ) {
2398				return;
2399			}
2400
2401			if ( ! toggle ) {
2402				toggle = 'show';
2403			}
2404
2405			$.each( fields, function( i, ifield ) {
2406				var get_element;
2407				var $this_epo_container;
2408
2409				matches[ i ] = 0;
2410
2411				if ( Array.isArray( ifield ) ) {
2412					$.each( ifield, function( ii, field ) {
2413						if ( typeof field !== 'object' ) {
2414							return true;
2415						}
2416						get_element = get_element_from_field( field.element );
2417
2418						if ( get_element && get_element.length > 0 ) {
2419							get_element.each( function( iii, element ) {
2420								var $element = $( element );
2421								var $pid1;
2422								var $epo_id1;
2423								var _events = 'change.cpflogic';
2424
2425								// this essentially only works for the plugin so we use
2426								// cache and not recalcualte each time
2427								if ( ! $this_epo_container || $this_epo_container.closest( '.tc-extra-product-options-inline' ).length ) {
2428									$pid1 = '.tm-product-id-' + $element.closest( '.tc-extra-product-options' ).attr( 'data-product-id' );
2429									$epo_id1 = "[data-epo-id='" + $element.closest( '.tc-extra-product-options' ).attr( 'data-epo-id' ) + "']";
2430									$this_epo_container = $( '.tc-extra-product-options' + $pid1 + $epo_id1 );
2431								}
2432
2433								if ( element && $element.length > 0 && ( ! $element.data( 'tmhaslogicevents' ) || refresh ) ) {
2434									if ( $element.is( '.tm-epo-variation-element' ) ) {
2435										// associated product event prefixes are added later
2436										add_variation_event( 'found_variation.tmlogic', false, function() {
2437											run_cpfdependson( $this_epo_container );
2438											jWindow.trigger( 'tm-do-epo-update' );
2439										} );
2440										add_variation_event( 'hide_variation.tmlogic', false, function() {
2441											run_cpfdependson( $this_epo_container );
2442											jWindow.trigger( 'tm-do-epo-update' );
2443										} );
2444									} else {
2445										if ( $element.is( ':text' ) || $element.is( 'textarea' ) ) {
2446											_events = 'change.cpflogic input.cpflogic';
2447										}
2448										if ( $element.is( ':input[type="number"]' ) ) {
2449											_events = 'change.cpflogic input.cpflogic keypress.cpflogic';
2450										}
2451										$element.off( _events ).on( _events, function() {
2452											run_cpfdependson( $this_epo_container );
2453										} );
2454									}
2455									$element.data( 'tmhaslogicevents', 1 );
2456								}
2457							} );
2458						}
2459						matches[ i ] = parseInt( matches[ i ], 10 ) + 1;
2460					} );
2461				}
2462			} );
2463
2464			elements.each( function() {
2465				var $this = $( this );
2466				var show = false;
2467
2468				$this.data( 'matches', matches ).data( 'toggle', toggle ).data( 'fields', fields );
2469
2470				switch ( toggle ) {
2471					case 'show':
2472						show = false;
2473						break;
2474					case 'hide':
2475						show = true;
2476						break;
2477				}
2478				if ( show ) {
2479					$this.removeClass( 'tc-hidden' );
2480				} else {
2481					$this.addClass( 'tc-hidden' );
2482				}
2483
2484				$this.data( 'isactive', show );
2485			} );
2486
2487			elements.addClass( 'iscpfdependson is-epo-depend' ).data( 'iscpfdependson', 1 );
2488			return elements;
2489		};
2490
2491		$.fn.run_cpfdependson = function() {
2492			run_cpfdependson();
2493		};
2494	}
2495
2496	$.tcepo = {
2497		formSubmitEvents: {},
2498
2499		oneOptionIsSelected: {},
2500
2501		initialActivation: {},
2502
2503		// Holds the active precentage of total current price type fields
2504		lateFieldsPrices: {},
2505
2506		errorObject: {},
2507
2508		showHideTotal: {}
2509	};
2510
2511	function validate_logic( l ) {
2512		return typeof l === 'object' && 'toggle' in l && 'rules' in l && l.rules.length > 0;
2513	}
2514
2515	function convert_rules( rules ) {
2516		if ( rules.what ) {
2517			if ( rules.what === 'all' ) {
2518				rules.rules = [ rules.rules ];
2519			} else if ( rules.what === 'any' ) {
2520				rules.rules = rules.rules.reduce( function( accumulator, elrule ) {
2521					accumulator.push( [ elrule ] );
2522					return accumulator;
2523				}, [] );
2524			}
2525			delete rules.what;
2526		}
2527		return rules;
2528	}
2529
2530	// The following loops are required for the logic to work on composite products that have custom variations
2531	function cpf_section_logic( obj ) {
2532		var root_element = $( obj );
2533		var all_sections = root_element.find( '.cpf-section' );
2534		var search_obj;
2535		var cpf_section;
2536		var sect;
2537		var logic;
2538		var haslogic;
2539		var fields;
2540		var section;
2541		var element;
2542		var operator;
2543		var value;
2544		var obj_section;
2545		var obj_element;
2546		var closestProductElement;
2547
2548		if ( root_element.is( '.cpf-section' ) ) {
2549			search_obj = false;
2550		} else {
2551			search_obj = all_sections;
2552		}
2553
2554		root_element.each( function( j, obj_el ) {
2555			if ( $( obj_el ).is( '.cpf-section' ) ) {
2556				cpf_section = $( obj_el );
2557			} else {
2558				cpf_section = $( obj_el ).find( '.cpf-section' );
2559			}
2560
2561			cpf_section.filter( '[data-haslogic="1"]' ).each( function( index, el ) {
2562				sect = $( el );
2563				logic = sect.data( 'logic' );
2564				// backwards compatibility conversion.
2565				logic = convert_rules( logic );
2566				haslogic = parseInt( sect.data( 'haslogic' ), 10 );
2567				fields = [];
2568				closestProductElement = sect.parent().closest( '.cpf-type-product' );
2569
2570				if ( haslogic === 1 && validate_logic( logic ) ) {
2571					$.each( logic.rules, function( i, irule ) {
2572						if ( irule ) {
2573							if ( Array.isArray( irule ) ) {
2574								fields[ i ] = [];
2575								$.each( irule, function( ii, rule ) {
2576									section = rule.section;
2577									element = rule.element;
2578									operator = rule.operator;
2579									value = rule.value;
2580
2581									if ( search_obj ) {
2582										if ( closestProductElement.length ) {
2583											obj_section = closestProductElement.find( '.cpf-section' ).filter( "[data-uniqid='" + section + "']" );
2584											if ( element !== section ) {
2585												obj_element = obj_section.find( '.cpf-element' ).eq( element );
2586											} else {
2587												obj_element = obj_section;
2588											}
2589										} else {
2590											obj_section = search_obj.filter( "[data-uniqid='" + section + "']" );
2591											if ( element !== section ) {
2592												obj_element = obj_section.find( '.cpf-element:not(.cpf-element .cpf-element)' ).eq( element );
2593											} else {
2594												obj_element = obj_section;
2595											}
2596										}
2597									} else if ( element !== section ) {
2598										obj_element = root_element.find( '.cpf-element' ).eq( element );
2599									} else {
2600										obj_element = obj_section;
2601									}
2602
2603									fields[ i ].push( {
2604										element: obj_element,
2605										operator: operator,
2606										value: value
2607									} );
2608								} );
2609							}
2610						}
2611					} );
2612					if ( ! sect.data( 'iscpfdependson' ) ) {
2613						sect.data( 'cpfdependson-fields', fields );
2614						sect.cpfdependson( fields, logic.toggle );
2615					} else {
2616						sect.cpfdependson( sect.data( 'cpfdependson-fields' ), logic.toggle, true );
2617					}
2618				}
2619			} );
2620		} );
2621	}
2622
2623	function cpf_element_logic( obj ) {
2624		var root_element = $( obj );
2625		var all_sections = root_element.find( '.cpf-section' ).not( '.cpf-type-product .cpf-section' );
2626		var search_obj;
2627		var current_element;
2628		var logic;
2629		var haslogic;
2630		var section;
2631		var element;
2632		var operator;
2633		var value;
2634		var obj_section;
2635		var obj_element;
2636		var closestProductElement;
2637
2638		if ( root_element.is( '.cpf-section' ) ) {
2639			search_obj = false;
2640		} else {
2641			search_obj = all_sections;
2642		}
2643
2644		root_element.find( '.cpf-element[data-haslogic="1"]' ).each( function( index, el ) {
2645			var fields = [];
2646
2647			current_element = $( el );
2648			logic = current_element.data( 'logic' );
2649			// backwards compatibility conversion.
2650			logic = convert_rules( logic );
2651
2652			haslogic = parseInt( current_element.data( 'haslogic' ), 10 );
2653
2654			closestProductElement = current_element.parent().closest( '.cpf-type-product' );
2655
2656			if ( haslogic === 1 && validate_logic( logic ) ) {
2657				$.each( logic.rules, function( i, irule ) {
2658					if ( irule ) {
2659						if ( Array.isArray( irule ) ) {
2660							fields[ i ] = [];
2661							$.each( irule, function( ii, rule ) {
2662								section = rule.section;
2663								element = rule.element;
2664								operator = rule.operator;
2665								value = rule.value;
2666
2667								if ( search_obj ) {
2668									if ( closestProductElement.length ) {
2669										obj_section = closestProductElement.find( '.cpf-section' ).filter( "[data-uniqid='" + section + "']" );
2670										if ( element !== section ) {
2671											obj_element = obj_section.find( '.cpf-element' ).eq( element );
2672										} else {
2673											obj_element = obj_section;
2674										}
2675									} else {
2676										obj_section = search_obj.filter( "[data-uniqid='" + section + "']" );
2677										if ( element !== section ) {
2678											obj_element = obj_section.find( '.cpf-element:not(.cpf-element .cpf-element)' ).eq( element );
2679										} else {
2680											obj_element = obj_section;
2681										}
2682									}
2683								} else if ( element !== section ) {
2684									obj_element = root_element.find( '.cpf-element' ).eq( element );
2685								} else {
2686									obj_element = obj_section;
2687								}
2688
2689								fields[ i ].push( {
2690									element: obj_element,
2691									operator: operator,
2692									value: value
2693								} );
2694							} );
2695						}
2696					}
2697				} );
2698
2699				if ( ! current_element.data( 'iscpfdependson' ) ) {
2700					current_element.data( 'cpfdependson-fields', fields );
2701					current_element.cpfdependson( fields, logic.toggle );
2702				} else {
2703					current_element.cpfdependson( current_element.data( 'cpfdependson-fields' ), logic.toggle, true );
2704				}
2705			}
2706		} );
2707	} // End Conditional logic
2708
2709	// Return price value without tax
2710	function tm_set_price_without_tax( value, _cart, force ) {
2711		var taxable;
2712		var tax_rate;
2713		var tax_display_mode;
2714		var prices_include_tax;
2715
2716		if ( _cart ) {
2717			taxable = _cart.attr( 'data-taxable' );
2718			tax_rate = _cart.attr( 'data-tax-rate' );
2719			tax_display_mode = _cart.attr( 'data-tax-display-mode' );
2720			prices_include_tax = _cart.attr( 'data-prices-include-tax' );
2721
2722			if ( force || ( taxable && tax_display_mode === 'incl' && prices_include_tax !== '1' ) ) {
2723				value = parseFloat( value ) / ( 1 + ( tax_rate / 100 ) );
2724			}
2725		}
2726
2727		return value;
2728	}
2729
2730	// Return price with tax
2731	function tm_set_price_with_tax( value, _cart, force ) {
2732		var taxable;
2733		var tax_rate;
2734		var tax_display_mode;
2735		var prices_include_tax;
2736
2737		if ( _cart ) {
2738			taxable = _cart.attr( 'data-taxable' );
2739			tax_rate = _cart.attr( 'data-tax-rate' );
2740			tax_display_mode = _cart.attr( 'data-tax-display-mode' );
2741			prices_include_tax = _cart.attr( 'data-prices-include-tax' );
2742			if ( force || ( taxable && tax_display_mode !== 'incl' && prices_include_tax === '1' ) ) {
2743				value = parseFloat( value ) * ( 1 + ( tax_rate / 100 ) );
2744			}
2745		}
2746
2747		return value;
2748	}
2749
2750	// Return  price
2751	function tm_set_backend_price( value, _cart, variation ) {
2752		var taxable;
2753		var tax_display_mode;
2754		var prices_include_tax;
2755
2756		if ( _cart ) {
2757			taxable = _cart.attr( 'data-taxable' );
2758			tax_display_mode = _cart.attr( 'data-tax-display-mode' );
2759			prices_include_tax = _cart.attr( 'data-prices-include-tax' );
2760			if ( taxable ) {
2761				if ( variation && variation.tc_tax_rate && String( variation.tc_tax_rate ) === '0' ) {
2762					return value;
2763				}
2764				if ( prices_include_tax === '1' ) {
2765					if ( tax_display_mode === 'incl' ) {
2766						// if we are not in the base tax
2767						if ( variation.tc_base_taxes_of_one !== variation.tc_modded_taxes_of_one ) {
2768							value = parseFloat( ( ( 1 - variation.tc_taxes_of_one ) * value ) * ( 1 / ( 1 - variation.tc_base_taxes_of_one ) ) );
2769						}
2770					} else {
2771						value = tm_set_price_with_tax( value, _cart );
2772					}
2773				} else if ( prices_include_tax !== '1' && tax_display_mode === 'incl' ) {
2774					value = tm_set_price_without_tax( value, _cart );
2775				}
2776			}
2777		}
2778
2779		return value;
2780	}
2781
2782	// Return a formatted currency value
2783	function tm_set_price_totals( value, _cart, notax, taxstring, element ) {
2784		var inc_tax_string = '';
2785		var sign = '';
2786		var val;
2787
2788		if ( ! notax ) {
2789			value = tm_set_tax_price( value, _cart, element, undefined, true );
2790		}
2791		val = Math.abs( value );
2792		if ( _cart && taxstring ) {
2793			inc_tax_string = _cart.attr( 'data-tax-string' );
2794		}
2795		if ( inc_tax_string === undefined ) {
2796			inc_tax_string = '';
2797		}
2798
2799		if ( value < 0 ) {
2800			sign = TMEPOJS.minus_sign + ' ';
2801		}
2802
2803		return tm_set_price_( val, sign, inc_tax_string );
2804	}
2805
2806	function replace_suffixes( value, rawValue, tc_totals_ob, totalsHolder ) {
2807		if ( totalsHolder.attr( 'data-tax-display-mode' ) === 'excl' ) {
2808			tc_totals_ob[ value ] = tc_totals_ob[ value ].replace( /{price_excluding_tax}/g, tm_set_price_totals( tc_totals_ob[ rawValue ], totalsHolder, true, false ) );
2809			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 ) );
2810		} else {
2811			tc_totals_ob[ value ] = tc_totals_ob[ value ].replace( /{price_including_tax}/g, tm_set_price_totals( tc_totals_ob[ rawValue ], totalsHolder, true, false ) );
2812			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 ) );
2813		}
2814		return tc_totals_ob;
2815	}
2816
2817	function tm_force_update_price( obj, price, formated_price, original_price, original_formated_price ) {
2818		tm_update_price( obj, price, formated_price, original_price, original_formated_price, true );
2819	}
2820
2821	function tm_update_price( obj, price, formated_price, original_price, original_formated_price, force ) {
2822		var $obj = $( obj );
2823		var w;
2824		var $ba_amount;
2825		var priceobj;
2826		var f;
2827		var pw;
2828
2829		if ( $obj.length === 0 ) {
2830			return;
2831		}
2832
2833		w = $obj.closest( '.tmcp-field-wrap' );
2834		pw = $obj.closest( '.tc-price-wrap' );
2835		f = w.find( '.tm-epo-field' );
2836
2837		if ( ! force && f.attr( 'data-no-price-change' ) === '1' && f.data( 'price-changed' ) ) {
2838			return;
2839		}
2840
2841		price = $.epoAPI.applyFilter( 'tc_adjust_update_price_price', price ); //number
2842		formated_price = $.epoAPI.applyFilter( 'tc_adjust_update_price_formated_price', formated_price, price ); //formatted
2843		original_price = $.epoAPI.applyFilter( 'tc_adjust_update_price_original_price', original_price ); //number
2844		original_formated_price = $.epoAPI.applyFilter( 'tc_adjust_update_price_original_formated_price', original_formated_price, original_price ); //formatted
2845
2846		if ( ! Number.isFinite( parseFloat( original_price ) ) ) {
2847			original_price = 0;
2848		}
2849		if ( ! Number.isFinite( parseFloat( price ) ) ) {
2850			price = 0;
2851		}
2852
2853		$ba_amount = w.find( '.before-amount,.after-amount' );
2854		priceobj = {
2855			price: formated_price,
2856			original_price: original_formated_price
2857		};
2858
2859		if ( ( TMEPOJS.tm_epo_auto_hide_price_if_zero === 'yes' && $.tmempty( price ) === false ) || TMEPOJS.tm_epo_auto_hide_price_if_zero !== 'yes' ) {
2860			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' ) ) ) ) ) {
2861				pw.addClass( 'tm-hidden' );
2862				$obj.addClass( 'tm-hidden' );
2863				$obj.empty();
2864				$ba_amount.addClass( 'tm-hidden' );
2865			} else {
2866				if ( original_price && original_price !== undefined && parseFloat( original_price ) !== parseFloat( price ) ) {
2867					$obj.html( $.epoAPI.template.html( tcAPI.templateEngine.sale_price, { price: priceobj } ) );
2868				} else {
2869					$obj.html( $.epoAPI.template.html( tcAPI.templateEngine.price, { price: priceobj } ) );
2870				}
2871				pw.removeClass( 'tm-hidden' );
2872				$obj.removeClass( 'tm-hidden' );
2873				$ba_amount.removeClass( 'tm-hidden' );
2874			}
2875		} else {
2876			pw.addClass( 'tm-hidden' );
2877			$obj.addClass( 'tm-hidden' );
2878			$obj.empty();
2879			$ba_amount.addClass( 'tm-hidden' );
2880		}
2881	}
2882
2883	function get_variation_current_settings( form, epoObject ) {
2884		var current_settings = {};
2885
2886		if ( epoObject.thisForm ) {
2887			form = epoObject.thisForm;
2888		}
2889
2890		form.find( '.variations select, .tc-epo-variable-product-selector' ).each( function() {
2891			var attribute_name;
2892			var value;
2893
2894			// Get attribute name from data-attribute_name, or from input name
2895			// if it doesn't exist
2896			if ( typeof $( this ).data( 'attribute_name' ) !== 'undefined' ) {
2897				attribute_name = $( this ).data( 'attribute_name' );
2898			} else {
2899				attribute_name = $( this ).attr( 'name' );
2900			}
2901
2902			// Encode entities
2903			value = $( this ).val();
2904
2905			// Add to settings array
2906			current_settings[ attribute_name ] = value;
2907		} );
2908
2909		return current_settings;
2910	}
2911
2912	function do_tm_custom_variations_update( form, all_variations, epoObject ) {
2913		var check_if_all_are_not_set = [];
2914		var formSettings = get_variation_current_settings( form, epoObject );
2915		var redo_check = true;
2916		var variationId = form.find( getVariationIdSelector( form ) ).val();
2917		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' );
2918
2919		if ( ! variationId ) {
2920			return;
2921		}
2922		form.find( '.cpf-type-variations' ).each( function( i, el ) {
2923			var t = $( el ).find( '.tm-epo-variation-element' );
2924			var id;
2925			var v;
2926			var exists = false;
2927
2928			check_if_all_are_not_set[ i ] = true;
2929
2930			if ( t.is( 'select' ) ) {
2931				id = $.epoAPI.dom.id( t.attr( 'data-tm-for-variation' ) );
2932				v = t.val();
2933				if ( v ) {
2934					check_if_all_are_not_set[ i ] = false;
2935				}
2936				t.children( 'option' ).each( function( x, o ) {
2937					exists = false;
2938					form.find( "[data-attribute_name='attribute_" + id + "']" )
2939						.children( 'option' )
2940						.each( function() {
2941							if ( $( this ).attr( 'value' ) === $( o ).attr( 'value' ) ) {
2942								exists = true;
2943								return false;
2944							}
2945						} );
2946					if ( ! exists ) {
2947						$( o ).prop( 'disabled', true ).hide();
2948					} else {
2949						$( o ).prop( 'disabled', false ).show();
2950					}
2951				} );
2952			} else {
2953				t.each( function( x, oe ) {
2954					var o = $( oe );
2955					var li = o.closest( 'li' );
2956					var input = li.find( '.tm-epo-variation-element' );
2957					var this_settings = $.extend( true, {}, formSettings );
2958					var matching_variations;
2959					var variation;
2960					var is_in_stock;
2961
2962					id = o.attr( 'data-tm-for-variation' );
2963					v = o.val();
2964					if ( o.is( ':checked' ) ) {
2965						check_if_all_are_not_set[ i ] = false;
2966					}
2967
2968					this_settings[ 'attribute_' + id ] = v;
2969
2970					matching_variations = $.fn.tm_find_matching_variations( all_variations, this_settings );
2971					variation = matching_variations.shift();
2972
2973					is_in_stock = variation && 'is_in_stock' in variation && variation.is_in_stock;
2974
2975					if ( ! is_in_stock ) {
2976						if ( ! input.is( ':checked' ) && ! is_in_stock ) {
2977							li.addClass( 'pointereventsoff' );
2978						} else {
2979							li.removeClass( 'pointereventsoff' );
2980						}
2981
2982						o.attr( 'disabled', 'disabled' ).addClass( 'tm-disabled' );
2983
2984						input.attr( 'disabled', 'disabled' );
2985						input.attr( 'data-tm-disabled', 'disabled' );
2986
2987						li.addClass( 'tm-attribute-disabled' ).fadeTo( 'fast', 0.5 );
2988					} else {
2989						o.prop( 'disabled', false ).removeClass( 'tm-disabled' );
2990						li.removeClass( 'pointereventsoff tm-attribute-disabled' ).fadeTo( 'fast', 1, function() {
2991							$( this ).css( 'opacity', '' );
2992						} );
2993						input.prop( 'disabled', false );
2994						input.removeAttr( 'data-tm-disabled' );
2995					}
2996				} );
2997			}
2998		} );
2999
3000		if ( check_if_all_are_not_set ) {
3001			check_if_all_are_not_set.shift();
3002
3003			$.each( check_if_all_are_not_set, function( i, el ) {
3004				if ( el === false ) {
3005					redo_check = false;
3006					return false;
3007				}
3008			} );
3009			if ( redo_check ) {
3010				form.find( '.cpf-type-variations' )
3011					.first()
3012					.each( function( i, el ) {
3013						var t;
3014						var li;
3015						var input;
3016
3017						t = $( el ).find( '.tm-epo-variation-element' );
3018
3019						if ( ! t.is( 'select' ) ) {
3020							t.each( function( x, o ) {
3021								o = $( o );
3022								li = o.closest( 'li' );
3023								input = li.find( '.tm-epo-variation-element' );
3024								o.prop( 'disabled', false ).removeClass( 'tm-disabled' );
3025								li.removeClass( 'tm-attribute-disabled' ).stop().css( 'opacity', '' );
3026								input.prop( 'disabled', false );
3027								input.removeAttr( 'data-tm-disabled' );
3028							} );
3029						}
3030					} );
3031			}
3032		}
3033	}
3034
3035	function tm_custom_variations_update( form, epoObject ) {
3036		var data;
3037		var all_variations = form.data( 'product_variations' );
3038		var product_id = parseInt( form.data( 'product_id' ), 10 );
3039		var globalVariationObject = form.data( 'globalVariationObject' ) || false;
3040
3041		if ( ! product_id ) {
3042			product_id = form.data( 'tc_product_id' );
3043		}
3044
3045		if ( ! product_id && form.is( tcAPI.compositeSelector ) ) {
3046			data = form.find( '.component_options' ).data( 'options_data' );
3047			product_id = data[ 0 ].option_id;
3048			if ( ! all_variations ) {
3049				all_variations = form.find( '.details.component_data' ).data( 'product_variations' );
3050			}
3051		}
3052
3053		if ( ! epoObject.is_associated ) {
3054			// Fallback to window property if not set - backwards compat
3055			if ( ! all_variations && window.product_variations && window.product_variations.product_id ) {
3056				all_variations = window.product_variations.product_id;
3057			}
3058			if ( ! all_variations && window.product_variations ) {
3059				all_variations = window.product_variations;
3060			}
3061			if ( ! all_variations && window[ 'product_variations_' + product_id ] ) {
3062				all_variations = window[ 'product_variations_' + product_id ];
3063			}
3064		}
3065
3066		if ( ! all_variations ) {
3067			if ( ! globalVariationObject ) {
3068				data = {
3069					action: 'woocommerce_tm_get_variations_array',
3070					post_id: product_id
3071				};
3072				$.post(
3073					TMEPOJS.ajax_url,
3074					data,
3075					function( response ) {
3076						globalVariationObject = response;
3077						form.data( 'globalVariationObject', response );
3078						do_tm_custom_variations_update( form, globalVariationObject.variations, epoObject );
3079					},
3080					'json'
3081				);
3082			} else {
3083				do_tm_custom_variations_update( form, globalVariationObject.variations, epoObject );
3084			}
3085
3086			return;
3087		}
3088		// may need 2.4 check for woocommerce_ajax_variation_threshold
3089		do_tm_custom_variations_update( form, all_variations, epoObject );
3090	}
3091
3092	function tm_fix_stock( cart, html ) {
3093		var custom_variations;
3094		var section;
3095
3096		if ( html === undefined ) {
3097			return false;
3098		}
3099		cart = $( cart );
3100		custom_variations = cart.find( '.tm-epo-variation-element' ).first();
3101		section = custom_variations.closest( '.tm-epo-variation-section' );
3102
3103		if ( custom_variations.length ) {
3104			section.find( '.tm-stock' ).remove();
3105			section.append( '<div class="tm-stock">' + html + '</div>' );
3106			return true;
3107		}
3108		cart.find( '.tm-stock' ).remove();
3109		cart.find( '.variations' ).after( '<div class="tm-stock">' + html + '</div>' );
3110		return true;
3111	}
3112
3113	function fix_stock( $this, form ) {
3114		var stock;
3115
3116		if ( TMEPOJS.tm_epo_global_move_out_of_stock === 'no' ) {
3117			return;
3118		}
3119		stock = $this.find( '.woocommerce-variation-availability' ).last();
3120		if ( ! stock.length ) {
3121			stock = $this.find( '.stock' ).last();
3122		}
3123
3124		if ( stock.length ) {
3125			form.find( '.tm-stock' ).remove();
3126			if ( tm_fix_stock( form, stock.prop( 'outerHTML' ) ) ) {
3127				stock.remove();
3128			}
3129		} else {
3130			form.find( '.tm-stock' ).remove();
3131		}
3132	}
3133
3134	function get_main_input_id( main_product, product, id ) {
3135		var selector = '';
3136		var inputid;
3137
3138		if ( id ) {
3139			selector = selector + "[value='" + id + "']";
3140		}
3141		if ( ! product ) {
3142			product = main_product;
3143		}
3144		inputid = product.find( tcAPI.addToCartSelector + selector );
3145		if ( inputid.length === 0 ) {
3146			inputid = product.find( tcAPI.tcAddToCartSelector + selector );
3147		}
3148		return inputid.last();
3149	}
3150
3151	function get_main_form( main_product, product, selector, id ) {
3152		if ( ! selector ) {
3153			selector = 'form';
3154		}
3155		return get_main_input_id( main_product, product, id ).closest( selector );
3156	}
3157
3158	function get_main_cart( main_product, product, selector, id ) {
3159		return get_main_form( main_product, product, selector, id );
3160	}
3161
3162	function tm_get_native_prices_block( obj ) {
3163		var selector = $.epoAPI.applyFilter( 'tcGetNativePricesBlockSelector', '.single_variation .price', obj );
3164
3165		return $( obj ).find( selector ).not( '.tc-price' );
3166	}
3167
3168	// URL replacement setup
3169	function tm_set_url_fields() {
3170		jDocument.on( 'click.cpfurl change.cpfurl tmredirect', '.tc-url-container .tmcp-radio, .tc-url-container .tmcp-radio+label', function( e ) {
3171			var data_url = $( this ).attr( 'data-url' );
3172			if ( data_url ) {
3173				if ( window.location !== data_url ) {
3174					e.preventDefault();
3175					window.location = data_url;
3176				}
3177			}
3178		} );
3179		jDocument.on( 'change.cpfurl tmredirect', '.tc-url-container .tmcp-select', function( e ) {
3180			var data_url = $( this ).children( 'option:selected' ).attr( 'data-url' );
3181			if ( data_url ) {
3182				if ( window.location !== data_url ) {
3183					e.preventDefault();
3184					window.location = data_url;
3185				}
3186			}
3187		} );
3188	}
3189
3190	function tm_floating_totals( this_epo_totals_container, is_quickview, main_cart ) {
3191		$.tcFloatingTotalsBox( this_epo_totals_container, is_quickview, main_cart );
3192	}
3193
3194	function tm_show_hide_add_to_cart_button( main_product, currentEpoObject ) {
3195		var button;
3196		var qty;
3197		var showHideCart = currentEpoObject.showHideCart;
3198
3199		if ( ! currentEpoObject.is_associated && showHideCart !== undefined ) {
3200			if ( TMEPOJS.tm_epo_hide_add_cart_button === 'yes' || TMEPOJS.tm_epo_hide_all_add_cart_button === 'yes' || TMEPOJS.tm_epo_hide_required_add_cart_button === 'yes' ) {
3201				button = main_product.find( tcAPI.addToCartButtonSelector ).first();
3202				qty = main_product.find( tcAPI.qtySelector ).first();
3203
3204				if ( showHideCart ) {
3205					button.removeClass( 'tc-hide-add-to-cart-button' );
3206					qty.removeClass( 'tc-hide-add-to-cart-button' );
3207				} else {
3208					button.addClass( 'tc-hide-add-to-cart-button' );
3209					qty.addClass( 'tc-hide-add-to-cart-button' );
3210				}
3211
3212				jWindow.trigger( 'epoShowHideCart', {
3213					main_product: main_product,
3214					currentEpoObject: currentEpoObject,
3215					showHideCart: showHideCart,
3216					button: button,
3217					qty: qty
3218				} );
3219			}
3220		}
3221	}
3222
3223	function addShowHidetoEpoObject( currentEpoObject, epoEventId, epoObject ) {
3224		var has_epo;
3225		var this_epo_container;
3226		var epos;
3227		var allElementsAreSelected;
3228		var showHideCart = true;
3229		var showHideTotal = true;
3230		var one_option_is_selected = $.tcepo.oneOptionIsSelected[ epoEventId ];
3231
3232		if ( currentEpoObject.is_associated ) {
3233			return currentEpoObject;
3234		}
3235
3236		if ( typeof epoObject === 'object' ) {
3237			has_epo = epoObject.has_epo;
3238			this_epo_container = epoObject.this_epo_container;
3239			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 );
3240		} else {
3241			has_epo = epoObject;
3242		}
3243
3244		currentEpoObject.showHideCart = undefined;
3245		currentEpoObject.showHideTotal = undefined;
3246
3247		if ( has_epo && ( TMEPOJS.tm_epo_hide_add_cart_button === 'yes' || TMEPOJS.tm_epo_hide_all_add_cart_button === 'yes' || TMEPOJS.tm_epo_hide_required_add_cart_button === 'yes' || TMEPOJS.tm_epo_hide_totals_until_any === 'yes' || TMEPOJS.tm_epo_hide_totals_until_all_required === 'yes' || TMEPOJS.tm_epo_hide_totals_until_all === 'yes' ) ) {
3248			// Hide cart button until an element is chosen
3249			if ( TMEPOJS.tm_epo_hide_add_cart_button === 'yes' ) {
3250				showHideCart = one_option_is_selected;
3251			}
3252
3253			// Hide Final total box until an element is chosen
3254			if ( TMEPOJS.tm_epo_hide_totals_until_any === 'yes' ) {
3255				showHideTotal = one_option_is_selected;
3256			}
3257
3258			// Hide until all required elements are chosen
3259			if ( TMEPOJS.tm_epo_hide_required_add_cart_button === 'yes' || TMEPOJS.tm_epo_hide_totals_until_all_required === 'yes' ) {
3260				epos = currentEpoObject.this_epo_container.find( '.cpf-element' ).not( '.cpf-type-variations' ).filter( '.tc-container-enabled.tc-is-required' );
3261				allElementsAreSelected = epos.toArray().every( function( element ) {
3262					var elementToCheck = '';
3263					var _class;
3264					var noSplit = false;
3265					var radio_checked;
3266					var checkbox_checked;
3267					var val;
3268
3269					element = $( element );
3270					if ( element.is( '.cpf-type-product' ) ) {
3271						elementToCheck = ':not(.tc-extra-product-options-inline .tm-epo-field)';
3272					}
3273					_class = element
3274						.attr( 'class' )
3275						.split( ' ' )
3276						.map( function( cls ) {
3277							if ( cls.indexOf( 'cpf-type-', 0 ) !== -1 ) {
3278								return cls;
3279							}
3280							return null;
3281						} )
3282						.filter( function( v ) {
3283							if ( v !== null && v !== undefined ) {
3284								return v;
3285							}
3286							return null;
3287						} );
3288
3289					if ( _class.length > 0 ) {
3290						_class = _class[ 0 ];
3291						if ( _class === 'cpf-type-product' ) {
3292							noSplit = true;
3293							if ( element.is( '.cpf-type-product-mode-product' ) || element.is( '.cpf-type-product-checkbox' ) || element.is( '.cpf-type-product-thumbnailmultiple' ) ) {
3294								_class = 'cpf-type-checkbox';
3295							} else if ( element.is( '.cpf-type-product-dropdown' ) ) {
3296								_class = 'cpf-type-select';
3297							} else {
3298								_class = 'cpf-type-radio';
3299							}
3300						}
3301						switch ( _class ) {
3302							case 'cpf-type-radio':
3303								radio_checked = element.find( 'input.tm-epo-field.tmcp-radio:checked' + elementToCheck );
3304								return radio_checked.length > 0;
3305
3306							case 'cpf-type-checkbox':
3307								checkbox_checked = element.find( 'input.tm-epo-field.tmcp-checkbox:checked' + elementToCheck );
3308								return checkbox_checked.length > 0;
3309
3310							case 'cpf-type-select':
3311								val = element.find( 'select.tm-epo-field.tmcp-select' + elementToCheck ).val();
3312								if ( val && ! noSplit ) {
3313									val = val.slice( 0, val.lastIndexOf( '_' ) );
3314								}
3315								break;
3316
3317							case 'cpf-type-selectmultiple':
3318								val = element.find( 'select.tm-epo-field.tmcp-selectmultiple' + elementToCheck ).val();
3319								if ( val && ! noSplit ) {
3320									val.forEach( function( option, i ) {
3321										val[ i ] = option.slice( 0, option.lastIndexOf( '_' ) );
3322									} );
3323								}
3324								break;
3325
3326							default:
3327								val = element.find( '.tm-epo-field' + elementToCheck ).val();
3328								break;
3329						}
3330						if ( Array.isArray( val ) ) {
3331							return val.some( function( item ) {
3332								return item !== '';
3333							} );
3334						}
3335						return val !== '';
3336					}
3337					return false;
3338				} );
3339				if ( TMEPOJS.tm_epo_hide_required_add_cart_button === 'yes' ) {
3340					showHideCart = allElementsAreSelected;
3341				}
3342				if ( TMEPOJS.tm_epo_hide_totals_until_all_required === 'yes' ) {
3343					showHideTotal = allElementsAreSelected;
3344				}
3345			}
3346
3347			// Hide until all elements are chosen
3348			if ( TMEPOJS.tm_epo_hide_all_add_cart_button === 'yes' || TMEPOJS.tm_epo_hide_totals_until_all === 'yes' ) {
3349				epos = currentEpoObject.this_epo_container.find( '.cpf-element' ).not( '.cpf-type-variations' ).filter( '.tc-container-enabled' );
3350				allElementsAreSelected = epos.toArray().every( function( element ) {
3351					var elementToCheck = '';
3352					var _class;
3353					var noSplit = false;
3354					var radio_checked;
3355					var checkbox_checked;
3356					var val;
3357
3358					element = $( element );
3359					if ( element.is( '.cpf-type-product' ) ) {
3360						elementToCheck = ':not(.tc-extra-product-options-inline .tm-epo-field)';
3361					}
3362					_class = element
3363						.attr( 'class' )
3364						.split( ' ' )
3365						.map( function( cls ) {
3366							if ( cls.indexOf( 'cpf-type-', 0 ) !== -1 ) {
3367								return cls;
3368							}
3369							return null;
3370						} )
3371						.filter( function( v ) {
3372							if ( v !== null && v !== undefined ) {
3373								return v;
3374							}
3375							return null;
3376						} );
3377
3378					if ( _class.length > 0 ) {
3379						_class = _class[ 0 ];
3380						if ( _class === 'cpf-type-product' ) {
3381							noSplit = true;
3382							if ( element.is( '.cpf-type-product-mode-product' ) || element.is( '.cpf-type-product-checkbox' ) || element.is( '.cpf-type-product-thumbnailmultiple' ) ) {
3383								_class = 'cpf-type-checkbox';
3384							} else if ( element.is( '.cpf-type-product-dropdown' ) ) {
3385								_class = 'cpf-type-select';
3386							} else {
3387								_class = 'cpf-type-radio';
3388							}
3389						}
3390						switch ( _class ) {
3391							case 'cpf-type-radio':
3392								radio_checked = element.find( 'input.tm-epo-field.tmcp-radio:checked' + elementToCheck );
3393								return radio_checked.length > 0;
3394
3395							case 'cpf-type-checkbox':
3396								checkbox_checked = element.find( 'input.tm-epo-field.tmcp-checkbox:checked' + elementToCheck );
3397								return checkbox_checked.length > 0;
3398
3399							case 'cpf-type-select':
3400								val = element.find( 'select.tm-epo-field.tmcp-select' + elementToCheck ).val();
3401								if ( val && ! noSplit ) {
3402									val = val.slice( 0, val.lastIndexOf( '_' ) );
3403								}
3404								break;
3405
3406							case 'cpf-type-selectmultiple':
3407								val = element.find( 'select.tm-epo-field.tmcp-selectmultiple' + elementToCheck ).val();
3408								if ( val && ! noSplit ) {
3409									val.forEach( function( option, i ) {
3410										val[ i ] = option.slice( 0, option.lastIndexOf( '_' ) );
3411									} );
3412								}
3413								break;
3414
3415							default:
3416								val = element.find( '.tm-epo-field' + elementToCheck ).val();
3417								break;
3418						}
3419						if ( Array.isArray( val ) ) {
3420							return val.some( function( item ) {
3421								return item !== '';
3422							} );
3423						}
3424						return val !== '';
3425					}
3426					return false;
3427				} );
3428				if ( TMEPOJS.tm_epo_hide_all_add_cart_button === 'yes' ) {
3429					showHideCart = allElementsAreSelected;
3430				}
3431				if ( TMEPOJS.tm_epo_hide_totals_until_all === 'yes' ) {
3432					showHideTotal = allElementsAreSelected;
3433				}
3434			}
3435
3436			currentEpoObject.showHideCart = showHideCart;
3437			currentEpoObject.showHideTotal = showHideTotal;
3438			$.tcepo.showHideTotal[ epoEventId ] = showHideTotal;
3439		}
3440
3441		return currentEpoObject;
3442	}
3443
3444	function goto_error_item( item, epoEventId ) {
3445		var el = $.tcepo.errorObject[ epoEventId ] || item;
3446		var elsection;
3447		var elsectionlink;
3448		var cpfElement;
3449		var pos;
3450
3451		if ( el ) {
3452			if ( TMEPOJS.tm_epo_disable_error_scroll !== 'yes' ) {
3453				elsection = el.closest( '.cpf-section' );
3454				elsectionlink = elsection.find( '.tm-section-link' );
3455				cpfElement = el.closest( '.cpf-element' );
3456
3457				if ( elsection.find( '.tm-toggle' ).length ) {
3458					elsection.find( '.tm-toggle' ).trigger( 'openwrap.tmtoggle' );
3459				}
3460				if ( window.tc_validation_offset === undefined ) {
3461					window.tc_validation_offset = -100;
3462				}
3463				if ( elsection.is( '.section_popup' ) ) {
3464					errorContainer.tcScrollTo( elsectionlink, 300, window.tc_validation_offset );
3465					elsectionlink.trigger( 'click.tmsectionpoplink' );
3466				} else if ( elsection.is( '.tm-owl-slider-section' ) ) {
3467					pos = el.closest( '.owl-item' ).index();
3468					elsection.find( '.tcowl-carousel' ).trigger( 'to.owl.carousel', [ pos, 100 ] );
3469					setTimeout( function() {
3470						elsection.find( '.tcowl-carousel' ).trigger( 'refresh.owl.carousel' );
3471
3472						if ( cpfElement.length > 0 ) {
3473							errorContainer.tcScrollTo( cpfElement, 300, window.tc_validation_offset );
3474						}
3475					}, 200 );
3476				} else if ( elsection.is( '.tc-tabs-section' ) ) {
3477					pos = el.closest( '.tc-tab-slide' ).index();
3478					el.closest( '.tc-tabs' ).find( '.tc-tab-headers .tc-tab-header .tab-header[data-id="tc-tab-slide' + pos + '"]' ).trigger( 'click.tmtabs' );
3479					setTimeout( function() {
3480						if ( cpfElement.length > 0 ) {
3481							errorContainer.tcScrollTo( cpfElement, 300, window.tc_validation_offset );
3482						}
3483					}, 200 );
3484				} else if ( cpfElement.length > 0 ) {
3485					errorContainer.tcScrollTo( cpfElement, 300, window.tc_validation_offset );
3486				}
3487			}
3488
3489			if ( ! item ) {
3490				$.tcepo.errorObject[ epoEventId ] = false;
3491			}
3492		}
3493	}
3494
3495	function tm_limit_c_selection( field, prevent ) {
3496		var allowed = parseInt( field.attr( 'data-limit' ), 10 );
3497		var checked = false;
3498		var val;
3499		var t;
3500		var q;
3501
3502		if ( allowed > 0 ) {
3503			checked = 0;
3504			field
3505				.closest( '.tm-extra-product-options-checkbox' )
3506				.find( "input.tm-epo-field[type='checkbox']:checked" )
3507				.each( function() {
3508					t = $( this );
3509					q = t.closest( 'li.tmcp-field-wrap' ).find( 'input.tm-qty' );
3510					if ( q.length > 0 ) {
3511						val = parseInt( q.val(), 10 );
3512						if ( val <= 0 ) {
3513							val = 1;
3514						}
3515						checked = parseInt( checked, 10 ) + val;
3516					} else {
3517						checked = parseInt( checked, 10 ) + 1;
3518					}
3519				} );
3520			if ( checked > allowed ) {
3521				if ( prevent ) {
3522					field.prop( 'checked', '' ).trigger( 'change' );
3523				}
3524				return false;
3525			}
3526		}
3527		return true;
3528	}
3529
3530	function tm_exact_c_selection( field, prevent ) {
3531		var allowed = parseInt( field.attr( 'data-exactlimit' ), 10 );
3532		var checked = false;
3533		var val;
3534		var t;
3535		var q;
3536
3537		if ( allowed > 0 ) {
3538			checked = 0;
3539			field
3540				.closest( '.tm-extra-product-options-checkbox' )
3541				.find( "input.tm-epo-field[type='checkbox']:checked" )
3542				.each( function() {
3543					t = $( this );
3544					q = t.closest( 'li.tmcp-field-wrap' ).find( 'input.tm-qty' );
3545					if ( q.length > 0 ) {
3546						val = parseInt( q.val(), 10 );
3547						if ( val <= 0 ) {
3548							val = 1;
3549						}
3550						checked = parseInt( checked, 10 ) + val;
3551					} else {
3552						checked = parseInt( checked, 10 ) + 1;
3553					}
3554				} );
3555			if ( checked > allowed ) {
3556				if ( prevent ) {
3557					field.prop( 'checked', '' ).trigger( 'change' );
3558				}
3559				return false;
3560			}
3561		}
3562		return true;
3563	}
3564
3565	function tm_limit_cont( fields, main_product, epoEventId ) {
3566		var checkall = true;
3567		var first_error_obj = false;
3568		var limit;
3569		var eln;
3570		var checked;
3571		var t;
3572		var val;
3573		var q;
3574		var ew;
3575		var em;
3576		var message;
3577		var field;
3578
3579		fields.each( function() {
3580			field = $( this );
3581			limit = field.find( "[type='checkbox'][data-limit]" );
3582			if ( limit.length && field_is_active( limit ) ) {
3583				eln = parseInt( limit.attr( 'data-limit' ), 10 );
3584				checked = 0;
3585				field.find( "input.tm-epo-field[type='checkbox']:checked" ).each( function() {
3586					t = $( this );
3587					q = t.closest( 'li.tmcp-field-wrap' ).find( 'input.tm-qty' );
3588					if ( q.length > 0 ) {
3589						val = parseInt( q.val(), 10 );
3590						if ( val <= 0 ) {
3591							val = 1;
3592						}
3593						checked = parseInt( checked, 10 ) + val;
3594					} else {
3595						checked = parseInt( checked, 10 ) + 1;
3596					}
3597				} );
3598				ew = field.closest( '.cpf-element' );
3599				em = ew.find( 'div.tm-error-min' );
3600
3601				if ( eln < checked ) {
3602					checkall = false;
3603					first_error_obj = field;
3604					if ( eln === 1 ) {
3605						message = TMEPOJS.tm_epo_global_validator_messages.epolimitsingle.replace( '{0}', eln );
3606					} else {
3607						message = TMEPOJS.tm_epo_global_validator_messages.epolimit.replace( '{0}', eln );
3608					}
3609					if ( em.length ) {
3610						em.remove();
3611					}
3612					if ( TMEPOJS.tm_epo_global_error_label_placement === 'before' ) {
3613						field.closest( '.tc-element-container' ).before( '<div class="tm-error-min tm-error tc-cell tcwidth tcwidth-100">' + message + '</div>' );
3614					} else {
3615						field.closest( '.tc-element-container' ).after( '<div class="tm-error-min tm-error tc-cell tcwidth tcwidth-100">' + message + '</div>' );
3616					}
3617					main_product.find( tcAPI.addToCartButtonSelector ).first().removeClass( 'disabled loading fpd-disabled' ).prop( 'disabled', false );
3618				} else {
3619					em.remove();
3620				}
3621			}
3622		} );
3623		if ( first_error_obj ) {
3624			$.tcepo.errorObject[ epoEventId ] = first_error_obj;
3625		}
3626		return checkall;
3627	}
3628
3629	function tm_check_limit_cont( limit_cont, main_product, epoEventId ) {
3630		$.tcepo.formSubmitEvents[ epoEventId ][ $.tcepo.formSubmitEvents[ epoEventId ].length ] = {
3631			trigger: function() {
3632				return tm_limit_cont( limit_cont, main_product, epoEventId );
3633			},
3634			on_true: function() {
3635				return true;
3636			},
3637			on_false: function() {
3638				goto_error_item( $( limit_cont ).find( '.tm-epo-field' ).first(), epoEventId );
3639				return true;
3640			}
3641		};
3642	}
3643
3644	function tm_exactlimit_cont( fields, main_product, epoEventId ) {
3645		var checkall = true;
3646		var first_error_obj = false;
3647		var exactlimit;
3648		var eln;
3649		var checked;
3650		var t;
3651		var val;
3652		var q;
3653		var ew;
3654		var em;
3655		var message;
3656		var field;
3657
3658		fields.each( function() {
3659			field = $( this );
3660			exactlimit = field.find( "[type='checkbox'][data-exactlimit]" );
3661			if ( exactlimit.length && field_is_active( exactlimit ) ) {
3662				eln = parseInt( exactlimit.attr( 'data-exactlimit' ), 10 );
3663				checked = 0;
3664				field.find( "input.tm-epo-field[type='checkbox']:checked" ).each( function() {
3665					t = $( this );
3666					q = t.closest( 'li.tmcp-field-wrap' ).find( 'input.tm-qty' );
3667					if ( q.length > 0 ) {
3668						val = parseInt( q.val(), 10 );
3669						if ( val <= 0 ) {
3670							val = 1;
3671						}
3672						checked = parseInt( checked, 10 ) + val;
3673					} else {
3674						checked = parseInt( checked, 10 ) + 1;
3675					}
3676				} );
3677				ew = field.closest( '.cpf-element' );
3678				em = ew.find( 'div.tm-error-min' );
3679
3680				if ( eln !== checked ) {
3681					checkall = false;
3682					first_error_obj = field;
3683					if ( eln === 1 ) {
3684						message = TMEPOJS.tm_epo_global_validator_messages.epoexactsingle.replace( '{0}', eln );
3685					} else {
3686						message = TMEPOJS.tm_epo_global_validator_messages.epoexact.replace( '{0}', eln );
3687					}
3688					if ( em.length ) {
3689						em.remove();
3690					}
3691					if ( TMEPOJS.tm_epo_global_error_label_placement === 'before' ) {
3692						field.closest( '.tc-element-container' ).before( '<div class="tm-error-min tm-error tc-cell tcwidth tcwidth-100">' + message + '</div>' );
3693					} else {
3694						field.closest( '.tc-element-container' ).after( '<div class="tm-error-min tm-error tc-cell tcwidth tcwidth-100">' + message + '</div>' );
3695					}
3696					main_product.find( tcAPI.addToCartButtonSelector ).first().removeClass( 'disabled loading fpd-disabled' ).prop( 'disabled', false );
3697				} else {
3698					em.remove();
3699				}
3700			}
3701		} );
3702		if ( first_error_obj ) {
3703			$.tcepo.errorObject[ epoEventId ] = first_error_obj;
3704		}
3705		return checkall;
3706	}
3707
3708	function tm_check_exactlimit_cont( exactlimit_cont, main_product, epoEventId ) {
3709		$.tcepo.formSubmitEvents[ epoEventId ][ $.tcepo.formSubmitEvents[ epoEventId ].length ] = {
3710			trigger: function() {
3711				return tm_exactlimit_cont( exactlimit_cont, main_product, epoEventId );
3712			},
3713			on_true: function() {
3714				return true;
3715			},
3716			on_false: function() {
3717				goto_error_item( $( exactlimit_cont ).find( '.tm-epo-field' ).first(), epoEventId );
3718				return true;
3719			}
3720		};
3721	}
3722
3723	function tm_minimumlimit_cont( fields, epoEventId ) {
3724		var checkall = true;
3725		var first_error_obj = false;
3726		var eln;
3727		var checked;
3728		var t;
3729		var val;
3730		var q;
3731		var ew;
3732		var em;
3733		var message;
3734		var field;
3735
3736		fields.each( function() {
3737			var minimumlimit;
3738
3739			field = $( this );
3740			minimumlimit = field.find( "[type='checkbox'][data-minimumlimit]" );
3741
3742			if ( minimumlimit.length && field_is_active( minimumlimit ) ) {
3743				eln = parseInt( minimumlimit.attr( 'data-minimumlimit' ), 10 );
3744				checked = 0;
3745				field.find( "input.tm-epo-field[type='checkbox']:checked" ).each( function() {
3746					t = $( this );
3747					q = t.closest( 'li.tmcp-field-wrap' ).find( 'input.tm-qty' );
3748					if ( q.length > 0 ) {
3749						val = parseInt( q.val(), 10 );
3750						if ( val <= 0 ) {
3751							val = 1;
3752						}
3753						checked = parseInt( checked, 10 ) + val;
3754					} else {
3755						checked = parseInt( checked, 10 ) + 1;
3756					}
3757				} );
3758				ew = field.closest( '.cpf-element' );
3759				em = ew.find( 'div.tm-error-min' );
3760				if ( eln > checked ) {
3761					checkall = false;
3762					first_error_obj = field;
3763					if ( eln === 1 ) {
3764						message = TMEPOJS.tm_epo_global_validator_messages.epominsingle.replace( '{0}', eln );
3765					} else {
3766						message = TMEPOJS.tm_epo_global_validator_messages.epomin.replace( '{0}', eln );
3767					}
3768					if ( em.length ) {
3769						em.remove();
3770					}
3771					if ( TMEPOJS.tm_epo_global_error_label_placement === 'before' ) {
3772						field.closest( '.tc-element-container' ).before( '<div class="tm-error-min tm-error tc-cell tcwidth tcwidth-100">' + message + '</div>' );
3773					} else {
3774						field.closest( '.tc-element-container' ).after( '<div class="tm-error-min tm-error tc-cell tcwidth tcwidth-100">' + message + '</div>' );
3775					}
3776				} else {
3777					em.remove();
3778				}
3779			}
3780		} );
3781
3782		if ( first_error_obj ) {
3783			$.tcepo.errorObject[ epoEventId ] = first_error_obj;
3784		}
3785
3786		return checkall;
3787	}
3788
3789	function tm_check_minimumlimit_cont( minimumlimit_cont, epoEventId ) {
3790		$.tcepo.formSubmitEvents[ epoEventId ][ $.tcepo.formSubmitEvents[ epoEventId ].length ] = {
3791			trigger: function() {
3792				return tm_minimumlimit_cont( minimumlimit_cont, epoEventId );
3793			},
3794			on_true: function() {
3795				return true;
3796			},
3797			on_false: function() {
3798				goto_error_item( false, epoEventId );
3799				return true;
3800			}
3801		};
3802	}
3803
3804	function cleanPrice( price ) {
3805		if ( price === null ) {
3806			return 0;
3807		}
3808
3809		if ( typeof price === 'object' ) {
3810			price = price[ 0 ];
3811		}
3812
3813		if ( ! Number.isFinite( parseFloat( price ) ) ) {
3814			price = 0;
3815		}
3816
3817		return price;
3818	}
3819
3820	function tm_apply_dpd( price, totals, apply, force ) {
3821		price = cleanPrice( price );
3822
3823		if ( apply ) {
3824			price = $.epoAPI.applyFilter( 'tc_apply_dpd', price, totals, apply, force );
3825		}
3826
3827		return price;
3828	}
3829
3830	function tm_calculate_product_regular_price( totals, allowfalse ) {
3831		var price = 0;
3832
3833		if ( totals.length > 0 ) {
3834			price = totals.data( 'regular-price' );
3835		}
3836
3837		price = $.epoAPI.applyFilter( 'tc_calculate_product_regular_price', price, totals );
3838
3839		if ( allowfalse && price === false ) {
3840			return false;
3841		}
3842		price = parseFloat( price );
3843
3844		if ( ! Number.isFinite( price ) ) {
3845			price = 0;
3846		}
3847
3848		return price;
3849	}
3850
3851	function tm_calculate_product_price( totals, allowfalse ) {
3852		var price = 0;
3853
3854		if ( totals.length > 0 ) {
3855			price = totals.data( 'price' );
3856		}
3857
3858		price = $.epoAPI.applyFilter( 'tc_calculate_product_price', price, totals );
3859
3860		if ( allowfalse && price === false ) {
3861			return false;
3862		}
3863		price = parseFloat( price );
3864
3865		if ( ! Number.isFinite( price ) ) {
3866			price = 0;
3867		}
3868
3869		return price;
3870	}
3871
3872	function calculateMathPrice( price, thisElement, epoObject, noevents, useOriginalPrice, funcTotal, cumulativeTotal, mathskip ) {
3873		var formula = price.toString();
3874		var val = 0;
3875		var matches;
3876		var match;
3877		var elementWrap;
3878		var element;
3879		var reg;
3880		var elementPrice = 0;
3881		var pos;
3882		var type;
3883		var id;
3884		var thisVal;
3885		var thisValForced;
3886		var thisElementId = thisElement.closest( '.cpf-element' ).attr( 'data-uniqid' );
3887		var thisElementWrap = thisElement.closest( '.tmcp-ul-wrap' );
3888		var totalsHolder_tc_totals_ob = epoObject.this_epo_totals_container.data( 'totalsHolder_tc_totals_ob' );
3889		var thisElementIndex = thisElementWrap.find( '.tmcp-field, .tmcp-fee-field, .tmcp-sub-fee-field' ).filter( ':checked' ).index( thisElement );
3890		var thisElementIndexForced = thisElementWrap.find( '.tmcp-field, .tmcp-fee-field, .tmcp-sub-fee-field' ).index( thisElement );
3891		var this_epo_container = epoObject.is_associated ? epoObject.this_epo_container : epoObject.this_epo_container.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector );
3892		var constants = $.epoAPI.util.parseJSON( TMEPOJS.tm_epo_math ) || {};
3893		var productPrice;
3894		var dynamicProductPrice;
3895		var __price;
3896		var __price_type;
3897
3898		if ( thisElementIndex === -1 && ! thisElement.is( '.tmcp-checkbox, .tmcp-radio' ) ) {
3899			thisElementIndex = 0;
3900		}
3901		if ( thisElementIndexForced === -1 && ! thisElement.is( '.tmcp-checkbox, .tmcp-radio' ) ) {
3902			thisElementIndexForced = 0;
3903		}
3904
3905		if ( ! thisElement.is( '.tcdisabled' ) && ! noevents && ! thisElement.data( 'addedtcEpoBeforeOptionPriceCalculation' ) ) {
3906			jWindow.on( 'tcEpoBeforeOptionPriceCalculation.math' + thisElementId, function() {
3907				tm_element_epo_rules( epoObject, thisElement, undefined, undefined, undefined, true );
3908			} );
3909			jWindow.on( 'tcEpoAfterNormalOptionPriceCalculation.math' + thisElementId, function() {
3910				thisElement.data( 'fetchOptionPrices', false );
3911				thisElement.data( 'fetchOptionPrices-forced', false );
3912				thisElement.data( 'fetchOptionPrices-fee', false );
3913				thisElement.data( 'fetchOptionPrices-fee-forced', false );
3914				thisElement.data( 'fetchOptionPrices-sub-fee', false );
3915				thisElement.data( 'fetchOptionPrices-sub-fee-forced', false );
3916			} );
3917			thisElement.data( 'addedtcEpoBeforeOptionPriceCalculation', 1 );
3918		}
3919
3920		if ( thisElement.is( '.tmcp-field' ) ) {
3921			if ( thisElement.data( 'fetchOptionPrices' ) ) {
3922				thisVal = thisElement.data( 'fetchOptionPrices' );
3923				thisValForced = thisElement.data( 'fetchOptionPrices-forced' );
3924			} else {
3925				thisVal = fetchOptionPrices( epoObject, thisElementWrap, '.tmcp-field', 0, 0, [], true );
3926				thisValForced = fetchOptionPrices( epoObject, thisElementWrap, '.tmcp-field', 0, 0, [], true, true );
3927				thisElement.data( 'fetchOptionPrices', thisVal );
3928				thisElement.data( 'fetchOptionPrices-forced', thisValForced );
3929			}
3930		} else if ( thisElement.is( '.tmcp-fee-field' ) ) {
3931			if ( thisElement.data( 'fetchOptionPrices-fee' ) ) {
3932				thisVal = thisElement.data( 'fetchOptionPrices-fee' );
3933				thisValForced = thisElement.data( 'fetchOptionPrices-fee-forced' );
3934			} else {
3935				thisVal = fetchOptionPrices( epoObject, thisElementWrap, '.tmcp-fee-field', 0, 0, [], true );
3936				thisValForced = fetchOptionPrices( epoObject, thisElementWrap, '.tmcp-fee-field', 0, 0, [], true, true );
3937				thisElement.data( 'fetchOptionPrices-fee', thisVal );
3938				thisElement.data( 'fetchOptionPrices-fee-forced', thisValForced );
3939			}
3940		} else if ( thisElement.is( '.tmcp-sub-fee-field' ) ) {
3941			if ( thisElement.data( 'fetchOptionPrices-sub-fee' ) ) {
3942				thisVal = thisElement.data( 'fetchOptionPrices-sub-fee' );
3943				thisValForced = thisElement.data( 'fetchOptionPrices-sub-fee-forced' );
3944			} else {
3945				thisVal = fetchOptionPrices( epoObject, thisElementWrap, '.tmcp-sub-fee-field', 0, 0, [], true );
3946				thisValForced = fetchOptionPrices( epoObject, thisElementWrap, '.tmcp-sub-fee-field', 0, 0, [], true, true );
3947				thisElement.data( 'fetchOptionPrices-sub-fee', thisVal );
3948				thisElement.data( 'fetchOptionPrices-sub-fee-forced', thisValForced );
3949			}
3950		}
3951
3952		Object.keys( constants ).forEach( function( key ) {
3953			var name;
3954			var value;
3955
3956			if ( constants[ key ].name !== '' && constants[ key ].value !== '' ) {
3957				name = constants[ key ].name;
3958				value = constants[ key ].value;
3959				if ( constants[ key ].name.isNumeric() ) {
3960					formula = formula.replace( '{' + name + '}', value );
3961				} else {
3962					name = new RegExp( '{' + name + '}', 'g' );
3963					if ( value.startsWith( '{' ) ) {
3964						formula = formula.replace( name, value );
3965					} else {
3966						formula = formula.replace( name, $.epoAPI.math.unformat( value.replace( ',', '.' ) ) );
3967					}
3968				}
3969			}
3970		} );
3971
3972		if ( totalsHolder_tc_totals_ob !== undefined ) {
3973			// product quantity
3974			formula = formula.replace( /{quantity}/g, $.epoAPI.math.unformat( totalsHolder_tc_totals_ob.qty ) );
3975			// original product price
3976			if ( useOriginalPrice && totalsHolder_tc_totals_ob.original_product_price !== undefined ) {
3977				productPrice = $.epoAPI.math.unformat( totalsHolder_tc_totals_ob.original_product_price );
3978			} else {
3979				productPrice = $.epoAPI.math.unformat( totalsHolder_tc_totals_ob.product_price );
3980			}
3981			if ( totalsHolder_tc_totals_ob.dynamic_product_price !== undefined ) {
3982				dynamicProductPrice = $.epoAPI.math.unformat( totalsHolder_tc_totals_ob.dynamic_product_price );
3983			} else {
3984				dynamicProductPrice = 0;
3985			}
3986		} else {
3987			// product quantity
3988			formula = formula.replace( /{quantity}/g, 0 );
3989			// original product price
3990			productPrice = 0;
3991			dynamicProductPrice = 0;
3992		}
3993
3994		productPrice = $.epoAPI.math.toFloat( productPrice );
3995
3996		formula = formula.replace( /{product_price}/g, productPrice );
3997		formula = formula.replace( /{dynamic_product_price}/g, dynamicProductPrice );
3998
3999		if ( ! funcTotal ) {
4000			funcTotal = 0;
4001		}
4002		funcTotal = $.epoAPI.math.toFloat( funcTotal );
4003
4004		formula = formula.replace( /{options_total}/g, funcTotal );
4005		formula = formula.replace( /{product_price_plus_options_total}/g, productPrice + funcTotal );
4006		formula = formula.replace( /{cumulative_total}/g, cumulativeTotal );
4007		formula = formula.replace( /{product_price_plus_cumulative_total}/g, productPrice + cumulativeTotal );
4008
4009		if ( thisValForced.floatingBoxData !== undefined && thisValForced.floatingBoxData[ thisElementIndexForced ] !== undefined ) {
4010			// the option/element value to float
4011			if ( thisValForced.floatingBoxData[ thisElementIndexForced ].input_type === 'number' || thisValForced.floatingBoxData[ thisElementIndexForced ].input_type === 'hidden' ) {
4012				formula = formula
4013					.replace( /{this.value}/g, $.epoAPI.math.toFloat( $.epoAPI.math.unformat( thisValForced.floatingBoxData[ thisElementIndexForced ].valueText ) ) );
4014			} else {
4015				formula = formula
4016					.replace( /{this.value}/g, $.epoAPI.math.toFloat( $.epoAPI.math.unformat( thisValForced.floatingBoxData[ thisElementIndexForced ].valueText, tcAPI.localDecimalSeparator ) ) );
4017			}
4018			// the option/element raw value
4019			if ( thisValForced.floatingBoxData[ thisElementIndexForced ].input_type === 'number' || thisValForced.floatingBoxData[ thisElementIndexForced ].input_type === 'hidden' ) {
4020				formula = formula
4021					.replace( /{this.rawvalue}/g, $.epoAPI.math.unformat( thisValForced.floatingBoxData[ thisElementIndexForced ].valueText ) );
4022			} else {
4023				formula = formula
4024					.replace( /{this.rawvalue}/g, $.epoAPI.math.unformat( thisValForced.floatingBoxData[ thisElementIndexForced ].valueText, tcAPI.localDecimalSeparator ) );
4025			}
4026			// the option/element raw value
4027			if ( thisValForced.floatingBoxData[ thisElementIndexForced ].input_type === 'number' || thisValForced.floatingBoxData[ thisElementIndexForced ].input_type === 'hidden' ) {
4028				formula = formula
4029					.replace( /{this.text}/g, $.epoAPI.math.unformat( thisValForced.floatingBoxData[ thisElementIndexForced ].valueText ) );
4030			} else {
4031				formula = formula
4032					.replace( /{this.text}/g, $.epoAPI.math.unformat( thisValForced.floatingBoxData[ thisElementIndexForced ].valueText, tcAPI.localDecimalSeparator ) );
4033			}
4034			// the option/element value length
4035			formula = formula
4036				.replace( /{this.value.length}/g, thisValForced.floatingBoxData[ thisElementIndexForced ].valueText.length );
4037		} else {
4038			formula = formula
4039				// the option/element value to float
4040				.replace( /{this.value}/g, 0 )
4041				// the option/element raw value
4042				.replace( /{this.rawvalue}/g, '' )
4043				// the option/element raw value
4044				.replace( /{this.text}/g, '' )
4045				// the option/element value length
4046				.replace( /{this.value.length}/g, 0 );
4047		}
4048
4049		formula = formula
4050			// the number of options the user has selected
4051			.replace( /{this.count}/g, thisVal.floatingBoxData.length )
4052			// the total option quantity of this element
4053			.replace(
4054				/{this.count.quantity}/g,
4055				thisVal.floatingBoxData
4056					.map( function( x ) {
4057						return x.quantity;
4058					} )
4059					.reduce( function( acc, thisval ) {
4060						return $.epoAPI.math.toFloat( acc ) + $.epoAPI.math.toFloat( thisval );
4061					}, 0 )
4062			)
4063			// the option quantity of this element
4064			.replace( /{this.quantity}/g, thisElement.data( 'tm-quantity' ) );
4065
4066		if ( formula.match( /\{(\s)*?field\.([^}]*)}/ ) ) {
4067			matches = formula.match( /\{(\s)*?field\.([^}]*)}/g );
4068			matches.forEach( function( field ) {
4069				match = field.match( /\{(\s)*?field\.([^}]*)}/ );
4070				if ( undefined !== match[ 2 ] && 'string' === typeof match[ 2 ] ) {
4071					pos = match[ 2 ].indexOf( '.', match[ 2 ].indexOf( '.' ) + 1 );
4072					if ( pos !== -1 ) {
4073						id = match[ 2 ].substring( 0, pos );
4074						type = match[ 2 ].substring( pos + 1 );
4075
4076						if ( $.inArray( type, [ 'price', 'value', 'value.length', 'rawvalue', 'text', 'text.length', 'quantity', 'count', 'count.quantity' ] ) !== -1 ) {
4077							elementWrap = this_epo_container.find( "[data-uniqid='" + $.epoAPI.util.escapeSelector( id ) + "']" );
4078							if ( elementWrap.length ) {
4079								element = elementWrap.find( '.tmcp-field, .tmcp-fee-field, .tmcp-sub-fee-field' );
4080								element = element.first();
4081
4082								if ( ! thisElement.is( '.tcdisabled' ) && ! noevents && ! thisElement.data( 'addedfieldtcEpoBeforeOptionPriceCalculation' ) ) {
4083									jWindow.on( 'tcEpoBeforeOptionPriceCalculation.math' + thisElementId, function() {
4084										tm_element_epo_rules( epoObject, thisElement, undefined, undefined, undefined, true );
4085										thisElement.trigger( 'tm-math-select-change-html-all' );
4086									} );
4087									thisElement.data( 'addedfieldtcEpoBeforeOptionPriceCalculation', 1 );
4088								}
4089								val = 0;
4090								switch ( type ) {
4091									case 'text':
4092									case 'rawvalue':
4093										val = '';
4094										break;
4095								}
4096
4097								if ( elementWrap.is( '.tc-container-enabled' ) ) {
4098									if ( ! mathskip && thisElement.attr( 'id' ) !== element.attr( 'id' ) ) {
4099										tm_element_epo_rules( epoObject, element, undefined, undefined, undefined, true, undefined, undefined, true );
4100									}
4101									if ( element.is( '.tmcp-field' ) ) {
4102										val = fetchOptionPrices( epoObject, elementWrap, '.tmcp-field', 0, 0, [], true, undefined, undefined, true );
4103									} else if ( element.is( '.tmcp-fee-field' ) ) {
4104										val = fetchOptionPrices( epoObject, elementWrap, '.tmcp-fee-field', 0, 0, [], true, undefined, undefined, true );
4105									} else if ( element.is( '.tmcp-sub-fee-field' ) ) {
4106										val = fetchOptionPrices( epoObject, elementWrap, '.tmcp-sub-fee-field', 0, 0, [], true, undefined, undefined, true );
4107									}
4108
4109									switch ( type ) {
4110										// element price
4111										case 'price':
4112											val = val.total;
4113											if ( thisElement.is( '.tmcp-dynamic' ) ) {
4114												__price = get_type( epoObject, element, 'price' );
4115												__price_type = get_type( epoObject, element, 'price_type' );
4116												if ( 'math' === __price_type && __price.includes( '{dynamic_product_price}' ) ) {
4117													val = 0;
4118												}
4119											}
4120											break;
4121
4122										// element value
4123										case 'value':
4124										case 'text':
4125										case 'rawvalue':
4126											if ( val.floatingBoxData ) {
4127												val = val.floatingBoxData
4128													.map( function( x ) {
4129														if ( x.input_type === 'number' || x.input_type === 'hidden' ) {
4130															if ( type === 'text' || type === 'rawvalue' ) {
4131																return x.valueText;
4132															}
4133															return $.epoAPI.math.unformat( x.valueText );
4134														}
4135														if ( type === 'text' || type === 'rawvalue' ) {
4136															return x.valueText;
4137														}
4138														return $.epoAPI.math.unformat( x.valueText, tcAPI.localInputDecimalSeparator );
4139													} )
4140													.reduce( function( acc, thisval ) {
4141														if ( type === 'text' || type === 'rawvalue' ) {
4142															return acc + thisval;
4143														}
4144														return $.epoAPI.math.toFloat( acc ) + $.epoAPI.math.toFloat( thisval );
4145													}, ( type === 'text' || type === 'rawvalue' ) ? '' : 0 );
4146
4147												if ( type === 'text' || type === 'rawvalue' ) {
4148													if ( val === '' ) {
4149														val = "''";
4150													} else if ( ! val.toString().isNumeric() ) {
4151														val = "'" + val.replace( "'", "\\'" ) + "'";
4152													}
4153												}
4154											}
4155											break;
4156
4157										// element value length
4158										case 'value.length':
4159										case 'text.length':
4160											if ( val.floatingBoxData ) {
4161												val = val.floatingBoxData
4162													.map( function( x ) {
4163														return x.valueText;
4164													} )
4165													.reduce( function( acc, thisval ) {
4166														return $.epoAPI.math.toFloat( acc ) + thisval.length;
4167													}, 0 );
4168											}
4169											break;
4170
4171										// element quantity
4172										// the total option quantity of this element
4173										case 'quantity':
4174										case 'count.quantity':
4175											if ( val.floatingBoxData ) {
4176												val = val.floatingBoxData
4177													.map( function( x ) {
4178														return x.quantity;
4179													} )
4180													.reduce( function( acc, thisval ) {
4181														return $.epoAPI.math.toFloat( acc ) + $.epoAPI.math.toFloat( thisval );
4182													}, 0 );
4183											}
4184											break;
4185
4186										// number of element options the user has selected
4187										case 'count':
4188											if ( val.floatingBoxData ) {
4189												val = val.floatingBoxData.length;
4190											}
4191											break;
4192									}
4193									if ( type !== 'text' && type !== 'rawvalue' ) {
4194										val = $.epoAPI.math.toFloat( val );
4195										if ( ! Number.isFinite( val ) ) {
4196											val = 0;
4197										}
4198									}
4199								}
4200							} else {
4201								val = 0;
4202								switch ( type ) {
4203									case 'text':
4204									case 'rawvalue':
4205										val = '';
4206										break;
4207								}
4208							}
4209							reg = new RegExp( match[ 0 ] );
4210							if ( type === 'text' || type === 'rawvalue' ) {
4211								formula = val === '' ? formula.replace( reg, "''" ) : formula.replace( reg, val );
4212							} else {
4213								formula = ! Number.isFinite( val ) ? formula.replace( reg, "'" + val.replace( "'", "\\'" ) + "'" ) : formula.replace( reg, val );
4214							}
4215						}
4216					}
4217				}
4218			} );
4219		}
4220
4221		try {
4222			elementPrice = tcmexp.evaluate( formula );
4223		} catch ( e ) {
4224			elementPrice = 0;
4225		}
4226
4227		return elementPrice;
4228	}
4229
4230	function get_type( epoObject, obj, type ) {
4231		var element = $( obj );
4232		var setter = element;
4233		var cart;
4234		var current_variation;
4235		var rules;
4236		var rulestype;
4237		var _rulestype;
4238		var pricetype;
4239		var variation_id_selector;
4240		var _tmcpulwrap;
4241		var price;
4242		var _rules;
4243
4244		cart = epoObject.main_cart;
4245		variation_id_selector = "input[name^='variation_id']";
4246		if ( cart.find( 'input.variation_id' ).length > 0 ) {
4247			variation_id_selector = 'input.variation_id';
4248		}
4249		current_variation = cart.find( variation_id_selector ).val();
4250		// Get current woocommerce variation
4251		if ( ! current_variation ) {
4252			current_variation = 0;
4253		}
4254
4255		if ( element.is( 'select' ) ) {
4256			setter = element.find( 'option:selected' );
4257		}
4258
4259		rules = $.epoAPI.util.parseJSON( setter.attr( 'data-rules' ) );
4260		rulestype = $.epoAPI.util.parseJSON( setter.attr( 'data-rulestype' ) );
4261
4262		pricetype = '';
4263		if ( typeof rules === 'object' ) {
4264			if ( current_variation in rules ) {
4265				price = rules[ current_variation ];
4266			} else {
4267				_rules = $.epoAPI.util.parseJSON( element.closest( '.tmcp-ul-wrap' ).attr( 'data-rules' ) );
4268
4269				if ( typeof _rules === 'object' ) {
4270					if ( current_variation in _rules ) {
4271						price = _rules[ current_variation ];
4272					} else {
4273						price = rules[ 0 ];
4274					}
4275				} else {
4276					price = rules[ 0 ];
4277				}
4278			}
4279			if ( typeof rulestype === 'object' ) {
4280				if ( current_variation in rulestype ) {
4281					pricetype = rulestype[ current_variation ];
4282				} else {
4283					_rulestype = $.epoAPI.util.parseJSON( element.closest( '.tmcp-ul-wrap' ).attr( 'data-rulestype' ) );
4284					if ( typeof _rulestype === 'object' ) {
4285						if ( current_variation in _rulestype ) {
4286							pricetype = _rulestype[ current_variation ];
4287						} else {
4288							pricetype = rulestype[ 0 ];
4289						}
4290					} else {
4291						pricetype = rulestype[ 0 ];
4292					}
4293				}
4294			} else {
4295				rulestype = $.epoAPI.util.parseJSON( element.closest( '.tmcp-ul-wrap' ).attr( 'data-ulestype' ) );
4296				if ( typeof rulestype === 'object' ) {
4297					if ( current_variation in rulestype ) {
4298						pricetype = rulestype[ current_variation ];
4299					} else {
4300						pricetype = rulestype[ 0 ];
4301					}
4302				}
4303			}
4304		} else {
4305			_tmcpulwrap = element.closest( '.tmcp-ul-wrap' );
4306			rules = $.epoAPI.util.parseJSON( _tmcpulwrap.attr( 'data-rules' ) );
4307
4308			if ( typeof rules === 'object' ) {
4309				if ( current_variation in rules ) {
4310					price = rules[ current_variation ];
4311				} else {
4312					price = rules[ 0 ];
4313				}
4314				if ( typeof rulestype === 'object' ) {
4315					if ( current_variation in rulestype ) {
4316						pricetype = rulestype[ current_variation ];
4317					} else {
4318						_rulestype = $.epoAPI.util.parseJSON( _tmcpulwrap.attr( 'data-rulestype' ) );
4319						if ( typeof _rulestype === 'object' ) {
4320							if ( current_variation in _rulestype ) {
4321								pricetype = _rulestype[ current_variation ];
4322							} else {
4323								pricetype = rulestype[ 0 ];
4324							}
4325						} else {
4326							pricetype = rulestype[ 0 ];
4327						}
4328					}
4329				} else {
4330					rulestype = $.epoAPI.util.parseJSON( _tmcpulwrap.attr( 'data-rulestype' ) );
4331					if ( typeof rulestype === 'object' ) {
4332						if ( current_variation in rulestype ) {
4333							pricetype = rulestype[ current_variation ];
4334						} else {
4335							pricetype = rulestype[ 0 ];
4336						}
4337					}
4338				}
4339			}
4340		}
4341
4342		if ( typeof price === 'object' ) {
4343			price = price[ 0 ];
4344		}
4345
4346		if ( typeof pricetype === 'object' ) {
4347			pricetype = pricetype[ 0 ];
4348		}
4349		if ( element.is( '.tmcp-fee-field' ) ) {
4350			if ( $.inArray( pricetype, [ 'fee', 'stepfee', 'currentstepfee' ] ) !== -1 ) {
4351				pricetype = '';
4352			}
4353		}
4354
4355		if ( type === 'price' ) {
4356			return price;
4357		}
4358
4359		return pricetype;
4360	}
4361
4362	function wordLength( str ) {
4363		var regex = new RegExp( /[\p{L}\d!@#$%^&*()_+=\{[\}\]|\\"':;?/>.<,-]+/, 'gu' );
4364		var m;
4365		var len = 0;
4366
4367		while ( ( m = regex.exec( str ) ) !== null ) {
4368			// This is necessary to avoid infinite loops with zero-width matches
4369			if ( m.index === regex.lastIndex ) {
4370				regex.lastIndex++;
4371			}
4372			len = len + m.length;
4373		}
4374		return len;
4375	}
4376
4377	// Set field price rules
4378	function tm_element_epo_rules( epoObject, obj, args, setter_override, noremove, manthnoevent, funcTotal, cumulativeTotal, mathskip ) {
4379		var element = $( obj );
4380		var setterall = element;
4381		var cart;
4382		var current_variation;
4383		var bundleid;
4384		var epoTotalsContainer;
4385		var apply_dpd;
4386		var product_price;
4387		var product_original_price;
4388		var is_range_field = element.is( '.tmcp-range' );
4389		var rules;
4390		var rulestype;
4391		var original_rules;
4392		var _rules;
4393		var _rulestype;
4394		var _original_rules;
4395		var pricetype;
4396		var price;
4397		var original_price;
4398		var raw_price;
4399		var raw_original_price;
4400		var formatted_price;
4401		var original_formatted_price;
4402		var textlength;
4403		var freechars;
4404		var min_value;
4405		var main_product = epoObject.main_product;
4406		var epoEventId = epoObject.epoEventId;
4407		var variation_id_selector;
4408		var _tmcpulwrap;
4409		var cart_total;
4410		var per_product_pricing = true;
4411		var addedPrice = 0;
4412		var originalAddedPrice = 0;
4413		var undiscounted_raw_price;
4414		var undiscounted_raw_original_price;
4415		var undiscounted_price;
4416		var undiscounted_original_price;
4417		var isFilled;
4418
4419		if ( element.data( 'associated_price_set' ) ) {
4420			return;
4421		}
4422
4423		if ( ! args ) {
4424			cart = epoObject.main_cart;
4425			if ( cart.data( 'per_product_pricing' ) !== undefined ) {
4426				per_product_pricing = cart.data( 'per_product_pricing' );
4427			}
4428			variation_id_selector = "input[name^='variation_id']";
4429			if ( cart.find( 'input.variation_id' ).length > 0 ) {
4430				variation_id_selector = 'input.variation_id';
4431			}
4432			current_variation = cart.find( variation_id_selector ).val();
4433
4434			bundleid = $.epoAPI.applyFilter( 'tc_get_bundleid', cart.attr( 'data-product_id' ), cart, epoObject );
4435
4436			// Get current woocommerce variation
4437			if ( ! current_variation ) {
4438				current_variation = 0;
4439			}
4440
4441			epoTotalsContainer = $.epoAPI.applyFilter( 'tc_get_totals_container', epoObject.this_epo_totals_container, element, main_product, bundleid );
4442			product_price = tm_calculate_product_price( epoTotalsContainer );
4443			product_original_price = tm_calculate_product_regular_price( epoTotalsContainer );
4444			apply_dpd = epoTotalsContainer.data( 'fields-price-rules' );
4445		} else {
4446			cart = args.cart;
4447			current_variation = args.current_variation;
4448
4449			bundleid = args.bundleid;
4450			epoTotalsContainer = args.epoTotalsContainer;
4451			product_price = args.product_price;
4452			product_original_price = args.product_original_price;
4453			apply_dpd = args.apply_dpd;
4454			per_product_pricing = args.per_product_pricing;
4455		}
4456		product_price = $.epoAPI.applyFilter( 'tc_alter_product_price', product_price, element, cart, epoTotalsContainer, bundleid );
4457		product_original_price = $.epoAPI.applyFilter( 'tc_alter_product_original_price', product_original_price, element, cart, epoTotalsContainer );
4458
4459		if ( product_price === false || ! per_product_pricing ) {
4460			return;
4461		}
4462
4463		if ( element.is( 'select' ) ) {
4464			setterall = element.find( 'option:selected' );
4465		}
4466		if ( setter_override ) {
4467			setterall = setter_override;
4468		}
4469
4470		setterall.toArray().forEach( function( setter ) {
4471			setter = $( setter );
4472
4473			rules = $.epoAPI.util.parseJSON( setter.attr( 'data-rules' ) );
4474			rulestype = $.epoAPI.util.parseJSON( setter.attr( 'data-rulestype' ) );
4475			original_rules = $.epoAPI.util.parseJSON( setter.attr( 'data-original-rules' ) );
4476			if ( element.is( '.tmcp-dynamic' ) ) {
4477				rules = $.epoAPI.util.parseJSON( setter.attr( 'data-formula' ) );
4478				original_rules = $.epoAPI.util.parseJSON( setter.attr( 'data-formula' ) );
4479				rulestype = $.epoAPI.util.parseJSON( setter.attr( 'data-calculation-type' ) );
4480			}
4481			if ( original_rules === undefined ) {
4482				original_rules = rules;
4483			}
4484
4485			pricetype = '';
4486			if ( typeof rules === 'object' ) {
4487				if ( current_variation in rules ) {
4488					price = rules[ current_variation ];
4489					original_price = original_rules[ current_variation ];
4490				} else {
4491					_rules = $.epoAPI.util.parseJSON( element.closest( '.tmcp-ul-wrap' ).attr( 'data-rules' ) );
4492					_original_rules = element.closest( '.tmcp-ul-wrap' ).data( 'original-rules' );
4493
4494					if ( typeof _rules === 'object' ) {
4495						if ( current_variation in _rules ) {
4496							price = _rules[ current_variation ];
4497						} else {
4498							price = rules[ 0 ];
4499						}
4500					} else {
4501						price = rules[ 0 ];
4502					}
4503
4504					if ( typeof _original_rules === 'object' ) {
4505						if ( current_variation in _original_rules ) {
4506							original_price = _original_rules[ current_variation ];
4507						} else {
4508							original_price = original_rules[ 0 ];
4509						}
4510					} else {
4511						original_price = original_rules[ 0 ];
4512					}
4513				}
4514
4515				if ( typeof rulestype === 'object' ) {
4516					if ( current_variation in rulestype ) {
4517						pricetype = rulestype[ current_variation ];
4518					} else {
4519						_rulestype = $.epoAPI.util.parseJSON( element.closest( '.tmcp-ul-wrap' ).attr( 'data-rulestype' ) );
4520						if ( typeof _rulestype === 'object' ) {
4521							if ( current_variation in _rulestype ) {
4522								pricetype = _rulestype[ current_variation ];
4523							} else {
4524								pricetype = rulestype[ 0 ];
4525							}
4526						} else {
4527							pricetype = rulestype[ 0 ];
4528						}
4529					}
4530				} else {
4531					rulestype = $.epoAPI.util.parseJSON( element.closest( '.tmcp-ul-wrap' ).attr( 'data-ulestype' ) );
4532					if ( typeof rulestype === 'object' ) {
4533						if ( current_variation in rulestype ) {
4534							pricetype = rulestype[ current_variation ];
4535						} else {
4536							pricetype = rulestype[ 0 ];
4537						}
4538					}
4539				}
4540			} else {
4541				_tmcpulwrap = element.closest( '.tmcp-ul-wrap' );
4542				rules = $.epoAPI.util.parseJSON( _tmcpulwrap.attr( 'data-rules' ) );
4543				original_rules = $.epoAPI.util.parseJSON( _tmcpulwrap.attr( 'data-original-rules' ) );
4544
4545				if ( typeof rules === 'object' ) {
4546					if ( current_variation in rules ) {
4547						price = rules[ current_variation ];
4548					} else {
4549						price = rules[ 0 ];
4550					}
4551					if ( typeof original_rules === 'object' ) {
4552						if ( current_variation in original_rules ) {
4553							original_price = original_rules[ current_variation ];
4554						} else {
4555							original_price = original_rules[ 0 ];
4556						}
4557					} else {
4558						original_price = price;
4559					}
4560
4561					if ( typeof rulestype === 'object' ) {
4562						if ( current_variation in rulestype ) {
4563							pricetype = rulestype[ current_variation ];
4564						} else {
4565							_rulestype = $.epoAPI.util.parseJSON( _tmcpulwrap.attr( 'data-rulestype' ) );
4566							if ( typeof _rulestype === 'object' ) {
4567								if ( current_variation in _rulestype ) {
4568									pricetype = _rulestype[ current_variation ];
4569								} else {
4570									pricetype = rulestype[ 0 ];
4571								}
4572							} else {
4573								pricetype = rulestype[ 0 ];
4574							}
4575						}
4576					} else {
4577						rulestype = $.epoAPI.util.parseJSON( _tmcpulwrap.attr( 'data-rulestype' ) );
4578						if ( typeof rulestype === 'object' ) {
4579							if ( current_variation in rulestype ) {
4580								pricetype = rulestype[ current_variation ];
4581							} else {
4582								pricetype = rulestype[ 0 ];
4583							}
4584						}
4585					}
4586				}
4587			}
4588
4589			if ( typeof pricetype === 'object' ) {
4590				pricetype = pricetype[ 0 ];
4591			}
4592			if ( element.is( '.tmcp-fee-field' ) ) {
4593				if ( $.inArray( pricetype, [ 'fee', 'stepfee', 'currentstepfee' ] ) !== -1 ) {
4594					pricetype = '';
4595				}
4596				apply_dpd = 0;
4597			}
4598
4599			if ( noremove === undefined ) {
4600				if ( element.is( 'select' ) ) {
4601					element.find( 'option' ).removeClass( 'tm-epo-late-field' ).removeData( 'tm-price-for-late islate' );
4602				} else {
4603					setter.removeClass( 'tm-epo-late-field' ).removeData( 'tm-price-for-late islate' );
4604				}
4605			}
4606			if ( pricetype !== 'math' ) {
4607				price = cleanPrice( price );
4608				original_price = cleanPrice( original_price );
4609			} else if ( typeof price === 'object' ) {
4610				price = price[ 0 ];
4611			}
4612
4613			undiscounted_raw_price = price;
4614			undiscounted_raw_original_price = original_price;
4615
4616			switch ( pricetype ) {
4617				case '':
4618					undiscounted_price = price;
4619					price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd );
4620					// original_price No change
4621					break;
4622				case 'math':
4623					price = calculateMathPrice( price, element, epoObject, manthnoevent, $.epoAPI.applyFilter( 'tc_use_undiscounted_price', undefined, element, cart, epoTotalsContainer ), funcTotal, cumulativeTotal, mathskip );
4624					undiscounted_price = price;
4625					price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd );
4626					original_price = calculateMathPrice( original_price, element, epoObject, true, true, funcTotal, cumulativeTotal, mathskip );
4627					// original_price No other change
4628					break;
4629				case 'percent_cart_total':
4630					cart_total = parseFloat( TMEPOJS.cart_total );
4631
4632					if ( ! Number.isFinite( cart_total ) ) {
4633						cart_total = 0;
4634					}
4635					undiscounted_price = ( price / 100 ) * cart_total;
4636					price = ( tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) / 100 ) * cart_total;
4637					original_price = ( tm_apply_dpd( original_price, epoTotalsContainer, apply_dpd ) / 100 ) * cart_total;
4638					break;
4639
4640				case 'percent':
4641					undiscounted_price = ( price / 100 ) * product_price;
4642					price = ( tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) / 100 ) * product_price;
4643					original_price = ( original_price / 100 ) * product_original_price;
4644					break;
4645				case 'percentcurrenttotal':
4646					$.tcepo.lateFieldsPrices[ epoEventId ].push( {
4647						setter: setter,
4648						price: price,
4649						original_price: original_price,
4650						bundleid: bundleid,
4651						pricetype: pricetype
4652					} );
4653					setter.data( 'tm-price-for-late', price ).data( 'tm-original-price-for-late', original_price ).data( 'islate', 1 ).addClass( 'tm-epo-late-field' );
4654					undiscounted_price = 0;
4655					price = 0;
4656					original_price = 0;
4657					break;
4658				case 'fixedcurrenttotal':
4659					price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd );
4660					$.tcepo.lateFieldsPrices[ epoEventId ].push( {
4661						setter: setter,
4662						price: price,
4663						original_price: original_price,
4664						bundleid: bundleid,
4665						pricetype: pricetype
4666					} );
4667					setter.data( 'tm-price-for-late', price ).data( 'tm-original-price-for-late', original_price ).data( 'islate', 1 ).addClass( 'tm-epo-late-field' );
4668					undiscounted_price = 0;
4669					price = 0;
4670					original_price = 0;
4671					break;
4672				case 'word':
4673					undiscounted_price = price * wordLength( setter.val() );
4674					price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) * wordLength( setter.val() );
4675					original_price = original_price * wordLength( setter.val() );
4676					break;
4677				case 'wordpercent':
4678					undiscounted_price = ( price / 100 ) * product_price * wordLength( setter.val() );
4679					price = ( tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) / 100 ) * product_price * wordLength( setter.val() );
4680					original_price = ( original_price / 100 ) * product_original_price * wordLength( setter.val() );
4681					break;
4682				case 'wordnon':
4683					freechars = parseInt( setter.attr( 'data-freechars' ), 10 );
4684					if ( ! Number.isFinite( freechars ) ) {
4685						freechars = 0;
4686					}
4687					textlength = wordLength( setter.val() ) - freechars;
4688					if ( textlength < 0 ) {
4689						textlength = 0;
4690					}
4691					undiscounted_price = price * textlength;
4692					price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) * textlength;
4693					original_price = original_price * textlength;
4694					break;
4695				case 'wordpercentnon':
4696					freechars = parseInt( setter.attr( 'data-freechars' ), 10 );
4697					if ( ! Number.isFinite( freechars ) ) {
4698						freechars = 0;
4699					}
4700					textlength = wordLength( setter.val() ) - freechars;
4701					if ( textlength < 0 ) {
4702						textlength = 0;
4703					}
4704					undiscounted_price = ( price / 100 ) * product_price * textlength;
4705					price = ( tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) / 100 ) * product_price * textlength;
4706					original_price = ( original_price / 100 ) * product_original_price * textlength;
4707					break;
4708
4709				case 'char':
4710					undiscounted_price = price * setter.val().length;
4711					price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) * setter.val().length;
4712					original_price = original_price * setter.val().length;
4713					break;
4714				case 'charpercent':
4715					undiscounted_price = ( price / 100 ) * product_price * setter.val().length;
4716					price = ( tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) / 100 ) * product_price * setter.val().length;
4717					original_price = ( original_price / 100 ) * product_original_price * setter.val().length;
4718					break;
4719				case 'charnospaces':
4720					undiscounted_price = price * setter.val().replace( /\s/g, '' ).length;
4721					price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) * setter.val().replace( /\s/g, '' ).length;
4722					original_price = original_price * setter.val().replace( /\s/g, '' ).length;
4723					break;
4724				case 'charnofirst':
4725					textlength = setter.val().length - 1;
4726					if ( textlength < 0 ) {
4727						textlength = 0;
4728					}
4729					undiscounted_price = price * textlength;
4730					price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) * textlength;
4731					original_price = original_price * textlength;
4732					break;
4733
4734				case 'charnon':
4735					freechars = parseInt( setter.attr( 'data-freechars' ), 10 );
4736					if ( ! Number.isFinite( freechars ) ) {
4737						freechars = 0;
4738					}
4739					textlength = setter.val().length - freechars;
4740					if ( textlength < 0 ) {
4741						textlength = 0;
4742					}
4743					undiscounted_price = price * textlength;
4744					price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) * textlength;
4745					original_price = original_price * textlength;
4746					break;
4747				case 'charpercentnon':
4748					freechars = parseInt( setter.attr( 'data-freechars' ), 10 );
4749					if ( ! Number.isFinite( freechars ) ) {
4750						freechars = 0;
4751					}
4752					textlength = setter.val().length - freechars;
4753					if ( textlength < 0 ) {
4754						textlength = 0;
4755					}
4756					undiscounted_price = ( price / 100 ) * product_price * textlength;
4757					price = ( tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) / 100 ) * product_price * textlength;
4758					original_price = ( original_price / 100 ) * product_original_price * textlength;
4759					break;
4760				case 'charnonnospaces':
4761					freechars = parseInt( setter.attr( 'data-freechars' ), 10 );
4762					if ( ! Number.isFinite( freechars ) ) {
4763						freechars = 0;
4764					}
4765					textlength = setter.val().replace( /\s/g, '' ).length - freechars;
4766					if ( textlength < 0 ) {
4767						textlength = 0;
4768					}
4769					undiscounted_price = price * textlength;
4770					price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) * textlength;
4771					original_price = original_price * textlength;
4772					break;
4773				case 'charpercentnonnospaces':
4774					freechars = parseInt( setter.attr( 'data-freechars' ), 10 );
4775					if ( ! Number.isFinite( freechars ) ) {
4776						freechars = 0;
4777					}
4778					textlength = setter.val().replace( /\s/g, '' ).length - freechars;
4779					if ( textlength < 0 ) {
4780						textlength = 0;
4781					}
4782					undiscounted_price = ( price / 100 ) * product_price * textlength;
4783					price = ( tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) / 100 ) * product_price * textlength;
4784					original_price = ( original_price / 100 ) * product_original_price * textlength;
4785					break;
4786
4787				case 'charpercentnofirst':
4788					textlength = setter.val().length - 1;
4789					if ( textlength < 0 ) {
4790						textlength = 0;
4791					}
4792					undiscounted_price = ( price / 100 ) * product_price * textlength;
4793					price = ( tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) / 100 ) * product_price * textlength;
4794					original_price = ( original_price / 100 ) * product_original_price * textlength;
4795					break;
4796				case 'step':
4797					if ( is_range_field ) {
4798						undiscounted_price = price * setter.val();
4799						price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) * setter.val();
4800						original_price = original_price * $.epoAPI.math.toFloat( setter.val() );
4801					} else {
4802						undiscounted_price = price * $.epoAPI.math.toFloat( setter.val() );
4803						price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) * $.epoAPI.math.toFloat( setter.val() );
4804						original_price = original_price * $.epoAPI.math.toFloat( setter.val() );
4805					}
4806					break;
4807				case 'currentstep':
4808					if ( is_range_field ) {
4809						undiscounted_price = setter.val();
4810						price = tm_apply_dpd( setter.val(), epoTotalsContainer, apply_dpd );
4811						original_price = tm_apply_dpd( setter.val(), epoTotalsContainer, apply_dpd );
4812					} else {
4813						undiscounted_price = $.epoAPI.math.toFloat( setter.val() );
4814						price = tm_apply_dpd( $.epoAPI.math.toFloat( setter.val() ), epoTotalsContainer, apply_dpd );
4815						original_price = tm_apply_dpd( $.epoAPI.math.toFloat( setter.val() ), epoTotalsContainer, apply_dpd );
4816					}
4817					break;
4818				case 'intervalstep':
4819					if ( is_range_field ) {
4820						min_value = parseFloat( $( '.tm-range-picker[data-field-id="' + setter.attr( 'id' ) + '"]' ).attr( 'data-min' ) );
4821						undiscounted_price = price * ( setter.val() - min_value );
4822						price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) * ( setter.val() - min_value );
4823						original_price = original_price * ( setter.val() - min_value );
4824					}
4825					break;
4826				case 'row':
4827					undiscounted_price = price * ( ( setter.val().match( /(\r\n|\n|\r)/gm ) || [] ).length + 1 );
4828					price = tm_apply_dpd( price, epoTotalsContainer, apply_dpd ) * ( ( setter.val().match( /(\r\n|\n|\r)/gm ) || [] ).length + 1 );
4829					original_price = original_price * ( ( setter.val().match( /(\r\n|\n|\r)/gm ) || [] ).length + 1 );
4830					break;
4831			}
4832
4833			raw_price = price;
4834			raw_original_price = original_price;
4835
4836			undiscounted_original_price = original_price;
4837			undiscounted_raw_price = undiscounted_price;
4838			undiscounted_raw_original_price = undiscounted_original_price;
4839
4840			if ( element.data( 'tm-quantity' ) ) {
4841				undiscounted_price = undiscounted_price * parseFloat( element.data( 'tm-quantity' ) );
4842				undiscounted_original_price = undiscounted_original_price * parseFloat( element.data( 'tm-quantity' ) );
4843				undiscounted_raw_price = undiscounted_raw_price * parseFloat( element.data( 'tm-quantity' ) );
4844				undiscounted_raw_original_price = undiscounted_raw_original_price * parseFloat( element.data( 'tm-quantity' ) );
4845
4846				price = price * parseFloat( element.data( 'tm-quantity' ) );
4847				original_price = original_price * parseFloat( element.data( 'tm-quantity' ) );
4848				raw_price = raw_price * parseFloat( element.data( 'tm-quantity' ) );
4849				raw_original_price = raw_original_price * parseFloat( element.data( 'tm-quantity' ) );
4850			}
4851
4852			addedPrice = addedPrice + parseFloat( price );
4853			originalAddedPrice = originalAddedPrice + parseFloat( original_price );
4854
4855			formatted_price = tm_set_price( addedPrice, epoTotalsContainer, false, false, setter, pricetype );
4856			original_formatted_price = tm_set_price( originalAddedPrice, epoTotalsContainer, false, false, setter, pricetype );
4857
4858			element.data( 'price_set', 1 );
4859			setter.data( 'price_set', 1 );
4860
4861			setter.data( 'undiscounted_raw_price', undiscounted_raw_price );
4862			setter.data( 'undiscounted_raw_original_price', undiscounted_raw_original_price );
4863			setter.data( 'undiscounted_price', tm_set_tax_price( undiscounted_price, epoTotalsContainer, setter, pricetype ) );
4864			setter.data( 'undiscounted_original_price', tm_set_tax_price( undiscounted_original_price, epoTotalsContainer, setter, pricetype ) );
4865
4866			setter.data( 'raw_price', raw_price );
4867			setter.data( 'raw_original_price', raw_original_price );
4868			setter.data( 'price', tm_set_tax_price( price, epoTotalsContainer, setter, pricetype ) );
4869			setter.data( 'original_price', tm_set_tax_price( original_price, epoTotalsContainer, setter, pricetype ) );
4870
4871			if ( ! setter_override ) {
4872				if ( element.is( '.tc-epo-field-product' ) ) {
4873					isFilled = false;
4874					if ( element.is( 'select' ) ) {
4875						if ( element.val() !== '' ) {
4876							isFilled = true;
4877						}
4878					} else if ( ( element.is( ':checkbox' ) || element.is( ':radio' ) ) ) {
4879						if ( element.is( ':checked' ) ) {
4880							isFilled = true;
4881						}
4882					} else if ( element.val() !== '' ) {
4883						isFilled = true;
4884					}
4885
4886					if ( ! isFilled ) {
4887						formatted_price = setter.data( 'price-html' );
4888						original_formatted_price = '';
4889					}
4890				}
4891				tm_update_price( setter.closest( '.tmcp-field-wrap' ).find( '.tc-price' ), addedPrice, formatted_price, originalAddedPrice, original_formatted_price );
4892				element.data( 'price-changed', 1 );
4893			}
4894		} );
4895	}
4896
4897	function tm_epo_rules( epoObject, theCart ) {
4898		var all_carts;
4899		var variation_id_selector;
4900		var per_product_pricing = true;
4901		var current_variation;
4902		var bundleid;
4903		var epoContainer;
4904		var epoTotalsContainer;
4905		var apply_dpd;
4906		var rules;
4907		var original_rules;
4908		var price;
4909		var formatted_price;
4910		var original_price;
4911		var original_formatted_price;
4912		var product_price;
4913		var product_original_price;
4914		var all_fields;
4915		var active_fields;
4916		var args;
4917		var main_product = epoObject.main_product;
4918		var epoEventId = epoObject.epoEventId;
4919		var this_epo_container = epoObject.this_epo_container;
4920		var this_epo_totals_container = epoObject.this_epo_totals_container;
4921
4922		if ( ! theCart ) {
4923			all_carts = main_product.find( '.cart' );
4924		} else {
4925			all_carts = theCart;
4926		}
4927		if ( all_carts.length <= 0 ) {
4928			return;
4929		}
4930
4931		$.tcepo.lateFieldsPrices[ epoEventId ] = [];
4932
4933		all_carts.toArray().forEach( function( cart ) {
4934			cart = $( cart );
4935			variation_id_selector = "input[name^='variation_id']";
4936			if ( cart.find( 'input.variation_id' ).length > 0 ) {
4937				variation_id_selector = 'input.variation_id';
4938			}
4939
4940			if ( cart.data( 'per_product_pricing' ) !== undefined ) {
4941				per_product_pricing = cart.data( 'per_product_pricing' );
4942			}
4943
4944			current_variation = cart.find( variation_id_selector ).val();
4945			bundleid = $.epoAPI.applyFilter( 'tc_get_bundleid', cart.attr( 'data-product_id' ), cart, epoObject );
4946
4947			// get current woocommerce variation
4948			if ( ! current_variation ) {
4949				current_variation = 0;
4950			}
4951
4952			epoContainer = $.epoAPI.applyFilter( 'tc_get_epo_container', this_epo_container, cart, main_product, bundleid );
4953			epoTotalsContainer = $.epoAPI.applyFilter( 'tc_get_totals_container', this_epo_totals_container, cart, main_product, bundleid );
4954
4955			// WooCommerce Dynamic Pricing & Discounts
4956			apply_dpd = epoTotalsContainer.data( 'fields-price-rules' );
4957
4958			// set initial prices for all fields
4959			if ( ! epoContainer.data( 'tm_rules_init_done' ) ) {
4960				if ( epoTotalsContainer.data( 'force-quantity' ) ) {
4961					cart.find( tcAPI.qtySelector ).val( epoTotalsContainer.data( 'force-quantity' ) );
4962				}
4963				epoContainer.toArray().forEach( function( el ) {
4964					$( el ).closest( '.tmcp-field-wrap' ).find( '.tm-epo-field' ).data( 'tm-quantity', $( el ).val() );
4965				} );
4966
4967				epoContainer
4968					.find( '.tmcp-attributes, .tmcp-elements' )
4969					.toArray()
4970					.forEach( function( element ) {
4971						element = $( element );
4972						rules = $.epoAPI.util.parseJSON( element.attr( 'data-rules' ) );
4973						original_rules = $.epoAPI.util.parseJSON( element.attr( 'data-original-rules' ) );
4974
4975						// if rule doesn't exit then init an empty rule
4976						if ( typeof rules !== 'object' ) {
4977							rules = {
4978								0: '0'
4979							};
4980						}
4981						if ( typeof original_rules !== 'object' ) {
4982							original_rules = {
4983								0: '0'
4984							};
4985						}
4986						if ( typeof rules === 'object' ) {
4987							// we skip price validation test so that every field has at least a price of 0
4988							price = tm_apply_dpd( rules[ $.epoAPI.math.toFloat( current_variation ) ], epoTotalsContainer, apply_dpd );
4989							formatted_price = tm_set_price( price, epoTotalsContainer );
4990							original_price = tm_apply_dpd( original_rules[ $.epoAPI.math.toFloat( current_variation ) ], epoTotalsContainer, apply_dpd );
4991							original_formatted_price = tm_set_price( original_price, epoTotalsContainer );
4992
4993							element
4994								.find( '.tmcp-field, .tmcp-fee-field ' )
4995								.toArray()
4996								.forEach( function( el ) {
4997									el = $( el );
4998									if ( per_product_pricing ) {
4999										if ( el.attr( 'data-no-price' ) === '1' ) {
5000											price = 0;
5001											original_price = 0;
5002										}
5003										el.data( 'raw_price', price );
5004										el.data( 'raw_original_price', original_price );
5005
5006										el.data( 'price', tm_set_tax_price( price, epoTotalsContainer, el ) );
5007										el.data( 'original_price', tm_set_tax_price( original_price, epoTotalsContainer, el ) );
5008
5009										tm_update_price( el.closest( '.tmcp-field-wrap' ).find( '.tc-price' ), price, formatted_price, original_price, original_formatted_price );
5010									} else {
5011										el.data( 'price', 0 );
5012										el.data( 'original_price', 0 );
5013										el.closest( '.tmcp-field-wrap' ).find( '.amount' ).empty();
5014									}
5015								} );
5016						}
5017					} );
5018				epoContainer.data( 'tm_rules_init_done', 1 );
5019			}
5020
5021			// skip specific field rules if per_product_pricing is false
5022			if ( ! per_product_pricing ) {
5023				return true;
5024			}
5025
5026			product_price = tm_calculate_product_price( epoTotalsContainer );
5027			product_original_price = tm_calculate_product_regular_price( epoTotalsContainer );
5028
5029			args = {
5030				cart: cart,
5031				current_variation: current_variation,
5032				bundleid: bundleid,
5033				epoTotalsContainer: epoTotalsContainer,
5034				product_price: product_price,
5035				product_original_price: product_original_price,
5036				apply_dpd: apply_dpd,
5037				per_product_pricing: per_product_pricing
5038			};
5039
5040			all_fields = epoContainer.find( '.tmcp-field,.tmcp-sub-fee-field,.tmcp-fee-field' );
5041			if ( ! epoObject.is_associated ) {
5042				all_fields = all_fields.not( tcAPI.associatedEpoSelector + ' ' + '.tmcp-field,' + tcAPI.associatedEpoSelector + ' ' + '.tmcp-sub-fee-field,' + tcAPI.associatedEpoSelector + ' ' + '.tmcp-fee-field' );
5043			}
5044			active_fields = all_fields.filter( '.tcenabled' );
5045
5046			// note: find a better way if any
5047			if ( ! $.tcepo.initialActivation[ epoEventId ] || ( active_fields.length === 0 && all_fields.length > 0 ) ) {
5048				all_fields.each( function() {
5049					field_is_active( $( this ) );
5050				} );
5051
5052				$.tcepo.initialActivation[ epoEventId ] = true;
5053			}
5054
5055			//  apply specific field rules
5056			all_fields.filter( '.tcenabled' ).each( function( index, element ) {
5057				tm_element_epo_rules( epoObject, element, args );
5058			} );
5059
5060			all_fields.each( function( index, element ) {
5061				$( element ).on( 'tc_element_epo_rules', function() {
5062					tm_element_epo_rules( epoObject, element, args );
5063				} );
5064			} );
5065		} );
5066	}
5067
5068	function add_late_fields_prices( epoObject, currentProductPrice, originalProductPrice, options_total, original_options_total, bid, _cart, applydpd ) {
5069		var total = 0;
5070		var originalTotal = 0;
5071		var totalFees = 0;
5072		var originalTotalFees = 0;
5073		var price;
5074		var originalPrice;
5075		var priceType;
5076		var setter;
5077		var id;
5078		var hidden;
5079		var bundleid;
5080		var realSetter;
5081		var productId;
5082		var epoId;
5083		var formattedPrice;
5084		var originalFormattedPrice;
5085		var epoEventId = epoObject.epoEventId;
5086		var taxPrice;
5087		var taxOriginalPrice;
5088		var hiddenName;
5089		var productPrice;
5090		var oProductPrice;
5091		var apply_dpd;
5092
5093		if ( applydpd !== undefined ) {
5094			apply_dpd = applydpd;
5095		} else {
5096			apply_dpd = epoObject.this_epo_totals_container.data( 'fields-price-rules' );
5097		}
5098		productPrice = currentProductPrice;
5099		oProductPrice = originalProductPrice;
5100
5101		$.tcepo.lateFieldsPrices[ epoEventId ].forEach( function( field ) {
5102			price = field.price;
5103			originalPrice = field.original_price;
5104			priceType = field.pricetype;
5105			setter = field.setter;
5106			bundleid = field.bundleid;
5107			realSetter = setter;
5108
5109			if ( priceType === 'percentcurrenttotal' ) {
5110				hiddenName = '_hidden';
5111			} else {
5112				hiddenName = '_hiddenfixed';
5113			}
5114
5115			if ( setter.is( 'option' ) ) {
5116				realSetter = setter.closest( 'select' );
5117			}
5118
5119			productPrice = parseFloat( $.epoAPI.applyFilter( 'tc_alter_product_price', productPrice, realSetter, _cart, epoObject.this_epo_totals_container, bid ) );
5120			oProductPrice = parseFloat( $.epoAPI.applyFilter( 'tc_alter_original_product_price', oProductPrice, realSetter, _cart, epoObject.this_epo_totals_container, bid ) );
5121
5122			id = $.epoAPI.dom.id( realSetter.attr( 'name' ) );
5123			productId = $( '.tc-totals-form.tm-totals-form-' + _cart.attr( 'data-cart-id' ) ).attr( 'data-product-id' );
5124			epoId = $( '.tc-totals-form.tm-totals-form-' + _cart.attr( 'data-cart-id' ) ).attr( 'data-epo-id' );
5125			//workaround to support composite products
5126			hidden = $( '.tc-extra-product-options.tm-product-id-' + productId + "[data-epo-id='" + epoId + "']" ).find( '#' + id + hiddenName );
5127
5128			if ( bundleid === bid ) {
5129				if ( priceType === 'percentcurrenttotal' ) {
5130					price = ( parseFloat( price ) / 100 ) * ( tm_apply_dpd( parseFloat( productPrice ), epoObject.this_epo_totals_container, apply_dpd ) + parseFloat( options_total ) );
5131					originalPrice = ( parseFloat( originalPrice ) / 100 ) * ( parseFloat( oProductPrice ) + parseFloat( original_options_total ) );
5132				} else if ( priceType === 'fixedcurrenttotal' ) {
5133					price = parseFloat( price ) + parseFloat( options_total );
5134					originalPrice = parseFloat( originalPrice ) + parseFloat( original_options_total );
5135				}
5136				if ( realSetter.data( 'tm-quantity' ) ) {
5137					price = price * parseFloat( realSetter.data( 'tm-quantity' ) );
5138					originalPrice = originalPrice * parseFloat( realSetter.data( 'tm-quantity' ) );
5139				}
5140
5141				if ( setter.data( 'isset' ) === 1 && field_is_active( setter ) ) {
5142					if ( realSetter.is( '.tmcp-field' ) ) {
5143						total = total + price;
5144						originalTotal = originalTotal + originalPrice;
5145					} else if ( realSetter.is( '.tmcp-fee-field' ) ) {
5146						totalFees = totalFees + price;
5147						originalTotalFees = originalTotalFees + originalPrice;
5148					}
5149				}
5150
5151				taxPrice = tm_set_tax_price( price, _cart, setter );
5152				taxOriginalPrice = tm_set_tax_price( originalPrice, _cart, setter );
5153
5154				formattedPrice = tm_set_price( price, _cart, false, false, setter );
5155				originalFormattedPrice = tm_set_price( originalPrice, _cart, false, false, setter );
5156				setter.data( 'price', taxPrice );
5157				setter.data( 'pricew', taxPrice );
5158				setter.data( 'original_price', taxOriginalPrice );
5159				setter.data( 'original_pricew', taxOriginalPrice );
5160
5161				tm_update_price( setter.closest( '.tmcp-field-wrap' ).find( '.tc-price' ), taxPr
5161ice, formattedPrice, taxOriginalPrice, originalFormattedPrice );
5162
5163				if ( hidden.length === 0 ) {
5164					realSetter.before( '<input type="hidden" id="' + id + hiddenName + '" name="' + id + hiddenName + '" value="' + tm_set_price_without_tax( price, _cart ) + '">' );
5165				}
5166				if ( setter.is( '.tm-epo-field.tmcp-radio' ) ) {
5167					if ( setter.is( ':checked' ) ) {
5168						hidden.val( tm_set_price_without_tax( price, _cart ) );
5169					}
5170				} else {
5171					hidden.val( tm_set_price_without_tax( price, _cart ) );
5172				}
5173			} else if ( setter.data( 'pricew' ) !== undefined ) {
5174				formattedPrice = tm_set_price( setter.data( 'pricew' ), _cart, true, false, setter );
5175				originalFormattedPrice = '';
5176
5177				if ( setter.data( 'original_pricew' ) !== undefined ) {
5178					originalFormattedPrice = tm_set_price( setter.data( 'original_pricew' ), _cart, true, false, setter );
5179				}
5180
5181				tm_update_price( setter.closest( '.tmcp-field-wrap' ).find( '.tc-price' ), setter.data( 'pricew' ), formattedPrice, setter.data( 'original_pricew' ), originalFormattedPrice );
5182			}
5183		} );
5184
5185		return {
5186			normal: [ total, originalTotal ],
5187			fees: [ totalFees, originalTotalFees ]
5188		};
5189	}
5190
5191	function tm_lazyload() {
5192		var container;
5193
5194		if ( TMEPOJS.tm_epo_no_lazy_load === 'yes' ) {
5195			return;
5196		}
5197
5198		if ( tmLazyloadContainer ) {
5199			container = $( tmLazyloadContainer ).find( 'img.tmlazy' );
5200		} else {
5201			container = $( '.tc-extra-product-options img.tmlazy' );
5202		}
5203
5204		container.lazyLoadXT();
5205		container.on( 'lazyshow', function() {
5206			jWindow.trigger( 'lazyLoadXToncomplete' );
5207		} );
5208	}
5209
5210	function tm_css_styles( obj ) {
5211		var slider;
5212		var $cart;
5213
5214		if ( ! obj ) {
5215			return;
5216		}
5217
5218		$cart = $( '.cart' );
5219
5220		obj.find( '.tm-owl-slider-section' ).each( function() {
5221			slider = $( this );
5222
5223			slider.find( '.tc-slider-content' ).addClass( 'tm-owl-slider' );
5224
5225			slider = slider.find( '.tm-owl-slider' );
5226
5227			slider
5228				.addClass( 'tcowl-carousel-show' )
5229				.addClass( 'tcowl-carousel' )
5230				.on( 'changed.owl.carousel', function() {
5231					$cart.css( 'display', 'block' ).addClass( 'slider-setup' );
5232				} )
5233				.tmowlCarousel( Object.assign( {
5234					rtl: TMEPOJS.isRTL === '1',
5235					dots: false,
5236					nav: true,
5237					items: 1,
5238					autoHeight: true,
5239					mouseDrag: false,
5240					touchDrag: true,
5241					navText: [ TMEPOJS.i18n_prev_text, TMEPOJS.i18n_next_text ],
5242					navClass: [ 'owl-prev button', 'owl-next button' ],
5243					navElement: 'a',
5244					loop: false,
5245					navRewind: false
5246				}, window.tmowlCarouselSettings || {} ) );
5247
5248			slider.removeClass( 'tcowl-carousel-show' );
5249		} );
5250
5251		if ( $.fn.tcTabs ) {
5252			obj.find( '.tc-tabs' ).tcTabs( {
5253				headers: 'tc-tab-headers',
5254				header: 'tab-header',
5255				dataopenattribute: 'data-tab',
5256				sortabletabs: false
5257			} );
5258		}
5259	}
5260
5261	function repeaterAdd( el, elementInnerWrap ) {
5262		var cpf = elementInnerWrap.closest( '.cpf-element' );
5263		var maxRows = cpf.data( 'repeater-max-rows' );
5264		var repeater = elementInnerWrap.find( '.tc-repeater-element' );
5265		var rows = repeater.length;
5266		var repeaterLast = repeater.last();
5267		var repeaterLastUL = repeater.last().find( '.tmcp-ul-wrap' );
5268		var clone;
5269		var cloneUl;
5270		var originalId = el.data( 'tc-repeater-id' );
5271		var index = el.data( 'tc-repeater-init' );
5272
5273		if ( maxRows ) {
5274			if ( rows >= maxRows ) {
5275				return false;
5276			}
5277		}
5278
5279		if ( rows + 1 >= maxRows && el.is( '.tc-repeater-add' ) ) {
5280			el.closest( '.tc-repeater-wrap' ).addClass( 'tc-hidden' );
5281		}
5282
5283		if ( repeaterLastUL.is( '.tm-element-ul-date, .tm-element-ul-time' ) ) {
5284			repeaterLastUL.find( '.tm-epo-field' ).tm_datepicker( 'destroy' );
5285			repeaterLastUL.find( '.tmcp-date-select' ).off();
5286		}
5287		if ( repeaterLastUL.is( '.tm-element-ul-color' ) ) {
5288			repeaterLastUL.find( '.tm-epo-field' ).spectrum( 'destroy' );
5289		}
5290
5291		clone = repeaterLast.tcClone( true );
5292
5293		clone.find( '.tm-epo-field' ).attr( 'id', function( i, value ) {
5294			return value.replace( /\_\d+$/g, '' ) + '_' + index;
5295		} );
5296		clone.find( '[data-for]' ).attr( 'data-for', function( i, value ) {
5297			return value.replace( /\_\d+$/g, '' ) + '_' + index;
5298		} );
5299		clone.find( '[for]' ).attr( 'for', function( i, value ) {
5300			return value.replace( /\_\d+$/g, '' ) + '_' + index;
5301		} );
5302		clone.find( '[data-field-id]' ).attr( 'data-field-id', function( i, value ) {
5303			return value.replace( /\_\d+$/g, '' ) + '_' + index;
5304		} );
5305		clone.find( '[data-tm-date]' ).attr( 'data-tm-date', function() {
5306			return originalId + '_' + index;
5307		} );
5308		clone.find( '.tm-epo-field' ).attr( 'name', function( i, value ) {
5309			return value.replace( /\[\d+\]/g, '[' + index + ']' );
5310		} );
5311		clone.find( '.tm-qty' ).attr( 'name', function( i, value ) {
5312			return value.replace( /\[\d+\]/g, '[' + index + ']' );
5313		} );
5314		clone.find( '.tmcp-date-select' ).attr( 'name', function( i, value ) {
5315			return value.replace( /\[\d+\]/g, '[' + index + ']' );
5316		} );
5317		clone.find( '.tmcp-date-select' ).attr( 'id', function( i, value ) {
5318			return originalId + '_' + index + '_' + value.substring( value.lastIndexOf( '_' ) + 1 );
5319		} );
5320
5321		cloneUl = clone.find( '.tmcp-ul-wrap' );
5322
5323		if ( elementInnerWrap.find( '.tc-repeater-element' ).length > 0 ) {
5324			elementInnerWrap.find( '.tc-repeater-delete' ).removeClass( 'tc-hidden' );
5325			clone.find( '.tc-repeater-delete' ).removeClass( 'tc-hidden' );
5326		}
5327
5328		if ( cloneUl.is( '.tm-element-ul-checkbox' ) ) {
5329			clone.find( 'li.tmcp-field-wrap' ).removeClass( 'tc-active' );
5330			clone
5331				.find( '.tm-epo-field.tmcp-checkbox' )
5332				.prop( 'checked', false );
5333			clone
5334				.find( '.tm-epo-field.tmcp-checkbox' )
5335				.filter( function( i, x ) {
5336					return $.inArray( $( x ).val(), el.data( 'repeater-init-value' ) ) !== -1;
5337				} )
5338				.prop( 'checked', true )
5339				.closest( 'li.tmcp-field-wrap' ).addClass( 'tc-active' );
5340		} else if ( cloneUl.is( '.tm-element-ul-radio' ) ) {
5341			clone.find( 'li.tmcp-field-wrap' ).removeClass( 'tc-active' );
5342			clone
5343				.find( '.tm-epo-field.tmcp-radio' )
5344				.filter( function( i, x ) {
5345					return $( x ).val() === el.data( 'repeater-init-value' );
5346				} )
5347				.prop( 'checked', true )
5348				.closest( 'li.tmcp-field-wrap' ).addClass( 'tc-active' );
5349		} else {
5350			clone.find( '.tm-epo-field' ).val( el.data( 'repeater-init-value' ) );
5351		}
5352
5353		if ( ! cloneUl.is( '.tm-element-ul-checkbox' ) && ! cloneUl.is( '.tm-element-ul-radio' ) ) {
5354			clone.find( '.tm-epo-field' ).val( el.data( 'repeater-init-value' ) );
5355		}
5356
5357		el.data( 'tc-repeater-init', el.data( 'tc-repeater-init' ) + 1 );
5358
5359		return [ clone, repeaterLast, repeaterLastUL ];
5360	}
5361
5362	function repeaterAddAfter( epoObject, clone, repeaterLast, repeaterLastUL, doevents ) {
5363		var cloneUl = clone.find( '.tmcp-ul-wrap' );
5364
5365		if ( cloneUl.is( '.tm-element-ul-range' ) ) {
5366			clone.find( '.tm-range-picker' ).removeData( 'tc-picker-init' ).attr( 'class', 'tm-range-picker' ).html( '' );
5367			setRangePickers( clone );
5368		}
5369		if ( cloneUl.is( '.tm-element-ul-date, .tm-element-ul-time' ) ) {
5370			tm_set_datepicker( repeaterLastUL );
5371			tm_set_datepicker( cloneUl );
5372		}
5373		if ( cloneUl.is( '.tm-element-ul-color' ) ) {
5374			tm_set_color_pickers( repeaterLastUL );
5375			tm_set_color_pickers( cloneUl );
5376		}
5377		clone.find( '.tm-tooltip' ).removeData( 'tctooltip' ).removeData( 'tm-has-tm-tip' );
5378		$.tcToolTip( clone.find( '.tm-tooltip' ) );
5379
5380		//  apply specific field rules
5381		clone.find( '.tm-epo-field' )
5382			.removeData( 'addedtcEpoBeforeOptionPriceCalculation' )
5383			.each( function( y, elc ) {
5384				var element = $( elc );
5385				field_is_active( element, false, true );
5386				if ( element.is( '.tcenabled' ) ) {
5387					tm_element_epo_rules( epoObject, element );
5388				}
5389				element.on( 'tc_element_epo_rules', function() {
5390					tm_element_epo_rules( epoObject, element );
5391				} );
5392			} );
5393		if ( ! doevents ) {
5394			return;
5395		}
5396		if ( cloneUl.is( '.tm-element-ul-checkbox' ) ) {
5397			clone
5398				.find( '.tm-epo-field.tmcp-checkbox' )
5399				.filter( ':checked' )
5400				.trigger( 'change.cpf' );
5401		} else if ( cloneUl.is( '.tm-element-ul-radio' ) ) {
5402			clone
5403				.find( '.tm-epo-field.tmcp-radio' )
5404				.filter( ':checked' )
5405				.trigger( 'change.cpf' );
5406		} else {
5407			clone.find( '.tm-epo-field' ).trigger( 'change.cpf' );
5408		}
5409	}
5410
5411	function repeaterDelete( elementInnerWrap, repeaterElement, repeaterObj, $this ) {
5412		var cpf = elementInnerWrap.closest( '.cpf-element' );
5413		var minRows = cpf.data( 'repeater-min-rows' );
5414		var rows = elementInnerWrap.find( '.tc-repeater-element' ).length;
5415		var repeaterElementIndex = repeaterElement.index();
5416		var message;
5417
5418		if ( minRows ) {
5419			if ( rows <= minRows ) {
5420				if ( $this ) {
5421					message = '<div class="tm-error-repeater tm-error tc-cell tcwidth tcwidth-100">' + $.tc_validator.messages.repeaterminrows( minRows ) + '</div>';
5422					$this.tcToolTip( { tip: message, onetime: true, trigger: true, tipclass: 'tc-error' } );
5423				}
5424				return false;
5425			}
5426		}
5427		if ( rows === 1 ) {
5428			return;
5429		}
5430		if ( rows === 2 ) {
5431			elementInnerWrap.find( '.tc-repeater-delete' ).addClass( 'tc-hidden' );
5432		}
5433		if ( repeaterObj.is( '.tc-repeater-add' ) ) {
5434			repeaterObj.closest( '.tc-repeater-wrap' ).removeClass( 'tc-hidden' );
5435		}
5436		repeaterElement.remove();
5437		repeaterObj.data( 'tc-repeater-init', repeaterObj.data( 'tc-repeater-init' ) - 1 );
5438		if ( repeaterElementIndex + 1 === rows ) {
5439			return;
5440		}
5441		elementInnerWrap.find( '.tc-repeater-element' )
5442			.toArray()
5443			.forEach( function( clone, index ) {
5444				clone = $( clone );
5445				clone.find( '.tm-epo-field' ).attr( 'id', function( i, value ) {
5446					return value.replace( /\_\d+$/g, '' ) + ( ( index !== 0 ) ? '_' + index : '' );
5447				} );
5448				clone.find( '[data-for]' ).attr( 'data-for', function( i, value ) {
5449					return value.replace( /\_\d+$/g, '' ) + ( ( index !== 0 ) ? '_' + index : '' );
5450				} );
5451				clone.find( '[for]' ).attr( 'for', function( i, value ) {
5452					return value.replace( /\_\d+$/g, '' ) + ( ( index !== 0 ) ? '_' + index : '' );
5453				} );
5454				clone.find( '[data-field-id]' ).attr( 'data-field-id', function( i, value ) {
5455					return value.replace( /\_\d+$/g, '' ) + ( ( index !== 0 ) ? '_' + index : '' );
5456				} );
5457				clone.find( '[data-tm-date]' ).attr( 'data-tm-date', function( i, value ) {
5458					return value.replace( /\_\d+$/g, '' ) + ( ( index !== 0 ) ? '_' + index : '' );
5459				} );
5460				clone.find( '.tm-epo-field' ).attr( 'name', function( i, value ) {
5461					return value.replace( /\[\d+\]/g, '[' + index + ']' );
5462				} );
5463				clone.find( '.tm-qty' ).attr( 'name', function( i, value ) {
5464					return value.replace( /\[\d+\]/g, '[' + index + ']' );
5465				} );
5466				clone.find( '.tmcp-date-select' ).attr( 'name', function( i, value ) {
5467					return value.replace( /\[\d+\]/g, '[' + index + ']' );
5468				} );
5469			} );
5470	}
5471
5472	function tm_set_repeaters( obj, epoObject ) {
5473		var currentCart;
5474		var qtyElement;
5475		var quantityRepeaters;
5476		if ( ! obj ) {
5477			return;
5478		}
5479		obj = $( obj );
5480
5481		if ( obj.length ) {
5482			currentCart = epoObject.main_cart;
5483			qtyElement = getQtyElement( currentCart );
5484			qtyElement = $.epoAPI.applyFilter( 'qtyElementForRepeaterQuantity', qtyElement, {
5485				epo: epoObject,
5486				currentCart: currentCart,
5487				obj: obj,
5488				qtyElement: qtyElement
5489			} );
5490			quantityRepeaters = obj.find( '.tc-repeater-quantity' );
5491			quantityRepeaters
5492				.toArray()
5493				.forEach( function( repeater, qx ) {
5494					var el = $( repeater );
5495					var tmEpoField;
5496					var repeaterElement;
5497					var length;
5498
5499					if ( el.data( 'tc-repeater-init' ) ) {
5500						return;
5501					}
5502					repeaterElement = el.find( '.tc-repeater-element' );
5503					length = repeaterElement.length;
5504					tmEpoField = repeaterElement.first().find( '.tm-epo-field' );
5505					if ( tmEpoField.is( ':checkbox' ) ) {
5506						el.data( 'repeater-init-value',
5507							tmEpoField.filter( ':checked' ).toArray().map( function( x ) {
5508								return $( x ).val();
5509							} ) );
5510					} else if ( tmEpoField.is( ':radio' ) ) {
5511						el.data( 'repeater-init-value', tmEpoField.filter( ':checked' ).val() );
5512					} else {
5513						el.data( 'repeater-init-value', tmEpoField.val() );
5514					}
5515					el.data( 'tc-repeater-init', length );
5516					el.data( 'tc-repeater-id', tmEpoField.attr( 'id' ) );
5517					el.data( 'tc-repeater-name', tmEpoField.attr( 'name' ) );
5518
5519					if ( qtyElement.length ) {
5520						qtyElement
5521							.off( 'change.r' + qx + 'cpf input.r' + qx + 'cpf' )
5522							.on( 'change.r' + qx + 'cpf input.r' + qx + 'cpf', function( event ) {
5523								var field = $( this );
5524								var prevValue = field.data( 'tm-prev-value' );
5525								var value = $.epoAPI.applyFilter( 'qtyElementForRepeaterQuantityValue', field.val(), {
5526									epo: epoObject,
5527									currentCart: currentCart,
5528									obj: obj,
5529									qtyElement: qtyElement,
5530									field: field
5531								} );
5532								var difference = value - prevValue;
5533								var elementInnerWrap;
5534								var thisRepeaterElement;
5535								var i;
5536								var ele;
5537								var cloned;
5538								var repeaterLast;
5539								var repeaterLastUL;
5540								var fieldprevval;
5541								if ( prevValue === undefined ) {
5542									prevValue = value - 1;
5543									difference = value - prevValue;
5544								}
5545								if ( event.isTrigger !== undefined ) {
5546									prevValue = el.find( '.tc-element-inner-wrap' ).find( '.tc-repeater-element' ).length;
5547									difference = value - prevValue;
5548								}
5549								if ( difference === 0 ) {
5550									return;
5551								}
5552								elementInnerWrap = el.find( '.tc-element-inner-wrap' );
5553								fieldprevval = $.epoAPI.applyFilter( 'qtyElementForRepeaterQuantity_tm-prev-value', field.val(), {
5554									epo: epoObject,
5555									currentCart: currentCart,
5556									obj: obj,
5557									qtyElement: qtyElement,
5558									field: field
5559								} );
5560								if ( fieldprevval <= 0 ) {
5561									fieldprevval = 1;
5562								}
5563								if ( qx === quantityRepeaters.length ) {
5564									field.data( 'tm-prev-value', fieldprevval );
5565								}
5566								if ( difference > 0 ) {
5567									thisRepeaterElement = elementInnerWrap.find( '.tc-repeater-element' ).eq( value - 1 );
5568									if ( thisRepeaterElement.length ) {
5569										return;
5570									}
5571									for ( i = 0; i < difference; i++ ) {
5572										cloned = repeaterAdd( el, elementInnerWrap );
5573										if ( cloned ) {
5574											if ( ele ) {
5575												ele = ele.add( cloned[ 0 ] );
5576											} else {
5577												ele = cloned[ 0 ];
5578											}
5579											if ( i === 0 ) {
5580												repeaterLast = cloned[ 1 ];
5581												repeaterLastUL = cloned[ 2 ];
5582											}
5583										}
5584									}
5585									if ( ele ) {
5586										ele.appendTo( elementInnerWrap.find( '.tc-element-container' ) );
5587										repeaterAddAfter( epoObject, ele, repeaterLast, repeaterLastUL );
5588									}
5589								} else {
5590									for ( i = value - difference; i > value; i -= 1 ) {
5591										thisRepeaterElement = elementInnerWrap.find( '.tc-repeater-element' ).eq( i - 1 );
5592										repeaterDelete( elementInnerWrap, thisRepeaterElement, el );
5593									}
5594								}
5595								currentCart.trigger( {
5596									type: 'tm-epo-update',
5597									norules: 2
5598								} );
5599							} );
5600						qtyElement.data( 'tm-prev-value', $.epoAPI.applyFilter( 'qtyElementForRepeaterQuantityValue', qtyElement.val(), {
5601							epo: epoObject,
5602							currentCart: currentCart,
5603							obj: obj,
5604							qtyElement: qtyElement,
5605							field: qtyElement
5606						} ) ).trigger( 'change' );
5607					}
5608				} );
5609
5610			obj.find( '.tc-repeater-add' )
5611				.toArray()
5612				.forEach( function( repeater ) {
5613					var el = $( repeater );
5614					var tmEpoField;
5615					var elementInnerWrap;
5616					var repeaterElement;
5617					var length;
5618					if ( el.data( 'tc-repeater-init' ) ) {
5619						return;
5620					}
5621					elementInnerWrap = el.closest( '.tc-element-inner-wrap' );
5622					repeaterElement = elementInnerWrap.find( '.tc-repeater-element' );
5623					length = repeaterElement.length;
5624					tmEpoField = repeaterElement.first().find( '.tm-epo-field' );
5625					if ( elementInnerWrap.find( '.tc-repeater-element' ).length > 1 ) {
5626						elementInnerWrap.find( '.tc-repeater-delete' ).removeClass( 'tc-hidden' );
5627					}
5628					if ( tmEpoField.is( ':checkbox' ) ) {
5629						el.data( 'repeater-init-value',
5630							tmEpoField.filter( ':checked' ).toArray().map( function( x ) {
5631								return $( x ).val();
5632							} ) );
5633					} else if ( tmEpoField.is( ':radio' ) ) {
5634						el.data( 'repeater-init-value', tmEpoField.filter( ':checked' ).val() );
5635					} else {
5636						el.data( 'repeater-init-value', tmEpoField.val() );
5637					}
5638					el.data( 'tc-repeater-init', length );
5639					el.data( 'tc-repeater-id', tmEpoField.attr( 'id' ) );
5640					el.data( 'tc-repeater-name', tmEpoField.attr( 'name' ) );
5641
5642					el.on( 'click.repeater', function() {
5643						var ele = repeaterAdd( el, elementInnerWrap );
5644						if ( ele ) {
5645							ele[ 0 ].appendTo( elementInnerWrap.find( '.tc-element-container' ) );
5646							repeaterAddAfter( epoObject, ele[ 0 ], ele[ 1 ], ele[ 2 ], true );
5647						}
5648					} );
5649				} );
5650
5651			obj.find( '.tc-repeater-delete .delete' ).on( 'click', function() {
5652				var $this = $( this );
5653				var elementInnerWrap = $this.closest( '.tc-element-inner-wrap' );
5654				var repeaterElement = $this.closest( '.tc-repeater-element' );
5655				repeaterDelete( elementInnerWrap, repeaterElement, elementInnerWrap.find( '.tc-repeater-add' ), $this );
5656			} );
5657		}
5658	}
5659
5660	function tm_set_color_pickers( obj ) {
5661		if ( ! obj ) {
5662			return;
5663		}
5664		obj = $( obj ).find( '.tm-color-picker' );
5665		if ( obj.length ) {
5666			obj.spectrum( {
5667				type: 'color',
5668				theme: 'epo',
5669				showButtons: true,
5670				allowEmpty: true,
5671				showInitial: true,
5672				showInput: true,
5673				clickoutFiresChange: false,
5674				chooseText: TMEPOJS.closeText,
5675				cancelText: TMEPOJS.i18n_cancel
5676			} );
5677			obj.spectrum( 'enable' );
5678		}
5679	}
5680
5681	function tm_set_lightbox( obj ) {
5682		if ( ! obj ) {
5683			return;
5684		}
5685		if ( $( obj ).length ) {
5686			// document ready
5687			$( function() {
5688				$( obj ).tclightbox();
5689			} );
5690		}
5691	}
5692
5693	function has_active_changes_product_image( field ) {
5694		var uic = field.closest( '.tmcp-field-wrap' ).find( 'label img' );
5695		var src = $( uic ).first().attr( 'data-original' );
5696
5697		if ( field.is( 'select.tm-product-image' ) ) {
5698			field = field.children( 'option:selected' );
5699		}
5700
5701		if ( ! src ) {
5702			src = $( uic ).first().attr( 'src' );
5703		}
5704		if ( ! src ) {
5705			src = field.attr( 'data-image' );
5706		}
5707		if ( field.attr( 'data-imagep' ) ) {
5708			src = field.attr( 'data-imagep' );
5709		}
5710		if ( src ) {
5711			return true;
5712		}
5713
5714		return false;
5715	}
5716
5717	function tm_set_upload_fields( epoObject ) {
5718		var field;
5719		var dT;
5720		var name;
5721		var file;
5722		var selector = epoObject.is_associated
5723			? epoObject.this_epo_container.find( '.tm-epo-field.tmcp-upload' )
5724			: epoObject.this_epo_container.find( '.tm-epo-field.tmcp-upload' ).not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector + ' .tm-epo-field.tmcp-upload' );
5725
5726		try {
5727			selector
5728				.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector + ' .tm-epo-field.tmcp-upload' )
5729				.toArray()
5730				.forEach( function( el ) {
5731					var dataFiles;
5732					var dataFilename;
5733					file = [];
5734					field = $( el );
5735					if ( field.attr( 'data-file' ) === '' ) {
5736						return false;
5737					}
5738					dataFiles = field.attr( 'data-file' ).split( '|' );
5739					if ( dataFiles.length === 0 ) {
5740						return false;
5741					}
5742					if ( ClipboardEvent || DataTransfer ) {
5743						dT = new ClipboardEvent( '' ).clipboardData || new DataTransfer();
5744					}
5745					dataFiles.forEach( function( dataFile ) {
5746						dataFilename = $.epoAPI.util.basename( dataFile );
5747						if ( ClipboardEvent || DataTransfer ) {
5748							dT.items.add( new File( [ dataFile ], dataFilename ) );
5749						}
5750						file.push( dataFile );
5751					} );
5752					if ( dT ) {
5753						el.files = dT.files;
5754					}
5755					file = file.join( '|' );
5756					name = field.attr( 'name' );
5757					field.trigger( 'tcupload' );
5758					field.after( '<input type="hidden" class="tmcp-upload-hidden" name="' + name + '" value="' + file + '">' );
5759					field.removeAttr( 'data-file' );
5760				} );
5761		} catch ( err ) {
5762			window.console.log( err );
5763			$( '.tm-epo-field.tmcp-upload' ).not( '.tm-multiple-file-upload' ).addClass( 'tc-nodt' );
5764			errorObject = err;
5765		}
5766	}
5767
5768	function tm_set_upload_rules( epoObject ) {
5769		var epoEventId = epoObject.epoEventId;
5770		var this_epo_container = epoObject.this_epo_container;
5771
5772		if ( TMEPOJS.tm_epo_upload_popup === 'yes' ) {
5773			$.tcepo.formSubmitEvents[ epoEventId ][ $.tcepo.formSubmitEvents[ epoEventId ].length ] = {
5774				trigger: function() {
5775					return true;
5776				},
5777				on_true: function() {
5778					var upload_fields = this_epo_container.data( 'num_uploads' );
5779					var thisPopup;
5780					var ajaxSuccessFunc;
5781					if ( upload_fields && Object.keys( upload_fields ).length ) {
5782						thisPopup = $.tcFloatBox( {
5783							fps: 1,
5784							ismodal: true,
5785							refresh: 'fixed',
5786							width: '50%',
5787							height: '300px',
5788							classname: 'flasho tc-wrapper',
5789							data: $.epoAPI.template.html( tcAPI.templateEngine.tc_upload_messages, {
5790								files: upload_fields,
5791								title: TMEPOJS.i18n_uploading_files,
5792								message: TMEPOJS.i18n_uploading_message
5793							} )
5794						} );
5795						ajaxSuccessFunc = function() {
5796							thisPopup.destroy();
5797							jDocument.off( 'ajaxSuccess', ajaxSuccessFunc );
5798						};
5799						jDocument.on( 'ajaxSuccess', ajaxSuccessFunc );
5800					}
5801
5802					return true;
5803				},
5804				on_false: function() {
5805					return true;
5806				}
5807			};
5808		}
5809	}
5810
5811	function tm_set_checkboxes_rules( epoObject ) {
5812		var this_epo_container = epoObject.this_epo_container;
5813		var main_product = epoObject.main_product;
5814		var epoEventId = epoObject.epoEventId;
5815		var limit_cont = this_epo_container.find( '.tm-limit' );
5816		var exactlimit_cont = this_epo_container.find( '.tm-exactlimit' );
5817		var minimumlimit_cont = this_epo_container.find( '.tm-minimumlimit' );
5818
5819		// Limit checkbox selection
5820		this_epo_container.on( 'change.cpflimit', 'input.tm-epo-field.tmcp-checkbox', function() {
5821			var $this = $( this );
5822			tm_limit_c_selection( $this, true );
5823			tm_exact_c_selection( $this, true );
5824		} );
5825		if ( limit_cont.length ) {
5826			tm_check_limit_cont( limit_cont, main_product, epoEventId );
5827		}
5828
5829		// Exact value checkbox check (Todo:check for isvisible)
5830		if ( exactlimit_cont.length ) {
5831			tm_check_exactlimit_cont( exactlimit_cont, main_product, epoEventId );
5832		}
5833
5834		// Minimum number checkbox check (Todo:check for isvisible)
5835		if ( minimumlimit_cont.length ) {
5836			tm_check_minimumlimit_cont( minimumlimit_cont, epoEventId );
5837		}
5838	}
5839
5840	function tm_theme_specific_actions( epoObject ) {
5841		var this_epo_container = epoObject.this_epo_container;
5842		var theme_name = TMEPOJS.theme_name;
5843		var all_epo_selects;
5844		var blaszok_selects;
5845
5846		if ( theme_name ) {
5847			theme_name = theme_name.toLowerCase();
5848			all_epo_selects = this_epo_container.find( 'select' );
5849
5850			switch ( theme_name ) {
5851				case 'flatsome':
5852				case 'flatsome-child':
5853				case 'flatsome child':
5854					all_epo_selects.wrap( '<div class="custom select-wrapper"/>' );
5855					break;
5856
5857				case 'avada':
5858				case 'avada-child':
5859				case 'avada child':
5860					all_epo_selects.wrap( '<div class="avada-select-parent tm-select-parent"></div>' );
5861					$( '<div class="select-arrow">&#xe61f;</div>' ).appendTo( this_epo_container.find( '.tm-select-parent' ) );
5862					if ( window.calc_select_arrow_dimensions ) {
5863						window.calc_select_arrow_dimensions();
5864						jWindow.on( 'tmsectionpoplink cpflogicdone', function() {
5865							window.calc_select_arrow_dimensions();
5866						} );
5867					} else if ( window.calcSelectArrowDimensions ) {
5868						window.calcSelectArrowDimensions();
5869						jWindow.on( 'tmsectionpoplink cpflogicdone', function() {
5870							window.calcSelectArrowDimensions();
5871						} );
5872					}
5873					break;
5874
5875				case 'bazar':
5876				case 'bazar-child':
5877				case 'bazar child':
5878					all_epo_selects.wrap( '<div class="tm-select-wrapper select-wrapper"/>' );
5879					break;
5880
5881				case 'blaszok':
5882				case 'blaszok-child':
5883				case 'blaszok child':
5884					blaszok_selects = function() {
5885						setTimeout( function() {
5886							$( '.tm-extra-product-options select' )
5887								.not( '.hasCustomSelect' )
5888								.filter( ':visible' )
5889								.each( function() {
5890									if ( ! $( this ).is( '.mpcthSelect' ) ) {
5891										$( this ).width( $( this ).outerWidth() );
5892										$( this ).customSelect( { customClass: 'mpcthSelect' } );
5893									}
5894								} );
5895						}, 100 );
5896					};
5897					jWindow.on( 'cpflogicrun', function() {
5898						blaszok_selects();
5899					} );
5900					jWindow.on( 'epo_options_visible', function() {
5901						blaszok_selects();
5902					} );
5903
5904					break;
5905
5906				case 'handmade':
5907				case 'handmade child theme':
5908					$( '.tm-owl-slider.tcowl-carousel' ).addClass( 'manual' );
5909					break;
5910			}
5911
5912			jWindow.trigger( 'tm-theme-specific-actions', {
5913				epo: {
5914					theme_name: theme_name,
5915					all_epo_selects: all_epo_selects
5916				}
5917			} );
5918		}
5919
5920		// Fix added +/- quantity button on most themes.
5921		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() {
5922			$( this ).closest( '.quantity' ).find( tcAPI.qtySelector ).trigger( 'change.cpf' );
5923		} );
5924	}
5925
5926	function tm_custom_variations( epoObject, form, item_id, $main_product, $epo_holder ) {
5927		var epoEventId = epoObject.epoEventId;
5928		var variation_id_selector = "input[name^='variation_id']";
5929		var tm_epo_variation_section;
5930		var li_variations;
5931		var composite_load_test;
5932		var form_event;
5933		var type;
5934		var name;
5935		var selector;
5936		var func;
5937		var i;
5938		var eventName = epoObject.is_associated ? 'tc_variation_form.tmlogic' : 'wc_variation_form.tmlogic';
5939		var eventNamePrefix = epoObject.is_associated ? 'tc_' : '';
5940		var variationsForm = epoObject.variations_form;
5941		var variationsTable = epoObject.is_associated ? variationsForm.find( '.tc-epo-element-variations' ) : variationsForm.find( '.variations' );
5942		var resetSelector = epoObject.is_associated ? '.tc-epo-element-variable-reset-variations' : '.reset_variations';
5943
5944		variationsForm.attr( 'data-epo_id', epoObject.epo_id );
5945
5946		if ( form.find( 'input.variation_id' ).length > 0 ) {
5947			variation_id_selector = 'input.variation_id';
5948		}
5949		if ( $epo_holder.find( '.tm-epo-variation-element' ).length || $epo_holder.data( 'tm-epo-variation-element' ) ) {
5950			tm_epo_variation_section = $epo_holder.find( '.tm-epo-variation-section' ).first();
5951			tm_epo_variation_section.find( '.cpf-type-variations' ).attr( 'data-epo_id', epoObject.epo_id ).attr( 'data-product_id', variationsForm.attr( 'data-product_id' ) );
5952
5953			$epo_holder.data( 'tm-epo-variation-element', tm_epo_variation_section.find( '.tm-epo-variation-element' ) );
5954
5955			if ( item_id && item_id !== 'main' && ! epoObject.is_associated ) {
5956				// on composite
5957
5958				variationsForm = epoObject.form;
5959				variationsTable = variationsForm.find( '.composite_component[data-item_id="' + item_id + '"]' ).find( '.variations' );
5960				variationsForm.attr( 'data-epo_id', epoObject.epo_id );
5961
5962				if ( variationsTable.length === 0 ) {
5963					return;
5964				}
5965
5966				li_variations = tm_epo_variation_section.closest( 'li.tm-extra-product-options-field' );
5967				if ( ! tm_epo_variation_section.is( '.tm-hidden' ) ) {
5968					variationsTable.hide();
5969				}
5970
5971				variationsTable.after( tm_epo_variation_section.addClass( 'tm-extra-product-options nopadding' ) );
5972				if ( li_variations.is( ':empty' ) ) {
5973					li_variations.hide();
5974				}
5975
5976				if ( ! tm_epo_variation_section.is( '.section_popup' ) ) {
5977					tm_epo_variation_section.removeClass( 'tc-cell' );
5978					tm_epo_variation_section.wrap( "<div class='tc-styled-variations'></div>" );
5979				} else {
5980					tm_epo_variation_section.wrap( "<div class='tc-styled-variations tc-row'></div>" );
5981				}
5982
5983				composite_load_test = false;
5984				form.off( eventName ).on( eventName, function() {
5985					composite_load_test = true;
5986					variationsForm.on( 'click.tmlogic', '.reset_variations', function() {
5987						tm_epo_variation_section.find( 'select.tm-epo-variation-element' ).val( '' ).children( 'option' ).prop( 'disabled', false ).show();
5988						tm_epo_variation_section.find( '.tm-epo-variation-element' ).prop( 'disabled', false ).removeClass( 'tm-disabled' ).prop( 'checked', false ).closest( 'li' ).show();
5989						jWindow.trigger( 'tmlazy' );
5990						tm_epo_variation_section.find( '.tm-epo-variation-element' ).trigger( 'tm_trigger_product_image' );
5991						tm_epo_variation_section.find( 'li' ).removeClass( 'tc-active tm-attribute-disabled' ).css( 'opacity', '' );
5992					} );
5993
5994					// Disable option fields that are unavaiable for current set of attributes
5995					form.off( 'woocommerce_update_variation_values_tmlogic' ).on( 'woocommerce_update_variation_values_tmlogic', function() {
5996						tm_custom_variations_update( form, epoObject );
5997					} );
5998					for ( i = 0; i < lateVariationEvent.length; i += 1 ) {
5999						form_event = lateVariationEvent[ i ];
6000						type = typeof form_event;
6001						if ( type === 'object' ) {
6002							name = typeof form_event.name === 'string' || false;
6003							selector = typeof form_event.selector === 'string' || false;
6004							func = typeof form_event.func === 'function' || false;
6005							if ( name && func ) {
6006								if ( selector === "input[name='variation_id']" ) {
6007									selector = variation_id_selector;
6008								}
6009								if ( form_event.selector ) {
6010									form.data( 'tm-styled-variations', 1 )
6011										.off( eventNamePrefix + form_event.name + i, selector )
6012										.on( eventNamePrefix + form_event.name + i, selector, form_event.func );
6013								} else {
6014									form.data( 'tm-styled-variations', 1 )
6015										.off( eventNamePrefix + form_event.name + i )
6016										.on( eventNamePrefix + form_event.name + i, form_event.func );
6017								}
6018							}
6019						}
6020					}
6021					lateVariationEvent = [];
6022					tm_epo_variation_section.find( '.tm-epo-variation-element:not(.tm-hidden .tm-epo-variation-element)' ).last().trigger( 'tm_epo_variation_element_change' );
6023				} );
6024				// document ready
6025				$( function() {
6026					if ( composite_load_test === false ) {
6027						form.trigger( eventName );
6028					}
6029				} );
6030			} else {
6031				if ( tm_epo_variation_section.length ) {
6032					if ( ! tm_epo_variation_section.is( '.tm-hidden' ) ) {
6033						variationsTable.hide();
6034					}
6035
6036					li_variations = tm_epo_variation_section.closest( 'li.tm-extra-product-options-field' );
6037
6038					variationsTable.after( tm_epo_variation_section.addClass( 'tm-extra-product-options nopadding' ) );
6039					if ( li_variations.is( ':empty' ) ) {
6040						li_variations.hide();
6041					}
6042
6043					if ( ! tm_epo_variation_section.is( '.section_popup' ) ) {
6044						tm_epo_variation_section.removeClass( 'tc-cell' );
6045						tm_epo_variation_section.wrap( "<div class='tc-styled-variations'></div>" );
6046					} else {
6047						tm_epo_variation_section.wrap( "<div class='tc-styled-variations tc-row'></div>" );
6048					}
6049
6050					variationsForm.off( 'click.tmlogic', resetSelector ).on( 'click.tmlogic', resetSelector, function() {
6051						tm_epo_variation_section.find( 'select.tm-epo-variation-element' ).val( '' ).children( 'option' ).prop( 'disabled', false ).show();
6052						tm_epo_variation_section.find( '.tm-epo-variation-element' ).prop( 'disabled', false ).removeClass( 'tm-disabled' ).prop( 'checked', false ).closest( 'li' ).show();
6053						jWindow.trigger( 'tmlazy' );
6054						tm_epo_variation_section.find( '.tm-epo-variation-element' ).trigger( 'tm_trigger_product_image' );
6055						tm_epo_variation_section.find( 'li' ).removeClass( 'tc-active tm-attribute-disabled' ).css( 'opacity', '' );
6056					} );
6057				}
6058
6059				// Disable option fields that are unavaiable for current set of attributes
6060				variationsForm.off( 'woocommerce_update_variation_values_tmlogic' ).on( 'woocommerce_update_variation_values_tmlogic', function() {
6061					tm_custom_variations_update( variationsForm, epoObject );
6062				} );
6063
6064				for ( i = 0; i < lateVariationEvent.length; i += 1 ) {
6065					form_event = lateVariationEvent[ i ];
6066					type = typeof form_event;
6067					if ( type === 'object' ) {
6068						name = typeof form_event.name === 'string' || false;
6069						selector = typeof form_event.selector === 'string' || false;
6070						func = typeof form_event.func === 'function' || false;
6071						if ( name && func ) {
6072							if ( selector === "input[name='variation_id']" ) {
6073								selector = variation_id_selector;
6074							}
6075							if ( form_event.selector ) {
6076								variationsForm
6077									.data( 'tm-styled-variations', 1 )
6078									.off( eventNamePrefix + form_event.name + i, selector )
6079									.on( eventNamePrefix + form_event.name + i, selector, form_event.func );
6080							} else {
6081								variationsForm
6082									.data( 'tm-styled-variations', 1 )
6083									.off( eventNamePrefix + form_event.name + i )
6084									.on( eventNamePrefix + form_event.name + i, form_event.func );
6085							}
6086						}
6087					}
6088				}
6089				lateVariationEvent = [];
6090				tm_epo_variation_section.find( '.tm-epo-variation-element:not(.tm-hidden .tm-epo-variation-element)' ).last().trigger( 'tm_epo_variation_element_change' );
6091			}
6092
6093			// global event for custom variations
6094			$.tcepo.formSubmitEvents[ epoEventId ][ $.tcepo.formSubmitEvents[ epoEventId ].length ] = {
6095				trigger: function() {
6096					return true;
6097				},
6098				on_true: function() {
6099					tm_epo_variation_section.find( '.tm-epo-variation-element' ).attr( 'disabled', 'disabled' );
6100					return true;
6101				},
6102				on_false: function() {
6103					tm_epo_variation_section.find( '.tm-epo-variation-element' ).prop( 'disabled', false );
6104				}
6105			};
6106
6107			$( document.body ).on( 'added_to_cart', function() {
6108				tm_epo_variation_section.find( '.tm-epo-variation-element' ).prop( 'disabled', false );
6109			} );
6110		}
6111	}
6112
6113	function repopulate_backup_image_atts( img, product_element ) {
6114		var $gallery_img = product_element.find( '.flex-control-nav li:eq(0) img' );
6115		var $gallery_wrapper = product_element.find( '.woocommerce-product-gallery__wrapper ' );
6116		var $product_img_wrap = $gallery_wrapper.find( '.woocommerce-product-gallery__image, .woocommerce-product-gallery__image--placeholder' ).eq( 0 );
6117		var $product_img = img;
6118		var $product_link = img.closest( 'a' );
6119
6120		$product_img.attr( 'data-o_' + 'src', $.tc_product_image_store[ 0 ].src );
6121		$product_img.attr( 'data-o_' + 'srcset', $.tc_product_image_store[ 0 ].srcset );
6122		$product_img.attr( 'data-o_' + 'sizes', $.tc_product_image_store[ 0 ].sizes );
6123		$product_img.attr( 'data-o_' + 'title', $.tc_product_image_store[ 0 ].title );
6124		$product_img.attr( 'data-o_' + 'alt', $.tc_product_image_store[ 0 ].alt );
6125		$product_img.attr( 'data-o_' + 'data-src', $.tc_product_image_store[ 0 ][ 'data-src' ] );
6126		$product_img.attr( 'data-o_' + 'data-large_image', $.tc_product_image_store[ 0 ][ 'data-large_image' ] );
6127		$product_img.attr( 'data-o_' + 'data-large_image_width', $.tc_product_image_store[ 0 ][ 'data-large_image_width' ] );
6128		$product_img.attr( 'data-o_' + 'data-large_image_height', $.tc_product_image_store[ 0 ][ 'data-large_image_height' ] );
6129		$product_img_wrap.attr( 'data-o_' + 'data-thumb', $.tc_product_image_store[ 1 ][ 'data-thumb' ] );
6130		if ( $.tc_product_image_store[ 2 ] ) {
6131			$gallery_img.attr( 'data-o_' + 'src', $.tc_product_image_store[ 2 ].src );
6132		}
6133
6134		$product_link.attr( 'data-o_' + 'href', $.tc_product_image_store[ 3 ].href );
6135		$product_link.attr( 'data-o_' + 'title', $.tc_product_image_store[ 3 ].title );
6136	}
6137
6138	function reset_saved_image( img, product_element ) {
6139		var $gallery_img = product_element.find( '.flex-control-nav li:eq(0) img' );
6140		var $gallery_wrapper = product_element.find( '.woocommerce-product-gallery__wrapper ' );
6141		var $product_img_wrap = $gallery_wrapper.find( '.woocommerce-product-gallery__image, .woocommerce-product-gallery__image--placeholder' ).eq( 0 );
6142		var $product_img = img;
6143		var $product_link = img.closest( 'a' );
6144
6145		// backup current product image attributes
6146		if ( ! $.isEmptyObject( $.tc_product_image ) ) {
6147			$.tc_product_image_store = $.tc_pre_populate_store();
6148			$.tc_product_image_store = $.tc_maybe_copy_object_values( $.tc_product_image_store, $.tc_product_image );
6149		} else {
6150			$.tc_product_image_store = $.tc_populate_store( img, product_element );
6151		}
6152
6153		$product_img.tc_update_attr( 'src', 0 );
6154		$product_img.tc_update_attr( 'srcset', 0 );
6155		$product_img.tc_update_attr( 'sizes', 0 );
6156		$product_img.tc_update_attr( 'title', 0 );
6157		$product_img.tc_update_attr( 'alt', 0 );
6158		$product_img.tc_update_attr( 'data-src', 0 );
6159		$product_img.tc_update_attr( 'data-large_image', 0 );
6160		$product_img.tc_update_attr( 'data-large_image_width', 0 );
6161		$product_img.tc_update_attr( 'data-large_image_height', 0 );
6162		$product_img_wrap.tc_update_attr( 'data-thumb', 1 );
6163		$gallery_img.tc_update_attr( 'src', 2 );
6164
6165		$product_link.tc_update_attr( 'href', 3 );
6166		$product_link.tc_update_attr( 'title', 3 );
6167	}
6168
6169	function image_update( data, img, product_element ) {
6170		var $gallery_img = product_element.find( '.flex-control-nav li:eq(0) img' );
6171		var $gallery_wrapper = product_element.find( '.woocommerce-product-gallery__wrapper ' );
6172		var $product_img_wrap = $gallery_wrapper.find( '.woocommerce-product-gallery__image, .woocommerce-product-gallery__image--placeholder' ).eq( 0 );
6173		var $product_img = img;
6174		var $product_link = img.closest( 'a' );
6175		var $img_zoom = $product_link.next( '.zoomImg' );
6176
6177		if ( data && data.image_link && data.image_link && data.image_link.length > 1 ) {
6178			if ( data.full_src === null || data.full_src === '' ) {
6179				data.full_src = data.image_link;
6180			}
6181			if ( data.full_src_w === null || data.full_src_w === '' ) {
6182				data.full_src_w = $product_img.attr( 'data-large_image_width' );
6183			}
6184			if ( data.full_src_h === null || data.full_src_h === '' ) {
6185				data.full_src_h = $product_img.attr( 'data-large_image_height' );
6186			}
6187			if ( $product_img.length ) {
6188				if ( ! data.image_srcset ) {
6189					data.image_sizes = false;
6190				}
6191				if ( ! data.image_sizes ) {
6192					data.image_srcset = false;
6193				}
6194				$product_img.tc_set_attr( 'src', data.image_link, 0 );
6195				$product_img.tc_set_attr( 'srcset', data.image_srcset, 0 );
6196				$product_img.tc_set_attr( 'sizes', data.image_sizes, 0 );
6197				$product_img.tc_set_attr( 'title', data.image_title, 0 );
6198				$product_img.tc_set_attr( 'alt', data.image_alt, 0 );
6199				$product_img.tc_set_attr( 'data-src', data.full_src, 0 );
6200				$product_img.tc_set_attr( 'data-large_image', data.full_src, 0 );
6201				$product_img.tc_set_attr( 'data-large_image_width', data.full_src_w, 0 );
6202				$product_img.tc_set_attr( 'data-large_image_height', data.full_src_h, 0 );
6203				$product_img_wrap.tc_set_attr( 'data-thumb', data.image_link, 1 );
6204			}
6205			if ( $gallery_img.length ) {
6206				$gallery_img.tc_set_attr( 'src', data.image_link, 2 );
6207			}
6208			if ( $product_link.length ) {
6209				$product_link.tc_set_attr( 'href', data.full_src, 3 );
6210				$product_link.tc_set_attr( 'title', data.image_caption, 3 );
6211			}
6212			if ( $img_zoom.length ) {
6213				$img_zoom.tc_set_attr( 'src', data.full_src, 4 );
6214			}
6215		} else {
6216			if ( $product_img.length ) {
6217				$product_img.tc_reset_attr( 'src', 0 );
6218				$product_img.tc_reset_attr( 'srcset', 0 );
6219				$product_img.tc_reset_attr( 'sizes', 0 );
6220				$product_img.tc_reset_attr( 'title', 0 );
6221				$product_img.tc_reset_attr( 'alt', 0 );
6222				$product_img.tc_reset_attr( 'data-src', 0 );
6223				$product_img.tc_reset_attr( 'data-large_image', 0 );
6224				$product_img.tc_reset_attr( 'data-large_image_width', 0 );
6225				$product_img.tc_reset_attr( 'data-large_image_height', 0 );
6226				$product_img_wrap.tc_reset_attr( 'data-thumb', 1 );
6227			}
6228			if ( $gallery_img.length ) {
6229				$gallery_img.tc_reset_attr( 'src', 2 );
6230			}
6231			if ( $product_link.length ) {
6232				$product_link.tc_reset_attr( 'href', 3 );
6233				$product_link.tc_reset_attr( 'title', 3 );
6234			}
6235			if ( $img_zoom.length ) {
6236				$img_zoom.tc_reset_attr( 'src', 4 );
6237			}
6238		}
6239	}
6240
6241	function get_main_product_image( epoObject, product_element ) {
6242		var img;
6243
6244		if ( epoObject.is_associated ) {
6245			img = product_element.find( '.tc-product-image .wp-post-image' ).first();
6246		} else if ( TMEPOJS.tm_epo_global_product_image_selector !== '' ) {
6247			img = $( TMEPOJS.tm_epo_global_product_image_selector );
6248		} else {
6249			img = product_element.find( '.woocommerce-product-gallery__image:not(.clone), .woocommerce-product-gallery__image--placeholder:not(.clone)' ).eq( 0 ).find( '.wp-post-image' ).first();
6250			if ( img.length === 0 ) {
6251				img = product_element.find( 'a.woocommerce-main-image img, img.woocommerce-main-image,a img' ).not( '.thumbnails img,.product_list_widget img' ).first();
6252			}
6253			if ( img.length === 0 ) {
6254				img = product_element.find( 'img.wp-post-image' ).not( '.thumbnails img,.product_list_widget img' ).first();
6255			}
6256			if ( img.length === 0 ) {
6257				img = product_element.find( '.elementor-widget-wd_single_product_gallery img.wp-post-image' ).first();
6258			}
6259			if ( img.length === 0 ) {
6260				img = product_element.find( '.elementor-widget-ae-post-image .wp-post-image' ).first();
6261			}
6262			if ( img.length === 0 ) {
6263				img = $( '.woocommerce div.product div.images' ).not( '.thumbnails img,.product_list_widget img' ).first();
6264			}
6265		}
6266
6267		if ( $( img ).length > 1 ) {
6268			img = $( img ).first();
6269		}
6270
6271		return img;
6272	}
6273
6274	function get_product_element( epoObject ) {
6275		var main_product;
6276		var product_id;
6277		var product_element;
6278
6279		if ( epoObject.is_associated ) {
6280			return epoObject.main_product.closest( '.tc-epo-element-product-container' );
6281		}
6282
6283		main_product = epoObject.main_product;
6284		product_id = epoObject.product_id;
6285		product_element = main_product.closest( '#product-' + product_id );
6286
6287		if ( product_element.length <= 0 ) {
6288			product_element = main_product.closest( '.post-' + product_id );
6289		}
6290
6291		return product_element;
6292	}
6293
6294	function gallery_compatibility_actions( gallery_type, clone_image, preload_img, visible, event_data, $form, product_element ) {
6295		var gallery;
6296		var _elements;
6297		var ge;
6298		var galleryWidth;
6299		var zoomEnabled;
6300		var image;
6301		var zoom_options;
6302
6303		for ( gallery in gallery_type ) {
6304			if ( Object.prototype.hasOwnProperty.call( gallery_type, gallery ) ) {
6305				gallery = gallery_type[ gallery ];
6306
6307				if ( gallery.enabled ) {
6308					switch ( gallery.type ) {
6309						case 'yith':
6310							if ( ! clone_image ) {
6311								if ( ! visible ) {
6312									gallery.yith_wcmg_zoom.attr( 'href', gallery._yith_wcmg_default_zoom );
6313								} else {
6314									gallery.yith_wcmg_zoom.attr( 'href', gallery.yith_wcmg_default_zoom );
6315								}
6316								if ( gallery.element.data( 'yith_magnifier' ) ) {
6317									gallery.element.yith_magnifier( 'destroy' );
6318								}
6319
6320								gallery.element.yith_magnifier( window.yith_magnifier_options );
6321							} else {
6322								clone_image.attr( 'srcset', preload_img ).attr( 'src-orig', preload_img );
6323
6324								if ( gallery.element.data( 'yith_magnifier' ) ) {
6325									gallery.element.yith_magnifier( 'destroy' );
6326								}
6327								_elements = {
6328									elements: {
6329										zoom: $( '.yith_magnifier_zoom' ),
6330										zoomImage: clone_image,
6331										gallery: $( '.yith_magnifier_gallery li a' )
6332									}
6333								};
6334
6335								gallery.element.yith_magnifier( $.extend( true, {}, window.yith_magnifier_options, _elements ) );
6336							}
6337							break;
6338						case 'iosslider':
6339							setTimeout(
6340								function( g ) {
6341									g.element.iosSlider( 'update' );
6342								}.bind( null, gallery ),
6343								150
6344							);
6345							break;
6346						case 'flexslider':
6347							jWindow.trigger( 'resize' );
6348							break;
6349						case 'elevatezoom':
6350							gallery.element.each(
6351								function( g, j ) {
6352									var elevateZoom = j( this ).data( 'elevateZoom' );
6353									if ( typeof elevateZoom !== 'undefined' ) {
6354										elevateZoom.swaptheimage( g, g );
6355									}
6356								}.bind( null, preload_img, $ )
6357							);
6358							break;
6359						case 'easyzoom':
6360							gallery.element.swap( null, preload_img );
6361							break;
6362						case 'easyzoom-flatsome':
6363							gallery.element.swap( preload_img, preload_img );
6364							break;
6365						case 'woocommerce':
6366							gallery.element.flexslider( 0 );
6367							ge = gallery.element;
6368							window.setTimeout(
6369								function( g, w ) {
6370									g.trigger( 'woocommerce_gallery_init_zoom' );
6371									w.trigger( 'resize' );
6372								}.bind( null, ge, jWindow ),
6373								10
6374							);
6375							break;
6376						case 'zoom':
6377							if ( product_element ) {
6378								galleryWidth = product_element.find( '.woocommerce-product-gallery--with-images' ).width();
6379								zoomEnabled = false;
6380
6381								image = gallery.element.find( 'img.wp-post-image' );
6382								if ( image.attr( 'data-large_image_width' ) > galleryWidth ) {
6383									zoomEnabled = true;
6384								}
6385
6386								if ( zoomEnabled ) {
6387									zoom_options = {
6388										touch: false
6389									};
6390									if ( 'ontouchstart' in window ) {
6391										zoom_options.on = 'click';
6392									}
6393
6394									gallery.element.trigger( 'zoom.destroy' );
6395									gallery.element.zoom( zoom_options );
6396								} else {
6397									gallery.element.trigger( 'zoom.destroy' );
6398								}
6399							}
6400							break;
6401					}
6402				}
6403			}
6404		}
6405
6406		jWindow.trigger( 'tm_gallery_compatibility_actions', {
6407			event_data: event_data,
6408			product_element: product_element,
6409			form: $form
6410		} );
6411	}
6412
6413	function get_gallery_type( epoObject, img, product_element ) {
6414		// YITH WooCommerce Zoom Magnifier
6415		var is_yith_wcmg;
6416		var yith_wcmg;
6417		var yith_wcmg_zoom;
6418		var yith_wcmg_default_zoom;
6419		var _yith_wcmg_default_zoom;
6420		var yith_wcmg_default_image;
6421
6422		// iosslider - Touch Enabled, Responsive jQuery Horizontal Content
6423		// Slider/Carousel/Image Gallery Plugin
6424		var is_iosSlider;
6425		var is_iosSlider_element;
6426
6427		// ThemeFusion flexslider
6428		var is_flexslider;
6429		var is_flexslider_element;
6430
6431		// elevateZoom A Jquery Image Zoom Plugin
6432		var is_elevateZoom;
6433		var is_elevateZoom_obj;
6434
6435		// EasyZoom jQuery image zoom plugin
6436		var is_easyzoom;
6437		var is_easyzoom_element;
6438
6439		// new flatsome easyzoom
6440		var is_easyzoom_flatsome;
6441		var is_easyzoom_flatsome_element;
6442
6443		// WooCommerce 2.7x gallery
6444		var is_wc27_gallery;
6445		var is_wc27_gallery_element;
6446		var wc27_zoom_target;
6447		var wc_single_product_params;
6448		var zoom_target_temp;
6449
6450		// fn.zoom
6451		var is_zoom_enabled;
6452		var zoom_images;
6453		var gallery;
6454
6455		if ( epoObject.is_associated ) {
6456			return {};
6457		}
6458
6459		// YITH WooCommerce Zoom Magnifier
6460		is_yith_wcmg = false;
6461		yith_wcmg = $( '.images' );
6462		yith_wcmg_zoom = $( '.yith_magnifier_zoom' );
6463		yith_wcmg_default_zoom = yith_wcmg.find( '.yith_magnifier_zoom' ).first().attr( 'href' );
6464		_yith_wcmg_default_zoom = yith_wcmg_default_zoom;
6465		yith_wcmg_default_image = yith_wcmg.find( '.yith_magnifier_zoom img' ).first().attr( 'src' );
6466
6467		// iosslider - Touch Enabled, Responsive jQuery Horizontal Content
6468		// Slider/Carousel/Image Gallery Plugin
6469		is_iosSlider = false;
6470		is_iosSlider_element = $( '.iosSlider.product-gallery-slider,.iosSlider.product-slider' );
6471
6472		// ThemeFusion flexslider
6473		is_flexslider = false;
6474		is_flexslider_element = product_element.find( '.images .fusion-flexslider' );
6475
6476		// elevateZoom A Jquery Image Zoom Plugin
6477		is_elevateZoom = img.data( 'elevateZoom' ) || false;
6478		is_elevateZoom_obj = product_element.find( 'div.product-images .woocommerce-main-image' );
6479
6480		// EasyZoom jQuery image zoom plugin
6481		is_easyzoom = false;
6482		is_easyzoom_element = product_element.find( '.images .easyzoom' );
6483
6484		// new flatsome easyzoom
6485		is_easyzoom_flatsome = false;
6486		is_easyzoom_flatsome_element = product_element.find( '.images .easyzoom' );
6487
6488		// WooCommerce 2.7x gallery
6489		is_wc27_gallery = false;
6490		is_wc27_gallery_element = product_element.find( '.woocommerce-product-gallery' );
6491		wc27_zoom_target = false;
6492		wc_single_product_params = window.wc_single_product_params;
6493
6494		// fn.zoom
6495		is_zoom_enabled = typeof $.fn.zoom === 'function' && wc_single_product_params && wc_single_product_params.zoom_enabled;
6496		zoom_images = false;
6497
6498		if ( window.yith_magnifier_options && yith_wcmg.data( 'yith_magnifier' ) ) {
6499			is_yith_wcmg = true;
6500		}
6501
6502		if ( is_iosSlider_element.length && is_iosSlider_element.iosSlider ) {
6503			is_iosSlider = true;
6504		}
6505
6506		if ( is_flexslider_element.length && is_flexslider_element.flexslider ) {
6507			is_flexslider = true;
6508		}
6509
6510		if ( is_easyzoom_element.length && is_easyzoom_element.filter( '.images .easyzoom.first' ).data( 'easyZoom' ) ) {
6511			is_easyzoom_element = is_easyzoom_element.filter( '.images .easyzoom.first' ).data( 'easyZoom' );
6512			is_easyzoom = true;
6513		}
6514
6515		if ( ! is_easyzoom ) {
6516			is_easyzoom_flatsome_element = product_element.find( '.images .has-image-zoom .slide' );
6517			if ( is_easyzoom_flatsome_element.length && is_easyzoom_flatsome_element.filter( '.images .has-image-zoom .slide.first' ).data( 'easyZoom' ) ) {
6518				is_easyzoom_flatsome_element = is_easyzoom_flatsome_element.filter( '.images .has-image-zoom .slide.first' ).data( 'easyZoom' );
6519				is_easyzoom_flatsome = true;
6520			}
6521		}
6522
6523		if ( document.readyState === 'complete' ) {
6524			setTimeout( function() {
6525				if ( is_easyzoom_element.length && is_easyzoom_element.data( 'easyZoom' ) ) {
6526					is_easyzoom_element = is_easyzoom_element.data( 'easyZoom' );
6527					is_easyzoom = true;
6528				}
6529				if ( is_easyzoom_flatsome_element.length && is_easyzoom_flatsome_element.data( 'easyZoom' ) ) {
6530					is_easyzoom_flatsome_element = is_easyzoom_flatsome_element.data( 'easyZoom' );
6531					is_easyzoom_flatsome = true;
6532				}
6533			}, 150 );
6534		} else {
6535			jWindow.on( 'load', function() {
6536				setTimeout( function() {
6537					if ( is_easyzoom_element.length && is_easyzoom_element.data( 'easyZoom' ) ) {
6538						is_easyzoom_element = is_easyzoom_element.data( 'easyZoom' );
6539						is_easyzoom = true;
6540					}
6541					if ( is_easyzoom_flatsome_element.length && is_easyzoom_flatsome_element.data( 'easyZoom' ) ) {
6542						is_easyzoom_flatsome_element = is_easyzoom_flatsome_element.data( 'easyZoom' );
6543						is_easyzoom_flatsome = true;
6544					}
6545				}, 150 );
6546			} );
6547		}
6548
6549		if ( is_wc27_gallery_element.length && is_wc27_gallery_element.data( 'flexslider' ) ) {
6550			is_wc27_gallery = true;
6551
6552			if ( typeof $.fn.zoom === 'function' && wc_single_product_params && wc_single_product_params.zoom_enabled ) {
6553				zoom_target_temp = img.closest( '.woocommerce-product-gallery__image' );
6554
6555				if ( zoom_target_temp.length > 0 && img.width() > $( '.woocommerce-product-gallery' ).width() ) {
6556					wc27_zoom_target = zoom_target_temp;
6557					img.data.wc27_zoom_target = wc27_zoom_target;
6558				}
6559			}
6560		}
6561
6562		if ( ! is_wc27_gallery && is_zoom_enabled ) {
6563			zoom_images = product_element.find( '.woocommerce-product-gallery__image' );
6564		}
6565
6566		gallery = {
6567			is_yith_wcmg: {
6568				type: 'yith',
6569				enabled: is_yith_wcmg,
6570				element: yith_wcmg,
6571				yith_wcmg_zoom: yith_wcmg_zoom,
6572				_yith_wcmg_default_zoom: _yith_wcmg_default_zoom,
6573				yith_wcmg_default_image: yith_wcmg_default_image
6574			},
6575			is_iosSlider: {
6576				type: 'iosslider',
6577				enabled: is_iosSlider,
6578				element: is_iosSlider_element
6579			},
6580			is_flexslider: {
6581				type: 'flexslider',
6582				enabled: is_flexslider,
6583				element: is_flexslider_element
6584			},
6585			is_elevateZoom: {
6586				type: 'elevatezoom',
6587				enabled: is_elevateZoom,
6588				element: is_elevateZoom_obj
6589			},
6590			is_easyzoom: {
6591				type: 'easyzoom',
6592				enabled: is_easyzoom,
6593				element: is_easyzoom_element
6594			},
6595			is_easyzoom_flatsome: {
6596				type: 'easyzoom-flatsome',
6597				enabled: is_easyzoom_flatsome,
6598				element: is_easyzoom_flatsome_element
6599			},
6600			is_wc27_gallery: {
6601				type: 'woocommerce',
6602				enabled: is_wc27_gallery,
6603				element: is_wc27_gallery_element
6604			},
6605			is_zoom_enabled: {
6606				type: 'zoom',
6607				enabled: ! is_wc27_gallery && is_zoom_enabled,
6608				element: zoom_images
6609			}
6610		};
6611
6612		return gallery;
6613	}
6614
6615	function tm_product_image_self( epoObject ) {
6616		var this_epo_container = epoObject.is_associated ? epoObject.this_epo_container : epoObject.this_epo_container.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector );
6617		var variationsForm = epoObject.variations_form;
6618		var main_product = epoObject.main_product;
6619		var $form = epoObject.form;
6620		var img;
6621		var gallery_type;
6622		var product_element = get_product_element( epoObject );
6623		var last_active_field = [];
6624		var t;
6625		var el;
6626		var el_current;
6627		var imp;
6628		var selector;
6629		var eventNamePrefix = epoObject.is_associated ? 'tc_' : '';
6630		// This currently has a limitation that it doesn't work if there is variation active onload.
6631		var main_tc_product_image_store;
6632
6633		img = get_main_product_image( epoObject, product_element );
6634		gallery_type = get_gallery_type( epoObject, img, product_element );
6635
6636		if ( $( img ).length > 0 ) {
6637			$form.on( eventNamePrefix + 'reset_image.tcpi', function() {
6638				setTimeout( function() {
6639					if ( TMEPOJS.tm_epo_global_image_recalculate === 'yes' ) {
6640						img = get_main_product_image( epoObject, product_element );
6641						$.tc_product_image_store = main_tc_product_image_store;
6642					}
6643					// restore product image atts from backup
6644					$.tc_product_image = $.tc_replace_object_values( $.tc_product_image, $.tc_product_image_store );
6645
6646					last_active_field = [];
6647
6648					$( this_epo_container.find( '.tm-product-image:checked,select.tm-product-image' ) )
6649						.add( variationsForm.find( '.tm-epo-variation-section' ).first().find( '.tm-product-image:checked,select.tm-product-image' ) )
6650						.each( function() {
6651							t = $( this );
6652							if ( field_is_active( t ) && t.val() !== '' ) {
6653								last_active_field.push( t );
6654							}
6655						} );
6656					if ( last_active_field.length ) {
6657						last_active_field[ last_active_field.length - 1 ].trigger( 'tm_trigger_product_image' );
6658					} else {
6659						$.tc_product_image_store = $.tc_populate_store( img, product_element );
6660					}
6661				}, window.tc_epo_product_image_change_delay || 0 );
6662			} );
6663
6664			$form.on( eventNamePrefix + 'found_variation.tcpi', function() {
6665				setTimeout( function() {
6666					if ( TMEPOJS.tm_epo_global_image_recalculate === 'yes' ) {
6667						img = get_main_product_image( epoObject, product_element );
6668					}
6669					reset_saved_image( img, product_element );
6670
6671					last_active_field = [];
6672					$( this_epo_container.find( '.tm-product-image:checked,select.tm-product-image' ) )
6673						.add( variationsForm.find( '.tm-epo-variation-section' ).first().find( '.tm-product-image:checked,select.tm-product-image' ) )
6674						.each( function() {
6675							t = $( this );
6676							if ( field_is_active( t ) && t.val() !== '' ) {
6677								last_active_field.push( t );
6678							}
6679						} );
6680					if ( last_active_field.length ) {
6681						repopulate_backup_image_atts( img, product_element );
6682						last_active_field[ last_active_field.length - 1 ].trigger( 'tm_trigger_product_image' );
6683					}
6684				}, window.tc_epo_product_image_change_delay || 0 );
6685			} );
6686
6687			$.tc_product_image_store = $.tc_maybe_copy_object_values_from_img( $.tc_product_image_store, img, product_element );
6688			main_tc_product_image_store = $.epoAPI.util.deepCopyArray( $.tc_product_image_store );
6689
6690			main_product.off( 'tm_change_product_image' ).on( 'tm_change_product_image', function( evt, event_data ) {
6691				var data;
6692				evt.stopImmediatePropagation();
6693
6694				el = event_data.element;
6695				el_current = event_data.element_current;
6696				if ( el && el_current ) {
6697					imp = el.data( 'imagep' );
6698					selector = '';
6699					if ( imp !== '' ) {
6700						selector = 'imagep';
6701					} else if ( el.data( 'changes-product-image' ) === 'images' ) {
6702						selector = 'image';
6703					}
6704					data = event_data.element_current.data( 'image-variations' );
6705
6706					if ( data ) {
6707						data = data[ selector ];
6708					}
6709
6710					if ( data === undefined ) {
6711						// Enter the following if you want to restore the original product image
6712						// main_product.trigger( 'tm_restore_product_image', event_data );
6713						return;
6714					}
6715
6716					last_active_field = [];
6717					$( this_epo_container.find( '.tm-product-image:checked,select.tm-product-image' ) )
6718						.add( variationsForm.find( '.tm-epo-variation-section' ).first().find( '.tm-product-image:checked,select.tm-product-image' ) )
6719						.each( function() {
6720							t = $( this );
6721							if ( t.is( 'option' ) ) {
6722								t = t.closest( 'select' );
6723							}
6724							if ( field_is_active( t ) && t.val() !== '' ) {
6725								last_active_field.push( t );
6726							}
6727						} );
6728
6729					if ( last_active_field.length ) {
6730						if ( ! last_active_field[ last_active_field.length - 1 ].is( el ) ) {
6731							return;
6732						}
6733					}
6734
6735					setTimeout( function() {
6736						if ( TMEPOJS.tm_epo_global_image_recalculate === 'yes' ) {
6737							img = get_main_product_image( epoObject, product_element );
6738						}
6739						image_update( data, img, product_element );
6740						gallery_compatibility_actions( gallery_type, img, data.image_link, false, event_data, $form, product_element );
6741					}, window.tc_epo_product_image_change_delay || 0 );
6742				}
6743			} );
6744
6745			main_product.off( 'tm_restore_product_image' ).on( 'tm_restore_product_image', function( evt, event_data ) {
6746				evt.stopImmediatePropagation();
6747
6748				el = event_data ? event_data.element : false;
6749				last_active_field = [];
6750
6751				if ( el ) {
6752					$( this_epo_container.find( '.tm-product-image:checked,select.tm-product-image' ) )
6753						.add( variationsForm.find( '.tm-epo-variation-section' ).first().find( '.tm-product-image:checked,select.tm-product-image' ) )
6754						.each( function() {
6755							t = $( this );
6756							if ( field_is_active( t ) && t.val() !== '' ) {
6757								last_active_field.push( t );
6758							}
6759						} );
6760					if ( last_active_field.length ) {
6761						if ( ! last_active_field[ last_active_field.length - 1 ].is( el ) ) {
6762							last_active_field[ last_active_field.length - 1 ].trigger( 'tm_trigger_product_image' );
6763							return;
6764						}
6765					}
6766				}
6767
6768				image_update( false, img, product_element );
6769				gallery_compatibility_actions( gallery_type, false, img.attr( 'src' ), false, event_data, $form, product_element );
6770			} );
6771
6772			last_active_field = [];
6773			$( this_epo_container.find( '.tm-product-image:checked,select.tm-product-image' ) )
6774				.add( variationsForm.find( '.tm-epo-variation-section' ).first().find( '.tm-product-image:checked,select.tm-product-image' ) )
6775				.each( function() {
6776					t = $( this );
6777					if ( field_is_active( t ) && t.val() !== '' ) {
6778						last_active_field.push( t );
6779					}
6780				} );
6781			if ( last_active_field.length ) {
6782				last_active_field[ last_active_field.length - 1 ].trigger( 'tm_trigger_product_image' );
6783			}
6784		}
6785
6786		jWindow.trigger( 'tm_product_image_loaded' );
6787	}
6788
6789	function tm_product_image_inline( epoObject ) {
6790		var this_epo_container = epoObject.is_associated ? epoObject.this_epo_container : epoObject.this_epo_container.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector );
6791		var main_product = epoObject.main_product;
6792		var product_id = epoObject.product_id;
6793		var $form = epoObject.form;
6794		var img;
6795		var product_element = get_product_element( epoObject );
6796		var gallery_type;
6797		var a;
6798		var img_src_original;
6799		var img_width;
6800		var img_height;
6801		var last_active_field = [];
6802		var t;
6803
6804		img = get_main_product_image( epoObject, product_element );
6805
6806		gallery_type = get_gallery_type( epoObject, img, product_element );
6807
6808		if ( $( img ).length > 0 ) {
6809			img.data( 'tm-current-image', false );
6810			a = img.closest( 'a' );
6811			img_src_original = img.attr( 'src' );
6812			img_width = img.width();
6813			img_height = img.height();
6814
6815			main_product.off( 'tm_change_product_image' ).on( 'tm_change_product_image', function( evt, e ) {
6816				var variation_element_section;
6817				var is_variation_element;
6818				var $this_epo_container;
6819				var tm_last_visible_image_element;
6820				var last_activate_field = [];
6821				var tm_current_image_element_id;
6822				var can_show_image;
6823				var $main_product;
6824				var $current_product_element;
6825				var preload_width;
6826				var preload_height;
6827				var current_cloned_image;
6828				var preloader;
6829				var clone_image;
6830				var preload_img;
6831				var preload_img_onerror;
6832
6833				variation_element_section = e.element.closest( '.cpf-section' );
6834				is_variation_element = variation_element_section.is( '.tm-epo-variation-section' );
6835				$this_epo_container = e.epo_holder;
6836				if ( is_variation_element ) {
6837					$this_epo_container = variation_element_section;
6838				}
6839				tm_last_visible_image_element = $this_epo_container.find( '.tm-product-image:checked,select.tm-product-image' );
6840				last_activate_field = [];
6841				tm_current_image_element_id = e.element.attr( 'id' );
6842				can_show_image = true;
6843				$main_product = e.main_product;
6844				$current_product_element = $main_product.closest( '#product-' + product_id );
6845				preload_width = img_width;
6846				preload_height = img_height;
6847				preloader = $( "<div class='blockUI blockOverlay tm-preloader-img'></div>" );
6848
6849				if ( $current_product_element.length <= 0 ) {
6850					$current_product_element = $main_product.closest( '.post-' + product_id );
6851				}
6852
6853				current_cloned_image = $current_product_element.find( '#' + tm_current_image_element_id + '_tmimage' );
6854				if ( current_cloned_image.length === 0 ) {
6855					current_cloned_image = img;
6856				}
6857
6858				preload_img_onerror = function() {
6859					preloader.remove();
6860					$form.tc_image_update( false );
6861					img.data( 'tm-current-image', false );
6862					$current_product_element.find( '.tm-clone-product-image' ).hide();
6863					img.show();
6864				};
6865
6866				if ( e.src === current_cloned_image.attr( 'src' ) && current_cloned_image.is( ':visible' ) ) {
6867					return;
6868				}
6869
6870				if ( e.src === false ) {
6871					preload_img_onerror();
6872					return;
6873				}
6874
6875				preloader.css( {
6876					width: preload_width,
6877					height: preload_height
6878				} );
6879
6880				// Get last active field
6881				tm_last_visible_image_element.each( function() {
6882					t = $( this );
6883					if (
6884						field_is_active( t ) &&
6885						has_active_changes_product_image( t ) &&
6886						tm_check_field_match( {
6887							element: t.closest( '.cpf-element' ),
6888							operator: 'isnotempty',
6889							value: ''
6890						} )
6891					) {
6892						last_activate_field.push( t );
6893					}
6894				} );
6895				// Get last active image
6896				if ( last_activate_field.length ) {
6897					tm_last_visible_image_element = last_activate_field[ last_activate_field.length - 1 ];
6898				}
6899
6900				if ( tm_last_visible_image_element.attr( 'id' ) !== e.element.attr( 'id' ) ) {
6901					can_show_image = false;
6902				}
6903
6904				clone_image = img.tcClone();
6905				preload_img = new Image();
6906				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' );
6907
6908				if ( can_show_image ) {
6909					img.before( preloader );
6910				}
6911
6912				gallery_type.is_yith_wcmg.yith_wcmg_default_zoom = gallery_type.is_yith_wcmg.element.find( '.yith_magnifier_zoom' ).first().attr( 'href' );
6913				gallery_type.is_yith_wcmg.yith_wcmg_default_image = gallery_type.is_yith_wcmg.element.find( '.yith_magnifier_zoom img' ).first().attr( 'src' );
6914
6915				preload_img.onerror = function() {
6916					preload_img_onerror();
6917				};
6918
6919				preload_img.onload = function() {
6920					if ( 'naturalHeight' in this ) {
6921						if ( this.naturalHeight + this.naturalWidth === 0 ) {
6922							this.onerror();
6923							return;
6924						}
6925					} else if ( this.width + this.height === 0 ) {
6926						this.onerror();
6927						return;
6928					}
6929					$current_product_element.find( '#' + tm_current_image_element_id + '_tmimage' ).remove();
6930					$current_product_element.find( '.tm-clone-product-image' ).hide();
6931					clone_image.prop( 'src', preload_img.src ).hide();
6932
6933					img.hide().after( clone_image );
6934
6935					clone_image.css( 'opacity', 0 ).show();
6936
6937					gallery_compatibility_actions( gallery_type, clone_image, preload_img.src );
6938
6939					preloader.animate(
6940						{
6941							opacity: 0
6942						},
6943						750,
6944						'easeOutExpo',
6945						function() {
6946							preloader.remove();
6947						}
6948					);
6949					clone_image.animate(
6950						{
6951							opacity: 1
6952						},
6953						window.tc_epo_image_animation_delay || 1500,
6954						'easeOutExpo',
6955						function() {}
6956					);
6957
6958					jWindow.trigger( 'tm_change_product_image_loaded', {
6959						src: e.src,
6960						element: e.element,
6961						main_product: e.main_product,
6962						epo_holder: e.epo_holder
6963					} );
6964				};
6965
6966				clone_image
6967					.attr( 'id', tm_current_image_element_id + '_tmimage' )
6968					.addClass( 'tm-clone-product-image' )
6969					.hide();
6970
6971				if ( clone_image.attr( 'src-orig' ) ) {
6972					clone_image.attr( 'src-orig', e.src );
6973				}
6974
6975				if ( can_show_image ) {
6976					preload_img.src = e.src;
6977
6978					$form.tc_image_update( e.element, clone_image );
6979
6980					img.data( 'tm-current-image', tm_current_image_element_id );
6981
6982					jWindow.trigger( 'tm_change_product_image_show', {
6983						src: e.src,
6984						element: e.element,
6985						main_product: e.main_product,
6986						epo_holder: e.epo_holder
6987					} );
6988				} else {
6989					clone_image.prop( 'src', e.src ).hide();
6990					img.after( clone_image );
6991				}
6992
6993				jWindow.trigger( 'tm_change_product_image_end', {
6994					src: e.src,
6995					element: e.element,
6996					main_product: e.main_product,
6997					epo_holder: e.epo_holder
6998				} );
6999			} );
7000
7001			main_product.off( 'tm_restore_product_image' ).on( 'tm_restore_product_image', function( evt, e ) {
7002				var tm_current_image_element_id;
7003				var $main_product;
7004				var $current_product_element;
7005				var variation_element_section;
7006				var is_variation_element;
7007				var current_element;
7008				var current_image_replacement;
7009				var found;
7010				var is_it_visible;
7011				var len;
7012				var el_to_check;
7013				var imgSrc;
7014				var $this_epo_container;
7015				var i;
7016
7017				jWindow.trigger( 'tm_restore_product_image_pre', {
7018					element: e.element,
7019					main_product: e.main_product,
7020					epo_holder: e.epo_holder
7021				} );
7022				tm_current_image_element_id = e.element.attr( 'id' );
7023				$main_product = e.main_product;
7024				$current_product_element = $main_product.closest( '#product-' + product_id );
7025				variation_element_section = e.element.closest( '.cpf-section' );
7026				is_variation_element = variation_element_section.is( '.tm-epo-variation-section' );
7027				found = false;
7028				imgSrc = img_src_original;
7029				$this_epo_container = e.epo_holder;
7030				if ( is_variation_element ) {
7031					$this_epo_container = variation_element_section;
7032				}
7033
7034				if ( $current_product_element.length <= 0 ) {
7035					$current_product_element = $main_product.closest( '.post-' + product_id );
7036				}
7037
7038				is_it_visible = $current_product_element.find( '#' + tm_current_image_element_id + '_tmimage' ).is( ':visible' );
7039
7040				$current_product_element.find( '#' + tm_current_image_element_id + '_tmimage' ).remove();
7041
7042				if ( $current_product_element.find( '.tm-clone-product-image' ).length === 0 ) {
7043					img.show();
7044					img.data( 'tm-current-image', false );
7045					$form.tc_image_update( false );
7046				} else {
7047					if ( ! is_it_visible ) {
7048						jWindow.trigger( 'tm_restore_product_image_loaded_exit', {
7049							element: e.element,
7050							main_product: e.main_product,
7051							epo_holder: e.epo_holder
7052						} );
7053						return;
7054					}
7055
7056					len = $current_product_element.find( '.tm-clone-product-image' ).length;
7057					tm_current_image_element_id = img.data( 'tm-current-image' );
7058
7059					for ( i = len - 1; i >= 0; i -= 1 ) {
7060						current_image_replacement = $current_product_element.find( '.tm-clone-product-image' ).eq( i );
7061						current_element = current_image_replacement.attr( 'id' ).replace( '_tmimage', '' );
7062						el_to_check = $this_epo_container.find( "[id='" + current_element + "']" );
7063
7064						if ( el_to_check.is( ':checked' ) && el_to_check.closest( '.cpf-element' ).is( ':visible' ) ) {
7065							$current_product_element.find( '.tm-clone-product-image' ).eq( i ).show();
7066							a.attr( 'href', $current_product_element.find( '.tm-clone-product-image' ).eq( i ).prop( 'src' ) );
7067							img.data( 'tm-current-image', current_element );
7068							found = true;
7069							break;
7070						} else {
7071							$current_product_element.find( '.tm-clone-product-image' ).eq( i ).hide();
7072						}
7073					}
7074					if ( ! found ) {
7075						img.show();
7076						img.data( 'tm-current-image', false );
7077						$form.tc_image_update( false );
7078					} else {
7079						$current_product_element.find( '#' + tm_current_image_element_id + '_tmimage' ).remove();
7080					}
7081				}
7082
7083				if ( found ) {
7084					imgSrc = current_image_replacement.attr( 'src' );
7085				}
7086
7087				gallery_compatibility_actions( gallery_type, false, imgSrc, $current_product_element.find( '.tm-clone-product-image' ).filter( ':visible' ).length );
7088
7089				jWindow.trigger( 'tm_restore_product_image_loaded', {
7090					element: e.element,
7091					main_product: e.main_product,
7092					epo_holder: e.epo_holder
7093				} );
7094			} );
7095
7096			main_product.off( 'tm_attempt_product_image' ).on( 'tm_attempt_product_image', function( evt, e ) {
7097				var $main_product;
7098				var $current_product_element;
7099				var variation_element_section;
7100				var is_variation_element;
7101				var $this_epo_container;
7102				var tm_last_visible_image_element;
7103				var last_activate_field;
7104				var tm_last_visible_image_element_id;
7105				var current_image_replacement;
7106				var current_element;
7107				var found;
7108				var tm_current_image_element_id;
7109				var len;
7110				var imgSrc;
7111				var el_to_check;
7112				var tmcie_id;
7113				var i;
7114
7115				$main_product = e.main_product;
7116				$current_product_element = $main_product.closest( '#product-' + product_id );
7117				if ( e.element ) {
7118					variation_element_section = e.element.closest( '.cpf-section' );
7119				} else {
7120					variation_element_section = $( $main_product.find( '.tm-epo-variation-section' ).first(), e.epo_holder );
7121				}
7122				is_variation_element = variation_element_section.is( '.tm-epo-variation-section' );
7123				$this_epo_container = e.epo_holder;
7124				if ( is_variation_element ) {
7125					$this_epo_container = variation_element_section;
7126				}
7127				tm_last_visible_image_element = $this_epo_container.find( '.tm-product-image:checked,select.tm-product-image' );
7128				last_activate_field = [];
7129				tm_last_visible_image_element_id = '';
7130				found = false;
7131				tm_current_image_element_id = img.data( 'tm-current-image' );
7132				imgSrc = img_src_original;
7133
7134				if ( $current_product_element.length <= 0 ) {
7135					$current_product_element = $main_product.closest( '.post-' + product_id );
7136				}
7137
7138				$this_epo_container = $main_product.find( '.tm-epo-variation-section' ).first().add( e.epo_holder );
7139				tm_last_visible_image_element = $this_epo_container.find( '.tm-product-image:checked,select.tm-product-image' );
7140
7141				tm_last_visible_image_element.each( function() {
7142					t = $( this );
7143					if (
7144						field_is_active( t ) &&
7145						has_active_changes_product_image( t ) &&
7146						tm_check_field_match( {
7147							element: t.closest( '.cpf-element' ),
7148							operator: 'isnotempty',
7149							value: ''
7150						} )
7151					) {
7152						last_activate_field.push( t );
7153					}
7154				} );
7155
7156				if ( last_activate_field.length ) {
7157					tm_last_visible_image_element = last_activate_field[ last_activate_field.length - 1 ];
7158					tm_last_visible_image_element_id = tm_last_visible_image_element.attr( 'id' );
7159				}
7160
7161				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 ) ) {
7162					tm_last_visible_image_element.last().trigger( 'tm_trigger_product_image' );
7163					return;
7164				}
7165
7166				tmcie_id = $this_epo_container.find( "[id='" + tm_current_image_element_id + "']" ).closest( '.cpf-element' );
7167				if ( ! tm_current_image_element_id || ( tmcie_id.data( 'isactive' ) !== false && tmcie_id.closest( '.cpf-section' ).data( 'isactive' ) !== false ) ) {
7168					return;
7169				}
7170
7171				$current_product_element.find( '#' + tm_current_image_element_id + '_tmimage' ).remove();
7172				len = $current_product_element.find( '.tm-clone-product-image' ).length;
7173
7174				if ( len === 0 ) {
7175					img.show();
7176					img.data( 'tm-current-image', false );
7177					$form.tc_image_update( false );
7178				} else {
7179					for ( i = len - 1; i >= 0; i -= 1 ) {
7180						current_image_replacement = $current_product_element.find( '.tm-clone-product-image' ).eq( i );
7181						current_element = current_image_replacement.attr( 'id' ).replace( '_tmimage', '' );
7182						el_to_check = $this_epo_container.find( "[id='" + current_element + "']" );
7183
7184						if ( el_to_check.is( ':checked' ) && el_to_check.closest( '.cpf-element' ).is( ':visible' ) ) {
7185							$current_product_element.find( '.tm-clone-product-image' ).eq( i ).show();
7186							a.attr( 'href', $current_product_element.find( '.tm-clone-product-image' ).eq( i ).prop( 'src' ) );
7187							img.data( 'tm-current-image', current_element );
7188							found = true;
7189							break;
7190						} else {
7191							$current_product_element.find( '.tm-clone-product-image' ).eq( i ).hide();
7192						}
7193					}
7194
7195					if ( ! found ) {
7196						img.show();
7197						img.data( 'tm-current-image', false );
7198						$form.tc_image_update( false );
7199					}
7200				}
7201
7202				if ( found ) {
7203					imgSrc = current_image_replacement.attr( 'src' );
7204				}
7205
7206				gallery_compatibility_actions( gallery_type, false, imgSrc, $current_product_element.find( '.tm-clone-product-image' ).filter( ':visible' ).length );
7207			} );
7208
7209			$( this_epo_container.find( '.tm-product-image:checked,select.tm-product-image' ) )
7210				.add( main_product.find( '.tm-epo-variation-section' ).first().find( '.tm-product-image:checked,select.tm-product-image' ) )
7211				.each( function() {
7212					t = $( this );
7213					if ( field_is_active( t ) && t.val() !== '' ) {
7214						last_active_field.push( t );
7215					}
7216				} );
7217			if ( last_active_field.length ) {
7218				last_active_field[ last_active_field.length - 1 ].trigger( 'tm_trigger_product_image' );
7219			}
7220		}
7221
7222		jWindow.trigger( 'tm_product_image_loaded' );
7223	}
7224
7225	function tm_product_image( epoObject ) {
7226		setTimeout( function() {
7227			if ( TMEPOJS.tm_epo_global_product_image_mode === 'inline' ) {
7228				tm_product_image_inline( epoObject );
7229			} else {
7230				tm_product_image_self( epoObject );
7231			}
7232		}, window.tc_epo_product_image_setup_delay || 0 );
7233	}
7234
7235	function tc_compatibility( epoObject ) {
7236		jWindow.trigger( 'tm-epo-compatibility', {
7237			epo: epoObject
7238		} );
7239	}
7240
7241	// Range picker setup
7242	function setRangePickers( obj ) {
7243		if ( ! noUiSlider ) {
7244			return;
7245		}
7246		obj.find( '.tm-range-picker' )
7247			.toArray()
7248			.forEach( function( picker ) {
7249				var el = $( picker );
7250				var $decimals = el.attr( 'data-step' ).split( '.' );
7251				var $tmfid = obj.find( '#' + $.epoAPI.dom.id( el.attr( 'data-field-id' ) ) );
7252				var $min = parseFloat( el.attr( 'data-min' ) );
7253				var $max = parseFloat( el.attr( 'data-max' ) );
7254				var $start = parseFloat( el.attr( 'data-start' ) );
7255				var $step = parseFloat( el.attr( 'data-step' ) );
7256				var $show_picker_value = el.attr( 'data-show-picker-value' );
7257				var $show_label = el.closest( 'li' ).find( '.tm-show-picker-value' );
7258				var $noofpips = parseFloat( el.attr( 'data-noofpips' ) );
7259				var $pips = null;
7260				var $tmh;
7261
7262				if ( el.data( 'tc-picker-init' ) ) {
7263					return;
7264				}
7265				el.data( 'tc-picker-init', 1 );
7266
7267				if ( $decimals.length === 1 ) {
7268					$decimals = 0;
7269				} else {
7270					$decimals = $decimals[ 1 ].length;
7271				}
7272				if ( ! Number.isFinite( $min ) ) {
7273					$min = 0;
7274				}
7275				if ( ! Number.isFinite( $max ) ) {
7276					$max = 0;
7277				}
7278				if ( $max <= $min ) {
7279					$max = parseFloat( $max ) + 1;
7280				}
7281				$start = $.epoAPI.math.unformat( $start, tcAPI.localDecimalSeparator );
7282				if ( ! Number.isFinite( $start ) ) {
7283					$start = 0;
7284				}
7285				$start = formatPrice( $start, { precision: $decimals } );
7286				if ( ! Number.isFinite( $step ) ) {
7287					$step = 0;
7288				}
7289				if ( ! Number.isFinite( $noofpips ) ) {
7290					$noofpips = 10;
7291				}
7292				if ( $noofpips < 2 ) {
7293					$noofpips = 2;
7294				}
7295
7296				if ( el.attr( 'data-pips' ) === 'yes' ) {
7297					$pips = {
7298						mode: 'count',
7299						values: $noofpips,
7300						filter: function( value, type ) {
7301							value = parseFloat( $.epoAPI.math.toFixed( value, $decimals ) );
7302
7303							if ( $step <= 0 ) {
7304								return 0;
7305							}
7306
7307							if ( type === 1 ) {
7308								if ( ! Number.isInteger( value ) ) {
7309									return 2;
7310								}
7311							}
7312
7313							return type;
7314						},
7315						format: {
7316							from: function( value ) {
7317								return $.epoAPI.math.unformat( value, tcAPI.localInputDecimalSeparator );
7318							},
7319							to: function( value ) {
7320								return formatPrice( value, { precision: $decimals } );
7321							}
7322						},
7323						density: 2
7324					};
7325				}
7326
7327				noUiSlider.create( el.get( 0 ), {
7328					direction: TMEPOJS.text_direction,
7329					start: $start,
7330					step: $step,
7331					connect: 'lower',
7332					// Configure tapping, or make the selected range dragable.
7333					behaviour: 'tap',
7334					// Full number format support.
7335					format: {
7336						from: function( value ) {
7337							return $.epoAPI.math.unformat( value, tcAPI.localDecimalSeparator );
7338						},
7339						to: function( value ) {
7340							return formatPrice( value, { precision: $decimals } );
7341						}
7342					},
7343					// Support for non-linear ranges by adding intervals.
7344					range: {
7345						min: [ $min ],
7346						max: [ $max ]
7347					},
7348					pips: $pips,
7349					tooltips: {
7350						from: function( value ) {
7351							return $.epoAPI.math.unformat( value, tcAPI.localInputDecimalSeparator );
7352						},
7353						to: function( value ) {
7354							return formatPrice( value, { precision: $decimals } );
7355						}
7356					}
7357				} );
7358
7359				$tmh = el.find( '.noui-handle-lower' );
7360				el.get( 0 ).noUiSlider.on( 'slide', function() {
7361					$tmfid.trigger( 'change.cpf' );
7362				} );
7363				el.get( 0 ).noUiSlider.on( 'update', function( values, handle ) {
7364					values[ handle ] = $.epoAPI.math.unformat( values[ handle ], tcAPI.localDecimalSeparator );
7365					handle = 0; //fixes rtl issue.
7366					if ( $show_picker_value !== 'left' && $show_picker_value !== 'right' ) {
7367						$tmh.attr(
7368							'title',
7369							formatPrice( values[ handle ], { precision: $decimals } )
7370						);
7371					}
7372					$tmfid.val( values[ handle ] ).trigger( 'change' );
7373					if ( $show_picker_value !== '' ) {
7374						$show_label.html(
7375							formatPrice( values[ handle ], { precision: $decimals } )
7376						);
7377					}
7378				} );
7379
7380				if ( $show_picker_value !== '' ) {
7381					$show_label.html( $start );
7382				}
7383
7384				if ( $show_picker_value !== 'left' && $show_picker_value !== 'right' ) {
7385					$tmh.attr( 'title', $start );
7386					el.addClass( 'noui-show-tooltip' );
7387				}
7388			} );
7389	}
7390
7391	// Range picker event setup
7392	function setRangePickersEvents() {
7393		if ( ! noUiSlider || jDocument.data( 'setRangePickersEvents' ) ) {
7394			return;
7395		}
7396		jDocument.on( 'click', '.tm-show-picker-value', function() {
7397			var $this = $( this );
7398			var li = $this.closest( '.tmcp-field-wrap' );
7399			var value = li.find( '.tmcp-range' ).val();
7400			var edit;
7401			var html5Slider = $this.closest( '.tmcp-field-wrap' ).find( '.tm-range-picker' );
7402
7403			$this.addClass( 'tc-hidden' ).after( $( '<input type="number" class="tm-show-picker-value-edit">' ) );
7404			edit = li.find( '.tm-show-picker-value-edit' );
7405			edit.focus().val( value ).wrap( '<div class="tm-show-picker-value-edit-wrap"></div>' );
7406			edit.attr( 'step', html5Slider.attr( 'data-step' ) );
7407			edit.attr( 'min', html5Slider.attr( 'data-min' ) );
7408			edit.attr( 'max', html5Slider.attr( 'data-max' ) );
7409			jDocument.data( 'range-picker-edit', li.find( '.tm-show-picker-value-edit' ) );
7410		} );
7411		jDocument.on( 'change input', '.tm-show-picker-value-edit', function() {
7412			var $this = $( this );
7413			var html5Slider = $this.closest( '.tmcp-field-wrap' ).find( '.tm-range-picker' );
7414			var $decimals = html5Slider.attr( 'data-step' ).split( '.' );
7415			var value = $this.val();
7416			if ( $decimals.length === 1 ) {
7417				$decimals = 0;
7418			} else {
7419				$decimals = $decimals[ 1 ].length;
7420			}
7421
7422			html5Slider.get( 0 ).noUiSlider.set( [ formatPrice( value, { precision: $decimals } ), null ] );
7423		} );
7424		jDocument.on( 'keydown', '.tm-show-picker-value-edit', function( event ) {
7425			var key;
7426
7427			key = event.which;
7428			if ( key === 13 ) {
7429				event.preventDefault();
7430			}
7431		} );
7432		jDocument.on( 'click', function( event ) {
7433			var $this;
7434
7435			if ( ! jDocument.data( 'range-picker-edit' ) || $( event.target ).is( '.tm-show-picker-value' ) ) {
7436				return;
7437			}
7438
7439			if ( $( event.target ).closest( '.tm-show-picker-value-edit-wrap' ).length === 0 ) {
7440				$this = jDocument.data( 'range-picker-edit' );
7441				$this.closest( '.tmcp-field-wrap' ).find( '.tm-show-picker-value' ).data( 'has-edit', 0 ).removeClass( 'tc-hidden' );
7442				$this.closest( '.tm-show-picker-value-edit-wrap' ).remove();
7443				jDocument.removeData( 'range-picker-edit' );
7444			}
7445		} );
7446		jDocument.data( 'setRangePickersEvents', 1 );
7447	}
7448
7449	function validate_date_with_options( date, inputElement ) {
7450		var input = $( inputElement );
7451		var inst = $.tm_datepicker._getInst( input[ 0 ] );
7452		var enabled_only_dates = input.data( 'tc-enabled_only_dates' );
7453		var disabled_weekdays = input.data( 'tc-disabled_weekdays' );
7454		var disabled_months = input.data( 'tc-disabled_months' );
7455		var disabled_dates = input.data( 'tc-disabled_dates' );
7456		var format = input.data( 'tc-format' );
7457		var day = date.getDay();
7458		var month = date.getDay() + 1;
7459		var string;
7460
7461		if ( ! $.tm_datepicker._isInRange( inst, date ) ) {
7462			return false;
7463		}
7464		if ( enabled_only_dates !== '' ) {
7465			string = $.tm_datepicker.formatDate( format, date );
7466			return enabled_only_dates.indexOf( string ) !== -1;
7467		}
7468		if ( disabled_weekdays.indexOf( day.toString() ) !== -1 ) {
7469			return false;
7470		}
7471		if ( disabled_months.indexOf( month.toString() ) !== -1 ) {
7472			return false;
7473		}
7474		if ( disabled_dates !== '' ) {
7475			string = $.tm_datepicker.formatDate( format, date );
7476			return disabled_dates.indexOf( string ) === -1;
7477		}
7478		return true;
7479	}
7480
7481	function correctDate( days ) {
7482		var sign, testDate, count, added, noOfDaysToAdd;
7483		if ( days.toString().isNumeric() ) {
7484			sign = days === 0 ? days : ( days > 0 ? 1 : -1 );
7485			if ( sign !== 0 ) {
7486				testDate = new Date();
7487				count = 1;
7488				added = false;
7489				noOfDaysToAdd = Math.abs( days );
7490				while ( count <= noOfDaysToAdd ) {
7491					if ( added === false ) {
7492						added = 0;
7493					}
7494					testDate.setDate( testDate.getDate() + ( 1 * sign ) );
7495					added++;
7496					if ( testDate.getDay() !== 0 && testDate.getDay() !== 6 ) {
7497						count++;
7498					}
7499				}
7500				if ( added !== false ) {
7501					days = added * sign;
7502				}
7503			}
7504		}
7505		return days;
7506	}
7507	// Date and time picker setup
7508	function tm_set_datepicker( obj ) {
7509		var inputIds;
7510		var elem;
7511		var timepickerSelector = '.tm-epo-timepicker';
7512
7513		if ( ! $.tm_datepicker ) {
7514			return;
7515		}
7516
7517		inputIds = $( 'input' )
7518			.map( function() {
7519				return this.id;
7520			} )
7521			.get()
7522			.join( ' ' );
7523
7524		elem = document.createElement( 'input' );
7525		elem.setAttribute( 'type', 'date' );
7526
7527		if ( elem.type === 'text' ) {
7528			timepickerSelector = '.tm-epo-system-timepicker';
7529		}
7530
7531		obj.find( timepickerSelector )
7532			.toArray()
7533			.forEach( function( el ) {
7534				var field = $( el );
7535				var _mintime = null;
7536				var _maxtime = null;
7537				var format = field.attr( 'data-time-format' ).trim();
7538				var date_theme = field.attr( 'data-time-theme' ).trim();
7539				var date_theme_size = field.attr( 'data-time-theme-size' ).trim();
7540				var date_theme_position = field.attr( 'data-time-theme-position' ).trim();
7541				var data_translation_hour = field.attr( 'data-tranlation-hour' ).trim();
7542				var data_translation_minute = field.attr( 'data-tranlation-minute' ).trim();
7543				var data_translation_second = field.attr( 'data-tranlation-second' ).trim();
7544
7545				field.attr( 'type', 'text' );
7546
7547				if ( field.attr( 'data-min-time' ).trim() !== '' ) {
7548					_mintime = field.attr( 'data-min-time' ).trim();
7549				}
7550				if ( field.attr( 'data-max-time' ).trim() !== '' ) {
7551					_maxtime = field.attr( 'data-max-time' ).trim();
7552				}
7553
7554				if ( field.attr( 'data-custom-time-format' ).trim() !== '' ) {
7555					format = field.attr( 'data-custom-time-format' ).trim();
7556				}
7557				if ( ! data_translation_hour ) {
7558					data_translation_hour = TMEPOJS.hourText;
7559				}
7560				if ( ! data_translation_minute ) {
7561					data_translation_minute = TMEPOJS.minuteText;
7562				}
7563				if ( ! data_translation_second ) {
7564					data_translation_second = TMEPOJS.secondText;
7565				}
7566
7567				field.tm_timepicker( Object.assign( {
7568					isRTL: TMEPOJS.isRTL,
7569					hourText: data_translation_hour,
7570					minuteText: data_translation_minute,
7571					secondText: data_translation_second,
7572					timeFormat: format,
7573					minTime: _mintime,
7574					maxTime: _maxtime,
7575					closeText: TMEPOJS.closeText,
7576					showOn: 'both',
7577					buttonText: '',
7578
7579					beforeShow: function( input, inst ) {
7580						$( inst.dpDiv )
7581							.removeClass( inputIds )
7582							.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' )
7583							.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 )
7584							.appendTo( 'body' );
7585
7586						jDocument.off( 'click', '.tm-ui-dp-overlay' ).on( 'click', '.tm-ui-dp-overlay', function() {
7587							field.tm_timepicker( 'hide' );
7588						} );
7589						jBody.addClass( 'tm-static' );
7590						field.prop( 'readonly', true );
7591
7592						jWindow.trigger( {
7593							type: 'tm-timepicker-beforeShow',
7594							input: input,
7595							inst: inst
7596						} );
7597					},
7598					onClose: function() {
7599						jBody.removeClass( 'tm-static' );
7600						field.prop( 'readonly', false );
7601						field.trigger( 'change' );
7602					}
7603				}, window.tmTimepickerSettings || window.timepicker_settings || {} ) );
7604				$( '#ui-tm-datepicker-div' ).hide();
7605			} );
7606
7607		obj.find( '.tm-epo-datepicker' )
7608			.toArray()
7609			.forEach( function( el ) {
7610				var field = $( el );
7611				var startDate = parseInt( field.attr( 'data-start-year' ).trim(), 10 );
7612				var endDate = parseInt( field.attr( 'data-end-year' ).trim(), 10 );
7613				var minDate = field.attr( 'data-min-date' ).trim();
7614				var maxDate = field.attr( 'data-max-date' ).trim();
7615				var disabled_dates = field.attr( 'data-disabled-dates' ).trim();
7616				var enabled_only_dates = field.attr( 'data-enabled-only-dates' ).trim();
7617				var exlude_disabled = field.attr( 'data-exlude-disabled' ).trim();
7618				var disabled_weekdays = field.attr( 'data-disabled-weekdays' ).trim().split( ',' );
7619				var disabled_months = field.attr( 'data-disabled-months' ).trim().split( ',' );
7620				var format = field.attr( 'data-date-format' ).trim();
7621				var show = field.attr( 'data-date-showon' ).trim();
7622				var default_date = field.attr( 'data-date-defaultdate' ).trim();
7623				var date_theme = field.attr( 'data-date-theme' ).trim();
7624				var date_theme_size = field.attr( 'data-date-theme-size' ).trim();
7625				var date_theme_position = field.attr( 'data-date-theme-position' ).trim();
7626				var $split;
7627				var $index;
7628				var $split2;
7629				var $index2;
7630
7631				if ( disabled_dates !== '' ) {
7632					$split = disabled_dates.split( ',' );
7633					$index = disabled_dates.indexOf( ',' );
7634
7635					if ( $index !== -1 && $split.length > 0 ) {
7636						disabled_dates = $split;
7637					}
7638				}
7639				if ( enabled_only_dates !== '' ) {
7640					$split2 = enabled_only_dates.split( ',' );
7641					$index2 = enabled_only_dates.indexOf( ',' );
7642
7643					if ( $index2 !== -1 && $split2.length > 0 ) {
7644						enabled_only_dates = $split2;
7645					}
7646				}
7647
7648				if ( minDate === '' ) {
7649					if ( startDate === '' ) {
7650						minDate = null;
7651					} else {
7652						minDate = new Date( startDate, 1 - 1, 1 );
7653					}
7654				} else if ( exlude_disabled ) {
7655					minDate = correctDate( minDate );
7656				}
7657				if ( maxDate === '' ) {
7658					if ( endDate === '' ) {
7659						maxDate = null;
7660					} else {
7661						maxDate = new Date( endDate, 12 - 1, 31 );
7662					}
7663				} else if ( exlude_disabled ) {
7664					maxDate = correctDate( maxDate );
7665				}
7666
7667				field.data( 'tc-enabled_only_dates', enabled_only_dates );
7668				field.data( 'tc-disabled_weekdays', disabled_weekdays );
7669				field.data( 'tc-disabled_months', disabled_months );
7670				field.data( 'tc-disabled_dates', disabled_dates );
7671				field.data( 'tc-format', format );
7672
7673				field.tm_datepicker( Object.assign( {
7674					monthNames: TMEPOJS.monthNames,
7675					monthNamesShort: TMEPOJS.monthNamesShort,
7676					dayNames: TMEPOJS.dayNames,
7677					dayNamesShort: TMEPOJS.dayNamesShort,
7678					dayNamesMin: TMEPOJS.dayNamesMin,
7679					isRTL: TMEPOJS.isRTL,
7680					showOtherMonths: true,
7681					selectOtherMonths: true,
7682					showOn: show,
7683					defaultDate: default_date,
7684					buttonText: '',
7685					showButtonPanel: true,
7686					firstDay: TMEPOJS.first_day,
7687					closeText: TMEPOJS.closeText,
7688					currentText: TMEPOJS.currentText,
7689					dateFormat: format,
7690					minDate: minDate,
7691					maxDate: maxDate,
7692					onSelect: function() {
7693						var input = $( this );
7694						var id = '#' + $.epoAPI.dom.id( input.attr( 'id' ) );
7695						var date = input.tm_datepicker( 'getDate' );
7696						var day = '';
7697						var month = '';
7698						var year = '';
7699						var day_field = obj.find( id + '_day' );
7700						var month_field = obj.find( id + '_month' );
7701						var year_field = obj.find( id + '_year' );
7702						var string;
7703						var ld;
7704
7705						if ( date ) {
7706							day = date.getDate();
7707							month = date.getMonth() + 1;
7708							year = date.getFullYear();
7709							string = $.tm_datepicker.formatDate( format, date );
7710							if (
7711								disabled_months.indexOf( month.toString() ) !== -1 ||
7712								disabled_weekdays.indexOf( date.getDay().toString() ) !== -1 ||
7713								disabled_dates.indexOf( string ) !== -1 ||
7714								( enabled_only_dates !== '' && enabled_only_dates.indexOf( string ) === -1 )
7715							) {
7716								ld = input.data( 'tm-last-date' );
7717								if ( input.data( 'tm-last-date' ) ) {
7718									ld = input.data( 'tm-last-date' );
7719								} else {
7720									ld = '';
7721								}
7722								input.val( ld );
7723								input.tm_datepicker( 'setDate', ld );
7724								if ( ld ) {
7725									date = input.tm_datepicker( 'getDate' );
7726									day = date.getDate();
7727									month = date.getMonth() + 1;
7728									year = date.getFullYear();
7729								} else {
7730									day = '';
7731									month = '';
7732									year = '';
7733								}
7734							}
7735						}
7736
7737						day_field.val( day );
7738						month_field.val( month );
7739						year_field.val( year );
7740
7741						input.data( 'tm-last-date', input.val() );
7742						input.tm_datepicker( 'hide' );
7743					},
7744					beforeShow: function( input, inst ) {
7745						$( inst.dpDiv )
7746							.removeClass( inputIds )
7747							.removeClass( 'tm-datepicker-normal tm-datepicker-top tm-datepicker-bottom' )
7748							.addClass( this.id + ' tm-bsbb-all tm-ui-skin-' + date_theme + ' tm-datepicker tm-datepicker-' + date_theme_position + ' tm-datepicker-' + date_theme_size )
7749							.appendTo( 'body' );
7750
7751						jDocument.off( 'click', '.tm-ui-dp-overlay' ).on( 'click', '.tm-ui-dp-overlay', function() {
7752							field.tm_datepicker( 'hide' );
7753						} );
7754						jDocument.off( 'click', '.ui-tm-datepicker-current' ).on( 'click', '.ui-tm-datepicker-current', function() {
7755							var tempDate = new Date(),
7756								today = $.tm_datepicker._daylightSavingAdjust( new Date( tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate() ) );
7757							var day = today.getDay();
7758							var month = today.getMonth() + 1;
7759							var id = '#' + inst.id.replace( /\\\\/g, '\\' );
7760							var check = false;
7761							var string;
7762							var date = field.tm_datepicker( 'getDate' );
7763
7764							if ( enabled_only_dates !== '' ) {
7765								string = $.tm_datepicker.formatDate( format, date );
7766								check = enabled_only_dates.indexOf( string ) !== -1;
7767							} else if ( disabled_months.indexOf( month.toString() ) !== -1 || disabled_weekdays.indexOf( day.toString() ) !== -1 ) {
7768								check = false;
7769							} else {
7770								if ( disabled_dates !== '' ) {
7771									string = $.tm_datepicker.formatDate( format, date );
7772									return [ disabled_dates.indexOf( string ) === -1, '' ];
7773								}
7774								check = true;
7775							}
7776							if ( check ) {
7777								$.tm_datepicker._setDate( inst, today );
7778								$.tm_datepicker._gotoToday( id );
7779							}
7780						} );
7781						jBody.addClass( 'tm-static' );
7782
7783						jWindow.trigger( {
7784							type: 'tm-datepicker-beforeShow',
7785							input: input,
7786							inst: inst
7787						} );
7788					},
7789					onClose: function() {
7790						jBody.removeClass( 'tm-static' );
7791						field.trigger( 'change' );
7792					},
7793					beforeShowDay: function( date ) {
7794						var day = date.getDay();
7795						var month = date.getMonth() + 1;
7796						var string;
7797
7798						if ( enabled_only_dates !== '' ) {
7799							string = $.tm_datepicker.formatDate( format, date );
7800							return [ enabled_only_dates.indexOf( string ) !== -1, '' ];
7801						}
7802						if ( disabled_months.indexOf( month.toString() ) !== -1 || disabled_weekdays.indexOf( day.toString() ) !== -1 ) {
7803							return [ false, '' ];
7804						}
7805						if ( disabled_dates !== '' ) {
7806							string = $.tm_datepicker.formatDate( format, date );
7807							return [ disabled_dates.indexOf( string ) === -1, '' ];
7808						}
7809						return [ true, '' ];
7810					}
7811				}, window.tmDatepickerSettings || {} ) );
7812
7813				$( '#ui-tm-datepicker-div' ).hide();
7814			} );
7815
7816		obj.find( '.tmcp-date-select' )
7817			.on( 'change.cpf', function() {
7818				var id = '#' + $.epoAPI.dom.id( $( this ).attr( 'data-tm-date' ) );
7819				var input = obj.find( id );
7820				var format = input.attr( 'data-date-format' );
7821				var day = obj.find( id + '_day' ).val();
7822				var month = obj.find( id + '_month' ).val();
7823				var year = obj.find( id + '_year' ).val();
7824				var dateFormat = $.tm_datepicker.formatDate( format, new Date( year, parseInt( month, 10 ) - 1, day ) );
7825
7826				if ( day > 0 && month > 0 && year > 0 ) {
7827					input.tm_datepicker( 'setDate', dateFormat );
7828					input.trigger( 'change' );
7829				} else {
7830					input.val( '' );
7831					input.trigger( 'change.cpf' );
7832				}
7833			} )
7834			.on( 'focus.cpf', function() {
7835				var id = '#' + $.epoAPI.dom.id( $( this ).attr( 'data-tm-date' ) );
7836				var input = obj.find( id );
7837				var day_select = obj.find( id + '_day' );
7838				var month_select = obj.find( id + '_month' );
7839				var year_select = obj.find( id + '_year' );
7840				var day = day_select.val();
7841				var month = month_select.val();
7842				var year = year_select.val();
7843				var _select = $( this );
7844
7845				if ( ( year !== '' && month !== '' && day !== '' ) || ( year !== '' && month !== '' && day === '' ) || ( day !== '' && year !== '' && month === '' ) || ( day !== '' && month !== '' && year === '' ) ) {
7846					_select
7847						.find( 'option' )
7848						.toArray()
7849						.forEach( function( element ) {
7850							var option = $( element );
7851							var val = option.val();
7852							var date_string = year + '-' + month + '-' + day;
7853							var d;
7854
7855							if ( _select.is( '.tmcp-date-day' ) ) {
7856								if ( year === '' || month === '' ) {
7857									return;
7858								}
7859								date_string = year + '-' + month + '-' + val;
7860							} else if ( _select.is( '.tmcp-date-month' ) ) {
7861								if ( year === '' || day === '' ) {
7862									return;
7863								}
7864								date_string = year + '-' + val + '-' + day;
7865							} else if ( _select.is( '.tmcp-date-year' ) ) {
7866								if ( day === '' || month === '' ) {
7867									return;
7868								}
7869								date_string = val + '-' + month + '-' + day;
7870							}
7871
7872							if ( val !== '' ) {
7873								try {
7874									d = $.tm_datepicker.parseDate( 'yy-mm-dd', date_string );
7875									if ( d ) {
7876										if ( validate_date_with_options( d, input ) ) {
7877											option.prop( 'disabled', false );
7878										} else {
7879											option.prop( 'disabled', true );
7880										}
7881									}
7882								} catch ( err ) {
7883									window.console.log( err );
7884
7885									option.prop( 'disabled', true );
7886									errorObject = err;
7887								}
7888							}
7889						} );
7890				} else {
7891					day_select.find( 'option' ).prop( 'disabled', false );
7892					month_select.find( 'option' ).prop( 'disabled', false );
7893					year_select.find( 'option' ).prop( 'disabled', false );
7894				}
7895			} );
7896
7897		jWindow.on( 'resizestart', function() {
7898			var activeElement = $( document.activeElement );
7899
7900			if ( activeElement.is( '.hasDatepicker' ) ) {
7901				activeElement.data( 'resizestarted', true );
7902
7903				// we don't use jWindow here because we want the current window width
7904				if ( $( window ).width() < 768 ) {
7905					activeElement.data( 'resizewidth', true );
7906					return;
7907				}
7908				activeElement.tm_datepicker( 'hide' );
7909			}
7910		} );
7911		jWindow.on( 'resizestop', function() {
7912			var activeElement = $( document.activeElement );
7913
7914			if ( activeElement.is( '.hasDatepicker' ) && activeElement.data( 'resizestarted' ) ) {
7915				if ( activeElement.data( 'resizewidth' ) ) {
7916					activeElement.tm_datepicker( 'hide' );
7917				}
7918				activeElement.tm_datepicker( 'show' );
7919			}
7920			activeElement.data( 'resizestarted', false );
7921			activeElement.data( 'resizewidth', false );
7922		} );
7923	}
7924
7925	function apply_submit_events( epoObject ) {
7926		var epoEventId = epoObject.epoEventId;
7927		var main_product = epoObject.main_product;
7928		var type;
7929		var form_is_submit = ! $.tcepo.formSubmitEvents[ epoEventId ].some( function( form_event ) {
7930			return typeof form_event && ( typeof form_event.trigger === 'function' || false ) && ! form_event.trigger();
7931		} );
7932
7933		$.tcepo.formSubmitEvents[ epoEventId ].forEach( function( form_event ) {
7934			type = typeof form_event;
7935			if ( type === 'object' ) {
7936				if ( form_is_submit ) {
7937					form_event.on_true();
7938				} else {
7939					form_event.on_false();
7940				}
7941			}
7942		} );
7943
7944		if ( ! form_is_submit ) {
7945			setTimeout( function() {
7946				main_product.find( tcAPI.addToCartButtonSelector ).first().removeClass( 'disabled' ).removeClass( 'loading' ).prop( 'disabled', false ).removeClass( 'fpd-disabled' );
7947			}, 100 );
7948		}
7949
7950		jWindow.trigger( 'tm-apply-submit-events', {
7951			epo: {
7952				form_is_submit: form_is_submit
7953			}
7954		} );
7955
7956		return form_is_submit;
7957	}
7958
7959	function tm_apply_validation( epoObject ) {
7960		var form = epoObject.form;
7961		var this_epo_container = epoObject.this_epo_container;
7962		var main_product = epoObject.main_product;
7963		var epoEventId = epoObject.epoEventId;
7964		var validation_rules;
7965		var has_rules;
7966
7967		if ( TMEPOJS.tm_epo_global_enable_validation === 'yes' ) {
7968			validation_rules = {};
7969
7970			this_epo_container
7971				.find( '.tmcp-ul-wrap' )
7972				.toArray()
7973				.forEach( function( tmcpulwrap ) {
7974					var field;
7975					var field_name;
7976					var subFieldName;
7977					var subRule;
7978					var productField;
7979
7980					tmcpulwrap = $( tmcpulwrap );
7981					has_rules = tmcpulwrap.data( 'tm-validation' );
7982					if ( has_rules && $.tmType( has_rules ) === 'object' ) {
7983						field = tmcpulwrap.find( '.tm-epo-field' );
7984						field_name = field.first().attr( 'name' );
7985						if ( tmcpulwrap.is( '.tm-extra-product-options-radio.tm-element-ul-radio' ) ) {
7986							field_name = field.last().attr( 'name' );
7987							validation_rules[ field_name ] = has_rules;
7988						} else if ( tmcpulwrap.is( '.tm-extra-product-options-checkbox.tm-element-ul-checkbox' ) ) {
7989							field.each( function( f, fname ) {
7990								if ( 'required' in has_rules ) {
7991									has_rules.required = function( elem ) {
7992										var len = tmcpulwrap.find( 'input.tm-epo-field.tmcp-checkbox:checked' ).length;
7993										if ( len === 0 ) {
7994											if ( field.last().attr( 'name' ) === $( elem ).attr( 'name' ) ) {
7995												return true;
7996											}
7997											return false;
7998										}
7999										return len <= 0;
8000									};
8001								}
8002								validation_rules[ $( fname ).attr( 'name' ) ] = has_rules;
8003							} );
8004						} else if ( tmcpulwrap.is( '.tm-extra-product-options-product.tm-element-ul-product' ) ) {
8005							if ( field.is( ':checkbox' ) ) {
8006								field.each( function( f, fname ) {
8007									if ( 'required' in has_rules ) {
8008										productField = $( fname );
8009										if ( productField.is( ':checkbox' ) ) {
8010											has_rules.required = function( elem ) {
8011												var checkedFields = tmcpulwrap.find( 'input.tm-epo-field.tmcp-checkbox:checked' );
8012												var len = checkedFields.length;
8013												var qtyCheck;
8014												if ( len === 0 ) {
8015													if ( field.last().attr( 'name' ) === $( elem ).attr( 'name' ) ) {
8016														return true;
8017													}
8018													return false;
8019												}
8020												qtyCheck = checkedFields.map( function() {
8021													return $( this );
8022												} ).get().some( function( element ) {
8023													return element.closest( '.tc-epo-element-product-holder' ).find( '.tm-qty' ).first().val() <= 0;
8024												} );
8025												if ( len > 0 ) {
8026													return qtyCheck;
8027												}
8028												return len <= 0;
8029											};
8030											if ( productField.attr( 'data-type' ) === 'variable' ) {
8031												subFieldName = productField.closest( '.tc-epo-element-product-holder' ).find( '.product-variation-id' ).first().attr( 'name' );
8032												subRule = {
8033													required: function( elem ) {
8034														var element = $( elem );
8035														var holder = element.closest( '.tc-epo-element-product-holder' );
8036														var checkbox = holder.find( '.tc-epo-field-product' );
8037
8038														if ( field_is_active( checkbox, true ) && checkbox.is( ':checked' ) ) {
8039															return true;
8040														}
8041														return false;
8042													}
8043												};
8044												validation_rules[ subFieldName ] = subRule;
8045											}
8046										}
8047									}
8048									validation_rules[ productField.attr( 'name' ) ] = has_rules;
8049								} );
8050							} else if ( field.is( ':radio' ) ) {
8051								has_rules.product_element_radio_qty = true;
8052								validation_rules[ field.attr( 'name' ) ] = has_rules;
8053								subFieldName = field.closest( '.tc-element-container' ).find( '.product-variation-id' ).first().attr( 'name' );
8054								subRule = {
8055									required: function( elem ) {
8056										var element = $( elem );
8057										var holder = element.closest( '.tc-element-container' );
8058										var radiobutton = holder.find( '.tc-epo-field-product:checked' );
8059
8060										if ( radiobutton.length && radiobutton.attr( 'data-type' ) === 'variable' && field_is_active( radiobutton, true ) && radiobutton.is( ':checked' ) ) {
8061											return true;
8062										}
8063										return false;
8064									}
8065								};
8066								validation_rules[ subFieldName ] = subRule;
8067							} else if ( field.is( 'select' ) ) {
8068								has_rules.product_element_select_qty = true;
8069								validation_rules[ field.attr( 'name' ) ] = has_rules;
8070								subFieldName = field.closest( '.tc-element-container' ).find( '.product-variation-id' ).first().attr( 'name' );
8071								subRule = {
8072									required: function( elem ) {
8073										var element = $( elem );
8074										var holder = element.closest( '.tc-element-container' );
8075										var select = holder.find( '.tc-epo-field-product' );
8076
8077										if ( select.length && select.children( ':selected' ).attr( 'data-type' ) === 'variable' && field_is_active( select, true ) ) {
8078											return true;
8079										}
8080										return false;
8081									}
8082								};
8083								validation_rules[ subFieldName ] = subRule;
8084							}
8085						} else {
8086							validation_rules[ field_name ] = has_rules;
8087						}
8088					}
8089				} );
8090
8091			form.removeData( 'tc_validator' );
8092			form.tc_validate( {
8093				focusInvalid: false,
8094				ignore:
8095					tcAPI.qtySelector +
8096					",.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)",
8097				rules: validation_rules,
8098				errorClass: 'tm-error',
8099				validClass: 'tm-valid',
8100				errorElement: 'label',
8101				errorPlacement: function( error, element ) {
8102					error.addClass( 'tc-cell tcwidth tcwidth-100' );
8103					if ( TMEPOJS.tm_epo_global_error_label_placement === 'before' ) {
8104						element.closest( '.tc-element-container' ).before( error );
8105					} else {
8106						element.closest( '.tc-element-container' ).after( error );
8107					}
8108					return false;
8109				},
8110				invalidHandler: function( event, validator ) {
8111					jWindow.trigger( 'tm-invalidHandler', {
8112						epo: {
8113							validator: validator
8114						}
8115					} );
8116					setTimeout( function() {
8117						if ( ! main_product.find( tcAPI.addToCartButtonSelector ).first().is( '.disabled' ) ) {
8118							main_product.find( tcAPI.addToCartButtonSelector ).first().removeClass( 'loading' ).prop( 'disabled', false ).removeClass( 'fpd-disabled' );
8119							main_product.find( tcAPI.addToCartButtonSelector ).first().removeClass( 'disabled' ).removeClass( 'loading' ).prop( 'disabled', false ).removeClass( 'fpd-disabled' );
8120						}
8121					}, 100 );
8122					if ( validator.errorList && validator.errorList[ 0 ] && validator.errorList[ 0 ].element ) {
8123						goto_error_item( $( validator.errorList[ 0 ].element ), epoEventId );
8124					}
8125				},
8126				submitHandler: function() {
8127					var ajaxSuccessFunc;
8128					if ( ! epoObject.is_quickview ) {
8129						main_product.find( tcAPI.addToCartButtonSelector ).first().addClass( 'disabled' );
8130						ajaxSuccessFunc = function() {
8131							main_product.find( tcAPI.addToCartButtonSelector ).first().removeClass( 'disabled' );
8132							jDocument.off( 'ajaxSuccess', ajaxSuccessFunc );
8133						};
8134						jDocument.on( 'ajaxSuccess', ajaxSuccessFunc );
8135					}
8136					return apply_submit_events( epoObject );
8137				}
8138			} );
8139
8140			// This should handle most ajax based add to cart solutions
8141			form.find( tcAPI.addToCartButtonSelector ).on( 'click', function( e ) {
8142				if ( ! form.tc_validate().form() ) {
8143					e.preventDefault();
8144					e.stopImmediatePropagation();
8145				}
8146			} );
8147
8148			return true;
8149		}
8150		return false;
8151	}
8152
8153	function tm_form_submit_event( epoObject ) {
8154		var form = epoObject.form;
8155		var epoEventId = epoObject.epoEventId;
8156
8157		jWindow.trigger( 'tm-from-submit', {
8158			epo: epoObject,
8159			functions: {
8160				tm_apply_validation: tm_apply_validation,
8161				apply_submit_events: apply_submit_events
8162			}
8163		} );
8164		if ( ! tm_apply_validation( epoObject ) && $.tcepo.formSubmitEvents[ epoEventId ].length ) {
8165			form.on( 'submit', function() {
8166				apply_submit_events( epoObject );
8167			} );
8168		}
8169
8170		jWindow.on( 'tc_apply_validation', function() {
8171			return tm_apply_validation( epoObject );
8172		} );
8173	}
8174
8175	function found_variation_tmepo( dataObject ) {
8176		var epoHolder = dataObject.epoHolder;
8177		var totalsHolder = dataObject.totalsHolder;
8178		var totalsHolderContainer = dataObject.totalsHolderContainer;
8179		var currentCart = dataObject.currentCart;
8180		var variationForm = dataObject.variationForm;
8181		var variation = dataObject.variation;
8182		var variations = totalsHolder.data( 'variations' );
8183		var product_price;
8184
8185		totalsHolder.data( 'current_variation', variation );
8186
8187		/**
8188		 * Currency converters that don't allow multi currency checkout will fail the following if statement
8189		 *
8190		 * if (variation.display_price!=undefined) {
8191		 *     product_price = variation.display_price;
8192		 *     totalsHolder.data('price', product_price);
8193		 * } else ...
8194		 *
8195		 */
8196		// This needs to be the first check as the next one
8197		// fails for taxed products as it displays the backend price only.
8198		if ( variation && 'display_price' in variation && ! totalsHolder.data( 'tm-epo-is-woocs' ) ) {
8199			product_price = variation.display_price;
8200
8201			totalsHolder.data( 'priceIsWithDiscount', '1' );
8202			// Fancy product Designer
8203			totalsHolder.removeData( 'tcprice' );
8204		} else if ( variations && variation && variation.variation_id && variations[ variation.variation_id ] !== undefined ) {
8205			product_price = variations[ variation.variation_id ];
8206
8207			// Fancy product Designer
8208			totalsHolder.removeData( 'tcprice' );
8209		} else if ( variation && $( variation.price_html ).find( '.amount:last' ).length ) {
8210			product_price = $( variation.price_html ).find( '.amount:last' ).text();
8211			product_price = product_price.replace( TMEPOJS.currency_format_thousand_sep, '' );
8212			product_price = product_price.replace( TMEPOJS.currency_format_decimal_sep, '.' );
8213			product_price = product_price.replace( /[^0-9.]/g, '' );
8214			product_price = parseFloat( product_price );
8215
8216			// Fancy product Designer
8217			totalsHolder.removeData( 'tcprice' );
8218		}
8219
8220		product_price = tm_set_backend_price( product_price, totalsHolder, variation );
8221		totalsHolder.data( 'price', product_price );
8222
8223		totalsHolderContainer.find( '.cpf-product-price' ).val( product_price );
8224
8225		setTimeout( function() {
8226			epoHolder.find( 'select.tm-epo-field' ).trigger( 'tm-select-change-html-all-math' );
8227		}, 100 );
8228
8229		// This must be run every time to get correct results for percent price types
8230		// if set norules then discount will not auto work upon chosing a variation
8231		if ( ! variationForm.data( 'tm-styled-variations' ) ) {
8232			currentCart.trigger( {
8233				type: 'tm-epo-update'
8234			} );
8235		}
8236	}
8237
8238	function fetchOptionPrices( epoObject, epoHolder, selector, total, original_total, floatingBoxData, showTotal, forced, setPriceTax, useUndiscountedPrice, mathTotal, cumulative ) {
8239		var obj;
8240		var noDpd;
8241		var priceArray;
8242		var priceCacheSelector = epoHolder.attr( 'class' ) + epoHolder.attr( 'data-uniqid' ) + selector + epoObject.is_associated + setPriceTax + forced + setPriceTax + useUndiscountedPrice || 'none';
8243		var total_taxed;
8244		var original_total_taxed;
8245		var vat_total = 0;
8246		var currentTotalsContainer;
8247		var epoinline;
8248		var funcTotal;
8249		var cumulativeTotal;
8250
8251		if ( priceCacheSelector !== 'none' && priceCache !== true && priceCache !== false && priceCache[ priceCacheSelector ] !== undefined ) {
8252			return priceCache[ priceCacheSelector ];
8253		}
8254
8255		noDpd = useUndiscountedPrice ? 'undiscounted_' : '';
8256		obj = epoHolder.find( selector );
8257		if ( epoObject.is_associated === false ) {
8258			obj = obj.not( tcAPI.associatedEpoSelector + ' ' + selector + ',.cpf-type-variations ' + selector );
8259		}
8260		if ( ! forced ) {
8261			obj = obj.filter( '.tcenabled' );
8262		}
8263
8264		if ( ! total ) {
8265			total = 0;
8266		}
8267		if ( ! original_total ) {
8268			original_total = 0;
8269		}
8270
8271		funcTotal = total;
8272		cumulativeTotal = total;
8273
8274		total_taxed = total;
8275		original_total_taxed = original_total;
8276
8277		if ( ! floatingBoxData ) {
8278			floatingBoxData = [];
8279		}
8280
8281		currentTotalsContainer = epoObject.this_epo_totals_container;
8282
8283		if ( obj.length ) {
8284			obj.toArray().forEach( function( tmcpfield ) {
8285				var field = $( tmcpfield );
8286				var _value = '';
8287				var fieldval;
8288				var field_div = field.closest( '.cpf-element' );
8289				var field_wrap = field.closest( '.tmcp-field-wrap' );
8290				var field_label_show = field_div.attr( 'data-fblabelshow' );
8291				var field_value_show = field_div.attr( 'data-fbvalueshow' );
8292				var field_title = '';
8293				var option_quantity = field_wrap.find( '.tm-qty' ).val();
8294				var option_price;
8295				var option_price_taxed;
8296				var option_original_price;
8297				var option_original_price_taxed;
8298				var liw;
8299				var cri;
8300				var tl;
8301				var options;
8302				var forrangepicker;
8303				var $decimals;
8304				var _valueText = '';
8305				var setter;
8306				var dofloatingBoxData = false;
8307
8308				if ( selector === '.tc-epo-field-product' ) {
8309					if ( field_div.is( '.cpf-type-product-thumbnailmultiple' ) || field_div.is( '.cpf-type-product-checkbox' ) ) {
8310						epoinline = field.closest( '.tc-epo-element-product-holder' ).find( '.tc-extra-product-options-inline' );
8311					} else if ( field_div.is( '.cpf-type-product-thumbnail' ) || field_div.is( '.cpf-type-product-radio' ) || field_div.is( '.cpf-type-product-dropdown' ) ) {
8312						epoinline = field_div.find( '.tc-epo-element-product-container[data-product_id="' + field.val() + '"]' ).find( '.tc-extra-product-options-inline' );
8313					} else if ( field_div.is( '.cpf-type-product-single' ) ) {
8314						epoinline = field_div.find( '.tc-extra-product-options-inline' );
8315					}
8316					currentTotalsContainer = $( '.tc-epo-totals' + '.tm-product-id-' + epoinline.attr( 'data-product-id' ) + '[data-epo-id="' + epoinline.attr( 'data-epo-id' ) + '"]' );
8317				}
8318
8319				if ( currentTotalsContainer.length ) {
8320					if ( field_label_show === '' ) {
8321						field_title = field_div.find( '.tc-epo-element-label-text' ).html();
8322					}
8323
8324					if ( option_quantity === undefined ) {
8325						option_quantity = '';
8326					}
8327					if ( mathTotal ) {
8328						tm_element_epo_rules( epoObject, field, undefined, undefined, undefined, undefined, funcTotal, cumulativeTotal );
8329					}
8330					if ( field.is( ':checkbox, :radio, :input' ) ) {
8331						option_price = 0;
8332						option_price_taxed = 0;
8333						option_original_price = 0;
8334						option_original_price_taxed = 0;
8335						if ( field.is( '.tmcp-checkbox, .tmcp-radio' ) ) {
8336							if ( forced || field.is( ':checked' ) ) {
8337								option_price = field.data( noDpd + 'raw_price' );
8338								option_price_taxed = field.data( noDpd + 'price' );
8339								option_original_price = field.data( noDpd + 'raw_original_price' );
8340								option_original_price_taxed = field.data( noDpd + 'original_price' );
8341								showTotal = true;
8342								field.data( 'isset', 1 );
8343								liw = field.closest( 'li.tmcp-field-wrap' );
8344								cri = liw.find( '.tc-image' );
8345								_value = '';
8346								_valueText = '';
8347
8348								tl = field.closest( 'li.tmcp-field-wrap' ).find( '.tc-label-text' );
8349								if ( tl.length ) {
8350									_value = tl.html();
8351									_valueText = _value;
8352								}
8353
8354								if ( cri.length ) {
8355									cri = cri.closest( '.tc-label-wrap' ).clone().addClass( 'tc-img-floating' );
8356									cri.find( '.tc-label, .tc-epo-style-wrapper, .tc-input-wrap' ).remove();
8357									_value = cri[ 0 ].outerHTML + '<span class="tc-label-text">' + _value + '</span>';
8358								}
8359								dofloatingBoxData = true;
8360							} else {
8361								field.data( 'isset', 0 );
8362							}
8363						} else if ( field.is( '.tmcp-select' ) ) {
8364							setter = field.find( 'option:selected' );
8365							option_price = setter.data( noDpd + 'raw_price' );
8366							option_price_taxed = setter.data( noDpd + 'price' );
8367							option_original_price = setter.data( noDpd + 'raw_original_price' );
8368							option_original_price_taxed = setter.data( noDpd + 'original_price' );
8369
8370							options = field.children( 'option:selected' );
8371							if ( ! ( options.val() === '' && options.attr( 'data-rulestype' ) === '' ) ) {
8372								showTotal = true;
8373							}
8374
8375							field.find( 'option' ).data( 'isset', 0 );
8376							setter.data( 'isset', 1 );
8377
8378							if ( ! ( setter.val() === '' && setter.attr( 'data-rulestype' ) === '' ) ) {
8379								_value = setter.attr( 'data-text' );
8380								dofloatingBoxData = true;
8381								_valueText = _value;
8382							}
8383						} else if ( field.is( '.tmcp-selectmultiple' ) ) {
8384							setter = field.find( 'option:selected' );
8385							setter.toArray().forEach( function( setterel ) {
8386								setterel = $( setterel );
8387								option_price = option_price + $.epoAPI.math.toFloat( setterel.data( noDpd + 'raw_price' ) );
8388								option_price_taxed = option_price_taxed + $.epoAPI.math.toFloat( setterel.data( noDpd + 'price' ) );
8389								option_original_price = option_original_price + $.epoAPI.math.toFloat( setterel.data( noDpd + 'raw_original_price' ) );
8390								option_original_price_taxed = option_original_price_taxed + $.epoAPI.math.toFloat( setterel.data( noDpd + 'original_price' ) );
8391
8392								options = field.children( 'option:selected' );
8393								if ( ! ( options.val() === '' && options.attr( 'data-rulestype' ) === '' ) ) {
8394									showTotal = true;
8395								}
8396
8397								field.find( 'option' ).data( 'isset', 0 );
8398								setterel.data( 'isset', 1 );
8399
8400								if ( ! ( setterel.val() === '' && setterel.attr( 'data-rulestype' ) === '' ) ) {
8401									_value = setterel.attr( 'data-text' );
8402									dofloatingBoxData = true;
8403									_valueText = _value;
8404								}
8405							} );
8406						} else {
8407							fieldval = field.val();
8408							if ( field.is( "[type='file']" ) ) {
8409								fieldval = fieldval.replace( 'C:\\fakepath\\', '' );
8410							}
8411							if ( fieldval ) {
8412								if ( field.is( '.tmcp-range' ) && fieldval === '0' ) {
8413									field.data( 'isset', 0 );
8414								} else {
8415									option_price = field.data( noDpd + 'raw_price' );
8416									option_price_taxed = field.data( noDpd + 'price' );
8417									option_original_price = field.data( noDpd + 'raw_original_price' );
8418									option_original_price_taxed = field.data( noDpd + 'original_price' );
8419									showTotal = true;
8420									field.data( 'isset', 1 );
8421
8422									_value = fieldval;
8423									if ( field.is( '.tmcp-range' ) ) {
8424										forrangepicker = field.closest( '.tmcp-field-wrap' ).find( '.tm-range-picker' );
8425										$decimals = forrangepicker.attr( 'data-step' ).split( '.' );
8426										if ( $decimals.length === 1 ) {
8427											$decimals = 0;
8428										} else {
8429											$decimals = $decimals[ 1 ].length;
8430										}
8431										_value = formatPrice( _value, { precision: $decimals } );
8432									}
8433									dofloatingBoxData = true;
8434									if ( field.is( '.tmcp-dynamic' ) ) {
8435										field_label_show = 'hidden';
8436										field_value_show = 'hidden';
8437									}
8438									_valueText = fieldval;
8439								}
8440							} else {
8441								field.data( 'isset', 0 );
8442							}
8443						}
8444						if ( ! option_price ) {
8445							option_price = 0;
8446						}
8447						if ( ! option_original_price ) {
8448							option_original_price = 0;
8449						}
8450						if ( ! option_price_taxed ) {
8451							option_price_taxed = 0;
8452						}
8453						if ( ! option_original_price_taxed ) {
8454							option_original_price_taxed = 0;
8455						}
8456						if ( dofloatingBoxData ) {
8457							floatingBoxData.push( {
8458								title: field_title,
8459								value: _value,
8460								valueText: _valueText,
8461								price: option_price_taxed,
8462								original_price: option_original_price_taxed,
8463								quantity: option_quantity,
8464								label_show: field_label_show,
8465								value_show: field_value_show,
8466								input_type: field.attr( 'type' )
8467							} );
8468						}
8469
8470						option_price_taxed = tm_set_tax_price( option_price, currentTotalsContainer, field, undefined, undefined, undefined, true );
8471						option_original_price_taxed = tm_set_tax_price( option_original_price, currentTotalsContainer, field, undefined, undefined, undefined, true );
8472
8473						if ( setPriceTax ) {
8474							option_price = option_price_taxed;
8475							option_original_price = option_original_price_taxed;
8476						}
8477
8478						total = $.epoAPI.math.toFloat( total ) + $.epoAPI.math.toFloat( option_price );
8479						total = $.epoAPI.math.toFloat( $.epoAPI.math.round( total, 10 ) );
8480						original_total = $.epoAPI.math.toFloat( original_total ) + $.epoAPI.math.toFloat( option_original_price );
8481						original_total = $.epoAPI.math.toFloat( $.epoAPI.math.round( original_total, 10 ) );
8482
8483						total_taxed = $.epoAPI.math.toFloat( total_taxed ) + $.epoAPI.math.toFloat( option_price_taxed );
8484						total_taxed = $.epoAPI.math.toFloat( $.epoAPI.math.round( total_taxed, 10 ) );
8485						vat_total = vat_total + $.epoAPI.math.toFloat( calculateTaxAmount( option_price_taxed, currentTotalsContainer ) );
8486						original_total_taxed = $.epoAPI.math.toFloat( original_total_taxed ) + $.epoAPI.math.toFloat( option_original_price_taxed );
8487						original_total_taxed = $.epoAPI.math.toFloat( $.epoAPI.math.round( original_total_taxed, 10 ) );
8488
8489						if ( cumulative ) {
8490							cumulativeTotal = total;
8491						}
8492					}
8493				}
8494			} );
8495		}
8496		priceArray = {
8497			total: total,
8498			original_total: original_total,
8499			total_taxed: total_taxed,
8500			original_total_taxed: original_total_taxed,
8501			vat_total: vat_total,
8502			floatingBoxData: floatingBoxData,
8503			showTotal: showTotal,
8504			elementsLength: obj.length
8505		};
8506
8507		if ( priceCache === true ) {
8508			priceCache = {};
8509			priceCache[ priceCacheSelector ] = priceArray;
8510		} else if ( priceCache !== true && priceCache !== false ) {
8511			priceCache[ priceCacheSelector ] = priceArray;
8512		}
8513
8514		return priceArray;
8515	}
8516
8517	function show_product_html( thisEpoObject, thisMainProduct, thisVariableProductContainer, type, $this, currentCart, variableProductContainers, isTrigger, qtyalt ) {
8518		var epoObjectCopy = $.extend( true, {}, thisEpoObject );
8519		var item_tm_extra_product_options = thisVariableProductContainer.find( tcAPI.associatedEpoSelector );
8520		var item = thisVariableProductContainer;
8521		var newEpoObject;
8522		var showOnly = true;
8523
8524		if ( item.closest( '.cpf-element' ).is( '.tc-hidden' ) ) {
8525			return;
8526		}
8527
8528		variableProductContainers.addClass( 'tm-hidden' );
8529		if ( variableProductContainers.length ) {
8530			toggleState( variableProductContainers, true );
8531		}
8532
8533		if ( type === 'variable' ) {
8534			if ( ! thisVariableProductContainer.is( '.tc-init-variations' ) ) {
8535				thisVariableProductContainer.addClass( 'variations_form' );
8536				setTimeout( function() {
8537					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 );
8538					thisVariableProductContainer.addClass( 'tc-init-variations' );
8539					thisVariableProductContainer.tc_product_variation_form( $this, currentCart, variableProductContainers, newEpoObject );
8540				}, 40 );
8541				showOnly = false;
8542			} else {
8543				thisVariableProductContainer.trigger( 'refresh.tc-variation-form' );
8544			}
8545		} else if ( ! thisVariableProductContainer.is( '.tc-init-product' ) ) {
8546			thisVariableProductContainer.addClass( 'tc-init-product' );
8547			variableProductContainers.find( '.tc-epo-element-variable-product' ).removeClass( 'variations_form' );
8548			variableProductContainers.find( '.tc-epo-element-variations' ).removeClass( 'variations' );
8549
8550			setTimeout( function() {
8551				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 );
8552			}, 20 );
8553			showOnly = false;
8554		}
8555
8556		setTimeout( function() {
8557			if ( variableProductContainers.length ) {
8558				toggleState( thisVariableProductContainer, false );
8559			}
8560		}, 200 );
8561		setTimeout( function() {
8562			if ( qtyalt.length ) {
8563				qtyalt.trigger( 'change' );
8564			}
8565			if ( thisVariableProductContainer.find( tcAPI.epoSelector ).length === 0 ) {
8566				thisVariableProductContainer.addClass( 'no-epo' );
8567			}
8568			thisVariableProductContainer.removeClass( 'tm-hidden' );
8569			if ( showOnly ) {
8570				jWindow.trigger( 'cpflogicdone' );
8571				thisVariableProductContainer.find( '.tm-quantity' ).trigger( 'showhide.cpfcustom' );
8572			}
8573			if ( isTrigger === undefined && TMEPOJS.tm_epo_global_product_element_scroll === 'yes' ) {
8574				jWindow.tcScrollTo( thisVariableProductContainer, 200, $.epoAPI.math.toFloat( TMEPOJS.tm_epo_global_product_element_scroll_offset ) );
8575			}
8576		}, 210 );
8577	}
8578
8579	function epoEventHandlers( epoObject, cartContainer, alternativeCart ) {
8580		// if cartContainer & alternativeCart is defined we are on a non default product (eg. composite product)
8581		var product_id = epoObject.product_id;
8582		var main_product = epoObject.main_product;
8583		var main_cart = epoObject.main_cart;
8584		var this_epo_container = epoObject.this_epo_container;
8585		var this_totals_container = epoObject.this_totals_container;
8586		var this_epo_totals_container = epoObject.this_epo_totals_container;
8587		var epoEventId = epoObject.epoEventId;
8588		var main_epo_inside_form = epoObject.main_epo_inside_form;
8589		var epo_id_selector = epoObject.epo_id_selector;
8590		var epo_id = epoObject.epo_id;
8591		var product_id_selector = epoObject.product_id_selector;
8592		var itemId = 'main';
8593		var epoHolder;
8594		var totalsHolderContainer;
8595		var totalsHolder;
8596		var currentCart;
8597		var variation_id_selector;
8598		var this_product_type;
8599		var variationForm;
8600		var qtyElement;
8601		var finalTotalBoxMode;
8602		var finalTotalBoxShowFinal;
8603		var finalTotalBoxShowOptions;
8604		var eventName = epoObject.is_associated ? 'tc-variation-form' : 'wc-variation-form';
8605		var eventNamePrefix = epoObject.is_associated ? 'tc_' : '';
8606		var epoVariationSection;
8607		var thismaxlength;
8608		var epoFieldAll;
8609		var selectSelector;
8610		var epoFieldText;
8611		var epoResetRadio;
8612		var epoFieldUpload;
8613		var epoFieldHasClearButton;
8614		var tmQty;
8615		var tmQuantity;
8616
8617		// Non default product (eg. composite product)
8618		if ( alternativeCart && cartContainer ) {
8619			itemId = $.epoAPI.applyFilter( 'tc_get_item_id', cartContainer.attr( 'data-item_id' ), cartContainer );
8620			epoHolder = main_product.find( '.tm-extra-product-options.tm-cart-' + itemId );
8621			totalsHolderContainer = main_product.find( '.tm-totals-form-' + itemId );
8622			totalsHolder = main_product.find( '.tm-epo-totals.tm-cart-' + itemId );
8623			variationForm = cartContainer.find( '.variations_form' ).first();
8624		// Default product
8625		} else {
8626			if ( ! main_cart || main_cart.length === 0 ) {
8627				if ( this_epo_container.is( '.tc-shortcode' ) ) {
8628					main_cart = main_product;
8629				} else {
8630					main_cart = get_main_cart( main_product, main_product, 'form', product_id );
8631				}
8632			}
8633			cartContainer = main_cart.parent();
8634			epoHolder = this_epo_container;
8635			totalsHolderContainer = this_totals_container;
8636			totalsHolder = this_epo_totals_container;
8637			variationForm = epoObject.variations_form;
8638		}
8639
8640		if ( epoObject.is_associated ) {
8641			itemId = epoHolder.attr( 'data-cart-id' );
8642		}
8643
8644		currentCart = alternativeCart || main_cart;
8645		totalsHolder.data( 'tm_for_cart', currentCart );
8646
8647		variation_id_selector = getVariationIdSelector( currentCart );
8648		qtyElement = getQtyElement( currentCart );
8649
8650		totalsHolder.data( 'variationIdElement', getVariationIdElement( currentCart, '.wceb_picker_wrap ' + variation_id_selector ) );
8651		totalsHolder.data( 'qty_element', qtyElement );
8652
8653		this_product_type = totalsHolder.data( 'type' );
8654
8655		variationForm.data( 'tc_product_id', product_id );
8656
8657		finalTotalBoxMode = totalsHolder.attr( 'data-tm-epo-final-total-box' );
8658		finalTotalBoxShowFinal = totalsHolder.attr( 'data-tm-epo-show-final-total' );
8659		finalTotalBoxShowOptions = totalsHolder.attr( 'data-tm-epo-show-options-total' );
8660
8661		jWindow.on( 'epoCalculateRules', function( event, dataObject ) {
8662			if ( event && dataObject && dataObject.currentCart ) {
8663				tm_epo_rules( epoObject, dataObject.currentCart );
8664			}
8665		} );
8666
8667		if ( currentCart.is( 'form' ) ) {
8668			currentCart.on( 'reset', function() {
8669				var form = $( this );
8670				setTimeout( function() {
8671					$( form.data( 'epo_id_selector' ) ).find( '.tm-epo-field' ).trigger( 'change' );
8672				}, 1 );
8673			} );
8674		}
8675
8676		tm_epo_rules( epoObject, currentCart );
8677
8678		epoFieldAll = epoHolder.find( '.tm-epo-field' );
8679		if ( ! epoObject.is_associated ) {
8680			epoFieldAll = epoFieldAll.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector + ' .tm-epo-field' );
8681		}
8682
8683		epoFieldText = epoHolder.find( '.tm-epo-field.tmcp-textarea,.tm-epo-field.tmcp-textfield' );
8684		if ( ! epoObject.is_associated ) {
8685			epoFieldText = epoFieldText.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector + ' .tm-epo-field' );
8686		}
8687
8688		epoResetRadio = epoHolder.find( '.tm-epo-reset-radio' );
8689		if ( ! epoObject.is_associated ) {
8690			epoResetRadio = epoResetRadio.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector + ' .tm-epo-reset-radio' );
8691		}
8692
8693		epoFieldUpload = epoHolder.find( '.tm-epo-field.tmcp-upload' );
8694		if ( ! epoObject.is_associated ) {
8695			epoFieldUpload = epoFieldUpload.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector + ' .tm-epo-field.tmcp-upload' );
8696		}
8697
8698		epoFieldHasClearButton = epoHolder.find( '.tm-has-clearbutton .tm-epo-field' );
8699		if ( ! epoObject.is_associated ) {
8700			epoFieldHasClearButton = epoFieldHasClearButton.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector + ' .tm-has-clearbutton .tm-epo-field' );
8701		}
8702
8703		tmQty = epoHolder.find( '.tm-quantity .tm-qty' );
8704		if ( ! epoObject.is_associated ) {
8705			tmQty = tmQty.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector + ' .tm-quantity .tm-qty' );
8706		}
8707
8708		tmQuantity = epoHolder.find( '.tm-quantity' );
8709		if ( ! epoObject.is_associated ) {
8710			tmQuantity = tmQuantity.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector + ' .tm-quantity' );
8711		}
8712
8713		selectSelector = epoHolder.find( 'select.tm-epo-field' );
8714		if ( ! epoObject.is_associated ) {
8715			selectSelector = selectSelector.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector + ' select.tm-epo-field' );
8716		}
8717		// update price amount for select elements
8718		selectSelector
8719			.off( 'tm-select-change-html' )
8720			.on( 'tm-select-change-html', function() {
8721				var field = $( this );
8722				var formatted_price;
8723				var original_formatted_price;
8724				var e_tip;
8725				var e_description;
8726				var sign;
8727
8728				if ( field.is( '.tc-epo-field-product' ) || field.is( '.tmcp-selectmultiple' ) ) {
8729					return;
8730				}
8731
8732				if ( main_cart && main_cart.data( 'per_product_pricing' ) !== undefined && ! main_cart.data( 'per_product_pricing' ) ) {
8733					return;
8734				}
8735
8736				formatted_price = tm_set_price( field.find( 'option:selected' ).data( 'price' ), totalsHolder, true, false, field );
8737				original_formatted_price = tm_set_price( field.find( 'option:selected' ).data( 'original_price' ), totalsHolder, true, false, field );
8738				e_tip = field.closest( '.tmcp-field-wrap' ).find( '.tc-tooltip' );
8739				e_description = field.closest( '.tmcp-field-wrap' ).find( '.tc-inline-description' );
8740
8741				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 );
8742
8743				if ( e_tip.length > 0 ) {
8744					e_tip.attr( 'data-tm-tooltip-html', field.find( 'option:selected' ).attr( 'data-tm-tooltip-html' ) ).trigger( 'tc-tooltip-html-changed' );
8745				}
8746
8747				if ( e_description.length > 0 ) {
8748					if ( field.find( 'option:selected' ).attr( 'data-tm-tooltip-html' ) ) {
8749						e_description.html( field.find( 'option:selected' ).attr( 'data-tm-tooltip-html' ) );
8750					} else {
8751						e_description.html( '' );
8752					}
8753				}
8754
8755				if (
8756					( field.find( 'option:selected' ).attr( 'data-hide-amount' ) === '0' || TMEPOJS.tm_epo_show_price_inside_option_hidden_even === 'yes' ) &&
8757					TMEPOJS.tm_epo_show_price_inside_option === 'yes' &&
8758					field.find( 'option:selected' ).attr( 'data-text' ) &&
8759					field.find( 'option:selected' ).data( 'price' )
8760				) {
8761					if (
8762						( TMEPOJS.tm_epo_auto_hide_price_if_zero === 'yes' && $.tmempty( field.find( 'option:selected' ).data( 'price' ) ) === false ) ||
8763						( TMEPOJS.tm_epo_auto_hide_price_if_zero !== 'yes' && field.find( 'option:selected' ).attr( 'data-
8763price' ) !== '' )
8764					) {
8765						sign = '';
8766						field.find( 'option:selected' ).html( field.find( 'option:selected' ).attr( 'data-text' ) + ' (' + sign + formatted_price + ')' );
8767					}
8768				}
8769
8770				if ( field.val() === '' ) {
8771					e_tip.addClass( 'tm-hidden' );
8772				} else if ( field.find( 'option:selected' ).attr( 'data-tm-tooltip-html' ) ) {
8773					e_tip.removeClass( 'tm-hidden' );
8774				} else {
8775					e_tip.addClass( 'tm-hidden' );
8776				}
8777			} )
8778			.off( 'tm-math-select-change-html-all tm-select-change-html-all tm-select-change-html-all-math' )
8779			.on( 'tm-math-select-change-html-all tm-select-change-html-all tm-select-change-html-all-math', function( event ) {
8780				var field = $( this );
8781				var e_tip;
8782				var e_description;
8783				var thisoption;
8784				var divider;
8785				var thisformatted_price;
8786
8787				if ( field.is( '.tc-epo-field-product' ) ) {
8788					return;
8789				}
8790
8791				e_tip = field.closest( '.tmcp-field-wrap' ).find( '.tc-tooltip' );
8792				e_description = field.closest( '.tmcp-field-wrap' ).find( '.tc-inline-description' );
8793
8794				if ( e_tip.length > 0 ) {
8795					e_tip.attr( 'data-tm-tooltip-html', field.find( 'option:selected' ).attr( 'data-tm-tooltip-html' ) ).trigger( 'tc-tooltip-html-changed' );
8796				}
8797
8798				if ( field.val() === '' ) {
8799					e_tip.addClass( 'tm-hidden' );
8800				} else if ( field.find( 'option:selected' ).attr( 'data-tm-tooltip-html' ) ) {
8801					e_tip.removeClass( 'tm-hidden' );
8802				} else {
8803					e_tip.addClass( 'tm-hidden' );
8804				}
8805
8806				if ( e_description.length > 0 ) {
8807					if ( field.find( 'option:selected' ).attr( 'data-tm-tooltip-html' ) ) {
8808						e_description.html( field.find( 'option:selected' ).attr( 'data-tm-tooltip-html' ) );
8809					} else {
8810						e_description.html( '' );
8811					}
8812				}
8813
8814				if ( main_cart && main_cart.data( 'per_product_pricing' ) !== undefined && ! main_cart.data( 'per_product_pricing' ) ) {
8815					return;
8816				}
8817
8818				if ( TMEPOJS.tm_epo_show_price_inside_option === 'yes' ) {
8819					field.find( 'option' ).each( function() {
8820						thisoption = $( this );
8821						if ( ! thisoption.val() ) {
8822							return true;
8823						}
8824
8825						if ( event.type === 'tm-select-change-html-all' ) {
8826							thisoption.removeClass( 'tm-epo-late-field' ).removeData( 'tm-price-for-late islate' );
8827							tm_element_epo_rules( epoObject, field, undefined, thisoption, 1 );
8828						} else if ( event.type === 'tm-math-select-change-html-all' ) {
8829							tm_element_epo_rules( epoObject, field, undefined, thisoption, 1, true );
8830						} else if ( event.type === 'tm-select-change-html-all-math' ) {
8831							thisoption.removeClass( 'tm-epo-late-field' ).removeData( 'tm-price-for-late islate' );
8832							tm_element_epo_rules( epoObject, field, undefined, thisoption, 1, true );
8833						}
8834						divider = 1;
8835
8836						if ( TMEPOJS.tm_epo_multiply_price_inside_option !== 'yes' ) {
8837							divider = field.data( 'tm-quantity' );
8838						}
8839
8840						if ( ! divider ) {
8841							divider = 1;
8842						}
8843
8844						if ( thisoption.data( 'price' ) ) {
8845							thisformatted_price = tm_set_price( thisoption.data( 'price' ) / divider, totalsHolder, true, false, field );
8846
8847							if ( ( thisoption.attr( 'data-hide-amount' ) === '0' || TMEPOJS.tm_epo_show_price_inside_option_hidden_even === 'yes' ) && thisoption.attr( 'data-text' ) ) {
8848								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' ) !== '' ) ) {
8849									thisoption.html( thisoption.attr( 'data-text' ) + ' (' + thisformatted_price + ')' );
8850								}
8851							}
8852						}
8853					} );
8854				}
8855			} )
8856			.off( 'tm-select-price-update-html-all' )
8857			.on( 'tm-select-price-update-html-all', function() {
8858				var field = $( this );
8859				var thisoption;
8860				var divider;
8861				var thisformatted_price;
8862
8863				if ( field.is( '.tc-epo-field-product' ) ) {
8864					return;
8865				}
8866
8867				if ( main_cart && main_cart.data( 'per_product_pricing' ) !== undefined && ! main_cart.data( 'per_product_pricing' ) ) {
8868					return;
8869				}
8870
8871				if ( TMEPOJS.tm_epo_show_price_inside_option === 'yes' ) {
8872					field.find( 'option' ).each( function() {
8873						thisoption = $( this );
8874						if ( ! thisoption.val() ) {
8875							return true;
8876						}
8877
8878						divider = 1;
8879
8880						if ( TMEPOJS.tm_epo_multiply_price_inside_option !== 'yes' ) {
8881							divider = field.data( 'tm-quantity' );
8882						}
8883
8884						if ( ! divider ) {
8885							divider = 1;
8886						}
8887
8888						if ( thisoption.data( 'price' ) ) {
8889							thisformatted_price = tm_set_price( thisoption.data( 'price' ) / divider, totalsHolder, true, false, field );
8890
8891							if ( ( thisoption.attr( 'data-hide-amount' ) === '0' || TMEPOJS.tm_epo_show_price_inside_option_hidden_even === 'yes' ) && thisoption.attr( 'data-text' ) ) {
8892								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-
8892price' ) !== '' ) ) {
8893									thisoption.html( thisoption.attr( 'data-text' ) + ' (' + thisformatted_price + ')' );
8894								}
8895							}
8896						}
8897					} );
8898				}
8899			} )
8900			.off( 'tm-select-change' )
8901			.on( 'tm-select-change', function() {
8902				var field = $( this );
8903				var thisElementId = field.closest( '.cpf-element' ).attr( 'data-uniqid' );
8904
8905				if ( field.is( '.tc-epo-field-product' ) ) {
8906					return;
8907				}
8908
8909				if ( main_cart && main_cart.data( 'per_product_pricing' ) !== undefined && ! main_cart.data( 'per_product_pricing' ) ) {
8910					return;
8911				}
8912
8913				field.removeData( 'addedtcEpoBeforeOptionPriceCalculation' );
8914				field.removeData( 'addedfieldtcEpoBeforeOptionPriceCalculation' );
8915				jWindow.off( 'tcEpoBeforeOptionPriceCalculation.math' + thisElementId );
8916				jWindow.off( 'tcEpoAfterNormalOptionPriceCalculation.math' + thisElementId );
8917
8918				field.trigger( 'tm-select-change-html' );
8919				field.trigger( 'tm-select-change-html-all' );
8920
8921				currentCart.trigger( {
8922					type: 'tm-epo-update',
8923					norules: 1,
8924					element: field
8925				} );
8926			} ).trigger( 'tm-select-change-html-all' );
8927
8928		// Element quantity selector
8929		tmQty
8930			.off( 'focus.cpf' )
8931			.on( 'focus.cpf', function() {
8932				var qtyField = $( this );
8933				var field = qtyField.closest( '.tmcp-field-wrap' ).find( '.tm-epo-field' );
8934				var currentVal = parseFloat( qtyField.val() );
8935				var max = parseFloat( qtyField.attr( 'max' ) );
8936				var min = parseFloat( qtyField.attr( 'min' ) );
8937				var step = qtyField.attr( 'step' );
8938				var check1 = tm_limit_c_selection( field, false );
8939				var check2 = tm_exact_c_selection( field, false );
8940				var check3 = true;
8941
8942				// Format values
8943				if ( ! currentVal || currentVal === '' || currentVal === 'NaN' ) {
8944					currentVal = 0;
8945				}
8946				if ( max === '' || max === 'NaN' ) {
8947					max = '';
8948				}
8949				if ( min === '' || min === 'NaN' ) {
8950					min = 0;
8951				}
8952				if ( step === 'any' || step === '' || step === undefined || parseFloat( step ) === 'NaN' ) {
8953					step = 1;
8954				}
8955
8956				if ( currentVal < min || currentVal > max ) {
8957					check3 = false;
8958				}
8959
8960				if ( check1 && check2 && check3 ) {
8961					qtyField.data( 'tm-prev-value', currentVal );
8962				} else {
8963					qtyField.data( 'tm-prev-value', min );
8964				}
8965			} )
8966			.off( 'change.cpf' )
8967			.on( 'change.cpf', function( event, data ) {
8968				var qtyField = $( this );
8969				var field = qtyField.closest( '.tmcp-field-wrap' ).find( '.tm-epo-field' );
8970				var currentVal = parseFloat( qtyField.val() );
8971				var max = parseFloat( qtyField.attr( 'max' ) );
8972				var min = parseFloat( qtyField.attr( 'min' ) );
8973				var step = qtyField.attr( 'step' );
8974				var check1 = tm_limit_c_selection( field, false );
8975				var check2 = tm_exact_c_selection( field, false );
8976				var check3 = true;
8977
8978				// Format values
8979				if ( ! currentVal || currentVal === '' || currentVal === 'NaN' ) {
8980					currentVal = 0;
8981				}
8982				if ( max === '' || max === 'NaN' ) {
8983					max = '';
8984				}
8985				if ( min === '' || min === 'NaN' ) {
8986					min = 0;
8987				}
8988				if ( step === 'any' || step === '' || step === undefined || parseFloat( step ) === 'NaN' ) {
8989					step = 1;
8990				}
8991
8992				if ( currentVal < min || currentVal > max ) {
8993					check3 = false;
8994				}
8995
8996				if ( check1 && check2 && check3 ) {
8997					if ( ! epoObject.noEpoUpdate ) {
8998						field.data( 'tm-quantity', qtyField.val() ).trigger( 'change', data );
8999					} else {
9000						field.data( 'tm-quantity', qtyField.val() ).trigger( 'change.cpf', data ).trigger( 'change.cpfproduct', data );
9001					}
9002					field.trigger( 'tm-select-change-html-all' );
9003				} else if ( qtyField.data( 'tm-prev-value' ) ) {
9004					qtyField.val( qtyField.data( 'tm-prev-value' ) );
9005				} else {
9006					qtyField.val( min );
9007				}
9008
9009				qtyField.trigger( 'cpf-changed' );
9010			} )
9011			.off( 'tmaddquantity' )
9012			.on( 'tmaddquantity', function() {
9013				var qtyField = $( this );
9014				var field = qtyField.closest( '.tmcp-field-wrap' ).find( '.tm-epo-field' );
9015
9016				field.data( 'tm-quantity', qtyField.val() );
9017			} );
9018
9019		// Insert characters remaining for text-areas and text-fields
9020		thismaxlength = epoHolder.find( '.tmcp-textfield.tm-epo-field[maxlength],textarea.tm-epo-field[maxlength]' );
9021		if ( ! epoObject.is_associated ) {
9022			thismaxlength = thismaxlength.not( tcAPI.epoSelector + ' ' + tcAPI.associatedEpoSelector + ' .tm-epo-field' );
9023		}
9024
9025		thismaxlength.each( function() {
9026			var field = $( this );
9027			var innerWrap;
9028			var html;
9029			if ( field.data( 'tcmaxlength' ) ) {
9030				return;
9031			}
9032			field.data( 'tcmaxlength', 1 );
9033			innerWrap = field.closest( '.tmcp-field-wrap-inner' );
9034			html = $.epoAPI.template.html( tcAPI.templateEngine.tc_chars_remanining, {
9035				maxlength: field.attr( 'maxlength' ),
9036				characters_remaining: TMEPOJS.i18n_characters_remaining
9037			} );
9038			innerWrap.append( $( html ) );
9039		} );
9040		thismaxlength
9041			.off( 'change.tc_maxlen input.tc_maxlen' )
9042			.on( 'change.tc_maxlen input.tc_maxlen', function() {
9043				var field = $( this );
9044
9045				field
9046					.closest( '.tmcp-field-wrap' )
9047					.find( '.tc-chars-remanining' )
9048					.html( parseInt( field.attr( 'maxlength' ), 10 ) - parseInt( field.val().length, 10 ) );
9049			} );
9050
9051		// Change product image event
9052		epoFieldAll
9053			.off( 'tm_trigger_product_image' )
9054			.on( 'tm_trigger_product_image', function() {
9055				var field = $( this );
9056				var currentElement;
9057				var uic;
9058				var variation_element_section;
9059				var is_variation_element;
9060				var src;
9061
9062				if ( field.is( '.tm-product-image:checkbox, .tm-product-image:radio, select.tm-product-image' ) ) {
9063					uic = field.closest( '.tmcp-field-wrap' ).find( 'label img' );
9064					variation_element_section = field.closest( '.cpf-section' );
9065					is_variation_element = variation_element_section.is( '.tm-epo-variation-section' );
9066
9067					currentElement = field;
9068					if ( field.is( 'select.tm-product-image' ) ) {
9069						currentElement = field.children( 'option:selected' );
9070					}
9071					if (
9072						$( uic ).length > 0 ||
9073						( is_variation_element && currentElement.attr( 'data-image' ) !== undefined ) ||
9074						( currentElement.attr( 'data-image' ) !== undefined && currentElement.attr( 'data-image' ) !== '' ) ||
9075						( currentElement.attr( 'data-imagep' ) !== undefined && currentElement.attr( 'data-imagep' ) !== '' )
9076					) {
9077						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' ) ) ) ) {
9078							src = $( uic ).first().attr( 'data-original' );
9079
9080							if ( ! src && ! is_variation_element ) {
9081								src = $( uic ).first().attr( 'src' );
9082							}
9083							if ( ! src ) {
9084								src = currentElement.attr( 'data-image' );
9085							}
9086							if ( currentElement.attr( 'data-imagep' ) ) {
9087								src = currentElement.attr( 'data-imagep' );
9088							}
9089							if ( src ) {
9090								main_product.trigger( 'tm_change_product_image', {
9091									src: src,
9092									element: field,
9093									element_current: currentElement,
9094									main_product: main_product,
9095									epo_holder: epoHolder
9096								} );
9097							} else {
9098								main_product.trigger( 'tm_change_product_image', {
9099									src: false,
9100									element: field,
9101									element_current: currentElement,
9102									main_product: main_product,
9103									epo_holder: epoHolder
9104								} );
9105							}
9106						} else {
9107							main_product.trigger( 'tm_restore_product_image', {
9108								element: field,
9109								element_current: currentElement,
9110								main_product: main_product,
9111								epo_holder: epoHolder
9112							} );
9113						}
9114					} else {
9115						main_product.trigger( 'tm_restore_product_image', {
9116							element: field,
9117							element_current: currentElement,
9118							main_product: main_product,
9119							epo_holder: epoHolder
9120						} );
9121					}
9122				} else {
9123					main_product.trigger( 'tm_attempt_product_image', {
9124						element: field,
9125						element_current: currentElement,
9126						main_product: main_product,
9127						epo_holder: epoHolder
9128					} );
9129				}
9130			} );
9131
9132		tmQuantity
9133			.off( 'showhide.cpfcustom' )
9134			.on( 'showhide.cpfcustom', function() {
9135				var quantity_selector = $( this );
9136				var field = quantity_selector.closest( '.tmcp-field-wrap' ).find( '.tm-epo-field' );
9137				var show = false;
9138				var tmqty;
9139				var tmqtyval;
9140				var tmqtymin;
9141				var radios;
9142
9143				if ( ! field.is( '.tm-epo-variation-element' ) ) {
9144					if ( field.is( 'select' ) ) {
9145						if ( field.val() !== '' ) {
9146							show = true;
9147						}
9148					} else if ( field.is( ':checkbox' ) ) {
9149						if ( field.is( ':checked' ) ) {
9150							show = true;
9151						}
9152					} else if ( field.is( ':radio' ) ) {
9153						if ( field.is( ':checked' ) ) {
9154							show = true;
9155							if ( TMEPOJS.tm_epo_show_only_active_quantities === 'yes' ) {
9156								radios = field.closest( '.tc-element-inner-wrap' ).find( '.tm-epo-field.tmcp-radio' );
9157								radios.each( function() {
9158									$( this ).closest( '.tmcp-field-wrap' ).find( '.tm-quantity' ).hide();
9159								} );
9160							}
9161						}
9162					} else if ( field.val() ) {
9163						show = true;
9164					}
9165
9166					tmqty = quantity_selector.find( '.tm-qty' );
9167					tmqtyval = tmqty.val();
9168					tmqtymin = tmqty.attr( 'min' ) || '';
9169
9170					if ( show ) {
9171						if ( TMEPOJS.tm_epo_show_only_active_quantities === 'yes' ) {
9172							quantity_selector.show();
9173						}
9174
9175						tmqty.removeClass( 'ignore' ).prop( 'disabled', false );
9176					} else {
9177						if ( TMEPOJS.tm_epo_show_only_active_quantities === 'yes' ) {
9178							quantity_selector.hide();
9179							if ( ! tmqtyval ) {
9180								tmqty.val( tmqtymin );
9181							}
9182						}
9183
9184						tmqty.addClass( 'ignore' ).prop( 'disabled', true );
9185					}
9186
9187					if ( epoHolder.is( '.tc-show' ) ) {
9188						setTimeout( function() {
9189							quantity_selector.closest( '.tcowl-carousel' ).trigger( 'refresh.owl.carousel' );
9190						}, 200 );
9191					}
9192				}
9193			} );
9194
9195		epoFieldAll
9196			.off( 'change.cpfcustom' )
9197			.on( 'change.cpfcustom', function() {
9198				$( this ).closest( '.tmcp-field-wrap' ).find( '.tm-quantity' ).trigger( 'showhide.cpfcustom' );
9199			} );
9200
9201		epoFieldAll
9202			.off( 'change.cpf' )
9203			.on( 'change.cpf', function( event, data ) {
9204				var field = $( this );
9205				var is_li = field.closest( '.tmcp-field-wrap' );
9206				var is_ul = field.closest( '.tmcp-ul-wrap' );
9207				var is_replace;
9208				var connector = is_ul.attr( 'data-tm-connector' );
9209
9210				if ( field.is( ':checkbox, :radio' ) ) {
9211					if ( field.is( ':radio' ) ) {
9212						if ( ! data ) {
9213							if ( connector !== undefined ) {
9214								$( '[data-tm-connector="' + connector + '"]' ).find( '.tmcp-field-wrap' ).removeClass( 'tc-active' ).find( '.tm-epo-reset-radio' ).addClass( 'tm-hidden' );
9215							} else {
9216								is_ul.find( '.tmcp-field-wrap' ).removeClass( 'tc-active' );
9217							}
9218						}
9219						if ( connector !== undefined ) {
9220							$( '[data-tm-connector="' + connector + '"]' ).find( '.tmcp-field-wrap' ).removeClass( 'tc-active' ).find( '.tm-epo-reset-radio' ).addClass( 'tm-hidden' );
9221						}
9222					}
9223					if ( field.is( ':checked' ) ) {
9224						is_li.addClass( 'tc-active' );
9225					} else {
9226						is_li.removeClass( 'tc-active' );
9227					}
9228				}
9229
9230				if ( ! field.is( '.tm-epo-variation-element' ) ) {
9231					if ( field.is( '.use_images:checkbox, .use_images:radio' ) && field.attr( 'data-imagec' ) ) {
9232						is_replace = is_li.find( '.radio-image,.checkbox-image' ).first();
9233						if ( is_replace.length > 0 ) {
9234							if ( field.is( ':checked' ) ) {
9235								is_replace.prop( 'src', field.attr( 'data-imagec' ) );
9236							} else {
9237								is_replace.prop( 'src', field.attr( 'data-image' ) );
9238							}
9239						}
9240					}
9241
9242					if ( field.is( '.use_images:radio' ) ) {
9243						field
9244							.closest( '.cpf-type-radio' )
9245							.find( '.use_images:radio' )
9246							.not( field )
9247							.each( function() {
9248								var r = $( this );
9249								r.closest( '.tmcp-field-wrap' ).find( '.radio-image' ).first().prop( 'src', r.attr( 'data-image' ) );
9250							} );
9251					}
9252
9253					if ( field.is( '.tmcp-range' ) ) {
9254						field.trigger( 'change.cpflogic' );
9255					}
9256					if ( field.is( 'select' ) ) {
9257						field.trigger( 'tm-select-change' );
9258					} else {
9259						if ( field.is( '.tmcp-radio' ) ) {
9260							field
9261								.closest( '.cpf-element' )
9262								.find( '.tm-quantity .tm-qty' )
9263								.each( function() {
9264									if ( ! $( this ).closest( 'li.tmcp-field-wrap' ).find( '.tmcp-radio' ).is( ':checked' ) ) {
9265										$( this ).attr( 'disabled', 'disabled' );
9266									} else {
9267										$( this ).prop( 'disabled', false );
9268									}
9269								} );
9270						}
9271
9272						priceCache = true;
9273						currentCart.trigger( {
9274							type: 'tm-epo-update',
9275							norules: 1,
9276							element: field
9277						} );
9278						priceCache = false;
9279					}
9280				}
9281
9282				field.trigger( 'tm_trigger_product_image' );
9283
9284				if ( epoHolder.is( '.tc-show' ) ) {
9285					setTimeout( function() {
9286						$( '.tm-owl-slider' ).each( function() {
9287							$( this ).trigger( 'refresh.owl.carousel' );
9288						} );
9289					}, 200 );
9290				}
9291				main_product.trigger( 'tm_attempt_product_image', {
9292					element: field,
9293					main_product: main_product,
9294					epo_holder: epoHolder
9295				} );
9296			} );
9297
9298		epoFieldAll.filter( '.tm-epo-field:text,input.tm-epo-field[type="number"],textarea.tm-epo-field' )
9299			.off( 'input.cpf' )
9300			.on( 'input.cpf', function() {
9301				$( this ).trigger( 'change.cpf' );
9302			} );
9303
9304		epoFieldAll
9305			.filter( ':checkbox:checked, :radio:checked' )
9306			.each( function() {
9307				$( this ).closest( '.tmcp-field-wrap' ).addClass( 'tc-active' );
9308				$( this ).trigger( 'change.cpf' );
9309			} );
9310
9311		epoFieldHasClearButton
9312			.off( 'change.cpfclearbutton' )
9313			.on( 'change.cpfclearbutton cpfclearbutton', function() {
9314				var field = $( this );
9315				var radioResetElement;
9316				var fieldWrap = field.closest( '.tmcp-field-wrap' );
9317				var fieldSearch;
9318
9319				if ( field.is( ':checked' ) ) {
9320					fieldSearch = field.closest( '.tc-element-inner-wrap' );
9321
9322					if ( fieldSearch.find( '.tc-epo-element-product-li-container' ).length ) {
9323						fieldSearch = fieldSearch.find( '.tmcp-ul-wrap' ).first().children( '.tmcp-field-wrap' ).not( '.tc-epo-element-product-li-container' );
9324					}
9325
9326					radioResetElement = fieldSearch.find( '.tm-epo-reset-radio' );
9327					if ( ! radioResetElement.length ) {
9328						radioResetElement = field.closest( '.tc-element-inner-wrap' ).find( '.tm-epo-reset-radio' ).first();
9329					}
9330					radioResetElement.removeClass( 'tm-hidden' );
9331
9332					fieldWrap.append( radioResetElement );
9333				}
9334			} );
9335
9336		epoResetRadio
9337			.off( 'click.cpf' )
9338			.on( 'click.cpf', function() {
9339				var radioResetElement = $( this );
9340				var fieldContainer = radioResetElement.closest( '.tc-element-inner-wrap' );
9341				var checkedRadios = fieldContainer.find( '.tm-epo-field.tmcp-radio:checked' );
9342
9343				if ( checkedRadios.length ) {
9344					checkedRadios.prop( 'checked', false );
9345					checkedRadios.trigger( 'change', { forced: 1 } );
9346				}
9347
9348				radioResetElement.addClass( 'tm-hidden' );
9349			} );
9350
9351		if ( _ && _.debounce ) {
9352			epoFieldText.on( 'keyup',
9353				_.debounce( function() {
9354					var $this = $( this );
9355
9356					if ( TMEPOJS.tm_epo_global_enable_validation === 'yes' && $.tc_validator && $this.closest( '.tmcp-ul-wrap' ).data( 'tm-validation' ) && $this.tc_rules() ) {
9357						currentCart.tc_validate().element( $this );
9358					}
9359					$this.trigger( 'change.cpf' );
9360					$this.closest( '.tmcp-field-wrap' ).find( '.tm-quantity' ).trigger( 'showhide.cpfcustom' );
9361				}, 10 )
9362			);
9363		}
9364
9365		epoFieldUpload
9366			.off( 'change.cpfv tcupload' )
9367			.on( 'change.cpfv tcupload', function() {
9368				var field = $( this );
9369				var label = field.closest( 'label' );
9370				var li = field.closest( '.tmcp-field-wrap' );
9371				var cpfUploadContainer = li.find( '.cpf-upload-container' );
9372				var name = li.find( '.tm-filename' );
9373				var val = field.val().replace( 'C:\\fakepath\\', '' );
9374				var valHidden = [];
9375				var num_uploads;
9376				var windowURL = window.URL || window.webkitURL;
9377				var files;
9378				var image;
9379				var uploadPreview = li.find( '.tc-upload-preview' );
9380				var addImage;
9381				var uniqid;
9382
9383				if ( cpfUploadContainer.length && name.length <= 0 ) {
9384					name = $( '<span class="tm-filename"></span>' );
9385					label.after( name );
9386				}
9387				if ( val === undefined || val === 'undefined' ) {
9388					val = '';
9389				}
9390
9391				field.next( '.tmcp-upload-hidden' ).remove();
9392
9393				valHidden = field.attr( 'data-file' );
9394				valHidden = valHidden ? valHidden.split( '|' ) : [];
9395				if ( this.files ) {
9396					files = Array.from( this.files );
9397				} else if ( valHidden.length > 0 ) {
9398					files = valHidden;
9399				}
9400
9401				if ( files.length > 1 ) {
9402					name.html( '' + files.length + ' ' + ( files.length === 1 ? TMEPOJS.i18n_file : TMEPOJS.i18n_files ) );
9403				} else if ( files.length === 1 ) {
9404					name.html( val );
9405				} else {
9406					name.empty();
9407				}
9408				if ( ! uploadPreview.length ) {
9409					uploadPreview = $( '<div class="tc-upload-preview tc-hidden"></div>' );
9410					li.append( uploadPreview );
9411				}
9412
9413				uploadPreview.empty();
9414
9415				num_uploads = epoHolder.data( 'num_uploads' );
9416				if ( ! num_uploads ) {
9417					num_uploads = [];
9418				}
9419				uniqid = field.closest( '.cpf-element' ).attr( 'data-uniqid' );
9420				if ( ! num_uploads[ uniqid ] ) {
9421					num_uploads[ uniqid ] = [];
9422				}
9423
9424				if ( ( val || files.length > 0 ) && windowURL && windowURL.createObjectURL ) {
9425					if ( TMEPOJS.tm_epo_upload_inline_image_preview === 'yes' ) {
9426						if ( files.length > 1 ) {
9427							uploadPreview.addClass( 'multiple' );
9428						} else {
9429							uploadPreview.removeClass( 'multiple' );
9430						}
9431						uploadPreview.removeClass( 'tc-hidden' );
9432					}
9433					addImage = function( dataFile, src, i, fileHolder, ext ) {
9434						var size = field[ 0 ].files && field[ 0 ].files[ i ] && field[ 0 ].files[ i ].size ? field[ 0 ].files[ i ].size : 0;
9435						var imageHTML = '<div class="tc-upload-image">';
9436						if ( src ) {
9437							imageHTML = imageHTML + '<img src="' + src + '">';
9438						} else {
9439							imageHTML = imageHTML + '<div class="tc-file-ext-overlay"></div>';
9440						}
9441						imageHTML = imageHTML + '<div class="tc-file-name">' + dataFile.name + '</div>';
9442						if ( ClipboardEvent || DataTransfer ) {
9443							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>';
9444						}
9445						if ( ext ) {
9446							imageHTML = imageHTML + '<div class="tc-file-ext">' + ext + '</div>';
9447						}
9448						imageHTML = imageHTML + '<div class="tc-file-size">' + readableFileSize( size ) + '</div>';
9449						imageHTML = imageHTML + '</div>';
9450						fileHolder.append( imageHTML );
9451					};
9452
9453					files.forEach( function( dataFile, i ) {
9454						var fileHolder;
9455						if ( TMEPOJS.tm_epo_upload_inline_image_preview === 'yes' ) {
9456							fileHolder = $( '<div class="tc-upload-file"></div>' );
9457							uploadPreview.append( fileHolder );
9458							image = new Image();
9459							image.onload = function() {
9460								addImage( dataFile, this.src, i, fileHolder );
9461							};
9462							image.onerror = function() {
9463								addImage( dataFile, false, i, fileHolder, dataFile.name.split( '.' ).pop() );
9464							};
9465							if ( valHidden.length > 0 ) {
9466								image.src = valHidden[ i ];
9467							} else {
9468								image.src = windowURL.createObjectURL( dataFile );
9469								windowURL.revokeObjectURL( dataFile );
9470							}
9471						}
9472						num_uploads[ uniqid ].push( dataFile.name );
9473					} );
9474					epoHolder.data( 'num_uploads', num_uploads );
9475				} else {
9476					delete num_uploads[ uniqid ];
9477				}
9478				if ( num_uploads[ uniqid ] && num_uploads[ uniqid ].length === 0 ) {
9479					delete num_uploads[ uniqid ];
9480				}
9481			} );
9482
9483		jDocument.on( 'click', '.tc-upload-remove', function() {
9484			var $this = $( this );
9485			var val;
9486			var cpfElement;
9487			var input;
9488			var fileWrap;
9489			var li;
9490			var uploadPreview;
9491			var name;
9492			var index;
9493			var files;
9494			var dT;
9495			var num_uploads;
9496			var uniqid;
9497			var uploadHidden;
9498			var dataFiles;
9499
9500			if ( ClipboardEvent || DataTransfer ) {
9501				cpfElement = $this.closest( '.cpf-element' );
9502				input = cpfElement.find( '.tm-epo-field' );
9503				fileWrap = $this.closest( '.tc-upload-file' );
9504				li = $this.closest( '.tmcp-field-wrap' );
9505				uploadPreview = li.find( '.tc-upload-preview' );
9506				name = li.find( '.tm-filename' );
9507				index = fileWrap.index();
9508				val = input.val().replace( 'C:\\fakepath\\', '' );
9509				if ( val === undefined || val === 'undefined' ) {
9510					val = '';
9511				}
9512
9513				files = Array.from( input[ 0 ].files );
9514				files.splice( index, 1 );
9515				dT = new ClipboardEvent( '' ).clipboardData || new DataTransfer();
9516
9517				files.forEach( function( dataFile ) {
9518					dT.items.add( dataFile );
9519				} );
9520
9521				if ( files.length > 1 ) {
9522					uploadPreview.addClass( 'multiple' );
9523				} else {
9524					uploadPreview.removeClass( 'multiple' );
9525				}
9526
9527				input[ 0 ].files = dT.files;
9528				fileWrap.remove();
9529				if ( dT.files.length > 1 ) {
9530					name.html( '' + dT.files.length + ' ' + ( dT.files.length === 1 ? TMEPOJS.i18n_file : TMEPOJS.i18n_files ) );
9531				} else if ( dT.files.length === 1 ) {
9532					name.html( val );
9533				} else {
9534					name.empty();
9535				}
9536
9537				num_uploads = epoHolder.data( 'num_uploads' );
9538				if ( ! num_uploads ) {
9539					num_uploads = [];
9540				}
9541				uniqid = cpfElement.closest( '.cpf-element' ).attr( 'data-uniqid' );
9542				if ( ! num_uploads[ uniqid ] ) {
9543					num_uploads[ uniqid ] = [];
9544				}
9545
9546				num_uploads[ uniqid ].splice( index, 1 );
9547				if ( num_uploads[ uniqid ].length === 0 ) {
9548					delete num_uploads[ uniqid ];
9549					input.val( '' );
9550				}
9551
9552				uploadHidden = input.next( '.tmcp-upload-hidden' );
9553				if ( uploadHidden.length ) {
9554					dataFiles = uploadHidden.val().split( '|' );
9555					if ( dataFiles.length > 0 ) {
9556						dataFiles.splice( index, 1 );
9557					}
9558					if ( dataFiles.length === 0 ) {
9559						uploadHidden.remove();
9560					} else {
9561						uploadHidden.val( dataFiles.join( '|' ) );
9562					}
9563				}
9564
9565				epoHolder.data( 'num_uploads', num_uploads );
9566			}
9567		} );
9568
9569		qtyElement
9570			.off( 'change.cpf input.cpf' )
9571			.on( 'change.cpf input.cpf', function() {
9572				var field = $( this );
9573
9574				currentCart.trigger( 'tm-epo-check-dpd' );
9575				field.data( 'tm-prev-value', field.val() );
9576				// It is required than when you update the product quantity
9577				// to recalculate the option price to accommodate price types
9578				// that depend on quantity
9579				currentCart.trigger( {
9580					type: 'tm-epo-update',
9581					norules: 2
9582				} );
9583			} )
9584			.data( 'tm-prev-value', qtyElement.val() );
9585
9586		// Support for math formula on associated products when they are initially hidden
9587		epoHolder
9588			.find( '.cpf-type-product' )
9589			.off( 'tc-logic' )
9590			.on( 'tc-logic', function() {
9591				var $this = $( this );
9592				if ( $this.find( '.tc-init' ).length ) {
9593					return;
9594				}
9595				if ( $this.data( 'isactive' ) && ! $this.data( 'donetclogic' ) ) {
9596					$this.data( 'donetclogic', true );
9597					$this.find( '.tc-epo-field-product' ).trigger( 'change.cpfproduct', { forced: 3 } );
9598				}
9599			} );
9600
9601		// Product element checkbox required status fix
9602		epoHolder
9603			.find( '.cpf-type-product .tc-epo-field-product.tc-epo-field-product-checkbox' )
9604			.off( 'change.cpfrequired' )
9605			.on( 'change.cpfrequired', function() {
9606				var $this = $( this );
9607				var cpfElement = $this.closest( '.cpf-element' );
9608				var checkboxes;
9609				var checkboxesChecked;
9610				var checkboxesNotChecked;
9611				if ( cpfElement.is( '.tc-is-required' ) ) {
9612					checkboxes = cpfElement.find( '.tmcp-field.tc-epo-field-product-checkbox' );
9613					checkboxesNotChecked = checkboxes.not( ':checked' );
9614					checkboxesChecked = cpfElement.find( '.tmcp-field.tc-epo-field-product-checkbox:checked' );
9615
9616					if ( checkboxesChecked.length > 0 ) {
9617						checkboxesNotChecked.prop( 'required', false );
9618						checkboxesChecked.prop( 'required', true );
9619					} else {
9620						checkboxes.attr( 'required', true );
9621						checkboxes.prop( 'required', true );
9622					}
9623				}
9624			} );
9625
9626		// Product element variable product support
9627		epoHolder
9628			.find( '.cpf-type-product .tc-epo-field-product' )
9629			.off( 'change.cpfproduct' )
9630			.on( 'change.cpfproduct', function( e, data ) {
9631				var $this = $( this );
9632				var value;
9633				var type;
9634				var selected;
9635				var variableProductContainers;
9636				var thisVariableProductContainer;
9637				var elementContainer = $this.closest( '.cpf-element' );
9638				var productContainerWraps = elementContainer.find( '.tc-epo-element-product-container-wrap' );
9639				var thisProductContainerWrap = $this.closest( '.tmcp-field-wrap' ).find( '.tc-epo-element-product-container-wrap' );
9640				var hasProductContainerWrap = thisProductContainerWrap.length > 0;
9641				var postData;
9642				var skip = false;
9643				var isTrigger = 1000;
9644				var qtyalt;
9645				var associatedSetter = $this;
9646				var associatedElement;
9647				var isFilled;
9648				var productPrice;
9649				var originalProductPrice;
9650				var epoField = elementContainer.find( '.tm-epo-field' ).not( '.tc-epo-element-product-li-container .tm-epo-field' );
9651				var checked = epoField.filter( ':checked' );
9652				var qty;
9653				var counter = $this.attr( 'data-counter' );
9654
9655				if ( false === elementContainer.data( 'isactive' ) ) {
9656					return;
9657				}
9658				if ( data && data.forced === 2 ) {
9659					return;
9660				}
9661
9662				if ( e.isTrigger !== undefined && $this.data( 'triggeredonce' ) && ! ( data && data.forced ) ) {
9663					return;
9664				}
9665
9666				$this.data( 'triggeredonce', 1 );
9667
9668				if ( ! $this.is( ':checkbox' ) ) {
9669					isTrigger = e.isTrigger;
9670				}
9671
9672				if ( epoField.is( ':radio' ) ) {
9673					if ( checked.length > 0 ) {
9674						qty = checked.closest( '.tmcp-field-wrap' ).find( 'input.tm-qty' );
9675					}
9676				} else if ( epoField.is( ':checkbox' ) ) {
9677					if ( checked.length > 0 ) {
9678						qty = $this.closest( '.tmcp-field-wrap' ).find( 'input.tm-qty' );
9679					}
9680				} else {
9681					qty = epoField.closest( '.tmcp-field-wrap' ).find( 'input.tm-qty' );
9682				}
9683
9684				if ( $this.is( ':checkbox' ) ) {
9685					if ( $this.is( '.tc-epo-field-product-hidden' ) ) {
9686						if ( $this.is( ':checked' ) ) {
9687							productContainerWraps.addClass( 'tc-active-product' );
9688						} else {
9689							productContainerWraps.removeClass( 'tc-active-product' );
9690						}
9691
9692						value = $this.val();
9693						type = $this.attr( 'data-type' );
9694						elementContainer.find( '.tc-epo-element-product-li-container' ).removeClass( 'tm-hidden' );
9695					} else {
9696						if ( ! $this.is( ':checked' ) ) {
9697							if ( hasProductContainerWrap ) {
9698								thisProductContainerWrap.addClass( 'tm-hidden' );
9699							}
9700							if ( ! ( data && data.forced ) ) {
9701								return;
9702							}
9703							skip = true;
9704						} else if ( hasProductContainerWrap ) {
9705							thisProductContainerWrap.removeClass( 'tm-hidden' );
9706						}
9707						if ( ! skip ) {
9708							value = $this.val();
9709							type = $this.attr( 'data-type' );
9710							elementContainer.find( '.tc-epo-element-product-li-container' ).removeClass( 'tm-hidden' );
9711						}
9712					}
9713				} else if ( $this.is( ':radio' ) ) {
9714					if ( ! $this.is( ':checked' ) ) {
9715						if ( hasProductContainerWrap ) {
9716							thisProductContainerWrap.addClass( 'tm-hidden' );
9717						}
9718						if ( ! ( data && data.forced ) ) {
9719							return;
9720						}
9721						skip = true;
9722					} else if ( hasProductContainerWrap ) {
9723						productContainerWraps.addClass( 'tm-hidden' );
9724						thisProductContainerWrap.removeClass( 'tm-hidden' );
9725					}
9726					if ( ! skip ) {
9727						value = $this.val();
9728						type = $this.attr( 'data-type' );
9729						elementContainer.find( '.tc-epo-element-product-li-container' ).removeClass( 'tm-hidden' );
9730					}
9731				} else if ( $this.is( 'select' ) ) {
9732					selected = $this.children( ':selected' );
9733					associatedSetter = selected;
9734					counter = selected.index();
9735					if ( $this.children( ':first' ).val() === '' ) {
9736						counter--;
9737					}
9738					value = $this.val();
9739					type = selected.attr( 'data-type' );
9740					elementContainer.find( '.tc-epo-element-product-li-container' ).removeClass( 'tm-hidden' );
9741				}
9742
9743				if ( $this.is( '.tc-epo-field-product-checkbox' ) ) {
9744					variableProductContainers = thisProductContainerWrap.find( '.tc-epo-element-product-container' );
9745				} else {
9746					variableProductContainers = elementContainer.find( '.tc-epo-element-product-container' );
9747				}
9748
9749				thisVariableProductContainer = variableProductContainers.filter( '[data-product_id="' + value + '"]' );
9750
9751				qtyalt = thisVariableProductContainer.find( tcAPI.associateQtySelector );
9752
9753				if ( productContainerWraps.html() !== '' && qty && qty.length > 0 && qtyalt.length === 0 ) {
9754					qty.val( 0 );
9755				}
9756				if ( $this.is( ':checkbox' ) ) {
9757					if ( $this.is( '.tc-epo-field-product-hidden' ) ) {
9758						if ( $this.is( ':checked' ) ) {
9759							if ( qtyalt.val() === '0' ) {
9760								if ( qtyalt.attr( 'min' ) !== '0' ) {
9761									qtyalt.val( qtyalt.attr( 'min' ) ).trigger( 'change' );
9762								}
9763							}
9764						} else {
9765							qtyalt.val( 0 );
9766							qtyalt.closest( '.tm-quantity-alt' ).removeClass( 'tm-hidden' );
9767							if ( data.forced !== 1 ) {
9768								qtyalt.closest( '.tm-quantity-alt' ).find( '.single_add_to_cart_product' ).trigger( 'cpfqtybutton' );
9769							}
9770							productContainerWraps.find( tcAPI.associatedEpoCart ).trigger( 'tm-epo-update' );
9771						}
9772					}
9773				} else if ( $this.is( ':radio' ) ) {
9774					if ( $this.val() && ! $this.data( 'set_initial' ) ) {
9775						if ( qtyalt.val() === '0' ) {
9776							if ( qtyalt.attr( 'min' ) !== '0' ) {
9777								qtyalt.val( qtyalt.attr( 'min' ) ).trigger( 'change' );
9778							}
9779							$this.data( 'set_initial', 1 );
9780						}
9781					}
9782				} else if ( $this.is( 'select' ) ) {
9783					if ( $this.val() && ! $this.data( 'set_initial' ) ) {
9784						if ( qtyalt.val() === '0' ) {
9785							if ( qtyalt.attr( 'min' ) !== '0' ) {
9786								qtyalt.val( qtyalt.attr( 'min' ) ).trigger( 'change' );
9787							}
9788							$this.data( 'set_initial', 1 );
9789						}
9790					}
9791				} else {
9792					return;
9793				}
9794
9795				if ( ! value ) {
9796					variableProductContainers.addClass( 'tm-hidden' );
9797					productPrice = $.epoAPI.util.parseJSON( associatedSetter.attr( 'data-rules' ) );
9798					productPrice = productPrice[ 0 ] || 0;
9799					originalProductPrice = $.epoAPI.util.parseJSON( associatedSetter.attr( 'data-original-rules' ) );
9800					originalProductPrice = originalProductPrice || 0;
9801					if ( associatedSetter.is( '.tcenabled' ) ) {
9802						associatedSetter.data( 'associated_price_set', 1 );
9803					}
9804					associatedSetter.data( 'price_set', 1 );
9805					associatedSetter.data( 'raw_price', productPrice );
9806					associatedSetter.data( 'raw_original_price', originalProductPrice );
9807					associatedSetter.data( 'price', productPrice );
9808					associatedSetter.data( 'original_price', originalProductPrice );
9809
9810					associatedElement = associatedSetter;
9811					if ( associatedElement.is( 'option' ) ) {
9812						associatedElement = associatedSetter.closest( 'select' );
9813					}
9814					isFilled = false;
9815					if ( associatedElement.is( '.tc-epo-field-product' ) ) {
9816						if ( associatedElement.is( 'select' ) ) {
9817							if ( associatedElement.val() !== '' ) {
9818								isFilled = true;
9819							}
9820						} else if ( ( associatedElement.is( ':checkbox' ) || associatedElement.is( ':radio' ) ) ) {
9821							if ( associatedElement.is( ':checked' ) ) {
9822								isFilled = true;
9823							}
9824						} else if ( associatedElement.val() !== '' ) {
9825							isFilled = true;
9826						}
9827					}
9828					tm_force_update_price(
9829						associatedSetter
9830							.closest( '.tmcp-field-wrap' )
9831							.find( '.tc-price' )
9832							.not( tcAPI.associatedEpoSelector + ' .tc-price' ),
9833						productPrice,
9834						isFilled ? tm_set_price_totals( productPrice ) : associatedSetter.data( 'price-html' ),
9835						originalProductPrice,
9836						isFilled ? tm_set_price_totals( originalProductPrice ) : ''
9837					);
9838
9839					qtyElement.trigger( 'change.cpf' );
9840
9841					return;
9842				}
9843
9844				if ( thisVariableProductContainer.length === 0 ) {
9845					// parent_id is used for customization purposes.
9846					postData = {
9847						action: 'wc_epo_get_associated_product_html',
9848						product_id: value,
9849						parent_id: epoHolder.attr( 'data-product-id' ),
9850						mode: elementContainer.attr( 'data-mode' ),
9851						layout_mode: elementContainer.attr( 'data-product-layout-mode' ),
9852						uniqid: elementContainer.attr( 'data-uniqid' ),
9853						name: $this.attr( 'name' ),
9854						counter: counter,
9855						quantity_min: elementContainer.attr( 'data-quantity-min' ),
9856						quantity_max: elementContainer.attr( 'data-quantity-max' ),
9857						priced_individually: elementContainer.attr( 'data-priced-individually' ),
9858						discount: elementContainer.attr( 'data-discount' ),
9859						discount_type: elementContainer.attr( 'data-discount-type' ),
9860						discount_exclude_addons: elementContainer.attr( 'data-discount-exclude-addons' ),
9861						show_image: elementContainer.attr( 'data-show-image' ),
9862						show_title: elementContainer.attr( 'data-show-title' ),
9863						show_title_link: elementContainer.attr( 'data-show-title-link' ),
9864						show_price: elementContainer.attr( 'data-show-price' ),
9865						show_description: elementContainer.attr( 'data-show-description' ),
9866						show_meta: elementContainer.attr( 'data-show-meta' ),
9867						disable_epo: elementContainer.attr( 'data-disable-epo' )
9868					};
9869
9870					elementContainer.block( { message: null, overlayCSS: { background: '#fff', opacity: 0.6 } } );
9871					$.ajax( {
9872						url: TMEPOJS.ajax_url,
9873						type: 'POST',
9874						data: postData,
9875						dataType: 'json',
9876						success: function( response ) {
9877							if ( response.result === 200 ) {
9878								thisVariableProductContainer = $( response.html );
9879								if ( hasProductContainerWrap ) {
9880									$this.closest( '.tmcp-field-wrap' ).find( '.tc-epo-element-product-container-wrap' ).empty().append( thisVariableProductContainer );
9881								} else {
9882									elementContainer.find( '.tc-epo-element-product-container-wrap' ).append( thisVariableProductContainer );
9883								}
9884								show_product_html( epoObject, main_product, thisVariableProductContainer, type, $this, currentCart, variableProductContainers, isTrigger, qtyalt );
9885								thisVariableProductContainer.find( tcAPI.associateQtySelector ).trigger( 'change' );
9886							}
9887						},
9888						complete: function() {
9889							elementContainer.unblock();
9890						}
9891					} );
9892				} else {
9893					show_product_html( epoObject, main_product, thisVariableProductContainer, type, $this, currentCart, variableProductContainers, isTrigger, qtyalt );
9894					thisVariableProductContainer.find( tcAPI.associateQtySelector ).trigger( 'change' );
9895				}
9896			} );
9897
9898		jDocument
9899			.off( 'click.cpfqtybutton cpfqtybutton', '.cpf-type-product .single_add_to_cart_product' )
9900			.on( 'click.cpfqtybutton cpfqtybutton', '.cpf-type-product .single_add_to_cart_product', function() {
9901				var $this = $( this );
9902				var qtyalt = $this.closest( '.tm-quantity-alt' ).find( tcAPI.associateQtySelector );
9903				var isAdd = $this.is( '.alt' );
9904				var productContainerWraps = $this.closest( '.cpf-element' ).find( '.tc-epo-element-product-container-wrap' );
9905				var qtyMin;
9906				var qtyMax;
9907
9908				if ( $this.data( 'inittriggeredonce' ) ) {
9909					qtyMin = $.epoAPI.math.toInt( qtyalt.attr( 'data-min' ) );
9910					qtyMax = $.epoAPI.math.toInt( qtyalt.attr( 'data-max' ) );
9911					if ( isAdd ) {
9912						productContainerWraps.addClass( 'tc-active-product' );
9913						qtyalt.attr( 'min', qtyMin );
9914						if ( qtyMax ) {
9915							qtyalt.attr( 'max', qtyMax );
9916						}
9917						if ( qtyalt.val() === '0' ) {
9918							if ( qtyalt.attr( 'min' ) === '0' ) {
9919								qtyalt.val( 1 ).trigger( 'change' );
9920							} else {
9921								qtyalt.val( qtyalt.attr( 'min' ) ).trigger( 'change' );
9922							}
9923						}
9924						$this.removeClass( 'alt' ).text( $this.attr( 'data-remove' ) );
9925					} else {
9926						productContainerWraps.removeClass( 'tc-active-product' );
9927						qtyalt.val( 0 ).trigger( 'change' );
9928						qtyalt.closest( '.tm-quantity-alt' ).removeClass( 'tm-hidden' );
9929						$this.addClass( 'alt' ).text( $this.attr( 'data-add' ) );
9930					}
9931				}
9932
9933				$this.data( 'inittriggeredonce', 1 );
9934
9935				productContainerWraps.find( tcAPI.associatedEpoCart ).trigger( 'tm-epo-update' );
9936			} );
9937
9938		jDocument
9939			.off( 'change.cpfqtyalt input.cpfqtyalt', '.cpf-type-product ' + tcAPI.associateQtySelector )
9940			.on( 'change.cpfqtyalt input.cpfqtyalt', '.cpf-type-product ' + tcAPI.associateQtySelector, function() {
9941				var $this = $( this );
9942				var epoField = $this.closest( '.cpf-element' ).find( '.tm-epo-field' ).not( '.tc-epo-element-product-li-container .tm-epo-field' );
9943				var addButton = $this.closest( '.tm-quantity-alt' ).find( '.single_add_to_cart_product' );
9944				var checked = epoField.filter( ':checked' );
9945				var qty;
9946				var qtyMin;
9947				var qtyMax;
9948				var associatedEpoCart;
9949
9950				qtyMin = $.epoAPI.math.toInt( $this.attr( 'min' ) );
9951				qtyMax = $.epoAPI.math.toInt( $this.attr( 'max' ) );
9952
9953				if ( epoField.is( '.tc-epo-field-product-hidden' ) && epoField.is( ':checkbox' ) ) {
9954					if ( checked.length === 0 && $this.val() !== '0' ) {
9955						epoField.prop( 'checked', true ).trigger( 'change' );
9956						checked = epoField.filter( ':checked' );
9957					} else if ( $this.val() === '0' && checked.length ) {
9958						epoField.prop( 'checked', false ).trigger( 'change' );
9959					}
9960				}
9961
9962				if ( epoField.is( ':radio' ) ) {
9963					if ( checked.length === 0 ) {
9964						return;
9965					}
9966					qty = checked.closest( '.tmcp-field-wrap' ).find( 'input.tm-qty' ).not( '.tc-element-qty' );
9967				} else if ( epoField.is( ':checkbox' ) ) {
9968					if ( checked.length === 0 ) {
9969						return;
9970					}
9971					qty = $this.closest( '.tmcp-field-wrap' ).find( 'input.tm-qty' ).not( '.tc-element-qty' );
9972				} else {
9973					qty = epoField.closest( '.tmcp-field-wrap' ).find( 'input.tm-qty' ).not( '.tc-element-qty' );
9974				}
9975
9976				if ( qty.length === 0 ) {
9977					return;
9978				}
9979
9980				qty.attr( 'min', qtyMin );
9981				if ( qtyMax ) {
9982					qty.attr( 'max', qtyMax );
9983				}
9984				associatedEpoCart = $this.closest( '.tc-epo-element-product-container' ).find( tcAPI.associatedEpoCart );
9985				associatedEpoCart.trigger( 'tm-epo-update' );
9986
9987				qty.val( $this.val() );
9988
9989				if ( $.epoAPI.math.toFloat( $this.val() ) > 0 ) {
9990					associatedEpoCart.find( '.tm-epo-field.tcenabled' ).removeClass( 'ignore' );
9991					$this.removeClass( 'ignore' );
9992				} else {
9993					associatedEpoCart.find( '.tm-epo-field.tcenabled' ).addClass( 'ignore' );
9994					$this.addClass( 'ignore' );
9995				}
9996				epoField.trigger( 'change.cpfproduct', { forced: 2 } );
9997				if ( addButton.data( 'inittriggeredonce' ) ) {
9998					if ( $this.val() === '0' ) {
9999						addButton.removeClass( 'alt' );
10000					} else {
10001						addButton.addClass( 'alt' );
10002					}
10003				}
10004				addButton.trigger( 'cpfqtybutton' );
10005			} );
10006
10007		// Global update event
10008		currentCart.off( 'tm-epo-update' ).on( 'tm-epo-update', function( event ) {
10009			var cart = $( this );
10010			var bundleid;
10011			var productPrice = false;
10012			var rawProductPrice = 0;
10013			var productRegularPrice = false;
10014			var rawProductRegularPrice = 0;
10015			var total = 0;
10016			var original_total = 0;
10017			var showTotal = false;
10018			var cartQty;
10019			var elementQty = 1;
10020			var priceOverrideMode;
10021			var perProductPricing = true;
10022			var floatingBoxData = [];
10023			var currentVariation;
10024			var cart_fee_options_total = 0;
10025			var cart_fee_options_original_total = 0;
10026			var _total;
10027			var _original_total;
10028			var late_total_price;
10029			var tc_totals_ob = {};
10030			var formatted_options_total;
10031			var formatted_options_original_total;
10032			var formatted_fees_total;
10033			var formatted_fees_original_total;
10034			var formatted_final_total;
10035			var formatted_final_original_total;
10036			var extraFee = 0;
10037			var raw_extraFee = 0;
10038			var product_total_price;
10039			var product_total_original_price;
10040			var calculateFinalProductPrice;
10041			var total_plus_fee;
10042			var original_total_plus_fee;
10043			var product_total_price_without_options;
10044			var unit_price;
10045			var unit_original_price;
10046			var formatted_unit_price;
10047			var formatted_unit_original_price;
10048			var html;
10049			var show_options_total = false;
10050			var show_vat_options_total = false;
10051			var show_fees_total = false;
10052			var formatted_extra_fee = '';
10053			var show_extra_fee = false;
10054			var show_final_total = false;
10055			var hide_native_price;
10056			var update_native_html;
10057			var _fprice;
10058			var _f_regular_price;
10059			var customerPriceFormat;
10060			var currentEpoObject;
10061			var raw_total;
10062			var raw__total;
10063			var raw_original_total;
10064			var raw__original_total;
10065			var raw_cart_fee_options_total;
10066			var raw_cart_fee_options_original_total;
10067			var raw_total_plus_fee;
10068			var raw_original_total_plus_fee;
10069			var raw_product_total_price_without_options;
10070			var raw_product_total_price;
10071			var raw_product_total_original_price;
10072			var fetch;
10073			var customer_price_format_wrap_start = '';
10074			var customer_price_format_wrap_end = '';
10075			var associatedSetter;
10076			var associatedPrice;
10077			var associatedRawPrice;
10078			var associatedOriginalPrice;
10079			var associatedRawOriginalPrice;
10080			var associatedFormattedPrice;
10081			var associatedFormattedOriginalPrice;
10082			var nativeProductPriceSelector;
10083			var elementsLength;
10084			var productFieldSyncVatTotal = 0;
10085			var productFieldSyncTotal = 0;
10086			var productFieldSyncOriginalTotal = 0;
10087			var productFieldSyncTotalTaxed = 0;
10088			var productFieldSyncOriginalTotalTaxed = 0;
10089			var totalProductField = 0;
10090			var originalTotalProductField = 0;
10091			var totalProductFieldTaxed = 0;
10092			var originalTotalProductFieldTaxed = 0;
10093			var _ftotal;
10094			var _foriginal_total;
10095			var totalsHolder_tc_totals_ob;
10096			var temp;
10097			var vat_options_total;
10098			var vat_options_total_plus_fee;
10099			var formatted_vat_options_total;
10100			var formatted_vat_options_total_plus_fee;
10101			var vat_total;
10102			var formatted_vat_total;
10103			var vat_product_base;
10104			var formatted_vat_product_base;
10105			var pricesIncludeTax;
10106			var dynamicCheck;
10107			var dynamicProductPrice = 0;
10108
10109			if ( event.epoObject ) {
10110				currentEpoObject = $.extend( true, {}, event.epoObject );
10111			} else {
10112				currentEpoObject = $.extend( true, {}, epoObject );
10113			}
10114
10115			if ( ! currentEpoObject ) {
10116				return;
10117			}
10118
10119			if ( currentEpoObject.noEpoUpdate ) {
10120				return;
10121			}
10122
10123			jWindow.trigger( 'tcEpoUpdateStart', {
10124				epo: currentEpoObject,
10125				alternativeCart: currentEpoObject,
10126				this_product_type: this_product_type,
10127				cart: cart,
10128				totalsHolder: totalsHolder,
10129				fetchOptionPrices: fetchOptionPrices,
10130				epoHolder: epoHolder
10131			} );
10132
10133			bundleid = $.epoAPI.applyFilter( 'tc_get_bundleid', cart.attr( 'data-product_id' ), cart, currentEpoObject );
10134			priceOverrideMode = totalsHolder.attr( 'data-price-override' );
10135			cartQty = getCurrentQty( cart );
10136			currentVariation = getCurrentVariation( cart );
10137
10138			if ( currentEpoObject.associated_connect && currentEpoObject.associated_connect.length === 1 ) {
10139				cartQty = parseFloat(
10140					currentEpoObject.main_product
10141						.find( tcAPI.associateQtySelector )
10142						.not( tcAPI.associatedEpoSelector + ' ' + tcAPI.qtySelector )
10143						.last()
10144						.val()
10145				);
10146			}
10147
10148			event.stopImmediatePropagation();
10149
10150			productPrice = $.epoAPI.applyFilter( 'tcGetCurrentProductPrice', tm_calculate_product_price( totalsHolder, true ), currentCart, totalsHolder );
10151
10152			rawProductPrice = productPrice;
10153
10154			productRegularPrice = $.epoAPI.applyFilter( 'tcGetCurrentProductRegularPrice', tm_calculate_product_regular_price( totalsHolder, true ), currentCart, totalsHolder );
10155
10156			rawProductRegularPrice = productRegularPrice;
10157
10158			productPrice = $.epoAPI.applyFilter( 'tcCalculateCurrentProductPrice', productPrice, {
10159				epo: currentEpoObject,
10160				alternativeCart: alternativeCart,
10161				cart: cart,
10162				main_product: main_product
10163			} );
10164
10165			if ( ! Number.isFinite( cartQty ) ) {
10166				if ( totalsHolder.attr( 'data-is-sold-individually' ) || getQtyElement( cart ).length === 0 ) {
10167					cartQty = 1;
10168				}
10169			}
10170
10171			// needed for inital math calculation
10172			totalsHolder_tc_totals_ob = {
10173				qty: cartQty,
10174				product_price: rawProductPrice,
10175				original_product_price: rawProductRegularPrice
10176			};
10177			totalsHolder.data( 'totalsHolder_tc_totals_ob', totalsHolder_tc_totals_ob );
10178
10179			if ( ! event.norules ) {
10180				tm_epo_rules( currentEpoObject, cart );
10181			} else if ( event.norules ) {
10182				if ( event.norules === 1 ) {
10183					tm_element_epo_rules( currentEpoObject, event.element );
10184				}
10185				$.tcepo.lateFieldsPrices[ epoEventId ] = [];
10186
10187				epoHolder
10188					.find( '.tm-epo-late-field' )
10189					.toArray()
10190					.forEach( function( setter ) {
10191						setter = $( setter );
10192						setter.data( 'price', 0 );
10193						$.tcepo.lateFieldsPrices[ epoEventId ].push( {
10194							setter: setter,
10195							price: setter.data( 'tm-price-for-late' ),
10196							original_price: setter.data( 'tm-original-price-for-late' ),
10197							bundleid: bundleid,
10198							pricetype: get_type( currentEpoObject, setter, 'price_type' )
10199						} );
10200					} );
10201			}
10202
10203			// Check for dynamic elements.
10204			dynamicCheck = epoHolder.find( '.tmcp-dynamic.dynamic-product-price:not(.tc-is-math-special, .tc-is-math-cumulative)' );
10205			if ( currentEpoObject.is_associated === false ) {
10206				dynamicCheck = dynamicCheck.not( tcAPI.associatedEpoSelector + ' ' + '.tmcp-dynamic.dynamic-product-price:not(.tc-is-math-special, .tc-is-math-cumulative)' );
10207			}
10208			dynamicCheck = dynamicCheck.filter( '.tcenabled' );
10209			if ( dynamicCheck.length > 0 ) {
10210				fetch = fetchOptionPrices( currentEpoObject, epoHolder, '.tmcp-dynamic.dynamic-product-price:not(.tc-is-math-special, .tc-is-math-cumulative)', 0, 0, floatingBoxData, showTotal );
10211				productPrice = fetch.total;
10212				dynamicProductPrice = productPrice;
10213				totalsHolderContainer.find( '.cpf-dynamic-product-price' ).val( dynamicProductPrice );
10214				totalsHolder_tc_totals_ob.dynamic_product_price = dynamicProductPrice;
10215				totalsHolder.data( 'totalsHolder_tc_totals_ob', totalsHolder_tc_totals_ob );
10216			}
10217
10218			if ( currentEpoObject.associated_connect && currentEpoObject.associated_connect.length === 1 ) {
10219				associatedSetter = currentEpoObject.associated_connect;
10220				if ( currentEpoObject.associated_connect.is( 'select' ) ) {
10221					associatedSetter = currentEpoObject.associated_connect.find( 'option:selected' );
10222				}
10223			}
10224
10225			// No reason to continue if the product price is invalid
10226			if ( productPrice === false ) {
10227				totalsHolder.data( 'tm-floating-box-data', [] );
10228				totalsHolder.empty();
10229				if ( currentEpoObject.associated_connect && currentEpoObject.associated_connect.length === 1 ) {
10230					tm_force_update_price(
10231						associatedSetter
10232							.closest( '.tmcp-field-wrap' )
10233							.find( '.tc-price' )
10234							.not( tcAPI.associatedEpoSelector + ' .tc-price' ),
10235						0,
10236						'',
10237						0,
10238						''
10239					);
10240				}
10241				main_cart.trigger( 'tm-epo-short-update', {
10242					container: cartContainer
10243				} );
10244				return;
10245			}
10246
10247			elementQty = $.epoAPI.applyFilter( 'tcAlterElementQty', elementQty, {
10248				epo: currentEpoObject,
10249				alternativeCart: alternativeCart,
10250				currentCart: currentCart,
10251				main_product: main_product
10252			} );
10253
10254			if ( currentCart.data( 'per_product_pricing' ) !== undefined ) {
10255				perProductPricing = currentCart.data( 'per_product_pricing' );
10256			}
10257
10258			perProductPricing = $.epoAPI.applyFilter( 'tcCalculatePerProductPricing', perProductPricing, {
10259				epo: currentEpoObject,
10260				alternativeCart: alternativeCart,
10261				cart: cart,
10262				main_product: main_product
10263			} );
10264
10265			if ( main_epo_inside_form && TMEPOJS.tm_epo_totals_box_placement === 'woocommerce_before_add_to_cart_button' ) {
10266				if ( ( this_product_type === 'variable' || this_product_type === 'variable-subscription' ) && ! totalsHolder.data( 'moved_inside' ) ) {
10267					totalsHolder.data( 'moved_inside', 1 );
10268				}
10269			}
10270
10271			jWindow.trigger( 'tcEpoBeforeOptionPriceCalculation', {
10272				epo: currentEpoObject,
10273				alternativeCart: currentEpoObject,
10274				this_product_type: this_product_type,
10275				cart: cart,
10276				totalsHolder: totalsHolder,
10277				fetchOptionPrices: fetchOptionPrices,
10278				epoHolder: epoHolder,
10279				total: total,
10280				original_total: original_total,
10281				floatingBoxData: floatingBoxData,
10282				showTotal: showTotal,
10283				cart_fee_options_total: cart_fee_options_total,
10284				cart_fee_options_original_total: cart_fee_options_original_total
10285			} );
10286
10287			if ( ! currentEpoObject.associated_connect && ! event.noassociated ) {
10288				if ( TMEPOJS.tm_epo_global_product_element_quantity_sync === 'yes' && ! cart.is( $.tcAPI().associatedEpoCart ) ) {
10289					cart.find( $.tcAPI().associatedEpoCart ).filter( ':visible' ).toArray().forEach( function( acart ) {
10290						$( acart ).trigger( {
10291							type: 'tm-epo-update',
10292							noassociated: 1
10293						} );
10294					} );
10295				}
10296			}
10297
10298			fetch = fetchOptionPrices( currentEpoObject, epoHolder, '.tmcp-field:not(.tmcp-dynamic,.tc-epo-field-product, .tc-is-math-special, .tc-is-math-cumulative)', total, original_total, floatingBoxData, showTotal );
10299			total = fetch.total;
10300			original_total = fetch.original_total;
10301			floatingBoxData = fetch.floatingBoxData;
10302			showTotal = fetch.showTotal;
10303			elementsLength = fetch.elementsLength;
10304
10305			fetch = fetchOptionPrices( currentEpoObject, epoHolder, '.tc-epo-field-product', productFieldSyncTotal, productFieldSyncOriginalTotal, floatingBoxData, showTotal );
10306			productFieldSyncTotal = fetch.total;
10307			productFieldSyncOriginalTotal = fetch.original_total;
10308			productFieldSyncTotalTaxed = fetch.total_taxed;
10309			productFieldSyncOriginalTotalTaxed = fetch.original_total_taxed;
10310			productFieldSyncVatTotal = fetch.vat_total;
10311			floatingBoxData = fetch.floatingBoxData;
10312			showTotal = fetch.showTotal;
10313			elementsLength = elementsLength + fetch.elementsLength;
10314
10315			totalsHolder.data( 'tm-floating-box-data', floatingBoxData );
10316
10317			fetch = fetchOptionPrices( currentEpoObject, epoHolder, '.tmcp-fee-field', cart_fee_options_total, cart_fee_options_original_total, floatingBoxData, showTotal, false, true );
10318			cart_fee_options_total = fetch.total;
10319			cart_fee_options_original_total = fetch.original_total;
10320			floatingBoxData = fetch.floatingBoxData;
10321			showTotal = fetch.showTotal;
10322			elementsLength = elementsLength + fetch.elementsLength;
10323
10324			jWindow.trigger( 'tcEpoAfterNormalOptionPriceCalculation', {
10325				epo: currentEpoObject,
10326				alternativeCart: currentEpoObject,
10327				this_product_type: this_product_type,
10328				cart: cart,
10329				totalsHolder: totalsHolder,
10330				fetchOptionPrices: fetchOptionPrices,
10331				epoHolder: epoHolder,
10332				total: total,
10333				original_total: original_total,
10334				floatingBoxData: floatingBoxData,
10335				showTotal: showTotal,
10336				cart_fee_options_total: cart_fee_options_total,
10337				cart_fee_options_original_total: cart_fee_options_original_total
10338			} );
10339
10340			// Original price + options price type requires this here.
10341			_total = total;
10342			_original_total = original_total;
10343
10344			late_total_price = add_late_fields_prices( currentEpoObject, parseFloat( productPrice ), parseFloat( rawProductRegularPrice ), parseFloat( _total + productFieldSyncTotal ), parseFloat( _original_total + productFieldSyncOriginalTotal ), bundleid, totalsHolder );
10345
10346			fetch = fetchOptionPrices( currentEpoObject, epoHolder, '.tmcp-field.tc-is-math-special:not(.tmcp-dynamic)', total, original_total, floatingBoxData, showTotal, undefined, undefined, undefined, true );
10347			total = fetch.total;
10348			original_total = fetch.original_total;
10349			floatingBoxData = fetch.floatingBoxData;
10350			showTotal = fetch.showTotal;
10351			elementsLength = elementsLength + fetch.elementsLength;
10352
10353			_total = total;
10354			_original_total = original_total;
10355
10356			_total = _total + late_total_price.normal[ 0 ];
10357			_original_total = _original_total + late_total_price.normal[ 1 ];
10358
10359			cart_fee_options_total = cart_fee_options_total + late_total_price.fees[ 0 ];
10360			cart_fee_options_original_total = cart_fee_options_original_total + late_total_price.fees[ 1 ];
10361
10362			total = _total;
10363			original_total = _original_total;
10364			fetch = fetchOptionPrices( currentEpoObject, epoHolder, '.tmcp-field.tc-is-math-cumulative:not(.tmcp-dynamic)', total, original_total, floatingBoxData, showTotal, undefined, undefined, undefined, true, true );
10365			total = fetch.total;
10366			original_total = fetch.original_total;
10367			floatingBoxData = fetch.floatingBoxData;
10368			showTotal = fetch.showTotal;
10369			elementsLength = elementsLength + fetch.elementsLength;
10370
10371			_total = total;
10372			_original_total = original_total;
10373
10374			// Check for dynamic elements.
10375			dynamicCheck = epoHolder.find( '.tmcp-dynamic.dynamic-product-price.tc-is-math-special' );
10376			if ( currentEpoObject.is_associated === false ) {
10377				dynamicCheck = dynamicCheck.not( tcAPI.associatedEpoSelector + ' ' + '.tmcp-dynamic.dynamic-product-price.tc-is-math-special' );
10378			}
10379			dynamicCheck = dynamicCheck.filter( '.tcenabled' );
10380			if ( dynamicCheck.length > 0 ) {
10381				fetch = fetchOptionPrices( currentEpoObject, epoHolder, '.tmcp-field.tmcp-dynamic.dynamic-product-price.tc-is-math-special', dynamicProductPrice, dynamicProductPrice, floatingBoxData, showTotal );
10382				dynamicProductPrice = fetch.total;
10383				productPrice = dynamicProductPrice;
10384				totalsHolderContainer.find( '.cpf-dynamic-product-price' ).val( dynamicProductPrice );
10385				totalsHolder_tc_totals_ob.dynamic_product_price = dynamicProductPrice;
10386				totalsHolder.data( 'totalsHolder_tc_totals_ob', totalsHolder_tc_totals_ob );
10387			}
10388
10389			dynamicCheck = epoHolder.find( '.tmcp-dynamic.dynamic-product-price.tc-is-math-cumulative' );
10390			if ( currentEpoObject.is_associated === false ) {
10391				dynamicCheck = dynamicCheck.not( tcAPI.associatedEpoSelector + ' ' + '.tmcp-dynamic.dynamic-product-price.tc-is-math-cumulative' );
10392			}
10393			dynamicCheck = dynamicCheck.filter( '.tcenabled' );
10394			if ( dynamicCheck.length > 0 ) {
10395				fetch = fetchOptionPrices( currentEpoObject, epoHolder, '.tmcp-field.tmcp-dynamic.dynamic-product-price.tc-is-math-cumulative', dynamicProductPrice, dynamicProductPrice, floatingBoxData, showTotal );
10396				dynamicProductPrice = fetch.total;
10397				productPrice = dynamicProductPrice;
10398				totalsHolderContainer.find( '.cpf-dynamic-product-price' ).val( dynamicProductPrice );
10399				totalsHolder_tc_totals_ob.dynamic_product_price = dynamicProductPrice;
10400				totalsHolder.data( 'totalsHolder_tc_totals_ob', totalsHolder_tc_totals_ob );
10401			}
10402
10403			// Check if there are any dynamic product price elements
10404			dynamicCheck = epoHolder.find( '.tmcp-dynamic.dynamic-product-price' );
10405			if ( currentEpoObject.is_associated === false ) {
10406				dynamicCheck = dynamicCheck.not( tcAPI.associatedEpoSelector + ' ' + '.tmcp-dynamic.dynamic-product-price' );
10407			}
10408			dynamicCheck = dynamicCheck.filter( '.tcenabled' );
10409			if ( ! dynamicCheck.length > 0 ) {
10410				totalsHolderContainer.find( '.cpf-dynamic-product-price' ).val( '' );
10411			}
10412
10413			// Dynamic Calculation
10414			dynamicCheck = epoHolder.find( '.tmcp-dynamic.calculation' );
10415			if ( currentEpoObject.is_associated === false ) {
10416				dynamicCheck = dynamicCheck.not( tcAPI.associatedEpoSelector + ' ' + '.tmcp-dynamic.calculation' );
10417			}
10418			dynamicCheck = dynamicCheck.filter( '.tcenabled' );
10419			if ( dynamicCheck.length > 0 ) {
10420				dynamicCheck.toArray().forEach( function( setter ) {
10421					var f;
10422					var ulWrap;
10423					setter = $( setter );
10424					ulWrap = setter.closest( '.tmcp-ul-wrap' );
10425					f = fetchOptionPrices( epoObject, ulWrap, '.tmcp-field.tmcp-dynamic.calculation', 0, 0, [], true, true );
10426					ulWrap.find( '.tc-result' ).html( f.total );
10427				} );
10428			}
10429
10430			// Dynamic Weight
10431			dynamicCheck = epoHolder.find( '.tmcp-dynamic.change-product-weight' );
10432			if ( currentEpoObject.is_associated === false ) {
10433				dynamicCheck = dynamicCheck.not( tcAPI.associatedEpoSelector + ' ' + '.tmcp-dynamic.change-product-weight' );
10434			}
10435			dynamicCheck = dynamicCheck.filter( '.tcenabled' );
10436			if ( dynamicCheck.length > 0 ) {
10437				dynamicCheck.toArray().forEach( function( setter ) {
10438					var f;
10439					var ulWrap;
10440					setter = $( setter );
10441					ulWrap = setter.closest( '.tmcp-ul-wrap' );
10442					f = fetchOptionPrices( epoObject, ulWrap, '.tmcp-field.tmcp-dynamic.change-product-weight', 0, 0, [], true, true );
10443					ulWrap.find( '.tc-result' ).html( f.total );
10444				} );
10445			}
10446
10447			// Check for dynamic override elements
10448			dynamicProductPrice = 0;
10449			dynamicCheck = epoHolder.find( '.tmcp-dynamic.override-product-price:not(.tc-is-math-special, .tc-is-math-cumulative)' );
10450			if ( currentEpoObject.is_associated === false ) {
10451				dynamicCheck = dynamicCheck.not( tcAPI.associatedEpoSelector + ' ' + '.tmcp-dynamic.override-product-price:not(.tc-is-math-special, .tc-is-math-cumulative)' );
10452			}
10453			dynamicCheck = dynamicCheck.filter( '.tcenabled' );
10454			if ( dynamicCheck.length > 0 ) {
10455				total = 0;
10456				fetch = fetchOptionPrices( currentEpoObject, epoHolder, '.tmcp-dynamic.override-product-price:not(.tc-is-math-special, .tc-is-math-cumulative)', dynamicProductPrice, dynamicProductPrice, floatingBoxData, showTotal );
10457				dynamicProductPrice = fetch.total;
10458				productPrice = dynamicProductPrice;
10459				_total = 0;
10460				_original_total = 0;
10461				totalsHolderContainer.find( '.cpf-override-product-price' ).val( dynamicProductPrice );
10462				totalsHolder_tc_totals_ob.override_product_price = dynamicProductPrice;
10463				totalsHolder.data( 'totalsHolder_tc_totals_ob', totalsHolder_tc_totals_ob );
10464			}
10465
10466			dynamicCheck = epoHolder.find( '.tmcp-dynamic.override-product-price.tc-is-math-special' );
10467			if ( currentEpoObject.is_associated === false ) {
10468				dynamicCheck = dynamicCheck.not( tcAPI.associatedEpoSelector + ' ' + '.tmcp-dynamic.override-product-price.tc-is-math-special' );
10469			}
10470			dynamicCheck = dynamicCheck.filter( '.tcenabled' );
10471			if ( dynamicCheck.length > 0 ) {
10472				fetch = fetchOptionPrices( currentEpoObject, epoHolder, '.tmcp-field.tmcp-dynamic.override-product-price.tc-is-math-special', dynamicProductPrice, dynamicProductPrice, floatingBoxData, showTotal );
10473				dynamicProductPrice = fetch.total;
10474				productPrice = dynamicProductPrice;
10475				_total = 0;
10476				_original_total = 0;
10477				totalsHolderContainer.find( '.cpf-override-product-price' ).val( dynamicProductPrice );
10478				totalsHolder_tc_totals_ob.override_product_price = dynamicProductPrice;
10479				totalsHolder.data( 'totalsHolder_tc_totals_ob', totalsHolder_tc_totals_ob );
10480			}
10481
10482			dynamicCheck = epoHolder.find( '.tmcp-dynamic.override-product-price.tc-is-math-cumulative' );
10483			if ( currentEpoObject.is_associated === false ) {
10484				dynamicCheck = dynamicCheck.not( tcAPI.associatedEpoSelector + ' ' + '.tmcp-dynamic.override-product-price.tc-is-math-cumulative' );
10485			}
10486			dynamicCheck = dynamicCheck.filter( '.tcenabled' );
10487			if ( dynamicCheck.length > 0 ) {
10488				fetch = fetchOptionPrices( currentEpoObject, epoHolder, '.tmcp-field.tmcp-dynamic.override-product-price.tc-is-math-cumulative', dynamicProductPrice, dynamicProductPrice, floatingBoxData, showTotal );
10489				dynamicProductPrice = fetch.total;
10490				productPrice = dynamicProductPrice;
10491				_total = 0;
10492				_original_total = 0;
10493				totalsHolderContainer.find( '.cpf-override-product-price' ).val( dynamicProductPrice );
10494				totalsHolder_tc_totals_ob.override_product_price = dynamicProductPrice;
10495				totalsHolder.data( 'totalsHolder_tc_totals_ob', totalsHolder_tc_totals_ob );
10496			}
10497
10498			// Check if there are any dynamic override elements
10499			dynamicCheck = epoHolder.find( '.tmcp-dynamic.override-product-price' );
10500			if ( currentEpoObject.is_associated === false ) {
10501				dynamicCheck = dynamicCheck.not( tcAPI.associatedEpoSelector + ' ' + '.tmcp-dynamic.override-product-price' );
10502			}
10503			dynamicCheck = dynamicCheck.filter( '.tcenabled' );
10504			if ( ! dynamicCheck.length > 0 ) {
10505				totalsHolderContainer.find( '.cpf-override-product-price' ).val( '' );
10506			}
10507
10508			jWindow.trigger( 'tcEpoAfterOptionPriceCalculation', {
10509				epo: currentEpoObject,
10510				alternativeCart: currentEpoObject,
10511				this_product_type: this_product_type,
10512				cart: cart,
10513				totalsHolder: totalsHolder,
10514				fetchOptionPrices: fetchOptionPrices,
10515				epoHolder: epoHolder,
10516				total: total,
10517				original_total: original_total,
10518				floatingBoxData: floatingBoxData,
10519				showTotal: showTotal,
10520				cart_fee_options_total: cart_fee_options_total,
10521				cart_fee_options_original_total: cart_fee_options_original_total
10522			} );
10523
10524			setTimeout( function() {
10525				epoHolder.find( 'select.tm-epo-field' ).trigger( 'tm-select-price-update-html-all' );
10526			}, 1 );
10527
10528			$.tcepo.oneOptionIsSelected[ epoEventId ] = showTotal;
10529			currentEpoObject = addShowHidetoEpoObject( currentEpoObject, epoEventId, elementsLength );
10530			tm_show_hide_add_to_cart_button( main_product, currentEpoObject );
10531
10532			if ( cart_fee_options_total > 0 ) {
10533				showTotal = true;
10534			}
10535
10536			if ( alternativeCart && ! perProductPricing ) {
10537				showTotal = false;
10538			}
10539
10540			if (
10541				finalTotalBoxMode === 'enable' ||
10542				finalTotalBoxMode === 'hideifoptionsiszero' ||
10543				finalTotalBoxMode === 'hideiftotaliszero'
10544			) {
10545				showTotal = true;
10546			}
10547
10548			if ( cartQty > 1 ) {
10549				showTotal = true;
10550			}
10551			if ( ( this_product_type === 'variable' || this_product_type === 'variable-subscription' ) && ! $.epoAPI.math.toFloat( currentVariation ) ) {
10552				showTotal = false;
10553			}
10554
10555			if ( finalTotalBoxMode === 'disable' ) {
10556				showTotal = false;
10557			}
10558			if ( TMEPOJS.tm_epo_change_variation_price === 'yes' || TMEPOJS.tm_epo_change_original_price === 'yes' ) {
10559				showTotal = true;
10560			}
10561
10562			if ( currentEpoObject.is_associated && ! perProductPricing ) {
10563				showTotal = false;
10564			}
10565
10566			if ( TMEPOJS.tm_epo_total_price_as_unit_price === 'yes' ) {
10567				cartQty = 1;
10568			}
10569
10570			product_total_price = parseFloat( productPrice * cartQty );
10571
10572			if ( TMEPOJS.extraFee ) {
10573				extraFee = parseFloat( TMEPOJS.extraFee );
10574				if ( ! Number.isFinite( extraFee ) ) {
10575					extraFee = 0;
10576				}
10577			}
10578
10579			calculateFinalProductPrice = $.epoAPI.applyFilter( 'tcCalculateFinalProductPrice', false, {
10580				alternativeCart: alternativeCart,
10581				product_price: productPrice,
10582				product_total_price: product_total_price,
10583				v_product_price: rawProductPrice,
10584				tm_set_tax_price: tm_set_tax_price,
10585				main_product: main_product,
10586				totalsHolder: totalsHolder,
10587				cartQty: cartQty
10588			} );
10589
10590			if (
10591				calculateFinalProductPrice !== false &&
10592				typeof calculateFinalProductPrice === 'object' &&
10593				Object.prototype.hasOwnProperty.call( calculateFinalProductPrice, 'productPrice' ) &&
10594				Object.prototype.hasOwnProperty.call( calculateFinalProductPrice, 'productTotalPrice' )
10595			) {
10596				productPrice = calculateFinalProductPrice.productPrice;
10597				product_total_price = calculateFinalProductPrice.productTotalPrice;
10598			}
10599
10600			_total = $.epoAPI.applyFilter( 'tc_adjust_options_price_per_unit', _total, product_total_price );
10601			total = parseFloat( _total * cartQty * elementQty );
10602			total = $.epoAPI.applyFilter( 'tc_adjust_options_total_price', total, cartQty, elementQty, _total, totalsHolder );
10603			if ( TMEPOJS.tm_epo_global_product_element_quantity_sync === 'no' ) {
10604				totalProductField = parseFloat( productFieldSyncTotal );
10605				totalProductFieldTaxed = parseFloat( productFieldSyncTotalTaxed );
10606			} else {
10607				totalProductField = parseFloat( productFieldSyncTotal * cartQty * elementQty );
10608				totalProductFieldTaxed = parseFloat( productFieldSyncTotalTaxed * cartQty * elementQty );
10609			}
10610			totalProductField = $.epoAPI.applyFilter( 'tc_adjust_options_productfield_total_price', totalProductField, cartQty, elementQty, _total, totalsHolder );
10611			totalProductFieldTaxed = $.epoAPI.applyFilter( 'tc_adjust_options_productfield_total_price_taxed', totalProductFieldTaxed, cartQty, elementQty, _total, totalsHolder );
10612
10613			_original_total = $.epoAPI.applyFilter( 'tc_adjust_options_price_per_unit', _original_total, product_total_price );
10614			original_total = parseFloat( _original_total * cartQty * elementQty );
10615			original_total = $.epoAPI.applyFilter( 'tc_adjust_options_original_total_price', original_total, cartQty, elementQty, _original_total, totalsHolder );
10616			if ( TMEPOJS.tm_epo_global_product_element_quantity_sync === 'no' ) {
10617				originalTotalProductField = parseFloat( productFieldSyncOriginalTotal );
10618				originalTotalProductFieldTaxed = parseFloat( productFieldSyncOriginalTotalTaxed );
10619			} else {
10620				originalTotalProductField = parseFloat( productFieldSyncOriginalTotal * cartQty * elementQty );
10621				originalTotalProductFieldTaxed = parseFloat( productFieldSyncOriginalTotalTaxed * cartQty * elementQty );
10622			}
10623			originalTotalProductField = $.epoAPI.applyFilter( 'tc_adjust_options_productfield_original_total_price', originalTotalProductField, cartQty, elementQty, _original_total, totalsHolder );
10624			originalTotalProductFieldTaxed = $.epoAPI.applyFilter( 'tc_adjust_options_productfield_original_total_price_taxed', originalTotalProductFieldTaxed, cartQty, elementQty, _original_total, totalsHolder );
10625
10626			if ( priceOverrideMode === '1' && parseFloat( total ) > 0 ) {
10627				productPrice = 0;
10628				rawProductPrice = 0;
10629				product_total_price = 0;
10630			}
10631
10632			product_total_price = $.epoAPI.applyFilter( 'tc_adjust_product_total_price_without_options', product_total_price );
10633
10634			total = $.epoAPI.applyFilter( 'tcAdjustTotal', total, {
10635				epo: currentEpoObject,
10636				totalsHolder: totalsHolder,
10637				cart: cart,
10638				main_product: main_product
10639			} );
10640			totalProductField = $.epoAPI.applyFilter( 'tcAdjustProductFieldTotal', totalProductField, {
10641				epo: currentEpoObject,
10642				totalsHolder: totalsHolder,
10643				cart: cart,
10644				main_product: main_product
10645			} );
10646			totalProductFieldTaxed = $.epoAPI.applyFilter( 'tcAdjustProductFieldTotalTaxed', totalProductFieldTaxed, {
10647				epo: currentEpoObject,
10648				totalsHolder: totalsHolder,
10649				cart: cart,
10650				main_product: main_product
10651			} );
10652			original_total = $.epoAPI.applyFilter( 'tcAdjustOriginalTotal', original_total, {
10653				epo: currentEpoObject,
10654				totalsHolder: totalsHolder,
10655				cart: cart,
10656				main_product: main_product
10657			} );
10658			originalTotalProductField = $.epoAPI.applyFilter( 'tcAdjustProductFieldOriginalTotal', originalTotalProductField, {
10659				epo: currentEpoObject,
10660				totalsHolder: totalsHolder,
10661				cart: cart,
10662				main_product: main_product
10663			} );
10664			originalTotalProductFieldTaxed = $.epoAPI.applyFilter( 'tcAdjustProductFieldOriginalTotalTaxed', originalTotalProductFieldTaxed, {
10665				epo: currentEpoObject,
10666				totalsHolder: totalsHolder,
10667				cart: cart,
10668				main_product: main_product
10669			} );
10670
10671			total = parseFloat( $.epoAPI.applyFilter( 'tc_adjust_total', total, totalsHolder ) );
10672			cart_fee_options_total = parseFloat( $.epoAPI.applyFilter( 'tc_adjust_totals_fee', cart_fee_options_total, totalsHolder ) );
10673			original_total = parseFloat( $.epoAPI.applyFilter( 'tc_adjust_original_total', original_total, totalsHolder ) );
10674			cart_fee_options_original_total = parseFloat( $.epoAPI.applyFilter( 'tc_adjust_original_total_fee', cart_fee_options_original_total, totalsHolder ) );
10675			raw_extraFee = extraFee;
10676
10677			total_plus_fee = total + cart_fee_options_total;
10678			original_total_plus_fee = original_total + cart_fee_options_original_total;
10679
10680			raw_total = total;
10681			raw__total = _total;
10682
10683			raw_cart_fee_options_total = cart_fee_options_total;
10684			raw_total_plus_fee = total_plus_fee;
10685
10686			raw_original_total = original_total;
10687			raw__original_total = _original_total;
10688
10689			raw_cart_fee_options_original_total = cart_fee_options_original_total;
10690			raw_original_total_plus_fee = original_total_plus_fee;
10691
10692			raw_product_total_price_without_options = product_total_price;
10693			raw_product_total_price = parseFloat( product_total_price + total_plus_fee + raw_extraFee );
10694			raw_product_total_original_price = parseFloat( rawProductRegularPrice + original_total_plus_fee + raw_extraFee );
10695
10696			productPrice = tm_set_tax_price( productPrice, totalsHolder, undefined, undefined, undefined, undefined, true );
10697			productRegularPrice = tm_set_tax_price( productRegularPrice, totalsHolder, undefined, undefined, undefined, undefined, true );
10698			product_total_price = tm_set_tax_price( product_total_price, totalsHolder, undefined, undefined, undefined, undefined, true );
10699
10700			total = tm_set_tax_price( total, totalsHolder, undefined, undefined, undefined, undefined, true );
10701			_total = tm_set_tax_price( _total, totalsHolder, undefined, undefined, undefined, undefined, true );
10702
10703			cart_fee_options_total = tm_set_tax_price( cart_fee_options_total, totalsHolder, undefined, undefined, undefined, undefined, true );
10704			total_plus_fee = parseFloat( cart_fee_options_total ) + parseFloat( total );
10705
10706			original_total = tm_set_tax_price( original_total, totalsHolder, undefined, undefined, undefined, undefined, true );
10707			_original_total = tm_set_tax_price( _original_total, totalsHolder, undefined, undefined, undefined, undefined, true );
10708
10709			cart_fee_options_original_total = tm_set_tax_price( cart_fee_options_original_total, totalsHolder, undefined, undefined, undefined, undefined, true );
10710			original_total_plus_fee = parseFloat( cart_fee_options_original_total ) + parseFloat( original_total );
10711
10712			extraFee = tm_set_tax_price( extraFee, totalsHolder, undefined, undefined, undefined, undefined, true );
10713
10714			// Calculate product price
10715			product_total_price_without_options = product_total_price;
10716			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 );
10717			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 );
10718
10719			// Calculate vat options total
10720			pricesIncludeTax = totalsHolder.attr( 'data-prices-include-tax' ) || TMEPOJS.prices_include_tax;
10721			if ( pricesIncludeTax === '1' ) {
10722				vat_options_total = productFieldSyncVatTotal + parseFloat( calculateTaxAmount( total, totalsHolder ) );
10723				vat_options_total_plus_fee = productFieldSyncVatTotal + parseFloat( calculateTaxAmount( total_plus_fee, totalsHolder ) );
10724				vat_total = productFieldSyncVatTotal + parseFloat( calculateTaxAmount( product_total_price, totalsHolder ) );
10725				vat_product_base = parseFloat( calculateTaxAmount( product_total_price_without_options, totalsHolder ) );
10726			} else {
10727				vat_options_total = productFieldSyncVatTotal + parseFloat( total - raw_total );
10728				vat_options_total_plus_fee = productFieldSyncVatTotal + parseFloat( total_plus_fee - raw_total_plus_fee );
10729				vat_total = productFieldSyncVatTotal + parseFloat( product_total_price - raw_product_total_price );
10730				vat_product_base = parseFloat( product_total_price_without_options - raw_product_total_price_without_options );
10731			}
10732
10733			raw_total = raw_total + totalProductField;
10734			raw__total = raw__total + totalProductField;
10735			raw_total_plus_fee = raw_total_plus_fee + totalProductField;
10736			raw_original_total = raw_original_total + originalTotalProductField;
10737			raw__original_total = raw__original_total + originalTotalProductField;
10738			raw_original_total_plus_fee = raw_original_total_plus_fee + originalTotalProductField;
10739			raw_product_total_price = raw_product_total_price + totalProductField;
10740			raw_product_total_original_price = raw_product_total_original_price + originalTotalProductField;
10741			total = total + totalProductFieldTaxed;
10742			_total = _total + totalProductFieldTaxed;
10743			total_plus_fee = total_plus_fee + totalProductFieldTaxed;
10744			original_total = original_total + originalTotalProductFieldTaxed;
10745			_original_total = _original_total + originalTotalProductFieldTaxed;
10746			original_total_plus_fee = original_total_plus_fee + originalTotalProductFieldTaxed;
10747			product_total_price = product_total_price + totalProductFieldTaxed;
10748			product_total_original_price = product_total_original_price + originalTotalProductFieldTaxed;
10749
10750			// Calculate unit price
10751			unit_price = parseFloat( productPrice + parseFloat( _total ) );
10752			unit_original_price = parseFloat( productPrice + parseFloat( _original_total ) );
10753			if ( TMEPOJS.tm_epo_fees_on_unit_price === 'yes' ) {
10754				unit_price = parseFloat( productPrice + parseFloat( _total ) + parseFloat( parseFloat( cart_fee_options_total ) / cartQty ) );
10755				unit_original_price = parseFloat( productPrice + parseFloat( _original_total ) + parseFloat( parseFloat( cart_fee_options_original_total ) / cartQty ) );
10756			}
10757
10758			// Format unit price
10759			formatted_unit_price = tm_set_price_totals( unit_price, totalsHolder, true, true );
10760			formatted_unit_original_price = tm_set_price_totals( unit_original_price, totalsHolder, true, true );
10761
10762			// Format extra fee
10763			if ( extraFee ) {
10764				show_extra_fee = true;
10765				formatted_extra_fee = tm_set_price_totals( extraFee, totalsHolder, true, true );
10766			}
10767
10768			// Format final total
10769			formatted_final_total = tm_set_price_totals( product_total_price, totalsHolder, true, true );
10770			formatted_final_original_total = tm_set_price_totals( product_total_original_price, totalsHolder, true, true );
10771
10772			// Format options total
10773			formatted_options_total = tm_set_price_totals( total, totalsHolder, true, true );
10774
10775			// Format fees total
10776			formatted_fees_total = tm_set_price_totals( cart_fee_options_total, totalsHolder, true, true );
10777
10778			// Format options original total
10779			formatted_options_original_total = tm_set_price_totals( original_total, totalsHolder, true, true );
10780
10781			// Format fees original total
10782			formatted_fees_original_total = tm_set_price_totals( cart_fee_options_original_total, totalsHolder, true, true );
10783
10784			// Format vat options total
10785			formatted_vat_options_total = tm_set_price_totals( vat_options_total );
10786			formatted_vat_options_total_plus_fee = tm_set_price_totals( vat_options_total_plus_fee );
10787			formatted_vat_total = tm_set_price_totals( vat_total );
10788			formatted_vat_product_base = tm_set_price_totals( vat_product_base );
10789
10790			// Backwards compatibility
10791			formatted_unit_price = $.epoAPI.applyFilter( 'tc_adjust_formatted_unit_price', formatted_unit_price, productPrice, _total, cart_fee_options_total, cartQty );
10792			formatted_options_total = $.epoAPI.applyFilter( 'tc_adjust_formatted_options_total', formatted_options_total, total, _total, cartQty );
10793			formatted_fees_total = $.epoAPI.applyFilter( 'tc_adjust_formatted_fees_total', formatted_fees_total, cart_fee_options_total );
10794			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 );
10795
10796			formatted_unit_price = $.epoAPI.applyFilter( 'tcAdjustFormattedUnitPrice', formatted_unit_price, {
10797				epo: currentEpoObject,
10798				totalsHolder: totalsHolder,
10799				event: event,
10800				unit_price: unit_price,
10801				productPrice: productPrice,
10802				_total: _total,
10803				total_plcart_fee_options_totals_fee: cart_fee_options_total,
10804				cartQty: cartQty
10805			} );
10806			formatted_unit_original_price = $.epoAPI.applyFilter( 'tcAdjustFormattedUnitOriginalPrice', formatted_unit_original_price, {
10807				epo: currentEpoObject,
10808				totalsHolder: totalsHolder,
10809				event: event,
10810				unit_original_price: unit_original_price,
10811				productPrice: productPrice,
10812				_original_total: _original_total,
10813				total_plcart_fee_options_totals_fee: cart_fee_options_total,
10814				cartQty: cartQty
10815			} );
10816			formatted_options_total = $.epoAPI.applyFilter( 'tcAdjustFormattedOptionsTotal', formatted_options_total, {
10817				epo: currentEpoObject,
10818				totalsHolder: totalsHolder,
10819				event: event,
10820				total: total,
10821				_total: _total,
10822				total_plus_fee: total_plus_fee,
10823				extraFee: extraFee,
10824				cartQty: cartQty
10825			} );
10826			formatted_options_original_total = $.epoAPI.applyFilter( 'tcAdjustFormattedOptionsOriginalTotal', formatted_options_original_total, {
10827				epo: currentEpoObject,
10828				totalsHolder: totalsHolder,
10829				event: event,
10830				original_total: original_total,
10831				_original_total: _original_total,
10832				original_total_plus_fee: original_total_plus_fee,
10833				extraFee: extraFee,
10834				cartQty: cartQty
10835			} );
10836			formatted_fees_total = $.epoAPI.applyFilter( 'tcAdjustFormattedFeesTotal', formatted_fees_total, {
10837				epo: currentEpoObject,
10838				totalsHolder: totalsHolder,
10839				event: event,
10840				cart_fee_options_total: cart_fee_options_total,
10841				extraFee: extraFee,
10842				cartQty: cartQty
10843			} );
10844			formatted_fees_original_total = $.epoAPI.applyFilter( 'tcAdjustFormattedFeesOriginalTotal', formatted_fees_original_total, {
10845				epo: currentEpoObject,
10846				totalsHolder: totalsHolder,
10847				event: event,
10848				cart_fee_options_original_total: cart_fee_options_original_total,
10849				extraFee: extraFee,
10850				cartQty: cartQty
10851			} );
10852			formatted_final_total = $.epoAPI.applyFilter( 'tcAdjustFormattedFinalTotal', formatted_final_total, {
10853				epo: currentEpoObject,
10854				totalsHolder: totalsHolder,
10855				event: event,
10856				product_total_price: product_total_price,
10857				product_total_price_without_options: product_total_price_without_options,
10858				total_plus_fee: total_plus_fee,
10859				extraFee: extraFee,
10860				cartQty: cartQty
10861			} );
10862			formatted_final_original_total = $.epoAPI.applyFilter( 'tcAdjustFormattedFinalOriginalTotal', formatted_final_original_total, {
10863				epo: currentEpoObject,
10864				totalsHolder: totalsHolder,
10865				event: event,
10866				product_total_original_price: product_total_original_price,
10867				product_total_price_without_options: product_total_price_without_options,
10868				original_total_plus_fee: original_total_plus_fee,
10869				extraFee: extraFee,
10870				cartQty: cartQty
10871			} );
10872
10873			if ( ( total > 0 && finalTotalBoxShowOptions === 'showtgz' ) || finalTotalBoxShowOptions === 'show' ) {
10874				show_options_total = true;
10875				if ( TMEPOJS.tm_epo_enable_vat_options_total === 'yes' ) {
10876					show_vat_options_total = true;
10877				}
10878			}
10879			if ( cart_fee_options_total !== 0 ) {
10880				show_fees_total = true;
10881			}
10882
10883			if ( formatted_final_total && finalTotalBoxShowFinal === 'show' ) {
10884				show_final_total = true;
10885			}
10886
10887			tc_totals_ob = {
10888				qty: cartQty,
10889				product_price: productPrice,
10890				raw_product_price: rawProductPrice,
10891				product_regular_price: productRegularPrice,
10892				raw_product_regular_price: rawProductRegularPrice,
10893				formatted_product_price: tm_set_price_totals( parseFloat( productPrice ) * cartQty ),
10894
10895				late_total_prices: late_total_price,
10896				late_total_price: tm_set_tax_price( late_total_price[ 0 ], totalsHolder ),
10897				late_total_original_price: tm_set_tax_price( late_total_price[ 1 ], totalsHolder ),
10898
10899				raw_options_price_per_unit: raw__total,
10900				raw_options_total_price: raw_total,
10901				raw_cart_fee_options_total_price: raw_cart_fee_options_total,
10902				raw_total_plus_fee: raw_total_plus_fee,
10903
10904				raw_options_original_price_per_unit: raw__original_total,
10905				raw_options_original_total_price: raw_original_total,
10906				raw_cart_fee_options_original_total_price: raw_cart_fee_options_original_total,
10907				raw_original_total_plus_fee: raw_original_total_plus_fee,
10908
10909				raw_product_total_price: raw_product_total_price,
10910				raw_product_total_original_price: raw_product_total_original_price,
10911				raw_product_total_price_without_options: raw_product_total_price_without_options,
10912
10913				options_price_per_unit: _total,
10914				options_total_price: total,
10915				cart_fee_options_total_price: cart_fee_options_total,
10916				total_plus_fee: total_plus_fee,
10917
10918				options_original_price_per_unit: _original_total,
10919				options_original_total_price: original_total,
10920				cart_fee_options_total_original_price: cart_fee_options_original_total,
10921				original_total_plus_fee: original_total_plus_fee,
10922
10923				vat_options_total: vat_options_total,
10924				vat_options_total_plus_fee: vat_options_total_plus_fee,
10925				formatted_vat_options_total: formatted_vat_options_total,
10926				formatted_vat_options_total_plus_fee: formatted_vat_options_total_plus_fee,
10927				vat_total: vat_total,
10928				formatted_vat_total: formatted_vat_total,
10929				vat_product_base: vat_product_base,
10930				formatted_vat_product_base: formatted_vat_product_base,
10931
10932				product_total_price: product_total_price,
10933				product_total_original_price: product_total_original_price,
10934				product_total_price_without_options: product_total_price_without_options,
10935
10936				product_unit_price: unit_price,
10937				product_unit_original_price: unit_original_price,
10938				formatted_unit_price: formatted_unit_price,
10939				formatted_options_total: formatted_options_total,
10940				formatted_fees_total: formatted_fees_total,
10941				formatted_final_total: formatted_final_total,
10942
10943				formatted_unit_original_price: formatted_unit_original_price,
10944				formatted_options_original_total: formatted_options_original_total,
10945				formatted_fees_original_total: formatted_fees_original_total,
10946				formatted_final_original_total: formatted_final_original_total,
10947
10948				formatted_extra_fee: formatted_extra_fee,
10949
10950				show_options_total: show_options_total,
10951				show_fees_total: show_fees_total,
10952				show_extra_fee: show_extra_fee,
10953				show_final_total: show_final_total,
10954				show_options_vat: show_vat_options_total,
10955
10956				unit_price: TMEPOJS.i18n_unit_price,
10957				show_unit_price: TMEPOJS.tm_epo_show_unit_price === 'yes',
10958				options_total: TMEPOJS.i18n_options_total,
10959				fees_total: TMEPOJS.i18n_fees_total,
10960				extra_fee: TMEPOJS.i18n_extra_fee,
10961				final_total: TMEPOJS.i18n_final_total,
10962				options_vat_total: TMEPOJS.i18n_vat_options_total,
10963
10964				totals_box_before_unit_price: TMEPOJS.totals_box_before_unit_price,
10965				totals_box_after_unit_price: TMEPOJS.totals_box_after_unit_price,
10966				totals_box_before_vat_options_totals_price: TMEPOJS.totals_box_before_vat_options_totals_price,
10967				totals_box_after_vat_options_totals_price: TMEPOJS.totals_box_after_vat_options_totals_price,
10968				totals_box_before_options_totals_price: TMEPOJS.totals_box_before_options_totals_price,
10969				totals_box_after_options_totals_price: TMEPOJS.totals_box_after_options_totals_price,
10970				totals_box_before_fee_totals_price: TMEPOJS.totals_box_before_fee_totals_price,
10971				totals_box_after_fee_totals_price: TMEPOJS.totals_box_after_fee_totals_price,
10972				totals_box_before_extra_fee_price: TMEPOJS.totals_box_before_extra_fee_price,
10973				totals_box_after_extra_fee_price: TMEPOJS.totals_box_after_extra_fee_price,
10974				totals_box_before_final_totals_price: TMEPOJS.totals_box_before_final_totals_price,
10975				totals_box_after_final_totals_price: TMEPOJS.totals_box_after_final_totals_price
10976			};
10977
10978			if ( TMEPOJS.customer_price_format ) {
10979				customer_price_format_wrap_start = TMEPOJS.customer_price_format_wrap_start;
10980				customer_price_format_wrap_end = TMEPOJS.customer_price_format_wrap_end;
10981				customerPriceFormat = TMEPOJS.customer_price_format;
10982			}
10983
10984			if ( formatted_options_total && total > 0 ) {
10985				_ftotal = formatPrice( total );
10986				_foriginal_total = formatPrice( original_total );
10987				if ( customerPriceFormat ) {
10988					_ftotal = customerPriceFormat.replace( '__PRICE__', _ftotal ).replace( '__CODE__', TMEPOJS.current_currency );
10989					if ( ! totalsHolder.data( 'is-on-sale' ) ) {
10990						_foriginal_total = customerPriceFormat.replace( '__PRICE__', _foriginal_total ).replace( '__CODE__', TMEPOJS.current_currency );
10991					}
10992				}
10993				_ftotal = $.epoAPI.applyFilter( 'tcFilterFormattedFTotal', _ftotal, {
10994					epo: currentEpoObject,
10995					totalsHolder: totalsHolder,
10996					event: event,
10997					total: total,
10998					_total: _total,
10999					total_plus_fee: total_plus_fee,
11000					extraFee: extraFee,
11001					cartQty: cartQty
11002				} );
11003				_foriginal_total = $.epoAPI.applyFilter( 'tcFilterFormattedFOriginalTotal', _foriginal_total, {
11004					epo: currentEpoObject,
11005					totalsHolder: totalsHolder,
11006					event: event,
11007					original_total: original_total,
11008					total: original_total,
11009					_total: _total,
11010					total_plus_fee: total_plus_fee,
11011					extraFee: extraFee,
11012					cartQty: cartQty
11013				} );
11014				if ( TMEPOJS.tm_epo_enable_original_final_total === 'yes' && total !== original_total ) {
11015					tc_totals_ob.formatted_options_total = $.epoAPI.util.decodeHTML(
11016						$.epoAPI.template.html( tcAPI.templateEngine.tc_formatted_sale_price, {
11017							price: _foriginal_total,
11018							sale_price: _ftotal,
11019							customer_price_format_wrap_start: customer_price_format_wrap_start,
11020							customer_price_format_wrap_end: customer_price_format_wrap_end
11021						} )
11022					);
11023					tc_totals_ob._foriginal_total = _foriginal_total;
11024					tc_totals_ob._ftotal = _ftotal;
11025				} else {
11026					tc_totals_ob.formatted_options_total = $.epoAPI.util.decodeHTML(
11027						$.epoAPI.util.decodeHTML(
11028							$.epoAPI.template.html( tcAPI.templateEngine.tc_formatted_price, {
11029								price: _ftotal,
11030								customer_price_format_wrap_start: customer_price_format_wrap_start,
11031								customer_price_format_wrap_end: customer_price_format_wrap_end
11032							} )
11033						)
11034					);
11035				}
11036			}
11037
11038			if ( formatted_final_total && product_total_price >= 0 ) {
11039				_fprice = formatPrice( product_total_price );
11040				if ( priceOverrideMode === '1' && parseFloat( total ) > 0 ) {
11041					_f_regular_price = parseFloat( raw_original_total_plus_fee + extraFee );
11042				} else {
11043					_f_regular_price = parseFloat( parseFloat( rawProductRegularPrice * cartQty ) + raw_original_total_plus_fee + extraFee );
11044				}
11045
11046				if ( customerPriceFormat ) {
11047					_fprice = customerPriceFormat.replace( '__PRICE__', _fprice ).replace( '__CODE__', TMEPOJS.current_currency );
11048					if ( ! totalsHolder.data( 'is-on-sale' ) ) {
11049						_f_regular_price = customerPriceFormat.replace( '__PRICE__', _f_regular_price ).replace( '__CODE__', TMEPOJS.current_currency );
11050					}
11051				}
11052
11053				_fprice = $.epoAPI.applyFilter( 'tc_adjust_native_price', _fprice, product_total_price );
11054				_f_regular_price = tm_set_tax_price( _f_regular_price, totalsHolder, undefined, undefined, undefined, undefined, true );
11055				_f_regular_price = formatPrice( _f_regular_price );
11056				_f_regular_price = $.epoAPI.applyFilter( 'tc_adjust_native_regular_price', _f_regular_price, product_total_price );
11057
11058				if ( TMEPOJS.tm_epo_enable_original_final_total === 'yes' && ( ( totalsHolder.data( 'is-on-sale' ) && priceOverrideMode !== '1' ) || _f_regular_price !== _fprice ) ) {
11059					tc_totals_ob.formatted_final_total = $.epoAPI.util.decodeHTML(
11060						$.epoAPI.template.html( tcAPI.templateEngine.tc_formatted_sale_price, {
11061							price: _f
11061_regular_price,
11062							sale_price: _fprice,
11063							customer_price_format_wrap_start: customer_price_format_wrap_start,
11064							customer_price_format_wrap_end: customer_price_format_wrap_end
11065						} )
11066					);
11067				} else {
11068					tc_totals_ob.formatted_final_total = $.epoAPI.util.decodeHTML(
11069						$.epoAPI.util.decodeHTML(
11070							$.epoAPI.template.html( tcAPI.templateEngine.tc_formatted_price, {
11071								price: _fprice,
11072								customer_price_format_wrap_start: customer_price_format_wrap_start,
11073								customer_price_format_wrap_end: customer_price_format_wrap_end
11074							} )
11075						)
11076					);
11077				}
11078				tc_totals_ob._f_regular_price = _f_regular_price;
11079				tc_totals_ob._fprice = _fprice;
11080			}
11081
11082			tc_totals_ob = replace_suffixes( 'formatted_fees_original_total', 'cart_fee_options_total_original_price', tc_totals_ob, totalsHolder );
11083			tc_totals_ob = replace_suffixes( 'formatted_fees_total', 'cart_fee_options_total_price', tc_totals_ob, totalsHolder );
11084			tc_totals_ob = replace_suffixes( 'formatted_final_original_total', 'product_total_original_price', tc_totals_ob, totalsHolder );
11085			tc_totals_ob = replace_suffixes( 'formatted_final_total', 'product_total_price', tc_totals_ob, totalsHolder );
11086			tc_totals_ob = replace_suffixes( 'formatted_options_original_total', 'options_original_total_price', tc_totals_ob, totalsHolder );
11087			tc_totals_ob = replace_suffixes( 'formatted_options_total', 'options_total_price', tc_totals_ob, totalsHolder );
11088			tc_totals_ob = replace_suffixes( 'formatted_unit_original_price', 'product_unit_original_price', tc_totals_ob, totalsHolder );
11089			tc_totals_ob = replace_suffixes( 'formatted_unit_price', 'product_unit_price', tc_totals_ob, totalsHolder );
11090
11091			if ( $.tcepo.showHideTotal !== undefined && $.tcepo.showHideTotal[ epoEventId ] !== undefined ) {
11092				showTotal = $.tcepo.showHideTotal[ epoEventId ];
11093			}
11094
11095			tc_totals_ob = $.epoAPI.applyFilter( 'tc_adjust_tc_totals_ob', tc_totals_ob, {
11096				epo_object: currentEpoObject,
11097				showTotal: showTotal,
11098				epoHolder: epoHolder,
11099				totalsHolder: totalsHolder,
11100				tm_set_price: tm_set_price,
11101				tm_set_price_totals: tm_set_price_totals,
11102				product_total_price: product_total_price,
11103				product_price: productPrice,
11104				qty: cartQty
11105			} );
11106
11107			if ( tc_totals_ob.showTotal !== undefined ) {
11108				showTotal = tc_totals_ob.showTotal;
11109			}
11110
11111			currentEpoObject.tc_totals_ob = tc_totals_ob;
11112
11113			showTotal = $.epoAPI.applyFilter( 'tcFinalTotalsBoxVisibility', showTotal, {
11114				epo: currentEpoObject,
11115				alternativeCart: alternativeCart,
11116				cart: cart,
11117				main_product: main_product,
11118				totalsHolder: totalsHolder,
11119				this_epo_totals_container: this_epo_totals_container
11120			} );
11121
11122			html = $.epoAPI.template.html( tcAPI.templateEngine.tc_final_totals, tc_totals_ob );
11123
11124			totalsHolder.data( 'tm-html', html );
11125			totalsHolder.data( 'tc_totals_ob', tc_totals_ob );
11126
11127			if ( currentEpoObject.associated_connect && currentEpoObject.associated_connect.length === 1 ) {
11128				if ( currentEpoObject.associated_connect.attr( 'data-no-price' ) === '1' ) {
11129					associatedPrice = 0;
11130					associatedRawPrice = 0;
11131					associatedOriginalPrice = 0;
11132					associatedRawOriginalPrice = 0;
11133					associatedFormattedPrice = '';
11134					associatedFormattedOriginalPrice = '';
11135					tm_force_update_price(
11136						associatedSetter
11137							.closest( '.tmcp-field-wrap' )
11138							.find( '.tc-price' )
11139							.not( tcAPI.associatedEpoSelector + ' .tc-price' ),
11140						associatedPrice,
11141						associatedFormattedPrice,
11142						associatedOriginalPrice,
11143						associatedFormattedOriginalPrice
11144					);
11145				} else {
11146					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 );
11147					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 );
11148					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 );
11149					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 );
11150
11151					associatedFormattedPrice = tm_set_price( associatedPrice, currentEpoObject.this_epo_totals_containe, false, false, associatedSetter );
11152					associatedFormattedOriginalPrice = tm_set_price( associatedOriginalPrice, currentEpoObject.this_epo_totals_containe, false, false, associatedSetter );
11153
11154					// Mainly used to update the price of the associated element when the associated product is variable.
11155					tm_force_update_price(
11156						associatedSetter
11157							.closest( '.tmcp-field-wrap' )
11158							.find( '.tc-price' )
11159							.not( tcAPI.associatedEpoSelector + ' .tc-price' ),
11160						associatedPrice,
11161						associatedFormattedPrice,
11162						associatedOriginalPrice,
11163						associatedFormattedOriginalPrice
11164					);
11165
11166					currentEpoObject.associated_connect.data( 'tm-quantity', tc_totals_ob.qty );
11167
11168					if ( currentEpoObject.associated_connect.data( 'tm-quantity' ) ) {
11169						associatedPrice = associatedPrice * parseFloat( currentEpoObject.associated_connect.data( 'tm-quantity' ) );
11170						associatedRawPrice = associatedRawPrice * parseFloat( currentEpoObject.associated_connect.data( 'tm-quantity' ) );
11171						associatedOriginalPrice = associatedOriginalPrice * parseFloat( currentEpoObject.associated_connect.data( 'tm-quantity' ) );
11172						associatedRawOriginalPrice = associatedRawOriginalPrice * parseFloat( currentEpoObject.associated_connect.data( 'tm-quantity' ) );
11173					}
11174
11175					associatedFormattedPrice = tm_set_price( associatedPrice, currentEpoObject.this_epo_totals_containe, false, false, associatedSetter );
11176					associatedFormattedOriginalPrice = tm_set_price( associatedOriginalPrice, currentEpoObject.this_epo_totals_containe, false, false, associatedSetter );
11177				}
11178
11179				currentEpoObject.associated_connect.data( 'price_set', 1 );
11180				if ( associatedSetter.is( '.tcenabled' ) ) {
11181					associatedSetter.data( 'associated_price_set', 1 );
11182				}
11183				associatedSetter.data( 'price_set', 1 );
11184				associatedSetter.data( 'raw_price', associatedRawPrice );
11185				associatedSetter.data( 'raw_original_price', associatedRawOriginalPrice );
11186				associatedSetter.data( 'price', tm_set_tax_price( associatedPrice, currentEpoObject.this_epo_totals_containe, associatedSetter ) );
11187				associatedSetter.data( 'original_price', tm_set_tax_price( associatedOriginalPrice, currentEpoObject.this_epo_totals_containe, associatedSetter ) );
11188
11189				currentEpoObject.associated_connect.data( 'price-changed', 1 );
11190
11191				setTimeout( function() {
11192					if ( ! ( currentEpoObject.associated_connect && event.noassociated ) ) {
11193						currentEpoObject.mainEpoObject.main_cart.trigger( {
11194							type: 'tm-epo-update',
11195							norules: 2
11196						} );
11197					}
11198				}, 20 );
11199			}
11200
11201			jWindow.trigger( 'tcEpoAfterCalculateTotals', {
11202				epo: currentEpoObject,
11203				alternativeCart: alternativeCart,
11204				this_product_type: this_product_type,
11205				cart: cart,
11206				bundleid: bundleid,
11207				totalsObject: tc_totals_ob,
11208				main_product: main_product,
11209				per_product_pricing: perProductPricing
11210			} );
11211
11212			hide_native_price = $.epoAPI.applyFilter( 'hide_native_price', true );
11213
11214			if ( cartQty > 0 ) {
11215				// hide native prices
11216				if ( TMEPOJS.tm_epo_change_variation_price === 'yes' ) {
11217					if ( hide_native_price === true && finalTotalBoxMode !== 'disable' ) {
11218						tm_get_native_prices_block( cart ).hide();
11219					} else {
11220						tm_get_native_prices_block( cart ).show();
11221					}
11222				}
11223
11224				if ( ! showTotal ||
11225					finalTotalBoxMode === 'disable' ||
11226					( finalTotalBoxMode === 'hideiftotaliszero' && product_total_price === 0 ) ||
11227					( finalTotalBoxMode === 'hideifoptionsiszero' && total_plus_fee === 0 )
11228				) {
11229					html = '';
11230					totalsHolder.html( html );
11231					totalsHolder.data( 'tm-floating-box-data', [] );
11232				} else {
11233					totalsHolder.html( html );
11234
11235					jWindow.trigger( 'tc-totals-container', {
11236						epo: tc_totals_ob,
11237						totals_holder: totalsHolder,
11238						data: {
11239							epo_object: currentEpoObject,
11240							tm_set_price: tm_set_price,
11241							tm_set_price_totals: tm_set_price_totals,
11242							product_total_price: product_total_price,
11243							product_price: productPrice,
11244							qty: cartQty
11245						},
11246						tm_epo_js: TMEPOJS
11247					} );
11248				}
11249
11250				if ( formatted_final_total && product_total_price >= 0 ) {
11251					update_native_html = tm_get_native_prices_block( cart );
11252
11253					if ( TMEPOJS.tm_epo_change_variation_price === 'yes' ) {
11254						if ( totalsHolder.data( 'is-on-sale' ) ) {
11255							temp = $.epoAPI.util.decodeHTML(
11256								$.epoAPI.template.html( tcAPI.templateEngine.tc_formatted_sale_price, {
11257									price: _f_regular_price,
11258									sale_price: _fprice,
11259									customer_price_format_wrap_start: customer_price_format_wrap_start,
11260									customer_price_format_wrap_end: customer_price_format_wrap_end,
11261									before_price_text: TMEPOJS.variation_price_before_price_text,
11262									after_price_text: TMEPOJS.variation_price_after_price_text
11263								} )
11264							);
11265							temp = {
11266								formatted: temp,
11267								raw: tc_totals_ob.product_total_price
11268							};
11269							temp = replace_suffixes( 'formatted', 'raw', temp, totalsHolder );
11270							temp = temp.formatted;
11271							update_native_html
11272								.html( temp )
11273								.show();
11274						} else {
11275							temp = $.epoAPI.util.decodeHTML(
11276								$.epoAPI.template.html( tcAPI.templateEngine.tc_formatted_price, {
11277									price: _fprice,
11278									customer_price_format_wrap_start: customer_price_format_wrap_start,
11279									customer_price_format_wrap_end: customer_price_format_wrap_end,
11280									before_price_text: TMEPOJS.variation_price_before_price_text,
11281									after_price_text: TMEPOJS.variation_price_after_price_text
11282								} )
11283							);
11284							temp = {
11285								formatted: temp,
11286								raw: tc_totals_ob.product_total_price
11287							};
11288							temp = replace_suffixes( 'formatted', 'raw', temp, totalsHolder );
11289							temp = temp.formatted;
11290							update_native_html
11291								.html( temp )
11292								.show();
11293						}
11294					}
11295
11296					if ( TMEPOJS.tm_epo_change_original_price === 'yes' ) {
11297						if ( ! alternativeCart || main_product.find( '.cpf-bto-price' ).length === 0 ) {
11298							if ( currentEpoObject.associated_connect ) {
11299								nativeProductPriceSelector = currentEpoObject.main_product.find( tcAPI.associatedNativeProductPriceSelector );
11300							} else {
11301								nativeProductPriceSelector = $( tcAPI.nativeProductPriceSelector );
11302							}
11303
11304							if ( nativeProductPriceSelector.length === 0 && main_product.is( '.tc-after-shop-loop' ) ) {
11305								nativeProductPriceSelector = main_product.closest( '.product' ).find( '.price' );
11306							}
11307							if ( nativeProductPriceSelector.data( 'tc-original-html' ) === undefined ) {
11308								nativeProductPriceSelector.data( 'tc-original-html', nativeProductPriceSelector.html() );
11309							}
11310							if ( product_total_price > 0 ) {
11311								if ( totalsHolder.data( 'is-on-sale' ) ) {
11312									temp = $.epoAPI.util.decodeHTML(
11313										$.epoAPI.template.html( tcAPI.templateEngine.tc_formatted_sale_price, {
11314											price: _f_regular_price,
11315											sale_price: _fprice,
11316											customer_price_format_wrap_start: customer_price_format_wrap_start,
11317											customer_price_format_wrap_end: customer_price_format_wrap_end,
11318											before_price_text: TMEPOJS.product_price_before_price_text,
11319											after_price_text: TMEPOJS.product_price_after_price_text
11320										} )
11321									);
11322									temp = {
11323										formatted: temp,
11324										raw: tc_totals_ob.product_total_price
11325									};
11326									temp = replace_suffixes( 'formatted', 'raw', temp, totalsHolder );
11327									temp = temp.formatted;
11328									nativeProductPriceSelector
11329										.html( temp )
11330										.show();
11331								} else {
11332									temp = $.epoAPI.util.decodeHTML(
11333										$.epoAPI.template.html( tcAPI.templateEngine.tc_formatted_price, {
11334											price: _fprice,
11335											customer_price_format_wrap_start: customer_price_format_wrap_start,
11336											customer_price_format_wrap_end: customer_price_format_wrap_end,
11337											before_price_text: TMEPOJS.product_price_before_price_text,
11338											after_price_text: TMEPOJS.product_price_after_price_text
11339										} )
11340									);
11341									temp = {
11342										formatted: temp,
11343										raw: tc_totals_ob.product_total_price
11344									};
11345									temp = replace_suffixes( 'formatted', 'raw', temp, totalsHolder );
11346									temp = temp.formatted;
11347									nativeProductPriceSelector
11348										.html( temp )
11349										.show();
11350								}
11351							} else if ( this_product_type && this_product_type !== 'composite' ) {
11352								if ( currentEpoObject.associated_connect ) {
11353									if ( currentEpoObject.variations_form.length ) {
11354										temp = currentEpoObject.this_epo_totals_container.data( 'variationIdElement' );
11355										if ( temp.length > 0 ) {
11356											temp = parseFloat( temp.val() );
11357											if ( ! ( ! temp || temp === 0 ) ) {
11358												nativeProductPriceSelector.html( $.epoAPI.util.decodeHTML( TMEPOJS.assoc_current_free_text ) );
11359											}
11360										}
11361									} else {
11362										nativeProductPriceSelector.html( $.epoAPI.util.decodeHTML( TMEPOJS.assoc_current_free_text ) );
11363									}
11364								} else {
11365									nativeProductPriceSelector.html( $.epoAPI.util.decodeHTML( TMEPOJS.current_free_text ) );
11366								}
11367							}
11368						}
11369
11370						jWindow.trigger( 'tcEpoMaybeChangePriceHtml', {
11371							epo: currentEpoObject,
11372							alternativeCart: alternativeCart,
11373							this_product_type: this_product_type,
11374							cart: cart,
11375							bundleid: bundleid,
11376							totalsObject: tc_totals_ob,
11377							main_product: main_product,
11378							nativePrice: _fprice
11379						} );
11380					}
11381				}
11382
11383				if ( alternativeCart ) {
11384					main_cart.trigger( {
11385						type: 'tm-epo-update',
11386						norules: 1
11387					} );
11388				} else {
11389					this_epo_totals_container.data( 'is_active', true );
11390				}
11391			} else {
11392				if ( currentEpoObject.associated_connect ) {
11393					nativeProductPriceSelector = currentEpoObject.main_product.find( tcAPI.associatedNativeProductPriceSelector );
11394					nativeProductPriceSelector.html( nativeProductPriceSelector.data( 'tc-original-html' ) );
11395				}
11396
11397				tm_get_native_prices_block( cart ).each( function() {
11398					var $npb = $( this );
11399					if ( ! $npb.data( 'tm-original-html' ) ) {
11400						$npb.data( 'tm-original-html', $npb.html() );
11401					} else {
11402						$npb.html( $npb.data( 'tm-original-html' ) );
11403					}
11404				} );
11405
11406				if ( rawProductPrice === 0 && TMEPOJS.tm_epo_remove_free_price_label === 'yes' ) {
11407					tm_get_native_prices_block( cart ).hide();
11408				} else if ( TMEPOJS.tm_epo_change_variation_price === 'yes' && ! ( hide_native_price === true && finalTotalBoxMode !== 'disable' ) ) {
11409					tm_get_native_prices_block( cart ).show();
11410				}
11411
11412				totalsHolder.empty();
11413
11414				if ( alternativeCart ) {
11415					main_cart.trigger( {
11416						type: 'tm-epo-update',
11417						norules: 1
11418					} );
11419				}
11420			}
11421
11422			main_cart.trigger( 'tm-epo-after-update', {
11423				container: cartContainer
11424			} );
11425
11426			jWindow.trigger( 'tc-epo-after-update', {
11427				epo: tc_totals_ob,
11428				totals_holder: totalsHolder,
11429				data: {
11430					epo_object: currentEpoObject,
11431					add_late_fields_prices: add_late_fields_prices,
11432					tm_set_price: tm_set_price,
11433					tm_set_price_totals: tm_set_price_totals,
11434					product_total_price: product_total_price,
11435					product_price: productPrice,
11436					qty: cartQty,
11437					bundleid: bundleid,
11438					currentCart: currentCart
11439				},
11440				tm_epo_js: TMEPOJS
11441			} );
11442		} );
11443
11444		if ( this_product_type === 'variable' || this_product_type === 'variable-subscription' ) {
11445			epoVariationSection = epoHolder.find( '.tm-epo-variation-section' ).first();
11446
11447			// Custom variation events
11448			epoVariationSection
11449				.find( '.tm-epo-reset-variation' )
11450				.off( 'click.cpfv' )
11451				.on( 'click.cpfv', function() {
11452					var field = $( this );
11453					var id = $.epoAPI.dom.id( field.attr( 'data-tm-for-variation' ) );
11454					var section = field.closest( '.cpf-type-variations' );
11455					var inputs = field.closest( '.cpf-element' ).find( '.tm-epo-variation-element' );
11456					var lis = field.closest( '.cpf-element' ).find( '.tmcp-field-wrap' );
11457
11458					inputs.prop( 'checked', false );
11459					lis.removeClass( 'tc-active' );
11460					variationForm
11461						.find( "[data-attribute_name='attribute_" + id + "']" )
11462						.val( '' )
11463						.trigger( 'change' );
11464					variationForm.find( "[data-attribute_name='attribute_" + id + "']" ).trigger( 'focusin' );
11465
11466					main_product
11467						.find( '.cpf-type-variations' )
11468						.not( section )
11469						.each( function( i, el ) {
11470							variationForm.find( "[data-attribute_name='attribute_" + $.epoAPI.dom.id( $( el ).find( '.tm-epo-variation-element' ).first().attr( 'data-tm-for-variation' ) ) + "']" ).trigger( 'focusin' );
11471						} );
11472					field.trigger( 'blur' );
11473					variationForm.trigger( 'woocommerce_update_variation_values_tmlogic' );
11474				} );
11475
11476			epoVariationSection
11477				.find( 'input.tm-epo-variation-element,input.tm-epo-variation-element + span' )
11478				.off( 'mouseup.cpfv' )
11479				.on( 'mouseup.cpfv', function() {
11480					var field = $( this );
11481					var id;
11482
11483					if ( field.is( 'span' ) ) {
11484						field = field.prev( 'input' );
11485					}
11486					if ( field.attr( 'disabled' ) ) {
11487						variationForm.find( '.reset_variations' ).trigger( 'click' );
11488					}
11489					id = $.epoAPI.dom.id( field.attr( 'data-tm-for-variation' ) );
11490					variationForm.find( "[data-attribute_name='attribute_" + id + "']" ).trigger( 'focusin' );
11491				} );
11492
11493			epoVariationSection
11494				.off( 'click.' + eventName + '.tmepo', '.reset_variations, .tc-epo-element-variable-reset-variations' )
11495				.on( 'click.' + eventName + '.tmepo', '.reset_variations, .tc-epo-element-variable-reset-variations', { _epoObject: epoObject }, function( event ) {
11496					var _nativeProductPriceSelector;
11497					if ( TMEPOJS.tm_epo_change_original_price === 'yes' ) {
11498						if ( ! alternativeCart || main_product.find( '.cpf-bto-price' ).length === 0 ) {
11499							if ( event.data._epoObject.associated_connect ) {
11500								_nativeProductPriceSelector = event.data._epoObject.main_product.find( tcAPI.associatedNativeProductPriceSelector );
11501							} else {
11502								_nativeProductPriceSelector = $( tcAPI.nativeProductPriceSelector );
11503							}
11504							if ( _nativeProductPriceSelector.data( 'tc-original-html' ) ) {
11505								_nativeProductPriceSelector.html( _nativeProductPriceSelector.data( 'tc-original-html' ) );
11506							}
11507						}
11508					}
11509					variationForm.find( '.variations .reset_variations, .tc-epo-element-variable-reset-variations' ).first().trigger( 'click' );
11510				} );
11511
11512			epoVariationSection
11513				.find( '.tm-epo-variation-element' )
11514				.off( 'change.cpfv tm_epo_variation_element_change' )
11515				.on( 'change.cpfv tm_epo_variation_element_change', function( e ) {
11516					var field = $( this );
11517					var id = $.epoAPI.dom.id( field.attr( 'data-tm-for-variation' ) );
11518					var value = field.val();
11519					var section = field.closest( '.cpf-type-variations' );
11520					var nativeSelect = variationForm.find( "[data-attribute_name='attribute_" + id + "']" );
11521					var exists;
11522
11523					if ( field.closest( '.tm-epo-variation-section' ).is( '.tm-hidden' ) ) {
11524						return;
11525					}
11526
11527					if ( ! ( e && e.type && e.type === 'tm_epo_variation_element_change' ) ) {
11528						exists = false;
11529						nativeSelect.each( function() {
11530							if ( this.value === value ) {
11531								exists = true;
11532								return false;
11533							}
11534						} );
11535						if ( ! exists ) {
11536							nativeSelect.trigger( 'focusin' );
11537						}
11538						nativeSelect.val( value ).trigger( 'change' );
11539					}
11540
11541					if ( ! value ) {
11542						nativeSelect.trigger( 'focusin' );
11543					}
11544
11545					main_product
11546						.find( '.cpf-type-variations' )
11547						.not( section )
11548						.each( function() {
11549							variationForm.find( '#' + $.epoAPI.dom.id( $( this ).find( '.tm-epo-variation-element' ).first().attr( 'data-tm-for-variation' ) ) ).trigger( 'focusin' );
11550						} );
11551
11552					field.trigger( 'blur' );
11553					variationForm.trigger( 'woocommerce_update_variation_values_tmlogic' );
11554				} )
11555				.off( 'focusin.cpfv' )
11556				.on( 'focusin.cpfv', function() {
11557					var field = $( this );
11558					var id;
11559
11560					if ( ! field.is( 'select' ) ) {
11561						return;
11562					}
11563
11564					id = $.epoAPI.dom.id( field.attr( 'data-tm-for-variation' ) );
11565					variationForm.find( "[data-attribute_name='attribute_" + id + "']" ).trigger( 'focusin' );
11566					variationForm.trigger( 'woocommerce_update_variation_values_tmlogic' );
11567				} );
11568
11569			variationForm.off( eventNamePrefix + 'found_variation.tmepo tm_fix_stock', '.single_variation_wrap' ).on( eventNamePrefix + 'found_variation.tmepo tm_fix_stock', '.single_variation_wrap', function() {
11570				fix_stock( $( this ), cartContainer );
11571			} );
11572
11573			// update prices when a variation is found
11574			variationForm
11575				.off( eventNamePrefix + 'found_variation.tmepo' )
11576				.on( eventNamePrefix + 'found_variation.tmepo', function( event, variation ) {
11577					var form = $( this );
11578
11579					totalsHolder.data( 'is-on-sale', variation.tc_is_on_sale );
11580					totalsHolder.data( 'regular-price', tm_set_backend_price( variation.display_regular_price, totalsHolder, variation ) );
11581
11582					jWindow.trigger( 'tm-epo-found-variation', {
11583						epo: epoObject,
11584						totalsHolder: totalsHolder,
11585						totalsHolderContainer: totalsHolderContainer,
11586						currentCart: currentCart,
11587						variationForm: form,
11588						variation: variation
11589					} );
11590
11591					found_variation_tmepo( {
11592						epoHolder: epoHolder,
11593						totalsHolder: totalsHolder,
11594						totalsHolderContainer: totalsHolderContainer,
11595						currentCart: currentCart,
11596						variationForm: form,
11597						variation: variation
11598					} );
11599
11600					fix_stock( form, cartContainer );
11601				} )
11602				.off( eventNamePrefix + 'hide_variation.tmepo' )
11603				.on( eventNamePrefix + 'hide_variation.tmepo', { _epoObject: epoObject }, function( event ) {
11604					var _nativeProductPriceSelector;
11605					if ( TMEPOJS.tm_epo_change_original_price === 'yes' ) {
11606						if ( ! alternativeCart || main_product.find( '.cpf-bto-price' ).length === 0 ) {
11607							if ( event.data._epoObject.associated_connect ) {
11608								_nativeProductPriceSelector = event.data._epoObject.main_product.find( tcAPI.associatedNativeProductPriceSelector );
11609							} else {
11610								_nativeProductPriceSelector = $( tcAPI.nativeProductPriceSelector );
11611							}
11612							if ( _nativeProductPriceSelector.data( 'tc-original-html' ) ) {
11613								_nativeProductPriceSelector.html( _nativeProductPriceSelector.data( 'tc-original-html' ) );
11614							}
11615						}
11616					}
11617					totalsHolder.data( 'price', false );
11618					// Fancy product Designer
11619					totalsHolder.removeData( 'tcprice' );
11620					currentCart.trigger( {
11621						type: 'tm-epo-update',
11622						norules: 2
11623					} );
11624				} )
11625				.off( eventNamePrefix + 'check_variations.tmepo' )
11626				.on( eventNamePrefix + 'check_variations.tmepo', function() {
11627					var data = {};
11628					var chosen = 0;
11629					var reset = epoVariationSection.find( '.reset_variations' );
11630
11631					variationForm.find( '.variations select, .tc-epo-variable-product-selector' ).each( function() {
11632						var attribute_name = $( this ).data( 'attribute_name' ) || $( this ).attr( 'name' );
11633						var value = $( this ).val() || '';
11634
11635						if ( value.length > 0 ) {
11636							chosen++;
11637						}
11638
11639						data[ attribute_name ] = value;
11640					} );
11641
11642					if ( chosen > 0 ) {
11643						if ( reset.css( 'visibility' ) === 'hidden' ) {
11644							reset.css( 'visibility', 'visible' ).hide().fadeIn();
11645						}
11646					} else {
11647						reset.css( 'visibility', 'hidden' );
11648					}
11649				} )
11650				.trigger( eventNamePrefix + 'check_variations' );
11651
11652			tm_custom_variations( epoObject, cartContainer, itemId, main_product, epoHolder );
11653		}
11654
11655		selectSelector.trigger( 'tm-select-change-html' );
11656		tmQty.trigger( 'change.cpf', { init: 1 } );
11657		tmQuantity.trigger( 'showhide.cpfcustom' );
11658		epoFieldHasClearButton.filter( ':checked' ).trigger( 'cpfclearbutton' );
11659
11660		jWindow.on( 'tm-do-epo-update', function() {
11661			// This must be run every time to get correct results for percent price types
11662			// if set norules then discount will not auto work upon chosing a variation
11663			currentCart.trigger( {
11664				type: 'tm-epo-update'
11665				//"norules": 2
11666			} );
11667		} );
11668
11669		jWindow.trigger( 'tm-epo-init-events', {
11670			epo: {
11671				epo_id: epo_id,
11672				form: epoObject.form,
11673				currentCart: currentCart,
11674				cart_container: cartContainer,
11675				epo_holder: epoHolder,
11676				totals_holder_container: totalsHolderContainer,
11677				totals_holder: totalsHolder,
11678				main_cart: main_cart,
11679				main_epo_inside_form: main_epo_inside_form,
11680				product_id_selector: product_id_selector,
11681				epo_id_selector: epo_id_selector,
11682				product_id: product_id,
11683				this_epo_container: this_epo_container,
11684				this_totals_container: this_totals_container,
11685				this_epo_totals_container: this_epo_totals_container
11686			}
11687		} );
11688
11689		jWindow.trigger( 'epoEventHandlers', {
11690			epo: epoObject,
11691			currentCart: currentCart,
11692			cartContainer: cartContainer,
11693			qtyElement: qtyElement,
11694			epoHolder: epoHolder,
11695			totalsHolderContainer: totalsHolderContainer,
11696			totalsHolder: totalsHolder,
11697			variationForm: variationForm,
11698			variation_id_selector: variation_id_selector,
11699			main_epo_inside_form: main_epo_inside_form,
11700			this_product_type: this_product_type,
11701			get_price_excluding_tax: get_price_excluding_tax,
11702			get_price_including_tax: get_price_including_tax
11703		} );
11704
11705		// show final totals
11706		if ( finalTotalBoxMode !== 'disable' ) {
11707			totalsHolderContainer.addClass( 'tc-show' );
11708		}
11709
11710		// show extra options
11711		jWindow.trigger( 'epo_options_before_visible' );
11712
11713		if ( TMEPOJS.tm_epo_progressive_display === 'yes' ) {
11714			setTimeout( function() {
11715				epoHolder
11716					.css( 'opacity', 0 )
11717					.addClass( 'tc-show' )
11718					.animate(
11719						{
11720							opacity: 1
11721						},
11722						tcAPI.epoAnimationDelay,
11723						'easeOutExpo',
11724						function() {
11725							jWindow.trigger( 'epo_options_visible' );
11726							jWindow.trigger( 'tmlazy' );
11727						}
11728					);
11729			}, tcAPI.epoDelay );
11730		} else {
11731			epoHolder.addClass( 'tc-show' );
11732			jWindow.trigger( 'epo_options_visible' );
11733			jWindow.trigger( 'tmlazy' );
11734		}
11735
11736		main_product.addClass( 'tc-init' );
11737	}
11738
11739	function run_wc_variation_form_cpf( epoObject ) {
11740		var form = epoObject.variations_form;
11741		var cart = epoObject.main_cart;
11742		var this_epo_container = epoObject.this_epo_container;
11743		var eventName = epoObject.is_associated ? 'tc_variation_form.cpf' : 'wc_variation_form.cpf';
11744
11745		form.off( eventName ).on( eventName, function() {
11746			if ( form.data( 'epo_loaded' ) ) {
11747				return;
11748			}
11749
11750			// Start Condition Logic
11751			cpf_section_logic( this_epo_container );
11752			cpf_element_logic( this_epo_container );
11753
11754			// Init field price rules
11755			$.tcepo.lateFieldsPrices[ epoObject.epoEventId ] = [];
11756
11757			epoEventHandlers( epoObject );
11758			tm_set_upload_fields( epoObject );
11759			tm_product_image( epoObject );
11760
11761			epoObject.noEpoUpdate = false;
11762
11763			setTimeout( function() {
11764				run_cpfdependson( this_epo_container );
11765				cart.trigger( {
11766					type: 'tm-epo-update',
11767					rules: 'init'
11768				} );
11769			}, 10 );
11770
11771			form.data( 'epo_loaded', true );
11772		} );
11773
11774		if ( variationsFormIsLoaded ) {
11775			form.trigger( eventName );
11776		}
11777
11778		jWindow.trigger( 'epo-after-init', { epo: epoObject } );
11779	}
11780
11781	function detect_variation_swatches_interval( epoObject ) {
11782		var $id = requestAnimationFrame( function() {
11783			detect_variation_swatches_interval( epoObject );
11784		} );
11785		var obj = epoObject.variations_form;
11786		var bound = obj.data( 'bound' );
11787		var eventName = epoObject.is_associated ? 'tc_variation_form.cpf' : 'wc_variation_form.cpf';
11788
11789		if ( bound ) {
11790			cancelAnimationFrame( $id );
11791			run_wc_variation_form_cpf( epoObject );
11792			obj.trigger( eventName );
11793		}
11794	}
11795
11796	function manualInitEPO( epoObject, item, itemCart, itemEpoContainer, main_product ) {
11797		var epoObjectOriginal = $.extend( true, {}, epoObject );
11798		var product_id = itemEpoContainer.attr( 'data-product-id' );
11799		var epo_id = itemEpoContainer.attr( 'data-epo-id' );
11800		var product_id_selector = '.tm-product-id-' + product_id;
11801		var epo_id_selector = "[data-epo-id='" + epo_id + "']";
11802		var epoEventId = 'p' + product_id + 'e' + epo_id;
11803		var this_epo_container = $( '.tc-extra-product-options' + product_id_selector + epo_id_selector );
11804		var this_totals_container = $( '.tc-totals-form' + product_id_selector + epo_id_selector );
11805		var this_epo_totals_container = $( '.tc-epo-totals' + product_id_selector + epo_id_selector );
11806
11807		epoObject.isManual = true;
11808
11809		$.tcepo.formSubmitEvents[ epoEventId ] = [];
11810		$.tcepo.errorObject[ epoEventId ] = false;
11811		$.tcepo.initialActivation[ epoEventId ] = false;
11812
11813		epoObject.product_id = product_id;
11814		epoObject.product_id_selector = product_id_selector;
11815		epoObject.epo_id = epo_id;
11816		epoObject.epo_id_selector = epo_id_selector;
11817		epoObject.epoEventId = epoEventId;
11818		epoObject.noEpoUpdate = true;
11819		epoObject.thisForm = item;
11820		epoObject.this_epo_container = this_epo_container;
11821		epoObject.this_totals_container = this_totals_container;
11822		epoObject.this_epo_totals_container = this_epo_totals_container;
11823
11824		tm_lazyload();
11825		main_product.find( '.tm-collapse' ).tmtoggle();
11826		main_product.find( '.tm-section-link' ).tmsectionpoplink();
11827
11828		tm_set_datepicker( item );
11829		setRangePickers( item );
11830		setRangePickersEvents();
11831		tm_set_repeaters( item, epoObject );
11832		tm_css_styles( item );
11833		tm_set_color_pickers( itemEpoContainer );
11834		tm_set_lightbox( itemEpoContainer.find( '.tc-lightbox-image' ).not( '.tm-extra-product-options-variations .radio-image' ) );
11835
11836		// Start Condition Logic
11837		cpf_section_logic( itemEpoContainer );
11838		cpf_element_logic( itemEpoContainer );
11839		run_cpfdependson( itemEpoContainer );
11840
11841		$.tcToolTip( item.find( '.tm-tooltip' ) );
11842		epoEventHandlers( epoObject, item, itemCart );
11843
11844		epoObject.noEpoUpdate = false;
11845
11846		itemCart.trigger( {
11847			type: 'tm-epo-update',
11848			norules: 2
11849		} );
11850		setTimeout( function() {
11851			epoObject.main_cart.trigger( {
11852				type: 'tm-epo-update',
11853				epoObject: epoObjectOriginal,
11854				norules: 1
11855			} );
11856		}, 200 );
11857		fix_stock( itemCart, item );
11858	}
11859
11860	function tm_init_epo( main_product, is_quickview, product_id, epo_id, associated_connect, mainEpoObject, reactivate ) {
11861		// Holds the main cart when using Composite Products
11862		var main_cart = false;
11863		var main_epo_inside_form = false;
11864		var main_totals_inside_form = false;
11865		var epoEventId;
11866		var has_epo = typeof product_id !== 'undefined';
11867		var not_has_epo = false;
11868		var add_to_cart_field;
11869		var product_id_selector;
11870		var epo_id_selector;
11871		var this_epo_container;
11872		var this_totals_container;
11873		var this_epo_totals_container;
11874		var epo_object;
11875		var variations_form;
11876		var detect_variation_swatches = $( '.variation_form_section .variations-table' ).length > 0;
11877		var is_associated = false;
11878
11879		main_product = $( main_product );
11880
11881		if ( main_product.is( '.tc-init' ) && ! reactivate ) {
11882			return true;
11883		}
11884
11885		if ( is_quickview ) {
11886			errorContainer = main_product;
11887		} else {
11888			errorContainer = $( window );
11889		}
11890
11891		jWindow.trigger( 'tm-epo-init-start' );
11892
11893		if ( ! has_epo ) {
11894			if ( main_product.is( '.product' ) ) {
11895				not_has_epo = true;
11896				has_epo = jBody.find( tcAPI.epoSelector ).length;
11897			}
11898		}
11899
11900		// return if product has no extra options and the totals box is not enabled for all products
11901		if ( ! has_epo && TMEPOJS.tm_epo_enable_final_total_box_all === 'no' && ! main_product.is( '.tm-no-options-composite' ) ) {
11902			jWindow.trigger( 'tm-epo-init-end-no-options' );
11903			return;
11904		}
11905
11906		// set the main_product variable again for products that have no extra options
11907		if ( not_has_epo ) {
11908			jWindow.trigger( 'tm-epo-init-no-options' );
11909			if ( main_product.is( '.product' ) && ! ( main_product.is( '.tm-no-options-pxq' ) || main_product.is( '.tm-no-options-composite' ) ) ) {
11910				main_product = jBody;
11911			}
11912		}
11913
11914		if ( ! product_id ) {
11915			add_to_cart_field = main_product.find( tcAPI.addToCartSelector ).last();
11916			if ( add_to_cart_field.length > 0 ) {
11917				product_id = add_to_cart_field.val();
11918			} else {
11919				add_to_cart_field = $( '.tc-totals-form.tm-totals-form-main' );
11920				product_id = add_to_cart_field.attr( 'data-product-id' );
11921			}
11922			if ( ! product_id ) {
11923				product_id = '';
11924			}
11925		}
11926
11927		if ( ! epo_id ) {
11928			epo_id = parseInt( main_product.find( 'input.tm-epo-counter' ).last().val(), 10 );
11929
11930			if ( ! Number.isFinite( epo_id ) ) {
11931				epo_id = '';
11932			}
11933		}
11934
11935		product_id_selector = '.tm-product-id-' + product_id;
11936		epo_id_selector = "[data-epo-id='" + epo_id + "']";
11937		this_epo_container = $( '.tc-extra-product-options' + product_id_selector + epo_id_selector );
11938		this_totals_container = $( '.tc-totals-form' + product_id_selector + epo_id_selector );
11939		this_epo_totals_container = $( '.tc-epo-totals' + product_id_selector + epo_id_selector );
11940		variations_form = main_product.find( '.variations_form' ).not( '.composite_component .variations_form' ).first();
11941		epoEventId = 'p' + product_id + 'e' + epo_id;
11942
11943		if ( variations_form && variations_form.attr( 'data-product_id' ) ) {
11944			if ( variations_form.attr( 'data-product_id' ) !== product_id ) {
11945				variations_form = main_product.find( ".variations_form[data-product_id='" + product_id + "']" );
11946			}
11947		}
11948
11949		main_cart = get_main_cart( main_product, main_product, 'form', product_id );
11950		if ( main_cart.length === 0 ) {
11951			if ( main_product.is( '.tc-shortcode-wrap' ) ) {
11952				main_cart = get_main_cart( this_totals_container, this_totals_container, '.tc-totals-form', product_id );
11953			} else if ( main_product.is( '.tc-epo-element-product-container' ) ) {
11954				main_cart = main_product.find( tcAPI.associatedEpoCart );
11955				// should never be 0
11956				if ( main_cart.length === 0 ) {
11957					main_cart = this_epo_container.parent( tcAPI.associatedEpoSelector );
11958					if ( main_cart.length === 0 ) {
11959						main_cart = main_product.find( '.tc-epo-element-product-container-right' );
11960					}
11961				}
11962				is_associated = true;
11963			}
11964		}
11965
11966		if ( is_associated && variations_form.length === 0 && main_product.is( '.variations_form' ) ) {
11967			variations_form = main_product;
11968		}
11969
11970		$.tcepo.formSubmitEvents[ epoEventId ] = [];
11971		$.tcepo.errorObject[ epoEventId ] = false;
11972		$.tcepo.initialActivation[ epoEventId ] = false;
11973
11974		if ( main_cart.find( tcAPI.epoSelector ).length > 0 ) {
11975			main_epo_inside_form = true;
11976		}
11977		if ( main_cart.find( '.tc-totals-form' ).length > 0 ) {
11978			main_totals_inside_form = true;
11979		}
11980
11981		if ( ! main_totals_inside_form ) {
11982			$.tcepo.formSubmitEvents[ epoEventId ][ $.tcepo.formSubmitEvents[ epoEventId ].length ] = {
11983				trigger: function() {
11984					return true;
11985				},
11986				on_true: function() {
11987					// hidden fields see totals.php
11988					var epos_hidden = $( '.tc-totals-form.tm-product-id-' + product_id + "[data-epo-id='" + epo_id + "']" ).tcClone();
11989					var formepo = $( '<div class="tm-hidden tm-formepo-normal"></div>' );
11990
11991					main_cart.find( '.tm-formepo-normal' ).remove();
11992					formepo.append( epos_hidden );
11993					main_cart.append( formepo );
11994					return true;
11995				},
11996				on_false: function() {
11997					setTimeout( function() {
11998						$( '.tm-formepo-normal' ).remove();
11999					}, 100 );
12000				}
12001			};
12002		}
12003		if ( ! main_epo_inside_form ) {
12004			$.tcepo.formSubmitEvents[ epoEventId ][ $.tcepo.formSubmitEvents[ epoEventId ].length ] = {
12005				trigger: function() {
12006					return true;
12007				},
12008				on_true: function() {
12009					// visible fields
12010					var epos = $( tcAPI.epoSelector + '.tm-product-id-' + product_id + "[data-epo-id='" + epo_id + "']" )
12011						.tcClone()
12012						.addClass( 'formepo' );
12013					var formepo = $( '<div class="tm-hidden tm-formepo"></div>' );
12014
12015					main_cart.find( '.tm-formepo' ).remove();
12016					formepo.append( epos );
12017
12018					main_cart.append( formepo );
12019					return true;
12020				},
12021				on_false: function() {
12022					setTimeout( function() {
12023						$( '.tm-formepo' ).remove();
12024					}, 100 );
12025				}
12026			};
12027		}
12028
12029		epo_object = {
12030			main_product: main_product,
12031			main_cart: main_cart,
12032			epo_id: epo_id,
12033			form: get_main_form( main_product ),
12034			main_epo_inside_form: main_epo_inside_form,
12035			product_id_selector: product_id_selector,
12036			epo_id_selector: epo_id_selector,
12037			product_id: product_id,
12038			this_epo_container: this_epo_container,
12039			this_totals_container: this_totals_container,
12040			this_epo_totals_container: this_epo_totals_container,
12041			qtySelector: tcAPI.qtySelector,
12042			manualInitEPO: manualInitEPO,
12043			epoEventId: epoEventId,
12044			variations_form: variations_form,
12045			has_epo: has_epo,
12046			is_quickview: is_quickview,
12047			is_associated: is_associated,
12048			is_epo_shortcode: this_epo_container.is( '.tc-shortcode' ),
12049			mainEpoObject: mainEpoObject,
12050			associated_connect: associated_connect,
12051			noEpoUpdate: true
12052		};
12053
12054		$( epo_object.form ).data( 'epo_object', epo_object );
12055		this_epo_container.data( 'epo_object', epo_object );
12056
12057		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 );
12058
12059		tm_set_checkboxes_rules( epo_object );
12060		tm_set_upload_rules( epo_object );
12061		tm_set_datepicker( this_epo_container );
12062		setRangePickers( this_epo_container );
12063		setRangePickersEvents();
12064		tm_set_repeaters( this_epo_container, epo_object );
12065		tm_set_url_fields();
12066
12067		$.tcToolTip( this_epo_container.find( '.tm-tooltip' ) );
12068
12069		this_epo_container.find( '.tm-collapse' ).tmtoggle();
12070		this_epo_container.find( '.tm-section-link' ).tmsectionpoplink();
12071
12072		if ( reactivate ) {
12073			this_epo_container.addClass( 'reactivate' );
12074		}
12075
12076		if ( variations_form.length > 0 ) {
12077			if ( reactivate ) {
12078				variations_form.data( 'epo_loaded', false );
12079			}
12080			this_epo_totals_container.data( 'price', false );
12081			if ( detect_variation_swatches ) {
12082				detect_variation_swatches_interval( epo_object );
12083			} else {
12084				run_wc_variation_form_cpf( epo_object );
12085			}
12086		} else {
12087			setTimeout( function() {
12088				// Start Condition Logic
12089				cpf_section_logic( this_epo_container );
12090				cpf_element_logic( this_epo_container );
12091				run_cpfdependson( this_epo_container );
12092
12093				// Init field price rules
12094				$.tcepo.lateFieldsPrices[ epoEventId ] = [];
12095				epoEventHandlers( epo_object );
12096				tm_set_upload_fields( epo_object );
12097				tm_product_image( epo_object );
12098
12099				jWindow.trigger( 'epo-after-init-in-timeout', { epo: epo_object } );
12100
12101				main_cart.trigger( 'tm-epo-check-dpd' );
12102				epo_object.noEpoUpdate = false;
12103				main_cart.trigger( {
12104					type: 'tm-epo-update',
12105					rules: 'init'
12106				} );
12107			}, 20 );
12108			jWindow.trigger( 'epo-after-init', { epo: epo_object } );
12109		}
12110
12111		tm_lazyload();
12112
12113		tm_css_styles( this_epo_container );
12114		tm_set_color_pickers( this_epo_container );
12115		tm_set_lightbox( this_epo_container.find( '.tc-lightbox-image' ).not( '.tm-extra-product-options-variations .radio-image' ) );
12116		tm_theme_specific_actions( epo_object );
12117		tc_compatibility( epo_object );
12118
12119		if ( ! is_associated ) {
12120			tm_floating_totals( this_epo_totals_container, is_quickview, main_cart );
12121			tm_form_submit_event( epo_object );
12122			epo_object = addShowHidetoEpoObject( epo_object, epoEventId, epo_object );
12123			tm_show_hide_add_to_cart_button( main_product, epo_object );
12124		}
12125
12126		jWindow.trigger( 'tm-epo-init-end', { epo: epo_object } );
12127
12128		return epo_object;
12129	}
12130
12131	function manual_init( container, reactivate ) {
12132		var $this = $( container );
12133		var product_id = $this.attr( 'data-product-id' );
12134		var epo_id = $this.attr( 'data-epo-id' );
12135		var quickview_floating = false;
12136		var testForm = $this.parent();
12137		if ( ! testForm.is( 'form' ) ) {
12138			testForm = $this.closest( 'form' );
12139			if ( ! testForm.is( 'form' ) ) {
12140				testForm = $this.parent();
12141			}
12142		}
12143		testForm = testForm.parent();
12144
12145		tm_init_epo( testForm, quickview_floating, product_id, epo_id, undefined, undefined, reactivate );
12146	}
12147
12148	function init_epo_plugin() {
12149		var epo_container;
12150		var epo_options_container;
12151
12152		if ( TMEPOJS.tm_epo_no_lazy_load === 'no' ) {
12153			$.extend( $.lazyLoadXT, {
12154				autoInit: false,
12155				selector: 'img.tmlazy',
12156				srcAttr: 'data-original',
12157				visibleOnly: false,
12158				updateEvent: $.lazyLoadXT.updateEvent + ' tmlazy'
12159			} );
12160		}
12161		/*
12162		 * tm-no-options-pxq = product has not options but the "Enable Final total box for all products" is on
12163		 * tm-no-options-composite = product is a composite product with no options but at least one of its bundles have options
12164		 */
12165		epo_container = $( '.tm-no-options-pxq, .tm-no-options-composite' );
12166
12167		if ( epo_container.length > 0 ) {
12168			// Special cases
12169			// -------------
12170			// Price x Quantity display (.tm-no-options-pxq) & composite
12171			// without option but a component has extra options
12172			// (.tm-no-options-composite)
12173
12174			epo_container.addClass( 'initializing' );
12175
12176			epo_container.each( function( loop_index, product_wrap ) {
12177				var inputepoid;
12178				product_wrap = $( product_wrap );
12179				inputepoid = product_wrap.find( 'input.tm-epo-counter' );
12180				if ( inputepoid.length > 1 ) {
12181					inputepoid.each( function() {
12182						var currentepoid = $( this );
12183						var currentcart = currentepoid.closest( '.cart' );
12184						var currentcartparent = currentcart.parent();
12185						if ( currentcartparent.is( 'form' ) ) {
12186							currentcartparent = currentcartparent.parent();
12187						}
12188
12189						if ( ! currentcartparent.is( '.initializing' ) ) {
12190							tm_init_epo( currentcartparent, false, undefined, parseInt( currentepoid.val(), 10 ) );
12191						}
12192					} );
12193				} else {
12194					tm_init_epo( product_wrap, false );
12195				}
12196				epo_container.removeClass( 'initializing' );
12197			} );
12198		}
12199
12200		// The setTimeout is used for compatibility with
12201		// skeleton screen mode that some themes have
12202
12203		setTimeout( function() {
12204			try {
12205				// new main way of calling tm_init_epo
12206				// -----------------------------------
12207				// Normal product pages
12208
12209				epo_options_container = $( tcAPI.epoSelector ).not( tcAPI.associatedEpoSelector + ' ' + tcAPI.epoSelector + ', .tm-no-options-pxq, .tm-no-options-composite, .wc-product-table ' + tcAPI.epoSelector );
12210
12211				if ( epo_options_container.length > 0 ) {
12212					epo_container.addClass( 'initializing' );
12213					epo_options_container.each( function() {
12214						var $this = $( this );
12215						var product_id = $this.attr( 'data-product-id' );
12216						var epo_id = $this.attr( 'data-epo-id' );
12217						var quickview_floating = false;
12218						var jProductWrap;
12219						var addInputs = false;
12220						var inputepoid;
12221
12222						// First check if we are in a loop.
12223						jProductWrap = $this.closest( '.tc-after-shop-loop.tm-has-options' );
12224
12225						if ( jProductWrap.length === 0 ) {
12226							// Check based on plugin add to cart selector.
12227							jProductWrap = $( tcAPI.tcAddToCartSelector + "[data-epo-id='" + epo_id + "'][value='" + product_id + "']" )
12228								.closest( 'form,.cart' )
12229								.first()
12230								.parent();
12231							// Check based on native add to cart selector.
12232							if ( jProductWrap.length === 0 ) {
12233								jProductWrap = $( tcAPI.addToCartSelector + "[value='" + product_id + "']" )
12234									.closest( 'form,.cart' )
12235									.first()
12236									.parent();
12237								if ( jProductWrap.length === 0 ) {
12238									// Check if we are in a shortcode
12239									jProductWrap = $this.closest( 'form,.cart' ).first().parent( '.tm-has-options' );
12240									if ( jProductWrap.length === 0 ) {
12241										if ( $this.is( '.tc-shortcode' ) ) {
12242											jProductWrap = $this.wrap( '<div class="tc-shortcode-wrap tc-wrap-' + epo_id + '"></div>' );
12243											jProductWrap = $this.parent();
12244										}
12245										if ( jProductWrap.length > 0 ) {
12246											addInputs = true;
12247										}
12248									}
12249								}
12250							}
12251						} else {
12252							addInputs = true;
12253						}
12254
12255						if ( jProductWrap.length > 0 ) {
12256							if ( addInputs ) {
12257								// in shop (variation logic will not work here)
12258								quickview_floating = true;
12259								$this
12260									.closest( 'form,.cart' )
12261									.first()
12262									.append( $( '<input name="add-to-cart" value="' + product_id + '" type="hidden">' ) );
12263								$this.closest( 'form,.cart' ).first().append( $( '<input type="hidden" value="" class="variation_id" name="variation_id">' ) );
12264							}
12265
12266							if ( jProductWrap.is( 'form' ) ) {
12267								jProductWrap = jProductWrap.parent();
12268							}
12269
12270							inputepoid = jProductWrap.find( 'input.tm-epo-counter' );
12271							if ( inputepoid.length > 1 ) {
12272								inputepoid.each( function() {
12273									var currentepoid = $( this );
12274									var currentcart = currentepoid.closest( '.cart' );
12275									var currentcartparent = currentcart.parent();
12276									if ( currentcartparent.is( 'form' ) ) {
12277										currentcartparent = currentcartparent.parent();
12278									}
12279
12280									if ( ! currentcartparent.is( '.initializing' ) ) {
12281										tm_init_epo( currentcartparent, quickview_floating, product_id, parseInt( currentepoid.val(), 10 ) );
12282									}
12283								} );
12284							} else {
12285								tm_init_epo( jProductWrap, quickview_floating, product_id, epo_id );
12286							}
12287						}
12288					} );
12289					epo_container.removeClass( 'initializing' );
12290				}
12291			} catch ( err ) {
12292				window.console.log( err );
12293				errorObject = err;
12294			}
12295		}, 1 );
12296	}
12297
12298	$.tcepo.tm_init_epo = function( main_product, is_quickview, product_id, epo_id ) {
12299		tm_init_epo( main_product, is_quickview, product_id, epo_id );
12300	};
12301
12302	$.tcepo.tmLazyloadContainer = function( container ) {
12303		tmLazyloadContainer = container;
12304	};
12305
12306	jWindow.on( 'tc_manual_init', function( evt, container ) {
12307		var reactivate;
12308		if ( 'container' in container && 'reactivate' in container ) {
12309			reactivate = container.reactivate;
12310			container = container.container;
12311		}
12312		manual_init( container, reactivate );
12313	} );
12314
12315	// document ready
12316	$( function() {
12317		tcAPI = $.epoAPI.applyFilter( 'tc_api', tcAPI );
12318
12319		jWindow.on( 'lazyLoadXToncomplete', function() {
12320			$( '.tm-owl-slider' ).each( function() {
12321				$( this ).trigger( 'refresh.owl.carousel' );
12322			} );
12323		} );
12324
12325		jWindow.on( 'tc_init_epo_plugin', function( evt ) {
12326			init_epo_plugin( evt );
12327		} );
12328
12329		jWindow.on( 'tcShowLastError', function() {
12330			window.console.log( errorObject );
12331		} );
12332
12333		function tcAjaxAddToCart( $this ) {
12334			var _pid;
12335			var epos;
12336			var _cpf_product_price;
12337			var _dynamic_product_price;
12338			var _override_product_price;
12339			var form_prefix;
12340			var epoid;
12341			var obj;
12342			var data;
12343			var tcTotalsForm;
12344
12345			currentAjaxButton = $this;
12346			_pid = currentAjaxButton.attr( 'data-product_id' );
12347			if ( undefined === _pid ) {
12348				_pid = currentAjaxButton.val();
12349			}
12350
12351			if ( undefined !== _pid ) {
12352				epoid = currentAjaxButton.closest( '.cart' ).find( '.tm-epo-counter' ).val();
12353				if ( ! epoid ) {
12354					epoid = currentAjaxButton.attr( 'data-epo-id' );
12355					if ( ! epoid ) {
12356						return;
12357					}
12358				}
12359				if ( currentAjaxButton.closest( '.tm-has-options' ).length !== 1 && currentAjaxButton.attr( 'data-epo-id' ) === undefined ) {
12360					return;
12361				}
12362
12363				obj = {};
12364
12365				epos = $( '.tc-extra-product-options.tm-product-id-' + _pid + '[data-epo-id="' + epoid + '"]' );
12366
12367				if ( epos.length > 1 ) {
12368					if ( epos.filter( '.formepo' ) ) {
12369						epos = epos.filter( '.formepo' );
12370					} else {
12371						epos = epos.first();
12372					}
12373				}
12374
12375				if ( epos.length === 1 ) {
12376					tcTotalsForm = $( '.tc-totals-form.tm-product-id-' + _pid + '[data-epo-id="' + epoid + '"]' );
12377					_cpf_product_price = tcTotalsForm.find( '.cpf-product-price' ).val();
12378					_dynamic_product_price = tcTotalsForm.find( '.cpf-dynamic-product-price' ).val();
12379					_override_product_price = tcTotalsForm.find( '.cpf-override-product-price' ).val();
12380					form_prefix = tcTotalsForm.find( '.tc_form_prefix' ).val();
12381
12382					obj = $.extend( obj, {
12383						tcajax: 1,
12384						tcaddtocart: _pid,
12385						cpf_product_price: _cpf_product_price,
12386						dynamic_product_price: _dynamic_product_price,
12387						override_product_price: _override_product_price
12388					} );
12389					if ( form_prefix ) {
12390						obj.tc_form_prefix = form_prefix;
12391					}
12392				}
12393				data = currentAjaxButton.data();
12394				data = $.extend( data, epos.tcSerializeObject(), obj );
12395
12396				currentAjaxButton.removeData();
12397				currentAjaxButton.data( data );
12398
12399				TMEPOJS.ajaxdata = {
12400					epos: epos,
12401					_pid: _pid,
12402					data: data
12403				};
12404			}
12405		}
12406
12407		// Betheme ajax add to cart.
12408		$( document ).on( 'click.tcajax', 'body.mfn-ajax-add-to-cart .single_add_to_cart_button:not(.disabled)', function() {
12409			var formepo;
12410			var $this = $( this );
12411			tcAjaxAddToCart( $this );
12412			TMEPOJS.ajaxdata.cart = $this.closest( '.cart' );
12413			TMEPOJS.ajaxdata.cart.find( '.tm-formepo' ).remove();
12414			formepo = $( "<div class='tm-hidden tm-formepo'></div>" );
12415			formepo.append( TMEPOJS.ajaxdata.epos.tcClone().addClass( 'formepo' ) );
12416			$this.after( formepo );
12417		} );
12418
12419		jBody.on( 'click.tcajax', '.ajax_add_to_cart', function() {
12420			tcAjaxAddToCart( $( this ) );
12421			if ( undefined !== TMEPOJS.ajaxdata ) {
12422				delete TMEPOJS.ajaxdata;
12423			}
12424		} );
12425
12426		$.ajaxPrefilter( function( options, originalOptions ) {
12427			var found = false;
12428			var hashes;
12429			var hash;
12430			var i;
12431			var params;
12432			var $thisbutton;
12433			var _data;
12434			var _urldata;
12435			var _pid;
12436			var epos;
12437			var _cpf_product_price;
12438			var _dynamic_product_price;
12439			var _override_product_price;
12440			var form_prefix;
12441			var obj;
12442			var oldData;
12443			var formData;
12444			var can_be_added = false;
12445			var associativeArray = {};
12446			var tcTotalsForm;
12447
12448			if ( TMEPOJS.tm_epo_enable_in_shop === 'yes' ) {
12449				hashes = options.url.split( '?' );
12450
12451				if ( hashes && hashes.length >= 1 ) {
12452					hashes = hashes[ 1 ];
12453					if ( hashes ) {
12454						hash = hashes.split( '&' );
12455						for ( i = 0; i < hash.length; i += 1 ) {
12456							params = hash[ i ].split( '=' );
12457							if ( params.length >= 1 ) {
12458								if ( params[ 0 ] && params[ 1 ] && params[ 0 ] === 'wc-ajax' && params[ 1 ] === 'add_to_cart' ) {
12459									found = true;
12460								}
12461							}
12462						}
12463						if ( found ) {
12464							options.originalsuccess = options.success;
12465							options.success = function( response ) {
12466								if ( response && response.error && response.product_url ) {
12467									if ( currentAjaxButton && currentAjaxButton.length === 1 ) {
12468										$thisbutton = currentAjaxButton;
12469									}
12470									$thisbutton = $( ".ajax_add_to_cart[data-product_id='" + originalOptions.data.product_id + "']" );
12471									$thisbutton.removeClass( 'added' );
12472									$thisbutton.removeClass( 'loading' );
12473								} else {
12474									options.originalsuccess.call( null, response );
12475								}
12476							};
12477						}
12478					}
12479				}
12480			}
12481
12482			if ( FormData && originalOptions.data ) {
12483				_data = originalOptions.data;
12484				if ( typeof originalOptions.data === 'string' ) {
12485					_data = $.epoAPI.util.parseParams( originalOptions.data );
12486				}
12487				if ( typeof _data[ 0 ] === 'object' ) {
12488					_data.forEach( function( item ) {
12489						associativeArray[ item.name ] = item.value;
12490					} );
12491					_data = associativeArray;
12492				}
12493
12494				_urldata = [];
12495				if ( originalOptions.url && originalOptions.url.indexOf ) {
12496					_urldata = $.epoAPI.util.parseParams( originalOptions.url.slice( originalOptions.url.indexOf( '?' ) + 1 ) );
12497				}
12498
12499				if ( 'quantity' in _data && _data.tcaddtocart && ( _data.product_id || _data[ 'add-to-cart' ] || _urldata.product_id || _urldata[ 'add-to-cart' ] ) ) {
12500					can_be_added = true;
12501					_pid = _data.tcaddtocart;
12502				} else if ( Array.isArray( _data ) ) {
12503					can_be_added = _data.some( function( item ) {
12504						return item.name === 'quantity';
12505					} ) && _data.some( function( item ) {
12506						return item.name === 'add-to-cart';
12507					} ) && _data.some( function( item ) {
12508						return item.name === 'tcaddtocart';
12509					} );
12510					_pid = _data.find( function( item ) {
12511						return item.name === 'tcaddtocart';
12512					} );
12513					if ( _pid ) {
12514						_pid = _pid.value;
12515					} else {
12516						_pid = false;
12517					}
12518				}
12519
12520				if ( can_be_added ) {
12521					if ( currentAjaxButton && currentAjaxButton.length === 1 && currentAjaxButton.closest( '.tm-has-options' ).length === 1 ) {
12522						epos = currentAjaxButton.closest( '.tm-has-options' ).find( '.tc-extra-product-options.tm-product-id-' + _pid );
12523					} else {
12524						epos = $( '.tc-extra-product-options.tm-product-id-' + _pid );
12525					}
12526
12527					if ( epos.length > 1 ) {
12528						if ( epos.filter( '.formepo' ) ) {
12529							epos = epos.filter( '.formepo' );
12530						} else {
12531							epos = epos.first();
12532						}
12533					}
12534					if ( epos.length === 1 ) {
12535						tcTotalsForm = $( '.tc-totals-form.tm-product-id-' + _pid );
12536						_cpf_product_price = tcTotalsForm.find( '.cpf-product-price' ).val();
12537						_dynamic_product_price = tcTotalsForm.find( '.cpf-dynamic-product-price' ).val();
12538						_override_product_price = tcTotalsForm.find( '.cpf-override-product-price' ).val();
12539						form_prefix = tcTotalsForm.find( '.tc_form_prefix' ).val();
12540						obj = {
12541							tcajax: 1,
12542							tcaddtocart: _pid,
12543							cpf_product_price: _cpf_product_price,
12544							dynamic_product_price: _dynamic_product_price,
12545							override_product_price: _override_product_price
12546						};
12547						if ( form_prefix ) {
12548							obj.tc_form_prefix = form_prefix;
12549						}
12550
12551						oldData = $.epoAPI.util.parseParams( options.data, true );
12552						oldData = $.extend( oldData, epos.tcSerializeObject(), obj );
12553						formData = new FormData();
12554
12555						Object.keys( oldData ).forEach( function( key ) {
12556							if ( key ) {
12557								formData.append( key, oldData[ key ] );
12558							}
12559						} );
12560
12561						epos.find( ':file' )
12562							.toArray()
12563							.forEach( function( el ) {
12564								for ( i = 0; i < $( el )[ 0 ].files.length; i++ ) {
12565									formData.delete( $( el ).attr( 'name' ) );
12566									formData.append( $( el ).attr( 'name' ), $( el )[ 0 ].files[ i ] );
12567								}
12568							} );
12569
12570						options.data = formData;
12571						options.contentType = false;
12572						options.cache = false;
12573						options.processData = false;
12574					}
12575				}
12576			}
12577		} );
12578
12579		jDocument.ajaxSuccess( function( event, request, settings ) {
12580			// quickview plugins
12581			var qv_container = TMEPOJS.quickview_array || 'null';
12582			var fromaddons = TMEPOJS.quickview_container || 'null';
12583			var added = {};
12584			var selectors;
12585			var container;
12586			var product_id;
12587			var epo_id;
12588			var noProductCheck;
12589			var testContainer;
12590			var parsedUrl;
12591			var time = 1;
12592			var detectContainer;
12593			var requestContainer;
12594
12595			if ( undefined !== TMEPOJS.ajaxdata ) {
12596				TMEPOJS.ajaxdata.cart.find( '.tm-formepo' ).remove();
12597				delete TMEPOJS.ajaxdata;
12598			}
12599
12600			parsedUrl = $.epoAPI.util.parseParams( settings.data );
12601			if ( parsedUrl.action === 'wc_epo_get_associated_product_html' ) {
12602				return;
12603			}
12604
12605			$( '.tm-formepo-normal' ).remove();
12606			$( '.tm-formepo' ).remove();
12607
12608			//fix for menu cart pop up
12609			$( '.tm-cart-link' ).tmpoplink();
12610
12611			qv_container = $.epoAPI.util.parseJSON( qv_container );
12612
12613			fromaddons = $.epoAPI.util.parseJSON( fromaddons );
12614
12615			for ( selectors in fromaddons ) {
12616				if ( Object.prototype.hasOwnProperty.call( fromaddons, selectors ) ) {
12617					added[ fromaddons[ selectors ][ 0 ] ] = $( fromaddons[ selectors ][ 1 ] );
12618				}
12619			}
12620
12621			$.extend( qv_container, added );
12622
12623			detectContainer = function() {
12624				var keyfound = false;
12625				Object.keys( qv_container ).forEach( function( key ) {
12626					if ( $( qv_container[ key ] ).length ) {
12627						keyfound = key;
12628					}
12629				} );
12630				return keyfound;
12631			};
12632			requestContainer = function( times ) {
12633				var id = requestAnimationFrame( function() {
12634					setTimeout( function() {
12635						requestContainer( times - 1 );
12636					}, 200 );
12637				} );
12638				var key = detectContainer();
12639				var epoContainer;
12640
12641				if ( key || 0 === times ) {
12642					cancelAnimationFrame( id );
12643					if ( key ) {
12644						noProductCheck = false;
12645						container = $( qv_container[ key ] );
12646
12647						if ( key === 'woothemes_quick_view' && container.is( '.fusion-woocommerce-quick-view-container' ) ) {
12648							return true;
12649						}
12650
12651						if ( key === 'fusion_quick_view_load' && container.find( tcAPI.epoSelector ).length === 0 ) {
12652							return true;
12653						}
12654
12655						if ( key === 'woodmart_quick_shop' ) {
12656							parsedUrl = $.epoAPI.util.parseParams( settings.url );
12657							if ( parsedUrl.action === 'woodmart_quick_shop' ) {
12658								testContainer = $( $.epoAPI.util.escapeSelector( qv_container[ key ] + '.post-' + parsedUrl.id ) );
12659								if ( testContainer.length ) {
12660									container = testContainer;
12661									noProductCheck = true;
12662								}
12663							}
12664						}
12665						if ( key === 'woodmart_quick_view' ) {
12666							parsedUrl = $.epoAPI.util.parseParams( settings.url );
12667							if ( parsedUrl.action === 'woodmart_quick_view' ) {
12668								testContainer = $( $.epoAPI.util.escapeSelector( qv_container[ key ] + '.post-' + parsedUrl.id ) );
12669								if ( testContainer.length ) {
12670									container = testContainer;
12671									noProductCheck = true;
12672								}
12673							}
12674						}
12675
12676						if ( key === 'quickview_pro' ) {
12677							parsedUrl = settings.url.split( '/' );
12678							if ( parsedUrl.length ) {
12679								testContainer = $( $.epoAPI.util.escapeSelector( qv_container[ key ] + ' .post-' + parsedUrl[ parsedUrl.length - 1 ] ) );
12680								if ( testContainer.length ) {
12681									container = testContainer;
12682									noProductCheck = true;
12683								}
12684							}
12685						}
12686
12687						if ( key === 'exwoofood_booking_info' || key === 'wqv_popup_content' || key === 'wp_food' || key === 'jet_popup_get_content' ) {
12688							noProductCheck = true;
12689						}
12690
12691						if ( key === 'woofood' && settings.data ) {
12692							parsedUrl = $.epoAPI.util.parseParams( settings.data );
12693							if ( parsedUrl.action === 'woofood_quickview_ajax' ) {
12694								testContainer = testContainer = container.find( 'form' ).parent();
12695								if ( testContainer.length ) {
12696									container = testContainer;
12697									noProductCheck = true;
12698								}
12699							}
12700						}
12701
12702						if ( container.find( '.product' ).length === 0 && container.is( '.product' ) ) {
12703							noProductCheck = true;
12704						}
12705
12706						if ( ( container.find( '.product' ).length > 0 || noProductCheck ) ) {
12707							container.removeClass( 'tc-init' );
12708
12709							if (
12710								key === 'fusion_quick_view_load' ||
12711								key === 'jet_popup_get_content' ||
12712								key === 'wp_food' ||
12713								key === 'woodmart_quick_shop' ||
12714								key === 'woodmart_quick_view' ||
12715								key === 'lightboxpro' ||
12716								key === 'jckqv_quick_view' ||
12717								key === 'yith_quick_view' ||
12718								key === 'theme_flatsome'
12719							) {
12720								variationsFormIsLoaded = true;
12721							}
12722							tmLazyloadContainer = container;
12723							epoContainer = tmLazyloadContainer.find( tcAPI.epoSelector );
12724							if ( epoContainer.length === 0 ) {
12725								delete qv_container[ key ];
12726								requestContainer( 10 );
12727								return true;
12728							}
12729
12730							if ( key === 'fusion_quick_view_load' ) {
12731								time = 1400;
12732							}
12733
12734							setTimeout( function() {
12735								product_id = epoContainer.attr( 'data-product-id' );
12736								epo_id = epoContainer.attr( 'data-epo-id' );
12737								if ( key === 'woodmart_quick_shop' ) {
12738									container.addClass( 'has-options' );
12739								}
12740
12741								// Reset element cache
12742								tcAPI.getElementFromFieldCache = [];
12743								tm_init_epo( tmLazyloadContainer, true, product_id, epo_id );
12744								jWindow.trigger( 'tmlazy' );
12745								jWindow.trigger( 'tm_epo_loaded_quickview' );
12746								if ( $.jMaskGlobals ) {
12747									tmLazyloadContainer.find( $.jMaskGlobals.maskElements ).each( function() {
12748										var t = $( this );
12749
12750										if ( t.attr( 'data-mask' ) ) {
12751											t.mask( t.attr( 'data-mask' ) );
12752										}
12753									} );
12754								}
12755							}, time );
12756						}
12757					}
12758				}
12759			};
12760			requestContainer( 10 );
12761		} );
12762
12763		init_epo_plugin();
12764
12765		$( '.tm-cart-link' ).tmpoplink();
12766		jBody.on( 'updated_checkout wc_fragments_loaded wc_fragments_refreshed wc_fragment_refresh', function() {
12767			$( '.tm-cart-link' ).tmpoplink();
12768		} );
12769
12770		jWindow.trigger( 'tmlazy' );
12771
12772		jWindow.trigger( 'tm_epo_loaded' );
12773	} );
12774
12775	function associated_table_item() {
12776		$( '.tc-associated-table-product td.product-name' ).each( function() {
12777			var el = $( this );
12778			if ( el.find( '.product-name' ).length === 0 ) {
12779				el.wrapInner( $( '<div class="tc-associated-table-product-indent"></div>' ) );
12780			}
12781		} );
12782	}
12783
12784	// Associated product cart indent
12785	jBody.on( 'updated_checkout updated_cart_totals', function() {
12786		associated_table_item();
12787	} );
12788
12789	associated_table_item();
12790
12791	// document ready
12792	$( function() {
12793		// Remove accept attribute from upload buttons when in Facebook or Instagram internral browser
12794		var ua = navigator.userAgent || navigator.vendor || window.opera;
12795		ua = ( ua.indexOf( 'FBAN' ) > -1 ) || ( ua.indexOf( 'FBAV' ) > -1 ) || ( ua.indexOf( 'Instagram' ) > -1 );
12796		if ( ua ) {
12797			$( '.tmcp-upload' ).removeAttr( 'accept' );
12798		}
12799
12800		// Fix several custom quantity buttons on themes
12801		jDocument.on( 'click', '.quantity .jckqv-qty-spinner, .quantity .ui-spinner-button', function() {
12802			$( this ).closest( '.quantity' ).find( tcAPI.qtySelector ).trigger( 'change' );
12803		} );
12804
12805		// bulk variations forms plugin
12806		$( '#wholesale_form' ).on( 'submit', function() {
12807			var _product_id = $( 'form.cart' ).find( tcAPI.addToCartSelector ).val();
12808			// visible fields
12809			var epos = $( tcAPI.epoSelector + ".tm-cart-main[data-product-id='" + _product_id + "']" ).tcClone();
12810			// hidden fields see totals.php
12811			var epos_hidden = $( ".tm-totals-form-main[data-product-id='" + _product_id + "']" ).tcClone();
12812			var formepo = $( "<div class='tm-hidden tm-formepo'></div>" );
12813
12814			formepo.append( epos );
12815			formepo.append( epos_hidden );
12816			$( this ).append( formepo );
12817			return true;
12818		} );
12819
12820		// Disable quote button if option validation fails
12821		jDocument.on( 'click', '#add_to_quote', function( e ) {
12822			var form;
12823			var epo_id;
12824			var epos;
12825
12826			if ( TMEPOJS && TMEPOJS.tm_epo_global_enable_validation === 'yes' ) {
12827				form = $( this ).parents( 'form' );
12828				epo_id = parseInt( form.find( '.tm-epo-counter' ).val(), 10 );
12829				epos = $( tcAPI.epoSelector + "[data-epo-id='" + epo_id + "']" );
12830
12831				// not validated
12832				if ( TMEPOJS.tm_epo_global_enable_validation === 'yes' && $.tc_validator && form.length > 0 && epos.length > 0 && ! form.tc_validate().form() ) {
12833					e.stopImmediatePropagation();
12834				}
12835			}
12836		} );
12837
12838		// PayPal for WooCommerce (PayPal Express Checkout button fix)
12839		$( '.single_add_to_cart_button.paypal_checkout_button' ).on( 'click', function( event ) {
12840			// this is the selector used by the paypal checkout plugin
12841			var form = $( '.cart' );
12842			var validator;
12843
12844			if ( form.data( 'tc_validator' ) ) {
12845				validator = form.data( 'tc_validator' );
12846				if ( validator.errorList ) {
12847					event.stopImmediatePropagation();
12848				}
12849			}
12850		} );
12851
12852		$( '.wc-product-table' ).on( 'init.wcpt', function( event, table ) {
12853			table.$table.find( tcAPI.epoSelector ).addClass( 'hidden' );
12854			table.$table.find( 'thead tr' ).append( '<th>&nbsp;</th>' );
12855			setTimeout( function() {
12856				table.$table.find( '.cart:not(.cart_group)' ).each( function() {
12857					var epo = $( this ).find( tcAPI.epoSelector );
12858					var tr = epo.closest( 'tr' );
12859
12860					$( "<td class='wc-product-table-epo'></td>" ).appendTo( tr ).append( epo );
12861					$( window ).trigger( 'tc_manual_init', epo );
12862					epo.removeClass( 'hidden' );
12863				} );
12864			}, 500 );
12865		} );
12866	} );
12867}( 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.