1

Im trying to make a formula dynamic and also the input fields. First problem is to change the (c1 + d2) into values like (1 + 2) depending on what is the value in input. consider that tdinput is dynamic so I can add as many as I can and formula can change anytime.

<input class="tdinput" type="text" data-key="c1">
<input class="tdinput" type="text" data-key="d2">

<input type="text" data-formula="(c1 + d2)">

<script>
    $('.tdinput').on('change', function() { 
        var key = $(this).attr('data-key');
        $('[data-formula*="+key+"]').each(function() { 
            //now here goes to change the data-formula by inputted values
            //calculate using eval()
        });
    });

</script>
el solo lobo
  • 973
  • 11
  • 23
Joshua Belarmino
  • 546
  • 9
  • 24

2 Answers2

2

You need to make a more modular approach with this. And make good use of the javascript jquery api you're using.

When a variable is defined by data-something-something you can access it by jQuerySelectedElement.data('something-something')

Now, eval is evil, but when you sanitise your input variables(in this case by parseInt) you should be relatively save from xss inputs etc..

What happens is, all the variables are inserted as an property in an object t. then eval will call and and access all the objects in t and do the calculation.

Only requirement is that you define all the variables not as just c2, but as t.c2 in your key definition properties.

have a look below at the play with the data properties and the eval.

When using eval ALWAYS make sure you only eval 'safe' data! Don't eval strings if you plan to safe user input! you open your site for XSS attacks then.

$('[data-formula]').on('keyup', function() { 
        var $this = $(this);
        var formulaName = $this.data('formula');
        var $output = $('[data-formula-name="'+formulaName+'"]');
        var formula = $output.data('formula-calc');
        
        var t = {};
        var keys = [];
        $select = $('[data-formula="'+formulaName+'"]');
        $select.each(function(index,elem) {
             var $elem = $(elem);
             var key = $elem.data('key');
             t[key] = parseFloat($elem.val());
             keys.push(key);
             if(isNaN(t[key])) {
                t[key]=0;
             }
        });
        for(var c=0;c<keys.length;c++) {
            formula = formula.replace(new RegExp(keys[c],'g'),'t.'+keys[c]);
        }
        var result = 0;
        eval('result = '+formula)
        $output.val(result)
        
    });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
sum:
<input class="tdinput" type="text" data-formula="sum" data-key="c1">
<input class="tdinput" type="text" data-formula="sum" data-key="d2">
<input type="text" data-formula-name="sum" data-formula-calc="(c1 + d2)" disabled>
<BR/>
xor
<input class="tdinput" type="text" data-formula="pow" data-key="c1">
<input class="tdinput" type="text" data-formula="pow" data-key="d2">
<input type="text" data-formula-name="pow" data-formula-calc="(c1 ^ d2)" disabled>
<BR/>
sub
<input class="tdinput" type="text" data-formula="sub" data-key="c1">
<input class="tdinput" type="text" data-formula="sub" data-key="d2">
<input type="text" data-formula-name="sub" data-formula-calc="(c1 - d2)" disabled>
<BR/>
silly
<input class="tdinput" type="text" data-formula="silly" data-key="c1">
<input class="tdinput" type="text" data-formula="silly" data-key="d2">
<input type="text" data-formula-name="silly" data-formula-calc="(c1 / d2 * 3.14567891546)" disabled>
Tschallacka
  • 27,901
  • 14
  • 88
  • 133
  • 1
    thank you for letting me understanding the concept of eval. i just notice that it cuts the processing of eval when you put non numeric values. – Joshua Belarmino Aug 23 '16 at 08:35
  • you don't want to input non numeric values. that will open you up to xss attacks, well, the ability to input non numeric values, that will be shared with others possibly, opens your site to xss attacks. I just added a isnan filter that only allows numeric input – Tschallacka Aug 23 '16 at 08:36
  • Also made keys fluid ;-) no more need for adding t. manually before it :-) – Tschallacka Aug 23 '16 at 08:48
1

You can use eval().

Logic

  • Fetch formula and save it in string
  • Get all valid keys
  • Replace keys with value in formula
  • Use eval() to process it

Sample

JSFiddle

$("#btnCalculate").on("click", function() {
   var $f = $("input[data-formula]");
   var formula = $f.data("formula");
   formula.split(/[^a-z0-9]/gi)
      .forEach(function(el) {
         if (el) {
            let v = $("[data-key='" + el + "']").val();
            formula = formula.replace(el, v);
         }
      });

   var result = eval(formula);
   console.log(result)
   $f.val(result)
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<input class="tdinput" type="text" data-key="c1">
<input class="tdinput" type="text" data-key="d2">
<br/>
<input type="text" data-formula="(c1 + d2)">
<button id="btnCalculate">calculate</button>

Reference

Community
  • 1
  • 1
Rajesh
  • 24,354
  • 5
  • 48
  • 79