Halaman Warung Melati kini lengkap isinya, tetapi pemesanan masih harus lewat telepon. Bagian terakhir menambahkan form pemesanan mini di dalam main: pengunjung mengisi nama, memilih menu, menentukan jumlah porsi, lalu menerima dialog ringkasan beserta total harganya. Validasi dasarnya diserahkan ke browser lewat atribut native, sedangkan JavaScript hanya menghitung total dan menampilkan dialog.
Menambahkan Form Pemesanan #
File restoran-pesan.html pada folder bagian ini melengkapi restoran-styling.html dengan satu tag script di head serta section baru berisi form:
<script src="pesan.js" defer></script>
<!-- baris 12-16: header hero; baris 18-57: section menu dan kontak -->
<section id="pesan">
<h2>Pesan Antar</h2>
<form id="form-pesan">
<div>
<label for="nama">Nama</label>
<input type="text" id="nama" name="nama" required>
</div>
<div>
<label for="menu-pilihan">Menu</label>
<select id="menu-pilihan" name="menu" required>
<option value="">-- Pilih menu --</option>
<option value="25000">Nasi Timbel Ayam - Rp25.000</option>
<option value="20000">Soto Bandung - Rp20.000</option>
<option value="28000">Pepes Ikan Mas - Rp28.000</option>
<option value="8000">Es Cincau Hijau - Rp8.000</option>
</select>
</div>
<div>
<label for="jumlah">Jumlah porsi</label>
<input type="number" id="jumlah" name="jumlah" min="1" max="20" value="1" required>
</div>
<button type="submit">Pesan Sekarang</button>
</form>
</section>Setiap bidang berpasangan dengan label lewat atribut for dan id, sehingga ketukan label juga memfokuskan bidangnya. Atribut required mewajibkan nama dan menu terisi, sedangkan min dan max membatasi jumlah porsi 1 sampai 20. Option pertama bernilai kosong berperan sebagai penanda “belum dipilih”; karena select-nya required, browser menolak submit selama opsi itu yang terpilih. Nilai pada setiap option menu lainnya adalah harga dalam rupiah, dan nilai itulah yang dibaca JavaScript nanti.
Setelah form, satu elemen dialog berisi tiga p ringkasan — nama, menu, total — serta tombol Tutup menunggu diisi skrip. Browser menolak pengiriman dan menampilkan pesan bawaan selama ada isian yang tidak memenuhi syarat; kita tidak menulis satu baris validasi pun.
Skrip Perhitungan Total #
Interaksinya digerakkan oleh file pesan.js yang berdampingan dengan halamannya:
const formPesan = document.querySelector("#form-pesan");
const dialogPesan = document.querySelector("#dialog-pesan");
const tombolTutup = document.querySelector("#tombol-tutup");
formPesan.addEventListener("submit", function (event) {
event.preventDefault();
const pilihanMenu = formPesan.elements.menu;
const namaMenu = pilihanMenu.options[pilihanMenu.selectedIndex].text;
const hargaMenu = Number(pilihanMenu.value);
const jumlahPorsi = Number(formPesan.elements.jumlah.value);
const total = hargaMenu * jumlahPorsi;
document.querySelector("#ringkasan-nama").textContent = formPesan.elements.nama.value;
document.querySelector("#ringkasan-menu").textContent = namaMenu;
document.querySelector("#ringkasan-total").textContent = "Rp" + total.toLocaleString("id-ID");
dialogPesan.showModal();
});
tombolTutup.addEventListener("click", function () {
dialogPesan.close();
});Output yang Dihasilkan:
Saat form dikirim dengan isian belum lengkap:
- Browser menampilkan pesan bawaan, misalnya "Isi bidang ini"
Saat form dikirim dengan isian lengkap (Siti, Soto Bandung, 3 porsi):
- Dialog "Ringkasan Pesanan" muncul di tengah layar di atas lapisan gelap
- Tertulis: Atas nama Siti, Menu Soto Bandung - Rp20.000, Total Rp60.000
Saat tombol "Tutup" atau Esc ditekan:
- Dialog tertutup dan halaman kembali normalMari kita bedah skrip tersebut:
- Baris 1-3:
querySelectormengambil referensi form, elemen dialog, dan tombol penutup. - Baris 5-7: listener submit memanggil
preventDefault()sehingga browser tidak benar-benar mengirim form; pengiriman hanya memicu perhitungan. - Baris 9-13:
formPesan.elements.menumengambil select; teks opsi terpilih menjadi nama menu, sedangkanNumber()mengubah nilai harganya menjadi angka, lalu total dihitung dikali jumlah porsi. - Baris 15-17: tiga elemen ringkasan diisi lewat
textContent;toLocaleString("id-ID")memberi pemisah ribuan sehingga 60000 tampil sebagai Rp60.000. - Baris 19-25:
showModal()menampilkan dialog sebagai modal dengan fokus di dalamnya, dan tombol Tutup memanggilclose()untuk menutupnya kembali.
Pemeriksaan Hasil Tahap Ini #
- Buka restoran-pesan.html, lalu tekan “Pesan Sekarang” dengan form kosong: browser menampilkan pesan bawaan pada bidang nama.
- Isi nama Siti, pilih menu, isi jumlah 3, lalu kirim: dialog muncul dengan total Rp60.000.
- Tutup dialog lewat tombol “Tutup”, buka kembali, lalu tekan Esc; keduanya menutup dialog tanpa menghalangi keyboard.
- Jalankan tests/cek-struktur.html, lalu lengkapi butir yang tersisa hingga 10 dari 10.
Sampai di sini proyek Website Restoran tuntas: hero yang menggugah, menu dan kontak informatif, tampilan hangat, serta pemesanan berfungsi. Proyek berikutnya, Halaman Dokumentasi, memakai pola serupa untuk keperluan lain: navigasi banyak halaman dan pencarian sederhana.
Referensi resmi untuk pendalaman:
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
pesan.js
Unduh berkasconst formPesan = document.querySelector("#form-pesan");
const dialogPesan = document.querySelector("#dialog-pesan");
const tombolTutup = document.querySelector("#tombol-tutup");
formPesan.addEventListener("submit", function (event) {
event.preventDefault();
const pilihanMenu = formPesan.elements.menu;
const namaMenu = pilihanMenu.options[pilihanMenu.selectedIndex].text;
const hargaMenu = Number(pilihanMenu.value);
const jumlahPorsi = Number(formPesan.elements.jumlah.value);
const total = hargaMenu * jumlahPorsi;
document.querySelector("#ringkasan-nama").textContent = formPesan.elements.nama.value;
document.querySelector("#ringkasan-menu").textContent = namaMenu;
document.querySelector("#ringkasan-total").textContent = "Rp" + total.toLocaleString("id-ID");
dialogPesan.showModal();
});
tombolTutup.addEventListener("click", function () {
dialogPesan.close();
});
restoran-pesan.html
Unduh berkas<!doctype html>
<html lang="id">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Warung Melati menyajikan masakan rumahan Sunda di Bandung setiap hari.">
<title>Warung Melati - Masakan Rumahan Sunda</title>
<link rel="stylesheet" href="../styles/style.css">
<script src="pesan.js" defer></script>
</head>
<body>
<header class="hero">
<img src="../assets/logo-resto.svg" alt="Logo Warung Melati" width="72" height="72">
<h1>Warung Melati</h1>
<p>Masakan rumahan Sunda, disajikan hangat sejak 2015</p>
</header>
<main>
<section id="menu">
<h2>Menu Hari Ini</h2>
<dl class="menu">
<dt>Nasi Timbel Ayam</dt>
<dd>Nasi putih hangat dengan ayam goreng, tahu, tempe, sambal, dan lalapan. Rp25.000</dd>
<dt>Soto Bandung</dt>
<dd>Kuah bening berisi irisan daging sapi, kacang tanah, dan emping. Rp20.000</dd>
<dt>Pepes Ikan Mas</dt>
<dd>Ikan mas berbumbu kuning yang dikukus dalam daun pisang. Rp28.000</dd>
<dt>Es Cincau Hijau</dt>
<dd>Cincau hijau dengan kuah gula merah dan santan. Rp8.000</dd>
</dl>
</section>
<section id="kontak">
<h2>Kontak dan Jam Buka</h2>
<address>
Jl. Melati No. 10, Bandung<br>
Telepon: <a href="tel:+6281200001111">0812-0000-1111</a><br>
Surel: <a href="mailto:[email protected]">[email protected]</a>
</address>
<table>
<caption>Jam buka</caption>
<thead>
<tr>
<th scope="col">Hari</th>
<th scope="col">Jam Operasional</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Senin - Jumat</th>
<td>08.00 - 20.00</td>
</tr>
<tr>
<th scope="row">Sabtu - Minggu</th>
<td>07.00 - 21.00</td>
</tr>
</tbody>
</table>
</section>
<section id="pesan">
<h2>Pesan Antar</h2>
<form id="form-pesan">
<div>
<label for="nama">Nama</label>
<input type="text" id="nama" name="nama" required>
</div>
<div>
<label for="menu-pilihan">Menu</label>
<select id="menu-pilihan" name="menu" required>
<option value="">-- Pilih menu --</option>
<option value="25000">Nasi Timbel Ayam - Rp25.000</option>
<option value="20000">Soto Bandung - Rp20.000</option>
<option value="28000">Pepes Ikan Mas - Rp28.000</option>
<option value="8000">Es Cincau Hijau - Rp8.000</option>
</select>
</div>
<div>
<label for="jumlah">Jumlah porsi</label>
<input type="number" id="jumlah" name="jumlah" min="1" max="20" value="1" required>
</div>
<button type="submit">Pesan Sekarang</button>
</form>
<dialog id="dialog-pesan">
<h2>Ringkasan Pesanan</h2>
<p>Atas nama: <strong id="ringkasan-nama"></strong></p>
<p>Menu: <span id="ringkasan-menu"></span></p>
<p>Total: <strong id="ringkasan-total"></strong></p>
<button type="button" id="tombol-tutup">Tutup</button>
</dialog>
</section>
</main>
<footer>
<p>© 2025 Warung Melati</p>
</footer>
</body>
</html>