jquery droppable accept

2019-01-31 13:08发布

问题:

Can anyone tell me how I can write a function in accept condition and then how does it finds out that what to accept and what not to accept. For example, I want to accept div a and div b in accept condition. How can I write I through a function?

回答1:

If you want the droppable to accept a selection of elements you can do something like this:

$(".droppable").droppable({
    accept: function(d) { 
        if(d.hasClass("foo")||(d.attr("id")=="bar")){ 
            return true;
        }
    }
});

This droppable will accept elements with the class "foo" or an element with the id "bar"



回答2:

If I understand your question correctly, you want to conditionally accept the dropped element based on custom code. Aberon's answer is the typical case: you want to allow only certain draggable options to be dropped based on their class, and all others will revert. If that answers your question, then fine.

However, there is a case for having the revert animation happen conditionally based on something more complex than a class match. In my own project, I am using drag-drop to add users to a group. If the dropped user is already in the group, I want the user helper element to revert back. Otherwise, I go ahead with an AJAX action to insert them. This is no substitute for back-end checking, but it's nice visual feedback.

I have looked elsewhere for a simple answer to this. Note to JQuery maintainers: to me, the most straightforward way would be to add some property to the event object in the drop function, like this:

$('.target').droppable({
    accept: '.valid'
    drop: function(event, ui) {
        if(isDropOK() == true) {
            // add child here
        } else {
            event.revert = true;
        }
    }
});

Sadly that doesn't work. Here's what does "work", though: set the draggable element to always revert, and then hide the helper if the condition is met. You can get a reference to the helper by looking for the only element on the page that has the class ".ui-draggable-dragging". Here's an example, replace "isDropOK()" with your own logic:

$('.valid').draggable({
    revert: true,
    helper: 'clone',
    opacity: 0.5
});

$('.target').droppable({
    accept: '.valid'
    drop: function(event, ui) {
        if(isDropOK() == true) {
            $('.ui-draggable-dragging').hide();
            // add child here
        }
    }
});

So to recap, every element will always revert unless you step in on the drop event and manually hide the helper. The revert animation will still happen, but your users won't see it. It's a little hack, but the end result seems to work all right.



回答3:

According to the Jquery documentation on Selectors.

All draggables that match the selector will be accepted. If a function is specified, the function will be called for each draggable on the page (passed as the first argument to the function), to provide a custom filter. The function should return true if the draggable should be accepted.

Thus,

$('.selector').droppable({ accept: '.special' }); 

in their example will only act as if something has been dropped on it if it has the class 'special'. It looks like it can accept any Jquery selector.



回答4:

In addition to Alex answer which is the best answer I found on this question, I like to add, that if you want to check for matching attributes between droppable and draggable, you can use the keyword this to access the droppable within your accept function. Here is a small example I recently used:

accept : function (draggable) {
  var id_group_drop, id_group_drag;

  //get the "id_group" stored in a data-attribute of the draggable
  id_group_drag = $(draggable).attr("data-id-group");

  //get the "id_group" stored in a data-attribute of the droppable
  id_group_drop = $(this).parent().attr("data-id-group");

  //compare the id_groups, return true if they match or false otherwise
  return id_group_drop == id_group_drag;
}

So the draggable is only accepted, when it's id_group (remember, just an example) matches with the id_group of the droppable, otherwise the draggable would be reverted. I think this could be a very common use-case, maybe this will help someone.



回答5:

This is the solution that I use:

... accept: '#diva,#divb', ...


回答6:

I've figured out a solution that works based on the condition that no draggable should be placed in a droppable already occupied by another draggable:

$(".placement").droppable({
    accept: function(elm) {
        // only allow draggables to the placement if there's no other draggable 
        // in the droppable
        if (!$(this).attr('isbusy'))
            return true;
    },
    drop: function(event, ui) {
        $(this).attr('isbusy', 'yeap'); // fill key with something

        var draggable = $(ui.draggable[0]);
        // free the draggable's previous droppable 
        if (draggable.attr('droppable')) {
            $('#' + draggable.attr('droppable')).attr('isbusy', '');
        }

        // save the new draggable's droppable
        draggable.attr('droppable', $(this).attr('id'));
    },
});


回答7:

Instead of using a class as accept, you can just use a function like and return true if it matches your criteria

$('#mydroppable').droppable(
{
    accept: function() { return true; },
    drop: function () { alert("Dropped!"); }
});


回答8:

This is my solution:

var foo = true;

$( ".draggable" ).draggable({ 
                        revert: function(){if(foo == true){return true;}else{foo = true;}},
                         });

    $("#droppable").droppable({
        activeClass: "ui-state-hover",
        hoverClass: "ui-state-active",
        drop: function( event, ui ) {
            if($this == $that){
                foo = true;
                alert("this will revert the draggable back to original position");
            }else{
                foo = false;
                alert("this will NOT revert the draggable back to original position");
            }
        }
    });