Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery UI sortable/draggable nesting example

I've been playing with jQuery UI sortable and draggable and I'm looking for a way to nest list items (only first and second level) depending on where they are dropped on the list.

Simple JSFiddle example of what I am trying to do: http://jsfiddle.net/picitelli/XZ4Tw/

$(".items").sortable({
    connectWith: ".items",
    placeholder: "placeholder",
    update: function(event, ui) {
        // update
    },
    sort: function(event, ui) {
        // sort
    }
});
$(".item").droppable({
    accept: ".item",
    hoverClass: "dragHover",
    drop: function( event, ui ) {
        console.log('drop');
        if (ui.position.left >= 20) {
            $(this).removeClass("first-level");
            $(this).addClass("second-level");
        } else {
            $(this).removeClass("second-level");
            $(this).addClass("first-level");
        }
    },
    over: function( event, ui ) {
        // over
    },
    activate: function( event, ui ) {
        // activate
    }
});

I want to be able to drag a list item and drop it before/after another list item, and depending on how far I am from the left (x) of the list, and how far I am from the bottom/top (y) of the list item I am dropping near, it will make that list item either a first and second level item. For instance, if I have a list item dragged on top of another, and I am closer to the bottom of that list item that I am hovering over, than if I was farther away from the bottom, if I drop it it will snap to the bottom of said list item and be a first-level item. If I was to move that list item further away and drop it, it would snap to the bottom and be a second-level item. The placeholder would update as well, invoking a class, just on hover, to show that the dropped list item would be either first or second level before it is actually dropped.

Per the fiddle above, in the drop method, I am checking to see how far the dragged list item is from the left. If it is greater than or equal to 20px, I am adding a "second-level" class that indents the list item. If it is less than 20px, I am adding a "first-level" class that keeps the list item flush left. Just for the left (x) calculation, this is working but it is not applying the classes to the dropped list item, it applies them to the list item that it has "jumped" over. Am I not invoking the correct method to perform this? Also, how would I go about performing such a calculation to determine where the list item would snap depending on how far (y) it is from the list item I am hovering over?

Any feedback/direction would be greatly appreciated.

like image 361
picitelli Avatar asked Dec 19 '13 17:12

picitelli


1 Answers

Well I thought you question looked like a fun challenge.. And I had some idea of how to do it but was not sure.. So I tried it out. Hopefully this will be useful.. I'm not sure if it does everything your looking for so if something is missing let me know. Thanks.

Here is an example that I came up with: Using the sortable events.

CSS

.placeholder-sub {
    background: #fff;
    border: 1px dashed #ccc;
    height: 50px;
    width: 480px;
    margin-left: 20px;
}

jQuery

$(".items").sortable({
    connectWith: ".items",
    placeholder: "placeholder",
    update: function(event, ui) {
        // update
    },
    start: function(event, ui) {
        if(ui.helper.hasClass('second-level')){
            ui.placeholder.removeClass('placeholder');
            ui.placeholder.addClass('placeholder-sub');
        }
        else{ 
            ui.placeholder.removeClass('placeholder-sub');
            ui.placeholder.addClass('placeholder');
        }
    },
    sort: function(event, ui) {
        var pos;
        if(ui.helper.hasClass('second-level')){
            pos = ui.position.left+20; 
            $('#cursor').text(ui.position.left+20);
        }
        else{
            pos = ui.position.left; 
            $('#cursor').text(ui.position.left);    
        }
        if(pos >= 32 && !ui.helper.hasClass('second-level')){
            ui.placeholder.removeClass('placeholder');
            ui.placeholder.addClass('placeholder-sub');
            ui.helper.addClass('second-level');
        }
        else if(pos < 25 && ui.helper.hasClass('second-level')){
            ui.placeholder.removeClass('placeholder-sub');
            ui.placeholder.addClass('placeholder');
            ui.helper.removeClass('second-level');
        }
    }
});

Fiddle

like image 95
Trevor Avatar answered Oct 19 '22 23:10

Trevor