12

これは私を夢中にさせています。説明するのは難しいですが、やってみます。

サイトのフロント ページに入力テキスト フィールドが 1 つあります。keyCode をチェックする keydown イベント オブザーバーをコーディングしました。その ENTER (または equiv) の場合は、入力値 (電子メール) をチェックします。電子メールが有効で DB 内で一意である場合、フォームが送信されます。基本的なもの、またはそう思うでしょう。

フィールドにメール アドレスを入力して Enter キーを押すと、すべてのブラウザで問題なく動作します。ただし、最初の数文字を入力し、矢印キーを使用して履歴ドロップダウン ボックスからメールを選択し (ここでの意味を理解していただければ幸いです)、Enter キーを押すと、結果が異なります。フォーム フィールドの値は、入力した数文字としてキャプチャされているため、検証は失敗しています。エンターキーを押して履歴ドロップダウンからメールを「選択」すると、入力しているようにブラウザーが中断しているようです。

Chrome と Safari では、正常に動作します。Enterキーを押して履歴ドロップダウンからメールを「選択」すると、そのメールアドレスがテキストボックスに入力されるだけです。2 回目の ENTER キーを押したときにのみ、イベント オブザーバーがトリガーされ、電子メールが検証されます。

なぜこれが起こっているのか、誰かが光を当ててくれることを願っています...私の直感はブラウザの問題であり、私が修正できないものになるでしょう.

ありがとうリー

編集:私の質問に明確にするために、「キーダウン」イベントを使用してエンターキーが押された瞬間をキャプチャすることを追加させてください。「キーアップ」イベントを試してみましたが、これで上記の問題は解決しましたが、フォームの送信を単独で停止できないようです。「keyup」イベントはデフォルトの動作の後にトリガーされるため、これは適切な選択ではありません。

さらに編集:

ありがとうございます。ところで、あなたの英語は素晴らしいです (下手な英語についてのあなたのコメントに応えて)。

イベントハンドラーを次から変更しました。

$("emailInputBox").observe("keydown", function(event) {
    return submitViaEnter(event, submitSignupFormOne);
});

これに:

$("emailInputBox").observe("keydown", function(event) {
    setTimeout(submitViaEnter.curry(event, submitSignupFormOne),0);
});

submitViaEnter:

function submitViaEnter(event, callback) {
var code = event.keyCode;
if (code == Event.KEY_RETURN) {
    event.stop();
    return callback(event);
}
return true;
}

動作しているように見えますが、現在の問題は、ブラウザーが関数を実行する前にデフォルトのアクションを実行することを許可されていることですsubmitViaEnter。つまり、Enter キーを押したときにフォームが送信されていることを意味します。

4

2 に答える 2

7

元の質問への回答

ええ、これは Gecko のバグです (ただし、Mac 固有ではありません)。

このコメントの最後の部分には、タイムアウトを使用するという回避策の説明が含まれています。

[編集] バグの説明を求めて以来

Enter キーを押してオートコンプリートがアクティブな場合、Firefox は (誤って) 最初にページのキー ハンドラーを起動し、次にブラウザーの内部キー ハンドラーを起動して、オートコンプリート ポップアップを閉じ、テキスト領域の値を更新します。オートコンプリート ポップアップを表示し、テキスト ボックスの値が変更されたことをページに知らせるだけです。

これは、キー ハンドラーが呼び出されたときに、オートコンプリートのハンドラーがまだ実行されていないことを意味します。オートコンプリート ポップアップはまだ開いており、テキスト ボックスの値は、オートコンプリートが発生する直前の状態になっています。

キー ハンドラーへの呼び出しを追加するsetTimeoutと、ブラウザーに「P1 の To-Do リストに既にあることを終えた直後にこの関数を実行してください」と言っていることになります。したがって、オートコンプリートのハンドラーが実行されます。これは、既に to-do リストに含まれているためです。次に、タイムアウトに設定したコードが実行されます (オートコンプリート ポップアップが既に閉じられ、テキストボックスの値が更新されている場合)。

[編集] 「さらなる編集」での質問への回答

右。動作させたい場合は、タイムアウトではなく、イベント ハンドラーでデフォルト アクションをキャンセルする必要があります。

function onKeyPress(ev) {
  if (... enter pressed ...) {
    setTimeout(function() {
      ... check the new textbox value after letting autocomplete work ...
    }, 0);
    // but cancel the default behavior (submitting the form) directly in the event listener
    ev.preventDefault();
    return false;
  }
}

Enter でフォームを送信したい場合は、より興味深い演習になりますが、送信していないようです。

于 2010-02-20T23:48:11.283 に答える
2

わかりました。どうもありがとうございました。前に欠けていたのはカレー機能でした。setTimeout 関数のスコープ内でイベントに取り組もうとしていました。

これは以下で機能します。submitViaEnter は eventobserver から呼び出され、keyDown イベントに応答します。

function submitViaEnter(event, callback) {
var code = event.keyCode;
if (code == Event.KEY_RETURN) {
    event.stop();
    setTimeout(callback.curry(event),0);        
    // return callback(event);
    // return false;    
}
return true;
}

eventObserver 内でデフォルト アクションを停止すると、文字を入力できなくなりました。だから私はif ENTERキー句の中に立ち往生しました。

于 2010-02-21T17:23:10.653 に答える