Skip to content

Commit 6449a50

Browse files
Add files via upload
1 parent b27b25a commit 6449a50

File tree

3 files changed

+319
-0
lines changed

3 files changed

+319
-0
lines changed

Task1/index.html

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta name="viewport" content="width=device-width,initial-scale=1" />
6+
<title>OIBSIP - calculator</title>
7+
<link rel="stylesheet" href="style.css">
8+
</head>
9+
<body>
10+
<main class="page">
11+
<div class="calc" role="application" aria-label="Calculator">
12+
<div class="display" aria-live="polite">
13+
<div id="expr" class="expression" aria-hidden="true">0</div>
14+
<div id="out" class="output" aria-live="polite">0</div>
15+
</div>
16+
17+
<div class="pad" id="pad" role="grid" aria-label="Calculator keys">
18+
<!-- Row 1 -->
19+
<button data-action="percent" aria-label="percent">%</button>
20+
<button data-action="paren" data-value="(" aria-label="open parenthesis">(</button>
21+
<button data-action="paren" data-value=")" aria-label="close parenthesis">)</button>
22+
<button data-action="clear" class="ce" aria-label="clear entry">CE</button>
23+
24+
<!-- Row 2 -->
25+
<button data-value="7">7</button>
26+
<button data-value="8">8</button>
27+
<button data-value="9">9</button>
28+
<button data-action="op" data-value="/" aria-label="divide">÷</button>
29+
30+
<!-- Row 3 -->
31+
<button data-value="4">4</button>
32+
<button data-value="5">5</button>
33+
<button data-value="6">6</button>
34+
<button data-action="op" data-value="*" aria-label="multiply">×</button>
35+
36+
<!-- Row 4 -->
37+
<button data-value="1">1</button>
38+
<button data-value="2">2</button>
39+
<button data-value="3">3</button>
40+
<button data-action="minus" aria-label="subtract">-</button>
41+
42+
<!-- Row 5 -->
43+
<button data-action="sqrt" aria-label="plus minus or square root">±√</button>
44+
<button data-value="0">0</button>
45+
<button data-value=".">.</button>
46+
<button data-action="plus" class="op" aria-label="add">+</button>
47+
</div>
48+
49+
<div class="bottom-row" role="toolbar" aria-label="additional controls">
50+
<button data-action="del" aria-label="backspace" class="backspace"></button>
51+
<button class="enter" data-action="enter" aria-label="enter">=</button>
52+
</div>
53+
</div>
54+
</main>
55+
56+
<script src="script.js" defer></script>
57+
</body>
58+
</html>

Task1/script.js

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
const exprEl = document.getElementById('expr');
2+
const outEl = document.getElementById('out');
3+
let expression = '';
4+
let lastAns = '0';
5+
6+
const isOperator = ch => ['+', '-', '*', '/'].includes(ch);
7+
const lastChar = () => expression.slice(-1);
8+
9+
function render() {
10+
exprEl.textContent = expression || '0';
11+
outEl.textContent = preview(expression) || '0';
12+
}
13+
14+
function safeEval(src) {
15+
if (!src) return '0';
16+
let s = src.replace(/×/g, '*').replace(/÷/g, '/').replace(/ans/g, String(lastAns));
17+
s = s.replace(/\s+/g, '');
18+
if (!/^[0-9+\-*/().%]+$/.test(s)) throw new Error('Invalid characters');
19+
if (/[\+\-\*\/\.%]$/.test(s)) throw new Error('Trailing operator');
20+
s = s.replace(/(\d+(?:\.\d+)?)%/g, '($1/100)');
21+
return String(Function(`return (${s})`)());
22+
}
23+
24+
function preview(src) {
25+
try { return safeEval(src); } catch { return ''; }
26+
}
27+
28+
function add(token) {
29+
if (['+', '*', '/'].includes(token) && expression === '') return;
30+
if (isOperator(token) && isOperator(lastChar())) {
31+
expression = expression.slice(0, -1) + token;
32+
render();
33+
return;
34+
}
35+
expression += token;
36+
render();
37+
}
38+
39+
function doAction(action, value) {
40+
switch (action) {
41+
case 'clear':
42+
expression = '';
43+
break;
44+
case 'del':
45+
expression = expression.slice(0, -1);
46+
break;
47+
case 'ans':
48+
expression += 'ans';
49+
break;
50+
case 'enter':
51+
try {
52+
const res = safeEval(expression);
53+
lastAns = res;
54+
expression = String(res);
55+
} catch (e) {
56+
expression = 'ERR';
57+
render();
58+
setTimeout(() => { expression = ''; render(); }, 800);
59+
return;
60+
}
61+
break;
62+
case 'percent':
63+
expression = expression.replace(/(\d+(?:\.\d+)?)$/, m => m + '%');
64+
break;
65+
case 'sqrt':
66+
try {
67+
const v = Number(safeEval(expression));
68+
if (Number.isNaN(v)) throw new Error('Bad value');
69+
expression = String(Math.sqrt(v));
70+
} catch {
71+
expression = 'ERR';
72+
render();
73+
setTimeout(() => { expression = ''; render(); }, 800);
74+
return;
75+
}
76+
break;
77+
case 'op':
78+
add(value);
79+
break;
80+
case 'paren':
81+
add(value);
82+
break;
83+
case 'plus':
84+
add('+');
85+
break;
86+
case 'minus':
87+
add('-');
88+
break;
89+
default:
90+
break;
91+
}
92+
render();
93+
}
94+
document.addEventListener('click', (e) => {
95+
const btn = e.target.closest('button');
96+
if (!btn) return;
97+
const action = btn.dataset.action;
98+
const value = btn.dataset.value;
99+
if (action) doAction(action, value);
100+
else if (typeof value !== 'undefined') add(value);
101+
});
102+
window.addEventListener('keydown', (e) => {
103+
if (e.key >= '0' && e.key <= '9') add(e.key);
104+
else if (e.key === '.') add('.');
105+
else if (e.key === 'Backspace') doAction('del');
106+
else if (e.key === 'Enter' || e.key === '=') doAction('enter');
107+
else if (['+','-','*','/','(',')'].includes(e.key)) add(e.key);
108+
else if (e.key === '%') doAction('percent');
109+
});
110+
render();

Task1/style.css

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
*{
2+
box-sizing:border-box;
3+
}
4+
5+
body{
6+
height: 100%;
7+
width: 100%;
8+
background: linear-gradient(135deg, rgba(44, 44, 42, 0.4), rgba(30,8,0,0.5), rgba(14, 13, 13, 0.9));
9+
background-size: 10000% 600%;
10+
animation: gradientMove 10s ease infinite;
11+
padding: 20px;
12+
}
13+
14+
@keyframes gradientMove {
15+
0% { background-position: 0% 50%; }
16+
50% { background-position: 100% 50%; }
17+
100% { background-position: 0% 50%; }
18+
}
19+
20+
body{
21+
margin:0;
22+
font-family:Inter, system-ui, -apple-system, 'Segoe UI', Roboto, Arial;
23+
display:flex;
24+
align-items:center;
25+
justify-content:center;
26+
min-height:100vh;
27+
}
28+
29+
.calc{
30+
width:360px;
31+
background:#ded9d9;
32+
border: 2px solid black;
33+
border-radius:16px;
34+
padding:16px;
35+
box-shadow:0 8px 24px rgba(0,0,0,0.12);
36+
}
37+
38+
.display{
39+
background:#787a7a;
40+
padding:12px 14px;
41+
border-radius:10px;
42+
border: 0.5px solid;
43+
margin-bottom:12px;
44+
width: 100%;
45+
overflow: hidden;
46+
}
47+
48+
.expression,
49+
.output {
50+
white-space: nowrap;
51+
overflow: hidden;
52+
text-overflow: ellipsis;
53+
}
54+
55+
.expression{
56+
color:#ffffff;
57+
font-size:13px;
58+
}
59+
60+
.output{
61+
font-size:34px;
62+
font-weight:700;
63+
color:#131313;
64+
text-align:right;
65+
}
66+
67+
.pad{
68+
display:grid;
69+
grid-template-columns:repeat(4,1fr);
70+
gap:10px;
71+
}
72+
73+
button{
74+
padding:14px;
75+
border-radius:8px;
76+
border:0.5px solid ;
77+
background:linear-gradient(180deg,#525456,#717374);
78+
font-size:16px;
79+
font-weight:600;
80+
cursor:pointer;
81+
transition: transform 120ms ease, box-shadow 120ms ease, opacity 120ms;
82+
min-height:48px;
83+
}
84+
85+
button:hover{
86+
transform:translateY(-3px);
87+
box-shadow:0 8px 18px rgba(0,0,0,0.25);
88+
color: beige;
89+
}
90+
91+
button:active{
92+
transform:translateY(0);
93+
box-shadow:inset 0 3px 6px rgba(0,0,0,0.4);
94+
}
95+
96+
button:focus{
97+
outline:3px solid rgba(255,255,255,0.4);
98+
outline-offset:2px;
99+
}
100+
101+
button.enter{
102+
grid-column:4/5;
103+
background:linear-gradient(180deg,#525456,#717374);
104+
color:#fff;
105+
}
106+
107+
.bottom-row{
108+
display:flex;
109+
gap:8px;
110+
margin-top:10px;
111+
}
112+
113+
.bottom-row button{
114+
flex:1;
115+
padding:12px;
116+
}
117+
118+
.bottom-row {
119+
display:flex;
120+
gap:10px;
121+
margin-top:12px;
122+
justify-content:center;
123+
}
124+
125+
.bottom-row .backspace {
126+
min-width: 92px;
127+
min-height: 44px;
128+
border-radius: 8px;
129+
background: linear-gradient(180deg, #4b4b4b, #353535);
130+
color: #fff;
131+
font-weight: 700;
132+
}
133+
134+
.bottom-row .enter {
135+
min-width: 120px;
136+
min-height: 44px;
137+
border-radius: 8px;
138+
background: linear-gradient(180deg, #dfe9ef, #c6d7e1);
139+
color: #111;
140+
font-weight: 800;
141+
}
142+
143+
@media (max-width:420px){
144+
.calc{
145+
width:320px
146+
}
147+
148+
button{
149+
min-height:56px;
150+
}
151+
}

0 commit comments

Comments
 (0)