Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make jQuery draggable with fixed X and Y axis?

I am wondering if there is a way to make the jQuery draggable to only drag straight up, down and left, right. I want to prevent the user from dragging a div diagonally. Using the grid option in the draggable UI is not possible in my situation.

http://jqueryui.com/demos/draggable/#constrain-movement

How is this possible?

Thanks!

like image 728
Fred Bergman Avatar asked Oct 15 '09 15:10

Fred Bergman


3 Answers

jQueryUI supports two methods for controlling dragging on a fixed track.

  1. You can use the axis option to limit dragging movement on a particular axis. For instance:

    $('.draggable_horiz').draggable({axis: "x"});
    

    More Info here: http://api.jqueryui.com/draggable/#option-axis

  2. You can constrain movement using an element or an array of x/y coordinates that define a bounding box.

        $('.draggable_track').draggable({ containment: [0,0, 250, 24] });
    
    or to just use the parent element as a reference track:
    
        $('.draggable_track').draggable({ containment: 'parent' });
    

    More info here: http://api.jqueryui.com/draggable/#option-containment

I hope this helps.

like image 138
mobilemonkey Avatar answered Nov 16 '22 02:11

mobilemonkey


I wrote a plugin that allows moving a draggable in both axes. It gets the job done but it would be better-implemented as a jQuery UI widget rather than a simple jQuery plugin.

Hosted Demo: http://jsbin.com/ugadu/1 (Editable via http://jsbin.com/ugadu/1/edit)

Plugin code:

$.fn.draggableXY = function(options) { 
  var defaultOptions = { 
    distance: 5, 
    dynamic: false 
  }; 
  options = $.extend(defaultOptions, options); 

  this.draggable({ 
    distance: options.distance, 
    start: function (event, ui) { 
      ui.helper.data('draggableXY.originalPosition', ui.position || {top: 0, left: 0}); 
      ui.helper.data('draggableXY.newDrag', true); 
    }, 
    drag: function (event, ui) { 
      var originalPosition = ui.helper.data('draggableXY.originalPosition'); 
      var deltaX = Math.abs(originalPosition.left - ui.position.left); 
      var deltaY = Math.abs(originalPosition.top - ui.position.top); 

      var newDrag = options.dynamic || ui.helper.data('draggableXY.newDrag'); 
      ui.helper.data('draggableXY.newDrag', false); 

      var xMax = newDrag ? Math.max(deltaX, deltaY) === deltaX : ui.helper.data('draggableXY.xMax'); 
      ui.helper.data('draggableXY.xMax', xMax); 

      var newPosition = ui.position; 
      if(xMax) { 
        newPosition.top = originalPosition.top; 
      } 
      if(!xMax){ 
        newPosition.left = originalPosition.left; 
      } 

      return newPosition; 
    } 
  }); 
}; 
like image 33
brianpeiris Avatar answered Nov 16 '22 01:11

brianpeiris


use the drag event to your advantage

$('.selector').draggable({
   drag: function(event, ui) { ... }
});

i'm not 100% sure how, but inside here, you can do a check on the coordinates. as ~jack-laplante said, this is where you would compare. if the coordinates are closer to the x axis than the y, change the axis to x

//setter
$('.selector').draggable('option', 'axis', 'x');

if the other way around change it to y. this will get you a snapping motion to always have the item either on the x axis or the y axis (from the starting point). you'd have to do a check to leave the item wherever it is if the axis was say (x+n,y+n), but it would be pretty impressive if someone got more than a few pixels staying on the |x|=|y| line.

you didn't specify if the axes always remain where they originally started or if they change depending on where the draggable item is on drag start (like if you move it a little bit, then let go, and try to drag it some more). there's a start: and end: event too that could help you with that part.

what exactly are you trying to drag that can't go diagonal, but can go left, right, up, and down?

like image 25
Brandon Henry Avatar answered Nov 16 '22 03:11

Brandon Henry