PageSourceSearch

https://musamexico.org/wp-content/plugins/woocommerce-tm-extra-product-options/assets/js/tm-api.js?ver=6.1.2

js musamexico.org collected 2026-10-02 07:00:01 UTC 19,318 bytes, 750 lines download raw bytes

1/**
2 * The following API is shared on both frontend and backend.
3 *
4 * No external libraries are loaded in this file.
5 *
6 * 1. Polyfills
7 * 2. themeComplete plugin JS API
8 * 3. themeComplete jQuery extensions
9 */
10/*jshint bitwise: false*/
11/**
12 * 1. Polyfills
13 *
14 * The following are required methods for
15 * the String, Number and Object prototype
16 */
17( function() {
18	'use strict';
19
20	/**
21	 * String.prototype.isNumeric()
22	 *
23	 * Determines whether a string contains a numeric value
24	 *
25	 * https://stackoverflow.com/questions/18082/validate-decimal-numbers-in-javascript-isnumeric
26	 */
27	if ( ! String.prototype.isNumeric ) {
28		Object.defineProperty( String.prototype, 'isNumeric', {
29			value: function() {
30				return ! isNaN( parseFloat( this ) ) && isFinite( this );
31			}
32		} );
33	}
34}() );
35
36// jQuery Mask Plugin v1.14.15
37// github.com/igorescobar/jQuery-Mask-Plugin
38window.jQuery.jMaskGlobals = {
39	maskElements: '.tc-extra-product-options input'
40};
41
42/**
43 * 2. themeComplete plugin JS API
44 */
45
46( function( $ ) {
47	'use strict';
48
49	$.epoAPI = {};
50	$.epoAPI.error = false;
51	$.epoAPI.math = {};
52	$.epoAPI.dom = {};
53	$.epoAPI.util = {};
54	$.epoAPI.locale = {};
55	$.epoAPI.template = {};
56
57	$.epoAPI.math.toFloat = function( s, d ) {
58		var n;
59
60		if ( ! ( typeof s === 'string' || typeof s === 'number' ) || isNaN( s ) ) {
61			return 0;
62		}
63		n = parseFloat( s );
64		if ( isNaN( n ) ) {
65			if ( d !== undefined ) {
66				return d;
67			}
68			return s;
69		}
70
71		return n;
72	};
73
74	$.epoAPI.math.toInt = function( s, d ) {
75		var n;
76
77		if ( ! ( typeof s === 'string' || typeof s === 'number' ) || isNaN( s ) || s === '' ) {
78			return 0;
79		}
80		n = parseInt( s, 10 );
81		if ( isNaN( n ) ) {
82			if ( d !== undefined ) {
83				return d;
84			}
85			return s;
86		}
87
88		return n;
89	};
90
91	/**
92	 * Rounds a number
93	 * modified from http://locutus.io/php/math/round/
94	 *
95	 * @param {any} value the value to round.
96	 * @param {int} precision the precision.
97	 * @param {string} mode the rounding mode.
98	 */
99	$.epoAPI.math.round = function( value, precision, mode ) {
100		var m;
101		var f;
102		var isHalf;
103		var n;
104		var sgn; // helper variables
105
106		// making sure precision is integer
107		precision = parseInt( precision, 10 );
108		if ( ! Number.isFinite( precision ) ) {
109			precision = 0;
110		}
111		m = Math.pow( 10, precision );
112		value = value * m;
113
114		// sign of the number
115		if ( typeof value === 'number' ) {
116			if ( value ) {
117				if ( value < 0 ) {
118					sgn = -1;
119				} else {
120					sgn = 1;
121				}
122			} else {
123				sgn = 0;
124			}
125		} else {
126			sgn = 0;
127		}
128
129		isHalf = value % 1 === 0.5 * sgn;
130		f = Math.floor( value );
131
132		if ( isHalf ) {
133			switch ( mode ) {
134				case 'PHP_ROUND_HALF_DOWN':
135					// rounds .5 toward zero
136					if ( sgn < 0 ) {
137						n = 1;
138					} else {
139						n = 0;
140					}
141					value = f + n;
142					break;
143				case 'PHP_ROUND_HALF_EVEN':
144					// rouds .5 towards the next even integer
145					value = f + ( ( f % 2 ) * sgn );
146					break;
147				case 'PHP_ROUND_HALF_ODD':
148					// rounds .5 towards the next odd integer
149					n = f % 2;
150					if ( n ) {
151						n = 0;
152					} else {
153						n = 1;
154					}
155					value = f + n;
156					break;
157				default:
158					// rounds .5 away from zero
159					if ( sgn > 0 ) {
160						n = 1;
161					} else {
162						n = 0;
163					}
164					value = f + n;
165			}
166		}
167
168		if ( ! isHalf ) {
169			value = Math.round( value );
170		}
171
172		return value / m;
173	};
174
175	$.epoAPI.dom.id = function( id ) {
176		if ( typeof id === 'undefined' ) {
177			return id;
178		}
179		if ( ! ( typeof id === 'string' || typeof id === 'number' ) || ( typeof id === 'number' && isNaN( id ) ) ) {
180			return id.toString();
181		}
182		return id.toString().replace( /(%|:|\.|\[|\]|,|=)/g, '\\$1' );
183	};
184
185	$.epoAPI.dom.scroll = function() {
186		var scrollLeft;
187		var scrollTop;
188
189		if ( window.pageYOffset ) {
190			scrollTop = window.pageYOffset;
191			scrollLeft = window.pageXOffset;
192		} else if ( document.documentElement && document.documentElement.scrollTop ) {
193			scrollTop = document.documentElement.scrollTop;
194			scrollLeft = document.documentElement.scrollLeft;
195		} else if ( document.body ) {
196			scrollTop = document.body.scrollTop;
197			scrollLeft = document.body.scrollLeft;
198		}
199
200		return { left: scrollLeft, top: scrollTop };
201	};
202
203	$.epoAPI.dom.size = function() {
204		var totalDocumentHeight;
205		var totalDocumentWidth;
206		var fullHeight;
207		var fullWidth;
208		var visibleWidth;
209		var visibleHeight;
210
211		if ( window.innerHeight && window.scrollMaxY ) {
212			totalDocumentWidth = window.innerWidth + window.scrollMaxX;
213			totalDocumentHeight = window.innerHeight + window.scrollMaxY;
214		} else if ( document.body.scrollHeight > document.body.offsetHeight ) {
215			totalDocumentWidth = document.body.scrollWidth;
216			totalDocumentHeight = document.body.scrollHeight;
217		} else {
218			totalDocumentWidth = document.body.offsetWidth;
219			totalDocumentHeight = document.body.offsetHeight;
220		}
221
222		if ( window.innerHeight ) {
223			if ( document.documentElement.clientWidth ) {
224				visibleWidth = document.documentElement.clientWidth;
225			} else {
226				visibleWidth = window.innerWidth;
227			}
228			visibleHeight = window.innerHeight;
229		} else if ( document.documentElement && document.documentElement.clientHeight ) {
230			visibleWidth = document.documentElement.clientWidth;
231			visibleHeight = document.documentElement.clientHeight;
232		} else if ( document.body ) {
233			visibleWidth = document.body.clientWidth;
234			visibleHeight = document.body.clientHeight;
235		}
236		if ( totalDocumentHeight < visibleHeight ) {
237			fullHeight = visibleHeight;
238		} else {
239			fullHeight = totalDocumentHeight;
240		}
241		if ( totalDocumentWidth < visibleWidth ) {
242			fullWidth = visibleWidth;
243		} else {
244			fullWidth = totalDocumentWidth;
245		}
246
247		return {
248			fullWidth: fullWidth,
249			fullHeight: fullHeight,
250
251			visibleWidth: visibleWidth,
252			visibleHeight: visibleHeight,
253
254			totalWidth: totalDocumentWidth,
255			totalHeight: totalDocumentHeight
256		};
257	};
258
259	// jQuery trim is deprecated, provide a trim method based on String.prototype.trim
260	$.epoAPI.util.trim = function( str ) {
261		if ( typeof str === 'string' ) {
262			// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trim#Polyfill
263			return str.replace( /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '' );
264		}
265		return str;
266	};
267
268	$.epoAPI.util.parseJSON = function( s ) {
269		var parsedjson;
270		var JSON = window.JSON;
271
272		try {
273			parsedjson = JSON.parse( s + '' );
274			if ( parsedjson && typeof parsedjson === 'object' && parsedjson !== null ) {
275				return parsedjson;
276			}
277		} catch ( err ) {
278			$.epoAPI.error = err;
279			return false;
280		}
281
282		return false;
283	};
284
285	$.epoAPI.util.decodeHTML = function( html ) {
286		var txt = document.createElement( 'textarea' );
287		txt.innerHTML = html;
288		return txt.value;
289	};
290
291	$.epoAPI.util.getStorage = function( type ) {
292		var storage;
293		var x;
294		try {
295			storage = window[ type ];
296			x = '__storage_test__';
297			storage.setItem( x, x );
298			storage.removeItem( x );
299			return storage;
300		} catch ( e ) {
301			return false;
302		}
303	};
304
305	$.epoAPI.util.basename = function( path ) {
306		return path.replace( /.*\//, '' );
307	};
308
309	// https://medium.com/javascript-in-plain-english/how-to-deep-copy-objects-and-arrays-in-javascript-7c911359b089
310	$.epoAPI.util.deepCopyArray = function( inObject ) {
311		var outObject;
312		var value;
313
314		if ( typeof inObject !== 'object' || inObject === null ) {
315			return inObject; // Return the value if inObject is not an object
316		}
317
318		// Create an array or object to hold the values
319		outObject = Array.isArray( inObject ) ? [] : {};
320
321		Object.keys( inObject ).forEach( function( key ) {
322			if ( inObject ) {
323				value = inObject[ key ];
324
325				// Recursively (deep) copy for nested objects, including arrays
326				outObject[ key ] = typeof value === 'object' && value !== null ? $.epoAPI.util.deepCopyArray( value ) : value;
327			}
328		} );
329
330		return outObject;
331	};
332
333	$.epoAPI.locale.getSystemDecimalSeparator = function() {
334		var n = 1.1;
335
336		n = /^1(.+)1$/.exec( n.toLocaleString() )[ 1 ];
337
338		return n;
339	};
340
341	$.epoAPI.template.html = function( template, obj ) {
342		var $template_html = template( obj );
343
344		$template_html = $template_html.replace( '/*<![CDATA[*/', '' );
345		$template_html = $template_html.replace( '/*]]>*/', '' );
346
347		return $template_html;
348	};
349
350	$.epoAPI.filters = {};
351
352	$.epoAPI.addFilter = function( $tag, $function_to_add, $priority, $accepted_args ) {
353		var $idx;
354
355		$priority = parseInt( $priority, 10 );
356		if ( isNaN( $priority ) ) {
357			$priority = 10;
358		}
359		$accepted_args = parseInt( $accepted_args, 10 );
360		if ( isNaN( $accepted_args ) ) {
361			$accepted_args = 1;
362		}
363		$idx = $function_to_add + '_' + $priority;
364		if ( ! $.epoAPI.filters[ $tag ] ) {
365			$.epoAPI.filters[ $tag ] = {};
366		}
367		if ( ! $.epoAPI.filters[ $tag ][ $priority ] ) {
368			$.epoAPI.filters[ $tag ][ $priority ] = {};
369		}
370		$.epoAPI.filters[ $tag ][ $priority ][ $idx ] = {
371			func: $function_to_add,
372			accepted_args: $accepted_args
373		};
374
375		return true;
376	};
377
378	$.epoAPI.removeFilter = function( $tag, $function_to_remove, $priority ) {
379		var $idx;
380		$priority = parseInt( $priority, 10 );
381		if ( isNaN( $priority ) ) {
382			$priority = 10;
383		}
384		$idx = $function_to_remove + '_' + $priority;
385
386		if ( $.epoAPI.filters[ $tag ] && $.epoAPI.filters[ $tag ][ $priority ] && $.epoAPI.filters[ $tag ][ $priority ][ $idx ] ) {
387			delete $.epoAPI.filters[ $tag ][ $priority ][ $idx ];
388			return true;
389		}
390
391		return false;
392	};
393
394	$.epoAPI.applyFilter = function( $tag, $value ) {
395		var $args = $.makeArray( arguments );
396		var priorities;
397
398		$args.splice( 0, 1 );
399
400		if ( ! $.epoAPI.filters[ $tag ] ) {
401			return $value;
402		}
403
404		priorities = $.epoAPI.filters[ $tag ];
405		$.each( priorities, function( i, el ) {
406			$.each( el, function( i2, el2 ) {
407				var func = el2.func;
408
409				if ( func instanceof Function ) {
410					$value = func.apply( null, $args );
411				} else if ( window[ func ] && window[ func ] instanceof Function ) {
412					$value = window[ func ].apply( null, $args );
413				}
414			} );
415		} );
416
417		return $value;
418	};
419
420	// Backwards compatibility (to be removed in the future)
421	$.tc_add_filter = $.epoAPI.addFilter;
422	$.tc_remove_filter = $.epoAPI.removeFilter;
423	$.tc_apply_filters = $.epoAPI.applyFilter;
424}( window.jQuery ) );
425
426/*
427 * Formatting functions
428 *
429 * Code modifiled from accounting.js
430 * http://openexchangerates.github.io/accounting.js/
431 */
432
433( function( $ ) {
434	'use strict';
435
436	/**
437	 * Check and normalise the value of precision (must be positive integer)
438	 *
439	 * @param {any} val the value to check.
440	 * @param {any} base the value to return is check fails.
441	 */
442	function checkPrecision( val, base ) {
443		val = Math.round( Math.abs( val ) );
444		return isNaN( val ) ? base : val;
445	}
446
447	/**
448	 * Takes a string/array of strings, removes all formatting/cruft
449	 * and returns the raw float value.
450	 *
451	 * @param {any} value the value to unformat.
452	 * @param {any} decimal the decimal point.
453	 */
454	function unformat( value, decimal ) {
455		var regex;
456		var unformatted;
457
458		// Recursively unformat arrays:
459		if ( Array.isArray( value ) ) {
460			return value.map( value, function( val ) {
461				return unformat( val, decimal );
462			} );
463		}
464
465		// Fails silently (need decent errors):
466		value = value || 0;
467
468		// Return the value as-is if it's already a number:
469		if ( typeof value === 'number' ) {
470			return value;
471		}
472
473		// Default decimal point comes from settings, but could be set to eg. "," in opts:
474		decimal = decimal || '.';
475
476		// Build regex to strip out everything except digits, decimal point and minus sign:
477		regex = new RegExp( '[^0-9-' + decimal + ']', [ 'g' ] );
478		unformatted = parseFloat(
479			( '' + value )
480				.replace( regex, '' ) // strip out any cruft
481				.replace( decimal, '.' ) // make sure decimal point is standard
482		);
483
484		// This will fail silently which may cause trouble, let's wait and see:
485		return ! isNaN( unformatted ) ? unformatted : 0;
486	}
487
488	/**
489	 * Implementation of toFixed() that treats floats more like decimals
490	 *
491	 * Fixes binary rounding issues (eg. (0.615).toFixed(2) === "0.61") that present
492	 * problems for accounting- and finance-related software.
493	 *
494	 * @param {any} value the value to convert.
495	 * @param {int} precision the precision.
496	 */
497	function toFixed( value, precision ) {
498		var exponentialForm;
499		var rounded;
500		var finalResult;
501
502		if ( ! Number.isFinite( value ) ) {
503			return '-';
504		}
505
506		precision = checkPrecision( precision, 2 );
507
508		exponentialForm = Number( unformat( value ) * Math.pow( 10, precision ) );
509		rounded = Math.round( exponentialForm );
510		finalResult = Number( rounded / Math.pow( 10, precision ) ).toFixed( precision );
511		return finalResult;
512	}
513
514	/**
515	 * Format into currency or a number, with comma-separated thousands and custom precision/decimal places
516	 *
517	 * opts = {
518	 *     symbol: "$",    // currency symbol is '$'
519	 *     format: "%s%v", // controls output: %s = symbol, %v = value (can be object, see docs)
520	 *     decimal: ".",   // decimal point separator
521	 *     thousand: ",",  // thousands separator
522	 *     precision: 2,   // decimal places
523	 * }
524	 *
525	 * @param {any} number the value to convert.
526	 * @param {Object} opts the options for formatting.
527	 */
528	function format( number, opts ) {
529		var formats;
530		var useFormat;
531		var negative;
532		var base;
533		var mod;
534
535		// Resursively format arrays:
536		if ( Array.isArray( number ) ) {
537			return number.map( number, function( val ) {
538				return format( val, opts );
539			} );
540		}
541
542		// Clean up number:
543		number = unformat( number );
544
545		// Do not format if opts are not correct or missing
546		if ( ! opts ) {
547			return number;
548		}
549
550		// Clean up precision
551		opts.precision = checkPrecision( opts.precision );
552
553		// Format currency
554		if ( opts.format && opts.symbol ) {
555			// Check format (returns object with pos, neg and zero):
556			formats = {
557				pos: opts.format,
558				neg: opts.format.replace( '-', '' ).replace( '%v', '-%v' ),
559				zero: opts.format
560			};
561
562			// Choose which format to use for this value:
563			useFormat = number > 0 ? formats.pos : number < 0 ? formats.neg : formats.zero;
564
565			// Return with currency symbol added:
566			opts.opts = {
567				precision: opts.precision,
568				thousand: opts.thousand,
569				decimal: opts.decimal
570			};
571
572			number = useFormat.replace( '%s', opts.symbol ).replace( '%v', format( Math.abs( number ), opts.opts ) );
573
574			// Format number
575		} else {
576			if ( ! Number.isFinite( number ) ) {
577				return '-';
578			}
579			// Do some calc:
580			negative = number < 0 ? '-' : '';
581			base = parseInt( toFixed( Math.abs( number || 0 ), opts.precision ), 10 ) + '';
582			mod = base.length > 3 ? base.length % 3 : 0;
583
584			// Format the number:
585			number = negative + ( mod ? base.substring( 0, mod ) + opts.thousand : '' ) + base.substring( mod ).replace( /(\d{3})(?=\d)/g, '$1' + opts.thousand ) + ( opts.precision ? opts.decimal + toFixed( Math.abs( number ), opts.precision ).split( '.' )[ 1 ] : '' );
586		}
587
588		return number;
589	}
590
591	$.epoAPI.math.unformat = unformat;
592	$.epoAPI.math.format = format;
593	$.epoAPI.math.toFixed = toFixed;
594}( window.jQuery ) );
595
596/**
597 * 3. themeComplete jQuery extensions
598 *
599 **/
600( function( $ ) {
601	'use strict';
602
603	var expo;
604	var rCRLF = /\r?\n/g;
605	var rcheckableType = /^(?:checkbox|radio)$/i;
606	var rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i;
607	var rsubmittable = /^(?:input|select|textarea|keygen)/i;
608
609	// Extend jQuery easing
610	if ( ! $.easing.easeInExpo ) {
611		expo = function( p ) {
612			return Math.pow( p, 6 );
613		};
614		$.easing.easeInExpo = expo;
615		$.easing.easeOutExpo = function( p ) {
616			return 1 - expo( 1 - p );
617		};
618		$.easing.easeInOutExpo = function( p ) {
619			return p < 0.5 ? expo( p * 2 ) / 2 : 1 - ( expo( ( p * -2 ) + 2 ) / 2 );
620		};
621	}
622
623	// Add jQuery plugins
624	$.fn.extend( {
625		// Create checkbox switch
626		tmcheckboxes: function() {
627			var tm_settings_wrap_checkbox = this.find( ":checkbox:not('.tm-default-checkbox')" ).not( '.wp-tab-panel :checkbox, .tm-weekdays-picker-wrap :checkbox, .tm-months-picker-wrap :checkbox' );
628			tm_settings_wrap_checkbox.wrap( '<label class="tm-epo-switch-wrapper-label"></label>' );
629			tm_settings_wrap_checkbox.wrap( '<span class="tm-epo-switch-wrapper tc"></span>' );
630			tm_settings_wrap_checkbox.after( '<span class="tc-label tm-epo-switch tc"></span>' );
631			return this;
632		},
633
634		// Encode a set of HTML elements as an array of names and values.
635		// Elements do not need to be inside a form
636		tcSerializeArray: function() {
637			return this.find( ':input' )
638				.filter( function() {
639					var type = this.type;
640
641					// Use .is( ":disabled" ) so that fieldset[disabled] works
642					return this.name && ! $( this ).is( ':disabled' ) && rsubmittable.test( this.nodeName ) && ! rsubmitterTypes.test( type ) && ( this.checked || ! rcheckableType.test( type ) );
643				} )
644				.map( function( i, elem ) {
645					var val = $( this ).val();
646
647					if ( val === null ) {
648						return null;
649					}
650
651					if ( Array.isArray( val ) ) {
652						return $.map( val, function( thisval ) {
653							return { name: elem.name, value: thisval.replace( rCRLF, '\r\n' ) };
654						} );
655					}
656
657					return { name: elem.name, value: val.replace( rCRLF, '\r\n' ) };
658				} )
659				.get();
660		},
661
662		// convert element to a valid JSON object
663		tcSerializeObject: function() {
664			var o = {};
665			var a = this.tcSerializeArray();
666
667			$.each( a, function() {
668				if ( o[ this.name ] !== undefined ) {
669					if ( this.name.endsWith( '[]' ) ) {
670						if ( ! o[ this.name ].push ) {
671							o[ this.name ] = [ o[ this.name ] ];
672						}
673						o[ this.name ].push( this.value || '' );
674					} else {
675						o[ this.name ] = this.value || '';
676					}
677				} else {
678					o[ this.name ] = this.value || '';
679				}
680			} );
681
682			return o;
683		},
684
685		// Scroll container to a specific element
686		tcScrollTo: function( obj, duration, offset ) {
687			var element = this;
688
689			obj = $( obj );
690			if ( obj.length === 0 ) {
691				return this;
692			}
693			if ( ! duration ) {
694				duration = 0;
695			}
696			if ( ! offset ) {
697				offset = 0;
698			}
699			if ( element[ 0 ].self === window ) {
700				element = $( 'html, body' );
701			} else {
702				if ( element.find( '.woodmart-scroll-content' ).length ) {
703					element = element.find( '.woodmart-scroll-content' );
704				}
705				if ( ! element.offset() ) {
706					element = $( 'html, body' );
707				} else {
708					offset = offset + ( element.scrollTop() - element.offset().top );
709				}
710			}
711
712			return element.animate(
713				{
714					scrollTop: $( obj ).offset().top + offset
715				},
716				duration
717			);
718		},
719
720		/**
721		 * Textarea and select clone() bug workaround | Spencer Tipping
722		 * Licensed under the terms of the MIT source code license
723		 * https://github.com/spencertipping/jquery.fix.clone/blob/master/jquery.fix.clone.js
724		 */
725		tcClone: function() {
726			var i;
727			var l;
728			var j;
729			var m;
730			var result = $.fn.clone.apply( this, arguments );
731			var textareas = this.find( 'textarea' ).add( this.filter( 'textarea' ) );
732			var resultTextareas = result.find( 'textarea' ).add( result.filter( 'textarea' ) );
733			var selects = this.find( 'select' ).add( this.filter( 'select' ) );
734			var resultSelects = result.find( 'select' ).add( result.filter( 'select' ) );
735
736			for ( i = 0, l = textareas.length; i < l; i += 1 ) {
737				$( resultTextareas[ i ] ).val( $( textareas[ i ] ).val() );
738			}
739			for ( i = 0, l = selects.length; i < l; i += 1 ) {
740				for ( j = 0, m = selects[ i ].options.length; j < m; j += 1 ) {
741					if ( selects[ i ].options[ j ].selected === true ) {
742						resultSelects[ i ].options[ j ].selected = true;
743					}
744				}
745			}
746
747			return result;
748		}
749	} );
750}( 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.