For loop and getElementById - javascript

Hopefully an easy one, but I am having trouble printing out a number series from a for loop, back to the HTML. See below for my code, when I hit the button, it only returns 10, but not the rest of the numbers - where am I going wrong?
<!DOCTYPE html>
<html>
<body>
<button onclick="myFunction()">Try It</button>
<p id="number"></p>
<script>
function myFunction() {
for (i=0; i<11; i++) {
document.getElementById("number").innerHTML=i+"</br>";
}
}
</script>
</body>
</html>

You're replacing the element's contents on each loop. If you want to add to the contents, use += rather than = (as a minimal change):
document.getElementById("number").innerHTML+=i+"</br>";
// here -----------------------------------^
That said, I wouldn't do that, because it's making the browser do a lot of unnecessary work under the covers. Every time you read the value of innerHTML, the browser has to spin through the element and build up a string representing its contents; and every time you write to innerHTML, it has to parse the HTML, wipe out previous elements, and build new ones.
Instead, consider building up a string and doing one assignment:
function myFunction() {
var i, s = "";
for (i=0; i<11; i++) {
s += i + "<br>";
}
document.getElementById("number").innerHTML = s;
}
Side note 1: Your code is falling prey to The Horror of Implicit Globals because you're not declaring i. I've fixed that above by declaring it.
Side note 2: </br> is an invalid tag. In HTML, it's <br> (or <br/>; the ending / is entirely optional). In XHTML, it's <br/>.

document.getElementById("number").innerHTML=i+"</br>";
will replace the HTML of number, change it to
document.getElementById("number").innerHTML+=i+"</br>";// see the `+`

Setting .innerHTML with = completely changes its content.
Use += to append content.
document.getElementById("number").innerHTML += i + "</br>";

Since most of the other answers have shown you the error, here's an edit of your code that shows how you can get the result you want but without hitting the DOM with each iteration of the loop:
function myFunction() {
// create an array
var arr = [];
for (var i = 0; i < 11; i++) {
// push the data to the array
arr.push(i + '<br/>');
}
// grab the element and then add the joined array to the html
document.getElementById("number").innerHTML = arr.join('');
}
DEMO

Related

Replace contents of <div> in a loop while waiting

I'm having difficulty figuring out my issue, or even finding solutions for it, which leads me to believe I may be going in the wrong direction.
On a cshtml page I have an ajax function tied to a button click. That routes back to my controller and a json string array is returned back to the client.
On the page itself I have <pre id="replaceMe">***</pre> defined. I am attempting to iterate through the json array doing $("#replaceMe").replaceWith('<pre id="replaceMe">' + data[i] + '</pre>');
Technically speaking this works, but only in the sense that the last update is visible. I might as well just go straight to the last element of the array.
I've tried using setTimeout to no avail, no changes and then suddenly the last element is displayed. I've found some sleep like functions that mimic the same basic behavior, all with similar results. I did see some recommendations for an async sleep, but none of my browsers seem to like the async and give me an error about a missing ;.
I then thought I could do something like
function updateSection(data) {
for (var i = 0; i < data.length; i++){
var section = $("#replaceMe");
section.fadeOut(500);
section.replaceWith('<pre id="replaceMe">' + data[i] + '</pre>');
section.fadeIn(500);
}
}
That however has the same end result. No apparent change and then suddenly it's the last element in the array.
I'm clearly going about this wrong, otherwise I'd find an example fairly readily I think, so what should I be doing instead?
To clarify and sum up, I want to replace the content of the <pre></pre> with text that's contained in an array. I want each iteration to be visible long enough for a human to see it and observe the changes (~1000ms) before going to the next iteration.
If, for example the array contains "Tom", "Dick", "Harry", then I would like for the page to have
<pre id="replaceMe">Tom</pre> for 1 second, then that element is replaced with
<pre id="replaceMe">Dick</pre> for 1 second, then that element is replaced with
<pre id="replaceMe">Harry</pre>
I am NOT looking for
<pre id="replaceMe">Tom</pre>
<pre id="replaceMe">Dick</pre>
<pre id="replaceMe">Harry</pre>
setTimeout in a for loop runs after the for loop execution completed. so, you always see the last value. to solve this, you can use $.each method which provides a callback function or use an Immediately Invoked Function Expression.
more detailed info: https://codehandbook.org/understanding-settimeout-inside-for-loop-in-javascript/
var data=[];
for(var i=0; i<10; i++){
data.push(i+' lorem ipsum doloret');
}
$.each(data, function(i, el){
setTimeout(function(){
$("#replaceMe").replaceWith('<pre id="replaceMe">' + data[i] + '</pre>');
},500 + ( i * 1000 ));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<pre id="replaceMe">***</pre>
You can do that using setInterval function:
var words = ['interating', 'and', 'replacing', 'text'];
var replace = document.querySelector('#replace');
var count = 0;
function replaceText() {
replace.innerHTML = words[count];
if(count === words.length - 1)
count = 0;
else
count++;
}
setInterval(replaceText, 1000);
Updating:
You don't need to replace all the element, you can replace only the content, using the atribute innerText.
//pass in the data to loop over, and the index to show
function updateSection(data, index) {
//get a reference to the section
var $section = $('#replaceMe');
//fade out the section over 500 milliseconds, then perform callback on finish
$section.fadeOut(500, () => {
//change the text
$section.text(data[index]);
//fade in the section over 500 milliseconds, and then advance the index
//use modulus to reset the index to 0 when it reaches beyond the array
$section.fadeIn(500, () => updateSection(data, ++index % data.length));
});
}
updateSection(['Tom', 'Dick', 'Harry'], 0);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="replaceMe">***</div>

JavaScript project not writing to document

I'm new to JavaScript at school, and this project isn't doing what I want it to do. (which is the reason for these posts in the first place, right?)
The goal is to have the user enter words one at a time with prompt in a function called startMeUp(), which then stops prompting when the user enters an empty string. (that part works)
It's then supposed to refer to a function "processString" that turns the inputted strings into an array, checks the length of each word in the array, and turns it uppercase if < 4 letters or lowercase if >= 4.
Finally, it's supposed to "return the converted string to a variable in the calling function startMeUp, and display the value using document.write"
I thought i was doing it correctly, but nothing is writing to the page, so i'm not sure where i've gone wrong. I've included the code below:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Exercise 2</title>
<script language="JavaScript" type="text/JavaScript">
//************************
// Main start-up function
// Invoked from the onload event
var someInput;
var someArray;
var someFinalString;
function startMeUp() {
do{
someInput = prompt("Enter a word");
}
while(someInput.length > 0);
processString(someInput);
document.write(someFinalString);
}
function processString(someInput){
//split the input string into a JavaScript array
someArray = someInput.split(" ");
//use a for loop to examine every word
for(i = 0; someArray[x]; i++)
{
if(someArray[i].length < 4)
{
someArray[i].toUpperCase();
}
if(someArray[i].length >= 4)
{
someArray[i].toLowerCase();
}
someFinalString = someArray.join(" ");
}
}
</script>
</head>
<body onload="startMeUp();">
</body>
</html>
Here is a working example of desire behavior.
function start() {
var input = "";
var str = "";
do {
input = prompt("Enter a word");
str += input + " ";
} while (input);
document.write(proccessStr(str));
}
function proccessStr (str) {
var arr = str.split(" ");
for (var i = 0; i < arr.length; i++) {
if (arr[i].length < 4)
arr[i] = arr[i].toUpperCase();
else
arr[i] = arr[i].toLowerCase();
}
return arr.join(" ");
}
start();
Codepen: https://codepen.io/anon/pen/qXByby (jsfiddle does'nt support docuent.write).
Few problems with your code.
You are using global variables without no need, not good practice
You don't save the all input from the user, so always the last string is saved, and that the empty string, so actually you send an empty string to your other function.
When you use string methods on string, it does'nt change the value inside the variable, it just creates new one, you need to assign it to the variable that holds the value in order to change it.
If look at my example, I used return to return the value of the transformed string to the first function, no need of global.
though I used document.write , it's not good practice , consider write to an element innerHTML/Text

Javascript: attempting to fill an array with a prompt but prompt is not displaying

I am attempting to call a method that asks the user how many entries they would like to make into an array and then prompts the user for each entry. I know this is likely a simple error but I cannot tell why my prompt is not working.
<script>
function testScore(){
var numberofScores = prompt("enter the number of scores:","");
var scores = new Array();
var whichScore=1;
for(var i=0; i<numberofScores; i++; whichScore++){
score[i]=prompt("enter score "+whichScore+":");
}
}
</script>
<a href="" onclick="testScore()">
Start Test score script
</a><br>
A loop is configured with 3 sections and thus two semi-colons. You had whichScore++ in a 4th section after adding a third semi-colon. You could have added it to the end of the configuration with a comma. But, adding it to the loop body, and not part of the loop declaration is cleaner. That said, the variable is not even needed. Just use (i + 1) and note that we're not modifying i here, we're just using an offset of it for display purposes only.
Also, in the loop: score[i], needs to be scores[i] and your <a> element should have an href="#" instead of an empty attribute.
Lastly, don't use inline HTML event handling attributes as they:
Make the code more difficult to read and lead to code duplication.
Cause global wrapper functions to be created around your supplied
attribute value that alter the binding of this in your function.
Don't follow the W3C DOM Event standard.
Use .addEventListener() in JavaScript instead:
// When the DOM content is ready
window.addEventListener("DOMContentLoaded", function(){
// Get a reference to the hyperlink and create a click event handler for it:
document.getElementById("makeScores").addEventListener("click", testScore);
function testScore(){
var numberofScores = prompt("enter the number of scores:","");
var scores = new Array();
for(var i = 0; i < numberofScores; i++){
scores[i] = prompt("enter score " + (i + 1) + ":");
}
console.log(scores);
}
});
Start Test score script
Here is a JSFiddle using your code. You have a lot going on here
https://jsfiddle.net/tcoedqkf/
First off, your for loop needs to have a comma besides the increments (although for readability I would do it in the for loop)
for(var i=0; i<numberofScores; i++,whichScore++){
Your variable name in the for loop is incorrect (missing an S)
scores[i]=prompt("enter score "+whichScore+":");
<script>
function testScore(){
var numberofScores = prompt("enter the number of scores:","");
var scores = new Array();
var whichScore=1;
for(var i=0; i<numberofScores; i++, whichScore++){
scores.push(prompt("enter score "+whichScore+":"));
//or
//scores[i]= (prompt("enter score "+whichScore+":"));
}
}
</script>
<a href="" onclick="testScore()">
Start Test score script
</a><br>
your variable is scores
Use Array.push, since you did not declare the array length in array constructor. Edit : You can also use scores[i]. It will work as well.
for only have three sections (separated by a semicolon ;): initialization, the condition and the incrementation. If you want to initialize or increment more variables use a comma ,. Like this:
for(var i = 0; i < numberofScores; i++, whichScore++) {
// ...
Since whichScore is basically just i + 1 you won't need to have two variables for that, just i will do:
for(var i = 0; i < numberofScores; i++) {
score[i] = prompt("enter score " + (i + 1) + ":");
// ...
Note that the parenthesis in (i + 1) are necessary so the numbers are added instead of concatenated.

Rewriting content of an HTML element using JavaScript

I'm new to JS, can't understand how to make this code work. I'm trying to overwrite the whole html source text.
var oldSource = document.documentElement.innerHTML;
alert(oldSource); //this works, it gets the whole html
document.write(Change(oldSource)); //doesn't work, writes undefined
function Change(source){
for (i = 0; i <= source.length; i++){
source[i] = "S"; // doesn't change the source[i]
}
}
You are changing the value of the variable oldSource, not the value of the documentElement.innerHTML.
.innerHTML just returns a string that contains the serialised content of that element. It doesn't return a reference to the content in the DOM.
Furthermore, document.write(Change(oldSource)) is saying write the return value of Change(oldSource) to the document... but your Change() function doesn't return anything, hence it is undefined.
Lastly, strings are immutable, meaning you can't change their contents after they have been created. Instead, you need to build up a new string in your function, like so:
function Change(source){
new_source = ""
for (i=0; i < source.length; i++){
new_source = new_source + "S"; //doesn't change the source[i]
}
return new_source
}
You can check all of this out in this jfiddle.
You need to return( source ); after your for loop
JavaScript strings are immutable. You can't use
source[i]="S";
to modify a string. You need to build a new string and return it.
It should be < source.length as well.
In JavaScript, this line: var oldSource = document.documentElement.innerHTML; copies the innerHTML into the oldSource variable. It does not save a reference to the innerHTML.
You are modifying the value stored in oldSource, but never applying it to the document.
In your Change function, you do not return any value - that is why you are getting an undefined. Add a 'return source;in yourChange` function to return a value.
The other problem is that you can't change the string in JavaScript. You should make a new variable for this. You can't edit source[i] - you can only retrieve the value that is there.
You need to return the new source string like below;
var oldSource = document.documentElement.innerHTML;
alert(oldSource); //this works, it gets the whole html
document.write(Change(oldSource)); //doesn't work, writes undefined
function Change(source){
for (i=0; i<=source.length; i++){
source[i]="S"
}
return source;
}
your function must return something, not just change
you cannot change strings this way, use .replace() method instead
if you specify what you really need to do, our help could be more effective
EDIT As far as I didn't find correct working code here, I want to suggest my one
function Change(source){
var str = source.split("");
for (var i=0; i<source.length; i++){
str[i] = "S";
}
return str.join("");
}
Maybe it's not the fastest way (though, why not) but it lets you to operate with indexes as you tried in your question.
working fiddle for Lego Stormtroopr
EDIT2 and this example shows how to do it in one line inside the loop (without creating extra variables)
for (var i=0; i<source.length; i++){
source = source.replace(new RegExp(source[i]), "S");
}

JavaScript array.sort() Issue

drafting up a quick listing tool to list local kids baseball teams. Takes a couple of inputs and writes to a text field. There's some validation and whatnot too, but that's out of scope and doesn't seem to be impacting things.
Problem is, I'm having trouble figuring out how to "capture" the existing text, add the new inputs and sort the whole lot, before writing the new result to the paragraph element (effectively replacing it).
So far I have:
var LeagueTeams = [];
var IndividualTeam = '';
LeagueTeams.push(document.forms[0].TeamName.value);
LeagueTeams.push(document.getElementById('TeamList')
LeagueTeams = LeagueTeams.sort();
for (j = 0; j < LeagueTeams.length; j++) {
IndividualTeam = LeagueTeams.pop();
IndividualTeam = IndividualTeam + '' + \n;
document.forms[0].TeamName.value += IndividualTeam;
}
What I end up getting is my input, and then an array of my input PLUS the previous contents, with a couple of line breaks. Setting the operator to = instead of =+ stops it from printing to the array at all.
i.e.
Enter: a
Text area: a
Then enter: b
Text area: a ab
(etc)
OK, now that we have a better idea of what you're trying to do, here's some code that will do that:
HTML:
<label>Enter Team Name: <input id="newTeam" type="text"></label>
<button id="add">Add</button><br>
All Teams:<br>
<textarea id="allTeams" rows="40" cols="40"></textarea>
Javascript (plain javascript, no framework, called after page is loaded):
var teamList = ["Dodgers", "Mets", "Giants"];
document.getElementById("add").onclick = function() {
var input = document.getElementById("newTeam");
if (input.value) {
teamList.push(input.value);
}
updateTeamList();
input.value = "";
}
function updateTeamList() {
teamList.sort();
var o = document.getElementById("allTeams");
o.value = teamList.join("\n");
}
updateTeamList();
And, you can see it working here: http://jsfiddle.net/jfriend00/HkhsL/
Comments on your existing code:
I'm not sure I understand what you're trying to do overall, but do you realize that this loop is going to have problems:
for (j = 0; j < LeagueTeams.length; j++) {
IndividualTeam = LeagueTeams.pop();
IndividualTeam = IndividualTeam + '' + \n;
document.forms[0].TeamName.value += IndividualTeam;
}
Each time you do LeagueTeams.pop() you are reducing the length of the array and you're continually comparing to LeagueTeams.length in the for loop. This will only get half way through the array because each time through the loop, you increment j and decrement LeagueTeams.length which means you'll only get half way through the array.
If you intend to iterate all the way through the array in your for loop, you should use this version that gets the length once initially and simplifies the code in the loop:
for (j = 0, len = LeagueTeams.length; j < len; j++) {
document.forms[0].TeamName.value += LeagueTeams.pop() + '\n';
}
or perhaps even better, this version that doesn't even use j:
while (LeagueTeams.length > 0) {
document.forms[0].TeamName.value += LeagueTeams.pop() + '\n';
}
Then further, I see that you're trying to use LeagueTeams.sort() on an array that has both strings in it and DOM object references. What are you trying to do with that sort because the built-in sort function does a lexigraphical sort (e.g. alpha) which will do something odd with a DOM reference (probably sort by whatever toString() returns which may be object type)?
If you want to sort the input by team name, then you would need to put both team name and the DOM reference into an object, insert that object into the array as one unit and then use a custom sort function that would sort by the name in the object. As your code is written above, you see to be using document.getElementById('TeamList') which is the same for all teams so I'm not sure why you're putting it into the array at all.
If you can show your HTML and a more complete version of your code, we could help further. What you have above is just a non-working piece of code and we don't know what your HTML looks like that it's trying to operate on.
FYI, there are several syntax errors in the code you posted, so this can't be running code:
Missing paren at the end of this: LeagueTeams.push(document.getElementById('TeamList'))
Missing quotes around \n: IndividualTeam = IndividualTeam + '' + '\n';
If you are just trying to make a list of the teams, try something like:
<script type="text/javascript">
function addTeam(form) {
var para = document.getElementById('teamList');
var teams = para.innerHTML.split(/<br\s*[\\]?>/);
teams.push(form.teamName.value);
para.innerHTML = teams.sort().join('<br>');
}
</script>
<form action="">
<input type="text" name="teamName">
<input type="button" value="Add team" onclick="addTeam(this.form)">
</form>
<p id="teamList"></p>
You may be using different elements or layout, but the strategy should be about the same. If you are making a set of options for a select, things are a little easier.

Categories