【发布时间】:2014-01-28 17:50:20
【问题描述】:
我们有一个显示弹出窗口的指令, 在弹出窗口中加载了一个模板,其中包含一个捕获文档中所有点击的指令。
当发生这种情况时,它会广播一个事件以关闭弹出窗口,并在 $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的按钮并将其加载到弹出div 中。 - 很好地触发 catch-outside-click 指令并在文档上绑定 clickhandler
- 在弹出窗口内单击不会执行任何操作(正如在指令中测试过的那样),但在弹出窗口外单击可以很好地关闭弹出窗口,因为它会广播在标头控制器中捕获的事件。
- 单击页面中的任意位置不会再次触发该指令,因此我们认为它已正确解除绑定。
- 除非您单击按钮再次打开弹出窗口。这似乎既绑定了一个新的文档点击事件,又立即触发了点击处理程序(这让我觉得它触发了第一个点击处理程序)。
目前我不知道如何测试它是触发第一个还是第二个 clickhandler。
任何人都知道如何缩小范围,或者我做错了什么,或者只是指出我如何调试这个问题以查看触发了哪个事件处理程序。
【问题讨论】:
标签: javascript angularjs event-handling