在移动即时通讯上,使用javascript切换下拉菜单。 单击列表项时,下拉列表应该可见,然后再次单击以切换回去。
问题:如果我想在下拉菜单中使用搜索栏,则该下拉菜单会切换回不可见的位置,在搜索栏中单击。
jQuery:
$('.has-dropdown-two').on('click', function() {
$(this).toggleClass('is-active').children('ul').toggleClass('is-visible');
});
首先,我尝试制作一个if子句,例如:
if ($(this).hasClass('nav-dropdown-two') ) ..
不起作用...然后我检查了console.log(this),看起来像单击ul时,它具有与单击li时相同的输出。
我做了一个非常简单的预览:
$('.has-dropdown-two').on('click', function() {
var $this = $(this);
$(this).toggleClass('is-active').children('ul').toggleClass('is-visible');
});
.has-dropdown-two > .menu-link { display: inline-block; }
.has-dropdown-two.is-active > .nav-dropdown-two {
display: block;
}
.nav-dropdown-two {
display: none;
position: absolute;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<li class="menu-item has-dropdown-two"> <a href="javascript:void(0);" class="menu-link stopnewline">Search</a>
<ul class="nav-dropdown-two menu">
<div class="search-container">
<form action="">
<input type="text" name="search">
<button type="submit">search</button>
</form>
</div>
</ul>
</li>
根据lumio的解决方案进行编辑:
$('.has-dropdown-two').on('click', function(event) {
if ( event.target.tagName === 'A' || event.target.tagName === 'I' ) {
$(this).toggleClass('is-active').children('ul').toggleClass('is-visible');
}else{
return;
}
});
答案 0 :(得分:3)
确实如mrdeadsven所述。事件冒泡了。这意味着,如果点击事件发生在孩子身上,那么它也发生在父母身上。除非得到预防。
您可以在<a>
标签上设置点击处理程序,也可以通过将事件参数传递给事件处理程序功能来检查实际单击的内容。
$('.has-dropdown-two').on('click', function( event ) {
// Check the tagName of clicked target element
const tagName = event.target.tagName;
if ( tagName === 'INPUT' || tagName === 'button' ) {
return;
}
var $this = $(this);
$(this).toggleClass('is-active').children('ul').toggleClass('is-visible');
});
.has-dropdown-two>.menu-link {
display: inline-block;
}
.has-dropdown-two.is-active>.nav-dropdown-two {
display: block;
}
.nav-dropdown-two {
display: none;
position: absolute;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li class="menu-item has-dropdown-two"> <a href="javascript:void(0);" class="menu-link stopnewline">Search</a>
<ul class="nav-dropdown-two menu">
<div class="search-container">
<form action="">
<input type="text" name="search">
<button type="submit">search</button>
</form>
</div>
</ul>
</li>
</ul>
无需使用jQuery,您可以非常轻松地完成上述示例。
另一种解决方案是检查<a>
标签是否导致事件触发。这甚至可能是更好的解决方案,因为它也适用于嵌套子菜单。
const subMenuToggle = ( event ) => {
// Only watch clicks on .toggle-switch
if ( !event.target.classList.contains( 'toggle-switch' ) ) {
return;
}
// Prevent the actual click on the link
event.preventDefault();
// Toggle .is-active on parent <li> element
const parent = event.target.parentNode;
const className = 'is-active';
parent.classList.toggle( className );
// Only open the next direct ul
parent.querySelectorAll( ':scope > ul' ).forEach( ( element ) =>
element.classList.toggle( className )
);
};
// Get all ul.navigation on the page
document
.querySelectorAll( '.navigation' )
.forEach( ( element ) => {
element.addEventListener( 'click', subMenuToggle );
} );
.nav-dropdown-two {
display: none;
}
.nav-dropdown-two.is-active {
display: block;
}
<!-- added .navigation for later -->
<ul class="navigation">
<li class="menu-item has-dropdown-two">
<!-- added the .toggle-switch for the event listener -->
<a href="#" class="toggle-switch">Search</a>
<ul class="nav-dropdown-two menu">
<li>
<div class="search-container">
<form action="">
<input type="text" name="search">
<button type="submit">search</button>
</form>
</div>
</li>
<li>
<a href="#" class="toggle-switch">more</a>
<ul class="nav-dropdown-two">
<li>Sub menu</li>
</ul>
</li>
</ul>
</li>
</ul>
答案 1 :(得分:0)
就像@mrdeadsven一样,这是由于event propagation造成的。
您可以通过将另一个侦听器附加到表单并在其中调用event.stopPropagation()
来关闭它。
$('form').on('click', function(e){
e.stopPropagation();
})