Tujuan Program
Tujuan Program |
Tujuan Program ini adalah untuk membuat soal ujian dengan menggunakan input.
Pengguna dapat memasukkan pertanyaan, pilihan jawaban, memilih jawaban yang
benar, serta menentukan waktu pengerjaan setiap soal. Setelah mengisi
formulir, pengguna dapat menghasilkan daftar soal ujian yang ditampilkan dalam
tabel. Setiap soal dilengkapi dengan tombol jawab untuk mengecek jawaban yang
telah dipilih, tombol hapus untuk menghapus soal, serta timer yang menghitung
mundur waktu pengerjaan setiap soal.
Tampilan Awal Program |
Dropdown untuk memilih jawaban yang tepat |
Setelah klik "Generate Exam" |
Tampilan setelah menjawab soal |
Source Code
Source code program ini bisa dilihat di Repository berikut: Source Code Mini Project
Github Repository: Main Repository
Kalian bisa mencoba program ini secara online dengan mengakses link berikut: Github Pages
Github Repository: Main Repository
Kalian bisa mencoba program ini secara online dengan mengakses link berikut: Github Pages
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Mini Project 3</title> <link rel="stylesheet" href="style.css"> </head> <body> <h1>Exam Generator</h1> <hr> <form> <div> <label>Question:</label> <input type="text" id="inputQuestion" placeholder="Ex: Apa itu Javascript" required> <br> </div> <div> <label>Options:</label> <input type="text" id="inputOption" placeholder="Pisah opsi dengan koma (Max 4)" required> </div> <div> <label>Correct Answer:</label> <select name="question" id="selectCorrectOption"> <option>Select Correct Answer</option> </select> </div> <div> <label>Time:</label> <input type="number" id="inputTime" placeholder="Ex: 5" required> <span> Menit</span> <br> </div> <div> <button onclick="generateQuestion()">Generate Exam</button> </div> </form> <hr> <table id="tableExam"> <tr> <th>No</th> <th colspan="4">Question</th> <th>Time</th> <th>Option</th> </tr> </table> <script src="script.js"></script> </body> </html>
script.js
let question = document.getElementById("inputQuestion"); let option = document.getElementById("inputOption"); let timeLimit = document.getElementById("inputTime"); let tableExam = document.getElementById("tableExam"); let optionSelect = document.getElementById("selectCorrectOption"); // ---------------------------------------------------------------------------- // function stringToArray(inputString) { let array = inputString.split(',', 4); for (let i = 0; i < array.length; i++) { array[i] = array[i].trim(); } return array; } function addAnswerToSelection() { let optionArray = stringToArray(option.value); optionSelect.innerHTML = ""; for (let i = 0; i < optionArray.length; i++) { if (optionArray[i]) { let optionElement = document.createElement("option"); optionElement.setAttribute("value", optionArray[i]); let optionTextNode = document.createTextNode(optionArray[i]); optionElement.appendChild(optionTextNode); optionSelect.appendChild(optionElement); } } } option.addEventListener('input', addAnswerToSelection); // ---------------------------------------------------------------------------- // function createButton(textContent, onclickFunction) { let button = document.createElement("button"); button.textContent = textContent; button.setAttribute("onclick", onclickFunction); return button; } function isChecked(input) { return input && input.value; } // ---------------------------------------------------------------------------- // function generateQuestion() { event.preventDefault(); if (isChecked(question) && isChecked(option) && isChecked(timeLimit)) { let tbody = document.createElement("tbody"); let trTop = document.createElement("tr"); let trBottom = document.createElement("tr"); let nomorUrut = document.createTextNode(tableExam.childElementCount); let questionText = document.createTextNode(question.value); let timeLimitText = document.createTextNode(timeLimit.value); let deleteButton = createButton("Hapus", "deleteQuestion(this)"); let answerButton = createButton("Jawab", "submitAnswer(this)"); let buttonCell = document.createElement("div"); buttonCell.appendChild(deleteButton); buttonCell.appendChild(answerButton); let tableArrayTop = [ nomorUrut, questionText, timeLimitText, buttonCell ]; for (let i = 0; i < tableArrayTop.length; i++) { let td = document.createElement("td"); td.appendChild(tableArrayTop[i]); if (i == 0 || i == 2 || i == 3) { td.setAttribute("rowspan", "2"); } if (i == 1) { td.setAttribute("colspan", "4"); } trTop.appendChild(td); } tbody.appendChild(trTop); let optionArray = stringToArray(option.value); let letterLabels = ['A', 'B', 'C', 'D']; for (let i = 0; i < optionArray.length; i++) { let td = document.createElement("td"); let radio = document.createElement("input"); radio.setAttribute("type", "radio"); radio.setAttribute("name", String(tableExam.childElementCount)); radio.setAttribute("value", optionArray[i]); let mainContainer = document.createElement("div"); mainContainer.setAttribute("style", "display: flex;"); let optionText = document.createTextNode(letterLabels[i] + '. ' + optionArray[i]); mainContainer.append(radio); mainContainer.append(optionText); td.appendChild(mainContainer); trBottom.appendChild(td); } tbody.appendChild(trBottom); tableExam.appendChild(tbody); let timeLimitCell = trTop.children[2]; let timeLimitMinutes = Number(timeLimit.value); tbody.timerInterval = countdownTimer(timeLimitMinutes, timeLimitCell); } else { alert("Form tidak boleh kosong") } } // ---------------------------------------------------------------------------- // function countdownTimer(minute, tableCell) { tableCell.textContent = minute + ":00"; let second = minute * 60; let interval = setInterval(function() { let remainingMinutes = Math.floor(second / 60); let remainingSeconds = second % 60; let formattedSecond; if (remainingSeconds < 10) { formattedSecond = "0" + remainingSeconds; } else { formattedSecond = remainingSeconds; } tableCell.textContent = remainingMinutes + ":" + formattedSecond; second--; if (second < 0) { clearInterval(interval); tableCell.textContent = "Waktu Habis"; tableCell.closest("tbody").style.color = "red"; } }, 1000); return interval; } function submitAnswer(button) { let selectedOption = optionSelect.value; let tbody = button.closest("tbody"); let inputs = tbody.getElementsByTagName("input"); let radioButton = []; for (let i = 0; i < inputs.length; i++) { if (inputs[i].type === "radio") { radioButton.push(inputs[i]); } } let answeredQuestion = false; for (let i = 0; i < radioButton.length; i++) { if (radioButton[i].checked) { answeredQuestion = true; if (radioButton[i].value === selectedOption) { tbody.style.backgroundColor = "lawngreen"; } else { tbody.style.backgroundColor = "lightsalmon"; } } } if (answeredQuestion) { radioButton.forEach(radio => { radio.disabled = true; }); clearInterval(tbody.timerInterval); } } function deleteQuestion(button) { let tbody = button.closest("tbody"); if (tbody) { tableExam.removeChild(tbody); updateNomorUrut(); } } function updateNomorUrut() { let tbody = tableExam.getElementsByTagName("tbody"); for (let i = 0; i < tbody.length; i++) { tbody[i + 1].children[0].children[0].textContent = i + 1; } }
Pembahasan
1. Buat Struktur HTML
Buat struktur HTML seperti pada source code. Bagian HTML berfungsi
menampilkan form input yang memungkinkan pengguna untuk membuat soal
ujian. Form ini terdiri dari input teks untuk pertanyaan, input teks untuk
pilihan jawaban yang dipisahkan oleh koma, dropdown untuk memilih jawaban
yang benar, dan input angka untuk menentukan waktu pengerjaan setiap soal.
Terdapat pula tombol "Generate Exam" untuk menghasilkan daftar soal ujian
yang akan ditampilkan dalam tabel di bawahnya.
2. Tambahkan Javascript
Tambahkan tag <script> pada HTML untuk menambahkan Javascript. Bila Javascript berada di
file terpisah (external), tambahkan attribute 'src'. Kode seperti pada
source code script.js.
Pembahasan Javascript Source Code
1. Inisialisasi variabel, dapatkan elemen HTML
berdasarkan id dan simpan dalam variabel.
let question = document.getElementById("inputQuestion"); let option = document.getElementById("inputOption"); let timeLimit = document.getElementById("inputTime"); let tableExam = document.getElementById("tableExam"); let optionSelect = document.getElementById("selectCorrectOption");
2. Function stringToArray(inputString), digunakan untuk
mengonversi string input pilihan jawaban menjadi array. Pada dasarnya,
function ini membagi string tersebut menjadi beberapa elemen array dengan
menggunakan koma sebagai delimiter, dengan maksimal empat elemen.
Setiap elemen array yang dihasilkan kemudian di-trim untuk
menghilangkan spasi di awal dan akhir, memastikan tidak ada spasi yang
tidak diinginkan.
function stringToArray(inputString) { let array = inputString.split(',', 4); for (let i = 0; i < array.length; i++) { array[i] = array[i].trim(); } return array; }
3. Function addAnswerToSelection(), Function ini
mengonversi input pilihan jawaban yang dipisahkan oleh koma menjadi array,
kemudian menambahkan setiap pilihan jawaban ke dalam dropdown untuk
memilih jawaban yang benar. Ini dilakukan dengan membuat elemen
<option> untuk setiap opsi jawaban dan menambahkannya ke
dalam elemen dropdown. Kemudian Event listener bertanggung jawab
untuk mengaktifkan function addAnswerToSelection() setiap kali
terjadi input pada field pilihan jawaban.
function addAnswerToSelection() { let optionArray = stringToArray(option.value); optionSelect.innerHTML = ""; for (let i = 0; i < optionArray.length; i++) { if (optionArray[i]) { let optionElement = document.createElement("option"); optionElement.setAttribute("value", optionArray[i]); let optionTextNode = document.createTextNode(optionArray[i]); optionElement.appendChild(optionTextNode); optionSelect.appendChild(optionElement); } } } option.addEventListener('input', addAnswerToSelection);
4. Function createButton(textContent, onclickFunction), Function createButton(textContent, onclickFunction) adalah
sebuah utilitas yang digunakan untuk membuat elemen tombol HTML dengan
teks dan fungsi klik yang ditentukan. Kemudian juga ada function isChecked(input) untuk validasi pengecekan isi input.
function createButton(textContent, onclickFunction) { let button = document.createElement("button"); button.textContent = textContent; button.setAttribute("onclick", onclickFunction); return button; } function isChecked(input) { return input && input.value; }
5. Function generateQuestion(), Function
generateQuestion() bertanggung jawab untuk membuat dan menambahkan
soal ujian ke dalam tabel. Saat tombol "Generate Exam" ditekan, function
ini memvalidasi bahwa semua input yang diperlukan, seperti pertanyaan,
pilihan jawaban, dan waktu pengerjaan, telah diisi. Jika valid, function
ini membuat baris baru dalam tabel yang mencakup nomor urut, pertanyaan,
waktu pengerjaan, dan pilihan jawaban dalam bentuk radio button. Selain
itu, function ini juga memulai timer mundur untuk setiap soal ujian. Jika
input tidak lengkap, function akan menampilkan pesan peringatan.
function generateQuestion() { event.preventDefault(); if (isChecked(question) && isChecked(option) && isChecked(timeLimit)) { let tbody = document.createElement("tbody"); let trTop = document.createElement("tr"); let trBottom = document.createElement("tr"); let nomorUrut = document.createTextNode(tableExam.childElementCount); let questionText = document.createTextNode(question.value); let timeLimitText = document.createTextNode(timeLimit.value); let deleteButton = createButton("Hapus", "deleteQuestion(this)"); let answerButton = createButton("Jawab", "submitAnswer(this)"); let buttonCell = document.createElement("div"); buttonCell.appendChild(deleteButton); buttonCell.appendChild(answerButton); let tableArrayTop = [ nomorUrut, questionText, timeLimitText, buttonCell ]; for (let i = 0; i < tableArrayTop.length; i++) { let td = document.createElement("td"); td.appendChild(tableArrayTop[i]); if (i == 0 || i == 2 || i == 3) { td.setAttribute("rowspan", "2"); } if (i == 1) { td.setAttribute("colspan", "4"); } trTop.appendChild(td); } tbody.appendChild(trTop); let optionArray = stringToArray(option.value); let letterLabels = ['A', 'B', 'C', 'D']; for (let i = 0; i < optionArray.length; i++) { let td = document.createElement("td"); let radio = document.createElement("input"); radio.setAttribute("type", "radio"); radio.setAttribute("name", String(tableExam.childElementCount)); radio.setAttribute("value", optionArray[i]); let mainContainer = document.createElement("div"); mainContainer.setAttribute("style", "display: flex;"); let optionText = document.createTextNode(letterLabels[i] + '. ' + optionArray[i]); mainContainer.append(radio); mainContainer.append(optionText); td.appendChild(mainContainer); trBottom.appendChild(td); } tbody.appendChild(trBottom); tableExam.appendChild(tbody); let timeLimitCell = trTop.children[2]; let timeLimitMinutes = Number(timeLimit.value); tbody.timerInterval = countdownTimer(timeLimitMinutes, timeLimitCell); } else { alert("Form tidak boleh kosong") } }
6. Function countdownTimer(minute, tableCell), Function
countdownTimer(minute, tableCell) berfungsi untuk membuat dan
mengelola timer mundur untuk setiap soal ujian dengan durasi waktu yang
ditentukan dalam menit. Timer ini ditampilkan dalam format menit:detik
pada sel tabel yang sesuai. Function menggunakan interval JavaScript untuk
mengupdate timer setiap detik dan menghentikan interval ketika waktu
habis. Selain itu, jika waktu habis, warna sel tabel akan diubah menjadi
merah sebagai indikator bahwa waktu pengerjaan telah berakhir.
function countdownTimer(minute, tableCell) { tableCell.textContent = minute + ":00"; let second = minute * 60; let interval = setInterval(function() { let remainingMinutes = Math.floor(second / 60); let remainingSeconds = second % 60; let formattedSecond; if (remainingSeconds < 10) { formattedSecond = "0" + remainingSeconds; } else { formattedSecond = remainingSeconds; } tableCell.textContent = remainingMinutes + ":" + formattedSecond; second--; if (second < 0) { clearInterval(interval); tableCell.textContent = "Waktu Habis"; tableCell.closest("tbody").style.color = "red"; } }, 1000); return interval; }
7. Function submitAnswer(button), Function
submitAnswer(button) digunakan untuk menanggapi aksi pengguna saat
tombol "Jawab" pada setiap soal ujian ditekan. Function ini memeriksa
jawaban yang dipilih oleh pengguna, memberikan umpan balik visual dengan
mengubah warna sel tabel, menonaktifkan radio button setelah jawaban
diberikan, dan menghentikan timer. Jika pengguna menjawab dengan benar,
sel tabel akan berwarna hijau; jika jawaban salah, sel tabel berwarna
merah. Selain itu, radio button akan dinonaktifkan agar pengguna tidak
dapat mengubah jawaban setelah memberikannya.
function submitAnswer(button) { let selectedOption = optionSelect.value; let tbody = button.closest("tbody"); let inputs = tbody.getElementsByTagName("input"); let radioButton = []; for (let i = 0; i < inputs.length; i++) { if (inputs[i].type === "radio") { radioButton.push(inputs[i]); } } let answeredQuestion = false; for (let i = 0; i < radioButton.length; i++) { if (radioButton[i].checked) { answeredQuestion = true; if (radioButton[i].value === selectedOption) { tbody.style.backgroundColor = "lawngreen"; } else { tbody.style.backgroundColor = "lightsalmon"; } } } if (answeredQuestion) { radioButton.forEach(radio => { radio.disabled = true; }); clearInterval(tbody.timerInterval); } }
8. Function deleteQuestion(button), Function
deleteQuestion(button) adalah sebuah fungsi yang dipanggil saat
tombol "Hapus" pada setiap baris soal ujian ditekan. Tujuannya adalah
untuk menghapus baris tabel yang mengandung soal ujian yang sesuai dengan
tombol yang ditekan. Function ini mendapatkan elemen
<tbody> yang merupakan parent dari tombol yang ditekan
menggunakan button.closest("tbody"), lalu menghapusnya dari tabel.
Setelah itu, function updateNomorUrut() dipanggil untuk memperbarui
nomor urut pada setiap baris soal ujian di tabel.
function deleteQuestion(button) { let tbody = button.closest("tbody"); if (tbody) { tableExam.removeChild(tbody); updateNomorUrut(); } }
9. Function updateNomorUrut(), Function
updateNomorUrut() bertujuan untuk memperbarui nomor urut setiap
soal ujian dalam tabel setelah ada perubahan, seperti penghapusan soal.
Function ini berjalan dengan cara mengambil semua elemen
<tbody> yang merupakan baris data soal ujian dalam tabel.
Setelah itu, function ini melakukan iterasi pada setiap elemen
<tbody>, mengambil nomor urut dari elemen tersebut, dan
memperbarui teks pada sel yang menampilkan nomor urut. Hal ini memastikan
bahwa nomor urut setiap soal selalu terurut dan sesuai dengan urutan yang
benar dalam tabel.
function updateNomorUrut() { let tbody = tableExam.getElementsByTagName("tbody"); for (let i = 0; i < tbody.length; i++) { tbody[i + 1].children[0].children[0].textContent = i + 1; } }
End
Jika sudah, kalian bisa mencoba program tersebut dengan mengakses laman ini.
0 Komentar