0

I have sort of this in a directives link function

angular.module('app', [])
  .directive('myDirective', function($document){
    return {
      link: function($scope, element){

        $document.on('click', function(event){
          var childElementWasClicked = element.find(event.target).length > 0;
          if(childElementWasClicked) return;
          $scope.hide();
        });

     }
   }
}

So I get this doesn't work beacuse of jquery lite's limitations, but I would really like to solve this without using jquery (full). I read this where they seem to solve finding with classes but I can't figure out how to solve it when having a element object like the event.target.

All help would be appreciated!

Community
  • 1
  • 1
Gustav
  • 3,408
  • 4
  • 24
  • 41
  • It's the $document service. its injected in the directive – Gustav Nov 04 '15 at 14:19
  • replace `find` by `querySelector` without testin length : [Element.querySelector()](https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelector) – Anonymous0day Nov 04 '15 at 14:46

3 Answers3

0

Nested child search to see if the target is the actual child of the element.

function find ( parent, child ){
    var selector = (child.id || child.className) ? (child.id ? "#" + child.id : "." + child.className) : child.nodeName,
        children = parent.querySelectorAll( selector ),
        isChild = false,
        item;

    for(var i = 0, l = children.length; i<l; i++){
        item = children[i];
        if( child.isEqualNode(item) ) {
            isChild = true;
            break;
        }
    }

    return isChild;
}
Stevanicus
  • 7,561
  • 9
  • 49
  • 70
  • 1
    not sure this will work because of `event.target.id` ! miss `#` – Anonymous0day Nov 04 '15 at 14:40
  • @Anonymous0day - thanks! You're right, edited my answer :) – Stevanicus Nov 04 '15 at 14:42
  • But your first approach was much better, according OP question : `element.querySelector(event.target)` – Anonymous0day Nov 04 '15 at 14:46
  • querySelector only excepts a string as it's argument https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector – Stevanicus Nov 04 '15 at 14:47
  • And also this doesn't cover the scenario if the class on the target exist on different elements as well? class is still to unspecific – Gustav Nov 04 '15 at 14:52
  • The querySelector example only searches child elements – Stevanicus Nov 04 '15 at 14:53
  • if the target element for exampel has the classname `"list-item foo"`, but it wasn't actually a child of `element`. However there are child elements of `element` that do contain `"list-item foo"`. Then it would return true, even though it wasn't a child element that was clicked, right? – Gustav Nov 04 '15 at 14:56
  • That's difficult to tell as you didn't specify what element is in your question – Stevanicus Nov 04 '15 at 14:57
  • Sorry yes, I was lazy. It is the second parameter to link-function. I'll edit question – Gustav Nov 04 '15 at 14:59
  • Updated answer if you need to check more specifically re: the actual html-element itself – Stevanicus Nov 04 '15 at 15:15
0

I ended up looking at the source code of this component and did it similar to the way that one is done, which is basically:

$document.on('click', function(event){
  var target = event.target.parentElement;
  var parentFound = false;
  while(angular.isDefined(target) && target !== null && !parentFound){
     if(target === element[0]){
       parentFound = true;
     }
     target = target.parentElement;
  }
  if(parentFound) return;
  $scope.hide();
});
Gustav
  • 3,408
  • 4
  • 24
  • 41
0

One solution possible could be : ( based on element, no class or id)

$document.on('click', function(event){
   var children = Array.prototype.slice.call(element.querySelectorAll('*'));
   var childElementWasClicked = children.indexOf(event.target) != -1;
   if(childElementWasClicked) return;
   $scope.hide();
});

Below a working test.

var element = $('#d0')[0];

$(document.body).on('click' , function(event){ // <-- just to simulate jqueryLite

    var children = Array.prototype.slice.call(element.querySelectorAll('*'));
    var childElementWasClicked = children.indexOf(event.target) != -1;
    
  if(childElementWasClicked) {
      var id = children[children.indexOf(event.target)].id;
      $(this).append($('<div class="dbg">you clicked on : ' +  id + '</div>')
      .delay(1000).hide(777));
    };
  

});
div{
  border : solid 1px #EEE;
  margin-left : 5px;
  padding : 3px;
  font-size : 0.8em;
  }
.dbg{
  position : absolute;
  top:0;
  border : solid 1px red;
  background : #FFF;
  }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='d0'>
  <div id='d0.0'>0.0</div>
  <div id='d0.1'>0.1</div>
  <div id='d0.2'>0.2
    <div id='d0.2.0'>0.2.0</div>
    <div id='d0.2.1'>0.2.1</div>
    <div id='d0.2.2'>0.2.2</div>
    <div id='d0.2.3'>0.2.3</div>
  </div>
  <div id='d0.3'>0.3</div>
</div>
<div id='d1'>
  <div id='d1.0'>1.0</div>
  <div id='d1.1'>1.1</div>
  <div id='d1.2'>1.2
    <div id='d1.2.0'>1.2.0</div>
    <div id='d1.2.1'>1.2.1</div>
    <div id='d1.2.2'>1.2.2</div>
    <div id='d1.2.3'>1.2.3</div>
  </div>
  <div id='d1.3'>0.3</div>
</div>
Anonymous0day
  • 3,012
  • 1
  • 14
  • 16