Skip to content

Instantly share code, notes, and snippets.

@dohzya
Last active March 5, 2018 10:15
Show Gist options
  • Save dohzya/913276c7d04c0e55629d720bbb5e05b5 to your computer and use it in GitHub Desktop.
Save dohzya/913276c7d04c0e55629d720bbb5e05b5 to your computer and use it in GitHub Desktop.
<html>
<head>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.35.0/codemirror.css">
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.35.0/theme/material.css">
<style>
body {
background: #EFEFEF;
}
.display {
border: 1px solid #AAA;
padding: 20px;
font-size: 20px;
width: 295px;
text-align: right;
height: 25px;
background: white;
font-family: monospace;
}
.calc ul {
margin: 0;
padding:0;
overflow: hidden;
border: 1px solid #CCC;
width: 335px;
list-style: none;
}
.calc li {
float: left;
border: 1px solid #CCC;
background-color: #555;
color: White;
padding: 20px;
width: 25px;
height: 20px;
text-align: center;
font-family: monospace;
}
.calc li:hover {
background: #777
}
.calc li:active {
background: AliceBlue;
color: #555
}
.calc li.disabled, li.disabled:hover, li.disabled:active {
background: #AAA;
color: white;
}
.doc {
position: absolute;
top: 335px;
height: calc(100% - 347px - 9px);
left: 9px;
width: 313px;
background: white;
border: 1px solid #CCC;
margin: 0;
padding: 5px 10px;
list-style: none;
overflow: auto;
}
.doc code {
background: #EFEFEF;
}
.doc li {
margin-top: 5px;
}
.doc li:first-child {
margin-top: 0;
}
.reload {
position: absolute;
top: 9px;
left: 355px;
right: 9px;
height: 30px;
width: calc(100% - 355px - 9px);
}
.editorCompute {
position: absolute;
top: 50px;
left: 355px;
right: 9px;
bottom: 90px;
height: calc(100% - 50px - 70px);;
}
.editorDisplayValue {
position: absolute;
bottom: 9px;
left: 355px;
right: 9px;
height: 50px;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.35.0/codemirror.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.35.0/mode/javascript/javascript.js"></script>
</head>
<body>
<div class="calc">
<div id="display" class="display"></div>
<ul id="buttons">
<li>7</li>
<li>8</li>
<li>9</li>
<li>C</li>
<li>AC</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>x</li>
<li>/</li>
<li>1</li>
<li>2</li>
<li>3</li>
<li>+</li>
<li>-</li>
<li>0</li>
<li class="disabled"></li>
<li class="disabled"></li>
<li class="disabled"></li>
<li>=</li>
</ul>
</div>
<ul class="doc">
<li>“<code>op ? call() : other</code>” means “if <code>op</code> then <code>call()</code>, else <code>other</code>”.</li>
<li><code>isDigit(input)</code> checks if <code>input</code> is a digit</li>
<li><code>addDigit(number, digit)</code> adds the given digit as last digit of the number. <code>addDigit(1, 2)</code> returns <code>12</code></li>
<li><code>call(op, number1, number2)</code> invoke the operation onto the two numbers. <code>call('+', 1, 2)</code> returns <code>3</code></li>
<li><code>or(number1, number2)</code> returns the first defined number. <code>or(1, 2)</code> returns <code>1</code>, but <code>or(undefined, 2)</code> returns <code>2</code></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<button id="reload" class="reload">RELOAD</button>
<textarea id="editorCompute">return function compute({total, currentValue, operation}, input) {
if (isDigit(input)) {
return {
total: total,
currentValue: addDigit(currentValue, input),
operation: operation
}
}
switch (input) {
case 'C':
return {
total: total,
currentValue: undefined,
operation: operation
}
case 'AC':
return {
total: undefined,
currentValue: undefined,
operation: undefined
}
case '=':
return {
total: operation ? call(operation, total, currentValue) : currentValue,
currentValue: undefined,
operation: undefined
}
default: // operator
return {
total: operation ? call(operation, total, currentValue) : or(total, currentValue),
currentValue: undefined,
operation: input
}
}
}</textarea>
<textarea id="editorDisplayValue">return function displayValue({currentValue, total}) {
return or(currentValue, total)
}</textarea>
<script>
function isDigit(input) {
switch (input) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
return true
}
return false
}
function addDigit(currentValue, input) {
const digit = parseInt(input, 10)
return currentValue ? (currentValue * 10 + digit) : digit
}
function call(operation, a, b) {
if (b === undefined) return a
if (a === undefined) return b
switch (operation) {
case '+': return a + b
case '-': return a - b
case '*': return a * b
case '/': return a / b
}
}
function or(a, b) {
return a === undefined ? b : a
}
const editorCompute = CodeMirror.fromTextArea(document.getElementById('editorCompute'), {
lineNumbers: true,
mode: 'javascript',
// theme: 'material'
})
editorCompute.getWrapperElement().classList.add('editorCompute')
const editorDisplayValue = CodeMirror.fromTextArea(document.getElementById('editorDisplayValue'), {
lineNumbers: true,
mode: 'javascript',
// theme: 'material'
})
editorDisplayValue.getWrapperElement().classList.add('editorDisplayValue')
const display = document.getElementById('display')
let state = {}
document.getElementById('buttons').onclick = function(event) {
if (event.target.classList.contains('disabled')) return
const input = event.target.innerText
console.log('--------------')
console.log('input:', input)
state = compute(state, input)
console.log('state:', state)
const valueToDisplay = displayValue(state)
display.innerText = valueToDisplay === undefined ? '' : valueToDisplay
}
function reload() {
compute = Function(editorCompute.getValue())()
displayValue = Function(editorDisplayValue.getValue())()
}
reload()
document.getElementById('reload').onclick = reload
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment