How to save radio buttons to local storage - javascript

i have a quiz with radio buttons ,sow i have to save the answears on my local storge ,but im stuck i don t know what else to do,im learnig sow dont hate me pls,tnx
This is my code sow far
<form id="quiz"> </form>
<script>
let object;
let httpRequest = new XMLHttpRequest();
httpRequest.open("GET", "quiz.json", true);
httpRequest.send();
httpRequest.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE) {
object = JSON.parse(this.response);
console.log(object)
}
let json = object
let quiz = document.getElementById("quiz");
let keyList = Object.keys(json.quiz);
for (let i = 0; i < keyList.length; i++) {
let key = keyList[i];
let questionItem = json.quiz[key];
let html = "<div>";
html += "<div><h2>Question " + (i + 1) + ": " + questionItem.question + "</h2></div>";
html += "<div>";
for (let i = 0; i < questionItem.options.length; i++) {
html += "<div >";
html += "<input type=\"radio\" id=\"q\" checked=\"checked\" name=\"qzz" + key + "_option\" value=\"" + questionItem.options[i] + "\">" + questionItem.options[i] ;
html += "</div>";
}
quiz.innerHTML += html;
}
quiz.innerHTML += "<input type=\"submit\" value=\"submit\">";
function save() {
var g1 = document.querySelector('input[type="radio]');
g1 = (g1) ? g1.value : '';
localStorage.setItem("g1", g1);
}
});

You can simplify your AJAX dialog by using fetch() instead of new XMLHttpRequest();. I straightened out a few things in your code (also see the initial remarks in #brianagulo's answer) and prepared a little set of sample data to demonstrate the whole functionality of the quiz. The jsonplaceholder.typicode.com url only serves as a working json-server endpoint. The received data is actually ignored here.
In your "production version" you will need to un-comment the line:
localStorage.setItem("quiz",JSON.stringify(ans))
The checked answers where collected in an object doing
[...document.querySelectorAll('input[type=radio]:checked')].reduce((a,{name,value}) =>(a[name]=value,a), {});
This
collects all checked radio button inputs with (document.querySelectorAll('input[type=radio]:checked')),
converts the collection of DOM elements into a proper array (with [... ])and eventually
reduce()-s its elements into an object where the element names are the property names and the (input-)element values are the property values.
And also please note that you can only store strings in local storage. Therefore I converted the ans object into a JSON string before using it in the .setItem() method.
const Q = {
quiz: [{
question: "Where was the Boston tea party?",
options: ["New York", "Detroit", "Boston", "Reno"]
}, {
question: "Where would you find Venice Beach?",
options: ["Detroit", "Venice", "Paris", "Los Angeles"]
}, {
question: "Where would you find Queens?",
options: ["London", "Paris", "Stockholm", "New York"]
}, {
question: "Where is Greenwich Village?",
options: ["London", "Paris", "Stockholm", "New York"]
}, {
question: "Where would you find the Gateway Arch?",
options: ["St. Quentin", "St. Louis", "St. Anton", "San Francisco"]
}]
}, quiz = document.getElementById("quiz");
var url = "quiz.json";
// in your productive version: comment out the following line
url = "https://jsonplaceholder.typicode.com/users/7"; // functioning test URL for fetch
function save(ev) {
ev.preventDefault();
const ans=[...document.querySelectorAll('input[type=radio]:checked')].reduce((a,{name,value}) =>(a[name]=value,a), {});
// in Stackoverflow snippets you cannot use local storage, so here is console.log instead:
console.log(ans);
// in your productive version: un-comment the following line
// localStorage.setItem("quiz",JSON.stringify(ans))
}
fetch(url).then(r => r.json()).then(object => {
// remove the following line:
object = Q; // use the static quiz from defined in Q instead ...
let json = object
let keyList = Object.keys(json.quiz);
for (let i = 0; i < keyList.length; i++) {
let key = keyList[i];
let questionItem = json.quiz[key];
let html = "<div>";
html += "<div><h2>Question " + (i + 1) + ": " + questionItem.question + "</h2></div>";
html += "<div>";
for (let i = 0; i < questionItem.options.length; i++) {
html += "<label>";
html += "<input type=\"radio\" id=\"q\" name=\"qzz" + key + "_option\" value=\"" + questionItem.options[i] + "\"> " + questionItem.options[i];
html += "</label><br>";
}
quiz.innerHTML += html;
}
quiz.innerHTML += "<input type=\"submit\" value=\"submit\">";
quiz.onsubmit=save;
});
<form id="quiz"> </form>

There is a typo on your save function. You are missing a quote after radio:
var g1 = document.querySelector('input[type="radio"]');
Also, your question is confusing but if what you are trying to do is get whether the radio is checked or not you must access the checked property and save that to localStorage. And if you want to save the state for all of the buttons then you should use querySelectorAll and save them that way instead. Example below of accessing a single input's checked value:
function save() {
// you can access it directly on this line
var g1 = document.querySelector('input[type="radio]').checked;
localStorage.setItem("g1", g1);
}
For saving them all
Lastly, it seems you are not actually calling the save() function. If your intention is to have the radios checked state saved to localStorage on click you may want to add an event to the submit button. For example:
<form id="quiz"> </form>
<script>
let object;
let httpRequest = new XMLHttpRequest();
httpRequest.open("GET", "quiz.json", true);
httpRequest.send();
httpRequest.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE) {
object = JSON.parse(this.response);
console.log(object)
}
let json = object
let quiz = document.getElementById("quiz");
let keyList = Object.keys(json.quiz);
for (let i = 0; i < keyList.length; i++) {
let key = keyList[i];
let questionItem = json.quiz[key];
let html = "<div>";
html += "<div><h2>Question " + (i + 1) + ": " + questionItem.question + "</h2></div>";
html += "<div>";
for (let i = 0; i < questionItem.options.length; i++) {
html += "<div >";
html += "<input type=\"radio\" id=\"q\" checked=\"checked\" name=\"qzz" + key + "_option\" value=\"" + questionItem.options[i] + "\">" + questionItem.options[i] ;
html += "</div>";
}
quiz.innerHTML += html;
}
quiz.innerHTML += "<input type=\"submit\" value=\"submit\">";
function save() {
// you can access it directly on this line
var g1 = document.querySelector('input[type="radio]').checked;
localStorage.setItem("g1", g1);
}
let submitButton = document.querySelector('input[type="submit"]');
submitButton.onclick = (event) => {
/* this prevents page refresh and submission to the backend which is a form default */
event.preventDefault();
// then we call the save function here
save();
};
});
If this was helpful please consider selecting as the answer

Related

how to list all local storage on page properly in javascript?

I am trying to show all my localstorage items value on my index page but for some reason it is not showing. can anyone see what I am doing wrong in my code below. In my index page script I am looping thorough the length of local storage and trying to display them on screen, only thing that display is one item. Please help. thanks for your help.
here is my code (index page script):
document.addEventListener("DOMContentLoaded", function (event) {
var dataFromLocalStorage = "";
for (var i = 0; i < localStorage.length; i++) {
dataFromLocalStorage =
dataFromLocalStorage + " " + localStorage.getItem(`key${i}`);
}
document.querySelector("#content").innerHTML = dataFromLocalStorage; // Updating same thing
})
The other script where I load it to localStorage:
var addToTheContent = document.getElementById("canvas");
var scheduleEvent = document.getElementById("scheduleStartTime");
var candidateId = document.getElementById('candsId');
var getCandId = document.getElementById("candsId");
var displayCandId = candidateId.options[candidateId.selectedIndex].value;
var id = 1;
function addTheEvent() {
var showText = addToTheContent.innerHTML = displayCandId + " ( " + scheduleEvent.value + " ) ";
localStorage.setItem(`key${id}`, JSON.stringify(showText))
id += 1
localStorage.getItem(`key${id}`);
window.location = "/";
}
"key${id}" is a template string, you need to use backticks `` instead of quotation marks "".
You could also loop through localStorage as you normally would for most JavaScript objects:
for(var key in localStorage) {
if(localStorage.hasOwnProperty(key)) { // ignore the prototype methods
// Do whatever you want with key and value found here
console.log(key + ": " + localStorage[key]);
}
}
Typo: Use i instead id
var dataFromLocalStorage = localStorage.getItem(`key${id}`);
correct:
var dataFromLocalStorage = `localStorage.getItem("key${i}");
Another thing, You are updating same innerHTML
var dataFromLocalStorage = "";
for (var i = 0; i < localStorage.length; i++) {
dataFromLocalStorage =
dataFromLocalStorage + " " + localStorage.getItem(`key${i}`);
}
document.querySelector("#content").innerHTML = dataFromLocalStorage; // Updating same thing
// do something with localStorage.getItem(localStorage.key(i));
// missing template string 'key${id}'
var id = 1;
function addTheEvent() {
var showText = displayCandId + " ( " + scheduleEvent.value + " ) ";
localStorage.setItem(`key${id}`, JSON.stringify(showText));
id += 1;
window.location = "/";
}

Javascript onmousehover event to connect information

So in my code I created a table pulling from an XML file that displayed two columns of information about plants. The goal of my program is to be able to hover over the first and print out the other information about that plant and print it in another section to the right of my table. The issue is that I am not gettign any console errors and the hover affect is not printing any information.
window.addEventListener("load", link_events);
var xhr = false;
function link_events() {
xhr = new XMLHttpRequest();
if(xhr) {
xhr.addEventListener("readystatechange", ShowFile);
xhr.open("GET", "plants.xml", true);
xhr.send();
} else {
alert("XHR not supported.");
}
}
function ShowFile() {
var i;
var title;
var cover;
var plant_table = "<table><tr><th>Common Name </th><th>Botanical Name </th></tr>";
if (xhr.readyState == 4) {
if (xhr.status == 200) {
//here we have gotten the file correctly
//loop through it and print out cover and title
var plantlist = xhr.responseXML.getElementsByTagName("PLANT");
//booklist is an array and each element is an object sub i
//so you have to use getElementBy something in order to pull the information
for (i = 0; i < plantlist.length; i++) {
var Common = plantlist[i].getElementsByTagName("COMMON")[0].firstChild.textContent;
var Botanical = plantlist[i].getElementsByTagName("BOTANICAL")[0].firstChild.textContent;
plant_table += "<tr>" +
"<td class =\"plant\">" + Common + "</td>" +
"<td>" + Botanical + "</td>" +
"</tr>";
}
plant_table += "</table>";
document.getElementById("outarea").innerHTML = plant_table;
}
var plants = document.getElementsByClassName("plant");
for (i=0; i < plants.length; i++) {
plants[i].onmouseover = HoverChoice;
}
}
function HoverChoice() {
var input = xhr.responseXML.getElementsByTagName("PLANT");
for (i = 0; i < input.length; i++) {
Common = input[i].getElementsByTagName("COMMON")[0].firstChild.textContent;
var Zone = input[i].getElementsByTagName("ZONE")[0].firstChild.textContent;
var Light = input[i].getElementsByTagName("LIGHT")[0].firstChild.textContent;
var Price = input[i].getElementsByTagName("PRICE")[0].firstChild.textContent;
if (plants == this.innerHTML) {
document.getElementById("inarea").innerHTML =
"<h1>" + Common + "</h1>" + "<br />" + "<br />" +
"Zone: " + Zone + "<br />" +
"Light: " + Light + "<br />" +
"Price: " + Price;
}
}
}
}
you could try using addEventListener method instead and see whether it works?
plants.forEach(function(plant){
plant.addEventListener("onmouseover", HoverChoice);
});
or going with the original loop you made it would be
for (i=0; i < plants.length; i++)
{
plants[i].addEventListener("onmouseover", HoverChoice);
}
I'm not anything professional, a common problem I used to encounter in these kinds of event listening functions was that calling a global function sometimes fails but making the function on the spot inside the event listener would work like addEventListener("onmouseover" , function() { return 0; });

Creating a list of students and assigning a function to each button

I am trying to allow clients to create a list of students then view more info by simply clicking on the button with the students name. I've got it to create the button and display the students name in the button but it only calls the function when I click submit to add the student to the list, the actual student button doesn't seem to function.
function updateStudentList() {
var html = "";
for (var i = 0; i < students.length; i++) {
html += "<li><button type='button' class='studentButton'" + "id=" + students[i].name +">" + students[i].name + "</button></li>";
}
$('#studentList').html(html);
for (var i = 0; i < students.length; i++) {
document.getElementById(students[i].name).addEventListener('click', openStudentInfo(students[i].name));
}
}
function openStudentInfo(studentName) {
console.log("Opening " + studentName + " info.");
var studentInfo = requestStudentByName(studentName);
if (studentInfo != null) {
var studentInfoForm = $("#studentInfoForm");
var html = "";
html += "<h3>Student Name: " + studentInfo.name + "</h3>";
html += "<h3>Student ID: " + studentInfo.studentID + "</h3>";
studentInfoForm.html(html);
$("#studentInfoModal").show();
}
}
HTML:
<ul data-role="listview" id="studentList"> </ul>
Note: I can't use the onclick tag in HTML, it causes security issues. Cordova also blocks this.
The way you binding the event is not ok. Try binding this way:
$(document).ready(function() {
$("#studentList").on("click", ".studentButton", function() {
var studentId = $(this).data("studentid");
openStudentInfo(studentId);
});
});
And in your HTML generation:
html += "<li><button type='button' class='studentButton' data-studentid='" + students[i].studentID +"'>" + students[i].name + "</button></li>";
This kind of event delagation works not metter how you create the elements inside the root element(studentList in this case), because the event was bound in it, and not on the dynamic elements.
no jquery version of DontVoteMeDown's answer
document.getElementById('studentList').addEventListener('click', function(event) {
var clickedEl = event.target;
if(clickedEl.className === 'studentButton') {
var studentId = clickedEl.dataset.studentId;
openStudentInfo(studentId);
}
});

Only show objects in array that contain a specific string

I was trying to make something where you can type a string, and the js only shows the objects containing this string. For example, I type Address1 and it searches the address value of each one then shows it (here: it would be Name1). Here is my code https://jsfiddle.net/76e40vqg/11/
HTML
<input>
<div id="output"></div>
JS
var data = [{"image":"http://www.w3schools.com/css/img_fjords.jpg","name":"Name1","address":"Address1","rate":"4.4"},
{"image":"http://shushi168.com/data/out/114/38247214-image.png","name":"Name2","address":"Address2","rate":"3.3"},
{"image":"http://www.menucool.com/slider/jsImgSlider/images/image-slider-2.jpg","name":"Name3","address":"Address3","rate":"3.3"}
];
var restoName = [], restoAddress = [], restoRate = [], restoImage= [];
for(i = 0; i < data.length; i++){
restoName.push(data[i].name);
restoAddress.push(data[i].address);
restoRate.push(data[i].rate);
restoImage.push(data[i].image);
}
for(i = 0; i < restoName.length; i++){
document.getElementById('output').innerHTML += "Image : <a href='" + restoImage[i] + "'><div class='thumb' style='background-image:" + 'url("' + restoImage[i] + '");' + "'></div></a><br>" + "Name : " + restoName[i] + "<br>" + "Address : " + restoAddress[i] + "<br>" + "Rate : " + restoRate[i] + "<br>" + i + "<br><hr>";
}
I really tried many things but nothing is working, this is why I am asking here...
Don't store the details as separate arrays. Instead, use a structure similar to the data object returned.
for(i = 0; i < data.length; i++){
if (data[i].address.indexOf(searchedAddress) !== -1) { // Get searchedAddress from user
document.getElementById("output").innerHTML += data[i].name;
}
}
Edits on your JSFiddle: https://jsfiddle.net/76e40vqg/17/
Cheers!
Here is a working solution :
var data = [{"image":"http://www.w3schools.com/css/img_fjords.jpg","name":"Name1","address":"Address1","rate":"4.4"},
{"image":"http://shushi168.com/data/out/114/38247214-image.png","name":"Name2","address":"Address2","rate":"3.3"},
{"image":"http://www.menucool.com/slider/jsImgSlider/images/image-slider-2.jpg","name":"Name3","address":"Address3","rate":"3.3"}
];
document.getElementById('search').onkeyup = search;
var output = document.getElementById('output');
function search(event) {
var value = event.target.value;
output.innerHTML = '';
data.forEach(function(item) {
var found = false;
Object.keys(item).forEach(function(val) {
if(item[val].indexOf(value) > -1) found = true;
});
if(found) {
// ouput your data
var div = document.createElement('div');
div.innerHTML = item.name
output.appendChild(div);
}
});
return true;
}
<input type="search" id="search" />
<div id="output"></div>

How can I create methods for json objects in javascript?

I've created a quiz where every question is a Question object which question has methods like print quiestion and so on. I've added my questions inside the javascript file but I want to move the questions to an external Json file.
However I can't find any article that covers how two create methods for the imported Json objects (the question objects) in this case. Here is a piece of code for the quiz object with one method before using getJson:
$(function(){
// <-- QUESTION OBJECT -->
function Question(question, choices, correctChoice, userAnswer, type) {
this.question = question;
this.choices = choices;
this.correctChoice = correctChoice;
this.userAnswer = userAnswer;
this.type = type; // either radio buttons or check boxes
// <-- write question method -->
this.writeQuestion = function() {
var questionContent;
questionContent = "<p class='question'>" + (currentQue + 1) + ". " + this.question + "</p>";
var checked = "";
if(this.type === "radio") {
for(var i=0; i < this.choices.length; i++) {
if((i+1) == this.userAnswer)
checked = "checked='checked'";
questionContent += "<p><input class='css-radio' id='radio" + (i+1) + "' " + checked + " type='radio' name='choices' value='choice'></input>";
questionContent += "<label class='css-label' for='radio" + (i+1) + "'>" + this.choices[i] + "</label></p>";
checked = "";
}
}
else {
for(var i=0; i < this.choices.length; i++) {
if ((i+1) == this.userAnswer[i])
checked = "checked='checked'";
questionContent += "<p><input class='css-checkbox' id='checkbox" + (i+1) + "' " + checked + " type='checkbox' name='choices' value='choice'></input>";
questionContent += "<label class='css-label-checkbox' for='checkbox" + (i+1) + "'>" + this.choices[i] + "</label></p>";
checked = "";
}
}
return $quizContent.html(questionContent);
};
You should create a constructor function that receives the json and defines all methods there, using the json you've provided, something rough like this:
function Question(questionJson) {
var data = questionJson;
//Public "methods" are defined to "this"
this.getCorrectAnswer = function() {
return data.correctAnswer;
};
//Private "methods
var doSomethingCrazy = function() {
return "crazy";
};
this.getSomethingCrazy = function() {
return doSomethingCrazy();
};
}
And then, lets say you have an array of questions:
var questions = [
{questionId: '1', correctAnswer: 'a', possibleAnswers: []},
{questionId: '2', correctAnswer: 'a', possibleAnswers: []},
];
You do:
var instances = [];
for (var q in questions) {
instances[q.questionId] = new Question(q);
}
This code worked:
var allQuestions = [];
var category = "history";
for(var i=0; i < jsonDataLength; i++) {
allQuestions[i] = new Question(); // create empty question Obj
var questionNr = "q" + (i+1).toString(); // store questionNr in variable
for(var properties in jsonData[category][questionNr]) // loop through questionObjs properties
allQuestions[i][properties] = jsonData[category][questionNr][properties];
// add them to empty QuestionObj
}

Categories