2012-03-31 84 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

相关问题