Hi,

I just cooked up this code allowing a tree structure to be re-nested.  
It works very similar to the NestedSortables plugin, except that it  
doesn't allow to sort the list, only to change the nesting of  
elements. Its way more stable than NestedSortables (at least in my  
tests so far), has no dependencies other than ui.draggable and  
ui.droppable, works with the latest versions of jQuery and is very  
minimalist.

What's it good for?
It's perfect as an admin interface for tree structured data, like,  
say, a category tree.

What's needed?
Developed on jQuery 1.2.6 with jquery.ui.draggable and  
jquery.ui.droppable version 1.6b.

Expects a nested list of data like:

<div id="list_container">
        <ul id="sortable_list">
                <li id="1">Item 1</li>
                <li id="2">Item 2
                        <ul>
                                <li id="3">Item 3</li>
                                ...
                        </ul>
                </li>
                ...
        </ul>
</div>


Here's the code:

jQuery(function () {
        $('#sortable_list li').draggable({
                revert  : 'invalid',
                start           : function (e, ui) {
                        // creating a temporary <div> that will be dragged 
around.
                        // works around some unwanted behavior, like being able 
to
                        // drag elements onto their own children.
                        // can be customized via CSS class .dragHelper
                        $(this).hide();
                        var helper_id = this.id+"-helper";
                        $(document.createElement('div')).append($(this).html())
                                .css({ position : 'absolute' })
                                .appendTo('#list_container')
                                .attr({ id : helper_id, class : 'dragHelper'});
                        $('body').mousemove(function (e) {
                                $('#'+helper_id).css({
                                        top     : (e.pageY - 
($('#'+helper_id).height()/2))+'px',
                                        left    : (e.pageX - 
($('#'+helper_id).width()/2))+'px'
                                });
                        });
                },
                stop            : function (e, ui) {
                        $(this).show().css({ top : 'inherit', left : 'inherit' 
});
                        $('body').unbind('mousemove');
                        $('#'+this.id+'-helper').remove();
                }
        }).droppable({
                hoverClass      : 'hoverDroppable',
                tolerance       : 'pointer',
                accept          : 'li',
                drop            : function (e, ui) {
                        if ($(this).children('ul').length) {
                                
$(this).children('ul:first').append(ui.draggable);
                        } else {
                                $(this).append($ 
(document.createElement('ul')).append(ui.draggable));
                        }
                        
                        $('#output').html(ui.draggable.attr('id') + ' is now a 
child of ' +  
this.id);
                }
        });
});

The last line ($('#output')...) should be changed to send the element  
id and new parent id to the server, where it can be saved to the  
database, or whatever else needs to be done.

It's far from being a ready-to-use plugin, but I thought somebody  
might find this useful to play around with.

Chrs,
Dav

Reply via email to