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>
Related
Just starting out playing with Brython. I'm running into a basic(?) problem.
I have:
<body onload="brython()">
<div id="demo"></div>
and
<script type="text/python3">
from browser import document
document["demo"].textContent = "foo<p/>foo"
</script>
The code runs fine, but renders in the browser as "foo<p/>foo". In other words, the browser does not evaluate the <p/> tag in the text of demo element inserted there by Brython.
When I do this with JavaScript (document.getElementById("demo").innerHTML = "foo<p/>foo") the <p/> tag is evaluated just fine.
My understanding is that the function brython() translates the Python code into JS after which the browser evaluates the resulting JS. But if this is so, why isn't the <p/> tag in the demo element evaluated?
Also, how do I fix this?
Thanks for helping,
Rene
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.
1) Here is what works just fine:
SearchTool.aspx (in the code snippet below) is a 3rd party product that will actually insert an iframe into the page at page load time with the search tool inside of it.
<html>
<head>....</head>
<body>
...
...
<h2>Search Tool</h2>
<script type='' src='http://foo.com/SearchTool.aspx</script>
...
</body>
</html>
2) Here is what I want to do:
I want my page to load quickly without the search tool being loaded at the same time. The user can read through my page and then, if they want, they can click on a button to load the search tool thereby delaying the tool load time to when they want it.
I want to be able to invoke the SearchTool.aspx from the click of a button as below, but I don't know what the code would look like in the showSearch() function below:
<h2>Search Tool</h2>
<script type='text/javascript'>
function showSearch(){
**** What would go here? *****
}
</script>
<input .....="" onclick="showSearch();"></input>
3) I have already explored creating the iframe manually:
In the code snippet #1 above that works just fine, if I do a view source and then create an iframe exactly like they do with all of the same properties, the Search Tool doesn't completely work properly. Weird I know, but true. So this is NOT an option.
Wrap your script tag in a div with the style display:none to hide it:
<h2>Search Tool</h2>
<div id="searchTool" style="display:none">
<script type='' src='http://foo.com/SearchTool.aspx</script>
</div>
...
Then, in your function, just show it :
function showSearch(){
document.getElementById("searchTool").style.display = 'block';
}
When i keep my javascript/jquery external, my code doesn't work. but when i combine them in my html file everything is fine.
any suggestions as to why this is?
here is the code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script type ="text/javascript" src="jquery.js"></script>
<script type ="text/javascript" src="program.js"></script>
</head>
<body>
<div id="clickme">
Click here
</div>
<img id="book" src="book.png" alt="" width="100" height="123" />
<p>First Paragraph</p>
<p>Second Paragraph</p>
<p>Yet one more Paragraph</p>
</body>
</html>
with external javascript
$('#clickme').click(function() {
$('#book').fadeOut('slow', function() {
// Animation complete.
});
});
$("p").click(function () {
$(this).slideUp();
});
VERSUS
<!DOCTYPE html>
<html>
<head>
<script type ="text/javascript" src="jquery.js"></script>
</head>
<body>
<div id="clickme">
Click here
</div>
<img id="book" src="book.png" alt="" width="100" height="123" />
<p>First Paragraph</p>
<p>Second Paragraph</p>
<p>Yet one more Paragraph</p>
<script>
$('#clickme').click(function() {
$('#book').fadeOut('slow', function() {
// Animation complete.
});
});
$("p").click(function () {
$(this).slideUp();
});
</script>
</body>
</html>
I guess you execute the click event before the DOM finishes loading. Wrap your code inside the dom ready event and it should work, Assuming your path to the external javascript file is correct.
$(function(){
$('#clickme').click(function() {
$('#book').fadeOut('slow', function() {
// Animation complete.
});
});
$("p").click(function () {
$(this).slideUp();
});
});
Always use firebug (console) to see what is wrong with the script, if you run into any script errors.
Your javascript is executed before there are elements on the page. You can get around this by using $(document).ready(function(){...}); or moving your external javascript files to the bottom.
Wrap your js code in external file in
$(document).ready(function(){
//your code goes here
});
Right now you are including external js file in header and it is executed. At this point there is no elements so $('#clickme') and $("p") are empty set. In the second example you run this code after rendering html with that elements.
The reason that there is a difference, is that in the external file your code is executing before the browser has fully parsed the DOM so you are attempting to programatically access elements of the page which the browser is not yet aware of. This is exactly what most people have already said, but let me elaborate a bit further...
Whilst a lot of people have mentioned using jQuery's document ready handler, I would like to point out that a workable solution is simply to move your script tags to the bottom of the page.
Not only will this solve your problem in itself, but it will also improve page load times because of how browsers treat scripts. When the browser encounters a script it stops everything else it is doing (known as a "blocking" operation), and parses and executes the script. This causes the page to just appear to stall from a user's perspective, meaning a bad user experience. Thus, because the scripts are parsed and executed only as they are encountered, by moving your scripts to the bottom you allow the browser to fully render the page so that the JavaScript does not block rendering.
Though rather than just moving scripts to the bottom of the page, I'd also follow what the others recommended and wrap the whole code in the document ready handler just to be extra safe that your code will always be executed at the correct time.
Also, in the debate of inline or external, external scripts are generally preferred as they are easier to maintain and the browser can cache them independently of the page (providing the correct HTTP headers are present).
To sum up here's some example code:
<html>
<head></head>
<body>
<!-- all your markup here -->
<!-- script at bottom, markup already rendered by this point -->
<script type="text/javascript" src="jquery.js"></script>
<!-- inline or external, still wrap in document ready handler -->
<!-- though external is better because the browser can cache it independently of the page -->
<script type="text/javascript">
//wrap in document ready to be extra safe
$(function() { /*code here*/ });
</script>
</html>
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();
});