Uri
Uri

Reputation: 26966

ng-click firing when selecting text or dragging

When using ng-click on a div:

<div ng-click="doSomething()">bla bla</div>

ng-click fires even if the user only selects or drags the div. How do I prevent that, while still enabling text selection?

Upvotes: 3

Views: 1512

Answers (2)

Ufuk A
Ufuk A

Reputation: 121

I had to deal with this, too, and came up with something much simpler. Basically you store the x-position on mousedown and then compare new x-position on mouseup:

ng-mousedown="setCurrentPos($event)"
ng-mouseup="doStuff($event)"

Function setCurrentPos():

var setCurrentPos = function($event) {
  $scope.currentPos = $event.offsetX;
}

Function doStuff():

var doStuff = function ($event) {
  if ($event.offsetX == $scope.currentPos) {
    // Only do stuff here, when mouse was NOT dragged
  } else {
    // Do other stuff, which includes mouse dragging
  }
}

Upvotes: 1

scarlz
scarlz

Reputation: 2512

In requiring something similar, where the usual text selection behavior is required on an element which should otherwise respond to ngClick, I wrote the following directive, which may be of use:

.directive('selectableText', function($window, $timeout) {
  var i = 0;      
  return {
    restrict: 'A',
    priority:  1,
    compile: function (tElem, tAttrs) {
      var fn = '$$clickOnNoSelect' + i++,
          _ngClick = tAttrs.ngClick;

      tAttrs.ngClick = fn + '($event)';

      return function(scope) {
        var lastAnchorOffset, lastFocusOffset, timer;

        scope[fn] = function(event) {
          var selection    = $window.getSelection(),
              anchorOffset = selection.anchorOffset,
              focusOffset  = selection.focusOffset;

          if(focusOffset - anchorOffset !== 0) {
            if(!(lastAnchorOffset === anchorOffset && lastFocusOffset === focusOffset)) {
              lastAnchorOffset = anchorOffset;
              lastFocusOffset  = focusOffset;
              if(timer) {
                $timeout.cancel(timer);
                timer = null;
              }
              return;
            }
          }
          lastAnchorOffset = null;
          lastFocusOffset  = null;

          // delay invoking click so as to watch for user double-clicking 
          // to select words
          timer = $timeout(function() {
            scope.$eval(_ngClick, {$event: event});  
            timer = null;
          }, 250);
        };
      };
    }
  };
});

Plunker: http://plnkr.co/edit/kkfXfiLvGXqNYs3N6fTz?p=preview

Upvotes: 2

Related Questions