Mootools 1.2 Sortables
If you haven’t already, be sure and check out the rest of the Mootools 1.2 tutorials in our 30 days series.
Today we are going to look at another of the bundled plugins from the “more” library. Sortables is a very powerful plugin and can really open up the options with your user interface designs. The sortables also include a great function called “serialize” that will output and array of the list element ids – great for integrating with server side scripting. Read on to learn how to create a new set of sortable items, and be sure to check out the live demo at the end.
The Basics
Creating a New Sortable Object
First, we are going to send our elements over to variables. For sortables, if you want multiple lists to have the potential to drag and drop list items between them, you are going to want to put all the lists inside an array like so:
var sortableListsArray = $$('#listA, #listB');
This places the ids of two uls into an array. We can now create a new sortable object from this array:
var sortableLists = new Sortables(sortableListsArray);
If we use the following html
<ul id="listA"> <li>Item A1</li> <li>Item A2</li> <li>Item A3</li> <li>Item A4</li> </ul> <ul id="listB"> <li>Item B1</li> <li>Item B2</li <li>Item B3</li> <li>Item B4</li> </ul>
then our sortable lists would come out looking something like this:
- Item A1
- Item A2
- Item A3
- Item A4
- Item B1
- Item B2
- Item B3
- Item B4
Sortables Options
If want to customize the functionality of your sortable list, you are going to need to tweak the options.
constrain
default – false
This option will determine whether your sortable list elements can jump between uls within the sortable object. For example, if you have two uls in the sortable object, you can “constrain” the list items to their parent ul by setting “constrain: true.”
var sortableLists = new Sortables(sortableListsArray, { constrain: false //false is default });
clone
default – false
Clone lets you add a “clone” element that will stay under your cursor when you sort, leaving the original element in place. Check out the example below to see a clone.
var sortableLists = new Sortables(sortableListsArray, { clone: true //false is default });
handle
default – false
Handle will accept an element to act as the drag handle. This is very handy if you want to keep the text in your list items selectable or you want other actions within the li. The default (false) will make the sortable element (the li) the drag handle.
var handleElements = $$('.handlesClass'); var sortableLists = new Sortables(sortableListsArray, { handle: handleElements //false is default });
opacity
default – 1
Opacity lets you adjust the sort element. If you use a clone, opacity affects the element that sorts, not the element that follows your cursor.
var sortableLists = new Sortables(sortableListsArray, { opacity: 1 //default is 1 });
revert
default – false
Revert will accept either “false” or Fx options. If you set Fx options within revert, it will create an effect for the sorted element to settle into place. For example, you could set “duration: long” and the clone would take its time to go back to its place in the list when you let go. To see revert in action, check out example below
var sortableLists = new Sortables(sortableListsArray, { revert: false //this is the default }); //you can also set Fx options var sortableLists = new Sortables(sortableListsArray, { revert: { duration: 50 } });
snap
default – 4
Snap lets you set how many px the user will drag the mouse before the element starts following.
var sortableLists = new Sortables(sortableListsArray, { snap: 10 //user will have to drag 10 px to start the list sorting });
Sortable Events
The sortable events are nice and straightforward. Each will pass the element being sorted (not the clone you are dragging, if you are using clone).
- onStart – fires when the drag starts (once snap kicks over)
- onSort – fires when the items change order
- onComplete – fires when you drop an element in place
We will check out the events in more detail (and you can see them in action) in the example below.
Sortable Methods
We haven’t talked specifically about methods before, though we have used them plenty of times. Methods are essentially functions that belong to classes. While classes are a subject for another day, let’s take a quick second to establish a general idea. This plugin (and the others we have looked at), all follow a similar pattern – initiate a “new” instance of the plugin, define one or more selector parameters, define your options, add some events and just like that you have a new sortable or tween. That pattern is the basis of a class. A class basically allows you to store options and functions to use over again. Methods are specific functions that exist within and add functionality of a given class. .set() and .get() for instance, are Methods that extend the element property. Within the Fx.Tween, .start() is a method. To get a better idea, let’s take a look over the sortable methods:
.detach();
With .detach();, you can “detach” all the current handles, making the entire list object not sortable. Useful for disabling sort.
.attach();
This method will “attach” the handles to the sort items, works to enable sorting after .detach();.
.addItems();
This allows you to add new items to your sortable list. Let’s say that you have a sortable list where the user can add a new item, once you add that new item, you will need to enable sorting on that new item.
.removeItems();
This method lets you remove the sorting capability of an item within a sortable list. This is useful when you want to lock a particular item within a specific list and not let it sort with others.
.addLists();
Instead of just adding a new item to an existing list, you may want to add a whole new list to the sortable object. .addLists(); even lets you add multiple lists, making it really easy to add more sortables.
.removeLists();
Lets you remove entire lists from the sortable object. This is useful for when you want to lock a particular list in place. You can remove the list, leaving another lists still in the object sortable, but locking the content of the removed list.
.serialize();
All of that sorting is great, but what if you want to do something with the data? .serialize(); will return a list of the item ids as well as their order on the list. You can choose which list to get data from with in the object by index number.
There are much bigger implications to methods than we are covering here, but let this serve as a introduction to the concept if it’s new, and we will get deeper into methods and classes in a later tutorial.
Example
The following example uses several options, all the events and all the methods described above. Hopefully the code will speak for itself, but refer to the comments for further info. Remember, everything below needs to go inside the domready event.
var sortableListsArray = $$('#numberlist, #letterlist'); var sortableLists = new Sortables(sortableListsArray, { //creates a clone to follow my cursor when i drag clone: true, //defines the class of the drag handle handle: '.handle', //will let you create an effect for the //item returning to list after drag revert: { //accepts Fx options duration: 50 }, //determines opacity of list element, not drag clone opacity: .5, onStart: function(el){ //passes element you are dragging $('start_ind').highlight('#F3F865'); el.highlight('#F3F865'); }, onSort: function(el) { //passes element you are dragging $('sort_ind').highlight('#F3F865'); }, onComplete: function(el) { //passes element you are dragging $('complete_ind').highlight('#F3F865'); var listOne = sortableLists.serialize(0); var listTwo = sortableLists.serialize(1); $('numberOrder').set('text', listOne).highlight('#F3F865'); ; $('letterOrder').set('text', listTwo).highlight('#F3F865'); ; } }).detach(); //disables the handles, so you must push the button to get them going var addListoSort = $('addListTest'); $('addListButton').addEvent('click', function(){ sortableLists.addLists(addListoSort); }); $('removeListButton').addEvent('click', function(){ sortableLists.removeLists(addListoSort); }); $('enable_handles').addEvent('click', function(){ sortableLists.attach(); }); $('disable_handles').addEvent('click', function(){ sortableLists.detach(); }); var itemOne = $('one'); $('add_item').addEvent('click', function(){ sortableLists.addItems(itemOne); }); $('remove_item').addEvent('click', function(){ sortableLists.removeItems(itemOne); });
The handles are not enabled by default (take a close look over the code). To start sorting, you will need to “enable handles.”
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- A
- B
- C
- D
- E
- F
- G
- add A
- add B
- add C
- add D
- add E
- add F
- add G
To Learn More…
Check out the docs entry about sortable lists.
Download a zip of everything you need to get started
Including the example above, an external javascript file, a css style sheet, a simple html file and the Mootools 1.2 core and more libraries.
Tomorrow’s Tutorial
Check out Day 17 where we will explore the accordion plugin
Questions, Comments, Suggestions
Please drop us a note if you have any questions or if you have anything to add to this tutorial. Thanks and hope you find it useful.
Tags: 30 days of mootools, javascript, Mootools 1.2, sortables plugin, tutorials
Is there any way to make the sortable list work in a hierarchy, as would be needed for sorting files and folders?
There are a few out there, not sure if anything is out for 1.2 yet. You can check out how it is done here:
http://www.ljpilon.nl/moofx/sorted-list-galore.php
I’ll be sure to post if I find something for 1.2 and if anyone else knows of a plugin, please drop a note.
Great tutorial! Do you know how to get a handle to the clone in order to add a css class etc. I know how to add the class but I do not know how to get a handle to the clone itself. Any help is appreciated.
never mind I just learned that the second event param gets a handle to the clone…
What would be the best way to use this between say 3 lists where you want to limit 2 of the lists to only allow 1 item each, but at the same time still let each lists’ items be dragable?
@Troy: here’s your note: http://ljpilon.nl/mootools/2008/12/19/saving-a-sortable-nested-list-mootools-12/
Tutorial to save a sortable nested list with mootools 1.2/ PHP/ MySQL.
Thanks a lot Troy – I’ve been fighting with this for a while today. I started with 60+ lines of code and Mootools’ serialize chopped it down to less than 10.
If there a way to save the lists thanks to a cookie?
Many tanks for this tutorial
[...] Sortables and Intro to Methods [...]
[...] Sortables and Intro to Methods [...]
[...] Sortables and Intro to Methods [...]
[...] Sortables and Intro to Methods [...]
[...] Sortables and Intro to Methods [...]
Hi!
Great tutorial
Can someone tell me if you can change the look of a sortable element when it’s dragged between 2 lists?
If i understand your question correctly, I would recommend using the onComplete event. Create a function that checks the parent UL for a given ID, then if the parent UL is one ID, do something to the li, if the ID belongs to the other UL, do something different. Hope this answers your question.
[...] Sortables and Intro to Methods [...]
Hi, I am using this example, but instead of list I want to use div tag. When I change list to div, items in one list cannot be dropped into other list, they are only allowed to be dropped in same list.
Is there any way to fix this problem?
Any help is appreciable!!
Alright, having an issue with serialize. It seems to be returning an array with the correct number of NULL objects. Why are they null?
I have created a little mootools test area with all the stuff I’ve been learning over the past week or so since I discovered mootools. You can find it at http://iamcorbin.net/tEsT/mootools.php
When you sort the 2 lists on the right it outputs the serialized content of the first list to the Firebug console. I’m trying to get the data from the list but it’s simply returning an array of empty objects?
Also, I implemented an accordion effect on the entire test area and on doing so it removes the top and bottom borders, this also removes the constraint on the draggables as you can move the cat picture and the timer off the bottom… I could use some assistance with this if anyone has any ideas
I am getting an error for console.clear(), says console is not defined.
This may not be the problem, but this a pretty neat console.log handler that won’t break ie. I actually ran into an issue earlier where I couldn’t read console.log until i wrapped it in this function.
//console.log, but won’t break ie
var firebug = function(message){
try { console.log(message); }
catch (err){}
5}
Well even without using firebug, if I output the serialized sortable it only gives me “, , , ,”(with the correct number of elements)
var sortables = $$(‘#sortableList1, #sortableList2′);
var sortableList = new Sortables(sortables, {
clone: true,
opacity: .5,
onComplete: function() {
var serialized1 = sortableList.serialize(0);
var serialized2 = sortableList.serialize(1);
firebug(serialized1);
}
});
Confused, I can’t seem to find any other references online as to mootools serialize returning null objects either
The li elements need id’s. That is what output serializes and then displays. Sorry I didn’t notice it sooner!
[...] ?????? [...]
THANK YOU!!!
The first site I see with a detailed explanation for Sortables. The methods part helped me a lot.
Thank you.