├── README.md ├── Example ├── page.css └── index.html ├── index.html ├── calculator.min.js ├── calculator.js ├── style.css └── knockout-2.1.0.js /README.md: -------------------------------------------------------------------------------- 1 | # HTML5, CSS3 and JavaScript calculator 2 | 3 | This was a small project we did just to play around with some of the 4 | latest web tools, such as KnockoutJS. We wanted to design and build 5 | something that looked clean, used no images and with a small amount of code. 6 | 7 | The result was a simple calculator built with pure CSS and a little bit 8 | of JavaScript and [Knockout](http://knockoutjs.com/) love. 9 | 10 | The calculator also has keyboard support through your keyboard numpad. 11 | 12 | ## License 13 | 14 | Copyright (C) 2012 Ideaviate AB 15 | 16 | Permission is hereby granted, free of charge, to any person obtaining a copy 17 | of this software and associated documentation files (the "Software"), to deal 18 | in the Software without restriction, including without limitation the rights 19 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 20 | copies of the Software, and to permit persons to whom the Software is 21 | furnished to do so, subject to the following conditions: 22 | 23 | The above copyright notice and this permission notice shall be included in all 24 | copies or substantial portions of the Software. 25 | 26 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 27 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 28 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 29 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 30 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 32 | -------------------------------------------------------------------------------- /Example/page.css: -------------------------------------------------------------------------------- 1 | 2 | 3 | .body { 4 | color: #606471; 5 | font-family: Arial, Helvetica, sans-serif; 6 | font-size: 12px; 7 | } 8 | 9 | .header { 10 | height: 140px; 11 | line-height: 140px; 12 | text-align: center; 13 | } 14 | 15 | .article { 16 | -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.1); 17 | -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.1); 18 | box-shadow: inset 0 1px 1px rgba(0,0,0,.1); 19 | background-color: #9599AB; 20 | background-image: -moz-linear-gradient(right bottom,#8B92A8 0%,#F6E0CB 100%); 21 | background-image: -webkit-gradient(linear,right bottom, left top,color-stop(0, #8B92A8),color-stop(1, #F6E0CB)); 22 | background: -webkit-linear-gradient(right bottom, #8B92A8 0%, #F6E0CB 100%); 23 | background: -o-linear-gradient(right bottom, #8B92A8 0%, #F6E0CB 100%); 24 | background: -ms-linear-gradient(right bottom, #8B92A8 0%, #F6E0CB 100%); 25 | background: linear-gradient(right bottom, #8B92A8 0%, #F6E0CB 100%); 26 | background-repeat: repeat-x; 27 | filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ff8B92A8', endColorstr='#ffF6E0CB', GradientType=0); 28 | border-bottom: 1px solid #BDC0CA; 29 | border-top: 1px solid #BDC0CA; 30 | height: 450px; 31 | position: relative; 32 | } 33 | 34 | .demo.calculator { 35 | -moz-box-shadow: inset 0px 1px #7b839b, 0 2px 5px rgba(0,0,0,.5); 36 | -webkit-box-shadow: inset 0px 1px #7b839b, 0 2px 5px rgba(0,0,0,.5); 37 | box-shadow: inset 0px 1px #7b839b, 0 2px 5px rgba(0,0,0,.5); 38 | position: absolute; 39 | margin: auto; 40 | top: 0; 41 | left: 0; 42 | right: 0; 43 | bottom: 0; 44 | height: 218px; 45 | } 46 | 47 | .footer { 48 | color: #9B9DA7; 49 | padding: 60px 0; 50 | text-align: center; 51 | } 52 | 53 | .bold { 54 | font-weight: bold; 55 | } 56 | .h1 { 57 | font-size: 20px; 58 | } 59 | 60 | .p { 61 | margin-bottom: 8px; 62 | } 63 | .link { 64 | color: #6399F1; 65 | text-decoration: none; 66 | } 67 | .link:hover { 68 | text-decoration: underline; 69 | } -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Calculator 5 | 6 | 7 | 8 | 9 |
10 |
11 |
12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |
33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /Example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Calculator 5 | 6 | 7 | 8 | 9 | 10 | 14 | 15 |
16 |

CSS3, HTML5 & JavaScript Calculator

17 |
18 |
19 |
20 |
21 |
22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 |
43 |
44 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /calculator.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 Ideaviate AB 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | var Calculator = function () { 23 | var a = this, b = 0, e; 24 | a.display = ko.observable("0"); 25 | a.isShowingResult = ko.observable(!1); 26 | a.number = function (b, e) { 27 | var d = e.target.innerText; 28 | a.isShowingResult() && (a.clearDisplay(), a.isShowingResult(!1)); 29 | "." == d && -1 < a.display().indexOf(".") || (d = "0" === a.display() && "." != d ? d : a.display() + d, a.display(d)) 30 | }; 31 | a.operator = function (c, f) { 32 | var d = f.target.innerText; 33 | if (!a.isShowingResult()) { 34 | switch (e) { 35 | case "+": 36 | b += parseFloat(a.display(), 10); 37 | break; 38 | case "-": 39 | b -= parseFloat(a.display(), 10); 40 | break; 41 | case "x": 42 | b *= parseFloat(a.display(), 10); 43 | break; 44 | case "\u00f7": 45 | b /= parseFloat(a.display(), 10); 46 | break; 47 | default: 48 | b = parseFloat(a.display(), 10) 49 | } 50 | } 51 | e && a.display(b); 52 | e = "=" === d ? null : d; 53 | a.isShowingResult(!0) 54 | }; 55 | a.negate = function () { 56 | if (!(a.isShowingResult() || "0" === a.display())) { 57 | var b = "-" === a.display().substr(0, 1) ? a.display().substr(1) : "-" + a.display(); 58 | a.display(b) 59 | } 60 | }; 61 | a.backspace = function () { 62 | a.isShowingResult() || (1 < a.display().length ? a.display(a.display().substr(0, a.display().length - 1)) : a.clearDisplay()) 63 | }; 64 | a.clear = function () { 65 | e = null; 66 | a.clearDisplay(); 67 | b = 0 68 | }; 69 | a.clearDisplay = function () { 70 | a.display("0") 71 | } 72 | }; 73 | ko.applyBindings(new Calculator); 74 | (function () { 75 | var a = { 48: "0", 49: "1", 50: "2", 51: "3", 52: "4", 53: "5", 54: "6", 55: "7", 56: "8", 57: "9", 96: "0", 97: "1", 98: "2", 99: "3", 100: "4", 101: "5", 102: "6", 103: "7", 104: "8", 105: "9", 106: "x", 107: "+", 109: "-", 110: ".", 111: "\u00f7", 8: "backspace", 13: "=", 46: "c", 67: "c" }, b = function (b) { 76 | if (b.keyCode in a) { 77 | var c = document.getElementById("calculator-button-" + a[b.keyCode]); 78 | c.className.match(/(\s|^)active(\s|$)/) || (c.className += " active"); 79 | setTimeout(function () { 80 | c.className.match(/(\s|^)active(\s|$)/) && (c.className = c.className.replace(/(\s|^)active(\s|$)/, " ")) 81 | }, 100); 82 | document.createEvent ? (b = document.createEvent("HTMLEvents"), b.initEvent("click", !0, !0), c.dispatchEvent(b)) : (b = document.createEventObject(), c.fireEvent("onclick", b)) 83 | } 84 | }; 85 | document.addEventListener ? document.addEventListener("keyup", b, !1) : document.attachEvent && document.attachEvent("keyup", b) 86 | })(); -------------------------------------------------------------------------------- /calculator.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 Ideaviate AB 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | var Calculator = function () { 23 | 24 | // Helper variable declarations 25 | var self = this, 26 | decimalMark = ".", 27 | sum = 0, 28 | prevOperator; 29 | 30 | // Define default values 31 | self.display = ko.observable("0"); 32 | self.isShowingResult = ko.observable(false); 33 | 34 | // Callback for each number button 35 | self.number = function (item, event) { 36 | var button = event.target.innerText || event.target.textContent; 37 | 38 | // If a result has been shown, make sure we 39 | // clear the display before displaying any new numbers 40 | if (self.isShowingResult()) { 41 | self.clearDisplay(); 42 | self.isShowingResult(false); 43 | } 44 | 45 | // Make sure we only add one decimal mark 46 | if (button == decimalMark && self.display().indexOf(decimalMark) > -1) 47 | return; 48 | 49 | // Make sure that we remove the default 0 shown on the display 50 | // when the user press the first number button 51 | var newValue = (self.display() === "0" && button != decimalMark) ? button : self.display() + button; 52 | // Update the display 53 | self.display(newValue); 54 | }; 55 | 56 | // Callback for each operator button 57 | self.operator = function (item, event) { 58 | var button = event.target.innerText || event.target.textContent; 59 | // Only perform calculation if numbers 60 | // has been entered since last operator button was pressed 61 | if (!self.isShowingResult()) { 62 | // Perform calculation 63 | switch (prevOperator) { 64 | case "+": 65 | sum = sum + parseFloat(self.display(), 10); 66 | break; 67 | case "-": 68 | sum = sum - parseFloat(self.display(), 10); 69 | break; 70 | case "x": 71 | sum = sum * parseFloat(self.display(), 10); 72 | break; 73 | case "÷": 74 | sum = sum / parseFloat(self.display(), 10); 75 | break; 76 | default: 77 | sum = parseFloat(self.display(), 10); 78 | }; 79 | } 80 | 81 | // Avoid showing a result until you have at least 82 | // two terms to perform calculation on 83 | if (prevOperator) 84 | self.display(sum); 85 | 86 | // Make sure we don't try to calculate with the equal sign 87 | prevOperator = (button === "=") ? null : button; 88 | // Always set the calculator into showing result state 89 | // after an operator button has been pressed 90 | self.isShowingResult(true); 91 | }; 92 | 93 | // Callback for negating a number 94 | self.negate = function () { 95 | // Disable the negate button when showing a result 96 | if (self.isShowingResult() || self.display() === "0") 97 | return; 98 | 99 | var newValue = (self.display().substr(0, 1) === "-") ? self.display().substr(1) : "-" + self.display(); 100 | self.display(newValue); 101 | }; 102 | 103 | // Callback for each backspace button 104 | self.backspace = function (item, event) { 105 | // Disable backspace if the calculator is shown a result 106 | if (self.isShowingResult()) 107 | return; 108 | 109 | // Remove the last character, and make the display zero when 110 | // last character is removed 111 | if (self.display().length > 1) { 112 | self.display(self.display().substr(0, self.display().length - 1)); 113 | } else { 114 | self.clearDisplay(); 115 | } 116 | }; 117 | 118 | // Clear the entire calculator 119 | self.clear = function () { 120 | prevOperator = null; 121 | self.clearDisplay(); 122 | sum = 0; 123 | }; 124 | 125 | // Clear just the display 126 | self.clearDisplay = function () { 127 | self.display("0"); 128 | }; 129 | }; 130 | 131 | // Apply knockout bindings 132 | ko.applyBindings(new Calculator()); 133 | 134 | // Enable keyboard controll 135 | (function () { 136 | // Key codes and their associated calculator buttons 137 | var calculatorKeys = { 138 | 48: "0", 49: "1", 50: "2", 51: "3", 52: "4", 53: "5", 54: "6", 139 | 55: "7", 56: "8", 57: "9", 96: "0", 97: "1", 98: "2", 99: "3", 140 | 100: "4", 101: "5", 102: "6", 103: "7", 104: "8", 105: "9", 141 | 106: "x", 107: "+", 109: "-", 110: ".", 111: "÷", 8: "backspace", 142 | 13: "=", 46: "c", 67: "c" 143 | }; 144 | 145 | // Helper function to fire an event on an element 146 | function fireEvent(element, event) { 147 | if (document.createEvent) { 148 | // Dispatch for firefox + others 149 | var evt = document.createEvent("HTMLEvents"); 150 | evt.initEvent(event, true, true); 151 | return !element.dispatchEvent(evt); 152 | } else { 153 | // Dispatch for IE 154 | var evt = document.createEventObject(); 155 | return element.fireEvent('on' + event, evt) 156 | } 157 | } 158 | 159 | // Helper functions to add/remove HTML-element classes 160 | // as IE didn't support the classList property prior to IE10 161 | function hasClass(ele, cls) { 162 | return ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)')); 163 | } 164 | 165 | function addClass(ele, cls) { 166 | if (!hasClass(ele, cls)) ele.className += " " + cls; 167 | } 168 | 169 | function removeClass(ele, cls) { 170 | if (hasClass(ele, cls)) { 171 | var reg = new RegExp('(\\s|^)' + cls + '(\\s|$)'); 172 | ele.className = ele.className.replace(reg, ' '); 173 | } 174 | } 175 | 176 | // Callback for every key stroke 177 | var keycallback = function (e) { 178 | // Check if the key was one of our calculator keys 179 | if (e.keyCode in calculatorKeys) { 180 | // Get button-element associated with key 181 | var element = document.getElementById("calculator-button-" + calculatorKeys[e.keyCode]); 182 | // Simulate button click on keystroke 183 | addClass(element, "active"); 184 | setTimeout(function () { removeClass(element, "active"); }, 100); 185 | // Fire click event 186 | fireEvent(element, "click"); 187 | } 188 | } 189 | 190 | // Attach a keyup-event listener on the document 191 | if (document.addEventListener) { 192 | document.addEventListener('keyup', keycallback, false); 193 | } else if (document.attachEvent) { 194 | document.attachEvent('keyup', keycallback); 195 | } 196 | })(); 197 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | 2 | /* ################# 3 | * ### CSS Reset ### 4 | * ################# */ 5 | 6 | html, body, div, span, applet, object, iframe, 7 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 8 | a, abbr, acronym, address, big, cite, code, 9 | del, dfn, em, img, ins, kbd, q, s, samp, 10 | small, strike, strong, sub, sup, tt, var, 11 | b, u, i, center, 12 | dl, dt, dd, ol, ul, li, 13 | fieldset, form, label, legend, 14 | table, caption, tbody, tfoot, thead, tr, th, td, 15 | article, aside, canvas, details, embed, 16 | figure, figcaption, footer, header, hgroup, 17 | menu, nav, output, ruby, section, summary, 18 | time, mark, audio, video { 19 | margin: 0; 20 | padding: 0; 21 | border: 0; 22 | font-size: 100%; 23 | font: inherit; 24 | vertical-align: baseline; 25 | } 26 | /* HTML5 display-role reset for older browsers */ 27 | article, aside, details, figcaption, figure, 28 | footer, header, hgroup, menu, nav, section { 29 | display: block; 30 | } 31 | body { 32 | line-height: 1; 33 | } 34 | ol, ul { 35 | list-style: none; 36 | } 37 | blockquote, q { 38 | quotes: none; 39 | } 40 | blockquote:before, blockquote:after, 41 | q:before, q:after { 42 | content: ''; 43 | content: none; 44 | } 45 | table { 46 | border-collapse: collapse; 47 | border-spacing: 0; 48 | } 49 | /* End of CSS Reset */ 50 | 51 | 52 | 53 | 54 | /* ######################### 55 | * ### Calculator styles ### 56 | * ######################### */ 57 | 58 | /* Grid units */ 59 | .u1, 60 | .u2, 61 | .u3, 62 | .u4 { 63 | float: left; 64 | margin: 3px; 65 | } 66 | .u1 { 67 | width: 40px; 68 | } 69 | .u2 { 70 | width: 86px; 71 | } 72 | .u3 { 73 | width: 132px; 74 | } 75 | .u4 { 76 | width: 178px; 77 | } 78 | 79 | .calculator { 80 | -moz-border-radius: 5px; 81 | -webkit-border-radius: 5px; 82 | border-radius: 5px; 83 | -moz-box-shadow: inset 0px 1px #7b839b; 84 | -webkit-box-shadow: inset 0px 1px #7b839b; 85 | box-shadow: inset 0px 1px #7b839b; 86 | background-color: #3C4150; 87 | border: 1px solid #181A20; 88 | float: left; 89 | padding: 6px; 90 | width: 184px; 91 | } 92 | 93 | .display { 94 | -moz-border-radius: 3px; 95 | -webkit-border-radius: 3px; 96 | border-radius: 3px; 97 | -moz-box-shadow: inset 0 1px 1px #0A0B0D, 0px 1px #5E6370; 98 | -webkit-box-shadow: inset 0 1px 1px #0A0B0D, 0px 1px #5E6370; 99 | box-shadow: inset 0 1px 1px #0A0B0D, 0px 1px #5E6370; 100 | -webkit-box-sizing: border-box; 101 | -moz-box-sizing: border-box; 102 | box-sizing: border-box; 103 | background-color: #17181E; 104 | border: 1px solid #181A20; 105 | padding: 0 10px; 106 | text-align: right; 107 | } 108 | .display-text { 109 | color: #fff; 110 | font-size: 22px; 111 | line-height: 42px; 112 | overflow: hidden; 113 | unicode-bidi: embed; 114 | width: 1000px; 115 | float: right; 116 | } 117 | .display-inner { 118 | width: 156px; 119 | overflow: hidden; 120 | } 121 | .button { 122 | -moz-border-radius: 3px; 123 | -webkit-border-radius: 3px; 124 | border-radius: 3px; 125 | -webkit-touch-callout: none; 126 | -webkit-user-select: none; 127 | -khtml-user-select: none; 128 | -moz-user-select: none; 129 | -ms-user-select: none; 130 | user-select: none; 131 | border: 1px solid #181A20; 132 | color: #fff; 133 | cursor: pointer; 134 | float: left; 135 | font-family: Arial, Helvetica, sans-serif; 136 | font-size: 12px; 137 | font-weight: bold; 138 | line-height: 25px; 139 | padding: 0 8px; 140 | text-align: center; 141 | text-decoration: none; 142 | vertical-align: middle; 143 | } 144 | .button:active, 145 | .button-active { 146 | position: relative; 147 | top: 1px; 148 | } 149 | .button:active, 150 | .button:focus { 151 | outline: 0; 152 | } 153 | /* Mozilla fix */ 154 | button::-moz-focus-inner { 155 | padding: 0; 156 | border: 0; 157 | } 158 | 159 | /* Buttons styling exceptions */ 160 | .button-backspace { 161 | font-size: 17px; 162 | font-weight: normal; 163 | } 164 | 165 | 166 | /* Button skins */ 167 | .button-gray { 168 | -moz-box-shadow: inset 0px 1px #9498A3, 0 1px 1px #323643; 169 | -webkit-box-shadow: inset 0px 1px #9498A3, 0 1px 1px #323643; 170 | box-shadow: inset 0px 1px #9498A3, 0 1px 1px #323643; 171 | background-color: #595E6B; 172 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#656976), to(#4B505E)); 173 | background-image: -webkit-linear-gradient(top, #656976, #4B505E); 174 | background-image: -o-linear-gradient(top, #656976, #4B505E); 175 | background-image: linear-gradient(to bottom, #656976, #4B505E); 176 | background-image: -moz-linear-gradient(top, #656976, #4B505E); 177 | background-repeat: repeat-x; 178 | filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ff656976', endColorstr='#ff4B505E', GradientType=0); 179 | text-shadow: 0px -1px #181A20; 180 | } 181 | .button-gray:hover { 182 | background-color: #666B78; 183 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#757985), to(#545867)); 184 | background-image: -webkit-linear-gradient(top, #757985, #545867); 185 | background-image: -o-linear-gradient(top, #757985, #545867); 186 | background-image: linear-gradient(to bottom, #757985, #545867); 187 | background-image: -moz-linear-gradient(top, #757985, #545867); 188 | background-repeat: repeat-x; 189 | filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ff757985', endColorstr='#ff545867', GradientType=0); 190 | } 191 | .button-gray.active, 192 | .button-gray:active { 193 | -webkit-box-shadow: inset 0 1px 1px #14171E, 0px 1px #5E6370; 194 | -moz-box-shadow: inset 0 1px 1px #14171E, 0px 1px #5E6370; 195 | box-shadow: inset 0 1px 1px #14171E, 0px 1px #5E6370; 196 | background-color: #292D3A; 197 | background-image: none; 198 | filter: progid:dximagetransform.microsoft.gradient(enabled=false); 199 | } 200 | .button-red { 201 | -moz-box-shadow: inset 0px 1px #CA9883, 0 1px 1px #323643; 202 | -webkit-box-shadow: inset 0px 1px #CA9883, 0 1px 1px #323643; 203 | box-shadow: inset 0px 1px #CA9883, 0 1px 1px #323643; 204 | background-color: #965F48; 205 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#A46E57), to(#844D37)); 206 | background-image: -webkit-linear-gradient(top, #A46E57, #844D37); 207 | background-image: -o-linear-gradient(top, #A46E57, #844D37); 208 | background-image: linear-gradient(to bottom, #A46E57, #844D37); 209 | background-image: -moz-linear-gradient(top, #A46E57, #844D37); 210 | background-repeat: repeat-x; 211 | filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ffA46E57', endColorstr='#ff844D37', GradientType=0); 212 | text-shadow: 0px -1px #58372A; 213 | } 214 | .button-red:hover { 215 | background-color: #A26B55; 216 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#B4806A), to(#915740)); 217 | background-image: -webkit-linear-gradient(top, #B4806A, #915740); 218 | background-image: -o-linear-gradient(top, #B4806A, #915740); 219 | background-image: linear-gradient(to bottom, #B4806A, #915740); 220 | background-image: -moz-linear-gradient(top, #B4806A, #915740); 221 | background-repeat: repeat-x; 222 | filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ffB4806A', endColorstr='#ff915740', GradientType=0); 223 | } 224 | .button-red.active, 225 | .button-red:active { 226 | -webkit-box-shadow: inset 0 1px 1px #2A130C, 0px 1px #5E6370; 227 | -moz-box-shadow: inset 0 1px 1px #2A130C, 0px 1px #5E6370; 228 | box-shadow: inset 0 1px 1px #2A130C, 0px 1px #5E6370; 229 | background-color: #472619; 230 | background-image: none; 231 | filter: progid:dximagetransform.microsoft.gradient(enabled=false); 232 | } 233 | .button-blue { 234 | -moz-box-shadow: inset 0px 1px #BCD6FF, 0 1px 1px #323643; 235 | -webkit-box-shadow: inset 0px 1px #BCD6FF, 0 1px 1px #323643; 236 | box-shadow: inset 0px 1px #BCD6FF, 0 1px 1px #323643; 237 | background-color: #598FE9; 238 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#6DA1F8), to(#427BD8)); 239 | background-image: -webkit-linear-gradient(top, #6DA1F8, #427BD8); 240 | background-image: -o-linear-gradient(top, #6DA1F8, #427BD8); 241 | background-image: linear-gradient(to bottom, #6DA1F8, #427BD8); 242 | background-image: -moz-linear-gradient(top, #6DA1F8, #427BD8); 243 | background-repeat: repeat-x; 244 | filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ff6DA1F8', endColorstr='#ff427BD8', GradientType=0); 245 | text-shadow: 0px -1px #2C4E88; 246 | } 247 | .button-blue:hover { 248 | background-color: #6E9EED; 249 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#83B0FC), to(#578ADE)); 250 | background-image: -webkit-linear-gradient(top, #83B0FC, #578ADE); 251 | background-image: -o-linear-gradient(top, #83B0FC, #578ADE); 252 | background-image: linear-gradient(to bottom, #83B0FC, #578ADE); 253 | background-image: -moz-linear-gradient(top, #83B0FC, #578ADE); 254 | background-repeat: repeat-x; 255 | filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ff83B0FC', endColorstr='#ff578ADE', GradientType=0); 256 | } 257 | .button-blue.active, 258 | .button-blue:active { 259 | -webkit-box-shadow: inset 0 1px 1px #0E192E, 0px 1px #5E6370; 260 | -moz-box-shadow: inset 0 1px 1px #0E192E, 0px 1px #5E6370; 261 | box-shadow: inset 0 1px 1px #0E192E, 0px 1px #5E6370; 262 | background-color: #1E3357; 263 | background-image: none; 264 | filter: progid:dximagetransform.microsoft.gradient(enabled=false); 265 | } 266 | 267 | 268 | 269 | -------------------------------------------------------------------------------- /knockout-2.1.0.js: -------------------------------------------------------------------------------- 1 | // Knockout JavaScript library v2.1.0 2 | // (c) Steven Sanderson - http://knockoutjs.com/ 3 | // License: MIT (http://www.opensource.org/licenses/mit-license.php) 4 | 5 | (function(window,document,navigator,undefined){ 6 | function m(w){throw w;}var n=void 0,p=!0,s=null,t=!1;function A(w){return function(){return w}};function E(w){function B(b,c,d){d&&c!==a.k.r(b)&&a.k.S(b,c);c!==a.k.r(b)&&a.a.va(b,"change")}var a="undefined"!==typeof w?w:{};a.b=function(b,c){for(var d=b.split("."),f=a,g=0;g",c[0];);return 4a.a.j(c,b[e])&&c.push(b[e]);return c},T:function(a,b){for(var a=a||[],c=[], 9 | e=0,f=a.length;ea.length?t:a.substring(0,b.length)===b},eb:function(a,b){for(var c="return ("+a+")",e=0;e",""]||!d.indexOf("",""]||(!d.indexOf("",""]||[0,"",""];b="ignored
"+d[1]+b+d[2]+"
";for("function"==typeof window.innerShiv?c.appendChild(window.innerShiv(b)):c.innerHTML=b;d[0]--;)c=c.lastChild;c=a.a.L(c.lastChild.childNodes)}return c}; 24 | a.a.Y=function(b,c){a.a.ga(b);if(c!==s&&c!==n)if("string"!=typeof c&&(c=c.toString()),"undefined"!=typeof jQuery)jQuery(b).html(c);else for(var d=a.a.pa(c),f=0;f"},Va:function(a,b){var c=d[a];c===n&&m(Error("Couldn't find any memo with ID "+a+". Perhaps it's already been unmemoized."));try{return c.apply(s,b||[]),p}finally{delete d[a]}},Wa:function(b,d){var e=[];c(b,e);for(var h=0,j=e.length;hc;c++)b=b();return b})};a.toJSON=function(b,c,e){b=a.Ta(b);return a.a.sa(b,c,e)}})();a.b("toJS",a.Ta);a.b("toJSON",a.toJSON);(function(){a.k={r:function(b){switch(a.a.o(b)){case "option":return b.__ko__hasDomDataOptionValue__===p?a.a.f.get(b,a.c.options.oa):b.getAttribute("value");case "select":return 0<=b.selectedIndex?a.k.r(b.options[b.selectedIndex]):n;default:return b.value}},S:function(b,c){switch(a.a.o(b)){case "option":switch(typeof c){case "string":a.a.f.set(b,a.c.options.oa, 39 | n);"__ko__hasDomDataOptionValue__"in b&&delete b.__ko__hasDomDataOptionValue__;b.value=c;break;default:a.a.f.set(b,a.c.options.oa,c),b.__ko__hasDomDataOptionValue__=p,b.value="number"===typeof c?c:""}break;case "select":for(var d=b.options.length-1;0<=d;d--)if(a.k.r(b.options[d])==c){b.selectedIndex=d;break}break;default:if(c===s||c===n)c="";b.value=c}}}})();a.b("selectExtensions",a.k);a.b("selectExtensions.readValue",a.k.r);a.b("selectExtensions.writeValue",a.k.S);a.g=function(){function b(a,b){for(var d= 40 | s;a!=d;)d=a,a=a.replace(c,function(a,c){return b[c]});return a}var c=/\@ko_token_(\d+)\@/g,d=/^[\_$a-z][\_$a-z0-9]*(\[.*?\])*(\.[\_$a-z][\_$a-z0-9]*(\[.*?\])*)*$/i,f=["true","false"];return{D:[],W:function(c){var e=a.a.w(c);if(3>e.length)return[];"{"===e.charAt(0)&&(e=e.substring(1,e.length-1));for(var c=[],d=s,f,k=0;k$/: 45 | /^\s*ko\s+(.*\:.*)\s*$/,h=g?/^<\!--\s*\/ko\s*--\>$/:/^\s*\/ko\s*$/,j={ul:p,ol:p};a.e={C:{},childNodes:function(a){return b(a)?d(a):a.childNodes},ha:function(c){if(b(c))for(var c=a.e.childNodes(c),e=0,d=c.length;e"),t))}};a.c.uniqueName.gb=0;a.c.checked={init:function(b,c,d){a.a.n(b,"click",function(){var f;if("checkbox"==b.type)f=b.checked;else if("radio"==b.type&&b.checked)f=b.value;else return;var g=c();"checkbox"==b.type&&a.a.d(g)instanceof Array?(f=a.a.j(a.a.d(g),b.value), 62 | b.checked&&0>f?g.push(b.value):!b.checked&&0<=f&&g.splice(f,1)):a.g.$(g,d,"checked",f,p)});"radio"==b.type&&!b.name&&a.c.uniqueName.init(b,A(p))},update:function(b,c){var d=a.a.d(c());"checkbox"==b.type?b.checked=d instanceof Array?0<=a.a.j(d,b.value):d:"radio"==b.type&&(b.checked=b.value==d)}};var F={"class":"className","for":"htmlFor"};a.c.attr={update:function(b,c){var d=a.a.d(c())||{},f;for(f in d)if("string"==typeof f){var g=a.a.d(d[f]),e=g===t||g===s||g===n;e&&b.removeAttribute(f);8>=a.a.ja&& 63 | f in F?(f=F[f],e?b.removeAttribute(f):b[f]=g):e||b.setAttribute(f,g.toString())}}};a.c.hasfocus={init:function(b,c,d){function f(b){var e=c();a.g.$(e,d,"hasfocus",b,p)}a.a.n(b,"focus",function(){f(p)});a.a.n(b,"focusin",function(){f(p)});a.a.n(b,"blur",function(){f(t)});a.a.n(b,"focusout",function(){f(t)})},update:function(b,c){var d=a.a.d(c());d?b.focus():b.blur();a.a.va(b,d?"focusin":"focusout")}};a.c["with"]={p:function(b){return function(){var c=b();return{"if":c,data:c,templateEngine:a.q.K}}}, 64 | init:function(b,c){return a.c.template.init(b,a.c["with"].p(c))},update:function(b,c,d,f,g){return a.c.template.update(b,a.c["with"].p(c),d,f,g)}};a.g.D["with"]=t;a.e.C["with"]=p;a.c["if"]={p:function(b){return function(){return{"if":b(),templateEngine:a.q.K}}},init:function(b,c){return a.c.template.init(b,a.c["if"].p(c))},update:function(b,c,d,f,g){return a.c.template.update(b,a.c["if"].p(c),d,f,g)}};a.g.D["if"]=t;a.e.C["if"]=p;a.c.ifnot={p:function(b){return function(){return{ifnot:b(),templateEngine:a.q.K}}}, 65 | init:function(b,c){return a.c.template.init(b,a.c.ifnot.p(c))},update:function(b,c,d,f,g){return a.c.template.update(b,a.c.ifnot.p(c),d,f,g)}};a.g.D.ifnot=t;a.e.C.ifnot=p;a.c.foreach={p:function(b){return function(){var c=a.a.d(b());return!c||"number"==typeof c.length?{foreach:c,templateEngine:a.q.K}:{foreach:c.data,includeDestroyed:c.includeDestroyed,afterAdd:c.afterAdd,beforeRemove:c.beforeRemove,afterRender:c.afterRender,templateEngine:a.q.K}}},init:function(b,c){return a.c.template.init(b,a.c.foreach.p(c))}, 66 | update:function(b,c,d,f,g){return a.c.template.update(b,a.c.foreach.p(c),d,f,g)}};a.g.D.foreach=t;a.e.C.foreach=p;a.t=function(){};a.t.prototype.renderTemplateSource=function(){m(Error("Override renderTemplateSource"))};a.t.prototype.createJavaScriptEvaluatorBlock=function(){m(Error("Override createJavaScriptEvaluatorBlock"))};a.t.prototype.makeTemplateSource=function(b,c){if("string"==typeof b){var c=c||document,d=c.getElementById(b);d||m(Error("Cannot find template with ID "+b));return new a.l.i(d)}if(1== 67 | b.nodeType||8==b.nodeType)return new a.l.M(b);m(Error("Unknown template type: "+b))};a.t.prototype.renderTemplate=function(a,c,d,f){return this.renderTemplateSource(this.makeTemplateSource(a,f),c,d)};a.t.prototype.isTemplateRewritten=function(a,c){return this.allowTemplateRewriting===t||!(c&&c!=document)&&this.V&&this.V[a]?p:this.makeTemplateSource(a,c).data("isRewritten")};a.t.prototype.rewriteTemplate=function(a,c,d){var f=this.makeTemplateSource(a,d),c=c(f.text());f.text(c);f.data("isRewritten", 68 | p);!(d&&d!=document)&&"string"==typeof a&&(this.V=this.V||{},this.V[a]=p)};a.b("templateEngine",a.t);a.Z=function(){function b(b,c,e){for(var b=a.g.W(b),d=a.g.D,j=0;j/g;return{mb:function(b,c,e){c.isTemplateRewritten(b,e)||c.rewriteTemplate(b,function(b){return a.Z.zb(b,c)},e)},zb:function(a,g){return a.replace(c,function(a,c,d,f,i,l,q){return b(q,c,g)}).replace(d,function(a,c){return b(c,"<\!-- ko --\>",g)})},Za:function(b){return a.s.na(function(c, 70 | e){c.nextSibling&&a.ya(c.nextSibling,b,e)})}}}();a.b("templateRewriting",a.Z);a.b("templateRewriting.applyMemoizedBindingsToNextSibling",a.Z.Za);(function(){a.l={};a.l.i=function(a){this.i=a};a.l.i.prototype.text=function(){var b=a.a.o(this.i),b="script"===b?"text":"textarea"===b?"value":"innerHTML";if(0==arguments.length)return this.i[b];var c=arguments[0];"innerHTML"===b?a.a.Y(this.i,c):this.i[b]=c};a.l.i.prototype.data=function(b){if(1===arguments.length)return a.a.f.get(this.i,"templateSourceData_"+ 71 | b);a.a.f.set(this.i,"templateSourceData_"+b,arguments[1])};a.l.M=function(a){this.i=a};a.l.M.prototype=new a.l.i;a.l.M.prototype.text=function(){if(0==arguments.length){var b=a.a.f.get(this.i,"__ko_anon_template__")||{};b.ua===n&&b.da&&(b.ua=b.da.innerHTML);return b.ua}a.a.f.set(this.i,"__ko_anon_template__",{ua:arguments[0]})};a.l.i.prototype.nodes=function(){if(0==arguments.length)return(a.a.f.get(this.i,"__ko_anon_template__")||{}).da;a.a.f.set(this.i,"__ko_anon_template__",{da:arguments[0]})}; 72 | a.b("templateSources",a.l);a.b("templateSources.domElement",a.l.i);a.b("templateSources.anonymousTemplate",a.l.M)})();(function(){function b(b,c,d){for(var f,c=a.e.nextSibling(c);b&&(f=b)!==c;)b=a.e.nextSibling(f),(1===f.nodeType||8===f.nodeType)&&d(f)}function c(c,d){if(c.length){var f=c[0],g=c[c.length-1];b(f,g,function(b){a.xa(d,b)});b(f,g,function(b){a.s.Wa(b,[d])})}}function d(a){return a.nodeType?a:0a.a.ja)&&b.nodes?b.nodes():s; 83 | if(c)return a.a.L(c.cloneNode(p).childNodes);b=b.text();return a.a.pa(b)};a.q.K=new a.q;a.ra(a.q.K);a.b("nativeTemplateEngine",a.q);(function(){a.ma=function(){var a=this.vb=function(){if("undefined"==typeof jQuery||!jQuery.tmpl)return 0;try{if(0<=jQuery.tmpl.tag.tmpl.open.toString().indexOf("__"))return 2}catch(a){}return 1}();this.renderTemplateSource=function(b,f,g){g=g||{};2>a&&m(Error("Your version of jQuery.tmpl is too old. Please upgrade to jQuery.tmpl 1.0.0pre or later."));var e=b.data("precompiled"); 84 | e||(e=b.text()||"",e=jQuery.template(s,"{{ko_with $item.koBindingContext}}"+e+"{{/ko_with}}"),b.data("precompiled",e));b=[f.$data];f=jQuery.extend({koBindingContext:f},g.templateOptions);f=jQuery.tmpl(e,b,f);f.appendTo(document.createElement("div"));jQuery.fragments={};return f};this.createJavaScriptEvaluatorBlock=function(a){return"{{ko_code ((function() { return "+a+" })()) }}"};this.addTemplate=function(a,b){document.write("