2011-03-09 21 views
1

我在想這裏有人能幫我弄清楚這個問題。暫時刪除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中,無論我做什麼,它都會在之後觸發onb​​lur事件我的所有代碼。我甚至試過這樣:

setTimeout(function() { 
    this.allowBlur = true; 
}.bind(this), 2) 

和我this._proxiedBlur仍然被調用後,我設置標記,以真實的!

因此,問題變成 - 我需要將我的標誌重置,以便在IE6反應DOM更改後執行?

回答

1

好的,我想通了。訣竅是設置在單獨的線程中的焦點:

   setTimeout(function() { 
        this.setFocusAndRestoreBlur(req); 
       }.bind(this), 0) 

,然後用另一個嵌套的setTimeout()復位該標誌。這似乎在IE6中正確排序事件:

setFocusAndRestoreBlur : function(req) { 
    setFocus(req); 

    setTimeout(function() { 
    this.allowBlur = true; 
    }.bind(this), 0) 
} 
+0

最好的解決方案應該是從您的範圍eheh中刪除IE6。我從來沒有遇到過這種情況,但如果這種情況有效的話,我會保持這種想法。 – JeanK 2011-03-12 02:03:20

0

我建議您以邏輯方式禁用模糊。

我的意思是,像這樣:

假設這是你的onblur事件功能,您可以通過標誌控制它:

function myOnBlur() { 
    if (ableToExecute) { 
    executeWhatYouNeed(); 
    } 
} 

所以,當你做你的要求,你設置的標誌爲false,然後在響應和您需要的處理之後,將平面重置爲true,以便您的onblur事件可以再次觸發您的請求。

我不知道這個簡單的控件是否可以幫助你,但你可以試試。

+0

不幸的是,我不控制onblur函數。這是由a4j框架編寫的,所以我不能輕鬆修改它的代碼。當然,我可以做一個包裝函數,我想...我仍然必須替換函數,但我會試一試,看看是否有不同的行爲 – 2011-03-10 00:13:17

+0

讓,我更新了我的文章與您的結果建議。有什麼想法嗎?謝謝。 – 2011-03-11 23:53:15