2012-03-31 78 views
0

我創建了一個非常簡單的jQuery「下拉列表」,它由兩個div元素組成。單擊第一個div時,會顯示第二個div。現在我想要再次關閉第二個div,當我在該div外部單擊時。但我不能(其實不想,如果它不是必需的)用下述證件或身體的事件監聽器是這樣的:在沒有文檔/ body-event-listener的情況下單擊外部隱藏元素

$('#div2').click(function(e) { 
    doSomething(); 
    e.stopPropagation(); 
}); 
$(document).click(function() { 
    $("#div2").hide(); 
}); 

原因:我有一個使用頁面上的其他元素e.stopPropagation();,如果用戶在打開下拉列表後點擊了這些元素,它將不會再次關閉。

我發現這個插件jALDropdown,即使我點擊e.stopPropagation();,甚至在頁面或瀏覽器之外的某個地方,也可以通過某種方式處理以關閉下拉列表,並且它似乎沒有使用任何文檔/ body-event-聽衆:http://india.assigninfo.com/assignlabs/jaldropdown

不幸的是,它不與Opera合作,所以我不能使用它。而且我沒有找到未被最小化的源代碼版本,因此我無法瞭解它的工作原理。

如果我點擊元素,頁面甚至瀏覽器之外,而沒有文檔/ body-event-listener,你是否有任何想法來實現這種行爲,以便下拉關閉(元素被隱藏)?謝謝!

+0

是的,這可以很容易地完成。 Lemme抓住了我爲自己編寫和使用的一些實用方法。 – 2012-03-31 22:48:29

回答

1

爲什麼不保持的$(document)。點擊()函數來隱藏你的部門,那麼這個功能添加到您的代碼,並調用它,而不是event.stopPropagation()的:

function stopPropAndCloseDiv2(event) { 
    $('#div2').hide(); 
    event.stopPropagation(); 
}; 

我測試了它,它似乎能正常工作。你只需要記住使用它。

UPDATE:

這折磨着我,我發現這個偉大的網站,我知道另一個答案。這裏的鏈接:

add code to a function programatically with JS

我試過這種方法,它似乎工作:http://jsfiddle.net/kXkFS/8/

下面的代碼(也有在測試頁面標記兩個按鈕):

jQuery.Event.prototype.stopPropagation = (function() { 
    var cached_function = jQuery.Event.prototype.stopPropagation; 

    return function() { 
     if (this.type == "click") { 
      // Your logic here. 
      console.log("I am a modified version of event.stopPropagation()!"); 
     } 
     cached_function.apply(this, arguments); // use .apply() to call it. 
    }; 
}()); 

$(document).click(function() { console.log("The document caught the event, too."); }); 
$('#clicker').click(function() { console.log("I'm going to let this event bubble."); }); 
$('#anotherClicker').click(function(event) { event.stopPropagation(); }); 

破壞者:當你點擊「Clicker」按鈕時,文檔也會登錄到控制檯。當您單擊「anotherClicker」按鈕時,自定義event.stopPropagation()函數將記錄到控制檯,並且文檔不會登錄到控制檯。現在,您可以將單擊事件處理程序添加到文檔中。有一件事:這可能會增加一些開銷,但前提是你經常打電話給stopPropagation()。

如果有人想要權衡像這樣使用jQuery對象的智慧,請這樣做。我想知道,但我看不到像這樣一個無害的變化將在未來炸燬網頁。

+0

是的,它會工作,但我不得不觸碰另一個事件處理程序並用此新函數替換stopPropagation調用。如果可能的話,我不想這樣做,但嘗試不使用$(document/body/window).click() - 就像jALDropdown所做的那樣。 – 2012-04-01 19:54:20

+0

@RenéSchubert:我添加的更新應該允許您單獨留下其他事件處理程序。相反,傳遞給它們的事件對象將發生更改。 – jCyCle 2012-04-03 00:42:37

+0

有趣,非常感謝!只有一個邏輯問題:如果我在下拉列表中單擊(這不是典型的下拉行爲,但仍可能是用例場景),我需要stopPropagation函數才能關閉下拉列表。而且如果我定義'$(document).click(function(){$('#div2')。hide();});',不可能打開下拉菜單。這就是爲什麼我用這樣的函數參數擴展你的代碼:'return function(noHide){if(this.type =='click'&&!noHide)...'這樣我可以防止關閉下拉菜單,但仍然不必觸摸其他事件處理程序。 – 2012-04-10 21:54:39

0
//generic drop-down menu 
//NOTE: only pass a menu object if there are multiple menus per toggle object 
var dropDown = function(toggle, menus) 
{ 
    toggle.click(function(e) { 
    e.preventDefault(); 
    //NOTE: container is assuming that the next sibling is the dropdown. 
    //change container to suit your needs 
    var container = $(this).next(); 
    if(menus !== undefined && !container.is(':visible')){ menus.hide(); } 

    if(!container.is(':visible')) 
    { 
     container.fadeIn('fast'); 
    } 
    else 
    { 
     container.fadeOut('fast'); 
    } 
    }); 
} 

//close stuff when the window is clicked 
var window_click = function(obj) 
{ 
    $(window).click(function(e) { 
    if(obj.is(':visible')) 
    { 
     obj.fadeOut(250); 
    } 
    }); 
} 

//override the window_click function when needed 
var stop_prop = function(obj) 
{ 
    obj.click(function(e) { 
    e.stopPropagation(); 
    }); 
} 

現在,只需使用它們,無論你想是這樣的:

var toggle = $('#myToggle'); 
var menu = $('#myMenu'); 

dropDown(toggle, menu); 
window_click(menu); 
stop_prop(toggle); 
stop_prop(menu); 

對於我的下拉標記,我幾乎總是使用這種模式:

<span class='toggle_name'></span> 
<ul class='menu_name' style='display:none;'> 
    <li>cool man</li> 
</ul>  

爲了解決您的散stopPropagation (),你也可以創建一個手動關閉所有菜單類的小函數。超級簡單:

var menus = { 
    //add any dropdown menu ids or classes here 
} 

//run this method on any conflicting stopProp clicks 
var closeMenus = function() 
{ 
    for(var key in menus) 
    { 
    if(menus.hasOwnProperty(key)) 
    { 
     menus[key].hide(); 
    } 
    } 
} 
+0

我嘗試了這一點,但它似乎並沒有工作。它會切換下拉列表,但不會關閉,當我在外面點擊時。你能提供一個可用的jsfiddle例子嗎?除此之外:$(window).click()不會與其他元素上使用的stopPropagation一起工作(除非我使用closeMenus函數,但我正在尋找一種解決方案,我不必觸摸其他事件處理程序)。而且jALDropdown也沒有那種東西。 – 2012-04-01 15:53:58

+0

你在這裏:) http://jsfiddle.net/tpbjV/9/ – 2012-04-01 18:20:14

+0

謝謝。當我點擊它時添加一個停止傳播的元素時,您的解決方案不再有效:http://jsfiddle.net/Dg2UN/3/這就是我想要解決的問題,而無需向元素事件添加額外的代碼 - 阻止傳播的聽衆。 – 2012-04-01 20:02:56

相關問題