1

I'm trying to write an onerror handler for images that replaces them with a loading image and then periodically tries to reload them. The problem I'm having is that if the loading image fails to load, it goes into an infinite loop of failure. I'm trying to deal with this by checking if the URL is the loading image:

if(photo.src != loadingImage) {
    // Try to reload the image
}

Unfortunately, loadingImage can be a relative URL (/images/loadingImage.jpg), but photo.src is always a full URL (http://example.com/images/loadingImage.jpg). Is there any way to generate this full URL without passing the function any more information? Obviously I could pass it the host name, or require full URLs, but I'd like to keep this function's interface as simple as possible.

EDIT:

Basically what I want is to guarantee that if I do photo.src = loadingImage, that this will be true: photo.src === loadingImage. The constraint is that I know nothing about loadingImage except that it's a valid URL (it could be absolute, relative to the server, or relative to the current page). photo.src can be any (absolute) URL, so not necessarily on the same domain as loadingImage.

Brendan Long
  • 53,280
  • 21
  • 146
  • 188
  • How are you getting the `loadingImage` variable? – mattsven Apr 25 '11 at 16:09
  • The function looks like this: `function retryImage(photo, loadingImage) { /* stuff */ }`. So `loadingImage` could be anything. I want it to work whenever `loadingImage` is a valid URL. – Brendan Long Apr 25 '11 at 16:13
  • You say that loadingImage and photo.src might be from different domains. if `loadingImage` is a relative URL, and isn't necessarily the same domain name as `photo.src`, how do you know what domain it's from? Is there a source URL you can tie it back to? If not, I don't know that you'll be able to accomplish what you're trying to do here. – Joshua Carmody Apr 25 '11 at 17:26
  • @Joshua Carmody: I editted the question to hopefully make it more clear. If `loadingImage` is a relative URL, it I want it to be handled like any other URL (so if it doesn't contain a scheme, it's relative to the current page, or the current page's server). – Brendan Long Apr 25 '11 at 18:23

3 Answers3

2

How about this? The photo should either be a full URL or relative to the current document.

var url;
// There probably other conditions to add here to make this bullet proof
if (photo.src.indexOf("http://") == 0 || 
    photo.src.indexOf("https://") == 0 || 
    photo.src.indexOf("//") == 0) {
  url = photo.src;
} else {
  url = location.href.substring(0, location.href.lastIndexOf('/')) + "/" + photo.src;
}
Ruan Mendes
  • 90,375
  • 31
  • 153
  • 217
  • 1
    +1 This worked in my tests. But I'd add a check to make sure that photo.src doesn't already start with a "/" to make sure you don't add two of them. Like `url = location.href.substring(0, location.href.lastIndexOf('/')) + (photo.src.indexOf("/") == 0 ? "" : "/") + photo.src;` or something. – Joshua Carmody Apr 25 '11 at 16:19
  • @Joshua, there are a number of things that can be done to improve it; however, if a url starts with a "/", it's supposed to be an absolute URL from the root of the server, so it shouldn't be handled as relative. – Ruan Mendes Apr 25 '11 at 16:58
  • the specific example the asker gave started with a "/". It's relative in the sense that it doesn't include the domain name and protocol. – Joshua Carmody Apr 25 '11 at 17:22
  • @Joshua, you're right, I was wrong to say that URLS starting with / are not relative. I'm not going to try to make this perfect, though, specially since it could lead to a rabbit hole – Ruan Mendes Apr 25 '11 at 20:57
2

Here's a couple methods people have used to convert relative URLs to absolute ones in javascript:

Alternatively, have you considered doing the opposite - converting the absolute URL to a relative one? If loadingimage always contains the entire path section of the URL, then something like this would probably work:

var relativePhotoSrc = photo.src;
if (relativePhotoSrc.indexOf("/") > 0 && relativePhotoSrc.indexOf("http://") == 0) {
    relativePhotoSrc = relativePhotoSrc.replace("http://", "");
    relativePhotoSrc = relativePhotoSrc.substring(relativePhotoSrc.indexOf("/"), relativePhotoSrc.length);
}
alert(relativePhotoSrc);
if (relativePhotoSrc != loadingImage && photo.src != loadingImage) {
    // Try to reload the image
}

There's probably a slightly more efficient/reliable way to do the string manipulation with a regular expression, but this seems to get the job done in my tests.

Community
  • 1
  • 1
Joshua Carmody
  • 13,410
  • 16
  • 64
  • 83
  • Thanks for the links. I considered turning the absolute URL into relative, but it's not necessarily the case that both images are on the same domain (it just happens to be that way in this case). – Brendan Long Apr 25 '11 at 16:25
  • The `document.createElement("a")` trick in that first link looks like it should do what I want. – Brendan Long Apr 25 '11 at 18:25
0

Just check if they end with the same string:

var u1 = '/images/loadingImage.jpg';
var u2 = 'http://example.com/images/loadingImage.jpg'

var len = Math.min(u1.length, u2.length);
var eq = u1.substring(u1.length - len) == u2.substring(u2.length - len);
Mike Blandford
  • 3,952
  • 4
  • 29
  • 32