jQueryUI droppable, stop propagation to overlapped sibling

点点圈 提交于 2019-11-26 14:51:41

问题


As you can see here: http://jsfiddle.net/rA4CB/6/

When I make the drop in the overlapped area it is received in both droppables, greedy doesn't work when the items are siblings. Is there any way to block the reception on droppables lower in the zIndex?

BTW, mouseOver won't fire for the droppable element as the mouse is actually over the draggable element.

relevant JS:

$(function() {
    $( "#draggable" ).draggable();
    $( "#droppable" ).droppable({
        tolerance:'pointer',
        drop: function( event, ui ) {
            $( this )
                .addClass( "ui-state-highlight" )
                .find( "p" )
                    .html( "Dropped!" );
        }
    });
    $( "#droppable2" ).droppable({
        tolerance:'pointer',
        greedy:true,
        drop: function( event, ui ) {
            $( this )
                .addClass( "ui-state-highlight" )
                .find( "p" )
                    .html( "Dropped!" );
        }
    });
});

回答1:


Okay, so I spend an hour trying to figure it out, then as soon as I ask I then find my answer

http://jsfiddle.net/rA4CB/7/

Modified the JS to the following:

$(function() {
    $( "#draggable" ).draggable();
    $( "#droppable" ).droppable({
        tolerance:'pointer',
        drop: function( event, ui ) {
            $( this )
                .addClass( "ui-state-highlight" )
                .find( "p" )
                    .html( "Dropped!" );
        }
    });
    $( "#droppable2" ).droppable({
        tolerance:'pointer',
        greedy:true,
        drop: function( event, ui ) {
            $( this )
                .addClass( "ui-state-highlight" )
                .find( "p" )
                    .html( "Dropped!" );
        },
        over: function(event, ui){
            $( "#droppable" ).droppable( "disable" )
        },
        out: function(event, ui){
            $( "#droppable" ).droppable( "enable" )
        }
    });
});



回答2:


$( "#droppable" ).droppable({
    greedy: true,
    drop: function( event, ui ) {
       if(ui.helper.is(".dropped")) {
           return false;
       }
       ui.helper.addClass(".dropped");
    }
});

Just set a css class on ui.helper of draggable. If the draggable has been accepted once, it will be refused by all other droppables (Could be done with the droppable "accept" parameter,too , like accept : ":not(.dropped)" and the class added to ui.draggable).




回答3:


If you have a number of droppable in a container area then what????

You must re think for that problem. Greedy works for only parent to child relationship not in siblings. So you must edit droppable js or put your own logic for it.

So if you have a numbers of droppable then you must write some extra code to handle dropping on perfect droppable as it is in this example A number of siblings droppables

For making perfect siblings droppable modify your droppbale as below

        var topElement = undefined;
        var topElementArray = Array();

        $( "#draggable" ).draggable();
        $( ".droppableBox" ).droppable({
            activeClass: "active-droppable",
            tolerance:'pointer',
            over: function( event, ui ) { 
                // This is for only show a message that z-index must be required for proppable
                // you can remove it after testing or after development
                if ($(this).css("z-index") == 'auto') {
                    alert("Please provide z-index for every droppable.");
                    return;
                }
                //

                topElement = undefined;
                topElementArray = Array();
                // Change it as you want to write in your code
                // For Container id or for your specific class for droppable or for both
                $('#demo > .droppableBox').each(function(){                     
                    _left = $(this).offset().left, _right = $(this).offset().left + $(this).width();
                    _top = $(this).offset().top, _bottom = $(this).offset().top + $(this).height();
                    if (event.pageX >= _left && event.pageX <= _right && event.pageY >= _top && event.pageY <= _bottom) {   
                          topElementArray.push($(this).attr('id'));
                    }
                });
            },
            drop: function( event, ui ) {
                if (!topElement) {
                    topElement = determineTopElement(topElementArray);
                }                   
                if ($(this).attr('id') == $(topElement).attr('id')) {
                    $( this ).addClass( "ui-state-highlight" ).find( "p" ).html( "Dropped!" );
                  // Your code after successful dropped element on specific siblings
                  // Start writing code for dropped element & perfect droppable
                }

            }
        });

        determineTopElement = function(_array) {
            var topElement;
            var zIndexHighest = 0;
            for (i = 0; i < _array.length; i++){
               var element = $("#"+ _array[i]);
               var z_index = $(element).css("z-index");
               if( z_index > zIndexHighest){
                   zIndexHighest = z_index;
                   topElement = element;
               }
            }
            return topElement;       
        }



回答4:


In certain circonstances :

myjQuery.droppable({
  over:function(evt,ui){
    ui.draggable.attr('drg_time', this.drg_time = evt.timeStamp)
  },
  accept:function(draggeds){
    if(draggeds.attr('drg_time'))
    {
      return draggeds.attr('drg_time') == this.drg_time
    }
    return draggeds.hasClass('acceptable_classes_here')
  },
  out:function(evt,ui){
    // useless but cleaner
    ui.draggable.removeAttr('drg_time')
  }
  drop:...,
})



回答5:


I had the same problem and made a small plugin :)

check it out:

https://stackoverflow.com/a/16720944/1308461




回答6:


I find that using #invertedSpear's method will cause UI state change which is not desirable in some cases. Here is the code.

var lastOpertion = new Date().getTime();

drop: function (event, ui) {
        if (new Date().getTime() - lastOpertion < 100) return;
        lastOpertion = new Date().getTime();
        ....
}



回答7:


So, when trying to find simple solution I came up with this (and it works for me):

            window.overNowOnThis = "";
            window.olderOnes = [];
            $obj.droppable({
                accept: ".draggable_imgs",
                drop: function(e, ui) {
                    if(window.overNowOnThis == this){
                        // Do whatever
                    }
                },
                over: function(event, ui){
                    window.olderOnes.push(window.overNowOnThis);
                    window.overNowOnThis = this;
                },
                out: function(){
                    var lastElem = window.olderOnes.pop();
                    window.overNowOnThis = lastElem;
                }
            });

Top element would be selected because on it "over" fires the last one. Also - if there is more than two siblings - then when moving out of element we set the last one as current. Using global "window" was for example. Better option would be using classes as it can safely keep data.




回答8:


It's very similar to invertedSpear answer. I had to change it a little bit because enabling/disabling inside "over"/"out" didn't work for me .I had to do below instead

$("#droppable2").droppable({
    greedy: true,
    drop: function (event, ui) {
        $("droppable").droppable("disable");
    }
}

I had to explicitly enable"droppable" div when I needed it. For instance, enable it when starting the drag event. Eg

$("#drageMe").draggable({
 start:function(event,ui){
   $("droppable").droppable("enable");  

} })




回答9:


try greedy option in ui dropable. see the fiddle link below for demo:

http://jsfiddle.net/creators_guru/3vT5C/embedded/result/

$( ".circles" ).droppable({
    greedy: true,
    drop: function( event, ui ) {
        $_data  =   ('drgged class = ' + ui.draggable.attr('class'));
        $_data1 =   ('droped id = #' + $(this).attr('id'));
        $('#data').html($_data + '<br/>'+$_data1);
        return false;
    }
});


来源:https://stackoverflow.com/questions/11997053/jqueryui-droppable-stop-propagation-to-overlapped-sibling

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