I\'m loading (large) images dynamically to draw into a html5 canvas, something like this:
var t = new Image();
t.onload = ...
t.src = \'http://myurl\';
This is the only way that I managed to get it to work in all modern browsers (Chrome, Safari, Mobile-Safari, Firefox, and IE9).
iframe
image tag
to the body
in the iframe
img.onload
completes, you can use that image dom element to draw to an html5 canvas with drawImage()
stop()
on the iframe
's contentWindow
(or execCommand("stop", false)
on contentDocument
in IE).I created a class for this, and put the coffeescript code (and it's compiled javascript) on github: Cancelable Html5 Image Loader
If you want to play with it, I also created a jsfiddle to test it out. Remember to start Fiddler2 (or something like it) to see that the actual network request is really being canceled.
You can try window.stop() to stop all requests, but not individual ones. In IE, it's not window.stop() it's document.execCommand("Stop", false).
If you've got other stuff going on request-wise, then doing this will interfere with it. (You would follow-up with a re-request for resources you still want, but that is too much like hard work).
So if you wanted to stop a single request for a large image, what you could do is load the image into a document within a hidden IFRAME. The onload event of the IFRAME can be used to load the image into the main document, by which time it ought to be cached (presuming you have the caching directives configured to do so).
If the image is taking too long, then you can access the IFRAME's contentWindow and issue a stop command to that.
You need to have as many IFRAME elements as there are images that can be requested simultaneously.
I have same problem actually and made some tests.
I have made some tests with iframes and have some success. Tested on Firefox 3.6 and Chrome. For the tests I used 9 images of 15Mb. With img preloading I killed my firefox several times (yes, not much memoty on this computer), using img the "suspend" action does not prevent image loading if the request have started, with iframes the suspend action really stop the download (as I remove the iframe). Next step will be testing with XMLHttpRequests. As this version of my test code is using the braowser cache behaviour form the image url to prevent a second loading and this works as well with ajax requests. But maybe with iframes I could find a way to retrieve binary data from the loaded image in iframe directly (with limitation on same domain urls).
This is my test code (really fast on Chrome, may kill your firefox with too much very big images):
// jQuery.imageload.shared.list contains an array of oversized images url
jQuery.each(imglist,function(i,imgsrc) {
name = 'imageload-frame';
id = name + "-" + i;
// with img it is not possible to suspend, the get is performed even after remove
//var loader = jQuery('<img />').attr('name', name).attr('id',id);
var loader = jQuery('<iframe />').attr('name', name).attr('id',id);
//no cache on GET query taken from jQuery core
// as we really want to download each image for these tests
var ts = +new Date;
// try replacing _= if it is there
var ret = imgsrc.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
// if nothing was replaced, add timestamp to the end
imgsrc = imgsrc + ((ret == imgsrc) ? (imgsrc.match(/\?/) ? "&" : "?") + "_=" + ts : "");
loader.css('display', 'none').appendTo('body');
loader.after( jQuery('<a>')
.text(' stop ')
.attr('href','#')
.click(function(){
loader.remove();
jQuery(this).text(' suspended ');
})
);
// start the load - preload
loader.attr('src',imgsrc);
// when preload is done we provide a way to get img in document
loader.load(function() {
jQuery(this).next("a:first")
.text(" retrieve ").unbind('click')
.click(function() {
var finalimg = jQuery('<img />');
// browser cache should help us now
// but there's maybe a way to get it direclty from the iframe
finalimg.attr('src',loader[0].src);
finalimg.appendTo('body');
});
});
});
edit and here is fillde to test it: http://jsfiddle.net/wPr3x/
I doubt there's a cross-browser way to make this happen without hacks. One suggestion is to make an AJAX request to a server-side script which returns a Base64 encoded version of the image which you can then set as the src
attribute. Then you can cancel this request if you decide to cancel loading the image. This could be difficult if you want to show the image progressively however.