Advice on sequencing items in web interfaces?
A small but common task in web interfaces, especially “admin” (back-end, content manager) interfaces, is sequencing items. Any time you have a collection of objects that requires arbitrary, user-defined ordering (i.e. ordering that can’t be derived from the objects’ values) you are faced with this problem. Navigation is a common example. If people can add items to a dynamically built navigation menu or tree, how do we let them specify the ordering so that “Contact” can appear below “About Us” or vice-versa?
One low-tech way is to add a numeric field that can be manually edited; you then sort the objects by that field before displaying them. (Sub-puzzle: a good one-word label for that sort of field eludes me. “Order” and “sequence” both apply more to the whole set than the individual; “number” is too vague; “precedence” is too technical.) This works, but always feels clunky – it reminds me of the bad old days of BASIC programming because you end up incrementing by 10s or 100s and then filling in the gaps as more items are added.
Other methods involve a bit more work on the interface end, and include up/down arrows to nudge position, or list boxes with references that can be added or removed by clicking buttons. These don’t seem worth the trouble.
Most elegant would be a drag-and-drop ordering solution, the pride of many a glorious Ajax demo. Because I can’t think of an appealing simpler alternative (and I really do like simple when I can get it), I’m actually considering this for a new project in which the user needs to be able to rearrange “page” objects in a presentation.
The drag-and-drop Ajax technique would surely be fun to do, but before diving in I wanted to float this quasi-lazyweb post to see if there are other good approaches to this little problem that I’m overlooking.
metapundit commented on Sat Jan 6 01:11:18 2007:
You’re probably going to implement this in Python, but if working with legacy PHP this might be useful…
I encapsulated the scriptaculous drag-n-drop effect along with some JS to serialise the order of the ul and save it to a hidden field in a PEAR QuickForm control. Now in any form I’m using QuickForm to generate, I can get a drag-n-drop list by saying
$page->addElement(‘sorter’,‘colors’,‘Color Order’, array(4 => “Blue”,9 => “Red”, 13 => “Green”));
And $_POST[‘colors’] will be a comma separated list of the keys in the order they were arranged.
Code is here and I put up a brief post about it… Feel free to rip off the JS or port to DJango equivalent.
More to the point of your question: the best way to handle this is drag and drop, but it should happen in the context of actual display! I wrote a basic product catalog that lets you put products in multiple categories and has a “Ordering” field for each category the product is in. Same crappy solution: increment ordering by 10 and fill in as needed.
This sort of solution makes sense to programmers because our brains have been damaged by thinking like computers all the time. Real people, however, have had enormous amounts of difficulty handling this sort of interface. As it turns out, I would have been enormously better suited to have invested the time to allow drag and drop ordering on the actual catalog display page so that the operation of ordering was intuitive and the details of implementation (a separate sequence number for every category) are not exposed to the user…
metapundit commented on Sat Jan 6 01:12:49 2007:
Whoops, lost my links. Code is at http://metapundit.net/samples/HTML_QuickForm_Sorter.php.txt and post is at http://metapundit.net/sections/blog/42
Taybin commented on Sat Jan 6 10:38:57 2007:
Drupal uses the term “weight” for the ordering field name.
Paul commented on Sat Jan 6 12:41:56 2007:
“Weight” seems better than most of my ideas. It still isn’t perfect since it doesn’t make it instantly obvious whether high or low numbers have greater priority, but in practice that’s probably not a big hangup.
metapundit – thanks for that, I’ll take a look. I think you’re right that in-place editing is often better. I’ve rarely implemented it, though, mostly due to weak JS chops I think. The toolkits have gotten good enough to override that excuse though.
tim commented on Thu Feb 15 05:10:18 2007:
Rails’s acts_as_list
defaults to using ‘position’ as the column name.
Paul commented on Thu Feb 15 15:33:01 2007:
Even better than “weight”, thanks!