2012-06-16 51 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/ –

相關問題