jQuery UI drop event of droppable widget firing twice

让人想犯罪 __ 提交于 2019-12-17 19:33:12

问题


Firstly, I know this question has been asked before, both in this site and others, but the answers are all rubbish for my scenario (if they're not rubbish entirely), and (at least for the question here: jQuery UI drop event of droppable fires on sortable), the suggestion is just to turn off .sortable entirely, which is most certainly not what I want to do.

Okay, I have this jquery (keep in mind if any options or html ids look silly, this is just for testing so I can try and figure this out):

$(function () {
    $("#sortable").sortable({
        revert: true
    });
    $("#draggable, #draggable2").draggable({
        connectToSortable: "#sortable",
        helper: "clone",
        revert: "invalid"
    });

    $("#sortable").droppable({
        drop: function (event, ui) { alert("done been triggered."); }
    });

    $("ul, li").disableSelection();
});

And here is the valid markup:

<div class="objectPaletteHolder">
    <ul>
        <li id="draggable" class="ui-state-highlight">Drag me down</li>
        <li id="draggable2" class="ui-state-highlight">Drag this down, too</li>
        <li id="draggable2" class="ui-state-highlight">Drag this down, also</li>
        <li id="draggable2" class="ui-state-highlight">Drag this down, as well</li>
        <li id="draggable2" class="ui-state-highlight">Drag this down, too</li>
        <li id="draggable2" class="ui-state-highlight">Drag this down, too</li>
        <li id="draggable2" class="ui-state-highlight">Drag this down, too</li>
        <li id="draggable2" class="ui-state-highlight click">Drag this down, click</li>
        <li id="draggable2" class="ui-state-highlight clicky">Drag this down, clicky</li>
    </ul>
</div>
<div class="editContainer">
    <ul id="sortable">
        <li class="ui-state-default">Item 1</li>
        <li class="ui-state-default">Item 2</li>
        <li class="ui-state-default">Item 3</li>
        <li class="ui-state-default">Item 4</li>
        <li class="ui-state-default">Item 5</li>
    </ul>
</div>

I do not have overlapping sortable divs or anything like that, and I think I understand 'why' this is happening (because sortable gets draggables properties by default?), I just can't seem to do anything about it.

The problem, of course, is that the...

drop: function (event, ui) { alert("done been triggered."); }

...is being triggered twice, when it is only needed once.

I would think that there would be a simple solution to this problem, for if this problem required a bunch of complex scripting to fix, than I would think that these particular jquery widgets wouldn't be worth all the trouble. Perhaps I am just confused?


回答1:


That's a known issue using both sortable and droppable on the same element.

You can use the sortable's receive event instead.

jsFiddle Demo

$("#sortable").sortable({
        revert: true,
        receive: function (event, ui) {      
            alert("receive been triggered.");
        }
}).droppable({ });



回答2:


I had a similar problem. There were 2 droppable elements, one of them had relative position, and another one - absolute. They were not nested, but a part of the one with absolute postion was above the part of the one with relative position (in jQuery docs this is called "intersect"). When I moved a draggable element to the "absolute" droppable, drop event was trigged twice. I have been searching for a few days, but didn't find any solution.

Then I decided to make a simple general workaround. Looks not very attractive, but this will help in any situation with firing 2 drop events.

drop: function( e, ui ) {
    if ( ! $('.already-dropped').length ) {
        $('body').addClass('already-dropped');
        setTimeout( function() {
            $('.already-dropped').removeClass('already-dropped');
        }, 100 );
        // callback code...
    }
}



回答3:


Maybe I'm a little too late but I posted this hopefully it will help someone. This is the code I use. Basically, if the function is called twice, the interval between them should be quick (quicker than what human usually do) so I set the number to be 200 milliseconds.

I used localStorage to set a variable called "last_call". It's the time the function was called. In the next call, we will check if the function was called previously. If it wasn't called, the function will continue executing. If it was called, we will check when the last time it was called. If it was called within 200 milliseconds (which obviously machine call, not human call), we will not call it again.

    var d = new Date();
    var this_time = d.getTime();
    if ( localStorage.getItem("last_call") != null)
    {
        if ((this_time - parseInt(localStorage.getItem("last_call"))) < 100)
        {

            return;
        }

    }
    localStorage.setItem("last_call", this_time);


来源:https://stackoverflow.com/questions/18664641/jquery-ui-drop-event-of-droppable-widget-firing-twice

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!