We are a user experience design and software development firm
Hire us to design your site, build your application, serve billions of users and solve real problems.
Last week I spent a couple of days lashing together a UI widget for a project that needed a little Ajax assistance. As always, I looked for an opportunity to learn something along the way, so I got signoff on using jQuery and some plugins I hadn't previously employed.
The result? A down-and-dirty mini-project that let me test drive Color Animations, jqModal and Low Pro for jQuery while employing tried-and-true solutions such as jQuery Templates and Live Query. What's more, the requirements for the widget itself left room for some careful consideration of user experience design.
In the end, I built a client-side demo in just a few days and handed it off to the project lead for integration with a complex back end. Now I'm free to refine my deadline-constrained code into something a little more OO and share the results.
This week, I'll talk about the project's complex usability requirements and Pathfinder's user-centered solution to those requirements. Next week, I'll walk you through our first pass at building custom code, roping in open-source libraries and making it all work together on a tight deadline. Finally, I'll walk you through the refactoring process so you can see the final, properly factored and reusable version.
The requirements centered around a subscription management interface in which members could be subscribed to a product, but only if they belonged to an eligible subscription group. Each member could belong to multiple groups, but at least one of those groups had to be eligible for subscription before the member could be subscribed to the product.
The workflow for this particular screen was for the user to choose which customer groups were eligible for any given subscription, and which customers within those eligible groups should actually be subscribed. (Group memberships themselves were handled on a different page.) Upon hitting our page, the user should be able to do the following:
The obvious design pattern here was a pair of multiselects, one for groups and one for members. Changes in the groups multiselect would propagate to the member multiselect. This sounded fine in theory, but we quickly learned that not all multiselects are created equal.
To differentiate between the selected and unselected items in a typical multiselect, you must employ a visual highlight. If you also want to call out changes that are pending in the current session, you must employ another visual highlight. Often, you end up with an eyesore: Either a visually chaotic collection of background colors (one each for initially selected, newly selected, initially unselected, and newly deselected) or an equally difficult-to-parse mixture of checkboxes and highlights (checkboxes for on/off, and a highlight to indicate pending changes).
Our solution to this problem was to use another time-honored design pattern: the linked multiselect. In this type of interface, each collection of selectable items is rendered as two physically distinct lists; the unselected items live in one list and the selected items in another. The user physically moves items between the two lists, either by clicking arrow icons or by dragging and dropping. (Due to time constraints, drag and drop isn't part of our current implementation.)
The advantages to this solution include the following:
The design pattern for linked multiselects is pretty well understood, but our implementation needed to support an additional dependency between one linked multiselect (the groups interface) and another (the members interface). Moving items from selected to unselected within the groups interface would cause items within the member interface to appear or disappear. We therefore had to repopulate the member multiselects in response to events within the group multiselects. We decided to call out these trickle-down effects with a tried & true Web 2.0 color fade effect.
As a courtesy to users, we also decided to retain the previous subscription state of members whose group eligibility was removed. This would alleviate a lot of tedium for users who accidentally changed a group's eligibility and then had to change it back.
Our tertiary requirements added complexity to the project. Because members could belong to multiple groups, we had to display the number of groups next to each member's name. That way, if the user needed to make sure a given member would remain subscribed, he could check how many groups that user belonged to before marking any of those groups ineligible.
Because our linked multiselects divided the members of a group into two boxes, we had removed the ability to see a group's entire membership at a glance. We therefore had to provide an alternate way to achieve this requirement. Our solution was the use of a modal dialog, a link to which appeared next to each group name. These links added some visual complexity to the multiselect, but we mitigated the visual noise with font size and color.
You can see the results of our interaction design by playing with our demo code. As a case study, I loaded up a collection of characters from Marvel Comics's "X-Men" franchise. As any fans of the mutant superheroes knows, the X-writers are famous for introducing scads of new characters and trading them between teams like a professional sports league. Using the X-characters allowed me to correctly model the many-to-many relationship between groups and members as they existed in my requirements.
Next time, we'll take a look at the actual code. In the meantime, you can check out the code on your own by viewing source on the above demo.
Topics: Ajax, Javascript, jQuery, Low Pro, OOP
Hire us to design your site, build your application, serve billions of users and solve real problems.
[...] last week’s post, I introduced the linked multiselect widget I was asked to implement on a tight deadline for an [...]
Pingback by Pathfinder Development » Implementing linked multiselects with jQuery, LiveQuery, and Low Pro: Part 2: First pass at the actual code, Monday, August 25, 2008 @ 2:54 pm