0

我创建了一个非常简单的 jQuery“下拉列表”,它由两个 div 元素组成。单击第一个 div 时,将显示第二个 div。现在,当我在该 div 外部单击时,我希望再次关闭第二个 div。但是我不能(如果没有必要,实际上也不想)使用这样的文档或正文事件侦听器:

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

原因:我在页面上使用了其他元素,e.stopPropagation();如果用户在打开下拉列表后单击这些元素,它不会再次关闭。

我发现这个插件 jALDropdown 以某种方式处理关闭下拉列表,即使我点击e.stopPropagation();,甚至在页面或浏览器之外的某个地方,它似乎没有使用任何文档/正文事件侦听器:http:/ /india.assigninfo.com/assignlabs/jaldropdown

抱歉,它不适用于 Opera,所以我不能使用它。而且我没有找到未最小化的源代码版本,因此我无法找出它是如何工作的。

如果我在元素、页面甚至浏览器之外单击而没有文档/正文事件侦听器,您是否有任何想法如何归档此行为,以便下拉菜单关闭(元素被隐藏)?谢谢!

4

2 回答 2

1

为什么不保留 $(document).click() 函数来隐藏您的划分,然后将此函数添加到您的代码中并调用它而不是 event.stopPropagation():

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

我测试了它,它似乎可以正常工作。你只需要记住使用它。

更新:

这让我很痛苦,我在我知道的这个很棒的网站上找到了另一个答案。这是链接:

使用 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(); });

剧透:当您单击“点击器”按钮时,文档也会记录到控制台。当您单击“anotherClicker”按钮时,自定义 event.stopPropagation() 函数会记录到控制台,而文档不会记录到控制台。现在,您可以将单击事件处理程序添加到文档中。

一件事:这可能会增加一些开销,但前提是您经常调用 stopPropagation() 。

如果有人想权衡像这样使用 jQuery 对象的智慧,请这样做。我想知道,但我看不到像这样的无害更改将来会炸毁网页。

于 2012-04-01T18:28:10.863 回答
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();
    }
  }
}
于 2012-03-31T22:54:12.313 回答