Jquery UI: How to make a draggable element can not be dropped on another draggable element?

2

I have a code that puts an icon on the screen every time you double click on the screen. These icons that are created are draggable. The problem is that I can drop the icons on top of each other and I do not know what to do to prevent the program from letting it drop an icon on top of another. I would like it when it releases the icon on another one it returns to its original place and rejects it. I tried greedy: true on the droppable, and also with stopProgagation but it does not work.

Here I leave the code:

$(document).ready(function(){
var i  = 0;
var counter = 0;

function newTimer(x,y) {

  var id = "#" + "timer" + counter;

  var clock = '<div id ="timer'+ counter + ' " class="ui-widget-content timer" '
  + ' style = "left: ' + x + 'px ; top: ' + y + 'px "><i class = "fa fa-clock-o fa-4x" aria-hidden = "true"> </i></div>';

  $('#content').append($(clock));

  $(".timer").draggable( {
    cointainment: "#content",
    snap: true,
    revert: "invalid"});
  counter++;
}

$("#content").droppable({
   greedy: true,
   accept: ".timer",
   drop: function( event, ui ) {
      i++;
      console.log("Lo soltaste " + i);
   }
});


$("#content").on( "dblclick", function(e) {
  var pos = $(this).offset();
  var posX = e.pageX - pos.left;
  var posY = e.pageY - pos.top;
  console.log("posicion x = " + posX);
  console.log("posicion y = " + posY);
  newTimer(posX,posY);
});
});

I would appreciate if you could guide me about it. The Jquery versions are jquery-2.2.4 and jquery-ui-1.11.4.

    
asked by KatGeek 23.07.2016 в 13:53
source

3 answers

2
  

First I'm going to make a couple of changes of things that were either wrong or they were giving me problems:

     
  • The property is containment and not cointainment
  •   
  • No position is specified for the .timer which gave me problems so I specified a position:absolute (and a position:relative to the container that I do not know if it had)
  •   

You can undo these changes if you want.

With those previous steps done, what you have to do is define a function for revert . This parameter is used to indicate if the element should return to the original position or not, it can have as a value a Boolean, a string (what you have) or a function.

If revert returns true then the element is returned to its original position; if not, the drag-drop is allowed. What you would do is create a function that checks if there is already another element timer that is in that same position, and if there is one, return true so that the drop is not made. The code of revert would be like this:

revert: function() {
            var current = $(this)[0];
            var found = false;
            $(".timer").not(this).each(function() {
                if (this.style.top == current.style.top && 
                    this.style.left == current.style.left) { 
                        found = true; 
                        return true; }
            });
            return found;
        }

And you can see how it works in this demo:

$(document).ready(function(){
  var i  = 0;
  var counter = 0;

  function newTimer(x,y) {

    var id = "#" + "timer" + counter;

    var clock = '<div id ="timer'+ counter + ' " class="ui-widget-content timer" '
    + ' style = "left: ' + x + 'px ; top: ' + y + 'px; position:absolute;"><i class = "fa fa-clock-o fa-4x" aria-hidden = "true"> </i></div>';

    $('#content').append($(clock));

    $(".timer").draggable( {
      containment: "#content",
      snap: true,
      revert: function() {
        var current = $(this)[0];
        var found = false;
        $(".timer").not(this).each(function() {
          if (this.style.top == current.style.top && this.style.left == current.style.left) { found = true; return true; }
        });
        return found;
      }
    });
    counter++;
  }

  $("#content").droppable({
    greedy: true,
    accept: ".timer",
    drop: function( event, ui ) {
      i++;
      console.log("Lo soltaste " + i);
    }
  });


  $("#content").on( "dblclick", function(e) {
    var pos = $(this).offset();
    var posX = e.pageX - pos.left;
    var posY = e.pageY - pos.top;
    console.log("posicion x = " + posX);
    console.log("posicion y = " + posY);
    newTimer(posX,posY);
  });
});
#content {
  width:400px;
  height:400px;
  background:#eee;
  position:relative;
}
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.0/jquery-ui.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css"/>

<div id="content"></div>
    
answered by 23.07.2016 / 17:37
source
0

Here is an example that you can use: link

    
answered by 23.07.2016 в 16:58
0

I advise you to use the libraries swingdrag.js and ripples.js

When you have your html elements (images in my case)

<img id="objeto1" src="images/jirafa.png" class = "draggable-jirafa"/>

<img id="silueta1" src="images/jirafa_sombra2.png" class = "droppable-jirafa"/>

Then it is a matter of assigning the function draggable to the element by its id

$('#objeto1').draggable({
            containment: "#form1",
        revert: true });

And to the other element, the function droppable :

$('#silueta1').droppable({
            tolerance: 'fit',
            hoverClass: 'active',
            accept: "#objeto1",
            drop: function(e, ui) {
                $(this).html(ui.draggable.remove().html());
                $(this).droppable('destroy');
                $( this )
                //.addClass( "ui-state-highlight" )
                .attr("src", "https://image.ibb.co/gAhVay/jirafa.png");
            }
        });

Then with the css you configure the elements to your liking and it is ready.

I'll give you a simplified example so you can understand it better: link

And a more complete example with several draggable and droppable elements: link

    
answered by 27.05.2018 в 17:21