javascript document.body undefined if not preceded by a document.write - javascript

With this minimal webpage:
<html>
<head>
<title>test</title>
<script type='text/javascript' src='test.js'></script>
</head>
<body>
</body>
</html>
This minmal 'test.js' script fails:
document.body.innerText = 'testje';
The document.body seems to be undefined:
0x800a138f - JavaScript runtime error: Unable to set property 'innerText'
of undefined or null reference
If one adds a document.write('blabla') before the code line, it works:
document.write('blabla');
document.body.innerText = 'testje';
This puzzles me, although it seems rather basic.
I am a Javascript newbe, so some explanation would be most welcome.

At the time the script is running there is no body tag, it hasn't been outputted to the DOM yet.
<html>
<head>
<title>test</title>
</head>
<body>
<!-- Place content here -->
<script type='text/javascript' src='test.js'></script>
</body>
</html>
when using document.write, the document is synchronously updated with the new content, and the browser fixes your mistake and adds a body element, that's why it's available after document.write.

The script appears in the head. At the time it runs, the start of the body has not been encountered, so the body does not exist and cannot be accessed via the DOM.
document.write writes HTML to the document. In this case, character data is being written. Since character data is not allowed in the head and the end tag for head and the start tag for body are optional, this ends the head element and starts the body. At this point the body exists and can be accessed.

You can't access body element until it's declared and your script is running in <head>.
Try this: window.onload = function(){ document.body.innerText = 'testje'; };
or place your script below <body>

Related

Calling iframe link from other js file not working

I created an iframe in vex6.html and a js file in styles.gq/test.js and in that file there is the link and id but when I try to call the code in html it does not work.
Here is my code for vex6.html
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
</head>
<body>
<script type="text/javascript" src="https://styles.gq/test.js" ></script>
<iframe id="vex6" width="100%" height="500" style="border:1px solid black;"></iframe>
</body>
</html>
here is my js code
document.getElementById("vex3").src
= "https://www.obviousplays.tk/gfiles/vex3";
document.getElementById("vex4").src
= "https://www.obviousplays.tk/gfiles/vex4";
document.getElementById("vex5").src
= "https://www.obviousplays.tk/gfiles/vex5";
document.getElementById("vex6").src
= "https://www.obviousplays.tk/Gfiles6/vex6";
document.getElementById("slope").src
= "https://www.obviousplays.tk/gfiles/slope";
I expected an iframe but instead there seems to be no link for the iframe
it is also spitting out the error cannot set properties of null (setting(src))
Add the line
<script type="text/javascript" src="https://styles.gq/test.js</script> after the iframe tag.
Worked for me.
Error in console: "script.js:3 Uncaught TypeError: Cannot set properties of null (setting 'src')"
Your script is loaded before the iframe content, meaning that you're trying to initialize the source of an unidentified object.
Solution: Place the <script> tag below your iframe. It is a good practice to place <script> tags at the bottom of the <body> tag so we can always access loaded content. However, sometimes it takes the contents a little bit more time until they fully load (despite placing the <script> tag at the bottom of the page). I'd suggest wrapping your code in window.onload = () {} It will ensure that all contents are loaded before firing the code.
<body>
<iframe id="vex3" width="100%" height="500" style="border:1px solid black;"></iframe>
<script type="text/javascript" src="https://styles.gq/test.js"></script>
</body>
Your code is fine and should work (pardon for criticizing). Anytime you seem to use repetitive code, it means that it can be simplified/automated like so:
window.onload = () => {
// Target all <iframe> tags.
iframes = document.querySelectorAll('iframe');
// Loop through list of <iframe> nodes.
Array.from(iframes).map(iframe => {
// Update <iframe>'s attribute "src" to the origin URL,
// and use the iframe's attribute "id" value as the final source.
iframe.setAttribute('src', `https://www.obviousplays.tk/gfiles/${iframe.id}`)
});
}

how to isolate js script from the html code?

i'd like to isolate the javascript code from the html code in two diferent files, originally I had this code:
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
</head>
<body>
<p id="body">HTML Text</p>
</body>
</html>
<script>
$(document).ready(function () {
$("#body").text("JS Text");
});
</script>
and the output of the <-p-> was the expected "JS Text".
Then I tried to isolate the js script to another file (script.js):
window.onload = function(){
var text = document.getElementById('body');
text.innerHTML ='JS Text';
}
I've also make the reference at the html file:
<script type="text/javascript"src="scripts.js"></script>
but then the output text is no longer the expected (JS Text) but (HTML text)
what else do I need to make the js script work again?
First, it is invalid to place anything after the closing HTML tag, so while your first bit of code worked, it was invalid.
If you remove the JavaScript and place it in its own file, it will continue to work as long as you reference the file properly (use a relative reference and test the file on a web server) and place the script element just prior to the closing body tag so that when the script is processed and attempts to find the right DOM element, the DOM will have been loaded at that time.
FYI:
If you have JQuery in the referenced script file, then your
script that references JQuery will need to occur in the HTML prior
to the script that uses it.
The type attribute in the script tag has not been needed in
several years.
It's not a good idea to name anything body so that you won't cause
confusion with the body element.
Don't use .innerHTML when the string you are working with doesn't
contain any HTML. .innerHTML has security and performance
implications. Use .textContent instead.
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
</head>
<body>
<p id="body">HTML Text</p>
<script src="relativePathToFile.js"></script>
</body>
</html>

Using vanilla javascript, add class to body from within head

I want to do a quick javascript check from within the head tag, like so:
<html>
<head>
...
<script>
document.body.classList.remove("no-js");
document.body.classList.add("js");
</script>
</head>
<body class='no-js'>
...
</body>
</html>
This doesn't work. Cannot read property classList of null, which...fair enough. If I move the <script> tag into <body>, everything works, but I want the <script> tag in <head>.
What are my options?
EDIT: I should have been much clearer about the error. I realize the problem is that body hasn't loaded when I'm trying to to add the class. However, I was using a bit of Modernizr originally and it was somehow able to modify the body class from within the head and I don't think it was using window.onload or anything like that.
Run the code after body is loaded. There are several approaches to solve the problem:
Move the code into a named function defined in global context and call it in onload.
<html>
<head>
...
<script>
function load() {
document.body.classList.remove("no-js");
document.body.classList.add("js");
}
</script>
</head>
<body onload="load();" class='no-js'>
...
</body>
</html>
Or move code to DOMContentLoaded event listener callback in order to call after dom elements are loaded.
<html>
<head>
...
<script>
document.addEventListener("DOMContentLoaded", function() {
document.body.classList.remove("no-js");
document.body.classList.add("js");
});
</script>
</head>
<body class='no-js'>
...
</body>
</html>
Or move the entire script tag to the end of the page.
<html>
<head>
...
</head>
<body class='no-js'>
...
<script>
document.body.classList.remove("no-js");
document.body.classList.add("js");
</script>
</body>
</html>
At the time the javascript is executed there is no body tag, because the browser hasn't gotten around to it yet. You need to either add the script tag in the body, or add it as an event to execute when the document has loaded. See DOMContentLoaded for an example.

Script tags - not linking (JS platform game)

I'm working through the 'create a platform game' project from Eloquent JavaScript and have an issue with script tags.
In the book we're told to display our level using:
<link rel="stylesheet" href="css/game.css">
<script>
var simpleLevel = new Level(simpleLevelPlan);
var display = new DOMDisplay(document.body, simpleLevel);
</script>
I've tried adding this (together with an additional script tag for my platform.js file) into index.html but the browser is giving nothing back, not sure what I'm doing wrong?
Ensure you are inserting your scripts in the right order:
<!DOCTYPE html>
<html>
<head>
Here you should put your "included" scripts with <script src=...>
</head>
<body>
...
</body>
<script>
Here you should put your first execution, if it needs the html page been completely loaded (as to use document.body).
</script>
</html>
The scripts are being executed as they appear into the page. If you use document, you have to delay the execution until the whole page has been loaded: Either by putting your script at the end of the HTML, either by putting an initialization function within the HEAD, and call it from body onload:
<head>
<script>
function myFunction(){...}
</script>
</head>
<body onload="return myFunction()">
...
</body>
Make sure to include the external JavaScript file you need in a separate <script> tag before your inline script!

Uncaught TypeError: Cannot set property 'onclick' of null onclick not working

see below is my javascript,
<script type="text/javascript">
document.getElementById('auth').onclick=change;
function change(){
this.className="account_holder";
}
</script>
html is
<td id="auth" class="authorised_reportericon" >
<a href="{% url incident.views.authorised_reporter %}">
<p align="center" style="color:black;font-size:16px;">Authorised Reporters</p></a>
</td>
I assigned td's id for onclick,but it is trowing error as Uncaught TypeError: Cannot set property 'onclick' of null
Put document.getElementById('auth').onclick=change; inside of window.onload, like:
window.onload = function () {
document.getElementById('auth').onclick=change;
};
According to the error you're getting, I'm guessing your Javascript is executed before your relevant HTML is rendered, meaning the element with the id "auth" isn't found. Putting it in an event where the whole DOM is ready should fix the problem.
Demo: Here
Most likely you've placed the script in the head of the document, which means it's running before the rest of the page has been rendered.
Instead, move it inside the body, to the very bottom, just before the closing </body> tag.
<!doctype html>
<html>
<head>
<title>my page</title>
</head>
<body>
<!-- your page content -->
<!-- your script -->
<script type="text/javascript">
document.getElementById('auth').onclick=change;
function change(){
this.className="account_holder";
}
</script>
</body>
</html>
Now the elements will be available before the script runs. This is because the page renders in order from top to bottom, and scripts block the rendering when loading.
So when the script is in the head, it prevents the rest of the page below it from rendering until the script is complete, which means the "auth" doesn't yet exist.
Using this positioning technique of the script toward the end allows it to run potentially much sooner than waiting for a window.onload event.

Categories

Resources