JavaScript event listener quiz - javascript

I am fairly new to Javascript and up until this point, have mainly been working through codecademy.com's JavaScript course, which has been great but focuses just on writing JavaScript code and not on using it for web development purposes(i.e. tying it in with HTML and CSS).
I recently got a JavaScript course from Udemy.com which does focus on usuing JavaScript for web development, which has also been great so far but there are some minor things that the instructor does which I know are not considered best practices anymore(the course may be a bit dated).
The main one is he is using HTML event handler attributes as opposed to using event listeners. I am trying to modify the code in the example to use an event listener, but so far I have had no success. I was hoping someone might be able to give a struggling newbie some insight into what I am doing wrong.
The HTML:
<!DOCTYPE html>
<html>
<head>
<title>Simple JavaScript Quiz</title>
<link rel ="stylesheet" href="css/style.css">
<script type = "text/javascript" src="js/script.js"></script>
</head>
<body>
<div id = "container">
<header>
<h1> Simple Javascript Quiz </h1>
<p> Test your knowledge in <strong>JavaScript fundamentals.</strong> </p>
</header>
<section>
<div id = "results"></div>
<form name = "quizForm" id = "qForm">
<h3>1. In which HTML element do we put in JavaScript code?</h3>
<input type = "radio" name = "q1" value = "a" id = "q1a">a. <js><br>
<input type = "radio" name = "q1" value = "b" id = "q1b">b. <script><br>
<input type = "radio" name = "q1" value = "c" id = "q1c">c. <body><br>
<input type = "radio" name = "q1" value = "c" id = "q1d">d. <link><br>
<h3>2. Which HTML attribute is used to reference an external JavaScript file?</h3>
<input type="radio" name="q2" value="a" id="q2a">a. src<br>
<input type="radio" name="q2" value="b" id="q2b">b. rel<br>
<input type="radio" name="q2" value="c" id="q2c">c. type<br>
<input type="radio" name="q2" value="d" id="q2d">d. href<br>
<h3>3. How would you write "Hello" in an alert box?</h3>
<input type="radio" name="q3" value="a" id="q3a">a. msg("Hello");<br>
<input type="radio" name="q3" value="b" id="q3b">b. alertBox("Hello");<br>
<input type="radio" name="q3" value="c" id="q3c">c. document.write("Hello");<br>
<input type="radio" name="q3" value="d" id="q3d">d. alert("Hello");<br>
<h3>4. JavaScript is directly related to the "Java" programming language</h3>
<input type="radio" name="q4" value="a" id="q4a">a. True<br>
<input type="radio" name="q4" value="b" id="q4b">b. False<br>
<h3>5. A variable in JavaScript must start with which special character</h3>
<input type="radio" name="q5" value="a" id="q5a">a. #<br>
<input type="radio" name="q5" value="b" id="q5b">b. $<br>
<input type="radio" name="q5" value="c" id="q5c">c. #<br>
<input type="radio" name="q5" value="d" id="q5d">d. No Special Character<br>
<br><br>
<input type = "submit" value ="Submit Answers">
</form>
</section>
<footer>
<p>Copyright © 2014, All Rights Reserved</p>
</footer>
</div>
</body>
</html>
The JavaScript:
function submitAnswers() {
var total = 5;
var score = 0;
//get user input
var q1 = document.forms["quizForm"]["q1"].value;
var q2 = document.forms["quizForm"]["q2"].value;
var q3 = document.forms["quizForm"]["q3"].value;
var q4 = document.forms["quizForm"]["q4"].value;
var q5 = document.forms["quizForm"]["q5"].value;
var qArray = [q1, q2, q3, q4, q5];
//reminds user to select each button if left unselected
for (var i = 0; i < qArray.length; i++) {
if (qArray[i] === null || qArray[i] === "") {
alert("You forgot to fill out question " + [i + 1]);
return false;
}
}
//set correct answers
var answers =["b", "a", "d", "b", "d"];
//check answers
for (var i = 0; i < qArray.length; i++) {
if (qArray[i] === answers[i]) {
score++;
}
}
//display results
var results = document.getElementById('results');
results.innerHTML = '<h3>You scored <span>' + score + '</span> out of <span>' + total + '</span></h3>';
return false;
};
var qForm = document.getElementById('qForm');
qForm.addEventListener('submit', submitAnswers, false);
The project is a simple HTML quiz that consists of 5 multiple choice questions.
When the submit button is clicked the code should calculate the score and write the result to an empty <div> element at the top of the page. If any question is left with an unchecked radio button, an alert window should pop up letting the user know.
The code runs fine when I use the HTML event handler attribute, but when I remove the HTML event handler and use the event lister instead I can't seem to get the code to run.

The specific issue here is that your script is referenced in the head element so it starts executing before the DOM is built and your qForm variable is null.
You will want to move the script reference to the bottom of the file. You also should add an event as a parameter to your function and call event.preventDefault() early on, so that your form does not end up submitting inadvertently if the return false is not reached for some reason.
Finally, you are not reading the radio button checked status correctly, but since you are learning I would leave that for you to figure.

Since you are using addEventListener prevent form submission with preventDefault method:
function submitAnswers(e) {
e.preventDefault();
// rest of the code ...
}
In your previous version when you used inline event registration onsubmit="return submitAnswers()" you could use simple return false to do the same.
Demo: http://jsfiddle.net/7xggt9ky/

Related

How can i retrieve this value using an alert box?

On my website i have a html file with the following configuration:
<script>
window.Conf.page = window.Conf.page || {};
$.extend(Conf.page, {"newNotifications":false,"userId":"125"}
</script>
In the same page i need to retrieve the value of userId using a script and display it into an alert box. I tried using this script:
<script>
alert(document.getElementsByName('userId'))
</script>
But i'm getting [object NodeList] inside the alert box.
What code could i use to get the value of userId inside the alert box?
Try like this:
alert(window.Conf.page.userId);
<script>
window.Conf.page = window.Conf.page || {};
var json = $.extend(Conf.page, {"newNotifications":false,"userId":"125"});
alert(json.userId);
</script>
or
<script>
window.Conf.page = window.Conf.page || {};
Conf.page = $.extend(Conf.page, {"newNotifications":false,"userId":"125"});
alert(Conf.page.userId);
</script>
This gets the value property of the element in the node list, the node list is a list of all the nodes with the name property matching the one you pass in, in the off chance you had two input fields with the name property being the same their index would be 0 and 1 respectively.
document.getElementsByName('userId')[0].value
I think what you are looking for is the getElementById if an looking for an HTML tag, or in your case here simply window.Conf.page.userId to get the value.
window.pageConf = window.pageConf || {};
$.extend(pageConf, {"newNotifications":false,"userId":"125"});
function onTestClick() {
var a = document.getElementsByName('userId');
document.getElementById('myLabelId').innerText = a.length;
// Result: 0
document.getElementById('myLabelId').innerText += " " + window.pageConf.userId;
// Result: 125
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button onclick="onTestClick()">Test</button><br/><br/>
<label id="myLabelId"></label>
Having said that, let's talk about "name" in a tag.
getElementsByName returns an array because Name is not unique to an element. Name is used for mainly 2 things:
For postback: When submitting a form, the value of input is posted with the "name" in the tag. For example:
Comments: <input id='myUniqueLocalId' name='comments' />
To group radio buttons or checkboxes together. Small example:
function onTestClick() {
var q1 = document.getElementsByName('q1');
document.getElementById('myLabelId').innerText += " " + q1.length + " " + q1[0].value + " " + q1[1].value;
// Result: 2 Yes No
}
Question 1:
<input type="radio" id="Yes" name="q1" value="Yes" checked>
<label for="Yes">Yes</label><be>
<input type="radio" id="No" name="q1" value="No">
<label for="No">No</label><br>
Question 2:
<input type="radio" id="Yes" name="q2" value="Yes">
<label for="Yes">Yes</label><be>
<input type="radio" id="No" name="q2" value="No" checked>
<label for="No">No</label><br>
<button onclick="onTestClick()">Test</button><br/><br/>
<label id="myLabelId"></label>

JavaScript read radio button value in IE and FireFox

I have a simple web form that uses JavaScript for building a POST statement. In Chrome, I can use a simple line of code...
var form = document.forms['myForm'];
var env = form.env.value;
The form itself looks like this...
<form name="myForm" action='JavaScript:xmlhttpPost("/path/to/some/pythoncode.py")'>
<input type="radio" name="env" id="env" value="inside">Inside
<input type="radio" name="env" id="env" value="outside" checked="checked">Outside
<input type="radio" name="env" id="env" value="both">Both
<input type="radio" name="env" id="env" value="neither">Neither
I have some text boxes on the form that I can use the same technique to find the value (
var name = form.fname.value
with a
<input type="text" name="fname" id="fname">
However, when I submit the form and build my post, the value for the radio buttons is always undefined. It works fine in Chrome, but nothing in IE or FireFox.
I tried var env = document.getElementById('env').value, but for some reason that always defaults to the first value (inside) no matter what I select. That method also does not return a value when using Chrome.
Is there something I'm missing for reading the checked value of a radio input in FF or IE?
Try this
function getValueFromRadioButton(name) {
//Get all elements with the name
var buttons = document.getElementsByName(name);
for(var i = 0; i < buttons.length; i++) {
//Check if button is checked
var button = buttons[i];
if(button.checked) {
//Return value
return button.value;
}
}
//No radio button is selected.
return null;
}
IDs are unique so you should not use the same ID for multiple items. You can remove the all the radio button IDs if you use this function.
You are using the same ID for multiple Elements, ID is unique for element on the page.
use different IDs.
edit: names can be the same. because then the radio buttons are as a group.
As stated, the IDs should be different to be valid, but you could accomplish this by eliminating the IDs all together and using just the input name:
var form = document.forms['myForm'];
var radios = form.elements["env"];
var env = null;
for(var i=0;i<radios.length;i++) {
if(radios[i].checked == true) {
env = radios[i].value;
}
}
<form name="myForm">
<input type="radio" name="env" value="inside">Inside
<input type="radio" name="env" ivalue="outside" checked="checked">Outside
<input type="radio" name="env" value="both">Both
<input type="radio" name="env" value="neither">Neither
</form>
Short & clear on ES-2015, for use with Babel:
function getValueFromRadioButton( name ){
return [...document.getElementsByName(name)]
.reduce( (rez, btn) => (btn.checked ? btn.value : rez), null)
}
console.log( getValueFromRadioButton('payment') );
<div>
<input type="radio" name="payment" value="offline">
<input type="radio" name="payment" value="online">
<input type="radio" name="payment" value="part" checked>
<input type="radio" name="payment" value="free">
</div>
You can try this:
var form = document.querySelector('form#myForm');
var env_value = form.querySelector('[name="env"]:checked').value;

How to render text from javascript object in HTML form

I have an array containing two objects:
var questions = [{question: "Is the sky blue?", choices: ["Yes", "No"], correctAnswer:0},{question: "Is water wet?", choices: ["Yes", "No"], correctAnswer:0}]
I have some javascript to make the questions render on the screen with HTML:
<script>
function askQuestion(x){
var questiontest = document.getElementById('question');
questiontest.innerHTML = x.question;
}
function loop(){
for(i = 0; i < questions.length; i++){
askQuestion(questions[i]);
}
}
left some stuff out here, not that relevant to question
addEventListener('load',loop);
</script>
My HTML looks like this, displays the current question but not the text of the choices found in the questions object:
<label for="choice" id="question"></label>
<br><input type="radio" id="choice_1" name="choice" value="1"></input>
<br><input type="radio" id="choice_2" name="choice" value="2"></input>
Using this code I can render the question and then two radio buttons i.e. without the text of the choices. Is there anyway that I can render the text of the choices from the questions object next to the radion buttons? or do I have to do something stupid like this to make it render correctly?
<br><input type="radio" name="choice" value="1"><p id="choice_1"></p></input>
I'm trying to do it with vanilla javascript at the moment and will research doing in with jQuery shortly.
Thanks any help appreciated!
Re-structure your HTML so you can label the inputs individually, then it becomes easy
HTML
<form id="qform" action="">
<fieldset>
<legend id="l0"></legend>
<label id="l1" for="c1"></label>
<input id="c1" type="radio" name="choice" value="1" />
<br />
<label id="l2" for="c2"></label>
<input id="c2" type="radio" name="choice" value="2" />
</fieldset>
</form>
JavaScript
function questionFactory() {
var i = 0,
l0 = document.getElementById('l0'),
l1 = document.getElementById('l1'),
l2 = document.getElementById('l2');
return function askQuestion() {
if (i >= questions.length) return false;
l0.textContent = questions[i].question;
l1.selected = false;
l1.textContent = questions[i].choices[0];
l2.selected = false;
l2.textContent = questions[i].choices[1];
++i;
return true;
}
}
var ask = questionFactory();
ask(); // asks q1, returns true
ask(); // asks q2, returns true
ask(); // returns false, there were no more questions to ask
DEMO

How to define textfield and radio button listeners in JavaScript

So for a class project I have to make this simple calculator, which was very easy to do. However, I'm required to define my event listeners in JavaScript instead of using something like:
onclick="compute()"
But I need the result of my calculator to update whenever I change a value in my field or select any of the radio buttons. How can I do this? The code I have now is not working.
<script>
function compute(){
var functionSelected = document.getElementsByName("function");
var valueOne = Number(document.getElementById("fielda").value);
var valueTwo = Number(document.getElementById("fieldb").value);
var ans = 0;
if(functionSelected[0].checked){
ans = (valueOne+valueTwo);
}
if(functionSelected[1].checked){
ans = (valueOne-valueTwo);
}
if(functionSelected[2].checked){
ans = (valueOne*valueTwo);
}
if(functionSelected[3].checked){
ans = (valueOne/valueTwo);
}
if(ans>=9007199254740992){
document.getElementById("solution").textContent = "ERROR NUMBER TO LARGE TO BE COMPUTED";
}
else{
document.getElementById("solution").textContent = "Equals: " + ans;
}
}
document.getElementById("fielda").addEventListener("change", compute(), false);
document.getElementById("fieldb").addEventListener("change", compute(), false);
document.getElementByName("function").onclick = compute();
</script>
</head>
<body>
<p>
<input type="number" id="fielda"/><br />
<input type="number" id="fieldb"/><br />
<label><input name="function" type="radio" value="add"/> Add</label><br />
<label><input name="function" type="radio" value="subtract"/> Subtract</label><br />
<label><input name="function" type="radio" value="multiply"/> Multiply</label><br />
<label><input name="function" type="radio" value="divide"/> Divide</label><br />
</p>
<p>
<output id="solution">Solution Will Appear Here</output>
</p>
</body>
You can use
<select ... onchange="javascript:compute();">
There are a lot of events that you can use in response to different events depending on the control.
They are named onmouseover, onclick, onchange, etc. and you can assign a javascript function to each one if you want.
Another alternative is to use you following syntax:
document.getElementById("id_of_select_control").onchange = function() {
// your code here
}
Or if you use jQuery in your project, something like this:
$("#id_of_select_control").change(function() {
// your code here
});

Change an onclick value with javascript

I'm pretty new to JS and maybe this is a very banal questions but I still can't figure out what's wrong. I have this simple html code:
<span>1</span>
<input id="check1" type="radio" value="a1"/>
<span>2</span>
<input id="check2" type="radio" value="b2"/>
<span>3</span>
<input id="check3" type="radio" value="c3"/>
<span>4</span>
<input id="check4" type="radio" value="a4"/>
<span>5</span>
<input id="check5" type="radio" value="b5"/>
<input id="red" type="button" value="Go" onclick=""/>
What i would like to achieve is, based on the radio checked change the onclick property.
For example, if check1 and check2 are checked go to google.com, if check1 and check3 go to jsfiddle.net etcetera. So I wrote a simple Javascript:
window.onchange = function redirect(){
if (document.getElementById('check1').checked && document.getElementById('check2').checked) {
location.href='www.google.com';
// document.getElementById('red').onclick="www.google.com"
}
else if (document.getElementById('check1').checked && document.getElementById('check3').checked) {
location.href='www.jsfiddle.net';
// document.getElementById('red').onclick="window.open('www.jsfiddle.net')"
}
}
Here You can find a JS Fiddle.
What I thought to do was to set the onclick property like I did with an image, using getElementById and then setting his source, so I wrote document.getElementById('red').onclick="window.open('random page')" but for some reason that I can't understand it doesn't work.
Questions:
1) As you can see in my code i wrote a location.href='address' that obviously doen't wait for the user to click the button, so that's not a solution, how can I make this work?
2)Is there a way to make this piece of code more scalable? What I mean is, in the future if I want to add another radio, I would have to modify manually the code and insert another else if, I thought about something like:
var radio = document.getElementByName('radio') //not sure if this is the right getElement
for (var i=1; i<radio.lenght; i++){
if radio[i].checked{ //is this right?
for (var n=i+1; n<radio.lenght; n++){
if radio[n].checked{
document.getElementById('red').onclick="window.open('random page')"
}
}
}
Any suggestion to my code is welcome.
​
Try out this in JS Fiddle. It contains how you can listen the onclick event of a button and to get the checked value of a radio button.
HTML part:
<form action="">
<input type="radio" name="vehicle" value="Yes" id='yes'>Yes<br>
<input type="radio" name="vehicle" value="No" id='no'>No
</form>
<input id="red" type="button" value="let's go"/>
JS part:
document.getElementById('red').onclick = function() {
if (document.getElementById('yes').checked) {
alert('I have a Vehicle.');
} else if(document.getElementById('no').checked) {
alert('I don\'t have a Vehicle.');
} else {
alert('No answer.');
}
}
If you use radio buttons, and you want only one to be selectable to the user at a time you have to set the same name attribute to them.
You can also make use of the value property of radio buttons for storing the redirection URL.
Here is a more useful example for you.
HTML part:
<form action="">
<input type="radio" name='redirect' value='https://www.google.com/' id='google'>Google<br />
<input type="radio" name='redirect' value='http://www.jsfiddle.net/' id='jsFiddle'>JS Fiddle<br />
<input type="radio" name='redirect' value='https://www.facebook.com/' id='Facebook'>Facebook
</form>
<input id="red" type="button" value="let's go"/>
JS part:
document.getElementById('red').onclick = function() {
var options = document.getElementsByName('redirect'),
length = options.length,
i = 0;
for (i; i < length; i++) {
if (options[i].checked) {
window.open(options[i].value);
}
}
}
if (document.getElementById('check1').checked&&document.getElementById('check2').checked)
{
document.getElementById('red').onclick=function(){
window.location.href ='http://www.google.com';
};
}
This code binds the function to the onclick event of element with id='red'. So add a bunch of such conditions and change the onclick binding whenever any radio button is checked/unchecked.

Categories