我有一些HTML菜单,当用户单击这些菜单的头部时,我会完全显示这些菜单。当用户在菜单区域外单击时,我希望隐藏这些元素。

jQuery是否可以实现这样的功能?

$("#menuscontainer").clickOutsideThisElement(function() {
    // Hide the menus
});

当前回答

假设您想要检测用户在外部或内部单击的div是否具有id,例如:“我的特殊小部件”。

收听身体点击事件:

document.body.addEventListener('click', (e) => {
    if (isInsideMySpecialWidget(e.target, "my-special-widget")) {
        console.log("user clicked INSIDE the widget");
    }
    console.log("user clicked OUTSIDE the widget");
});

function isInsideMySpecialWidget(elem, mySpecialWidgetId){
    while (elem.parentElement) {
        if (elem.id === mySpecialWidgetId) {
            return true;
        }
        elem = elem.parentElement;
    }
    return false;
}

在这种情况下,您不会破坏页面中某些元素的正常点击流,因为您没有使用“stopPropagation”方法。

其他回答

试试这个:

$('html').click(function(e) {
  if($(e.target).parents('#menuscontainer').length == 0) {
    $('#menuscontainer').hide();
  }
});

https://jsfiddle.net/4cj4jxy0/

但请注意,如果单击事件无法到达html标记,则这将无法工作。(可能其他元素已停止传播())。

    $('#menucontainer').click(function(e){
        e.stopPropagation();
     });

    $(document).on('click',  function(e){
        // code
    });

为了更易于使用和表达代码,我为此创建了一个jQuery插件:

$('div.my-element').clickOut(function(target) { 
    //do something here... 
});

注意:target是用户实际单击的元素。但回调仍然在原始元素的上下文中执行,所以您可以像在jQuery回调中预期的那样使用它。

插件:

$.fn.clickOut = function (parent, fn) {
    var context = this;
    fn = (typeof parent === 'function') ? parent : fn;
    parent = (parent instanceof jQuery) ? parent : $(document);

    context.each(function () {
        var that = this;
        parent.on('click', function (e) {
            var clicked = $(e.target);
            if (!clicked.is(that) && !clicked.parents().is(that)) {
                if (typeof fn === 'function') {
                    fn.call(that, clicked);
                }
            }
        });

    });
    return context;
};

默认情况下,单击事件侦听器放置在文档上。但是,如果要限制事件侦听器范围,可以传入一个jQuery对象,该对象表示父级元素,该元素将是侦听单击的顶级父级元素。这可以防止不必要的文档级事件侦听器。显然,除非提供的父元素是初始元素的父元素,否则它将无法工作。

使用方式如下:

$('div.my-element').clickOut($('div.my-parent'), function(target) { 
    //do something here...
});
$(document).on('click.menu.hide', function(e){
  if ( !$(e.target).closest('#my_menu').length ) {
    $('#my_menu').find('ul').toggleClass('active', false);
  }
});

$(document).on('click.menu.show', '#my_menu li', function(e){
  $(this).find('ul').toggleClass('active');
});
div {
  float: left;
}

ul {
  padding: 0;
  position: relative;
}
ul li {
  padding: 5px 25px 5px 10px;
  border: 1px solid silver;
  cursor: pointer;
  list-style: none;
  margin-top: -1px;
  white-space: nowrap;
}
ul li ul:before {
  margin-right: -20px;
  position: absolute;
  top: -17px;
  right: 0;
  content: "\25BC";
}
ul li ul li {
  visibility: hidden;
  height: 0;
  padding-top: 0;
  padding-bottom: 0;
  border-width: 0 0 1px 0;
}
ul li ul li:last-child {
  border: none;
}
ul li ul.active:before {
  content: "\25B2";
}
ul li ul.active li {
  display: list-item;
  visibility: visible;
  height: inherit;
  padding: 5px 25px 5px 10px;
}
<script src="https://code.jquery.com/jquery-2.1.4.js"></script>
<div>
  <ul id="my_menu">
    <li>Menu 1
      <ul>
        <li>subMenu 1</li>
        <li>subMenu 2</li>
        <li>subMenu 3</li>
        <li>subMenu 4</li>
      </ul>
    </li>
    <li>Menu 2
      <ul>
        <li>subMenu 1</li>
        <li>subMenu 2</li>
        <li>subMenu 3</li>
        <li>subMenu 4</li>
      </ul>
    </li>
    <li>Menu 3</li>
    <li>Menu 4</li>
    <li>Menu 5</li>
    <li>Menu 6</li>
  </ul>
</div>

这里是jsbin版本http://jsbin.com/xopacadeni/edit?html,css,js,输出

如果您正在使用“弹出窗口”等工具,则可以使用“onFocusOut”事件。

window.onload=函数(){document.getElementById(“内部div”).focus();}函数loseFocus(){警报(“在外面单击”);}#集装箱{背景色:浅蓝色;宽度:200px;高度:200px;}#内部div{背景色:浅灰色;宽度:100px;高度:100px;}<div id=“container”><input type=“text”id=“inside div”onfocusout=“loseFocus()”></div>