├── calculator.jpg
├── README.md
├── index.html
├── .gitignore
├── style.css
└── calculator.js
/calculator.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oxica/Calculator-JavaScript/HEAD/calculator.jpg
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Calculator-JavaScript
2 |
3 | 
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Calculator - JavaScript
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 |
9 | # Diagnostic reports (https://nodejs.org/api/report.html)
10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11 |
12 | # Runtime data
13 | pids
14 | *.pid
15 | *.seed
16 | *.pid.lock
17 |
18 | # Directory for instrumented libs generated by jscoverage/JSCover
19 | lib-cov
20 |
21 | # Coverage directory used by tools like istanbul
22 | coverage
23 | *.lcov
24 |
25 | # nyc test coverage
26 | .nyc_output
27 |
28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
29 | .grunt
30 |
31 | # Bower dependency directory (https://bower.io/)
32 | bower_components
33 |
34 | # node-waf configuration
35 | .lock-wscript
36 |
37 | # Compiled binary addons (https://nodejs.org/api/addons.html)
38 | build/Release
39 |
40 | # Dependency directories
41 | node_modules/
42 | jspm_packages/
43 |
44 | # TypeScript v1 declaration files
45 | typings/
46 |
47 | # TypeScript cache
48 | *.tsbuildinfo
49 |
50 | # Optional npm cache directory
51 | .npm
52 |
53 | # Optional eslint cache
54 | .eslintcache
55 |
56 | # Microbundle cache
57 | .rpt2_cache/
58 | .rts2_cache_cjs/
59 | .rts2_cache_es/
60 | .rts2_cache_umd/
61 |
62 | # Optional REPL history
63 | .node_repl_history
64 |
65 | # Output of 'npm pack'
66 | *.tgz
67 |
68 | # Yarn Integrity file
69 | .yarn-integrity
70 |
71 | # dotenv environment variables file
72 | .env
73 | .env.test
74 |
75 | # parcel-bundler cache (https://parceljs.org/)
76 | .cache
77 |
78 | # Next.js build output
79 | .next
80 |
81 | # Nuxt.js build / generate output
82 | .nuxt
83 | dist
84 |
85 | # Gatsby files
86 | .cache/
87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js
88 | # https://nextjs.org/blog/next-9-1#public-directory-support
89 | # public
90 |
91 | # vuepress build output
92 | .vuepress/dist
93 |
94 | # Serverless directories
95 | .serverless/
96 |
97 | # FuseBox cache
98 | .fusebox/
99 |
100 | # DynamoDB Local files
101 | .dynamodb/
102 |
103 | # TernJS port file
104 | .tern-port
105 |
--------------------------------------------------------------------------------
/style.css:
--------------------------------------------------------------------------------
1 | *{
2 | padding: 0;
3 | margin: 0;
4 | background-origin: padding-box;
5 | font-family: 'Poppins', sans-serif;
6 | }
7 |
8 | html{
9 | font-size: 16px;
10 | background-color: #6fc7bb;
11 | }
12 |
13 | .calculator{
14 | position: absolute;
15 |
16 | top: 50%;
17 | left: 50%;
18 |
19 | transform: translate(-50%, -50%);
20 | }
21 |
22 | .calc-container{
23 | background-color: rgba(14, 15, 14, 0.867);
24 |
25 | width: 300px;
26 | height: auto;
27 |
28 | border-radius: 30px 30px 30px 30px;
29 | }
30 |
31 | .output{
32 | width: 100%;;
33 | }
34 |
35 | .operation{
36 | width: 300px;
37 | height: 70px;
38 |
39 | color: #878787;
40 |
41 | font-size: 1.9em;
42 | font-weight: bold;
43 |
44 | position: relative;
45 | overflow: hidden;
46 | }
47 | .operation .value{
48 | position: absolute;
49 |
50 | bottom: 5px;
51 | right : 10px;
52 |
53 | white-space: nowrap;
54 | overflow: hidden;
55 | }
56 |
57 | .result{
58 | width: 300px;
59 | height: 140px;
60 |
61 | color: #FFF;
62 |
63 | font-size: 2.7em;
64 | font-weight: bold;
65 |
66 | overflow: hidden;
67 | position: relative;
68 | }
69 |
70 | .result .value{
71 | position: absolute;
72 |
73 | top: 50%;
74 | transform: translateY(-50%);
75 | right : 10px;
76 |
77 | white-space: nowrap;
78 | overflow: hidden;
79 | }
80 |
81 |
82 | .input{
83 | background-color: #FFF;
84 |
85 | border-radius: 0 0 25px 25px;
86 | border: 1px solid #1d1d1d;
87 | height: 340px;
88 | }
89 |
90 | .row {
91 | display: flex;
92 | justify-content: space-around;
93 | align-items: center;
94 | }
95 |
96 | .row button{
97 | width: 50px;
98 | height: 50px;
99 |
100 | font-size: 1.5em;
101 |
102 | border: none;
103 | border-radius: 50%;
104 | background-color: transparent;
105 |
106 | margin : 8px;
107 |
108 | cursor: pointer;
109 | }
110 |
111 | .row button:hover{
112 | font-weight: bold;
113 | }
114 |
115 | .row #calculate{
116 | color: #FFF;
117 | background-color: #46e0bc;
118 | width : 121px;
119 | border-radius: 50px;
120 | }
121 | .row #delete{
122 | color: #FFF;
123 | background-color: #ec6e4e;
124 | }
125 |
126 | #division, #multiplication, #subtraction, #addition {
127 | color: #18b893;
128 | }
--------------------------------------------------------------------------------
/calculator.js:
--------------------------------------------------------------------------------
1 | const input_element = document.querySelector(".input");
2 | const output_operation_element = document.querySelector(".operation .value");
3 | const output_result_element = document.querySelector(".result .value");
4 |
5 | let calculator_buttons = [
6 | {
7 | name : "delete",
8 | symbol : "⌫",
9 | formula : false,
10 | type : "key"
11 | },{
12 | name : "clear",
13 | symbol : "C",
14 | formula : false,
15 | type : "key"
16 | },{
17 | name : "percent",
18 | symbol : "%",
19 | formula : "/100",
20 | type : "number"
21 | },{
22 | name : "division",
23 | symbol : "÷",
24 | formula : "/",
25 | type : "operator"
26 | },{
27 | name : "7",
28 | symbol : 7,
29 | formula : 7,
30 | type : "number"
31 | },{
32 | name : "8",
33 | symbol : 8,
34 | formula : 8,
35 | type : "number"
36 | },{
37 | name : "9",
38 | symbol : 9,
39 | formula : 9,
40 | type : "number"
41 | },{
42 | name : "multiplication",
43 | symbol : "×",
44 | formula : "*",
45 | type : "operator"
46 | },{
47 | name : "4",
48 | symbol : 4,
49 | formula : 4,
50 | type : "number"
51 | },{
52 | name : "5",
53 | symbol : 5,
54 | formula : 5,
55 | type : "number"
56 | },{
57 | name : "6",
58 | symbol : 6,
59 | formula : 6,
60 | type : "number"
61 | },{
62 | name : "addition",
63 | symbol : "+",
64 | formula : "+",
65 | type : "operator"
66 | },,{
67 | name : "1",
68 | symbol : 1,
69 | formula : 1,
70 | type : "number"
71 | },{
72 | name : "2",
73 | symbol : 2,
74 | formula : 2,
75 | type : "number"
76 | },{
77 | name : "3",
78 | symbol : 3,
79 | formula : 3,
80 | type : "number"
81 | },{
82 | name : "subtraction",
83 | symbol : "–",
84 | formula : "-",
85 | type : "operator"
86 | },{
87 | name : "0",
88 | symbol : 0,
89 | formula : 0,
90 | type : "number"
91 | },{
92 | name : "comma",
93 | symbol : ".",
94 | formula : ".",
95 | type : "number"
96 | },{
97 | name : "calculate",
98 | symbol : "=",
99 | formula : "=",
100 | type : "calculate"
101 | }
102 | ];
103 |
104 | let data = {
105 | operation : [],
106 | result : [],
107 | }
108 |
109 | function createCalculatorButtons(){
110 | const btns_per_row = 4;
111 | let added_btns = 0;
112 |
113 | calculator_buttons.forEach( (button, index) => {
114 | if( added_btns % btns_per_row == 0 ){
115 | input_element.innerHTML += ``;
116 | }
117 |
118 | const row = document.querySelector(".row:last-child");
119 | row.innerHTML += ``;
122 |
123 | added_btns++;
124 | });
125 | }
126 | createCalculatorButtons();
127 |
128 | input_element.addEventListener("click", event => {
129 | const target_btn = event.target;
130 |
131 | calculator_buttons.forEach( button => {
132 | if( button.name == target_btn.id ) calculator(button);
133 | });
134 |
135 | });
136 |
137 | function calculator( button ){
138 | if( button.type == "operator" ){
139 | data.operation.push(button.symbol);
140 | data.result.push(button.formula);
141 | }
142 | else if( button.type == "number" ){
143 | data.operation.push(button.symbol);
144 | data.result.push(button.formula);
145 | }
146 | else if( button.type == "key" ){
147 | if( button.name == "clear" ){
148 | data.operation = [];
149 | data.result = [];
150 | updateOutputResult(0);
151 | }
152 | else if( button.name == "delete" ){
153 | data.result.pop();
154 | data.operation.pop();
155 | }
156 | }
157 | else if( button.type == "calculate" ){
158 |
159 | // PUSH WHAT'S LEFT IN TEMP TO RESULT AND JOIN RESULT
160 | let result_joined = data.result.join('');
161 |
162 | // CLEAR ALL ARRAYS, NO NEED TO SAVE ANYTHING ANYMORE
163 | data.operation = [];
164 | data.result = [];
165 |
166 | // CHECK IF THERE WAS A SYNATX ERROR IN THE operation
167 | let result_final;
168 | try {
169 | result_final = eval(result_joined);
170 | } catch (error) {
171 | if (error instanceof SyntaxError) {
172 | result_final = "Syntax Error!"
173 | updateOutputResult( result_final );
174 | return;
175 | }
176 | }
177 |
178 | // FORMAT THE RESULT
179 | result_final = formatResult(result_final);
180 |
181 | // SAVE RESULT FOR ANY FUTURE USE
182 | data.operation.push(result_final);
183 | data.result.push(result_final);
184 |
185 | // UPDATE OUTPUT
186 | updateOutputResult( result_final );
187 |
188 | return;
189 | }
190 |
191 | updateOutputOperation( data.operation.join('') );
192 | }
193 |
194 | function updateOutputOperation(operation){
195 | output_operation_element.innerHTML = operation;
196 | }
197 |
198 | function updateOutputResult(result){
199 | output_result_element.innerHTML = result;
200 | }
201 |
202 | function digitCounter(number){
203 | return number.toString().length;
204 | }
205 |
206 | function isFloat(number){
207 | return number % 1 != 0;
208 | }
209 |
210 | const max_output_number_length = 10;
211 | const output_precision = 5;
212 |
213 | function formatResult( result ){
214 | if( digitCounter(result) > max_output_number_length){
215 | if( isFloat(result) ){
216 | const result_int = parseInt(result);
217 | const result_int_length = digitCounter(result_int);
218 |
219 | if( result_int_length > max_output_number_length ){
220 | return result.toPrecision(output_precision);
221 | }else{
222 | const num_digits_after_point = max_output_number_length - result_int_length;
223 | return result.toFixed(num_digits_after_point);
224 | }
225 | }else{
226 | return result.toPrecision(output_precision);
227 | }
228 | }else{
229 | return result;
230 | }
231 | }
--------------------------------------------------------------------------------