what I need to do is simple to say but (for me) hard to do:
using javascript, given an image name, ie "image01.jpg", I need to check if this image exists in a certain folder or path (local or on the web). If the image does not exist under that folder, I need to check if the same image exists in another folder.
for example, with pseudo code
imageToFind = 'image01.jpg'
path1 = 'users/john/images'
path2 = 'users/mike/img'
if path1+'/'+imageToFind exists
//do something
else
if path2+'/'+imageToFind exists
//do something
else
print('NOT FOUND')
what kind of approach do you suggest? I tryed to achieve this using ajax first, and then using javascript's Image() , but I failed in both these cases.
Thanks in advance for any help, best regards
Use the onerror callback :
var img = new Image();
img.onerror = function(){
img = new Image(); // clean the error (depends on the browser)
img.onerror = function(){
console.log('not found at all !');
};
img.src = path2+'/'+imageToFind;
};
img.src = path1+'/'+imageToFind;
You can pretty much rely on native onload and onerror event handlers which fire for Image nodes. So it could look like
var images = ['users/john/images/image01.jpg','users/mike/img/image01.jpg','some/more/path/image01.jpg'];
(function _load( img ) {
var loadImage = new Image();
loadImage.onerror = function() {
// image could not get loaded, try next one in list
_load( images.shift() );
};
loadImage.onload = function() {
// this image was loaded successfully, do something with it
};
loadImage.src = img;
}( images.shift() ));
This code probably does a little more than you actually asked for. You can basically but as much image paths as you wish into that array, the script will search the list until it could load one image successfully.
try something like
objImg = new Image();
objImg.src = 'photo.gif';
if(!objImg.complete)
{
img.src = path2+'/'+imageToFind; //load other image
}else{
img.src = path1+'/'+imageToFind;
}
I think you need to ask yourself: why don't I know whether the images exist?
I feel like you should not have this problem, or want to solve it in this way.
Related
My requirement is that, to showcase images available in the directory to the browser view. Using javascript. For that, i have named all images with a same prefix and changed the number to the each image at the end.as shown below.
Folder
gal-img-1.jpg
gal-img-2.jpg
gal-img-3.jpg
gal-img-4.jpg
...
now the code i written something like below.
for(j=1;j<=10;j++){
var objImg = new Image();
var imgSrc = '/assets/images/work/gal-img-'+j+'.jpg'
objImg.src = imgSrc;
objImg.onerror = function (){
j = 11;
console.log("done")
}
}
Now, when i check console, i can see the loop is not stopping when there is no image as 'gal-img-5.jpg'. i see 404 not found error for 5,6,7,8,9,10. after these errors i see "done"(console.log).
Here i want is when there is no image in the directory the for loop needs to stop.
Can someone help me on this.
You can use a bit of recursion using Jaromanda X's mentioned onload method.
function loadImages(i) {
objImg = new Image();
objImg.src = `/assets/images/work/gal-img-${i}.jpg`;
objImg.onload = function () {
if (i < 11) loadImages(++i); // Always have an exit condition with recursion
}
}
// You need to call loadImages(0)
The above would show an error message for the file not found and will not try to load more images.
I found this method below and it works fine in order to check if an image is fully loaded:
var myimg = new Image();
myimg.onload = function(){
alert("The image is now loaded");
}
myimg.src = "image url";
My question is:
How can I do an alert("The image couldn't be loaded") if, for some reason, the image couldn't be loaded or found (e.g., if the image URL is broken or even the image no longer exists from the provided image url)? Is there a way to solve this?
image nodes also allow for a DOM Level 1 onerror event handler.
myimg.onerror = function() {
};
If anything fails on loading or while loading an image, that handler will get executed. In addition to that, its not a bad idea at all to also check for the dimenions within the onload event
myimg.onload = function() {
if( this.height && this.width ) {
} else {
// you might want to catch this case here too
}
}
The following Code Works in every browser accept every version of IE, can someone please help! There seems to be a problem with the cat.onload method....I have done so many tests and am at a loss...any help would be appreciated
Thanks!
var bannerCount = 0;
var bannerImgsArr = new Array();
bannerImgsArr[0] ='image1.jpg';
bannerImgsArr[1] ='image2.jpg';
bannerImgsArr[2] ='image3.jpg';
bannerImgsArr[3] ='image4.jpg';
$(document).ready(function() {
preloadBannerImages();
});
function preloadBannerImages(){
//create new image object
var cat = new Image();
//give Image src attribute the image file name
cat.src =bannerImgsArr[bannerCount];
//if the counter represents the last image in the current gallery enter here:
if(bannerCount == 3){
//When the image has been loaded the following function is exicuted
cat.onload = function() {
//Removes the LOADING message hard coded into the html page;
document.getElementById("bigbox").removeChild(document.getElementById("loading"));
}
}else{
//when current image is finished loading increments the img index and
//calls the loading function again for the next image in the gallery
bannerCount++;
cat.onload =preloadBannerImages;
}
}
You are defining the onload handler for the image after setting the src property. Do the one before the other.
If that doesn't solve your problem, you really need to elaborate what exactly doesn't work.
Don't rely on the onload-event of images, it may not fire if the image was loaded before and comes from the cache
[edit]
The function most likely ends and calls itself again before the image is downloaded, so the image isn't cached. Load the images into a persistent store (e.g. array) that hangs around until they are all downlaoded and cached.
[/edit]
You don't have to wait for the DOM to be ready to load images:
var bannerCount = 0;
var bannerImgsArr = ['image1.jpg','image2.jpg','image3.jpg','image4.jpg'];
var imageArray = [];
for (var i=0, iLen=bannerImgsArr.length; i<iLen; i++) {
imageArray[i] = new Image();
imageArray[i].src = bannerImgsArr[i];
}
Now when the DOM is ready, you can use one of the preloaded images.
...
cat.src = imageArr[bannerCount].src;
...
function swapImg(imgId) {
var image = document.getElementById(imgId);
if (image.getAttribute("class") == "unselected") {
image.setAttribute("src", "img/frownie.gif");
console.log(image);
}
}
if i look at what's outputted to console, the src of the image is correct. but it's not changing in my browser. what's up? (ie, the image stays the same even though the source url is changing...)
I would write your function this way, this should also take care of your error:
function swapImg(imgId) {
var image = document.getElementById(imgId);
if (image.className == "unselected") {
image.src = 'img/frownie.gif';
console.log(image);
}
}
ugh i'm dumb. i accidentally wrote id instead of class in my code so there are multiple images with the same id, which meant i found the first one and swapped it and not the others. thanks for trying :(
I'm using the following code to insert some HTML into a div, and to preload any images that might be contained in that HTML (the html var's data is actually fetched from an AJAX request in the real code). This is to prevent the browser from loading the fetched HTML's images upon showing the div (using the slideDown event) - because this results in the effect's fluidity being broken as it loads image mid-transition. I suppose I could use an interlaced JPEG so that the dimensions of the image are known almost immediately, but obviously it'd be nice to get a cleaner method worked out. :P
var html = '<img src="images/test.jpg" alt="test" />';
$('div.content').hide().html(html);
$('div.content img').each(function(){
var img = new Image();
img.src = $(this).attr('src');
$(this).attr('src', img.src);
});
$('div.content').slideDown('normal');
I'm using the Image object and its subsequent assigning as per the advice given here, but unfortunately the image still isn't cached by the browser using this method, because the sildeDown() effect is still interrupted as the image loads.
Any help or alternative methods? Many thanks.
Edit - 21st Sept 09
Progress! Turns out the browser was caching the image, I just wasn't giving it time to do so (it just needed a second to load with an alert() or setInterval()). Now introducing what is probably the messiest code ever - I am using an infinite loop to create that pause.
The new method extends the old code above by binding a function (that adds each image's src to an array) to that image's successful load event. It then gets stuck in an infinite loop as it waits until all the images have loaded and therefore appeared in the array. This seems to work as a way to synchronously pre-load images - but a problem remains; the while() loop for some reason cycles infinitely even once all the images are loaded, unless I add an alert() to pause it for a moment.
The new code:
var html = '<img src="images/test.jpg" alt="test" />';
$('div.content').hide().html(html);
// define usr variables object
$.usrvar = {};
// array of loaded images' urls
$.usrvar.images = [];
// boolean for whether this content has images (and if we should check they are all loaded later)
$.usrvar.hasimages = false;
// foreach of any images inside the content
$('div.content img').each(function(){
// if we're here then this content has images..
$.usrvar.hasimages = true;
// set this image's src to a var
var src = $(this).attr('src');
// add this image to our images array once it has finished loading
$(this).load(function(){
$.usrvar.images.push(src);
});
// create a new image
var img = new Image();
// set our new image's src
img.src = src;
});
// avoid this code if we don't have images in the content
if ($.usrvar.hasimages != false) {
// no images are yet loaded
$.usrvar.imagesloaded = false;
// repeatedly cycle (while() loop) through all images in content (each() loop)
while ($.usrvar.imagesloaded != true) {
$('div.content img').each(function(){
// get this loop's image src
var src = $(this).attr('src');
// if this src is in our images array, it must have finished loading
if ($.usrvar.images.indexOf(src) != -1) {
// set imagesloaded to trueai
$.usrvar.imagesloaded = true;
} else {
// without the pause caused by this alert(), this loop becomes infinite?!
alert('pause');
// this image is not yet loaded, so set var to false to initiate another loop
// (ignores whether imagesloaded has been set to true by another image, because ALL
// need to be loaded
$.usrvar.imagesloaded = false;
}
});
}
}
$('div.content').slideDown('normal');
I made the following solution but it hasn't been tested, so you're warned ;)
// HTML (any formatting possible)
// no src for the images: it is provided in alt which is of the form url::actualAlt
var html = "<p><img alt='images/test.jpg::test' /><br />Some Text<br /><img alt='images/test2.jpg::test2' /></p>";
$(document).ready(function() {
// Reference to the content div (faster)
var divContent = $("div.content");
// Hide the div, put the HTML
divContent.hide().html(html);
// Webkit browsers sometimes do not parse immediately
// The setTimeout(function,1) gives them time to do so
setTimeout(function() {
// Get the images
var images = $("img",divContent);
// Find the number of images for synchronization purpose
var counter = images.length;
// Synchronizer
// will show the div when all images have been loaded
function imageLoaded() {
if (--counter<=0) $('div.content').slideDown('normal');
}
// Loading loop
// For each image in divContent
$.each(images,function() {
// Get the url & alt info from the alt attribute
var tmp = $(this).attr("alt").split("::");
// Set the alt attribute to its actual value
$(this).attr("alt",tmp[1]);
// Wire the onload & onerror handlers
this.onload = this.onerror = imageLoaded;
// Set the image src
this.src = tmp[0];
});
},1);
});
Create an interval/timeout and let it check your compterGenerated css-height, if it's autosized it'll begin from 0 and end to 100 (for example). But in Safari it loads the height before the image, so it'll propably not work in all browsers...
I was playing with this and I created a slightly different solution. Instead of pushing images onto an array when they are loaded, you push them all onto an array in the loop, then in the load event you remove them from the array and call a 'finished' function. It checks if the images array is empty, and if it is then it clears up and shows the content.
var html = '< animg src="images/test.jpg" alt="test" />'; // not allowed to post images...
$('div.content').hide().html(html);
// preload images
// define usr variables object
$.usrvar = {};
// array of loaded images' urls
$.usrvar.images = [];
// initially no images
$.usrvar.hasimages = false;
$('div.content img').each(function() {
// if we're here then this content has images..
$.usrvar.hasimages = true;
// set this image's src to a var
var src = this.src;
// add this image to our images array
$.usrvar.images.push(src);
// callback when image has finished loading
$(this).load(function(){
var index = $.usrvar.images.indexOf(src);
$.usrvar.images.splice(index,1);
finish_loading();
});
// create a new image
var img = new Image();
// set our new image's src
img.src = src;
});
if(!$.usrvar.hasimages) finish_loading();
function finish_loading() {
if($.usrvar.hasimages) {
if($.usrvar.images.length > 0) return;
}
$('div.content').slideDown('normal');
}
Edit: Looking at Julien's post, his method is better. My method works in a similar way but like the original solution keeps track of images by an array of srcs rather than just a count (which is more efficient).
Edit 2: well I thought it was a better solution, but it seems it doesnt work for me. Maybe something to do with the load event getting called too close to each other. Sometimes it will work but sometimes it will hang when loading images, and the image counter never reaches zero. I've gone back to the method in my post above.
Edit 3: It appears it was the setTimeout that was causing the problem.
This is what I use. As you can see by my points, I'm no pro, but I found this somewhere and it works great for me and seems much simpler than everything posted. Maybe I missed a requirement though. :)
var myImgs = ['images/nav/img1.png', 'images/nav/img2.png', 'images/nav/img3.png', 'images/nav/img4.png', 'images/expand.png', 'images/collapse.png'];
function preload(imgs) {
var img;
for (var i = 0, len = imgs.length; i < len; ++i) {
img = new Image();
img.src = imgs[i];
}
}
preload(myImgs);