My favorites | English | Sign in

Google Desktop APIs (Labs)

Meeting User Expectations: Interacting With Items

Omar Khan, Software Engineer
August 2007

Introduction

Computer users learn all kinds of arbitrary conventions: blue underlined text is a hyperlink, an I-beam cursor means you can select text, clicking 'OK' for all the dialogs during software installation—whoops! That's not such a good one, but you get my point.

This is no different with gadgets. Most users first encounter Google Desktop gadgets by using the news gadget or some other item-based gadget. They learn the default way of interacting with gadgets from these first encounters. As I post more articles on code.google.com and the Google Desktop APIs blog, one of my themes will focus on how we, as gadget creators, should design our interfaces given a user's habits. In this article, I'll examine how users typically interact with a gadget and show how to get the expected behavior out of the gadget.

Expected item behaviors

The News Gadget
The News Gadget

In the news gadget, the user sees lots of news stories, each of which is a content item. Here are the interactions users come to expect from the news gadget:

  1. Mousing over an item highlights that item: In the news gadget, the background color changes slightly to indicate which item has focus (this may not be relevant if your gadget only has one item).
  2. Single-click to open details view: The details view gives a larger view on the item's information.
  3. Double-click to fully open item: In the news gadget, double-clicking opens the item in the user's default web browser.
  4. Click again to close: If the user is looking at an item in the details view, clicking that item again in the gadget closes the item.

Many gadgets in our gallery, unfortunately, violate these expectations. This may seem minor, but users value consistency. Not only is it pleasing, it makes the experience much easier, and lets users focus on the unique features of the gadget, not its odd behavior.

How to get these behaviors in a gadget

When I tell developers about these common behaviors, a common reply is 'OK, so how do I get my gadget to do that?' Here's a brief description that focuses on items that are enclosed in a div tag.

First, you want to have an array of such items:

var items_ = [];

Suppose you want to create 5 items. Each item has some main text and a date. The entire item should be clickable and should change colors when it's highlighted. Here's some code to achieve that:

for (var j = 0; j < 5; ++j) {
  // (1) Generate the per-item code that will be called depending on how the user interacts with the item
  var commonCode = ' onmouseover="hilightItem(' + j + ');" onmouseout="unhilightItem(' + j + ');" enabled="true" ' +
    'onclick="onItemClick(' + j + ');" ondblclick="onItemDblClick(' + j + ');"';

  // (2) construct the item, and include the common interaction code  
  var newDiv = '<div x="0" y="' + 45 * j + '" width="248" height="40" background="#ebebeb" ' + commonCode + '>' +
    '<label name="itemName" x="0" y="0" align="left" width="246" size="14" ' +
       'font="Georgia" ' + commonCode + '>' + itemName[j] + '</label>' +
    '<label name="itemDate" x="0" y="19" align="left" width="246" size="12" height="20" ' +
       'font="Georgia" ' + commonCode + '>' + itemDate[j] + '</label>' +
    '</div>';

   // (3) store the item in our global items_ array
   items_[j] = content.appendElement(newDiv);
}

Notice that in (1) we handle all the common behaviors when interacting with an item. The onmouseover and onmouseout handlers deal with highlights, the onclick handler controls the details view, and the ondblclick handler will deal with opening the item. Referring to (2), since all the elements of the div must be clickable (the container, the text, and the date), we add the common code to all parts of the div. Finally, we keep a reference to the div in our items array (3).

The highlighting handlers are as follows:

function hilightItem(itemIndex) {
    // we use an image for the background. This image is stored in the gg file of the gadget
    items_[itemIndex].background = "selected.png";
}

function unhilightItem(itemIndex) {
    // we return to our default background color when the user moves the mouse away from the item
    items_[itemIndex].background = "#EBEBEB";
}

Displaying a details view, and properly closing it when the user clicks the item again, is also quite easy:

var currentItemDetailsView_ = -1;

function onItemClick(itemIndex) {
  // close the details view if already displaying
  if (itemIndex == currentItemDetailsView_) {
    plugin.CloseDetailsView();
    currentItemDetailsView_ = -1;
    return;
  }

  // otherwise construct details view..
  // DO WORK HERE

  // show details
  plugin.ShowDetailsView(htmlDetailsView, title, gddDetailsViewFlagToolbarOpen, onDetailsViewFeedback);
  currentItemDetailsView_ = itemIndex ;
}

function onDetailsViewFeedback(detailsViewFlags) {
  // the user/system closed the details view
  if (detailsViewFlags == gddDetailsViewFlagNone)
     currentItemDetailsView_ = -1;
}

Finally, opening an item on double-click is handled by this code:

function onItemDblClick(itemIndex) {
  var shell = new ActiveXObject("Shell.Application");
  shell.Open(itemUrls[itemIndex]);
}

Conclusion

This small amount of work is worth doing to make users feel more comfortable with your gadget. Please post comments to our developer forum if you do something different in your gadgets, or have thoughts on what I've described here.