4

I have a 'box' that can be dragged and dropped onto a column of droppable divs. The draggable box snaps to the droppable div using the JqueryUI position function, but when I resize the draggable box to 3x the original height or more, I can no longer move the box a single 'droppable div' lower.

$( ".ru" ).droppable({
  activeClass: "active",
  hoverClass: "hover",
  drop: function(event, ui) {
    ui.draggable.position({
      of: $(this),
      my: 'top left',
      at: 'top left'
    });
  }
});

I hope that makes sense, basically to recreate the problem, resize the draggable box to 3x the height and try to drag it 1 div down.

jsfiddle: link

Thanks for any help.

Mike
  • 87
  • 8
  • So the jsfiddle version is behaving a little differently to the local copy on my browser. When the draggable box is 3 divs in height, its still selecting the 'middle' droppable div out of the 3 its covering but it will position correctly. When it's 2 divs in height, it will position half down between 2 divs. – Mike Dec 28 '15 at 11:45

1 Answers1

2

The my and at options take values in the order of 'horizontal-alignment vertical-alignment'. Default value is 'center', which is why the mistake in syntax has the result you describe in your comment. Simply switch the order from 'top left' to 'left top'.

UPDATED: I've also added a custom tolerance option for .droppable() so that hovering is activated on a droppable when the top of #box is over it.

$.ui.intersect = function(draggable, droppable, toleranceMode) {

  var draggableLeft, draggableTop,
    x1 = (draggable.positionAbs || draggable.position.absolute).left,
    y1 = (draggable.positionAbs || draggable.position.absolute).top + 15,
    x2 = x1 + draggable.helperProportions.width,
    y2 = y1 + draggable.helperProportions.height,
    l = droppable.offset.left,
    t = droppable.offset.top,
    r = l + droppable.proportions.width,
    b = t + droppable.proportions.height;

  return (l < x1 + (draggable.helperProportions.width) && 
    x2 - (draggable.helperProportions.width) < r && 
    t < y1 + 1 && 
    b > y1 - 1); 
};

$( "#box" ).draggable({
  revert: "invalid",
});

$( ".ru" ).droppable({
  hoverClass: "hover",
  tolerance: "custom", //added this line
  drop: function(event, ui) {
    ui.draggable.position({
      of: $(this),
      my: 'left top', //edited this line
      at: 'left top' //edited this line
    });
  }
});

Check out this UPDATED working fiddle: https://jsfiddle.net/joL53wkq/5/

digglemister
  • 1,477
  • 3
  • 16
  • 31
  • Thanks for that, it works quite well with the 'tolerance: pointer' addition, but can be a bit weird if the pointer is at the bottom of a 3x div high draggable since it will still position it from the left top. I didn't realize the droppable div goes off the vertical center of the draggable div, that could explain why it's acting like it is. Is there any way to change the location from vertical center to say the top center? – Mike Dec 28 '15 at 23:44
  • @Mike I've updated my answer to include a custom tolerance option that might suit what you want. Hope it helps and is not too late! – digglemister Dec 30 '15 at 20:48
  • That's perfect, thanks so much for all the effort. Now I just need to put aside some time to try and properly understand what you done there. ;) – Mike Dec 31 '15 at 02:40