Finding height of image using JavaScript - image load error - javascript

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);
}
})
})

Related

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>

Using JavaScript to dynamically change display style in img tags

I show links to 240 images on a page. The real images are uploaded by users. I tried to avoid showing an empty image if users did not upload it yet. jQuery did not work for me because of conflicts, so I have to do it in pure JavaScript.
image(s) links:
<img class="photo240" src="http://www.example.com/i/%%GLOBAL__AuthorID%%/p/b01.jpg" onerror="imgError()">
My JavaScript:
function imgError()
{
alert('The image could not be loaded.');
var _aryElm=document.getElementsByTagName('img'); //return an array with every <img> of the page
for( x in _aryElm) {
_elm=_aryElm[x];
_elm.className="photo240off";
}
}
The style photo240off equals to display:none.
Right now, whenever an image misses, all the images are turned to style photo240off and I want only the missing image to be hidden. So there is something wrong with my script.
(the overall script works well, because I get the alert).
Use this to get the image with the error.
Change to:
onerror="imgError(this)"
Then the function can be:
function imgError(el) {
alert('The image could not be loaded.');
el.className = "photo240off";
}
You need to reference the image from your onerror call and change the class only for that one.
Something like this:
HTML
<img class="photo240" src="example.jpg" onerror="imgError(this)">
JS
function imgError(el) {
el.className="photo240off";
}

jQuery, JavaScript, HTML: how to load images after everything else is loaded?

I have a very complex page with a lot of scripts and a rather long loading time. On top of that page I want to implement the jquery Nivo Slider (http://nivo.dev7studios.com/).
In the documentation it says I have to list all images for the slider inside of a div#slider
<div id="slider">
<img src="images/slide1.jpg" alt="" />
<img src="images/slide2.jpg" alt="" title="#htmlcaption" />
<img src="images/slide3.jpg" alt="" title="This is an example of a caption" />
<img src="images/slide4.jpg" alt="" />
</div>
However I might have 10 images with a 1000x400px which is quite big. Those images would load when the page loads. Since they are in my header this might take quite a while.
I looking for a way to use any jquery Slider Plugin (like the nivo slider) but either dynamically load images or load all those images after everything else on my page has loaded.
Any idea how I could solve that?
Is there even a way to start a javascript process after everything else on the page has loaded? If there is a way I might have an solution for my problem (using the jquery ajax load() method) ... However I have no idea how to wait for everything else to load and then start the slider with all the images.
Here's what we did and its working great. We skipped setting src attribute of img and added img-location to a fake attribute lsrc. Then we load a dynamic image with lsrc value, and set the src of actual image only after its loaded.
Its not about faster loading, but its about showing the images only when its downloaded completely on your page, so that user do not have to see that annoying half-loaded images. A placeholder-image can be used while the actual images are being loaded.
Here's the code.
$(function(){
$.each(document.images, function(){
var this_image = this;
var src = $(this_image).attr('src') || '' ;
if(!src.length > 0){
//this_image.src = options.loading; // show loading
var lsrc = $(this_image).attr('lsrc') || '' ;
if(lsrc.length > 0){
var img = new Image();
img.src = lsrc;
$(img).load(function() {
this_image.src = this.src;
});
}
}
});
});
Edit: Trick is to set the src attribute only when that source is loaded in temporary img. $(img).load(fn); handles that.
In addition to Xhalent's answer, use the .append() function in jQuery to add them to the DOM:
Your HTML would just have:
<div id="slider">
</div>
And then your jquery would be:
jQuery(function(){
$("#slider").append('<img src="images/slide1.jpg" alt="" />');
});
check out jquery load() event, it waits for everything including graphics
$(window).load(function () {
// run code
});
on load you could then load the images using:
var image = new Image();
image.src = "/path/to/huge/file.jpg";
You can add a function onload to the image too
image.onload = function() {
...
}
I am using the below to power my slider and improve the page load performance.
for (var i = document.images.length - 1; i >= 0; i--) {
var this_image = document.images[i];
var src = $(this_image).attr('src') || '' ;
if(!src.length > 0){
var lsrc = $(this_image).attr('lsrc') || '' ;
if(lsrc.length > 0){
$(this_image).attr("src",lsrc);
}
}
}
the best way to use is b -lazy js.
bLazy is a lightweight lazy loading image script (less than 1.2KB minified and gzipped). It lets you lazy load and multi-serve your images so you can save bandwidth and server requests. The user will have faster load times and save data loaded if he/she doesn't browse the whole page.
For a full list of options, functions and examples go to the blog post: http://dinbror.dk/blog/blazy.
The following example is a lazy loading multi-serving responsive images example with a image callback :) If your device width is smaller than 420 px it'll serve a lighter and smaller version of the image. When an image has loaded it removes the loader in the callback.
In Html
<img class="b-lazy"
src="placeholder-image.jpg"
data-src="image.jpg"
data-src-small="small-image.jpg"
alt="Image description" />
In js
var bLazy = new Blazy({
breakpoints: [{
width: 420 // Max-width
, src: 'data-src-small'
}]
, success: function(element){
setTimeout(function(){
// We want to remove the loader gif now.
// First we find the parent container
// then we remove the "loading" class which holds the loader image
var parent = element.parentNode;
parent.className = parent.className.replace(/\bloading\b/,'');
}, 200);
}
});
Example
jquery has a syntax for executing javascript after document has loaded:
<script type="text/javascript">
jQuery(function(){
//your function implementation here...
});
</script>

Detect when a specific image has finished loading

I have an image on a webpage which is being dynamically generated by a server-side CGI program. Periodically this image is refreshed by a timer and/or changed based on user input. So I have a JavaScript function like
// <img id="screen" src=""> is elsewhere in the page
function reloadImage() {
$("#screen").attr("src", make_cgi_url_based_on_form_inputs());
}
This works just fine, but sometimes it takes awhile to load the image. So I'd like for some sort of message to appear that says "Loading image..." but then have that image disappear when the image has loaded and is being displayed in the browser.
Is there any kind of JavaScript event that can do this? Alternatively, is there any other way I can load/change/update an image and detect when the loading is finished, through Ajax or whatever else?
You can try out this jquery solution: http://jqueryfordesigners.com/image-loading/
$(function () {
var img = new Image();
$(img).load(function () {
//$(this).css('display', 'none'); // .hide() doesn't work in Safari when the element isn't on the DOM already
$(this).hide();
$('#loader').removeClass('loading').append(this);
$(this).fadeIn();
}).error(function () {
// notify the user that the image could not be loaded
}).attr('src', 'http://farm3.static.flickr.com/2405/2238919394_4c9b5aa921_o.jpg');
});

How can I determine if an image has loaded, using Javascript/jQuery?

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

Categories

Resources