After trying to build a web-based calculator, I refer to many codes of the blog god, summarize and modify them, and sort out the following.
Attachment: Demo Source code
I. HTML+CSS
The concrete structure style is as follows, referring to the interface of mobile calculator basically. Button function can view demo, can be achieved.
This distribution is not the focus, just attach the code to understand the JS behavior.
HTML/structure:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>JS Implementing a Lightweight Calculator</title> <link href="css/style.css" type="text/css" rel="stylesheet" /> <script src="js/script.js" type="text/javascript" rel="stylesheet"></script> </head> <body> <div id="box"> <div id="top"> <p>Lightweight Calculator by PYJ</p> <input id="screen0" type="text" style="margin-top: 100px;" disabled/> <input id="screen1" type="text" style="margin-top: 190px;" disabled/> </div> <div id="main"> <span class="div1" style="font-size: 26px">(</span> <span class="div1" style="font-size: 26px">)</span> <span class="div1" style="font-size: 26px">DEL</span> <span class="div1">/</span> <span class="div2">7</span> <span class="div2">8</span> <span class="div2">9</span> <span class="div1">*</span> <span class="div2">4</span> <span class="div2">5</span> <span class="div2">6</span> <span class="div1">-</span> <span class="div2">1</span> <span class="div2">2</span> <span class="div2">3</span> <span class="div1">+</span> <span class="div2">0</span> <span class="div2">.</span> <span class="div1">C</span> <span class="div3" style="width: 94px;background: orangered;">=</span> </div> </div> </body> </html>
CSS/presentation:
*{ margin: 0; padding: 0; font-family: "Consolas", "Menlo", "Courier", monospace; } span{display: block;} body{background: #f0f2f1;} #box{ width: 380px; height: 675px; margin-top: 8px; margin-left: auto; margin-right: auto; box-shadow:0 0 10px #888; } #top{ width: inherit; height: 285px; background: #333333; position: relative; } #top p{ color: #e7e7e7; font-size: 16px; padding-top: 5px; padding-right: 10px; text-align: right; } #top input{ width: 368px; height: 70px; position: absolute; color: #e8e8e8; background: none; border: none; font-size: 35px; text-align: right; line-height: 70px; cursor: text; padding-right: 10px; } #main{ width: inherit; height: 390px; background: #f0f2f1; } #main span{ width: 94px; height: 77px; border-right: 1px solid #dff0d8; border-top: 1px solid #dff0d8; float: left; font-size: 32px; text-align: center; line-height: 80px; cursor: pointer; } .div1{color: orangered;} .div2{color: #000;} .div3{border-right: none;color: #fff;} #main span:hover{background: #e1e1e1;} #main span:active{box-shadow: 0 0 5px 5px #fff;}
JavaScript/Behavior
The problems to be solved in the behavior layer can be summarized as follows: getting the content of the button clicked, giving the corresponding response or composition expression, calculating the expression and displaying it.
1. Initialization (screen clearing):
1 window.onload = function(){ 2 var screen0 = document.getElementById('screen0'), //Get the display content 3 screen1 = document.getElementById('screen1'); //Get the contents of the lower display 4 screen0.value = null; 5 screen1.value = null; 6 calculate(screen0, screen1); 7 };
2. The last line of the above code calls the calculate() function to get the button character:
1 function calculate(screen0,screen1){ 2 var box = document.getElementById('main'), //Get the button box 3 count = 0; //Record the number of characters or numbers on the display 4 5 box.onclick = function(e){ 6 var symbol = e.target.innerText; //Get the button character 7 8 //Does the content exceed the allowable length? 9 if((screen1.value + symbol).length > 40){ 10 alert('Content exceeds the maximum length!'); 11 return null; 12 } 13 if(symbol == 'C'){ //Zero clearing 14 count = 0; 15 screen0.value = null; 16 screen1.value = null; 17 }else if(symbol != '='){ //Expression 18 if(symbol == 'DEL'){ 19 if(screen1.value == null){ 20 count = 0; 21 }else{ 22 screen1.value = screen1.value.slice(0,-1); 23 count--; 24 } 25 }else{ 26 screen1.value += symbol; 27 } 28 }else if(symbol == '='){ //Computational results 29 screen0.value = screen1.value; 30 screen1.value = test(screen1.value); 31 } 32 } 33 }
Judgment is made on zeroing, deletion, "=" and other characters respectively, and different processing results are given.
3. Press "=" to calculate the preceding string:
But before calculating, we need to know about the loss of JS digital precision. The realization of computer binary system and the limitation of digits will make some numbers unable to be expressed in a finite way, but the finite numbers are infinite in the binary system of computer. The "discarding" caused by the limitation of storage digits will lead to the loss of accuracy. Specific content is no longer expanded, you can go to see the relevant documents.
In order to solve the problem of precision loss of floating point number, a method is defined for Math object.
1 Math.formatFloat = function (exp, digit){ 2 var m = Math.pow(10, digit); 3 return parseInt(exp*m, 10)/m; 4 }; 5 //Put decimals into bitwise integers (multipliers) and then reduce them back to their original multiples (dividers)
The core algorithm of calculator is the operation of expression.
The idea of this paper is to divide expressions into symbols and use recursion:
1 function test(text) { 2 var index = 0; //Record Symbol Index 3 4 while(text){ 5 //First calculate the contents in parentheses 6 if(text.lastIndexOf("(") > -1){ 7 index = text.lastIndexOf("("); 8 var endIndex = text.indexOf(")", index); 9 if(endIndex > -1) { 10 var result = test(text.substring(index + 1, endIndex)); 11 return Math.formatFloat(test(text.substring(0, index) + result + text.substring(endIndex + 1)) ,2); 12 } 13 14 }else if(text.indexOf("+") >-1){ 15 index = text.indexOf("+"); 16 return Math.formatFloat(test(text.substring(0, index)) + test(text.substring(index + 1)) ,2); 17 18 }else if(text.lastIndexOf("-") > -1){ 19 index = text.lastIndexOf("-"); 20 if(text[index-1] == '*'){ 21 return Math.formatFloat(test(text.substring(0, index-1)) * test(text.substring(index)) ,2); 22 }else if(text[index-1] == '/'){ 23 return Math.formatFloat(test(text.substring(0, index-1)) / test(text.substring(index)) ,2); 24 }else{ 25 return Math.formatFloat(test(text.substring(0, index)) - test(text.substring(index + 1)) ,2); 26 } 27 28 }else if(text.lastIndexOf("*") > -1){ 29 index = text.lastIndexOf("*"); 30 return Math.formatFloat(test(text.substring(0, index)) * test(text.substring(index + 1)) ,2); 31 32 }else if(text.lastIndexOf("/") > -1){ 33 index = text.lastIndexOf("/"); 34 return Math.formatFloat(test(text.substring(0, index)) / test(text.substring(index + 1)) ,2); 35 36 }else{ 37 return Math.formatFloat(text,2); 38 } 39 } 40 41 return null; 42 }
Attention should be paid to: firstly, the contents of parentheses should be calculated; the "-" sign and division sign should be extracted from the tail of the expression, otherwise the calculation will be wrong; the "-" sign can be divided into minus sign and minus sign; the solution is to split the multiplication sign and division sign before the "-" sign by multiplication sign or division sign; the application of Math.formatFloat() method .
The effect chart is as follows, if there are bug s or mistakes in the text, we hope to point out [cuddle fist]