Change image with jQuery and see image getting loaded - javascript

I am dynamically changing images with jQuery using $('img').attr('src','newUrl');
Doing so, the image is only displayed when entirely loaded.
My connection is slow, so I would like the image to directly display and see it getting progressively loaded, the same way images “appear” when I arrive on any page on the web (whether from top to bottom, or from blurry to sharp depending on the compression algorithm of the image).
I want to do this with javascript, jQuery, or any simpler alternative.
(I know how to display a progress bar, or a "loading…" text while the image loads, that's not what I'm looking for)
Here's a fiddle if you want to update.

I've found a way to do that, what you want. Don't use attr("src",) from jquery, remove and add the hole img element with html(), so you trigger the browser to load the image source and the browser displays the image while loading (tested in chrome).
Html:
<p><button>change image source</button></p>
<div>
<img src="http://xxxxx">
</div>
Script:
var newImg = '<img src="http://yyyyyy">';
$('button').click(function(){
$('div').html(newImg);
});
Here is your updated fiddle: http://jsfiddle.net/jxwv52u7/1/
I hope it helps.

Based on some testing I did about a year ago, I found no reliable way to get a load event when changing the .src of an image from one value to another. As such, I had to resort to loading a new image and replacing the one I had with the new one when the new image was loaded. That code has been running successfully in several hundred web sites (it's used by a slideshow) for about a year now so I know it works.
If you set the load handler BEFORE you set the .src property on a new image, you will reliably get the load event. Here's some code I wrote just earlier today for capturing the load event: jQuery: How to check when all images in an array are loaded?.
This code that attaches the event handler BEFORE settings the .src works for me in the modern browsers I've tried it in (I didn't test older browsers):
$("img").one("load", function() {
// image loaded here
}).attr("src", url);
You can see it work here:DEMO and you can test any browsers you want using that jsFiddle. Just click on the image to cause it to load a new image. It cycles through three different images (setting .src each time), loading two of them uniquely every time (never from the cache) and one from the cache in order to test both cases. It outputs a msg to the screen whenever the .load handler is called so you can see if it's called.

Related

Using jQuery to replace UIKit's Slideshow source image with a responsive one based on srcset

HTML:
<div id="rb-hero" class="rb-hero uk-block uk-flex uk-flex-middle uk-contrast arrowed">
<ul class="uk-slideshow uk-slideshow-fullscreen" id="biggie_slides" data-uk-slideshow="{pauseOnHover: false, autoplay:true}">
<li><img src="{theUrlMedium}" alt="{theAltText}" srcset="{theUrlSmall} 750w, {theUrlMedium} 1200w, {theUrlLarge} 2000w, {theUrlXL} 3000w" ></li>
</ul>
</div>
jQuery:
$('#rb-hero li img').each(function() {
var theSrc = $(this).prop('currentSrc');
// console.log(theSrc);
$(this).prev('div').attr('style', 'background-image: url( '+theSrc+' )');
});
UIKit provides a slideshow function, and I have it in use and it works just fine. The way it works is to use each image slide's src as an inline background-image style attribute on a dynamically-created div. All works fine.
The problem is that UIKit does not use the appropriately-sized image from the provided srcset (which is also working correctly per the currentSrc info in devtools), it simply grabs the fallback img src and thus a pretty high-res image when on mobile.
I'm trying to loop through the elements and replace the inline style's background-imagesource with the currentSrc, but I'm hitting a wall.
The each() method is doing its magic and the console logs the smaller-sized image based on the appropriate srcset source at smaller screens, but the setting of the inline style is going nowhere.
So I'm missing something, and it's probably going to be obvious and glaring but in addition to sleep I need an assist.
Thanks.
Edit: Updated code to a better working place and now only the final bit's not working.
I edited my first answer as it was complete nonsense.
I did some testing with your code and two differently sized images and found that it actually works, but only if certain conditions are met:
I noticed that the browser won't load a smaller sized image from the srcset if there's a larger one already in the cache. I guess it's meant to work this way, but you'll have to keep that in mind and clear the browser cache while testing.
But if you first resize your browser window, then clear the cache and reload the page, the smaller images actually are being loaded and set as background images. I also had to wrap your code in a setTimeout function, otherwise even the console.log was empty and nothing happened. This wasn't necessary with an enlarged browser window (probably because it loaded the image straight from the src tag so there was no delay).
Another problem is that uikit will have set the background image from the src tag and the browser will have loaded it before you set the image url from the srcset, so you'll load both files (which is even worse than only loading the large one on a small screen).
The cleanest and easiest solution would be to modify uikit's slideshow component. They only had to change the part where the image url is read from attr('src') to prop('currentSrc').

Detecting when an image has loaded

Is it possible to detect - using jQuery or pure DOM manipulation / events - when an image that was injected into the document has fully loaded? For example, a script needs to replace one image with another. If it just changes the src attribute, the user will see an image disappear briefly (or not so briefly, depending on their connection). So, a better option would be to create a new image element in some hidden place (or, if cross-platformly possible, out of DOM entirely) and switch images only when the new one is ready. Can this be done?
EDIT: It might be a separate question, but still... Is there also a way to detect when an image has failed to load?
You can use image.onload = function(){<...>};
Image is the actual image you want to get the load of.
<img src='...' id='image'>
In order to check if the image finished loading do the following->
document.getElementById('image').onload = function(){<...>}
or
document.getElementById('image').addEventListener('load',function(){<...>},false);
If you want to check if the image failed to load do this->
document.getElementById('image').onerror = function(){<...>}
or
document.getElementById('image').addEventListener('error',function(){<...>},false);
Note
.addEventListener method won't work in IE8. If you are planning on supporting it I can edit my answer.
yes you can do that by using the .load() event.
like,
$('#img1').load(function(){ alert('loaded'); });
the alert will be displayed when the resources for that particular selector has loaded fully.
The .load() event does not always work as expected and is prone to fail under different circumstances. For broadest browser support I suggest to use DeSandro's imagesLoaded (which I find to be best practice anyway): https://github.com/desandro/imagesloaded

How to select a loaded image and insert it into a div

I've got an image that is loaded when the site is called.
<img id="some_Image" src="some_source">
Now I want to reuse that image and NOT request it again from "some_source". (Because it has to be computed and I do not want to recalculate it). I want that image later to be displayed in some JQuery dialog. I know the existance of append and prepend functions, but reading the documentation it seems like I have to insert a whole image tag as an argument, which results in requesting the image again. (if the browser doesn't cache the image)
have a look at the jQuery clone
it is supposed to work with images as well, if the image has been loaded by the browser its supposed to reuse it.
EDIT:
$( "#some_image" ).clone().appendTo( "#some_div" );
By default, all browsers cache as much as they can (js, css, images). This way, the moment your image is loaded you can create a new <img> tag with the same source path and the browser will use its local cached file.

jQuery changing <img> src with $(selector).prop takes a long time

So there's no issue with this code functionality itself. I have something like this:
<div>
<div><img id="imageToChange" src="/path/image.png" /></div>
<div id="textToChange">Text</div>
</div>
I have another part of my code, that changes the image src/text with jQuery.
function changeImage() {
$('#imageToChange').prop('src', '/path/image2.png');
$('#textToChange').html('New Text');
}
As you may expect, this works exactly as I expect it to. But with 1 quirk.
In all the main browsers (chrome/FF/IE). The image takes a long time to change.
So for example, when I call changeImage(), the text will change instantly, but the image may not change until 1-2 seconds later. (Not large images by any stretch, about ~6KB, and local)
I haven't found anyone else really complaining about it, but what I'm wondering is if there's any way to speed up the changing of the image src? Perhaps a better way to do it?
This is jquery 1.8.0 as well.
Thanks
I have seen this behavior before. The delay is caused by the image not being cached and the subsequent load time. The only solutions I know of:
Preload your images with JavaScript Image objects.
Handle the load event on the image and update the text after the image as loaded. Note jQuery lists some issues to watch out for:
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
http://api.jquery.com/load-event/
You may want to try altering the attribute using the jquery .attr function. If I recall correctly the src tag of an image is an attribute not a property. Although both .prop and .attr do relatively the same function, to ensure consistent behavior between browsers you may want to use the .attr tag instead.
$('#imageToChange').attr('src', '/path/image2.png');
As far as the delay goes, this could be due to the size of the image. The browser has to make a GET request to the server for the image and then paint the DOM with it. If the image is large, it could cause a time lapse between when the code changes the source and when the new image is properly written to the DOM. If the image is large, you may want to consider scaling it down or optimizing it for web use.
Hope this helps.
You can pre-load the image using the Javascript Image object.
In the head of your document put
<script type="text/javascript">
img2 = new Image();
img2.src = "/path/image2.png";
</script>
when you change the src of the image you fetch another image file. it makes an HTTP request for the new image, so it needs to load before showing it. could this be it?
btw, for this reason you can pre-load the image with js. either add
<img src="path/to/image.jpg" style="display: none" />
to your html or using JS
var im = new Image(1,1);
im.src = "path/to/image.jpg";
this way the image will be cached
It's the delay of network. Try this:
<div>
<div><img id="imageToChange" src="/path/image.png" /></div>
<div id="textToChange">Text</div>
</div>
<img src='/path/image2.png' style='display:none'>
it is likely the load time of your images. if this is the case, loading the image the first time should be the only slow one. a follow up load, after changing the image to something else, would be fast.
$('#imageToChange').prop('src', '/path/image1.png');
//slow, need to fetch image
$('#imageToChange').prop('src', '/path/image2.png');
//slow, need to fetch image
$('#imageToChange').prop('src', '/path/image1.png');
//fast, it already has this image
As a solution, you could try preloading your images. Or, better yet, use css sprites.

jQuery .load importing special characters

I currently have a mind boggling error. I am using the .load function in jQuery to load images for a slideshow and getting a bunch of errors below by img tag that i am importing the url to. I have done my best to demonstrate my function and markup below. I do not get an error in any modern browsers but IE gives me errors
$('a').click(function(e){
$(trainFull).fadeOut(400, function(){
jQuery(trainFull[0]).load('http://img.jpg", function(){
jQuery(this).hide().attr('src', 'http://img.jpg").fadeIn(400);
});
<img alt="Train Full" src="http://img.jpg" ">
<img xmlns="http://www.w3.org/1999/xhtml">�����JFIF���d�d�����Ducky�����(�����Adobe�d���������--etc, etc, etc/>
If I understand you correctly, you're trying to pre-load the image using jQuery's XMLHttpRequest wrapper (load()). This is... unlikely to work well.
What you're seeing is IE trying to interpret binary image data as text (with predictably poor results), jQuery trying to stuff them into your <img> element, and IE trying to display them. While this probably does manage to pre-cache the image, it's the wrong tool for the job... and as you've demonstrated, a tool that can fail badly.
Fortunately, there are easier ways. Most browsers provide built-in support for loading images and notifying a script when they have loaded. For instance:
$('<img />') // detached image, used to pre-load
.attr('src', 'http://img.jpg') // tell it which image to load
.load(function() // attach a callback to inform us when it's loaded
{
// within the callback, "this" refers to the temporary image element
// that has just finished loading its source
// now that the image is in the cache,
$(trainFull[0])
.attr('src', this.src) // let our on-page image display it
.fadeIn(400); // and show that
});
If you want to learn more about this, I recommend starting with: jQuery ajax images preload.

Categories