Blair Conrad

Animating Google Chrome Extension Page Action Icons

I'm enjoying using (and working on) Library Lookup</a>, 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: .

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();