1

I am using the following code to implement a calculator on my website:

function addChar(input, character) {
  if (input.value == null || input.value == "0")
    input.value = character
  else
    input.value += character
}

function cos(form) {
  form.display.value = Math.cos(form.display.value);
}

function sin(form) {
  form.display.value = Math.sin(form.display.value);
}

function tan(form) {
  form.display.value = Math.tan(form.display.value);
}

function sqrt(form) {
  form.display.value = Math.sqrt(form.display.value);
}

function ln(form) {
  form.display.value = Math.log(form.display.value);
}

function exp(form) {
  form.display.value = Math.exp(form.display.value);
}

function deleteChar(input) {
  input.value = input.value.substring(0, input.value.length - 1)
}

function changeSign(input) {
  if (input.value.substring(0, 1) == "-")
    input.value = input.value.substring(1, input.value.length)
  else
    input.value = "-" + input.value
}

function compute(form) {
  form.display.value = eval(form.display.value)
}

function square(form) {
  form.display.value = eval(form.display.value) * eval(form.display.value)
}

function checkNum(str) {
  for (var i = 0; i < str.length; i++) {
    var ch = str.substring(i, i + 1)
    if (ch < "0" || ch > "9") {
      if (ch != "/" && ch != "*" && ch != "+" && ch != "-" && ch != "." && ch != "(" && ch != ")") {
        alert("invalid entry!")
        return false
      }
    }
  }
  return true
}
<FORM NAME="sci-calc">
  <TABLE CELLSPACING="0" CELLPADDING="1">
    <TR>
      <TD COLSPAN="5" ALIGN="center">
        <INPUT NAME="display" VALUE="0" SIZE="28" MAXLENGTH="25">
      </TD>
    </TR>
    <TR>
      <TD ALIGN="center">
        <INPUT TYPE="button" VALUE=" exp " ONCLICK="if (checkNum(this.form.display.value)) { exp(this.form) }">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" VALUE="  7  " ONCLICK="addChar(this.form.display, '7')">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" VALUE="  8  " ONCLICK="addChar(this.form.display, '8')">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" VALUE="  9  " ONCLICK="addChar(this.form.display, '9')">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" VALUE="   /   " ONCLICK="addChar(this.form.display, '/')">
      </TD>
    </TR>
    <TR>
      <TD ALIGN="center">
        <INPUT TYPE="button" VALUE="   ln   " ONCLICK="if (checkNum(this.form.display.value)) { ln(this.form) }">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" VALUE="  4  " ONCLICK="addChar(this.form.display, '4')">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" VALUE="  5  " ONCLICK="addChar(this.form.display, '5')">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" VALUE="  6  " ONCLICK="addChar(this.form.display, '6')">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" VALUE="   *   " ONCLICK="addChar(this.form.display, '*')">
      </TD>
    </TR>
    <TR>
      <TD ALIGN="center">
        <INPUT TYPE="button" VALUE=" sqrt " ONCLICK="if (checkNum(this.form.display.value)) { sqrt(this.form) }">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" VALUE="  1  " ONCLICK="addChar(this.form.display, '1')">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" VALUE="  2  " ONCLICK="addChar(this.form.display, '2')">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" VALUE="  3  " ONCLICK="addChar(this.form.display, '3')">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" VALUE="   -   " ONCLICK="addChar(this.form.display, '-')">
      </TD>
    </TR>
    <TR>
      <TD ALIGN="center">
        <INPUT TYPE="button" VALUE="  sq  " ONCLICK="if (checkNum(this.form.display.value)) { square(this.form) }">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" VALUE="  0  " ONCLICK="addChar(this.form.display, '0')">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" VALUE="   .  " ONCLICK="addChar(this.form.display, '.')">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" VALUE=" +/- " ONCLICK="changeSign(this.form.display)">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" VALUE="   +  " ONCLICK="addChar(this.form.display, '+')">
      </TD>
    </TR>
    <TR>
      <TD ALIGN="center">
        <INPUT TYPE="button" VALUE="    (    " ONCLICK="addChar(this.form.display, '(')">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" VALUE="cos" ONCLICK="if (checkNum(this.form.display.value)) { cos(this.form) }">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" VALUE=" sin" ONCLICK="if (checkNum(this.form.display.value)) { sin(this.form) }">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" VALUE=" tan" ONCLICK="if (checkNum(this.form.display.value)) { tan(this.form) }">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" VALUE="   )   " ONCLICK="addChar(this.form.display, ')')">
      </TD>
    </TR>
    <TR>
      <TD ALIGN="center">
        <INPUT TYPE="button" VALUE="clear" ONCLICK="this.form.display.value = 0 ">
      </TD>
      <TD ALIGN="center" COLSPAN="3">
        <INPUT TYPE="button" VALUE="backspace" ONCLICK="deleteChar(this.form.display)">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" VALUE="enter" NAME="enter" ONCLICK="if (checkNum(this.form.display.value)) { compute(this.form) }">
      </TD>
    </TR>
  </TABLE>
</FORM>

I am wondering if it's possible to change these inputs such that they do not contain inline JavaScript (my understanding is that .click is favored over onClick event handlers)? I am not sure how to do so within the framework of a form. If it is possible in this case, how might that look?

Mosh Feu
  • 28,354
  • 16
  • 88
  • 135
newbie2015
  • 251
  • 3
  • 17
  • "within the framework of a form" — doesn't really make any difference – Quentin Dec 29 '15 at 12:54
  • https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener – Quentin Dec 29 '15 at 12:54
  • What I would suggest is using the `value` attributes of each button from javascript. Instead of specifying what needs to be appended to the display for each button separately, simply register click events on any of them and append whatever is the clicked button's `value` – Sinstein Dec 29 '15 at 13:03
  • Created a JSFiddle solution with unobtrusive JS - https://jsfiddle.net/fixit/2nrpt0dr/ – Yonatan Ayalon Dec 29 '15 at 14:13
  • I went with the jQuery solution proposed below and added a few things (see: https://jsfiddle.net/Lh2x7vja/48/ ). But there's still a few kinks... the deleteChar function doesn't stop when there's only one number remaining in the display. How can I get it to do so? – newbie2015 Dec 31 '15 at 04:24

4 Answers4

3

.click isn't actually part of JavaScript itself. It's part of a JavaScript library called jQuery

If you use jQuery, this is what your code should look like:

function addChar(input, character) {
  if (input.value == null || input.value == "0")
    input.value = character
  else
    input.value += character
}

function cos(form) {
  form.display.value = Math.cos(form.display.value);
}

function sin(form) {
  form.display.value = Math.sin(form.display.value);
}

function tan(form) {
  form.display.value = Math.tan(form.display.value);
}

function sqrt(form) {
  form.display.value = Math.sqrt(form.display.value);
}

function ln(form) {
  form.display.value = Math.log(form.display.value);
}

function exp(form) {
  form.display.value = Math.exp(form.display.value);
}

function deleteChar(input) {
  input.value = input.value.substring(0, input.value.length - 1)
}

function changeSign(input) {
  if (input.value.substring(0, 1) == "-")
    input.value = input.value.substring(1, input.value.length)
  else
    input.value = "-" + input.value
}

function compute(form) {
  form.display.value = eval(form.display.value)
}

function square(form) {
  form.display.value = eval(form.display.value) * eval(form.display.value)
}

function checkNum(str) {
  for (var i = 0; i < str.length; i++) {
    var ch = str.substring(i, i + 1)
    if (ch < "0" || ch > "9") {
      if (ch != "/" && ch != "*" && ch != "+" && ch != "-" && ch != "." && ch != "(" && ch != ")") {
        alert("invalid entry!")
        return false
      }
    }
  }
  return true
}

$('#button-exp').click(function() {
  if (checkNum(this.form.display.value)) {
    exp(this.form)
  }
});

$('#button-divide').click(function() {
  addChar(this.form.display, '/')
});

$('#button-ln').click(function() {
  if (checkNum(this.form.display.value)) {
    ln(this.form)
  }
});

$('#button-sqrt').click(function() {
  if (checkNum(this.form.display.value)) {
    sqrt(this.form)
  }
});

$('#button-minus').click(function() {
  addChar(this.form.display, '-')
});

$('#button-multiply').click(function() {
  addChar(this.form.display, '*')
});

$('#button-square').click(function() {
  if (checkNum(this.form.display.value)) {
    square(this.form)
  }
});

$('#button-dot').click(function() {
  addChar(this.form.display, '.')
});

$('#button-plus').click(function() {
  addChar(this.form.display, '+')
});

$('#button-pos').click(function() {
  changeSign(this.form.display)
});

$('#button-cos').click(function() {
  if (checkNum(this.form.display.value)) {
    cos(this.form)
  }
});

$('#button-sin').click(function() {
  if (checkNum(this.form.display.value)) {
    sin(this.form)
  }
});

$('#button-tan').click(function() {
  if (checkNum(this.form.display.value)) {
    tan(this.form)
  }
});

$('#button-cb').click(function() {
  addChar(this.form.display, ')')
});


$('#button-clear').click(function() {
  this.form.display.value = 0
});


$('#button-bsp').click(function() {
  deleteChar(this.form.display)
});

$('#button-enter').click(function() {
  if (checkNum(this.form.display.value)) {
    compute(this.form)
  }
});

$.each([1, 2, 3, 4, 5, 6, 7, 8, 9, 0], function(i, e) {
  $('#button-' + e).click(function() {
    addChar(this.form.display, e);
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<FORM NAME="sci-calc">
  <TABLE CELLSPACING="0" CELLPADDING="1">
    <TR>
      <TD COLSPAN="5" ALIGN="center">
        <INPUT NAME="display" VALUE="0" SIZE="28" MAXLENGTH="25">
      </TD>
    </TR>
    <TR>
      <TD ALIGN="center">
        <INPUT TYPE="button" ID='button-exp' VALUE=" exp ">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" ID="button-7" VALUE="  7  ">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" ID="button-8" VALUE="  8  ">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" ID="button-9" VALUE="  9  ">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" ID="button-divide" VALUE="   /   ">
      </TD>
    </TR>
    <TR>
      <TD ALIGN="center">
        <INPUT TYPE="button" ID="button-ln" VALUE="   ln   ">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" ID="button-4" VALUE="  4  ">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" ID="button-5" VALUE="  5  ">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" ID="button-6" VALUE="  6  ">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" ID="button-multiply" VALUE="   *   ">
      </TD>
    </TR>
    <TR>
      <TD ALIGN="center">
        <INPUT TYPE="button" ID="button-sqrt" VALUE=" sqrt ">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" ID="button-1" VALUE="  1  ">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" ID="button-2" VALUE="  2  ">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" ID="button-3" VALUE="  3  ">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" ID="button-minus" VALUE="   -   ">
      </TD>
    </TR>
    <TR>
      <TD ALIGN="center">
        <INPUT TYPE="button" ID="button-square" VALUE="  sq  ">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" ID="button-0" VALUE="  0  ">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" ID="button-dot" VALUE="   .  ">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" ID="button-pos" VALUE=" +/- ">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" ID="button-plus" VALUE="   +  ">
      </TD>
    </TR>
    <TR>
      <TD ALIGN="center">
        <INPUT TYPE="button" ID="button-ob" VALUE="    (    " ONCLICK="addChar(this.form.display, '(')">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" ID="button-cos" VALUE="cos">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" ID="button-sin" VALUE=" sin">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" ID="button-tan" VALUE=" tan">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" ID="button-cb" VALUE="   )   ">
      </TD>
    </TR>
    <TR>
      <TD ALIGN="center">
        <INPUT TYPE="button" ID="button-clear" VALUE="clear">
      </TD>
      <TD ALIGN="center" COLSPAN="3">
        <INPUT TYPE="button" ID="button-bsp" VALUE="backspace">
      </TD>
      <TD ALIGN="center">
        <INPUT TYPE="button" ID="button-enter" VALUE="enter" NAME="enter" ONCLICK="">
      </TD>
    </TR>
  </TABLE>
</FORM>

If you want to do it with pure JavaScript, do this:

document.querySelector('#button-sin').addEventListener(function() {
  if (checkNum(this.form.display.value)) {
    sin(this.form)
  }
});

Of course, it's possible to improve this even more, but this fulfills what you need.

  • 1
    Thanks! I should have specified jQuery as that is what I was hoping for! – newbie2015 Dec 29 '15 at 16:17
  • A quick follow-up question... the backspace function clears the display of altogether if the string length is 1 when you click the button. How would I get it to produce a 0 in that case? – newbie2015 Dec 30 '15 at 02:00
1

Honestly I wouldn't bother too much.

While yes, in general, you should keep your javascript in the javascript and your html in the html, there's no absolute need to do so and if it works... why change it?

However, I would suggest maybe something like this:

Define your buttons with:

<button type="button" data-value="1">1</button>
<button type="button" data-function="sin">sin</button>

Then, when defining your event handler, you can do it on your form:

form.onclick = function(e) {
    e = e || window.event;
    var t = e.srcElement || e.target;
    while( t.nodeName != "BUTTON" && t != this) t = t.parentNode;
    if( t.nodeName == "BUTTON") {
        // so we have a button...
        if( t.getAttribute("data-value")) {
            addChar(t.getAttribute("data-value"));
        }
        if( t.getAttribute("data-function")) {
            form.display.value = Math[t.getAttribute("data-function")](form.display.value);
        }
        // define more button types here
    }
};

In this way, you only have one event handler, which is generally a good idea as opposed to having an event handler for each button.

Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592
0

A working JS solution: unobtrusive JavaScript with onclick Delegation

HTML

<FORM NAME="sci-calc">
<TABLE CELLSPACING="0" CELLPADDING="1">
<TR>
<TD COLSPAN="5" ALIGN="center"><INPUT id="results_input" NAME="display" VALUE="0" SIZE="28" MAXLENGTH="25"></TD>
</TR>
<TR>
<TD ALIGN="center"><INPUT TYPE="button" VALUE=" exp "></TD>
<TD ALIGN="center"><INPUT TYPE="button" VALUE="  7  "></TD>
<TD ALIGN="center"><INPUT TYPE="button" VALUE="  8  "></TD>
<TD ALIGN="center"><INPUT TYPE="button" VALUE="  9  "></TD>
<TD ALIGN="center"><INPUT TYPE="button" VALUE="   /   "></TD>
</TR>
<TR>
<TD ALIGN="center"><INPUT TYPE="button" VALUE="   ln   "></TD>
<TD ALIGN="center"><INPUT TYPE="button" VALUE="  4  "></TD>
<TD ALIGN="center"><INPUT TYPE="button" VALUE="  5  "></TD>
<TD ALIGN="center"><INPUT TYPE="button" VALUE="  6  "></TD>
<TD ALIGN="center"><INPUT TYPE="button" VALUE="   *   "></TD>
</TR>
<TR>
<TD ALIGN="center"><INPUT TYPE="button" VALUE=" sqrt "></TD>
<TD ALIGN="center"><INPUT TYPE="button" VALUE="  1  "></TD>
<TD ALIGN="center"><INPUT TYPE="button" VALUE="  2  "></TD>
<TD ALIGN="center"><INPUT TYPE="button" VALUE="  3  "></TD>
<TD ALIGN="center"><INPUT TYPE="button" VALUE="   -   "></TD>
</TR>
<TR>
<TD ALIGN="center"><INPUT TYPE="button" VALUE="  sq  "></TD>
<TD ALIGN="center"><INPUT TYPE="button" VALUE="  0  "></TD>
<TD ALIGN="center"><INPUT TYPE="button" VALUE="   .  "></TD>
<TD ALIGN="center"><INPUT TYPE="button" VALUE=" +/- "></TD>
<TD ALIGN="center"><INPUT TYPE="button" VALUE="   +  "></TD>
</TR>
<TR>
<TD ALIGN="center"><INPUT TYPE="button" VALUE="    (    "></TD>
<TD ALIGN="center"><INPUT TYPE="button" VALUE="cos"></TD>
<TD ALIGN="center"><INPUT TYPE="button" VALUE=" sin"></TD>
<TD ALIGN="center"><INPUT TYPE="button" VALUE=" tan"></TD>
<TD ALIGN="center"><INPUT TYPE="button" VALUE="   )   "></TD>
</TR>
<TR>
<TD ALIGN="center"><INPUT TYPE="button" VALUE="clear"></TD>
<TD ALIGN="center" COLSPAN="3"><INPUT TYPE="button" VALUE="backspace"></TD>
<TD ALIGN="center"><INPUT TYPE="button" VALUE="enter" NAME="enter"></TD>
</TR>
</TABLE>
</FORM>

Javascript

function setOnClick() {

  document.onclick = function(e) {
    var resultsInput = document.getElementById("results_input");
    var target = e.target;
    if (target.tagName === "INPUT") {
        var trimmedValue = target.value.trim();

            switch (true){
        case trimmedValue == "enter":
            if (checkNum(resultsInput)) { compute(resultsInput) }   
        break;
        case trimmedValue == "clear":
            resultsInput.value = 0;
        break;
        case trimmedValue == "backspace":
            deleteChar(resultsInput)
        break;
        case (trimmedValue === "ln" || trimmedValue === "exp" || trimmedValue === "sq" || trimmedValue === "sqrt" || trimmedValue === "cos" || trimmedValue === "tan"):
            if (checkNum(resultsInput)) { 
            if (trimmedValue === "ln") {
                trimmedValue = "log";
            }
            else if (trimmedValue === "sq") {
              resultsInput.value = eval(resultsInput.value) * eval(resultsInput.value)
              break;
            }
            resultsInput.value = eval(Math[trimmedValue](resultsInput.value));
          } 
        break;
                default:
            addChar(resultsInput, target.value);    
        break;
      }
    }
  }
}

function addChar(input, character) {
    if(input.value == null || input.value == "0")
        input.value = character.trim();
    else
        input.value += character.trim();
}


function deleteChar(input) {
    input.value = input.value.substring(0, input.value.length - 1)
}

function changeSign(input) {
    if(input.value.substring(0, 1) == "-")
        input.value = input.value.substring(1, input.value.length)
    else
        input.value = "-" + input.value
}

function compute(resultsInput) {
    resultsInput.value = eval(resultsInput.value)
}

function checkNum(str) {
console.log("str: ",str);
    for (var i = 0; i < str.length; i++) {
        var ch = str.substring(i, i+1)
        if (ch < "0" || ch > "9") {
            if (ch != "/" && ch != "*" && ch != "+" && ch != "-" && ch != "."
            && ch != "(" && ch!= ")") {
            alert("invalid entry!")
            return false
            }
        }
    }
    return true
}

setOnClick();
Yonatan Ayalon
  • 1,959
  • 18
  • 19
  • reference credit for multiple cases in switch - http://stackoverflow.com/questions/5464362/javascript-using-a-condition-in-switch-case/9055603#9055603 – Yonatan Ayalon Dec 29 '15 at 14:17
-1

U need to add id to each input controls like

<input id="myControl">

Then in javascript

function cos(form) {
    form.display.value = Math.cos(form.display.value);
}
$(document).ready(function(){
    $("#myControl").click($('#idOfDisplayControl'));
});
Ashutosh Singh
  • 609
  • 6
  • 21