2

I have recreated a blueprint, which has 60+ rooms, as an inline SVG.

There are functions that display information, such as pictures, when you select or hover a room. I'm using one div container to display the pictures by setting its background property to url('path-of-image.ext'), as can be seen below.

var cla = document.getElementsByClassName('cla');

for (i = 0; i < cla.length; i++) {
  cla[i].addEventListener('mouseenter', fun);
}

function fun(){
  var str = 'url("media/' + this.id.slice(4) + '.jpg")';
  pictureFrame.style.background = str;
  pictureFrame.style.backgroundSize = 'cover';
  pictureFrame.style.backgroundPosition = 'center'
}

The reason I'm not using the background property's shorthand is because I plan on animating the background-position property with a transition.

However, not all rooms have pictures. Hence console throws the following error, GET ... net::ERR_FILE_NOT_FOUND, when you select or hover said rooms. The error doesn't cause the script to break, but I would prefer not to run that code every single time a room is hovered, even when a given room doesn't have pictures.

Even though I know this can be done imperatively with if/else statements, I'm trying to do this programmatically since there are so many individual rooms.

I've tried using try/catch, but this doesn't seem to detect this sort of error.

Any ideas?

Is it even possible to detect this kind of error?

oldboy
  • 5,729
  • 6
  • 38
  • 86

2 Answers2

2

You could attempt to read it using FileReader and catch/handle NotFoundError error.

If it were to error, you could assign it to an object or array which you would first check upon hover. If the file was in that array, you could avoid attempting to read it again and just handle however you like.

Here is a good article by Nicholas Zakas on using FileReader

Jordan Bonitatis
  • 1,527
  • 14
  • 12
  • 1
    I'm posting this as an alternative to @quetzaluz's proposed solution, which would be the approach I'd actually prefer. – Jordan Bonitatis Mar 04 '17 at 22:27
  • yep! would his solution work locally?? i guess i could do that too. create an array of all the rooms with pictures, and then loop through the array to check if the room has pictures or not – oldboy Mar 04 '17 at 22:30
  • ah - sorry. i thought you were asking if my solution above would work locally. mine would work locally, yes. @quetzaluz's may not work, depending on how your filepaths' are structured – Jordan Bonitatis Mar 04 '17 at 22:35
  • Yup - if you're having trouble implementing, ping me on chat – Jordan Bonitatis Mar 05 '17 at 01:09
  • word. thanks. i think i'm just gonna use an array for the time being since there's really only 9 photos right now lol – oldboy Mar 05 '17 at 07:06
1

First off I would see if there is a way of checking if the file exists before the document even loads so that you don't make unnecessary requests. If you have a database on the backend which can manage this that would serve you very well in the long term

Since you make it sound like the way you only know a file exists is by requesting it, here's a method that will allow you to try this:

function UrlExists(url)
{
    var http = new XMLHttpRequest();
    http.open('HEAD', url, false);
    http.send();
    return http.status!=404;
}

This won't request the image twice because of browser caching. As you can see that method is itself being depricated and overall the best way you can remedy this problem is checking before the page even loads; if you have a database or datastructure of any sort, add a class or property to the element if the image exists or not. Then, in your existing method, you can call something like document.getElementsByClassName('cla-with-image') to get only records that you've determined has an image (much more efficient than trying to load images that don't exist).

If you end up using that UrlExists method, then you can just modify your existing method to be

function fun(){
  var url = "media/' + this.id.slice(4) + '.jpg";
  if (UrlExists(url)) {
      var str = 'url(' + url + ')';
      pictureFrame.style.background = str;
      pictureFrame.style.backgroundSize = 'cover';
      pictureFrame.style.backgroundPosition = 'center'
  }
}
Community
  • 1
  • 1
quetzaluz
  • 1,071
  • 12
  • 17
  • thing is i would've used ajax, but i don't need to concern myself with this right now. i'm building it for a company, and it might be somebody else who implements it, so right now i'm just concerned about performance and it working offline. thanks for responding tho!!<3 any other ideas? – oldboy Mar 04 '17 at 22:04
  • Ah that's my only main idea (follow best practices + here's a method if you want). I updated my reply to include how you would use that existing method in your code. I've upvoted your question in hope that you'll get more of the replies you need! – quetzaluz Mar 04 '17 at 22:17
  • 1
    Try the answer from the other poster. – quetzaluz Mar 04 '17 at 22:34