Nayfin
Nayfin

Reputation: 395

Intricate drag and drop jquery UI

Update: Here is the final fiddle. Thanks Twisty. https://jsfiddle.net/natjkern/55n1Lg61/14/

Here is a mock up of my site http://jsfiddle.net/natjkern/pjq9wqLy/

On the right I have a fixed list of elements called #userList. This element must be set to overflow: auto, as the number of user elements is variable. I then need to drag a copy into dropzone, which again can vary in size, so it's container must be also set to overflow auto. I need the container to auto scroll when dragged element is dragged to edge to allow user to place element anywhere in dropzone. So far my best idea is to append to body first to escape the original auto overflow container then append to #dropzone on droppable({over:}). But this isn't really working out. Any UI experts out there that can give me a hand? Here is my code so far:

$(document).ready(function () {
    $('.moveMe').draggable({
        helper: "clone",
        appendTo: 'body',
        revert: 'invalid',
        scroll: true,

    });
    $('#dropZone').droppable({
        accept: '.moveMe',
        //here is where my problem arrises
        // I need #dropZoneCon to scroll to place 

        over: function (event, ui) {
            ui.helper.draggable.detach().appendTo($(this));
            $('#DropZone div').css('position','absolute');
            ui.helper.draggable.draggable('option', 'containment', 'parent');
        },
    /*    */
        drop: function (event, ui) {
            ui.helper.draggable.detach().appendTo($(this));
            $('#DropZone div').css('position','absolute');
            ui.helper.draggable.draggable('option', 'containment', 'parent');
        },
    });
});

Note: commenting out over: allow me to place element where I would like, but I really need the scrolling to work.

Upvotes: 1

Views: 313

Answers (1)

Twisty
Twisty

Reputation: 30903

This is a little clunky, but it does what you're looking to do.

http://jsfiddle.net/Twisty/55n1Lg61/5/

JQuery

$(document).ready(function() {
  var tEntered = false;
  $('.moveMe').draggable({
    helper: "clone",
    appendTo: 'body',
    revert: 'invalid',
    drag: function(e, u) {
      var curPos = u.offset;
      var $target = $("#dropZoneCon");
      var tVP = $target.offset();
      var tW = Math.floor($target.width());
      var tH = Math.floor($target.height());
      var pad = 20;
      var scrInc = 10;
      var x0 = tVP.top;
      var x1 = tVP.top + tH;
      var y0 = tVP.left;
      var y1 = tVP.left + tW;
      $("#dragInfo").html("Over #dropZone: " + tEntered + ", top: " +
        tVP.top + "/" + curPos.top + "/" + x1 + " left: " + tVP.left + "/" + curPos.left + "/" + y1);
      if (tEntered) {
        // Increase Scroll
        if (curPos.left >= (y1 - pad) && curPos.left <= y1) {
          $target.scrollLeft($target.scrollLeft() + scrInc);
        }
        if (curPos.top >= (x1 - pad) && curPos.top <= x1) {
          $target.scrollTop($target.scrollTop() + scrInc);
        }
        // Decrease Scroll
        if (curPos.left >= y0 && curPos.left <= (y0 + pad)) {
          $target.scrollLeft($target.scrollLeft() - scrInc);
        }
        if (curPos.top >= x0 && curPos.top <= (x0 + pad)) {
          $target.scrollTop($target.scrollTop() - scrInc);
        }
      }
    }
  });
  $('#dropZone').droppable({
    accept: '.moveMe',
    over: function(e, u) {
      tEntered = true;
    },
    out: function(e, u) {
      tEntered = false;
    },
    drop: function(event, ui) {
      ui.draggable.detach().appendTo($(this));
      $('#DropZone div').css('position', 'absolute');
      ui.draggable.draggable('option', 'containment', 'parent');
    },
  });
});

So we do a lot of the heavy lifting in the drag event since we can determine the position of the drag object from this event. In the drag event we define a number of variables:

  • curPos the current position of our draggable object in { top, left }
  • $target the dropZone container
  • tVP the Target View Port offset in { top, left }
  • tW & tH the Target's Width and Height
  • scrInc a value we will use to increase or decrease the scroll position
  • pad the amount of pixels to use as the edge detection of tVP
  • x0 & x1 are the tVP top edge and bottom edge
  • y0 & y1 are the tVP left edge and right edge

I defined tEntered outside of these functions, so I can access it from either draggable or droppable. Since droppable has over and out, we can use those to change this value.

Now, when tEntered is true, meaning we are dragging an object over the target, we look to see if the x and y might be within our padding. If they are we increase or decrease the scroll position.

I found this helpful: http://www.jqwidgets.com/community/topic/how-detect-area-dropped-inside-a-div-into-another-div/

This should allow you to do what you want unless I misunderstood. Comment if you have questions.

Upvotes: 1

Related Questions