How can I determine if an image has loaded, using Javascript/jQuery? - javascript
I'm writing some Javascript to resize the large image to fit into the user's browser window. (I don't control the size of the source images unfortunately.)
So something like this would be in the HTML:
<img id="photo"
src="a_really_big_file.jpg"
alt="this is some alt text"
title="this is some title text" />
Is there a way for me to determine if the src image in an img tag has been downloaded?
I need this because I'm running into a problem if $(document).ready() is executed before the browser has loaded the image. $("#photo").width() and $("#photo").height() will return the size of the placeholder (the alt text). In my case this is something like 134 x 20.
Right now I'm just checking if the photo's height is less than 150, and assuming that if so it is just alt text. But this is quite a hack, and it would break if a photo is less than 150 pixels tall (not likely in my particular case), or if the alt text is more than 150 pixels tall (could possibly happen on a small browser window).
Edit: For anyone wanting to see the code:
$(function()
{
var REAL_WIDTH = $("#photo").width();
var REAL_HEIGHT = $("#photo").height();
$(window).resize(adjust_photo_size);
adjust_photo_size();
function adjust_photo_size()
{
if(REAL_HEIGHT < 150)
{
REAL_WIDTH = $("#photo").width();
REAL_HEIGHT = $("#photo").height();
if(REAL_HEIGHT < 150)
{
//image not loaded.. try again in a quarter-second
setTimeout(adjust_photo_size, 250);
return;
}
}
var new_width = . . . ;
var new_height = . . . ;
$("#photo").width(Math.round(new_width));
$("#photo").height(Math.round(new_height));
}
});
Update: Thanks for the suggestions. There is a risk of the event not being fired if I set a callback for the $("#photo").load event, so I have defined an onLoad event directly on the image tag. For the record, here is the code I ended up going with:
<img id="photo"
onload="photoLoaded();"
src="a_really_big_file.jpg"
alt="this is some alt text"
title="this is some title text" />
Then in Javascript:
//This must be outside $() because it may get called first
var isPhotoLoaded = false;
function photoLoaded()
{
isPhotoLoaded = true;
}
$(function()
{
//Hides scrollbars, so we can resize properly. Set with JS instead of
// CSS so that page doesn't break with JS disabled.
$("body").css("overflow", "hidden");
var REAL_WIDTH = -1;
var REAL_HEIGHT = -1;
$(window).resize(adjust_photo_size);
adjust_photo_size();
function adjust_photo_size()
{
if(!isPhotoLoaded)
{
//image not loaded.. try again in a quarter-second
setTimeout(adjust_photo_size, 250);
return;
}
else if(REAL_WIDTH < 0)
{
//first time in this function since photo loaded
REAL_WIDTH = $("#photo").width();
REAL_HEIGHT = $("#photo").height();
}
var new_width = . . . ;
var new_height = . . . ;
$("#photo").width(Math.round(new_width));
$("#photo").height(Math.round(new_height));
}
});
Either add an event listener, or have the image announce itself with onload. Then figure out the dimensions from there.
<img id="photo"
onload='loaded(this.id)'
src="a_really_big_file.jpg"
alt="this is some alt text"
title="this is some title text" />
Using the jquery data store you can define a 'loaded' state.
<img id="myimage" onload="$(this).data('loaded', 'loaded');" src="lolcats.jpg" />
Then elsewhere you can do:
if ($('#myimage').data('loaded')) {
// loaded, so do stuff
}
The right answer, is to use event.special.load
It is possible that the load event will not be triggered if the image is loaded from the browser cache. To account for this possibility, we can use a special load event that fires immediately if the image is ready. event.special.load is currently available as a plugin.
Per the docs on .load()
You want to do what Allain said, however be aware that sometimes the image loads before dom ready, which means your load handler won't fire. The best way is to do as Allain says, but set the src of the image with javascript after attaching the load hander. This way you can guarantee that it fires.
In terms of accessibility, will your site still work for people without javascript? You may want to give the img tag the correct src, attach you dom ready handler to run your js: clear the image src (give it a fixed with and height with css to prevent the page flickering), then set your img load handler, then reset the src to the correct file. This way you cover all bases :)
As per one of the recent comments to your original question
$(function() {
$(window).resize(adjust_photo_size);
adjust_photo_size();
function adjust_photo_size() {
if (!$("#photo").get(0).complete) {
$("#photo").load(function() {
adjust_photo_size();
});
} else {
...
}
});
Warning This answer could cause a serious loop in ie8 and lower, because img.complete is not always properly set by the browser. If you must support ie8, use a flag to remember the image is loaded.
Try something like:
$("#photo").load(function() {
alert("Hello from Image");
});
There's a jQuery plugin called "imagesLoaded" that provides a cross-browser compatible method to check if an element's image(s) have been loaded.
Site: https://github.com/desandro/imagesloaded/
Usage for a container that has many images inside:
$('container').imagesLoaded(function(){
console.log("I loaded!");
})
The plugin is great:
works for checking a container with many images inside
works for check an img to see if it has loaded
I found this worked for me
document.querySelector("img").addEventListener("load", function() { alert('onload!'); });
Credit goes totaly to Frank Schwieterman, who commented on accepted answer. I had to put this here, it's too valuable...
Any comments on this one?
...
doShow = function(){
if($('#img_id').attr('complete')){
alert('Image is loaded!');
} else {
window.setTimeout('doShow()',100);
}
};
$('#img_id').attr('src','image.jpg');
doShow();
...
Seems like works everywhere...
I just created a jQuery function to load an image using jQuerys Deferred Object which makes it very easy to react on load/error event:
$.fn.extend({
loadImg: function(url, timeout) {
// init deferred object
var defer = $.Deferred(),
$img = this,
img = $img.get(0),
timer = null;
// define load and error events BEFORE setting the src
// otherwise IE might fire the event before listening to it
$img.load(function(e) {
var that = this;
// defer this check in order to let IE catch the right image size
window.setTimeout(function() {
// make sure the width and height are > 0
((that.width > 0 && that.height > 0) ?
defer.resolveWith :
defer.rejectWith)($img);
}, 1);
}).error(function(e) {
defer.rejectWith($img);
});
// start loading the image
img.src = url;
// check if it's already in the cache
if (img.complete) {
defer.resolveWith($img);
} else if (0 !== timeout) {
// add a timeout, by default 15 seconds
timer = window.setTimeout(function() {
defer.rejectWith($img);
}, timeout || 15000);
}
// return the promise of the deferred object
return defer.promise().always(function() {
// stop the timeout timer
window.clearTimeout(timer);
timer = null;
// unbind the load and error event
this.off("load error");
});
}
});
Usage:
var image = $('<img />').loadImg('http://www.google.com/intl/en_com/images/srpr/logo3w.png')
.done(function() {
alert('image loaded');
$('body').append(this);
}).fail(function(){
alert('image failed');
});
See it working at: http://jsfiddle.net/roberkules/AdWZj/
This function checks if an image is loaded based on having measurable dimensions. This technique is useful if your script is executing after some of the images have already been loaded.
imageLoaded = function(node) {
var w = 'undefined' != typeof node.clientWidth ? node.clientWidth : node.offsetWidth;
var h = 'undefined' != typeof node.clientHeight ? node.clientHeight : node.offsetHeight;
return w+h > 0 ? true : false;
};
We developed a page where it loaded a number of images and then performed other functions only after the image was loaded. It was a busy site that generated a lot of traffic. It seems that the following simple script worked on practically all browsers:
$(elem).onload = function() {
doSomething();
}
BUT THIS IS A POTENTIAL ISSUE FOR IE9!
The ONLY browser we had reported issues on is IE9. Are we not surprised? It seems that the best way to solve the issue there is to not assign a src to the image until AFTER the onload function has been defined, like so:
$(elem).onload = function() {
doSomething();
}
$(elem).attr('src','theimage.png');
It seems that IE 9 will sometimes not throw the onload event for whatever reason. Other solutions on this page (such as the one from Evan Carroll, for example) still did not work. Logically, that checked if the load state was already successful and triggered the function and if it wasn't, then set the onload handler, but even when you do that we demonstrated in testing that the image could load between those two lines of js thereby appearing not loaded to the first line and then loading before the onload handler is set.
We found that the best way to get what you want is to not define the image's src until you have set the onload event trigger.
We only just recently stopped supporting IE8 so I can't speak for versions prior to IE9, otherwise, out of all the other browsers that were used on the site -- IE10 and 11 as well as Firefox, Chrome, Opera, Safari and whatever mobile browser people were using -- setting the src before assigning the onload handler was not even an issue.
May I suggest a pure CSS solution altogether?
Just have a Div that you want to show the image in. Set the image as background. Then have the property background-size: cover or background-size: contain depending on how you want it.
cover will crop the image until smaller sides cover the box.
contain will keep the entire image inside the div, leaving you with spaces on sides.
Check the snippet below.
div {
height: 300px;
width: 300px;
border: 3px dashed grey;
background-position: center;
background-repeat: no-repeat;
}
.cover-image {
background-size: cover;
}
.contain-image {
background-size: contain;
}
<div class="cover-image" style="background-image:url(https://assets1.ignimgs.com/2019/04/25/avengers-endgame-1280y-1556226255823_1280w.jpg)">
</div>
<br/>
<div class="contain-image" style="background-image:url(https://assets1.ignimgs.com/2019/04/25/avengers-endgame-1280y-1556226255823_1280w.jpg)">
</div>
I find that this simple solution works best for me:
function setEqualHeight(a, b) {
if (!$(a).height()) {
return window.setTimeout(function(){ setEqualHeight(a, b); }, 1000);
}
$(b).height($(a).height());
}
$(document).ready(function() {
setEqualHeight('#image', '#description');
$(window).resize(function(){setEqualHeight('#image', '#description')});
});
</script>
image.complete might be another option https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/complete
Related
onload not working in <img> element
I don't understand why this function doesn't fire. I want to declare an image in HTML with a single onload function, which will automatically take care of the image's source and mouseover/out functions. The HTML looks like this: <img id="menuBtnNovo" onload="imgButton(this)"/> and the JS function imgButton looks like this: function imgButton(e){ window.alert("asdasdad"); e.src="images/def/" + e.Id + ".png"; e.onmouseover= function(){ *change image here*} e.onmouseout= function(){ *change image back here*} } Now, not even the alert pops up, and I don't know why. I tried putting script in <head> and setting src to none src="" in the <img>. I'm using Firefox, but it doesn't work in Edge either. Question is: how do I fire onload function on an image element? Also, if you have any idea of your own way of implementing this behaviour of automatically loading certain images (that would actually be buttons/links), feel free to share it. I'm new to JS but not to programming. As you might see, all images are in "images/def/..." and all images for when the mouse is over the img are in "images/mo/...".
I always try and let browser do image replacements, but if you have to use script, than you can do something like this on DOM ready, or window load event: $('img[data-regular]').each(function(i) { var thisImage = $(this); var regular = thisImage.data('regular'); var hover = thisImage.data('hover'); thisImage.attr('src', regular); /* Preload image for hover */ $('<img/>')[0].src = hover; /* Set events */ thisImage.on('mouseenter', function(e) { thisImage.attr('src', hover); }).on('mouseleave', function(e) { thisImage.attr('src', regular); }); }); <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <img data-regular="https://placehold.it/350x150" data-hover="https://placehold.it/450x200" /> Also on JSFiddle.
How to manually show tab loading indicator via javascript?
I'm talking about an icon that is displayed on a tab during page loading. Chrome: Firefox (with TreeTab plugin): You get the idea. I want to make it seem like the page is loading, when it's already loaded. Some event fires is javascript and then the tab looks like it's being loaded. Is there a way to do that? One way I can think of is to replace a favicon with a spinner, but I'm not sure if it's possible to change on the fly and even if it is, it would be a hassle to make it cross-browser.
I don't think it is a good idea to do it, you'll make your users do a lot of useless requests, and this kills trees : / IMO, it's better to do all you have in the page itself, and let the browser's UI do his own stuff. But since I liked the challenge, here is one hacky way : Loading an iframe will trigger this icon in both chrome and Firefox[1], so you could , append an iframe in the document, set its src to some huge document, onload of the iframe, set it again with a ? cache hack, regularly check if the duration has elapsed so you can remove the iframe's src. [1] It seems that Firefox does trigger the icon only if it was triggered when the document was still loading. In code : // how to use : showTabLoader(25000); // takes duration in ms as only parameter function showTabLoader(duration) { if (!duration) return; var now = performance.now(); // To avoid flickering, you need some big document // Please change this url in your script, wikimedia may not be happy with us. var url = 'https://upload.wikimedia.org/wikipedia/commons/3/35/Viborg_Katedralskole_Symmetrical.jpg'; var iframe = document.createElement('iframe'); iframe.style.display = 'none'; document.body.appendChild(iframe); iframe.onload = function() { if (performance.now() - now < +duration) { this.src = url + '?' + Math.random(); } }; var check = function(time) { if (time - now > +duration) { iframe.src = ''; iframe.parentNode.removeChild(iframe); return; } requestAnimationFrame(check); } requestAnimationFrame(check); iframe.src = url; }
I recently thought of the same idea. A neat option is to use a dynamic favicon instead of hacking in hidden requests, which is a really bad idea in my opinion. I found this example. It's to much code to include here and doesn't work in iframes so no way of showing it directly on Stackoverflow. Instead i describe the idea behind. https://www.cssscript.com/favicon-loading-indicator-favloader/ The idea is simple. Replace the favicon in an interval with the loading animation icons. A favicon cannot be GIF so you have to load each image step by step with JS. When you are done, simply replace it back with the original favicon. For me this works at least in all chrome based browsers. Firefox throw some errors in this example, but i guess it can be fixed.
Alternitive: There is no function that shows the actual loading process of the webpage. But you can do it manually, like you said! The event below starts to run when the page is fully loaded, even after all the images are loaded: $(window).on('load', function() { // do stuff }); So what you could do is set up your html like this: <div class="preloader"> // your loader here, animations, video, gif, anything you want </div> <div class="main" style="display: none;"> // the page </div> and your jquery like this: $(window).on('load', function() { setTimeout(function() { $('.preloader').css('display', 'none'); $('.main').css('opacity', '1'); }, 5000); // <-- 5seconds }); And there you have your manual loading function! Works perfect. Example website: ifly50 EDIT: added code snippet Code snippet: $(window).on('load', function() { setTimeout(function() { $('.preloader').css('display', 'none'); $('.main').css('display', 'block'); }, 3000); // <-- 3 seconds }); <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="preloader">loading</div> <div class="main" style="display: none;">main</div>
Finding height of image using JavaScript - image load error
I can't seem to find the height of an image using Javascript on a Typo3 website. Basically I have javascript that runs inside a $(document).ready(function () { . It looks for an image on the page and finds its height & width, then carries out opperations based on the results. Sometimes this works and sometimes it doesn't. Usually, I get a width value but no height. I suspect this is because the browser hasn't finnished loading the image. To solve this I have included a 2second delay to ensure img is loaded before looking for its height. But that isn't a very good way of solving the problem, especially if someone has low download speeds. How else could I check that an image is loaded fully before carrying out opperations? Here is some HTML: <div class="resize-thumb-img"> <img src="#.jpg" /> </div> <div class="resize-thumb-img"> <img src="#.jpg" /> </div> <div class="resize-thumb-img"> <img src="#.jpg" /> </div> And some JS: $(document).ready(function () { setTimeout(myFunctionX, 2000); function myFunctionX() { $(".resize-thumb-img img").each(function(){ //for each image console.log("working on image: "+$(this).width() +"x"+$(this).height()); /* MORE WORK HERE */ }); } }); The console log can give results like 235x420 OR 235x0 OR 0x0
I found a solution which I think helps in this context. It checks an image to see if its width is "0". If it is, it waits 1 second and then tries again. If its not "0", it calls the function I had before. Might be useful to include || null to the first if statement - I havn't tested on all browsers. $(document).ready(function () { checkLoadState(); function checkLoadState() //checks to see if images are loaded before continuing { if ($(".resize-thumb-img img").width() != "0") { console.log("Images loaded. Resizig..."); myFunctionX(); } else { console.log("Waiting for images to load."); setTimeout(checkLoadState, 1000); // check again in a second } } function myFunctionX() { $(".resize-thumb-img img").each(function(){ //for each image console.log("working on image: "+$(this).width() +"x"+$(this).height()); /* MORE WORK HERE */ }); } });
You can try the below one: $('img').each(function() { $(this).attr('height',$(this).height()); $(this).attr('width',$(this).width()); }); This will help you to find the height of your image using jquery.
If you have control over the server-side scripts, couldn't you simply store the size of the bitmap in a database together with its filename? Then you could set the WIDTH and HEIGHT attributes of the IMG elements.
What you need to do is bind a function to the load event for any images that aren't yet loaded, something like this function processImage(imageElement){ // do your stuff here var img=$(imageElement); console.log("working on image: "+img.width() +"x"+img.height()); } $(document).ready(function () { // iterate through the images $(".resize-thumb-img img").each(function(){ var img = $(this); if(img.width()==0 || img.height()==0){ // image has not fully loaded yet, so process it once loaded img.on('load',function(){processImage(this);}) }else{ // image is loaded so process the image straight away processImage(this); } }) })
Javascript/JQuery - How can I reset onError function for broken images? (for a second broken image)
OK, I've got the onError javascript working nicely. However, in most cases I need to try an alternate image and if THAT is broken as well, it needs to fall back to a local default image. On the initial broken image (http://somesite.com/someimage.jpg), this code correctly loads the alternate image that is passed. However, as you can see from the code, I'm trying to reset the source.onerror so that if the alternate image is broken as well, it will just load the local default image (/some/local/file.jpg). However, defaultImage() is never called. It's not a matter of passing in the "this" either because if I change it to source.onerror="alert('hi')"; it never gets called anyway. It appears that when the page loads, it only kicks of onerror once and never tries it again. Is there some way I can force the DOM to try loading the img again so that the new onerror function will kick off if the alternate image is broken? <img src="http://somesite.com/someimage.jpg" onerror="AltImage(this, 'http://sommesite.com/otherimage.jpg');"/> <img src="http://somesite.com/someimage.jpg" onerror="AltImage(this, '');"/> <script> function AltImage(source, alt_image){ if (alt_image !=""){ source.src = alt_image; source.onerror = "defaultImage(this)"; return true; } source.src = "/some/local/file.jpg"; source.onerror = ""; return true; } function defaultImage(source) { source.src = "/some/local/file.jpg"; data.onerror=""; return true; } </script>
You can check if the image exists or not by using the function below instead of your method : function ImgLoad(myobj,sSrc) { var oImg=new Image(); oImg.src="http://mydomain.com/images/"+sSrc; oImg.onload=function(){myobj.src=oImg.src} oImg.onerror=function(){myobj.src="http://mydomain2.com/images/"+sSrc} }
What I would try to do: $(function() { $('img.fallbackable').error(function() { $(this).unbind('error'); this.onerror = function() { this.src = 'default.png'; }; this.src = $(this).data('altsrc'); }) .attr('src', function() { return $(this).data('src'); }); }); And in HTML define your images which should have desired behaviour the next way: <img data-src="someimage.jpg" data-altsrc="otherimage.jpg" class="fallbackable"> So images start loading not immediately but only when the DOM is ready and all these image objects have onerror handler attached. Thus we make sure that for all such images (which is marked with class fallbackable) there is an error handler to be executed if needed.
Get the real width and height of an image with JavaScript? (in Safari/Chrome)
I am creating a jQuery plugin. How do I get the real image width and height with Javascript in Safari? The following works with Firefox 3, IE7 and Opera 9: var pic = $("img") // need to remove these in of case img-element has set width and height pic.removeAttr("width"); pic.removeAttr("height"); var pic_real_width = pic.width(); var pic_real_height = pic.height(); But in Webkit browsers like Safari and Google Chrome values are 0.
Webkit browsers set the height and width property after the image is loaded. Instead of using timeouts, I'd recommend using an image's onload event. Here's a quick example: var img = $("img")[0]; // Get my img elem var pic_real_width, pic_real_height; $("<img/>") // Make in memory copy of image to avoid css issues .attr("src", $(img).attr("src")) .load(function() { pic_real_width = this.width; // Note: $(this).width() will not pic_real_height = this.height; // work for in memory images. }); To avoid any of the effects CSS might have on the image's dimensions, the code above makes an in memory copy of the image. This is a very clever solution suggested by FDisk. You can also use the naturalHeight and naturalWidth HTML5 attributes.
Use the naturalHeight and naturalWidth attributes from HTML5. For example: var h = document.querySelector('img').naturalHeight; Works in IE9+, Chrome, Firefox, Safari and Opera (stats).
function getOriginalWidthOfImg(img_element) { var t = new Image(); t.src = (img_element.getAttribute ? img_element.getAttribute("src") : false) || img_element.src; return t.width; } You don't need to remove style from the image or image dimensions attributes. Just create an element with javascript and get the created object width.
There's a lot of discussion in the accepted answer about a problem where the onload event doesn't fire if an image is loaded from the WebKit cache. In my case, onload fires for cached images, but the height and width are still 0. A simple setTimeout resolved the issue for me: $("img").one("load", function(){ var img = this; setTimeout(function(){ // do something based on img.width and/or img.height }, 0); }); I can't speak as to why the onload event is firing even when the image is loaded from the cache (improvement of jQuery 1.4/1.5?) — but if you are still experiencing this problem, maybe a combination of my answer and the var src = img.src; img.src = ""; img.src = src; technique will work. (Note that for my purposes, I'm not concerned about pre-defined dimensions, either in the image's attributes or CSS styles — but you might want to remove those, as per Xavi's answer. Or clone the image.)
The root problem is that WebKit browsers (Safari and Chrome) load JavaScript and CSS information in parallel. Thus, JavaScript may execute before the styling effects of CSS have been computed, returning the wrong answer. In jQuery, I've found that the solution is to wait until document.readyState == 'complete', .e.g., jQuery(document).ready(function(){ if (jQuery.browser.safari && document.readyState != "complete"){ //console.info('ready...'); setTimeout( arguments.callee, 100 ); return; } ... (rest of function) As far as width and height goes... depending on what you are doing you may want offsetWidth and offsetHeight, which include things like borders and padding.
this works for me (safari 3.2), by firing from within the window.onload event: $(window).load(function() { var pic = $('img'); pic.removeAttr("width"); pic.removeAttr("height"); alert( pic.width() ); alert( pic.height() ); });
You can programmatically get the image and check the dimensions using Javascript without having to mess with the DOM at all. var img = new Image(); img.onload = function() { console.log(this.width + 'x' + this.height); } img.src = 'http://www.google.com/intl/en_ALL/images/logo.gif';
What about image.naturalHeight and image.naturalWidth properties? Seems to work fine back quite a few versions in Chrome, Safari and Firefox, but not at all in IE8 or even IE9.
Jquery has two properties called naturalWidth and naturalHeight, you can use in this way. $('.my-img')[0].naturalWidth $('.my-img')[0].naturalHeight Where my-img is a class name used to select my image.
How we get right real dimensions without a blink real image: (function( $ ){ $.fn.getDimensions=function(){ alert("First example:This works only for HTML code without CSS width/height definition."); w=$(this, 'img')[0].width; h=$(this, 'img')[0].height; alert("This is a width/height on your monitor: " + $(this, 'img')[0].width+"/"+$(this, 'img')[0].height); //This is bad practice - it shows on your monitor $(this, 'img')[0].removeAttribute( "width" ); $(this, 'img')[0].removeAttribute( "height" ); alert("This is a bad effect of view after attributes removing, but we get right dimensions: "+ $(this, 'img')[0].width+"/"+$(this, 'img')[0].height); //I'am going to repare it $(this, 'img')[0].width=w; $(this, 'img')[0].height=h; //This is a good practice - it doesn't show on your monitor ku=$(this, 'img').clone(); //We will work with a clone ku.attr( "id","mnbv1lk87jhy0utrd" );//Markup clone for a final removing ku[0].removeAttribute( "width" ); ku[0].removeAttribute( "height" ); //Now we still get 0 alert("There are still 0 before a clone appending to document: "+ $(ku)[0].width+"/"+$(ku)[0].height); //Hide a clone ku.css({"visibility" : "hidden",'position':'absolute','left':'-9999px'}); //A clone appending $(document.body).append (ku[0]); alert("We get right dimensions: "+ $(ku)[0].width+"/"+$(ku)[0].height); //Remove a clone $("#mnbv1lk87jhy0utrd").remove(); //But a next resolution is the best of all. It works in case of CSS definition of dimensions as well. alert("But if you want to read real dimensions for image with CSS class definition outside of img element, you can't do it with a clone of image. Clone method is working with CSS dimensions, a clone has dimensions as well as in CSS class. That's why you have to work with a new img element."); imgcopy=$('<img src="'+ $(this, 'img').attr('src') +'" />');//new object imgcopy.attr( "id","mnbv1lk87jhy0aaa" );//Markup for a final removing imgcopy.css({"visibility" : "hidden",'position':'absolute','left':'-9999px'});//hide copy $(document.body).append (imgcopy);//append to document alert("We get right dimensions: "+ imgcopy.width()+"/"+imgcopy.height()); $("#mnbv1lk87jhy0aaa").remove(); } })( jQuery ); $(document).ready(function(){ $("img.toreaddimensions").click(function(){$(this).getDimensions();}); }); It works with <img class="toreaddimensions"...
As stated before, Xavi answer won't work if images are in the cache. The issue responds to webkit not firing the load event on cached images, so if the width/height attrs are no explicitly set in the img tag, the only reliable way to get the images is to wait for the window.load event to be fired. The window.load event will fire always, so it's safe to access the width/height of and img after that without any trick. $(window).load(function(){ //these all work $('img#someId').css('width'); $('img#someId').width(); $('img#someId').get(0).style.width; $('img#someId').get(0).width; }); If you need to get the size of dynamically loaded images that might get cached (previously loaded), you can use Xavi method plus a query string to trigger a cache refresh. The downside is that it will cause another request to the server, for an img that is already cached and should be already available. Stupid Webkit. var pic_real_width = 0, img_src_no_cache = $('img#someId').attr('src') + '?cache=' + Date.now(); $('<img/>').attr('src', img_src_no_cache).load(function(){ pic_real_width = this.width; }); ps: if you have a QueryString in the img.src already, you will have to parse it and add the extra param to clear the cache.
As Luke Smith says, image load is a mess. It's not reliable on all browsers. This fact has given me great pain. A cached image will not fire the event at all in some browsers, so those who said "image load is better than setTimeout" are wrong. Luke Smith's solution is here. And there is an interesting discussion about how this mess might be handled in jQuery 1.4. I have found that it's pretty reliable to set the width to 0, then wait for the "complete" property to go true and the width property to come in greater than zero. You should watch for errors, too.
$("#myImg").one("load",function(){ //do something, like getting image width/height }).each(function(){ if(this.complete) $(this).trigger("load"); }); From Chris' comment: http://api.jquery.com/load-event/
My situation is probably a little different. I am dynamically changing the src of an image via javascript and needed to ensure that the new image is sized proportionally to fit a fixed container (in a photo gallery). I initially just removed the width and height attributes of the image after it is loaded (via the image's load event) and reset these after calculating the preferred dimensions. However, that does not work in Safari and possibly IE (I have not tested it in IE thoroughly, but the image doesn't even show, so...). Anyway, Safari keeps the dimensions of the previous image so the dimensions are always one image behind. I assume that this has something to do with cache. So the simplest solution is to just clone the image and add it to the DOM (it is important that it be added to the DOM the get the with and height). Give the image a visibility value of hidden (do not use display none because it will not work). After you get the dimensions remove the clone. Here is my code using jQuery: // Hack for Safari and others // clone the image and add it to the DOM // to get the actual width and height // of the newly loaded image var cloned, o_width, o_height, src = 'my_image.jpg', img = [some existing image object]; $(img) .load(function() { $(this).removeAttr('height').removeAttr('width'); cloned = $(this).clone().css({visibility:'hidden'}); $('body').append(cloned); o_width = cloned.get(0).width; // I prefer to use native javascript for this o_height = cloned.get(0).height; // I prefer to use native javascript for this cloned.remove(); $(this).attr({width:o_width, height:o_height}); }) .attr(src:src); This solution works in any case.
There is now a jQuery plugin, event.special.load, to deal with cases where the load event on a cached image doesn't fire: http://github.com/peol/jquery.imgloaded/raw/master/ahpi.imgload.js
Recently I needed to find width and height for setting default size of .dialog representing graph. Solution I use was : graph= $('<img/>', {"src":'mySRC', id:'graph-img'}); graph.bind('load', function (){ wid = graph.attr('width'); hei = graph.attr('height'); graph.dialog({ autoOpen: false, title: 'MyGraphTitle', height:hei, width:wid }) }) For me this works in FF3, Opera 10, IE 8,7,6 P.S. You may be find some more solutions looking inside some plugins like LightBox or ColorBox
To add to Xavi's answer, Paul Irish's github David Desandro's gitgub offers a function called imagesLoaded() that works on the same principles, and gets around the problem of some browser's cached images not firing the .load() event (with clever original_src -> data_uri -> original_src switching). It's is widely used and updated regularly, which contributes to it being the most robust solution to the problem, IMO.
This works for both cached and dynamically loaded images. function LoadImage(imgSrc, callback){ var image = new Image(); image.src = imgSrc; if (image.complete) { callback(image); image.onload=function(){}; } else { image.onload = function() { callback(image); // clear onLoad, IE behaves erratically with animated gifs otherwise image.onload=function(){}; } image.onerror = function() { alert("Could not load image."); } } } To use this script: function AlertImageSize(image) { alert("Image size: " + image.width + "x" + image.height); } LoadImage("http://example.org/image.png", AlertImageSize); Demo: http://jsfiddle.net/9543z/2/
I've done some workaround utility function, using imagesLoaded jquery plugin: https://github.com/desandro/imagesloaded function waitForImageSize(src, func, ctx){ if(!ctx)ctx = window; var img = new Image(); img.src = src; $(img).imagesLoaded($.proxy(function(){ var w = this.img.innerWidth||this.img.naturalWidth; var h = this.img.innerHeight||this.img.naturalHeight; this.func.call(this.ctx, w, h, this.img); },{img: img, func: func, ctx: ctx})); }, You can use this by passing url, function and its context. Function is performed after image is loaded and return created image, its width and height. waitForImageSize("image.png", function(w,h){alert(w+","+h)},this)
If the image is already used, you sholud: set image simensions to initial image.css('width', 'initial'); image.css('height', 'initial'); get dimensions var originalWidth = $(this).width(); var originalHeight = $(this).height();
You can use the naturalWidth and naturalHeight properties of the HTML image element. (Here's more info). You would use it like this: //you need a reference to the DOM element, not a jQuery object. It would be better if you can use document.getElementByTagsName or ID or any other native method var pic = $("img")[0]; var pic_real_width = pic.naturalWidth; var pic_real_height = pic.naturalHeight; It seems like this works in all browsers except on IE from version 8 and below.
I checked out the answer of Dio and it works great for me. $('#image').fadeIn(10,function () {var tmpW = $(this).width(); var tmpH = $(this).height(); }); Make sure that you call all your functions aso. that handle with the image size in the recaller function of fadeIn(). Thanks for this.
I use different approach, simply make Ajax call to server to get image size when image object is in use. //make json call to server to get image size $.getJSON("http://server/getimagesize.php", {"src":url}, SetImageWidth ); //callback function function SetImageWidth(data) { var wrap = $("div#image_gallery #image_wrap"); //remove height wrap.find("img").removeAttr('height'); //remove height wrap.find("img").removeAttr('width'); //set image width if (data.width > 635) { wrap.find("img").width(635); } else { wrap.find("img").width(data.width); } } and of course server side code: <?php $image_width = 0; $image_height = 0; if (isset ($_REQUEST['src']) && is_file($_SERVER['DOCUMENT_ROOT'] . $_REQUEST['src'])) { $imageinfo = getimagesize($_SERVER['DOCUMENT_ROOT'].$_REQUEST['src']); if ($imageinfo) { $image_width= $imageinfo[0]; $image_height= $imageinfo[1]; } } $arr = array ('width'=>$image_width,'height'=>$image_height); echo json_encode($arr); ?>
This works cross browser var img = new Image(); $(img).bind('load error', function(e) { $.data(img, 'dimensions', { 'width': img.width, 'height': img.height }); }); img.src = imgs[i]; get the dimensions by using $(this).data('dimensions').width; $(this).data('dimensions').height; Cheers!
Another suggestion is to use imagesLoaded plugin. $("img").imagesLoaded(function(){ alert( $(this).width() ); alert( $(this).height() ); });
$(document).ready(function(){ var image = $("#fix_img"); var w = image.width(); var h = image.height(); var mr = 274/200; var ir = w/h if(ir > mr){ image.height(200); image.width(200*ir); } else{ image.width(274); image.height(274/ir); } }); // This code helps to show image with 200*274 dimention
Here's a cross browser solution that triggers an event when your selected images are loaded: http://desandro.github.io/imagesloaded/ you can look up the height and width within the imagesLoaded() function.
Stumbled upon this thread trying to find an answer for my own question. I was trying to get an image's width/height in a function AFTER the loader, and kept coming up with 0. I feel like this might be what you're looking for, though, as it works for me: tempObject.image = $('<img />').attr({ 'src':"images/prod-" + tempObject.id + ".png", load:preloader }); xmlProjectInfo.push(tempObject); function preloader() { imagesLoaded++; if (imagesLoaded >= itemsToLoad) { //itemsToLoad gets set elsewhere in code DetachEvent(this, 'load', preloader); //function that removes event listener drawItems(); } } function drawItems() { for(var i = 1; i <= xmlProjectInfo.length; i++) alert(xmlProjectInfo[i - 1].image[0].width); }
Check out this repository in github! Great Example to check the Width and Height using Javascript https://github.com/AzizAK/ImageRealSize ---Edited is requested from some comments .. Javascript code: function CheckImageSize(){ var image = document.getElementById("Image").files[0]; createReader(image, function (w, h) { alert("Width is: " + w + " And Height is: "+h); }); } function createReader(file, whenReady) { var reader = new FileReader; reader.onload = function (evt) { var image = new Image(); image.onload = function (evt) { var width = this.width; var height = this.height; if (whenReady) whenReady(width, height); }; image.src = evt.target.result; }; reader.readAsDataURL(file); } and HTML code : <html> <head> <title>Image Real Size</title> <script src="ImageSize.js"></script> </head> <body> <input type="file" id="Image"/> <input type="button" value="Find the dimensions" onclick="CheckImageSize()"/> </body> <html>
For functions where you do not want to alter the original placement or image. $(this).clone().removeAttr("width").attr("width"); $(this).clone().removeAttr("height").attr("height);