PageSourceSearch

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

js musamexico.org collected 2026-10-02 07:00:10 UTC 37,491 bytes, 1,321 lines download raw bytes

1
2/*jshint esversion: 6 */
3( function( window ) {
4	'use strict';
5
6	var empty = function( mixedVar ) {
7		var undef;
8		var key;
9		var i;
10		var len;
11		var emptyValues = [ undef, null, false, 0, '', '0' ];
12		for ( i = 0, len = emptyValues.length; i < len; i++ ) {
13			if ( mixedVar === emptyValues[ i ] ) {
14				return true;
15			}
16		}
17		if ( typeof mixedVar === 'object' ) {
18			for ( key in mixedVar ) {
19				if ( mixedVar.hasOwnProperty( key ) ) {
20					return false;
21				}
22			}
23			return true;
24		}
25		return false;
26	};
27
28	var array_key_exists = function( key, search ) {
29		if ( ! search || ( search.constructor !== Array && search.constructor !== Object ) ) {
30			return false;
31		}
32		return key in search;
33	};
34
35	var getNumberOfParameters = function( func ) {
36		const ARROW = true;
37		const FUNC_ARGS = ARROW ? /^(function)?\s*[^\(]*\(\s*([^\)]*)\)/m : /^(function)\s*[^\(]*\(\s*([^\)]*)\)/m;
38		const FUNC_ARG_SPLIT = /,/;
39		const FUNC_ARG = /^\s*(_?)(.+?)\1\s*$/;
40		const STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
41
42		return ( ( func || '' )
43			.toString()
44			.replace( STRIP_COMMENTS, '' )
45			.match( FUNC_ARGS ) || [ '', '', '' ] )[ 2 ]
46			.split( FUNC_ARG_SPLIT )
47			.map( function( arg ) {
48				return arg.replace( FUNC_ARG, function( all, underscore, name ) {
49					return name.split( '=' )[ 0 ].trim();
50				} );
51			} )
52			.filter( String )
53			.length;
54	};
55
56	var getNumberOfRequiredParameters = function( func ) {
57		return func.length;
58	};
59
60	var is_scalar = function( mixedVar ) {
61		return ( /boolean|number|string/ ).test( typeof mixedVar );
62	};
63
64	var gettype = function( obj ) {
65		return {}.toString.call( obj ).split( ' ' )[ 1 ].slice( 0, -1 ).toLowerCase();
66	};
67
68	var floatval = function( s, d ) {
69		var n;
70
71		if ( ! ( typeof s === 'string' || typeof s === 'number' ) || isNaN( s ) ) {
72			if ( d !== undefined ) {
73				return d;
74			}
75			return 0;
76		}
77		n = parseFloat( s );
78		if ( isNaN( n ) ) {
79			if ( d !== undefined ) {
80				return d;
81			}
82			return s;
83		}
84
85		return n;
86	};
87
88	var strcmp = function( str1, str2 ) {
89		return ( ( str1 === str2 ) ? 0 : ( ( str1 > str2 ) ? 1 : -1 ) );
90	};
91
92	var bindec = function( binaryString ) {
93		binaryString = ( binaryString + '' ).replace( /[^01]/gi, '' );
94		return parseInt( binaryString, 2 );
95	};
96
97	var decbin = function( number ) {
98		if ( number < 0 ) {
99			number = 0xFFFFFFFF + number + 1;
100		}
101		return parseInt( number, 10 ).toString( 2 );
102	};
103
104	var dechex = function( number ) {
105		if ( number < 0 ) {
106			number = 0xFFFFFFFF + number + 1;
107		}
108		return parseInt( number, 10 ).toString( 16 );
109	};
110
111	var decoct = function( number ) {
112		if ( number < 0 ) {
113			number = 0xFFFFFFFF + number + 1;
114		}
115		return parseInt( number, 10 ).toString( 8 );
116	};
117
118	var deg2rad = function( angle ) {
119		return angle * 0.017453292519943295; // (angle / 180) * Math.PI;
120	};
121
122	var roundWithPrecision = function( num, dec = 0 ) {
123		var num_sign = num >= 0 ? 1 : -1;
124		return dec === 0 ? Math.round( num ) : parseFloat( ( Math.round( ( num * Math.pow( 10, dec ) ) + ( num_sign * 0.0001 ) ) / Math.pow( 10, dec ) ).toFixed( dec ) );
125	};
126
127	var hexdec = function( hexString ) {
128		hexString = ( hexString + '' ).replace( /[^a-f0-9]/gi, '' );
129		return parseInt( hexString, 16 );
130	};
131
132	var octdec = function( octString ) {
133		octString = ( octString + '' ).replace( /[^0-7]/gi, '' );
134		return parseInt( octString, 8 );
135	};
136
137	var hypot = function( x, y ) {
138		var t;
139		x = Math.abs( x );
140		y = Math.abs( y );
141		t = Math.min( x, y );
142		x = Math.max( x, y );
143		t = t / x;
144		return x * Math.sqrt( 1 + ( t * t ) ) || null;
145	};
146
147	var THEMECOMPLETE_EPO_MATH = {
148		variables: {},
149		on_var_not_found: undefined,
150		on_var_validation: undefined,
151		operators: {},
152		functions: {},
153		cache: {},
154		construct: function() {
155			this.add_defaults();
156			this.set_division_by_zero_to_zero();
157			return this;
158		},
159		add_operator: function( $operator ) {
160			this.operators[ $operator.operator ] = $operator;
161			return this;
162		},
163		evaluate: function( $expression, $cache = true ) {
164			return this.execute( $expression, $cache );
165		},
166		execute: function( $expression, $cache = true ) {
167			var $cache_key = $expression;
168			var $calculator;
169			var $tokens;
170			var result;
171
172			if ( ! array_key_exists( $cache_key, this.cache ) ) {
173				$tokens = new THEMECOMPLETE_EPO_MATH_Tokenizer( $expression, this.operators );
174				$tokens = $tokens.tokenize().build_reverse_polish_notation();
175				if ( $cache ) {
176					this.cache[ $cache_key ] = $tokens;
177				}
178			} else {
179				$tokens = this.cache[ $cache_key ];
180			}
181
182			$calculator = new THEMECOMPLETE_EPO_MATH_Calculator( this.functions, this.operators );
183
184			result = $calculator.calculate( $tokens, this.variables, this.on_var_not_found, this );
185
186			if ( 'number' !== gettype( result ) || isNaN( result ) ) {
187				result = 0;
188			}
189
190			return result;
191		},
192		add_function: function( $name, $function ) {
193			this.functions[ $name ] = new THEMECOMPLETE_EPO_MATH_CustomFunction( $name, $function );
194			return this;
195		},
196		get_vars: function() {
197			return this.variables;
198		},
199		get_var: function( $variable ) {
200			if ( ! array_key_exists( $variable, this.variables ) ) {
201				if ( this.on_var_not_found && 'function' === typeof this.on_var_not_found ) {
202					this.on_var_not_found( $variable );
203				}
204				return THEMECOMPLETE_EPO_MATH_Error.trigger( 'Variable (' + $variable + ') not set', 'UnknownVariableError', 0 );
205			}
206			return this.variables[ $variable ];
207		},
208		set_var: function( $variable, $value ) {
209			if ( this.on_var_validation && 'function' === typeof this.on_var_validation ) {
210				$value = this.on_var_validation( $variable, $value );
211			}
212			this.variables[ $variable ] = $value;
213			return this;
214		},
215		var_exists: function( $variable ) {
216			return array_key_exists( $variable, this.variables );
217		},
218		set_vars: function( $variables, $clear = true ) {
219			var $this = this;
220			if ( $clear ) {
221				this.remove_vars();
222			}
223			$variables.forFach( function( $value, $name ) {
224				$this.set_var( $name, $value );
225			} );
226			return this;
227		},
228		set_var_not_found_handler: function( $handler ) {
229			this.on_var_not_found = $handler;
230			return this;
231		},
232		set_var_validation_handler: function( $handler ) {
233			this.on_var_validation = $handler;
234			return this;
235		},
236		remove_var: function( $variable ) {
237			delete this.variables[ $variable ];
238			return this;
239		},
240		remove_vars: function() {
241			this.variables = {};
242			this.on_var_not_found = null;
243			return this;
244		},
245		get_operators: function() {
246			return this.operators;
247		},
248		get_functions: function() {
249			return this.functions;
250		},
251		remove_operator: function( $operator ) {
252			delete this.operators[ $operator ];
253		},
254		set_division_by_zero_to_zero: function() {
255			this.add_operator(
256				new THEMECOMPLETE_EPO_MATH_Operator(
257					'/',
258					false,
259					180,
260					function( $a, $b ) {
261						$a = Number( $a );
262						$b = Number( $b );
263						return 0 == $b ? 0 : $a / $b; // eslint-disable-line eqeqeq
264					}
265				)
266			);
267			return this;
268		},
269		get_cache: function() {
270			return this.cache;
271		},
272		clear_cache: function() {
273			this.cache = [];
274		},
275		add_defaults: function() {
276			var $this = this;
277			var default_operators = this.default_operators();
278			var default_functions = this.default_functions();
279			Object.keys( default_operators ).forEach( function( $name ) {
280				var $operator = default_operators[ $name ];
281				$this.add_operator( new THEMECOMPLETE_EPO_MATH_Operator( $name, $operator[ 2 ], $operator[ 1 ], $operator[ 0 ] ) );
282			} );
283			Object.keys( default_functions ).forEach( function( $name ) {
284				var $callable = default_functions[ $name ];
285				$this.add_function( $name, $callable );
286			} );
287			this.on_var_validation = this.default_var_validation;
288			this.variables = this.default_vars();
289			return this;
290		},
291		default_operators: function() {
292			return {
293				'+': [
294					function( $a, $b ) {
295						$a = floatval( $a, 0 );
296						$b = floatval( $b, 0 );
297						return $a + $b;
298					},
299					170,
300					false
301				],
302				'-': [
303					function( $a, $b ) {
304						$a = floatval( $a, 0 );
305						$b = floatval( $b, 0 );
306						return $a - $b;
307					},
308					170,
309					false
310				],
311				// unary positive token.
312				uPos: [
313					function( $a ) {
314						$a = floatval( $a, 0 );
315						return $a;
316					},
317					200,
318					false
319				],
320				// unary minus token.
321				uNeg: [
322					function( $a ) {
323						$a = floatval( $a, 0 );
324						return 0 - $a;
325					},
326					200,
327					false
328				],
329				'*': [
330					function( $a, $b ) {
331						$a = floatval( $a, 0 );
332						$b = floatval( $b, 0 );
333						return $a * $b;
334					},
335					180,
336					false
337				],
338				'/': [
339					function( $a, $b ) {
340						$a = floatval( $a, 0 );
341						$b = floatval( $b, 0 );
342						if ( empty( $b ) ) {
343							return THEMECOMPLETE_EPO_MATH_Error.trigger( 'Division By Zero', 'DivisionByZeroError', 0 );
344						}
345						return $a / $b;
346					},
347					180,
348					false
349				],
350				'^': [
351					function( $a, $b ) {
352						$a = floatval( $a, 0 );
353						$b = floatval( $b, 0 );
354						return Math.pow( $a, $b );
355					},
356					220,
357					true
358				],
359				'%': [
360					function( $a, $b ) {
361						$a = floatval( $a, 0 );
362						$b = floatval( $b, 0 );
363						return $a % $b;
364					},
365					180,
366					false
367				],
368				'&&': [
369					function( $a, $b ) {
370						$a = String( $a );
371						$b = String( $b );
372						if ( $a.isNumeric() ) {
373							$a = floatval( $a, 0 );
374						}
375						if ( $b.isNumeric() ) {
376							$b = floatval( $b, 0 );
377						}
378						return $a && $b ? 1 : 0;
379					},
380					100,
381					false
382				],
383				'||': [
384					function( $a, $b ) {
385						$a = String( $a );
386						$b = String( $b );
387						if ( $a.isNumeric() ) {
388							$a = floatval( $a, 0 );
389						}
390						if ( $b.isNumeric() ) {
391							$b = floatval( $b, 0 );
392						}
393						return $a || $b ? 1 : 0;
394					},
395					90,
396					false
397				],
398				'==': [
399					function( $a, $b ) {
400						$a = String( $a );
401						$b = String( $b );
402						if ( $a.isNumeric() && $b.isNumeric() ) {
403							return floatval( $a ) === floatval( $b ) ? 1 : 0;
404						}
405						return 0 === strcmp( $a, $b ) ? 1 : 0;
406					},
407					140,
408					false
409				],
410				'!=': [
411					function( $a, $b ) {
412						$a = String( $a );
413						$b = String( $b );
414						if ( $a.isNumeric() && $b.isNumeric() ) {
415							return floatval( $a ) !== floatval( $b ) ? 1 : 0;
416						}
417						return 0 === strcmp( $a, $b ) ? 1 : 0;
418					},
419					140,
420					false
421				],
422				'>=': [
423					function( $a, $b ) {
424						$a = String( $a );
425						$b = String( $b );
426						if ( $a.isNumeric() ) {
427							$a = floatval( $a, 0 );
428						}
429						if ( $b.isNumeric() ) {
430							$b = floatval( $b, 0 );
431						}
432						return $a >= $b ? 1 : 0;
433					},
434					150,
435					false
436				],
437				'>': [
438					function( $a, $b ) {
439						$a = String( $a );
440						$b = String( $b );
441						if ( $a.isNumeric() ) {
442							$a = floatval( $a, 0 );
443						}
444						if ( $b.isNumeric() ) {
445							$b = floatval( $b, 0 );
446						}
447						return $a > $b ? 1 : 0;
448					},
449					150,
450					false
451				],
452				'<=': [
453					function( $a, $b ) {
454						$a = String( $a );
455						$b = String( $b );
456						if ( $a.isNumeric() ) {
457							$a = floatval( $a, 0 );
458						}
459						if ( $b.isNumeric() ) {
460							$b = floatval( $b, 0 );
461						}
462						return $a <= $b ? 1 : 0;
463					},
464					150,
465					false
466				],
467				'<': [
468					function( $a, $b ) {
469						$a = String( $a );
470						$b = String( $b );
471						if ( $a.isNumeric() ) {
472							$a = floatval( $a, 0 );
473						}
474						if ( $b.isNumeric() ) {
475							$b = floatval( $b, 0 );
476						}
477						return $a < $b ? 1 : 0;
478					},
479					150,
480					false
481				]
482			};
483		},
484		default_functions: function() {
485			var $this = this;
486			return {
487				abs: Math.abs,
488				acos: Math.acos,
489				acosh: Math.acosh,
490				arcsin: Math.asin,
491				arcctg: function( $arg ) {
492					return ( Math.PI / 2 ) - Math.atan( $arg );
493				},
494				arccot: function( $arg ) {
495					return ( Math.PI / 2 ) - Math.atan( $arg );
496				},
497				arccotan: function( $arg ) {
498					return ( Math.PI / 2 ) - Math.atan( $arg );
499				},
500				arcsec: function( $arg ) {
501					return Math.acos( 1 / $arg );
502				},
503				arccosec: function( $arg ) {
504					return Math.asin( 1 / $arg );
505				},
506				arccsc: function( $arg ) {
507					return Math.asin( 1 / $arg );
508				},
509				arccos: Math.acos,
510				arctan: Math.atan,
511				arctg: Math.atan,
512				array: function( ...$args ) {
513					return $args;
514				},
515				asin: Math.asin,
516				atan: Math.atan,
517				atan2: Math.atan2,
518				atanh: Math.atanh,
519				atn: Math.atan,
520
521				avg: function( $arg1, ...$args ) {
522					var sum;
523					if ( Array.isArray( $arg1 ) ) {
524						if ( 0 === $arg1.length ) {
525							return THEMECOMPLETE_EPO_MATH_Error.trigger( 'Array must contain at least one element!', 'InvalidArgumentError', 0 );
526						}
527					}
528					$args = [].concat.apply( [], [ $arg1, ...$args ] );
529
530					sum = $args.reduce( function( previousValue, currentValue ) {
531						return floatval( currentValue, 0 ) + floatval( previousValue, 0 );
532					} );
533					return sum / $args.length;
534				},
535				average: function( $arg1, ...$args ) {
536					var sum;
537					if ( Array.isArray( $arg1 ) ) {
538						if ( 0 === $arg1.length ) {
539							return THEMECOMPLETE_EPO_MATH_Error.trigger( 'Array must contain at least one element!', 'InvalidArgumentError', 0 );
540						}
541					}
542					$args = [].concat.apply( [], [ $arg1, ...$args ] );
543
544					sum = $args.reduce( function( previousValue, currentValue ) {
545						return floatval( currentValue, 0 ) + floatval( previousValue, 0 );
546					} );
547					return sum / $args.length;
548				},
549				bindec: bindec,
550				ceil: Math.ceil,
551				cos: Math.cos,
552				cosec: function( $arg ) {
553					return Math.sin( 1 / $arg );
554				},
555				csc: function( $arg ) {
556					return Math.sin( 1 / $arg );
557				},
558				cosh: Math.cosh,
559				ctg: function( $arg ) {
560					return Math.cos( $arg ) / Math.sin( $arg );
561				},
562				cot: function( $arg ) {
563					return Math.cos( $arg ) / Math.sin( $arg );
564				},
565				cotan: function( $arg ) {
566					return Math.cos( $arg ) / Math.sin( $arg );
567				},
568				cotg: function( $arg ) {
569					return Math.cos( $arg ) / Math.sin( $arg );
570				},
571				ctn: function( $arg ) {
572					return Math.cos( $arg ) / Math.sin( $arg );
573				},
574				decbin: decbin,
575				dechex: dechex,
576				decoct: decoct,
577				deg2rad: deg2rad,
578				exp: Math.exp,
579				expm1: Math.expm1,
580				floor: Math.floor,
581				int: Math.floor,
582				fmod: function( $arg1, $arg2 ) {
583					return $arg1 % $arg2;
584				},
585				hexdec: hexdec,
586				hypot: hypot,
587				if: function( $expr, $trueval, $falseval ) {
588					var $exres;
589					if ( 0 === $expr || 1 === $expr || true === $expr || false === $expr ) {
590						$exres = $expr;
591					} else {
592						$exres = $this.execute( $expr );
593					}
594					if ( $exres ) {
595						return $this.execute( $trueval );
596					}
597					return $this.execute( $falseval );
598				},
599				intdiv: function( $arg1, $arg2 ) {
600					return Math.trunc( Math.trunc( $arg1 ) / Math.trunc( $arg2 ) );
601				},
602				ln: Math.log,
603				lg: Math.log10,
604				log: Math.log,
605				log1p: Math.log1p,
606				max: function( $arg1, ...$args ) {
607					var $array;
608					if ( Array.isArray( $arg1 ) && 0 === $arg1.length ) {
609						return THEMECOMPLETE_EPO_MATH_Error.trigger( 'Array must contain at least one element!', 'InvalidArgumentError', 0 );
610					}
611					$array = Array.isArray( $arg1 ) ? $arg1 : [ $arg1, ...$args ];
612					$array = $array.map( floatval );
613
614					return Math.max( ...$array );
615				},
616				min: function( $arg1, ...$args ) {
617					var $array;
618					if ( Array.isArray( $arg1 ) && 0 === $arg1.length ) {
619						return THEMECOMPLETE_EPO_MATH_Error.trigger( 'Array must contain at least one element!', 'InvalidArgumentError', 0 );
620					}
621					$array = Array.isArray( $arg1 ) ? $arg1 : [ $arg1, ...$args ];
622					$array = $array.map( floatval );
623
624					return Math.min( ...$array );
625				},
626				octdec: octdec,
627				pi: function() {
628					return Math.PI;
629				},
630				pow: Math.pow,
631				rad2deg: function( angle ) {
632					return angle * 57.29577951308232; // angle / Math.PI * 180
633				},
634				round: roundWithPrecision,
635				sin: Math.sin,
636				sinh: Math.sinh,
637				sec: function( $arg ) {
638					return 1 / Math.cos( $arg );
639				},
640				sqrt: Math.sqrt,
641				tan: Math.tan,
642				tanh: Math.tanh,
643				tn: Math.tan,
644				tg: Math.tan,
645				lookuptable: function( field, lookupTableId ) {
646					var lookupTables;
647					var x;
648					var y;
649					var table;
650					var xColumn;
651					var price = 0;
652					var tableNum = 0;
653					var TMEPOJS = window.TMEPOJS;
654
655					if ( TMEPOJS ) {
656						lookupTables = window && window.jQuery && window.jQuery.epoAPI && window.jQuery.epoAPI.util.parseJSON( TMEPOJS.lookupTables );
657						if ( lookupTables ) {
658							if ( Array.isArray( lookupTableId ) ) {
659								tableNum = lookupTableId[ 1 ];
660								lookupTableId = lookupTableId[ 0 ];
661							}
662							if ( empty( lookupTableId ) ) {
663								return 0;
664							}
665							if ( empty( tableNum ) ) {
666								tableNum = 0;
667							}
668							if ( Array.isArray( field ) ) {
669								x = field[ 0 ];
670								y = field[ 1 ];
671							} else {
672								x = field;
673								y = '';
674							}
675
676							table = lookupTables[ lookupTableId ];
677							if ( table ) {
678								table = table[ tableNum ];
679								if ( table ) {
680									table = table.data;
681									xColumn = table[ x ];
682									if ( xColumn === undefined && x && x !== undefined ) {
683										if ( floatval( x ) === 0 ) {
684											xColumn = table[ Object.keys( table )[ 0 ] ];
685										} else if ( x ) {
686											x = $this.find_lookup_table_index( x, table );
687											xColumn = table[ x ];
688										}
689									}
690									if ( xColumn !== undefined ) {
691										if ( y && y !== undefined ) {
692											y = $this.find_lookup_table_index( y, xColumn );
693										} else {
694											// fetch the first row since this means we want
695											// a single row result
696											y = Object.keys( xColumn )[ 0 ];
697										}
698										if ( y === 'max' ) {
699											price = floatval( xColumn[ Object.keys( xColumn )[ Object.keys( xColumn ).length - 1 ] ] );
700										} else {
701											price = floatval( xColumn[ y ] );
702										}
703									}
704								}
705							}
706						}
707					}
708					return price;
709				}
710			};
711		},
712		find_lookup_table_index: function( value, table ) {
713			var r;
714			var keys = Object.keys( table );
715			value = floatval( value );
716
717			r = keys.map( function( n ) {
718				return n === 'max' ? n : floatval( n );
719			} ).reduce( function( a, b ) {
720				if ( b === 'max' && value > a ) {
721					return b;
722				}
723				if ( a === 'max' && value > b ) {
724					return a;
725				}
726				if ( a < b ) {
727					if ( value > a && value <= b ) {
728						return b;
729					}
730				} else {
731					if ( ( value > b && value <= a ) || ( value > a || b === 'max' ) ) {
732						return a;
733					}
734					return b;
735				}
736				if ( value > b ) {
737					return b;
738				}
739				return a;
740			} );
741			keys = keys.map( function( n ) {
742				return n === 'max' ? n : floatval( n );
743			} );
744
745			if ( value > Math.max( ...keys ) || value < Math.min( ...keys ) ) {
746				return false;
747			}
748
749			return r;
750		},
751		default_vars: function() {
752			return {
753				pi: 3.141592653589793,
754				e: 2.718281828459045
755			};
756		},
757		default_var_validation: function( $variable, $value ) {
758			if ( ! is_scalar( $value ) && ! Array.isArray( $value ) && undefined !== $value ) {
759				return THEMECOMPLETE_EPO_MATH_Error.trigger( 'Variable (' + $variable + ') type (' + gettype( $value ) + ') is not scalar or array!', 0 );
760			}
761			return $value;
762		}
763	};
764
765	var THEMECOMPLETE_EPO_MATH_Tokenizer = function( $input, $operators ) {
766		var node = {
767			tokens: [],
768			input: '',
769			operators: {},
770			number_buffer: '',
771			string_buffer: '',
772			allow_negative: true,
773			in_single_quoted_string: false,
774			in_double_quoted_string: false,
775			is_number: function( ch ) {
776				return ch >= '0' && ch <= '9';
777			},
778			is_alpha: function( ch ) {
779				return ( ch >= 'a' && ch <= 'z' ) || ( ch >= 'A' && ch <= 'Z' ) || '_' === ch;
780			},
781			is_dot: function( ch ) {
782				return '.' === ch;
783			},
784			is_lp: function( ch ) {
785				return '(' === ch;
786			},
787			is_rp: function( ch ) {
788				return ')' === ch;
789			},
790			is_comma: function( ch ) {
791				return ',' === ch;
792			},
793			empty_number_buffer_as_literal: function() {
794				if ( this.number_buffer.length ) {
795					this.tokens.push( THEMECOMPLETE_EPO_MATH_Token( THEMECOMPLETE_EPO_MATH_Constants.LITERAL, this.number_buffer ) );
796					this.number_buffer = '';
797				}
798			},
799			empty_str_buffer_as_variable: function() {
800				if ( '' !== this.string_buffer ) {
801					this.tokens.push( THEMECOMPLETE_EPO_MATH_Token( THEMECOMPLETE_EPO_MATH_Constants.VARIABLE, this.string_buffer ) );
802					this.string_buffer = '';
803				}
804			},
805			tokenize: function() {
806				var is_last_char_escape = false;
807				var $this = this;
808				var $token_test = [];
809
810				this.tokens = [];
811
812				this.input.toString().split( '' ).forEach( function( ch ) {
813					switch ( true ) {
814						case $this.in_single_quoted_string:
815							if ( '\\' === ch ) {
816								if ( is_last_char_escape ) {
817									$this.string_buffer += '\\';
818									is_last_char_escape = false;
819								} else {
820									is_last_char_escape = true;
821								}
822								break;
823							} else if ( "'" === ch ) {
824								if ( is_last_char_escape ) {
825									$this.string_buffer += "'";
826									is_last_char_escape = false;
827								} else {
828									$this.tokens.push( THEMECOMPLETE_EPO_MATH_Token( THEMECOMPLETE_EPO_MATH_Constants.STRING, $this.string_buffer ) );
829									$this.in_single_quoted_string = false;
830									$this.string_buffer = '';
831								}
832								break;
833							}
834							if ( is_last_char_escape ) {
835								$this.string_buffer += '\\';
836								is_last_char_escape = false;
837							}
838							$this.string_buffer += ch;
839							break;
840						case $this.in_double_quoted_string:
841							if ( '\\' === ch ) {
842								if ( is_last_char_escape ) {
843									$this.string_buffer += '\\';
844									is_last_char_escape = false;
845								} else {
846									is_last_char_escape = true;
847								}
848								break;
849							} else if ( '"' === ch ) {
850								if ( is_last_char_escape ) {
851									$this.string_buffer += '"';
852									is_last_char_escape = false;
853								} else {
854									$this.tokens.push( THEMECOMPLETE_EPO_MATH_Token( THEMECOMPLETE_EPO_MATH_Constants.STRING, $this.string_buffer ) );
855									$this.in_double_quoted_string = false;
856									$this.string_buffer = '';
857								}
858								break;
859							}
860							if ( is_last_char_escape ) {
861								$this.string_buffer += '\\';
862								is_last_char_escape = false;
863							}
864							$this.string_buffer += ch;
865							break;
866						case '[' === ch:
867							$this.tokens.push( THEMECOMPLETE_EPO_MATH_Token( THEMECOMPLETE_EPO_MATH_Constants.FUNCTION, 'array' ) );
868							$this.allow_negative = true;
869							$this.tokens.push( THEMECOMPLETE_EPO_MATH_Token( THEMECOMPLETE_EPO_MATH_Constants.LEFTPARENTHESIS, '' ) );
870							break;
871						case ' ' === ch || '\n' === ch || '\r' === ch || '\t' === ch:
872							/**
873							 * In case those tokens must not be ingored use the following
874							 *
875							 * $this.empty_number_buffer_as_literal();
876							 * $this.empty_str_buffer_as_variable();
877							 * $this.tokens.push( THEMECOMPLETE_EPO_MATH_Token( THEMECOMPLETE_EPO_MATH_Constants.SPACE, '' ) );
878							 */
879							break;
880						case $this.is_number( ch ):
881							if ( '' !== $this.string_buffer ) {
882								$this.string_buffer += ch;
883								break;
884							}
885							$this.number_buffer += ch;
886							$this.allow_negative = false;
887							break;
888						case 'e' === ch.toLowerCase():
889							if ( $this.number_buffer.length && -1 !== $this.number_buffer.indexOf( '.' ) ) {
890								$this.number_buffer += 'e';
891								$this.allow_negative = false;
892								break;
893							}
894							/* falls through */
895						case $this.is_alpha( ch ):
896							if ( $this.number_buffer.length ) {
897								$this.empty_number_buffer_as_literal();
898								$this.tokens.push( THEMECOMPLETE_EPO_MATH_Token( THEMECOMPLETE_EPO_MATH_Constants.OPERATOR, '*' ) );
899							}
900							$this.allow_negative = false;
901							$this.string_buffer += ch;
902							break;
903						case '"' === ch:
904							$this.in_double_quoted_string = true;
905							break;
906						case "'" === ch:
907							$this.in_single_quoted_string = true;
908							break;
909						case $this.is_dot( ch ):
910							$this.number_buffer += ch;
911							$this.allow_negative = false;
912							break;
913						case $this.is_lp( ch ):
914							if ( '' !== $this.string_buffer ) {
915								$this.tokens.push( THEMECOMPLETE_EPO_MATH_Token( THEMECOMPLETE_EPO_MATH_Constants.FUNCTION, $this.string_buffer ) );
916								$this.string_buffer = '';
917							} else if ( $this.number_buffer.length ) {
918								$this.empty_number_buffer_as_literal();
919								$this.tokens.push( THEMECOMPLETE_EPO_MATH_Token( THEMECOMPLETE_EPO_MATH_Constants.OPERATOR, '*' ) );
920							}
921							$this.allow_negative = true;
922							$this.tokens.push( THEMECOMPLETE_EPO_MATH_Token( THEMECOMPLETE_EPO_MATH_Constants.LEFTPARENTHESIS, ch ) );
923							break;
924						case $this.is_rp( ch ) || ']' === ch :
925							$this.empty_number_buffer_as_literal();
926							$this.empty_str_buffer_as_variable();
927							$this.allow_negative = false;
928							$this.tokens.push( THEMECOMPLETE_EPO_MATH_Token( THEMECOMPLETE_EPO_MATH_Constants.RIGHTPARENTHESIS, ch ) );
929							break;
930						case $this.is_comma( ch ):
931							$this.empty_number_buffer_as_literal();
932							$this.empty_str_buffer_as_variable();
933							$this.allow_negative = true;
934							$this.tokens.push( THEMECOMPLETE_EPO_MATH_Token( THEMECOMPLETE_EPO_MATH_Constants.PARAMSEPARATOR, ch ) );
935							break;
936						default:
937							// special case for unary operations.
938							if ( '-' === ch || '+' === ch ) {
939								if ( $this.allow_negative ) {
940									$this.allow_negative = false;
941									$this.tokens.push( THEMECOMPLETE_EPO_MATH_Token( THEMECOMPLETE_EPO_MATH_Constants.OPERATOR, '-' === ch ? 'uNeg' : 'uPos' ) );
942									break;
943								}
944								// could be in exponent, in which case negative should be added to the number_buffer.
945								if ( $this.number_buffer && 'e' === $this.number_buffer[ $this.number_buffer.length - 1 ] ) {
946									$this.number_buffer += ch;
947									break;
948								}
949							}
950							$this.empty_number_buffer_as_literal();
951							$this.empty_str_buffer_as_variable();
952
953							if ( '$' !== ch ) {
954								if ( $this.tokens.length > 0 ) {
955									if ( THEMECOMPLETE_EPO_MATH_Constants.OPERATOR === $this.tokens[ $this.tokens.length - 1 ].type ) {
956										$this.tokens[ $this.tokens.length - 1 ].value += ch;
957									} else {
958										$this.tokens.push( THEMECOMPLETE_EPO_MATH_Token( THEMECOMPLETE_EPO_MATH_Constants.OPERATOR, ch ) );
959									}
960								} else {
961									$this.tokens.push( THEMECOMPLETE_EPO_MATH_Token( THEMECOMPLETE_EPO_MATH_Constants.OPERATOR, ch ) );
962								}
963							}
964							$this.allow_negative = true;
965					}
966				} );
967				this.empty_number_buffer_as_literal();
968				this.empty_str_buffer_as_variable();
969
970				this.tokens.forEach( function( $token, $key ) {
971					$token_test[ $key ] = $token.type;
972				} );
973				$token_test.forEach( function( $type, $key ) {
974					if ( $key > 0 && 'space' === $type && 'variable' === $token_test[ $key + 1 ] && 'variable' === $token_test[ $key - 1 ] ) {
975						$this.tokens[ $key ] = new THEMECOMPLETE_EPO_MATH_Token( THEMECOMPLETE_EPO_MATH_Constants.LITERAL, 0 );
976						$this.tokens.splice( $key + 1, 1 );
977						$this.tokens.splice( $key - 1, 1 );
978					}
979				} );
980				return this;
981			},
982			build_reverse_polish_notation: function() {
983				var $tokens = [];
984				var $stack = [];
985				var $param_counter = [];
986				var $ctoken;
987				var $f;
988				var $op1;
989				var $op2;
990				var $this = this;
991
992				try {
993					this.tokens.forEach( function( $token ) {
994						switch ( $token.type ) {
995							case THEMECOMPLETE_EPO_MATH_Constants.LITERAL:
996							case THEMECOMPLETE_EPO_MATH_Constants.VARIABLE:
997							case THEMECOMPLETE_EPO_MATH_Constants.STRING:
998								$tokens.push( $token );
999
1000								if ( $param_counter.length > 0 && 0 === $param_counter[ $param_counter.length - 1 ] ) {
1001									$param_counter.push( $param_counter.pop() + 1 );
1002								}
1003
1004								break;
1005
1006							case THEMECOMPLETE_EPO_MATH_Constants.FUNCTION:
1007								if ( $param_counter.length > 0 && 0 === $param_counter[ $param_counter.length - 1 ] ) {
1008									$param_counter.push( $param_counter.pop() + 1 );
1009								}
1010								$stack.push( $token );
1011								$param_counter.push( 0 );
1012
1013								break;
1014
1015							case THEMECOMPLETE_EPO_MATH_Constants.LEFTPARENTHESIS:
1016								$stack.push( $token );
1017
1018								break;
1019
1020							case THEMECOMPLETE_EPO_MATH_Constants.PARAMSEPARATOR:
1021								while ( THEMECOMPLETE_EPO_MATH_Constants.LEFTPARENTHESIS !== $stack[ $stack.length - 1 ].type ) {
1022									if ( 0 === $stack.length ) {
1023										return THEMECOMPLETE_EPO_MATH_Constants.trigger( 'Incorrect Brackets', 'IncorrectBracketsError', $tokens );
1024									}
1025									$tokens.push( $stack.pop() );
1026								}
1027								$param_counter.push( $param_counter.pop() + 1 );
1028
1029								break;
1030
1031							case THEMECOMPLETE_EPO_MATH_Constants.OPERATOR:
1032								if ( ! array_key_exists( $token.value, $this.operators ) ) {
1033									return THEMECOMPLETE_EPO_MATH_Error.trigger( $token.value, 'UnknownOperatorError', $tokens );
1034								}
1035								$op1 = $this.operators[ $token.value ];
1036
1037								while ( $stack.length > 0 && THEMECOMPLETE_EPO_MATH_Constants.OPERATOR === $stack[ $stack.length - 1 ].type ) {
1038									if ( ! array_key_exists( $stack[ $stack.length - 1 ].value, $this.operators ) ) {
1039										return THEMECOMPLETE_EPO_MATH_Error.trigger( $stack[ $stack.length - 1 ].value, 'UnknownOperatorError', $tokens );
1040									}
1041									$op2 = $this.operators[ $stack[ $stack.length - 1 ].value ];
1042
1043									if ( $op2.priority >= $op1.priority ) {
1044										$tokens.push( $stack.pop() );
1045
1046										continue;
1047									}
1048
1049									break;
1050								}
1051								$stack.push( $token );
1052
1053								break;
1054
1055							case THEMECOMPLETE_EPO_MATH_Constants.RIGHTPARENTHESIS:
1056								while ( true ) {
1057									try {
1058										$ctoken = $stack.pop();
1059
1060										if ( THEMECOMPLETE_EPO_MATH_Constants.LEFTPARENTHESIS === $ctoken.type ) {
1061											break;
1062										}
1063										$tokens.push( $ctoken );
1064									} catch ( $e ) {
1065										return THEMECOMPLETE_EPO_MATH_Constants.trigger( 'Incorrect Brackets', 'IncorrectBracketsError', $tokens );
1066									}
1067								}
1068
1069								if ( $stack.length > 0 && THEMECOMPLETE_EPO_MATH_Constants.FUNCTION === $stack[ $stack.length - 1 ].type ) {
1070									$f = $stack.pop();
1071									$f.param_count = $param_counter.pop();
1072									$tokens.push( $f );
1073								}
1074
1075								break;
1076
1077							case THEMECOMPLETE_EPO_MATH_Constants.SPACE:
1078								// do nothing.
1079						}
1080					} );
1081				} catch ( $e ) {
1082					$tokens = [];
1083					return THEMECOMPLETE_EPO_MATH_Error.trigger( $e, 'Error', $tokens );
1084				}
1085
1086				while ( 0 !== $stack.length ) {
1087					if ( THEMECOMPLETE_EPO_MATH_Constants.LEFTPARENTHESIS === $stack[ $stack.length - 1 ].type || THEMECOMPLETE_EPO_MATH_Constants.RIGHTPARENTHESIS === $stack[ $stack.length - 1 ].type ) {
1088						return THEMECOMPLETE_EPO_MATH_Error.trigger( 'Incorrect Brackets', 'IncorrectBracketsError', $tokens );
1089					}
1090
1091					if ( THEMECOMPLETE_EPO_MATH_Constants.SPACE === $stack[ $stack.length - 1 ].type ) {
1092						$stack.pop();
1093						continue;
1094					}
1095					$tokens.push( $stack.pop() );
1096				}
1097
1098				return $tokens;
1099			}
1100		};
1101		node.input = $input;
1102		node.operators = $operators;
1103		return node;
1104	};
1105
1106	var THEMECOMPLETE_EPO_MATH_Constants = {
1107		LITERAL: 'literal',
1108		VARIABLE: 'variable',
1109		OPERATOR: 'operator',
1110		LEFTPARENTHESIS: 'LP',
1111		RIGHTPARENTHESIS: 'RP',
1112		FUNCTION: 'function',
1113		PARAMSEPARATOR: 'separator',
1114		STRING: 'string',
1115		SPACE: 'space'
1116
1117	};
1118
1119	var THEMECOMPLETE_EPO_MATH_Token = function( $type, $value, $name ) {
1120		var node = {
1121			type: THEMECOMPLETE_EPO_MATH_Constants.LITERAL,
1122			value: undefined,
1123			name: undefined,
1124			param_count: null
1125		};
1126		node.type = $type;
1127		node.value = $value;
1128		node.name = $name;
1129		return node;
1130	};
1131
1132	var THEMECOMPLETE_EPO_MATH_Operator = function( $operator, $is_right_assoc, $priority, $function ) {
1133		var node = {
1134			operator: '',
1135			is_right_assoc: false,
1136			priority: 0,
1137			function: null,
1138			places: 0
1139		};
1140		node.operator = $operator;
1141		node.is_right_assoc = $is_right_assoc;
1142		node.priority = $priority;
1143		node.function = $function;
1144		node.places = getNumberOfParameters( $function );
1145
1146		node.execute = function( $stack ) {
1147			var $args = [];
1148			var $i;
1149			var $result;
1150
1151			if ( $stack.length < this.places ) {
1152				// Empty the $stack
1153				$stack.splice( 0, $stack.length );
1154				return THEMECOMPLETE_EPO_MATH_Error.trigger( 'Incorrect Expression', 'IncorrectExpressionError', new THEMECOMPLETE_EPO_MATH_Token( THEMECOMPLETE_EPO_MATH_Constants.LITERAL, 0 ) );
1155			}
1156
1157			for ( $i = 0; $i < this.places; $i++ ) {
1158				$args.unshift( $stack.pop().value );
1159			}
1160
1161			$result = this.function.apply( null, $args );
1162			if ( 'number' !== gettype( $result ) && 'string' !== gettype( $result ) ) {
1163				$result = 0;
1164			}
1165
1166			return new THEMECOMPLETE_EPO_MATH_Token( THEMECOMPLETE_EPO_MATH_Constants.LITERAL, $result );
1167		};
1168
1169		return node;
1170	};
1171
1172	var THEMECOMPLETE_EPO_MATH_CustomFunction = function( $name, $function ) {
1173		var node = {
1174			name: '',
1175			function: undefined,
1176			required_param_count: undefined
1177		};
1178
1179		node.name = $name;
1180		node.function = $function;
1181		node.required_param_count = getNumberOfRequiredParameters( $function );
1182
1183		node.execute = function( $stack, $param_count_in_stack ) {
1184			var $args = [];
1185			var $i;
1186			var $argument;
1187			var $result;
1188			if ( $param_count_in_stack < this.required_param_count ) {
1189				$param_count_in_stack = this.required_param_count;
1190			}
1191			// We skip this section.
1192			if ( $param_count_in_stack < this.required_param_count ) {
1193				// Empty the $stack
1194				$stack.splice( 0, $stack.length );
1195				return THEMECOMPLETE_EPO_MATH_Error.trigger( this.name, 'IncorrectNumberOfFunctionParametersError', new THEMECOMPLETE_EPO_MATH_Token( THEMECOMPLETE_EPO_MATH_Constants.LITERAL, 0 ) );
1196			}
1197
1198			if ( $param_count_in_stack > 0 ) {
1199				for ( $i = 0; $i < $param_count_in_stack; $i++ ) {
1200					$argument = $stack.length ? $stack.pop().value : 0;
1201					if ( null === $argument ) {
1202						$argument = '0';
1203						$args.push( $argument );
1204					} else {
1205						$args.unshift( $argument );
1206					}
1207				}
1208			}
1209
1210			$result = this.function.apply( null, $args );
1211
1212			if ( $result === Infinity || $result === -Infinity ) {
1213				$result = 0;
1214			}
1215
1216			return THEMECOMPLETE_EPO_MATH_Token( THEMECOMPLETE_EPO_MATH_Constants.LITERAL, $result );
1217		};
1218
1219		return node;
1220	};
1221
1222	var THEMECOMPLETE_EPO_MATH_Calculator = function( $functions, $operators ) {
1223		var node = {
1224			functions: {},
1225			operators: {}
1226		};
1227		node.functions = $functions;
1228		node.operators = $operators;
1229
1230		node.calculate = function( $tokens, $variables, $on_var_not_found = null, $math_object = false ) {
1231			var $this = this;
1232			/** Array of THEMECOMPLETE_EPO_MATH_Token */
1233			var $stack = [];
1234			var $result;
1235
1236			if ( empty( $tokens ) ) {
1237				return 0;
1238			}
1239			try {
1240				$tokens.forEach( function( $token ) {
1241					var $variable;
1242					var $value;
1243					if ( THEMECOMPLETE_EPO_MATH_Constants.LITERAL === $token.type || THEMECOMPLETE_EPO_MATH_Constants.STRING === $token.type ) {
1244						$stack.push( $token );
1245					} else if ( THEMECOMPLETE_EPO_MATH_Constants.VARIABLE === $token.type ) {
1246						$variable = $token.value;
1247
1248						$value = null;
1249
1250						if ( array_key_exists( $variable, $variables ) ) {
1251							$value = $variables[ $variable ];
1252						} else if ( $on_var_not_found && 'function' === typeof $on_var_not_found ) {
1253							$value = $on_var_not_found( $variable );
1254						} else {
1255							$value = $variable;
1256							$math_object.variables[ $variable ] = $value;
1257							$variables[ $variable ] = $value;
1258						}
1259						$stack.push( THEMECOMPLETE_EPO_MATH_Token( THEMECOMPLETE_EPO_MATH_Constants.LITERAL, $value, $variable ) );
1260					} else if ( THEMECOMPLETE_EPO_MATH_Constants.FUNCTION === $token.type ) {
1261						if ( ! array_key_exists( $token.value, $this.functions ) ) {
1262							$math_object.add_function(
1263								$token.value,
1264								function() {
1265									return 0;
1266								}
1267							);
1268							$this.functions = $math_object.functions;
1269							if ( ! array_key_exists( $token.value, $this.functions ) ) {
1270								return THEMECOMPLETE_EPO_MATH_Error.trigger( $token.value, 'UnknownFunctionError', 0 );
1271							}
1272							THEMECOMPLETE_EPO_MATH_Error.trigger( $token.value, 'UnknownFunctionError', 0 );
1273						}
1274						$stack.push( $this.functions[ $token.value ].execute( $stack, $token.param_count ) );
1275					} else if ( THEMECOMPLETE_EPO_MATH_Constants.OPERATOR === $token.type ) {
1276						if ( ! array_key_exists( $token.value, $this.operators ) ) {
1277							return THEMECOMPLETE_EPO_MATH_Error.trigger( $token.value, 'UnknownOperatorError', 0 );
1278						}
1279						$stack.push( $this.operators[ $token.value ].execute( $stack ) );
1280					}
1281				} );
1282			} catch ( $e ) {
1283				if ( window.TMEPOJS && window.TMEPOJS.WP_DEBUG ) {
1284					window.console.log( $e );
1285				}
1286			}
1287			$result = $stack.pop();
1288
1289			if ( null === $result || ! empty( $stack ) ) {
1290				return THEMECOMPLETE_EPO_MATH_Error.trigger( 'Stack must be empty', 'IncorrectExpressionError', 0 );
1291			}
1292
1293			if ( false === $result.value ) {
1294				$result.value = 0;
1295			}
1296
1297			if ( true === $result.value ) {
1298				$result.value = 1;
1299			}
1300
1301			if ( 'string' === gettype( $result.value ) && $result.value.isNumeric() ) {
1302				$result.value = floatval( $result.value );
1303			}
1304
1305			return $result.value;
1306		};
1307		return node;
1308	};
1309
1310	var THEMECOMPLETE_EPO_MATH_Error = {
1311		trigger: function( $msg, $code = '', $return = false ) {
1312			if ( window.TMEPOJS && window.TMEPOJS.WP_DEBUG ) {
1313				window.console.log( $code + '\n' + $msg );
1314				window.console.trace();
1315			}
1316			return $return;
1317		}
1318	};
1319
1320	window.tcmexp = THEMECOMPLETE_EPO_MATH.construct();
1321}( window ) );

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.