2012-06-16 48 views
2

我想弄清楚在移动Safari,Android浏览器和Android的Firefox(“Fennec”)中看到的效果是一个错误或预期的行为。基本上,问题是在某些情况下,即使<input>元素最初未被用户点击,<input>元素也可以在某些情况下接收键盘焦点。这是一个错误?点击一个元素可能会导致不同的元素接收键盘焦点

这里是一个可再现的测试案例:

<!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> 

http://jsfiddle.net/f7TKc/2/

在移动浏览器

或者直接:

http://fiddle.jshell.net/f7TKc/2/show/

在这个例子中,屏幕盖位于上方该文档,但在touchend上,屏幕封面被隐藏,并移动了元素<input>到用户点击屏幕盖的地方。在Mobile Safari,Android Browser和Fennec 13.0b1中,<input>元素莫名其妙地收到了键盘焦点。

我不能在较新版本的Fennec中测试它,因为它在模拟器中崩溃。

这是一个错误或预期的行为?

+1

HTTP ://code.google.com/p/android/issues/detail?id = 6721? – Slartibartfast

回答

1

是的,我认为这是一个错误,这可能是在同一行的位置: http://code.google.com/p/android/issues/detail?id=6721,如果它是这样,那么该链接有几个解决方法等已经尝试了,你可以试试

+0

此问题似乎与[6721](http://code.google.com/p/android/issues/detail?id=6721)不同,但看到该错误报告和相应的讨论使我相信这确实是一个错误。谢谢你的链接。 –

0

我想这是预期的行为。

移动网络浏览器的开发人员需要为小型显示器上设计不佳的网页做特殊调整。

如果网页无法正确缩放,UI元素很容易被其他图层覆盖。

允许单击事件向下传播通过图层将防止UI元素无法使用。

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

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

与您的代码玩弄后,我意识到,sceencover被删除,输入在“touchstart移动到触摸位置”。输入然后在“touchend”处接收焦点。

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

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); 
+0

对于我遇到此问题的实际网页(以几种不同的方式),我正在使用Google的[快速按钮技术](https://developers.google.com/mobile/articles/fast_buttons)以避免〜300ms touchend和click之间的延迟。所以,实际的网页实际上是更新'touchend'上的文档,但是我在编写测试用例时犯了一个错误。我已经更新了这个问题。在'touchend'上设置一个超时后进行更改似乎不能解决问题。 –

0

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

<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> 
+0

我修改了这个想法,将最后一个'touchstart'事件保存在全局中。只要'newItemInputEl'接收到'focus'事件,它就会检查最后一次'touchstart'事件的目标是否是输入元素。如果不是,则调用blur()以放弃键盘焦点:http://jsfiddle.net/f7TKc/3/此方法适用于iOS 5.0,5.1和6.0,但它不适用于iOS 4.3.2。事实证明,iOS 4.3.2 Mobile Safari不会将触摸事件分派给输入元素:http://jsfiddle.net/3zjQW/1/所以我添加了一个'click'捕获侦听器来重置全局,它的工作原理如下:http ://jsfiddle.net/f7TKc/4/ –

相关问题