Using MooTools 1.2 For Drag, Drop, Sort, Save
This post has been updated: Using jQuery or MooTools For Drag, Drop, Sort, Save. The code on this page is no longer best practice.
The following is a repost of an article that ran on Script & Style a few months ago....
My customers love being able to control their website's content so I build a lot of administrative control into their website. One administrative control I frequently build is a News control. I allow the customer to add, edit, delete, and sort news items. My customers especially love sorting their articles because of the fashion of which they can sort: drag and drop. Here's how I do it.
The MySQL Table
id | title | sort_order |
---|---|---|
1 | Article 1 | 1 |
2 | Article 2 | 2 |
3 | Article 3 | 3 |
4 | Article 4 | 4 |
5 | Article 5 | 5 |
6 | Article 6 | 6 |
My news table contains more fields but these are the important fields per this example.
The PHP / XHTML
<?php <div id="message-box"><?php echo $message; ?> Waiting for sortation submission...</div> <form id="dd-form" action="<?php echo $_SERVER['REQUEST_URI']; ?>" method="post"> <p><input type="checkbox" value="1" name="auto_submit" id="auto_submit" <?php if($_POST['auto_submit']) { echo 'checked="checked"'; } ?> /> <label for="auto_submit">Automatically submit on drop event</label></p> <ul id="sortable-list"> <?php $sort_order = array(); while($item = mysql_fetch_assoc($result)) { echo '<li class="sortme" alt="',$item['id'],'">',$item['title'],'</li>'; $sort_order[] = $item['sort_order']; } ?> </ul> <br /> <input type="hidden" name="sort_order" id="sort_order" value="<?php echo implode($sort_order,'|'); ?>" /> <input type="submit" name="do_submit" value="Submit Sortation" class="button" /> </form> <?php } else { ?> <p>Sorry! There are no items in the system.</p> <?php } ?>
We query the database to get every news item. What's extremely important is that the query sorts the items by their original sort order. We set the "rel" attribute equal to the article's ID and the list item's text to the article title.
The CSS
#sortable-list { padding:0; } li.sortme { padding:4px 8px; color:#000; cursor:move; list-style:none; width:500px; background:#ddd; margin:10px 0; border:1px solid #999; } #message-box { background:#fffea1; border:2px solid #fc0; padding:4px 8px; margin:0 0 14px 0; width:500px; }
I use the above CSS to format the news items so that the customer knows each news item may be dragged. None of the CSS is essential to this system.
The MooTools JavaScript
/* when the DOM is ready */ /* create sortables */ var sb = new Sortables('sortable-list', { /* set options */ clone:true, revert: true, /* initialization stuff here */ initialize: function() { }, /* once an item is selected */ onStart: function(el) { el.setStyle('background','#add8e6'); }, /* when a drag is complete */ onComplete: function(el) { el.setStyle('background','#ddd'); //build a string of the order var sort_order = ''; $$('#sortable-list li').each(function(li) { sort_order = sort_order + li.get('alt') + '|'; }); $('sort_order').value = sort_order; //autosubmit if the checkbox says to if($('auto_submit').checked) { //do an ajax request var req = new Request({ url:'', method:'post', autoCancel:true, data:'sort_order=' + sort_order + '&ajax=' + $('auto_submit').checked + '&do_submit=1&byajax=1', onRequest: function() { $('message-box').set('text','Updating the sort order in the database.'); }, onSuccess: function() { $('message-box').set('text','Database has been updated.'); } }).send(); } } }); });
We use Moo 1.2's Sortables plugin class to select all element within the list and make them sortable (drag and drop). Every time the sort order is changed, the hidden sort_order element is built and reset using a "|" as a separator. If the checkbox is checked, an ajax call is made to update the sort order in the database. Otherwise, the regular form submission via submit button will also save the sortation.
The "Header" PHP / MySQL
/* on form submission */ if(isset($_POST['do_submit'])) { /* split the value of the sortation */ $ids = explode('|',$_POST['sort_order']); /* run the update query for each id */ foreach($ids as $index=>$id) { if($id != '') { $query = 'UPDATE test_table SET sort_order = '.$index.' WHERE id = '.$id; $result = mysql_query($query,$connection) or die(mysql_error().': '.$query); } } /* now what? */ if($_POST['byajax']) { die(); } else { $message = 'Sortation has been saved.'; } }
The header is where the new sort order is committed. We split the sort_order form value by the "|" and perform a query for each item to update its order. Lastly, if the byajax flag is sent, we just die out the PHP script -- if not, we continue to load the page.
Hot system, right? Dragging and dropping is by far the fastest way to sort a list of items. What are your thoughts? Have any ideas for improvements?
On FF3 the dragging animation is slow and not fluid…
@nulll: Works for me.
FF 3.0.4 – works fine.
Don’t have time to go trough the whole post now, but the final example looks nice ;)
Wouldn’t it be an idea to use an ordered list, so you can use the alt property for an ID? IMHO, that’d make it even more useful.
Argh, nevermind. Misread what the alt field was already used for.
Nice example, but isn’t it easier to use the native ‘serialize‘ function from the Sortables class onComplete?
Works somehow, had another sort of SQL connection so had to remove the $connection in ($query, $connection) but weird thing, say I drag ‘6’ to position ‘1’ and then submit it jumps back to its former position, after that when I do it for the second time, it updates to my DB. Whats wrong? :p
@null: Sometimes Firefox leaks memory if you have it open for too long or if you have way too many tabs open. Not sure what your computer configuration is like but perhaps there isn’t enough memory available when you’re running Firefox and trying to use drag & drop examples. But this work of art works really well! I’ve combined David’s work with some of my PHP.MySQL apps and the drag&drop sorting makes for a very great app! Cheers!
With Opera works fine but with my up to date FF 3.0 on Kubuntu 8.04 is not fluid while dragging the objects…even on a new fresh launched istance of FF
Hey nice effect, thanks ;)
How can I use this if I have multiple users in a system, and I want to let them create their own list using this sorting method. I have a table called “users” with columns id, email, username and password. Is it possible to attach a “sort_list” to every email in my system?
Thanks in advance!
Thanks! Great post..
What if I want to implement more than just one list?
I have a site with a number of users, and each of these should be able to create their own list, from data from the same database.
I have a table called “users” with columns; id, username, email, password. I have a table called “sources” with columns; id, name, rss. These users should be able to make their own list out of those data from the “sources”-table.
Is it possible to throw the sort_order in a columns in the “users”-tables, so that it says 1,1|6,2|7,3|13,4 .. id 1 from sources should be placed as #1 on the list, id 6 from sources should be placed as #2 on the list, id 7 from sources should be placed as #3 etc.
Very nice!!! I’ve been looking for something exactly like this. Kudos, mate!
Sweet, you made this much quicker for me.
My sortables also have ajax requests in a click event. Even if I didn’t drag, simply clicking caused the onComplete of the sortables to fire, so I was constantly requesting the sorting script even when I wasn’t sorting.
I added a variable
sorted = false
. Then put in:then in my
onComplete
I put:@rpflo: would you be willing to share you code? I am looking to use the code in this example to submit an form via ajax when there has been a change to any of the form’s input fields. I have been experimenting with different scripts but am having a difficult time figuring out how to do an ‘onChange’ type of deal versus an ‘onClick.’ I also tried the periodical stuff but I don’t want to constantly send the form via ajax…I only need the forms submitted when there’s been a change.
@Hugo
Here’s my code, but reading your question I’m not sure it has anything to do with this!
Feel free to click my name to visit my site and get a hold of me.
Basically I’ve got a click event on the same li’s as my sortables. When I simply clicked them I’d get two requests: the click event request (which I wanted) and the request to re-sort them (which I didn’t want unless I actually resorted them).
Hi David! There’s any way to sort the list when I read the data from the database?
I save all the div positions into a database, now I want to create a form with that order.
Thanks in advanced.
@John
In your table you should have a field called ‘sort_order’. In your select query write:
$$query = “SELECT stuff FROM yourTable ORDER BY sort_order ASC”;
@rpflo yes, I have something like that in my db, but this is my problem: I’m using this to sort colors, the people can drag & drop colors and save into a database under his user, but when they try to edit I need to put all the colors in the same order than they save. There’s an option in the javascript code to set those values from the db? Something like an “initial order”
Thanks in advanced.
@John
I’m lost … If you’re saying you need two orders, have two fields, sort_order and edit_order.
But again, I’m lost. Not sure why you’d want to allow somebody to sort things like this and then not want it to sort?
This demo looks really cool, I’ve been looking for something like this (physically available) for a while.
As an aside, have you seen the Great Big Massive demo? The guy claims to use mootools aswell and his demos show it inserting objects before, after and EVEN swapping. Looks ace, I tried to get his code but he says its secret until release. Pffft :(
Worth a look! –> http://www.youtube.com/watch?v=pvvmqP89lb8
If you get any code, gimme some :D~~~
Hey David, this is really cool, i am new at javascript libraries, so i have problem with this tutorial, cause i don’t know which Moo-Tools library to include.
I checked their website and the Sortables class is contained in the …more.js plugin and addEvent method is in the core, so how i can include all of the used classes and methods into one js file. I tried including both, the more and the core, but it doesn’t work for me…
Thank you in advance.
Cheers!!!
No need of replay, i got it work, thanks anyway…
I think seriously to start using MooTools over others libraries, maybe include Jquery too.
Hey David, again me… I remade your task here, so you can drag and drop the items and the order gets updated in the hidden input and when the user is ready, i added a button to update the database via ajax. I am using bit of OOP PHP to print the list dynamic on each update. I was wondering if i could post it here, cause i was looking for something similar online, but never found it, so if someone finds it useful can take it from here.
If anybody wants the zip file, you can email me at u4zoran2002@yahoo.com
Thanks again for this useful example David.
I implemented this into a project I’ve been working on, works great, but after reading…
“In keeping with our new pledge to release more often, we’ve been working hard lately to get 1.2.1 ready for release, and we’re finally happy with it. This release brings a ton of bug fixes, and is a drop in replacement for 1.2.0. (That’s right, no breaking changes!”) I decided to test it, well, it breaks. Any ideas?
Is there a way to save the modifications into a cookie set by mootools (hash.cookie)?
How can we do it with your piece of code?
Thanks a lot!
Hi there,
I’m kinda new in this kind of stuff!! Never the less, i’ve managed to create a sortable div structure with your script. You can see it when you click on my website… (http://www.unikoop.into-cms.nl/into-cms/frontpage/index.php?dragable=true). The left column works like a charm (no update in a database yet, but that will come later on). My main question here is, can I use several sortables on one page similar like the one i’ve created? I want the user to create the order by replacing the items. So the order of all the columns on the site needs to be sortable. Is this possible with this script? Or is there an other script that can handle something like this. I’ve searched the web for all kinds of solutions, but your script was the one that answered my needs for this site…
I hope to here from you soon!!
Greets,
Douwe
I can’t figure out how to ‘plugin’ my db within the PHP above… as in i’m not seeing how above, the PHP knows what db to get the table info from! Doesn’t the php need to address (username/pwd)?
hi all., Do you know what is this line for? specially this php code “”
“<input type=”hidden” name=”sort_order” id=”sort_order” value=”” />”
Co’z im using Smarty and Php.,
thanks you all!
its really good but can u please help me
i find it not working when i put mootools-core-1.2 with it
Can we use this to swap instead sorting?
Great post indeed!
I’ve built facebook like photo order sorting stuffs by using this example – you can see the details here
http://kodegeek.wordpress.com/2009/07/22/facebook-like-photo-order-sorting-in-mootools/
Thnx David!
David,
Do you have any suggestions for nested sortables? I am going insane!
@ Jumanji
It is putting turning the array of integers into a pipe delimited string. You should assign that string value to smarty and output it instead.
Hi! Awesome piece of code. I’m not a php/ajax pro, so this is giving me a headache: I have a list of items order from 1 to infinite, but the system keeps updating the order giving 0 to the first element. How can I modify the script to start in 1 ??
Thanks a lot!
Great code,
Already implemented it.
However, i have found a problem maybe you can help me with this.
If you add a text input inside the LI tag in Firefox you wont be able to change ths value of it, in IE6 it can be done.
I tried to add an event on every textbox so when the user clicks on it it selects all the text inside it, but this is not happening.
I guess some code from the Sortables class is preventing firing the event.
Regards,
Alex
Can you write a version that is using jquery? Looking forward to your next awesome tutorial. You are my javascript teacher, thank you, arigatogozaimasu, kamsahamdina :)
is this compatible with 1.2.3
I’m having no luck, then again I could be missing something besides fixing the $, $$ issue
i don’t think its compatible with 1.2.1 – 1.2.3 actually
on FF3 works like a charm for me…
@BG
They are talking about the MooTools version number, not a browser.
Can someone upoad a folder where all the Demofiles are in? With : The PHP / XHTML, The CSS, The MooTools Javascript…
I too have had no luck getting this code to work, and it seems to have nothing to do with mootools, and something with the php? perhaps its something I’m missing with
I query the database? Seems very useful though, something I’ve been trying to solve for a while. Posting the files would be of great help.
-bay
I too have had no luck getting this code to work, and it seems to have nothing to do with mootools, and something with the php? perhaps its something I’m missing with
I query the database? Seems very useful though, something I’ve been trying to solve for a while.
-bay
Man, you just don’t check ANYTHING in IE, do you?
I appreciate your resources… however… don’t pollute the web with half working scripts.
John Doish: Works for me in IE6, IE7, and IE8. How fitting that your last name is so close to “douche”!
David, didn’t you make this post back in your unenlightened Windows/IE days anyway? Your screenshot reeks of windows font rendering.
I’ve used this code in many of my projects. Are you sure it works in IE 8, with compatibility view off? For me (using your demo) it loses the sortable item’s container styling when dragging. It would be great if there was a workaround for that.
Hey, I figured out why styling is lost when dragging in IE 8. The problem is with css, so I changed following style
li.sortme{ padding:4px 8px; color:#000; cursor:move; list-style:none; width:500px; background:#ddd; margin:10px 0; border:1px solid #999; }
to
#sortable-list li{ padding:4px 8px; color:#000; cursor:move; list-style:none; width:500px; background:#ddd; margin:10px 0; border:1px solid #999; }
It worked for me with compatibility view on/off.
Alexander said: “If you add a text input inside the LI tag in Firefox you wont be able to change ths value of it, in IE6 it can be done.”
Having the same problem, anyone knows how to fix it ?
Is there anyone who can help me getting this worked with 2 columns…. I can’t get it worked….?
Please contact me, thanks A LOT!!
it isnt let me drag!
can you give a full page, not slices?
thank you
@Chris: did you find the reason for the missbehaviour thats every thing works fine only after the second time?
It should be great if you tell us what components are included in the “more” library, so that we can rebuild it
Hi,
thanks to David for the code :)
For who have to use input text inside sortable item, use handle option:
var mySortables = new Sortables(‘#list-1, #list-2′, {
constrain: true,
clone: false,
revert: true,
handle:’whatever’
});
– handle – (string: defaults to false) A selector to select an element inside each sortable item to be used as the handle for sorting that item. If no match is found, the element is used as its own handle.
bye
Somebody please help me
i get the error
Notice: Undefined variable: message in sort-save.php on line 185
Waiting for sortation submission…
while the coding on that line is
Waiting for sortation submission…
Thanx
Waiting for sortation submission…
@Faiz: Waiting for sortation submission…
the coding is in div message box.. when am pasting it here its not showin in the comments.. sorry for the duplicate lines.. plz help
Thank you very much for the tutorial, this helped me a lot and saved some time :)
@Faiz: try wrapping changing the echo $message to if(isset($message)){echo $message; }
I appreciate the tutorial. I’m wondering: how do you customize this for each visitor?
Right now if I sort something, it gets saved to the database, but this ‘sortation’ is then applied for all users who view it. In your opinion, what would be a suitable way to make it so that for each user they see their own custom sorting?
great tutorial. but i have one problem, I was implementing drag/drop to one new project. and the problem occurs when drag a element from main view and drop it to a div that has fixed position on the bottom of browser’s window. All elements that are not behind the fixed div could be dropped on this div, any other elements that need to use browser’s scroll bar to view couldn’t be dropped. The draggable element that behind the fixed div somehow ignores the div as drop zone.
the problem only occurs when using fixed position
Any ideas?
Hi Guys,
Wondered if I could get a little help. I just cannot get this code to update the database. Infact I cannot get it to interact with the
url
location at all.I use a piece of Ajax on the page before thats works fine
BUT the code on this page appears to work as the list sorts when I drag and drop it, it states that the database has been updated by the
onSuccess
function, but it appears to not interact with the controller/action. I cant understand how it reports success when its obviously not succeeding.A bit of a headache this!
Many thanks
Mark
Hi David,
Sorry to bug you in the middle of the gunners game – when you get a moment could you let me know if your moo sortables script can be used for a dynamic amount of UL’s
and if so, would you have a small implementation of it as I just can’t get any more than the first
any help would be v.greatfuly appreciated.
pSouper
Is there any way to get the browser to scroll with this? I’m using it to sort a gallery and when there are more thumbnails than will fit on the screen, I need the browser to automatically scroll when dragging the thumbnail. Thanks!
That pretty much explains the logic behind all the pieces of this Sortable List example. I know it’s not very flashy, but the purpose of this example was to illustrate some of the cool things that can be done with a Sortable List and when they will be executed.
Can please someone explain how to create the correct MySql Table?
Thanks !!
for this example it simply needs a table called “test_table” with two fields:
id
andsort_order
Hi David! I have problem on using mootools on my site – it destroys my layout. Is it because I also run jquery?
Hi Dave
Im really sorry to bother you but i could really do with your help.
Im trying to make a simple list sortable by drap and drop but the darn thing wont work for me.
If you could help me out i would be very grateful as it has held me up the last few days.
I can send you my index file if you can help me out.
I have used this
http://jqueryui.com/demos/sortable/
but it wont work for me :-(
Much appreciated
Ken
Great example,
@redmike if you use both of jQuery and MooTools, you have to use
jQuery.noConflict
and wrap your jQuery code in