why doesn't the script work this way? - javascript

Following is a statement that should run according to me when the HTML page loads.
document.getElementById("name_field").value = "JavaScript";
But this does nothing.If i try to do the same thing the different way :
window.onload = init;
function init() {
document.getElementById("name_field").value = "JavaScript";
}
Then this works fine.
What is wrong with the first script.?
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<script type="text/javascript" src="valtest.js">
</script>
</head>
<body>
<form>
<label>Enter your name <input type="text" id="name_field" /></label> <br/>
<input type="submit" value="submit" />
</form>
</body>
</html>

Onload runs after the HTML has been rendered in the page. So in your first example the element is not yet available for JavaScript processing.
Most use "document ready", which means the document has been rendered.
jQuery example:
$(document).ready(function() {
init()
});

Your HTML probably looks like this:
<script>
document.getElementById("name_field").value = "JavaScript";
</script>
<!--
More
code
here
-->
<input id="name_field" value="Static">
If that's the case, when the JavaScript is run there is no element with the ID "name_field" in the DOM yet.
window.onload is executed only after the entire DOM has been loaded and parsed ... which is why running the function then works. (It would also work if it was attached to any other event handler that ran after the DOM was loaded, or even if the order of the script and input tags were reversed.)

The element with id 'name_field' isn't available in the DOM yet because the whole document gets loaded in the sequencial order.
The second example will execute once the document has been loaded and your element is available.

the javascript in your first sample execute immediately, before any DOM has rendered. You have to wait for the DOM to render before you try to operate on it, which you are doing in your second sample.

The first script may or may not work depending on where it is placed within your HTML. If the script is before the field itself (the <input id="name_field" />), the script will run before the browser acknowledges the existence of the field, so it will do nothing (actually, it should throw an error stating that you are trying to access the value property of an undefined object).
The second version runs after the page finishes loading. By then, the browser already knows about your field, to the script works.

Related

HTML/javascript: prevent paint before code executes

I have a page with a javascript file at the end. the file is placed at the end so that I get access to all the dom elements.
let us say the markup looks like this
<html>
<head></head>
<body>
//lot of markup here
<script src="my-js.js"></script>
<body>
the sample markup is just to show the location of my js file.
the first like in the js file (my-js.js) is
document.body.style.visibility = 'hidden';
After the code runs I set the visibility back to hidden
From what I have understood(from a lot of articles related to this including in stackoverflow ones) is that the browser reaches the js, then executes it, and then continues with render and then paints.
If that was true, my code as described should work fine.
However, what is happening now is that, the page is shown (for less than 500ms) as it is before the code executed, then quickly hidden and then shown again after the code executed.
in short, what I want is:
page is hidden > code executes > page is shown
instead what I get is
page is shown > page is hidden > code executes > page is shown
My question is why is the page shown for that split second? what am I doing wrong here?
PS: Please note that I cannot change the location of the js nor add another. So, do not post any solution that suggest the same.
More importantly, I want to know why my code is wrong.
You might be interested in using the defer method.
defer means “wait for the parser to finish to execute this”. It’s roughly equivalent to binding your script to the DOMContentLoaded event, or using jQuery.ready. When the code does run, everything in the DOM will be available for you to use. Unlike async, defer’d code will run in the order it appears in the HTML of the page, it is just deferred until after the HTML is fully parsed.
For example:
<script src="my-js.js" defer></script>
See more here
Put the script tag right at the start of the body so it will be evaluated almost exactly as the body is rendered.
<html>
<head></head>
<body>
<script>
document.body.style.visibility = 'hidden';
</script>
<p>Sample text</p>
</body>
</html>
You can also add a style tag to set the body's visibility to hidden.
body{
visibility: hidden;
}
<html>
<head></head>
<body>
<p>Sample text</p>
</body>
</html>

what's the difference between onload action and an action in a bottom script

Is there any functional difference between using body onload:
<!DOCTYPE html>
<html>
<head>
<title>testing body onload</title>
</head>
<body onload="fu('this is from body onload')">
<h2 id="I1">nothing yet</h2>
<script>
function fu (msg) {
document.getElementById("I1").innerHTML = msg ;
}
</script>
</body>
</html>
on the one hand and executing a script at the end of the body:
<!DOCTYPE html>
<html>
<head>
<title>testing body onload</title>
</head>
<body>
<h2 id="I1">nothing yet</h2>
<script>
function fu (msg){
document.getElementById("I1").innerHTML = msg ;
}
fu('this is from bottom script') ;
</script>
</body>
</html>
The second seems better to me, certainly when there are more actions to do when a page is loaded. But maybe there is a pitfall I don't know?
Yes, there is. Putting your code at the bottom is like putting it in a domready event, not onload.
Domready means that the html code was read (so the dom is ready, or in other words, you can now find dom elements with js selectors), while onload means that all the assets (img, css, etc..) are loaded as well (so, a much longer event).
Edit:
please also refer to MDN docs:
(this is basically like jquery's domready, and it's a document object's event):
https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded
this is the onload event, and it's a window object's event:
https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onload
onload documentation from Mozilla:
The load event fires at the end of the document loading process. At
this point, all of the objects in the document are in the DOM, and all
the images, scripts, links and sub-frames have finished loading.
Placing scripts at the base of the page will run as soon as the browser has rendered the HTML.
For perception purposes I would combine the two and place your scripts at the bottom of the page in an onload callback, if needed.

Javascript Function Not Being Called after dynamic loading

I have a weird issue that i am hoping someone can help resolve.
Problem
When i load html dynamically via .load() function, if any aspect of html in the loaded fragment tries to access the javascript query functions in original HTML page, it doesn't work. Example code below:
Main HTML page (main.html)
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head lang="en">
<!--javascript load functions etc... standard header stuff -->
</head>
<body>
<div id="dynamic_section_fragment"></div>
Load Fragment
<script type="text/javascript">
// <![CDATA[
function loadFragment() {
$("#dynamic_section_fragment").load("/api/fragment/");
};
$(".checkvalue").click(function () {
$.getJSON("/api/checkvalue", {term: $(this).attr('value')}, function () {
console.info("submitted for checking");
})
});
// ]]>
</script>
</body>
</html>
FRAGMENT File (fragment.html)
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head lang="en">
</head>
<body>
<div th:fragment="check_value">
<br/>
Check the value in the attribute field
<br/>
<a href="javascript:" th:attr="value='123'" class="checkvalue">Check This<a/>
</div>
</body>
</html>
SPRING MVC Controller Method
#RequestMapping("/api/checkvalue")
public String getFragment(Model model) {
return "fragment :: check_value";
}
So a run down of actions:
-Main.html page loads
-User clicks on Load Fragment hyperlink
-Javascript dynamically loads the relevant fragment into the div
-User clicks on Check This hyperlink, nothing happens
Is there something i am missing or something i need to be aware?
It is as if Thymeleaf has preregistered all the possible scenarios of events and doesn't allow any others.
Only way i have been able to get it to work is by injecting the "checkvalue" javascript within the fragment, which as you can agree is a bad way of doing things.
Help is appreciated.
You are applying the click event listener to all existing objects with the checkvalue class.
$(".checkvalue").click(function ()
What you rather wish to do (to make the click event apply to all the existing and any new added, dynamically) is to set a event on a parent in the dom tree (parent both to the existing and to all that will be added).
In your case, the body tag would probably be the safe bet.
The following should suffice:
$('body').on('click', '.checkvalue', function() { ...
Simplified, the code will apply a listener on the body element instead of the .checkvalue objects, and whenever a object with the .checkvalue class is clicked (wether dynamically or statically loaded), the event will fire.
edit
I would also suggest that you, in your javascript, don't use jquery before you know for certain that it is loaded.
The jquery lib have a way of fixing this for you, by using the $( document ).ready() function:
$( document ).ready(function() {
// All jquery dependant code here.
});

how to check DOM is ready using JavaScript?

i am using this script in my jsp. some time when i click on that particular button it works fine but some time it doesn't work and show Script Error : document.form is null not an object. what ever i searched i found that document is not finished loading when i call reset. how can i check whether the document has loaded or not?
<head>
<script type="text/javascript">
function closeWarning(){
document.forms[0].reset();
}
</script>
</head>
<body onLoad="closeWarning();"
<jsp:include flush="true" page="/myCart/header.jsp"/>
<div>
// content of body
</div>
</body>
If you don't want to use jQuery, you can use an event listener for DOMContentLoaded, as in:
if(document.addEventListener) document.addEventListener("DOMContentLoaded",closeWarning,false);
This will work for everyone except IE, which uses onreadystatechanged, as in:
document.onreadystatechange=function() { if(this.readyState=="complete") { closeWarning();
}
}
One way is using jQuery and it's ready() function.

Basic jQuery .load Problem

I am trying to use jQuery's .load function to dynamically load content into my webpage. This seem so simple, but I cannot make it work. To try and figure it out, I made a test page with just basic structure, but the external content still won't load:
jquery.html
<html>
<head>
<title>JQuery Test</title>
<script src="jquery1.5.min.js"></script>
</head>
<body>
<script>
$('#foo').load('test.html');
</script>
<div id="foo"></div>
</body>
</html>
test.html
<p>Text text</p>
I'm sure I have made a tiny error, but I can't find it anywhere!
You need to encapsulate your script in the $(document).ready() otherwise #foo won't exist when the script is executed:
<script>
$(document).ready(function(){
$('#foo').load('test.html');
});
</script>
You need to wait for the document to be ready before you can access the DOM. Just add a $(document).ready() around your original code:
<html>
<head>
<title>JQuery Test</title>
<script src="jquery1.5.min.js"></script>
</head>
<body>
<script>
$(document).ready( function() {
$('#foo').load('test.html');
});
</script>
<div id="foo"></div>
</body>
</html>
or if you want a shorter code:
$(function() {
$('#foo').load('test.html');
});
Informally, what's happening is that, as your browser reads the code you wrote, it's drawing its contents as it goes along. When it reaches your <script> tag, it executes it. But when $("#foo") gets executed, the browser's still processing the <script> and hasn't reached the part of the code where you told it there's a div called foo, so the browser doesn't know it exists, and jquery will just find nothing.
Of course, the idea that the browser will just sequentially read your code and render it as it goes is naive at best, so while it might seem that just moving the <script> tag to the bottom of the code would work, you're not actually guaranteed it will work. Instead, the browser will notify you when it's done drawing the page by firing a load (and possibly a DOMContentLoaded) event. So all code that depends on the whole html being drawn should be executed in an event handler bound to those events.
jQuery makes waiting for the page to be loaded easy, just use something like this:
$.ready(function() {
doStuff();
});

Categories