我正在学习Javascript,我正在尝试创建一个简单的下拉菜单。我可以在顶部菜单的Google主页上看到我所需功能的一个示例,其中包含“更多”和“设置”下拉列表。特别是当您单击菜单时,菜单消失。
我需要在Javascript中的hideMenus函数中放置什么代码,以便在屏幕上的任何位置发生单击时隐藏可见的uls?
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
<title>Untitled 1</title>
<style type="text/css">
a
{
color:blue;
}
.info ul.submenu
{
border: solid 1px #e0e0e0;
background-color: #fff;
position: absolute;
padding: 0;
z-index: 2;
display: none;
}
.info ul.submenu li
{
display: block;
border-top: solid 1px #e0e0e0;
margin: 0px 10px 0 10px;
}
.info ul.submenu li a
{
display: block;
padding: 7px 0px 6px 0;
color: #1177ee;
cursor:pointer;
}
</style>
<script type="text/javascript">
function hideMenus()
{
//TODO
}
function menu(id) {
var myLayer = document.getElementById(id);
myLayer.onblur = function() {
myLayer.style.display = 'none';
};
if (myLayer.style.display == "none" || myLayer.style.display == "") {
myLayer.style.display = "block";
} else {
myLayer.style.display = "none";
}
}
</script>
</head>
<body onclick="hideMenus();">
<div class="info">
Some Text Boom A <a onclick="menu('id1');">Link</a> | More text
<a onclick="menu('id2');">Another Link</a> | more text
<ul id="id1" class="submenu">
<li><a href="dfhdfh">A1</a></li>
<li><a href="aetjetjsd">A2 This is Long</a></li>
<li><a href="etetueb">A3</a></li>
</ul>
<ul id="id2" class="submenu">
<li><a href="dfhdfh">B1</a></li>
<li><a href="aetjetjsd">B2</a></li>
<li><a href="etetueb">B3</a></li>
</ul>
</div>
</body>
</html>
我不想使用jQuery。
答案 0 :(得分:1)
看起来你的设置相当不错。您可能会遇到一些事件冒泡问题(有关更多信息,请查看PPK's Event Order Article)。这似乎超出了您当前问题的范围,所以我只会告诉您所要求的内容:
hideMenus()
{
var uls = document.getElementsByTagName('ul'), i;
for (i = 0; i < uls.length; i++)
{
if (uls[i].className === 'submenu' && uls[i].style.display !== 'none')
{
uls[i].style.display = 'none';
}
}
}
首先,我们在页面上获得所有&lt; ul&gt;。然后,我们遍历所有这些,检查它是否是子菜单,以及它当前是否显示。如果两者都是真的,那么我们隐藏它。
此代码存在一些错误:
class="animal submenu"
),则不会隐藏菜单getElementsByClass
的跨浏览器支持,这是唯一的方法。这些不是很大的错误,特别是如果你只是用它来学习javascript,并且如果你密切控制你的代码(即没有其他开发人员正在研究它)。总而言之,这是一个很好的垫脚石。
将来,我建议使用addEvent
- 一个相当常见的函数,允许您在不使用onclick="..."
的情况下向元素添加事件处理程序。它有几种不同的实现,但它们(几乎)从你的角度来看都是一样的。以下是Dean Edwards's Version和John Resig's Version
答案 1 :(得分:0)
这里或多或少是我们在网络应用中用于下拉菜单的逻辑:
<html>
<head>
<title></title>
</head>
<body>
<div style="position:relative;width:250px">
<a id="link" href="javascript:" onclick="showDiv(this)">Show menu</a>
<ul id="entries" style="display:none;background:#DEF;padding:0;margin:0">
<li>item 1</li>
<li>item 2</li>
</ul>
<input id="inp" style="position:absolute;left:-30px;width:0" />
</div>
<script>
function showDiv(lnk){
var entries = document.getElementById('entries'),
inp = document.getElementById('inp'),
nh = 'data-nohide';
//show the entries
entries.style.display = 'block';
entries.removeAttribute(nh);
inp.focus();
//if mouse over, can't close it
entries.onmouseover = function(){
this.setAttribute(nh, true);
inp.focus();
};
//if mouse out, can close it
entries.onmouseout = function(){
this.removeAttribute(nh);
};
entries.onclick = function(e){
//code when the user clicks on the menu...
alert((e.target||e.sourceElement).innerHTML);
this.style.display = 'none';
};
//if the user press ESC
inp.onkeyup = function(e){
if(e.keyCode === 27){
this.style.display = 'none';
this.removeAttribute(nh);
}else{
//do something else with other keys(ie:down, up, enter)...
inp.focus();
}
};
//click somewhere else input onblur
inp.onblur = function(){
if(!entries.getAttribute(nh)){
entries.style.display = 'none';
entries = inp = null;
}
};
}
</script>
</body>
</html>
诀窍是使用具有input
的{{1}}字段,当它失去时,会触发focus
并关闭菜单。
当用户点击菜单中的某个项目时,onblur
,mouseover
会阻止mouseout
触发。
要想像链接上的打开/关闭一样具有切换效果,我想需要2个相互隐藏的链接。
答案 2 :(得分:-1)
如果你点击身体,你可以在任何地方捕获一个点击。 由于javascript事件传播模型,如果您单击任何元素上的任何位置并且不会阻止事件传播,它将到达正文并隐藏菜单。
所以基本上这意味着你想捕捉身体onclick并让它隐藏菜单,所以当你点击页面的任何区域时,它会关闭菜单。
但这隐藏了一些不必要的行为 - 当您点击按钮显示菜单时,菜单将显示并快速隐藏(当事件到达正文时)。为了防止这种情况,当您单击显示菜单的按钮时,您将希望阻止事件传播(您可以在我下面发布的代码中看到它是如何工作的)。代码显示了您需要触摸的位置,以使其正常工作。
// this function stops event e or window.event if e is not present from
// propagating to other elements.
function stop_event(e) {
if(!e) {
e = window.event;
}
if (e.stopPropagation) e.stopPropagation();
e.cancelBubble = true;
if (e.preventDefault) e.preventDefault();
e.returnValue = false;
return false;
}
// now you just hide all the menus in your hideMenus
function hideMenus()
{
//pseudocode!
for all visible menus - hide // or if you want you can hide all menus,
// the hidden will remain hidden
}
现在是重要的一部分。
function menu(id) {
// your stuff here
stop_event(); // this will stop the event going down to the body
// and hiding it after showing it
// this means it will not flicker like: show-hide
}
最后是你的整个UL元素:
//partly pesudocode
ul.onclick = function() { stop_event(); }
再次解释这是做什么的:
第一。您将hideMenu函数挂钩到body.onclick。这意味着如果我们不停止事件,它将始终隐藏菜单。
第二。单击菜单按钮时,显示菜单,然后我们停止事件进入正文。这样,body.onclick将不会触发,并且在我们打开它之后它不会立即隐藏菜单。
第三。 ul.onclick意味着当我们点击它时菜单不会隐藏(虽然如果你想在单击菜单本身时隐藏菜单,你可以删除这部分)。