我们有一个显示弹出窗口的指令, 在弹出窗口中,加载了一个模板,其中包含一个捕获文档中所有点击的指令。
当发生这种情况时,它会广播一个事件来关闭弹出窗口,并取消绑定$document
上的事件。
这是捕获文档点击的指令。
aOS.directive('catchOutsideClick',
[
'$document',
'eventsService',
function CatchOutsideClickDirective($document, eventsService) {
var CatchClick = function CatchClick(scope, element, attrs) {
// Check if there was clicked on parent or one of its children
function isDescendant(parent, child) {
var node = child.parentNode;
while (node !== null) {
if (node === parent) {
return true;
}
node = node.parentNode;
}
return false;
}
// Done clicking
var onOutsideClick = function onOutsideClick(event) {
var clickedItem = event.target;
if (!isDescendant(element[0], clickedItem) && element[0] !== clickedItem) {
eventsService.publish('clicked-outside-popup', element[0]);
$document.unbind('click', onOutsideClick);
}
};
// Catch clicks!
$document.bind('click', onOutsideClick);
};
return {
restrict: 'A',
scope: false,
link: CatchClick
};
}
]
);
这是加载弹出窗口的html:
<div id="header" ng-controller="framework.header">
<div data-ng-include="popupTemplate"></div>
</div>
为简单起见,让我们说控制器framework.header
将$scope.popupTemplate
切换到下面显示的html路径:
<div ng-controller="user.profle" catch-outside-click>
<!-- loads of content -->
</div>
模板的包含似乎完美无缺,但这是我们现在看到的行为:
popupTemplate
的按钮,然后将其加载到弹出窗口中。 目前我不知道如何测试是否触发了第一个或第二个点击处理程序。
任何人都知道如何缩小范围,或者我做错了什么,或者只是指出我如何调试此问题以查看触发了哪个事件处理程序。
答案 0 :(得分:0)
我们现在能够解决这个问题:
aOS.directive('catchOutsideClick',
[
'$document',
'eventsService',
function CatchOutsideClickDirective($document, eventsService) {
...
setTimeout( function() {
$document.bind('click', onOutsideClick);
}, 0);
...
}
]);
看起来setTimeout(绑定到click)中的代码在下一个'循环'中执行(尽管timeout设置为0),其中包含模板的单击处理相同(上一个)循环,即catch-click指令初始化的位置。至少那是我在调查这个问题时得到的感觉。
如果有人能够证实这一点或有更合理的解释(也许是更合理的解决方案),我们仍然渴望学习: - )