2014-04-01 48 views
0

我們有自定義上下文菜單,用右鍵單擊來替換瀏覽器菜單。我們希望能夠以與瀏覽器隱藏默認上下文菜單相同的方式來中止(隱藏)上下文菜單 - 在未註冊爲點擊的菜單之外的任何地方點擊。該解決方案應適用於綁定事件和默認瀏覽器操作,但不會妨礙其他事件的能力,即。 hover免燒。如何禁用上下文菜單中止的所有單擊操作?

一個例子

在Firefox中,右鍵點擊此頁面上打開上下文菜單。將鼠標懸停在此頁頂部的

Questions-Tags-Users-Badges-Unanswered 

。即使上下文菜單已打開,突出顯示仍然存在。現在,點擊此頁面上的文本區域,如頂部的搜索框。上下文菜單將隱藏,但光標不會將文本框對焦(除非在菜單關閉的情況下再次單擊它)。

我們如何在JavaScript中模擬這種行爲?

拒絕選項我們已經考慮

  1. 使用透明DIV在整個頁面。問題:這可以捕捉點擊任何地方,但打破懸停事件和懸停CSS。

  2. 檢查每個點擊處理程序中的上下文菜單打開變量,並將處理程序分配給所有鏈接,並輸入元素以檢測上下文菜單打開狀態,該狀態關閉上下文菜單,取消打開狀態並阻止處理程序默認。問題:非常草率的代碼和維護噩夢。

+0

只是報告說,在我的電腦(Windows版的Firefox)上,通過上下文菜單打開單擊並集中在文本框中 – guest

+0

使用Firefox 37在Ubuntu上,第一次點擊不會集中,但只會關閉上下文菜單,如上所述。 – geira

回答

1

考慮一個被拒絕的選項#2的變體,其中您有一個文檔上的單個事件偵聽器。

document.addEventListener('click', function (e) { 
    if (contextMenuOpen) { 
     e.preventDefault(); 
     e.stopPropagation(); 
    } 
}, true); 

有關true更多信息,查找useCaptureevent flow

+0

一個小問題:上下文菜單事件觸發,然後點擊事件觸發。這會導致菜單打開並立即關閉。 – Nick

+0

+1用於事件捕獲。有幾個問題需要解決,即處理菜單自動關閉和文本區域是可聚焦的,因爲焦點事件首先被觸發。 – Nick

0

Guest在事件捕獲的正確軌道上,但解決方案有一些故障。這是一個更強大的解決方案,可以解決以下問題:

  1. 不要立即關閉菜單右鍵單擊事件,在右鍵菜單後立即觸發。
  2. 當上下文菜單打開時,不要讓文本字段變得焦點 - 焦點事件首先觸發並且不會被捕獲單擊事件捕獲。我們還需要設置焦點捕獲處理程序。
  3. 處理由焦點和點擊處理程序產生的問題,這兩個問題都會觸發。

要做到這一點,你需要兩個捕獲事件處理程序:

document.addEventListener('focus', function(e){eDocumentFocusCapture(e)}, true); 
document.addEventListener('click', function(e){eDocumentClickCapture(e)}, true); 

// If the context menu is open, ignore the focus event. 
eDocumentFocusCapture = function(e){ 
    if(RowContextMenuIsOpen){ 
     console.log('focus event sees the menu open: cancel focus, but leave menu be. Click will take care of closing it.'); 
     e.stopImmediatePropagation(); 
     e.preventDefault(); 
     e.target.blur(); // tell the clicked element it is not focused, otherwise you can't focus it until you click elsewhere first! 
    } 
} 


eDocumentClickCapture = function(e){ 

    // A right click fires immediatly after context menu is fired, 
    // we prevent the menu from closing immediately by skipping one right click event 
    if(RowContextMenuWasJustOpened===true && e.button===2){ 
     console.log('right click self bypass'); 
     RowContextMenuWasJustOpened=false; 
     return; 
    } 

    if(this.protected.RowContextMenuIsOpen){ 
     console.log('click event sees menu open, I will close it.'); 
     this.HideRowContextMenu();  
     e.stopImmediatePropagation(); 
     e.preventDefault();  
    } 
} 
相關問題