Last active
December 23, 2015 21:39
-
-
Save etale/6698339 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta name="viewport" content="width=device-width, user-scalable=no"> | |
<meta charset="UTF-8"> | |
<title>Natural Calc</title> | |
<style> | |
body { | |
width: 100%; | |
position: fixed; | |
bottom: 0; | |
overflow: auto; | |
display: -webkit-box; | |
-webkit-box-orient: vertical; | |
margin: 0; | |
font-size: 1.5rem; | |
font-family: serif; | |
-webkit-text-size-adjust: 100%; | |
-moz-text-size-adjust: 100%; | |
-ms-text-size-adjust: 100%; | |
-o-text-size-adjust: 100%; | |
text-size-adjust: 100%; | |
} | |
.focus { | |
background-color: #fff; | |
} | |
.button { | |
color: #eee; | |
background-color: #444; | |
} | |
table { | |
width: 100%; | |
border-collapse: collapse; | |
} | |
#display { | |
background-color: #eee; | |
border: 0; | |
border-collapse: collapse; | |
} | |
#display input { | |
width: 100%; | |
font-family: serif; | |
font-size: 1.5rem; | |
color: #aaa; | |
background-color: transparent; | |
margin: 0; | |
border: 0; | |
} | |
#display td { | |
text-align: right; | |
background-color: transparent; | |
padding: 0 10px; | |
margin: 0; | |
border: 0; | |
} | |
#keypad td { | |
width: 16.6667%; | |
text-align: center; | |
color: #eee; | |
background-color: #444; | |
padding: 0.75rem; | |
border: 0; | |
} | |
</style> | |
<script> | |
var | |
pi2 = Math.PI * 2, nil = 'nil', | |
equal = function(a, b) { | |
return a.ord === b.ord && a.arg === b.arg | |
}, | |
shift = function(a) { | |
return (a === 0) ? 0 : {ord: a.ord + 1, arg: a.arg} | |
}, | |
succ = function(a) { | |
return log(shift(exp(a))) | |
}, | |
add = function(a, b) { | |
return (a === nil || b === nil) ? nil : | |
(a === 0 ) ? b : | |
(b === 0 ) ? a : | |
equal(a, minus(b)) ? 0 : | |
(a.ord < b.ord) ? add(b, a) : | |
mul(a, succ(mul(inverse(a), b))) | |
}, | |
mul = function(a, b) { | |
return (a === nil || b === nil) ? nil : | |
(a === 0 || b === 0 ) ? 0 : | |
{ord: a.ord + b.ord, arg: (a.arg + b.arg) % 1} | |
}, | |
minus = function(a) { | |
return (a === nil) ? nil : | |
(a === 0 ) ? 0 : | |
{ord: a.ord, arg: (a.arg + 0.5) % 1} | |
}, | |
inverse = function(a) { | |
return (a === nil) ? nil : | |
(a === 0 ) ? nil : | |
{ord: - a.ord, arg: (a.arg === 0) ? 0 : (1 - a.arg)} | |
}, | |
_log = function(a) { | |
var ord, arg | |
if (a.arg >= 0.5) a.arg -= 1 | |
a.arg *= pi2 | |
ord = Math.log(a.ord * a.ord + a.arg * a.arg) * 0.5 | |
arg = Math.atan2(a.arg, a.ord) / pi2 | |
if (arg < 0) arg += 1 | |
return {ord: ord, arg: arg} | |
}, | |
log = function(a) { | |
return (a === nil || a === 0) ? nil : | |
(a.ord === 0 && a.arg === 0) ? 0 : | |
_log(a) | |
}, | |
_exp = function(a) { | |
var ord, arg | |
if (a.arg >= 0.5) a.arg -= 1 | |
a.arg *= pi2 | |
ord = Math.exp(a.ord) * Math.cos(a.arg) | |
arg = (Math.exp(a.ord) * Math.sin(a.arg) / pi2) % 1 | |
if (arg < 0) arg += 1 | |
return {ord: ord, arg: arg} | |
}, | |
exp = function(a) { | |
return (a === nil) ? nil : | |
(a === 0 ) ? {ord: 0, arg: 0} : | |
_exp(a) | |
} | |
var | |
e, touch, | |
isFixed = function() { | |
return e.hasOwnProperty('value') | |
}, | |
fix = function() { | |
var _, ord, arg | |
if (isFixed()) return | |
_ = e.data.textContent.split('.') | |
_ = [0, 1, 2].map(function(i) { | |
return _[i] ? _[i] : '0' | |
}) | |
ord = parseFloat(_[0] + '.' + _[1]) | |
arg = parseFloat( '0.' + _[2]) | |
set(log({ord: ord, arg: arg})) | |
}, | |
fixAsIs = function() { | |
var _, ord, arg | |
if (isFixed()) { | |
set(exp(e.value)) | |
} else | |
{ | |
_ = e.data.textContent.split('.') | |
_ = [0, 1, 2].map(function(i) { | |
return _[i] ? _[i] : '0' | |
}) | |
ord = parseFloat(_[0] + '.' + _[1]) | |
arg = parseFloat( '0.' + _[2]) | |
set({ord: ord, arg: arg}) | |
} | |
}, | |
moveFocus = function() { | |
e.classList.remove('focus') | |
this.cell.classList.add('focus') | |
e = this.cell | |
}, | |
makeCell = function() { | |
var cell = document.createElement('tr') | |
var label = document.createElement('td') | |
var input = document.createElement('input') | |
var data = document.createElement('td') | |
label.appendChild(input) | |
cell.appendChild(label) | |
cell.appendChild(data) | |
cell.label = input | |
cell.data = data | |
input.cell = cell | |
input.onchange = function() { | |
if (this.value === '') { | |
this.cell.data[touch] = moveFocus | |
while (this.cell.previousSibling.label.value !== '') { | |
display.insertBefore(this.cell, this.cell.previousSibling) | |
} | |
this.cell.classList.remove('button') | |
} else | |
{ | |
this.cell.data[touch] = function() { | |
isFixed() && push(); set(this.cell.value) | |
} | |
if (e === this.cell) { | |
fix() | |
e.previousSibling ? e.previousSibling.data[touch]() : push() | |
} | |
this.cell.classList.add('button') | |
while (this.cell.nextSibling && this.cell.nextSibling.label.value === '') { | |
display.insertBefore(this.cell, this.cell.nextSibling.nextSibling) | |
} | |
while (this.cell.nextSibling && this.cell.nextSibling.value.ord < this.cell.value.ord) { | |
display.insertBefore(this.cell, this.cell.nextSibling.nextSibling) | |
} | |
} | |
} | |
data.cell = cell | |
data.textContent = '0' | |
data[touch] = moveFocus | |
return cell | |
}, | |
push = function() { | |
display.insertBefore(makeCell(), e.nextSibling) | |
e.nextSibling.data[touch]() | |
}, | |
pop = function() { | |
var value = e.value | |
if (!e.previousSibling) { | |
return | |
} | |
e.previousSibling.data[touch]() | |
display.removeChild(e.nextSibling) | |
return value | |
}, | |
set = function(a) { | |
var aord, aarg | |
e.value = a | |
if (a === nil) { | |
e.data.textContent = nil | |
} else | |
if (a === 0) { | |
e.data.textContent = '0' | |
} else | |
{ | |
aord = a.ord.toFixed(6).split('.') | |
aarg = a.arg.toFixed(6).split('.') | |
aord[1] = aord[1] ? aord[1] : '0' | |
aarg[1] = aarg[1] ? aarg[1] : '0' | |
e.data.textContent = aord[0] + '.' + aord[1] + '.' + aarg[1] + 'X' | |
} | |
}, | |
numeric = function() { | |
var label = this.textContent | |
if (isFixed()) { | |
push(); e.data.textContent = label | |
} else | |
{ | |
if (e.data.textContent === '0') { | |
e.data.textContent = label | |
} else | |
{ | |
e.data.textContent += label | |
} | |
} | |
}, | |
keys = { | |
'0': numeric, | |
'1': numeric, | |
'2': numeric, '3': numeric, '4': numeric, '5': numeric, | |
'6': numeric, '7': numeric, '8': numeric, '9': numeric, | |
'.': function() { | |
isFixed() && push() | |
e.data.textContent += '.' | |
}, | |
'↑': function() { | |
if (isFixed()) { | |
push(); set(e.previousSibling.value) | |
} else | |
{ | |
fix() | |
} | |
}, | |
'↓': function() { | |
if (e.previousSibling) { | |
pop() | |
} else | |
{ | |
delete e.value | |
e.data.textContent = '0' | |
} | |
}, | |
'←': function() { | |
if (isFixed()) { | |
delete e.value | |
e.data.textContent = '0' | |
} else | |
{ | |
e.data.textContent = e.data.textContent.slice(0, -1) | |
if (e.data.textContent === '') { | |
e.data.textContent = '0' | |
} | |
} | |
}, | |
'g': function() { | |
isFixed() && push(); set({ord: 10.7352, arg: 0}) | |
}, | |
'm': function() { | |
isFixed() && push(); set({ord: 80.1104, arg: 0}) | |
}, | |
's': function() { | |
isFixed() && push(); set({ord: 99.6290, arg: 0}) | |
}, | |
'exp': function() { | |
fixAsIs() | |
}, | |
'log': function() { | |
fix(); set(log(e.value)) | |
}, | |
'/': function() { | |
fix(); set(inverse(e.value)) | |
}, | |
'−': function() { | |
fix(); set(minus(e.value)) | |
}, | |
'\\': function() { | |
alert('Not Implemented') | |
}, | |
' ': function() { | |
if (e.previousSibling) { | |
fix(); _ = pop(); set(mul(e.value, _)) | |
} | |
}, | |
'+': function() { | |
if (e.previousSibling) { | |
fix(); _ = pop(); set(add(e.value, _)) | |
} | |
} | |
} | |
touch = document.createElement('div') | |
.hasOwnProperty('ontouchend') ? 'ontouchend' : 'onmouseup'; | |
var | |
display = document.createElement('table'), | |
keypad = document.createElement('table') | |
e = makeCell() | |
display.appendChild(e) | |
display.setAttribute('id', 'display'); | |
[ | |
['↑' , '↓', '←', '7', '8', '9'], | |
['g' , 'm', 's', '4', '5', '6'], | |
['log', ' ', '/', '1', '2', '3'], | |
['exp', '+', '−', '0', '.', '\\'] | |
].forEach(function(tds) { | |
var tr = document.createElement('tr') | |
tds.forEach(function(td) { | |
var _ = document.createElement('td') | |
_.textContent = td | |
_[touch] = keys[td] | |
tr.appendChild(_) | |
}) | |
keypad.appendChild(tr) | |
}) | |
keypad.setAttribute('id', 'keypad') | |
onload = function() { | |
document.body.appendChild(display) | |
document.body.appendChild(keypad) | |
} | |
</script> | |
</head> | |
<body></body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
calc.html