How to check if DOM element is fully loaded? - javascript

I'm loading really big web page with thousands of elements.
How can I test if node has fully loaded including it self and all it child elements but I don't want to wait for whole page to be loaded.
For example lets have this page:
<html>
<head>
<script>
var cnt = 0;
var id = setInterval(function test() {
var e = document.querySelector('#content')
if (!e) return;
// how to test is "e" fully loaded ?
if (cnt == e.childNodes.length) {
clearInterval(id);
} else {
cnt = e.childNodes.length;
console.log(cnt);
}
}, 10);
</script>
</head>
<body>
<div id="content">
<div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div>
<!-- ... add 30k div elements -->
</div>
</body>
</html>
This will print something like this on console:
4448
9448
14448
19448
24948
30000

I think that the load event would be an more apropriate answer to your question.
It can be atached to an ellement and fires when everything is loaded including images and other resources.
some examples you can find here.
https://developer.mozilla.org/en-US/docs/Web/Events/load
https://www.w3schools.com/jsref/event_onload.asp
but if you don't care about the resources than you might want to look at this.
https://developers.google.com/speed/docs/insights/rules

say you want to alert after the div#content is loaded. if you put your javascript after div's closing tag, it will run after loading all the html prior to the script.
<div id="content">
// your content
</div>
<script type="text/javascript">
alert("finished loading until this point");
</script>

Related

Does jQuery .length defies DOM ready?

I have this code:
Function loader() will keep running until <body> does exist. When <body> does exist, insert .loader
<html>
<head>
<script type="text/javascript" src="jquery/jquery-3.2.1.min.js"></script>
<script type="text/javascript">
loader();
function loader() {
if (!$('body').length) {
window.requestAnimationFrame(loader);
} else {
$('<div class="loader"></div>').prependTo('body');
}
};
</script>
</head>
<body>
<!-- elements -->
</body>
</html>
I want to ask this line
if (!$('body').length) {}
What do .length use to determine its return, is it <body> or <body></body>? Does .length wait for closing tag </body> or not? If it does, what is my alternatives? I need .loader to be inserted without waiting for </body>.
My last resort would be
<body>
<div class="container"></div>
<!-- rest of elements -->
</body>
So then
if (!$('.container').length) {}
But I need alternatives that don't interfere with the elements structure.
EDIT:
I rephrase the question and add below codes.
<html>
<head>
<script type="text/javascript" src="jquery/jquery-3.2.1.min.js"></script>
<script type="text/javascript">
$(function(){
console.log("ready timestamp");
});
loader();
function loader() {
if (!$('body').length) {
window.requestAnimationFrame(loader);
} else {
console.log("length timestamp");
}
};
</script>
</head>
<body>
<!-- elements -->
</body>
</html>
Output:
15:03:19.862 length timestamp
15:03:20.198 ready timestamp
Length timestamp always lower than ready timestamp.
Tested with:
Chrome 71.0 and FF 65.0
Enable timestamp in Console Settings (Developer Tools -> Console -> Show timestamps).
Other might ask why I did this, what's right about 300ms?
I implement PWA and need loader, like this:
Showing loader while navigating between pages - PWA.
The problem is, there is 300ms between .on('beforeunload') of the previous page and $() of the next page. It's a blip, obviously.
This blip can ideally/easily be solved by server side scripting but as I mentioned above, I have no access to server side scripting, the furthest I can ask is a blank element <div class="container"></div>.
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
console.log( $('#tryToFindMe').length );
</script>
<div id="tryToFindMe"></div>
Similar to how your question tries to access the body before it is defined, this snippet tries to access the div before it is defined. In both cases, the element will not be found.
The reason for this is because when your browser is parsing your webpage into the Document Object Model it parses from top down. So at the point that the script runs, the html that will create the div in the DOM has not been processed yet. So the script tries to lookup the element, it does not exist, and the length is zero.
This is why using the jQuery document ready, binding to the DOMContentLoaded event or the load event exist. These different approaches defer the execution of your logic until either the entire page has been parsed into the DOM, or in the case of load, that not only the page has been parsed into the DOM, but all the resources have been received as well (images, videos, etc). Without these approaches, the script will need to appear in the page after the element is defined to ensure the element exists already in the DOM.
The important part when thinking about interacting with the DOM is not to think in terms of HTML. The DOM contains Nodes, not HTML. The nodes are generated from the HTML.
You can just use a jQuery document ready function ($(() => {})) like so:
$(() => {
$(`<div class="loader"></div>`).prependTo("body");
});
I ran another test.
<html>
<head>
<script type="text/javascript" src="jquery/jquery-3.2.1.min.js"></script>
<script type="text/javascript">
$(function(){
console.log("ready timestamp");
});
loader_bottom();
loader_body();
loader_top();
function loader_bottom() {
if (!$('.container_bottom').length) {
window.requestAnimationFrame(loader_bottom);
} else {
console.log("container_bottom.length timestamp");
}
};
function loader_top() {
if (!$('.container_top').length) {
window.requestAnimationFrame(loader_top);
} else {
console.log("container_top.length timestamp");
}
};
function loader_body() {
if (!$('body').length) {
window.requestAnimationFrame(loader_body);
} else {
console.log("body.length timestamp");
}
};
</script>
</head>
<body>
<div class="container_top"></div>
<!-- elements between -->
<div class="container_bottom"></div>
</body>
</html>
Output:
09:09:16.894 body.length timestamp
09:09:16.897 container_top.length timestamp
09:09:17.090 container_bottom.length timestamp
09:09:17.220 ready timestamp
Because $('.container_top') adjacent to $('body'), changing the sequence,
loader_top();
loader_body();
Not suprisingly output:
09:09:39.708 container_top.length timestamp
09:09:39.708 body.length timestamp
Hence I come into conclusions:
Does jQuery .length defies DOM ready? Yes it does.
What do .length use to determine its return, is it <body> or <body></body>? It is <body>.
Although the right phrase for second question should be:
What DOM Parser use to determine nodes, is it <tag> or <tag></tag>? The answer is <tag>.
Actually I'm not surprised that we can manipulate DOM before it's ready. Besides, $().ready() is just an event when DOM is ready. Javascript is multi-thread so (I thought) DOM Manipulating should could run parallel with DOM Parsing. Not until this code I can prove that.

PreLoad Index.HTML from another Page - Javascript

Firstly, I've searched around and found some things close to what I was looking for but nothing that helped me get to a solution. I have a professional landing page that uses a lot of high res images and stuff so I want to preload it before the users see it so it comes in smoothly. I'm using the below Javascript (I found) to load it in. But I don't think the current Javascript is actually preloading Index.HTML before displaying it. The below javascript is loaded from Preloader.html which I'll display that code below too.
preload.js
(function() {
var preload = document.getElementById("preload");
var loading = 0;
var id = setInterval(frame, 64);
function frame() {
if(loading == 100) {
clearInterval(id);
window.open("index.html", "_self");
return false;
} else {
loading = loading + 1;
if (loading == 90) {
preload.style.animation = "fadeout 1s ease";
}
}
}
})();
Preloader.html
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" type="text/css" href="css/style.css"/>
</head>
<body>
<div class="preload" id="preload">
<div class="logo">
</div>
<div class="loader-frame">
<div class="loader1" id="loader1"></div>
<div class="loader2" id="loader2"></div>
</div>
</div>
<script type="text/javascript" src="js/preload.js"></script>
</body>
</html>
I'm pretty sure it's because I'm a complete noob to javascipt and it's only doing window.open and no actual tracking of the index.html page being preloaded. But I couldn't find anything online to confirm this. I believe all my preload.js is doing right now is just on a delay timer using the else statement then it opens index.html without it actually being preloaded.
Thanks for your time, Cheers!
What is going on here is that you're "loading" the page when the counter reaches 100%, and then you're asking the browser to load the page. Indeed no preloading is being done because all that needs to be loaded is the page itself. To sum it up.
The loader page "loads" itself
The loader page displays some animation
When the counter reaches 100, the code asks the browser to navigate to another page
Browser opens page and starts loading the real content
You need to keep all this code together in your page, there is no correct way of knowing the PERCENTAGE of loading from your website, but you can know WHEN it has loaded by using this function:
<script>
window.onload = function() {
alert('page finished loading all images, css and js!');
hideOverlay();
};
</script>
Use this function to hide your overlayElement like so:
function hideOverlay() {
document.querySelector('#preload').style.display = 'none';
}

jQuery : why is document.ready function not working properly

I am trying to learn jQuery and I am confused how document.ready() function works
$(document).ready(function(){}
In html,
<script type="text/javascript" src="jquery.js"></script>
<script src="script.js" type="text/javascript"></script>
links are at the very bottom of the document, just before the closing body tag. In my javaScript file, I have all my code inside the .ready function. Yet, when I load the page, and I hover over a link, my cursor doesn't turn into a pointer for a couple of seconds, and if I immediately scroll down, the text is not yet loaded for a couple of seconds, either.
My javaScript file has a bunch of iframes etc... so I can understand why the delay, but what confuses me is that I thought the whole point of the .ready function was that the javaScript wasn't loaded until everything else in the page was loaded first? So surely my text and my css should be working straight away? Here is my code if it helps. I can post css too if required.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>myPage</title>
<link rel="stylesheet" type="text/css" href="styles2.css">
</head>
<body>
<div id="container">
<div id="backgroundLeft"><img id='backgroundLeftImage' src="Left.jpg" width="100%"></div>
<div id="wrap">
<p id="text">...some text... <span id="firstLink" class="link">click me</span>.<span><iframe id="frame" class="rect" scrolling="no" marginwidth=0 marginheight=0></iframe>
</span> ...some more text.... <span id="secondLink" class="link">click me</span>,
</span><span>
<iframe id="frame2" class="rect" scrolling="no" marginwidth=0 marginheight=0></iframe>
</span>
... some more text... <span id="thirdLink" class="link">click me</span> </span><span>
<iframe id="frame3" class="rect" scrolling="no" marginwidth=0 marginheight=0></iframe>
</span> ... some more text...
ETC...
</p>
</div>
<div id="backgroundRight"><img id='backgroundRightImage' src="2VillesRight.jpg" width="100%"></div>
<script type="text/javascript" src="jquery.js"></script>
<script src="script2.js" type="text/javascript"></script>
</body>
</html>
js
$(document).ready(function(){
var frame = $("#frame");
frame.attr("src","iframe.html");
var frame2 = $("#frame2");
frame2.attr("src","iframe2.html");
var frame3 = $("#frame3");
etc...
var player;
frame.bind("load", function () {
player = $(this).contents().find("#firstVid");
player.on('ended', function () {
frame.removeClass("open");
});
});
$("#firsLink").click(function(){
if (frame.hasClass("open"))
{
frame.removeClass("open");
player[0].pause();
}
else {
frame.addClass("open");
player[0].play();
}
});
var player2;
frame2.bind("load", function () {
player2 = $(this).contents().find("#sylvainVid");
player2.on('ended', function () {
frame2.removeClass("open");
});
});
$("#secondLink").click(function(){
if (frame2.hasClass("open"))
{
frame2.removeClass("open");
player2[0].pause();
}
else {
frame2.addClass("open");
player2[0].play();
}
});
var player3;
frame3.bind("load", function () {
player3 = $(this).contents().find("#etienneVid");
player3.on('ended', function () {
frame3.removeClass("open");
});
});
$("#thirdLink").click(function(){
if (frame3.hasClass("open"))
{
frame3.removeClass("open");
player3[0].pause();
}
else {
frame3.addClass("open");
player3[0].play();
}
});
etc...
});
I do know my code is repetitive, I am teaching myself so focused on getting it to work for now. Why is my main page taking so long to load if all my code is inside the "document.ready"? Thanks for your time
you can instead bind your javascript to the window.load event like this
Edit: tis is not good practice and unsupported in newer versions of jQuery
$(window).load(function(){ ... });
Correct way to do this
$(window).on("load", function(){ ... });
document ready lets you access the complete markup, even if the images and iframes have not loaded yet, this is desired in most cases.
In your case however, you might want to take the time penalty of waiting for everything to load, this is that the window.load event does.
$(document).ready() will only wait for all of the page's elements to load. It will NOT wait for the iFrames to load their content.
You can refer to this post if you have more questions:
$(document).ready and iframe content
Are you sure JQuery is loading properly? The source (src) property needs to point to the correct path. I find using the developer's tools to review errors, manipulate CSS and check DOM state to be helpful when learning. I prefer Chrome.
Happened to me too. What I found that, the solution is to include the file at the bottom outside of html tag (i.e the file in which you are using $(document).ready() ).
I assume that, this is because the html document is not ready by the time when browser compiler reached at this function.

Page Redirect Not Working for mobile device

I have the following code that doesn't redirect when a mobile device accesses the web page. Where I'm I going wrong?
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
var bodyclass = $('body').is('.index');
if ((screen.width <= 800) && (bodyclass = true)) {
window.location = "m/index.html";
}
</script>
<title>screen stest</title>
</head>
<body class="index">
<div class="style">
<h1>index try10000</h1>
</div>
</body>
</html>
There are a couple of things, first are you sure your device is <= 800px width? Second your script is being loaded in the head and blocks the loading of the remaining DOM structure. As you have code that relies on the DOM being loaded you need to defer the execution of your script until the DOM is loaded. Wrap you code in a DOM ready function (example using jQuery).
$(function() {
var bodyclass = $('body').is('.index');
if ((screen.width <= 800) && (bodyclass = true)) {
window.location = "m/index.html";
}
});
Or better yet, just move your script to be the last element of the body. Then there is no need for a DOM ready wrapper.

How to hide a div if an URL cannot reached?

I have integrated a Twitter feed into a website, if the end location (presumably http://twitter.com/something) cannot be reached, the feed does not display. This is ideal, however I have a title div placed directly above the feed which remains visible regardless of whether the feed is displayed on the page or not.
Is it possible to prevent the div (#title) from displaying if a URL cannot be reached? I've found JavaScript snippets which look to hide a div based on the URL of the file being viewed, but this doesn't seem to work in my situation.
HTML:
<div id="title">
<h3>Latest Tweets</h3>
</div>
<div id="twitter_update_list">
<script type="text/javascript" src="http://twitter.com/javascripts/blogger.js">
</script>
<script type="text/javascript" src="http://api.twitter.com/1/statuses/user_timeline/SW_Trains.json?callback=twitterCallback2&count=3">
</script>
</div>
Many thanks in advance. I understand that this may not be possible with JS.
Use this.
<div id="title" style="display:none;">
<h3>Latest Tweets</h3>
</div>
<div id="twitter_update_list">
<script type="text/javascript" src="http://twitter.com/javascripts/blogger.js">
</script>
<script type="text/javascript" src="http://api.twitter.com/1/statuses/user_timeline/SW_Trains.json?callback=twitterCallback2&count=3">
</script>
</div>
<script type="text/javascript">
window.onload = function(){
var tdata = jQuery('#twitter_update_list').html().length;
if(tdata > 0)
{
jQuery('#title').css('display','block');
}
else
{
jQuery('#title').css('display','none');
}
}
</script>
May be it helps to you.
Maybe sth like
var divContent = document.getElementById('twitter_update_list');
if (NOT divContent) {
//no content detected
document.getElementById('title').style.visibility = 'hidden';
}
This is untested and I don't know if it works. You will have to create a function which will be executed when the page has completely loaded. Maybe sth like:
window.onload = function(){
// your code...
};
After load make a function that tests the content of the div that would hold the content. If is empty just hide whatever you need to hide.

Categories