2

Mobile Safari、Androidブラウザ、Firefox for Android( "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でこれをテストすることはできません。

これはバグですか、それとも予想される動作ですか?

4

3 に答える 3

1

はい、これはバグだと思います。これはここでも同じ行にある可能性があります: http ://code.google.com/p/android/issues/detail?id=6721その場合、リンクにはいくつかの回避策があります他の人はあなたが試すことができるものを試しました

于 2012-10-24T17:23:51.497 に答える
0

これは予想される動作だと思います。

モバイルWebブラウザーの開発者は、小さなディスプレイでデザインが不十分なWebページに特別な対応をする必要があります。

Webページが適切に拡大縮小されない場合、UI要素は別のレイヤーで簡単に覆われる可能性があります。

クリックイベントがレイヤー全体に伝播できるようにすると、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);
于 2012-10-20T09:35:51.607 に答える
0

タッチイベントは、touchstart、touchend、clickの順に呼び出されます。タッチイベントのタッチスタートが入力で発生したかどうかを知る必要があります。オブジェクト変数を暗黙的に宣言し(これはjavascriptで許可されています)、falseに初期化できます。タッチスタートイベントでtrueに設定します。次に、タッチエンドやクリックイベントでその値を確認します。次のコードは、期待どおりに機能します。

    <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>
于 2012-10-23T00:09:10.640 に答える