How to know if an element is rendered? - javascript

My element has transition: transform .5s
then it has a separate class: transform: translatex(-100%)
So what I would like to achieve is that initially, the element is positioned towards the left. At window onload,When the element is rendered, I remove the transform class, and the browser would animate the element back to its correct position.
But what actually happens is that when the page becomes visible/rendered, the element is already at the correct position. and there is no animation.
I tried setTimeout(function() {}, 0); it doesn't work. If I setTimeout for 1 second, it works, but sometime rendering takes long, and I have to setTimeout for 2 seconds. But then sometimes it renders fast, and 2 seconds is a long time to wait.
So overall, I feel this is not a reliable or a correct way of doing this.
How can I achieve what I want, the correct way?
Edit:
Sorry guys, after trying to put together a demo, I realized I wasn't removing the class at window onload. This is because my element and its javascript and css are loaded with AJAX. So it can happen before the window onload or after the window onload.
Anyway, now my question is, what if the window takes a long time to load? Could it be possible that my element would be rendered before window finishes loading? Or does browsers only render when the entire window finishes loadings?
Because I want to animate the element as soon as possible. So, is it safe to wait for window onload, in the case that window takes a long time to load(images and slow connection, and stuff)?
And if I load the element with AJAX after the window loads, could I immediately run the animation by removing the transform? Or should I detect for when the element is rendered?

You might want to try using a combination of the DOMContentLoaded event and requestAnimationFrame. DOMContentLoaded fires after the document has been completely loaded and parsed but before all of the images and other assets on the page have completed downloading. requestAnimationFrame will delay the removal of the class until after the page has been painted so the element will properly transition.
var box = document.getElementById('box'),
showBox = function (){
box.classList.remove('offscreen');
};
document.addEventListener("DOMContentLoaded", function(event) {
window.requestAnimationFrame(showBox);
});
jsfiddle

You should use DOM Content Loaded event of javascript
document.addEventListener("DOMContentLoaded", function(event) {
console.log("DOM fully loaded and parsed");
});
This will be fired only when your entire content is loaded and parsed fully by your browser.

Don't consider this an answer as I am sure you can find something more elegant, but this may give you some ideas.
Add this to the javascript AJAXed in - be sure to wrap the javascript in a document.ready:
$(function(){
var giveup = 0; //in case something goes wrong
var amirendered = 0;
while (amirendered==0){
setTimeout(function(){
if (element.length){
amirendered = 1;
$('#myElement').addClass(doTransition);
}
},200);
giveup++;
if (giveup>200) amirendered++; //prevent endless loop
}
}); //END document.ready

Related

How to clear these intervals?

I'm creating my own JSFiddle-like webapp and I want to implement elements resizing, but keep document height unchanged, so I have to recalculate elements dimensions on each resize.
I have this script:
var a = setInterval(setHeight, 1);
var b = setInterval(formsWidth, 1);
iframe.onResizeStart = a;
html.onResizeStart = b;
iframe.onResizeStop = clearInterval(a);
html.onResizeStop = clearInterval(b);
Iframe is an element where user codes are rendered and HTML is one of my three textareas. I want this script to recalculate textareas heights on iframe resize and recalculate their widths on changing width of one of them.
I managed to make this work, but I couldn't stop intervals and I need help with it.
The above code doesn't work now at all, probably because of calling a variable onResizeStart.
I'd be grateful if someone could help me.
I prefer not to use jQuery.
It doesn't work because you're calling clearInterval() almost immediately after calling setInterval(), so the intervals are never getting a chance to execute. You'll need to store away a and b and then call clearInterval() on them at a later time, after the resizing is all done.
EDIT: Looking at this more closely, just wrap each call to clearInterval() in a function. That way clearInterval won't get executed immediately, but rather when the onResizeStop event is fired.
iframe.onResizeStop = function() { clearInterval(a); };

Perform animation on a page after page has loaded

I am doing maintenance work for a website. The logo on the home page is supposed to bounce in from left after page has loaded but the animation begins even when the page is still loading.
The code is
$(document).ready(function(){
$('#logo-large').addClass('animated bounceInLeft');
});
The site is using animate.css library
The ready method do not wait for resources to load.
While JavaScript provides the load event for executing code when a page is rendered, this event does not get triggered until all assets such as images have been completely received. In most cases, the script can be run as soon as the DOM hierarchy has been fully constructed. The handler passed to .ready() is guaranteed to be executed after the DOM is ready, so this is usually the best place to attach all other event handlers and run other jQuery code. When using scripts that rely on the value of CSS style properties, it's important to reference external stylesheets or embed style elements before referencing the scripts.
Reference: https://api.jquery.com/ready/
Use window.load method:
The load event is sent to an element when it and all sub-elements have been completely loaded. This event can be sent to any element associated with a URL: images, scripts, frames, iframes, and the window object.
$(window).on('load', function() {
$('#logo-large').addClass('animated bounceInLeft');
});
Reference: https://api.jquery.com/load-event/
The problem here is that you say "page loaded" but you haven't defined what that means. The animation is, indeed, playing after the DOM has loaded. That's what the $(document).ready method insures. However, any images or asynchronous calls can still trigger after the DOM is ready. So... the REAL question is, do you want to wait til after the images have loaded AND do you have any asynchronous calls that need to be accounted for.
I just wrote this so I'm not 100% sure if it doesn't have any bugs, but this should work for both cases.
jQuery.prototype.pageComplete = function(promises, callback){
if(!callback){
callback = promises;
promises = [];
}
var images = jQuery.Deferred();
var DOMReady = jQuery.Deferred();
var count = this.length;
promises.push(images);
promises.push(DOMReady);
jQuery(document).ready(function(){
DOMReady.resolve();
});
function counter(){
if(--count == 0) images.resolve();
}
this.each(function(image){
var img = new Image();
img.onload = counter;
img.src = image.src;
});
jQuery.when.apply(jQuery, promises).then(callback);
};
You use it like so:
// for just images
$('img').pageComplete(function(){
// code to transition image here
});
// for images and ajax
$('img').pageComplete([
ajax1, // these are all promises created by jQuery.ajax
ajax2,
ajax3
],
function(){
// code to transition image here
});
Try this one, solution should work without jquery
window.onload = function() {
document.getElementById('logo-large').classList.add('animated', 'bounceInLeft');
};
Use The Window Load Function
This will wait until the whole page has loaded before running the animation
jQuery(window).load(function() {
$('#logo-large').addClass('animated bounceInLeft');
});)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

jQuery/JavaScript wait for page to load, but no shorter than specified time

I'm having the following issue:
I want to display an overlay until the page loads completely, which works just fine.
The problem is that on fast connections the overlay would disappear immediately, which is not what I want to achieve.
I was trying to do it the following way:
$(document).ready(function(){
setTimeout(function(){
$(window).load(function(){
$('#overlay').fadeOut(1200);
});
},1500);
});
which seemed logical to me. Didn't work. I replaced setTimeout with setInterval, didn't work, too. I put the $(window).load...etc. in a function and called it with an external setTimeout, no success. The best result in regard to that additional timer was, that browsers ignored it altogether; most of the time the overlay just stays there, nothing happens.
What am I missing?
You certainly don't need $(window).load... within the setTimeout function. In fact, putting it within the timeout will ensure that it never executes since the window.load event will have already fired before you assign it your function to fadeOut the overlay.
I've adjusted my code based on your feedback. The basic principle is to determine how long it took to get everything ready and then reduce the timeout based on the time already elapsed. This way your fastest connections will still get a delay while your slowest connections will execute the fadeout immediately.
Live Demo
//Put this line in a script tag as high up on the page as possible
window.timeInMs = Date.now();
Instead of document.ready which executes after the document is loaded, use window.load which executes after the entire page has loaded (frames, objects, images) - src.
$(window).load(function(){
var maxTimeout = 1500;//Everyone waits at least this amount, including fast browsers.
//Compute the elapsed time, default to 0 if more than maxTimeout has elapsed.
var remainingTime = Math.max(maxTimeout - (Date.now() - window.timeInMs), 0);
setTimeout(function(){
$('#overlay').fadeOut(1200);
}, remainingTime);
});

Placeholder while an image is loading with Ember.js [duplicate]

I'm currently working on a web application which has a page which displays a single chart (a .png image). On another part of this page there are a set of links which, when clicked, the entire page reloads and looks exactly the same as before except for the chart in the middle of the page.
What I want to do is when a link is clicked on a page just the chart on the page is changed. This will speed things up tremendously as the page is roughly 100kb large, and don't really want to reload the entire page just to display this.
I've been doing this via JavaScript, which works so far, using the following code
document.getElementById('chart').src = '/charts/10.png';
The problem is that when the user clicks on the link, it may take a couple of seconds before the chart changes. This makes the user think that their click hasn't done anything, or that the system is slow to respond.
What I want to happen is display a spinner / throbber / status indicator, in place of where the image is while it is loading, so when the user clicks the link they know at least the system has taken their input and is doing something about it.
I've tried a few suggestions, even using a psudo time out to show a spinner, and then flick back to the image.
A good suggestion I've had is to use the following
<img src="/charts/10.png" lowsrc="/spinner.gif"/>
Which would be ideal, except the spinner is significantly smaller than the chart which is being displayed.
Any other ideas?
I've used something like this to preload an image and then automatically call back to my javascript when the image is finished loading. You want to check complete before you setup the callback because the image may already be cached and it may not call your callback.
function PreloadImage(imgSrc, callback){
var objImagePreloader = new Image();
objImagePreloader.src = imgSrc;
if(objImagePreloader.complete){
callback();
objImagePreloader.onload=function(){};
}
else{
objImagePreloader.onload = function() {
callback();
// clear onLoad, IE behaves irratically with animated gifs otherwise
objImagePreloader.onload=function(){};
}
}
}
You could show a static image that gives the optical illusion of a spinny-wheel, like these.
Using the load() method of jQuery, it is easily possible to do something as soon as an image is loaded:
$('img.example').load(function() {
$('#spinner').fadeOut();
});
See: http://api.jquery.com/load-event/
Use the power of the setTimeout() function (More info) - this allows you set a timer to trigger a function call in the future, and calling it won't block execution of the current / other functions (async.).
Position a div containing the spinner above the chart image, with it's css display attribute set to none:
<div> <img src="spinner.gif" id="spinnerImg" style="display: none;" /></div>
The nbsp stop the div collapsing when the spinner is hidden. Without it, when you toggle display of the spinner, your layout will "twitch"
function chartOnClick() {
//How long to show the spinner for in ms (eg 3 seconds)
var spinnerShowTime = 3000
//Show the spinner
document.getElementById('spinnerImg').style.display = "";
//Change the chart src
document.getElementById('chart').src = '/charts/10.png';
//Set the timeout on the spinner
setTimeout("hideSpinner()", spinnerShowTime);
}
function hideSpinner() {
document.getElementById('spinnerImg').style.display = "none";
}
Use CSS to set the loading animation as a centered background-image for the image's container.
Then when loading the new large image, first set the src to a preloaded transparent 1 pixel gif.
e.g.
document.getElementById('mainimg').src = '/images/1pix.gif';
document.getElementById('mainimg').src = '/images/large_image.jpg';
While the large_image.jpg is loading, the background will show through the 1pix transparent gif.
Building on Ed's answer, I would prefer to see something like:
function PreLoadImage( srcURL, callback, errorCallback ) {
var thePic = new Image();
thePic.onload = function() {
callback();
thePic.onload = function(){};
}
thePic.onerror = function() {
errorCallback();
}
thePic.src = srcURL;
}
Your callback can display the image in its proper place and dispose/hide of a spinner, and the errorCallback prevents your page from "beachballing". All event driven, no timers or polling, plus you don't have to add the additional if statements to check if the image completed loading while you where setting up your events - since they're set up beforehand they'll trigger regardless of how quickly the images loads.
Some time ago I have written a jQuery plugin which handles displaying a spinner automatically http://denysonique.github.com/imgPreload/
Looking in to its source code should help you with detecting when to display the spinner and with displaying it in the centre of the loaded image.
I like #duddle's jquery method but find that load() isn't always called (such as when the image is retrieved from cache in IE). I use this version instead:
$('img.example').one('load', function() {
$('#spinner').remove();
}).each(function() {
if(this.complete) {
$(this).trigger('load');
}
});
This calls load at most one time and immediately if it's already completed loading.
put the spinner in a div the same size as the chart, you know the height and width so you can use relative positioning to center it correctly.
Aside from the lowsrc option, I've also used a background-image on the img's container.
Be aware that the callback function is also called if the image src doesn't exist (http 404 error). To avoid this you can check the width of the image, like:
if(this.width == 0) return false;
#iAn's solution looks good to me. The only thing I'd change is instead of using setTimeout, I'd try and hook into the images 'Load' event. This way, if the image takes longer than 3 seconds to download, you'll still get the spinner.
On the other hand, if it takes less time to download, you'll get the spinner for less than 3 seconds.
I would add some random digits to avoid the browser cache.

HTML / Javascript wait for graphics to be drawn

I've heard about the onload function which is called after the element is fully loaded.
In the case of graphics or images, does that mean it will wait until the image is displayed in the browser?
<body onload="foo()">...
<img onload="bar();"....
If not, is there a way to get the event when all graphics are drawn and images are displayed on a page?
In my case it´s only one 1600*1200 jpeg image and i draw on it. But the image has to be displayed before i start drawing, even with the onload event i see the drawed lines before the image appear.
Yes body onload will wait until all images (and other content) are loaded/displayed in the browser. The img onload will wait until that specific image has loaded/is displayed
Images have a complete property that's true when they are loaded.
e.g. would test if everything has loaded:
var allImagesLoaded = true;
$("IMG").each(function(){ allImagesLoaded &= $(this).attr("complete"); });
if(allImagesLoaded){ alert("Done!");}
Images raise a load event once they've finished loading
why dont you keep a counter for your images that will decrement by one on each image load.
check if it equal to 0 then call some another function.
in this way you can do the thing you want to when all images are loaded
$(function() {
$('img').one('load',function() {
// fire when image loads decrement the counter
if counter ==0
fireanotherfunction()
});
});
by above code u can attain your purpose
When reading the jQuery ready API documentation here:
While JavaScript provides the load event for executing code when a
page is rendered, this event does not get triggered until all assets
such as images have been completely received.
So onload is launched after everything has been loaded (and displayed).
See the window.load event:
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 and sub-frames have finished loading.
This is exact what you want, I believe.
JQuery's $(document).ready is not what you want:
In cases where code relies on loaded assets (for example, if the dimensions of an image are required), the code should be placed in a handler for the load event [instead of the ready event].
If you're using plain JS, window.load is what you want.
If you are using jQuery, you'll want $(document).load.
try jquery ready function
$(document).ready(function(){
bar();
});
I'm not sure if it works, but it's a try :D
I have the same problem developing a web view for an Android app. The load events (both for window and image element) as well as the complete state of the image element fire too early. My (svg) image has not yet finished drawing and thus calculations on the size go wrong.
The only workaround that I have found is a very short timer (1ms or maybe 10ms). That works for me because I have only one such image to consider. And since I start this timer when the image data has already loaded, this short lapse should be long enough for the device to paint the image.
window.addEventListener('load', function() {
var img = document.getElementById('logo');
window.setTimeout(function(){
var imgRatio = img.naturalWidth / img.naturalHeight;
var renderedWidth = parseInt(window.getComputedStyle(img).width.match(/(\d+)px/));
console.log(renderedWidth, img.complete);
if (renderedWidth < img.naturalWidth) {
img.style.height = (renderedWidth / imgRatio) + 'px';
}
}, 1);
}
Instead of the window load event, the image's load event should also work. But I found it safer to wait for everything, because other elements might affect the drawing of my image.

Categories

Resources