1

I want to restrict basically the following implementation of an angular.js drag directive into the boundaries of a parent element. How do I do that?

Here is a jsbin that visualizes my issue: http://jsbin.com/maxife/3/edit?html,css,js,output

Maxim Zubarev
  • 2,403
  • 2
  • 29
  • 48

1 Answers1

4

You must modify the drag directive in order to achieve this,
Since event.pageX and event.pageY properties return the position of the mouse pointer relative to the left edge of the whole document, you need to:

  • Change these properties to be relative to the parent element
  • Look how it is done here: jQuery get mouse position within an element
    our event.offsetX and event.offsetY will provide us the position of the mouse clicked inside the span element:
<span my-draggable>Drag Me</span>
    Which is not what we are looking for, you have to get the parent element height and width attributes, and after you get them - then using the offsetX / offsetY for right positioning inside the parent div block.

How you get it into the directive? Use this: Get element parent height inside directive in AnguarJS

  • Another option is that we will limit the x,y vars inside mousemove function
  • This way you will only be able to move it inside the parent element, preventing from saving position outside of the element, using CSS.

    Again you will have to use the attributes of height and width from the parent element, but you will not have to touch the position or use offsets, just add before element.css({..}):

          if(x>27){
           x=27;
           }
          else if(x<0){
            x=0;
          }
          if(y>77){
            y=77;
          }
          else if(y<0){
            y=0;
          }
    

    I have done it manually, so you can have an example before using the parent attributes. You will have to take span width+height in consideration if you don't want some of the span element to get outside the div of course.


    The full module:

    angular.module('dragModule', [])
    .directive('myDraggable', ['$document', function($document) {
    return {
      link: function(scope, element, attr) {
        var startX = 0, startY = 0, x = 0, y = 0;
    
        element.css({
         position: 'absolute',
         border: '1px solid red',
         backgroundColor: 'lightgrey',
         cursor: 'pointer'
        });
    
        element.on('mousedown', function(event) {
          // Prevent default dragging of selected content
          event.preventDefault();
          startX = event.pageX - x;
          startY = event.pageY - y;
          $document.on('mousemove', mousemove);
          $document.on('mouseup', mouseup);
        });
    
        function mousemove(event) {
          y = event.pageY - startY;
          x = event.pageX - startX;
          if(x>27){
             x=27;
           }
          else if(x<0){
            x=0;
          }
          if(y>77){
            y=77;
          }
          else if(y<0){
            y=0;
          }
          element.css({
            top: y + 'px',
            left:  x + 'px'
          });
        }
    
        function mouseup() {
          $document.off('mousemove', mousemove);
          $document.off('mouseup', mouseup);
        }
      }
    };
    }]);
    

    In the JSbin: JSbin link

    Community
    • 1
    • 1
    Liadco
    • 414
    • 4
    • 12
    • I have been trying to use your module, but can't seem to have any luck with it. Would you mind posting a JSfiddle or codepen? – realappie Feb 14 '16 at 04:28
    • @5parc Sure, added [JSbin link](http://jsbin.com/zabugi/1/edit?html,css,js,output) – Liadco Feb 14 '16 at 16:25
    • Considering that this should be a directive, I was hoping for a more generic answer, as this solution would apply only for the one exact example i gave above, but if I change the positioning of the parent container, this directive will not work properly any more. I can see how this might be changed though to become generic enough, so I will accept this in some time if there won't be a better answer soon. – Maxim Zubarev Feb 14 '16 at 23:25
    • As I said, "I have done it manually" with the current x/y relevant for the example, but of course "you will have to use the attributes of height and width from the parent element" (and you have a link how to implement that to the directive) I just didn't dig too much inside, gave you the idea so you can complete the directive easily. Good luck :) – Liadco Feb 15 '16 at 14:23