Reputation: 70
Might be a simple question for some, but im currently stuck here.
What i'm trying to create is a quiz, that grabs the questions, answers, solutions and the type of question from a JSON.
So far, it works and i get an array with the answers selected and removing the answers that are unselected. But the array gets filled with the id, but i actually want it's answerList index.
{
"quid":1,
"question": "question 1",
"answerList":["answer 1_1","answer 1_2"],
"solution":[1],
"type":"checkbox"
}
This is what my JSON looks like. When running the code below, and checking both boxes, i get an array as ["answer1_1", "answer1_2"]. But i need an array like [0, 1] because i later on want to compare it to the solution, to see if the selection was correct or not. Also, since there are mulitple checkbox questions (i removed everything else since it's irelevant here), it gets all pushed into the same array. Ideally i'd get arr1=[0, 1], if both were selected in this case and arr=[0, 1, 2] for the next.
Maybe i've been sitting here for too long to not see the obvious, simple answer to my question.
Anyway, here is a code snippet.
//Parse JSON
let quizDyn = JSON.parse(`[
{
"quid":1,
"question": "question 1",
"answerList":["answer 1_1","answer 1_2"],
"solution":[1],
"type":"checkbox"
}, {
"quid":2,
"question": "question 2",
"answerList":["answer 2_1","answer 2_2","answer 2_3"],
"solution":[0,1,2],
"type":"checkbox"
}, {
"quid":3,
"question": "question 3",
"answerList":["answer 3_1","answer 3_2","answer 3_3","answer 3_4"],
"solution":[0],
"type":"checkbox"
}
]`)
// just creating a div here
var spalteQuiz = document.createElement("div")
spalteQuiz.setAttribute("class", "spalteQuiz")
document.body.append(spalteQuiz)
for (var i = 0; i < quizDyn.length; i++) {
var neuesQuiz = document.createElement("div")
neuesQuiz.setAttribute("class", "quiz")
var aktuellesQuiz = document.getElementById("pOut")
neueFrage = document.createElement("p")
neueFrage.setAttribute("class", "frage")
neueFrage.setAttribute("id", "frage " + (i + 1) + " frage")
neueFrage.setAttribute("name", "frage " + (i + 1) + " frage")
neueFrage.textContent = quizDyn[i].question
var aktuelleFrage = document.getElementById("divOut")
spalteQuiz.append(neuesQuiz)
neuesQuiz.append(neueFrage)
var frageTyp = quizDyn[i].type
var anzahlAntworten = quizDyn[i].answerList.length
var quidi = quizDyn[i].quid
var quid = quizDyn.quid
var entferneLeerzeichen = str => str.replace(/[\s,.]/g, '')
// variable used for my array
var loesung = []
// function that's used for questions that are to be answered with checkboxes
function istCheckbox() {
//creating the <form>'s
var form = document.createElement("form")
form.setAttribute("name", "frage" + quidi + "form")
neuesQuiz.append(form)
// creating the <input>'s
for (let i = 0; i < anzahlAntworten; i++) {
checkbox = document.createElement("input")
checkbox.setAttribute("type", "checkbox")
checkbox.setAttribute("name", "frage" + quidi + "checkbox")
checkbox.setAttribute("id", entferneLeerzeichen(quizDyn[quidi - 1].answerList[i]))
// creating the <label>'s
var label = document.createElement("label")
label.textContent = quizDyn[quidi - 1].answerList[i]
label.setAttribute("for", entferneLeerzeichen(quizDyn[quidi - 1].answerList[i]))
// here i check if the checkbox is checked
checkbox.addEventListener('change', function() {
// if it's checked, push the checkboxes id to the array
if (this.checked) {
loesung.push(this.id)
} else {
// when unchecking, find the index of the unchecked checkbox'S id
index = loesung.indexOf(this.id)
// splice 1 object at the position of index
loesung.splice(index, 1)
}
// console log the array
console.log(loesung)
})
// appending it all
var zeilenUmbruch = document.createElement("br")
form.append(checkbox)
form.append(label)
form.append(zeilenUmbruch)
}
}
//there is more usually, because irelevant
function istTyp() {
istCheckbox()
}
istTyp()
}
Upvotes: 1
Views: 84
Reputation: 22320
I don't see the point of an event listener, here is my way of considering this code.
const quizDyn =
[ { quid: 1, question: 'question 1', answerList: ['answer 1_1', 'answer 1_2'], solution: [1], type: 'checkbox' }
, { quid: 2, question: 'question 2', answerList: ['answer 2_1', 'answer 2_2', 'answer 2_3'], solution: [0, 1, 2], type: 'checkbox' }
, { quid: 3, question: 'question 3', answerList: ['answer 3_1', 'answer 3_2', 'answer 3_3', 'answer 3_4'], solution: [0], type: 'checkbox' }
]
, spalteQuiz = document.createElement('div')
, quizForm = document.createElement('form')
;
spalteQuiz.className = 'spalteQuiz'
spalteQuiz.append(quizForm)
document.body.append(spalteQuiz)
quizDyn.forEach((quiz,idxQuestion)=>
{
let field = document.createElement('fieldset')
field.innerHTML = `<legend>${quiz.question}</legend>\n`
quiz.answerList.forEach((answer,idxAnswer)=>
{
field.innerHTML += `<label><input name="${answer}" type="${quiz.type}" value="${idxQuestion}_${idxAnswer}">${answer}</label>\n`
})
quizForm.appendChild(field)
})
quizForm.innerHTML += `<button type="submit"> verify </button> <button type="reset"> reset </button>`
quizForm.onsubmit = e =>
{
e.preventDefault()
quizForm.querySelectorAll('input').forEach(answerX =>
{
let [quizN,answerN] = answerX.value.split('_').map(Number)
answerX.closest('label').className = (answerX.checked === quizDyn[quizN].solution.includes(answerN) ) ? 'good' : 'bad'
})
}
quizForm.onreset = e =>
{
quizForm.querySelectorAll('label').forEach(lb=>lb.className = '')
}
div.spalteQuiz fieldset {
margin : .7em 0;
width : 20em;
}
div.spalteQuiz label {
display : block;
float : left;
clear : both;
}
div.spalteQuiz label.bad {
color:red;
}
div.spalteQuiz label.good {
color:green;
}
Upvotes: 1
Reputation: 619
Based on your design, i commented what i did to your event listener.
// Parse JSON
const quizDyn = JSON.parse(`[
{
"quid":1,
"question": "question 1",
"answerList":["answer 1_1","answer 1_2"],
"solution":[1],
"type":"checkbox"
}, {
"quid":2,
"question": "question 2",
"answerList":["answer 2_1","answer 2_2","answer 2_3"],
"solution":[0,1,2],
"type":"checkbox"
}, {
"quid":3,
"question": "question 3",
"answerList":["answer 3_1","answer 3_2","answer 3_3","answer 3_4"],
"solution":[0],
"type":"checkbox"
}
]`)
// just creating a div here
const spalteQuiz = document.createElement('div')
spalteQuiz.setAttribute('class', 'spalteQuiz')
document.body.append(spalteQuiz)
for (let i = 0; i < quizDyn.length; i++) {
const neuesQuiz = document.createElement('div')
neuesQuiz.setAttribute('class', 'quiz')
const aktuellesQuiz = document.getElementById('pOut')
const neueFrage = document.createElement('p')
neueFrage.setAttribute('class', 'frage')
neueFrage.setAttribute('id', 'frage ' + (i + 1) + ' frage')
neueFrage.setAttribute('name', 'frage ' + (i + 1) + ' frage')
neueFrage.textContent = quizDyn[i].question
const aktuelleFrage = document.getElementById('divOut')
spalteQuiz.append(neuesQuiz)
neuesQuiz.append(neueFrage)
const frageTyp = quizDyn[i].type
const anzahlAntworten = quizDyn[i].answerList.length
const quidi = quizDyn[i].quid
const quid = quizDyn.quid
const entferneLeerzeichen = str => str.replace(/[\s,.]/g, '')
// variable used for my array
const loesung = []
// function that's used for questions that are to be answered with checkboxes
function istCheckbox () {
// creating the <form>'s
const form = document.createElement('form')
form.setAttribute('name', 'frage' + quidi + 'form')
neuesQuiz.append(form)
// creating the <input>'s
for (let i = 0; i < anzahlAntworten; i++) {
const checkbox = document.createElement('input')
checkbox.setAttribute('type', 'checkbox')
checkbox.setAttribute('name', 'frage' + quidi + 'checkbox')
checkbox.setAttribute(
'id',
entferneLeerzeichen(quizDyn[quidi - 1].answerList[i])
)
// creating the <label>'s
const label = document.createElement('label')
label.textContent = quizDyn[quidi - 1].answerList[i]
label.setAttribute(
'for',
entferneLeerzeichen(quizDyn[quidi - 1].answerList[i])
)
// here i check if the checkbox is checked
checkbox.addEventListener('change', function () {
// if it's checked, push the checkboxes id to the array
if (this.checked) {
// loesung.push(this.id)
// save this context for further use
const answerString = this.id
// re-add the space that was remove
// THIS VERY CRUDE, CONSIDER NOT USING SPACES AT ALL!(!!!)
const answerStringNew =
answerString.substr(0, 6) +
' ' +
answerString.substr(answerString.lastIndexOf('r') + 1)
// filter question array to get index of element which includes the choosen answer in the answerList
const quidElement = quizDyn.findIndex(el =>
el.answerList.includes(answerStringNew)
)
// get the index of the answer in answerList
const indexInAnswerList = quizDyn[quidElement].answerList.indexOf(answerStringNew)
// push index to loesung
loesung.push(indexInAnswerList)
} else {
// when unchecking, find the index of the unchecked checkbox'S id
const index = loesung.indexOf(this.id)
// splice 1 object at the position of index
loesung.splice(index, 1)
}
// console log the array
console.log(loesung)
})
// appending it all
const zeilenUmbruch = document.createElement('br')
form.append(checkbox)
form.append(label)
form.append(zeilenUmbruch)
}
}
// there is more usually, because irelevant
function istTyp () {
istCheckbox()
}
istTyp()
}
But you could also use something like an data
property to store the index when creating your element and just to use that, instead of reconstructing strings.
// Parse JSON
const quizDyn = JSON.parse(`[
{
"quid":1,
"question": "question 1",
"answerList":["answer 1_1","answer 1_2"],
"solution":[1],
"type":"checkbox"
}, {
"quid":2,
"question": "question 2",
"answerList":["answer 2_1","answer 2_2","answer 2_3"],
"solution":[0,1,2],
"type":"checkbox"
}, {
"quid":3,
"question": "question 3",
"answerList":["answer 3_1","answer 3_2","answer 3_3","answer 3_4"],
"solution":[0],
"type":"checkbox"
}
]`)
// just creating a div here
const spalteQuiz = document.createElement('div')
spalteQuiz.setAttribute('class', 'spalteQuiz')
document.body.append(spalteQuiz)
for (let i = 0; i < quizDyn.length; i++) {
const neuesQuiz = document.createElement('div')
neuesQuiz.setAttribute('class', 'quiz')
const aktuellesQuiz = document.getElementById('pOut')
const neueFrage = document.createElement('p')
neueFrage.setAttribute('class', 'frage')
neueFrage.setAttribute('id', 'frage ' + (i + 1) + ' frage')
neueFrage.setAttribute('name', 'frage ' + (i + 1) + ' frage')
neueFrage.textContent = quizDyn[i].question
const aktuelleFrage = document.getElementById('divOut')
spalteQuiz.append(neuesQuiz)
neuesQuiz.append(neueFrage)
const frageTyp = quizDyn[i].type
const anzahlAntworten = quizDyn[i].answerList.length
const quidi = quizDyn[i].quid
const quid = quizDyn.quid
const entferneLeerzeichen = str => str.replace(/[\s,.]/g, '')
// variable used for my array
const loesung = []
// function that's used for questions that are to be answered with checkboxes
function istCheckbox () {
// creating the <form>'s
const form = document.createElement('form')
form.setAttribute('name', 'frage' + quidi + 'form')
neuesQuiz.append(form)
// creating the <input>'s
for (let i = 0; i < anzahlAntworten; i++) {
const checkbox = document.createElement('input')
checkbox.setAttribute('type', 'checkbox')
checkbox.setAttribute('name', 'frage' + quidi + 'checkbox')
checkbox.setAttribute(
'id',
entferneLeerzeichen(quizDyn[quidi - 1].answerList[i])
)
// add an data attribut
checkbox.setAttribute('data-index', i)
// creating the <label>'s
const label = document.createElement('label')
label.textContent = quizDyn[quidi - 1].answerList[i]
label.setAttribute(
'for',
entferneLeerzeichen(quizDyn[quidi - 1].answerList[i])
)
// here i check if the checkbox is checked
checkbox.addEventListener('change', function () {
// if it's checked, push the checkboxes id to the array
if (this.checked) {
// loesung.push(this.id)
// push data-index to loesung
// this.dataset contains all attribuates 'data-'
// but dataset only hold strings, so Number()
// makes the index an integer again
loesung.push(Number(this.dataset.index))
} else {
// when unchecking, find the index of the unchecked checkbox'S id
const index = loesung.indexOf(this.id)
// splice 1 object at the position of index
loesung.splice(index, 1)
}
// console log the array
console.log(loesung)
})
// appending it all
const zeilenUmbruch = document.createElement('br')
form.append(checkbox)
form.append(label)
form.append(zeilenUmbruch)
}
}
// there is more usually, because irelevant
function istTyp () {
istCheckbox()
}
istTyp()
}
(I did not touch the uncheck function, since your question revolved around the index of the answerList array)
Upvotes: 1