Drag-n-Drop Sorting of Documents [ROUGH CUT]
Imagine the following situation - say you've got a set of documents which are all children of one container document. From within this parent container document you want to be able to quickly change the order in which the child documents appear. Sound familiar? It's a scenario I've come across a couple of times before and only now have I found a solution I'm happy with enough to share.
A Real-World Scenario
Let's use the example of a newsletter document. In this case the parent form is called something like newsletter and simply contains the title and date of the newsletter. Once saved we can add the child news item document to it. It's these news items that it would be nice to be able to sort as the author pleases.
In most cases news would be sorted by date/time. However with newsletter this is not always the case and so being able to adjust the order is a must in most cases. Whether or not you need to compile newsletters there's bound to be a scenario where the following technique would come in handy.
How to Sort Documents
The idea for the technique came to me both out of a necessity to develop it and from the inspiration I took from a demo of the Yahoo! UI Library, where they have a cross-browser sortable list.
Support
- Full
- Win / IE 6+ (IE 5.5 too?)
- Win & Mac / Mozilla (Firefox 1.5, Camino 1.0 etc)
- Mac / Safari 2.0 (should work in 1.2+ ?)
- Partial
- Win & Mac / Opera 8.5 (No Ajax, but sorting and form submission work)
- None
- Win / Opera 9.0 (sorting broken)
- Mac / IE 5.2 (no Ajax OR sorting. dead browser anyhow)
ass
Coding
Flesh-out the following items:
- An embedded view is treated as HTML and renders a set of LI elements on the parent document.
- When the page loads the script.aculo.us code makes this list sortable.
- Whenever a news item is moved (i.e the list items) the list of UNIDs for each child (in the new order) is posted to the server as an Ajax request.
- The Ajax request is sent to the UpdateOrder form where the UNIDs are stored in a multivalue field called NewOrder.
- The WQS agent for the UpdateOrder form iterates through each UNID and updates the news item's order (but only if it needs to)
- The agent returns (content-type:text/plain) a list of what it did.
- The browser-side script displays this list of changes to the user and uses the Yellow Fade Technique to highlight the message.
Notes:
- When Ajax isn't supported the "Update" button can be used. Note, however, that Ajax is only likely not to work on older browser or those with no script support. On these browsers it's unlikely that the drag-n-drop sorting will work and, so, there's not much point in the button. I left the button on because there could be a case when sorting does work but Ajax doesn't. Safari 1.0 or some Opera versions for example.
- Each LI has a hidden field called NewOrder. This is passed via POST to the server when Ajax is not used and the button is pressed instead.
Turned off conflicts in child form.
Mention inclusion of hidden text field in each LI element for use when no Ajax (although not in Safari, where order of fields is not reflected after re-sort)
Demo
Available here
Downloads
Most up to date database is Version 0.5
Version 0.5 fixes a problem in all previous versions described in this blog entry and also up
grades to Prototype 1.5 and Scriptaculous 1.7.
Version 0.1 uses the Yahoo! UI Library instead of Script.aculo.us and does NO T use Ajax. Horses for courses.
Taking It Further
Rep conflicts are a problem. How about having the Ajax call check the last-mod dates. Or with XML
Summary
Put summary here
Is using Ajax a good idea?
Wither SortOrder fields
I'm working on something EXACTLY like this right now, only my problem is I want to be able to drag/drop table rows.
I've only seen IE only solutions. No good here, so I was going to write my own. Wonder if it's not just easier to build a list like this... and create a new table/row for each list item and just drag/drop that way. Hmmm...
I use a bunch of functionality that uses a hidden iframe as a controller to send URL's back to the server when something is done (like clicking on a delete document link). I'd probably just call an agent with a bunch of parameters identifying the changes to the sort order, so no need for ajax.
Reply
Re: Wither SortOrder fields
Hi Bob,
Just had a quick thought for your problem with the Table row.
Instead of replacing the row itself, why not just swap the contents of the rows around!
Later
Patrick
Reply
Re: Wither SortOrder fields
Bob. Look here http://ajaxscaffold.height1percent.com/ Download the code and look at script.js file. In it the comment states:
// The following is a cross browser way to move around <tr> elements in a <table> or <tbody>
Not tested/tried but it sounds promising.
Jake
Reply
Re: Wither SortOrder fields
Bob/Jake,
Any luck with sorting table rows as I m struggling to implement such a scenario as fields are constructed on the fly using AJAX and DHHTML ?
Jas
Reply
That's the ticket!
That is some cool stuff!!
Reply
Wow!
That's cool! :)
Reply
Problems in IE
A couple of notes. I'm going to look deeper, but I figured I'd pass along what I found. Re-ordering in IE leaves the innerHTML tag set to the red message. If you then perform another drang and drop, it appears to trigger the onComplete as the yellow fade happens, though the entire message is not calculated (the documents are not listed after the message). The script also appears to crash Firefox 1.5. 1.5.0.1 works but does not print out the proper message.
Reply
Re: Problems in IE
It turned out to be something screwy here. I downloaded the app again and re-signed the agent and it works fine. Now I can start picking it apart and learning more from the maestro.
Reply
lotusnotes
very nice
Reply
Do you have a later version
I noticed that you upgraded the code at one time. Is this still the method you use for drag and drop sorting of documents?
Have you or anyone implemented this with a categorized view?
Reply
Re: Do you have a later version
Hi Tanny,
Yes, this is still what I use and recommend.
Adding it to a categorised view might not be easy.
It would depend if you want to drag items from one category to another?
Jake
Reply
Show the rest of this thread
Window scrolling when dragging
Currently the code does not allow the user to drag a news item below the bottom of the browser window if the body is scrolled. To fix that change the code at the bottom of the page from:
Sortable.create('NewOrder', {onUpdate:updateOrder})
To:
Sortable.create('NewOrder', {scroll:window,onUpdate:updateOrder})
This will allow the window to scroll while the user drags a news item to the non-visible area of the page.
Reply
Can this sort technique be used for a view that has been imbedded in a subform?
Reply
The technique should apply anywhere - no matter whether it's on a subform or not.
Reply
Show the rest of this thread