jit
jit

Reputation: 1626

draggable droppable with sortable

we trying to integrate multiple drggable and droppable. we are using sortable for ease of clone functionality in this scenario. draggable once dropped need to be draggable again.

how do we limit sortable to receive only one element and revert to original if more than one dropped onto it.

look like out and over functions of sortable are misbehaving in that case.

commented line code is for disabling dropping second element on sortable. which is not working as expected.

Two issues when you enable my commented code:

  1. draggable clone not reverting to original place after moving out of droppable.
  2. draggable element moved from one droppable to another reverting to draggable's original place.

For a demonstration, see this jsfiddle

script:

//  jQuery.noConflict();

jQuery( document ).ready(function() { init();});
function init() {

  var mouse_button = false;
  jQuery('.ui-draggable').live({
      mousedown: function () {
          mouse_button = true;
      },
      mouseup: function () {

          if (jQuery(this).attr('data-pos') == 'out' && jQuery(this).attr('data-id')) {
              var p = jQuery('#' + jQuery(this).attr('data-id'));
              var offset = p.offset();
              jQuery(this).hide();
              jQuery(this).animate({ left: offset.left, top: offset.top, width: jQuery(this).width, height: jQuery(this).height }, 100, function () {
                  jQuery(this).remove();
                  $( ".ui-droppable" ).each(function() {
                    if($(this).children().length == 0) {
                      $( this ).removeClass("dontDrop");
                    }
                  });
                  //if(p[0].hasAttribute("draggable"))
                  p.draggable("enable");

             //     $('.ui-droppable').sortable('option', 'connectWith',$('.ui-droppable').not('.dontDrop'));
             //     $('.ui-draggable').draggable('option', 'connectToSortable',$('.ui-droppable').not('.dontDrop'));

              });
          }
          mouse_button = false;
      },
      mouseout: function () {
          if (mouse_button) {
              mouse_button = false;
          }
      }

  });

    jQuery( '.ui-draggable' ).draggable( {
      cursor: 'move',
      helper: 'clone',
      connectToSortable: ".ui-droppable",
      revert: function (event, ui) {
        }
    } );


    jQuery(".ui-droppable").sortable({
        cursor: "move",
        connectWith: ".ui-droppable",
        receive: function (event, ui) {

        if($(this).children().length >= 1) {

            $(this).children().addClass('filled');
            $(this).addClass('dontDrop');

            $( ".ui-droppable" ).each(function() {
              if($(this).children().length == 0) {
                $( this ).removeClass("dontDrop");
              }
            });
       //     $('.ui-droppable').sortable('option', 'connectWith',$('.ui-droppable').not('.dontDrop'));
       //     $('.ui-draggable').draggable('option', 'connectToSortable',$('.ui-droppable').not('.dontDrop'));
        }else {
            $(this).children().removeClass('filled');
        }
        if (jQuery(this).data().sortable.currentItem) {
                jQuery(this).data().sortable.currentItem.attr('data-id', jQuery(ui.item).attr("id"));
               // if(jQuery(ui.item)[0].hasAttribute("draggable"))
                jQuery(ui.item).draggable("disable");
            }

        },
        out: function (event, ui) {  if (ui.helper) { ui.helper.attr('data-pos', 'out'); } },
        over: function (event, ui) { ui.helper.attr('data-pos', 'in'); }
    });

  }

Upvotes: 2

Views: 1434

Answers (3)

Twisty
Twisty

Reputation: 30899

Determining when to revert may be best done in .draggable() using revert: function(){}.

Function: A function to determine whether the element should revert to its start position. The function must return true to revert the element.

You can do this:

  jQuery('.ui-draggable').draggable({
    cursor: 'move',
    helper: 'clone',
    connectToSortable: ".ui-droppable",
    revert: function(item) {
      if (!item) {
        return true;
      } else {
        if (item.hasClass("dontDrop")) {
          return true;
        }
      }
      return false;
    }
  });

the revert function is passed false if the draggable item is not accepted. For example, if it is dropped on something that is not a target. If the draggable item is accepted, a jQuery Object is passed back.

See more: jQueryUI sortable,draggable revert event

The logic is a little confusing. If what is passed back is false, we return true to revert letting draggable revert the item to it's position. If what is passed back is not false, then it's an object we can test. If the target is "full", we revert. Otherwise we do not revert.

Sortable still wants add the item for some reason. May need to adjust to update and clear out any items that are not class "filled".

Fiddle: https://jsfiddle.net/Twisty/7mmburcx/32/

Upvotes: 0

ecrb
ecrb

Reputation: 710

Here's a working example: click here

You can user Jquery's draggable and droppable interactions to achieve what you want. Check the working example.

$(document).ready(function () {

  $(".ui-draggable").draggable(draggable_options) //make cards draggable

  $(".ui-droppable").droppable({ //handle card drops
    greedy: true,
    drop: function (event, ui) {
      handleDrop(this, event, ui)
    },
    accept: function () {
      return checkIfShouldAcceptTheDraggable(this)
    }
  })
})

Upvotes: 2

Ali Soltani
Ali Soltani

Reputation: 9946

You can do it like this:(Online Demo (fiddle))

var draggable_options = {
  helper: 'clone',
  cursor: 'move',
  revert: 'invalid',
};

$(".ui-draggable").draggable(draggable_options);

$(".ui-droppable").droppable({
  drop: function(event, ui) {
    var $item = ui.draggable;
    $item.draggable(draggable_options)
    $item.attr('style', '')
    $(this).append($item)
  },
  accept: function() {
    return $(this).find("li").length === 0 // Your condition
  }
});

$(".textToImageRightPanel").droppable({
  drop: function(event, ui) {
    var $item = ui.draggable;
    $item.draggable(draggable_options);
    $item.attr('style', '');
    // Return to older place in list
    returnToOlderPlace($item);
  }
});

// Return item by drop in older div by data-tabidx
function returnToOlderPlace($item) {
  var indexItem = $item.attr('data-tabidx');
  var itemList = $(".textToImageRightPanel").find('li').filter(function() {
    return $(this).attr('data-tabidx') < indexItem
  });
  if (itemList.length === 0)
    $("#cardPile").find('ul').prepend($item);
  else
    itemList.last().after($item);
}

Upvotes: 1

Related Questions