Web Development
HTML Course
CSS Course
JavaScript Course
PHP Course
Python Course
SQL Course
SEO Course

Project: Image Changer with DOM and Events

This project uses DOM manipulation and events to change the displayed image when the user clicks a button.

Change the Image

let imageIndex = 1;

function changeImage() {
  imageIndex = imageIndex === 1 ? 2 : 1;
  const img = document.getElementById("image");
  img.src = `images/img${imageIndex}.png`;
}
Image

Project: Character Counter with Validation

This project uses DOM manipulation and events to count the characters entered in a text field and validate if the limit has been exceeded.

const textarea = document.getElementById("comment");
const counter = document.getElementById("counter");
const error = document.getElementById("error");
const limit = 100;

textarea.addEventListener("input", () => {
  const length = textarea.value.length;
  counter.textContent = `${length} / ${limit} characters`;

  if (length > limit) {
    error.textContent = "You have exceeded the character limit!";
    counter.style.color = "red";
  } else {
    error.textContent = "";
    counter.style.color = "black";
  }
});

function submitComment() {
  const length = textarea.value.length;
  if (length > limit) {
    alert("The comment is too long!");
  } else if (length === 0) {
    alert("The comment cannot be empty!");
  } else {
    alert("Comment submitted!");
    textarea.value = "";
    counter.textContent = `0 / ${limit} characters`;
    counter.style.color = "black";
  }
}

Write a Comment

0 / 100 characters


Project: To-Do List App

This project creates a simple to-do list application that allows the user to add, check off, and delete tasks.

Add a Task

function addTask() {
  const input = document.getElementById("taskInput");
  const value = input.value.trim();

  if (value === "") {
    alert("Please enter a task!");
    return;
  }

  const li = document.createElement("li");
  li.textContent = value;
  li.style.margin = "8px 0";
  li.style.cursor = "pointer";

  li.onclick = function () {
    li.style.textDecoration = li.style.textDecoration === "line-through" ? "none" : "line-through";
    li.style.color = li.style.textDecoration === "line-through" ? "gray" : "black";
  };

  const deleteBtn = document.createElement("button");
  deleteBtn.textContent = "Delete";
  deleteBtn.style.marginLeft = "10px";
  deleteBtn.style.padding = "4px 8px";
  deleteBtn.onclick = function () {
    li.remove();
  };

  li.appendChild(deleteBtn);
  document.getElementById("taskList").appendChild(li);
  input.value = "";
}

Project: Secret Message Encoder

This project uses JavaScript functions to encode and decode secret messages using simple methods like Base64.

Encode a Message

Decode a Message

function encodeMessage() {
  const input = document.getElementById("messageInput").value;
  if (input.trim() === "") {
    alert("Write a message before encoding!");
    return;
  }
  const encoded = btoa(input);
  document.getElementById("encodedMessage").textContent = `Encoded: ${encoded}`;
}

function decodeMessage() {
  const input = document.getElementById("encodedMessageInput").value;
  try {
    const decoded = atob(input);
    document.getElementById("decodedMessage").textContent = `Decoded: ${decoded}`;
  } catch (e) {
    alert("The input is not a valid Base64 message!");
  }
}

Singleton Pattern

const Singleton = (function () {
  let instance;

  function createInstance() {
    return { message: "This is the unique instance." };
  }

  return {
    getInstance: function () {
      if (!instance) {
        instance = createInstance();
      }
      return instance;
    }
  };
})();

const inst1 = Singleton.getInstance();
const inst2 = Singleton.getInstance();
console.log(inst1 === inst2);

Ensures that there is only one instance of an object and provides a global point of access.

Factory Pattern

function AnimalFactory(type) {
  if (type === "dog") {
    return { sound: () => "Woof!" };
  } else if (type === "cat") {
    return { sound: () => "Meow!" };
  }
  return { sound: () => "Unknown!" };
}

const animal = AnimalFactory("cat");
console.log(animal.sound());

Creates objects without specifying the exact class — useful for flexible instantiation.

Observer Pattern

class Subject {
  constructor() {
    this.observers = [];
  }

  add(observer) {
    this.observers.push(observer);
  }

  notify(message) {
    this.observers.forEach(obs => obs.update(message));
  }
}

class Observer {
  update(message) {
    console.log("Received:", message);
  }
}

const subject = new Subject();
const obs1 = new Observer();
subject.add(obs1);
subject.notify("Hello!");

Allows an object to notify other objects when its state changes.

Module Pattern and IIFE

This project demonstrates how to use an Immediately Invoked Function Expression (IIFE) to create a module with private variables and public methods.

Counter Module

const Counter = (function () {
  let value = 0;

  function updateDisplay() {
    document.getElementById("counterValue").textContent = `Value: ${value}`;
  }

  return {
    increment: function () {
      value++;
      updateDisplay();
    },
    decrement: function () {
      value--;
      updateDisplay();
    }
  };
})();

Value: 0

MVC Pattern Introduction

This project demonstrates the Model-View-Controller principle in JavaScript, an architecture that separates application logic into three distinct components:

Counter with MVC Architecture

// 🔹 MODEL: manages the data
const Model = {
  value: 0,
  increment: function () {
    this.value++;
  },
  decrement: function () {
    this.value--;
  },
  getValue: function () {
    return this.value;
  }
};

// 🔹 VIEW: displays the data
const View = {
  display: function (value) {
    document.getElementById("view").textContent = `Value: ${value}`;
  }
};

// 🔹 CONTROLLER: connects user actions to model and view
const Controller = {
  increment: function () {
    Model.increment(); // modify the data
    View.display(Model.getValue()); // update the interface
  },
  decrement: function () {
    Model.decrement();
    View.display(Model.getValue());
  }
};

// 🔹 Initialization: display the initial value
View.display(Model.getValue());

Value: 0

Top