My name is Paul Bissex, and e-scribe.com is my consulting business. I build web applications using as much open source software as possible. From September to June I teach web design and other important non-photographic professional skills to photographers. In the '90s I wrote technology commentary and reviews for magazines, newspapers, and web publications, including Wired, Salon.com, FamilyPC, the late lamented Web Review, and the Chicago Tribune. Feel free to email me.
I'm co-authoring a book, "Python Web Development with Django", with Jeff Forcier and Wesley Chun. It will be published by Prentice Hall in July 2008, but is available for pre-ordering on Amazon now.
This site is built on a fresh trunk checkout of Django, running on Python 2.5.1, served by Apache and mod_python. The database is SQLite. The operating system is FreeBSD, on a VPS hosted at Johncompanies.com. Comment-spam protection by Akismet. Vintage topo imagery from the Maptech archive.
Akismet, del.icio.us, Django, dpaste.com, Emacs, FreeBSD, Freenode, jQuery, LaunchBar, MacPorts, Markdown, Mercurial, OS X, Postfix, Python, SQLite, Subversion, TextMate, Trac, Ubuntu Linux, wmii
Copyright 2008
by Paul Bissex
and E-Scribe New Media
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.
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
"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.
Rails's acts_as_list defaults to using 'position' as the column name.
Comments use Markdown syntax. Your comment will not appear until approved, which may take a few hours or more. Spammers will be torpedoed.
The iPhone keyboard doesn't suck
Python one-liner of the day
7 comments
How not to advocate via Google Code
2 comments
99 problems
3 comments
bitmonk
Obscure "svn mv" problem solved
98 days ago
Charlie
Book news: Rough Cuts and Amazon
99 days ago
Simon Griffee
Django Mercurial mirror tweaks
116 days ago
Jason Calleiro
From PHP to Python
117 days ago
Yuli
dpaste.com
120 days ago
bruce
Neat Python hack: infix operators
124 days ago
David Reynolds
The original Lego Star Wars
132 days ago
At least 38476 pieces of comment spam killed since January 12th. Thanks are mostly due to Akismet.
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...