Automatic calculation in text box

Asked

Viewed 2,648 times

11

Good morning. Is there any way when the user type this in a text box:

inserir a descrição da imagem aqui

A script runs the account automatically and results, in this case=1 ? It is also important that it does this with all operations and that it is in pure javascript.

Thank you.

3 answers

11


Yes this is possible. The easiest way is by using the eval();.

HTML

<input type="text" id="calculator" />
<div id="result"></div>

javascript

var input = document.getElementById('calculator');
var result = document.getElementById('result');
input.addEventListener('keyup', calcular);
function calcular(){
    var conta = eval(this.value);
    result.innerHTML = conta;
}

Example: http://jsfiddle.net/4djdy/1

The example above grabs an event receiver keyup and runs a function each time a key is released (keyup). This function runs the eval() that in the background runs this string as code.

There are other safer and more laborious ways, this implies regex to detect operators like division, multiplication, etc. But I think this example answers the question.


Without eval():

I have to leave a parentesis: Eval() is one of the most powerful tools of Javascript and may be very useful, but in some cases raises security problems.
(More on that in this answer)

If you want to do the same without Eval, the code is much more extensive. Out of curiosity I made by hand a code to solve this. You may be able to save a few lines but it won’t be much smaller without using Eval(). However, this example (http://jsfiddle.net/n34PT/) is Eval-free:

var input = document.getElementById('calculator');
input.addEventListener('keyup', calcular);

function calcular(e) {
    calculadora(e.target.value);
}
var conta = 0;
var operadores = ['*', '/', '+', '-', ];
var operacoes = [

function (a, b) {
    return a * b;
},

function (a, b) {
    return a / b;
},

function (a, b) {
    return a + b;
},

function (a, b) {
    return a - b;
}];
var stop = 0;

function resolverParentesis(eq) {
    return eq.replace(/\(.*\)/, function (match) {
        return calculadora(match.substring(1, match.length - 1));
    });
}

function calculadora(pedido) {
    if (pedido.match(/[*\/+\-]$/)) return;
    var pedido = pedido.replace(/\s/g, '');
    pedido = resolverParentesis(pedido);
    if (!/[*\/+\-]/.test(pedido)) return resultado(pedido);
    var regex = /[*\/]/.test(pedido) ? new RegExp("([^\/*+\-]*[*\/][^\/*+\-]*)") : new RegExp("([^\/*+\-]*[+\-][^\/*+\-]*)");
    pedido = processar(pedido, regex);
    if (/[*\/+\-]/.test(pedido)) return calculadora(pedido);
    return resultado(pedido);
}

function processar(input, regex) {
    return input.replace(regex, function (str) {
        var op = str.match(/([*\/+\-])/)[0];
        var pedacos = str.split(op);
        var fn = operacoes[operadores.indexOf(op)];
        return fn(pedacos[0] * 1, pedacos[1] * 1);
    });
}

function resultado(conta){
    var result = document.getElementById('result');
    result.innerHTML = conta
}

4

The answer from Sérgio using Eval is a simple solution but it has some problems:

  • Security: Eval will execute any Javascript code, not just arithmetic expressions. You have to take care that only values written by the user themselves are evaluated, to avoid vulnerabilities of Cross Site Scripting (XSS).

  • Eval is a black box: it either returns the result of the account or nothing. In particular:

    • You have no control over how error messages are generated.
    • You have no control over how accounts are done and cannot define your own operators.

If these limitations are important, an alternative is to do the math yourself. Build a parser that converts the text into a syntax tree and evaluate that tree. It’s a little too long to describe in an OS post, but you’ll find how to do that in several algorithmic books and over the internet (I’d recommend a top-down parser - it’s easier to program at hand and error messages are simpler)

http://www.codeproject.com/Articles/318667/Mathematical-Expression-Parser-Using-Recursive-Des

  • About the syntax tree, this other issue here from SOPT has some information that may be useful. It does not use the same language, but the question and answer reading may provide some intuitions important about the workaround @hugomg suggested. :)

  • Hugo, the Eval can be very useful as in the case of this question. But to complete the my answer I put together a version without.

  • 1

    In case you create a parser as suggested here in this answer, it is worth a look at the following tools: jison, esprima and Peg.

0

Based on Sergio’s response, created a simpler example without using eval().

var input = document.getElementById('calculator');
var result = document.getElementById('result');
input.addEventListener('keyup', calcular);
function calcular(){
    //var conta = eval(this.value);
    var conta = new Function("return " + this.value);
    var resultado = conta();
    
    result.innerHTML = resultado;
}
<input type="text" id="calculator" />
<div id="result"></div>

In this case a Function is created based on the sent string. Note that some errors will appear on the console in a few moments, because the return type "1+1+", for example, is not valid.

In this case, you could solve with a simple validation before creating the function. This would solve the problem of "black box" quoted by hugomg in his reply. But we’d still have the XSS problem.

This answer is only intended to add knowledge of the various possible possibilities of solving your problem in a simple way.

Here you can find many other examples.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.