OLD | NEW |
1 /** | 1 /** |
2 * Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 * Copyright (c) 2012 The Chromium Authors. All rights reserved. |
3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
5 **/ | 5 **/ |
6 | 6 |
7 function Model(precision) { | 7 function Model(precision) { |
8 this.reset_({precision: precision}); | 8 this.reset_({precision: precision}); |
9 } | 9 } |
10 | 10 |
11 /** | 11 /** |
12 * Handles a calculator event, updating the calculator state accordingly and | 12 * Handles a calculator key input, updating the calculator state accordingly and |
13 * returning an object with 'accumulator', 'operator', and 'operand' properties | 13 * returning an object with 'accumulator', 'operator', and 'operand' properties |
14 * representing that state. | 14 * representing that state. |
15 * | 15 * |
16 * @private | 16 * @private |
17 */ | 17 */ |
18 Model.prototype.handle = function(event) { | 18 Model.prototype.handle = function(input) { |
19 switch (event) { | 19 switch (input) { |
20 case '+': | 20 case '+': |
21 case '-': | 21 case '-': |
22 case '/': | 22 case '/': |
23 case '*': | 23 case '*': |
24 // For operations, ignore the last operator if no operand was entered, | 24 // For operations, ignore the last operator if no operand was entered, |
25 // otherwise perform the current calculation before setting the new | 25 // otherwise perform the current calculation before setting the new |
26 // operator. In either case, clear the operand and the defaults. | 26 // operator. In either case, clear the operand and the defaults. |
27 var operator = this.operand && this.operator; | 27 var operator = this.operand && this.operator; |
28 var result = this.calculate_(operator, this.operand); | 28 var result = this.calculate_(operator, this.operand); |
29 return this.reset_({accumulator: result, operator: event}); | 29 return this.reset_({accumulator: result, operator: input}); |
30 case '=': | 30 case '=': |
31 // For the equal sign, perform the current calculation and save the | 31 // For the equal sign, perform the current calculation and save the |
32 // operator and operands used as defaults, or if there is no current | 32 // operator and operands used as defaults, or if there is no current |
33 // operator, use the default operators and operands instead. In any case, | 33 // operator, use the default operators and operands instead. In any case, |
34 // clear the operator and operand and return a transient state with a '=' | 34 // clear the operator and operand and return a transient state with a '=' |
35 // operator. | 35 // operator. |
36 var operator = this.operator || this.defaults.operator; | 36 var operator = this.operator || this.defaults.operator; |
37 var operand = this.operator ? this.operand : this.defaults.operand; | 37 var operand = this.operator ? this.operand : this.defaults.operand; |
38 var result = this.calculate_(operator, operand); | 38 var result = this.calculate_(operator, operand); |
39 var defaults = {operator: operator, operand: this.operand}; | 39 var defaults = {operator: operator, operand: this.operand}; |
40 return this.reset_({accumulator: result, defaults: defaults}); | 40 return this.reset_({accumulator: result, defaults: defaults}); |
41 case 'AC': | 41 case 'AC': |
42 return this.reset_({}); | 42 return this.reset_({}); |
43 case 'C': | 43 case 'C': |
44 return this.operand ? this.set_({operand: null}) : | 44 return this.operand ? this.set_({operand: null}) : |
45 this.operator ? this.set_({operator: null}) : | 45 this.operator ? this.set_({operator: null}) : |
46 this.handle('AC'); | 46 this.handle('AC'); |
47 case 'back': | 47 case 'back': |
48 var length = (this.operand || '').length; | 48 var length = (this.operand || '').length; |
49 return (length > 1) ? this.set_({operand: this.operand.slice(0, -1)}) : | 49 return (length > 1) ? this.set_({operand: this.operand.slice(0, -1)}) : |
50 this.operand ? this.set_({operand: null}) : | 50 this.operand ? this.set_({operand: null}) : |
51 this.set_({operator: null}); | 51 this.set_({operator: null}); |
52 case '+ / -': | 52 case '+ / -': |
53 var initial = (this.operand || '0')[0]; | 53 var initial = (this.operand || '0')[0]; |
54 return (initial === '-') ? this.set_({operand: this.operand.slice(1)}) : | 54 return (initial === '-') ? this.set_({operand: this.operand.slice(1)}) : |
55 (initial !== '0') ? this.set_({operand: '-' + this.operand}) : | 55 (initial !== '0') ? this.set_({operand: '-' + this.operand}) : |
56 this.set_({}); | 56 this.set_({}); |
57 default: | 57 default: |
58 var operand = (this.operand || '0') + event; | 58 var operand = (this.operand || '0') + input; |
59 var duplicate = (operand.replace(/[^.]/g, '').length > 1); | 59 var duplicate = (operand.replace(/[^.]/g, '').length > 1); |
60 var overflow = (operand.replace(/[^0-9]/g, '').length > this.precision); | 60 var overflow = (operand.replace(/[^0-9]/g, '').length > this.precision); |
61 return operand.match(/^0[0-9]/) ? this.set_({operand: operand[1]}) : | 61 return operand.match(/^0[0-9]/) ? this.set_({operand: operand[1]}) : |
62 (!duplicate && !overflow) ? this.set_({operand: operand}) : | 62 (!duplicate && !overflow) ? this.set_({operand: operand}) : |
63 this.set_({}); | 63 this.set_({}); |
64 } | 64 } |
65 } | 65 } |
66 | 66 |
67 /** | 67 /** |
68 * Reset the model's state to the passed in state. | 68 * Reset the model's state to the passed in state. |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
113 * Returns the string representation of the passed in value rounded to the | 113 * Returns the string representation of the passed in value rounded to the |
114 * model's precision, or "+Infinity" or "-Infinity" on overflow. | 114 * model's precision, or "+Infinity" or "-Infinity" on overflow. |
115 * | 115 * |
116 * @private | 116 * @private |
117 */ | 117 */ |
118 Model.prototype.round_ = function(x) { | 118 Model.prototype.round_ = function(x) { |
119 var rounded = String(Number(x.toFixed(this.precision - 1))); | 119 var rounded = String(Number(x.toFixed(this.precision - 1))); |
120 var overflow = (rounded.replace(/[^0-9]/g, '').length > this.precision); | 120 var overflow = (rounded.replace(/[^0-9]/g, '').length > this.precision); |
121 return (overflow || Math.abs(x) == Infinity) ? 'E' : rounded; | 121 return (overflow || Math.abs(x) == Infinity) ? 'E' : rounded; |
122 } | 122 } |
OLD | NEW |