Нажмите за пределами меню, чтобы закрыть в jquery
Поэтому у меня есть раскрывающееся меню, которое отображается по щелчку в соответствии с требованиями бизнеса. Меню снова становится скрытым после того, как вы отошли от него.
Но теперь меня просят оставить его на месте, пока пользователь не щелкнет в любом месте документа. Как это можно сделать?
Это упрощенная версия того, что я имею сейчас:
$(document).ready(function() {
$("ul.opMenu li").click(function(){
$('#MainOptSubMenu',this).css('visibility', 'visible');
});
$("ul.opMenu li").mouseleave(function(){
$('#MainOptSubMenu',this).css('visibility', 'hidden');
});
});
<ul class="opMenu">
<li id="footwo" class="">
<span id="optImg" style="display: inline-block;"> <img src="http://localhost.vmsinfo.com:8002/insight/images/options-hover2.gif"/> </span>
<ul id="MainOptSubMenu" style="visibility: hidden; top: 25px; border-top: 0px solid rgb(217, 228, 250); background-color: rgb(217, 228, 250); padding-bottom: 15px;">
<li>some</li>
<li>nav</li>
<li>links</li>
</ul>
</li>
</ul>
Я пробовал что то подобное $('document[id!=MainOptSubMenu]').click(function()
думая, что это вызовет все, что не было меню, но это не сработало.
17 ответов
Посмотрите на подход, который использовался в этом вопросе:
Как я могу обнаружить щелчок за пределами элемента?
Прикрепите событие щелчка к телу документа, которое закрывает окно. Прикрепите отдельное событие щелчка к окну, которое останавливает распространение в теле документа.
$('html').click(function() {
//Hide the menus if visible
});
$('#menucontainer').click(function(event){
event.stopPropagation();
});
Ответ правильный, но он добавит слушателя, который будет срабатывать при каждом нажатии на вашу страницу. Чтобы избежать этого, вы можете добавить слушателя только один раз:
$('a#menu-link').on('click', function(e) {
e.preventDefault();
e.stopPropagation();
$('#menu').toggleClass('open');
$(document).one('click', function closeMenu (e){
if($('#menu').has(e.target).length === 0){
$('#menu').removeClass('open');
} else {
$(document).one('click', closeMenu);
}
});
});
Изменить: если вы хотите избежать stopPropagation()
на начальной кнопке вы можете использовать это
var $menu = $('#menu');
$('a#menu-link').on('click', function(e) {
e.preventDefault();
if (!$menu.hasClass('active')) {
$menu.addClass('active');
$(document).one('click', function closeTooltip(e) {
if ($menu.has(e.target).length === 0 && $('a#menu-link').has(e.target).length === 0) {
$menu.removeClass('active');
} else if ($menu.hasClass('active')) {
$(document).one('click', closeTooltip);
}
});
} else {
$menu.removeClass('active');
}
});
stopPropagation
параметры плохие, потому что они могут мешать другим обработчикам событий, включая другие меню, которые могли бы прикрепить закрывающие обработчики к элементу HTML.
Вот простое решение, основанное на ответе пользователя 2989143:
$('html').click(function(event) {
if ($(event.target).closest('#menu-container, #menu-activator').length === 0) {
$('#menu-container').hide();
}
});
Если в вашем случае плагин подходит, то я предлагаю плагин Бена Алмана, расположенный здесь:
его использование так же просто, как это:
$('#menu').bind('clickoutside', function (event) {
$(this).hide();
});
надеюсь это поможет.
2 варианта, которые вы можете исследовать:
- При отображении меню поместите большой пустой DIV за ним, закрывающий остальную часть страницы, и назначьте событие по щелчку, чтобы закрыть меню (и себя). Это похоже на методы, используемые с лайтбоксами, когда щелчок по фону закрывает лайтбокс
- При отображении меню прикрепите обработчик событий одноразового щелчка к телу, которое закрывает меню. Для этого вы используете '.one()' в jQuery.
Я нашел вариант решения Grsmto, и решение Денниса устранило мою проблему.
$(".MainNavContainer").click(function (event) {
//event.preventDefault(); // Might cause problems depending on implementation
event.stopPropagation();
$(document).one('click', function (e) {
if(!$(e.target).is('.MainNavContainer')) {
// code to hide menus
}
});
});
Я недавно столкнулся с той же проблемой. Я написал следующий код:
$('html').click(function(e) {
var a = e.target;
if ($(a).parents('.menu_container').length === 0) {
$('.ofSubLevelLinks').removeClass('active'); //hide menu item
$('.menu_container li > img').hide(); //hide dropdown image, if any
}
});
Это сработало для меня отлично.
Как насчет этого?
$(this).mouseleave(function(){
var thisUI = $(this);
$('html').click(function(){
thisUI.hide();
$('html').unbind('click');
});
});
Я использую это решение с несколькими элементами с одинаковым поведением на одной странице:
$("html").click(function(event){
var otarget = $(event.target);
if (!otarget.parents('#id_of element').length && otarget.attr('id')!="id_of element" && !otarget.parents('#id_of_activator').length) {
$('#id_of element').hide();
}
});
stopPropagation () - плохая идея, она нарушает стандартное поведение многих вещей, включая кнопки и ссылки.
Я считаю более полезным использовать mousedown-event вместо click-event. Событие click не работает, если пользователь нажимает на другие элементы на странице с событиями click. В сочетании с методом jQuery one() это выглядит так:
$("ul.opMenu li").click(function(event){
//event.stopPropagation(); not required any more
$('#MainOptSubMenu').show();
// add one mousedown event to html
$('html').one('mousedown', function(){
$('#MainOptSubMenu').hide();
});
});
// mousedown must not be triggered inside menu
$("ul.opMenu li").bind('mousedown', function(evt){
evt.stopPropagation();
});
Это не должно быть сложным.
$(document).on('click', function() {
$("#menu:not(:hover)").hide();
});
Даже я сталкивался с такой же ситуацией, и один из моих наставников донес эту идею до себя.
шаг:1 при нажатии на кнопку, на которой мы должны показать выпадающее меню. затем добавьте приведенное ниже имя класса "more_wrap_background" к текущей активной странице, как показано ниже
$('.ui-page-active').append("<div class='more_wrap_background' id='more-wrap-bg'> </div>");
шаг-2, а затем добавить клики для тега div, как
$(document).on('click', '#more-wrap-bg', hideDropDown);
где hideDropDown - это функция, которая вызывается, чтобы скрыть выпадающее меню
Шаг 3 и важный шаг при скрытии раскрывающегося меню заключается в том, чтобы удалить тот класс, который вы добавили ранее, например
$('#more-wrap-bg').remove();
Я удаляю, используя его идентификатор в приведенном выше коде
.more_wrap_background {
top: 0;
padding: 0;
margin: 0;
background: rgba(0, 0, 0, 0.1);
position: fixed;
display: block;
width: 100% !important;
z-index: 999;//should be one less than the drop down menu's z-index
height: 100% !important;
}
$("html").click( onOutsideClick );
onOutsideClick = function( e )
{
var t = $( e.target );
if ( !(
t.is("#mymenu" ) || //Where #mymenu - is a div container of your menu
t.parents( "#mymenu" ).length > 0
) )
{
//TODO: hide your menu
}
};
И лучше установить слушателя только тогда, когда ваше меню видно, и всегда удаляйте слушателя после того, как меню станет скрытым.
Я думаю, что вам нужно что-то вроде этого: http://jsfiddle.net/BeenYoung/BXaqW/3/
$(document).ready(function() {
$("ul.opMenu li").each(function(){
$(this).click(function(){
if($(this).hasClass('opened')==false){
$('.opMenu').find('.opened').removeClass('opened').find('ul').slideUp();
$(this).addClass('opened');
$(this).find("ul").slideDown();
}else{
$(this).removeClass('opened');
$(this).find("ul").slideUp();
}
});
});
});
Я надеюсь, что это полезно для вас!
Используйте селектор ": видимый". Где.menuitem это скрываемый элемент (ы) ...
$('body').click(function(){
$('.menuitem:visible').hide('fast');
});
Или, если у вас уже есть элемент (ы).menuitem в...
var menitems = $('.menuitem');
$('body').click(function(){
menuitems.filter(':visible').hide('fast');
});
Если вы не используете jQuery и хотите использовать чистый CSS и HTML, это решение.
- Создайте элемент триггера и внутри него напишите свой всплывающий элемент.
- Прикрепите обработчик щелчка, чтобы отображать всплывающее окно при щелчке элемента триггера.
- Создайте элемент фона, который растягивается на всю ширину экрана, и прикрепите обработчики кликов к тому, что скрывает всплывающее окно.
- Все прикрепленные обработчики кликов должны останавливать распространение события, чтобы другие обработчики не вызывались.
Найдите живой код ниже