我在想這裏有人能幫我弄清楚這個問題。暫時刪除IE中的「onblur」處理程序
我需要暫時禁用輸入字段的'onblur'屬性中的代碼,然後重新啓用它。我需要這樣做的原因是B/C我的工作流程如下:
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;
}
}
這種運作良好,在所有瀏覽器(FF,鉻,歌劇),除了IE6。
在IE6中它種的作品。首先,以使其在IE瀏覽器在所有的工作,我不得不修改調用「setFocusAndRestoreBlur」像這樣:
setTimeout(function() {
this.setFocusAndRestoreBlur(req);
}.bind(this), 0)
這有當前線程完成後運行代碼的效果。出於某種原因,IE不尊重我已經刪除了處理程序的事實,如果我嘗試在同一個線程中設置焦點!
所以,通過這種修改,我第一次在幾個字段中輸入一些數字,一切都很好。我得到的日誌輸出看起來像這樣:
類型的東西爲 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
但是,當我回到第一個輸入字段時,覆蓋值和製表符,我得到th是:
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;
},
現在,我所要做的就是設置這.allowBlur作爲非常最後一件事,我應該沒事。這裏存在這個問題。在所有其他瀏覽器中,當我修改DOM樹時,onblur事件被觸發,所以它被正確地阻止。但在IE6中,無論我做什麼,它都會在之後觸發onblur事件我的所有代碼。我甚至試過這樣:
setTimeout(function() {
this.allowBlur = true;
}.bind(this), 2)
和我this._proxiedBlur仍然被調用後,我設置標記,以真實的!
因此,問題變成 - 我需要將我的標誌重置,以便在IE6反應DOM更改後執行?
最好的解決方案應該是從您的範圍eheh中刪除IE6。我從來沒有遇到過這種情況,但如果這種情況有效的話,我會保持這種想法。 – JeanK 2011-03-12 02:03:20