views:

175

answers:

4

I have an Android application that generates some HTML which is rendered locally, in a Webkit view.

The details of the HTML generation aren't really that important except for:

  • the bulk of it comes from one place, and I cannot change it
  • the template around that HTML (including headers, footers, HEAD etc), the CSS, and Javascript is under my control.
  • most images are under my control, and rendered separately from the untouchable HTML. These images come from local disk, and do not require the network. It can be assumed that these images are always available.
  • the untouchable HTML contains images which would, ideally be displayed. If the network is unavailable, it is these images that would fail to load.
  • the complete HTML file is likely to be stashed to disk, long before it is rendered. i.e. we cannot render different HTML based on network availability.

The app is likely to be offline for at least some of the time, so I wish to handle the case where images fail to load.

The images in question are predominantly 1x1 tracking images, but may include images that should be visible if they're available.

Without invoking JQuery, or an external library, what would you advise my plan of attack?

I have thoughts on how to do this, but realise that they are many pitfalls to worry about:

  • with a CSS selector, select all the images that haven't loaded (is there such a selector?) and use display:none;.
  • with Javascript, set the alt attribute on every image to the empty string. This would need to be done on document.onLoad?
  • check the availability of the network, and then using CSS hide all images with @href~=^http. I'm not sure how/when to apply this style.

If it helps, for this problem, I seem to have the following sub-problems. It is not clear the optimal strategy for any of them:

  • how to determine the loaded-ness of the images or the state of the network.
  • how to hide/mask the failed to load images, such that it is not detectable by the user that the image is missing.
  • when to perform these tasks (e.g. when the document/window has finished loading?)
  • how to apply them.

Any thoughts, code, suggestions would be gratefully received.

+1  A: 

how to determine the loaded-ness of the images or the state of the network.

One approach may be to maintain references all of the images in the DOM and bind an onload event which is fired when the image has finished loading. After a specified amount of time, any image which hasn't fired can be assumed to be problematic.

how to hide/mask the failed to load images, such that it is not detectable by the user that the image is missing.

You've already mentioned some options. Have you thought about removing the element from the DOM altogether? Client will no longer attampt to load the image.

when to perform these tasks (e.g. when the document/window has finished loading?)

You cannot use the document or window onload events because that won't fire until everything on the DOM has loaded. Checking the readiness of the DOM varies between browsers (Lucky you're only dealing with one!). This might get you started.

Tate Johnson
+1  A: 

Interesting question.

Looking in Firefox, if an image doesn't load, its naturalHeight (and width too) is 0. You could probably use some javascript in android to read a similar property. My test script in Firebug was simply:

document.getElementsByTagName('img')[0].naturalHeight
David Caunt
A: 

If your images are not content to be consumed instead of text or to supplement text then they should be CSS background images. Background images are completely passive and do not show at all if they cannot be retrieved or processed.

+4  A: 
  • how to determine the loaded-ness of the images or the state of the network.
  • how to hide/mask the failed to load images, such that it is not detectable by the user that the image is missing

You may look at the onerror event which is triggered when an image fails to load:

<img src="image.png" alt="image" onerror="this.parentNode.removeChild(this)" />
  • when to perform these tasks (e.g. when the document/window has finished loading?)
  • how to apply them.

This worked for me in Firefox and Chrome when I added it ad the very end of my document (before </body>):

var imgs = document.getElementsByTagName('img')
 for(var i=0,j=imgs.length;i<j;i++){
  imgs[i].onerror = function(e){
  this.parentNode.removeChild(this);
 }
}

It is quite posiible that if an image at the begining of your document didn't load, and you attach yor event handlers when the document is ready some browsers may not fire that handler - you should test it on your target platform.

pawel
This is exactly what I was looking for. Thanks.
jamesh