Skip to content

Instantly share code, notes, and snippets.

Created March 8, 2016 15:31
Show Gist options
  • Select an option

  • Save anonymous/047fd9ae1fe6c281feeb to your computer and use it in GitHub Desktop.

Select an option

Save anonymous/047fd9ae1fe6c281feeb to your computer and use it in GitHub Desktop.

Revisions

  1. @invalid-email-address Anonymous created this gist Mar 8, 2016.
    7 changes: 7 additions & 0 deletions Calculator.markdown
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,7 @@
    Calculator
    ----------
    Calculator app, for freecodecamp.com

    A [Pen](http://codepen.io/monzee/pen/VaeGLG) by [Mon Zafra](http://codepen.io/monzee) on [CodePen](http://codepen.io/).

    [License](http://codepen.io/monzee/pen/VaeGLG/license).
    36 changes: 36 additions & 0 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,36 @@
    <div id="container">
    <main>
    <div id="display">123456789012345</div>
    <div id="keypad">
    <div class="key-row">
    <div id="key-1">1</div>
    <div id="key-2">2</div>
    <div id="key-3">3</div>
    <div id="key-div">/</div>
    </div>
    <div class="key-row">
    <div id="key-4">4</div>
    <div id="key-5">5</div>
    <div id="key-6">6</div>
    <div id="key-mul">*</div>
    </div>
    <div class="key-row">
    <div id="key-7">7</div>
    <div id="key-8">8</div>
    <div id="key-9">9</div>
    <div id="key-sub">-</div>
    </div>
    <div class="key-row">
    <div id="key-0">0</div>
    <div id="key-dec">.</div>
    <div id="key-neg">&#x00b1;</div>
    <div id="key-add">+</div>
    </div>
    <div class="key-row">
    <div id="key-clr" class="span-2">clear</div>
    <div id="key-bksp">&#x232b;</div>
    <div id="key-eq">=</div>
    </div>
    </div>
    </main>
    </div>
    222 changes: 222 additions & 0 deletions script.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,222 @@
    class BinOp {
    constructor(op, prec, fn) {
    this.op = op;
    this.precedence = prec;
    this.fn = fn;
    }

    show() {
    return `[op: ${this.op}]`;
    }

    eval(stack) {
    let right = stack.pop();
    let left = stack.pop();
    try {
    stack.push(this.fn(left, right));
    } catch (e) {
    console.log(e);
    stack.push(+"nope");
    }
    }
    }

    class Num {
    constructor(n) {
    this.n = n;
    }

    show() {
    return this.n;
    }

    eval(stack) {
    stack.push(this.n);
    }
    }

    const OPS = {
    [Symbol.for('+')]: new BinOp('+', 1, (a, b) => a + b),
    [Symbol.for('-')]: new BinOp('-', 1, (a, b) => a - b),
    [Symbol.for('*')]: new BinOp('*', 2, (a, b) => a * b),
    [Symbol.for('/')]: new BinOp('/', 2, (a, b) => a / b)
    }

    class Calculator {
    constructor() {
    this.buffer = [];
    this.ops = [];
    this.machine = [];
    }

    get digits() {
    return this.buffer.join('');
    }

    flush() {
    if (this.pending) {
    this.pushOperand();
    this.pushOperator(this.pending);
    this.pending = null;
    }
    }

    pushOperand() {
    if (this.buffer.length) {
    this.machine.push(new Num(+this.digits));
    this.buffer = [];
    }
    }

    pushOperator(operator) {
    let op = OPS[Symbol.for(operator)];
    let n = 0, i = this.ops.length - 1;
    for (; i >= 0; i--) {
    let prev = this.ops[i];
    if (op.precedence <= prev.precedence) {
    this.machine.push(prev);
    n++;
    } else {
    break;
    }
    }
    this.ops.splice(i + 1, n);
    this.ops.push(op);
    }

    calculate() {
    for (let o of this.ops.reverse()) {
    this.machine.push(o);
    }
    let output = [];
    for (let e of this.machine) {
    console.log(e.show());
    e.eval(output);
    }
    let answer = output.pop();
    this.machine = [];
    this.ops = [];
    this.buffer = ('' + answer).split('');
    this.evaluated = true;
    return answer;
    }
    }


    jQuery(function () {
    const $ = jQuery;

    let model = new Calculator;

    const view = {
    $: $('#display'),

    show(n) {
    this.$.text(n);
    },

    clear() {
    this.show('0');
    this.deselect();
    },

    update() {
    this.show(model.digits || '0');
    },

    select(node) {
    this.deselect();
    this.$highlighted = $(node).addClass('active');
    },

    deselect() {
    if (this.$highlighted) {
    this.$highlighted.removeClass('active');
    this.$highlighted = null;
    }
    }
    }

    const digit = n => _ => {
    if (n === 0 && !model.buffer.length) {
    return;
    }
    if (model.evaluated) {
    model = new Calculator;
    } else {
    model.flush();
    }
    model.buffer.push(n);
    view.update();
    }

    const operator = op => e => {
    view.select(e.target);
    model.pending = op;
    model.evaluated = null;
    }

    const controller = {
    'key-0': digit(0),
    'key-1': digit(1),
    'key-2': digit(2),
    'key-3': digit(3),
    'key-4': digit(4),
    'key-5': digit(5),
    'key-6': digit(6),
    'key-7': digit(7),
    'key-8': digit(8),
    'key-9': digit(9),

    'key-add': operator('+'),
    'key-sub': operator('-'),
    'key-mul': operator('*'),
    'key-div': operator('/'),

    ['key-clr']() {
    model = new Calculator;
    view.clear();
    },

    ['key-bksp']() {
    if (model.buffer.length) {
    model.buffer.pop();
    model.evaluated = null;
    view.update();
    }
    },

    ['key-dec']() {
    if (model.buffer.indexOf('.') === -1) {
    model.flush();
    model.buffer.push('.');
    model.evaluated = null;
    view.update();
    }
    },

    ['key-neg']() {
    if (!model.buffer.length || model.buffer[0] !== '-') {
    model.buffer.unshift('-');
    } else {
    model.buffer.shift();
    }
    model.evaluated = null;
    view.update();
    },

    ['key-eq']() {
    model.pushOperand();
    model.calculate();
    view.deselect();
    view.update();
    }
    }

    $('#container').on('click', '.key-row > div', e => {
    let handler = controller[e.target.id];
    handler && handler(e);
    });

    view.clear();
    });
    1 change: 1 addition & 0 deletions scripts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1 @@
    <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
    58 changes: 58 additions & 0 deletions style.css
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,58 @@
    body {
    padding: 2em;
    }
    #container {
    display: flex;
    flex-flow: row nowrap;
    justify-content: center;
    align-content: center;
    align-items: center;
    }
    main {
    border: 1px solid #333;
    flex: 0 1 auto;
    background: #dedede;
    padding: 0.5em;
    }
    #keypad {
    }
    #display {
    font-size: 2em;
    line-height: 1;
    background: #fff;
    border: 1px solid #a0a0a0;
    margin: 0.25em;
    padding: 0.5em;
    text-align: right;
    width: 12em;
    font-family: monospace;
    overflow-wrap: word-wrap;
    word-break: break-all;
    }
    .key-row {
    display: flex;
    flex-flow: row no-wrap;
    }
    .key-row > div {
    border: 1px solid #a0a0a0;
    background: #fff;
    padding: 1em;
    margin: 0.5em;
    flex: 1 1 auto;
    text-align: center;
    cursor: pointer;
    font-family: monospace;
    }
    .key-row > div:hover {
    background: #c0c0c0;
    }
    .key-row > div:active {
    background: #808080;
    }
    .key-row > div.active {
    background: #80e080;
    }
    .key-row .span-2 {
    flex-grow: 3;
    flex-shrink: 1;
    }