h1

Nested Sortable jQuery Plugin

July 22, 2007

UPDATE: The plugin has now reached its 1.0 version, and is available in a compressed version and with documentation. Please check the project homepage at: http://nestedsortables.googlecode.com/

I am showing now the first version of what I call the “Nested Sortable” jQuery plugin. It is based on the same nesting idea shown on the previous prototypes and used on the bbPress forum ordering, but it is totally rewritten and has a very different (and I believe simpler/more efficient) inner working.

A demo of it can be seen here.

The highlights of it are:

  • Built on top of Interface ‘s Sortable and maintains compatibility with it. This means you can use the same options available on the Sortable, plus a few extra ones specific to the nesting. You can also mix Sortables and NestedSortables on the same page.
  • Just as easy to use (see the code examples on the demo).
  • Can be easily configured for left-to-right or right-to-left nesting.
  • Can be used with any type of HTML element (that allows nesting), not only ULs and LIs.
  • You can define a class for the nesting the draggable is currently hovering on, to make it clearer to the user (see my ugly yellow example – could be made pretty with some css styling).
  • All the previous bugs/misbehaviours with the prototype are gone (hopefully without additional ones being introduced).

It was tested under IE7 and FF2. What is still lacking for it to be complete (and useable) is a serialization function, which I should finish in a few days (serialization is now complete, see my comment bellow). As things evolve I should probably add a few callbacks to allow its behavior to be easily configured.

So, the next step for the WordPress page list project is to create a higher level jQuery plugin that will be built on top of this one and will, given a JSON object input, fetched via AJAX, dynamically create the Nested Sortable, with pagination support, using the idea Mike gave on the last comment (the user hovers over a Droppable, which should fetch and display the additional pages). It will be more like a widget.

60 comments

  1. This is exactly what I’ve been searching for. Is there any way to limit the number of levels that can be nested? I need to limit it for a table of contents.

    I use prototype and scriptaculous, but after seeing this I’d be willing to try out jquery and interface. Keep up the good work.


  2. I hadn’t thought of that yet, so there is no way to do that yet. It shouldn’t be so hard to do, I will try to implement it. Thanks for the comments.


  3. That would be great. The level limiter and the serialization function will make this a very powerful tool.

    You mentioned adding callbacks as well. Does Jquery have built in callbacks for sortables, or am I mistaken? If not, the addition of this feature would help.

    Thanks and stay motivated.


  4. There are callbacks that are already defined by Interface’s Sortable, and they should work here too (onChange, onStart, onStop… – look then up at http://interface.eyecon.ro/docs/sort ). I was mentioning about defining callbacks specific to the nesting, such as when you nest one element to another, and things like that.


  5. I have finished the implementation of serialization. It can now be seen in the demo. Pay attention to the onChange callback, which is actually defined by the original iSortable, but is not documented.

    I began coding the nesting limit as xsaint suggested, but it got a little more complicated than I initially thought, so I am postponing it to a later date. The additional callbacks will probably be added as I have a need for them, but I believe the ones already defined by the iSortable are enough for most cases.

    I am planning on adding this plugin to the jQuery plugin repository in September, by then it should be more mature and with some additional features. Until them it can be freely used, but with care and not many warranties.


  6. Well done


  7. It is very good plugin.

    but not working in IE6.
    Do you have any suggestions to let it work in IE6?

    Thank you!


  8. Bin: The plugin was working, but I realized now there was a tiny sintax error in my demo file that made it not work in IE. It is fixed and is working in IE7 now, it should be working in IE6 as well.


  9. BTW, if you were curious the error was that there was a comma at the end of a Javascript object literal (like “{one:1, two:2,}”), which IE complains about, but FF doesn’t.


  10. I’m interested in your script, but the demo doesn’t work anymore. It looks like the links to the javascript files are dead. Do you plan on putting them back on? Or is it a problem with my browser (FF2) ? Thanks.


  11. I think your demo did get messed up. The required .js files are not found!


  12. Yes, it was, I had updated it to a newer version in the SVN and forgot to change the JavaScript include paths. Now it is working.


  13. URL of the demo points to localhost!?

    Would you please fix the URL? I would really like to see this demo.


  14. Sorry, yesterday I was changing all the URLs in the blog, and forgot to put the proper domain name (left “localhost” in the URLs). It is working now.


  15. I am using this script in my latest project. Works great. Thanks


  16. Nice to hear that. Don’t forget to update it from the SVNas often as you can, and watch out for release of the first official version, which will come with a packed .js (the file should be more than 50% smaller).


  17. I would like to use your great sortable plugin to manage the order of categories and subcategories.
    My question is: Is it possible to limit the nesting?
    Example good:
    – Cat 1
    — Subcat 1.1
    — Subcat 1.2
    – Cat 2

    Example bad:
    – Cat 1
    — Subcat 1.1
    —– Subcat 1.1.1
    – Cat 2


  18. Not yet. I began implementing it on request, but it got a little complicated and I had to move to finishing the Widget and the other pendencies related to GSoC. But I will put some effort into it in a short while.


  19. That would be great!


  20. deja vu


  21. […] jQuery’s Interface plugin which allows for the sorting of nested lists. You can read about it in his blog and see it in action here (his blog article is linking to the wrong […]


  22. The NestedSortable plugin has now reached its definitive version. Check the UPDATE in the beginning of this post.


  23. Fantastic piece of work Bernardo!

    One question:
    I’d like to restrict dropping on certain nodes.
    How would you go with it? (I’m just starting with jQuery…)


  24. Heh, quick solution for my above question:

    add to build: function(conf) under this.nestedSortCfg :
    noDropClass: conf.noDropClass ? conf.noDropClass : “”

    add to shouldNestItem : function(e, precedingItem ) after if(!precedingItem) {return false;} :

    if($(precedingItem).hasClass(e.nestedSortCfg.noDropClass)) {return false;}

    Perhaps it could be added to the trunk? 🙂


  25. And one more thing:
    my above code will work only with jQuery 1.2 and above because of hasClass function which is not available in the previous jQuery versions.


  26. Hi Peter,

    Thanks a lot for the comments. That is a great suggestion. I will add it to trunk.


  27. I figured out a way to avoid having to rely on jQuery 1.2, using the code bellow:
    if(jQuery(precedingItem).filter(“.” + e.nestedSortCfg.noDropClass).length > 0) {return false;}


  28. It’s in trunk already. I called the option “noNestingClass”. I added an example to the tests as well.


  29. Cool, cheers! 🙂


  30. Hi,

    Really nice plugin!
    As mentioned before is there any way to limit the number of levels that can be nested?
    Or is this possible using noNestingClass in some way?

    Thanks!


  31. Hum4ngus: Thanks for the comments. Not yet. noNestingClass is only if you want some of the elements to never take children. I would like to implement that now, but a more urgent matter is porting the plugin to use jQueryUI, so I am affraid this is going to be left in the dark for a while.

    If you want to give it a shot, just look at the commented code where I began implementing it (it got harder than I initially thought, so I had to move to other priorities). If I manage to do it I will apply it for all to use.


  32. Hello,

    Thank you for the reply.
    I understand, and I’ve already looked at the commented code for the nested items limit.
    I’m not a star in javascript so that didn’t do any good :P.

    Anyway, I’ll still be using your plugin. Thanks!


  33. Almost managed it to work.

    Is there a sample somewhere on how to take the database information with id/parent id and turn it into the json array needed to populate the tree?

    Right now im having a terrible time with recursion, arrays etc.

    Thanks for all help.


  34. You might look at the “Rails Plugin” code if you know Ruby on Rails (your might just use the plugin and spare your time).

    For a PHP example you can see what was done for WordPress in the patch file, under the wp-includes/class-page-order.php file.

    Note those 2 examples deal with pagination on the server side, which makes them much more complicated. If you don’t need server side pagination it gets much more simple.

    You will need a library to generate JSON from a Hash/Array. You will probably need a recursive function that grabs and converts to a Hash/Array all nodes that are children of a given node, and calls itself on nodes that have children.


  35. Hi, it’s nice script. But, how can I use script with the float’s elements?


  36. @tapazukk: You mean with using the “float” option of interface’s Sortable? I don’t see a use for it (AFAIK “float” is designed to allow you to sort vertically, like in a “zigsaw” puzzle), but it might work, but I never used it.


  37. Hi first of all thank you for this nice script.
    I have a question i whant to use this script as a layout managet with more then one sortables withing every nested item.

    But now i will get nothing then just a little bit of rouble.
    Is anyone who have tryed this script with blocks instead of lines?

    I hope you can help me becouse i have been looking over whole google and found nothing that looks like something like that i have seen a few sites who have a layout manager with blocks end nested blocks but i couldend rip it or anything.

    If you know a solution or know a way to make use script so i can use it like that i will be verry happy.

    Greets Krijn


  38. @Krijn: What do you mean by blocks? You can use any kind of HTML element that can be nested, be it a P tags, DIVs, and so on.

    Do you want to have Sortables inside those elements? I haven’t tested that but it might work.

    Post me a link to a page with the code you are using and I will see what I can do.


  39. I noticed the issue with IE in regards to only being able to drag items once. Has there been a patch to this?

    This is a great plugin. I love it.


  40. Hi,

    First of all, thank you for this great script. I have no problems with it, but have a problem with my php mysql updating script. I posted my question here http://code.google.com/p/nestedsortables/wiki/NestedSortableDocumentation

    I think it should be a simple solution, so if somebody would like to take a look, I would be very grateful.

    Thanks!


  41. This content has been Agglom (erated): http://www.agglom.com/agglom/28 – jQuery – nested sortables


  42. I’m a huge fan of your plugin, I’ve been able to do a number of things with it. What I’m wondering though is how I can append new children to the existing list. I’m making separate AJAX calls and returning the children but would now like to append those under their parent. Any suggestions on how to do this?


  43. Excellent script, works like charm and easy to extend. Thanks for sharing!


  44. Hi
    Anyone knows whether this will be fixed to work with the latest jQuery?
    This is a magnificant piece of work, just really sad that it does not work with jQuery UI yet.


  45. To make it work in IE with latest jQuery I had to unbind and bind the plugin after every drop.

    Read docs for unbinding the plugin.


  46. Hi first of all thank you for this nice script.

    I have a probleme with the serialization… I can’t retrieve all datas via $_post request. I have only the first item of the array !

    I have posted a message on google code http://code.google.com/p/nestedsortables/wiki/NestedSortableDocumentation (the last post)

    Thank’s for your answer


  47. Hi,
    very nice script, but I still have problem with IE. Onse you drag an item it is not draggable any more.
    Dmitrijs you are talking about binding, colud you please post an example

    Thanks


  48. There are also problems with bingding. I added links in sortable widget with jquery bind. But as soon as link is clicked the click function is unbinded.
    Anybody with same problem?

    here is the code

    $(document).ready(function(){
    $(‘#pages’).NestedSortableWidget({
    loadUrl: “my_list_json.js”,
    name: “pageList”,
    handle: true,
    onLoad: function(){
    $(“.confirmDelete”).bind(“click”, function(){
    $(“#dialog”).dialog({
    title: ‘Confirm delete’,
    draggable: false,
    modal: true,
    buttons: { “Ok”: function() { $(this).dialog(“close”); }, “Cancel”: function(){$(this).dialog(“close”);} },
    resizable: false
    });
    return false;
    });
    }
    });
    });


  49. D*mn! i’ll google next time got any request!!

    Thanks 4 this!


  50. It’s really helpful if someone try to make tree view like me 😀


  51. This is awesome! However, I need to use jquery 1.2.5 and unfortunately this messes up things in IE. Is there a workaround?


  52. 2sale:

    jquery code from my website

    function createnestedsort(el) {

    if (!$(el).length)
    return;

    $(el).NestedSortable({
    accept: ‘page-item’,
    onChange: function(serialized) {
    $.post(‘/Pages/ReorderCategories’ + ‘?’ + Math.random(), serialized[0].hash + “”);
    },
    onStop: function() {
    if (isie) {
    $(el).NestedSortableDestroy();
    createnestedsort(el);
    }
    },
    autoScroll: true,
    helperclass: ‘helper’,
    nestingPxSpace: 22,
    handle: ‘.sort-handle’
    });

    reloadcategoryajax(“#sortable”);
    }


  53. Hi,

    Is there also a way to make it work with a horizontal menu?

    example:

    CSS:

    #menuList li { 
        display             : inline;
    }
    

    HTML:

    
    one
    two
    three
    
    

    Thanks!


  54. @Jasper: Horizontal sorting is not contemplated (you can do left-to-right or right-to-left as of now). It shouldn’t be hard to alter the plugin to do that.


  55. hi bernardo,

    by the way great work,
    i’d like to use this plugin.

    wont to know if its possible to make your plugin (onChange function) work with real nested sets (lft, rgt, level) in a db structure.

    to do so i need at onChange only the current (dragged node) with its new parent and previous sibling in that serialized way.

    so i can update the orm db (expect a root_node at least) with something like:

    move_to_next_sibling($dragged_node, $new_previous_sibling)

    or

    move_to_first_child($dragged_node, $new_parent_node)


  56. Hi, awesome plugin!

    However with jQuery 1.3.2, in IE7/8 it works, but afer you have dragged an item, it becomes no longer draggable.

    Will you be able to fix this IE bug at some point? Im so impressed im using an old version of jQuery on the page that im using your plugin!

    Thanks, Seb


  57. Good job guy !
    it’s exactly what i search for.
    I use it with an AJAX request to order a Pages Tree.

    Have Fun


  58. @Seb: It’s a problem with Interface, which was deprecated, and the newest versions of jQuery (after 1.1). A few people have discussed some workarounds at the wiki page at googlecode (http://nestedsortables.googlecode.com), if I am not mistaken, but I’ve never tested it myself.

    It will take a complete rewrite of the plugin to make it independent from Interface and maybe use jQuery UI (the next Interface) and make it really compatible with jQuery 1.3 and up.


  59. I was struggling for a few hours.
    Problem: The .helper class would not appear, kept on display: none; and other strange events.
    Workaround: I was using $(‘ul.myUl’), but that part of plugin only works with id’s, so when I replaced it with $(‘#right-to-left’) it was ok. That also fixes another less obvious bug. The sporadicaly disappearing of list items when you drag them too far out of the list.

    After that, yes… thanks for the nice script!


  60. So is the limit on nested levels ever going to be implemented?

    I am trying to incorporate this into my own content management system. It would be used to sort the pages and navigation order. I want to restrict the levels of dropdowns, otherwise i’ll have to use a much simpler method.



Leave a reply to oleonav Cancel reply