Animating Google Chrome Extension Page Action Icons

I'm enjoying using (and working on) Library Lookup, but I'm not entirely satisfied with the Page Action icons that pop up when searching, or when a book is found, or not found. In particular, I wanted a small animation while the search was ongoing, something like this: animated_search.

Unfortunately, the animated GIF didn't work - Google Chrome Extensions don't support them.

Briefly deterred, I regrouped and tried a different tack - something I like to call A Bunch o' PNGs and Some Javascript. First, I got myself three PNGs to display (okay, that's not entirely true - they're what I made the GIF from to begin with)

  • searching_eyes_right.png
  • searching_eyes_down.png
  • searching_eyes_left.png

Next, I needed a way to switch between the frames. I put the image names in an array, initialized an index, and wrote a small function that uses window.setTimeout to switch to a new icon every 0.3 seconds.

var searching_images = ['searching_eyes_down.png',
                        'searching_eyes_right.png',
                        'searching_eyes_down.png',
                        'searching_eyes_left.png'];

var image_index = 0;

var keep_switching_icon = true;
function rotateIcon()
{               
   if ( keep_switching_icon )
   {
      chrome.pageAction.setIcon({tabId: sender.tab.id, path: searching_images[image_index]});
      image_index = (image_index + 1) % searching_images.length;
      window.setTimeout(rotateIcon, 300);
   }
}

Then I start the rotation just before hitting the web server to see if the book's available and stop it when a result is found. Flipping the keep_switching_icon flag as soon as the search completes ensures that the animating thread doesn't overwrite a "found" or "not found" icon.

window.setTimeout(rotateIcon, 300);

var xhr = new XMLHttpRequest();
xhr.open("GET", searchurl, true);
xhr.onreadystatechange = function() 
{
    if (xhr.readyState == 4) 
    {
       keep_switching_icon = false;
       if ( xhr.status != 200 )
       {
            chrome.pageAction.setIcon({tabId: sender.tab.id, path: 'my_book_error_19.png'});
            // other error handling
       }
      // process found and not found cases
};
xhr.send();