List box adding and remove with same index - javascript

DEMO
In my project, I used a custom Listbox. It's working correctly at one side. If I remove from Left Sidebox, I need to Place that Old Position at the Right side.
$('#items li').click(function() {
var selected = [];
selected.push($(this).html());
$(this).remove();
generateOptionElements(selected, '#selected');
});
populateItems('#items li');
//populate items box with arr
function populateItems(arr, targetMultiSelect) {
arr.sort();
generateOptionElements(arr, targetMultiSelect);
}
//create option elements
function generateOptionElements(arr, targetMultiSelect) {
for (var i = 0; i < arr.length; i++) {
var option = document.createElement('li');
option.insertAdjacentHTML("beforeend",arr[i]);
$(targetMultiSelect).append(option);
}
}

The main pont of the snippet below is that you should create an Array of Objects and manipulate that in JS, and only output the resulting HTML. It's better than manipulating the DOM.
// Array of Objects - the questions and answers and other
// needed information
const questions = [{
position: 0,
side: 1,
q: "0Animals giving birth to young ones:",
a: ["Oviparous", "Oviviviparous", "Viviparous", "Both a and b"]
},
{
position: 1,
side: 1,
q: "1Animals giving birth to young ones:",
a: ["Oviparous", "Oviviviparous", "Viviparous", "Both a and b"]
},
{
position: 2,
side: 1,
q: "2Animals giving birth to young ones:",
a: ["Oviparous", "Oviviviparous", "Viviparous", "Both a and b"]
},
{
position: 3,
side: 1,
q: "3Animals giving birth to young ones:",
a: ["Oviparous", "Oviviviparous", "Viviparous", "Both a and b"]
},
{
position: 4,
side: 1,
q: "4Animals giving birth to young ones:",
a: ["Oviparous", "Oviviviparous", "Viviparous", "Both a and b"]
},
]
// adding the created HTML to the DOM
const populateSides = questions => {
// filling out left and right sides
document.getElementById('right').innerHTML = questionListHtml(questions.filter(e => e.side === 1))
document.getElementById('left').innerHTML = questionListHtml(questions.filter(e => e.side === -1))
// adding click event listener to each question
document.querySelectorAll('.question').forEach(e => {
e.addEventListener('click', function(ev) {
questions.find(el => el.position === Number(e.getAttribute('data-order'))).side *= -1
populateSides(questions)
})
})
}
// template for the list
const questionListHtml = questions => {
let html = ''
html += '<ol>'
questions.forEach(e => {
html += `<li class="question" data-order="${e.position}">${singleQuestion(e)}</li>`
})
html += '</ol>'
return html
}
// template for the single question
const singleQuestion = q => {
let html = ''
html += `${q.q}`
html += `<ol>`
q.a.forEach(e => {
html += `<li>${e}</li>`
})
html += `</ol>`
return html
}
populateSides(questions)
#left {
background: red;
}
#right {
background: yellow
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootswatch/4.3.1/cerulean/bootstrap.min.css" rel="stylesheet" />
<div class="container">
<div class="row">
<div id="left" class="col left">
</div>
<div id="right" class="col">
</div>
</div>
</div>

Related

Radio Buttons are being grouped while having different id's JavaScript

I am trying to create some questions where you can choose an option from 1 to 5.
I am doing this using radio buttons, and I also change their ID so that they are not the same entity.
Although I am first creating the first question and after the other one, for some reason all the radio buttons are connected and I can only choose 1 button out of the 10 if I create 2 questions, and not 1 from the first question and 1 from the next one.
Does anyone know how to fix this problem? Check my code below to see the problem. Thanks
This is my code:
const questionnaire = document.getElementById('questionaire');
var numsQN = 0;
questionnaire.onclick = ev => {
if (ev.target.tagName === "BUTTON") {
switch (ev.target.className) {
case "remove-qu":
switch (ev.target.parentNode.className) {
case "numQuestion":
numsQN--;
document.getElementById('numberOfNumQuestions').innerHTML = "Number Questions = " + numsQN;
break;
}
ev.target.parentNode.remove();
break;
case "add-numli":
newNumSubquestion(ev.target.closest(".starQuestion").querySelector('ul'), false)
break;
}
}
else {
switch (ev.target.className) {
case "remove-numli":
ev.target.parentNode.remove();
break;
}
}
}
function newNumQuestion() {
questionnaire.insertAdjacentHTML('beforeend', `
<div class='numQuestion'> <div class="numbers"> <ul></ul> </div>`);
}
function newNumSubquestion(q, subquestionNumber) {
q.insertAdjacentHTML('beforeend', `
<li class="numSubquestion">
<span class="numSubquestionName">Sub-question</span>
<div id='colourRadioButtons'> </div>`);
var element = document.getElementById("colourRadioButtons");
var newName = "colourRadioButtons" + subquestionNumber + "";
element.id = newName;
let lastRadio = false;
const numbers = { "5": false, "4": false, "3": false, "2": false, "1": false, },
radioStatic = {
name: "colour", onchange: (event) => {
if (lastRadio) {
numbers[lastRadio] = false;
}
lastRadio = event.currentTarget.value;
numbers[lastRadio] = event.currentTarget.checked;
}, type: "radio"
}; // radioStatic
for (let key in numbers) {
element.appendChild(
Object.assign(document.createElement("label"), { textContent: key })).appendChild(
Object.assign(document.createElement("input"), radioStatic, { checked: numbers[key], value: key }));
if (numbers[key]) {
lastRadio = key;
}
}
}
function generateNumberQuestion() {
let howManyOptionEachNumsQuestionHas = 2;
for (let i = 0; i < 1; i++) {
newNumQuestion(true);
for (let j = 0; j < howManyOptionEachNumsQuestionHas; j++) {
newNumSubquestion(questionnaire.querySelector("div.numQuestion:last-child ul"), j);
}
}
}
document.getElementById("addNumButton").onclick = function () { generateNumberQuestion(); };
<h1 id="myText" contenteditable="true">Survey Name</h1>
<button type="button" id="addNumButton">Number Rating</button>
<form>
<div id="questionaire"></div>
</form>

Trouble ADDING points to quiz game. It adds 2 instead of 1. JS

I've looked into the stackoverflow recommendations about posts with similar titles and nothing solved my issue. Im new to JS, im trying to make a simple multiple choice quiz. If you get it correct you score a point, if not, u don't get any but the question counter increases, the thing is after the first question everything adds double the value, here's a quick video showcasing de error: https://gyazo.com/9fbdf63508b2713992935d813f29788e pay attention to the bottom-right corner.
This is a side project and I've been stuck on it for almost 2 weeks now.. no joke. Any help is extremely appreciated, my main language is Spanish so that's the reason of the variables names. Here's the code:
let pregunta = document.getElementById('preguntafinal');
let puntaje = document.getElementById('puntaje');
let opcion1 = document.getElementById('opcion1');
let opcion2 = document.getElementById('opcion2');
let opcion3 = document.getElementById('opcion3');
let opcion4 = document.getElementById('opcion4');
let puntito1 = document.querySelector('puntito1');
let idPreg = 0;
let respSeleccionada;
let puntosTotales = 0;
let preguntasTotales = 0;
function iterarJuego() {
pregunta.innerText = arrayPreguntas[idPreg].preg;
opcion1.innerText = arrayPreguntas[idPreg].opcionuno;
opcion2.innerText = arrayPreguntas[idPreg].opciondos;
opcion3.innerText = arrayPreguntas[idPreg].opciontres;
opcion4.innerText = arrayPreguntas[idPreg].opcioncuatro;;
elegirRespuesta();
}
function elegirRespuesta() {
opcion1.addEventListener("click", asd => {
respSeleccionada = arrayPreguntas[idPreg].opcionuno;
funAnalizar(respSeleccionada);
});
opcion2.addEventListener("click", asd => {
respSeleccionada = arrayPreguntas[idPreg].opciondos;
funAnalizar(respSeleccionada);
});
opcion3.addEventListener("click", asd => {
respSeleccionada = arrayPreguntas[idPreg].opciontres;
funAnalizar(respSeleccionada);
});
opcion4.addEventListener("click", asd => {
respSeleccionada = arrayPreguntas[idPreg].opcioncuatro;
funAnalizar(respSeleccionada);
});
}
function funAnalizar() {
console.log(respSeleccionada);
console.log(arrayPreguntas[idPreg].error);
if (respSeleccionada == arrayPreguntas[idPreg].error) {
console.log("correcto");
respCorrecta(respSeleccionada);
} else if (respSeleccionada != arrayPreguntas[idPreg].error) {
console.log("incorrecto");
respIncorrecta(respSeleccionada);
}
}
function respCorrecta() {
puntosTotales++;
preguntasTotales++;
puntaje.innerText = puntosTotales + "/" + preguntasTotales;
idPreg++;
iterarJuego(idPreg);
console.log("ja");
}
function respIncorrecta() {
preguntasTotales++;
puntaje.innerText = puntosTotales + "/" + preguntasTotales;
idPreg++;
iterarJuego(idPreg);
console.log("jant");
}
arrayPreguntas = [{
idPreg: 0,
preg: "Que significa AI en Japonés?",
opcionuno: 'amor',
opciondos: 'carcel',
opciontres: 'pizza',
opcioncuatro: 'caja',
error: 'amor'
}, {
idPreg: 1,
preg: "Cual es el hiragana 'ME' ?",
opcionuno: 'ぬ',
opciondos: 'ね',
opciontres: 'ぐ',
opcioncuatro: 'め',
error: 'め'
}, {
idPreg: 2,
preg: "En hiragana: DESAYUNO , ALMUERZO , CENA ?",
opcionuno: 'ぬ',
opciondos: 'ね',
opciontres: 'ぐ',
opcioncuatro: 'め',
error: 'め'
}, {
idPreg: 3,
preg: "Como se dice madre y padre ?",
opcionuno: 'chichi hana',
opciondos: 'hana mitsu',
opciontres: 'kirei chichi',
opcioncuatro: 'undo chichi',
error: 'kirei chichi'
}, {
idPreg: 4,
preg: "Que significa きれい ?",
opcionuno: 'rey y reina',
opciondos: 'lindo y linda',
opciontres: 'hermoso y hermosa',
opcioncuatro: 'salvaje y saldro',
error: 'lindo y linda'
}]
iterarJuego();
That's the .js ..if for some reason the html is needed ill add it with an edit.
Redid everything into English, it was messy (BTW there's a button called "Tidy" in the editor) but I couldn't find the bug, I might've corrected it without being aware I had? Anyways, I liked the flow of the code so instead of giving up I made some improvements.
The terse syntax is from HTMLFormElement interface:
Figure I
// <form id="QA"> name attribute can be used as id
const QA = document.forms.QA;
// We can make a reference to all form controls in <form>
const IO = QA.elements;
// With that defined, referencing form controls is simple
IO.question // <output id='question'>
IO.next // <button id='next'>
The HTMLFormControlsCollection interface allows us to group form controls by a common name attribute and use array methods on them or extract a value of a checked or selected form control:
Figure II
// 1 of 4 <input id='optB' name='opt' type='radio' value='optB' checked>
IO.opt // HTMLCollection of all [name='opt']
[...IO.opt] // Array of all [name='opt']
IO.opt.value // Automatically gets the value of the checked [name='opt']
I replaced the 4 click handlers with one submit handler:
Figure III
// <form> is bound to the submit event
QA.onsubmit = evaluate;
function evaluate(e) {
e.preventDefault();
If you decide to handle the submit event remember to use e.preventDefault()
otherwise the will attempt to send data to a server, and the response
will kill the page.
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<style>
html {
font: 300 3ch/1.2 'Segoe UI'
}
#score {
font-size: 1.25rem;
}
#score::before {
content: 'Score: '
}
ol {
list-style: lower-latin;
margin-top: 0
}
input,
button {
font: inherit
}
li {
margin-bottom: 8px;
}
button {
display: inline-flex;
align-items: center;
padding: 0 0.5rem;
cursor: pointer
}
</style>
</head>
<body>
<main>
<form id='QA'>
<fieldset>
<legend><output id='score'></output></legend>
<output id='question'></output>
<ol>
<li>
<input id='optA' name='opt' type='radio' value='optA'>
<label for='optA'></label>
</li>
<li>
<input id='optB' name='opt' type='radio' value='optB'>
<label for='optB'></label>
</li>
<li>
<input id='optC' name='opt' type='radio' value='optC'>
<label for='optC'></label>
</li>
<li>
<input id='optD' name='opt' type='radio' value='optD'>
<label for='optD'></label>
</li>
</ol>
<menu>
<button id='next'>Next</button>
</menu>
</fieldset>
</form>
</main>
<script>
const QA = document.forms.QA;
const IO = QA.elements;
const question = IO.question;
const score = IO.score;
const opt1 = IO.optA.nextElementSibling;
const opt2 = IO.optB.nextElementSibling;
const opt3 = IO.optC.nextElementSibling;
const opt4 = IO.optD.nextElementSibling;
let qID = 0;
let totalP = 0;
let totalQ = 0;
function quiz() {
question.textContent = (qID + 1) + '. ' + qArray[qID].ques;
opt1.textContent = qArray[qID].optA;
opt2.textContent = qArray[qID].optB;
opt3.textContent = qArray[qID].optC;
opt4.textContent = qArray[qID].optD;
[...IO.opt].forEach(o => {
if (o.checked) {
o.checked = false;
}
});
}
QA.onsubmit = evaluate;
function evaluate(e) {
e.preventDefault();
let selected = IO.opt.value;
if (selected === qArray[qID].right) {
correct();
} else {
wrong();
}
}
function correct() {
totalP++;
totalQ++;
score.textContent = totalP + " / " + totalQ;
qID++;
if (qID >= qArray.length) {
return IO.next.style.display = 'none';
}
quiz();
}
function wrong() {
totalQ++;
score.textContent = totalP + " / " + totalQ;
qID++;
if (qID >= qArray.length) {
return IO.next.style.display = 'none';
}
quiz();
}
qArray = [{
qID: 0,
ques: "Que significa AI en Japonés?",
optA: 'amor',
optB: 'carcel',
optC: 'pizza',
optD: 'caja',
right: 'optA'
}, {
qID: 1,
ques: "Cual es el hiragana 'ME' ?",
optA: 'ぬ',
optB: 'ね',
optC: 'ぐ',
optD: 'め',
right: 'optD'
}, {
qID: 2,
ques: "En hiragana: DESAYUNO , ALMUERZO , CENA ?",
optA: 'ぬ',
optB: 'ね',
optC: 'ぐ',
optD: 'め',
right: 'optB'
}, {
qID: 3,
ques: "Como se dice madre y padre ?",
optA: 'chichi hana',
optB: 'hana mitsu',
optC: 'kirei chichi',
optD: 'undo chichi',
right: 'optC'
}, {
qID: 4,
ques: "Que significa きれい ?",
optA: 'rey y reina',
optB: 'lindo y linda',
optC: 'hermoso y hermosa',
optD: 'salvaje y saldro',
right: 'optB'
}];
quiz();
</script>
</body>
</html>

JSXgraph not moving points when I change a function

I'm using JSXgraph to show students limsups and liminfs. The version works here - http://ibldynamics.com/exercises/ex2_56.html
Here's the code:
<div style="width: 500px; height: 40px;">
<p style="display: inline;">N:</p>
// Create a slider for the values of N
<input id="NSlider" type="range" min="1" max="19" value="1" step="1" style="width: 50%;">
<p style="display: inline;"><span id="NOut"></span></p>
<script>
// Get the value of N from the slider
var NSlider = document.getElementById("NSlider");
var NOutput = document.getElementById("NOut");
NOutput.innerHTML = NSlider.value; // Output value for student to see
</script>
</div>
<!-- Create board with points -->
<div id="box" class="jxgbox" style="width:500px; height:500px;">
<script type="text/javascript">
// Create board
var board = JXG.JSXGraph.initBoard('box', {
boundingbox: [-1, 2, 21, -0.2],
axis: true,
grid: true
});
// Generate points in the sequence and graph points of the sequence
var i;
var s = [null];
for (i = 1; i <= 20; i++) {
s.push(1 + Math.pow(-1, i) / i);
board.create('point', [i, s[i]], {
color: 'yellow',
fixed: true,
withLabel: false
});
}
// Genereate liminfs and limsups
var infs = [null],
sups = [null];
for (i = 1; i <= 20; i++) {
infs.push(Math.min.apply(null, s.slice(i + 1)));
sups.push(Math.max.apply(null, s.slice(i + 1)));
}
// Graph liminf and limsup points
var liminf = board.create('point', [
function() { return NSlider.value; },
function() { return infs[NSlider.value]; }], {
color: 'blue',
withLabel: false
});
var limsup = board.create('point', [
function() { return NSlider.value; },
function() { return sups[NSlider.value]; }], {
color: 'orange',
withLabel: false
});
board.update()
</script>
</div>
<script>
// Set board to update when the N slider is updated
NSlider.oninput = function () {
NOutput.innerHTML = this.value; // Output value for student to see
liminf.moveTo([NSlider.value, infs[NSlider.value]]);
limsup.moveTo([NSlider.value, sups[NSlider.value]]);
}
</script>
The problem is the version I have here - http://ibldynamics.com/exercises/ex2_57.html
I've only changed two things. The function that I use to generate the points is s.push((-1)**i*(1 + (1 / i))); and the bounding box is a little bigger. For some reason the blue points won't show up any more.
Any ideas?

Sort array of objects by key values and displaying them on a HTML element

I'm making a movie sorter list, you enter the title and then the rating and it will show you the movies in order by rating. I have an array of objects and I managed to sort the array by rating, but I can't find a way to actually display the array in order on the HTML DOM.
I've tried for loops and forEach's but they don't work the way I want.
const movieTitle = document.querySelector(".movie-title");
const movieRating = document.querySelector(".movie-rating");
const movieList = document.querySelector(".movie-list");
const sortBtn = document.querySelector(".btn");
let movieStorage = [];
function sendMovie() {
if(event.keyCode == 13) {
if(movieTitle.value != "" && movieRating.value != "") {
title = movieTitle.value;
rating = parseInt(movieRating.value);
movieStorage.push({
title: title,
rating: rating
});
// If rating of a is bigger than rating of b return 1, if not return -1
movieStorage.sort((a, b) => (a.rating > b.rating) ? -1 : 1);
console.log(movieStorage);
addMovieToList(title, rating);
movieTitle.value = "";
movieRating.value = "";
} else {
console.log("Fields missing");
}
}
}
function addMovieToList(title, rating) {
const div = document.createElement("div");
div.className = "list-items";
div.innerHTML = `
<div class="item-title">
<p>${title}</p>
</div>
<div class="item-rating">
<p>${rating}</p>
</div>
<div class="item-delete">
<i class="fa fa-trash trash-icon delete"></i>
</div>
`;
movieList.appendChild(div);
}
function sortByRating(element) {
for(let i = 0; i < movieStorage.length; i++) {
element.innerHTML = `
<div class="item-title">
<p>${movieStorage[i].title}</p>
</div>
<div class="item-rating">
<p>${movieStorage[i].rating}</p>
</div>
<div class="item-delete">
<i class="fa fa-trash trash-icon delete"></i>
</div>
`;
}
}
document.addEventListener("click", (e) => {
const deleteIcon = e.target;
const item = document.querySelector(".list-items");
if(deleteIcon.classList.contains("delete")) {
deleteIcon.parentElement.parentElement.remove(item);
}
})
tldr demo
After sorting the array, you need a way to reference movie divs to sort them. There are many ways to do it, what I chose is using id. When you create movie <div>, give it an ID unique for each movie name:
// Simple function to generate hash number for each string
function hashStr(stringValue) {
var hash = 0, i, chr;
if (stringValue.length === 0) return hash;
for (i = 0; i < stringValue.length; i++) {
chr = stringValue.charCodeAt(i);
hash = ((hash << 5) - hash) + chr;
hash |= 0; // Convert to 32bit integer
}
return hash;
}
const MOVIES = [
{name: "a", rating: 3},
{name: "b", rating: 6},
{name: "c", rating: 3},
{name: "d", rating: 2},
{name: "e", rating: 1},
];
function showMovies() {
const moviesDiv = document.querySelector("#movies");
for(const movie of MOVIES)
{
const id = "movie-"+hashStr(movie.name);
// If there's no element with the ID, we need to create the DIV for the movie
if(!document.querySelector("#"+id)) {
const elm = document.createElement("div");
elm.appendChild(new Text(movie.name + " ("+movie.rating+"/10)"));
elm.id = id;
elm.classList.add("movie");
moviesDiv.appendChild(elm);
}
}
}
Then, when sorting, you can reference each movie by ID:
// Sort movies using given property (eg. "name")
// The second param determines sort direction
function sortBy(property, ascending=true) {
MOVIES.sort((a,b) =>{
return cmp(a[property], b[property], ascending);
});
// Now after sorting the array, we can sort the HTML elements
const moviesDiv = document.querySelector("#movies");
let lastMovie = null;
for(const movie of MOVIES)
{
const id = "#movie-"+hashStr(movie.name);
const movieDiv = document.querySelector(id);
console.log(id, movieDiv);
// If created
if(movieDiv) {
// remove and append after last processed movie (for the first movie, this will append to top)
moviesDiv.insertBefore(movieDiv, lastMovie);
}
}
}
// Compare string and number, makes no sense for other types
function cmp(a,b, ascending=true) {
if(typeof a=='number' && typeof b == "number") {
return ascending ? a-b : b-a;
}
else if(typeof a=='string' && typeof b == "string"){
return (ascending ? 1 : -1) * a.localeCompare(b);
}
else {
return 0;
}
}
When you add a movie, you just call sort again. You will need to remember the last sorting parameters for that.
Your sort will work fine. The problem is that after you've sorted you can't just display that movie, you have to redisplay the entire list. You're almost there with your sortByRating method, but it doesn't recreate the entire list correctly. Try something like:
function showMoviesList(element) {
let innerHTML = "";
for (let i = 0; i < movieStorage.length; i++) {
innerHTML += `
<div class="item-title">
<p>${movieStorage[i].title}</p>
</div>
<div class="item-rating">
<p>${movieStorage[i].rating}</p>
</div>
<div class="item-delete">
<i class="fa fa-trash trash-icon delete"></i>
</div>
`;
}
element.innerHTML = innerHTML;
}
This resets the inner HTML of the element to the complete movie list in order every time it's called.
Now call showMoviesList(movieList) instead of calling addMovieToList in sendMovie.

Adding answers to a random questions quiz javascript

I am currently making a quiz in Javascript that randomizes questions and answers. I have the questions randomizing but how do I add the answers to go along with a certain question? I also want each answer to be placed in a div of its own, like so: http://imgur.com/a/l9w9j
Here's the code I have so far:
var display = document.getElementById("questions");
var questions = ['What is the weather like?',
'What time of day is it?',
'Whats your favourite music?',
'Which season is your favourite?',
'What colour are your eyes?'];
var questionTracker = [];
var questionAmount = 1;
// Iterate however many times
for (var i = 0; i < questionAmount; i++) {
// Keep creating random numbers until the number is unique
do {
var randomQuestion = Math.floor(Math.random() * questions.length);
} while (existingQuestions());
display.innerHTML += questions[randomQuestion] + '<br>';
// Add the question to the tracker
questionTracker.push(randomQuestion);
}
// If the current random number already exists in the tracker, return true
function existingQuestions() {
for (var i = 0; i < questionTracker.length; i++) {
if (questionTracker[i] === randomQuestion) {
return true;
}
}
return false;
}
And my HTML:
<div id="questions">
</div>
<div id="answers">
<div class="answers-left">
<div class="answer1" tabIndex="1">Sunny</div>
<div class="answer2" tabIndex="2">Raining</div>
</div>
<div class="answers-right">
<div class="answer3" tabIndex="3">Cloudy</div>
<div class="answer4" tabIndex="4">Windy</div>
</div>
<div class="clear"></div>
</div>
Her you can use of object instead of array
var questionData= {
"questions":[
{
"question":"this is hard question to answer",
"answers":[
"yes","no","why not","none"
]
},
{
"question":"this is 2nd hard question to answer",
"answers":[
"yes","no","why not","none"
]
}
]
}
questionData.map(function(question){
//Here you can write the dom structure that you like
})
You can store your questions and answers inside an array of objects
Each object hold a question and an answers property. answers is an array that contains each possible answers.
The following code will take a random question using Math.random() to find a random index. With this index, you can select the object in the array and then select the question and answers.
I added some CSS to add the desired effect. This can be improved with the colors/size/margins/... you want
var questionElement = document.getElementById("questions");
var answersElements = document.getElementsByClassName("answer");
var data = [{
question: 'What is the weather like?',
answers: ['Sunny', 'Raining', 'Cloudy', 'Windy']
}, {
question: 'What time of day is it?',
answers: ['Morning', 'Lunch', 'Evening', 'Night']
}];
var randomIndex = Math.floor(Math.random() * data.length);
questionElement.innerHTML = data[randomIndex].question;
for (let i = 0; i < answersElements.length; i++) {
answersElements[i].innerHTML = data[randomIndex].answers[i];
}
.answer {
display: inline-block;
background-color: #00BCD4;
margin: 1em;
}
<div id="questions">
</div>
<div id="answers">
<div class="answers-left">
<div class="answer" tabIndex="1">Sunny</div>
<div class="answer" tabIndex="2">Raining</div>
</div>
<div class="answers-right">
<div class="answer" tabIndex="3">Cloudy</div>
<div class="answer" tabIndex="4">Windy</div>
</div>
<div class="clear"></div>
</div>
Why not add the answers to the questions in an object array?
var display = document.getElementById("questions");
var answers = document.getElementById("answers");
var answersLeft = document.getElementById("answers-left");
var answersRight = document.getElementById("answers-right");
var questions = [{
"q": "What is the weather like?",
"a": [
"Sunny",
"Raining",
"Cloudy",
"Windy"
]
},
{
"q": "What time of day is it?",
"a": [
"Sunny",
"Raining",
"Cloudy",
"Windy"
]
},
{
"q": "Whats your favourite music?",
"a": [
"Sunny",
"Raining",
"Cloudy",
"Windy"
]
},
{
"q": "Which season is your favourite?",
"a": [
"Sunny",
"Raining",
"Cloudy",
"Windy"
]
},
{
"q": "What colour are your eyes?",
"a": [
"Sunny",
"Raining",
"Cloudy",
"Windy"
]
}
];
var questionTracker = [];
var questionAmount = 1;
// Iterate however many times
for (var i = 0; i < questionAmount; i++) {
// Keep creating random numbers until the number is unique
do {
var randomQuestion = Math.floor(Math.random() * questions.length);
} while (existingQuestions());
display.innerHTML += questions[randomQuestion].q + '<br>';
var answersToQ = questions[randomQuestion].a;
for (var j = 0; j < answersToQ.length; j++) {
var answer = "<p>" + answersToQ[j] + "</p>";
if (j % 2 === 0) {
answersLeft.innerHTML += answer;
} else {
answersRight.innerHTML += answer;
}
}
// Add the question to the tracker
questionTracker.push(randomQuestion);
}
// If the current random number already exists in the tracker, return true
function existingQuestions() {
for (var i = 0; i < questionTracker.length; i++) {
if (questionTracker[i] === randomQuestion) {
return true;
}
}
return false;
}
<style type="text/css">
#answers-left {
position: relative;
float: left;
width: 50%;
}
#answers-right {
position: relative;
float: right;
width: 50%;
}
#answers p {
background-color: blue;
width: 50%;
text-align: center;
color: #fff;
cursor: pointer;
}
</style>
<div id="questions">
</div>
<div id="answers">
<div id="answers-left">
</div>
<div id="answers-right">
</div>
</div>
Here is example that i made for you with following code.
Sorry but i did not have time to make ccs rules, but you can see that questions are mixed and answers for them all mixed all so.
http://devel.vis25.com/test.php
I recommend you to use something like this, for my example you will need Jquery and Jquery templates
Here is link to Jquery download jquery tempaltes
Here is example of you'r tempaltes and html.
<html>
<head>
<script src="https://devel.vis25.com//Vendors/JqueryUI/external/jquery/jquery.js"></script>
<script src="http://devel.vis25.com/Vendors/jquery.tmpl.min.js"></script>
</head>
<body onload="RenderQuestions();">
<div id="Questions"></div>
<script id="Question-Tempalte" type="text/x-jQuery-tmpl">
<div class="Question" id=question-"${ID}">
<div class="Question-text">${QuestionText}</div>
<div class="Question-answer-container" id="Question-answer-container-${ID}"></div>
</div>
</script>
<script id="Answer-Tempalte" type="text/x-jQuery-tmpl">
<div class="answer" id="answer-${ID}">
<div class="answer-text" tabIndex="${ID}">${answerText}</div>
</div>
</script>
</body>
</html>
with javascript do something like this.
//Function that is called in body 'onload' event.
function RenderQuestions(){
//Array of you'r questions as json objects
var questions = [
{ ID : '1', QuestionText : 'What is the weather like?' },
{ ID : '2', QuestionText : 'What time of day is it?' },
{ ID : '3', QuestionText : 'Whats your favourite music?' },
{ ID : '4', QuestionText : 'Which season is your favourite?' },
{ ID : '5', QuestionText : 'What colour are your eyes?' },
];
//Call shuffle function for your questions, so they are mixed randomly.
var ShuffledQuestions = shuffle( questions );
//Loop true all of your questions and render them inside of your questions <div>
//Allso call functions 'RenderAnswers()' by question id value[ 'ID' ].
$.each(ShuffledQuestions, function(index, value){
$( '#Question-Tempalte' ).tmpl( value ).appendTo( '#Questions' );
RenderAnswers( value[ 'ID' ] );
});
}
//Shuffle function return randomly mixed array.
function shuffle( array ) {
var currentIndex = array.length, temporaryValue, randomIndex;
while (0 !== currentIndex) {
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
}
//RenderAnswers function takes QuestionID as argument so we can render answer elements for right questions, and we have right answers.
function RenderAnswers( QuestionID ){
var Answers = [];
//Check which question are we rendering.
//Answers for question ID 1 ( 'What is the weather like?' ).
if( QuestionID == 1){
Answers = [
{ AnswersID : 1 , answerText : 'Sunny' },
{ AnswersID : 2 , answerText : 'Raining'},
{ AnswersID : 3 , answerText : 'Cloudy'},
{ AnswersID : 4 , answerText : 'Windy'},
];
}
//Answers for question ID 2 ( 'What time of day is it?' ).
if( QuestionID == 2){
Answers = [
{ AnswersID : 1 , answerText : '8:00' },
{ AnswersID : 2 , answerText : '12:00'},
{ AnswersID : 3 , answerText : '18:00'},
{ AnswersID : 4 , answerText : '00:00'},
];
}
//Answers for question ID 3 ( 'Whats your favourite music?' ).
if( QuestionID == 3){
Answers = [
{ AnswersID : 1 , answerText : 'Rock' },
{ AnswersID : 2 , answerText : 'pop'},
{ AnswersID : 3 , answerText : 'rap'},
{ AnswersID : 4 , answerText : 'EDM'},
];
}
//Answers for question ID 4 ( 'Which season is your favourite?' ).
if( QuestionID == 4){
Answers = [
{ AnswersID : 1 , answerText : 'Summer' },
{ AnswersID : 2 , answerText : 'Winter'},
{ AnswersID : 3 , answerText : ''},
{ AnswersID : 4 , answerText : ''},
];
}
//Answers for question ID 5 ( 'What colour are your eyes?' ).
if( QuestionID == 4){
Answers = [
{ AnswersID : 1 , answerText : 'blue' },
{ AnswersID : 2 , answerText : 'brown'},
{ AnswersID : 3 , answerText : 'green'},
{ AnswersID : 4 , answerText : ''},
];
}
//Shuffle answers.
var ShuffledAnswers = shuffle( Answers );
//Renders answer elements for question.
$( '#Answer-Tempalte' ).tmpl( ShuffledAnswers ).appendTo( '#Question-answer-container-'+QuestionID );
}
Hope i was able to help you, and feel free to ask anything is i did not understand your question right !
Best regards,
Vis25

Categories