检测是否在元素外部点击(必须支持在覆盖元素中点击)
Detect if clicking outside of element (Must support clicking in overlay elements)
目前我找到的最佳解决方案:
ko.bindingHandlers.clickedIn = (function () {
function getBounds(element) {
var pos = element.offset();
return {
x: pos.left,
x2: pos.left + element.outerWidth(),
y: pos.top,
y2: pos.top + element.outerHeight()
};
}
function hitTest(o, l) {
function getOffset(o) {
for (var r = { l: o.offsetLeft, t: o.offsetTop, r: o.offsetWidth, b: o.offsetHeight };
o = o.offsetParent; r.l += o.offsetLeft, r.t += o.offsetTop);
return r.r += r.l, r.b += r.t, r;
}
for (var b, s, r = [], a = getOffset(o), j = isNaN(l.length), i = (j ? l = [l] : l).length; i;
b = getOffset(l[--i]), (a.l == b.l || (a.l > b.l ? a.l <= b.r : b.l <= a.r))
&& (a.t == b.t || (a.t > b.t ? a.t <= b.b : b.t <= a.b)) && (r[r.length] = l[i]));
return j ? !!r.length : r;
}
return {
init: function (element, valueAccessor) {
var target = valueAccessor();
$(document).click(function (e) {
if (element._clickedInElementShowing === false && target()) {
var $element = $(element);
var bounds = getBounds($element);
var possibleOverlays = $("[style*=z-index],[style*=absolute]").not(":hidden");
$.each(possibleOverlays, function () {
if (hitTest(element, this)) {
var b = getBounds($(this));
bounds.x = Math.min(bounds.x, b.x);
bounds.x2 = Math.max(bounds.x2, b.x2);
bounds.y = Math.min(bounds.y, b.y);
bounds.y2 = Math.max(bounds.y2, b.y2);
}
});
if (e.clientX < bounds.x || e.clientX > bounds.x2 ||
e.clientY < bounds.y || e.clientY > bounds.y2) {
target(false);
}
}
element._clickedInElementShowing = false;
});
$(element).click(function (e) {
e.stopPropagation();
});
},
update: function (element, valueAccessor) {
var showing = ko.utils.unwrapObservable(valueAccessor());
if (showing) {
element._clickedInElementShowing = true;
}
}
};
})();
首先查询所有具有z-index或绝对位置的可见元素。然后,它将这些元素与我想要隐藏的元素进行碰撞测试。如果是命中,我会计算一个新的边界,考虑到覆盖边界。
它不是坚如磐石,但有效。如果您看到上述方法的问题,请随时发表评论
老问题
我用的是Knockout但这一般适用于DOM/Javascript
我试图找到一个可靠的方法,如果检测到你点击一个元素之外。我的代码看起来像这样
ko.bindingHandlers.clickedIn = {
init: function (element, valueAccessor) {
var target = valueAccessor();
var clickedIn = false;
ko.utils.registerEventHandler(document, "click", function (e) {
if (!clickedIn && element._clickedInElementShowing === false) {
target(e.target == element);
}
clickedIn = false;
element._clickedInElementShowing = false;
});
ko.utils.registerEventHandler(element, "click", function (e) {
clickedIn = true;
});
},
update: function (element, valueAccessor) {
var showing = ko.utils.unwrapObservable(valueAccessor());
if (showing) {
element._clickedInElementShowing = true;
}
}
};
它的工作原理是同时监听点击目标元素和文档。如果你点击文档而不是目标元素,你就点击它的外部。这是有效的,但是,不是覆盖项目,如日期选择器等。这是因为它们不在目标元素中,而是在主体中。我能解决这个问题吗?是否有更好的方法来确定是否在元素外部点击?
edit:这种方法有效,但只有当覆盖层小于我想要监视的元素
ko.bindingHandlers.clickedIn = {
init: function (element, valueAccessor) {
var target = valueAccessor();
$(document).click(function (e) {
if (element._clickedInElementShowing === false) {
var $element = $(element);
var pos = $element.offset();
if (e.clientX < pos.left || e.clientX > (pos.left + $element.width()) ||
e.clientY < pos.top || e.clientY > (pos.top + $element.height())) {
target(false);
}
}
element._clickedInElementShowing = false;
});
$(element).click(function (e) {
e.stopPropagation();
});
},
update: function (element, valueAccessor) {
var showing = ko.utils.unwrapObservable(valueAccessor());
if (showing) {
element._clickedInElementShowing = true;
}
}
};
我想要一个更可靠的方法
我通常是这样解决的:
http://jsfiddle.net/jonigiuro/KLxnV/$('.container').on('click', function(e) {
alert('hide the child');
});
$('.child').on('click', function(e) {
alert('do nothing');
e.stopPropagation(); //THIS IS THE IMPORTANT PART
});
我不知道你的叠加项是如何生成的,但你总是可以检查点击目标是否是你想要限制点击的元素的子元素。
相关文章:
- 未能加载,因为找不到支持的源.当播放HTML5音频元素时
- 拖放具有触摸支持的元素
- Masonry v3 在追加元素时是否仍然支持飞入过渡
- 针对图片元素或 srcset 支持的 Javascript 测试
- 使用 JavaScript 更改网页元素的支持 Bean 的值
- “间歇”;jqLite不支持通过选择器查找元素"当使用RequireJS加载AngularJS时
- 如何检测对禁用元素上事件的支持
- 不支持的HTML5元素和属性的JavaScript解决方法
- 如何检查svg<g>元素支持css转换
- jQuery:输入元素's类型不支持选择
- 检查元素是否合法地支持src属性或innerHTML
- 检测是否在元素外部点击(必须支持在覆盖元素中点击)
- 寻找支持svg元素绑定的js框架
- FirefoxOS是否支持HTML5 data元素?
- 如何检测浏览器对“图片”的支持元素
- 哪些浏览器支持在input[type="file"]元素上触发click事件
- 如何在模板标签中找到元素,需要在单个解决方案中支持所有浏览器
- 按类隐藏元素(只支持Javascript,不支持Jquery)
- knockout.js是否支持html元素之间的绑定?
- 哪些HTML元素支持'target'属性