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.