Favicons should ideally be easy to manipulate, as easy as manipulating the web page's UI. (Favicons are the little website icons you see in the address bar, browser tabs, etc.) For example, a chat app like Meebo could signal that your buddy's trying to contact you, a mail app like GMail could indicate You Have Mail!
I've found surprisingly little info on this - is anyone doing it? Anyway, I've been wanting to play around with this for a while and having recently submitted the final book draft (post pending), I finally had some spare time to play with it. Fortunately, it turns out to be perfectly feasible - it seems that Firefox and Opera both use <link> tags to determine favico, and this can be changed dynamically to satisfaction. The only gotcha is that you can't try to be too efficient - if you reuse an existing link object and overwrite its href property, the browsers won't pay any attention. so you simply have to remove the existing link tag and add back a new one with the new icon URL. Unfortunately, IE and Safari don't seem to use the link technique at all - I think they just use the "favicon.ico" file. If you know of a way their icons could be dynamically manipulated, please mail me or add a comment here.
So I've created a library, favicon.js, that lets you manipulate favicons with a single call - changeFavicon("theIconUrl.ico");. You can also set the document title, changeFavicon("theIconUrl.ico", "Hi Everybody!"), which just sets document.title. There are a couple of demos and a brief FAQ:
- Type a letter, see the icon change.
- The icons cycle automatically, using a timer. So you can stick it in a background tab and see how it looks.
- FAQ
Implementation Details. Here’s the favicon.js code as it stands, all 32 lines of it :-). [javascript] var favicon = {
change: function(iconURL) { if (arguments.length==2) { document.title = optionalDocTitle; } this.addLink(iconURL, “icon”); this.addLink(iconURL, “shortcut icon”); },
addLink: function(iconURL, relValue) { var link = document.createElement(“link”); link.type = “image/x-icon”; link.rel = relValue; link.href = iconURL; this.removeLinkIfExists(relValue); this.docHead.appendChild(link); },
removeLinkIfExists: function(relValue) { var links = this.docHead.getElementsByTagName(“link”); for (var i=0; i<links .length; i++) { var link = links[i]; if (link.type==”image/x-icon” && link.rel==relValue) { this.docHead.removeChild(link); return; // Assuming only one match at most. } } },
docHead:document.getElementsByTagName(“head”)[0] } [/javascript]
Update (Two Days Later)
Crikey! Dugg and on Delicious Popular. And, well, Ajaxian too ;-). Digg is interesting ... The last time I submitted my own story to digg, it got precisely two diggs (thanks to the other guy!). This time, I didn't bother. Is there a moral here?
New, improved, with animate(). Most people get dynamic favicons, but some people have said this whole thing is about animation, about as useful as a blink tag, etc. Okay, that kind of misses the main point, which is about notifying the user while a tab is in the background. The FAQ makes it pretty clear that animated icons was a kind of afterthought (actually, it only occurred to me after I created the cycling demo - changing according to a timer was simply the easiest way to update a background tab, since there's no chat functionality needed or anything like that). But, you know, when a simple idea like that causes seems so wrong to some people, there's probably wheels in it. And while I did say animated GIFs are possibly more elegant in the FAQ, it since occurred to me that it's a bit of a hassle for the casual developer to make an animated GIF. You also get the benefit of compatibility with Opera (and maybe others?). So I've added an animate() method, only 8 more lines in all, that lets you cycle through a sequence of images. I expect to post it over the weekend. Mmm...Eye Candy!