The easiest way to implement this is by using the onError handler that the Document Object Model (DOM) provides for image tags as part of the HTML specification. Whenever an image fails to load, the onError handler gets fired, if there is one. This is the perfect place to display an alternate image source file.
Anyway, SharePoint 2010 provides functionality built into its Picture Library to display thumbnails of pictures stored in the library. These thumbnails are created when the picture is accessed and are cached to speed up subsequent accesses.
The Problem
The way SharePoint handles thumbnails for pictures that don’t exist in the library does not jive well with the way Firefox determines if a picture does not exist. SharePoint does not return a 404 Not Found exception when accessing a thumbnail page that doesn’t exist because it’s trying to generate the thumbnail in the background and instead returns an empty picture. Firefox receives this empty picture and treats it like a successful call.
The end result is that Firefox doesn’t fire the onError handler for that particular image, even though no image has actually been returned. How can we prevent such a situation from happening?
The Solution
The simple solution, if you have server-side access to SharePoint via the Object Model is to check the library yourself before generating the link to the image that the picture exists in the library. However, this isn’t always an option, especially if you aren’t running on the server. Your best options are to check that the image exists in the onLoad handler or to access the image through the JavaScript Client Object Model. Either way, you don’t want to load the image immediately when you create it because you need to attach the handlers. I’ll show both examples.
Override onLoad Handler
The onLoad handler fires when the image is “successfully” loaded by the browser. Once here, you need to check the image size to make sure that it’s not 0 x 0. If it is 0 x 0, you’ll want to fire the onError handler to avoid duplicating code. I’m assuming that you’re using jQuery. If you’re not, the functionality is similar but not identical.
1: /*Assume that $image already exists and points to a jQuery object wrapping an IMG tag*/
2: $image.error(function ()
3: {
4: this.src = '../images/silhouette.jpg';
5: }).load(function ()
6: {
7: if(this.width <= 0 && this.height <= 0)
8: {
9: $(this).error();
10: }
11: }).attr('src', '[Path to target image]');
Use the JavaScript Client Object Model for SharePoint 2010
You can also use the Client Object Model to determine if the object exists in the library and act accordingly. Once again, I’ll be assuming you have jQuery
1: /*Assume that $image already exists and points to a jQuery object wrapping an IMG tag*/
2: var listItems;
3: function verifyPicture()
4: { 5: var clientContext = new SP.ClientContext('[Site URL]');
5: var list = clientContext.get_web().get_lists().getByTitle('[Picture Library]');
6:
7: var query = new SP.CamlQuery();
8: query.set_viewXml('<View><Query><Where><Eq>' +
9: '<FieldRef Name="Name" /><Value Type="' + $value '"></Value>' +
10: '</Eq></Where></Query></View>');
11:
12: listItems = list.getItems(query);
13: clientContext.load(listItems);
14:
15: clientContext.executeQueryAsync(Function.createDelegate(this, onQuerySucceeded), Function.createDelegate(this, onQueryFailed));
16: }
17: function onQuerySucceeded(sender, args)
18: {
19: if(listItems.length > 0)
20: {
21: $image.attr('src', '[Path to image]');
22: }
23: else
24: {
25: $image.attr('src', '../images/silhouette.jpg');
26: }
27: }
28:
29: function onQueryFailed(sender, args)
30: {
31: $image.attr('src', '../images/silhouette.jpg');
32: }
This is more complicated and slower, but is guaranteed to give you the correct result. Only if you can get the element back from the picture library in question will you use the thumbnail. You’ll be showing the silhouette if there are any issues.
I have no personal preference in the matter, except that you might find it more difficult to work with the SharePoint Object Model and jQuery at the same time.