I need to check if an image URL is valid, which means that the image loads properly in the browser.
I've tried using this:
const src = "https://i.imgur.com/vXPYhT5.jpeg"
const img = new Image()
img.onload = () => console.log("valid image :)")
img.onerror = () => console.log("invalid image :(")
img.crossOrigin = "anonymous"
img.src = src
The problem is that the above code outputs "invalid image :(" in some mobile browsers e.g Safari, even when the image is valid.
To be more clear: the above code is not a cross browser solution for that problem.
Example of user agent this problem happened:
{
"userAgentInfo": {
"browserName": "Safari",
"browserVersion": "13.0.5",
"engineName": "AppleWebKit",
"engineVersion": "605.1.15",
"isBot": false,
"isMobile": true,
"os": "CPU iPhone OS 13_3_1 like Mac OS X",
"platform": "iPhone"
}
}
PS1: The image have all kind of CORS stuff enabled.
PS2: I can not see the error because its just a notification from the error tracker like Airbrake.nofity("Invalid image") on img.onerror.
According to Mozilla CDN: The Image() constructor creates a new HTMLImageElement instance. It is functionally equivalent to document.createElement('img').
See this link: https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/Image
I have also checked the functionality is not working in Opera on my macOs! However, it is working on all other browsers. see this link:
https://jsbin.com/hofitusoke/edit?html,js,console,output
Moreover, for Browser compatibility, it is mentioned for some opera for mobile the functionality is unknown!
some mobile browsers doesn't load image until it is place on DOM to reduce data consumption. So I don't have test device. But you can try this code.
function validateImageUrl(url) {
const image = document.createElement('img');
image.onload = () => { console.log("valid image :)") }
image.onerror = () => { console.log("invalid image :(") }
image.crossOrigin = "anonymous"
image.style.display = 'none';
document.body.appendChild(image);
image.src = url;
}
validateImageUrl('https://i.imgur.com/vXPYhT5.jpeg');
Related
I am trying to load a simple image using javascript, for that I am using following code
function loadImage(src) {
var image = new Image;
image.onload = function() {
document.body.appendChild(image);
};
image.onerror = function() {
document.body.appendChild(document.createTextNode('\nError loading as image: ' + this.src));
};
image.src = src;
}
loadImage('http://www.linkedin.com/favicon.ico');
loadImage('http://www.facebook.com/favicon.ico');
Fiddle Link
The problem I am facing is whole thing working in chrome and firefox but not working in internet explorer. I am not much used to with javascript.
Any solutions ?
IE will not load an ICO image into the browser unless its contentType is image/x-icon.
I can confirm by looking at the network tab in Firefox that the contentType for the LinkedIn image is application/octet-stream which would explain why IE will not show it while the Facebook image has a content type of image/x-icon which IE likes.
There is nothing you can from the browser other than don't request an image that has that type set on its server. I'm quite sure that sites like LinkedIn will have other small images from there site that you can link to.
FYI, if you look at the linkedIn source for it's homepage, you will find a tag that points to http://s.c.lnkd.licdn.com/scds/common/u/images/logos/favicons/v1/16x16/favicon.ico which works just fine in IE (because it's an image/x-icon).
It is also worth noting that some older versions of IE (and to be honest, I don't recall if IE8 is one of the affected ones), the onload event is NOT fired of the image is loaded from cache.
function loadImage(src) {
function doOnLoad() {
document.body.appendChild(image);
}
var image = new Image;
image.onload = doOnLoad;
image.onerror = function() {
document.body.appendChild(document.createTextNode('\nError loading as image: ' + this.src));
};
image.src = src;
if (image.complete) {
doOnLoad();
}
}
call the function on window load :-
<script type="text/javascript">
function loadImage(src) {
var image = new Image;
image.onload = function() {
document.body.appendChild(image);
};
image.onerror = function() {
document.body.appendChild(document.createTextNode('\nError loading as image: ' + this.src));
};
image.src = src;
}
window.onload=loadImage('http://www.linkedin.com/favicon.ico');
</script>
the image is not loading, when you call the method after load all the elements then it will work.
I'm trying to save my drawn circles on my canvas to the localstorage, but I just can't get it to work, at all.
So far this is my save-code in JS.
function saveCanvas() {
var canvas = document.getElementById("imgCanvas"),
doomslayer = canvas.toDataURL();
if (typeof (localStorage) !== "undefined") {
localStorage.setItem('imgCanvas', doomslayer);
} else {
document.getElementById("save").innerHTML.dataURL = "Local Storage not supported";
}
}
function loadCanvas() {
var image = localStorage.getItem('imgCanvas');
document.getElementById('imgCanvas').src = image;
}
JSFiddle link
Got it to work now, finally!
Working fiddle :)
You must load the saved data url into an Image and then use drawImage to load it onto the canvas
IE limitation: localStorage is only available on a served page (local execution won't work!).
// save to localStorage
localStorage.setItem("imgCanvas",canvas.toDataURL());
// reload from localStorage
var img=new Image();
img.onload=function(){
context.drawImage(img,0,0);
}
img.src=localStorage.getItem("imgCanvas");
I have a problem. I am trying to draw an image onto a canvas. The image is not from the HTML page, but on a file. Here is the code i use:
var img = new Image();
img.src = "/images/logo.jpg";
this._canvas.drawImage(img, 300, 300);// this is line 14
now, here's the problem. This does not seem to work on Firefox and IE10 (I haven't tested yet on other browsers). On Firefox (21) I get:
[19:09:02.976] NS_ERROR_NOT_AVAILABLE: Component is not available # file:///D:/Watermellon/scripts/base-classes.js:14
and on IE10 i get:
SCRIPT16389: Unspecified error.
base-classes.js, line 14 character 13
The files and their directories are:
root/index.html
root/scripts/base-classes.js
root/images/logo.jpg
Now when I change the img.src to a URL (an image from another site) everything works fine, the image draws itself after a delay(for it's get from the url). What am I doing wrong?
I'm guessing the problem is that the image isn't loaded yet before you attempt to use it. Try this:
var img = new Image();
img.onload = function () {
this._canvas.drawImage(img, 300, 300);// this is line 14
};
img.src = "images/logo.jpg";
The src property is set after binding the event because a cached image's load event fires immediately (which is a common problem in IE).
And according to your structure, the path to the image would probably be images/logo.jpg (removing the first /)
You need to wait for the image to load before attempting to draw it into a canvas:
var img = new Image();
img.src = "/images/logo.jpg";
img.onload = function () {
this._canvas.drawImage(img, 300, 300);// this is line 14
}
The problem that I guess here, is when the resources be available?, but there is a way to confirm that the resources are available, just check 'complete' attribute of the image object.
if (img.complete == true){
// is available.
} else {
// wait until is ready.
}
Also, you can make a merge method with onload event and a delay method that checking both stuff.
var img = new Image();
//first attach handler
img.onload = function(e){
if (e.target.complete == true) {
yourHandler(e);
} else {
var maxTimes = 10;
var countTimes = 0;
function retryLoadImage() {
setTimeout(function () {
if (countTimes > maxTimes) {
// -- cannot load image.
return;
} else {
if (e.target.complete == true) {
yourHandler(e);
} else {
retryLoadImage();
}
}
countTimes++;
}, 50);
};
}
};
img.src = yourSource;
This is working for me!!! on IE and FF.
Straight to point. I want to set the limit of the width and height of the image when user upload an image using plupload.
Letsay:
if
width: 1000px
height: 1000px
else
you must upload image with at least width:1000px and height:1000px
// $(".form").validator();
$(function() {
if($("#uploader").length > 0) {
var uploader = new plupload.Uploader({
runtimes : 'html5,flash,silverlight',
browse_button : 'pickfile',
container : 'uploader',
max_file_size : '10mb',
url : 'design.php?do=upload&ajax=1',
multiple_queues: false,
file_data_name: 'design',
flash_swf_url : www + '/js/plupload.flash.swf',
silverlight_xap_url : www + '/js/plupload.silverlight.xap',
filters : [
{title : "Image files", extensions : "jpg,gif,png,jpeg,bmp"}
]
});
$('#uploadfiles').click(function(e) {
if($("#uploader select[name=category]").val() == "") {
$("#uploader select[name=category]").next('.error-required').show();
return false;
}
uploader.start();
e.preventDefault();
});
uploader.init();
So, is this possible?
You can easily write a filter for plupload.
Here is filter for min required width.
Add bellow code to your script. (Just copy)
plupload.addFileFilter('min_width', function(maxwidth, file, cb) {
var self = this, img = new o.Image();
function finalize(result) {
// cleanup
img.destroy();
img = null;
// if rule has been violated in one way or another, trigger an error
if (!result) {
self.trigger('Error', {
code : plupload.IMAGE_DIMENSIONS_ERROR,
message : "Image width should be more than " + maxwidth + " pixels.",
file : file
});
}
cb(result);
}
img.onload = function() {
// check if resolution cap is not exceeded
finalize(img.width >= maxwidth);
};
img.onerror = function() {
finalize(false);
};
img.load(file.getSource());
});
And add this filter to your upload script.
filters : {
min_width: 700,
},
Plupload doesn't support this itself (although it has been requested). There are probably a couple of reasons for this, firstly because you just can't get the image dimensions before upload in IE (you can in some other browsers) and secondly, whilst that would work for some browsers using the using the HTML4/5 methods, I am not sure that the Flash/Silverlight etc. methods would also be able to reliably determine dimensions.
If you were happy with limited browser, HTML4/5 methods only you should hook into the "FilesAdded" event e.g.
uploader.bind('FilesAdded', function(up, files) {
//Get src of each file, create image, remove from file list if too big
});
I recently wanted to do the same thing, and was able to achieve it the way Thom was suggesting. He was correct on it's limitation though; if you want to add this, it will only work in modern browsers and not in the flash or silverlight runtimes. This is not a huge issue, as my non-html5 users will just get an error after upload, rather than before.
I initialized a total image count variable to keep track of the images placed on the page. Also a vairable to store photos we want to delete after we read them all.
var total_image_count = 0;
var files_to_remove = [];
Then I read the pending files with FileReader(), place them on the page, and get their width
init:{
FilesAdded: function(up, files) {
if (uploader.runtime == "html5"){
files = jQuery("#"+uploader.id+"_html5")[0].files
console.log(files);
for (i in files){
//create image tag for the file we are uploading
jQuery("<img />").attr("id","image-"+total_image_count).appendTo("#upload-container");
reader_arr[total_image_count] = new FileReader();
//create listener to place the data in the newly created
//image tag when FileReader fully loads image.
reader_arr[total_image_count].onload = function(total_image_count) {
return function(e){
var img = $("#image-"+total_image_count);
img.attr('src', e.target.result);
if ($(img)[0].naturalWidth < 1000){
files_to_remove.push(files[i]); //remove them after we finish reading in all the files
//This is where you would append an error to the DOM if you wanted.
console.log("Error. File must be at least 1000px");
}
}
}(total_image_count);
reader_arr[total_image_count].readAsDataURL(files[i]);
total_image_count++;
}
for (i in files_to_remove){
uploader.removeFile(files_to_remove[i]);
}
}
}
}
As a side note, I was wanting to show image thumbnails anyway, so this method works great for me. I have not figured out how to get an image's width without first appending it to the DOM.
Sources:
Thumbnail an image before upload:
https://stackoverflow.com/a/4459419/686440
Accessing image's natural width:
https://stackoverflow.com/a/1093414/686440
to access width and heigth without thumbnail an image you can do this:
uploader.bind('FilesAdded', function(up, files) {
files = jQuery("#"+uploader.id+"_html5").get(0).files;
jQuery.each(files, function(i, file) {
var reader = new FileReader();
reader.onload = (function(e) {
var image = new Image();
image.src = e.target.result;
image.onload = function() {
// access image size here using this.width and this.height
}
};
});
reader.readAsDataURL(file);
}
}
Is there a way to determine if a image path leads to an actual image, Ie, detect when an image fails to load in JavaScript.
For a web app, I am parsing a xml file and dynamically creating HTML images from a list of image paths. Some image paths may no longer exist on the server so I want to fail gracefully by detecting which images fail to load and deleting that HTML img element.
Note jQuery solutions wont be able to be used(the boss doesn't want to use jQuery, yes I know dont get me started). I know of a way in jQuery to detect when an image is loaded, but not whether it failed.
My code to create img elements but how can I detect if the img path leads to a failed to load image?
var imgObj = new Image(); // document.createElement("img");
imgObj.src = src;
You could try the following code. I can't vouch for browser compatibility though, so you'll have to test that.
function testImage(URL) {
var tester=new Image();
tester.onload=imageFound;
tester.onerror=imageNotFound;
tester.src=URL;
}
function imageFound() {
alert('That image is found and loaded');
}
function imageNotFound() {
alert('That image was not found.');
}
testImage("http://foo.com/bar.jpg");
And my sympathies for the jQuery-resistant boss!
The answer is nice, but it introduces one problem. Whenever you assign onload or onerror directly, it may replace the callback that was assigned earlier. That is why there's a nice method that "registers the specified listener on the EventTarget it's called on" as they say on MDN. You can register as many listeners as you want on the same event.
Let me rewrite the answer a little bit.
function testImage(url) {
var tester = new Image();
tester.addEventListener('load', imageFound);
tester.addEventListener('error', imageNotFound);
tester.src = url;
}
function imageFound() {
alert('That image is found and loaded');
}
function imageNotFound() {
alert('That image was not found.');
}
testImage("http://foo.com/bar.jpg");
Because the external resource loading process is asynchronous, it would be even nicer to use modern JavaScript with promises, such as the following.
function testImage(url) {
// Define the promise
const imgPromise = new Promise(function imgPromise(resolve, reject) {
// Create the image
const imgElement = new Image();
// When image is loaded, resolve the promise
imgElement.addEventListener('load', function imgOnLoad() {
resolve(this);
});
// When there's an error during load, reject the promise
imgElement.addEventListener('error', function imgOnError() {
reject();
})
// Assign URL
imgElement.src = url;
});
return imgPromise;
}
testImage("http://foo.com/bar.jpg").then(
function fulfilled(img) {
console.log('That image is found and loaded', img);
},
function rejected() {
console.log('That image was not found');
}
);
This:
<img onerror="this.src='/images/image.png'" src="...">
/**
* Tests image load.
* #param {String} url
* #returns {Promise}
*/
function testImageUrl(url) {
return new Promise(function(resolve, reject) {
var image = new Image();
image.addEventListener('load', resolve);
image.addEventListener('error', reject);
image.src = url;
});
}
return testImageUrl(imageUrl).then(function imageLoaded(e) {
return imageUrl;
})
.catch(function imageFailed(e) {
return defaultImageUrl;
});
jQuery + CSS for img
With jQuery this is working for me :
$('img').error(function() {
$(this).attr('src', '/no-img.png').addClass('no-img');
});
And I can use this picture everywhere on my website regardless of the size of it with the following CSS3 property :
img.no-img {
object-fit: cover;
object-position: 50% 50%;
}
TIP 1 : use a square image of at least 800 x 800 pixels.
TIP 2 : for use with portrait of people, use object-position: 20% 50%;
CSS only for background-img
For missing background images, I also added the following on each background-image declaration :
background-image: url('path-to-image.png'), url('no-img.png');
NOTE : not working for transparent images.
Apache server side
Another solution is to detect missing image with Apache before to send to browser and remplace it by the default no-img.png content.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} /images/.*\.(gif|jpg|jpeg|png)$
RewriteRule .* /images/no-img.png [L,R=307]
More to the answer of Rafael Martins, if you are using React, use this code:
<img
src="https://example.com/does_not_exist.png"
onError={(e) => {
e.currentTarget.src = "https://example.com/default.png"
}}
/>
Here's a function I wrote for another answer: Javascript Image Url Verify. I don't know if it's exactly what you need, but it uses the various techniques that you would use which include handlers for onload, onerror, onabort and a general timeout.
Because image loading is asynchronous, you call this function with your image and then it calls your callback sometime later with the result.
This is a variation of #emil.c answer but resolves with true/false based on image loading or not (as opposed to throwing an error when it fails):
function testImage(url) {
if (!url || typeof url !== 'string') return Promise.resolve(false);
return new Promise((resolve) => {
const imgElement = new Image();
imgElement.addEventListener('load', () => resolve(true));
imgElement.addEventListener('error', () => resolve(false));
imgElement.src = url;
});
}
just like below:
var img = new Image();
img.src = imgUrl;
if (!img.complete) {
//has picture
}
else //not{
}