Javascript/For Loop/Basic code/Only runs once - javascript

first off yes, I did look at many other codes on this topic and none of those are like mine. I have a very basic code so I apologize if I missed something obvious but I cannot understand why my code will only show one number.
Here is the code.
<!DOCTYPE html>
<head>
</head>
<body>
<div id="test"></div>
<script>
var wildCard = (Math.floor(Math.random() * 5) + 1);
var temp = 1;
for (var i=0; i < 5; i++){
document.getElementById("test").innerHTML = wildCard + "<br />";
temp++;
}
</script>
</body>
</html>
Very basic code, however the only thing is that I only get one random number printed instead of 5 going down in a vertical line. I would like to know what I am missing as to why it will not loop.

Reason why only one number gets printed instead of five is because the DOM node with id test's inner html is replaced in every iteration. When the for-loop ends, you only see the value of the last iteration.
You can use createTextNode and appendChild to complete this task as follows:
var temp = 1;
for (var i=0; i < 5; i++){
const wildCard = (Math.floor(Math.random() * 5) + 1);
const textNode = document.createTextNode(wildCard);
const testDiv = document.getElementById("test");
testDiv.appendChild(textNode)
testDiv.appendChild(document.createElement("br"));
temp++;
}

Generate a new random number in each iteration of the loop, and then assign the full HTML once, after the loop has finished.
<script>
var temp = 1;
var html = "";
for (var i=0; i < 5; i++) {
var wildCard = (Math.floor(Math.random() * 5) + 1);
html += wildCard + "<br/>";
temp++;
}
document.getElementById("test").innerHTML = html;
</script>

Related

Why is my code causing (EDIT:) my page to crash?

I'm trying to randomly load some images to the page's html divs and my code is sometimes working, like on the first page load, but on maybe the second or third it causes the page to blank out and buffer and crashes the tab.
Here's a link to the full file (Excluding image srcs):
Here's the full js file: (be careful because it will crash the tab if you reload it several times)
https://repl.it/GBvG/2
var topnum = 7; //will later be used to represent current index
var rando; //will later be used as a swap index
var temporary; //will later be used as a temporary holder so we can swap rando and topnum
var myCard = document.getElementsByClassName('card');
var myArray = [
'Images/aceheart.png',
'Images/aceheart.png',
'Images/kingheart.png',
'Images/kingheart.png',
'Images/queenheart.png',
'Images/queenheart.png',
'Images/tenheart.png',
'Images/tenheart.png'
];
function create(){
while(topnum > 0){ //loops over all 8 elements
rando = Math.floor((Math.random() * topnum) + 0);
//will swap elements as long as the random index we got is not the same as the current index
if(myArray[rando] !== myArray[topnum]){
temporary = myArray[topnum];
myArray[topnum] = myArray[rando]; //randomizes topindex value
myArray[rando] = temporary;
topnum--;
}; // end of if
}; //end of while
for(var i = 0; i <= 8;i++){
var imgElement = "<img src='" + myArray[i] + "' alt='test' width='200px' height='275px'/>";
myCard[i].innerHTML = imgElement;
}; //end of for loop
}; // end of create
I'm almost positive the problem is with this snippet, though I don't know why:
for(var i = 0; i <= 8;i++){
var imgElement = "<img src='" + myArray[i] + "' alt='test' width='200px' height='275px'/>";
myCard[i].innerHTML = imgElement;
}; //end of for loop
You have 8 cards but your loop runs 9 iterations.
Change
for(var i = 0; i <= 8;i++)
To
for(var i = 0; i < 8;i++) // use `<` instead of `<=`
Also, as Gerardo Furtado mentioned in the comments, you should put topnum-- outside the if in the while loop. Otherwise you'll have an infinite loop.
while(topnum > 0) {
rando = Math.floor((Math.random() * topnum) + 0);
if(myArray[rando] !== myArray[topnum]){
// ...
}
topnum--; // <-- move the decrement here
}

Javascript - Display array elements

I am trying to run a simple Javascript to display the elements of an array that I create by splitting a string. The code is as follows:
<!DOCTYPE html>
<html>
<body>
<h1>JavaScript Loops</h1>
<p id="demo"></p>
<script>
var text = "01/01/2016";
var parts = text.split("/");
var i;
for (i = 0; i < parts.length; i++) {
var x += parts[i] + "<br>";
}
document.getElementById("demo").innerHTML = x;
</script>
</body>
</html>
The above code does not display anything on the browser and I can't for the life of me figure out where the error is. Can someone advise?
This line is tricky, so any JavaScript compiler would complaint:
var x += parts[i] + "<br>";
Uncaught SyntaxError: Unexpected token +=
You can't declare a variable with the "+=" assignment operator.
Let's rewrite this assignment:
var x = x + parts[i] + "<br>";
When it works, the result is the same. Only that the first time this runs, x is undefined, not initialized yet. Concatenating undefined to any a string will contain the string undefined in the result.
But does it re-declare the variable? No, because a concept called hoisting, any variable declaration, even inside a loop, is pushed to the top of the scope, in this case the global scope. (We're not talking about let and const)
To solve that, before you read from this variable, you need to definitely assign to it, i.e. initialize.
var x = '';
Later you'll be able to use the operator +=, and then you don't need to use the var keyword.
fgil give you good answer - you declare x variable in loop, at the first - it's not initialized (you have get error on += ), and second - you reset variable each iteration by declaring it at the loop. But I think that this loop is not needed. You can make code more simple and short if you will use method join of Array. Look at this:
<!DOCTYPE html>
<html>
<body>
<h1>JavaScript Loops</h1>
<p id="demo"></p>
<script>
var text = "01/01/2016";
var parts = text.split("/");
var x = parts.join("<br>") + "<br>";
document.getElementById("demo").innerHTML = x;
</script>
</body>
</html>
Here fiddler with sample
You can do it in one line:
document.getElementById("demo").innerHTML = "01/01/2016".split("/").join("<br>") + "<br>";
you are just failing in a basic concept. var x must be declared before the loop, like this:
var x = '';
for (i = 0; i < parts.length; i++) {
x += parts[i] + "<br>";
}
Define x outside the for loop.
var text = "01/01/2016";
var parts = text.split("/");
var x = "";
for (i = 0; i < parts.length; i++) {
x = x + parts[i] + "<br>";
}
document.getElementById("demo").innerHTML = x;

Push method displayed incorrectly

I have an issue with this code. I want to push the odds number in a array called number. But when I display it with document.write it doesn't print out the way it supposed to. Please help!!
Here's what it displays: 11,31,3,51,3,5,71,3,5,7,9 instead of: 1,2,3,4,5,6,7,8,9
<!DOCTYPE html>
<html>
<head>
<title>Trial</title>
</head>
<body>
<script>
var number = [];
var i;
for (i = 0; i < 5; i++) {
var x = 2 * i + 1;
number.push(x);
document.write(number)
};
</script>
</body>
</html>
Put documet.write() after for loop. You are actually writing array of numbers at each stage.
var number= [];
var i;
for (i=0; i<5; i++)
{var x =2*i+1;
number.push(x);
};
document.write(number)

How to do a script for odd and even numbers from 1 to 1000 in Javascript?

I am studying a book of Javascript with solved examples but there is one example without solution. I would like to know how to do it ...
In javascript (in browser) I should do is write even numbers from 1-1000 and after it is finished write odd numbers from 1-1000 ... I am not sure how to add there very small "pause" between number writing and how to know if first cycle is over and start writing odd numbers?
Here is How I started:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Test</title>
</head>
<body>
<script type="text/javascript">
/* <![CDATA[ */
var i;
for (i = 0; i < 1000; i++)
if ((i % 2) == 0)
document.writeln(i);
/* ]]> */
</script>
</body>
</html>
Give this a try:
function partA() {
for (var i = 0; i < 1000; i++){
if ((i % 2) == 0) document.write(i + ' ');
}
window.setTimeout(partB,1000)
}
function partB() {
for (var i = 0; i < 1000; i++){
if ((i % 2) !== 0) document.write(i + ' ');
}
}
partA();
SIDENOTE:
Use document.write for testing only.
If you execute it, on a loaded HTML document, all HTML elements will be overwritten. ( As you can see in my example )
I was not able to make a pause occur between the iterations of counting. The below code, in place of your script, will give you 0-1000 evens, then odds, 1 per line.
There is some discussion of waiting in javascript already on the site: What's the equivalent of Java's Thread.sleep() in JavaScript?
<script>
for(var mod = 0; mod<2; mod++){
for (var i = 0; i < 1000; i++)
if ((i % 2) == mod)
document.writeln(i+"<br>");
}
</script>
You should try something like this:
(function(){
for (var i = 0; i < 1000; i++){
if ((i % 2) === 0) document. write(i + ' ');
}
for (var i = 0; i < 1000; i++){
if ((i % 2) !== 0) document. write(i + ' ');
}
})();
*You should only use document.write for testing purpose
First of all if you want even number from 1 to 1000 your iteration variable should start from 1, not 0. :)
To write odd numbers after even ones you can just put another loop behind the first one with if(i%2==1) and it should be fine!
I am not sure how to add there the "pause" between number writing and how to know if first cycle is over and start writinf odd numbers
Use a function. It should also be in that book you're reading. Use one for even and another for odd. There should be a chapter regarding event handling, where you use elements (like buttons) to handle clicks. Use that to call the functions.
Also, try reading further. document.write* functions aren't really ideal, save for stuff done during the loading of the page. Try using much more advanced ways to write to the DOM. Those.. should be in that book as well.
Then lastly, JavaScript doesn't "pause", nor does it have something like sleep. It has timers though, but it works differently from sleep.
One an unrelated note, I believe you're using an old book. "HTML5" only requires a the "html5 doctype" and <html>.
<!doctype html>
<html>
...
Other solutions posted here are correct, but there's no reason to go through all the modulo work:
function evens () {
var i;
for (i = 2; i <= 1000; i++,i++) {
document.writeln(i + '<br>');
}
};
function odds () {
var i;
for (i = 1; i < 1000; i++,i++) {
document.writeln(i + '<br>');
}
};
evens();
setTimeout(odds, 2000);
function setCode() {
var textbox1 = document.getElementById('textbox1');
var textbox2 = document.getElementById('textbox2');
var divResult = document.getElementById('divResult');
var c = ['azimuth','background','background-attachment',
'background-color','background-image',
'background-position','background-repeat',
'behavior','border','border-bottom',
'border-bottom-color','border-bottom-style',
'border-bottom-width','border-collapse',
'border-color','border-left','border-left-color',
'border-left-style','border-left-width','border-right',
'border-right-color','border-right-style',
'border-right-width','border-spacing','border-style',
'border-top','border-top-color','border-top-style',];
var code0 = ( function set(C0) {
return ( C0 +=
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[Math.floor(Math.random()*10)])
&& (C0.length == 3) ? C0 : set(C0);
}
)('');
textbox1.value = code0;
divResult.innerHTML = c[textbox1.value];
var t;
t = setTimeout('setCode()', 1000);
}
<script type="text/javascript">
var number = 0;
while (number <= 1000) {
if (number % 2 === 0) {
document.write(number + " is even number <br />");
number = number + 1;
} else {
document.write(number + " is odd number <br/>");
number = number + 1;
}
}
</script>

How to make js "for" loop more efficient?

I am wondering how to make the loop below more efficient. On my page it has more iterations than 100, that is why, as you can imagine it is troublesome.
for (var i = 0; i < 1000; i += 1) {
var el = document.createElement('div');
el.appendChild(document.createTextNode('Node ' + (i + 1)));
document.getElementById('nodeHolder').appendChild(el);
}
Thanx for help in advance.
All I can really suggest is getting a reference to the nodeHolder element outside of the for:
var nodeHolder = document.getElementById('nodeHolder');
for (var i = 0; i < 1000; i += 1) {
var el = document.createElement('div');
el.appendChild(document.createTextNode('Node ' + (i + 1)));
nodeHolder.appendChild(el);
}
Or perhaps using a document fragment to hold the interim changes/appends and then add that to to the nodeHolder after the loop:
var fragment = document.createDocumentFragment();
for (var i = 0; i < 1000; i += 1) {
var el = document.createElement('div');
el.appendChild(document.createTextNode('Node ' + (i + 1)));
fragment.appendChild(el);
}
document.getElementById('nodeHolder').appendChild(fragment.cloneNode(true));
JS Fiddle showing both approaches (with timing if the console is available).
jQuery way...
var d = '';
for(var i=0;i<1000;i++) d += '<div>Node ' + (i + 1) + '</div>';
$('#nodeHolder').append(d);
Or javascript inside html...
<div id="nodeHolder">
<script>(function() { for(var i=0;i<1000;i++) document.write('<div>Node ' + (i + 1) + '</div>'); })();</script>
</div>
Maybe: You could generate a HTML String in the for loop like:
<div>Node 1</div><div>Node 2</div>
and then set the .innerHTML property of nodeHolder to this string after the whole loop is completed.
(... and let the DOM renderer figure out how to best optimize the action)
In summary:
Cache your DOM selector.
Ditch the for loop, and go for a reverse while loop.
Only append your element to the DOM once. The DOM is almost always the bottleneck.
In this pattern, you can take advantage of a reverse loop:
//Cache the DOM element
var node = document.getElementById('nodeHolder'),
markup = [];
//Run the loop backwards for additional speed
var i = 10000;
while(i--){
markup.push('<div>Node ' + (i + 1) + '</div>');
}
//Reverse the array, join it, then set the innerHTML
node.innerHTML = markup.reverse().join('');​
Working example: http://jsfiddle.net/ZAkMZ/3/
Reverse while loop speed reference: https://blogs.oracle.com/greimer/entry/best_way_to_code_a
jQuery version:
//Cache the DOM element
var node = $('#nodeHolder'),
markup = [];
//Run the loop backwards for additional speed
var i = 10000;
while(i--){
markup.push('<div>Node ' + (i + 1) + '</div>');
}
//Reverse the array, join it, then set the innerHTML
node.append(markup.reverse().join(''));​
You definitely need to use DocumentFragment as suggested by #David Thomas.
The most efficient version as I see is this... cloneNode is always better than createElement, switching between shallow or deep copy (still faster than createEl) as required.
Not that it gives a significant gain but you should shy away from assignments when you can. Store data in variables only when you need to. Of course when it comes to readability it's a different thing.
var fragment = document.createDocumentFragment();
var tplEl = document.createElement('div');
var contentTpl = document.createTextNode('Node ');
for (var i = 1; i <= 1000; i++) {
var curNode = contentTpl.cloneNode(false);
curNode.nodeValue = curNode.nodeValue + i;
tplEl.cloneNode(false).appendChild(curNode);
fragment.appendChild(tplEl);
}
document.getElementById('nodeHolder').appendChild(fragment);
Note that adding the fragment to the nodeHolder adds all childs of fragment as childs to nodeHolder triggering only 1 flow as opposed to 1000 flows in your earlier code.
Reference: Speeding up JavaScript
May be this way:
for (var i = 0; i < 100; i+=1) {
$("<div/>").appendTo("body").attr({"class":'txtHolder'});
$(".txtHolder").append(i+1);
}​

Categories

Resources