Check if image exists on server using JavaScript?
You could use something like:
function imageExists(image_url){
var http = new XMLHttpRequest();
http.open('HEAD', image_url, false);
http.send();
return http.status != 404;
}
Obviously you could use jQuery/similar to perform your HTTP request.
$.get(image_url)
.done(function() {
// Do something now you know the image exists.
}).fail(function() {
// Image doesn't exist - do something else.
})
Check if image exists before loading
The problem it does not work is getThumbnail() method will not behave as you want.
The .onload is an async call and for this case, getThumbnail(value) will always have undefined returned result;
To accomplish what you want, you can do something like:
<img src="/image/..." onerror="javascript:this.src='images/default.jpg'"/>
Check if image exists without loading it
Since JavaScript (and therefore jQuery) is client-side and the image resides server-side before loading there is no way to check to see if the image exists without using Ajax or your server-side scripting to make sure the image exists.
Checking if image does exists using javascript
The general strategy is to use an DOM Image
object instance, set the src
property to the URL of the image you want to check (which will cause the browser to fetch and load the image), and then handle the load
and error
events to determine existence or absence, respectively.
Here's an example promise-based approach:
function imageExists(url) {
return new Promise(resolve => {
var img = new Image()
img.addEventListener('load', () => resolve(true))
img.addEventListener('error', () => resolve(false))
img.src = url
})
}
const url = 'http://www.google.com/images/srpr/nav_logo14.png'
imageExists(url)
.then(ok => console.log(`RESULT: exists=${ok}`))
// => RESULT: exists=true
How to check if image exists?
This is probably the shortest possible code to handle lost images in JS. imagePad
is a reference to the DOM element in which you want to show the image.
var img = new Image();
img.addEventListener('error', function (e) {
// Image not found, show the default
this.src = iconBase + 'gen.png';
});
img.addEventListener('load', function () {
imagePad.appendChild(img);
}
img.src = 'the_given_src';
Test if a photo exists Javascript
Among other things, you need an event handler to execute the test.
<script>
var photosArray = ["1.jpg", "2.jpg", "3.jpg", "4.jpg"];
var src = photosArray[4] + '?v=' + new Date().getTime(); // photosArray[5] doesn't exist because arrays are 0-indexed
console.log('src: ' + src);
function imageExists(src){
var http = new XMLHttpRequest();
var exists;
http.open('GET', src, true);
http.onreadystatechange = function(){
if (http.readyState === 4 && http.status >= 200 && http.status < 300) {
console.log('okay');
exists = true;
// do something
}
else {
console.log('fail');
exists = false;
// do something
}
// do something, perhaps foo(exists);
}
http.send();
}
imageExists(src);
</script>
You can't simply return the value for exists
from this function however, because XMLHttpRequest
, as you noted, is asynchronous: imageExists()
will return before the XMLHttpRequest
has finished, and you'll get false negatives. Returning the event handler will not return a value for imageExists
either, only for the event handler function. The best you can do is do something when the XMLHttpRequest
's onreadystatechange
(or, in modern browsers, onload
) event fires.
You should look into Promises, the fetch
API, or create a variable in the parent scope (updating it from the event handler) and check it at intervals, in order to ascertain whether the image exists.
Alternatively, use window.setTimeout
with a variable in parent scope and check that variable after 'a reasonable amount of time' -- hint: judging what a reasonable amount of time should be is not a simple matter, given the almost impossible task of measuring the client's internet connection speed or deducing any kind of deterministically reliable estimate for 'a reasonable amount of time' for images of varying sizes.
Also, be aware that requesting an image may not give you a reliable result, as images can be cached by the browser. Hence why I append a cache-busting string to src
with '?v=' + new Date().getTime();
What you can do is attach event handlers on the image itself, like this:
<img src="/path/to/whatever.jpg" onerror="this.style.display='none'">
or
<style>img.not-loaded { display: none; }</style>
<img src="/path/to/whatever.jpg" class="not-loaded" onload="this.className=''">
Either of which would serve to hide the image if it wasn't found or if the request for it otherwise failed.
Edit: based on your comments, this is how you might go about it:
window.imageExists = function(main_img){ main_img.className+=' loaded'; [].slice.call(main_img.parentNode.querySelectorAll('.secondary-image')).forEach(function(this_img){ this_img.src = this_img.getAttribute('data-src'); }); };
img { display: none; } img.loaded { display: block; width: 100%; } img.secondary-image.loaded { display: inline-block; width: 20%; }
<div class="main-image-container"> <img src="http://i.imgur.com/VwQjLZI.jpg" class="main-image" onload="imageExists(this)"> <img src="" data-src="http://i.imgur.com/VwQjLZI.jpg" class="secondary-image" onload="this.className+=' loaded';"> <img src="" data-src="http://i.imgur.com/VwQjLZI.jpg" class="secondary-image" onload="this.className+=' loaded';"> <img src="" data-src="http://google.com/does_not_exist.jpg" class="secondary-image" onload="this.className+=' loaded';"> <img src="" data-src="http://i.imgur.com/VwQjLZI.jpg" class="secondary-image" onload="this.className+=' loaded';"></div>
Using JavaScript to wait until an image exists in the server?
Assuming you don't have any way for the server to notify the client that the image is ready, you could poll for the image with a simple fetch.
fetch('https://example.com/some-image.jpg', {
method: 'HEAD'
}).then((res) => {
if (res.ok) {
// Your image is ready
}
});
Do that every 5 or 10 seconds, or whatever is appropriate for your use case.
How to check if an image is available and display it with v-if
Checking image exists on the server in JS is well described in another SO question - Check if image exists on server using JavaScript?
So it is easy just to choose one of the solutions and integrate it into Vue. Since you want to use it in the v-for
loop, plain function is a bad solution. Better will be to introduce computed
property and extend existing object with some new properties:
Deleted my previous code - computed
is a bad choice either in this case because array/objects returned from computed
prop is not reactive data (changing the content of object returned by computed
will NOT trigger Vue re-render)
New example below shows solution combining deep watching input data (organisation
) + maintaining extended data in the data
part of the component...
const vm = new Vue({
el: '#app',
data() {
return {
// this if external input in question (prop maybe)
organisation: {
owners: [{
employeeId: 100,
name: "Bill",
},
{
employeeId: 200,
name: "Murray",
fail: true // just for demo purposes
},
{
employeeId: 300,
name: "Billy",
},
]
},
ownersWithImage: [],
}
},
methods: {
checkImageExists(owner) {
const img = new Image()
img.onload = () => {
owner.doesImageExist = true
}
img.onerror = () => {
owner.doesImageExist = false
}
img.src = owner.imageUrl
},
extendOwnerWithImage(owner) {
const extendedOwner = {
...owner,
imageUrl: 'https://www.fillmurray.com/250/' + owner.employeeId,
doesImageExist: false // default
}
if (!owner.fail) // just for demo purposes
this.checkImageExists(extendedOwner)
return extendedOwner
}
},
watch: {
'organisation.owners': {
handler: function() {
this.ownersWithImage = this.organisation.owners.map(this.extendOwnerWithImage)
},
immediate: true,
deep: true
}
},
})
.user-profile-image {
width: 150px;
height: 150px;
background-size: cover;
background-position: top center;
border-radius: 50%;
background-color: grey;
text-align: center;
vertical-align: middle;
line-height: 150px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div v-for="owner in ownersWithImage" :key="owner.employeeId">
<div v-if="owner.doesImageExist" :style="`background-image:url(${owner.imageUrl})`" class="user-profile-image">
<span>{{ owner.name }}</span>
</div>
<div v-else class="user-profile-image"><span>{{ owner.name }}</span></div>
</div>
</div>
Related Topics
How to Tell If a String Contains a Certain Character in JavaScript
Save Embedded Pdf from Website
Call a Function from an If-Statement Inside a Function
Check If Json Response Data Is Empty
Image Taken from Camera Not Saved to Gallery
How to Apply CSS to Parent Using Child Selector - With CSS or Angular 2
Regex to Get String Between Curly Braces
Javascript File Not Updating No Matter What I Do
Hierarchical Json from Flat With Parent Id
Uncaught Typeerror: Cannot Read Property 'Click' of Null Chrome Extension
How to Make a Bot Delete Messages After a Certain Time Period
React Js Error: Is Not Defined React/Jsx-No-Undef
Why Does Google Chrome Always Add Space After Selected Text
Keep Selected Dropdown Result After Refreshing Page, Jquery
How to Check If Input Field Is in Focus or Not
Select Value of Input Element Inside HTML Table Using Jquery