Proje Detayları

Proje Tanımı

Bu projede, temel aritmetik işlemleri (toplama, çıkarma, çarpma, bölme) yapabilen basit bir hesap makinesi uygulaması geliştireceğiz. Proje, DOM manipülasyonu ve olay işleme (event handling) konularını pekiştirmenize yardımcı olacak.

Adım Adım Geliştirme

1 HTML Yapısını Oluşturma

İlk olarak, hesap makinesinin HTML yapısını oluşturalım. Bir ekran (display) ve tuşlar için butonlar içeren bir yapı oluşturacağız.

index.html
<!DOCTYPE html>
<html lang="tr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Basit Hesap Makinesi</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div class="calculator">
        <div class="calculator-display" id="display">0</div>
        <div class="calculator-keys">
            <button class="calculator-key key-clear" id="clear">C</button>
            <button class="calculator-key key-operator" data-operator="/">&divide;</button>
            <button class="calculator-key key-operator" data-operator="*">&times;</button>
            <button class="calculator-key key-operator" data-operator="-">-</button>
            <button class="calculator-key" data-number="7">7</button>
            <button class="calculator-key" data-number="8">8</button>
            <button class="calculator-key" data-number="9">9</button>
            <button class="calculator-key key-operator" data-operator="+">+</button>
            <button class="calculator-key" data-number="4">4</button>
            <button class="calculator-key" data-number="5">5</button>
            <button class="calculator-key" data-number="6">6</button>
            <button class="calculator-key" data-number="1">1</button>
            <button class="calculator-key" data-number="2">2</button>
            <button class="calculator-key" data-number="3">3</button>
            <button class="calculator-key key-equal" id="equal">=</button>
            <button class="calculator-key" data-number="0">0</button>
            <button class="calculator-key" data-number=".">.</button>
        </div>
    </div>
    
    <script src="script.js"></script>
</body>
</html>

Not: HTML yapısında, veri öznitelikleri (data attributes) kullanarak butonların işlevlerini belirtiyoruz. data-number özniteliği sayı tuşlarını, data-operator özniteliği ise operatör tuşlarını belirtiyor. Bu, JavaScript kodunda bu tuşları kolayca seçmemizi sağlayacak.

2 CSS ile Stil Verme

Şimdi, hesap makinesine stil verelim. Grid layout kullanarak tuşları düzenleyeceğiz ve görsel olarak çekici bir arayüz oluşturacağız.

style.css
* {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

body {
    font-family: Arial, sans-serif;
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 100vh;
    background-color: #f5f5f5;
}

.calculator {
    width: 100%;
    max-width: 300px;
    background-color: #f7f7f7;
    border-radius: 10px;
    box-shadow: 0 5px 15px rgba(0,0,0,0.1);
    overflow: hidden;
}

.calculator-display {
    background-color: #333;
    color: white;
    font-size: 2rem;
    padding: 20px;
    text-align: right;
    font-family: 'Courier New', monospace;
}

.calculator-keys {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    grid-gap: 1px;
    background-color: #999;
}

.calculator-key {
    background-color: white;
    border: none;
    padding: 20px;
    font-size: 1.2rem;
    cursor: pointer;
    transition: background-color 0.3s;
}

.calculator-key:hover {
    background-color: #f0f0f0;
}

.key-operator {
    background-color: #f8a51d;
    color: white;
}

.key-operator:hover {
    background-color: #e5951a;
}

.key-equal {
    background-color: #4caf50;
    color: white;
    grid-column: -2;
    grid-row: 2 / span 4;
}

.key-equal:hover {
    background-color: #43a047;
}

.key-clear {
    background-color: #f44336;
    color: white;
}

.key-clear:hover {
    background-color: #e53935;
}

İpucu: CSS Grid, hesap makinesi tuşlarını düzenlemek için mükemmel bir seçenektir. Eşittir (=) tuşunu diğer tuşlardan daha büyük yapmak için grid-column ve grid-row özelliklerini kullanıyoruz.

3 JavaScript ile İşlevsellik Ekleme

Son olarak, JavaScript ile hesap makinesine işlevsellik ekleyelim. Tuşlara tıklandığında gerçekleşecek olayları ve hesaplama mantığını kodlayacağız.

script.js
// DOM elementlerini seçme
const display = document.getElementById('display');
const numberButtons = document.querySelectorAll('[data-number]');
const operatorButtons = document.querySelectorAll('[data-operator]');
const equalButton = document.getElementById('equal');
const clearButton = document.getElementById('clear');

// Hesap makinesi durumu
let firstOperand = null;
let operator = null;
let waitingForSecondOperand = false;

// Ekranı güncelleme fonksiyonu
function updateDisplay(value) {
    display.textContent = value;
}

// Sayı tuşlarına tıklama olayı
numberButtons.forEach(button => {
    button.addEventListener('click', () => {
        const number = button.getAttribute('data-number');
        inputNumber(number);
    });
});

// Operatör tuşlarına tıklama olayı
operatorButtons.forEach(button => {
    button.addEventListener('click', () => {
        const op = button.getAttribute('data-operator');
        inputOperator(op);
    });
});

// Eşittir tuşuna tıklama olayı
equalButton.addEventListener('click', () => {
    calculate();
});

// Temizle tuşuna tıklama olayı
clearButton.addEventListener('click', () => {
    clear();
});

// Sayı girişi işleme
function inputNumber(number) {
    const currentValue = display.textContent;
    
    if (waitingForSecondOperand) {
        updateDisplay(number);
        waitingForSecondOperand = false;
    } else {
        updateDisplay(currentValue === '0' ? number : currentValue + number);
    }
}

// Operatör girişi işleme
function inputOperator(op) {
    const currentValue = parseFloat(display.textContent);
    
    if (operator && waitingForSecondOperand) {
        operator = op;
        return;
    }
    
    if (firstOperand === null) {
        firstOperand = currentValue;
    } else if (operator) {
        const result = calculate();
        updateDisplay(result);
        firstOperand = result;
    }
    
    waitingForSecondOperand = true;
    operator = op;
}

// Hesaplama işlemi
function calculate() {
    if (operator === null || waitingForSecondOperand) {
        return parseFloat(display.textContent);
    }
    
    const secondOperand = parseFloat(display.textContent);
    let result = 0;
    
    switch (operator) {
        case '+':
            result = firstOperand + secondOperand;
            break;
        case '-':
            result = firstOperand - secondOperand;
            break;
        case '*':
            result = firstOperand * secondOperand;
            break;
        case '/':
            if (secondOperand === 0) {
                updateDisplay('Hata');
                clear();
                return;
            }
            result = firstOperand / secondOperand;
            break;
    }
    
    // Sonucu yuvarlama (çok uzun ondalık sayıları önlemek için)
    result = Math.round(result * 1000000) / 1000000;
    
    updateDisplay(result);
    
    // Durumu sıfırlama
    firstOperand = null;
    operator = null;
    waitingForSecondOperand = false;
    
    return result;
}

// Hesap makinesini sıfırlama
function clear() {
    updateDisplay('0');
    firstOperand = null;
    operator = null;
    waitingForSecondOperand = false;
}

// Klavye desteği (bonus)
document.addEventListener('keydown', (event) => {
    const key = event.key;
    
    // Sayılar ve nokta
    if (/[0-9.]/.test(key)) {
        inputNumber(key);
    }
    
    // Operatörler
    if (['+', '-', '*', '/'].includes(key)) {
        inputOperator(key);
    }
    
    // Enter tuşu (=)
    if (key === 'Enter') {
        calculate();
    }
    
    // Escape tuşu (C)
    if (key === 'Escape') {
        clear();
    }
});

Uyarı: Sıfıra bölme durumunu kontrol etmeyi unutmayın. Yukarıdaki kodda, sıfıra bölme durumunda "Hata" mesajı gösteriliyor ve hesap makinesi sıfırlanıyor.

4 Projeyi Test Etme ve Hata Ayıklama

Hesap makinesini oluşturduktan sonra, farklı senaryoları test ederek doğru çalıştığından emin olun:

  • Basit işlemler: 2 + 2 = 4, 5 - 3 = 2, 4 * 3 = 12, 10 / 2 = 5
  • Ardışık işlemler: 2 + 3 * 4 = 14 (2 + 3 = 5, 5 * 4 = 20)
  • Ondalık sayılar: 2.5 + 1.3 = 3.8
  • Sıfıra bölme: 5 / 0 = "Hata"
  • Temizle tuşu: C tuşuna basıldığında hesap makinesi sıfırlanmalı
  • Klavye desteği: Sayılar, operatörler, Enter ve Escape tuşları çalışmalı

Herhangi bir hata veya beklenmeyen davranış tespit ederseniz, JavaScript kodunuzu gözden geçirin ve düzeltin.

5 Bonus Özellikleri Ekleme

Temel hesap makinesi işlevselliğini tamamladıktan sonra, aşağıdaki bonus özellikleri ekleyebilirsiniz:

Yüzde (%) İşlemi

Yüzde İşlemi Ekleme
// HTML'e yüzde tuşu ekleyin
// <button class="calculator-key key-operator" data-operator="%">%</button>

// JavaScript'te calculate fonksiyonuna yüzde işlemini ekleyin
case '%':
    result = firstOperand * (secondOperand / 100);
    break;

Pozitif/Negatif Değiştirme (+/-)

Pozitif/Negatif Değiştirme Ekleme
// HTML'e +/- tuşu ekleyin
// <button class="calculator-key" id="toggle-sign">+/-</button>

// JavaScript'te +/- tuşu için olay dinleyici ekleyin
document.getElementById('toggle-sign').addEventListener('click', () => {
    const currentValue = parseFloat(display.textContent);
    updateDisplay(-currentValue);
});

İşlem Geçmişi

İşlem Geçmişi Ekleme
// HTML'e işlem geçmişi için bir element ekleyin
// <div class="calculator-history" id="history"></div>

// JavaScript'te işlem geçmişi için değişkenler ve fonksiyonlar ekleyin
const history = document.getElementById('history');
let historyList = [];

function addToHistory(calculation, result) {
    historyList.push(`${calculation} = ${result}`);
    updateHistory();
}

function updateHistory() {
    history.innerHTML = '';
    historyList.forEach(item => {
        const historyItem = document.createElement('div');
        historyItem.textContent = item;
        history.appendChild(historyItem);
    });
}

// calculate fonksiyonunda sonuç hesaplandıktan sonra geçmişe ekleyin
addToHistory(`${firstOperand} ${operator} ${secondOperand}`, result);

Proje Zorlukları ve Çözümleri

Zorluk 1: Ardışık İşlemler

Hesap makinelerinde, bir işlem tamamlandıktan sonra başka bir işlem yapılabilir. Örneğin, 2 + 3 = 5 işleminden sonra, 5 * 4 = 20 işlemi yapılabilir. Bu durumu doğru bir şekilde yönetmek önemlidir.

Çözüm: inputOperator fonksiyonunda, eğer zaten bir operatör ve ilk operand varsa, calculate fonksiyonunu çağırarak mevcut işlemi tamamlayın ve sonucu yeni ilk operand olarak kullanın.

Zorluk 2: Ondalık Sayılar

JavaScript'te ondalık sayılarla çalışırken, bazen beklenmeyen sonuçlar alabilirsiniz. Örneğin, 0.1 + 0.2 = 0.30000000000000004 gibi.

Çözüm: Sonuçları belirli bir hassasiyetle yuvarlayarak bu sorunu çözebilirsiniz. Yukarıdaki kodda, Math.round(result * 1000000) / 1000000 kullanarak sonucu 6 ondalık basamağa yuvarlıyoruz.

Zorluk 3: Sıfıra Bölme

Matematiksel olarak, bir sayıyı sıfıra bölmek tanımsızdır ve JavaScript'te Infinity değeri döndürür.

Çözüm: Bölme işlemi yapmadan önce, ikinci operandın sıfır olup olmadığını kontrol edin. Eğer sıfırsa, bir hata mesajı gösterin ve hesap makinesini sıfırlayın.

Geliştirme İpuçları

  • Modüler Kod Yazın: Kodunuzu küçük, anlaşılır fonksiyonlara bölün. Her fonksiyon tek bir işi yapmalıdır.
  • Durum Yönetimi: Hesap makinesinin durumunu (ilk operand, operatör, ikinci operand bekleniyor mu vb.) doğru bir şekilde yönetin.
  • Hata Kontrolü: Sıfıra bölme gibi hata durumlarını kontrol edin ve kullanıcıya uygun mesajlar gösterin.
  • Kullanıcı Deneyimi: Hesap makinesinin kullanımını kolaylaştırmak için klavye desteği ekleyin.
  • Görsel Geri Bildirim: Tuşlara tıklandığında görsel geri bildirim sağlayın (hover efektleri, aktif durum stilleri vb.).

Proje Genişletme Fikirleri

  • Bilimsel Hesap Makinesi: Trigonometrik fonksiyonlar (sin, cos, tan), logaritma, karekök, üs alma gibi bilimsel hesap makinesi özellikleri ekleyin.
  • Tema Değiştirme: Kullanıcının açık/koyu tema arasında geçiş yapabilmesini sağlayın.
  • Hafıza Fonksiyonları: M+, M-, MR, MC gibi hafıza fonksiyonları ekleyin.
  • İşlem Geçmişi: Yapılan işlemlerin geçmişini gösterin ve geçmişteki işlemleri tekrar kullanabilme özelliği ekleyin.
  • Parantez Desteği: Matematiksel işlem önceliğini değiştirmek için parantez kullanımı ekleyin.