I am writing an internet site, using javascript, HTML for IE9.
I found solution to loading dynamically the image by:
document.getElementById("id_image").filters.item("DXImageTransform.Microsoft.AlphaImageLoader").src = document.getElementById("id_filepic").value
id_image related to the <IMG> and id_filepic related to <input id="id_filepic" type="file">
After the line:
document.getElementById("id_image").filters.item("DXImageTransform.Microsoft.AlphaImageLoader").src = document.getElementById("id_filepic").value
what is the exact event that occurs just after the image is shown on the html page (hence, the image has width + height), and how can I capture that event?
It is important to me knowing the solution for IE9.
It doesn't have to be after that line, since it will be asynchronous anyway, but here it is:
document.getElementById("id_image").filters.item("DXImageTransform.Microsoft.AlphaImageLoader").src = document.getElementById("id_filepic").value;
document.getElementById("id_image").addEventListener('load', (function(i) {
return function() {
console.log(i, 'loaded');
}, false);
})(i));
Source: Javascript Image onload event binding
I want to participate my solution, I have found.
Well, the above is not compilable, and also 'onload' is not the correct event (it is not fired after using the "filter" command, as far as I investigated).
What I did is a little delay, with timeout command (about one second) like this :
setTimeout(function () {
alert("w: " + $("#id_image").width());
alert("h: " + $("#id_image").height());
}, 1000);
(even 100 milliseconds is enough, but I check that out for very large images. 1 second is quite big not to fall by code on large images).
After the delay, I could retrieve the image width and height with no problem.
That's complete this issue.
Related
Problem- I am displaying some images on a page which are being served by some proxy server. In each page I am displaying 30 images ( 6 rows - 5 in each row). Here if due to overload or due to any other issue if proxy server could not able to server images( either all images or some of them) in 6 seconds then I want to replace unloaded image url with some other url using javascript so that I could display 30 images at the end.
What I tried is below.
objImg = new Image();
objImg.src = 'http://www.menucool.com/slider/prod/image-slider-4.jpg';
if(!objImg.complete)
{
alert('image not loaded');
}else{
img.src = 'http://www.menucool.com/slider/prod/image-slider-4.jpg';
}
I also tried with below code.
$('img[id^="picThumbImg_"]').each(function(){
if($(this).load()) {
//it will display loaded image id's to console
window.console.log($(this).attr('id'));
}
});
I could not use set time-out for each image because it will delay all page load.
I checked other similar question on stack-overflow but no solution worked me perfectly as I need to display multiple images.Please guide how to proceed.
You don't have to wait 6 seconds, or using TimeOut. You can check if the images are loaded or not using the onload Javascript/Jquery event. I know, it will take a little bit to dispatch the onerror event, let see:
Why don't use the load Jquery event on the window or the image itself?
$(window).load(function(){
//check each image
})
Disadvantage:
It will wait for other resources like scripts, stylesheets & flash, and not just images, which may or may not be OK to you.
If the image loads from the cache, some browsers may not fire off the event (included yours and that's why your code is not working)
Why don't use the error Jquery event on the image itself?
$('img[id^="picThumbImg_"]').error(function(){
//image loading error
})
Disadvantages:
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
Note:: Error is almost the same that the load event
Improving the code!:
$('img[id^="picThumbImg_"]').one('error', function() {
// image load error
}).each(function() {
if(!this.complete) $(this).error();
});
This will avoid few things of the previous code, but you still will have to wait if it's a 404 and you're replacing it in the onerror event, that will take a little bit right?
So, what now!
You can use this awesome plugin!. Once you add the reference, you just have to use something like:
var imgLoad = imagesLoaded('#img-container');
imgLoad.on( 'always', function() {
// detect which image is broken
for ( var i = 0, len = imgLoad.images.length; i < len; i++ ) {
if(!imgLoad.images[i].isLoaded){
//changing the src
imgLoad.images[i].img.src = imgLoad.images[i].img.getAttribute("data-src2");
}
}
});
Your HTML markup should look like:
<div id="img-container">
<div class="row">
...
</div>
<div class="row">
<img src="original-path.jpg" data-src2="alternative-path.jpg">
...
</div>
<div class="row">
...
</div>
</div>
Note: You don't need jQuery in this case and this plugin is suggested by Paul Irish ;)
Give all your images a specific class. Loop through your images and use .load() to check if loaded, example below...
Detect image load
The title of the question expresses what I think is the ultimate question behind my particular case.
My case:
Inside a click handler, I want to make an image visible (a 'loading' animation) right before a busy function starts. Then I want to make it invisible again after the function has completed.
Instead of what I expected I realize that the image never becomes visible. I guess that this is due to the browser waiting for the handler to end, before it can do any redrawing (I am sure there are good performance reasons for that).
The code (also in this fiddle: http://jsfiddle.net/JLmh4/2/)
html:
<img id="kitty" src="http://placekitten.com/50/50" style="display:none">
<div>click to see the cat </div>
js:
$(document).ready(function(){
$('#enlace').click(function(){
var kitty = $('#kitty');
kitty.css('display','block');
// see: http://unixpapa.com/js/sleep.html
function sleepStupidly(usec)
{
var endtime= new Date().getTime() + usec;
while (new Date().getTime() < endtime)
;
}
// simulates bussy proccess, calling some function...
sleepStupidly(4000);
// when this triggers the img style do refresh!
// but not before
alert('now you do see it');
kitty.css('display','none');
});
});
I have added the alert call right after the sleepStupidly function to show that in that moment of rest, the browser does redraw, but not before. I innocently expected it to redraw right after setting the 'display' to 'block';
For the record, I have also tried appending html tags, or swapping css classes, instead of the image showing and hiding in this code. Same result.
After all my research I think that what I would need is the ability to force the browser to redraw and stop every other thing until then.
Is it possible? Is it possible in a crossbrowser way? Some plugin I wasn't able to find maybe...?
I thought that maybe something like 'jquery css callback' (as in this question: In JQuery, Is it possible to get callback function after setting new css rule?) would do the trick ... but that doesn't exist.
I have also tried to separte the showing, function call and hiding in different handlers for the same event ... but nothing. Also adding a setTimeout to delay the execution of the function (as recommended here: Force DOM refresh in JavaScript).
Thanks and I hope it also helps others.
javier
EDIT (after setting my preferred answer):
Just to further explain why I selected the window.setTimeout strategy.
In my real use case I have realized that in order to give the browser time enough to redraw the page, I had to give it about 1000 milliseconds (much more than the 50 for the fiddle example). This I believe is due to a deeper DOM tree (in fact, unnecessarily deep).
The setTimeout let approach lets you do that.
Use JQuery show and hide callbacks (or other way to display something like fadeIn/fadeOut).
http://jsfiddle.net/JLmh4/3/
$(document).ready(function () {
$('#enlace').click(function () {
var kitty = $('#kitty');
// see: http://unixpapa.com/js/sleep.html
function sleepStupidly(usec) {
var endtime = new Date().getTime() + usec;
while (new Date().getTime() < endtime);
}
kitty.show(function () {
// simulates bussy proccess, calling some function...
sleepStupidly(4000);
// when this triggers the img style do refresh!
// but not before
alert('now you do see it');
kitty.hide();
});
});
});
Use window.setTimeout() with some short unnoticeable delay to run slow function:
$(document).ready(function() {
$('#enlace').click(function() {
showImage();
window.setTimeout(function() {
sleepStupidly(4000);
alert('now you do see it');
hideImage();
}, 50);
});
});
Live demo
To force redraw, you can use offsetHeight or getComputedStyle().
var foo = window.getComputedStyle(el, null);
or
var bar = el.offsetHeight;
"el" being a DOM element
I do not know if this works in your case (as I have not tested it), but when manipulating CSS with JavaScript/jQuery it is sometimes necessary to force redrawing of a specific element to make changes take effect.
This is done by simply requesting a CSS property.
In your case, I would try putting a kitty.position().left; before the function call prior to messing with setTimeout.
What worked for me is setting the following:
$(element).css('display','none');
After that you can do whatever you want, and eventually you want to do:
$(element).css('display','block');
I want to detect through jQuery or Javascript when a specific video inside an html5 tag has been entirely loaded (I mean, downloaded into the cache of the browser). The video has the preload = "auto" attribute.
I tried everything in my power to do this (I'm a beginner) with no luck. Can't seem to find any event I could listen to, is there any way to do this?
PS: the only thing I came across is the network_state property of the video object, but the references around the web doesn't seem to agree with the state it returns, and when I tried it I didn't find a state for "LOADED".
EDIT: I found an event I think I can use, the canPlayThrough. I tested it and it seemed to work, but I'm not sure if it really tells me that the video has been totally loaded, or just that it loaded enough data to start playing (which is no good).
You can bind to the ended event :
$("video").bind(eventname, function() {
alert("I'm done!");
});
Where eventname is the event you want to list to
A complete list of events is here -> http://dev.w3.org/html5/spec/Overview.html#mediaevents
UPDATED :
To get a percentage loaded you can use a combination of 2 events :
$("video").bind('durationchange', checkProgress);
$("video").bind('progress', checkProgress);
function updateSeekable() {
var percentageComplete = (100 / (this.duration || 1) *
($(this).seekable && $(this).seekable.length ? $(this).seekable.end : 0)) + '%';
}
I have the following code I am using for a photo gallery. In Internet Explorer 7 & 8 the gallery stops working. The image fades out after several clicks and the new image does not fade in. After this occurrence happens (about 6 or so clicks) the gallery does not function at all. All other browsers work flawlessly. I have also used this code in several other pages with no problems.
$("#list-image-carousel").find('a').click(function(e) {
e.preventDefault();
var src = $(this).attr("href");
$("#main-img").find('img').fadeOut(400,
function() {
$("<img/>").attr("src", src).load(function() {
$("#main-img").find('img').attr("src", this.src).fadeIn(400);
})
})
});
Any ideas are greatly appreciated. Thanks in advance!
Here's one possibility: it looks like you're establishing the "load" handler on your temporary image element after you're initializing the "src". That's a problem in IE - reverse the order of those things and see if that helps.
$("#main-img").find('img').fadeOut(400,
function() {
$("<img/>").load(function() {
$("#main-img").find('img').attr("src", this.src).fadeIn(400);
}).attr("src", src);
})
If the image is in the cache, then when you assign the "src" attribute IE will immediately ready the element. If there's no "load" handler defined at that point, it won't queue up the event at all.
Also, just as a note, the construct
$('#main-img').find("img")
could be written:
$('#main-img img')
Doing it like that is a little shorter, but in truth it may or may not actually be faster. Probably would be, I think.
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.