Skip to content
This is my space, where experience meets the will to start over. This is my space, where experience meets the will to start over.

The first step is knowing where you want to go.

  • Home
  • Coding Hub
    • Software & Project
      • Small Biz Ops – S.B.O.
        • SmallBizOps – Day 10/90
      • CRM/ERP
      • MyTracker
      • My Budget
    • Form Zero to “WoW”
      • JavaScript from Zero (Completed)
        • 2. Remove and Edit List Items
        • 3. Separate HTML and JavaScript, Use addEventListener and Conditional Logic
        • 4. Add Dynamic CSS Classes
        • 5. Save & Restore Your List with localStorage
        • 6 – Turn Your App into a Full To-Do List
      • Python from Zero (Completed)
        • 2. Lists & Loops
        • 3. Conditional Menus
        • 4. Edit & Remove Tasks (with closing: Python vs PHP and Large Data)
        • 5 – Save to File: Make Your Tasks Survive Restarts
        • 6 — Pythin from zero – Final Project Polishing: Numbering, Formatting, and Preparing for CSV
      • Rust – From Zero to “WoW” (Completed)
        • 1 – Setup and Project Structure in Rust
        • 2 – User input: validation and error handling
        • 3 – Rust from Zero to “WoW – BMI Calculation and Conditional Logic
        • 4 –Rust – Clear, Formatted Output
        • 5 – Rust – Final Thoughts: Precision as a Form of Respect
      • Go from Zero to “WoW” (Completed)
        • 1 – Why Go Is Perfect for a Personal Expense Tracker
        • 2 – Logging Expenses and Console Input
        • 3 – Go from Zero to “WoW” – Smart Filtering & Display Logic
        • 4 – Go – Saving Data to Local Files
        • 5 – Go – Final Project – Expense Tracker in Go
      • C++ from Zero to “WoW” (Completed)
        • 1 – Why C++ for file organization?
        • 2 – C++ – File Type Detection and Classification
        • 3 – C++ – Creating & Managing Subfolders
        • 4 – C++ – Safe File Movement and User Feedback
        • 5 – C++ – Order as Mental Clarity
      • Ubuntu – From Zero to “WoW” (Completed)
        • 2 – Ubuntu – The Desktop Environment and Essential Commands
        • 3 – Ubuntu – Managing Files, Folders, and Permissions
        • 4 – Ubuntu – Installing and Updating Software with APT and Snap
        • 5 – Ubuntu – Customizing the Desktop Environment
        • 6 – Ubuntu – Network and Device Configuration
        • 7 – Ubuntu – User Management & System Security — “The Cathedral of Permissions”
        • 8 – Ubuntu – The Talking Machine: Terminal & Bash Scripting
        • 9 – Ubuntu – Ubuntu as a Server or Development Environment
        • 10 – Ubuntu – Backup, Maintenance & Troubleshooting
    • Git Hub Repository
      • Small Biz Ops – S.B.O.
      • Mini ERP – PHP & MySQL
      • CleverCRM (Java, Spring Boot)
      • FraudWatch (Python, FastAPI + scikit-learn)
      • OnboardIQ – Smart Onboarding Portal (Flask + SQLite Demo)
    • ArchPilot
      • 1-Users & Roles, End-to-End (Architecture, Database, and Cross-Framework Code)
      • 2 – Client Registry (CRM) Across Frameworks
      • 3 – Project & Budget Tracker (ERP)
      • 4 – Approval Workflow Engine Multi-step routing, status tracking, escalation paths
      • 5 – Audit Trail & Versioning
    • Small Biz Ops – S.B.O.
  • Vivere in USA
  • P4Y
  • Testi poetici
    • 1 – Sospeso
    • 2 – Il bicchiere di vetro quieto
    • 3 – Quando l’amore inciampa
    • 4 – Ma chi siete davvero?
    • 5 – Above the Thread of Day
    • 6 – The Truth That Doesn’t Exist
    • 7 – All of You, I Miss
    • 8 – The Captain and the Ocean
    • 9 – Between Light and Mist
    • 10 – Il peso delle scelte
  • Contact
  • Admin
This is my space, where experience meets the will to start over.
This is my space, where experience meets the will to start over.

The first step is knowing where you want to go.

Coding – Step 9.4 – JavaScript from Zero – Add Dynamic CSS Classes

Posted on 9 Agosto 202517 Agosto 2025 By Francesco

Mark items as complete by toggling CSS classes (and keep the DOM accessible & tidy)

🧠 Why this lesson matters

After building the basic To-Do List with menu and core actions, it’s time to make it interactive in the browser. With just a few lines of JavaScript, we can:

  • Add or remove CSS classes in response to user clicks.
  • Visually mark an item as “completed” (line-through, faded color).
  • Keep the DOM accessible by updating ARIA attributes.

🎯 Goal

Implement a “click-to-complete” feature: clicking an item marks it as complete, clicking again restores it.

🧩 Starter HTML structure

<section class="todo">
  <h3>My Tasks</h3>
  <ul id="todo-list">
    <li class="todo-item" role="checkbox" aria-checked="false" tabindex="0">Buy coffee beans</li>
    <li class="todo-item" role="checkbox" aria-checked="false" tabindex="0">Email the client</li>
    <li class="todo-item" role="checkbox" aria-checked="false" tabindex="0">Book dentist appointment</li>
  </ul>
</section>

🔎 Accessibility note

We use role="checkbox", aria-checked, and tabindex="0" for screen reader and keyboard navigation support. We’ll update aria-checked when toggling completion status.

🎨 CSS: style for completed items

.todo-item {
  cursor: pointer;
  padding: 8px 10px;
  border-bottom: 1px solid #eee;
  transition: background 0.15s ease;
}

.todo-item:hover,
.todo-item:focus {
  background: #f7faff;
  outline: none;
}

.todo-item.done {
  text-decoration: line-through;
  color: #6b7280;  /* muted gray */
  opacity: 0.85;
}

⚙️ JavaScript: toggle “done” class (click & keyboard)

We’ll use event delegation: instead of adding a listener to each <li>, we attach it to the parent <ul> and detect which item was clicked.

// script.js
const list = document.getElementById('todo-list');

function toggleItem(el) {
  el.classList.toggle('done');
  const isDone = el.classList.contains('done');
  el.setAttribute('aria-checked', String(isDone));
}

list.addEventListener('click', (e) =&gt; {
  const item = e.target.closest('.todo-item');
  if (!item || !list.contains(item)) return;
  toggleItem(item);
});

// Keyboard support: Space/Enter
list.addEventListener('keydown', (e) =&gt; {
  const item = e.target.closest('.todo-item');
  if (!item) return;

  const key = e.key.toLowerCase();
  if (key === ' ' || key === 'enter') {
    e.preventDefault(); // prevent page scroll with Space
    toggleItem(item);
  }
});

💡 Why event delegation?

If the list grows (items added or removed), you don’t need to attach new listeners. You listen once on the parent list and handle the targets dynamically. Less memory, less code, more scalability.

📦 Variation: dedicated “Complete” button

If you prefer an explicit control for each item, add a button inside the <li>.

&lt;ul id="todo-list"&gt;
  &lt;li class="todo-item" role="checkbox" aria-checked="false" tabindex="0"&gt;
    Buy coffee beans
    &lt;button class="mark-btn" aria-label="Mark as complete"&gt;Complete&lt;/button&gt;
  &lt;/li&gt;
&lt;/ul&gt;
list.addEventListener('click', (e) =&gt; {
  const btn = e.target.closest('.mark-btn');
  if (!btn) return;

  const item = btn.closest('.todo-item');
  if (!item) return;

  item.classList.toggle('done');
  const isDone = item.classList.contains('done');
  item.setAttribute('aria-checked', String(isDone));

  // Update button text/label
  btn.textContent = isDone ? 'Undo' : 'Complete';
  btn.setAttribute('aria-label', isDone ? 'Mark as not complete' : 'Mark as complete');
});

🗃️ (Optional) Persist state with localStorage

Want completed status to remain after a page refresh? Serialize states to localStorage.

const STORAGE_KEY = 'todoStates-v1';

function saveState() {
  const states = [];
  list.querySelectorAll('.todo-item').forEach((li) =&gt; {
    states.push({ text: li.textContent.trim(), done: li.classList.contains('done') });
  });
  localStorage.setItem(STORAGE_KEY, JSON.stringify(states));
}

function loadState() {
  const raw = localStorage.getItem(STORAGE_KEY);
  if (!raw) return;
  try {
    const states = JSON.parse(raw);
    const items = list.querySelectorAll('.todo-item');
    states.forEach((st, i) =&gt; {
      const li = items[i];
      if (!li) return;
      li.classList.toggle('done', !!st.done);
      li.setAttribute('aria-checked', String(!!st.done));
    });
  } catch (e) {
    console.warn('Storage parse error', e);
  }
}

list.addEventListener('click', (e) =&gt; {
  if (e.target.closest('.todo-item')) {
    toggleItem(e.target.closest('.todo-item'));
    saveState();
  }
});
list.addEventListener('keydown', (e) =&gt; {
  if (e.key === ' ' || e.key.toLowerCase() === 'enter') {
    toggleItem(e.target.closest('.todo-item'));
    saveState();
  }
});

document.addEventListener('DOMContentLoaded', loadState);

🚫 Common mistakes

  • Overwriting className instead of using classList.toggle() (can remove other classes unintentionally).
  • Forgetting to update aria-checked — the interface looks fine visually but isn’t accessible.
  • Attaching a listener to each <li> individually (not scalable).
  • Handling only clicks and ignoring keyboard events (Space/Enter).

🧪 Exercises

  1. Dual class: in addition to .done, add a .highlight class when an item is focused (keyboard) and remove it on blur.
  2. Dynamic counter: display “N completed out of M” and update it on each toggle.
  3. Filters: add three buttons “All / Active / Completed” that filter items using CSS classes (show/hide).
  4. Unique IDs: generate a unique ID for each item and persist state in localStorage using a {id: done} map instead of index matching.

📌 Key takeaways

  • element.classList.toggle('done') is the fastest way to mark an item as complete.
  • Event delegation keeps code lightweight and scalable.
  • Accessibility: always update aria-checked and handle Space/Enter.
  • localStorage can persist state across page reloads.

Post Views: 272

Condividi:

  • Condividi su Facebook (Si apre in una nuova finestra) Facebook
  • Condividi su X (Si apre in una nuova finestra) X
Javascript Coding

Navigazione articoli

Previous post
Next post

Francesco

My name is Francesco Boschi, originally from Italy and currently based in the United States. For over twenty years, I’ve worked as a manager and consultant across diverse sectors — from education and cultural institutions to the food industry — developing skills in operational management, strategic consulting, and complex problem-solving. In recent years, I’ve combined this experience with a strong passion for software development, creating custom tools designed to simplify workflows and meet real business needs.

Relocating to the U.S. marks the beginning of a new chapter: a personal and professional decision driven by the desire to be close to my son and to embrace new challenges in a different environment. Today, my goal is to turn my experience into meaningful solutions, blending strategic vision with technical expertise to help people and organizations work more effectively.

I enjoy moving between different worlds, adapting tools and approaches to people and contexts. I bring leadership, flexibility, attention to detail, analytical thinking, and a strong problem-solving mindset — along with a deep curiosity to learn and grow. Above all, I believe in sharing: I’m always eager to offer my experience to support the growth of others.

Related Posts

Coding

Coding Step 11.4 – Rust – Form Zero to “WoW” – Clear, Formatted Output

Posted on 12 Ottobre 202512 Ottobre 2025

How a simple BMI calculator in Rust turns clear console output into a moment of “wow.” Three versions, one idea: precision is a form of respect.

Condividi:

  • Condividi su Facebook (Si apre in una nuova finestra) Facebook
  • Condividi su X (Si apre in una nuova finestra) X
Read More
Coding

Coding – Step 9 – JavaScript from Scratch – Build Your First Interactive App: The Shopping List

Posted on 22 Luglio 202520 Agosto 2025

Introduction JavaScript is the language that brings web pages to life. It’s everywhere: websites, apps, games, automation scripts, and even robots. In this first article, we’ll go beyond the classic alert() — we’ll build a real, functional mini-app using nothing but HTML + CSS + JavaScript. What We’ll Build We’ll…

Condividi:

  • Condividi su Facebook (Si apre in una nuova finestra) Facebook
  • Condividi su X (Si apre in una nuova finestra) X
Read More
Coding

ArchPilot – Step 3 – Project & Budget Tracker (ERP)

Posted on 30 Novembre 202530 Novembre 2025

A cross-framework showcase of the Project & Budget Tracker module, demonstrating how different technologies handle the same ERP workflow with clarity, adaptability, and architectural insight.

Condividi:

  • Condividi su Facebook (Si apre in una nuova finestra) Facebook
  • Condividi su X (Si apre in una nuova finestra) X
Read More

Iscriviti alla nostra Newsletter

🤞 Let's keep in touch

We do not send spam! Read our Privacy policy for more information.

Controlla la tua casella di posta o la cartella spam per confermare la tua iscrizione

Cerca nel sito

©2026 This is my space, where experience meets the will to start over. | WordPress Theme by SuperbThemes