[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"blog-post-3-hizli-javascript-mini-projesi-todo-sayac-ve-modal-kodlu":3},{"dataItem":4,"heading":36,"metaData":38,"schema":81},["Reactive",5],{"id":6,"title":7,"summary":8,"content":9,"seo_title":10,"seo_description":11,"seo_keywords":12,"slug":13,"createdAt":14,"updatedAt":14,"blog_categories":15,"authors":19,"image":24,"thumb":25,"image_webp":26,"thumb_webp":27,"rating":28,"heading_title":7,"heading_sub_title":17,"readingTime":29,"url":34,"comments":35,"meta_cover":24},21078,"3 Hızlı JavaScript Mini Projesi: Todo, Sayaç ve Modal (Kodlu)","Bu rehberde vanilla JavaScript ile 3 hızlı mini proje yapacağız: localStorage ile kalıcı Todo listesi, setInterval/clearInterval ile sayaç ve modern \u003Cdialog> elementiyle erişilebilir modal. Kodları kopyalayıp tek bir HTML dosyasında hemen deneyebilirsiniz.","\u003Ch2>Bu yazıda ne yapacağız?\u003C/h2>\n\u003Cp>Pratik “yaparak öğrenme” için üç küçük ama işe yarar \u003Cstrong>vanilla JavaScript\u003C/strong> projesi kuracağız:\u003C/p>\n\u003Cul>\n\u003Cli>\u003Cstrong>Todo uygulaması\u003C/strong>: Ekle / tamamlandı işaretle / sil + \u003Cstrong>localStorage\u003C/strong> ile kalıcılık\u003C/li>\n\u003Cli>\u003Cstrong>Sayaç\u003C/strong>: Başlat / durdur / sıfırla + \u003Cstrong>setInterval\u003C/strong> / \u003Cstrong>clearInterval\u003C/strong>\u003C/li>\n\u003Cli>\u003Cstrong>Modal\u003C/strong>: Modern ve semantik \u003Cstrong>&lt;dialog&gt;\u003C/strong> ile aç/kapat\u003C/li>\n\u003C/ul>\n\u003Cp>Hedef, “çok kapsamlı framework projesi” değil; \u003Cem>DOM seçme, event yönetimi, durum (state) tutma ve küçük UI akışları\u003C/em> gibi temel kasları güçlendirmek.\u003C/p>\n\u003Chr>\n\u003Ch2>Ön koşullar ve kurulum\u003C/h2>\n\u003Cp>Şunlar yeterli: temel HTML, çok az CSS ve temel JavaScript. İsterseniz her projeyi ayrı dosyada, isterseniz tek dosyada deneyebilirsiniz. Aşağıdaki şablonla başlayın.\u003C/p>\n\u003Cblockquote>\n\u003Cp>\u003Cstrong>index.html (başlangıç şablonu)\u003C/strong>\u003Cbr>\n&lt;!doctype html&gt;\u003Cbr>\n&lt;html lang=&quot;tr&quot;&gt;\u003Cbr>\n&lt;meta charset=&quot;utf-8&quot;&gt;\u003Cbr>\n&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot;&gt;\u003Cbr>\n&lt;title&gt;JS Mini Projeler&lt;/title&gt;\u003Cbr>\n&lt;style&gt;\u003Cbr>\n  body { font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial; margin: 24px; }\u003Cbr>\n  .row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }\u003Cbr>\n  .card { border: 1px solid #ddd; border-radius: 10px; padding: 16px; margin: 16px 0; }\u003Cbr>\n  ul { padding-left: 18px; }\u003Cbr>\n  li.done { text-decoration: line-through; opacity: 0.7; }\u003Cbr>\n  button { cursor: pointer; }\u003Cbr>\n&lt;/style&gt;\u003Cbr>\n&lt;h1&gt;3 Hızlı JavaScript Mini Projesi&lt;/h1&gt;\u003Cbr>\n&lt;!-- Aşağıdaki bölümlere projelerin HTML'lerini ekleyeceğiz --&gt;\u003Cbr>\n&lt;script&gt;\u003Cbr>\n  // Aşağıdaki bölümlere projelerin JS kodlarını ekleyeceğiz\u003Cbr>\n&lt;/script&gt;\u003Cbr>\n&lt;/html&gt;\u003C/p>\n\u003C/blockquote>\n\u003Cp>\u003Cem>Not:\u003C/em> Bu rehber, olay bağlamak için \u003Cstrong>addEventListener\u003C/strong> yaklaşımını kullanır. MDN, event dinleme için bu yöntemin standart ve sürdürülebilir olduğunu detaylıca açıklar. Kaynak: \u003Ca href=\"https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener\">MDN addEventListener\u003C/a>.\u003C/p>\n\u003Chr>\n\u003Ch2>Mini Proje 1: localStorage’lı Todo Uygulaması\u003C/h2>\n\u003Ch3>Ne öğreneceksiniz?\u003C/h3>\n\u003Cul>\n\u003Cli>Input’tan veri alma ve listeye basma\u003C/li>\n\u003Cli>Tek tek öğelere tıklama/işaretleme\u003C/li>\n\u003Cli>Silme işlemi\u003C/li>\n\u003Cli>\u003Cstrong>localStorage\u003C/strong> ile sayfa kapanıp açılsa bile veriyi koruma\u003C/li>\n\u003C/ul>\n\u003Cp>MDN’e göre Web Storage API, bir origin için anahtar-değer mantığında depolama sağlar ve tarayıcı oturumları arasında veriyi tutabilir. Kaynak: \u003Ca href=\"https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API\">MDN Web Storage API\u003C/a>.\u003C/p>\n\u003Ch3>Todo HTML\u003C/h3>\n\u003Cblockquote>\n\u003Cp>\u003Cstrong>HTML (Todo kartı)\u003C/strong>\u003Cbr>\n&lt;div class=&quot;card&quot; id=&quot;todoCard&quot;&gt;\u003Cbr>\n  &lt;h2&gt;Todo&lt;/h2&gt;\u003Cbr>\n  &lt;div class=&quot;row&quot;&gt;\u003Cbr>\n    &lt;input id=&quot;todoInput&quot; placeholder=&quot;Yeni iş...&quot; /&gt;\u003Cbr>\n    &lt;button id=&quot;addTodoBtn&quot;&gt;Ekle&lt;/button&gt;\u003Cbr>\n    &lt;button id=&quot;clearTodosBtn&quot; title=&quot;Tümünü sil&quot;&gt;Temizle&lt;/button&gt;\u003Cbr>\n  &lt;/div&gt;\u003Cbr>\n  &lt;p id=&quot;todoHint&quot;&gt;&lt;em&gt;İpucu: Öğeye tıklayınca tamamlandı olur.&lt;/em&gt;&lt;/p&gt;\u003Cbr>\n  &lt;ul id=&quot;todoList&quot;&gt;&lt;/ul&gt;\u003Cbr>\n&lt;/div&gt;\u003C/p>\n\u003C/blockquote>\n\u003Ch3>Todo JavaScript (kopyala-yapıştır)\u003C/h3>\n\u003Cp>\u003Cstrong>Kritik nokta:\u003C/strong> localStorage yalnızca \u003Cem>string\u003C/em> saklar. Dizi/nesne saklamak için \u003Cstrong>JSON.stringify\u003C/strong>, geri okurken \u003Cstrong>JSON.parse\u003C/strong> kullanın. Kaynak: \u003Ca href=\"https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API\">MDN Web Storage API\u003C/a>.\u003C/p>\n\u003Cblockquote>\n\u003Cp>\u003Cstrong>JS (Todo)\u003C/strong>\u003Cbr>\nconst todoInput = document.querySelector('#todoInput');\u003Cbr>\nconst addTodoBtn = document.querySelector('#addTodoBtn');\u003Cbr>\nconst clearTodosBtn = document.querySelector('#clearTodosBtn');\u003Cbr>\nconst todoListEl = document.querySelector('#todoList');\u003Cbr>\n\u003Cbr>\nconst STORAGE_KEY = 'miniProjects.todos.v1';\u003Cbr>\nlet todos = [];\u003Cbr>\n\u003Cbr>\nfunction storageAvailable(type) {\u003Cbr>\n  try {\u003Cbr>\n    const storage = window[type];\u003Cbr>\n    const x = '__storage_test__';\u003Cbr>\n    storage.setItem(x, x);\u003Cbr>\n    storage.removeItem(x);\u003Cbr>\n    return true;\u003Cbr>\n  } catch (e) {\u003Cbr>\n    return false;\u003Cbr>\n  }\u003Cbr>\n}\u003Cbr>\n\u003Cbr>\nfunction loadTodos() {\u003Cbr>\n  if (!storageAvailable('localStorage')) {\u003Cbr>\n    // Depolama kullanılamazsa uygulama yine çalışsın; sadece kalıcılık olmaz.\u003Cbr>\n    return;\u003Cbr>\n  }\u003Cbr>\n  const raw = localStorage.getItem(STORAGE_KEY);\u003Cbr>\n  if (!raw) return;\u003Cbr>\n  try {\u003Cbr>\n    todos = JSON.parse(raw) ?? []; \u003Cbr>\n  } catch (e) {\u003Cbr>\n    todos = [];\u003Cbr>\n  }\u003Cbr>\n}\u003Cbr>\n\u003Cbr>\nfunction saveTodos() {\u003Cbr>\n  if (!storageAvailable('localStorage')) return;\u003Cbr>\n  localStorage.setItem(STORAGE_KEY, JSON.stringify(todos));\u003Cbr>\n}\u003Cbr>\n\u003Cbr>\nfunction renderTodos() {\u003Cbr>\n  todoListEl.innerHTML = '';\u003Cbr>\n\u003Cbr>\n  todos.forEach((t) =&gt; {\u003Cbr>\n    const li = document.createElement('li');\u003Cbr>\n    li.textContent = t.text;\u003Cbr>\n    li.dataset.id = t.id;\u003Cbr>\n    if (t.done) li.classList.add('done');\u003Cbr>\n\u003Cbr>\n    const delBtn = document.createElement('button');\u003Cbr>\n    delBtn.textContent = 'Sil';\u003Cbr>\n    delBtn.style.marginLeft = '8px';\u003Cbr>\n    delBtn.addEventListener('click', (ev) =&gt; {\u003Cbr>\n      ev.stopPropagation();\u003Cbr>\n      deleteTodo(t.id);\u003Cbr>\n    });\u003Cbr>\n\u003Cbr>\n    li.appendChild(delBtn);\u003Cbr>\n    li.addEventListener('click', () =&gt; toggleDone(t.id));\u003Cbr>\n    todoListEl.appendChild(li);\u003Cbr>\n  });\u003Cbr>\n}\u003Cbr>\n\u003Cbr>\nfunction addTodo(text) {\u003Cbr>\n  const trimmed = text.trim();\u003Cbr>\n  if (!trimmed) return;\u003Cbr>\n  todos.unshift({ id: crypto.randomUUID ? crypto.randomUUID() : String(Date.now()), text: trimmed, done: false });\u003Cbr>\n  saveTodos();\u003Cbr>\n  renderTodos();\u003Cbr>\n}\u003Cbr>\n\u003Cbr>\nfunction toggleDone(id) {\u003Cbr>\n  todos = todos.map((t) =&gt; (t.id === id ? { ...t, done: !t.done } : t));\u003Cbr>\n  saveTodos();\u003Cbr>\n  renderTodos();\u003Cbr>\n}\u003Cbr>\n\u003Cbr>\nfunction deleteTodo(id) {\u003Cbr>\n  todos = todos.filter((t) =&gt; t.id !== id);\u003Cbr>\n  saveTodos();\u003Cbr>\n  renderTodos();\u003Cbr>\n}\u003Cbr>\n\u003Cbr>\naddTodoBtn.addEventListener('click', () =&gt; {\u003Cbr>\n  addTodo(todoInput.value);\u003Cbr>\n  todoInput.value = '';\u003Cbr>\n  todoInput.focus();\u003Cbr>\n});\u003Cbr>\n\u003Cbr>\ntodoInput.addEventListener('keydown', (e) =&gt; {\u003Cbr>\n  if (e.key === 'Enter') {\u003Cbr>\n    addTodoBtn.click();\u003Cbr>\n  }\u003Cbr>\n});\u003Cbr>\n\u003Cbr>\nclearTodosBtn.addEventListener('click', () =&gt; {\u003Cbr>\n  todos = [];\u003Cbr>\n  saveTodos();\u003Cbr>\n  renderTodos();\u003Cbr>\n});\u003Cbr>\n\u003Cbr>\nloadTodos();\u003Cbr>\nrenderTodos();\u003C/p>\n\u003C/blockquote>\n\u003Ch3>Todo için pratik notlar\u003C/h3>\n\u003Cul>\n\u003Cli>\u003Cstrong>Depolama her zaman çalışmayabilir:\u003C/strong> Özel mod, tarayıcı ayarları veya kota sınırları gibi nedenlerle localStorage kullanımı kısıtlanabilir. Bu yüzden yukarıdaki gibi “kullanılabilir mi?” kontrolü yapmak faydalıdır. (MDN örnek yaklaşımı: \u003Ca href=\"https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API\">Web Storage API\u003C/a>)\u003C/li>\n\u003Cli>\u003Cstrong>Hassas veri kaydetmeyin:\u003C/strong> localStorage, sayfadaki JavaScript tarafından okunabilir. Bu nedenle parola/token gibi hassas bilgiler için uygun bir yer değildir. Todo gibi düşük riskli içerikler için daha makul bir tercihtir.\u003C/li>\n\u003Cli>\u003Cstrong>Event yaklaşımı:\u003C/strong> Inline onclick yerine \u003Cstrong>addEventListener\u003C/strong> ile olay bağlamak, kodu daha bakımı kolay hale getirir. (Kaynak: \u003Ca href=\"https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener\">MDN addEventListener\u003C/a>)\u003C/li>\n\u003C/ul>\n\u003Chr>\n\u003Ch2>Mini Proje 2: setInterval ile Sayaç (Başlat/Durdur/Sıfırla)\u003C/h2>\n\u003Ch3>Ne öğreneceksiniz?\u003C/h3>\n\u003Cul>\n\u003Cli>Zamanlayıcı başlatma ve durdurma\u003C/li>\n\u003Cli>Interval ID saklama\u003C/li>\n\u003Cli>UI güncelleme\u003C/li>\n\u003C/ul>\n\u003Cp>MDN’e göre \u003Cstrong>setInterval\u003C/strong>, bir fonksiyonu belirli aralıklarla çalıştırır; durdurmak için \u003Cstrong>clearInterval\u003C/strong> gerekir. Ayrıca zamanlama, tarayıcının olay döngüsü nedeniyle “mükemmel dakiklikte” olmayabilir. Kaynak: \u003Ca href=\"https://developer.mozilla.org/en-US/docs/Web/API/Window/setInterval\">MDN setInterval\u003C/a>.\u003C/p>\n\u003Ch3>Sayaç HTML\u003C/h3>\n\u003Cblockquote>\n\u003Cp>\u003Cstrong>HTML (Sayaç kartı)\u003C/strong>\u003Cbr>\n&lt;div class=&quot;card&quot; id=&quot;counterCard&quot;&gt;\u003Cbr>\n  &lt;h2&gt;Sayaç&lt;/h2&gt;\u003Cbr>\n  &lt;p&gt;Geçen süre: &lt;strong id=&quot;counterValue&quot;&gt;0&lt;/strong&gt; sn&lt;/p&gt;\u003Cbr>\n  &lt;div class=&quot;row&quot;&gt;\u003Cbr>\n    &lt;button id=&quot;startCounterBtn&quot;&gt;Başlat&lt;/button&gt;\u003Cbr>\n    &lt;button id=&quot;pauseCounterBtn&quot;&gt;Durdur&lt;/button&gt;\u003Cbr>\n    &lt;button id=&quot;resetCounterBtn&quot;&gt;Sıfırla&lt;/button&gt;\u003Cbr>\n  &lt;/div&gt;\u003Cbr>\n&lt;/div&gt;\u003C/p>\n\u003C/blockquote>\n\u003Ch3>Sayaç JavaScript\u003C/h3>\n\u003Cblockquote>\n\u003Cp>\u003Cstrong>JS (Sayaç)\u003C/strong>\u003Cbr>\nconst counterValueEl = document.querySelector('#counterValue');\u003Cbr>\nconst startCounterBtn = document.querySelector('#startCounterBtn');\u003Cbr>\nconst pauseCounterBtn = document.querySelector('#pauseCounterBtn');\u003Cbr>\nconst resetCounterBtn = document.querySelector('#resetCounterBtn');\u003Cbr>\n\u003Cbr>\nlet seconds = 0;\u003Cbr>\nlet intervalId = null;\u003Cbr>\n\u003Cbr>\nfunction renderCounter() {\u003Cbr>\n  counterValueEl.textContent = String(seconds);\u003Cbr>\n}\u003Cbr>\n\u003Cbr>\nfunction startCounter() {\u003Cbr>\n  if (intervalId !== null) return; // zaten çalışıyor\u003Cbr>\n  intervalId = window.setInterval(() =&gt; {\u003Cbr>\n    seconds += 1;\u003Cbr>\n    renderCounter();\u003Cbr>\n  }, 1000);\u003Cbr>\n}\u003Cbr>\n\u003Cbr>\nfunction pauseCounter() {\u003Cbr>\n  if (intervalId === null) return;\u003Cbr>\n  window.clearInterval(intervalId);\u003Cbr>\n  intervalId = null;\u003Cbr>\n}\u003Cbr>\n\u003Cbr>\nfunction resetCounter() {\u003Cbr>\n  pauseCounter();\u003Cbr>\n  seconds = 0;\u003Cbr>\n  renderCounter();\u003Cbr>\n}\u003Cbr>\n\u003Cbr>\nstartCounterBtn.addEventListener('click', startCounter);\u003Cbr>\npauseCounterBtn.addEventListener('click', pauseCounter);\u003Cbr>\nresetCounterBtn.addEventListener('click', resetCounter);\u003Cbr>\n\u003Cbr>\nrenderCounter();\u003C/p>\n\u003C/blockquote>\n\u003Ch3>Sayaç için pratik notlar\u003C/h3>\n\u003Cul>\n\u003Cli>\u003Cstrong>Zaman kayması normal olabilir:\u003C/strong> setInterval, ideal senaryoda her 1000 ms’de bir çalışır; ancak sekme arka plana gidince veya ana iş parçacığı yoğunken gecikmeler görülebilir. (Kaynak: \u003Ca href=\"https://developer.mozilla.org/en-US/docs/Web/API/Window/setInterval\">MDN setInterval\u003C/a>)\u003C/li>\n\u003Cli>\u003Cstrong>Daha “ölçüme yakın” sayaç isterseniz:\u003C/strong> seconds’ı arttırmak yerine başlangıç zamanını saklayıp \u003Cem>Date.now()\u003C/em> farkından hesaplama yapabilirsiniz. Bu yaklaşım, gecikmeleri daha iyi tolere eder.\u003C/li>\n\u003C/ul>\n\u003Chr>\n\u003Ch2>Mini Proje 3: &lt;dialog&gt; ile Modern Modal\u003C/h2>\n\u003Ch3>Neden &lt;dialog&gt;?\u003C/h3>\n\u003Cp>Modal pencereler, klasik olarak div + overlay ile yapılır. Modern tarayıcılarda \u003Cstrong>&lt;dialog&gt;\u003C/strong> elementi, semantik bir seçenek sunar ve \u003Cstrong>showModal()\u003C/strong> / \u003Cstrong>close()\u003C/strong> gibi API’lerle gelir. MDN ayrıca showModal ile açıldığında dış alanın etkileşimini engelleme (inert davranışı) ve \u003Cstrong>ESC\u003C/strong> ile kapatma gibi davranışları açıklar. Kaynak: \u003Ca href=\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog\">MDN dialog\u003C/a>.\u003C/p>\n\u003Ch3>Modal HTML\u003C/h3>\n\u003Cblockquote>\n\u003Cp>\u003Cstrong>HTML (Modal kartı + dialog)\u003C/strong>\u003Cbr>\n&lt;div class=&quot;card&quot; id=&quot;modalCard&quot;&gt;\u003Cbr>\n  &lt;h2&gt;Modal&lt;/h2&gt;\u003Cbr>\n  &lt;button id=&quot;openModalBtn&quot;&gt;Modal Aç&lt;/button&gt;\u003Cbr>\n&lt;/div&gt;\u003Cbr>\n\u003Cbr>\n&lt;dialog id=&quot;demoDialog&quot;&gt;\u003Cbr>\n  &lt;h3&gt;Merhaba!&lt;/h3&gt;\u003Cbr>\n  &lt;p&gt;Bu bir &amp;lt;dialog&amp;gt; modal örneğidir.&lt;/p&gt;\u003Cbr>\n  &lt;div class=&quot;row&quot;&gt;\u003Cbr>\n    &lt;button id=&quot;closeModalBtn&quot;&gt;Kapat&lt;/button&gt;\u003Cbr>\n  &lt;/div&gt;\u003Cbr>\n&lt;/dialog&gt;\u003C/p>\n\u003C/blockquote>\n\u003Ch3>Modal JavaScript\u003C/h3>\n\u003Cblockquote>\n\u003Cp>\u003Cstrong>JS (Modal)\u003C/strong>\u003Cbr>\nconst openModalBtn = document.querySelector('#openModalBtn');\u003Cbr>\nconst dialogEl = document.querySelector('#demoDialog');\u003Cbr>\nconst closeModalBtn = document.querySelector('#closeModalBtn');\u003Cbr>\n\u003Cbr>\nfunction canUseDialog() {\u003Cbr>\n  return typeof HTMLDialogElement !== 'undefined' &amp;&amp; typeof dialogEl.showModal === 'function';\u003Cbr>\n}\u003Cbr>\n\u003Cbr>\nopenModalBtn.addEventListener('click', () =&gt; {\u003Cbr>\n  if (!canUseDialog()) {\u003Cbr>\n    // Basit bir geri dönüş: En azından mesajı göster\u003Cbr>\n    window.alert('Tarayıcınız dialog özelliğini desteklemiyor olabilir.');\u003Cbr>\n    return;\u003Cbr>\n  }\u003Cbr>\n  dialogEl.showModal();\u003Cbr>\n});\u003Cbr>\n\u003Cbr>\ncloseModalBtn.addEventListener('click', () =&gt; dialogEl.close());\u003Cbr>\n\u003Cbr>\n// İsteğe bağlı: dialog dışına tıklayınca kapat (kullanıcı deneyimi tercihi).\u003Cbr>\ndialogEl.addEventListener('click', (e) =&gt; {\u003Cbr>\n  const rect = dialogEl.getBoundingClientRect();\u003Cbr>\n  const clickedInDialog = (\u003Cbr>\n    e.clientX &gt;= rect.left &amp;&amp; e.clientX &lt;= rect.right &amp;&amp;\u003Cbr>\n    e.clientY &gt;= rect.top &amp;&amp; e.clientY &lt;= rect.bottom\u003Cbr>\n  );\u003Cbr>\n  if (!clickedInDialog) dialogEl.close();\u003Cbr>\n});\u003C/p>\n\u003C/blockquote>\n\u003Ch3>Modal için erişilebilirlik ve uyumluluk notları\u003C/h3>\n\u003Cul>\n\u003Cli>\u003Cstrong>ESC ile kapatma:\u003C/strong> &lt;dialog&gt; modal modda açıldığında çoğu modern tarayıcı ESC davranışını destekler. Detaylar: \u003Ca href=\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog\">MDN dialog\u003C/a>.\u003C/li>\n\u003Cli>\u003Cstrong>Odak (focus) yönetimi:\u003C/strong> &lt;dialog&gt; bu konuda yardımcı olur; yine de modal açılınca ilk etkileşimli öğeye odak vermek iyi bir alışkanlıktır (ör. kapat butonu).\u003C/li>\n\u003Cli>\u003Cstrong>Eski tarayıcılar:\u003C/strong> &lt;dialog&gt; her ortamda aynı şekilde çalışmayabilir. Üretim senaryosunda bir polyfill veya role=&quot;dialog&quot; tabanlı erişilebilir bir geri dönüş yaklaşımı değerlendirin.\u003C/li>\n\u003C/ul>\n\u003Chr>\n\u003Ch2>Hepsini toparlayan mini kontrol listesi\u003C/h2>\n\u003Cul>\n\u003Cli>\u003Cstrong>State\u003C/strong>: Veriyi (todos, seconds gibi) tek bir değişkende tutup UI’ı o state’ten üretin.\u003C/li>\n\u003Cli>\u003Cstrong>Render fonksiyonu\u003C/strong>: DOM güncellemelerini tek yerde yapın (renderTodos, renderCounter).\u003C/li>\n\u003Cli>\u003Cstrong>Event yönetimi\u003C/strong>: Inline handler yerine addEventListener kullanın. (Kaynak: \u003Ca href=\"https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener\">MDN addEventListener\u003C/a>)\u003C/li>\n\u003Cli>\u003Cstrong>Kalıcılık\u003C/strong>: localStorage ile saklarken JSON.stringify/parse uygulayın. (Kaynak: \u003Ca href=\"https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API\">MDN Web Storage API\u003C/a>)\u003C/li>\n\u003Cli>\u003Cstrong>Zamanlayıcılar\u003C/strong>: setInterval başlatmayı/bitirmeyi kontrol edin; sekme arka planda farklı davranışlar olabileceğini unutmayın. (Kaynak: \u003Ca href=\"https://developer.mozilla.org/en-US/docs/Web/API/Window/setInterval\">MDN setInterval\u003C/a>)\u003C/li>\n\u003C/ul>\n\u003Chr>\n\u003Ch2>Bir sonraki adım: Mini projeleri büyütme fikirleri\u003C/h2>\n\u003Cul>\n\u003Cli>\u003Cstrong>Todo\u003C/strong>: Filtre (tümü/aktif/tamamlanan), düzenleme (edit), sürükle-bırak sıralama.\u003C/li>\n\u003Cli>\u003Cstrong>Sayaç\u003C/strong>: Pomodoro (25/5), tur (lap) kayıtları, sesli bildirim.\u003C/li>\n\u003Cli>\u003Cstrong>Modal\u003C/strong>: Onay penceresi (confirm), form içeren modal, klavye kısayolları.\u003C/li>\n\u003C/ul>\n\u003Cp>Kodları hızlıca denemek için bir online editöre (ör. \u003Ca href=\"https://codepen.io/\">https://codepen.io/\u003C/a>) tek HTML olarak yapıştırıp çalıştırabilirsiniz. Gerçek bir proje ortamında ise dosyaları ayırmanız (app.js, styles.css) okunabilirliği artırır.\u003C/p>\n\u003Cp>\u003Cem>Genel not:\u003C/em> Bu yazı eğitim amaçlıdır. Üretim uygulamalarında tarayıcı uyumluluğu, erişilebilirlik testleri ve veri güvenliği gereksinimleri ayrıca değerlendirilmelidir.\u003C/p>","3 Hızlı JavaScript Mini Projesi (Todo, Sayaç, Modal) – Kodlu","Vanilla JavaScript ile 3 mini proje: localStorage’lı Todo, setInterval’lı sayaç ve \u003Cdialog> ile erişilebilir modal. Kopyala-yapıştır kodlar ve pratik ipuçları.","javascript başlangıç kodları, mini proje, todo app, sayaç proje, modal örneği, vanilla javascript, localStorage, setInterval, dialog","3-hizli-javascript-mini-projesi-todo-sayac-ve-modal-kodlu","2026-03-08T16:11:51.000Z",{"id":16,"title":17,"slug":18},207,"Mini JS Projeleri","mini-js-projeleri",{"id":20,"name":21,"nickname":22,"slug":23},92,"Burak Demirtaş","CodeMentor","burak-demirtas","/media/blog/756c42484b61f0ee7b6c749252b85dc4.jpg","/media/blog/756c42484b61f0ee7b6c749252b85dc4_thumb.jpg","/media/blog/756c42484b61f0ee7b6c749252b85dc4.webp","/media/blog/756c42484b61f0ee7b6c749252b85dc4_thumb.webp",null,{"minutes":30,"wordCount":31,"imageCount":32,"formatted":33},8,1531,0,"8 dk okuma süresi","/blog/mini-js-projeleri/3-hizli-javascript-mini-projesi-todo-sayac-ve-modal-kodlu",[],["Reactive",37],{"title":7,"subTitle":17,"image":24},["Reactive",39],{"title":10,"meta":40,"link":75},[41,43,45,48,51,54,57,60,63,66,69,71,73],{"hid":42,"name":42,"content":11},"description",{"hid":44,"name":44,"content":12},"keywords",{"hid":46,"name":46,"content":47},"author","Başlangıç Seviyesi Kod & Snippet Rehberi",{"hid":49,"name":49,"content":50},"robots","index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1",{"hid":52,"property":52,"content":53},"og:type","website",{"hid":55,"property":55,"content":56},"og:title","Başlangıç Kod & Snippet Rehberi | KodÖğreniyorum",{"hid":58,"property":58,"content":59},"og:description","Yeni başlayanlara yönelik kısa kod örnekleri, snippet'ler ve adım adım alıştırmalar. Hızlı uygulamalarla temel programlama mantığını pekiştir.",{"hid":61,"property":61,"content":62},"og:image","https://kodogreniyorum.com/media/blog/756c42484b61f0ee7b6c749252b85dc4.jpg",{"hid":64,"property":64,"content":65},"og:url","https://kodogreniyorum.com/blog/mini-js-projeleri/3-hizli-javascript-mini-projesi-todo-sayac-ve-modal-kodlu",{"hid":67,"name":67,"content":68},"twitter:card","summary_large_image",{"hid":70,"name":70,"content":56},"twitter:title",{"hid":72,"name":72,"content":59},"twitter:description",{"hid":74,"name":74,"content":62},"twitter:image",[76,78],{"rel":77,"href":65},"canonical",{"rel":79,"href":80},"amphtml","https://amp.kodogreniyorum.com/blog/mini-js-projeleri/3-hizli-javascript-mini-projesi-todo-sayac-ve-modal-kodlu",["Reactive",82],{"@context":83,"@graph":84},"https://schema.org",[85,98],{"@type":86,"headline":10,"image":62,"author":87,"publisher":90,"datePublished":14,"dateModified":14,"mainEntityOfPage":96,"description":11},"BlogPosting",{"@type":88,"name":21,"url":89},"Person","https://kodogreniyorum.com/yazarlar/burak-demirtas",{"@type":91,"name":47,"logo":92},"Organization",{"@type":93,"url":94,"width":95,"height":95},"ImageObject","https://kodogreniyorum.com/img/icons/favicon.png",32,{"@type":97,"@id":65},"WebPage",{"@type":99,"itemListElement":100},"BreadcrumbList",[101,106,110,113],{"@type":102,"position":103,"name":104,"item":105},"ListItem",1,"Ana Sayfa","https://kodogreniyorum.com",{"@type":102,"position":107,"name":108,"item":109},2,"Blog","https://kodogreniyorum.com/blog",{"@type":102,"position":111,"name":17,"item":112},3,"https://kodogreniyorum.com/blog/mini-js-projeleri",{"@type":102,"position":114,"name":7,"item":65},4]