2009-07-21 140 views
12

this question類似,但更進一步。我想檢測一組項目,我在下面的方式正在處理以外的用戶點擊:檢測點擊外部元素?

$('#menu div').live('click', function() { 
    // Close other open menu items, if any. 
    // Toggle the clicked menu item. 

    $('body').one('click', function(event) { 
     // Hide the menu item. 
     event.stopPropagation(); 
    }); 
}); 

這個工程就像一個魅力,不幸的是,當另一個菜單項打開並且 第二點擊,它需要兩次點擊來打開第二個項目。第一個 點擊隱藏已打開的第一個菜單項,第二個顯示第二個菜單項 。

「正確」的行爲,在工作方式如下:

  • 點擊菜單項打開它。
  • 單擊相同的菜單項(或它的子項)將關閉它。
  • 點擊另一個菜單項關閉第一個,打開第二個。
  • 點擊離開(打開)菜單項關閉它們。

我試圖取代上述$('body').one()以忽略菜單項點擊收效甚微的以下內容:

// Captures click on menu items in spite of the not. 
$('*').not('#menu *').one('click', function() { // Hide menu } 
$('*:not(#menu)').one('click', function() { // Hide menu } 

一如既往,感謝您的幫助!

回答

29

只是外挪動身子點擊處理程序,並做這樣的事情:

$('body').bind('click', function(e) { 
    if($(e.target).closest('#menu').length == 0) { 
     // click happened outside of menu, hide any visible menu items 
    } 
}); 

它被錯誤地在e.target在IE無法正常工作的意見中指出,這是不正確的,因爲jQuery's Event object修復了這些不一致之處(IE,Safari)。

+0

什麼是移動`body`點擊菜單單擊處理程序之外處理的目的是什麼?通過在打開菜單項後應用它,似乎可以完成相同的任務(如果菜單從未打開,則無需捕獲每次主體點擊的開銷)。或者我錯過了什麼? – chuckg 2009-07-21 18:48:27

+0

這是一個公平點;我認爲,無論用戶何時點擊菜單項,綁定和解除綁定都是不必要的。除了進入另一個頁面之外,通常不會在頁面上點擊太多,在這種情況下,額外的點擊處理程序完全不相關。在一天結束時,根據您的需求,兩者都可以,所以您可以堅持一個處理程序,如果它符合您的需求。 – 2009-07-21 19:20:36

15

我寫了這個很久以前,jQuery的光輝歲月之前...

function clickedOutsideElement(elemId) { 
    var theElem = getEventTarget(window.event); 
    while(theElem != null) { 
    if(theElem.id == elemId) 
     return false; 
    theElem = theElem.offsetParent; 
    } 
    return true; 
} 

function getEventTarget(evt) { 
    var targ = (evt.target) ? evt.target : evt.srcElement; 
    if(targ != null) { 
    if(targ.nodeType == 3) 
     targ = targ.parentNode; 
    } 
    return targ; 
} 

document.onclick = function() { 
    if(clickedOutsideElement('divTest')) 
    alert('Outside the element!'); 
    else 
    alert('Inside the element!'); 
}