Saving a reordered list
Update 05/11: version 0.2 of the DHTML Library has a helper function to “serialize” the order of a list:
ToolMan.junkdrawer().serializeList(myList)
It returns a string representation of the list as described in the remainder of this post.
Tim Erfle and several others have asked a question like the following:
Is there anyway to report the order of the list after it has been sorted by the user? Its a super cool script, but it would be helpful if store the user modified order in the database.
Because the sorting is done by rearranging elements in the DOM, all you have to do is iterate over the parent element’s children to extract the new order. For example:
function foo(listID) {
var list = document.getElementById(listID);
var items = list.getElementsByTagName("li");
var itemsString = "";
for (var i = 0; i < items.length; i++) {
if (itemsString.length > 0) itemsString += ":";
itemsString += items[i].innerHTML;
}
alert(itemsString);
}
To use this in a form submit replace alert(itemsString) with something like myHiddenInput.value = itemsString. Or you could stuff itemsString in a cookie or pass it back to the server with XMLHttpRequest. The above example uses items[i].innerHTML which works fine so long as your list items are plain text. A better approach is to give each LI element a unique identifier. You can use the ID attribute or — if you’re not concerned about valid XHTML — invent a new attribute to use. A list would look something like this:
<ul>
<li listID="325"><a href="...">Copper</a></li>
<li listID="27"><a href="...">Gold</a></li>
<li listID="131"><a href="...">Gold</a></li>
...
</ul>
And use a script like this to extract the order:
function foo(listID, formInput) {
var list = document.getElementById(listID);
var items = list.getElementsByTagName("li");
var itemIDs = "";
for (var i = 0; i < items.length; i++) {
if (itemIDs.length > 0) itemIDs += ":";
itemIDs += items[i].getAttribute("listID");
}
// do something with itemIDs
}
Hi Tim… wonderfull script!, but, i want to see an example using this script in a button saving the order…
The next update to my examples may include an demonstration of saving the order.
The new version of DnD Sortable Lists now demonstrates the technique I described for saving a reordered list. All the example lists remember their order (via cookies).
Hi Tim I’m building a form in PHP and I want to use your wonderful “drag & drop”. My form sends datas in a SQL database.
But I don’t know how save the result of the sort.
Can You help me ?
Thanks for helping
Matt
Matt,
You need to use a hidden HTML input and JavaScript to fill in the serialized version of the list when the form is submitted.
This requires that the user still clicks a “Save” button. If you want the reordered lists saved automatically you need to look at something like Ajax.
Thanks for this answer. Unfortunately I did not succeed in doing what you propose to me.
Is it possible to register the result of the list in a field and then that changes automatically when the user made of the modifications ?
Thanks for helping if you have time.
Matt
Matt,
There are two basic possibilities here. The first step, though, is to write a javascript function that saves a text version of the current order of the elements, like this:
Then choose whether you want to calculate the new order at the end of a drag event (which is probably unnecessary if you’re not using ajax) or just right before you submit the form. If you want it to get calculated before form submission, add an event handler to your tag, as in:
where “myListsId” corresponds to the “id” attribute of the unordered list. You can then explode() the value in PHP into an array, and iterate over the array to save the order.
Ack. Some things were mis-auto-translated there by wordpress.
Sorry the post contained code.
Hi,
This is a very good function. But when I send my request to the database, results of ordered list are not write in the base.
I have no error message with my PHP script.
Someone understands what it is wrong ?
Here is my code.
Javascript function:
My hidden input:
My submit :
My list:
My php script:
I hope it works and that you can help me. The Javascript function have been modified by Antares.
Thanks Matt
Looks like either WordPress or the Markdown plug-in is insisting on backslash escaping things in code blocks. Works fine for posts, but not for comments. Hmm…
I don’t know if I’m too late, but I’m using the tool-man library for reorganising a list in a user specified order. Had to add a little function in the core.js file to do what I wanted, but here’s how it works.
Function added to core.js
writeListOrder : function(id, dest) { var list = ToolMan.junkdrawer().serializeList(document.getElementById(id)) document.getElementById(dest).value = list },Button to save changes: “
As you must have guessed, numeric is my list’s id, while liste is an hidden input field where I write the ordered list.
Each item in my list can be disabled/enabled on the main page with a checkbox named checkbox# where # correspond to an increasing integer to identify each field and is set as the unique id of my item in the database (using a loop to load all the items). Then using PHP to update the table, I do this:
if ($action == "sauvegarder") { $i = -1; $ordre = explode("|", $_POST['liste']); foreach($ordre as $num) { $i += 1; if ($_POST['checkbox'.$num] != 1) { $check = 0; } else { $check = 1; } $sql = "UPDATE artisteici SET ordre='".$i."', actif='".$check."' WHERE numero='".$num."'"; $save = mysql_query($sql) or die(mysql_error()); } }My MySQL table uses a column called order where I enter the order took from the list. Therefore, when my page is loaded (the one the user views), I sort my results using the “order” column. I hope I made myself clear enough, if you have any question be sure to ask.
Hi ! I saw your script it a very nice one.
I am trying to use your script to get the reordered values and save it using PHP.
Could you show me how to do it step by step?
Thanks
Given:
How do I return the li bodies instead of the li ids? That is to say One|Two|Three instead of 1|2|3?
In the above, replace the code sample with this:
I give up, I’m sure you’ll know what I mean.
Hey, I don’t know if I’m too late with this, but I know all the hype is built up around AJAX, but if you guys want a simpler implementation regardless of what server-side language why not just use some simple Remote Calling. There is a beautiful example over at 15 seconds by Rajesh Toleti. http://www.15seconds.com/issue/050922.htm Take a look at that, it’s written in .net, but i was able to write it in standard asp within a few minutes. If anyone needs some help just shoot me an email, alan@alancece.com
I copy the code to my server and everything runs perfectly except the order is not saved. Has anyone else had this problem?
I have tried the other examples posted and continue to get errors on the following line:
var items = list.getElementsByTagName(”li”);
Any help would be appreciated…
I did figure it out somewhat… The save works in IE and not Firefox. I was using Firefox and wasn’t seeing the save happening…
-Greg
I have adapted what has been recommended here to prevent the need for the user to click a form button to make the update. Whenever the user finishes dragging an item, the database is updated. I admit that if the users wants to update every item it will use lots of queries, but at the end of the day, it is nicer for the user!
I needed to let users sort a bunch of links (their favourites on my site), so in the database each favourite had a position stored with it, so I can display the list in the right order without having to the functionality provided by tool-man (and I use these positions to calculate the most popular favourite across all users etc…)
To do this, I edited the ‘dragsort.js’ file, and added a call to a function in the onDragEnd function: _onDragEnd : function(dragEvent) { ToolMan.coordinates().create(0, 0).reposition(dragEvent.group.element) updateDB(); } The function updateDB() creates the string of orders as mentioned above (x|y|z): function updateDB() { var list = document.getElementById(’draggable’); var items = list.getElementsByTagName(’li’); var ids = ‘’; for (var i = 0; i 0) ids += ‘|’; var id = items[i].getAttribute(’heading’); ids += id; } if (document.getElementById(’favorder’).value != ids) { document.getElementById(’jsupdater’).src = ‘/js_tracker.php?updateorder=’ + ids; document.getElementById(’favorder’).value = ids; }
} The function relies on there being a hidden input field named favorder, and the UL has id=”draggable”. Also, an image with 0px width and height, and id is “js_updater”. This is purely relevant for my site, and could be generalised by passing in IDs…
So, when the order of the list is changed, the picture’s source is changed to /js_tracker.php?updateorder=x|y|z
The jstracker file is a PHP script that interfaces with the database: $order = explode(”|”, $GET[updateorder]); if (strlen($order[0]) > 0) { foreach ($order as $position => $id) { $position++; mysql_query(”UPDATE SET position = $position WHERE = $id”); } }
Hope this helps someone!
Hi, I am looking for using this concept in my web site. But the different thing is that i am not using “li” but i have “div’s” and in these “div’s” i have multiple table’s. I need to shuffle these “div’s” and not the tables. Then i need to store the name of the div’s and there current order in DB and when the page loads next time i want that after retreving the order of div’s from DB i should be able to render it on the page. the table’s in each “div” contains data that is generated dynamically. Can anyone help me on this?
Thanks
Hi, Please mail me the solution of above query at sachin316@yahoo.com
Thanks
Hi, The ID is “sachin316@yahoo.com”
Thanks,
Hello. I was wondering if you would be interested in working with me in order to enhance your software to add the functionality to be able to drag items into sub categories. I’ve been working on it, it seems tough, and am seeking assistance. What I mean is instead of inserting before or after, you’d be inserting inside a new element. For the most part I have alot of it down, but its extremely buggy.
Let me know if you’re interested. I’m posting this where ever I can find an input box so you can see it.
If all you want is to save the order when a form is submitted, put a hidden input field inside the list item itself.
Now there’s no Javascript or non-standard HTML. Just post the form; the countryCodes will be posted in the order in which you left them.
Patrick
Hi, first time caller long time listener.
I’d like to say I am a big fan of the tool-man script, absolutely bang-up job.
That being said I would like to ask a question about the ordering and arrangement of the 2d lists and I was hoping that you could answer it for me.
Given that the example arranges the elements left to right top to bottom, like so…
1 2 3 4 5 6 7 8 9
Is it possible to arrange the list top to bottom left to right like this?
1 4 7 2 5 8 3 6 9
I know by changing the float property to right I can arrange it like this…
3 2 1 6 5 4 9 8 7
But I don’t think that CSS any other defined floats (except for none).
Secondly I noticed that the lists always snap to the RHS of any table cell they are in is there away to center them?
Thank you for your time, I hope my questions are not to elementary. Once again big fan.
SF
Using matt55’s example code shown on 5/13/2005, I got the same results… Only I changed the hidden input field name to match from q2 to q1.
Like grguth on 3/23/2006, it works fine in Internet Explorer, but fails in Firefox.
Any Ideas? I’m running Firefox 1.5.0.6…
Thanks,
-Ghost
My problem is that when I use a hidden input field to send the data to PHP, it works in IE, but not in Firefox.
I’m using the following code:
function saveOrderList(listId) { var list = document.getElementById(listId); var items = list.getElementsByTagName(’li’); var ids = ‘’; var hiddeninput = document.getElementById(’listarray’); // the input field storing the order
}
bravo charlie delta echo foxtrot golf hotel india juliet kilo lima mike november oscar papa quebec romeo sierra tango uniform victor whiskey xray yankee zulu
The form submits to:
\n”; ?>
Internet Explorer v6.0.2900 displays: hidden value: o|b|c|d|g|i|j|k|l|m|w|y|t|x|z|s|p|h|n|q|v|f|u|a|e|r
While Firefox v1.5.0.6 displays: hidden value:
Any help would be greatly appreciated.
Opps, my code example got trashed…
My problem is that when I use a hidden input field to send the data to PHP, it works in IE, but not in Firefox.
I’m using the following code:
The form submits to:
Internet Explorer v6.0.2900 displays: hidden value: o|b|c|d|g|i|j|k|l|m|w|y|t|x|z|s|p|h|n|q|v|f|u|a|e|r
While Firefox v1.5.0.6 displays: hidden value:
I would really appreciate any help you can provide…
Try this one. It work both FF & IE….
Javascript Function :
function post(){ list_var = junkdrawer.serializeList(phoneticlong) document.order2.order.value = list_var order2.submit() }In Body : `
apple bud clock down extra
`
In reorder.php :
"; for($x=0;$x"; } ?>Hope it help…
Thanks
Duh! Click Here! =)
I have applied some of the information found here to try saving locations of entire moving divs (not restricted to lists). The method was quite successful. Here are the basics in case you’re interested:
This is all that is required to save the boxHandle location to a text file. Every time a user moves a box, the new location is saved transparently.
To load the information: 1. When the main page is loaded or refreshed, php code in the header downloads the data from the text file and deserializes it. 2. In the body of the document, php code inserts the deserialized data in another invisible form field.
3. The javascript ‘window.onload’ event is used to get the string from the invisible form element and the ‘document.control.loadedLocations.value.split(”,”)’ method is used to transform it back into an array. 4. The array is then used to set the ’style.left’ and ’style.top’ properties of the box.
The use of an array allows to have as many boxes as you like (only limited by size of xmlhttp query). This is the first time that I use javascript so this might not be the best way to do things (but it works!).
Hello oto,
I’ve been racking my brain for 2 weeks trying to figure out what you’ve just accomplished … impressive …
If i’m reading your comments accuratly, youve managed to capture the positions of the dragged elements and save these positions to file …
Question … would you be so kind as to provide me with a working sample of what youve just done? At this point I’m willing to donate a few bucks to save myself more time. (Please!)
Thanks in advance …
Respectfully,
Chris chrisATintensivexDOTcom
Sure, no problem. I’d rather not publish it on this blog. Email me mark@otomotion.com
Mark
I’ve integrated the code into something I’m working on and it works quite nicely, the only trouble is that I’ve got a button which will add a new item to the bottom of the list. How do I get new item to register and update the constraints?
I’ve tried and tried, but either the new item doesn’t work, or I get the new item working and the other items break.
Any chance of a “rehash()” or “addNew()” function?
I would like to user your simplest one, two, three list reordering. For newbies, would it be possible for you to create a page with just this example and the code it uses.
Your examples are very impressive, but having them all in one file makes it a little harder to get started.
Thanks
I have a problem at http://research.psychol.cam.ac.uk/~kl278/experiments/recruitment.php under the heading Favourite Foods : I’m using the script to sort a list of items by drag and drop and it works fine on its own.
The issue arises when I wish to submit the data in the listboxes and textboxes within the sortable list to a MySQL database to be recorded. Namely, the data that client enters into these listboxes and textboxes are passed through only for those entries that are not sorted within the list by drag and drop i.e. as soon as the user has drag and dropped one of the items, the data user has entered is not recorded in the database for that item - and it doesn’t matter whether the user enters the data before or after the drag and drop. And to be more specific, the data is actually recorded if you just move the list item around on spot (without dragging it across any items), but as soon as you move it across, even without release (drop) and come back to the original location, data is not recorded. In other words it seems that the ‘drag across’ event in the sortable list script seems to erase the user input or seems unable to pass it through form submit … I hope this description is understandable. How do I get all data to pass through, irrespective of how much the user sorts the list ?
Many thanks !
p.s. I’m using Form Tools to record the submitted data in my MySQL database (http://www.formtools.org/) and I believe there should be no problems on that side.
[…] streamofconsciousness » Saving a reordered list […]
Hello. I have a question that I would really like help on. I’m trying to understand how you do the repositioning - it seems you use relative position for the list items, but is the table absolutely positioned? I would ideally like to make lists sortable with no other information than the relative positions of the list elements, but I find that when I drag the elements the mouse cursor jumps off the element and also the whole table moves to compensate for the moving element….
Guys I found solution to the problem where it doesnt work in Firefox but works in IE
in this change to
For more details: http://www.webdeveloper.com/forum/showthread.php?p=907759#post907759
Enjoy!!
hi Matt55,
several things in your code are wrong.
a) Your javascript tries to get the wrong id. Relating to your hidden input form field it must be q1 NOT q2 b) Your javascript cannot get the id, because the hidden input form field has none. Just add id=”q1″ to that form field
Instead of itemID as an attribute I would rather use title as attribute, because this is an allowed attribute.
Works for me!
HTH
Hi, I am facing issue where I am using this script and trying to put combo box inside block. My page need that combo box to let user pick some option and each block has combo box. Problem with safari is when I put this combo box inside the box, combo box is not clickable now. Users can’t pick any options from combo box.
Is there any fix for this?
-Shalin
hi, I am trying to use drop down box and place it in to sortable list. But when I do that drop down control does not work in safari and users can’t select any options from drop down.
Is there workaround for this problem?
This is a most excellent script. But I was playing around with your version 0.2 here, and though it works great in Chrome and FF, it gives an error in IE when you release the mouse button. Here’s what I get:
Invalid argument. drag.js, Line 122, Char 4
Of course, IE has horrible debugging, so this message probably doesn’t help any (didn’t help me). Any ideas what’s causing this error? I’m using IE8 (both with and without compatibility enabled.
Thanks!
I’m having the same problem with IE8. I LOVE this script! It’s incredible!! Are there any fixes available or could someone point me in the right direction?
Thanks!!
Hello your scripts works fine
I have a question : I try to make a dynamic sorting drag and drop list who can be refresh with ajax or a simple document.getElementById(’myid’).innerHTML like :
refresh works.
But the elements of the of the list are not draggable after …
Could you help me please ?
Thanks
HI guys I have been using this script for a couple years now on a social network site and I really don’t want to change to another script. Users on my site have “friends” and this script is used to allow them to save there “top” friends in the order they like. I have a drop down form where they can pick the number of top friends they like for instance “12″ in firefox this highlights 12 of the table cells to make them a different color, also there is a form to save this order the output is saved in mysql like this 1|2|3|4|5 and also the form submits the number 4, 8, OR 12 from the dropdown selector for quanity of top friends, also sould not if I pick 12 then out of hundreds of draggable friends, the script knows to only save the first 12 or whichever number is picked.
1 issue is in google chrome and internet explorer, the top 12 are no longer highlighted with a different color, this only works in firefox now however, in IE and chrome the 12 even though not highlighted the script still functions correctly
2nd issue, instead of hitting a save button that submits these 2 fields myTopFriends and topNumber to my php script which updates mysql, I would really like to make this work with a simple ajax call to submit these automaticly after moving a top friends, I know where to put such code at on mouse up or whatever but I can not figure out which code to use, I saw in the comments above where a guy said he used ajax, I tried his posted method but it does not work for me, any help greatly appreciated
Currently my version has a form that allo
I really need to make this script update using AJAX I would really appreciate if anyone can do that I can pay for this hack
Hi all,
To fix the issue with IE8 replace line 122 of drag.cs (dragEvent.group.element.style.zIndex = originalZIndex) with: dragEvent.group.element.style.zIndex = ‘auto’
I am not sure what downstream effect this will have, and I guess this depends on your implementation. It does fix my issue with IE8.
Can anyone elaborate on the reason for the zIndex being set to the originalZIndex? Is there an instance when it will not be auto?
Thanks.