Loop blocks DOM Manipulation - javascript

I have a simple counting loop that counts to 10000 and logs every number to the console. Before i start the loop i want to write "TEST" to the body in my html.
Although i do this before i start the loop it appends "TEST" to the body only after the loop is done. However i can log something to the console before starting the loop. I think i am blocking the browser thread or something, i don't know how to write this in a non blocking manner. I have been trying to figure out this Problem for quite some time. Your Help would be much appreciated !!!
My HTML code:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<button onclick="myfunc()">click me</button>
</body>
<script src="index.js"></script>
</html>
My javascript code:
function myfunc() {
var h1 = document.createElement("h1").innerText = "TEST"
document.body.appendChild(h1) //appends only after loop is done
console.log("test") // this works
for (var i = 0; i < 10000; i++){
console.log(i)
}
}

One solution is to put your loop code in a timeout and set the delay to 1 millisecond
function myfunc() {
var h1 = document.createElement("h1")
h1.innerText = "TEST"
document.body.appendChild(h1) //appends before the loop
console.log("test") // this works
setTimeout(()=>{
for (var i = 0; i < 10000; i++){
console.log(i)
}
},1)
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<button onclick="myfunc()">click me</button>
</body>
<script src="index.js"></script>
</html>

Related

Javascript - setTimeout

I am learning Javascript right now. I have a small issue that I can't figure out how to solve it. I would like to clear content of my html page after my function displayed "Hi hi" in web page.
<html>
<body onload="alertFunc()">
<script>
function alertFunc() {
var statement = "Hi hi"
for (let i = 0; i < statement.length; i++) {
let c = statement.charAt(i);
setTimeout(function(){
document.write(c);
},i * 1000);
}
}
</script>
</body>
</html>
try this to clear content of your site after 1 second
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Learning </title>
</head>
<body>
<script>
document.write('hi hi');
function alertFunc() {
setTimeout(function(){
document.write(' ');
}, 1000);
}
alertFunc();
</script>
</body>
</html>
if you want to change content with time again and again then you have to use setInterval

"cannot read property 'innerHTML' of null" error

I am getting the error "cannot read property'innerHTML' of null" at line 11 in the file letterbyletter.js. Its code is this:
function printLetterByLetter(destination, message, speed){
let h = 0;
var interval = setInterval(function(){
if (h===0) {
stop=false
}
if (h > message.length||(stop===true&&h!==0)){
clearInterval(interval);
stop=false
}else if (message.charAt(h)!=="<") {
document.getElementById(destination).innerHTML += message.charAt(h);
h++;
}else {
document.getElementById(destination).innerHTML += "<br>"
h+=4
}
}, speed);
}
It is being called here:
function run(num9) {
if (stats[3][1]>enemies[num9].speed) {
let r=Math.ceil(Math.random()*100)
if (r>=50) {
battlechk=false
document.getElementById("body").innerHTML="<div class=\"textbox\" id=\"textbox\"></div>"
printLetterByLetter("textbox","You escaped from "+enemies[num9].name+"!",50)
document.getElementById("body").innerHTML+="<button class=\"option\" onclick=\"supdateGUI3()\">Confirm</button>"
}else {
document.getElementById("body").innerHTML="<div class=\"textbox\" id=\"textbox\"></div>"
printLetterByLetter("textbox",enemies[num9].name+" blocks your path! "+enemies[num9].name+" attacks you!",50)
document.getElementById("body").innerHTML+="<button class=\"option\" onclick=\"battle("+num9+")\">Confirm</button>"
}
}else {
let r=Math.ceil(Math.random()*100)
if (r>=90) {
battlechk=false
document.getElementById("body").innerHTML="<div class=\"textbox\" id=\"textbox\"></div>"
printLetterByLetter("textbox","You escaped from "+enemies[num9].name+"!",50)
document.getElementById("body").innerHTML+="<button class=\"option\" onclick=\"supdateGUI3()\">Confirm</button>"
}else {
document.getElementById("body").innerHTML="<div class=\"textbox\" id=\"textbox\"></div>"
printLetterByLetter("textbox",enemies[num9].name+" blocks your path! "+enemies[num9].name+" attacks you!",50)
document.getElementById("body").innerHTML+="<button class=\"option\" onclick=\"battle("+num9+")\">Confirm</button>"
}
}
battle(num9)
}
Every one of the calls in the above code cause the same error. A deeper look reveals that the textbox is there when printLetterByLetter is called and that the destination is textbox. When I console logged document.getElementById(destination) I got null. printLetterByLetter has worked every other time I have used it and I haven't gotten an error when I have used other commands that are similar. My entire code can be found here: https://github.com/Fish767/Space-Clones. The files in question are run.js and letterbyletter.js. Destination is a string and the line before I called printLetterByletter I added the element with an id of textbox.
Steps to reproduce: press move and left twice and then move and explore until you get into a battle. Then press run.
The html doc is this:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="css/first.css">
<title id="title">Lives in Space</title>
</head>
<body id="body">
<script src="js/globalvars.js"></script>
<script src="js/sleep.js"></script>
<script src="js/letterbyletter.js"></script>
<script src="js/format.js"></script>
<script src="js/cleardoc.js"></script>
<script src="js/doEffects.js"></script>
<script src="js/use.js"></script>
<script src="js/toss.js"></script>
<script src="js/battleresults.js"></script>
<script src="js/friend.js"></script>
<script src="js/run.js"></script>
<script src="js/attack.js"></script>
<script src="js/battle.js"></script>
<script src="js/event.js"></script>
<script src="js/explore.js"></script>
<script src="js/moveto.js"></script>
<script src="js/second.js"></script>
<script src="js/rpgland.js"></script>
<script src="js/loop.js"></script>
</body>
</html>
I can easily do what I want in another way. What I am asking is why doesn't this way work.
I cloned the repo.
There is no "#textbox" in DOM when the error happen, it was replaced with "#statsbox" on battle function. You'll want to use chrome dev tool to debug step by step and it'll help you develop this game more easier also.
Happy coding!
It is because when you click the "confirm" button, you execute battle(0), and the first instruction in this function is to overwrite the entire DOM : document.getElementById("body").innerHTML="<div id=\"statsbox\"></div><div id=\"option-container\"></div>". So everything else disappears.
The reason why you can console.log the element at the beginning of printLetterByLetter() and then 10 lines later it logs null is because those 10 lines are within a setInterval which gets executed later, at the end of the lifecycle. The DOM has been overwritten in-between.

Display the result of a function as variable in a browser using document.getElementbyId.innerHTML in JavaScript

I am a newbie to JavaScript < 1 Week old
I wrote a very short HTML/JavaScript and got it to display on console.
Basically, I want to display the result of a function used as a variable inside the <p> tag of the HTML.
I got the script to display in the console.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<script>
var kilo = function(pound) {
return pound/2.2;
}
kilo (220);
console.log (kilo(220));
</script>
<script>
var kilog = function(pounds) {
return pounds/2.2;
}
console.log (kilog(440));
</script>
<p id="Kilograms"><!--I want the result here--></p>
</body>
</html>
How do I get the result of the function as a variable i.e var kilo (pounds)... to display in the p tag with id Kilograms?
Script shold be after BODY code, or you should add document ready event listener. So, try this solution:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<p id="Kilograms"><!--I want the result here--></p>
</body>
<script>
var kilo = function(pound) {
return pound/2.2;
}
kilo (220);
console.log (kilo(220));
var kilog = function(pounds) {
return pounds/2.2;
}
console.log (kilog(440));
document.getElementById("Kilograms").innerHTML = kilog(440);
</script>
</html>
Example in JSBin: https://jsbin.com/pacovasuve/edit?html,output
You can try this in your js code.
document.getElementById("Kilograms").innerHTML="write whatever you want here";
Try this
var p = document.getElementById('Kilograms');
p.innerHtml = 'any text';
// OR
p.innerHtml = kilog(440);

Naming variables in for loop

I'm new to JS and HTML. I learned that it's possible to name a variable by code. So i tried some simple variable naming code. However, it doesn't print anything on the page.
What seems to be the problem?
javascript
for (var i = 0; i < 10; i++) {
window['var' + i] = i;
}
document.getElementById("text").innerHTML = "" + var8;
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<script src="JScript.js"></script>
<title>Practice</title>
</head>
<body>
<p><span id="text"></span>left</p>
</body>
</html>
Enclose your javascript code in below document.ready function, so that it will execute only when your page is ready.
$(document).ready(function () {
// enter your code here
});

document.write hangs and times out

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Title</title>
<script language="JavaScript">
<!--
function showtags()
{
var tag;
for(i = 0; i < document.all.length; i++)
{
tag = document.all(i).tagName;
document.write(tag + ' ');
//document.write("<br>");
}
}
// -->
</script>
</head>
<body>
<script>
showtags();
</script>
</body>
</html>
If I un-comment the second document.write() in the loop inside the function then it hangs (it does not display anything and times out). I appreciate your help.
document.all is a "live" collection. Each time you loop, you add 2 new items. This means every time it evaluates the length property it's always going to be larger than i.

Categories