Belajar Javascript Melalui 30+ Proyek Menarik untuk Pemula!

Jelajahi dunia Javascript dengan 30+ proyek menarik! Tingkatkan keterampilan coding Anda dan raih keahlian baru dengan belajar sambil berkreasi! Klik sekarang!

By WGS INDONESIA
4.9/4.9
Indonesia
Rp 43,750.00 GRATIS
E-COURSE banner with text and icons representing Artificial Intelligence and video learning

Detail Pembelajaran

Belajar Javascript Melalui 30+ Proyek Menarik untuk Pemula!
  • Belajar Javascript, Proyek Pemula, Pemrograman Web, Pengembangan Software, Tutorial Coding

Baca Online

Belajar Javascript Melalui 30+ Proyek Menarik untuk Pemula!

Daftar Isi

  1. Pengantar Javascript dan Cara Belajar Proyek
  2. Persiapan Lingkungan dan Tools
  3. Proyek 1-5: Dasar Interaksi dan Manipulasi DOM
  4. Proyek 6-10: Event Handling dan Form Validation
  5. Proyek 11-15: API dan Fetch Data
  6. Proyek 16-20: Penyimpanan Data dan LocalStorage
  7. Proyek 21-25: Animasi dan Efek Visual
  8. Proyek 26-30+: Mini Game dan Project Kompleks
  9. Sumber Belajar dan Channel Youtube Rekomendasi

1. Pengantar Javascript dan Cara Belajar Proyek

Javascript adalah bahasa pemrograman yang berjalan di browser dan memungkinkan kita membuat website interaktif. Belajar melalui proyek nyata adalah cara terbaik untuk memahami konsep dan meningkatkan kemampuan coding.

Dalam ebook ini, Anda akan belajar lebih dari 30 proyek menarik yang disusun bertahap mulai dari dasar hingga tingkat lanjut. Setiap proyek dilengkapi dengan penjelasan step-by-step dan source code lengkap.

Ilustrasi belajar Javascript dengan laptop dan kode program di layar

2. Persiapan Lingkungan dan Tools

Untuk mulai belajar, siapkan beberapa tools berikut:

  • Browser modern: Google Chrome, Firefox, atau Edge.
  • Editor kode: Visual Studio Code (VSCode) sangat direkomendasikan.
  • Live Server Extension: Untuk menjalankan proyek secara langsung di browser.
  • Console Developer Tools: Gunakan fitur console di browser untuk debugging.

Anda juga bisa menggunakan platform online seperti CodePen , JSFiddle , atau StackBlitz untuk mencoba kode tanpa instalasi.

Screenshot Visual Studio Code dengan ekstensi Live Server aktif

3. Proyek 1-5: Dasar Interaksi dan Manipulasi DOM

Pada tahap awal, kita belajar cara mengakses dan memanipulasi elemen HTML menggunakan Javascript.

Proyek 1: Menampilkan Pesan Alert

Buat file index.html dan tambahkan kode berikut:

<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Proyek 1 - Alert</title>
</head>
<body>
  <script>
    alert("Halo, selamat belajar Javascript!");
  </script>
</body>
</html>

Proyek 2: Mengubah Teks dengan DOM

Buat file index.html dengan isi:

<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Proyek 2 - DOM Manipulation</title>
</head>
<body>
  <h1 id="judul">Judul Awal</h1>
  <button onclick="ubahTeks()">Ubah Judul</button>

  <script>
    function ubahTeks() {
      document.getElementById("judul").textContent = "Judul Telah Diubah!";
    }
  </script>
</body>
</html>

Proyek 3: Menambahkan Elemen Baru

Menambahkan elemen paragraf baru ke dalam halaman:

<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Proyek 3 - Tambah Elemen</title>
</head>
<body>
  <div id="container">
    <h2>Daftar Buah</h2>
  </div>
  <button onclick="tambahParagraf()">Tambah Buah</button>

  <script>
    function tambahParagraf() {
      const container = document.getElementById("container");
      const p = document.createElement("p");
      p.textContent = "Apel";
      container.appendChild(p);
    }
  </script>
</body>
</html>

Proyek 4: Mengubah Style CSS dengan Javascript

Mengubah warna teks dan latar belakang:

<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Proyek 4 - Ubah Style</title>
</head>
<body>
  <h1 id="judul">Judul Dinamis</h1>
  <button onclick="ubahStyle()">Ubah Warna</button>

  <script>
    function ubahStyle() {
      const judul = document.getElementById("judul");
      judul.style.color = "white";
      judul.style.backgroundColor = "blue";
      judul.style.padding = "10px";
      judul.style.borderRadius = "8px";
    }
  </script>
</body>
</html>

Proyek 5: Menangani Event Keyboard

Menampilkan pesan saat tombol keyboard ditekan:

<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Proyek 5 - Event Keyboard</title>
</head>
<body>
  <h2>Tekan tombol keyboard apa saja</h2>
  <p id="output">Tombol yang ditekan: -</p>

  <script>
    document.addEventListener("keydown", function(event) {
      document.getElementById("output").textContent = "Tombol yang ditekan: " + event.key;
    });
  </script>
</body>
</html>
Ilustrasi manipulasi DOM dan event handling Javascript

4. Proyek 6-10: Event Handling dan Form Validation

Pada tahap ini, kita belajar menangani event lebih kompleks dan membuat validasi form sederhana.

Proyek 6: Menangani Klik Button dengan Event Listener

<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Proyek 6 - Event Listener</title>
</head>
<body>
  <button id="btn" class="px-4 py-2 bg-blue-600 text-white rounded">Klik Aku</button>
  <p id="pesan"></p>

  <script>
    const btn = document.getElementById("btn");
    btn.addEventListener("click", function() {
      document.getElementById("pesan").textContent = "Button telah diklik!";
    });
  </script>
</body>
</html>

Proyek 7: Validasi Form Sederhana

<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Proyek 7 - Validasi Form</title>
</head>
<body>
  <form id="form" action="#">
    <label for="email">Email:</label>
    <input type="email" id="email" name="email" required>
    <button type="submit">Kirim</button>
  </form>
  <p id="error" style="color:red;"></p>

  <script>
    const form = document.getElementById("form");
    const error = document.getElementById("error");

    form.addEventListener("submit", function(e) {
      const email = form.email.value;
      if (!email.includes("@")) {
        e.preventDefault();
        error.textContent = "Email harus mengandung '@'";
      } else {
        error.textContent = "";
      }
    });
  </script>
</body>
</html>

Proyek 8: Toggle Dark Mode

<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Proyek 8 - Dark Mode</title>
  <style>
    body.dark {
      background-color: #121212;
      color: #eee;
    }
  </style>
</head>
<body>
  <button id="toggle" class="px-4 py-2 bg-gray-800 text-white rounded">Toggle Dark Mode</button>

  <script>
    const btn = document.getElementById("toggle");
    btn.addEventListener("click", () => {
      document.body.classList.toggle("dark");
    });
  </script>
</body>
</html>

Proyek 9: Membuat Countdown Timer

<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Proyek 9 - Countdown Timer</title>
</head>
<body>
  <h2>Countdown: <span id="timer">10</span> detik</h2>

  <script>
    let count = 10;
    const timer = document.getElementById("timer");

    const interval = setInterval(() => {
      count--;
      timer.textContent = count;
      if (count === 0) {
        clearInterval(interval);
        alert("Waktu habis!");
      }
    }, 1000);
  </script>
</body>
</html>

Proyek 10: Membuat Modal Popup

<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Proyek 10 - Modal Popup</title>
  <style>
    #modal {
      display: none;
      position: fixed;
      top: 0; left: 0; right: 0; bottom: 0;
      background: rgba(0,0,0,0.5);
      justify-content: center;
      align-items: center;
    }
    #modalContent {
      background: white;
      padding: 20px;
      border-radius: 8px;
      max-width: 300px;
      text-align: center;
    }
  </style>
</head>
<body>
  <button id="openBtn" class="px-4 py-2 bg-blue-600 text-white rounded">Buka Modal</button>

  <div id="modal">
    <div id="modalContent">
      <p>Ini adalah modal popup!</p>
      <button id="closeBtn" class="px-3 py-1 bg-red-600 text-white rounded">Tutup</button>
    </div>
  </div>

  <script>
    const modal = document.getElementById("modal");
    const openBtn = document.getElementById("openBtn");
    const closeBtn = document.getElementById("closeBtn");

    openBtn.addEventListener("click", () => {
      modal.style.display = "flex";
    });

    closeBtn.addEventListener("click", () => {
      modal.style.display = "none";
    });

    window.addEventListener("click", (e) => {
      if (e.target === modal) {
        modal.style.display = "none";
      }
    });
  </script>
</body>
</html>
Ilustrasi event handling dan validasi form Javascript

5. Proyek 11-15: API dan Fetch Data

Belajar mengambil data dari API menggunakan fetch dan menampilkannya di halaman.

Proyek 11: Fetch Data dari API Publik

<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Proyek 11 - Fetch API</title>
</head>
<body>
  <h2>Daftar User</h2>
  <ul id="userList"></ul>

  <script>
    fetch("https://jsonplaceholder.typicode.com/users")
      .then(response => response.json())
      .then(data => {
        const userList = document.getElementById("userList");
        data.forEach(user => {
          const li = document.createElement("li");
          li.textContent = user.name + " (" + user.email + ")";
          userList.appendChild(li);
        });
      })
      .catch(error => {
        console.error("Error:", error);
      });
  </script>
</body>
</html>

Proyek 12: Menampilkan Gambar dari API

<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Proyek 12 - Gambar API</title>
</head>
<body>
  <h2>Random Dog Image</h2>
  <img id="dogImage" alt="Gambar anjing acak dari API" width="300" />
  <button id="btn" class="px-4 py-2 bg-blue-600 text-white rounded">Muat Ulang</button>

  <script>
    const img = document.getElementById("dogImage");
    const btn = document.getElementById("btn");

    function loadImage() {
      fetch("https://dog.ceo/api/breeds/image/random")
        .then(res => res.json())
        .then(data => {
          img.src = data.message;
        });
    }

    btn.addEventListener("click", loadImage);
    loadImage();
  </script>
</body>
</html>

Proyek 13: Mengirim Data dengan POST

Contoh mengirim data ke API (dummy) menggunakan fetch POST:

<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Proyek 13 - POST Data</title>
</head>
<body>
  <button id="sendBtn" class="px-4 py-2 bg-green-600 text-white rounded">Kirim Data</button>
  <p id="response"></p>

  <script>
    const btn = document.getElementById("sendBtn");
    const responseP = document.getElementById("response");

    btn.addEventListener("click", () => {
      fetch("https://jsonplaceholder.typicode.com/posts", {
        method: "POST",
        headers: {
          "Content-Type": "application/json"
        },
        body: JSON.stringify({
          title: "foo",
          body: "bar",
          userId: 1
        })
      })
      .then(res => res.json())
      .then(data => {
        responseP.textContent = "Response ID: " + data.id;
      });
    });
  </script>
</body>
</html>

Proyek 14: Menampilkan Data dengan Async/Await

<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Proyek 14 - Async Await</title>
</head>
<body>
  <h2>Daftar Post</h2>
  <ul id="postList"></ul>

  <script>
    async function fetchPosts() {
      try {
        const res = await fetch("https://jsonplaceholder.typicode.com/posts");
        const posts = await res.json();
        const postList = document.getElementById("postList");
        posts.slice(0, 5).forEach(post => {
          const li = document.createElement("li");
          li.textContent = post.title;
          postList.appendChild(li);
        });
      } catch (error) {
        console.error(error);
      }
    }
    fetchPosts();
  </script>
</body>
</html>

Proyek 15: Menangani Error Fetch

<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Proyek 15 - Error Handling</title>
</head>
<body>
  <h2>Fetch dengan Error Handling</h2>
  <ul id="dataList"></ul>
  <p id="errorMsg" style="color:red;"></p>

  <script>
    async function fetchData() {
      try {
        const res = await fetch("https://jsonplaceholder.typicode.com/invalidurl");
        if (!res.ok) throw new Error("Network response was not ok");
        const data = await res.json();
        const dataList = document.getElementById("dataList");
        data.forEach(item => {
          const li = document.createElement("li");
          li.textContent = item.title;
          dataList.appendChild(li);
        });
      } catch (error) {
        document.getElementById("errorMsg").textContent = "Terjadi kesalahan: " + error.message;
      }
    }
    fetchData();
  </script>
</body>
</html>
Ilustrasi fetch API dan async await Javascript

6. Proyek 16-20: Penyimpanan Data dan LocalStorage

Belajar menyimpan data di browser menggunakan LocalStorage dan SessionStorage.

Proyek 16: Menyimpan dan Mengambil Data LocalStorage

<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Proyek 16 - LocalStorage</title>
</head>
<body>
  <input type="text" id="inputNama" placeholder="Masukkan nama">
  <button id="saveBtn" class="px-4 py-2 bg-green-600 text-white rounded">Simpan</button>
  <p id="savedName">Nama tersimpan: -</p>

  <script>
    const inputNama = document.getElementById("inputNama");
    const saveBtn = document.getElementById("saveBtn");
    const savedName = document.getElementById("savedName");

    saveBtn.addEventListener("click", () => {
      const nama = inputNama.value;
      if (nama) {
        localStorage.setItem("namaUser", nama);
        savedName.textContent = "Nama tersimpan: " + nama;
        inputNama.value = "";
      }
    });

    window.onload = () => {
      const nama = localStorage.getItem("namaUser");
      if (nama) {
        savedName.textContent = "Nama tersimpan: " + nama;
      }
    };
  </script>
</body>
</html>

Proyek 17: Menghapus Data LocalStorage

<button id="hapusBtn" class="px-4 py-2 bg-red-600 text-white rounded">Hapus Nama</button>

<script>
  const hapusBtn = document.getElementById("hapusBtn");
  hapusBtn.addEventListener("click", () => {
    localStorage.removeItem("namaUser");
    document.getElementById("savedName").textContent = "Nama tersimpan: -";
  });
</script>

Proyek 18: Menggunakan SessionStorage

<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Proyek 18 - SessionStorage</title>
</head>
<body>
  <input type="text" id="inputSession" placeholder="Masukkan data session">
  <button id="saveSessionBtn" class="px-4 py-2 bg-green-600 text-white rounded">Simpan Session</button>
  <p id="sessionData">Data session: -</p>

  <script>
    const inputSession = document.getElementById("inputSession");
    const saveSessionBtn = document.getElementById("saveSessionBtn");
    const sessionData = document.getElementById("sessionData");

    saveSessionBtn.addEventListener("click", () => {
      const data = inputSession.value;
      if (data) {
        sessionStorage.setItem("dataSession", data);
        sessionData.textContent = "Data session: " + data;
        inputSession.value = "";
      }
    });

    window.onload = () => {
      const data = sessionStorage.getItem("dataSession");
      if (data) {
        sessionData.textContent = "Data session: " + data;
      }
    };
  </script>
</body>
</html>

Proyek 19: Menyimpan Array di LocalStorage

<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Proyek 19 - Array LocalStorage</title>
</head>
<body>
  <button id="saveArrayBtn" class="px-4 py-2 bg-green-600 text-white rounded">Simpan Array</button>
  <button id="loadArrayBtn" class="px-4 py-2 bg-blue-600 text-white rounded">Tampilkan Array</button>
  <ul id="listArray"></ul>

  <script>
    const saveArrayBtn = document.getElementById("saveArrayBtn");
    const loadArrayBtn = document.getElementById("loadArrayBtn");
    const listArray = document.getElementById("listArray");

    const buah = ["Apel", "Jeruk", "Mangga"];

    saveArrayBtn.addEventListener("click", () => {
      localStorage.setItem("buahList", JSON.stringify(buah));
      alert("Array tersimpan!");
    });

    loadArrayBtn.addEventListener("click", () => {
      const data = localStorage.getItem("buahList");
      if (data) {
        const arr = JSON.parse(data);
        listArray.innerHTML = "";
        arr.forEach(item => {
          const li = document.createElement("li");
          li.textContent = item;
          listArray.appendChild(li);
        });
      }
    });
  </script>
</body>
</html>

Proyek 20: Membuat To-Do List dengan LocalStorage

Contoh sederhana membuat aplikasi to-do list yang menyimpan data di localStorage.

<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Proyek 20 - To-Do List</title>
  <style>
    ul { list-style-type: none; padding: 0; }
    li { padding: 5px 0; }
  </style>
</head>
<body>
  <h2>To-Do List</h2>
  <input type="text" id="taskInput" placeholder="Tambah tugas">
  <button id="addTaskBtn" class="px-3 py-1 bg-green-600 text-white rounded">Tambah</button>
  <ul id="taskList"></ul>

  <script>
    const taskInput = document.getElementById("taskInput");
    const addTaskBtn = document.getElementById("addTaskBtn");
    const taskList = document.getElementById("taskList");

    function loadTasks() {
      const tasks = JSON.parse(localStorage.getItem("tasks")) || [];
      taskList.innerHTML = "";
      tasks.forEach((task, index) => {
        const li = document.createElement("li");
        li.textContent = task;
        li.style.cursor = "pointer";
        li.addEventListener("click", () => {
          tasks.splice(index, 1);
          localStorage.setItem("tasks", JSON.stringify(tasks));
          loadTasks();
        });
        taskList.appendChild(li);
      });
    }

    addTaskBtn.addEventListener("click", () => {
      const task = taskInput.value.trim();
      if (task) {
        const tasks = JSON.parse(localStorage.getItem("tasks")) || [];
        tasks.push(task);
        localStorage.setItem("tasks", JSON.stringify(tasks));
        taskInput.value = "";
        loadTasks();
      }
    });

    window.onload = loadTasks;
  </script>
</body>
</html>
Ilustrasi penyimpanan data di browser menggunakan LocalStorage

7. Proyek 21-25: Animasi dan Efek Visual

Belajar membuat animasi dan efek visual menggunakan Javascript dan CSS.

Proyek 21: Animasi Bergerak dengan setInterval

<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Proyek 21 - Animasi Bergerak</title>
  <style>
    #kotak {
      width: 50px;
      height: 50px;
      background-color: red;
      position: relative;
    }
  </style>
</head>
<body>
  <div id="kotak"></div>

  <script>
    const kotak = document.getElementById("kotak");
    let posisi = 0;
    const interval = setInterval(() => {
      if (posisi >= 300) {
        clearInterval(interval);
      } else {
        posisi += 5;
        kotak.style.left = posisi + "px";
      }
    }, 30);
  </script>
</body>
</html>

Proyek 22: Efek Fade In dan Fade Out

<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Proyek 22 - Fade In Out</title>
  <style>
    #box {
      width: 200px;
      height: 100px;
      background-color: teal;
      opacity: 0;
      transition: opacity 1s;
    }
    #box.show {
      opacity: 1;
    }
  </style>
</head>
<body>
  <button id="toggleBtn" class="px-4 py-2 bg-blue-600 text-white rounded">Toggle Fade</button>
  <div id="box"></div>

  <script>
    const box = document.getElementById("box");
    const toggleBtn = document.getElementById("toggleBtn");

    toggleBtn.addEventListener("click", () => {
      box.classList.toggle("show");
    });
  </script>
</body>
</html>

Proyek 23: Membuat Slider Gambar Sederhana

<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Proyek 23 - Slider Gambar</title>
  <style>
    #slider {
      width: 300px;
      height: 200px;
      overflow: hidden;
      position: relative;
    }
    #slider img {
      width: 100%;
      height: 100%;
      position: absolute;
      opacity: 0;
      transition: opacity 0.5s;
    }
    #slider img.active {
      opacity: 1;
      position: relative;
    }
  </style>
</head>
<body>
  <div id="slider">
    <img src="https://placehold.co/300x200/png?text=Gambar+1" alt="Gambar 1" class="active">
    <img src="https://placehold.co/300x200/png?text=Gambar+2" alt="Gambar 2">
    <img src="https://placehold.co/300x200/png?text=Gambar+3" alt="Gambar 3">
  </div>

  <script>
    const images = document.querySelectorAll("#slider img");
    let current = 0;

    setInterval(() => {
      images[current].classList.remove("active");
      current = (current + 1) % images.length;
      images[current].classList.add("active");
    }, 3000);
  </script>
</body>
</html>

Proyek 24: Membuat Tooltip Sederhana

<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Proyek 24 - Tooltip</title>
  <style>
    .tooltip {
      position: relative;
      display: inline-block;
      cursor: pointer;
    }
    .tooltip .tooltiptext {
      visibility: hidden;
      width: 140px;
      background-color: black;
      color: #fff;
      text-align: center;
      border-radius: 6px;
      padding: 5px 0;
      position: absolute;
      z-index: 1;
      bottom: 125%;
      left: 50%;
      margin-left: -70px;
      opacity: 0;
      transition: opacity 0.3s;
    }
    .tooltip:hover .tooltiptext {
      visibility: visible;
      opacity: 1;
    }
  </style>
</head>
<body>
  <div class="tooltip">Arahkan mouse ke saya
    <span class="tooltiptext">Ini adalah tooltip!</span>
  </div>
</body>
</html>

Proyek 25: Membuat Loading Spinner

<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Proyek 25 - Loading Spinner</title>
  <style>
    .spinner {
      border: 8px solid #f3f3f3;
      border-top: 8px solid #3498db;
      border-radius: 50%;
      width: 60px;
      height: 60px;
      animation: spin 1s linear infinite;
      margin: 20px auto;
    }
    @keyframes spin {
      0% { transform: rotate(0deg);}
      100% { transform: rotate(360deg);}
    }
  </style>
</head>
<body>
  <div class="spinner"></div>
</body>
</html>
Ilustrasi animasi dan efek visual Javascript

8. Proyek 26-30+: Mini Game dan Project Kompleks

Pada tahap ini, kita akan membuat mini game dan project yang menggabungkan berbagai konsep Javascript.

Proyek 26: Game Tebak Angka

<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Proyek 26 - Tebak Angka</title>
</head>
<body>
  <h2>Game Tebak Angka 1-100</h2>
  <input type="number" id="inputAngka" placeholder="Masukkan angka" min="1" max="100">
  <button id="tebakBtn" class="px-3 py-1 bg-blue-600 text-white rounded">Tebak</button>
  <p id="hasil"></p>

  <script>
    const angkaRahasia = Math.floor(Math.random() * 100) + 1;
    const inputAngka = document.getElementById("inputAngka");
    const tebakBtn = document.getElementById("tebakBtn");
    const hasil = document.getElementById("hasil");

    tebakBtn.addEventListener("click", () => {
      const tebakan = Number(inputAngka.value);
      if (!tebakan || tebakan < 1 || tebakan > 100) {
        hasil.textContent = "Masukkan angka antara 1 sampai 100!";
        return;
      }
      if (tebakan === angkaRahasia) {
        hasil.textContent = "Selamat! Tebakan Anda benar.";
      } else if (tebakan < angkaRahasia) {
        hasil.textContent = "Tebakan terlalu kecil.";
      } else {
        hasil.textContent = "Tebakan terlalu besar.";
      }
    });
  </script>
</body>
</html>

Proyek 27: Game Tic Tac Toe

Contoh sederhana game Tic Tac Toe dengan Javascript:

<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Proyek 27 - Tic Tac Toe</title>
  <style>
    #board {
      display: grid;
      grid-template-columns: repeat(3, 100px);
      grid-gap: 5px;
      margin-bottom: 10px;
    }
    .cell {
      width: 100px;
      height: 100px;
      background: #eee;
      font-size: 3rem;
      display: flex;
      justify-content: center;
      align-items: center;
      cursor: pointer;
      user-select: none;
    }
    #status {
      font-weight: bold;
    }
  </style>
</head>
<body>
  <h2>Game Tic Tac Toe</h2>
  <div id="board">
    <div class="cell" data-index="0"></div>
    <div class="cell" data-index="1"></div>
    <div class="cell" data-index="2"></div>
    <div class="cell" data-index="3"></div>
    <div class="cell" data-index="4"></div>
    <div class="cell" data-index="5"></div>
    <div class="cell" data-index="6"></div>
    <div class="cell" data-index="7"></div>
    <div class="cell" data-index="8"></div>
  </div>
  <button id="resetBtn" class="px-4 py-2 bg-blue-600 text-white rounded">Reset</button>
  <p id="status">Giliran: X</p>

  <script>
    const board = document.getElementById("board");
    const cells = document.querySelectorAll(".cell");
    const status = document.getElementById("status");
    const resetBtn = document.getElementById("resetBtn");

    let currentPlayer = "X";
    let gameActive = true;
    let boardState = Array(9).fill(null);

    function checkWin() {
      const winPatterns = [
        [0,1,2],[3,4,5],[6,7,8],
        [0,3,6],[1,4,7],[2,5,8],
        [0,4,8],[2,4,6]
      ];
      return winPatterns.some(pattern => {
        const [a,b,c] = pattern;
        return boardState[a] && boardState[a] === boardState[b] && boardState[a] === boardState[c];
      });
    }

    function checkDraw() {
      return boardState.every(cell => cell !== null);
    }

    function handleClick(e) {
      const index = e.target.getAttribute("data-index");
      if (!gameActive || boardState[index]) return;

      boardState[index] = currentPlayer;
      e.target.textContent = currentPlayer;

      if (checkWin()) {
        status.textContent = "Pemenang: " + currentPlayer;
        gameActive = false;
        return;
      }

      if (checkDraw()) {
        status.textContent = "Seri!";
        gameActive = false;
        return;
      }

      currentPlayer = currentPlayer === "X" ? "O" : "X";
      status.textContent = "Giliran: " + currentPlayer;
    }

    cells.forEach(cell => cell.addEventListener("click", handleClick));

    resetBtn.addEventListener("click", () => {
      boardState.fill(null);
      cells.forEach(cell => cell.textContent = "");
      currentPlayer = "X";
      gameActive = true;
      status.textContent = "Giliran: " + currentPlayer;
    });
  </script>
</body>
</html>

Proyek 28: Kalkulator Sederhana

<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Proyek 28 - Kalkulator</title>
  <style>
    input, button {
      font-size: 1.2rem;
      margin: 5px;
    }
  </style>
</head>
<body>
  <h2>Kalkulator Sederhana</h2>
  <input type="number" id="num1" placeholder="Angka 1">
  <input type="number" id="num2" placeholder="Angka 2">
  <br>
  <button id="tambah">+</button>
  <button id="kurang">-</button>
  <button id="kali">*</button>
  <button id="bagi">/</button>
  <p id="hasil">Hasil: </p>

  <script>
    const num1 = document.getElementById("num1");
    const num2 = document.getElementById("num2");
    const hasil = document.getElementById("hasil");

    function hitung(operator) {
      const a = parseFloat(num1.value);
      const b = parseFloat(num2.value);
      if (isNaN(a) || isNaN(b)) {
        hasil.textContent = "Hasil: Masukkan angka valid";
        return;
      }
      let res;
      switch(operator) {
        case '+': res = a + b; break;
        case '-': res = a - b; break;
        case '*': res = a * b; break;
        case '/': res = b !== 0 ? a / b : "Tidak bisa dibagi 0"; break;
      }
      hasil.textContent = "Hasil: " + res;
    }

    document.getElementById("tambah").addEventListener("click", () => hitung('+'));
    document.getElementById("kurang").addEventListener("click", () => hitung('-'));
    document.getElementById("kali").addEventListener("click", () => hitung('*'));
    document.getElementById("bagi").addEventListener("click", () => hitung('/'));
  </script>
</body>
</html>

Proyek 29: Stopwatch Sederhana

<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Proyek 29 - Stopwatch</title>
  <style>
    #display {
      font-size: 2rem;
      margin-bottom: 10px;
    }
  </style>
</head>
<body>
  <h2>Stopwatch</h2>
  <div id="display">00:00:00</div>
  <button id="startBtn" class="px-3 py-1 bg-green-600 text-white rounded">Start</button>
  <button id="stopBtn" class="px-3 py-1 bg-red-600 text-white rounded">Stop</button>
  <button id="resetBtn" class="px-3 py-1 bg-gray-600 text-white rounded">Reset</button>

  <script>
    let timer;
    let seconds = 0;

    const display = document.getElementById("display");
    const startBtn = document.getElementById("startBtn");
    const stopBtn = document.getElementById("stopBtn");
    const resetBtn = document.getElementById("resetBtn");

    function formatTime(sec) {
      const hrs = Math.floor(sec / 3600);
      const mins = Math.floor((sec % 3600) / 60);
      const secs = sec % 60;
      return `${hrs.toString().padStart(2,'0')}:${mins.toString().padStart(2,'0')}:${secs.toString().padStart(2,'0')}`;
    }

    startBtn.addEventListener("click", () => {
      if (!timer) {
        timer = setInterval(() => {
          seconds++;
          display.textContent = formatTime(seconds);
        }, 1000);
      }
    });

    stopBtn.addEventListener("click", () => {
      clearInterval(timer);
      timer = null;
    });

    resetBtn.addEventListener("click", () => {
      clearInterval(timer);
      timer = null;
      seconds = 0;
      display.textContent = "00:00:00";
    });
  </script>
</body>
</html>

Proyek 30: Quiz Interaktif Sederhana

Contoh quiz pilihan ganda interaktif dengan Javascript:

<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Proyek 30 - Quiz Interaktif</title>
  <style>
    .option {
      margin: 5px 0;
      cursor: pointer;
      padding: 5px;
      border: 1px solid #ccc;
      border-radius: 4px;
    }
    .option:hover {
      background-color: #f0f0f0;
    }
  </style>
</head>
<body>
  <h2>Quiz Javascript</h2>
  <div id="quiz"></div>
  <button id="submitBtn" class="px-4 py-2 bg-blue-600 text-white rounded mt-4">Submit</button>
  <p id="result"></p>

  <script>
    const quizData = [
      {
        question: "Apa tipe data untuk angka di Javascript?",
        options: ["string", "number", "boolean", "object"],
        answer: "number"
      },
      {
        question: "Fungsi apa yang digunakan untuk menampilkan pesan di console?",
        options: ["alert()", "prompt()", "console.log()", "document.write()"],
        answer: "console.log()"
      }
    ];

    const quizDiv = document.getElementById("quiz");
    const result = document.getElementById("result");
    const submitBtn = document.getElementById("submitBtn");

    quizData.forEach((item, index) => {
      const qDiv = document.createElement("div");
      const qTitle = document.createElement("p");
      qTitle.textContent = (index + 1) + ". " + item.question;
      qDiv.appendChild(qTitle);

      item.options.forEach(option => {
        const label = document.createElement("label");
        label.classList.add("option");
        const input = document.createElement("input");
        input.type = "radio";
        input.name = "q" + index;
        input.value = option;
        label.appendChild(input);
        label.appendChild(document.createTextNode(option));
        qDiv.appendChild(label);
      });

      quizDiv.appendChild(qDiv);
    });

    submitBtn.addEventListener("click", () => {
      let score = 0;
      quizData.forEach((item, index) => {
        const selected = document.querySelector('input[name="q' + index + '"]:checked');
        if (selected && selected.value === item.answer) {
          score++;
        }
      });
      result.textContent = "Skor Anda: " + score + " dari " + quizData.length;
    });
  </script>
</body>
</html>
Ilustrasi mini game dan project kompleks Javascript

9. Sumber Belajar dan Channel Youtube Rekomendasi

Berikut beberapa sumber belajar dan channel YouTube yang sangat membantu untuk menguasai Javascript:

Ilustrasi berbagai sumber belajar online Javascript dengan icon buku dan laptop

Edukasi Terkait