ここの誰かが私がこの問題を理解するのを手伝ってくれるのだろうか。
入力フィールドの「onblur」属性のコードを一時的に無効にしてから、再度有効にする必要があります。これを行う必要がある理由は、私のワークフローが次のとおりです。
1)AJAXイベントは、入力フィールドの「onblur」属性によってトリガーされます。これは、ユーザーがフィールドからタブで移動して次のフィールドに移動した結果です。
2)ページが更新され、Javascriptコードが「onafterajax」フックから呼び出されます。
3)私のコードはDOMの深刻な再配置を行っているため、現在の入力フィールドへのフォーカスが失われます。したがって、手動でフォーカスを復元する必要があります。すべての入力フィールドにフォーカスハンドラーをアタッチしたので、最後にフォーカスがあったフィールドを追跡できるので、どこにフォーカスを置くかがわかります。
4)正しい入力フィールドで.focus()を呼び出します。これにより、何らかの理由で' onblurが発生します。'同じ入力フィールドで起動します。これはすべてのブラウザで発生します。これはa)フィールドがまだ焦点を合わせていたことを示唆していますか?!b)ステップ1が再度実行されるため、無限ループを作成します。
無限ループを回避するために、次のことを行いました。DOMの再配置を実行する前に、次のことを行います。
if ( window.currentFocusId ) {
this.savedFocusId = currentFocusId;
this.onblur_bak = $(this.savedFocusId).onblur;
$(this.savedFocusId).onblur = null;
LOG.warn(" --- Disabling blur on " + this.savedFocusId);
}
次に、DOMハッカーを完了した後、次のようにします。
setFocusAndRestoreBlur : function(req) {
if ( this.savedFocusId ) {
var focusElement = req.form.elements[this.savedFocusId];
LOG.warn(" ------ Focusing on " + focusElement.id);
if (focusElement) {
focusElement.focus();
if (focusElement.select) {
focusElement.select();
}
}
LOG.warn(" --- Enabling blur on " + this.savedFocusId);
$(this.savedFocusId).onblur = this.onblur_bak;
delete this.onblur_bak;
delete this.savedFocusId;
}
}
これは、IE6を除くすべてのブラウザー(FF、Chrome、Opera)でうまく機能します。
IE6ではそれは一種の働きをします。まず、IEで機能させるには、「setFocusAndRestoreBlur」の呼び出しを次のように変更する必要がありました。
setTimeout(function() {
this.setFocusAndRestoreBlur(req);
}.bind(this), 0)
これには、現在のスレッドが終了した後にコードを実行する効果があります。同じスレッドにフォーカスを設定しようとすると、何らかの理由でIEはonblurハンドラーを削除したという事実を尊重しません。
したがって、この変更により、初めていくつかのフィールドにいくつかの数値を入力したときは、すべて問題ありません。次のようなログ出力が得られます。
j_id390に何かを入力し、タブをオフにします。
warn[16:35:33,091]: blur fired from statementProgramsDataTable:0:j_id390
warn[16:35:33,092]: --- Disabling blur on statementProgramsDataTable:0:j_id397
warn[16:35:33,225]: ------ Focusing on statementProgramsDataTable:0:j_id397
warn[16:35:33,225]: --- Enabling blur on statementProgramsDataTable:0:j_id397
j_id397に何かを入力し、タブをオフにします。
warn[16:35:38,259]: blur fired from statementProgramsDataTable:0:j_id397
warn[16:35:38,260]: --- Disabling blur on statementProgramsDataTable:0:j_id446
warn[16:35:38,390]: ------ Focusing on statementProgramsDataTable:0:j_id446
warn[16:35:38,390]: --- Enabling blur on statementProgramsDataTable:0:j_id446
ただし、最初の入力フィールドに戻り、値を上書きしてタブをオフにすると、次のようになります。
warn[17:18:15,454]: blur fired from statementProgramsDataTable:0:j_id390
warn[17:18:15,469]: --- Disabling blur on statementProgramsDataTable:0:j_id397
warn[17:18:16,870]: ------ Focusing on statementProgramsDataTable:0:j_id397
warn[17:18:16,874]: --- Enabling blur on statementProgramsDataTable:0:j_id397
warn[17:18:18,097]: blur fired from statementProgramsDataTable:0:j_id397
warn[17:18:18,112]: --- Disabling blur on statementProgramsDataTable:0:j_id397
warn[17:18:19,550]: ------ Focusing on statementProgramsDataTable:0:j_id397
warn[17:18:19,555]: --- Enabling blur on statementProgramsDataTable:0:j_id397
warn[17:18:24,492]: blur fired from statementProgramsDataTable:0:j_id397
warn[17:18:24,187]: --- Disabling blur on statementProgramsDataTable:0:j_id397
warn[17:18:24,531]: ------ Focusing on statementProgramsDataTable:0:j_id397
warn[17:18:24,545]: --- Enabling blur on statementProgramsDataTable:0:j_id397
ほとんどの場合、このループは可変数の反復で続き、入力フィールドが正しくフォーカスされた状態で停止します。ループが無限に見える場所を数回見ました。
IEがonblurハンドラーの不在を再び尊重していないように見えますか?でもたまに?!
だから、これは私が混乱しているところです。IEの動作に一貫性がないのはなぜですか?私は何が間違っているのですか?もっと良い方法はありますか?
任意のアイデアをいただければ幸いです。
ヴァル
編集:
JeanKが提案したアプローチを試しました。それでも機能しませんが、この試みから潜在的に役立つことを学びました。
次のように、元の「onblur」関数をプロキシでラップします。
this.allowBlur = false;
if ( !this._functionsEqual($(this.savedFocusId).onblur, this._proxiedBlur) ) {
$(this.savedFocusId).onblur = this.proxyOnBlur($(this.savedFocusId).onblur);
}
そしてプロキシ機能自体:
proxyOnBlur : function(method) {
var object = this;
this._proxiedBlur = function(event) {
if ( object.allowBlur ) {
return method.apply(this, [event || window.event])
}
};
return this._proxiedBlur;
},
さて、私がしなければならないのは、 this.allowBlurを最後のものとして設定することだけです、そして私は大丈夫なはずです。そしてここに問題があります。他のすべてのブラウザーでは、DOMツリーを変更するとonblurイベントが発生するため、正しくブロックされます。しかし、IE6では、私が何をしても、すべてのコードの後にonblurイベントが発生します。私もこれを試しました:
setTimeout(function() {
this.allowBlur = true;
}.bind(this), 2)
フラグをtrueに設定した後も、this._proxiedBlurが呼び出されます。
したがって、問題は次のようになります-IE6がDOMの変更に反応した後に実行されるように、フラグをリセットする必要があるのはどこですか?