Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
106 views
in Technique[技术] by (71.8m points)

javascript - Click everywhere but here event

Was wondering how I would implement a 'Click everywhere but on this element' event.

I have something that you can compare to a list of files in a file explorer. You can select certain elements but if you click outside the element controller it needs to deselect everything.

enter image description here

Added a screenshot to make it more clear. So what I want to do is that if I click anywhere but on the language elements it should fire an event.

Update

To clarify I am not asking how I can do this with jQuery.

question from:https://stackoverflow.com/questions/12931369/click-everywhere-but-here-event

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

EDIT: There were a couple of problems in this old, old answer.

*Also: Marking Community Wiki (no points for me) because errors

  1. N calls for N uses of the directive. This probably isn't desirable for uses within the same scope with matching expressions.

  2. NOTHING WAS TEARING DOWN THE EVENT HANDLERS!!!! BAD! BAD! BAD!

So, I'm updating this answer. Hopefully it didn't cause anyone too much trouble.

Updated answer

Here's a new plunker with those issues fixed ... there are likely other things that individual application developers will run into. This is just an example of how to handle this problem.

app.factory('clickAnywhereButHereService', function($document){
  var tracker = [];
  
  return function($scope, expr) {
    var i, t, len;
    for(i = 0, len = tracker.length; i < len; i++) {
      t = tracker[i];
      if(t.expr === expr && t.scope === $scope) {
        return t;    
      }
    }
    var handler = function() {
      $scope.$apply(expr);
    };
    
    $document.on('click', handler);
    
    // IMPORTANT! Tear down this event handler when the scope is destroyed.
    $scope.$on('$destroy', function(){
      $document.off('click', handler);
    });
    
    t = { scope: $scope, expr: expr };
    tracker.push(t);
    return t;
  };
});

app.directive('clickAnywhereButHere', function($document, clickAnywhereButHereService){
  return {
    restrict: 'A',
    link: function(scope, elem, attr, ctrl) {
      var handler = function(e) {
        e.stopPropagation();
      };
      elem.on('click', handler);
      
      scope.$on('$destroy', function(){
        elem.off('click', handler);
      });
      
      clickAnywhereButHereService(scope, attr.clickAnywhereButHere);
    }
  };
});

Original answer (with fixes for teardown of event handlers)

You were close with the one answer you've found, but I've put together a plunk for you to show you what it was missing.

app.directive('clickAnywhereButHere', function($document){
  return {
    restrict: 'A',
    link: function(scope, elem, attr, ctrl) {
      var elemClickHandler = function(e) {
        e.stopPropagation();
      };
      
      var docClickHandler = function() {
        scope.$apply(attr.clickAnywhereButHere);
      };
      
      elem.on('click', elemClickHandler);
      $document.on('click', docClickHandler);
      
      // teardown the event handlers when the scope is destroyed.
      scope.$on('$destroy', function() {
        elem.off('click', elemClickHandler);
        $document.off('click', docClickHandler);
      });
    }
  }
})

HTML

<a click-anywhere-but-here="clickedSomewhereElse()" 
  ng-click="clickedHere()">Don't Click Me!</a>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...