آموزش ساخت ماشین حساب با جاوااسکریپت


🎯 اهداف یادگیری

  • آشنایی با اصول اولیه DOM Manipulation
  • یادگیری مدیریت رویدادها در جاوااسکریپت
  • پیاده سازی منطق عملیات ریاضی
  • ساخت یک پروژه عملی و کاربردی

📌 ساختار HTML ماشین حساب

ابتدا ساختار پایه ماشین حساب را با HTML می‌سازیم:

html
<!-- ساختار اصلی ماشین حساب -->
<div class="calculator">
<input type="text" class="display" disabled>
<div class="buttons">
<button class="btn" data-value="7">7</button>
<button class="btn" data-value="8">8</button>
<button class="btn" data-value="9">9</button>
<button class="btn operator" data-value="+">+</button>
<!-- سایر دکمه‌ها -->
</div>
</div>

توضیحات ساختار:

  • ورودی نمایشگر: برای نمایش اعداد و نتایج
  • دکمه‌های اعداد: با data-value برای مقداردهی
  • دکمه‌های عملگرها: کلاس operator برای تشخیص عملگرها

📌 استایل‌دهی با CSS

برای زیباتر شدن ماشین حساب از CSS استفاده می‌کنیم:

css
.calculator {
width: 300px;
margin: 0 auto;
border: 1px solid #ccc;
border-radius: 5px;
padding: 10px;
}
.display {
width: 100%;
height: 40px;
margin-bottom: 10px;
text-align: right;
}
.buttons {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 5px;
}

ویژگی‌های CSS:

  • طرح‌بندی شبکه‌ای: استفاده از Grid برای چیدمان دکمه‌ها
  • طراحی واکنش‌گرا: مناسب برای تمام دستگاه‌ها
  • استایل‌دهی نمایشگر: تراز متن به راست و اندازه مناسب

📌 پیاده‌سازی منطق جاوااسکریپت

حالا به بخش اصلی پروژه یعنی پیاده‌سازی منطق ماشین حساب می‌رسیم:

javascript
// انتخاب المان‌های مورد نیاز
const display = document.querySelector('.display');
const buttons = document.querySelectorAll('.btn');
// متغیرهای محاسبات
let currentInput = '';
let firstOperand = null;
let operator = null;
let waitingForSecondOperand = false;
// افزودن رویداد کلیک به دکمه‌ها
buttons.forEach(button => {
button.addEventListener('click', (e) => {
const value = e.target.getAttribute('data-value');
if (e.target.classList.contains('operator')) {
handleOperator(value);
return;
}
handleNumber(value);
updateDisplay();
});
});

توابع کمکی:

javascript
function handleNumber(number) {
if (waitingForSecondOperand) {
currentInput = number;
waitingForSecondOperand = false;
}else {
currentInput = currentInput === '' ? number : currentInput + number;
}
}
function handleOperator(nextOperator) {
const inputValue = parseFloat(currentInput);
if (operator && waitingForSecondOperand) {
operator = nextOperator;
return;
}
if (firstOperand === null) {
firstOperand = inputValue;
}else {
const result = calculate(firstOperand, inputValue, operator);
currentInput = String(result);
firstOperand = result;
}
waitingForSecondOperand = true;
operator = nextOperator;
}

تابع محاسبات:

javascript
function calculate(firstOperand, secondOperand, operator) {
switch (operator) {
case '+':
return firstOperand + secondOperand;
case '-':
return firstOperand - secondOperand;
case '*':
return firstOperand * secondOperand;
case '/':
return firstOperand / secondOperand;
default:
return secondOperand;
}
}
function updateDisplay() {
display.value = currentInput;
}

ویژگی‌های منطق ماشین حساب:

  • مدیریت وضعیت: پیگیری عملوندها و عملگرها
  • پشتیبانی از عملیات متوالی: امکان انجام چندین محاسبه پشت سر هم
  • خطایابی: مدیریت موارد خاص مانند تقسیم بر صفر

📌 بهبود پروژه

برای حرفه‌ای‌تر شدن پروژه، این ویژگی‌ها را اضافه کنید:

javascript
// دکمه پاک کردن (C)
function clearCalculator() {
currentInput = '';
firstOperand = null;
operator = null;
waitingForSecondOperand = false;
updateDisplay();
}
// دکمه اعشار (.)
function inputDecimal(dot) {
if (waitingForSecondOperand) {
currentInput = '0.';
waitingForSecondOperand = false;
return;
}
if (!currentInput.includes(dot)) {
currentInput += dot;
}
}

ویژگی‌های پیشرفته:

  • پشتیبانی از اعداد اعشاری: استفاده از نقطه اعشار
  • پاک کردن حافظه: قابلیت reset کردن ماشین حساب
  • مدیریت خطاها: نمایش پیام برای عملیات نامعتبر

📌 تمرین عملی

این ویژگی‌ها را به ماشین حساب اضافه کنید:

  1. دکمه درصد (%) برای محاسبه درصد
  2. دکمه تغییر علامت (±)
  3. پشتیبانی از صفحه کلید (اضافه کردن event listener برای کلیدها)
javascript
// راهنمای پیاده‌سازی پشتیبانی از صفحه کلید
document.addEventListener('keydown', (e) => {
if (e.key >= '0' && e.key <= '9') {
handleNumber(e.key);
}else {
switch (e.key) {
case '+':
case '-':
case '*':
case '/':
handleOperator(e.key);
break;
case '.':
inputDecimal(e.key);
break;
case 'Enter':
handleOperator('=');
break;
}
}
updateDisplay();
});