1

I'm fairly new to JavaScript and its functionalities. I am currently trying to make a basic calculator to try out some skills, and have encountered a problem. When i try to put in a double digit number, it add the 2 numbers together, Ex: I put in 12 + 5, and the answer i get is 8. It add the double digit together and cannot figure out how to fix it. Thanks, and I am open to any suggestions :) PS: Sorry its a lot `

            </div>
                    <button type="button" onclick="putToScreen(1); xValue += parseInt(1)" class="inputButton1 input" value="1">1</button>
                    <button type="button" onclick="putToScreen(2); xValue += parseInt(2)" class="inputButton1 input" value="2">2</button>
                    <button type="button" onclick="putToScreen(3); xValue += parseInt(3)" class="inputButton1 input" value="3">3</button>
                    <button type="button" onclick="putToScreen('+'); plusButton++" class="inputButton1" value="+">+</button>
                    <button type="button" onclick="putToScreen(4); xValue += parseInt(4)" class="inputButton2 input" value="4">4</button>
                    <button type="button" onclick="putToScreen(5); xValue += parseInt(5)" class="inputButton2 input" value="5">5</button>
                    <button type="button" onclick="putToScreen(6); xValue += parseInt(6)" class="inputButton2 input" value="6">6</button>
                    <button type="button" onclick="putToScreen('-')" class="inputButton2" value="-">-</button>
                    <button type="button" onclick="putToScreen(7); xValue += parseInt(7)" class="inputButton3 input" value="7">7</button>
                    <button type="button" onclick="putToScreen(8); xValue += parseInt(8)" class="inputButton3 input" value="8">8</button>
                    <button type="button" onclick="putToScreen(9); xValue += parseInt(9)" class="inputButton3 input" value="9">9</button>
                    <button type="button" onclick="putToScreen('*')" class="inputButton3" value="*">*</button>
                    <button type="button" onclick="clearScreen()" class="inputButton" value="C">C</button>
                    <button type="button" onclick="putToScreen(0); xValue += parseInt(0)" class="inputButton4 input" value="0">0</button>
                    <button type="button" class="inputButton4" onclick="compute()" value="=">=</button>
                    <button type="button" onclick="putToScreen('/')" class="inputButton4" value="/">/</button>
        </div>
    </div>
    <script type="text/javascript">
        var input = document.getElementsByClassName("inputButton");
        //var valueBox = document.getElementById("answer");
        var answer = document.getElementById("answer");

        // var xValue = do i +=
        var xValue = 0;
        var yValue = 0;
        var plusButton = 0;
        //var finalAnswer

        function putToScreen (x) {
            var node = document.createTextNode(x);
            answer.appendChild(node);
        }

        function clearScreen() {
            answer.innerHTML = "";
            xValue = 0;
            yValue = 0;
            plusButton = 0;
        }

        function add () {
            if (plusButton >= 1) {
                document.getElementsByClassName("input").onclick = "yValue +=";
            }
            var sum = parseInt(xValue) + parseInt(yValue);
            answer.innerHTML = sum;
        }

        //var sum = parseInt(xValue) + parseInt(yValue);

        function compute () {
            if(plusButton >= 1) {
                add();
            }
        }

`

Ryan
  • 727
  • 2
  • 14
  • 31

3 Answers3

1

Update

@Ryan called me to task for recommending eval – for good reason. I don't agree that eval is always evil, and I do think it's appropriate to use in this situation, because input is limited to button presses. But I should have pointed out that eval should always be used with caution.

See Calculate string value in javascript, not using eval to see other arguments in favor of using eval for this type of problem.

But a wonderful alternative was presented by @yckart, so here's my new recommendation.

Change the compute function to this:

function compute () {
  answer.innerHTML = new Function('return ' + answer.innerHTML)();
}

You can then remove all the logic that does the calculations. (Otherwise, you'd need to write a recursive descent parser, which is a major task.)

To answer your question, "Does it work with things like square roots and squares?": eval and the Function method will work with any valid JavaScript expression:

  1. Math.sqrt(number) returns the square root of a number.
  2. Math.pow(number, 2) squares a number.

Snippet

function putToScreen (x) {
  var node = document.createTextNode(x);
  answer.appendChild(node);
}

function clearScreen() {
  answer.innerHTML = '';
}

function compute () {
  answer.innerHTML = new Function('return ' + answer.innerHTML)();
}
button {
  width: 2em;
}
<div id="answer"></div>
<hr>
<button onclick="putToScreen(this.innerText)" >1</button>
<button onclick="putToScreen(this.innerText)" >2</button>
<button onclick="putToScreen(this.innerText)" >3</button>
<button onclick="putToScreen(this.innerText)" >+</button><br>
<button onclick="putToScreen(this.innerText)" >4</button>
<button onclick="putToScreen(this.innerText)" >5</button>
<button onclick="putToScreen(this.innerText)" >6</button>
<button onclick="putToScreen(this.innerText)" >-</button><br>
<button onclick="putToScreen(this.innerText)" >7</button>
<button onclick="putToScreen(this.innerText)" >8</button>
<button onclick="putToScreen(this.innerText)" >9</button>
<button onclick="putToScreen(this.innerText)" >*</button><br>
<button onclick="clearScreen(this.innerText)" >C</button>
<button onclick="putToScreen(this.innerText)" >0</button>
<button onclick="compute()"                   >=</button>
<button onclick="putToScreen(this.innerText)" >/</button>
Community
  • 1
  • 1
Rick Hitchcock
  • 35,202
  • 5
  • 48
  • 79
  • Now don't get the rookie dependent on `eval`. It loads a completely separate parser instance, it's inefficient, and it's bad practice. You do him a disservice by not helping him learn the right way. – rojo Nov 19 '14 at 00:09
  • Thanks a lot, I had been trying to fix this for a long time – Ryan Nov 19 '14 at 00:09
  • Ha, @rojo, I considered that, but this seems like a decent use for `eval`. – Rick Hitchcock Nov 19 '14 at 00:11
  • @Ryan [Please read this](http://xkr.us/js/eval). I'll help you find a better solution when I get to a computer if no one else has by then. If teaching yourself JavaScript is indeed your goal, don't settle for `eval` as a solution. @RickHitchcock I don't mean to torpedo your answer. It was a clever solution, just not a healthy one for a rookie. – rojo Nov 19 '14 at 00:19
  • Ryan, @rojo makes a good point that `eval` should be avoided when possible. The difficulty in writing an expression parser, combined with the fact that the code being evaluated is not coming from the outside, makes me feel that `eval` is safe in this situation. There are different views on this, and you'll see some of them at http://stackoverflow.com/questions/197769/when-is-javascripts-eval-not-evil/198031#198031. – Rick Hitchcock Nov 19 '14 at 00:23
  • One other thing, as I'm editing this. Won't this won't work, when I go to try to add functions for -, / , * , etc? – Ryan Nov 19 '14 at 00:45
  • `eval` handles all the calculations, so you don't need to add the functions. If I find time, I may post an expression parser. If @Ryan beats me to it, he deserves the credit. – Rick Hitchcock Nov 19 '14 at 00:51
  • does it work with things like square roots and squares? – Ryan Nov 19 '14 at 01:14
  • 1
    @RickHitchcock @Ryan I started writing a calculator and got a little carried away. [See this fiddle](http://jsfiddle.net/calraith/n5amL6t0/). I used a `switch` statement to handle the operations. It's pretty if I do say so myself. Ryan, it's so different from your code that I'm hesitant to post it as an answer. But if you look at my code you might find some ideas to use in your own. – rojo Nov 19 '14 at 03:59
  • 1
    @rojo, that's beautiful. Calculating interim results like that makes it unnecessary to take operator precedence into account. I wrote a parser for this problem, but I think it's a bit much to post here. However, I've found a good alternative to `eval`, and I've updated my answer. – Rick Hitchcock Nov 19 '14 at 19:26
  • 1
    @RickHitchcock Thanks man. I initially did `new Function` the way you did, but it still loads an additional compiler similar to `eval`. I eventually decided just to bite the bullet and make a `switch` statement. – rojo Nov 19 '14 at 19:46
  • 1
    @RickHitchcock @rojo Thanks for all your help guys. I actually managed to find a way to get passed the problem above, and wothout using `eval()`. It was actually a pretty simple solution. All I needed to do was create a global variable, that i later called with function add(). I stored the original xValue in the global variable and then reset xValue back to zero, then just added the xValue and the other global variable together. The entire problem, was with the yValue, because it wasn't exactly being called/used correctly. But still, thanks for all your help – Ryan Nov 20 '14 at 17:12
0

The reason is that by each button that you press you increase xvalue and yvalue by the corresponding digit that belongs to the button, respectively. So if you for example type in 12, you increase xvalue first by 1 and then by 2.

Note

xValue+=n

increases xvalue by n. You can equivalently write it like this

xValue=xValue+ n

which light be more familiar.

damare
  • 201
  • 1
  • 5
  • I understand what you're saying, but I'm still a little confused on how I would go about to fix the problem. Thanks again – Ryan Nov 18 '14 at 23:35
0

You should handle the user input as a string until +, -, * or / is pressed. That means you dont add the digit as a number to xValue but as a string. For example for pressing 1 you use

xValue+= "1"

If you then type in 12, you get

xValue = "12"

If the user now presses one of the other buttons, you know that this number is completed and you can convert it into a number using parseInt().

damare
  • 201
  • 1
  • 5
  • I just tried that and it didn't work. for each number I did onclick="putToScreen(1); xValue += '1'", then changed the JavaScript to ' function add () { xValue = parseInt(xValue); if (plusButton >= 1) { document.getElementsByClassName("input").onclick = "yValue +="; } var sum = parseInt(xValue) + parseInt(yValue); answer.innerHTML = sum; }' Sorry, I bet the solution is really obvious – Ryan Nov 18 '14 at 23:55