RPN JavaScript Calculator
HTML
<!-- This content is licensed under a Creative Commons Attributions 4.0 International License -->
<!-- Author: Itay Grudev -->
<div class="calculator">
<!-- Screen and clear key -->
<div class="top">
<ul class="battery">
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<div class="brand">Elka</div>
<form>
<div class="operation"></div>
<input type="text" autofocus />
</form>
<span class="clear">C</span>
</div>
<div class="keys">
<span value="sqrt" class="function">√</span>
<span value="pow" class="opfunc">x<sup>y</sup></span>
<span value="abs" class="function">|x|</span>
<span value="log" class="function">log</span>
<span value="m+" class="memory">M+</span>
<span value="m-" class="memory last">M-</span>
<span value="sin" class="function">sin</span>
<span value="cos" class="function">cos</span>
<span value="tan" class="function">tan</span>
<span value="pi" class="constant">π</span>
<span value="mr" class="memory">MR</span>
<span value="mc" class="memory last">MC</span>
<span>7</span>
<span>8</span>
<span>9</span>
<span class="operator">+</span>
<span>4</span>
<span>5</span>
<span>6</span>
<span class="operator">-</span>
<span>1</span>
<span>2</span>
<span>3</span>
<span value="/" class="operator">÷</span>
<span>0</span>
<span>.</span>
<span class="eval">=</span>
<span value="*" class="operator">x</span>
</div>
</div>
CSS
@import url(http://fonts.googleapis.com/css?family=Quantico);
/* Basic reset */
.calculator, .calculator * {
margin: 0;
padding: 0;
box-sizing: border-box;
font: bold 14px Quantico, Arial, sans-serif;
}
/* Calculator styles */
.calculator {
width: 325px;
margin: 0 auto;
padding: 20px 20px 9px;
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
background: #BBD6F5;
background: linear-gradient(#BBD6F5, #A1C4EB);
border-radius: 3px;
box-shadow: 0 5px #3D6B9F, 0px 10px 15px rgba(0, 0, 0, 0.2);
}
.top span.clear {
float: right;
margin: 0 0 11px 7px !important;
}
.calculator .top .battery {
float: left;
overflow: hidden;
}
.calculator .top .battery li {
float: left;
width: 20px;
height: 30px;
margin: 0 3px 17px 0;
background: #FFE5BD;
border-radius: 2px;
box-shadow: 0 1px #BFB19A;
list-style: none;
}
.calculator .top .brand {
float: right;
margin: 5px 12px 0 0;
font-size: 17px;
color: rgba(255, 255, 255, 0.6);
cursor: default;
}
.calculator .top form {
height: 40px;
width: 212px;
float: left;
position: relative;
background: rgba(0, 0, 0, 0.2);
border-radius: 3px;
box-shadow: inset 0px 4px rgba(0, 0, 0, 0.2);
}
.calculator .top form .operation {
position: absolute;
top: 13px; left: 3px;
font-size: 14px;
color: white;
}
.calculator .top form .operation *,
.calculator .keys span * {
font-size: 11px;
}
.calculator .top form input {
border: 0;
position: absolute;
left: 16px; right: 3px; top: 11px;
background: transparent;
font-size: 17px;
line-height: 40x;
color: white;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2);
text-align: right;
letter-spacing: 1px;
}
.calculator .top form input:focus {
outline: 0;
}
.calculator .keys,
.calculator .top {
...
JavaScript
function attachArrayMethodsToNodeList(e){NodeList.prototype[e]=Array.prototype[e]}var arrayMethods=Object.getOwnPropertyNames(Array.prototype);arrayMethods.forEach(attachArrayMethodsToNodeList); // Adds forEach method to NodeList objects
var calculator_data = { };
var parseEval = function(expression)
{
var functions = [
"function sqrt(n) { return Math.sqrt(n); }",
"function abs(n) { return Math.abs(n); }",
"function log(n) { return Math.log(n); }",
"function pow(a, n) { return Math.pow(a, n); }",
"function sin(n) { return Math.sin(n); }",
"function cos(n) { return Math.cos(n); }",
"function tan(n) { return Math.tan(n); }",
"function asin(n) { return Math.asin(n); }",
"function acos(n) { return Math.acos(n); }",
"function atan(n) { return Math.atan(n); }",
"function floor(n) { return Math.floor(n); }",
"function ceil(n) { return Math.ceil(n); }",
"function random(n) { return Math.random(n); }",
"var pi = Math.PI;",
"var e = Math.E;"];
try {
return Function([], functions.join("") + "return " + expression)();
} catch (e) {
// Common mistake fix - missed last closing bracket
return Function([], functions.join("") + "return " + expression + ")")();
}
}
document.querySelectorAll('.calculator form')[0].childNodes.forEach(function (form) {
form.addEventListener('submit', function(e) {
e.preventDefault();
return false;
});
});
document.querySelectorAll('.calculator span').forEach(function (key) {
key.addEventListener('click', function(e) {
// Itterate to find calculator object
var calc = key;
do {
calc = calc.parentNode;
} while (calc.className != "calculator");
// Init calculator's data
if(calculator_data[calc] == undefined)
calculator_data[calc] = { operator: undefined, stack: [], mem: 0 };
var data...