15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (c) 2012 The Chromium Authors. All rights reserved. 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Use of this source code is governed by a BSD-style license that can be 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * found in the LICENSE file. 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) **/ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function View(window) { 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.display = window.document.querySelector('#calculator-display'); 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.buttons = window.document.querySelectorAll('#calculator-buttons button'); 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window.addEventListener('keydown', this.handleKey_.bind(this)); 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Array.prototype.forEach.call(this.buttons, function(button) { 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) button.addEventListener('click', this.handleClick_.bind(this)); 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) button.addEventListener('mousedown', this.handleMouse_.bind(this)); 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) button.addEventListener('touchstart', this.handleTouch_.bind(this)); 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) button.addEventListener('touchmove', this.handleTouch_.bind(this)); 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) button.addEventListener('touchend', this.handleTouchEnd_.bind(this)); 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) button.addEventListener('touchcancel', this.handleTouchEnd_.bind(this)); 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, this); 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)View.prototype.clearDisplay = function(values) { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.display.innerHTML = ''; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.addValues(values); 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)View.prototype.addResults = function(values) { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.appendChild_(this.display, null, 'div', 'hr'); 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.addValues(values); 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)View.prototype.addValues = function(values) { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var equation = this.makeElement_('div', 'equation'); 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.appendChild_(equation, null, 'span', 'accumulator', values.accumulator); 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.appendChild_(equation, null, 'span', 'operation'); 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.appendChild_(equation, '.operation', 'span', 'operator'); 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.appendChild_(equation, '.operation', 'span', 'operand', values.operand); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.appendChild_(equation, '.operator', 'div', 'spacer'); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.appendChild_(equation, '.operator', 'div', 'value', values.operator); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.setAttribute_(equation, '.accumulator', 'aria-hidden', 'true'); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.display.appendChild(equation).scrollIntoView(); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)View.prototype.setValues = function(values) { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var equation = this.display.lastElementChild; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.setContent_(equation, '.accumulator', values.accumulator || ''); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.setContent_(equation, '.operator .value', values.operator || ''); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.setContent_(equation, '.operand', values.operand || ''); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)View.prototype.getValues = function() { 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var equation = this.display.lastElementChild; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) accumulator: this.getContent_(equation, '.accumulator') || null, 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) operator: this.getContent_(equation, '.operator .value') || null, 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) operand: this.getContent_(equation, '.operand') || null, 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** @private */ 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)View.prototype.handleKey_ = function(event) { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.onKey.call(this, event.shiftKey ? ('^' + event.which) : event.which); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** @private */ 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)View.prototype.handleClick_ = function(event) { 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.onButton.call(this, event.target.dataset.button) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** @private */ 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)View.prototype.handleMouse_ = function(event) { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event.target.setAttribute('data-active', 'mouse'); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** @private */ 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)View.prototype.handleTouch_ = function(event) { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event.preventDefault(); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.handleTouchChange_(event.touches[0]); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** @private */ 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)View.prototype.handleTouchEnd_ = function(event) { 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.handleTouchChange_(null); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** @private */ 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)View.prototype.handleTouchChange_ = function(location) { 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var previous = this.touched; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.isInButton_(previous, location)) { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.touched = this.findButtonContaining_(location); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (previous) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) previous.removeAttribute('data-active'); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.touched) { 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.touched.setAttribute('data-active', 'touch'); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.onButton.call(this, this.touched.dataset.button); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** @private */ 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)View.prototype.findButtonContaining_ = function(location) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var found; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; location && i < this.buttons.length && !found; ++i) { 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.isInButton_(this.buttons[i], location)) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found = this.buttons[i]; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return found; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** @private */ 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)View.prototype.isInButton_ = function(button, location) { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var bounds = location && button && button.getClientRects()[0]; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var x = bounds && location.clientX; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var y = bounds && location.clientY; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var x1 = bounds && bounds.left; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var x2 = bounds && bounds.right; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var y1 = bounds && bounds.top; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var y2 = bounds && bounds.bottom; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (bounds && x >= x1 && x < x2 && y >= y1 && y < y2); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** @private */ 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)View.prototype.makeElement_ = function(tag, classes, content) { 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var element = this.display.ownerDocument.createElement(tag); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) element.setAttribute('class', classes); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) element.textContent = content || ''; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return element; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** @private */ 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)View.prototype.appendChild_ = function(root, selector, tag, classes, content) { 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var parent = (root && selector) ? root.querySelector(selector) : root; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parent.appendChild(this.makeElement_(tag, classes, content)); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** @private */ 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)View.prototype.setAttribute_ = function(root, selector, name, value) { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var element = root && root.querySelector(selector); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (element) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) element.setAttribute(name, value); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** @private */ 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)View.prototype.setContent_ = function(root, selector, content) { 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var element = root && root.querySelector(selector); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (element) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) element.textContent = content || ''; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** @private */ 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)View.prototype.getContent_ = function(root, selector) { 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var element = root && root.querySelector(selector); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return element ? element.textContent : null; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 154