Is there any way without AJAX of changing the loading order of images on a page? Or even a way to completely halt or pause loading of images already present?
The use case is simple - I have a long list of images down a page, and visitors will be landing on different spots of the page using URL anchors (/images#middle-of-page) that refer to actual containers for those images.
I'd like in the least to load the images inside the requested container FIRST, then continue loading the rest of the images.
The challenge is that there is no way to know the image paths of the requested container image before loading the page DOM.
I've tried getting the container img contents on load, then using the Javascript new Image() technique, but it doesn't change the fact that that image on the page will still be waiting for all previous images to load.
I've also tried immediately prepending a div in the body with a background image (CSS) of said img path, but this also does not prioritize the image load.
Any other ideas?
You need to have a DOM with empty img placeholders, i.e.
<img src="" mysrc="[real image url here]" />
Or you can make images to display "Loading..." image by default. You can even cache real image url in some custom tag, mysrc for example. Then once you know what exactly images you want to show (and in what order) you need to build a sequence of image loading
var images = [];//array of images to show from start and in proper order
function step(i){
var img = images[i++];
img.onload = function(){
step(i);
}
img.src = "[some url here]"
}
Hope this helps.
For interest, this is the function I ended up implementing based on the answers here (I made it an on-demand loading function for optimum speed):
function loadImage(img) { // NEED ALTERNATE METHOD FOR USERS w/o JAVASCRIPT! Otherwise, they won't see any images.
//var img = new Image(); // Use only if constructing new <img> element
var src = img.attr('alt'); // Find stored img path in 'alt' element
if(src != 'loaded') {
img
.load(function() {
$(this).css('visibility','visible').hide().fadeIn(200); // Hide image until loaded, then fade in
$(this).parents('div:first').css('background','none'); // Remove background ajax spinner
$(this).attr('alt', 'loaded'); // Skip this function next time
// alert('Done loading!');
})
.error(function() {
alert("Couldn't load image! Please contact an administrator.");
$(this).parents('div:first').find("a").prepend("<p>We couldn't find the image, but you can try clicking here to view the image(s).</p>");
$(this).parents('div:first').css('background','none');
})
.attr('src', src);
}
}
The img loading="lazy" attribute now provides a great way to implement this.
With it, images load automatically only when on the viewport. But you can also force them to load by setting in the JavaScript:
document.getElementById('myimg').loading = 'eager';
I have provided a full runnable example at: How do you make images load lazily only when they are in the viewport?
One really cool thing about this method is that it is fully SEO friendly, since the src= attribute contains the image source as usual, see also: Lazy image loading with semantic markup
Related
I want to asynchronously download image, so first user sees a low resolution image, and higher resolution version is downloaded in the background. I have tried the following.
<html>
<head>
<script>
window.addEventListener('load', function () {
var kuvaEl = document.getElementById('kuva');
var r_src = kuvaEl.getAttribute('r-src');
var a_src = kuvaEl.getAttribute('a-src');
kuvaEl.setAttribute('src', r_src);
kuvaEl.setAttribute('src', a_src);
});
</script>
</head>
<body>
<img id="kuva" src="http://www.viikonloppu.com/wp-content/uploads/2014/04/lotoflaughters.com_-619x428.jpg?c3bc1b"
a-src="https://www.manitowoccranes.com/~/media/Images/news/2014/Potain-China-hi-res.jpg"
r-src="http://fuzyll.com/images/2016/angel_oak_panorama.jpg" />
</body>
</html>
But the problem is r_src download is aborted when src is change second time. I want to download both of these images in parallel, and show the r_src first (only if it downloads faster than a_src), and when the *a_src *is ready, show the a_src.
Also, is it possible to download these a_src and r_src images to the browser cache before the src is actually changed? Ideally I would like the the src change to either retrieve the image from the cache or join the pending download for that url.
I can also use jQuery. IE7 must support the implementation.
You just need to use javascript or jquery and load two version of the same image. the first will be your low res, but you will download a high res inside an hidden img tag.
When the download is complete, you just hide / delete the low res image and show the high res.
This link show some test and few way to do it. And it should support ie7 Load a low-res background image first, then a high-res one
You can use interlaced progressive JPEG format.
This method is the preferred method for handling high quality images and has been implemented by so many websites.the idea is that the compression of the image is made in such away that the when you send the image the receiver gets the image in finer and finer detail has the sending of the data progressed.
if you dont want to use the abouve technique
Have the low quality image in the src of the image. once the whole page loaded successfully,change the low quality image with high quality image
<img id="target-image" src="low-quality.jpg" data-src="high-quality.jpg" />
$(window).load(function(){
var imgSrc = $('#target-image').data('src');
$('#target-image').attr('src',imgSrc);
});
You should put your low res as default src. Then use JS to download the high res version and on download completion, change image src.
Also, good practice is to use data-* for custom attributes
If your really want a parallel download, you should replace "load" event for the "DOMContentLoaded" event. However, this will extend the time your user has to wait until page is ready. Your should keep the load event to prioritize critical assets loading (scripts and stylesheets)
window.addEventListener('load', function() {
// get all images
let images = document.getElementsByClassName("toHighRes");
// for each images, do the background loading
for (let i = 0; i < images.length; i++) {
InitHighResLoading(images[i]);
}
});
function InitHighResLoading(image) {
let hrSrc = image.dataset["hr"];
let img = new Image();
img.onload = () => {
// callback when image is loaded
image.src = hrSrc;
}
// launch download
img.src = hrSrc;
}
img {
/* only for code snippet */
max-height: 300px;
}
<img class="toHighRes"
data-hr="https://www.manitowoccranes.com/~/media/Images/news/2014/Potain-China-hi-res.jpg"
src="http://fuzyll.com/images/2016/angel_oak_panorama.jpg" />
I want to load two images in a single <img /> tag. First small image will be shown by src attribute and second large image will be inside data-src attribute but one image will be shown at once, that will be in src attribute. I want when page load small image will be load and show first and after completing loading of large image in the background it will be replaced by small image so that we can see large image. I have the code that will take large image from data-src attribute and place large image in src attribute.
$(document).ready(function(){
$("#image4").load(function(){
var imgDefer = document.getElementsByTagName('img');
for (var i=0; i<imgDefer.length; i++) {
if(imgDefer[i].getAttribute('data-src')) {
imgDefer[i].setAttribute('src',imgDefer[i].getAttribute('data-src'));
} }
});
});
I want to do this because I don't want to wait for long time to load large image, instead I want to see the small image first. I am facing the problem when page load, it's loading small and large images in parallel. For your information images have the drag and zoom functionality.
Current live code is here: http://virtualepark.com/new1/demo.html
The code you posted here is not deployed on your server - there is some other stuff using the mousewheel-event.
Try loading the big image hidden in the background and once its loaded, set the url of the visible image:
//get all images
$('img').each(function(i, img) {
var img = $(img);
//if they have a data-src
if(img.attr('data-src')) {
//register for the load-event for the initial image
img.one('load', function() {
//if small image is loaded, begin loading the big image
//create new hidden image
var hiddenImg = new Image();
hiddenImg.onload = function() {
//if the hidden image is loaded, set the src-attribute of the
//real image (it will show instantly)
img.attr('src', img.attr('data-src'));
};
//trigger loading of the resource
hiddenImg.src = img.attr('data-src');
});
});
});
(credits to Load image from url and draw to HTML5 Canvas)
you can load to hidden tag and after load complet change them.
you can try to start the loading after the image is loaded.
$('img').load(function(){
var bigImgSrc = $(this).data('src');
var img = $(this);
if(bigImgSrc != img.prop('src')){
var bigImg =$('<img>').prop('src', bigImgSrc);
bigImg.load(function(){
img.prop('src', bigImgSrc);
});
}
});
I'm not 100% sure if you need to append the bigImg to the DOM or if it also loads like this. If you need to add it to the DOM use bigImg.hide().appendTo('body') and then use the remove funtion when loaded.
You should also be aware that the load-function not work in all cases, see https://api.jquery.com/load-event/
edit there was in an infinity loop in the prev. code example
I'm loading an image onto a texture map with GLGE (sorta like webGl). However for the sake of loading speed I'm loading a low resolution image first (which would be quicker) and then want to change the src to the high resolution image once the large image is loaded. This is what I'm doing now
var texture = new GLGE.texture();
function updateTexture(){
var image=new Image();
image.src = "models/testLargeMap_map0.jpg"; // load image
image.onload = function(){
texture.image("models/testLargeMap_map0.jpg"); // supposedly swap image on load (not working as I thought)
}
}
However, when during this period of changing the src, the model and all its functions freeze. How do I make it load the image asynchronously and on load swap it to the higher texture for a smooth instantaneous texture change?
You can set an image.onload event handler like this:
var big_image = new Image();
big_image.onload = function () {
texture.image("models/testLargeMap_map0.jpg");
}
big_image.src = "models/testLargeMap_map0.jpg";
(Note that I set the onload handler first, then set the src attribute. If I do it the other way around, it fails in IE).
This will preload the image before calling texture.image. I don't know anything about this library though, so I can't be certain it will use the pre-loaded image.
The image.src will be requesting the image from the server and it will initiate the onload event, and again u are requesting the image to be swapped so it is getting freezed. Why do you need this approach. You can have better way of doing this like, allow the low resolution image to be loaded first then assign the onmouseover or onclick event for the image on that time u can show a popup like shown on google images and then in it just display the high resolution images. On that time u will be requesting a single image the process will be quicker.
Hope this helps you
I'm not familiar with "GLGE" but it looks like the problem is that the method .image() loads the image again (kind regardless if that happens in the load event handler for the same image).
So unless you can set the image reference directly, like
texture = this; // within the load handler
there is no way to accomplish it with this library.
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.
I'm trying to preload about 150 images and I want to be able to be able to do two things...
1) The images are being preloaded using a list of file names. Not every single file name in the list has a file to match up to it.
eg) pic04.jpg may not exist, even if it is in the list.
So when I'm preloading, i would like to be able to figure out whether or not the image exists, if possible.
2) Right now the function is simply preloading all 150 images using
pictures[i] = new Image();
pictures[i].src = "path/to/my/images/" + imageName[i] + ".jpg";
The function executes extremely fast, but the images don't seem to have been preloaded. Do I need to do something to make the site wait til the images have loaded before continuing?
Any ideas?
The function executes extremely fast, but the images don't seem to have been preloaded.
the images are being loaded asynchronously. The function finishes its execution but the browser continues loading the images in background
So when I'm preloading, i would like to be able to figure out whether or not the image exists, if possible.
yes, it is possible. You can use onerror event handler on the Image object
var img = new Image();
img.onerror=function(){alert('error: '+this.src);}
img.onload=function(){alert('image loaded: '+this.src);}
img.src='path/to/image.jpg';