HTML CSS JavaScript

Belum masuk. Progresmu tidak tersimpan.

Masuk
  • Bab 3 dari 7
  • 30 menit
  • 1 latihan kode
  • 4 soal kuis

HTML ke JavaScript: Tag Script dan DOM

Di bab ini (9 bagian)
  1. Tujuan
  2. Tag <script>: dua bentuk
  3. Posisi pemuatan: kenapa bisa null
  4. DOM: halaman berubah jadi pohon objek
  5. Memilih elemen
  6. Mengubah teks dan atribut
  7. Membuat dan menyisipkan elemen
  8. Kesalahan umum
  9. Rangkuman

Tujuan bab ini

  • Memasang JavaScript ke HTML dengan <script> inline maupun src, di posisi yang aman.
  • Membedakan script biasa, defer, async, dan type="module".
  • Memahami DOM sebagai pohon objek yang diubah JavaScript.
  • Memilih elemen, mengubah teks dan atribut, serta membuat dan menyisipkan elemen baru.

Tag <script>: dua bentuk

Seperti CSS, JavaScript bisa ditulis langsung di HTML atau di file terpisah.

<!-- inline: kodenya di dalam tag -->
<script>
  console.log("Halo dari inline");
</script>

<!-- external: kodenya di file lain -->
<script src="js/script.js"></script>

Untuk proyek sungguhan, pilih external dengan alasan yang sama seperti CSS: bisa dipakai banyak halaman, di-cache browser, dan HTML tetap bersih. Dua aturan kecil yang sering bikin bingung:

  • Tag <script> wajib ditutup dengan </script>, walau isinya kosong. <script src="..." /> tidak dikenali sebagai tag tertutup.
  • Kalau tag punya src, kode yang ditulis di antara tag pembuka dan penutup diabaikan. Pilih salah satu.

Path di src mengikuti aturan yang sama dengan href di <link>: relatif terhadap file HTML yang membuka.

Posisi pemuatan: kenapa bisa null

Browser membaca HTML dari atas ke bawah sambil membangun halaman. Saat bertemu <script> biasa (tanpa atribut tambahan), browser berhenti, mengunduh, menjalankan script itu, baru lanjut membaca HTML. Ini disebut parser-blocking.

Akibatnya terlihat di contoh ini:

<head>
  <script>
    const judul = document.querySelector("#judul");
    console.log(judul); // null
  </script>
</head>
<body>
  <h1 id="judul">Halo</h1>
</body>

Console mencetak null, karena saat script berjalan, <h1> belum dibuat. Baris berikutnya seperti judul.textContent = "..." langsung error: Cannot set properties of null. Kodemu benar, waktunya yang salah.

Empat posisi tag script dan risikonya

Ada beberapa cara memperbaikinya:

CaraKapan dijalankanCocok untuk
<script src> sebelum </body>Setelah semua elemen di atasnya terbentukCara paling sederhana
<script defer src> di <head>Diunduh paralel, dijalankan setelah HTML selesai dibaca, sesuai urutanPilihan terbaik untuk kebanyakan script
<script async src>Dijalankan begitu selesai diunduh, urutan tidak dijaminScript mandiri seperti analitik
<script type="module" src>Otomatis berperilaku seperti deferKode modern yang memakai import/export

Penjelasan lebih detail:

  • defer membuat browser mengunduh file sambil terus membaca HTML. Script baru dijalankan setelah seluruh dokumen selesai di-parse, tepat sebelum event DOMContentLoaded. Kalau ada beberapa script defer, urutannya dijaga sesuai urutan di HTML. Atribut defer hanya berlaku untuk script dengan src. Di script inline, defer diabaikan.
  • async juga mengunduh paralel, tapi menjalankan script begitu filenya siap, bisa sebelum HTML selesai, dan urutan antar script async tidak dijamin. Jangan pakai untuk script yang memanipulasi elemen atau yang bergantung pada script lain.
  • type="module" menandai file sebagai ES module (standar sejak ES2015). Module otomatis ditunda seperti defer, berjalan dalam strict mode, dan variabel tingkat atasnya tidak menjadi global. Module juga bisa memakai import untuk memecah kode ke beberapa file. Detail sintaks modul ada di kelas JavaScript.

Alternatif lain, kode dibungkus dengan event:

<script>
  document.addEventListener("DOMContentLoaded", () => {
    document.querySelector("#judul").textContent = "Siap!";
  });
</script>

Walau script ini ditaruh di <head>, isinya baru jalan setelah struktur halaman siap, jadi judul berubah jadi "Siap!".

DOM: halaman berubah jadi pohon objek

Saat membaca HTML, browser tidak menyimpannya sebagai teks. Ia membangun DOM (Document Object Model): pohon objek di memori. Paling atas ada document, di bawahnya <html>, lalu cabang <head> dan <body>, dan seterusnya sampai teks terkecil.

Poin yang sering disalahpahami: JavaScript tidak mengedit file .html. JavaScript mengedit pohon di memori. Kalau kamu muat ulang halaman, pohon dibangun ulang dari file asli, dan semua perubahan dari JavaScript hilang. Karena itu, di DevTools tab Elements kamu melihat DOM yang sekarang (sudah diubah JS), sedangkan View Page Source menampilkan file asli dari server.

Setiap node di pohon itu adalah objek dengan properti (textContent, id, className) dan method (append, remove, addEventListener).

Memilih elemen

Polanya selalu sama: pilih, simpan ke variabel, lalu ubah.

const judul = document.getElementById("judul");    // tanpa #
const tombolPertama = document.querySelector(".tombol");
const semuaTombol = document.querySelectorAll(".tombol");
MethodHasilKalau tidak ketemu
getElementById("x")Satu elemen dengan id="x"null
querySelector(selector)Elemen pertama yang cocok dengan selector CSSnull
querySelectorAll(selector)Semua yang cocok, berupa NodeListNodeList kosong

Kabar baiknya, querySelector memakai selector yang sama persis dengan CSS: #id, .class, [data-status="habis"], nav a. Ilmu selector dari bab sebelumnya langsung terpakai. NodeList dari querySelectorAll bisa di-loop dengan forEach atau for...of.

Mengubah teks dan atribut

judul.textContent = "Selamat Datang";       // teks murni
judul.innerHTML = "<em>Halo</em> Dunia";    // ditafsirkan sebagai HTML

const logo = document.querySelector("img.logo");
logo.setAttribute("src", "img/logo-baru.png");
logo.alt = "Logo Ruang Materi";
  • textContent memperlakukan isinya sebagai teks biasa. Kalau isinya <b>, yang tampil adalah tulisan <b>, bukan huruf tebal. Ini pilihan paling aman, terutama untuk input pengguna.
  • innerHTML menafsirkan isinya sebagai HTML. Berguna, tapi jangan pernah diisi teks dari pengguna, karena bisa disisipi script jahat (serangan XSS).
  • setAttribute(nama, nilai) mengubah atribut apa pun. Banyak atribut juga punya properti langsung seperti el.id, el.href, img.src.

Membuat dan menyisipkan elemen

const daftar = document.querySelector("#daftar");
const item = document.createElement("li");
item.textContent = "Belajar DOM";
item.dataset.id = "4";
daftar.append(item);

Hasilnya: daftar #daftar mendapat item baru "Belajar DOM" di posisi paling bawah, dengan atribut data-id="4". Elemen dari createElement belum tampil sampai disisipkan ke pohon lewat append (atau appendChild, prepend, before, after). Untuk menghapus elemen, panggil el.remove().

Kesalahan umum

  • Script di <head> tanpa defer, lalu heran querySelector menghasilkan null.
  • Menulis getElementById("#judul"). Method ini menerima id tanpa #. Sebaliknya, querySelector butuh #.
  • Mengira querySelector mengembalikan semua elemen. Ia hanya mengambil yang pertama. Pakai querySelectorAll lalu loop.
  • Memakai async untuk script yang mengubah DOM, sehingga kadang jalan kadang error tergantung kecepatan unduhan.
  • Mengisi innerHTML dengan input pengguna. Pakai textContent.
  • Lupa append setelah createElement, jadi elemen baru tidak pernah muncul.

Rangkuman

  • <script> bisa inline atau src. Kalau ada src, isi di dalam tag diabaikan.
  • Script biasa memblokir parsing. Taruh sebelum </body>, atau pakai defer di <head>. async untuk script mandiri, type="module" otomatis tertunda.
  • DOM adalah pohon objek di memori. JavaScript mengubah pohon itu, bukan file HTML.
  • Pilih elemen dengan getElementById, querySelector, atau querySelectorAll, yang memakai selector CSS.
  • Ubah isi dengan textContent (aman) atau innerHTML (hati-hati), atribut dengan setAttribute, lalu buat elemen baru dengan createElement dan append.

Selesaikan bab ini

  1. 1. Baca materi
  2. 2. Latihan kode (1)
  3. 3. Kuis (4 soal)

Latihan kode: Isi daftar materi lewat DOM

HTML-nya punya daftar kosong. Lengkapi JavaScript supaya daftar terisi dari array materi:

  1. Pilih #daftar dan #jumlah, simpan ke variabel.
  2. Hapus li.kosong dengan remove().
  3. Untuk setiap materi, buat <li> dengan createElement, isi textContent, beri data-id mulai dari "1", lalu append ke daftar.
  4. Ubah teks #jumlah jadi "3 materi" memakai materi.length.
  5. Ubah href milik #sumber jadi https://developer.mozilla.org dengan setAttribute.

Cek pemahaman

  1. 1Apa yang dicetak `console.log`?

    <head>
      <script>
        const judul = document.querySelector("#judul");
        console.log(judul);
      </script>
    </head>
    <body>
      <h1 id="judul">Halo</h1>
    </body>
  2. 2Atribut apa yang membuat script diunduh paralel lalu dijalankan setelah HTML selesai di-parse, dengan urutan antar script tetap terjaga?

  3. 3Kalau tag `<script>` punya atribut `src`, kode yang ditulis di antara tag pembuka dan penutupnya diabaikan.

  4. 4Item apa saja yang tampil di daftar setelah script berjalan?

    <ul id="daftar">
      <li>A</li>
      <li>B</li>
    </ul>
    <script>
      const li = document.createElement("li");
      li.textContent = "C";
      document.querySelector("#daftar").append(li);
      document.querySelector("li").remove();
    </script>