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

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

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

当前回答

用纯JavaScript编写的方法

let menu = document.getElementById("menu");

document.addEventListener("click", function(){
    // Hide the menus
    menu.style.display = "none";
}, false);

document.getElementById("menuscontainer").addEventListener("click", function(e){
    // Show the menus
    menu.style.display = "block";
    e.stopPropagation();
}, false);

其他回答

$('#propertyType').on("click",function(e){
          self.propertyTypeDialog = !self.propertyTypeDialog;
          b = true;
          e.stopPropagation();
          console.log("input clicked");
      });

      $(document).on('click','body:not(#propertyType)',function (e) {
          e.stopPropagation();
          if(b == true)  {
              if ($(e.target).closest("#configuration").length == 0) {
                  b = false;
                  self.propertyTypeDialog = false;
                  console.log("outside clicked");
              }
          }
        // console.log($(e.target).closest("#configuration").length);
      });

我有一个应用程序,它的工作方式与Eran的示例类似,只是当我打开菜单时,我会将单击事件附加到主体。。。有点像这样:

$('#menucontainer').click(function(event) {
  $('html').one('click',function() {
    // Hide the menus
  });

  event.stopPropagation();
});

有关jQuery的one()函数的更多信息

如果您正在为IE和FF 3.*编写脚本,并且您只想知道单击是否发生在某个框区域内,您也可以使用以下内容:

this.outsideElementClick=函数(objEvent,objElement){var objCurrentElement=objEvent.target | | objEvent.srcElement;var blnSideX=false;var blnSideY=false;如果(objCurrentElement.getBoundingClientRect().left>=objElement.getBoundingClientRect().left&&objCurrentElement.getBoundingClientRectblnSideX=真;如果(objCurrentElement.getBoundingClientRect().top>=objElement.getBoundingClientRect().ttop&&objCurrentElement.getBoundingClientRectblnSideY=真;如果(blnSideX&&blnSideY)return false;其他的返回true;}

这是面向未来观众的普通JavaScript解决方案。

单击文档中的任何元素时,如果已切换所单击元素的id,或者隐藏元素未隐藏且隐藏元素不包含所单击元素,则切换该元素。

(function () {
    "use strict";
    var hidden = document.getElementById('hidden');
    document.addEventListener('click', function (e) {
        if (e.target.id == 'toggle' || (hidden.style.display != 'none' && !hidden.contains(e.target))) hidden.style.display = hidden.style.display == 'none' ? 'block' : 'none';
    }, false);
})();

(函数(){“使用严格”;var hidden=document.getElementById('hidden');document.addEventListener('click',函数(e){如果(e.target.id==“toggle”| |(hidden.style.display!=“none”&&!hidden.concloss(e.target)))hidden.syle.display=hidden.sstyle.display==“none?”block':'无';},假);})();<a href=“javascript:void(0)”id=“toggle”>切换隐藏潜水</a><div id=“hidden”style=“display:none;”>此内容通常是隐藏的。单击此内容以外的任何位置,使我消失</div>

如果您要在同一页面上进行多个切换,可以使用以下方式:

将隐藏的类名添加到可折叠项中。单击文档后,关闭所有不包含所单击元素且未隐藏的隐藏元素如果单击的元素是切换,请切换指定的元素。

(函数(){“使用严格”;var hiddenItems=document.getElementsByClassName('hidden'),隐藏;document.addEventListener('click',函数(e){for(var i=0;hidden=hiddenItems[i];i++){如果(!hidden.contains(e.target)&&hidden.style.display!='无”)hidden.style.display=“无”;}if(e.target.getAttribute('data-toggle')){var toggle=document.querySelector(e.target.getAttribute('data-toggle'));toggle.style.display=toggle.style.display==“无”?'block':'无';}},假);})();<a href=“javascript:void(0)”data toggle=“#hidden1”>切换隐藏潜水</a><div class=“hidden”id=“hidden1”style=“display:none;”data hidden=“true”>此内容通常隐藏</div><a href=“javascript:void(0)”data toggle=“#hidden2”>切换隐藏潜水</a><div class=“hidden”id=“hidden2”style=“display:none;”data hidden=“true”>此内容通常隐藏</div><a href=“javascript:void(0)”data toggle=“#hidden3”>切换隐藏潜水</a><div class=“hidden”id=“hidden3”style=“display:none;”data hidden=“true”>此内容通常隐藏</div>

您可以监听文档上的单击事件,然后使用.clost()确保#menucontainer不是被单击元素的祖先或目标。

如果不是,则单击的元素位于#menucontainer之外,您可以安全地隐藏它。

$(document).click(function(event) { 
  var $target = $(event.target);
  if(!$target.closest('#menucontainer').length && 
  $('#menucontainer').is(":visible")) {
    $('#menucontainer').hide();
  }        
});

编辑–2017-06-23

如果您计划关闭菜单并希望停止侦听事件,也可以在事件侦听器之后进行清理。此函数将只清理新创建的侦听器,保留文档上的任何其他单击侦听器。使用ES2015语法:

export function hideOnClickOutside(selector) {
  const outsideClickListener = (event) => {
    const $target = $(event.target);
    if (!$target.closest(selector).length && $(selector).is(':visible')) {
        $(selector).hide();
        removeClickListener();
    }
  }

  const removeClickListener = () => {
    document.removeEventListener('click', outsideClickListener);
  }

  document.addEventListener('click', outsideClickListener);
}

编辑–2018-03-11

对于那些不想使用jQuery的人。这是上面的纯vanillaJS(ECMAScript6)代码。

function hideOnClickOutside(element) {
    const outsideClickListener = event => {
        if (!element.contains(event.target) && isVisible(element)) { // or use: event.target.closest(selector) === null
          element.style.display = 'none';
          removeClickListener();
        }
    }

    const removeClickListener = () => {
        document.removeEventListener('click', outsideClickListener);
    }

    document.addEventListener('click', outsideClickListener);
}

const isVisible = elem => !!elem && !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); // source (2018-03-11): https://github.com/jquery/jquery/blob/master/src/css/hiddenVisibleSelectors.js 

注:这是基于Alex的评论,仅供使用!元素。包含(event.target)而不是jQuery部分。

但是element.clost()现在也可以在所有主要浏览器中使用(W3C版本与jQuery版本稍有不同)。Polyfills可以在以下位置找到:Element.clost()

编辑–2020-05-21

如果您希望用户能够在元素内部单击并拖动,则在元素外部释放鼠标,而不关闭元素:

      ...
      let lastMouseDownX = 0;
      let lastMouseDownY = 0;
      let lastMouseDownWasOutside = false;

      const mouseDownListener = (event: MouseEvent) => {
        lastMouseDownX = event.offsetX;
        lastMouseDownY = event.offsetY;
        lastMouseDownWasOutside = !$(event.target).closest(element).length;
      }
      document.addEventListener('mousedown', mouseDownListener);

在外部ClickListener中:

const outsideClickListener = event => {
        const deltaX = event.offsetX - lastMouseDownX;
        const deltaY = event.offsetY - lastMouseDownY;
        const distSq = (deltaX * deltaX) + (deltaY * deltaY);
        const isDrag = distSq > 3;
        const isDragException = isDrag && !lastMouseDownWasOutside;

        if (!element.contains(event.target) && isVisible(element) && !isDragException) { // or use: event.target.closest(selector) === null
          element.style.display = 'none';
          removeClickListener();
          document.removeEventListener('mousedown', mouseDownListener); // Or add this line to removeClickListener()
        }
    }