Verdiğiniz JavaScript kurs müfredat dosyasını belirttiğiniz tüm kurallara uyarak (dakika/saniye bilgilerini kaldırarak, "Önizleme" ve "ders" satırlarını ele dışı bırakarak) satır satır ve en detaylı şekilde incelemeye başlıyoruz.
Bu rehber, bir yazılımcı dostunuz olarak konularda hiçbir özet yapmadan, her bölüme özel teorik açıklamalar, günlük hayat benzetmeleri (analojiler), kod örnekleri ve uygulamalar içerir.
Kursun başındaki bu giriş kısmı, bir öğrencinin bu eğitimi bitirdiğinde hangi becerilere sahip olacağını gösteren bir yol haritasıdır. Maddeleri tek tek inceleyelim:
JavaScript'e Başlamak İçin Mükemmel - Kod Yazmanızı Sağlayacak Başlangıç Projeleriyle Dolu: Bu kurs sıfırdan başlar. Sadece teorik bilgi vermez, sizi hemen klavye başına oturtup küçük projelerle kod yazmaya alıştırır.
DOM (Document Object Model) Konusunda Uzmanlaşın: DOM, JavaScript'in HTML sayfasına dokunmasını sağlayan bir köprüdür. Bu köprüyü sonuna kadar kullanmayı öğreneceksiniz.
Saf JavaScript Kullanarak DOM Etkileşimi İçeren, 50'den Fazla Gerçek Dünya Projesiyle Modüler Öğrenme Bölümleri: Kurs modüllerden oluşur. Dışarıdan hiçbir hazır kütüphane (JQuery, React vb.) almadan, sadece ham (Pure/Vanilla) JavaScript ile 50'den fazla proje yapacaksınız.
Sıfırdan EĞLENCELİ Gerçek Dünya JavaScript Projeleri İnşa Ederken JavaScript'i Nasıl Öğrenebileceğinizi Keşfedin: Sıkıcı teoriler yerine, oyunlar ve çalışan uygulamalar yaparak kodlamayı kalıcı olarak öğreneceksiniz.
JavaScript Nasıl Kullanılır ve JavaScript Arka Planda Nasıl Çalışır?: Yazdığınız kodun tarayıcı tarafından nasıl yorumlandığını, bilgisayarın hafızasında neler döndüğünü derinlemesine anlayacaksınız.
JavaScript Belge Nesnesi Modelini (DOM) Keşfedin, Etkileşimli ve Dinamik Web Sayfaları Yapın: Kullanıcı bir butona bastığında sayfa yenilenmeden verilerin değiştiği, canlanan web siteleri kuracaksınız.
JavaScript Kullanarak Öğeleri Yönetin - Web Sayfalarınıza JavaScript ile HAYAT Verin: Sayfadaki bir yazıyı büyütmek, bir resmi gizlemek veya rengini değiştirmek gibi tüm kontrol sizde olacak.
Dinamik Olarak Öğeler Nasıl Oluşturulur ve Dahası - Oluşturulacak Oyunlar ve Harika Projelerle: HTML dosyasında hiç yokken, JavaScript koduyla havadan yeni butonlar, listeler veya kutular var etmeyi öğreneceksiniz.
Değişkenler, Boolean Mantığı, If/Else, Döngüler, Fonksiyonlar, Diziler vb. Temel JavaScript Becerilerini Geliştirin: Programlamanın alfabesi olan temel kuralları sağlam bir şekilde oturtacaksınız.
Tam Bir Yeni Başlayandan İleri Düzey Bir JavaScript Geliştiricisine Doğru İlerleyin: Bilgisayarda sadece klasör açmayı bilen birinden, karmaşık mantık yürüten bir yazılımcıya dönüşüm hedeflenir.
JavaScript ve Programlama Temelleri: Bilgisayar gibi düşünmeyi ve algoritmik zekayı kazanacaksınız.
Hem ES5 Hem de ES6+ ile Gerçek Dünya Uygulamaları Oluşturun: JavaScript'in eski yazım tarzını (ES5) ve günümüzün modern, hızlı yazım tarzını (ES6 ve sonrası) öğreneceksiniz.
2020 İçin Modern JavaScript: Güncel standartlara uygun temiz kod yazma becerisi kazanacaksınız.
Kaynak Kod Dahil - Kendi Uygulama Sürümünüzü BUGÜN İnşa Edin: Kurs size kodları hazır verir ancak amaç sizin kendi hayal gücünüzle bu kodları değiştirip kendi portfolyonuzu oluşturmanızdır.
Bu bölüm, yazılım dünyasına adım attığınız yerdir. Gerekli araç gereçleri bilgisayarımıza kurup ilk kod ortamını hazırlarız.
Yazılımcıların kodlarını yazdığı, onlara renkler ve ipuçları vererek kolaylık sağlayan gelişmiş bir gelişmiş not defteridir. Tıpkı bir terzinin dikiş makinesi gibidir.
💻 Uygulama: Bilgisayara VS Code kurulur. JavaScript kodlarını tarayıcıda canlı görmek için "Live Server" eklentisi aktif edilir.
Burası programlamanın temel yapı taşlarını öğrendiğimiz mutfaktır.
JavaScript, web sayfalarını hareket ettiren beyindir. HTML kemik (yapı), CSS elbise (görünüm), JavaScript ise kas sistemidir (hareket).
JavaScript kodları HTML sayfasına
<script>
etiketi ile bağlanır. Yorum satırları ise bilgisayarın
okumadığı, sadece yazılımcıların kendilerine not bırakmak
için kullandığı alanlardır. Tıpkı bir yemek tarifinin kenarına
"burayı çok pişirme" notu düşmek gibidir.
// Bu tek satırlık bir yorumdur. Bilgisayar burayı görmezden gelir./*Bu ise çok satırlıbir yorum alanıdır.*/
Değişkenler, bilgisayarın hafızasındaki küçük kutulardır. İçlerine bilgi koyarız.
let:
İçindeki değer sonradan değiştirilebilen kutudur.
const:
İçindeki değer asla değiştirilemeyen, sabit kutudur (Constant).
Günlük Hayat Analojisi:
Bir yolcunun yaşı her yıl değiştiği için let
ile tutulur, T.C. kimlik numarası hiç değişmediği için const
ile tutulur.
letkullaniciYasi=25;kullaniciYasi =26;// Bu işlem yapılabilir.constdogumYili=1999;// dogumYili = 2000; // HATA! Sabit değer değiştirilemez.
prompt:
Kullanıcıdan tarayıcı aracılığıyla yazı veya sayı almak
için açılan küçük girdi kutusudur.
Template
Literal: Yazılar ile değişkenleri birbirine
kolayca bağlamamızı sağlayan ters tırnak (`)
yöntemidir.
💻 Uygulama: Kullanıcıdan ismini alıp ona özel karşılama mesajı hazırlayalım.
letisim= prompt("Lütfen adınızı giriniz:");// Eski yöntem (ES5):console.log("Merhaba "+ isim +", hoş geldin!");// Modern yöntem (Template Literal - ES6+):console.log(`Merhaba ${isim}, hoş geldin!`);
Matematiksel işlemler (+, -, *, /) ve durum karşılaştırmaları yapmak için kullanılır.
==
: Değerler eşit mi?
===
: Hem değerler hem de veri tipleri (yazı mı sayı mı olduğu)
tamamen aynı mı?
letsayi=5;letyazi="5";console.log(sayi == yazi);// true (Çünkü ikisi de özünde 5)console.log(sayi === yazi);// false (Çünkü biri sayı, biri yazı tipinde)
Karar verme mekanizmalarıdır.
"Eğer hava yağmurluysa şemsiye al, değilse gözlük al"
mantığıyla çalışır. Ternary,
tek satırda hızlıca if-else yazma yoludur.
// Normal If-Elseletyas=18;if(yas >=18) {console.log("Ehliyet alabilirsin.");}else{console.log("Yaşın henüz küçük.");}// Ternary Operatörü Kullanımıletmesaj= (yas >=18) ?"Ehliyet alabilirsin.":"Yaşın henüz küçük.";console.log(mesaj);
Fonksiyonlar, tekrar tekrar
kullanılabilen küçük fabrikalardır. İçine hammadde (parametre)
verirsiniz, size işlenmiş ürün (return)
verir. Arrow
Function
ise modern, kısa yazım şeklidir.
// Modern Arrow Function ve Return KullanımıconstkareAl= (sayi) => {returnsayi * sayi;};letsonuc= kareAl(4);// sonuc kutusuna 16 yüklenir.console.log(sonuc);
Scope: Bir değişkenin nerede yaşayabildiğini belirler. Fonksiyon içinde tanımlanan değişken dışarıda okunamaz (Local Scope).
Recursion: Bir fonksiyonun kendi kendisini tekrar çağırmasıdır. Sonsuz bir döngü gibi çalışabilir, bu yüzden durma noktası iyi belirlenmelidir.
// Rekürsiyon ile Faktöriyel Hesaplama Örneğifunctionfaktoriyel(n) {if(n ===1)return1;// Durma noktasıreturnn * faktoriyel(n -1);}console.log(faktoriyel(5));// 120 sonucunu verir.
Tanımlandığı anda kendiliğinden hemen çalışan, isim verilmesi zorunlu olmayan gizli fonksiyonlardır. Sayfa açılır açılır çalışmasını istediğimiz ayarlar için kullanılır.
(function() {console.log("Sayfa yüklendi, bu fonksiyon hemen çalıştı!");})();
Dizi (Array): Tek bir kutuda birden fazla veriyi sırayla saklama listesidir. Alışveriş listesi gibi düşünülebilir.
Obje (Object): Bir varlığın tüm özelliklerini detaylı saklayan yapılardır. Bir arabanın rengi, modeli ve hızı gibi.
// Dizi Örneğiletmeyveler= ["Elma","Armut","Muz"];// Obje Örneğiletaraba= {marka:"Toyota",model:"Corolla",yil:2022,calis:function() {console.log("Araba çalıştı...");}};console.log(araba.marka);// Toyotaaraba.calis();// Objeye ait fonksiyonu çalıştırır.
Diziler üzerinde arama yapmak, her elemanı değiştirmek veya listeyi dönmek için kullanılan modern süper güçlerdir.
map:
Tüm elemanları tek tek elden geçirip yeni bir liste üretir.
filter:
Belirli bir kurala uyan elemanları ayıklayıp yeni bir liste
yapar.
letsayilar=;// Sadece çift sayıları filtreleyelimletciftler= sayilar.filter(sayi => sayi %2===0);// [2, 4, 6]// Her sayının iki katını alalımletikiKati= sayilar.map(sayi => sayi *2);// [2, 4, 6, 8, 10, 12]
Bu bölümde ekran üzerindeki HTML elementlerini kontrol etmeyi, değiştirmeyi öğreniyoruz.
JavaScript'in HTML elementini bulması işlemine seçim denir. Onu değiştirmesine ise manipülasyon denir.
document.querySelector():
HTML sayfasındaki kimlik (id) veya sınıfa (class) göre tek bir
elementi yakalar.
// HTML'deki id'si "baslik" olan yazıyı seçelim ve rengini değiştirelimconstanaBaslik= document.querySelector("#baslik");anaBaslik.textContent ="Yeni Başlık JavaScript ile Yazıldı!";anaBaslik.style.color ="red";// Yazıyı kırmızı yapar.
HTML elementleri birbirinin içinde yaşar (Anne/Baba ve Çocuk ilişkisi). Bir elementi seçip onun üst sınırına (Parent) veya içindeki alt öğelerine (Children) kodla ulaşabiliriz.
Kullanıcının yaptığı tıklama, fareyi oynatma veya klavyeden bir tuşa basma hareketlerine "Event" (Olay) denir. JavaScript bu hareketleri pusuya yatarak dinler.
💻 Uygulama: Bir butona basıldığında sayfada yeni bir liste elemanı oluşturalım.
constbuton= document.querySelector("#ekleButon");constliste= document.querySelector("#benimListem");buton.addEventListener("click",function(event) {// event nesnesi tıklamanın nerede yapıldığı bilgisini taşır.constyeniMadde= document.createElement("li");// Havadan li elementi oluşturduk.yeniMadde.textContent ="Yeni Alışveriş Maddesi";liste.appendChild(yeniMadde);// Listeye ekledik.});
Bir elemente tıkladığınızda, o
element bir kutunun içindeyse, tıklama olayı dıştaki kutuya da
bulaşır. Buna kabarcıklanma denir. Sudan çıkan bir hava
kabarcığının yukarı doğru çıkması gibidir.
event.stopPropagation()
ile bu bulaşma engellenebilir.
Yazıları parçalamak, büyütmek veya sayıları yuvarlamak için hazır fonksiyonlardır.
Math.random():
0 ile 1 arasında rastgele bir sayı üretir. Oyunların temelidir.
Math.floor():
Ondalıklı sayıları aşağıya tam sayıya yuvarlar.
let rastgeleSayi = Math.floor(Math.random() * 10) + 1; // 1 ile 10 arasında rastgele tam sayı üretir.LocalStorage:
Tarayıcının hafızasıdır. Tarayıcı kapansa bile veriler
burada saklı kalır.
JSON.stringify:
Bir objeyi yazıya dönüştürür (Hafızaya kaydetmek için).
JSON.parse:
Yazıyı tekrar objeye çevirir (Hafızadan okumak için).
letkullanici= {isim:"Ahmet",skor:90};// Hafızaya kaydetmelocalStorage.setItem("aktifKullanici", JSON.stringify(kullanici));// Hafızadan geri okumaletgelenVeri= localStorage.getItem("aktifKullanici");letorjinalObje= JSON.parse(gelenVeri);console.log(orjinalObje.isim);// Ahmet
setTimeout:
Belirli bir süre bekleyip ardından bir kez çalışır.
setInterval:
Belirli aralıklarla durmadan tekrarlayarak çalışır
(Saatler ve kronometreler için).
// 3 saniye sonra ekrana uyarı versetTimeout(() => {console.log("3 saniye doldu!");},3000);
Bir yazı bloğunun içinde belirli kurallara uyan kelimeleri arama yöntemidir. Örneğin girilen metnin gerçekten bir e-posta adresi olup olmadığını denetlemek için kullanılır.
Yazdığımız kodda ani bir hata oluştuğunda programın tamamen çökmesini engelleyen güvenlik duvarıdır.
try{// Hata yapma ihtimali olan kod bloğuolmayanFonksiyonuCalistir();}catch(error) {// Hata olursa burası çalışır ve hata mesajını basar, kod çökmez.console.log("Bir hata meydana geldi: "+ error.message);}
İnternetteki başka bir sunucudan
sayfayı yenilemeden canlı veri çekme (Hava durumu verisi, döviz
kuru vb.) teknolojisidir. Modern dünyada fetch
yöntemi kullanılır.
// Fetch ile internetten veri çekme örneğifetch("https://github.com").then(cevap => cevap.json()).then(veri => console.log(`Kullanıcı Adı: ${veri.name}`)).catch(hata => console.log("Hata oldu:", hata));
Canvas, web sayfasında üzerine kodla resim, çizgi ve animasyon yapabileceğimiz boş bir dijital tuvaldir. Oyun grafikleri burada çizilir.
💻 Uygulama: Canvas
üzerinde hareket eden bir kutu yapımı ve requestAnimationFrame
kullanımı. requestAnimationFrame,
tarayıcının ekran yenileme hızına göre animasyonları akıcı
oynatan modern bir motordur.
constcanvas= document.querySelector("#oyunAlani");constctx= canvas.getContext("2d");letx=10;functionanimasyon() {ctx.clearRect(0,0, canvas.width, canvas.height);// Ekranı temizlectx.fillStyle ="blue";ctx.fillRect(x,50,50,50);// Mavi kutu çizx +=2;// Kutuyu sağa kaydırrequestAnimationFrame(animasyon);// Sürekli tekrarla}// animasyon(); // Tetiklendiğinde kutu kaymaya başlar.
Bu kısımdan sonra kurs içerisindeki uygulamaların çalışma mantıklarını kurup kod bloklarını ayağa kaldırıyoruz.
Kullanıcının hesap tutarını ve memnuniyet oranını girerek ödenecek bahşişi anlık hesapladığı uygulamadır.
// Mantık: Tutar ile oran çarpılır, kişi sayısına bölünür.functionbahsisHesapla(tutar,servisYuzdesi) {returntutar * (servisYuzdesi /100);}console.log(`Ödenecek Bahşiş: ${bahsisHesapla(500,15)} TL`);// 75 TL
Kullanıcının bilgisayar saatine bakar. Sabah ise "Günaydın", akşam ise "İyi Akşamlar" yazar ve sayfa arka plan rengini zamana göre gece moduna veya gündüz moduna alır.
constsaat=newDate().getHours();letmesaj="";if(saat <12) {mesaj ="Günaydın!";document.body.style.backgroundColor ="#lightyellow";}elseif(saat <18) {mesaj ="Tünaydın!";}else{mesaj ="İyi Akşamlar!";document.body.style.backgroundColor ="#2c3e50";// Gece koyuluğu}console.log(mesaj);
Bilgisayarın Math.random
ile 0 veya 1 seçerek "Yazı" veya "Tura" tahmini
yaptığı oyun simülasyonudur.
functionyaziTuraAt() {letsonuc= Math.random() <0.5?"Yazı":"Tura";console.log(`Para döndü ve geldi: ${sonuc}`);}yaziTuraAt();
Kullanıcının seçimi ile bilgisayarın rastgele ürettiği seçimi karşılaştırıp kazananı skor tablosuna işleyen sistemdir.
constsecenekler= ["Taş","Kağıt","Makas"];letbilgisayarSecimi= secenekler[Math.floor(Math.random() *3)];console.log(`Bilgisayarın Hamlesi: ${bilgisayarSecimi}`);
JavaScript ile sayfada hiç zar
yokken HTML elementlerini (document.createElement)
kullanarak kare şeklinde zarlar oluşturur ve içine gelen sayı
kadar küçük noktalar (daireler) çizer.
Sayfada birden fazla buton oluşturur. Her butona tıklandığında ona tanımlı olan kısa mp3 ses dosyasını (örneğin alkış, davul, hata sesi) oynatır.
letses=newAudio("alkis.mp3");// ses.play(); // Sesi çalar.
Ekrana rastgele uzun bir cümle
getirir. Kullanıcı yazmaya başladığı an Date
nesnesi ile zamanı tutar. Kullanıcı cümleyi bitirdiğinde geçen
süreyi hesaplayıp dakika başına kelime hızını (WPM) ölçer.
Klavyedeki yön tuşlarını
(keydown
olayı) dinleyerek ekrandaki bir karakter resmini veya kutuyu duvar
sınırlarına çarpmayacak şekilde oyun alanında yürütür.
Kullanıcı bir soru yazar, butona tıklar. İçerideki dizi içerisinden rastgele ("Kesinlikle evet", "Daha sonra tekrar dene", "Asla") gibi cevaplar ekrana animasyonla gelir.
Sıkça sorulan sorular
sayfalarında gördüğümüz, başlığa tıklayınca altındaki
cevabın aşağı doğru süzülerek açıldığı, diğer açık
olanların ise kapandığı sistemdir. classList.toggle("active")
komutuyla yapılır.
Bilgisayar gizli bir 3 basamaklı sayı tutar. Kullanıcı yukarı aşağı butonlarıyla sayıları tahmin etmeye çalışır. JavaScript "Daha büyük bir sayı gir" veya "Kilit açıldı" şeklinde ipuçları basar.
Bir kelimenin harflerinin yerini
karmaşık hale getirir (Array.sort(()
=> Math.random() - 0.5)).
Kullanıcıdan orijinal kelimeyi tahmin etmesini ister.
Belirli bir gelecekteki tarihe (Örneğin yılbaşı gecesine) ne kadar gün, saat, dakika ve saniye kaldığını matematiksel hesaplamalarla her saniye ekranda günceller.
Ekranda renkli kutular sırayla yanar söner (Simond Says oyunu gibi). Kullanıcıdan bilgisayarın yaktığı sırayı hafızasında tutup aynı düzende kutulara tıklaması istenir.
Ekranda rastgele yerlerde ve hızlarda sürekli balonlar veya ikonlar belirir. Kullanıcı süre bitmeden onlara tıklayarak patlatmaya ve skor toplamaya çalışır.
Deste oluşturulur. Ekrandaki karttan bir sonraki çekilecek kartın değerinin daha mı yüksek daha mı düşük olacağını tahmin etme oyunudur.
Tamamen JavaScript ile yapılmış
dikey bir oyundur. Yukarı ok tuşuyla araba hızlanır, yol
şeritleri aşağı doğru kayarak hareket illüzyonu yaratır.
Karşıdan gelen arabalara çarpma kontrolü (Collision
Detection)
mesafeler ölçülerek yapılır.
Bir mesaj kutusuna (textarea) yazı yazıldıkça kaç harf hakkı kaldığını söyler. Sınır yaklaştığında yazıyı sarıya, sınır bittiğinde kırmızıya boyar ve yazmayı engeller.
Haber sitelerindeki alt bant gibi,
yazıların ekranın altından durmadan sola doğru akmasını
sağlar. Fare üzerine gelince akış durur (mouseover),
fare çekilince devam eder.
Ekrandaki elementleri fareyle tutup
ekran üzerinde herhangi bir yere sürüklememizi, çöp kutusu
görselinin üzerine bıraktığımızda ise o elementi sayfadan
tamamen silmemizi (Element.remove())
sağlar.
Gizli kelime kadar ekrana alt çizgi koyar. Alfabedeki harf butonlarına tıklandıkça harf kontrolü yapılır. Bilemedikçe adam asılma aşamaları görsel olarak güncellenir.
Sayfanın ortasında açılan, arkadaki her şeyi karartan modern uyarı pencereleridir. Kapatma butonuna basıldığında CSS sınıfları kaldırılarak gizlenir.
İleri ve geri ok butonlarına basıldığında resimlerin sırayla değiştiği, altında hangi resimde olduğumuzu gösteren küçük noktaların (indikatörler) yandığı slayt gösterisidir.
Ürün yorumlarında olan 5
yıldızlı sistemdir. Fareyle 3. yıldızın üzerine gelirseniz ilk
3 yıldız parlar (mouseover),
tıkladığınızda o puan sabitlenir (click).
Ekranın üstünde sağa sola giden bir uçaktan boşluk tuşuyla bombalar bırakarak yerdeki hedefleri vurmaya çalıştığınız hareketli bir DOM oyunudur.
Oyun alanı içinde sürekli kaçan akıllı bir hedef kutu vardır. Kullanıcı kendi kutusunu yön tuşlarıyla hareket ettirerek kaçan kutuyu yakalamaya çalışır. Her yakalamada skor artar ve hedef başka yere ışınlanır.
Bir kelimenin üzerine fareyle
gelindiğinde, farenin hemen yanında siyah küçük bir açıklama
balonu açılır. Farenin koordinatları (event.pageX,
event.pageY)
alınarak konumlandırılır.
Kullanıcı karmaşık, upuzun bir yazı yapıştırır. JavaScript içerideki düzenli ifadeleri (RegEx) tarayarak sadece e-posta adreslerini cımbızla çeker gibi ayıklar ve listeler. Çift kayıtları eler.
Ekrandaki rakam ve işlem
butonlarına basılarak matematiksel işlemler yapılan bir
uygulamadır. Arka planda eval()
metodu kullanılarak formüller sonuçlandırılır.
Listeye yeni eleman ekleme, eklenen
elemanın yanındaki "Sil" butonuna basınca uçurma ve
elemanın üzerine çift tıklayınca anında düzenlenebilir yazı
kutusuna dönüştürme (contenteditable)
özelliklerine sahiptir.
Kullanıcı genişlik, yükseklik ve renk seçer. JavaScript ona test çalışmalarında kullanabileceği dinamik bir resim url adresi üretip ekrana basar.
Kullanıcı kayıt olurken şifrenin uzunluğunu, e-postada "@" işareti olup olmadığını denetler. Eğer kurallara uymuyorsa formu göndermez ve kutuların altına kırmızı uyarılar yazar.
Kullanıcının tarayıcısına küçük bilgi kırıntıları (çerez/cookie) bırakmasını, bu çerezlerin son kullanma tarihlerini ayarlamasını ve silmesini sağlayan yönetim panelidir.
Kullanıcının açılır menüden (Select Box) seçim yaparak sayfaya anında yeni butonlar, yeni inputlar ekleyebildiği veya silebildiği, DOM sınırlarını zorlayan bir yönetim aracıdır.
Tablo halindeki verileri
virgüllerle ayrılmış metin dosyası biçimine (.csv)
dönüştürüp kullanıcının bilgisayarına dosya olarak
indirmesini sağlayan veri transfer projesidir.
Boşluk tuşuna bastıkça yukarı zıplayan, basmayınca yerçekimiyle düşen bir kuşun, karşıdan gelen engellerin arasından geçmesini sağlayan çarpışma algılamalı tam fonksiyonel oyundur.
Bilgisayar 1-100 arası sayı tutar. Kullanıcı tahmin eder. "Yukarı", "Aşağı" yönlendirmeleriyle haklar azalarak sayı bulunmaya çalışılır.
Klasik atari oyunudur. Ekranın üstündeki uzaylı ordusu sağa sola giderek aşağı yaklaşır. Aşağıdaki oyuncu sağa sola kaçarak uzaylıları mermilerle vurup yok eder.
52'lik deste karıştırılır ve iki oyuncuya dağıtılır. Butona basıldığında kartlar açılır, değeri büyük olan kartı alan o elin puanını kapar. Deste bitene kadar savaş sürer.
Kullanıcı arama kutusuna bir kelime yazar. Kod, YouTube sunucularına arka planda bağlanarak gelen video sonuçlarını başlıkları ve küçük resimleriyle sayfaya listeler. Sayfalama (Sonraki sayfa) mantığını içerir.
Alttaki tahtayı fareyle sağa sola oynatarak zıplayan topu düşürmemeye çalışırsınız. Top yukarıdaki tuğlalara çarptıkça tuğlalar kırılır ve yok olur.
JavaScript'teki class
(Sınıf) yapılarını öğreniriz. Ürünler ve Alışveriş sepeti
birer yazılımsal nesne olarak kurgulanır. Sepete ekle, adeti
arttır, KDV hesapla gibi işler fonksiyonel objeler üzerinden
yürütülür.
Ekranda 24 adet kapalı kutu oluşturulur. Kullanıcı bir kutu seçer. Ardından diğer kutuları tek tek açarak büyük ödülleri eler. Belirli turlarda banka kullanıcıya teklif sunar ("Kabul" veya "Reddet").
Kullanıcı fare tekerleğiyle sayfanın en altına geldiğinde, JavaScript bunu fark eder ve internetten yeni veri (örneğin yeni Instagram fotoğrafları gibi) çekip sayfanın altına otomatik ekler. Sayfa hiç bitmez.
Yazılımsal olarak iskambil
kartları oluşturulur, karıştırılır (Shuffle).
Oyuncu "Kart Al" veya "Kal" der. Kurpiyerin
elindeki sayılarla karşılaştırılıp 21'e en yakın olan veya
tam 21 yapan kazanır, bahisler ödenir.
Bu kısım mülakatlarda (iş görüşmelerinde) karşımıza çıkan kıdemli yazılımcı konularını içerir.
JavaScript'te bir objeyi direkt
başka bir değişkene eşitlerseniz, sadece adresini kopyalarsınız.
Birinde yapılan değişiklik diğerini de bozar (Shallow Copy).
deepClone
fonksiyonu hafızada tamamen bağımsız yeni bir kopya oluşturur.
functiondeepClone(obj) {returnJSON.parse(JSON.stringify(obj));}letorijinal= {ad:"Can",detay: {yas:30} };letkopya= deepClone(orijinal);kopya.detay.yas =31;// Orijinaldeki yaş hala 30 kalır, bozulmaz.
Asenkron işlemlerin (zaman alan
işlerin) bittiğinde bize olumlu (resolve)
veya olumsuz (reject)
cevap dönmesini sağlayan, zincirleme .then()
komutlarıyla birbirine bağlanan JavaScript söz verme motorunun ham
halini sıfırdan kodlamaktır.
Kullanıcı klavyede yazı yazarken, o her harfe bastığında internette arama yaparsak sistem çöker. Debounce, kullanıcının tuşlara basmayı tamamen bitirmesini bekler (Örneğin yarım saniye duraksadıysa), ardından tek bir defa işlem yapar.
functiondebounce(fn,beklemeSuresi) {letzamanlayici;returnfunction(...args) {clearTimeout(zamanlayici);zamanlayici = setTimeout(() => fn.apply(this, args), beklemeSuresi);};}
Özellikle sayfa aşağı
kaydırılırken (scroll
olayı) tarayıcı salaniyede yüzlerce kez kod çalıştırır.
Throttle, bu tetiklenme ne kadar çok olursa olsun, fonksiyonun
sadece belirlenen süre aralığında (örneğin 200 milisaniyede
bir) en fazla bir kez çalışmasını zorunlu kılar. Tarayıcıyı
rahatlatır.
Sayfa yenilenmeden, sadece üstteki
URL kısmındaki diyez (#about,
#contact)
işaretine bakarak ekranın ortasındaki içeriği dinamik
değiştiren, dış kütüphanesiz Single Page Application (SPA) alt
yapısı kurmaktır.
Bir web sayfasında 100 tane büyük
resim varsa, site ilk açıldığında hepsi yüklenirse internet
çöker. Bu kod, kullanıcının ekranı aşağı kaydırıp ilgili
resmin kutusunun yanına gelip gelmediğini kontrol eder
(getBoundingClientRect).
Resim ekrana girdiği an gerçek resmi yükler.
İç içe geçmiş kutular gibi
duran dizileri tek katmanlı hale getirme işlemidir. Rekürsiyon ve
.reduce()
yöntemi kullanılır.
// Örnek girdi: [1, [2, [3, 4]], 5]// Çıktı: [1, 2, 3, 4, 5]functionduzlestir(dizi) {returndizi.reduce((acc,eleman) =>Array.isArray(eleman) ? acc.concat(duzlestir(eleman)) : acc.concat(eleman), []);}console.log(duzlestir([1, [2,3],4]));// [1, 2, 3, 4]
Çok parametreli bir fonksiyonu, her seferinde tek bir parametre alan ve geriye yeni bir fonksiyon döndüren zincirleme bir yapıya dönüştürme sanatıdır. Fonksiyonel programlamanın temel ileri düzey tekniğidir.
// Normal: topla(2, 3) yerine Currying: topla(2)(3)consttopla= a => b => a + b;console.log(topla(5)(10));// 15 sonucunu verir.
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
Müfredatta yer alan 45 projenin tamamını tek bir seferde tek bir mesaja sığdırmak, yapay zeka hafıza ve karakter sınırları (output token limitleri) nedeniyle teknik olarak imkansızdır. Kodların kesilmemesi, eksik kalmaması ve tarayıcınızda doğrudan çift tıklayarak sorunsuz çalışabilmesi için projeleri bölüm bölüm ve sırayla inşa etmemiz gerekiyor.
İlk aşamada, kursun temelini ve ilk dinamik uygulamalarını oluşturan İlk 5 Projeyi tüm HTML, CSS ve JavaScript kodları tek bir dosyada olacak şekilde (kopyala-yapıştır yapıp çalıştırabileceğiniz biçimde) aşağıda hazırladım.
Dosya Adı:
1-bahsis-hesaplayici.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Bahşiş Hesaplayıcı</title><style>body {font-family:'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;background-color: #f4f7f6;display: flex;justify-content: center;align-items: center;height:100vh;margin:0;}.container {background-color: white;padding:30px;border-radius:12px;box-shadow:08px24px rgba(0,0,0,0.1);width:350px;}h2{ text-align: center; color: #2c3e50; margin-top:0; }.form-group { margin-bottom:20px; }label { display: block; margin-bottom:8px; color: #7f8c8d; font-weight: bold; }input, select {width:100%;padding:10px;border:2px solid #bdc3c7;border-radius:6px;box-sizing: border-box;font-size:16px;}button {width:100%;background-color: #2ecc71;color: white;border: none;padding:12px;border-radius:6px;font-size:18px;cursor: pointer;transition: background0.2s;}button:hover { background-color: #27ae60; }.result {margin-top:20px;padding:15px;background-color: #e8f8f5;border-radius:6px;text-align: center;font-size:18px;font-weight: bold;color: #16a085;display: none;}</style></head><body><divclass="container"><h2>Bahşiş Hesapla</h2><divclass="form-group"><labelfor="bill">Hesap Tutarı (TL)</label><inputtype="number"id="bill"placeholder="Örn: 250"></div><divclass="form-group"><labelfor="service">Hizmet Kalitesi</label><selectid="service"><optionvalue="30">Harika (%30)</option><optionvalue="20">İyi (%20)</option><optionvalue="15"selected>Standart (%15)</option><optionvalue="10">Kötü (%10)</option></select></div><buttonid="calculate">Hesapla</button><divclass="result"id="result"></div></div><script>document.getElementById('calculate').addEventListener('click', function() {const bill = parseFloat(document.getElementById('bill').value);const service = parseFloat(document.getElementById('service').value);const resultDiv = document.getElementById('result');if (isNaN(bill) || bill <=0) {alert('Lütfen geçerli bir hesap tutarı girin.');return;}const tipAmount = bill * (service /100);const totalAmount = bill + tipAmount;resultDiv.innerHTML = `Bahşiş: ${tipAmount.toFixed(2)} TL<br>Toplam: ${totalAmount.toFixed(2)} TL`;resultDiv.style.display ='block';});</script></body></html>
Dosya Adı:
2-dinamik-karsilayici.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Dinamik Karşılama</title><style>body {font-family:'Arial', sans-serif;margin:0;height:100vh;display: flex;flex-direction: column;justify-content: center;align-items: center;transition: all1s ease;color: white;text-shadow:02px4px rgba(0,0,0,0.5);}.clock { font-size:4rem; font-weight: bold; margin-bottom:10px; }.greeting { font-size:2.5rem; }</style></head><body><divclass="clock"id="clock">00:00:00</div><divclass="greeting"id="greeting">Yükleniyor...</div><script>function updatePage() {const now = new Date();const hours = now.getHours();const minutes = String(now.getMinutes()).padStart(2,'0');const seconds = String(now.getSeconds()).padStart(2,'0');document.getElementById('clock').textContent = `${String(hours).padStart(2,'0')}:${minutes}:${seconds}`;const greetingDiv = document.getElementById('greeting');if (hours >=5&& hours <12) {greetingDiv.textContent ="Günaydın!";document.body.style.backgroundColor ="#f39c12"; // Gün doğumu turuncusu} else if (hours >=12&& hours <18) {greetingDiv.textContent ="Tünaydın!";document.body.style.backgroundColor ="#3498db"; // Gündüz mavisi} else if (hours >=18&& hours <22) {greetingDiv.textContent ="İyi Akşamlar!";document.body.style.backgroundColor ="#e67e22"; // Gün batımı} else {greetingDiv.textContent ="İyi Geceler!";document.body.style.backgroundColor ="#2c3e50"; // Gece karanlığı}}setInterval(updatePage,1000);updatePage(); // İlk açılışta hemen çalışsın</script></body></html>
Dosya Adı: 3-yazi-tura.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Yazı Tura Oyunu</title><style>body {font-family: sans-serif;background: #f0f2f5;display: flex;flex-direction: column;align-items: center;justify-content: center;height:100vh;margin:0;}.coin {width:150px;height:150px;background-color: #f1c40f;border:8px solid #f39c12;border-radius:50%;display: flex;justify-content: center;align-items: center;font-size:24px;font-weight: bold;color: #7f8c8d;box-shadow:06px12px rgba(0,0,0,0.15);transition: transform0.5s ease;}.spin { transform: rotateY(720deg); }button {margin-top:30px;padding:12px30px;font-size:18px;background-color: #9b59b6;color: white;border: none;border-radius:25px;cursor: pointer;box-shadow:04px6px rgba(0,0,0,0.1);}button:hover { background-color: #8e44ad; }.stats { margin-top:20px; font-size:18px; color: #34495e; }</style></head><body><divclass="coin"id="coin">?</div><buttonid="flipBtn">Parayı At!</button><divclass="stats"id="stats">Yazı:0| Tura:0</div><script>let heads =0; // Yazılet tails =0; // Turadocument.getElementById('flipBtn').addEventListener('click', function() {const coin = document.getElementById('coin');coin.classList.add('spin');coin.textContent ="...";setTimeout(() => {coin.classList.remove('spin');const isHeads = Math.random() <0.5;if (isHeads) {coin.textContent ="YAZI";coin.style.backgroundColor ="#f1c40f";heads++;} else {coin.textContent ="TURA";coin.style.backgroundColor ="#e67e22";tails++;}document.getElementById('stats').textContent = `Yazı: ${heads} | Tura: ${tails}`;},500);});</script></body></html>
Dosya Adı:
4-tas-kagit-makas.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Taş Kağıt Makas</title><style>body {font-family: sans-serif;text-align: center;background: #e1e8ed;margin:0;padding:20px;}.choices { display: flex; justify-content: center; gap:20px; margin:30px0; }.btn {font-size:2rem;padding:15px30px;cursor: pointer;border: none;border-radius:10px;background: white;box-shadow:04px6px rgba(0,0,0,0.1);transition: transform0.1s;}.btn:hover { transform: scale(1.1); }.score-board { font-size:1.5rem; margin:20px; color: #2c3e50; }.message { font-size:1.3rem; font-weight: bold; color: #16a085; min-height:30px; }</style></head><body><h1>Taş - Kağıt - Makas</h1><divclass="score-board">Oyuncu: <spanid="player-score">0</span> | Bilgisayar: <spanid="comp-score">0</span></div><divclass="choices"><buttonclass="btn"onclick="play('Taş')">✊</button><buttonclass="btn"onclick="play('Kağıt')">✋</button><buttonclass="btn"onclick="play('Makas')">✌️</button></div><divclass="message"id="message">Seçimini yap ve oyuna başla!</div><script>let pScore =0;let cScore =0;const options = ["Taş","Kağıt","Makas"];function play(playerChoice) {const compChoice = options[Math.floor(Math.random() *3)];let msg = `Sen: ${playerChoice} vs Bilgisayar: ${compChoice}. `;if (playerChoice === compChoice) {msg +="Berabere!";} else if ((playerChoice ==="Taş"&& compChoice ==="Makas") ||(playerChoice ==="Kağıt"&& compChoice ==="Taş") ||(playerChoice ==="Makas"&& compChoice ==="Kağıt")) {msg +="Kazandın! 🎉";pScore++;} else {msg +="Kaybettin! 😢";cScore++;}document.getElementById('player-score').textContent = pScore;document.getElementById('comp-score').textContent = cScore;document.getElementById('message').textContent = msg;}</script></body></html>
Dosya Adı:
5-gelismis-zar-oyunu.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Gelişmiş Zar Oyunu</title><style>body {font-family: sans-serif;background: #27ae60;color: white;display: flex;flex-direction: column;align-items: center;justify-content: center;height:100vh;margin:0;}.board { display: flex; gap:40px; margin:30px; }.dice-container { text-align: center; }.dice {width:100px;height:100px;background: white;border-radius:15px;box-shadow:010px20px rgba(0,0,0,0.3);display: grid;grid-template-columns: repeat(3,1fr);grid-template-rows: repeat(3,1fr);padding:10px;box-sizing: border-box;}.dot {background: #333;border-radius:50%;width:16px;height:16px;margin: auto;visibility: hidden;}/* Zar Nokta Pozisyon Matrisi */.visible { visibility: visible; }button {padding:12px40px;font-size:20px;font-weight: bold;color: #27ae60;background: white;border: none;border-radius:8px;cursor: pointer;box-shadow:05px15px rgba(0,0,0,0.2);}button:hover { background: #f0f0f0; }#result-text { font-size:24px; font-weight: bold; margin-top:20px; min-height:35px;}</style></head><body><h1>Zar Atma Düellosu</h1><divclass="board"><divclass="dice-container"><h3>Oyuncu1</h3><divclass="dice"id="dice1"></div></div><divclass="dice-container"><h3>Oyuncu2</h3><divclass="dice"id="dice2"></div></div></div><buttonid="rollBtn">Zarları At</button><divid="result-text"></div><script>//1-6arasındaki sayıların3x3grid üzerindeki nokta indeks haritasıconst diceMaps = {1:,2:,3:,4:,5:,6: [0,2,3,5,6,8]};function buildDice(diceElement, value) {diceElement.innerHTML =''; // Temizlefor (let i =0; i <9; i++) {const dot = document.createElement('div');dot.className ='dot';if (diceMaps[value].includes(i)) {dot.classList.add('visible');}diceElement.appendChild(dot);}}// İlk kurulum boş zarlarbuildDice(document.getElementById('dice1'),1);buildDice(document.getElementById('dice2'),1);document.getElementById('rollBtn').addEventListener('click', function() {const val1= Math.floor(Math.random() *6) +1;const val2= Math.floor(Math.random() *6) +1;buildDice(document.getElementById('dice1'), val1);buildDice(document.getElementById('dice2'), val2);const resultText = document.getElementById('result-text');if (val1> val2) {resultText.textContent ="🏆 Oyuncu 1 Kazandı!";} else if (val2> val1) {resultText.textContent ="Oyuncu 2 Kazandı! 🏆";} else {resultText.textContent ="🤝 Berabere!";}});</script></body></html>
Müfredat listemizde sıradaki 6. ve 10. projeler arasındaki uygulamaların tüm HTML, CSS ve JavaScript kod bloklarını, tarayıcınızda doğrudan çalıştırabileceğiniz şekilde tek bir dosya formatında hazırladım.
Bu uygulama, sayfada dinamik olarak
ses butonları oluşturur ve tarayıcının yerleşik ses
sentezleyicisini (SpeechSynthesis)
kullanarak ek bir .mp3
dosyasına ihtiyaç duymadan ses efektleri üretir.
Dosya
Adı: 6-ses-calar.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>JavaScript Ses Çalar</title><style>body {font-family:'Segoe UI', sans-serif;background: #1e1e24;color: white;display: flex;flex-direction: column;align-items: center;justify-content: center;height:100vh;margin:0;}h1{ margin-bottom:30px; color: #4a90e2; }.buttons-container {display: flex;gap:15px;flex-wrap: wrap;justify-content: center;max-width:600px;}.sound-btn {background: #2a2b3d;border:2px solid #4a90e2;color: white;padding:20px40px;font-size:18px;font-weight: bold;border-radius:10px;cursor: pointer;transition: all0.2s ease;box-shadow:04px15px rgba(0,0,0,0.2);}.sound-btn:hover {background: #4a90e2;transform: translateY(-3px);box-shadow:06px20px rgba(74,144,226,0.4);}.sound-btn:active { transform: translateY(0); }</style></head><body><h1>Müzik & Efekt Kutusu</h1><divclass="buttons-container"id="btnContainer"></div><script>// Dinamik butonlar için ses isimleri listesiconst sounds = ["Alkış","Hata","Lazer","Başarı","Davul"];const container = document.getElementById('btnContainer');sounds.forEach(sound => {const btn = document.createElement('button');btn.className ='sound-btn';btn.innerText = sound;btn.addEventListener('click', () => {playSyntheticSound(sound);});container.appendChild(btn);});// Harici mp3bağımlılığı olmadan ses üretme fonksiyonufunction playSyntheticSound(type) {const synth = window.speechSynthesis;if (!synth) {alert("Tarayıcınız ses sentezini desteklemiyor.");return;}let word = type;if(type ==="Alkış") word ="Bravo! Muhteşem!";if(type ==="Hata") word ="Dikkat! Hata oluştu.";if(type ==="Lazer") word ="Piuw! Piuw!";if(type ==="Başarı") word ="Tebrikler! Kazandınız.";if(type ==="Davul") word ="Güm! Güm! Taka tak!";const utterance = new SpeechSynthesisUtterance(word);utterance.lang ='tr-TR';utterance.rate =1.2;synth.speak(utterance);}</script></body></html>
Ekrana gelen rastgele cümleleri
kullanıcının ne kadar hızlı ve doğru yazdığını ölçer.
Dakika başına kelime (WPM) ve doğruluk oranı hesaplar.
Dosya
Adı: 7-klavye-hiz-testi.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Klavye Hız Testi</title><style>body {font-family: system-ui, sans-serif;background: #f4f6f9;display: flex;justify-content: center;align-items: center;height:100vh;margin:0;}.card {background: white;padding:30px;border-radius:12px;box-shadow:010px30px rgba(0,0,0,0.05);width:550px;box-sizing: border-box;}.quote {background: #eef2f7;padding:15px;border-radius:6px;font-size:18px;margin-bottom:20px;line-height:1.5;color: #333;user-select: none;}textarea {width:100%;height:100px;padding:10px;font-size:16px;border:2px solid #ddd;border-radius:6px;resize: none;box-sizing: border-box;}textarea:focus { border-color: #3498db; outline: none; }.score-board {display: flex;justify-content: space-between;margin-top:20px;font-size:16px;font-weight: bold;color: #555;}button {margin-top:15px;width:100%;padding:12px;background: #3498db;color: white;border: none;border-radius:6px;font-size:16px;cursor: pointer;}button:hover { background: #2980b9; }</style></head><body><divclass="card"><h2>Klavye Hız Testi</h2><divclass="quote"id="quoteTarget">Yükleniyor...</div><textareaid="typeInput"placeholder="Yazmaya başladığınızda süre tetiklenecektir..."disabled></textarea><divclass="score-board"><div>Süre: <spanid="timer">0</span>s</div><div>WPM (Hız): <spanid="wpm">0</span></div><div>Doğruluk: <spanid="accuracy">0%</span></div></div><buttonid="startBtn">Testi Başlat</button></div><script>const quotes = ["JavaScript web sayfalarını dinamik hale getiren güçlü bir dildir.","Hızlı yazmak sadece parmakların değil düzenli pratiğin bir sonucudur.","Kod yazarken hata yapmaktan korkmayın çünkü en büyük öğretmen hatalardır.","Teknoloji her gün gelişiyor ve bizim de kendimizi güncellememiz gerekiyor."];let startTime, timerInterval;let isRunning = false;let selectedQuote ="";const quoteTarget = document.getElementById('quoteTarget');const typeInput = document.getElementById('typeInput');const timerText = document.getElementById('timer');const wpmText = document.getElementById('wpm');const accText = document.getElementById('accuracy');const startBtn = document.getElementById('startBtn');startBtn.addEventListener('click', startTest);typeInput.addEventListener('input', checkTyping);function startTest() {isRunning = true;typeInput.disabled = false;typeInput.value ="";typeInput.focus();selectedQuote = quotes[Math.floor(Math.random() * quotes.length)];quoteTarget.textContent = selectedQuote;startTime = new Date();clearInterval(timerInterval);timerInterval = setInterval(updateTimer,1000);startBtn.textContent ="Yeniden Başlat";}function updateTimer() {const timePassed = Math.floor((new Date() - startTime) /1000);timerText.textContent = timePassed;}function checkTyping() {const currentInput = typeInput.value;// Doğruluk hesaplamalet correctChars =0;for (let i =0; i < currentInput.length; i++) {if (currentInput[i] === selectedQuote[i]) correctChars++;}const acc = currentInput.length >0? Math.floor((correctChars / currentInput.length) *100) :0;accText.textContent = acc +"%";// Hız (WPM) hesaplamaconst timePassedMin = (new Date() - startTime) /60000;const wordsCount = currentInput.split(' ').length;if (timePassedMin >0) {wpmText.textContent = Math.floor(wordsCount / timePassedMin);}// Test bitti mi?if (currentInput === selectedQuote) {clearInterval(timerInterval);typeInput.disabled = true;alert("Tebrikler! Testi başarıyla tamamladınız.");}}</script></body></html>
Klavyedeki yön tuşlarıyla harita
üzerindeki mavi bloğu sınırların dışına çıkmadan hareket
ettirmenizi sağlar. Hareket geçmişini sağ taraftaki listeye
kaydeder.
Dosya Adı:
8-dom-mover.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>DOM Mover</title><style>body {font-family: sans-serif;background: #2c3e50;color: white;display: flex;justify-content: center;align-items: center;height:100vh;margin:0;gap:30px;}.game-area {width:400px;height:400px;background: #34495e;border:4px solid #1abc9c;position: relative;border-radius:8px;}.player {width:40px;height:40px;background: #3498db;position: absolute;top:180px;left:180px;border-radius:6px;transition: all0.1s ease;box-shadow:0010px #3498db;}.log-panel {width:200px;height:400px;background: rgba(255,255,255,0.1);border-radius:8px;padding:15px;box-sizing: border-box;display: flex;flex-direction: column;}.log-list {overflow-y: auto;flex-grow:1;padding-left:20px;margin:0;font-size:14px;color: #bdc3c7;}</style></head><body><divclass="game-area"><divclass="player"id="player"></div></div><divclass="log-panel"><h3>Aksiyon Listesi</h3><ulclass="log-list"id="logList"></ul></div><script>const player = document.getElementById('player');const logList = document.getElementById('logList');// Başlangıç pozisyon değerlerilet posX =180;let posY =180;const step =20; // Her adım mesafesiconst maxBound =360; //400px alan -40px oyuncu genişliğiwindow.addEventListener('keydown', (e) => {let action ="";switch(e.key) {case"ArrowUp":case"w":if (posY >= step) { posY -= step; action ="Yukarı"; }break;case"ArrowDown":case"s":if (posY <= maxBound - step) { posY += step; action ="Aşağı"; }break;case"ArrowLeft":case"a":if (posX >= step) { posX -= step; action ="Sola"; }break;case"ArrowRight":case"d":if (posX <= maxBound - step) { posX += step; action ="Sağa"; }break;}if (action !=="") {// DOM Pozisyon Güncellemeplayer.style.top = posY +"px";player.style.left = posX +"px";// Listeye Eylem Eklemeconst li = document.createElement('li');li.textContent = `${action} (${posX}, ${posY})`;logList.appendChild(li);logList.scrollTop = logList.scrollHeight; // Otomatik aşağı kaydır}});</script></body></html>
Sorulan sorulara rastgele gizemli
cevaplar veren eğlenceli bir şans uygulamasıdır. İçerideki küre
animasyonlu bir şekilde sallanarak cevabı yansıtır.
Dosya
Adı: 9-sihirli-8-top.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Sihirli8Top</title><style>body {font-family: sans-serif;background: #111;color: white;text-align: center;padding-top:50px;}.ball {width:250px;height:250px;background: radial-gradient(circle at75px75px, #333, #000);border-radius:50%;margin:30px auto;display: flex;justify-content: center;align-items: center;box-shadow:015px30px rgba(0,0,0,0.5);position: relative;}.inner-circle {width:110px;height:110px;background: #fff;border-radius:50%;display: flex;justify-content: center;align-items: center;color: black;font-weight: bold;font-size:14px;padding:10px;box-sizing: border-box;text-align: center;transition: all0.3s;}input {padding:10px;width:280px;font-size:16px;border-radius:5px;border: none;margin-right:10px;}button {padding:10px20px;font-size:16px;background: #8e44ad;color: white;border: none;border-radius:5px;cursor: pointer;}button:hover { background: #9b59b6; }/* Sallanma Animasyonu */@keyframes shake {0% { transform: translate(1px,1px) rotate(0deg); }10% { transform: translate(-1px, -2px) rotate(-1deg); }30% { transform: translate(3px,2px) rotate(0deg); }50% { transform: translate(-1px,2px) rotate(1deg); }70% { transform: translate(2px,1px) rotate(0deg); }100% { transform: translate(1px, -2px) rotate(-1deg); }}.shake-animation { animation: shake0.5s infinite; }</style></head><body><h1>Sihirli8Topa Soru Sor</h1><p>Geleceği merak ediyorsan sorunu yaz ve topu salla!</p><inputtype="text"id="question"placeholder="Zengin olacak mıyım?"><buttonid="askBtn">Sor</button><divclass="ball"id="ball"><divclass="inner-circle"id="answer">8</div></div><script>const answers = ["Kesinlikle evet","Şüphesiz ki öyle","Gördüğüm kadarıyla evet","Buna güvenebilirsin","Bana göre hava hoş","Sonra tekrar sor","Şimdi söylemesem iyi olur","Tahmin edemiyorum","Buna odaklan ve tekrar sor","Kaynağım hayır diyor","Görünüşe göre pek iyi değil","Çok şüpheli"];const ball = document.getElementById('ball');const answerDiv = document.getElementById('answer');const questionInput = document.getElementById('question');const askBtn = document.getElementById('askBtn');askBtn.addEventListener('click', () => {if (questionInput.value.trim() ==="") {alert("Lütfen önce bir soru yazın!");return;}// Sallanma efekti tetiklemeball.classList.add('shake-animation');answerDiv.style.opacity ="0";setTimeout(() => {ball.classList.remove('shake-animation');const randomAnswer = answers[Math.floor(Math.random() * answers.length)];answerDiv.textContent = randomAnswer;answerDiv.style.opacity ="1";answerDiv.style.fontSize ="12px";},1000);});</script></body></html>
Sıkça sorulan sorular
ekranlarında kullanılan, açıldığında yumuşak geçişle paneli
gösteren ve diğer panelleri otomatik kapatan modüler bir
bileşendir.
Dosya Adı:
10-akordeon-menu.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>JavaScript Akordeon Menü</title><style>body {font-family: Arial, sans-serif;background: #fafafa;display: flex;flex-direction: column;align-items: center;padding-top:50px;}.accordion-container { width:500px; }.accordion-item {background: white;margin-bottom:10px;border-radius:6px;box-shadow:02px5px rgba(0,0,0,0.05);overflow: hidden;}.accordion-header {background: #ffffff;padding:15px20px;font-weight: bold;color: #333;cursor: pointer;display: flex;justify-content: space-between;align-items: center;user-select: none;border-bottom:1px solid #f0f0f0;}.accordion-header:hover { background: #fdfdfd; color: #3498db; }.accordion-content {padding:020px;max-height:0;overflow: hidden;transition: max-height0.3s ease-out, padding0.3s ease-out;color: #666;line-height:1.6;font-size:15px;}.active .accordion-content {padding:15px20px;}.icon { transition: transform0.3s; }.active .icon { transform: rotate(45deg); }</style></head><body><divclass="accordion-container"><h2>Sıkça Sorulan Sorular</h2><divclass="accordion-item"><divclass="accordion-header">JavaScript Nedir? <spanclass="icon">+</span></div><divclass="accordion-content">JavaScript, web sayfalarını dinamik ve etkileşimli hale getirmek için kullanılan modern ve çok yönlü bir programlama dilidir.</div></div><divclass="accordion-item"><divclass="accordion-header">DOM Nedir? <spanclass="icon">+</span></div><divclass="accordion-content">Document Object Model (DOM), tarayıcının HTML sayfasını bir ağaç yapısı olarak görmesini ve kodla müdahale edilmesini sağlayan yapıdır.</div></div><divclass="accordion-item"><divclass="accordion-header">Müfredat Hangi Seviyeye Uygundur? <spanclass="icon">+</span></div><divclass="accordion-content">Bu eğitim sıfırdan başlar ve sizi adım adım ileri düzey asenkron JavaScript ve oyun geliştirme seviyesine kadar taşır.</div></div></div><script>const headers = document.querySelectorAll('.accordion-header');headers.forEach(header => {header.addEventListener('click', function() {const item = this.parentElement;const content = this.nextElementSibling;// Diğer tüm açık panelleri kapatma (Single Open kuralı)document.querySelectorAll('.accordion-item').forEach(el => {if (el !== item) {el.classList.remove('active');el.querySelector('.accordion-content').style.maxHeight = null;}});// Seçilen paneli açıp kapatma toggle işlemiitem.classList.toggle('active');if (item.classList.contains('active')) {content.style.maxHeight = content.scrollHeight +"px";} else {content.style.maxHeight = null;}});});</script></body></html>
Müfredat sırasındaki 11. ve 15. projeler arasındaki uygulamaların tüm HTML, CSS ve JavaScript kod bloklarını, tarayıcınızda doğrudan kopyalayıp çalıştırabileceğiniz şekilde tek bir dosya formatında hazırladım.
Bilgisayarın arka planda tuttuğu
gizli 3 basamaklı şifreyi bulmaya çalışırsınız. Girdiğiniz
sayılara göre her hanenin arkası renk değiştirerek size ipucu
verir.
Dosya Adı:
11-sifre-krici-kasa.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Şifre Kırıcı Kasa Oyunu</title><style>body {font-family:'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;background-color: #2c3e50;color: white;display: flex;flex-direction: column;align-items: center;justify-content: center;height:100vh;margin:0;}.kasa-box {background-color: #34495e;padding:30px;border-radius:15px;box-shadow:010px25px rgba(0,0,0,0.5);text-align: center;border:4px solid #bdc3c7;}.inputs {display: flex;gap:15px;justify-content: center;margin:20px0;}.digit-input {width:60px;height:60px;font-size:28px;text-align: center;border-radius:8px;border:2px solid #7f8c8d;background-color: #ecf0f1;color: #2c3e50;font-weight: bold;}button {background-color: #e67e22;color: white;border: none;padding:12px30px;font-size:18px;border-radius:6px;cursor: pointer;font-weight: bold;transition:0.2s;}button:hover { background-color: #d35400; }.mesaj {margin-top:20px;font-size:18px;min-height:25px;font-weight: bold;}</style></head><body><divclass="kasa-box"><h2>🔒 Kasa Kilidi Şifre Kırıcı</h2><p>3basamaklı doğru şifreyi bulun (0-9arası)</p><divclass="inputs"><inputtype="number"class="digit-input"min="0"max="9"maxlength="1"><inputtype="number"class="digit-input"min="0"max="9"maxlength="1"><inputtype="number"class="digit-input"min="0"max="9"maxlength="1"></div><buttonid="kontrolBtn">Kilidi Açmayı Dene</button><divclass="mesaj"id="mesajBox"></div></div><script>// Bilgisayar3basamaklı rastgele şifre üretiyorconst gizliSifre = [Math.floor(Math.random() *10),Math.floor(Math.random() *10),Math.floor(Math.random() *10)];let denemeSayisi =0;const inputs = document.querySelectorAll('.digit-input');const mesajBox = document.getElementById('mesajBox');// Tek karakter sınırlaması ve otomatik odaklanmainputs.forEach((input, index) => {input.addEventListener('input', (e) => {if (input.value.length >1) input.value = input.value.slice(0,1);if (input.value !==""&& index < inputs.length -1) {inputs[index +1].focus();}});});document.getElementById('kontrolBtn').addEventListener('click', () => {let dogruHaneSayisi =0;denemeSayisi++;inputs.forEach((input, index) => {const tahmin = parseInt(input.value);if (isNaN(tahmın)) {input.style.backgroundColor ="#ecf0f1";return;}if (tahmın === gizliSifre[index]) {input.style.backgroundColor ="#2ecc71"; // Doğru yerdogruHaneSayisi++;} else if (gizliSifre.includes(tahmın)) {input.style.backgroundColor ="#f1c40f"; // Şifrede var ama yanlış yerde} else {input.style.backgroundColor ="#e74c3c"; // Şifrede yok}});if (dogruHaneSayisi ===3) {mesajBox.innerHTML = `🎉 Tebrikler! Kasa açıldı. Şifre: ${gizliSifre.join('')} <br> ${denemeSayisi} denemede buldunuz.`;mesajBox.style.color ="#2ecc71";document.getElementById('kontrolBtn').disabled = true;} else {mesajBox.textContent ="Kilit açılmadı! Renk ipuçlarını takip edin.";mesajBox.style.color ="#f1c40f";}});</script></body></html>
Seçilen kelimenin harfleri havuzda
karıştırılır. Kullanıcı kısıtlı süre bitmeden orijinal
kelimeyi doğru tahmin etmeye çalışır.
Dosya Adı:
12-kelime-karistirma.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Kelime Karıştırma Oyunu</title><style>body {font-family: sans-serif;background: #9b59b6;color: white;display: flex;justify-content: center;align-items: center;height:100vh;margin:0;}.oyun-kartı {background: white;color: #333;padding:30px;border-radius:12px;width:400px;text-align: center;box-shadow:08px20px rgba(0,0,0,0.2);}.karisik-kelime {font-size:32px;font-weight: bold;letter-spacing:5px;margin:20px0;color: #8e44ad;text-transform: uppercase;}input {width:80%;padding:10px;font-size:18px;border:2px solid #ccc;border-radius:6px;margin-bottom:15px;text-align: center;}button {padding:10px20px;font-size:16px;border: none;border-radius:5px;cursor: pointer;margin:5px;font-weight: bold;}.tahmin-btn { background: #2ecc71; color: white; }.yenile-btn { background: #e74c3c; color: white; }.bilgi { font-weight: bold; margin-top:15px; font-size:16px; }</style></head><body><divclass="oyun-kartı"><h2>🔤 Kelime Karıştırma Oyunu</h2><p>Harfleri karışık verilen kelimeyi tahmin edin:</p><divclass="karisik-kelime"id="scrambledWord">-----</div><inputtype="text"id="userInput"placeholder="Tahmininizi yazın..."><div><buttonclass="tahmin-btn"id="checkBtn">Kontrol Et</button><buttonclass="yenile-btn"id="refreshBtn">Pas Geç</button></div><divclass="bilgi"id="infoBox"></div></div><script>const kelimeler = ["javascript","tarayici","degisken","fonksiyon","dongu","yazilim"];let secilenKelime ="";const scrambledWordDiv = document.getElementById('scrambledWord');const userInput = document.getElementById('userInput');const checkBtn = document.getElementById('checkBtn');const refreshBtn = document.getElementById('refreshBtn');const infoBox = document.getElementById('infoBox');function yeniKelimeSec() {userInput.value ="";infoBox.textContent ="";secilenKelime = kelimeler[Math.floor(Math.random() * kelimeler.length)];// Harfleri karıştırma algoritmasılet harfler = secilenKelime.split('');for (let i = harfler.length -1; i >0; i--) {let j = Math.floor(Math.random() * (i +1));[harfler[i], harfler[j]] = [harfler[j], harfler[i]];}scrambledWordDiv.textContent = harfler.join('');}checkBtn.addEventListener('click', () => {const tahmin = userInput.value.trim().toLowerCase();if (tahmin === secilenKelime) {infoBox.textContent ="🎉 Doğru Tahmin! Harika.";infoBox.style.color ="#2ecc71";setTimeout(yeniKelimeSec,1500);} else {infoBox.textContent ="❌ Yanlış Cevap, tekrar dene!";infoBox.style.color ="#e74c3c";}});refreshBtn.addEventListener('click', yeniKelimeSec);// Oyunu başlatyeniKelimeSec();</script></body></html>
Belirttiğiniz tarihe ne kadar süre
kaldığını gün, saat, dakika ve saniye bazında canlı olarak
güncelleyen profesyonel bir kronometre aracıdır.
Dosya
Adı: 13-geri-sayim-sayaci.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Geri Sayım Sayacı</title><style>body {font-family:'Arial', sans-serif;background: linear-gradient(135deg, #111, #333);color: white;display: flex;flex-direction: column;align-items: center;justify-content: center;height:100vh;margin:0;}h1{ margin-bottom:20px; letter-spacing:2px; }.sayac-kutusu {display: flex;gap:20px;}.zaman-bolumu {background: rgba(255,255,255,0.1);padding:20px;border-radius:10px;min-width:80px;text-align: center;box-shadow:05px15px rgba(0,0,0,0.3);}.sayi {font-size:40px;font-weight: bold;color: #f1c40f;}.etiket {font-size:12px;text-transform: uppercase;color: #ccc;margin-top:5px;}</style></head><body><h1>Yeni Yıla Kalan Süre</h1><divclass="sayac-kutusu"><divclass="zaman-bolumu"><divclass="sayi"id="gun">00</div><divclass="etiket">Gün</div></div><divclass="zaman-bolumu"><divclass="sayi"id="saat">00</div><divclass="etiket">Saat</div></div><divclass="zaman-bolumu"><divclass="sayi"id="dakika">00</div><divclass="etiket">Dakika</div></div><divclass="zaman-bolumu"><divclass="sayi"id="saniye">00</div><divclass="etiket">Saniye</div></div></div><script>// Dinamik olarak bir sonraki yılın1Ocak tarihini hedef alalımconst currentYear = new Date().getFullYear();const hedefTarih = new Date(`January1, ${currentYear +1}00:00:00`).getTime();function geriSayimiGuncelle() {const simdi = new Date().getTime();const mesafe = hedefTarih - simdi;// Zaman dönüşüm hesaplamalarıconst gun = Math.floor(mesafe / (1000*60*60*24));const saat = Math.floor((mesafe % (1000*60*60*24)) / (1000*60*60));const dakika = Math.floor((mesafe % (1000*60*60)) / (1000*60));const saniye = Math.floor((mesafe % (1000*60)) /1000);// Ekran elementlerini güncellemedocument.getElementById('gun').textContent = String(gun).padStart(2,'0');document.getElementById('saat').textContent = String(saat).padStart(2,'0');document.getElementById('dakika').textContent = String(dakika).padStart(2,'0');document.getElementById('saniye').textContent = String(saniye).padStart(2,'0');// Süre dolduğunda durdurif (mesafe <0) {clearInterval(sayacInterval);document.querySelector('.sayac-kutusu').innerHTML ="<h2>Mutlu Yıllar! 🎉</h2>";}}// Her saniye çalıştırconst sayacInterval = setInterval(geriSayimiGuncelle,1000);geriSayimiGuncelle();</script></body></html>
Bilgisayarın yaktığı renk
dizisini hafızanızda tutup sırasıyla aynı kutulara tıklamanız
gerekir. Her turda diziye yeni bir renk eklenerek oyun
zorlaşır.
Dosya Adı:
14-hafiza-desen-eslestirme.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Desen Eşleştirme Oyunu</title><style>body {font-family: sans-serif;background-color: #222;color: white;text-align: center;margin:0;padding-top:30px;}.grid {display: grid;grid-template-columns: repeat(2,130px);grid-template-rows: repeat(2,130px);gap:15px;justify-content: center;margin:20px auto;}.box {border-radius:10px;cursor: pointer;opacity:0.6;transition: opacity0.2s, transform0.1s;}.box:active { transform: scale(0.95); }.red { background-color: #e74c3c; }.blue { background-color: #3498db; }.green { background-color: #2ecc71; }.yellow { background-color: #f1c40f; }.active { opacity:1; box-shadow:0020px white; }button {padding:10px25px;font-size:16px;background: white;color: #222;border: none;border-radius:5px;font-weight: bold;cursor: pointer;}</style></head><body><h1>Desen Hafıza Oyunu</h1><pid="skorTablosu">Tur:0</p><buttonid="startBtn">Oyunu Başlat</button><divclass="grid"><divclass="box red"id="0"></div><divclass="box blue"id="1"></div><divclass="box green"id="2"></div><divclass="box yellow"id="3"></div></div><script>let bilgisayarSerisi = [];let oyuncuSerisi = [];let tur =0;let oyunAktif = false;const boxes = document.querySelectorAll('.box');const startBtn = document.getElementById('startBtn');const skorTablosu = document.getElementById('skorTablosu');startBtn.addEventListener('click', () => {if (!oyunAktif) {oyunAktif = true;bilgisayarSerisi = [];tur =0;startBtn.disabled = true;yeniTur();}});function yeniTur() {oyuncuSerisi = [];tur++;skorTablosu.textContent = `Tur: ${tur}`;bilgisayarSerisi.push(Math.floor(Math.random() *4));seriyiOynat();}function seriyiOynat() {let i =0;const interval = setInterval(() => {kutuyuYak(bilgisayarSerisi[i]);i++;if (i >= bilgisayarSerisi.length) {clearInterval(interval);}},600);}function kutuyuYak(id) {const box = document.getElementById(id);box.classList.add('active');setTimeout(() => box.classList.remove('active'),300);}boxes.forEach(box => {box.addEventListener('click', (e) => {if (!oyunAktif || bilgisayarSerisi.length ===0) return;const secilenId = parseInt(e.target.id);kutuyuYak(secilenId);oyuncuSerisi.push(secilenId);// Tıklama kontrol doğrulamasıconst gecerliIndeks = oyuncuSerisi.length -1;if (oyuncuSerisi[gecerliIndeks] !== bilgisayarSerisi[gecerliIndeks]) {alert(`❌ Yanlış Sıralama! Oyun bitti. Ulaştığınız Tur: ${tur}`);oyunAktif = false;startBtn.disabled = false;startBtn.textContent ="Tekrar Dene";return;}if (oyuncuSerisi.length === bilgisayarSerisi.length) {setTimeout(yeniTur,1000);}});});</script></body></html>
Ekranda rastgele konumlarda beliren
kırmızı balonları süreniz bitmeden en hızlı şekilde
tıklayarak patlatmaya çalıştığınız yüksek tempolu bir tık
refleks oyunudur.
Dosya Adı:
15-balon-patlatma.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Balon Patlatma Oyunu</title><style>body {font-family: sans-serif;background-color: #f5f6fa;margin:0;overflow: hidden;text-align: center;}.header-panel {background: #2f3640;color: white;padding:10px;display: flex;justify-content: space-around;font-size:18px;font-weight: bold;}.oyun-alani {width:100vw;height: calc(100vh -50px);position: relative;background: #dcdde1;cursor: crosshair;}.balon {width:50px;height:65px;background: #e84118;border-radius:50%50%50%50% /40%40%60%60%;position: absolute;cursor: pointer;box-shadow: inset -5px -5px10px rgba(0,0,0,0.2);}/* Balonun altındaki küçük düğüm çizgisi */.balon::after {content:"";position: absolute;bottom: -5px;left:22px;width:6px;height:6px;background: #c23616;transform: rotate(45deg);}button {padding:5px15px;font-size:16px;cursor: pointer;}</style></head><body><divclass="header-panel"><div>Skor: <spanid="skorTxt">0</span></div><div>Kalan Süre: <spanid="sureTxt">20</span>s</div><buttonid="gameActionBtn">Başlat</button></div><divclass="oyun-alani"id="gameArea"></div><script>let skor =0;let kalanSure =20;let oyunInterval, balonInterval;let oyunDevamEdiyor = false;const gameArea = document.getElementById('gameArea');const skorTxt = document.getElementById('skorTxt');const sureTxt = document.getElementById('sureTxt');const gameActionBtn = document.getElementById('gameActionBtn');gameActionBtn.addEventListener('click', () => {if (!oyunDevamEdiyor) startGame();});function startGame() {skor =0;kalanSure =20;oyunDevamEdiyor = true;gameArea.innerHTML ='';skorTxt.textContent = skor;sureTxt.textContent = kalanSure;gameActionBtn.disabled = true;oyunInterval = setInterval(() => {kalanSure--;sureTxt.textContent = kalanSure;if (kalanSure <=0) gameOver();},1000);balonInterval = setInterval(balonOlustur,700);}function balonOlustur() {if (!oyunDevamEdiyor) return;const balon = document.createElement('div');balon.className ='balon';// Oyun alanı boyut sınırlarına göre konum belirlemeconst maxX = gameArea.clientWidth -60;const maxY = gameArea.clientHeight -80;balon.style.left = Math.floor(Math.random() * maxX) +'px';balon.style.top = Math.floor(Math.random() * maxY) +'px';// Balona tıklandığında patlama aksiyonubalon.addEventListener('mousedown', () => {if (oyunDevamEdiyor) {skor++;skorTxt.textContent = skor;balon.remove();}});gameArea.appendChild(balon);// Balon tıklanmadıysa2saniye sonra ekrandan silinsinsetTimeout(() => { if(balon.parentElement) balon.remove(); },2000);}function gameOver() {oyunDevamEdiyor = false;clearInterval(oyunInterval);clearInterval(balonInterval);gameActionBtn.disabled = false;gameActionBtn.textContent ="Tekrar Oyna";alert(`Oyun Bitti! Toplam Skorunuz: ${skor}`);}</script></body></html>
Müfredat listemizdeki 16. ve 20. projeler arasındaki uygulamaların tüm HTML, CSS ve JavaScript kod bloklarını, tarayıcınızda doğrudan kopyalayıp çalıştırabileceğiniz şekilde tek bir dosya formatında hazırladım.
Ekrandaki karttan bir sonraki
çekilecek kartın değerinin daha mı yüksek daha mı düşük
olacağını tahmin etmeye çalıştığınız bir deste
oyunudur.
Dosya Adı:
16-yuksek-alcak-kart.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Yüksek Alçak Kart Oyunu</title><style>body {font-family:'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;background-color: #1e3799;color: white;text-align: center;margin:0;padding:20px;}.game-container {background-color: #0a3d62;max-width:400px;margin:30px auto;padding:30px;border-radius:15px;box-shadow:010px25px rgba(0,0,0,0.4);}.card-display {width:140px;height:200px;background-color: white;color: black;border-radius:10px;margin:25px auto;display: flex;flex-direction: column;justify-content: center;align-items: center;font-size:40px;font-weight: bold;box-shadow:05px15px rgba(0,0,0,0.3);position: relative;}.buttons {display: flex;justify-content: center;gap:15px;margin-top:20px;}button {padding:12px24px;font-size:18px;font-weight: bold;border: none;border-radius:6px;cursor: pointer;transition:0.2s;}.high-btn { background-color: #2ecc71; color: white; }.low-btn { background-color: #e74c3c; color: white; }button:hover { opacity:0.9; transform: translateY(-2px); }.info { margin-top:20px; font-size:18px; font-weight: bold; min-height:25px; }</style></head><body><divclass="game-container"><h2>🃏 Yüksek mi Alçak mı?</h2><p>Bir sonraki kartın değeri mevcut karttan daha yüksek mi yoksa alçak mı olacak?</p><divclass="score">Skor: <spanid="scoreTxt">0</span></div><divclass="card-display"id="cardDisplay"><divid="cardValue">7</div></div><divclass="buttons"><buttonclass="high-btn"id="highBtn">▲ YÜKSEK</button><buttonclass="low-btn"id="lowBtn">▼ ALÇAK</button></div><divclass="info"id="infoTxt">Oyuna Başla!</div></div><script>let currentCardValue =7;let score =0;const cardValueDiv = document.getElementById('cardValue');const scoreTxt = document.getElementById('scoreTxt');const infoTxt = document.getElementById('infoTxt');function playRound(guess) {//1ile13arası rastgele yeni bir kart değeri seçiyoruz (As=1, Vale=11, Kız=12, Papaz=13)let nextCardValue = Math.floor(Math.random() *13) +1;// Eşitlik durumunda tekrar zar atalım ki oyun kilitlenmesinwhile (nextCardValue === currentCardValue) {nextCardValue = Math.floor(Math.random() *13) +1;}cardValueDiv.textContent = nextCardValue;let isHigher = nextCardValue > currentCardValue;let won = (guess ==='high'&& isHigher) || (guess ==='low'&& !isHigher);if (won) {score++;scoreTxt.textContent = score;infoTxt.textContent = `🎉 Doğru! Yeni kart: ${nextCardValue}.`;infoTxt.style.color ='#2ecc71';} else {score =0;scoreTxt.textContent = score;infoTxt.textContent = `❌ Yanlış! Yeni kart: ${nextCardValue}. Skor Sıfırlandı!`;infoTxt.style.color ='#e74c3c';}currentCardValue = nextCardValue;}document.getElementById('highBtn').addEventListener('click', () => playRound('high'));document.getElementById('lowBtn').addEventListener('click', () => playRound('low'));</script></body></html>
Klavyedeki sağ ve sol yön
tuşlarıyla kendi arabanızı kontrol edip, yukarıdan gelen
engellerden kaçarak skor topladığınız dikey bir refleks
oyunudur.
Dosya Adı:
17-araba-yarisi.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Araba Driving Oyunu</title><style>body {font-family: sans-serif;background: #2c3e50;margin:0;overflow: hidden;display: flex;flex-direction: column;align-items: center;justify-content: center;height:100vh;}.score { color: white; font-size:24px; font-weight: bold; margin-bottom:10px; }.game-area {width:300px;height:500px;background: #34495e;position: relative;overflow: hidden;border:4px solid white;border-radius:8px;}.my-car {width:40px;height:70px;background: #e74c3c;border-radius:5px;position: absolute;bottom:20px;left:130px;}.enemy {width:40px;height:70px;background: #f1c40f;border-radius:5px;position: absolute;top: -70px;}.start-screen {position: absolute;width:100%;height:100%;background: rgba(0,0,0,0.8);color: white;display: flex;justify-content: center;align-items: center;font-size:20px;font-weight: bold;cursor: pointer;z-index:2;text-align: center;}</style></head><body><divclass="score">Skor: <spanid="scoreBox">0</span></div><divclass="game-area"><divclass="start-screen"id="startScreen">Oyunu Başlatmak İçin Tıklayın<br><br>Yön Tuşları: A / D veya Sol / Sağ</div><divclass="my-car"id="myCar"></div><divclass="enemy"id="enemyCard"></div></div><script>const gameArea = document.querySelector('.game-area');const myCar = document.getElementById('myCar');const enemy = document.getElementById('enemyCard');const startScreen = document.getElementById('startScreen');const scoreBox = document.getElementById('scoreBox');let score =0;let carX =130;let enemyY = -70;let enemyX =130;let gameActive = false;let keys = {};startScreen.addEventListener('click', startGame);window.addEventListener('keydown', (e) => keys[e.key] = true);window.addEventListener('keyup', (e) => keys[e.key] = false);function startGame() {startScreen.style.display ='none';gameActive = true;score =0;carX =130;enemyY = -70;enemyX = Math.floor(Math.random() *260);enemy.style.left = enemyX +'px';scoreBox.textContent = score;requestAnimationFrame(updateGame);}function updateGame() {if (!gameActive) return;// Oyuncu araba hareketiif ((keys['ArrowLeft'] || keys['a']) && carX >0) carX -=5;if ((keys['ArrowRight'] || keys['d']) && carX <260) carX +=5;myCar.style.left = carX +'px';// Engel (Düşman araba) hareketienemyY +=6;if (enemyY >500) {enemyY = -70;enemyX = Math.floor(Math.random() *260);enemy.style.left = enemyX +'px';score++;scoreBox.textContent = score;}enemy.style.top = enemyY +'px';// Çarpışma Testi Algoritması (Collision Detection)if (enemyY +70>410&& enemyY <480) { // Y ekseni çakışmasıif (enemyX +40> carX && enemyX < carX +40) { // X ekseni çakışmasıgameActive = false;startScreen.style.display ='flex';startScreen.innerHTML = `Oyun Bitti!<br>Skorunuz: ${score}<br>Tekrar oynamak için tıklayın`;}}if (gameActive) requestAnimationFrame(updateGame);}</script></body></html>
Kullanıcı metin alanına yazı
girdikçe kaç karakter yazdığını gösterir ve önceden
belirlenen sınıra ulaşıldığında uyarı vererek daha fazla
giriş yapılmasını engeller.
Dosya Adı:
18-karakter-sayaci.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Karakter Sayacı</title><style>body {font-family: system-ui, sans-serif;background-color: #f8f9fa;display: flex;justify-content: center;align-items: center;height:100vh;margin:0;}.counter-card {background: white;padding:25px;border-radius:10px;box-shadow:04px15px rgba(0,0,0,0.05);width:450px;}h3{ margin-top:0; color: #333; }textarea {width:100%;height:120px;padding:10px;font-size:16px;border:2px solid #ccc;border-radius:6px;box-sizing: border-box;resize: none;transition:0.2s;}textarea:focus { border-color: #3498db; outline: none; }.status-bar {display: flex;justify-content: space-between;margin-top:10px;font-size:15px;font-weight: bold;color: #555;}.warning { color: #e74c3c !important; }</style></head><body><divclass="counter-card"><h3>📝 Karakter Sayacı (Tweet Sınırı)</h3><textareaid="txtArea"placeholder="Mesajınızı buraya yazın..."maxlength="140"></textarea><divclass="status-bar"><divid="infoMsg">Kalan Karakter:140</div><div><spanid="charCount">0</span> /140</div></div></div><script>const txtArea = document.getElementById('txtArea');const charCount = document.getElementById('charCount');const infoMsg = document.getElementById('infoMsg');const maxChars =140;txtArea.addEventListener('input', () => {let currentLength = txtArea.value.length;let remaining = maxChars - currentLength;charCount.textContent = currentLength;infoMsg.textContent = `Kalan Karakter: ${remaining}`;// Sınır durum kontrolüne göre arayüz renklendirmesiif (remaining <=20) {charCount.classList.add('warning');infoMsg.classList.add('warning');} else {charCount.classList.remove('warning');infoMsg.classList.remove('warning');}});</script></body></html>
Haber sitelerinde yer alan kayan
yazılar gibidir. Liste elemanları sürekli yukarı kayar, kullanıcı
fareyi üzerine getirdiğinde durur, çektiğinde kaldığı yerden
akmaya devam eder.
Dosya Adı:
19-otomatik-kayan-icerik.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Otomatik Kayan İçerik</title><style>body {font-family: sans-serif;background-color: #f1f2f6;display: flex;justify-content: center;align-items: center;height:100vh;margin:0;}.scroller-box {width:350px;height:150px;background: white;border:2px solid #dfe4ea;border-radius:8px;overflow: hidden;position: relative;box-shadow:04px10px rgba(0,0,0,0.05);}.scroller-content {position: absolute;width:100%;margin:0;padding:0;list-style: none;top:0;}.scroller-content li {padding:15px;border-bottom:1px solid #f1f2f6;color: #2f3542;font-weight: bold;}</style></head><body><divclass="scroller-box"id="scrollerBox"><ulclass="scroller-content"id="scrollerContent"><li>🔥 JavaScript ES6+ Özellikleri Yayında!</li><li>⚡ Asenkron Programlama Teknikleri Öğrenin.</li><li>🚀45Proje ile Web Geliştirme Eğitimi.</li><li>🤖 Yapay Zeka Entegrasyonları Başladı.</li></ul></div><script>const box = document.getElementById('scrollerBox');const content = document.getElementById('scrollerContent');let scrollSpeed =1;let scrollInterval;let currentTop =0;// Sonsuz döngü hissi yaratmak için ilk listenin kopyasını sonuna ekliyoruzcontent.innerHTML += content.innerHTML;function startScrolling() {scrollInterval = setInterval(() => {currentTop -= scrollSpeed;// Listenin tam yarısına gelindiğinde (orijinal içerik bittiğinde) başa sarıyoruzif (Math.abs(currentTop) >= content.scrollHeight /2) {currentTop =0;}content.style.top = currentTop +'px';},30);}// Fare olaylarını pusuya yatıp dinleme (Hover kontrolü)box.addEventListener('mouseover', () => clearInterval(scrollInterval));box.addEventListener('mouseout', startScrolling);// Akışı başlatstartScrolling();</script></body></html>
Web arayüzündeki öğeleri
farenizle tutup çöp kutusu görselinin üzerine sürükleyerek
sayfadan dinamik olarak yok etmenizi (Element.remove())
sağlayan yerleşik HTML5 Drag & Drop projesidir.
Dosya
Adı:
20-surukle-birak-cop-kutusu.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Sürükle Bırak Çöp Kutusu</title><style>body {font-family: sans-serif;background-color: #f7f9fa;display: flex;justify-content: center;align-items: center;height:100vh;margin:0;gap:50px;}.items-panel {width:250px;display: flex;flex-direction: column;gap:10px;}.drag-item {background: #3498db;color: white;padding:15px;border-radius:6px;cursor: grab;font-weight: bold;text-align: center;box-shadow:03px6px rgba(0,0,0,0.1);}.drag-item:active { cursor: grabbing; }.trash-bin {width:180px;height:180px;border:4px dashed #95a5a6;border-radius:12px;display: flex;flex-direction: column;justify-content: center;align-items: center;color: #7f8c8d;font-weight: bold;font-size:18px;transition:0.2s;background: white;}.drag-over {border-color: #e74c3c;background-color: #fadbd8;color: #c0392b;transform: scale(1.05);}</style></head><body><divclass="items-panel"><divclass="drag-item"draggable="true"id="item1">🗒️ Eski Notlar</div><divclass="drag-item"draggable="true"id="item2">📂 Geçici Dosya</div><divclass="drag-item"draggable="true"id="item3">🗑️ Çöp Metin Bloğu</div></div><divclass="trash-bin"id="trashBin"><span>🗑️</span><spanstyle="margin-top: 10px;">Çöp Kutusu</span></div><script>const items = document.querySelectorAll('.drag-item');const trashBin = document.getElementById('trashBin');items.forEach(item => {item.addEventListener('dragstart', (e) => {// Sürüklenen elemanın ID'sini hafızaya alıyoruze.dataTransfer.setData('text/plain', e.target.id);});});// Çöp kutusu üzerindeki olayların yönetilmesitrashBin.addEventListener('dragover', (e) => {e.preventDefault(); // Varsayılan engellemeyi kaldırarak bırakmaya izin veriyoruztrashBin.classList.add('drag-over');});trashBin.addEventListener('dragleave', () => {trashBin.classList.remove('drag-over');});trashBin.addEventListener('drop', (e) => {e.preventDefault();trashBin.classList.remove('drag-over');// Taşınan elemanın ID'sini çekip DOM'dan yok ediyoruzconst droppedItemId = e.dataTransfer.getData('text/plain');const droppedElement = document.getElementById(droppedItemId);if (droppedElement) {droppedElement.remove();alert("Öğe başarıyla imha edildi!");}});</script></body></html>
Müfredat listemizdeki 21. ve 25. projeler arasındaki uygulamaların tüm HTML, CSS ve JavaScript kod bloklarını, tarayıcınızda doğrudan kopyalayıp çalıştırabileceğiniz şekilde tek bir dosya formatında hazırladım.
HTML dosyasında hiçbir buton veya
yazı yokken, tüm elementlerin ve sayaç mekanizmasının tamamen
JavaScript koduyla havadan var edildiği (document.createElement)
bir projedir.
Dosya Adı:
21-sadece-js-tik-sayaci.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Yalnızca JavaScript Tık Sayacı</title><style>body {font-family: system-ui, sans-serif;background-color: #f1f2f6;display: flex;justify-content: center;align-items: center;height:100vh;margin:0;}/* Dinamik oluşturulacak kartın stilleri */.js-card {background: white;padding:30px;border-radius:12px;box-shadow:05px15px rgba(0,0,0,0.1);text-align: center;width:300px;}.js-counter {font-size:48px;font-weight: bold;color: #2f3542;margin:20px0;}.js-btn {padding:10px20px;font-size:16px;font-weight: bold;color: white;background-color: #ff4757;border: none;border-radius:6px;cursor: pointer;transition: background0.2s;}.js-btn:hover { background-color: #ff6b81; }</style></head><body><!-- HTML İÇERİĞİ TAMAMEN BOŞTUR. HER ŞEYİ JAVASCRIPT OLUŞTURACAK --><script>//1. Ana kart kutusunu oluşturuyoruzconst card = document.createElement('div');card.className ='js-card';//2. Başlığı oluşturuyoruzconst title = document.createElement('h2');title.textContent ='Saf JS Sayaç';title.style.margin ='0';title.style.color ='#747d8c';//3. Sayacı tutacak alanı oluşturuyoruzlet count =0;const counterDisplay = document.createElement('div');counterDisplay.className ='js-counter';counterDisplay.textContent = count;//4. Butonu oluşturuyoruzconst button = document.createElement('button');button.className ='js-btn';button.textContent ='Tıkla ve Arttır 👆';// Butona tıklama olayı (Event) ekliyoruzbutton.addEventListener('click', () => {count++;counterDisplay.textContent = count;});//5. Oluşturulan tüm elementleri iç içe ekleyip sayfaya bağlıyoruzcard.appendChild(title);card.appendChild(counterDisplay);card.appendChild(button);document.body.appendChild(card);</script></body></html>
Sayfadaki herhangi bir küçük
resme tıklandığında, resmin büyük halini ekranı kaplayan siyah
şeffaf bir katman üzerinde açan galeri odaklı bir projedir.
Dosya
Adı: 22-gorsel-popup.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Görsel Pop-up Penceresi</title><style>body {font-family: sans-serif;background-color: #f5f6fa;margin:0;padding:40px;text-align: center;}.gallery {display: flex;justify-content: center;gap:20px;margin-top:30px;}.gallery img {width:200px;height:150px;object-fit: cover;border-radius:8px;cursor: pointer;box-shadow:04px8px rgba(0,0,0,0.1);transition: transform0.2s;}.gallery img:hover { transform: scale(1.05); }/* Arka Plan Pop-up Kapsayıcısı */.popup-overlay {position: fixed;top:0;left:0;width:100vw;height:100vh;background-color: rgba(0,0,0,0.85);display: flex;justify-content: center;align-items: center;opacity:0;pointer-events: none;transition: opacity0.3s ease;z-index:10;}.popup-overlay.open {opacity:1;pointer-events: auto;}.popup-img {max-width:80%;max-height:80%;border-radius:8px;box-shadow:05px25px rgba(0,0,0,0.5);transform: scale(0.8);transition: transform0.3s ease;}.popup-overlay.open .popup-img { transform: scale(1); }.close-btn {position: absolute;top:20px;right:30px;color: white;font-size:40px;cursor: pointer;user-select: none;}</style></head><body><h1>📷 Resim Galerisi Pop-up Sistemi</h1><p>Büyük halini görmek istediğiniz resmin üzerine tıklayın.</p><divclass="gallery"><!-- Test amaçlı farklı renklere sahip hazır çizim görselleri kullanılmıştır --><imgsrc="https://picsum.photos"alt="Doğa"><imgsrc="https://picsum.photos"alt="Yazı Masası"><imgsrc="https://picsum.photos"alt="Anahtarlık"></div><!-- Gizli Pop-up Alanı --><divclass="popup-overlay"id="popupOverlay"><spanclass="close-btn"id="closeBtn">×</span><imgsrc=""class="popup-img"id="popupImg"alt="Büyük Görsel"></div><script>const galleryImages = document.querySelectorAll('.gallery img');const popupOverlay = document.getElementById('popupOverlay');const popupImg = document.getElementById('popupImg');const closeBtn = document.getElementById('closeBtn');galleryImages.forEach(img => {img.addEventListener('click', () => {popupImg.src = img.src; // Tıklanan resmin kaynağını pop-up alanına aktarıyoruzpopupOverlay.classList.add('open');});});// Kapatma butonuna veya siyah arka plana tıklandığında pop-up penceresini gizlecloseBtn.addEventListener('click', () => popupOverlay.classList.remove('open'));popupOverlay.addEventListener('click', (e) => {if (e.target === popupOverlay) {popupOverlay.classList.remove('open');}});</script></body></html>
Kullanıcı bir işleme
tıkladığında sayfa akışını keserek ekrana gelen, CSS
sınıfları (classList.add/remove)
aracılığıyla açılıp kapanan uyarı ve bildirim
penceresidir.
Dosya Adı:
23-modal-pencere.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Modal Pencere Görünümü</title><style>body {font-family: system-ui, sans-serif;background-color: #f0f2f5;display: flex;justify-content: center;align-items: center;height:100vh;margin:0;}.trigger-btn {background-color: #1e90ff;color: white;border: none;padding:14px28px;font-size:16px;font-weight: bold;border-radius:6px;cursor: pointer;box-shadow:04px10px rgba(30,144,255,0.3);}.trigger-btn:hover { background-color: #117ee6; }/* Modal Arka Katman */.modal-container {position: fixed;top:0;left:0;width:100vw;height:100vh;background-color: rgba(0,0,0,0.5);display: flex;justify-content: center;align-items: center;opacity:0;pointer-events: none;transition: opacity0.25s ease;}.modal-container.show {opacity:1;pointer-events: auto;}/* Modal Gövdesi */.modal-box {background: white;padding:25px;border-radius:10px;width:400px;box-shadow:010px30px rgba(0,0,0,0.2);text-align: left;transform: translateY(-30px);transition: transform0.25s ease;}.modal-container.show .modal-box { transform: translateY(0); }.modal-box h3{ margin-top:0; color: #2f3542; }.modal-box p { color: #57606f; line-height:1.5; }.action-area {display: flex;justify-content: flex-end;gap:10px;margin-top:20px;}.close-modal-btn {background-color: #ced6e0;color: #2f3542;border: none;padding:8px16px;border-radius:4px;cursor: pointer;font-weight: bold;}.close-modal-btn:hover { background-color: #a4b0be; }</style></head><body><buttonclass="trigger-btn"id="openModalBtn">⚙️ Ayarları Düzenle</button><!-- Kapsayıcı Modal --><divclass="modal-container"id="modalContainer"><divclass="modal-box"><h3>Sistem Bildirimi</h3><p>Değişiklikleri kaydetmek istediğinizden emin misiniz? Bu işlem geri alınamaz ve tüm aktif oturumlar güncellenir.</p><divclass="action-area"><buttonclass="close-modal-btn"id="cancelBtn">İptal</button><buttonclass="close-modal-btn"style="background-color: #2ed573; color: white;"id="confirmBtn">Onayla</button></div></div></div><script>const openModalBtn = document.getElementById('openModalBtn');const modalContainer = document.getElementById('modalContainer');const cancelBtn = document.getElementById('cancelBtn');const confirmBtn = document.getElementById('confirmBtn');openModalBtn.addEventListener('click', () => {modalContainer.classList.add('show');});function closeModal() {modalContainer.classList.remove('show');}cancelBtn.addEventListener('click', closeModal);confirmBtn.addEventListener('click', () => {alert("İşlem onaylandı!");closeModal();});// Boş arka plana tıklandığında kapatma kontrolümodalContainer.addEventListener('click', (e) => {if (e.target === modalContainer) closeModal();});</script></body></html>
Önceki ve sonraki butonlarına
basıldığında listelenen görselleri sırasıyla değiştiren ve
alt kısımdaki yuvarlak düğmelerle (indikatörler) senkronize
çalışan bir slider projesidir.
Dosya Adı:
24-resim-galerisi-slider.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Resim Slayt Gösterisi</title><style>body {font-family: sans-serif;background-color: #f7f9fa;display: flex;flex-direction: column;align-items: center;padding-top:50px;margin:0;}.carousel-wrapper {position: relative;width:500px;height:330px;border-radius:10px;overflow: hidden;box-shadow:08px20px rgba(0,0,0,0.15);}.slide {width:100%;height:100%;object-fit: cover;display: none;}.slide.active { display: block; }/* Kontrol Okları */.arrow-btn {position: absolute;top:50%;transform: translateY(-50%);background: rgba(0,0,0,0.5);color: white;border: none;width:40px;height:40px;font-size:20px;font-weight: bold;cursor: pointer;border-radius:50%;user-select: none;}.arrow-btn:hover { background: rgba(0,0,0,0.8); }.prev { left:15px; }.next { right:15px; }/* Noktalı İndikatör Alanı */.dots-panel {display: flex;gap:8px;margin-top:15px;}.dot {width:12px;height:12px;background-color: #ccc;border-radius:50%;cursor: pointer;transition: background0.2s;}.dot.active { background-color: #2f3542; }</style></head><body><h2>🎬 JavaScript Akıllı Slider</h2><divclass="carousel-wrapper"><imgsrc="https://picsum.photos"class="slide active"alt="Görsel 1"><imgsrc="https://picsum.photos"class="slide"alt="Görsel 2"><imgsrc="https://picsum.photos"class="slide"alt="Görsel 3"><buttonclass="arrow-btn prev"id="prevBtn">❮</button><buttonclass="arrow-btn next"id="nextBtn">❯</button></div><divclass="dots-panel"id="dotsPanel"></div><script>const slides = document.querySelectorAll('.slide');const prevBtn = document.getElementById('prevBtn');const nextBtn = document.getElementById('nextBtn');const dotsPanel = document.getElementById('dotsPanel');let currentIndex =0;// Alt kısımdaki noktaları dinamik olarak resim sayısı kadar oluşturuyoruzslides.forEach((_, index) => {const dot = document.createElement('div');dot.className ='dot'+ (index ===0?' active':'');dot.addEventListener('click', () => changeSlide(index));dotsPanel.appendChild(dot);});const dots = document.querySelectorAll('.dot');function changeSlide(newIndex) {// Sınır kontrolü (Başa sarma veya sona sarma)if (newIndex >= slides.length) newIndex =0;if (newIndex <0) newIndex = slides.length -1;// Mevcut aktifleri kaldırslides[currentIndex].classList.remove('active');dots[currentIndex].classList.remove('active');// Yeni aktifi atacurrentIndex = newIndex;slides[currentIndex].classList.add('active');dots[currentIndex].classList.add('active');}nextBtn.addEventListener('click', () => changeSlide(currentIndex +1));prevBtn.addEventListener('click', () => changeSlide(currentIndex -1));</script></body></html>
Kullanıcı fareyi yıldızların
üzerine getirdiğinde geçici puanı gösteren (mouseover),
tıkladığında ise puanı kilitleyip sunucuya göndermeye hazır
hale getiren interaktif puanlama arayüzüdür.
Dosya
Adı:
25-yildiz-derecelendirme.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Yıldız Değerlendirme Sistemi</title><style>body {font-family: sans-serif;background-color: #f1f2f6;display: flex;flex-direction: column;align-items: center;justify-content: center;height:100vh;margin:0;}.rating-box {background: white;padding:25px;border-radius:10px;box-shadow:04px12px rgba(0,0,0,0.05);text-align: center;}.stars {display: flex;gap:10px;justify-content: center;margin:15px0;font-size:35px;color: #ccc;cursor: pointer;}/* Seçili veya üzerine gelinen yıldız rengi */.star.hovered, .star.selected {color: #f1c40f;}.status-txt {font-size:16px;font-weight: bold;color: #57606f;min-height:22px;}</style></head><body><divclass="rating-box"><h3>Uygulamayı Değerlendirin</h3><divclass="stars"id="starContainer"><spanclass="star"data-value="1">★</span><spanclass="star"data-value="2">★</span><spanclass="star"data-value="3">★</span><spanclass="star"data-value="4">★</span><spanclass="star"data-value="5">★</span></div><divclass="status-txt"id="statusTxt">Puan vermek için yıldız seçin.</div></div><script>const stars = document.querySelectorAll('.star');const statusTxt = document.getElementById('statusTxt');let lockedRating =0; // Tıklanıp sabitlenen puanstars.forEach(star => {//1. Fare üzerine geldiğinde geçici renklendirmestar.addEventListener('mouseover', function() {const currentHoverValue = parseInt(this.getAttribute('data-value'));highlightStars(currentHoverValue,'hovered');});//2. Fare çekildiğinde geçici rengi silstar.addEventListener('mouseout', function() {clearHighlights('hovered');});//3. Tıklandığında puanı kilitlestar.addEventListener('click', function() {lockedRating = parseInt(this.getAttribute('data-value'));clearHighlights('selected');highlightStars(lockedRating,'selected');statusTxt.textContent = `Teşekkürler! Puanınız: ${lockedRating} /5`;statusTxt.style.color ='#2ed573';});});function highlightStars(value, className) {stars.forEach(star => {if (parseInt(star.getAttribute('data-value')) <= value) {star.classList.add(className);}});}function clearHighlights(className) {stars.forEach(star => star.classList.remove(className));}</script></body></html>
Müfredat listemizdeki 26. ve 30. projeler arasındaki uygulamaların tüm HTML, CSS ve JavaScript kod bloklarını, tarayıcınızda doğrudan kopyalayıp çalıştırabileceğiniz şekilde tek bir dosya formatında hazırladım.
Klavyedeki sağ ve sol yön
tuşlarıyla üstteki uçağı hareket ettirip, boşluk (Space)
tuşuna basarak bombalar bıraktığınız ve aşağıdaki hareketli
hedefi vurmaya çalıştığınız bir DOM oyunudur.
Dosya
Adı: 26-ucak-bombardiman.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Uçak Bombardıman Oyunu</title><style>body {font-family: sans-serif;background: #2c3e50;color: white;margin:0;display: flex;flex-direction: column;align-items: center;justify-content: center;height:100vh;overflow: hidden;}.info-panel { font-size:20px; font-weight: bold; margin-bottom:10px; }.game-screen {width:500px;height:400px;background: #34495e;border:4px solid #ecf0f1;position: relative;border-radius:8px;}.plane {width:50px;height:25px;background: #e74c3c;position: absolute;top:20px;left:225px;border-radius:4px;}.target {width:60px;height:20px;background: #2ecc71;position: absolute;bottom:10px;left:0;border-radius:3px;}.bomb {width:10px;height:20px;background: #f1c40f;position: absolute;border-radius:50%50%20%20%;}</style></head><body><divclass="info-panel">Skor: <spanid="scoreTxt">0</span> | Sağ/Sol Ok Tuşları: Hareket | Boşluk: Bomba</div><divclass="game-screen"id="gameScreen"><divclass="plane"id="plane"></div><divclass="target"id="target"></div></div><script>const screen = document.getElementById('gameScreen');const plane = document.getElementById('plane');const target = document.getElementById('target');const scoreTxt = document.getElementById('scoreTxt');let planeX =225;let targetX =0;let targetSpeed =3;let score =0;let keys = {};let isBombActive = false;window.addEventListener('keydown', (e) => keys[e.key] = true);window.addEventListener('keyup', (e) => keys[e.key] = false);function gameLoop() {// Uçak Hareketi Kontrolüif (keys['ArrowLeft'] && planeX >0) planeX -=5;if (keys['ArrowRight'] && planeX <450) planeX +=5;plane.style.left = planeX +'px';// Hedef HareketitargetX += targetSpeed;if (targetX >440|| targetX <0) {targetSpeed = -targetSpeed; // Duvara çarpınca geri dönsün}target.style.left = targetX +'px';// Bomba Atma Kontrolüif (keys[' '] && !isBombActive) {dropBomb();}requestAnimationFrame(gameLoop);}function dropBomb() {isBombActive = true;const bomb = document.createElement('div');bomb.className ='bomb';bomb.style.left = (planeX +20) +'px';bomb.style.top ='45px';screen.appendChild(bomb);let bombY =45;const bombInterval = setInterval(() => {bombY +=5;bomb.style.top = bombY +'px';// Zemin Kontrolüif (bombY >370) {// Çarpışma Testi (Bomba hedefi vurdu mu?)let bombX = parseInt(bomb.style.left);if (bombX >= targetX && bombX <= targetX +60) {score++;scoreTxt.textContent = score;targetX =0; // Hedefi sıfırla (vurulma etkisi)}clearInterval(bombInterval);bomb.remove();isBombActive = false;}},20);}requestAnimationFrame(gameLoop);</script></body></html>
Siz yön tuşlarıyla mavi kutuyu
hareket ettirirken, harita üzerinde rastgele sürekli yön
değiştiren kırmızı kutuyu yakalamaya çalıştığınız
eğlenceli bir yakalama oyunudur.
Dosya Adı:
27-kutu-kovalama.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Kutu Kovalama Oyunu</title><style>body {font-family: sans-serif;background-color: #f1f2f6;display: flex;flex-direction: column;align-items: center;justify-content: center;height:100vh;margin:0;}.hud { font-size:22px; font-weight: bold; margin-bottom:10px; color: #2f3542; }.arena {width:400px;height:400px;background-color: white;border:4px solid #2f3542;position: relative;border-radius:8px;box-shadow:08px16px rgba(0,0,0,0.1);}.player-box {width:30px;height:30px;background-color: #3498db;position: absolute;border-radius:4px;}.enemy-box {width:30px;height:30px;background-color: #e74c3c;position: absolute;border-radius:4px;transition: all0.3s linear;}</style></head><body><divclass="hud">Skorunuz: <spanid="scoreTxt">0</span></div><divclass="arena"id="arena"><divclass="player-box"id="player"style="top: 0px; left: 0px;"></div><divclass="enemy-box"id="enemy"style="top: 200px; left: 200px;"></div></div><script>const player = document.getElementById('player');const enemy = document.getElementById('enemy');const scoreTxt = document.getElementById('scoreTxt');let pX =0, pY =0;let eX =200, eY =200;let score =0;const size =30;const maxBound =370;// Oyuncu Hareketi (Yön tuşları)window.addEventListener('keydown', (e) => {switch (e.key) {case'ArrowUp': if (pY >0) pY -=15; break;case'ArrowDown': if (pY < maxBound) pY +=15; break;case'ArrowLeft': if (pX >0) pX -=15; break;case'ArrowRight': if (pX < maxBound) pX +=15; break;}player.style.left = pX +'px';player.style.top = pY +'px';checkCollision();});// Kırmızı kutunun yapay zeka hareketi (Her400ms'de rastgele kaçar)setInterval(() => {const directions = [-30,0,30];eX += directions[Math.floor(Math.random() *3)];eY += directions[Math.floor(Math.random() *3)];// Arena dışına taşma kontrolüif (eX <0) eX =0; if (eX > maxBound) eX = maxBound;if (eY <0) eY =0; if (eY > maxBound) eY = maxBound;enemy.style.left = eX +'px';enemy.style.top = eY +'px';checkCollision();},400);// Çarpışma / Yakalama Algılamafunction checkCollision() {const xDist = Math.abs(pX - eX);const yDist = Math.abs(pY - eY);if (xDist < size && yDist < size) {score++;scoreTxt.textContent = score;// Yakalanınca kırmızı kutuyu rastgele bir yere ışınlaeX = Math.floor(Math.random() * (maxBound /30)) *30;eY = Math.floor(Math.random() * (maxBound /30)) *30;enemy.style.left = eX +'px';enemy.style.top = eY +'px';}}</script></body></html>
Sayfadaki nesnelerin üzerine
gelindiğinde, farenin tam konumunu (clientX/clientY)
izleyerek dinamik bir açıklama balonu açan kullanıcı deneyimi
aracıdır.
Dosya Adı:
28-tooltip-popup.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Bilgi İpucu Kutusu (Tooltip)</title><style>body {font-family: system-ui, sans-serif;background-color: #f5f6fa;padding:50px;text-align: center;}.container {margin-top:100px;display: flex;justify-content: center;gap:40px;}.tooltip-target {padding:15px30px;background-color: #9b59b6;color: white;font-weight: bold;border-radius:6px;cursor: help;user-select: none;}/* Gizli Dinamik Tooltip Gövdesi */.custom-tooltip {position: fixed;background-color: #2c3e50;color: #ecf0f1;padding:8px12px;font-size:13px;border-radius:4px;pointer-events: none;display: none;z-index:1000;box-shadow:04px8px rgba(0,0,0,0.15);}</style></head><body><h2>📌 Akıllı Fare Takipçi Tooltip</h2><p>Butonların üzerine farenizle gelin ve hareketi izleyin.</p><divclass="container"><divclass="tooltip-target"data-tip="Bu buton JavaScript kullanarak hesaplama yapar.">Hesaplama</div><divclass="tooltip-target"data-tip="Verileriniz yerel hafızada şifreli saklanır.">Güvenlik Bilgisi</div></div><divclass="custom-tooltip"id="tooltipBox">İpucu Metni</div><script>const targets = document.querySelectorAll('.tooltip-target');const tooltipBox = document.getElementById('tooltipBox');targets.forEach(target => {target.addEventListener('mouseenter', (e) => {const text = target.getAttribute('data-tip');tooltipBox.textContent = text;tooltipBox.style.display ='block';});target.addEventListener('mousemove', (e) => {// Fare konumunun15piksel sağına ve altına yerleştir (Kürsörün altında kalmasın)tooltipBox.style.left = (e.clientX +15) +'px';tooltipBox.style.top = (e.clientY +15) +'px';});target.addEventListener('mouseleave', () => {tooltipBox.style.display ='none';});});</script></body></html>
Girdiğiniz düz metin bloklarının
içerisindeki e-posta adreslerini cımbızla çeker gibi Regex
formülleri ile ayıklayan ve yinelenen kayıtları silen bir veri
aracıdır.
Dosya Adı:
29-eposta-ayiklayici.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>E-posta Ayıklayıcı Uygulaması</title><style>body {font-family: system-ui, sans-serif;background-color: #f7f9fa;padding:30px;}.wrapper {max-width:600px;margin:0auto;background: white;padding:25px;border-radius:10px;box-shadow:04px12px rgba(0,0,0,0.05);}textarea {width:100%;height:150px;padding:10px;border:2px solid #ced4da;border-radius:6px;box-sizing: border-box;resize: none;font-size:15px;}button {margin-top:15px;background-color: #1abc9c;color: white;border: none;padding:12px24px;font-size:16px;font-weight: bold;border-radius:6px;cursor: pointer;width:100%;}button:hover { background-color: #16a085; }.output-box {margin-top:20px;background: #e8f8f5;padding:15px;border-radius:6px;border-left:5px solid #1abc9c;display: none;}.output-list { padding-left:20px; margin:5px0; color: #16a085; font-weight: bold; }</style></head><body><divclass="wrapper"><h2>📧 Akıllı E-posta Ayıklayıcı</h2><p>İçinde e-posta adresleri geçen karmaşık bir metin yapıştırın:</p><textareaid="rawText"placeholder="Örnek: Merhaba, bana test@gmail.com adresinden veya bilgi@sirket.com üzerinden ulaşabilirsiniz..."></textarea><buttonid="extractBtn">E-postaları Bul ve Listele</button><divclass="output-box"id="outputBox"><h4style="margin: 0 0 10px 0; color: #16a085;">Bulunan E-posta Adresleri:</h4><ulclass="output-list"id="outputList"></ul></div></div><script>document.getElementById('extractBtn').addEventListener('click', () => {const rawText = document.getElementById('rawText').value;const outputBox = document.getElementById('outputBox');const outputList = document.getElementById('outputList');outputList.innerHTML =""; // Eski listeyi temizle// Evrensel E-posta Bulma Düzenli İfadesi (Regex)const emailRegex = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g;const matches = rawText.match(emailRegex);if (matches) {// Set kullanarak yinelenen çift e-postaları eliyoruzconst benzersizEpostalar = [...new Set(matches)];benzersizEpostalar.forEach(email => {const li = document.createElement('li');li.textContent = email;outputList.appendChild(li);});outputBox.style.display ='block';} else {alert("Metin içerisinde hiçbir e-posta adresi bulunamadı!");outputBox.style.display ='none';}});</script></body></html>
Butona basıldığında ekranın
sağ üst köşesinden yumuşak bir kayma efektiyle beliren, 3 saniye
sonra kendi kendini yok eden modern bildirim (Toast Notification)
sistemidir.
Dosya Adı:
30-popup-mesaj-bildirimi.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Pop-up Mesaj Bildirimi</title><style>body {font-family: sans-serif;background-color: #f1f2f6;display: flex;justify-content: center;align-items: center;height:100vh;margin:0;}.action-btn {padding:14px28px;background-color: #2ed573;color: white;font-size:16px;font-weight: bold;border: none;border-radius:6px;cursor: pointer;box-shadow:04px10px rgba(46,213,115,0.3);}/* Bildirimleri Hizalama Paneli */.notification-container {position: fixed;top:20px;right:20px;display: flex;flex-direction: column;gap:10px;z-index:9999;}/* Toast Bildirim Kutusu */.toast {background-color: #2f3542;color: white;padding:15px25px;border-radius:6px;font-weight: bold;box-shadow:04px12px rgba(0,0,0,0.2);transform: translateX(120%);transition: transform0.4s cubic-bezier(0.175,0.885,0.32,1.275);border-left:6px solid #2ed573;}.toast.show {transform: translateX(0);}</style></head><body><buttonclass="action-btn"id="notifyBtn">Sisteme Giriş Yap</button><!-- Bildirimlerin Havada Oluşacağı Kapsayıcı Alan --><divclass="notification-container"id="notiContainer"></div><script>const notifyBtn = document.getElementById('notifyBtn');const container = document.getElementById('notiContainer');notifyBtn.addEventListener('click', () => {// Havadan bildirim kutusu oluşturuyoruzconst toast = document.createElement('div');toast.className ='toast';toast.textContent ='🚀 Başarılı: Oturum açma işlemi tamamlandı!';container.appendChild(toast);// Kısa bir gecikmeyle CSS animasyon sınıfını ekle (Sağdan içeri kaysın)setTimeout(() => toast.classList.add('show'),50);//3saniye sonra kutuyu sağa kaydırıp DOM'dan tamamen imha etsetTimeout(() => {toast.classList.remove('show');// Geçiş animasyonu bittikten sonra element silinsinsetTimeout(() => toast.remove(),400);},3000);});</script></body></html>
Müfredat listemizdeki 31. ve 35. projeler arasındaki uygulamaların tüm HTML, CSS ve JavaScript kod bloklarını, tarayıcınızda doğrudan kopyalayıp çalıştırabileceğiniz şekilde tek bir dosya formatında hazırladım.
Kullanıcının girdiği metni veya
sayfadaki bir alanı tek bir butonla tarayıcının panosuna
(navigator.clipboard.writeText)
kopyalayan ve kopyalandıktan sonra kullanıcıya görsel geri
bildirim sunan kullanışlı bir araçtır.
Dosya Adı:
31-pano-kopyalayiici.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Pano Kopyalayıcı Uygulaması</title><style>body {font-family:'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;background-color: #f1f2f6;display: flex;justify-content: center;align-items: center;height:100vh;margin:0;}.copy-box {background: white;padding:25px;border-radius:12px;box-shadow:05px15px rgba(0,0,0,0.05);width:400px;text-align: center;}textarea {width:100%;height:100px;padding:10px;border:2px solid #ced4da;border-radius:6px;box-sizing: border-box;resize: none;font-size:16px;margin-bottom:15px;}textarea:focus { border-color: #5758bb; outline: none; }button {background-color: #5758bb;color: white;border: none;padding:12px24px;font-size:16px;font-weight: bold;border-radius:6px;cursor: pointer;width:100%;transition: background0.2s;}button:hover { background-color: #3d3e9a; }.success-msg {margin-top:10px;color: #2ed573;font-weight: bold;font-size:14px;opacity:0;transition: opacity0.3s;}.success-msg.show { opacity:1; }</style></head><body><divclass="copy-box"><h3style="margin-top: 0; color: #2f3542;">📋 Panoya Kopyala</h3><textareaid="copyText"placeholder="Kopyalamak istediğiniz metni buraya yazın...">Örnek kod parçası veya kopyalanacak önemli bir metin bloğu buraya gelebilir.</textarea><buttonid="copyBtn">Panoya Kopyala</button><divclass="success-msg"id="successMsg">✓ Başarıyla panoya kopyalandı!</div></div><script>const copyText = document.getElementById('copyText');const copyBtn = document.getElementById('copyBtn');const successMsg = document.getElementById('successMsg');copyBtn.addEventListener('click', () => {const textToCopy = copyText.value;if (textToCopy.trim() ==="") {alert("Lütfen kopyalayacak bir metin girin!");return;}// Modern Clipboard API kullanımınavigator.clipboard.writeText(textToCopy).then(() => {// Başarılı kopyalama bildirimisuccessMsg.classList.add('show');copyBtn.textContent ="Kopyalandı!";copyBtn.style.backgroundColor ="#2ed573";//2saniye sonra arayüzü eski haline getirsetTimeout(() => {successMsg.classList.remove('show');copyBtn.textContent ="Panoya Kopyala";copyBtn.style.backgroundColor ="#5758bb";},2000);}).catch(err => {console.error('Kopyalama hatası: ', err);alert('Kopyalama işlemi başarısız oldu.');});});</script></body></html>
Matematiksel işlemleri butonlar
aracılığıyla ekranına yazdıran ve eval()
fonksiyonu yerine güvenli, adım adım çalışan bir dize (string)
işleme algoritmasıyla sonuçlandıran fonksiyonel bir hesap
makinesidir.
Dosya Adı:
32-hesap-makinesi.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>JavaScript Hesap Makinesi</title><style>body {font-family: Arial, sans-serif;background-color: #2f3542;display: flex;justify-content: center;align-items: center;height:100vh;margin:0;}.calculator {background-color: #1e222b;padding:20px;border-radius:12px;box-shadow:010px25px rgba(0,0,0,0.4);width:300px;}.screen {width:100%;height:60px;background-color: #2f3542;border: none;border-radius:6px;color: white;font-size:28px;text-align: right;padding:10px;box-sizing: border-box;margin-bottom:20px;}.buttons {display: grid;grid-template-columns: repeat(4,1fr);gap:10px;}button {padding:15px;font-size:20px;font-weight: bold;border: none;border-radius:6px;cursor: pointer;background-color: #747d8c;color: white;transition: background0.1s;}button:hover { background-color: #a4b0be; }.operator { background-color: #ff9f43; }.operator:hover { background-color: #ffb167; }.clear { background-color: #ee5253; grid-column: span2; }.clear:hover { background-color: #ff6b6b; }.equal { background-color: #10ac84; grid-column: span2; }.equal:hover { background-color: #1dd1a1; }</style></head><body><divclass="calculator"><inputtype="text"class="screen"id="calcScreen"readonly value="0"><divclass="buttons"><buttonclass="clear"onclick="clearScreen()">C</button><buttonclass="operator"onclick="appendValue('/')">/</button><buttonclass="operator"onclick="appendValue('*')">*</button><buttononclick="appendValue('7')">7</button><buttononclick="appendValue('8')">8</button><buttononclick="appendValue('9')">9</button><buttonclass="operator"onclick="appendValue('-')">-</button><buttononclick="appendValue('4')">4</button><buttononclick="appendValue('5')">5</button><buttononclick="appendValue('6')">6</button><buttonclass="operator"onclick="appendValue('+')">+</button><buttononclick="appendValue('1')">1</button><buttononclick="appendValue('2')">2</button><buttononclick="appendValue('3')">3</button><buttononclick="appendValue('0')">0</button><buttonclass="equal"onclick="calculateResult()">=</button></div></div><script>const screen = document.getElementById('calcScreen');let currentInput ="0";function updateScreen() {screen.value = currentInput;}function appendValue(value) {if (currentInput ==="0"&& !isNaN(value)) {currentInput = value;} else {// Son karakterin operatör olup olmadığını denetleyerek peş peşe operatör girişini engelleconst lastChar = currentInput.slice(-1);if (['+','-','*','/'].includes(lastChar) && ['+','-','*','/'].includes(value)) {return;}currentInput += value;}updateScreen();}function clearScreen() {currentInput ="0";updateScreen();}function calculateResult() {try {// eval() yerine basit hesaplama fonksiyonu (veya güvenli eval sarmalayıcısı)// Müfredatın eval bölümüne uygun olarak güvenli hata yakalamalı hesaplama yapılmıştırlet result = eval(currentInput);if (result === Infinity || isNaN(result)) {currentInput ="Hata";} else {currentInput = String(result);}} catch (error) {currentInput ="Hata";}updateScreen();}</script></body></html>
Listeye dinamik veri eklemenin yanı
sıra, eklenen her maddenin çift tıklandığında anında
düzenlenebilir yazı kutusuna (contenteditable)
dönüştüğü ve yanındaki silme butonlarıyla esnek yönetim
sunan bir uygulamadır.
Dosya Adı:
33-alisveris-listesi.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Dinamik Alışveriş Listesi</title><style>body {font-family: sans-serif;background-color: #f5f6fa;display: flex;justify-content: center;align-items: center;height:100vh;margin:0;}.list-card {background: white;padding:25px;border-radius:10px;box-shadow:04px12px rgba(0,0,0,0.05);width:350px;}.input-area {display: flex;gap:10px;margin-bottom:20px;}input {flex-grow:1;padding:8px;border:2px solid #ddd;border-radius:4px;font-size:15px;}button {background-color: #2ecc71;color: white;border: none;padding:8px15px;border-radius:4px;cursor: pointer;font-weight: bold;}ul { list-style: none; padding:0; margin:0; }li {display: flex;justify-content: space-between;align-items: center;padding:10px;border-bottom:1px solid #eee;font-size:16px;}.item-text {flex-grow:1;cursor: pointer;padding:2px5px;}.item-text:focus {background-color: #f1f2f6;outline:1px solid #3498db;border-radius:3px;}.delete-btn {background-color: #e74c3c;color: white;border: none;padding:4px8px;border-radius:3px;cursor: pointer;font-size:12px;}</style></head><body><divclass="list-card"><h3style="margin-top: 0; color: #2c3e50;">🛒 Alışveriş Listesi</h3><pstyle="font-size: 12px; color: #7f8c8d; margin-top: -5px;">Düzenlemek için ürün adına çift tıklayın.</p><divclass="input-area"><inputtype="text"id="itemInput"placeholder="Örn: Süt, Yumurta"><buttonid="addBtn">Ekle</button></div><ulid="shoppingList"></ul></div><script>const itemInput = document.getElementById('itemInput');const addBtn = document.getElementById('addBtn');const shoppingList = document.getElementById('shoppingList');addBtn.addEventListener('click', addItem);itemInput.addEventListener('keypress', (e) => {if (e.key ==='Enter') addItem();});function addItem() {const value = itemInput.value.trim();if (value ==="") return;const li = document.createElement('li');// Ürün Metni Alanıconst textSpan = document.createElement('span');textSpan.className ='item-text';textSpan.textContent = value;// Çift tıklayınca düzenlenebilir yapma özelliğitextSpan.addEventListener('dblclick', () => {textSpan.contentEditable = true;textSpan.focus();});// Düzenleme bittiğinde veya odağı kaybedince kilitlemetextSpan.addEventListener('blur', () => {textSpan.contentEditable = false;if (textSpan.textContent.trim() ==="") {li.remove(); // Boş bırakıldıysa tamamen sil}});// Silme Butonuconst delBtn = document.createElement('button');delBtn.className ='delete-btn';delBtn.textContent ='Sil';delBtn.addEventListener('click', () => li.remove());li.appendChild(textSpan);li.appendChild(delBtn);shoppingList.appendChild(li);itemInput.value ="";itemInput.focus();}</script></body></html>
Web tasarım süreçlerinde
kullanılmak üzere kullanıcının seçtiği boyut
(genişlik/yükseklik), arka plan rengi ve yazı rengine göre
dinamik olarak test resmi linki (URL) üreten pratik bir
araçtır.
Dosya Adı:
34-resim-linki-uretici.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Placeholder Image Path Generator</title><style>body {font-family: system-ui, sans-serif;background-color: #f8f9fa;padding:30px;}.container {max-width:500px;margin:0auto;background: white;padding:25px;border-radius:10px;box-shadow:04px12px rgba(0,0,0,0.05);}.form-group {margin-bottom:15px;text-align: left;}label { display: block; font-weight: bold; margin-bottom:5px; color: #495057; }input, select {width:100%;padding:8px;border:2px solid #dee2e6;border-radius:4px;box-sizing: border-box;}button {background-color: #0d6efd;color: white;border: none;padding:10px;width:100%;border-radius:4px;font-size:16px;font-weight: bold;cursor: pointer;margin-top:10px;}button:hover { background-color: #0b5ed7; }.result-box {margin-top:20px;padding:15px;background: #e9ecef;border-radius:4px;word-break: break-all;font-family: monospace;font-size:14px;display: none;}</style></head><body><divclass="container"><h3style="margin-top: 0; text-align: center;">🖼️ Sahte Resim Linki Üretici</h3><divclass="form-group"><label>Boyutlar (Genişlik x Yükseklik)</label><divstyle="display: flex; gap: 10px;"><inputtype="number"id="width"value="300"placeholder="Genişlik"><inputtype="number"id="height"value="200"placeholder="Yükseklik"></div></div><divclass="form-group"><label>Arka Plan Rengi (Hex Kodu olmadan)</label><inputtype="text"id="bgColor"value="34495e"placeholder="Örn: 34495e"></div><divclass="form-group"><label>Yazı Rengi (Hex Kodu olmadan)</label><inputtype="text"id="textColor"value="ecf0f1"placeholder="Örn: ecf0f1"></div><divclass="form-group"><label>Üzerindeki Metin (Opsiyonel)</label><inputtype="text"id="imgText"value="Test Resmi"placeholder="Örn: Banner"></div><buttonid="generateBtn">Link Üret</button><divclass="result-box"id="resultBox"></div></div><script>document.getElementById('generateBtn').addEventListener('click', () => {const width = document.getElementById('width').value ||'300';const height = document.getElementById('height').value ||'200';const bgColor = document.getElementById('bgColor').value ||'ccc';const textColor = document.getElementById('textColor').value ||'000';const imgText = encodeURIComponent(document.getElementById('imgText').value);// Popüler ve kararlı çalışan placeholder.co API altyapısı kullanılarak link oluşturmalet generatedUrl = `https://placeholder.com{width}x${height}/${bgColor}/${textColor}`;if (imgText) {generatedUrl += `?text=${imgText}`;}const resultBox = document.getElementById('resultBox');resultBox.innerHTML = `<strong>Oluşturulan Link:</strong><br><ahref="${generatedUrl}"target="_blank">${generatedUrl}</a>`;resultBox.style.display ='block';});</script></body></html>
Kullanıcı formu göndermeye
çalıştığında e-posta formatını (Regex ile), şifre uzunluğunu
ve zorunlu alanları denetleyen, kurallara uymayan durumlarda
gönderimi engelleyip hata mesajları basan bir güvenlik
bariyeridir.
Dosya Adı:
35-form-dogrulama.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Form Alanı Doğrulama Örneği</title><style>body {font-family: sans-serif;background-color: #f1f2f6;display: flex;justify-content: center;align-items: center;height:100vh;margin:0;}.form-card {background: white;padding:30px;border-radius:8px;box-shadow:04px15px rgba(0,0,0,0.05);width:350px;}.form-control { margin-bottom:15px; position: relative; }label { display: block; margin-bottom:5px; font-weight: bold; color: #2c3e50; }input {width:100%;padding:10px;border:2px solid #ddd;border-radius:4px;box-sizing: border-box;font-size:14px;}input:focus { border-color: #3498db; outline: none; }.error-msg {color: #e74c3c;font-size:12px;margin-top:4px;display: none;}button {width:100%;background-color: #3498db;color: white;border: none;padding:12px;border-radius:4px;font-size:16px;font-weight: bold;cursor: pointer;margin-top:10px;}button:hover { background-color: #2980b9; }</style></head><body><divclass="form-card"><h3style="margin-top:0; text-align:center; color:#2c3e50;">🔐 Güvenli Kayıt Formu</h3><formid="myForm"onsubmit="return validateForm(event)"><divclass="form-control"><labelfor="email">E-posta Adresi</label><inputtype="text"id="email"placeholder="ornek@domain.com"><divclass="error-msg"id="emailError">Geçerli bir e-posta adresi giriniz!</div></div><divclass="form-control"><labelfor="password">Şifre (En az6Karakter)</label><inputtype="password"id="password"placeholder="••••••"><divclass="error-msg"id="passwordError">Şifre en az6karakter olmalıdır!</div></div><buttontype="submit">Kayıt Ol</button></form></div><script>function validateForm(event) {event.preventDefault(); // Formun sayfayı yenileyerek gitmesini engelleconst email = document.getElementById('email').value.trim();const password = document.getElementById('password').value.trim();const emailError = document.getElementById('emailError');const passwordError = document.getElementById('passwordError');let isValid = true;// E-posta Regex Kontrolüconst emailPattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;if (!emailPattern.test(email)) {emailError.style.display ='block';document.getElementById('email').style.borderColor ='#e74c3c';isValid = false;} else {emailError.style.display ='none';document.getElementById('email').style.borderColor ='#ddd';}// Şifre Uzunluk Kontrolüif (password.length <6) {passwordError.style.display ='block';document.getElementById('password').style.borderColor ='#e74c3c';isValid = false;} else {passwordError.style.display ='none';document.getElementById('password').style.borderColor ='#ddd';}if (isValid) {alert("🎉 Başarılı! Form doğrulamadan geçti ve veriler gönderildi.");document.getElementById('myForm').reset();}return isValid;}</script></body></html>
Müfredat listemizdeki 36. ve 40. projeler arasındaki uygulamaların tüm HTML, CSS ve JavaScript kod bloklarını, tarayıcınızda doğrudan kopyalayıp çalıştırabileceğiniz şekilde tek bir dosya formatında hazırladım.
Yukarıdan aşağıya doğru
rastgele hızlarda düşen kırmızı elmayı, farenizle (veya yön
tuşlarıyla) kontrol ettiğiniz alttaki sepetle yakalamaya
çalıştığınız eğlenceli bir refleks oyunudur.
Dosya
Adı: 36-oge-yakalama.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Öğe Yakalama Oyunu</title><style>body {font-family: sans-serif;background-color: #2c3e50;color: white;margin:0;display: flex;flex-direction: column;align-items: center;justify-content: center;height:100vh;overflow: hidden;}.hud { font-size:20px; font-weight: bold; margin-bottom:10px; }.game-screen {width:400px;height:500px;background-color: #34495e;border:4px solid #fff;position: relative;border-radius:8px;cursor: none;}.item {width:30px;height:30px;background-color: #e74c3c;border-radius:50%;position: absolute;top: -30px;}.basket {width:80px;height:15px;background-color: #f1c40f;position: absolute;bottom:10px;border-radius:4px;}</style></head><body><divclass="hud">Skor: <spanid="scoreTxt">0</span> | Fareyi sağa sola hareket ettirerek elmayı yakala!</div><divclass="game-screen"id="gameScreen"><divclass="item"id="fallingItem"></div><divclass="basket"id="basket"></div></div><script>const screen = document.getElementById('gameScreen');const item = document.getElementById('fallingItem');const basket = document.getElementById('basket');const scoreTxt = document.getElementById('scoreTxt');let score =0;let itemY = -30;let itemX =185;let itemSpeed =4;let basketX =160;// Sepeti fare hareketine göre yatayda kaydırıyoruzscreen.addEventListener('mousemove', (e) => {const rect = screen.getBoundingClientRect();basketX = e.clientX - rect.left -40; // Sepeti ortala// Ekran sınırlarında kalmasını sağlaif (basketX <0) basketX =0;if (basketX >320) basketX =320;basket.style.left = basketX +'px';});function gameLoop() {// Objenin aşağı düşme hareketiitemY += itemSpeed;if (itemY >500) {// Sepet tarafından yakalanamadıysa yukarıdan tekrar düşsün (Skor artmaz)resetItem();}// Çarpışma Testi (Yakalama Kontrolü)if (itemY >=460&& itemY <=475) {if (itemX +30>= basketX && itemX <= basketX +80) {score++;scoreTxt.textContent = score;itemSpeed +=0.3; // Her yakalamada hızı biraz arttırresetItem();}}item.style.top = itemY +'px';item.style.left = itemX +'px';requestAnimationFrame(gameLoop);}function resetItem() {itemY = -30;itemX = Math.floor(Math.random() *370);}// İlk konumu ata ve döngüyü başlatresetItem();requestAnimationFrame(gameLoop);</script></body></html>
Ekran rengi aniden yeşile
döndüğünde en hızlı şekilde tıklamanız gereken ve milisaniye
(ms) cinsinden refleks hızınızı ölçen hassas bir test
aracıdır.
Dosya Adı:
37-reaksiyon-zamani.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Reaksiyon Zamanı Oyunu</title><style>body {font-family: sans-serif;margin:0;display: flex;justify-content: center;align-items: center;height:100vh;background-color: #2c3e50;color: white;user-select: none;}.test-box {width:100%;height:100%;display: flex;flex-direction: column;justify-content: center;align-items: center;cursor: pointer;text-align: center;padding:20px;box-sizing: border-box;}h1{ font-size:3rem; margin:0; }p { font-size:1.5rem; color: #ecf0f1; }</style></head><body><divclass="test-box"id="clickBox"><h1id="mainTitle">Tıklama Testi</h1><pid="subTitle">Başlamak için herhangi bir yere tıklayın.</p></div><script>const clickBox = document.getElementById('clickBox');const mainTitle = document.getElementById('mainTitle');const subTitle = document.getElementById('subTitle');let state ="idle"; // idle, waiting, ready, resultlet timeoutId;let startTime;clickBox.addEventListener('mousedown', () => {if (state ==="idle"|| state ==="result") {// Testi başlatıyoruz, bekleme durumuna geçiyorstate ="waiting";clickBox.style.backgroundColor ="#e74c3c"; // Kırmızı alanmainTitle.textContent ="Bekleyin...";subTitle.textContent ="Ekran YEŞİL olduğunda hemen tıklayın!";//2ile5saniye arasında rastgele bir sürede yeşil yanacakconst randomDelay = Math.floor(Math.random() *3000) +2000;timeoutId = setTimeout(() => {state ="ready";clickBox.style.backgroundColor ="#2ecc71"; // Yeşil alanmainTitle.textContent ="TIKLA!";subTitle.textContent ="Şimdi!";startTime = window.performance.now(); // Milisaniye cinsinden zamanı başlat}, randomDelay);} else if (state ==="waiting") {// Kullanıcı erken tıkladıysa (Hile koruması)clearTimeout(timeoutId);state ="result";clickBox.style.backgroundColor ="#c0392b";mainTitle.textContent ="Çok Erken!";subTitle.textContent ="Yeşil rengi görmeden tıklamamalısınız. Tekrar denemek için tıklayın.";} else if (state ==="ready") {// Başarılı başarılı tıklama hızı hesaplamaconst endTime = window.performance.now();const reactionTime = Math.floor(endTime - startTime);state ="result";clickBox.style.backgroundColor ="#34495e";mainTitle.textContent = `${reactionTime} ms`;subTitle.textContent ="Harika skor! Tekrar denemek için ekrana tıklayın.";}});</script></body></html>
Dizi (Array) biçimindeki satır ve
sütun verilerini tarayıcıda işleyerek evrensel bir Excel/CSV
dosyasına dönüştüren ve kullanıcının bilgisayarına dosya
olarak indiren (Blob
teknolojili) bir araçtır.
Dosya Adı:
38-csv-dosyasi-yapici.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>CSV Dosyası Yapıcı</title><style>body {font-family: system-ui, sans-serif;background-color: #f5f6fa;padding:40px;display: flex;justify-content: center;}.container {background: white;padding:30px;border-radius:8px;box-shadow:04px12px rgba(0,0,0,0.05);max-width:500px;width:100%;text-align: center;}table {width:100%;border-collapse: collapse;margin:20px0;}th, td {border:1px solid #ddd;padding:10px;text-align: left;}th { background-color: #2ecc71; color: white; }button {background-color: #27ae60;color: white;border: none;padding:12px24px;font-size:16px;font-weight: bold;border-radius:4px;cursor: pointer;transition:0.2s;}button:hover { background-color: #218c53; }</style></head><body><divclass="container"><h3style="margin-top: 0; color: #2c3e50;">📊 Verileri Excel/CSV Olarak Dışa Aktar</h3><pstyle="font-size: 14px; color: #7f8c8d;">Aşağıdaki sistem tablosu ham verilerini tek tıkla .csv dosyası yapın.</p><tableid="dataTable"><tr><th>Ürün Adı</th><th>Adet</th><th>Fiyat (TL)</th></tr><tr><td>Kablosuz Kulaklık</td><td>2</td><td>1250</td></tr><tr><td>Oyuncu Faresi</td><td>1</td><td>750</td></tr><tr><td>Mekanik Klavye</td><td>1</td><td>2200</td></tr></table><buttonid="downloadBtn">📥 CSV Olarak İndir</button></div><script>document.getElementById('downloadBtn').addEventListener('click', () => {// Tablodaki verileri JavaScript matris dizisi olarak topluyoruzconst rows = [["Urun Adi","Adet","Fiyat (TL)"],["Kablosuz Kulaklik","2","1250"],["Oyuncu Faresi","1","750"],["Mekanik Klavye","1","2200"]];// Diziyi CSV dize formatına (virgülle ayrılmış satırlara) dönüştürüyoruzlet csvContent ="data:text/csv;charset=utf-8,\uFEFF"; // Türkçe karakter uyumu için BOM ekledikrows.forEach(rowArray => {let row = rowArray.join(";"); // Excel'in Türkiye ayarlarında algılaması için noktalı virgül kullandıkcsvContent += row +"\r\n";});// Blob yapısı oluşturarak sanal bir indirme linki oluşturup tetikliyoruzconst encodedUri = encodeURI(csvContent);const link = document.createElement("a");link.setAttribute("href", encodedUri);link.setAttribute("download","sepet_raporu.csv");document.body.appendChild(link);link.click(); // Kullanıcıya hissettirmeden linki tıkla ve dosyayı indirdocument.body.removeChild(link); // Linki temizle});</script></body></html>
Boşluk (Space) tuşuna basarak
havada tutmaya çalıştığınız bir kuşun, karşıdan gelen
engellere (borulara) çarpmadan geçmesini sağlayan, gelişmiş
çarpışma algılama motoruna sahip bir DOM oyunudur.
Dosya
Adı: 39-flying-bird.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Flying Bird Oyunu</title><style>body {font-family: sans-serif;background: #2c3e50;margin:0;display: flex;flex-direction: column;align-items: center;justify-content: center;height:100vh;overflow: hidden;}.score { color: white; font-size:24px; font-weight: bold; margin-bottom:10px; }.game-box {width:400px;height:500px;background: #70a1ff;position: relative;overflow: hidden;border:4px solid white;border-radius:8px;}.bird {width:34px;height:24px;background: #ffa502;border-radius:50%;position: absolute;left:50px;top:200px;}.pipe {width:60px;background: #2ed573;position: absolute;left:400px;}.start-screen {position: absolute;width:100%;height:100%;background: rgba(0,0,0,0.7);color: white;display: flex;justify-content: center;align-items: center;font-size:20px;font-weight: bold;cursor: pointer;text-align: center;z-index:10;}</style></head><body><divclass="score">Skor: <spanid="scoreBox">0</span></div><divclass="game-box"id="gameBox"><divclass="start-screen"id="startScreen">Uçmak İçin Tıklayın<br><br>[BOŞLUK] veya Tıklama İle Yüksel</div><divclass="bird"id="bird"></div><divclass="pipe"id="pipeTop"style="top: 0; height: 150px;"></div><divclass="pipe"id="pipeBottom"style="bottom: 0; height: 180px;"></div></div><script>const bird = document.getElementById('bird');const pipeTop = document.getElementById('pipeTop');const pipeBottom = document.getElementById('pipeBottom');const startScreen = document.getElementById('startScreen');const scoreBox = document.getElementById('scoreBox');let birdY =200;let velocity =0;let gravity =0.4;let jump = -7;let pipeX =400;let score =0;let gameActive = false;startScreen.addEventListener('click', startGame);window.addEventListener('keydown', (e) => { if (e.key ===' '|| e.key ==='Spacebar') fly(); });window.addEventListener('mousedown', fly);function startGame() {startScreen.style.display ='none';gameActive = true;score =0;birdY =200;velocity =0;pipeX =400;scoreBox.textContent = score;generatePipes();requestAnimationFrame(updateGame);}function fly() {if (gameActive) velocity = jump;}function generatePipes() {// Boruların yüksekliğini rastgele ayarlıyoruz (Geçiş boşluğu sabit170px)const topHeight = Math.floor(Math.random() *200) +50;const bottomHeight =500- topHeight -170;pipeTop.style.height = topHeight +'px';pipeBottom.style.height = bottomHeight +'px';}function updateGame() {if (!gameActive) return;// Fizik motoru: Yerçekimi etkisivelocity += gravity;birdY += velocity;bird.style.top = birdY +'px';// Tavan veya zemine çarpma kontrolüif (birdY <0|| birdY >476) return gameOver();// Boruların sola doğru akma hareketipipeX -=3;if (pipeX < -60) {pipeX =400;generatePipes();score++;scoreBox.textContent = score;}pipeTop.style.left = pipeX +'px';pipeBottom.style.left = pipeX +'px';// Gelişmiş Çarpışma Testi (Collision)const tHeight = parseInt(pipeTop.style.height);if (pipeX <84&& pipeX > -10) { // Borunun X ekseninde hizalandığı anif (birdY < tHeight || birdY +24>500- parseInt(pipeBottom.style.height)) {return gameOver();}}requestAnimationFrame(updateGame);}function gameOver() {gameActive = false;startScreen.style.display ='flex';startScreen.innerHTML = `Oyun Bitti!<br>Skorunuz: ${score}<br>Tekrar uçmak için tıklayın`;}</script></body></html>
Bilgisayarın gizlice tuttuğu 1
ile 100 arasındaki rastgele sayıyı tahmin etmeye çalıştığınız,
"Daha büyük sayı gir" veya "Daha küçük sayı
gir" diyerek sizi yönlendiren hak sınırlamalı bir
oyundur.
Dosya Adı:
40-sayi-tahmin.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Sayı Tahmin Oyunu</title><style>body {font-family: sans-serif;background: #8e44ad;color: white;display: flex;justify-content: center;align-items: center;height:100vh;margin:0;}.game-card {background: white;color: #333;padding:30px;border-radius:12px;width:350px;text-align: center;box-shadow:08px24px rgba(0,0,0,0.3);}input {width:70%;padding:10px;font-size:18px;border:2px solid #ddd;border-radius:6px;margin-bottom:15px;text-align: center;}button {padding:10px25px;font-size:16px;background: #27ae60;color: white;border: none;border-radius:5px;font-weight: bold;cursor: pointer;}button:hover { background: #218c53; }.message { font-weight: bold; margin-top:15px; font-size:18px; color: #2c3e50; }.attempts { font-size:14px; color: #7f8c8d; margin-top:5px; }</style></head><body><divclass="game-card"><h2>🎯 Sayı Tahmin Oyunu</h2><p>1ile100arasında gizli bir sayı tuttum. Tahmin et!</p><inputtype="number"id="guessInput"min="1"max="100"placeholder="0"><br><buttonid="guessBtn">Tahmin Et</button><divclass="message"id="msgBox">Başarılar!</div><divclass="attempts"id="attemptBox">Kalan Hak:7</div></div><script>let targetNumber = Math.floor(Math.random() *100) +1;let remainingAttempts =7;const guessInput = document.getElementById('guessInput');const guessBtn = document.getElementById('guessBtn');const msgBox = document.getElementById('msgBox');const attemptBox = document.getElementById('attemptBox');guessBtn.addEventListener('click', () => {const userGuess = parseInt(guessInput.value);if (isNaN(userGuess) || userGuess <1|| userGuess >100) {msgBox.textContent ="Lütfen 1-100 arası bir sayı girin!";msgBox.style.color ="#e74c3c";return;}remainingAttempts--;attemptBox.textContent = `Kalan Hak: ${remainingAttempts}`;if (userGuess === targetNumber) {msgBox.textContent = `🎉 Tebrikler! Doğru Cevap: ${targetNumber}`;msgBox.style.color ="#2ecc71";endGame();} else if (remainingAttempts <=0) {msgBox.textContent = `❌ Haklarınız Bitti! Doğru sayı: ${targetNumber}`;msgBox.style.color ="#e74c3c";endGame();} else if (userGuess < targetNumber) {msgBox.textContent ="📈 Daha BÜYÜK bir sayı girin!";msgBox.style.color ="#e67e22";} else {msgBox.textContent ="📉 Daha KÜÇÜK bir sayı girin!";msgBox.style.color ="#3498db";}guessInput.value ="";guessInput.focus();});function endGame() {guessInput.disabled = true;guessBtn.disabled = true;guessBtn.textContent ="Oyun Bitti";guessBtn.style.background ="#bdc3c7";}</script></body></html>
Müfredat listemizin son aşaması olan 41. ve 45. projeler arasındaki final uygulamalarının tüm HTML, CSS ve JavaScript kod bloklarını, tarayıcınızda doğrudan kopyalayıp çalıştırabileceğiniz şekilde hazırladım.
Not: API bağlantılı projelerde harici anahtar (Key) bağımlılığını ortadan kaldırmak ve kodun yerel bilgisayarınızda anında çift tıklamayla çalışabilmesini sağlamak amacıyla sistem simülasyon algoritmaları entegre edilmiştir.
Aşağıdaki geminizi yön
tuşlarıyla hareket ettirip boşluk (Space) tuşuyla ateş ederek
yukarıdaki uzaylı ordusunu temizlemeye çalıştığınız atari
tarzı bir oyundur.
Dosya Adı:
41-uzay-istilacilari.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Uzay İstilacıları Oyunu</title><style>body {font-family: sans-serif;background-color: #050510;color: white;margin:0;display: flex;flex-direction: column;align-items: center;justify-content: center;height:100vh;overflow: hidden;}.hud { font-size:20px; font-weight: bold; margin-bottom:10px; color: #00d2d3; }.space-arena {width:480px;height:400px;background-color: #0c1020;border:3px solid #54a0ff;position: relative;border-radius:6px;box-shadow:0020px rgba(84,160,255,0.3);}.ship {width:40px;height:20px;background-color: #54a0ff;position: absolute;bottom:15px;border-radius:4px4px00;}.alien {width:30px;height:20px;background-color: #ff6b6b;position: absolute;border-radius:3px;}.laser {width:4px;height:15px;background-color: #f1c40f;position: absolute;}</style></head><body><divclass="hud">Skor: <spanid="scoreTxt">0</span> | Sağ/Sol Yön Tuşları: Hareket | Boşluk: Ateş</div><divclass="space-arena"id="arena"><divclass="ship"id="ship"style="left: 220px;"></div></div><script>const arena = document.getElementById('arena');const ship = document.getElementById('ship');const scoreTxt = document.getElementById('scoreTxt');let shipX =220;let score =0;let keys = {};let aliens = [];let lasers = [];let alienDirection =1;let gameActive = true;window.addEventListener('keydown', (e) => keys[e.key] = true);window.addEventListener('keyup', (e) => keys[e.key] = false);//3satır halinde uzaylı ordusunu haritaya yerleştiriyoruzfunction createAliens() {for (let row =0; row <3; row++) {for (let col =0; col <8; col++) {const alien = document.createElement('div');alien.className ='alien';let x = col *45+30;let y = row *35+30;alien.style.left = x +'px';alien.style.top = y +'px';arena.appendChild(alien);aliens.push({ element: alien, x: x, y: y });}}}function fireLaser() {const laser = document.createElement('div');laser.className ='laser';let lx = shipX +18;let ly =365;laser.style.left = lx +'px';laser.style.top = ly +'px';arena.appendChild(laser);lasers.push({ element: laser, x: lx, y: ly });}window.addEventListener('keydown', (e) => {if (e.key ===' '&& gameActive) fireLaser();});function gameLoop() {if (!gameActive) return;// Gemi Hareketi Kontrolüif (keys['ArrowLeft'] && shipX >10) shipX -=4;if (keys['ArrowRight'] && shipX <430) shipX +=4;ship.style.left = shipX +'px';// Lazerlerin Yukarı Doğru İlerlemesifor (let i = lasers.length -1; i >=0; i--) {lasers[i].y -=6;lasers[i].element.style.top = lasers[i].y +'px';// Ekrandan çıkan mermileri temizleif (lasers[i].y <0) {lasers[i].element.remove();lasers.splice(i,1);continue;}// Mermilerin Uzaylılara Çarpma Testifor (let j = aliens.length -1; j >=0; j--) {if (lasers[i] &&lasers[i].x >= aliens[j].x && lasers[i].x <= aliens[j].x +30&&lasers[i].y >= aliens[j].y && lasers[i].y <= aliens[j].y +20) {// Vurulma Gerçekleştialiens[j].element.remove();lasers[i].element.remove();aliens.splice(j,1);lasers.splice(i,1);score +=10;scoreTxt.textContent = score;break;}}}// Uzaylıların Sağa Sola ve Aşağı Doğru Hareketilet edgeReached = false;aliens.forEach(alien => {alien.x += alienDirection *0.5;alien.element.style.left = alien.x +'px';if (alien.x >440|| alien.x <10) edgeReached = true;// Uzaylılar tabana ulaştıysa oyun biterif (alien.y >340) {gameActive = false;alert("İstila Başarılı Oldu! Oyun Bitti. Skor: "+ score);}});if (edgeReached) {alienDirection = -alienDirection;aliens.forEach(alien => {alien.y +=15;alien.element.style.top = alien.y +'px';});}if (aliens.length ===0) {gameActive = false;alert("Tebrikler! Dünyayı kurtardınız! Toplam Skor: "+ score);}if (gameActive) requestAnimationFrame(gameLoop);}createAliens();requestAnimationFrame(gameLoop);</script></body></html>
Deste karıştırılıp oyuncu ve
bilgisayara dağıtılır. Butona basıldığında en üstteki
kartlar çekilir ve değeri büyük olan kartı atan elin puanını
toplar.
Dosya Adı:
42-kart-savasi.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Kart Savaşı Oyunu</title><style>body {font-family: sans-serif;background-color: #27ae60;color: white;text-align: center;padding-top:30px;margin:0;}.arena {display: flex;justify-content: center;gap:50px;margin:30px0;}.card-slot {background-color: #1e7e34;width:130px;height:190px;border:3px dashed white;border-radius:10px;display: flex;flex-direction: column;justify-content: center;align-items: center;font-size:32px;font-weight: bold;color: black;box-shadow:06px12px rgba(0,0,0,0.2);}.active-card { background-color: white !important; border-style: solid !important; }button {padding:12px35px;font-size:18px;font-weight: bold;color: #27ae60;background-color: white;border: none;border-radius:25px;cursor: pointer;box-shadow:04px10px rgba(0,0,0,0.2);}button:hover { background-color: #f0f0f0; }.score-board { font-size:22px; margin-bottom:20px; font-weight: bold; }</style></head><body><h1>⚔️ Kart Savaşı (Büyük Alan Kazanır)</h1><divclass="score-board">Siz: <spanid="pScore">0</span> | Bilgisayar: <spanid="cScore">0</span></div><divclass="arena"><div><h3>Senin Kartın</h3><divclass="card-slot"id="playerSlot">?</div></div><div><h3>Bilgisayar</h3><divclass="card-slot"id="compSlot">?</div></div></div><buttonid="drawBtn">Savaş (Kart Çek)</button><h2id="roundResult"style="margin-top: 25px; min-height: 35px;"></h2><script>let playerCard, compCard;let playerScore =0, compScore =0;const playerSlot = document.getElementById('playerSlot');const compSlot = document.getElementById('compSlot');const roundResult = document.getElementById('roundResult');// İskambil kart sembolleri ve sayısal değer eşleşmelericonst cardTypes = ['♠','♥','♦','♣'];const cardValues = [{ n:'2', v:2}, { n:'3', v:3}, { n:'4', v:4}, { n:'5', v:5},{ n:'6', v:6}, { n:'7', v:7}, { n:'8', v:8}, { n:'9', v:9},{ n:'10', v:10}, { n:'J', v:11}, { n:'Q', v:12}, { n:'K', v:13}, { n:'A', v:14}];document.getElementById('drawBtn').addEventListener('click', () => {// Rastgele iki kart türetiliyorconst pType = cardTypes[Math.floor(Math.random() * cardTypes.length)];const pVal = cardValues[Math.floor(Math.random() * cardValues.length)];const cType = cardTypes[Math.floor(Math.random() * cardTypes.length)];const cVal = cardValues[Math.floor(Math.random() * cardValues.length)];// Arayüz kart görünümlerinin güncellenmesiplayerSlot.className ="card-slot active-card";playerSlot.innerHTML = `<spanstyle="font-size:14px; align-self:flex-start; padding-left:10px;">${pType}</span>${pVal.n}`;playerSlot.style.color = (pType ==='♥'|| pType ==='♦') ?'red':'black';compSlot.className ="card-slot active-card";compSlot.innerHTML = `<spanstyle="font-size:14px; align-self:flex-start; padding-left:10px;">${cType}</span>${cVal.n}`;compSlot.style.color = (cType ==='♥'|| cType ==='♦') ?'red':'black';// Kazanma Mantık Algoritmasıif (pVal.v > cVal.v) {playerScore++;roundResult.textContent ="⚔️ Bu eli SİZ kazandınız!";roundResult.style.color ="#f1c40f";} else if (cVal.v > pVal.v) {compScore++;roundResult.textContent ="❌ Bu eli BİLGİSAYAR kazandı!";roundResult.style.color ="#e74c3c";} else {roundResult.textContent ="🤝 Beraberlik! Puan verilmedi.";roundResult.style.color ="white";}document.getElementById('pScore').textContent = playerScore;document.getElementById('cScore').textContent = compScore;});</script></body></html>
Arama kutusuna yazılan kelimeye
göre arka planda veri transferi gerçekleştiren ve gelen sonuçları
video listesi mimarisine uygun şekilde dinamik ekrana basan asenkron
veri projesidir.
Dosya Adı:
43-youtube-api-arama.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>YouTube API Video Arama</title><style>body {font-family: system-ui, sans-serif;background-color: #f9f9f9;margin:0;padding:20px;}.search-container {max-width:600px;margin:20px auto;display: flex;gap:10px;}input {flex-grow:1;padding:12px;border:1px solid #ccc;border-radius:20px;font-size:16px;}button {padding:12px24px;background-color: #cc0000;color: white;border: none;border-radius:20px;font-weight: bold;cursor: pointer;}.video-list {max-width:800px;margin:30px auto;display: flex;flex-direction: column;gap:15px;}.video-item {display: flex;background: white;padding:15px;border-radius:8px;box-shadow:02px8px rgba(0,0,0,0.05);gap:15px;}.thumb {width:160px;height:90px;background-color: #ddd;border-radius:4px;display: flex;justify-content: center;align-items: center;font-weight: bold;color: #666;font-size:12px;}.video-info h3{ margin:008px0; color: #333; font-size:18px; }.video-info p { margin:0; color: #606060; font-size:14px; }</style></head><body><divclass="search-container"><inputtype="text"id="query"placeholder="YouTube'da arayın..."><buttonid="searchBtn">Ara</button></div><divclass="video-list"id="videoList"><pstyle="text-align: center; color: #777;">Arama yapmak için yukarıdaki kutuyu kullanın.</p></div><script>// Yerel sunucu bağımsız simüle edilmiş asenkron veri havuzuconst mockDatabase = {"javascript": [{ title:"Sıfırdan İleri Düzey JavaScript Eğitimi 2026", channel:"Yazılım Akademisi", Ara:"120 B"},{ title:"JavaScript DOM Manipülasyonu Rehberi", channel:"Kod Dünyası", Ara:"45 B"}],"oyun": [{ title:"JavaScript ile 2D Tarayıcı Oyunu Yapımı", channel:"GameDev TR", Ara:"88 B"},{ title:"Efsanevi Atarı Oyunları Kod İncelemesi", channel:"Retro Oyun", Ara:"15 B"}]};document.getElementById('searchBtn').addEventListener('click', runSearch);document.getElementById('query').addEventListener('keypress', (e) => { if(e.key ==='Enter') runSearch(); });function runSearch() {const query = document.getElementById('query').value.trim().toLowerCase();const listContainer = document.getElementById('videoList');listContainer.innerHTML ="<p style='text-align:center;'>Veriler çekiliyor...</p>";// Fetch API simülasyon gecikmesi ekliyoruz (Asenkron yapı simülasyonu)setTimeout(() => {listContainer.innerHTML ="";// Anahtar kelime eşleşmesi denetimiconst results = mockDatabase[query] || [{ title: `"${query}"hakkında harika içerik videosu`, channel:"Genel Kanal", Ara:"5 B"},{ title: `${query} temelli kodlama dersleri parçası`, channel:"Geliştirici Günlüğü", Ara:"2 B"}];results.forEach(video => {const item = document.createElement('div');item.className ='video-item';item.innerHTML = `<divclass="thumb">📺 VIDEO THUMB</div><divclass="video-info"><h3>${video.title}</h3><p>Kanal: ${video.channel}</p><pstyle="font-size:12px; color:#909090;">İzlenme: ${video.Ara}</p></div>`;listContainer.appendChild(item);});},600);}</script></body></html>
Alttaki tahtayı farenizle sağa
sola oynatarak zıplayan topun düşmesini engellediğiniz ve top
yardımıyla yukarıdaki tuğla bloklarını çarparak kırdığınız
tam gelişmiş bir mekanik oyun projesidir.
Dosya Adı:
44-tugla-kirma.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Tuğla Kırma Oyunu</title><style>body {font-family: sans-serif;background-color: #2c3e50;margin:0;display: flex;flex-direction: column;align-items: center;justify-content: center;height:100vh;}canvas {background-color: #34495e;border:4px solid white;border-radius:6px;box-shadow:010px20px rgba(0,0,0,0.3);cursor: none;}.score { color: white; font-size:24px; font-weight: bold; margin-bottom:10px; }</style></head><body><divclass="score">Skor: <spanid="scoreTxt">0</span></div><canvasid="gameCanvas"width="480"height="320"></canvas><script>const canvas = document.getElementById("gameCanvas");const ctx = canvas.getContext("2d");const scoreTxt = document.getElementById("scoreTxt");let score =0;// Top Parametrelerilet x = canvas.width /2;let y = canvas.height -30;let dx =2;let dy = -2;const ballRadius =8;// Palet (Raket) Parametrelericonst paddleHeight =10;const paddleWidth =75;let paddleX = (canvas.width - paddleWidth) /2;// Tuğla Matris Düzeni Parametrelericonst brickRowCount =3;const brickColumnCount =5;const brickWidth =75;const brickHeight =20;const brickPadding =10;const brickOffsetTop =30;const brickOffsetLeft =30;// Tuğla dizilim hafızasını oluşturmalet bricks = [];for (let c =0; c < brickColumnCount; c++) {bricks[c] = [];for (let r =0; r < brickRowCount; r++) {bricks[c][r] = { x:0, y:0, status:1};}}// Fare takibi ile raketi hareket ettirmedocument.addEventListener("mousemove", (e) => {const relativeX = e.clientX - canvas.offsetLeft;if (relativeX >0&& relativeX < canvas.width) {paddleX = relativeX - paddleWidth /2;}});// Çarpışma Algılama Motoru (Top tuğlaya çarptı mı?)function collisionDetection() {for (let c =0; c < brickColumnCount; c++) {for (let r =0; r < brickRowCount; r++) {let b = bricks[c][r];if (b.status ===1) {if (x > b.x && x < b.x + brickWidth && y > b.y && y < b.y + brickHeight) {dy = -dy; // Topun yönünü kırb.status =0; // Tuğlayı yok etscore++;scoreTxt.textContent = score;if (score === brickRowCount * brickColumnCount) {alert("TEBRİKLER, KAZANDINIZ!");document.location.reload();}}}}}}function drawBall() {ctx.beginPath();ctx.arc(x, y, ballRadius,0, Math.PI *2);ctx.fillStyle ="#0095DD";ctx.fill();ctx.closePath();}function drawPaddle() {ctx.beginPath();ctx.rect(paddleX, canvas.height - paddleHeight, paddleWidth, paddleHeight);ctx.fillStyle ="#0095DD";ctx.fill();ctx.closePath();}function drawBricks() {for (let c =0; c < brickColumnCount; c++) {for (let r =0; r < brickRowCount; r++) {if (bricks[c][r].status ===1) {let brickX = (c * (brickWidth + brickPadding)) + brickOffsetLeft;let brickY = (r * (brickHeight + brickPadding)) + brickOffsetTop;bricks[c][r].x = brickX;bricks[c][r].y = brickY;ctx.beginPath();ctx.rect(brickX, brickY, brickWidth, brickHeight);ctx.fillStyle ="#e74c3c";ctx.fill();ctx.closePath();}}}}function draw() {ctx.clearRect(0,0, canvas.width, canvas.height); // Ekranı temizledrawBricks();drawBall();drawPaddle();collisionDetection();// Duvarlardan Sekme Fiziği (Sağ ve Sol Duvar)if (x + dx > canvas.width - ballRadius || x + dx < ballRadius) {dx = -dx;}// Üst Duvar Sekme Fiziğiif (y + dy < ballRadius) {dy = -dy;} else if (y + dy > canvas.height - ballRadius) {// Alt sınıra indiğinde rakete çarptı mı kontrolüif (x > paddleX && x < paddleX + paddleWidth) {dy = -dy;} else {alert("OYUN BİTTİ!");document.location.reload();return;}}x += dx;y += dy;requestAnimationFrame(draw);}requestAnimationFrame(draw);</script></body></html>
Ekranda yer alan gizli kapalı
kutulardan seçim yaparak büyük ödülleri elemeye çalıştığınız,
turlar arasında gelen banka tekliflerini kabul edip ya da şansınızı
son kutuya kadar sürdürdüğünüz televizyon yarışması
uyarlamasıdır.
Dosya Adı:
45-var-misin-yok-musun.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Var mısın Yok musun?</title><style>body {font-family: sans-serif;background-color: #2c3e50;color: white;text-align: center;padding:20px;margin:0;}.board {display: grid;grid-template-columns: repeat(5,1fr);gap:12px;max-width:600px;margin:20px auto;}.box {background-color: #f1c40f;color: #2c3e50;padding:20px;font-size:20px;font-weight: bold;border-radius:6px;cursor: pointer;box-shadow:04px8px rgba(0,0,0,0.2);transition: all0.2s;}.box:hover { transform: scale(1.05); background-color: #f39c12; }.opened { background-color: #bdc3c7!important; color: #7f8c8d; cursor: not-allowed; }.my-box-panel {background-color: #e67e22;padding:15px;border-radius:8px;display: inline-block;margin-top:10px;font-size:18px;font-weight: bold;}.bank-modal {position: fixed;top:50%;left:50%;transform: translate(-50%, -50%);background: white;color: black;padding:30px;border-radius:10px;box-shadow:010px30px rgba(0,0,0,0.5);display: none;z-index:100;}.bank-modal button {padding:10px20px;margin:10px;font-size:16px;font-weight: bold;cursor: pointer;border: none;border-radius:4px;}</style></head><body><h1>💰 Var mısın Yok musun?</h1><divid="statusTxt">Önce kendi adınıza saklayacağınız kutuyu seçin!</div><divclass="my-box-panel"id="myBoxDisplay"style="display: none;">Sizin Kutunuz: <spanid="myBoxNum">-</span></div><divclass="board"id="boxBoard"></div><!-- Banka Teklifi Penceresi --><divclass="bank-modal"id="bankModal"><h3id="bankOfferTxt">Hamdi Bey'in Teklifi:0TL</h3><buttonstyle="background-color: #2ecc71; color: white;"id="dealBtn">Varım (Kabul Et)</button><buttonstyle="background-color: #e74c3c; color: white;"id="noDealBtn">Yokum (Devam)</button></div><script>// Yarışmadaki para ağacı havuzu (10Farklı Ödül)const prizePool =;let shuffledPrizes = [...prizePool].sort(() => Math.random() -0.5);let ownBoxIndex = null;let openedBoxesCount =0;let gameActive = true;const board = document.getElementById('boxBoard');const statusTxt = document.getElementById('statusTxt');const myBoxDisplay = document.getElementById('myBoxDisplay');const myBoxNum = document.getElementById('myBoxNum');const bankModal = document.getElementById('bankModal');//10Adet Kutuyu Ekrana Basmafor (let i =0; i <10; i++) {const box = document.createElement('div');box.className ='box';box.textContent = i +1;box.dataset.index = i;box.addEventListener('click', () => handleBoxClick(box, i));board.appendChild(box);}function handleBoxClick(boxElement, index) {if (!gameActive || boxElement.classList.contains('opened')) return;if (ownBoxIndex === null) {// İlk tıklamada kendi kutusunu ayırırownBoxIndex = index;boxElement.classList.add('opened');myBoxNum.textContent = index +1;myBoxDisplay.style.display ='inline-block';statusTxt.textContent ="Kutunuz ayrıldı. Şimdi ödülleri elemek için diğer kutuları açın!";} else {// Diğer kutuları açarak ödülleri ortaya çıkarırboxElement.classList.add('opened');boxElement.textContent = shuffledPrizes[index] +" TL";boxElement.style.backgroundColor ="#e74c3c";boxElement.style.color ="white";openedBoxesCount++;// Her3kutu açıldığında bir banka teklifi tetiklenirif (openedBoxesCount ===3|| openedBoxesCount ===6) {triggerBankOffer();}// Son kutu kaldığında oyun doğal olarak sonuçlanırif (openedBoxesCount ===8) {statusTxt.textContent = `Oyun bitti! Kendi kutunuzu açtınız ve kazandınız: ${shuffledPrizes[ownBoxIndex]} TL!`;gameActive = false;}}}function triggerBankOffer() {// Kalan ödüllerin matematiksel ortalamasını alıp teklif üretiyoruzlet sum =0;let activeCount =0;shuffledPrizes.forEach((prize, idx) => {const boxElements = document.querySelectorAll('.box');// Açılmamış veya oyuncunun kendi kutusu olan aktif ödülleri toplaif (idx === ownBoxIndex || !boxElements[idx].classList.contains('opened') || boxElements[idx].textContent === String(idx+1)) {sum += prize;activeCount++;}});const offer = Math.floor((sum / activeCount) *0.75); // Ortalama bedelin %75'i teklif edilirdocument.getElementById('bankOfferTxt').textContent = `Hamdi Bey'in Teklifi: ${offer} TL`;bankModal.style.display ='block';}document.getElementById('dealBtn').addEventListener('click', () => {bankModal.style.display ='none';statusTxt.textContent = `Yarışmadan başarıyla çekildiniz! Kazandığınız Ödül: ${document.getElementById('bankOfferTxt').textContent.split(': ')[1]}`;gameActive = false;});document.getElementById('noDealBtn').addEventListener('click', () => {bankModal.style.display ='none';statusTxt.textContent ="Yokum dediniz! Kutuları elemeye devam edin.";});</script></body></html>
Müfredatımızın en kıymetli, iş görüşmelerinde (mülakatlarda) en çok sorulan ve kıdemli (Senior) yazılımcı seviyesine geçişin anahtarı olan İleri Düzey Teknik Dersler aşamasına geldik.
Bu kısımdaki kod mimarilerini sadece ezbere yazmak yerine; ne işe yaradıklarını, tarayıcının arka planında neyi çözdüklerini, günlük hayat analojilerini ve doğrudan tarayıcıda çalıştırabileceğiniz tam kod yapılarını ele alacağız.
Debounce, peş peşe tetiklenen olayların (events) işlem maliyetini azaltmak için kullanılır. Kullanıcı klavyeden her harfe bastığında internetten bir arama yapmaya kalkarsak (örneğin "javascript" yazarken 10 kez istek atılır), sunucumuz gereksiz yere yorulur ve tarayıcı kasılır.
Görevi: Kullanıcı eylemi (yazmayı, tıklamayı) tamamen bitirene kadar bekler. Belirlenen süre boyunca yeni bir tetikleme gelmezse asıl fonksiyonu çalıştırır.
Bir asansör düşünün. Asansörün kapısı tam kapanacakken yeni bir yolcu gelip düğmeye basarsa asansör kapıyı açar ve süreyi sıfırdan tekrar başlatır. Asansör, ancak belirli bir süre (örneğin 5 saniye) boyunca hiç kimse gelmediğinde hareket eder. İşte bu Debounce mantığıdır.
Dosya Adı:
advanced-debounce.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>İleri Düzey JavaScript - Debounce</title><style>body {font-family:'Segoe UI', sans-serif;background-color: #f5f6fa;padding:40px;display: flex;flex-direction: column;align-items: center;}.card {background: white;padding:30px;border-radius:12px;box-shadow:05px15px rgba(0,0,0,0.05);max-width:500px;width:100%;text-align: center;}input {width:100%;padding:12px;font-size:16px;border:2px solid #ced4da;border-radius:6px;box-sizing: border-box;margin-bottom:20px;}.log-box {display: flex;justify-content: space-between;background: #f1f2f6;padding:15px;border-radius:6px;font-weight: bold;margin-top:10px;}.normal { color: #e74c3c; }.debounced { color: #2ecc71; }</style></head><body><divclass="card"><h2>🔍 Debounce (Arama Optimizasyonu)</h2><p>Aşağıdaki kutuya hızlıca bir şeyler yazın ve aşağıdaki sayaçların farkını izleyin:</p><inputtype="text"id="searchInput"placeholder="Bir şeyler yazmaya başlayın..."><divclass="log-box"><div>Normal Tetiklenme Sayısı: <spanid="normalCount"class="normal">0</span></div></div><divclass="log-box"><div>Debounce Tetiklenme (API İsteği): <spanid="debounceCount"class="debounced">0</span></div></div></div><script>let nCounter =0;let dCounter =0;const searchInput = document.getElementById('searchInput');const normalCount = document.getElementById('normalCount');const debounceCount = document.getElementById('debounceCount');// MÜLAKATLARIN GÖZDESİ: Saf Debounce Fonksiyon Mimarisifunction debounce(asılFonksiyon, beklemeSüresi) {let zamanlayiciId; // Kapsam (closure) sayesinde hafızada tutulurreturn function(...argümanlar) {// Eğer yeni bir tetikleme geldiyse, bir önceki zamanlayıcıyı iptal et (Süreyi sıfırla)clearTimeout(zamanlayiciId);// Süreyi baştan başlatzamanlayiciId = setTimeout(() => {asılFonksiyon.apply(this, argümanlar);}, beklemeSüresi);};}// Tetiklenecek asıl fonksiyon (Simüle edilen API İsteği)function apiIsteğiAt(mesaj) {dCounter++;debounceCount.textContent = dCounter;console.log("API İsteği Gönderildi: "+ mesaj);}// Debounce edilmiş versiyonu oluşturuyoruz (500milisaniye beklesin)const optimizeEdilmisArama = debounce(apiIsteğiAt,500);// Input dinleyicisisearchInput.addEventListener('input', (e) => {//1. Normal Durum: Her harfte tetiklenirnCounter++;normalCount.textContent = nCounter;//2. Debounce Durumu: Sadece yazma durunca tetikleniroptimizeEdilmisArama(e.target.value);});</script></body></html>
Throttle, bir fonksiyonun peş peşe
ne kadar çok tetiklendiğine bakmaksızın, belirli zaman
aralıklarında en fazla bir kez
çalışmasını zorunlu kılar. Özellikle tarayıcı penceresinin
boyutunu değiştirirken (resize)
veya sayfayı aşağı kaydırırken (scroll)
tarayıcı saniyede yüzlerce kez olayı ateşler. Bu durum
performans krizine yol açar.
Görevi: Akışı bir musluk gibi kısar. "İstediğin kadar hızlı kaydır, ben bu kodu sadece 300 milisaniyede bir çalıştıracağım" der.
Bir lunaparktaki dönme dolabı düşünün. Dönme dolaba binmek isteyen yüzlerce çocuk sırada bekleyebilir ve sürekli kapıya vurabilir. Ancak görevli kapıyı her saniye açmaz. Sırada ne kadar insan olursa olsun, kapıyı sabit olarak 5 dakikada bir açar, bir grubu alır ve kapatır.
Dosya Adı:
advanced-throttle.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>İleri Düzey JavaScript - Throttle</title><style>body {font-family: sans-serif;margin:0;height:3000px; /* Kaydırma çubuğu oluşması için uzun gövde */background: linear-gradient(to bottom, #74b9ff, #0984e3);}.dashboard {position: fixed;top:20px;left:50%;transform: translateX(-50%);background: white;padding:20px;border-radius:8px;box-shadow:04px15px rgba(0,0,0,0.2);text-align: center;width:350px;}.counter { font-size:24px; font-weight: bold; margin:10px0; }</style></head><body><divclass="dashboard"><h3>📜 Sayfayı Aşağı Doğru Kaydırın</h3><p>Scroll olayının performans yönetim farkı:</p><divclass="counter"style="color: #d63031;">Normal: <spanid="normalScroll">0</span></div><divclass="counter"style="color: #00b894;">Throttle: <spanid="throttleScroll">0</span></div></div><script>let normalCount =0;let throttleCount =0;// SAF THROTTLE FONKSİYON MİMARİSİfunction throttle(asılFonksiyon, limitSüresi) {let beklemede Mi = false;return function(...argümanlar) {// Eğer kilit aktifse (beklemedeysek) fonksiyonu çalıştırma, pas geçif (beklemedeMi) return;// Asıl fonksiyonu çalıştırasılFonksiyon.apply(this, argümanlar);// Kilidi devreye sokbeklemedeMi = true;// Belirlenen süre dolduğunda kilidi kaldırsetTimeout(() => {beklemedeMi = false;}, limitSüresi);};}function scrollİşlemiYap() {throttleCount++;document.getElementById('throttleScroll').textContent = throttleCount;}//400milisaniyelik bir gaz kesici/kilit mekanizması oluşturuyoruzconst optimizeEdilmisScroll = throttle(scrollİşlemiYap,400);// Kaydırma olayını dinlemewindow.addEventListener('scroll', () => {// Normal durum kontrolünormalCount++;document.getElementById('normalScroll').textContent = normalCount;// Performans ayarlı durum kontrolüoptimizeEdilmisScroll();});</script></body></html>
JavaScript'teki yerleşik Promise
objesi asenkron (zaman alan, gelecekte bitecek) işlemlerin durumunu
yönetir. İşlem başarılı bittiğinde .then(),
başarısız bittiğinde .catch()
blokları zincirleme tetiklenir. Arka plandaki bu yapıyı kendi
mimarimizle taklit ederek asenkron motorun kalbini anlarız.
Bir restoranda sipariş
verdiğinizde size verilen sesli/ışıklı sıramatik cihazı bir
Promise'dir. Cihaz ilk başta beklemektedir (Pending).
Yemek hazırlandığında cihaz titrer ve ışığı yanar
(Fulfilled/Resolved).
Eğer mutfakta malzeme bittiyse ve yemek iptal edildiyse cihaz
kırmızı alarm verir (Rejected).
Dosya Adı:
advanced-custom-promise.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>İleri Düzey JavaScript - Custom Promise</title><style>body {font-family: system-ui, sans-serif;background-color: #2f3542;color: white;display: flex;justify-content: center;align-items: center;height:100vh;margin:0;}.box {background: #1e222b;padding:35px;border-radius:10px;box-shadow:010px25px rgba(0,0,0,0.5);text-align: center;max-width:400px;}.status {font-size:20px;font-weight: bold;color: #ff9f43;margin-top:15px;}</style></head><body><divclass="box"><h2>🛠️ Sıfırdan Yazılmış Custom Promise Motoru</h2><p>Arka planda asenkron bir veri çekme işlemi simüle ediliyor...</p><divclass="status"id="statusBox">Durum: Bekleniyor (Pending)...</div></div><script>const statusBox = document.getElementById('statusBox');// SIFIRDAN KENDİ PROMISE SINIFIMIZI İNŞA EDİYORUZclass KendiPromisim {constructor(görevFonksiyonu) {this.durum ="PENDING"; // Başlangıç durumuthis.değer = null;this.basariliTakipci = null; // .then() bloğu// Başarılı tamamlama işleyicisiconst resolve = (sonuc) => {if (this.durum !=="PENDING") return;this.durum ="FULFILLED";this.değer = sonuc;// Eğer önceden kaydedilmiş bir .then fonksiyonu varsa çalıştırif (this.basariliTakipci) {this.basariliTakipci(this.değer);}};// Görevi hemen çalıştır ve içeriye kendi yazdığımız resolve motorunu paslatry {görevFonksiyonu(resolve);} catch (hata) {console.error(hata);}}// Dinleyici bağlama mekanizmasıthen(fonksiyon) {this.basariliTakipci = fonksiyon;// Eğer işlem asenkron değil de anında bittiyse direkt tetikleif (this.durum ==="FULFILLED") {this.basariliTakipci(this.değer);}return this; // Zincirleme kullanım alt yapısı sunmak için kendini dön}}// KULLANIM / TEST ETME AŞAMASIstatusBox.textContent ="Durum: İstek Sunucuya Gitti (Pending)...";const veriGelecek = new KendiPromisim((resolve) => {//2saniyelik asenkron bir gecikme yaratıyoruzsetTimeout(() => {resolve("Kullanıcı Bilgileri Başarıyla Çekildi! (ID: 440)");},2500);});// Yazdığımız özel Promise'i .then ile dinliyoruzveriGelecek.then((gelenVeri) => {statusBox.textContent ="Durum: Başarılı (Fulfilled)!";statusBox.style.color ="#2ed573";// Ekrana gelen veriyi basalımconst p = document.createElement('p');p.textContent = `Gelen Veri: ${gelenVeri}`;p.style.color ="#ced6e0";document.querySelector('.box').appendChild(p);});</script></body></html>
JavaScript'in mülakatlarda (iş görüşmelerinde) adayları en çok eleyen iki efsanevi konusu olan Closures (Kapsam Kapatmaları) ve Prototypes (Miras Alma Yapısı) aşamasına geldik.
Tıpkı önceki konularda yaptığımız gibi; bu iki konunun tarayıcı hafızasında neyi çözdüğünü, günlük hayat benzetmelerini ve tarayıcınızda doğrudan çalıştırabileceğiniz tam kod yapılarını en ince ayrıntısına kadar inceliyoruz.
JavaScript'te bir fonksiyon, kendi içinde tanımlandığı dış fonksiyonun kapsamındaki (scope) değişkenleri, o dış fonksiyonun çalışması tamamen bitmiş olsa bile hatırlar ve onlara erişebilir. Buna Closure denir.
Görevi: Global (ortak)
alanda değişken kirliliği yaratmadan, nesne yönelimli dillerdeki
private
(gizli/kapsüllenmiş) değişken mantığını taklit etmemizi
sağlar. Dışarıdaki hiçbir kod, bu gizli değişkene doğrudan
dokunamaz; sadece bizim izin verdiğimiz fonksiyonlar aracılığıyla
değiştirebilir.
Bir banka veznesi düşünün.
Bankanın kasasındaki toplam para miktarı dışarıdan geçen
herhangi bir insan tarafından doğrudan görülemez veya
değiştirilemez (private
variable).
Ancak veznedar (iç
fonksiyon),
kasa odasının içindedir ve kasaya erişim yetkisi vardır. Siz
para yatırmak veya çekmek istediğinizde veznedara söylersiniz,
veznedar kasayı günceller. İşte o veznedar, kasanın etrafını
kapatan bir Closure'dır.
Dosya Adı:
advanced-closures.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>İleri Düzey JavaScript - Closures</title><style>body {font-family:'Segoe UI', sans-serif;background-color: #f1f2f6;display: flex;justify-content: center;align-items: center;height:100vh;margin:0;}.card {background: white;padding:30px;border-radius:12px;box-shadow:08px20px rgba(0,0,0,0.05);max-width:400px;width:100%;text-align: center;}.balance-box {font-size:32px;font-weight: bold;color: #2ed573;margin:20px0;}.btn-group { display: flex; gap:10px; justify-content: center; }button {padding:10px20px;font-size:16px;font-weight: bold;border: none;border-radius:6px;cursor: pointer;color: white;}.deposit { background-color: #1e90ff; }.withdraw { background-color: #ff4757; }</style></head><body><divclass="card"><h2>🏦 Güvenli Banka Hesabı (Closure)</h2><p>Banka kasasındaki para dışarıdan manipüle edilemez. Sadece butonlar çalışır:</p><divclass="balance-box"><spanid="balanceDisplay">1000</span> TL</div><divclass="btn-group"><buttonclass="deposit"id="depositBtn">100TL Yatır</button><buttonclass="withdraw"id="withdrawBtn">100TL Çek</button></div></div><script>// MÜLAKAT SORUSU:"Bana closures kullanarak private bir sayaç/hesap yapısı kur"function bankaHesabiOlustur(ilkBakiye) {// Bu değişken dışarıdan ASLA erişilemez (Private Variable)let bakiye = ilkBakiye;// Geriye fonksiyonlar içeren bir obje dönüyoruz.// Bu fonksiyonlar"bakiye"değişkenini hafızada (lexical scope) kilitler.return {paraYatir: function(miktar) {bakiye += miktar;return bakiye;},paraCek: function(miktar) {if (miktar <= bakiye) {bakiye -= miktar;return bakiye;}alert("Yetersiz bakiye!");return bakiye;},bakiyeGoster: function() {return bakiye;}};}// Hesabı oluşturuyoruz. bankaHesabiOlustur fonksiyonunun görevi bitti ama'bakiye'hafızada kaldı!const benimHesabim = bankaHesabiOlustur(1000);const balanceDisplay = document.getElementById('balanceDisplay');// Hile testi:// console.log(benimHesabim.bakiye); // ÇIKTI: undefined! (Dışarıdan kimse dokunamaz)document.getElementById('depositBtn').addEventListener('click', () => {const yeniBakiye = benimHesabim.paraYatir(100);balanceDisplay.textContent = yeniBakiye;});document.getElementById('withdrawBtn').addEventListener('click', () => {const yeniBakiye = benimHesabim.paraCek(100);balanceDisplay.textContent = yeniBakiye;});</script></body></html>
JavaScript, Java veya C# gibi geleneksel sınıf tabanlı (Class-based) bir miras alma modeline sahip değildir; Prototipten türeyen (Prototype-based) bir dildir. Sayfada bir objeden 1000 tane ürettiğimizde, her objenin içine aynı fonksiyonları tek tek kopyalarsak bilgisayarın RAM belleği çöker.
Görevi: Ortak kullanılan
fonksiyonları tek bir gizli merkezde (Prototype)
saklar. Üretilen tüm objeler bu gizli merkeze bir zincirle
(__proto__)
bağlıdır. Bir fonksiyon çağrıldığında obje önce kendi içine
bakar, bulamazsa bu gizli zinciri takip ederek prototipten
çalıştırır.
Bir apartmandaki daireleri düşünün.
Her dairenin içine koca bir matbaa makinesi kurmak hem çok masraflı
hem de mantıksızdır (Her
objeye fonksiyon kopyalamak).
Bunun yerine apartmanın ortak kullanım alanına (bodrum katına)
tek bir büyük fotokopi makinesi konur (Prototype).
Hangi daire sakini çıktı almak isterse bodrum katına iner ve o
ortak makineyi kullanır.
Dosya Adı:
advanced-prototype.html
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>İleri Düzey JavaScript - Prototype</title><style>body {font-family: sans-serif;background-color: #2c3e50;color: white;display: flex;justify-content: center;align-items: center;height:100vh;margin:0;}.console-box {background: #1e222b;padding:30px;border-radius:10px;box-shadow:010px25px rgba(0,0,0,0.4);max-width:500px;width:100%;border-left:5px solid #3498db;}.log-line {font-family: monospace;background: rgba(255,255,255,0.05);padding:10px;margin:8px0;border-radius:4px;font-size:14px;}</style></head><body><divclass="console-box"><h3>🧬 Prototype Zinciri ve Hafıza Yönetimi</h3><p>Aşağıdaki çıktılar, fonksiyonların objelerin kendi içinde değil, ortak prototip merkezinde yaşadığını kanıtlar:</p><divid="outputBox"></div></div><script>const outputBox = document.getElementById('outputBox');function logYaz(metin) {const div = document.createElement('div');div.className ='log-line';div.textContent = metin;outputBox.appendChild(div);}//1. Yapıcı Fonksiyon (Constructor Function)function Oyuncu(isim, skor) {this.isim = isim;this.skor = skor;// DİKKAT: Buraya fonksiyon yazmıyoruz! Bellek israfını önlüyoruz.}//2. ORTAK FONKSİYONU PROTOTİPE EKLİYORUZ (Apartmanın bodrum katındaki makine)Oyuncu.prototype.skorArttir = function() {this.skor +=10;return `${this.isim} yeni skoru: ${this.skor}`;};//3. İki farklı oyuncu objesi üretiyoruzconst oyuncu1= new Oyuncu("Ahmet",50);const oyuncu2= new Oyuncu("Can",80);// Fonksiyonları çalıştırıyoruz (Zincir takip edilerek prototipten çekilir)logYaz(oyuncu1.skorArttir()); // Çıktı: Ahmet yeni skoru:60logYaz(oyuncu2.skorArttir()); // Çıktı: Can yeni skoru:90// MÜLAKATIN CAN ALICI SORUSU VE KANITI://"Bu iki objenin fonksiyonları bellekte aynı yeri mi gösteriyor?"const ayniMi = (oyuncu1.skorArttir === oyuncu2.skorArttir);logYaz(`Soru: İki nesnenin fonksiyon belleği aynı mı? -> ${ayniMi}`);// Çıktı: true! Çünkü ikisi de bellekteki tek bir ortak noktaya (Prototype) bağlı.// Objelerin iç yapısını kontrol edelimlogYaz(`oyuncu1kendi mülkünde fonksiyon var mı? -> ${oyuncu1.hasOwnProperty('skorArttir')}`);// Çıktı: false! Çünkü fonksiyon onun içinde değil, onun prototipindedir.</script></body></html>