I am working on a very simple quiz javascript project, with a score and a start button, that generates questions when it gets clicked. I started work in the JS code by adding an onclick event listener, but it is not working as expected. Here is the code snippet that is supposed to be working but doesn't work, with a few comments. Keep in mind that I am very inexperienced in Javascript, so I may have misused some JS methods.
function rng() {
return Math.floor(Math.random * 10)
}
let stbt = document.getElementById("start")
stbt.addEventListener("click", function() {
stbt.remove //should remove the start button when it gets clicked.
let q = document.createElement("p") //created an html paragraph.
switch(rng()) {
case 1:
let qc = document.createTextNode("What is the capital of Chile?")
q.appendChild(qc) /*this should theoretically insert text into the html paragraph that gets created when the start button gets clicked,
the switch statement that is switching the simple rng function should make it so that questions get generated randomly.*/
break;
case 2:
let qc = document.createTextNode("What is the highest mountain in Britain?")
q.appendChild(qc)
break;
case 3:
let qc = document.createTextNode("What is the smallest country in the world?")
q.appendChild(qc)
break;
case 4:
let qc = document.createTextNode("Alberta is a province of which country?")
q.appendChild(qc)
break;
case 5:
let qc = document.createTextNode("How many countries still have the shilling as currency?")
q.appendChild(qc)
break;
case 6:
let qc = document.createTextNode("Which is the only vowel not used as the first letter in a US State?")
q.appendChild(qc)
break;
case 7:
let qc = document.createTextNode("What is the largest country in the world?")
q.appendChild(qc)
break;
case 8:
let qc = document.createTextNode("Where would you find the River Thames?")
q.appendChild(qc)
break;
case 9:
let qc = document.createTextNode("What is the hottest continent on Earth?")
q.appendChild(qc)
break;
case 0:
let qc = document.createTextNode("What is the longest river in the world?")
q.appendChild(qc)
break;
}
})
It is not the listener at fault here, but a number of small errors that are causing your code not to work.
You are not calling two functions: Math.random should be Math.random(), and stbt.remove should be stbt.remove().
Because of the way you have written your switch your qc variable is scoped across all your case statements, so you can't declare it again. You can fix this by either declaring it outside of the switch and assigning it in the case statements, or using braces to scope the variable to each case.
let qc; //<--- declare qc;
switch (rng()) {
case 1:
qc = document.createTextNode("What is the capital of Chile?")
...
break;
case 2:
qc = document.createTextNode("What is the highest mountain in Britain?")
...
or
switch (rng()) {
case 1: { //<--- braces to scope variable declaration
let qc = document.createTextNode("What is the capital of Chile?")
...
break;
}
case 2: {
let qc = document.createTextNode("What is the highest mountain in Britain?")
...
break;
}
case 3: {
...
Lastly, you never append your <p> element to the DOM. You'll need to either query an element to append to, or as in the example below, append directly to the document.body
The switch statement tends to be quite verbose and so it helps to avoid duplication as much as possible. Instead of appending the new text node within each case you can instead move it after the switch and call it just once.
stbt.addEventListener("click", function () {
...
let qc;
switch (rng()) {
case 1:
...
}
// Avoid duplication by appending once at the end
q.appendChild(qc)
document.body.appendChild(q) //<--- append <p> to DOM
});
function rng() {
return Math.floor(Math.random() * 10); //<--- parentheses needed to call function;
}
const stbt = document.getElementById("start");
stbt.addEventListener("click", function () {
stbt.remove(); //<--- parentheses needed to call function;
let q = document.createElement("p");
let qc; //<--- declare qc;
switch (rng()) {
case 1: {
let qc = document.createTextNode("What is the capital of Chile?")
break;
}
case 2:
qc = document.createTextNode("What is the highest mountain in Britain?")
break;
case 3:
qc = document.createTextNode("What is the smallest country in the world?")
break;
case 4:
qc = document.createTextNode("Alberta is a province of which country?")
break;
case 5:
qc = document.createTextNode("How many countries still have the shilling as currency?")
q.appendChild(qc)
break;
case 6:
qc = document.createTextNode("Which is the only vowel not used as the first letter in a US State?")
break;
case 7:
qc = document.createTextNode("What is the largest country in the world?")
break;
case 8:
qc = document.createTextNode("Where would you find the River Thames?")
q.appendChild(qc)
break;
case 9:
qc = document.createTextNode("What is the hottest continent on Earth?")
break;
case 0:
qc = document.createTextNode("What is the longest river in the world?")
break;
}
// Avoid duplication by appending once at the end
q.appendChild(qc)
document.body.appendChild(q) //<--- append <p> to the DOM
});
<button type="button" id='start'>Start</button>
Making it more general
Using a switch can be very clear in showing what is happening, but it does lead to a lot of duplication. If you wanted to add a question you would need to add a whole new case statement as well as change the constant within your rng() function. To avoid this you might want to think about other structures that might serve your purpose.
Here is an example using an Array to store the questions which is accessed by index using the returned value from the rng() (which has been changed to accept a max value). With this structure, adding a question is simply a matter of adding to the array, the rest takes care of itself.
function rng(max) {
return Math.floor(Math.random() * max)
}
const questions = [
"What is the capital of Chile?",
"What is the highest mountain in Britain?",
"What is the smallest country in the world?",
"Alberta is a province of which country?",
"How many countries still have the shilling as currency?",
"Which is the only vowel not used as the first letter in a US State?",
"What is the largest country in the world?",
"Where would you find the River Thames?",
"What is the hottest continent on Earth?",
"What is the longest river in the world?",
]
const stbt = document.getElementById("start")
const div = document.getElementById("questions")
stbt.addEventListener("click", function () {
// pass the length of the questions array as the max value for the rng()
const questionIndex = rng(questions.length);
const question = questions[questionIndex];
stbt.remove();
const q = document.createElement("p");
const qc = document.createTextNode(question)
q.appendChild(qc)
div.appendChild(q)
});
<button type="button" id='start'>Start</button>
<div id='questions'></div>
Related
I'm working on a Mass Effect personality quiz that has been adapted from the EasyDamus D&D quiz from the 90s, and I'm having trouble with the results page. Namely, I'm trying to include an image to match each result, but I don't know how to do so when the code implements the results using a switch statement. Here is a snippet of the code:
var win = window.open("", "win","width=900,height=550,top=25,left=50,toolbar=yes,menubar=yes,scrollbars=yes,resizable=yes,location=yes");
with (win.document) {
open("text/html", "replace");
write("<html><head><link rel='stylesheet' type='text/css' href='index.css'><title>Your Results Are In!\<\/title>\<\/head>");
write("<body text='#FFFFFF' font-family='massEffect' link='#5555FF' vlink='#6666EE' bgcolor='#F2ECDA' background='images/space.png'>");
write("<center><h2><b><font color='#FFFFFF'>You Are A:\<\/font>\<\/b>\<\/h2>\<\/center>");
write("<br><center><h1><b>");
switch (race) {
case "human": write("Human\<\/b> "); break;
case "asari": write("Asari\<\/b> "); break;
case "turian": write("Turian\<\/b> "); break;
case "salarian": write("Salarian\<\/b> "); break;
case "krogan": write("Krogan\<\/b> "); break;
case "quarian": write("Quarian\<\/b> "); break;
case "geth": write("Geth\<\/b> "); break;
case "volus": write("Volus\<\/b> "); break;
case "rachni": write("Rachni\<\/b> "); break;
case "batarian": write("Batarian\<\/b> "); }
switch (primclass) {
case "soldier": write(" Soldier"); break;
case "infiltrator": write(" Infiltrator"); break;
case "engineer": write(" Engineer"); break;
case "adept": write(" Adept"); break;
case "sentinel": write(" Sentinel"); break;
case "vanguard": write(" Vanguard"); }
switch (secclass) {
case "soldier": write("/Soldier"); break;
case "infiltrator": write("/infiltrator"); break;
case "engineer": write("/Engineer"); break;
case "adept": write("/Adept"); break;
case "sentinel": write("/Sentinel"); break;
case "none": write(""); break;
case "vanguard": write("/Vanguard"); }
write("<br><h2><br>Race:<br></h2>");
switch (race) {
case "human": `
The last line is the flavor text for each result, and while there's no issue with how it displays, I'm trying to find a way to have an image precede it. I have the pictures available, most of them in array called from a local folder. What would be the best way to have the images appear?
I've searched for solutions for a few weeks, most of which recommend event listeners, but I haven't been able to get it to work for me.
This code does a lot of stuff. First of all with switch statement, it should set up some variable for a particular case. Also its always a good practice to provide a default case for each switch-statement.
function decideOnRace(race) {
let result = '';
switch (race) {
case "human":
result = "Human\<\/b> ";
break;
default:
result = 'something else";
break;
}
}
// place this accordingly
const raceTextToWrite = decideOnRace(race);
write(raceTextToWrite);
Following this practice for all the different cases should help you progress e.g., for secclass, primclass, etc.
So I have been working on a Discord bot for my server for a few days using Node.js and am brand new to JS. I am trying to convert some of the code from a Magic 8 Ball completed after a model for a tutorial to JS to Implement as a function (just the random number and case switch).
This is from the C# Project:
switch (random.Next(4))
{
case 0:
Console.WriteLine("YES");
speechSynthesizer.Speak("Yes");
break;
case 1:
Console.WriteLine("NO");
speechSynthesizer.Speak("No");
break;
case 2:
Console.WriteLine("HELL NO");
speechSynthesizer.Speak("Hell no");
break;
case 3:
speechSynthesizer.Speak("Hell yes");
Console.WriteLine("HELL YES");
break;
}
and this is in what I am trying to implement:
switch( Math.random.Next(4)) {
case 0:
msg.channel.send('Yes');
break;
case 1:
msg.channel.send('No');
break;
case 2:
msg.channel.send('Hell yes!');
break;
case 3:
msg.channel.send('Hell No!');
break;
}
I am essentially trying to add a part where you can send "Magic 8 Ball", and it will return a Yes/No/Hell Yes/Hell No.
Edit:
So I followed the advice of a comment, and switched "case" to all lowercase in each instance. The error I recieve now is that math is undefined. Another article just suggested switching math to Math. next is not a function.
If your problem is generating a random int to use in your switch, you'll need to know how to generate a pseudorandom int in the first place.
Math.random generates a a float in the range of [0, 1)
So you'll need to take that value, multiply it by your max, and then floor it to turn it in to an integer.
Math.floor(Math.random() * max)
Your final code would look like this:
switch(Math.floor(Math.random() * 4))) { // 4 is maximum n of options
case 0:
msg.channel.send('Yes');
break;
case 1:
msg.channel.send('No');
break;
case 2:
msg.channel.send('Hell yes!');
break;
case 3:
msg.channel.send('Hell No!');
break;
}
I'm trying to swap the background-color of some specific divs basing on their content.
Their background-color should swap when their input is like "Lifestyle" or "Politics" or "Economy" or "Local" or "Sports" or "News".
var colorInput = document.getElementById('views-field-field-section').textContent;
switch (colorInput) {
case 'Lifestyle':
document.getElementById('views-field-field-section').style.backgroundColor = '#9518b8';
break;
case 'Local':
document.getElementById('views-field-field-section').style.backgroundColor = '#009fe3';
break;
case 'Sports':
document.getElementById('views-field-field-section').style.backgroundColor = '#95c11f';
break;
case 'Economy':
document.getElementById('views-field-field-section').style.backgroundColor = '#d40d10';
break;
case: 'Politics':
document.getElementById('views-field-field-section').style.backgroundColor = '#ffcc00';
break;
default:
break;
}
http://jsfiddle.net/gFN6r/501/
You cannot use ids more than once in an html document. This would be invalid html. I have changed the id to a class, and then used the following code and it works:
var colorInput = document.getElementsByClassName('views-field-field-section');
for(i=0; i<colorInput.length; i++) {
var colorInputText = colorInput[i].textContent.trim();
switch (colorInputText) {
case 'Lifestyle':
colorInput[i].style.backgroundColor = '#9518b8';
break;
case 'Local':
colorInput[i].style.backgroundColor = '#009fe3';
break;
case 'Sports':
colorInput[i].style.backgroundColor = '#95c11f';
break;
case 'Economy':
colorInput[i].style.backgroundColor = '#d40d10';
break;
case 'Politics':
colorInput[i].style.backgroundColor = '#ffcc00';
break;
default:
text ='Nix!';
}
}
Here is the jsfiddle:
http://jsfiddle.net/gFN6r/505/
Oh man. Don't use the same id :) But if it is necessary, ok...
I adjusted a little bit your source code, e.g. there was some syntax error, and added jQuery, hope it's not a problem :)
If you use the same id, this will not work - $('#myid'), but this will - $('[id=myid]')
Don't forget to use trim-like function to remove trailing spaces.
And please think a little about how to avoid the same id in your code.
http://jsfiddle.net/gFN6r/506/
$('[id=views-field-field-section]').each(function() {
var text = $(this).text();
text = $.trim(text);
switch (text) {
case 'Lifestyle':
$(this).css({backgroundColor: '#9518b8'});
break;
case 'Local':
$(this).css({backgroundColor: '#009fe3'});
break;
case 'Sports':
$(this).css({backgroundColor: '#95c11f'});
break;
case 'Economy':
$(this).css({backgroundColor: '#d40d10'});
break;
case 'Politics':
$(this).css({backgroundColor: '#ffcc00'});
break;
default:
$(this).text('Nix!');
break;
}
});
Here you have it using jQuery to simplify plunker.
The id is set on the containing parent, while you need to iterate over the children and to check for their content. Note that I've used .trim() to eliminate start and trailing spaces so the match case would catch.
Enumerate use abs 1 -1 =0 -1 = -1(abs) gets you back to 1 so if you start with $case=1 and just -1 as an absolute value you will tick tock between 1 & 0 either way you always subtract 1
I have a problem with writing my code dynamic. I am doing a course in javascript programming and I am having some struggles with the final part of one assignment.
Exercise 8.2
Extend your switch-case statement with a default value. The result should
be 'That is an unknown fruit.' when the variable 'myFruit' has an unknown
value. Answer with the result where 'myFruit = pear'.
Write your code below and put the answer into the variable ANSWER.
var myFruit = "pear";
switch (myFruit) {
case "banana":
console.log("The banana is yellow.");
break;
case "apple":
console.log("The apple is green.");
break;
case "kiwi":
console.log("The kiwi is green.");
break;
case "plum":
console.log("The plum is purple");
break;
default:
console.log("That is an unknown fruit.");
break;}
How do I formulate this result in a variable?
I have tried to write like this:
var result = switch (myFruit);
But that does not work.
You can declare the result variable, and inside the switch statement cases, instead of console.logging the result, you can assign the value to the result variable, like so:
var myFruit = "pear";
var result;
switch (myFruit) {
case "banana":
result = "The banana is yellow.";
break;
case "apple":
result = "The apple is green.";
break;
case "kiwi":
result = "The kiwi is green.";
break;
case "plum":
result = "The plum is purple";
break;
default:
result = "That is an unknown fruit.";
break;
}
http://jsfiddle.net/uqxtmc25/
I won't write out all the code for you, but point you in the right direction. You need to set the text in a variable and return it:
switch ..
case "something":
var message = "Your message here.";
break;
...
Once your switch sets the value, then you use it as you need to.
You cannot return a value from a switch statement by using the switch statement like an operation.
You can not call the switch statement like var result = switch (myFruit);, it is not a function. You would have to move all the switch case code into a function:
function mySwitchCase(fruit){
var returnResult='';
switch (fruit) {
case "banana":
returnResult="The banana is yellow.";
break;
case "apple":
returnResult="The apple is green.";
break;
case "kiwi":
returnResult"The kiwi is green.";
break;
case "plum":
returnResult"The plum is purple";
break;
default:
returnResult"That is an unknown fruit.";
break;
}
return returnResult;
}
then you can call it like this:
var result = mySwitchCase(myFruit);
You can save the result in a variable answer and then use that variables to print out the result;
function fruitSwitcher (myFruit) {
var answer = "That is an unknown fruit.";
switch (myFruit) {
case "banana":
answer = "The banana is yellow.";
break;
case "apple":
answer = "The apple is green.";
break;
case "kiwi":
answer ="The kiwi is green.";
break;
case "plum":
answer = "The plum is purple";
break;
default:
// no really needed
answer ="That is an unknown fruit.";
break;
}
return answer;
}
var myFruit = "pear";
var answer = fruitSwitcher(myFruit);
console.log(answer); //That is an unknown fruit.
The default case in the previous code is superfluous as the variable answer is initialised to a default value. If an unknown fruit in passed in input, none of the switch cases matches it and, therefore, the answer variables never changes value and the function returns the default value.
I have the following HTML:
<select id="rankBox">
<option value="0">100</option>
<option value="1">150</option>
<option value="2">200</option>
<option value="3">250</option>
<option value="4">300</option>
<option value="5">350</option>
<option value="6">400</option>
</select>
<input type="Submit" id="button1" value="Generate" onclick="doStuff()">
and the following Javascript:
function doStuff() {
var choice = $("#rankBox option:selected").val();
console.log(choice);
switch (choice) {
case 0:
case 1:
colorQ = "^7";
break;
case 2:
colorQ = "^L";
break;
case 3:
colorQ = "^A";
break;
case 4:
colorQ = "^8";
break;
case 5:
colorQ = "^+";
break;
case 6:
colorQ = "^<";
break;
default:
alert("Something went wrong");
break;
}
alert(colorQ);
}
In short, I have a switch statement which is supposed to check the value of the option the user has selected. As you may see, I have added console.log to see if the problem is with acquiring the user's input, but that is not the issue. The issue is the switch statement, which just does not work.
Am I using wrong syntax or something?
jsFiddle: http://jsfiddle.net/3qTHW/2/ (jsFiddle doesn't work in my browser at all, says doStuff() is not defined)
Thanks in advance.
It's not an integer, it's a string, as all values from an element are strings.
You'll have to either parse it as an integer :
function doStuff() {
var choice = parseInt( $("#rankBox option:selected").val(), 10);
....etc
or change the switch to work with strings (you should be trimming)
switch ( $.trim(choice) ) {
case '0':
case '1':
....etc
This was an easy problem, by looking at the code one could see that the line var choice = $("#rankBox option:selected").val(); is adding string to variable choice. And that is the reason none of the case statements worked and the default code executed.
The best way not to run into such problems is to "Debug" your JavaScript code properly. This will save you a lot of precious time and you will find the root cause to each problem yourself.
To debug your code, you can use Firebug extension in Firefox. This will actually stop the code execution for you and guide you line by line telling you the state of each variable at every line of code. So in case of your problem, all I did was add your code in .html file and ran it in Firefox with "Debugger" points specified. The JS code looked like this.
function doStuff() {
var choice = $("#rankBox option:selected").val();
debugger; // This is the point where the debugging starts
console.log(choice); // console.log wont help as it did not tell me the type
switch (choice) { // Here Firebug tells me that choice is actually a string
case 0:
case 1:
colorQ = "^7";
break;
case 2:
colorQ = "^L";
break;
case 3:
colorQ = "^A";
break;
case 4:
colorQ = "^8";
break;
case 5:
colorQ = "^+";
break;
case 6:
colorQ = "^<";
break;
default:
alert("Something went wrong");
break;
}
alert(colorQ);
}
Note I put a "debugger" above console.log(). From this point onward, the code stopped at each line and I could see the value in each variable. This helped me notice string value in choice.
Happy Debugging :)
Use javascript parseInt() method like this :
var choice = parseInt($("#rankBox option:selected").val());