Skip to content

Instantly share code, notes, and snippets.

@likewinter
Last active April 22, 2016 14:52
Show Gist options
  • Save likewinter/ae529ddf18ce91b1b113323785f04523 to your computer and use it in GitHub Desktop.
Save likewinter/ae529ddf18ce91b1b113323785f04523 to your computer and use it in GitHub Desktop.
FreeCodeCamp Calculator
<div class="calculator">
<input type="text" class="display" name="display">
<div class="buttons operations">
<button data-operation="ac">AC</button>
<button data-operation="+">+</button>
<button data-operation="-">-</button>
<button data-operation="*">*</button>
<button data-operation="/">/</button>
<button data-operation="=">=</button>
</div>
<div class="buttons digits">
<button data-value="9">9</button>
<button data-value="8">8</button>
<button data-value="7">7</button>
<button data-value="6">6</button>
<button data-value="5">5</button>
<button data-value="4">4</button>
<button data-value="3">3</button>
<button data-value="2">2</button>
<button data-value="1">1</button>
<button data-value="0">0</button>
</div>
</div>
const expressionStack = {
stack: [],
isPreviousDigit() {
return typeof this.stack[this.stack.length-1] === 'number';
},
isPreviousOperation() {
return !this.isPreviousDigit();
},
push(element) {
if (typeof element === 'number') {
if (this.isPreviousDigit()) {
this.stack.push(Number(this.stack.pop() + String(element)));
} else {
this.stack.push(element);
}
}
if (/[-+*/]/.test(element)) {
if (!this.isPreviousOperation()) {
this.stack.push(element);
}
}
},
get() {
return this.stack;
},
clear() {
this.stack = [];
}
}
const expressionEval = stack => {
if (expressionStack.isPreviousOperation()) return stack;
let result = stack[0];
for (let i = 1; i < stack.length; i += 2) {
switch (stack[i]) {
case '+':
result += stack[i+1];
break;
case '-':
result -= stack[i+1];
break;
case '*':
result *= stack[i+1];
break;
case '/':
result /= stack[i+1];
break;
}
}
return [result];
}
const display = {
el: document.getElementsByClassName('display')[0],
stackTransformer(stack) {
return stack.length ? stack.join('') : '0';
},
refresh() {
console.log(expressionStack.get());
this.el.value = this.stackTransformer(expressionStack.get());
}
}
const digitClick = e => {
if (e.target.tagName !== 'BUTTON') return;
const digit = e.target.getAttribute('data-value');
expressionStack.push(Number(digit));
display.refresh();
}
const operationClick = e => {
if (e.target.tagName !== 'BUTTON') return;
const operation = e.target.getAttribute('data-operation');
switch (operation) {
case '=':
expressionStack.stack = expressionEval(expressionStack.stack);
break;
case 'ac':
expressionStack.clear();
break;
default:
expressionStack.push(operation);
break;
}
display.refresh(expressionStack);
}
const buttons = {
digits: document.getElementsByClassName('buttons digits')[0],
operations: document.getElementsByClassName('buttons operations')[0]
}
buttons.digits.addEventListener('click', digitClick);
buttons.operations.addEventListener('click', operationClick);
display.refresh(expressionStack);
@use cssnext;
@use postcss-nested;
.calculator {
width: 500px;
padding:30px;
border: 2px solid #555;
border-radius: 10px;
box-sizing: content-box;
input.display {
width: 100%;
font-size: 2em;
font-family: Impact, sans-serif;
background-color: #EEE;
margin-bottom: 15px;
text-align: right;
}
& .buttons {
& button {
border-radius: 10px;
border: 2px solid black;
background-color: #EEE;
font-size: 2em;
font-family: Impact, sans-serif;
}
&.digits {
display: flex;
flex-direction: row-reverse;
flex-wrap: wrap;
justify-content: space-around;
& button {
width: calc(100%/3 - 10px);
padding:12px 0;
margin: 5px 0;
}
}
&.operations {
display: flex;
justify-content: space-around;
margin-bottom: 10px;
& button {
width: calc(100%/6 - 10px);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment