├── LICENSE ├── README.md ├── assets ├── back_remove.png ├── calc_style.css └── favicon.png ├── code.js └── index.html /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Alexandros Florides 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Javascript Calculator 2 | 3 | [![AlexFlorides - javascript-calculator](https://img.shields.io/static/v1?label=AlexFlorides&message=javascript-calculator&color=blue&logo=github)](https://github.com/AlexFlorides/javascript-calculator "Go to GitHub repo") 4 | [![stars - javascript-calculator](https://img.shields.io/github/stars/AlexFlorides/javascript-calculator?style=social)](https://github.com/AlexFlorides/javascript-calculator) 5 | [![forks - javascript-calculator](https://img.shields.io/github/forks/AlexFlorides/javascript-calculator?style=social)](https://github.com/AlexFlorides/javascript-calculator) 6 | 7 | --- 8 | 9 | A simple calculator built using vanilla HTML, CSS and JavaScript. 10 | 11 | ## Controls / Functionality 12 | 13 | - Can be controlled using either mouse / touchscreen or by using the keyboard pressing the corresponding keys. 14 | 15 | - Decimal point can be inserted using both comma or dot key on the keyboard. 16 | 17 | - Backspace deletes last digit. 18 | 19 | - By keep pressing the equal operator will recalculate result based on the last operation. 20 | 21 | - Last operation will show up above the input box every time any of the operators is selected. 22 | 23 | ## Demo 24 | 25 | [![View site - GH Pages](https://img.shields.io/badge/View_site-GH_Pages-2ea44f?style=for-the-badge)](https://alexflorides.github.io/javascript-calculator/) 26 | 27 | ![javascript-calculator](https://user-images.githubusercontent.com/47948084/230783857-6933cdde-4cba-43f5-8aeb-ef992d9507dc.png) 28 | 29 | ## Contributions 30 | 31 | - Feel free to suggest any improvements by creating an issue. 32 | 33 | - You can also work on an already open issue and pull request when finished, so I can review the changes and eventually merge them to the base branch. -------------------------------------------------------------------------------- /assets/back_remove.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFlorides/javascript-calculator/401f441578d61c1865e6142c283ff2280d9b0caa/assets/back_remove.png -------------------------------------------------------------------------------- /assets/calc_style.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-size: 2.5vh; 3 | top: 15%; 4 | left: 40%; 5 | margin: 0 auto; 6 | background-color: black; 7 | font-family: 'Roboto', sans-serif; 8 | } 9 | 10 | h1 { 11 | color: white; 12 | text-align: center; 13 | margin: 0; 14 | } 15 | 16 | #calculator { 17 | width: auto; 18 | height: auto; 19 | padding: 1.5vh; 20 | border: 5px solid #666666; 21 | border-radius: 15px; 22 | margin: 0; 23 | position: absolute; 24 | top: 50%; 25 | left: 50%; 26 | -ms-transform: translate(-50%, -50%); 27 | transform: translate(-50%, -50%); 28 | } 29 | 30 | .box { 31 | text-align:right; 32 | font-size: 2.8vh; 33 | height: 3vh; 34 | line-height: 3vh; 35 | padding: 1em; 36 | border: 2px solid #e68a00; 37 | color: white; 38 | border-radius: 15px; 39 | background-color: black; 40 | } 41 | 42 | #last_operation_history { 43 | height: 1.8vh; 44 | font-size: 1.8vh; 45 | text-align:right; 46 | padding-right: 1.5vh; 47 | color: rgb(177, 176, 176); 48 | background-color: black; 49 | } 50 | 51 | button { 52 | width:9vh; 53 | height: 9vh; 54 | font-weight:bold; 55 | font-size: 3vh; 56 | color: white; 57 | background-color: #666666; 58 | border-radius: 50%; 59 | border: 1px solid #333333; 60 | } 61 | 62 | #backspace_btn { 63 | background-image: url("../assets/back_remove.png"); 64 | background-repeat: no-repeat; 65 | background-position: 50% 50%; 66 | background-size: 1.7em; 67 | } 68 | 69 | button:hover { 70 | background-color: #999999; 71 | cursor: pointer; 72 | } 73 | 74 | .operator { 75 | background-color: #e68a00; 76 | } 77 | 78 | .operator:hover { 79 | background-color: #ffd11a; 80 | } 81 | 82 | #equal_sign { 83 | width: 100%; 84 | border-radius: 15px; 85 | } 86 | -------------------------------------------------------------------------------- /assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFlorides/javascript-calculator/401f441578d61c1865e6142c283ff2280d9b0caa/assets/favicon.png -------------------------------------------------------------------------------- /code.js: -------------------------------------------------------------------------------- 1 | var operators = ["+", "-", "/", "*"]; 2 | 3 | var box = null; 4 | var last_operation_history = null; 5 | var operator = null; 6 | var equal = null; 7 | var dot = null; 8 | 9 | var firstNum = true; 10 | 11 | var numbers = []; 12 | var operator_value; 13 | var last_button; 14 | var calc_operator; 15 | 16 | var total; 17 | 18 | var key_combination = [] 19 | function button_number(button) { 20 | 21 | operator = document.getElementsByClassName("operator"); 22 | box = document.getElementById("box"); 23 | last_operation_history = document.getElementById("last_operation_history"); 24 | equal = document.getElementById("equal_sign").value; 25 | dot = document.getElementById("dot").value; 26 | 27 | last_button = button; 28 | 29 | // if button is not an operator or = sign 30 | if (!operators.includes(button) && button!=equal){ 31 | // if it is the first button clicked 32 | if (firstNum){ 33 | // and it's a dot, show 0. 34 | if (button == dot){ 35 | box.innerText = "0"+dot; 36 | } 37 | // else clear box and show the number 38 | else { 39 | box.innerText = button; 40 | } 41 | firstNum = false; 42 | } 43 | else { 44 | 45 | // return if the box value is 0 46 | if (box.innerText.length == 1 && box.innerText == 0){ 47 | 48 | if (button == dot){ 49 | box.innerText += button; 50 | } 51 | return; 52 | } 53 | // return if the box already has a dot and clicked button is a dot 54 | if (box.innerText.includes(dot) && button == dot){ 55 | return; 56 | } 57 | // maximum allowed numbers inputted are 20 58 | if (box.innerText.length == 20){ 59 | return; 60 | } 61 | 62 | // if pressed dot and box already has a - sign, show -0. 63 | if (button == dot && box.innerText == "-"){ 64 | box.innerText = "-0"+dot; 65 | } 66 | // else append number 67 | else { 68 | box.innerText += button; 69 | } 70 | } 71 | } 72 | // if it's an operator or = sign 73 | else { 74 | 75 | // return if operator is already pressed 76 | if (operator_value != null && button == operator_value){ 77 | return 78 | } 79 | 80 | // show minus sign if it's the first value selected and finally return 81 | if (button == "-" && box.innerText == 0){ 82 | box.innerText = button; 83 | firstNum = false; 84 | operator_value = button 85 | showSelectedOperator() 86 | return; 87 | } 88 | // return if minus operator pressed and it's already printed on screen 89 | else if (operators.includes(button) && box.innerText == "-"){ 90 | return 91 | } 92 | // return if minus operator pressed and history already has equal sign 93 | else if (button == "-" && operator_value == "-" && last_operation_history.innerText.includes("=")){ 94 | return 95 | } 96 | 97 | // set value of operator if it's one 98 | if (operators.includes(button)){ 99 | if (typeof last_operator != "undefined" && last_operator != null){ 100 | calc_operator = last_operator 101 | } 102 | else { 103 | calc_operator = button 104 | } 105 | if (button == "*"){ 106 | last_operator = "×" 107 | } 108 | else if (button == "/"){ 109 | last_operator = "÷" 110 | } 111 | else { 112 | last_operator = button 113 | } 114 | operator_value = button 115 | firstNum = true 116 | showSelectedOperator() 117 | } 118 | 119 | // add first number to numbers array and show it on history 120 | if (numbers.length == 0){ 121 | numbers.push(box.innerText) 122 | if (typeof last_operator != "undefined" && last_operator != null){ 123 | last_operation_history.innerText = box.innerText + " " + last_operator 124 | } 125 | } 126 | // rest of calculations 127 | else { 128 | if (numbers.length == 1){ 129 | numbers[1] = box.innerText 130 | } 131 | var temp_num = box.innerText 132 | 133 | // calculate total 134 | if (button==equal && calc_operator != null){ 135 | var total = calculate(numbers[0], numbers[1], calc_operator) 136 | box.innerText = total; 137 | 138 | // append second number to history 139 | if (!last_operation_history.innerText.includes("=")){ 140 | last_operation_history.innerText += " " + numbers[1] + " =" 141 | } 142 | 143 | temp_num = numbers[0] 144 | 145 | numbers[0] = total 146 | operator_value = null 147 | showSelectedOperator() 148 | 149 | // replace first number of history with the value of total 150 | var history_arr = last_operation_history.innerText.split(" ") 151 | history_arr[0] = temp_num 152 | last_operation_history.innerText = history_arr.join(" ") 153 | } 154 | // update history with the value on screen and the pressed operator 155 | else if (calc_operator != null) { 156 | last_operation_history.innerText = temp_num + " " + last_operator 157 | calc_operator = button 158 | numbers = [] 159 | numbers.push(box.innerText) 160 | } 161 | } 162 | } 163 | 164 | } 165 | // highlight operator button when selected 166 | function showSelectedOperator(){ 167 | 168 | var elements = document.getElementsByClassName("operator"); 169 | 170 | for (var i=0; i0){ 253 | // if last button pressed is an operator 254 | if (operators.includes(last_button)){ 255 | // if the displayed text is just a negative sign, replace it with a 0 256 | if (box.innerText == "-"){ 257 | box.innerText = 0 258 | firstNum = true 259 | return 260 | } 261 | // if the displayed text is not a just a negative sign, replace it with a negative sign 262 | else { 263 | box.innerText = "-" 264 | firstNum = false 265 | } 266 | } 267 | // if last button pressed is not an operator, change its sign 268 | else { 269 | box.innerText = -box.innerText 270 | 271 | if (numbers.length==1){ 272 | numbers[0] = box.innerText 273 | } 274 | else { 275 | numbers[1] = box.innerText 276 | } 277 | } 278 | } 279 | return 280 | } 281 | 282 | // if displayed text is 0, replace it with a negative sign 283 | if (box.innerText == 0){ 284 | box.innerText = "-" 285 | firstNum = false 286 | return 287 | } 288 | box.innerText = -box.innerText 289 | } 290 | 291 | // function to calculate square root of the number currently on screen 292 | function square_root(){ 293 | box = document.getElementById("box"); 294 | var square_num = Math.sqrt(box.innerText) 295 | box.innerText = square_num 296 | numbers.push(square_num) 297 | } 298 | 299 | // function to calculate the division of 1 with the number currently on screen 300 | function division_one(){ 301 | box = document.getElementById("box"); 302 | var square_num = 1/box.innerText 303 | box.innerText = square_num 304 | numbers.push(square_num) 305 | } 306 | 307 | // function to calculate the power of the number currently on screen 308 | function power_of(){ 309 | box = document.getElementById("box"); 310 | var square_num =Math.pow(box.innerText, 2) 311 | box.innerText = square_num 312 | numbers.push(square_num) 313 | } 314 | 315 | // function to calculate the percentage of a number 316 | function calculate_percentage(){ 317 | var elements = document.getElementsByClassName("operator"); 318 | box = document.getElementById("box"); 319 | 320 | if (numbers.length > 0 && typeof last_operator != "undefined"){ 321 | 322 | var perc_value = ((box.innerText / 100) * numbers[0]) 323 | if (!Number.isInteger(perc_value)) { 324 | perc_value = perc_value.toFixed(2); 325 | } 326 | box.innerText = perc_value 327 | numbers.push(box.innerText) 328 | 329 | // append second number to history 330 | if (!last_operation_history.innerText.includes("=")){ 331 | last_operation_history.innerText += " " + numbers[1] + " =" 332 | } 333 | } 334 | else { 335 | box.innerText = box.innerText/100 336 | } 337 | 338 | numbers.push(box.innerText) 339 | var res = calculate(numbers[0], numbers[1], last_operator) 340 | box.innerText = res 341 | operator_value = "=" 342 | 343 | // deselect operator if any selected 344 | for (var i=0; i 0 && typeof last_operator != "undefined"){ 354 | box.innerText = 0 355 | var temp = numbers[0] 356 | numbers = [] 357 | numbers.push(temp) 358 | firstNum = true; 359 | } 360 | } 361 | 362 | document.addEventListener('keydown', keyPressed); 363 | document.addEventListener('keyup', keyReleased); 364 | 365 | // function to capture keydown events 366 | function keyPressed(e) { 367 | e.preventDefault() 368 | var equal = document.getElementById("equal_sign").value; 369 | var dot = document.getElementById("dot").value; 370 | 371 | if (e.key == "Delete"){ 372 | button_clear(); 373 | return; 374 | } 375 | 376 | var isNumber = isFinite(e.key); 377 | var enterPress; 378 | var dotPress; 379 | var commaPress = false; 380 | 381 | if (e.key == "Enter"){ 382 | enterPress = equal; 383 | } 384 | if (e.key == "."){ 385 | dotPress = dot; 386 | } 387 | if (e.key == ","){ 388 | commaPress = true; 389 | } 390 | 391 | if (isNumber || operators.includes(e.key) || e.key == "Enter" || e.key == dotPress || 392 | commaPress || e.key == "Backspace"){ 393 | if (e.key == "Enter"){ 394 | button_number(enterPress) 395 | } 396 | else if (e.key == "Backspace"){ 397 | document.getElementById("backspace_btn").style.backgroundColor = "#999999"; 398 | backspace_remove() 399 | } 400 | else if (commaPress){ 401 | button_number(dot) 402 | } 403 | else { 404 | button_number(e.key) 405 | } 406 | } 407 | if (e.key) { 408 | key_combination[e.code] = e.key; 409 | } 410 | } 411 | 412 | // function to capture keyup events 413 | function keyReleased(e){ 414 | if (key_combination['ControlLeft'] && key_combination['KeyV']) { 415 | navigator.clipboard.readText().then(text => { 416 | box = document.getElementById("box"); 417 | var isNumber = isFinite(text); 418 | if (isNumber){ 419 | var copy_number = text 420 | firstNum = true 421 | button_number(copy_number) 422 | } 423 | }).catch(err => { 424 | console.error('Failed to read clipboard contents: ', err); 425 | }); 426 | } 427 | if (key_combination['ControlLeft'] && key_combination['KeyC']) { 428 | box = document.getElementById("box"); 429 | navigator.clipboard.writeText( box.innerText) 430 | } 431 | key_combination = [] 432 | e.preventDefault() 433 | // set the color of the backspace button back to its original 434 | if (e.key == "Backspace"){ 435 | document.getElementById("backspace_btn").style.backgroundColor = "#666666"; 436 | } 437 | } -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Calculator 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |

Calculator

16 |

17 |

0

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 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 |
56 |
57 | 58 | 59 | --------------------------------------------------------------------------------