Android 这是虫子吗?轻触一个元素可能导致另一个元素接收键盘焦点

Android 这是虫子吗?轻触一个元素可能导致另一个元素接收键盘焦点,android,iphone,mobile-safari,touch-event,fennec,Android,Iphone,Mobile Safari,Touch Event,Fennec,我正试图弄清楚,在Mobile Safari、Android浏览器和Firefox for Android(“Fennec”)中看到的效果是一个bug还是预期行为。基本上,问题在于元素在某些情况下可以接收键盘焦点,即使用户最初没有点击元素 这是一个可复制的测试用例: <!DOCTYPE html> <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8

我正试图弄清楚,在Mobile Safari、Android浏览器和Firefox for Android(“Fennec”)中看到的效果是一个bug还是预期行为。基本上,问题在于
元素在某些情况下可以接收键盘焦点,即使用户最初没有点击
元素

这是一个可复制的测试用例:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="viewport" content="width=device-width, user-scalable=no">
<style>
#screenCover {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    background-color: rgba(0, 0, 0, 0.3);
    z-index: 1;
}

#newItemInput {
    position: absolute;
    width: 200px;
    height: 20px;
}
</style>
</head>
<body>

<div id="screenCover"></div>
<input id="newItemInput" type="text">

<script type="text/javascript" language="JavaScript">
var screenCoverEl = document.getElementById("screenCover"),
    newItemInputEl = document.getElementById("newItemInput");

newItemInputEl.value = String(navigator.userAgent);

screenCoverEl.addEventListener("touchend", function (event) {
    // Move the <input> element in the way.
    newItemInputEl.style.top = (event.changedTouches[0].clientY - 10) + "px";
    newItemInputEl.style.left = (event.changedTouches[0].clientX - 10) + "px";

    // Hide the screen cover. Note that the screen cover was the original target of the tap.
    screenCoverEl.style.display = "none";
}, false);

newItemInputEl.addEventListener("click", function (event) {
    this.setSelectionRange(0, this.value.length);
}, false);
</script>
</body>
</html>

#电影封面{
位置:绝对位置;
排名:0;
右:0;
底部:0;
左:0;
背景色:rgba(0,0,0,0.3);
z指数:1;
}
#newItemInput{
位置:绝对位置;
宽度:200px;
高度:20px;
}
var screenCoverEl=document.getElementById(“screenCover”),
newItemInputEl=document.getElementById(“newItemInput”);
newItemInputEl.value=字符串(navigator.userAgent);
screenCoverEl.addEventListener(“触摸端”,函数(事件){
//将元素移到中间位置。
newItemInputEl.style.top=(event.changedTouches[0].clientY-10)+“px”;
newItemInputEl.style.left=(event.changedTouches[0].clientX-10)+“px”;
//隐藏屏幕盖。请注意,屏幕盖是水龙头的原始目标。
screenCoverEl.style.display=“无”;
},假);
newItemInputEl.addEventListener(“单击”),函数(事件){
此.setSelectionRange(0,此.value.length);
},假);

或直接在移动浏览器中:

在本例中,屏幕盖位于文档顶部,但在
触摸端
,屏幕盖被隐藏,并且
元素被移动到用户点击屏幕盖的位置。在Mobile Safari、Android浏览器和Fennec 13.0b1中,
元素莫名其妙地接收键盘焦点

我无法在更新版本的Fennec中测试这一点,因为它在模拟器中崩溃


这是错误还是预期的行为?

我想这是预期的行为

移动网络浏览器的开发者需要在小屏幕上对设计拙劣的网页进行特殊调整

如果网页不能正确缩放,UI元素很容易被另一层覆盖

允许click事件向下传播到各个层可以防止UI元素不可用

我没有任何文件支持这个理论

------编辑--------

在玩了你的代码之后,我意识到sceencover正在被删除,输入被移动到“touchstart”的触摸位置。然后输入在“触摸端”接收焦点

您可以通过在移动输入之前设置延迟来验证这一点。如果您的手指在输入之前被移除,它将不会接收焦点。当输入移动时,如果您仍在触摸屏幕,它将接收焦点

screenCoverEl.addEventListener("touchstart", function (event) {

screenCoverEl.style.display = "none";
setTimeout(function() {
        newItemInputEl.style.top = (event.touches[0].clientY - 10) + "px";
        newItemInputEl.style.left = (event.touches[0].clientX - 10) + "px";
    },250);


}, false);

触摸事件按以下顺序调用:touchstart、touchend、click。您需要知道触摸事件的touchstart是否发生在您的输入上。您可以隐式声明一个对象变量(这在javascript中是允许的)并将其初始化为false。在touchstart事件中,将其设置为true。然后在touchend和/或click事件中检查其值。下面的代码完全按照预期工作

    <script type="text/javascript" language="JavaScript">
    var screenCoverEl = document.getElementById("screenCover"),
    newItemInputEl = document.getElementById("newItemInput");

newItemInputEl.value = String(navigator.userAgent);


screenCoverEl.addEventListener("touchstart", function (event) {
    // Move the <input> element in the way.

    screenCoverEl.style.display = "none";

    newItemInputEl.style.top = (event.touches[0].clientY - 10) + "px";
    newItemInputEl.style.left = (event.touches[0].clientX - 10) + "px";

    // Hide the screen cover. Note that the screen cover was the original target of the tap.

}, false);

newItemInputEl.touchStartedHere = false; // remember if a touch event started on this input
newItemInputEl.addEventListener("touchstart", function (event) {

    this.touchStartedHere = true; //set true if did..

}, false);
newItemInputEl.addEventListener("click", function (event) {


    if(this.touchStartedHere){ // do what you want if touch started here
        this.setSelectionRange(0, this.value.length);  
    }else{  // prevent from receiving focus if touch didn't start here.
        this.blur();
    }
    this.touchStartedHere = false;  // reset to false to prepare for next touch event.

}, false);
</script>

var screenCoverEl=document.getElementById(“screenCover”),
newItemInputEl=document.getElementById(“newItemInput”);
newItemInputEl.value=字符串(navigator.userAgent);
screenCoverEl.addEventListener(“touchstart”),函数(事件){
//将元素移到中间位置。
screenCoverEl.style.display=“无”;
newItemInputEl.style.top=(event.touch[0].clientY-10)+“px”;
newItemInputEl.style.left=(event.touch[0].clientX-10)+“px”;
//隐藏屏幕盖。请注意,屏幕盖是水龙头的原始目标。
},假);
newItemInputEl.touchStartedHere=false;//还记得此输入上是否启动了触摸事件吗
newItemInputEl.addEventListener(“touchstart”,函数(事件){
this.touchtstartedhere=true;//如果有,则设置为true。。
},假);
newItemInputEl.addEventListener(“单击”),函数(事件){
如果(this.touchtstartedhere){//如果在此处开始触摸,则执行所需操作
此.setSelectionRange(0,此.value.length);
}否则{//如果触摸未在此处开始,将阻止接收焦点。
这个。blur();
}
this.touchtstartedhere=false;//重置为false以准备下一次触摸事件。
},假);

是的,我认为这是一个bug,可能与这里的内容相同:
如果是这样的话,那么这个链接有一些其他人已经尝试过的解决方法,你可以尝试

对于我遇到这个问题的实际网页(以几种不同的方式),我使用谷歌的方法来避免touchend和click之间约300毫秒的延迟。因此,实际的网页实际上正在更新
touchend
上的文档,但我在准备测试用例时犯了一个错误。我已经更新了问题。在
touchend
上设置超时,然后进行更改,似乎无法解决问题?我修改了这个想法,将最后一个
touchstart
事件保存在全局文件中。每当
newitemputel
接收到
focus
事件时,它会检查上一次
touchstart
事件的目标是否为输入元素。如果没有,则调用blur()以放弃键盘焦点:这种方法在iOS 5.0、5.1和6.0中有效,但在iOS 4.3.2中不起作用。事实证明,iOS 4.3.2 Mobile Safari没有向输入元素发送触摸事件:因此我添加了一个
单击
捕获侦听器来重置全局设置,它起了作用:这个问题似乎与不同,但看到错误报告和相应的讨论让我相信这确实是一个错误。谢谢你的链接。