我正在尝试处理按钮单击。“按钮”是一个自定义 div,也可以包含子项。当用户在元素内点击和释放时,点击回调应该触发。如果用户在内部单击然后在外部拖动和释放,则处理程序不应触发。我需要让它在桌面和移动设备上都能正常工作,因此我正在使用mousedown/mouseup
和touchstart/touchend
事件。
即使用户在外面释放,我也需要将按钮类从“按下”更改为“正常”,因此我需要添加一个侦听器来捕获文档上的释放事件:
var $myElement = $("#myelement"); //This is a div and can also contain children.
$myElement.on("mousedown touchstart", function(e){
$(this).addClass("pressed");
$(document).on("mouseup touchend", function listener(e){
$myElement.removeClass("pressed");
$(document).off("mouseup touchend", listener);
var $target = $(e.target);
if ($target.is($myElement) || $target.parents().is($myElement)){
//FIXME
alert("Inside!");
//do something here
return false;
} else {
//FIXME
alert("Outside!");
//let event bubble
}
});
return false;
});
它在点击时可以正常工作,但在触摸事件中不能按预期工作。我已经在 Chrome for Android 中对此进行了测试,当按下元素时,然后拖出“内部!” 显示警报。
问题是在这种情况下:
if ($target.is($myElement) || $target.parents().is($myElement)){
我正在尝试检查touchend
事件是否发生在按钮或任何孩子中。如果按钮没有子按钮,当单击它然后在外部释放时,OR 子句的第一部分解析为 true。如果按钮有子项并且我在子项中单击,然后在屏幕的任何其他部分释放,则子句的第二部分为真。
这段代码有什么问题?
提前致谢。
更新
我也在 BlackBerry 10 中对其进行了测试,结果相同。显然,touchend
事件的目标是按钮(或孩子),即使我点击了外面。这是它应该如何工作的吗?
更新
这就是原因。这就是W3C 文档关于该事件的说法:
此事件的目标必须与在此触摸点放置在表面上时接收到 touchstart 事件的元素相同,即使该触摸点已经移出目标元素的交互区域。
这对我来说毫无意义,但无论如何这解释了我的问题。我假设该touchend
事件将在手指被释放的元素上调用。是否可以使用不同的方法检测到手指在外面的释放?
更新
我试图获取 的坐标touchevent
以使用document.elementFromPoint
. 问题是这个事件不包含坐标(changedTouches
和touches
列表是空的)。我已经在调试器中彻底检查了事件,除了原始事件之外,没有办法从中检索坐标。然后我想我可以缓存最后一个touchmove
事件并从那里获取坐标,但是这个事件又没有自己的坐标!为什么这两个事件在它们无用的情况下仍然存在?我已经在 iOS、Android 和 BB10 中测试了这种方法,结果相同。
我已经放弃了。即使用户在外面点击,我也会调用回调。我不敢相信这是 2013 年的家伙,而且没有(简单的)方法可以做到这一点?我可以使用拖放 api,但据此它在移动设备上不受支持(必须喜欢移动 Web 开发)。