I am trying to find a pure Angular way of determining if a clicked element is a child of another. In jQuery I would do has() but not sure which way to do it in Angular besides running through all the children and doing a compare.
jQuery:
if($(someelement).has(another)) { };
You could use the methods provided by AngularJs built-in jqLite http://docs.angularjs.org/api/angular.element "jqLite is a tiny, API-compatible subset of jQuery that allows Angular to manipulate the DOM"
You could go the other way around.
Instead of asking whether B is a child of A, you can ask whether A is an ancestor of B:
function isAncestor(ancestor, element) {
var parent = element.parentNode;
while (parent && parent!=ancestor) {
parent = parent.parentNode;
}
return parent==ancestor;
}
I'm going to put this here, as i'm trying to solve the same problem and thought it might be useful to someone else, even though it's not a strict replacement for has().
My first solution was to use Element.getBoundingClientRect().
If you're dealing with a rectangular target you can check the x and y of the click event against the bounding rect of element (which is an angular.element)
$document.bind('click', function(evt) {
var x = evt.x,
y = evt.y,
rect = element[0].getBoundingClientRect();
if(x > rect.left && x < rect.right && y > rect.top && y < rect.bottom) {
//you've clicked somewhere in the element
}
});
IE8+ works fine, but there's a minor bug in 5-7
http://www.quirksmode.org/dom/w3c_cssom.html
Annoyingly if your element contains other elements that don't affect it's width/height that won't work. But you could use this (slightly hacky) solution
link: function(scope, element, attrs) {
var clicked = false;
element.on('click', eClickHandler);
$document.on('click', clickHandler);
function eClickHandler(event) {
clicked = true;
$timeout(function() {
clicked = false;
});
}
function clickHandler(event) {
if(!clicked) {
// click occurred outside
}
}
}