-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathClickHide.js
More file actions
96 lines (77 loc) · 2.27 KB
/
ClickHide.js
File metadata and controls
96 lines (77 loc) · 2.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/**
* @author: +HampusAhlgren
*
* Click anywhere else but in the directive element and it will trigger
* the given function.
*
*/
var ClickHide = angular.module('ClickHide', []);
ClickHide.directive('clickHide', function( $document, $parse, $timeout ){
return{
link: function( $scope, element, attr ){
$scope._init = function(){
if(attr.chActivate){
$scope.$watch( attr.chActivate, $scope.onActivationChange );
}else{
// activate imediatly
$scope.listenForClick();
}
//clean up
$scope.$on('$destroy', function(){
$document.unbind('click', $scope.onClick);
});
}
$scope.onActivationChange = function( newValue ){
if( newValue == true ){
$scope.listenForClick();
}
// in the case that the user changed the activation
// condition without clicking outside the parentElement
// ex. Clicking close instead. We then wan't to make sure
// we unbind the click listener - otherwise we'll get some
// funky behaviour.
else if( newValue == false ){
$document.unbind('click', $scope.onClick);
}
}
$scope.listenForClick = function(){
$timeout(function(){
// Make sure we don't allow multiple listeners
// can't rely n the destroy always being run.
$document.unbind('click', $scope.onClick);
$document.on('click', $scope.onClick);
}, 10);
}
/**
* First click after activating.
*/
$scope.onClick = function( e ){
// check if the user has clicked outside of the
// element
if( !$scope._isDecendantOfParent(e.target, element) ){ // yes he did
// parse and execute the click
// action
$scope.$apply(function(){
$parse(attr.chClick)($scope);
});
$document.unbind('click', $scope.onClick); // now we don't have to listen anymore
}
}
/**
*
*/
$scope._isDecendantOfParent = function( decendantElement, parentElement ){
var currentParent = decendantElement;
while( currentParent.nodeName != 'BODY' ){
if( currentParent == parentElement[0] ){ return true }
currentParent = currentParent.parentNode;
// We're iterating inside a DOM fragment that's not
// attached to the DOM.
if( currentParent == null ) return true;
}
return false;
}
$scope._init();
}
}
});