Will setting the image.src to itself cause onLoad to fire? - javascript

I can't seem to find a definitive answer to this one...
Assume I have a JavaScript reference to an image on the page and I bind a load event handler to that element. For example, something like this:
HTML
<img id="myImage" src="http://example.com/image.jpg" />
JavaScript
var $myImage = $('#myImage');
$myImage.load(function() {
alert('Image loaded!')
});
Now, if I do this:
var imageElem = $myImage[0];
imageElem.src = imageElem.src; // Re-assign the image source path
...will the load event handler fire even if the image has already been loaded from the server? It seems to do in Firefox, but is it safe to rely on this behaviour?
(The reason I ask is I've seen this used in a jQuery plugin to check when all images have been loaded. If the image is loaded before the load event handler is bound, then it won't fire, unless it's re-triggered using the method above.)

Setting img.src should trigger load, with some caveats. According to jQuery's own documentation regarding the .load event,
Caveats of the load event when used with images
A common challenge developers attempt to solve using the .load()
shortcut is to execute a function when an image (or collection of
images) have completely loaded. There are several known caveats with
this that should be noted. These are:
It doesn't work consistently nor reliably cross-browser
It doesn't fire correctly in WebKit if the image src is set to the same src as
before
It doesn't correctly bubble up the DOM tree
Can cease to fire for images that already live in the browser's cache

checked this in Chrome inspector:
> img = document.createElement('img')
<img>​
> img.addEventListener('load', function(e) {console.log('loaded');});
undefined
> img.src = 'http://placekitten.com/200/300';
"http://placekitten.com/200/300"
loaded
> img.src = 'http://placekitten.com/200/300';
"http://placekitten.com/200/300"
> img.src = 'http://placekitten.com/200/30';
"http://placekitten.com/200/30"
loaded
> img.src = 'http://placekitten.com/200/300';
"http://placekitten.com/200/300"
loaded
> img.src = 'http://placekitten.com/200/300';
"http://placekitten.com/200/300"
So to answer with regards to Chrome - no, not unless you set the src to something else first.

I had this problem too and found a simple solution.
You can fire the loaded event multiple times by replacing the source attribute. Even if the value equals the existing source. You just have to add an different parameter, which is ignored by the server.
Take a look at this example:
var source = "http://example.com/image.jpg";
var imageElement = document.createElement('img');
imageElement.src = source + "?ignorethis=" + new Date().getTime(); // loaded
imageElement.src = source + "?ignorethis=" + new Date().getTime(); // loaded again
I know, it's a bit dirty, but works cross-browser.

Related

How to fire onload event for Image() on Android with Ionic 3

I'm trying to trigger function on "onload" event of Image() (HTMLImageElement) on Android with Ionic 3. It works with iOS but unfortunately doesn't work with Android.
How can I trigger onload function on Android? I do not use it with <img> or other tag, so I cannot fire it with <img (load)="functionHere()">.
(I have seen some of the other "onload" questions on Stack Overflow, this is about a specific situation with Android/Ionic 3).
Here is my example code:
this.backgroundImageSource = new Image();
this.backgroundImageSource.src = this.image;
this.backgroundImageSource.onload = function() {
// THIS PART DOESNT FIRE ON ANDROID
console.log("ONLOAD TRIGGERED");
}
If the example code is used exactly as shown, then the issue could be with onload event handler being defined after the event could happen. You should define the event handler function before the event could occur.
So onload must be handled before src attribute is set. Although, I'm not sure if the JS engine fixes this in any of its optimization steps.
this.backgroundImageSource = new Image();
//This has to be done before setting src
this.backgroundImageSource.onload = function() {
console.log("ONLOAD TRIGGERED");
}
this.backgroundImageSource.src = this.image;
I had the same problem.
I discovered that the base64 did not include a header/descriptor and so for that reason it was not firing.
I fixed this by appending a header in cases where one did not exist:
if (!base64Data.includes(',')) {
// Detect if base64 image is missing header/descriptor
console.log("Prepending descriptor to Base64 image string")
base64Data = `data:image/jpeg;base64,${base64Data}`;
}
(The comma is used to separate the header from the body).

Is there a replacement for .load() event handler?

I need a cross-browser (of course) way to get the native dimensions of an image file. All that I've found (e.g., Craig Buckler, Jack Moore, and
Chris Coyier) seem to require the image to have been loaded.
Unfortunately the .load() event handler of jQuery is now deprecated, but even if it weren't the docs make clear shortcomings that keep it from fulfilling my purpose:
It doesn't work consistently nor reliably cross-browser
It doesn't fire correctly in WebKit if the image src is set to the same src as before
It doesn't correctly bubble up the DOM tree
Can cease to fire for images that already live in the browser's cache
Is there a simple replacement for .load(), one that doesn't have those limits? Or maybe a quick workaround? I'd rather not install a whole library or plugin, but obviously jQuery is on the table.
I think this is as cross browser as you'll get
function get_dimensions(image_element, callback) {
var img = new Image();
img.onload = function() {
callback({width: this.width, height: this.height});
}
img.src = image_element.src;
if (img.complete) img.onload(); // avoids caching issues
}
you can call it like
var image = document.getElementById('myImage');
var width, height;
get_dimensions(image, function(dimensions) {
width = dimensions.width;
height = dimensions.height;
});

Using jQuery .error() to load replacement image for when an img tag doesn't load properly

I'm just wondering why the following doesn't seem to work for me (tried with Chrome and FF):
<img src="" />
<img src="asdf" />
// Change broken images to a placeholder image
$('img').error(function(){
$(this).attr('src', 'http://placehold.it/100');
});
Here's the jsFiddle
The onerror event has already fired, so you need to create a new image and listen for an error event on that :
$('img').each(function() {
var img = new Image(),
self = this;
img.onerror = function(){
$(self).prop('src', 'http://placehold.it/100');
}
img.src = this.src;
});
FIDDLE
this should answer your question
The event handler must be attached before the browser fires the error event, which is why the example sets the src attribute after attaching the handler. Also, the error event may not be correctly fired when the page is served locally; error relies on HTTP status codes and will generally not be triggered if the URL uses the file: protocol.
http://api.jquery.com/error/

detecting img loads in javascript

I have a function where I get the img src value as the parameter, what I want to do is check to see if that image loads with a 200 ok or 404/some other error. If it gets a 200 ok, then I want to inject an img tag with that src into the DOM(I reason that during checking,it also gets loaded into the browser cache and injecting that img tag into the DOM loads it from the cache ). I tried with a simple snippet of code as follows :
function checkImage(src)
{
var img = new Image(),
tag = '<img src="'+src+'" />',
alt = '<span>sorry,image broken</span>';
img.onload = function(){
$('.some-container').html(tag);
};
img.onerror = function(){
$('.some-container').html(alt);
};
img.src = src;
}
It worked fine in chrome, but went havok in firefox and ie(both of them are firing only the error event no matter whether the image loaded fine or broke). Instead of using onload and onerror, I tried it using jquery like :
$(img).load(...).error(...).attr('src',url);
$(img).on('load',...).on('error',...).attr('src',url);
$('<img />').load(...).error(...).attr('src',url);
$('<img />').on('load',...).on('error',...).attr('src',url);
and even tried the jquery.imagesLoaded plugin by desandro(https://github.com/desandro/imagesloaded) like :
$(img).imagesLoaded().done(...).fail(...);
$(img).imagesLoaded().progress(function(instance,image){
image.isLoaded?alert('loaded'):alert('broken');
});
$('<img />').imagesLoaded().done(...).fail(...).attr('src',url);
$('<img />').imagesLoaded().progress(function(instance,image){
image.isLoaded?alert('loaded'):alert('broken');
});
I also tried the solutions from :
jQuery callback on image load (even when the image is cached)
https://groups.google.com/forum/#!topic/jquery-dev/7uarey2lDh8
but as it turns out, works in chrome, but not in FF or IE, is there any solution where I can check for an image which is present in memory but not in the "DOM" ? Thanks in advance.
You have to check for image onload after setting a source to it.
var img = new Image();
//set source to the image
img.src = "set/image/source/path"
img.onload = function(){
//if image load is successful
//create an jQuery object out of this image
var jQimage = $(this);
$('.myContainer').html(jQimage);
}
Also note that jQuery load function cannot guarantee you a cross browser check for image loading as mentioned in jQuery docs
So, the best approach is to check onload with native javascript and create an jQuery object if necessary to make use of jQuery methods.
Have a look at what w3schools has to say about the Image() javascript object.
http://www.w3schools.com/jsref/dom_obj_image.asp
onabort - Loading of an image is interrupted, W3C YES
onerror - An error occurs when loading an image, W3C YES
onload - An image is finished loading, W3C YES
also the complete property of the Image() object, determines if the browser is finished loading an image, Unfortunately this particular property is not W3c
hope that helps a little
PS: After having a little Google search I found this Q/A from Stack overflow.
Cross-browser image onload event handling

Changing <img src="XXX" />, js event when new image has finished loading?

I have a photo gallery web page where a single <img src="XXX" /> element's src is changed (on a click) with JavaScript to show the next image—a poor man's ajax I guess. Works great on faster connections when the new image appears almost immediately. Even if it takes a few seconds to load, every browser I've tested it on keeps the old image in place until the new one is completely loaded.
It's a little confusing waiting those few seconds on a slow connection, though, and I'm wondering if there's some JavaScript event that fires when the new image is done loading, allowing me to put a little working... animated gif or something up in the meantime.
I know I could use AJAX for real (I'm using jQuery already), but this is such a nice and simple solution. Besides this lag, is there any other reason I should stay away from this approach to changing images?
You can set up a handler on the "load" event.
$('img.whatever')
.load(function() { /* do stuff */ })
.attr('src', newURL);
Actually I guess you'd want to do this with "live()":
$('img.reloadable').live('load', function() { $(this).show(); });
// ...
$('img#someId').hide().attr('src', newURL);
edit — whoa, where did that year go? Well, it turns out that one problem with that "live" approach I typed in way back when is that the "load" event does not bubble. Now what you can do, however, is leverage the way that "Image" objects (as opposed to <img> DOM elements) behave. Basically, the function that changes the URL can use an "Image" element as the place to keep the handler. The code that changes the actual "src" attribute of the real <img> tag would then also update the "src" of the "Image" object instance. The browser will only really load the image once (assuming cache control is all cool), but the browser will still call the "onload" handler of the "Image":
(function() {
var imageObj = new Image();
imageObj.onload = function() {
// code to run when image loads from server
};
$('#hypotheticalButton').click(function() {
$('#imgToUpdate').attr('src', newURL);
imageObj.src = newURL;
});
})();
You just just preload the images with jQuery so that way when the user clicks, the next image is already loaded and there shouldn't be a delay...that is unless the user goes to your page, and starts clicking on the image before they are loaded.
http://engineeredweb.com/blog/09/12/preloading-images-jquery-and-javascript
var slideimg = $('#slideimage');
slideimg.click(function(){
var img = new Image();
var url = 'url_to_next_image.jpg';
$(img).bind('load',function(){
$('#loading').hide();
slideimg.attr('src',url);
}).attr('src',url);
$('#loading').show();
});
This should work even with IE's crazy cache handling.

Categories