How to load image to object and set default if error? - javascript

I have container where I should load the image. The image has actual image that is unique for each id. If image doesn't exist for that id then it should load default image. Here is example of what I have:
function addImage() {
var image = new Image();
image.addEventListener('load', function () {
this.src = 'images/'+id+'_image01.jpg';
});
image.addEventListener('error', function (e) {
// Image not found, show the default
image.src = 'images/default.jpg';
});
image.width = 233;
console.log(image);
}
The output of the function above in the console looks like this:
<img width="233">
The only attribute that is appended to image object is width. I'm wondering why source is not appended. It should look like this:
<img width="233" src="images/89_image01.jpg"> //Image exist
or this if image does not exist:
<img width="233" src="images/default.jpg"> //Image does not exist
I'm not sure why my function only attached width. If anyone can detect the problem please let me know.

You need to add the src attribute to the image object after outside the onload event handler so it actually call that event handler or call the onerror event handler.
function addImage(id) {
var image = new Image();
image.addEventListener('error', function onError (e) {
// Image not found, show the default
image.removeEventListener(error, onError);
image.src = 'images/default.jpg';
});
image.width = 233;
image.src = 'images/'+id+'_image01.jpg';
console.log(image);
}
Also, don't forget to remove the onError event handler once the default image has loaded, this will save a few headaches if you default image is not found.

Related

OnClick loading background-image from url with timeout or fail function?

I have an HTML button with an onclick function "clicked()".
If clicked I want to load an image as "background-image" of a div tag.
The image shall be loaded from a server that serves the image very unreliable (rain-radar),
very high answer time up to timeout. I have no control of the server but I am allowed
to fetch the image.
If the image cannot be loaded or is not loaded after 30 seconds I want to show either a failover image or a simple text message to try again later.
I tried to define a second (failover) image url to the style background-image attribute but
then my page always loads the failover image and I guess that's not how it works. Also I dont want to show a "loading image failed" image while page still waits to receive an answer...
index.html
...
GoToDiv
...
javascript:
function clicked(){
document.getElementById('gotoDiv').style.backgroundImage = "url('https://UNRELIABLE.SERVER/pic.jpg'), url('/failover.jpg')";
}
I there a proper way to do that?
You can try a preloading technique
function clicked() {
var elem = document.getElementById('gotoDiv');
elem.style.backgroundImage = 'url("loading.gif")';
function setErrorImg () {
elem.style.backgroundImage = 'url("failover.jpg")';
}
var timer = window.setTimeout(setErrorImg, 30000);
var img = new Image();
img.onload = function() {
window.clearTimeout(timer);
elem.style.backgroundImage = 'url("' + img.src + '")';
};
img.onerror = setErrorImg;
img.src = 'https://UNRELIABLE.SERVER/pic.jpg';
}

Is an event triggered when an HTML link element (<a/>) containing base64 data as href is ready?

I have created a webpage that basically displays 2 images side by side.
It has a "download" button, which triggers a vanilla Javascript function, which creates a <canvas> HTML element and concatenates the two images inside of it. It then creates a link with the base64-encoded result image as href and clicks on it:
<a download="image.png" id="dllink" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABQAAAAMnCAYAAABhnf9DAAAgAElEQVR4nOzdR48kD3rn96j03pfv6qo21dVd3qT3JryP9Jll281..."></a>
Here is what the function I'm using looks like:
/**
* Create canvas, draw both images in it, create a link with the result
* image in base64 in the "href" field, append the link to the document,
* and click on it
*/
function saveImage() {
// Get left image
var imgLeft = new Image();
imgLeft.setAttribute('crossOrigin', 'anonymous');
imgLeft.src = "imgleft/" + idxImageShownLeft + ".jpg";
imgLeft.onload = function() {
// Once the left image is ready, get right image
var imgRight = new Image()
imgRight.setAttribute('crossOrigin', 'anonymous');
imgRight.src = "imgright/" + idxImageShownRight + ".jpg";
imgRight.onload = function() {
// Once the right image is ready, create the canvas
var canv = document.createElement("canvas");
var widthLeft = parseInt(imgLeft.width);
var widthRight = parseInt(imgRight.width);
var width = widthLeft + widthRight;
var height = imgLeft.height;
canv.setAttribute("width", width);
canv.setAttribute("height", height);
canv.setAttribute("id", "myCanvas");
canv.setAttribute('crossOrigin', 'anonymous');
var ctx = canv.getContext("2d");
// Draw both images in canvas
ctx.drawImage(imgLeft, 0, 0);
ctx.drawImage(imgRight, widthLeft, 0);
// Create PNG image out of the canvas
var img = canv.toDataURL("image/png");
// Create link element
var aHref = document.createElement('a');
aHref.href = img;
aHref.setAttribute("id", "dllink");
aHref.download = "image.png";
// Append link to document
var renderDiv = document.getElementById("render");
renderDiv.replaceChild(aHref, document.getElementById("dllink"));
// Click on link
aHref.click();
}
}
}
My problem is that this works fine on Firefox, but not on Chrome.
After a bit of investigating, I realized that by setting a breakpoint before the aHref.click(); line in Chrome, it worked fine. I think that it means that the aHref.click(); is called before the <a href="data:image/png;base64,...></a> is ready to be clicked, but I don't know for sure.
I couldn't find a duplicate of this topic. What keywords should I use just to be 100% sure?
Am I investigating in the right direction?
Is there an event I could rely on in order to call aHref.click(); only when it is ready?
You could wrap it in an init function that gets called when the window completes loading.
function init() {
aHref.click();
}
window.onload = init;
Its similar to the vanilla equivalent of jQuery's .ready() method.
aHref , document.getElementById("dllink") appear to be same element ? Though "dllink" has not yet been appended to document when .replaceChild called ?
Try substituting
renderDiv.appendChild(aHref);
for
renderDiv.replaceChild(aHref, document.getElementById("dllink"));

Something goes wrong with fadeIn

Hello I want to fadeOut image, and then do fadeIn with a new one, so I wrote a simple code, but something goes wrong, because when .photo img fadesOut, then fadesIn this same photo, but after, a few second its changes because of new "src", but even if browser didn't load a new image, the old one shound't show, becuase src is changed, but it shows, and after a second, maybe two changes to the new one. Can somebody tell me what's wrong?
var dimage = $next.children("img").attr("rel");
$(".photo img").fadeOut("slow", function () {
$(".photo img").attr("src", dimage);
$(".photo img").fadeIn("slow");
});
This may be because the image has to load after the src is altered.
Consider putting the image in a tag, then setting the css property to display:none. This way the image will preload in the browser before your script runs and will be available when it does.
you aren't giving the new image enough time to load.
function loadImage (src) {
return $.Deferred(function(def){
var img = new Image();
img.onload = function(){
def.resolve(src);
}
img.src = src;
}).promise();
}
var dimage = $next.children("img").attr("rel");
var imageLoadedDef = loadImage(dimage);
$(".photo img").fadeOut("slow", function () {
def.done(function(src){
$(".photo img").attr("src", src);
$(".photo img").fadeIn("slow");
});
});
the problem as highlighted is about images not ready for display when you call them, so the solution is to preload them before starting the slideshow, create a function with an array of images path
function preLoad(){
var imgs = {'test1.jpg', 'test2.jpg', 'test3.jpg'};
var img = document.createElement('img');
for(var i = 0; i < imgs.leght; i++){
img.src = imgs[i]; //all images gets preloaded at this stage
}
startSlider(); //here you will do your code
}

How to detect dimensions of file using File API and Dropzone.js

Using Dropzone.js, I need to detect the dimesions of the image when added files and apply them to its parent .details div. The following code code works and return an alert with the added image width.
myDropzone.on("addedfile", function(file, xhr) {
var fr;
fr = new FileReader;
fr.onload = function() {
var img;
img = new Image;
img.onload = function() {
return alert(img.width);
};
return img.src = fr.result;
};
return fr.readAsDataURL(file);
});
The thing is that I have no idea how to assign the width to its parent .details element which set the preview width of the preview.
I try replacing the alert for this code but it doesn't do anything.
$(this).parent('.details').css('height',img.height);
I'm a bit lost in how to relate the value inside the onload function to applying it to its parent class.
With the latest version of dropzone you don't have to write this code yourself.
Simply read the file.width and file.height properties that are set on the file object when the thumbnail is generated.
The problem, why your CSS doesn't affect the element, is because you didn't specify the unit, px in this case. So your code can be:
myDropzone.on("thumbnail", function(file) {
$(this.element).parent('.details').css('height', file.height + 'px');
});

Capturing load event for images dynamically changing their source

I am changing src for image dynamically and want to capture on load event for that image. Is there a way I can do it?
Several years ago, I discovered that the onload event was not reliable in some browsers (I don't remember which ones) when setting .src for the second time. As such, I settled for replacing the image object. I would create a new image object, set the onload handler, set the .src value and then when it loads, insert it into the page in place of the existing image.
When creating an image from scratch in javascript, you do this:
var img = new Image();
img.onload = function() {
// put your onload code here
};
img.src = "xxx.jpg"
If you just want to change the .src of an image, you just find the DOM object in the page and set it's .src property.
var img = document.getElementById("myImage");
img.src = "xxx.jpg";
If you want to try to capture the onload event when resetting the .src (what I had reliability problems with a couple years ago, you would do this:
var img = document.getElementById("myImage");
img.onload = function() {
// your code here
};
img.src = "xxx.jpg";
If you want to load a new image and replace an existing one with it when it loads, you would do this:
function replaceImg(oldImage, newSrc) {
var img = new Image();
img.onload = function() {
var parent = oldImage.parentNode;
parent.insertBefore(img, oldImage);
parent.removeChild(oldImage);
// put any other code you want here when the
// replacement image is loaded and in place
};
img.src = newSrc;
}
And, you would call this like this:
<img id="myImage" src="yyy.jpg">
var oldImage = document.getElementById("myImage");
replaceImg(oldImage, "xxx.jpg");
// create image object
var image = new Image();
image.onload = function () {
// do stuff
$('#myimageelementid').prop('src', image.src); // set the element in the DOM with this image
}
image.src = "image.jpg"; // will trigger onload when loaded

Categories