javascript arrays and looping - javascript

I'm jessi and I'm a web development student. I'm trying to write a program with arrays and I'm stuck. I have an array of phrases and when a user enters a number between 1 and 10 it is supposed to show that many phrases on the screen but I'm stuck. I don't know how to display multiple results on the screen. I'd really appreciate any help. Thanks.
<!DOCTYPE html>
<html>
<head>
<title>Get A Response</title>
</head>
<body>
<form>
<h1>Select how many phrases you want displayed.</h1>
<input type="number" class="userInput"></input>
<button type="submit" value="submit" onclick="showme()"></button>
</form>
<div class="myphrases">
</div>
<script src="js/main.js"></script>
</body>
</html>
////////////////// Javascript
function showme() {
var number = document.querySelector('.userInput').value;
var display = "";
var phrases = [
"Hello there",
"What's up Doc",
"Because I said so",
"Say it again",
"It's a celebration",
"Enjoy yourselves",
"Welcome",
"Where did you go", "Why you crying", "Stop playing"];
var random = Math.floor(Math.random() * phrases.length);
for(var i = 0; i < phrases.length; i++) {
}
}

First, you should set up an HTML element that will serve as your output area. An empty div element is a good choice. You've already done that with: <div class="myphrases"></div>.
Next, the HTML input element does not get a closing tag (</input>) and instead of using a submit button, just use a regular button (since you are not actually submitting data anywhere).
Also, don't use inline HTML event handling attributes (onclick, onmouseover, etc.) as they:
Create spaghetti code that leads to duplication and makes the code harder to read.
Causes global anonymous wrapper functions to be created around your attribute's value and change the this binding in your callback functions.
Don't follow the W3C Event standard of using .addEventListener().
Next, don't have your loop go over every phrase (phrases.length). Only have it go for the amount of times the user has entered.
Finally, you can update the div output area by adjusting its innerHTML to be a string that you build up from your loop:
// Get reference to the text box, the button and the output area
var number = document.querySelector('.userInput');
var btn = document.querySelector("button");
var output = document.querySelector(".myphrases");
// Set up the event handling function for the button
btn.addEventListener("click", showme);
function showme() {
var display = "";
var phrases = [
"Hello there",
"What's up Doc",
"Because I said so",
"Say it again",
"It's a celebration",
"Enjoy yourselves",
"Welcome",
"Where did you go", "Why you crying", "Stop playing"];
// String to hold loop results
var result = "";
// Set up the upper limit for the loop.
// If the entered value is greater than the length of the array, use the length
// of the array. If not, use the value entered by the user
var count = number.value > phrases.length ? phrases.length : number.value;
for(var i = 0; i < count; i++) {
var random = Math.floor(Math.random() * phrases.length);
result += phrases[random] + "<br>";
}
// Inject the string into the output area
output.innerHTML = result;
}
<form>
<h1>Select how many phrases you want displayed.</h1>
<input type="number" class="userInput">
<button type="button">Submit</button>
</form>
<div class="myphrases"></div>

Related

Challenging Javascript Comparison Issue (always returning false) | tested/researched before posting

This is my very first post ever so please forgive me for any indiscretions! I am almost at my wits end, as I have been at this for several hours now, I believe to have thoroughly done my research and tried quite a bit of solutions. I am also kind of new at programming but consider myself a quick learner!
In the below code, I am trying to compare the "buttonClicked" variable which gets the this.innerText value from the button that has been clicked on the page to the "triviaAnswer" variable which receives its value the from array "arrayOfTrivias[j].answer" which pulls its value from the current index object in the triviaArray.
Even though I can console.log both the values and they both show to be the same value, whenever they hit my if statement, all buttons will either return a false match (even the button that matches) to the "triviaAnswer" or a true match (even buttons that don't match) to the "triviaAnswer" depending on the comparison property being ran.
I have tried the following with no success (although I could have missed something!)
~single/both vars: toString(), indexOf, typeOf
~operators: ===, ==, .eq()
~passing both variables into blank strings for comparison
~switching the variable's placement in the comparison
My goal is to get the string value from the button clicked and see if it matches the 'triviaAnswer'.
All the code is mine (except for the obvious CDN links).
Any and all help is most certainly appreciated! If you happen to solve this issue, please explain how you found the solution, as I would like to learn from this experience! :-)
The comparison issue happens in the "On-Click Events" section.
Here is my code:
JavaScript
$( document ).ready(function() {
//This is the array we will use to store our trivia objects.
var triviaArray = [];
/**
* Set the start of the array. We will also use this to keep track of our
* place is the array.
* Set it to minus so we can go to the first objext (0) in the array when we
* begin.
*/
var j = -1;
//Countdown timer variables
var countdownNumber = 60;
var intervalId;
//button trackers
var buttonClicked;
//comparison variables
var triviaAnswer;
//score variables
var correctAnswers = 0;
var incorrectAnswers = 0;
var noAnswers = 0;
var triviaObj1 = {
question: "What is the highest grossing anime film worldwide?",
options: ["Spirited Away", "Howl's Moving Castle", "Your Name", "Pokemon The Movie"],
answer: "Your Name"
}
var triviaObj2 = {
question: "What is an Otaku?",
options: ["A type of sushi", "A type of anime fan", "A type of bullet train", "A type of bonsai"],
answer: "A type of anime fan"
}
var triviaObj3 = {
question: "What is historically the most popular professional sport in Japan?",
options: ["Baseball", "Basketball", "Sumo Wrestling", "Marital Arts"],
answer: "Baseball"
}
triviaArray = [triviaObj1, triviaObj2, triviaObj3];
$("#startButton").on("click", function() {
// pass the array of triviaObjects to the triviaGenerator
triviaGenerator(triviaArray);
//Start the countdown/timer
countdownTimer();
//Hide start button afterward pressed, we won't need it anymore
$("#startButton").hide();
});
// handles the user button clicks
$("body").on("click", ".optionButton", function () {
buttonClicked = this.innerText;
//if user clicks on an option button, run the following
if ($(this).parent().attr('id') === "optionsContainer") {
console.log("buttonClicked:", buttonClicked);
console.log("triviaAnswer:", triviaAnswer);
//Run the comparison, check the buttons text and the "answer" from the
object. StackOverflow "Problem If Statement Here"
if (buttonClicked == triviaAnswer) {
alert("CORRECT");
} else {
alert("WRONG");
}
}
});
function countdownTimer() { // this will be our countdown timer.
intervalId = setInterval(decrement, 1000);
}
function decrement() { // The decrement function.
countdownNumber--;
$("#countdown").html("<h2>" + countdownNumber + "</h2>");
if (countdownNumber === 0) {
timesUp(); //run the gameOver function.
}
}
function timesUp() {
clearInterval(intervalId);
countdownNumber = 60; //reset and restart the countdown.
countdownTimer();
triviaGenerator(triviaArray); //move to the next trivia object.
}
function triviaGenerator (arr) { // We will use this function to generate our array.
var arrayOfTrivias = arr;
j = j + 1; //Go up one in the array (go to the next object in the array)
j = j % arrayOfTrivias.length; // end of the array ? -> go back to the beginning
triviaAnswer = arrayOfTrivias[j].answer; //assign the trivia's answer to a global variable so we can do a comparison against the users answer
//Print the trivia's question to the page
//Make sure the div is clear for the insertion of the trivia's question
$("#questionContainer").text("");
//Insert the question for the trivia we are on
var triviaQuestion = arrayOfTrivias[j].question;
$("#questionContainer").append( "<h2>" + triviaQuestion + "</h2>");
var optionsArray = arrayOfTrivias[j].options;
// Loop through the options array for this trivia and print//append them as buttons to the screen.
$("#optionsContainer").text("");
for (var i = 0; i < optionsArray.length; i++) {
$("#optionsContainer").append("<button class='optionButton btn btn-default'>" + "<h2>" + optionsArray[i] + "</h2> </button>");
}
}
});
HTML
<!DOCTYPE html>
<html>
<head>
<title>Trivia Game</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<nav class="navbar navbar-inverse header">
<div class="container-fluid">
Header/Navbar here
</div>
</nav>
<div class="container-fluid text-center">
<div class="row content">
<div class="col-sm-2 sidenav"></div>
<div class="col-sm-8 left-center">
<p id="welcomeBanner"> Welcome to the Trivia Page</p>
<div id="dynamicDiv">
<button id="startButton" class="btn btn-danger center">
Start
</button>
<div id="countdown"></div>
<div id="questionContainer"></div>
<div id="optionsContainer"></div>
</div>
</div>
<div class="col-sm-2 sidenav"></div>
</div>
</div>
<footer class="container-fluid text-center footer">
<p> Footer Text </p>
</footer>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script type="text/javascript" src="script.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js" integrity="sha384-b/U6ypiBEHpOf/4+1nzFpr53nxSS+GLCkfwBdFNTxtclqqenISfwAzpKaMNFNmj4" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/js/bootstrap.min.js" integrity="sha384-h0AbiXch4ZDo7tp9hKZ4TsHbi047NrKGLO3SEJAg45jXxnGIfYzk4Si90RDIqNm1" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXT sjBbfaDjzALeQsN6M" crossorigin="anonymous">
</body>
</html>
There seems to be an extra space in the buttonClicked variable.
You can use trim and your condition works :
buttonClicked = this.innerText.trim();
if (buttonClicked == triviaAnswer) {
}
edited after #Luke Stoward comment
Try comparing both values like this:
if (buttonClicked.trim() == triviaAnswer.trim()) {.....
Sometimes there is a whitespace somewhere at the end which is cut out by Javascripts trim() function.
It would appear that when you make a call to buttonClicked = this.innerText; the value being retrieved does indeed have some whitespace characters on the end. You can confirm this by logging the length of the variable with console.log(buttonClicked.length);
To fix this you must trim the whitespace characters like so
buttonClicked = buttonClicked.trim();
I have created this fiddle (with your code) that demonstrates the fix and working program: https://jsfiddle.net/fu3szacb/2/
Side note: I would avoid declaring global variables in JavaScript, this is bad practice and can lead to a world of confusion and pain. Better to avoid this when learning the language.
A useful link to provide context on global variables and why they should be avoided. (There are many sources) https://www.w3schools.com/js/js_scope.asp
As everybody said, this could be about whitespace and not trimming and you could try just by
buttonClicked = buttonClicked.trim();
But I would add that when coming to comparing strings in Javascript you have to be careful with the comparison and usually trim() as well as using the toLowerCase() or toUpperCase() in both variables being compared.
Also, for this case I would never rely on just comparing string because you're repeting the string of the correct and you can make many typo errors. If I were you I would use an array of answers every time with numbered answers, so then you only have to retrieve the numbers and compare them, and this is safer and easier.
You can save in each answer variable the number/index of the position with the right answer and if your worry is capturing the number from the HTML, I'm seeing you're using jQuery. You can just hide the number of each option in every option tag as an attribute
numberAnswer="2"
and get it with
clickedNumberAnswer = $(this).attr('numberAnswer')
just below the line
if ($(this).parent().attr('id') === "optionsContainer") {
so the comparison becomes
if(clickedNumberAnswer == triviaAnswer)
It would be very strange now to have problems with whitespace and the case-sensitive issues are impossible. Now the triviaAnswer should contain a number and, if my memory is good enough, Javascript converts automatically when comparing "2" == 2, so it's even better.

Hangman Game - Repeated string issue

I was working on my Hangman game, and I have a frustrating issue where once I click the start button to start the game, dashes print to the div not only once, but many times after(once the word to guess has been inputted). I am trying to have the dashes print only once to the div. For example, for the word dog, I want --- to print, and no more dashes after start is pressed. Could you point me in the right direction? Here is the jsfiddle: https://jsfiddle.net/jfn46wjm/
Here is the javascript code for where it appends to the page:
//loop for underscores
//creates under scores for each letter;
for (i = 0; i < input.length; i++) {
placeholder += "-";
}
//append dashes to the page
var grab = document.getElementById("test");
var secret = document.createElement("p");
secret.id = "guessp";
var textn = document.createTextNode(placeholder);
secret.appendChild(textn);
grab.appendChild(secret);
check this Latest jsFiddle
i added a flag printed and checking if it's true before printing any more dashes.
this is the updated link. please check and see if it's working fine.
This part:
var grab = document.getElementById("test");
var secret = document.createElement("p");
secret.id = "guessp";
var textn = document.createTextNode(placeholder);
secret.appendChild(textn);
grab.appendChild(secret);
means that you insert your placeholder ("---") into <div id="test"/>.
In your checkInput method you're calling:
var spguess = document.getElementById("guessp");
And since in your HTML code you have:
<p id="guessp"></p>
<div id="test">
</div>
Then your checkInput method refers to the first <p/> element, while at start you insert new <p id="guessp"/> to your <div id="test">. And then you get this error.

Call function .oninput

JSFIDDLE
HTML:
<input type="number" id="strScore" class="attribScore" min=8 max=15>
<input type="number" id="strMod" class="attribMod" readonly="readonly">
Javascript:
/****************************************************************
document.getElementById("strScore").oninput = function update(e) {
var result = document.getElementById("strMod");
var attribScore = $('#strScore').val();
result.value = (Math.floor((attribScore / 2) -5));
}
******************************************************************/
var strScore = $('#strScore').val();
var strMod = $('#strMod').val();
var update = function(score, mod) {
attribMod = (Math.floor(score / 2) - 5);
mod.value = attribMod;
};
update(strScore,strMod);
When the left input is updated with an ability score, the right input should reflect the ability modifier.
The commented section of javascript is perfectly functional, but I would really rather not have a separate function for every input that needs to be updated like this - one function is far easier to isolate and troubleshoot in the future. What I'd like to do is have one function to which I can pass the score and modifier input values as arguments (strScore and strMod in this case) and have it update the modifier field via the .oninput event. My attempt at this is below the commented section of javascript. I feel like I'm just not connecting the dots on how to call the function appropriately or correctly update the Modifier input passed to the function.
Phew. Got pulled away from the desk. Here is a solution for you. You just need to make sure that the strscore is set with an id number. This way you can relate to what strmod you want to change.
Ex. strScore1 = strMod1 and strScore2 = strMod2
This will setup a scenario where you don't have to touch anymore JavaScript to do this same function in the future. Allowing you to add as many score and mod couplets as you want in the HTML part.
We are binding the 'input' event on the class of .attributeScore which allows us to set the function. There is no need to pass in values because they are already included by default. As long as the score input has a class of .attributeScore, then it will fire that function.
We can use this.value to grab the score value, and then sub-string out the identity of the score aka 1 for strScore1 from the this.id attribute of the input field.
If we concatenate that sub-string with #strMod we can update the value of the corresponding strMod attribute with inline math.
Here is the jsfiddle: http://jsfiddle.net/hrofz8rg/
<!DOCTYPE html>
<html>
<head>
<title>Some JavaScript Example</title>
</head>
<body>
<input type="number" id="strScore1" class="attribScore" min=8 max=15>
<input type="number" id="strMod1" class="attribMod" readonly="readonly">
<br>
<br>
<input type="number" id="strScore2" class="attribScore" min=8 max=15>
<input type="number" id="strMod2" class="attribMod" readonly="readonly">
<!-- JavaScript -->
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script>
$(".attribScore").bind({
'input':function(){
var attrib_num = this.id.substring(8,this.length);
$('#strMod' + attrib_num).val((Math.floor(this.value / 2) - 5));
}
});
</script>
</body>
</html>
Hope that helps! Enjoy!
Modifying your function to accept to dom nodes rather than two values would allow you to reuse the function in separate events that use different dom nodes relatively easily.
/****************************************************************
document.getElementById("strScore").oninput = function update(e) {
var result = document.getElementById("strMod");
var attribScore = $('#strScore').val();
result.value = (Math.floor((attribScore / 2) -5));
}
******************************************************************/
var update = function($score, $mod) {
var attribMod = (Math.floor($score.val() / 2) - 5);
$mod.val(attribMod);
};
document.getElementById("strScore").oninput = function update(e) {
var $score = $('#strScore');
var $mod = $('#strMod');
update($score, $mod);
};
Even better though would be able to dynamically figure out which mod element you should target based on which score element the event was triggered on, then you wouldn't need a separate function to do the calculation/update while keeping the code dry.

In java script how do I link these arrays with this user input so it will print out the food and the fruit

I am trying to get the user to put in a number press the submit button and then it outputs the food and the fruit together so that it will be like a lunch thing. PLease help. Thanks
<!DOCTYPE html>
<html>
<body>
<form action="demo_form.asp">
Type of food (between 0 and 5): <input type="number" name="x" min="0" max="5">
</form>
<script>
var food = new Array();
food[0] = "hot dog";
food[1] = "chicken fingers";
food[2] = "veggie sandwhich";
food[3] = "Home fries"
food[4] = "pb and j"
food[5] = "pizza"
var y = Math.floor(Math.random()*6)
var fruit = new Array();
fruit[0] = "orange";
fruit[1] = "banana";
fruit[2] = "apple";
fruit[3] = "kiwi"
fruit[4] = "lemon"
fruit[5] = "peach"
{
document.write(food[x] + fruit[y]+"<br>");
}
</script>
</body>
</html>
You need to add an onchange handler to the input element or add a button with an onclick handler to trigger the action after the user enters a number. That should call a function to display the values, probably in another HTML element. You can use addEventListener or simply add the call to the element something like this:
<input type="number" name="x" min="0" max="5" onchange="showLunch(this);" /> // (note the closed input element!)
The onchange will fire when the user tabs out of the input field. You may want to try a button with onclick or whatever. Experiment.
Your form is not going to be posted to a server, so there's really no need for it. Everything will happen in the Javascript code. Your function could be something like:
function showLunch( btn ) {
document.getElementById('lunch').innerHTML = "lunch is " + food(btn.value) + fruit[btn.value];
}
In the function I assume an added HTML div to hold the answer:
<div id="lunch" ></div>
This is just a start, you may need to clean it up as you go. Have fun...

Javascript no jquery - Split a textareas single column list (unknown line count) & display in csv's of 150

I am trying to put together what I thought would be an easy solution for a friend.
He has a list of fan emails that he collects at gigs and off his website.
He sticks them in a single column file and saves them.
He needs to have them in comma delimited format containing 150 each, one single line.
He wants a "simple" local HTML form he can paste the list into and have the results displayed.
So, I started working on it but, it has proven past my ability.
So far I have some basics but, I really need help.
As you can see, I am really a beginner.
<html><head>
<script type="text/javascript">
function makeit(){
var enteredEmails = document.getElementById("emails").value;
var cnt = document.getElementById("breakcnt").value;
var mails = enteredEmails.toString();
var textareacnt = '1';
// Now I think I need to loop or create arrays of emails up to cnt //
csvmails = mails.splice(0,cnt)
// Then dynamically generate some textareas or boxes populated with a single comma delimited line of cnt" emails //
document.write("<textarea id=\"textareacnt\">" + csvmails + "</textarea>")
textareacnt++;
}
</script>
</head><body>
<form onsubmit="makeit();">
<textarea name="emails" id="emails" rows="10" cols="75"></textarea><br />
<input type="text" name="breakcnt" id="breakcnt"><br />
<input type="submit" name="submit" value="submit">
</form>
<textarea id="results"></textarea>
</body></html>
The textarera will have emails pasted into it like:
amail1#sometld.com
bmail1#sometld.com
cmail1#sometld.com
amail4#sometld.com
zmail10#sometld.com
... up to 6000 fan emails he has collected over the years
He needs the results to be:
amail1#sometld.com,bmail1#sometld.com,cmail1#sometld.com,amail4#sometld.com,zmail10#sometld.com
up to 150 emails long as I am sure the last chunk or array will not contain 150.
I cant get anything to work and I spent 6 hours on this so far.
Can someone please help? I feel like a complete idiot.
All you have to do is split the text into an array and then splice the array in a loop and join the slices you take out like this:
var emails= document.getElementById('emails').value.split(/\s+/), list="";
while(emails.length) {
list+=emails.splice(0,150).join(',')+"\n";
}
//list now has the result you are looking for
I have made an example of how to this here: http://jsfiddle.net/PfB42/2/
All you have to do is paste the emails into the text area and it will automatically change the format to the one you are looking for, and insert it to the <pre> area below the textarea
This should achieve what you want.
Don't be so hard on yourself mate :)
<html><head>
<script type="text/javascript">
function makeit(){
var enteredEmails = document.getElementById("emails").value;
var results = document.getElementById("results");
var index = 0;
var index2 = enteredEmails.indexOf("\n");
while(true) {
results.value += enteredEmails.substring(index, index2);
index = index2+1;
var index2 = enteredEmails.indexOf("\n", index+1);
//EOF
if(index2 == -1) {
results.value += ",";
results.value += enteredEmails.substring(index, enteredEmails.length);
break;
} else {
results.value += ",";
}
}
}
</script>
</head><body>
<form onsubmit="makeit();">
<textarea name="emails" id="emails" rows="10" cols="75"></textarea><br />
<input type="button" value="submit" onclick="makeit()">
</form>
<textarea id="results"></textarea>
</body></html>
Ouch, don't use that complicated scripts. Strings have functions exactly for that purpose:
var input = document.getElementById("emails").value;
input = input.replace(/\r\n/g, "\n"); // I hate this
var emails = input.split("\n"); // make an Array
var output = emails.join(","); // should we use ", " instead?
Of course you could put everyhing in one line ;-)

Categories

Resources