开发者

Make jQuery sortable items droppable to their peers

开发者 https://www.devze.com 2023-01-03 02:39 出处:网络
I have a sortable list (of tasks). It helps pri开发者_运维知识库oritize tasks, so I want to keep this functionality. Now I want to add subtasks to the functionality: I want to enable users to drag one

I have a sortable list (of tasks). It helps pri开发者_运维知识库oritize tasks, so I want to keep this functionality. Now I want to add subtasks to the functionality: I want to enable users to drag one task over to another task and drop it there to turn it into a subtask.

Applying .draggable() and .droppable() to items that are already sortable has no effect. What could I do?


I put together a demo of how to do this... but it may not be the best method. Here are some problems I've discovered:

  • Because this code uses the placeholder to figure out where you are moving the list, you can only drop an item inside another item if you approach it from the top. I did get a working version where you could drop an item anywhere inside the base item, but the code was just too messy and cumbersome.
  • Sometimes when an item from the other list is dropped in an item, it becomes stuck. I'm not sure why, but it becomes unstuck when the list group is moved to the other list.

I'm sure there is a better method, one that calculates the intersection of list items (just like the sortable script does). But this is a quick and dirty method.

$(function() {
    var phTop, container, indx;
    $("#sortable1, #sortable2").sortable({
        connectWith: '.connectedSortable',
        beforeStop: function(e,ui){
            phTop = ui.placeholder.position().top;
            container = ui.placeholder.parent();
            indx = ui.placeholder.index();
        },
        stop: function(e,ui){
            var list = container.find('> li').eq(indx);
            // 15 is a pixel tolerance between the two items (dragging in from the top)
            if ( Math.abs( phTop - ui.position.top ) < 15 ) {
                // prevent list depth > 1
                if (ui.item.find('li').length > 0) { return; }
                // add ul inside of li to make subgroup
                if (!list.find('ul').length) { list.append('<ul></ul>'); }
                ui.item.appendTo( list.find('> ul') );
            }
            container.find('li > ul:empty').remove(); // remove empty subgroups
        }
    }).disableSelection();
});


After I posted my question I had no patience, and I decided to ignore UI.sortable altogether, building the required functionality from draggable and droppable and using special divs as spacers that would swell up on dragover to facilitate dropping in between tasks.

That worked to some degree, except it's all much more code and it's a lot more jittery and bugprone than sortable, even with the refreshPositions option set to true. Still, there might be other valid reasons to want to circumvent UI.sortable.

In very brief faux code: $(.taskitem).draggable

revert: invalid

start: animate height of spacers from 0 to 5

$(.spacer).droppable

over: animate height from 5 to 50

out: animate height back to 5

drop: insert draggable after spacer

find spacer with same index as draggable and move it along

0

精彩评论

暂无评论...
验证码 换一张
取 消