Oscar Godson
Oscar Godson

Reputation: 32716

jQuery UI draggable wont go back to first point

I have a jQuery UI draggable element. It's extremely simple. It's just a div (container) with another div inside (draggable piece) set to a grid. The problem is after I move the element one time I can't go back to the first point. If i change the grid size it works, but I need it to work on this grid as it's matching some element below it

Relevant JS:

 $('<div class="slider_wrap"><div class="slider"></div></div>').appendTo('#chart');

 $('#chart .slider')
    .draggable({
      containment:'parent',
      grid:[distanceBetweenPoints,0],
      opacity: 0.25
    })
    .bind('mousedown', function(e, ui){
      // bring target to front
      $(e.target.parentElement).append( e.target );
    })
    .bind('drag', function(e, ui){
      // update coordinates manually, since top/left style props don't work on SVG
      e.target.setAttribute('x', ui.position.left);
    })
    .bind('dragstop',function(e, ui){
      //a = true offset of slider piece
      var a = ui.position.left + distanceBetweenPoints;
      var b = containerWidth;
      var c = thePoints.length;
      var d = b / c;
      var x = a / d;
      //Since the points are in an array which starts at 0, not 1, we -1 from the currentPoint
      console.log(x)
      var currentPoint = Math.round(x)-1;
      thisPointIndex = currentPoint;
      chart.series[0].data[currentPoint].select(true);
    });

Any ideas?

Example: http://jsbin.com/ucebar

Upvotes: 2

Views: 1186

Answers (3)

RonnieSan
RonnieSan

Reputation: 182

I was able to solve it with the following:

.draggable({
  ...
  drag : function(event, ui) {
    ui.position.left = Math.round(ui.position.left / distance_between_points) * distance_between_points;
  }
});

Upvotes: 0

Brock Adams
Brock Adams

Reputation: 93443

You're using a fractional grid size, for example 39.7 px. So, with each drag, the div gets offset a pixel to the left. This means that position zero quickly becomes unavailable:

That is: at point 1, ui.position.left will be 38 pixels or less.
Since moving the minimum jump (39.7px) -- towards point 0 -- will take the div outside the bounding rectangle, that move is not allowed.

And, using the nearest integer for grid size will quickly result in misalignment between the grid and the data points.

One way around all this is to:

  1. Delete the grid:[distanceBetweenPoints,0], parameter.

  2. Instead, snap the div upon drag stop, like so:

    /*--- Snap to nearest grid.
    */
    var gridPos     = Math.round ( 
                        Math.round (ui.position.left / distanceBetweenPoints) 
                        * distanceBetweenPoints
                    );
    var delta       = gridPos - ui.position.left;
    var newOffset   = $(this).offset ().left  +  delta;
    $(this).offset ( {left: newOffset} );
    


See it in action at jsBin.

Upvotes: 1

Pelshoff
Pelshoff

Reputation: 1464

I didnt have time to work out a real solution, but I found that if you drag and drop the slider moves slightly more to the left each time. The reason it can't go back into first place is that after the first drop, there is not enough room anymore. Good luck!

Upvotes: 0

Related Questions