Javascript 主体 OnClick
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3521487/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Javascript body OnClick
提问by Jim Roboju
I'm in the process of learning Javascript and I'm trying to create a simple dropdown menu. An example of my desired functionality can be seen on the google homepage in the top menu with the "more" and "settings" dropdown. Specifically when you click off the menu, the menu disappears.
我正在学习 Javascript,我正在尝试创建一个简单的下拉菜单。我想要的功能的一个例子可以在谷歌主页的顶部菜单的“更多”和“设置”下拉菜单中看到。特别是当您单击菜单外时,菜单会消失。
What code do I need to place in the hideMenus function in Javascript to hide the visible uls when a click occurs anywhere on screen?
我需要在 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>
I do not want to use jQuery.
我不想使用 jQuery。
采纳答案by Ryan Kinal
It looks like you have a pretty decent setup as-is. You'll likely run into some event bubbling problems (for more info, take a look at PPK's Event Order Article). That seems to be outside of the scope of your current question, so I'll just give you what you asked for:
看起来你有一个相当不错的设置。您可能会遇到一些事件冒泡问题(有关更多信息,请查看PPK 的事件顺序文章)。这似乎超出了您当前问题的范围,因此我将仅提供您所要求的内容:
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';
}
}
}
First, we get all the <ul>'s on the page. Then, we loop through all of them, check to see if it's a submenu, and if it's currently displayed. If both are true, then we hide it.
首先,我们获取页面上的所有 <ul>。然后,我们遍历所有这些,检查它是否是一个子菜单,以及它当前是否显示。如果两者都是真的,那么我们隐藏它。
There are a couple faults with this code:
这段代码有几个错误:
- If the uls have more than one class (
class="animal submenu"), then it will not hide the menu - It will look through allthe <ul>'s on the page. This isn't exactly efficient, but it's the only way to do it without cross-browser support for
getElementsByClass.
- 如果 uls 有多个类 (
class="animal submenu"),那么它不会隐藏菜单 - 它将查看页面上的所有<ul>。这并不完全有效,但它是在没有跨浏览器支持的情况下做到这一点的唯一方法
getElementsByClass。
These aren't huge faults, especially if you're only using this to learn about javascript, and if you closely control your code (i.e. no other developers are working on it). All in all, it's a good stepping stone.
这些都不是很大的错误,特别是如果您只是使用它来学习 javascript,并且如果您严格控制您的代码(即没有其他开发人员正在处理它)。总而言之,这是一个很好的垫脚石。
In the future, I'd suggest using addEvent- a fairly common function that allows you to add event handlers to elements without using onclick="...". There are a couple different implementations of it, but they (almost) all work the same from your perspective. Here are links to Dean Edwards's Versionand John Resig's Version
将来,我建议使用addEvent- 一个相当常见的函数,它允许您向元素添加事件处理程序,而无需使用onclick="...". 它有几种不同的实现,但从您的角度来看,它们(几乎)都一样。这里是Dean Edwards 版本和John Resig 版本的链接
Good luck!
祝你好运!
回答by Mic
Here is more or less the logic we use in our web app for drop down menus:
以下是我们在 Web 应用程序中用于下拉菜单的逻辑:
<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>
The trick is to use an inputfield that has the focus, and when it looses it an onbluris triggered and close the menu.
诀窍是使用具有 的input字段,focus当它丢失时,onblur会触发并关闭菜单。
The mouseover, mouseoutare there to prevent the onblurto fire when the user click an item in the menu.
的mouseover,mouseout在那里,以防止onblur火灾,当用户单击该菜单中的项目。
To have a toggle effect like an open/close on the link, I guess 2 links that hide each other are needed.
要在链接上具有打开/关闭之类的切换效果,我想需要 2 个相互隐藏的链接。
回答by bisko
You can capture a click anywhere if you put onclick on the body. Because of the javascript event propagation model, if you click anywhere on any element and you don't stop the event from propagating, it will reach body and hide the menus.
如果您将 onclick 放在身体上,您可以在任何地方捕获点击。由于 javascript 事件传播模型,如果您单击任何元素上的任何位置并且不阻止事件传播,它将到达正文并隐藏菜单。
So basically this means that you want to capture body onclick and make it to hide the menus so when you click on any area of the page, it will close the menus.
所以基本上这意味着您想要捕获主体 onclick 并使其隐藏菜单,因此当您单击页面的任何区域时,它将关闭菜单。
But this hides a bit of unwanted behaviour - when you click on the button to show the menu, the menu will display and quickly after that hide (when the event reaches body). To prevent this, you will want to stop the event from propagating when you click on the button which shows the menu (you can see how this works in the code I posted below). The code shows where you need to touch to make it work nicely.
但这隐藏了一些不需要的行为 - 当您单击按钮以显示菜单时,菜单将显示并在隐藏之后快速显示(当事件到达正文时)。为了防止这种情况,当您单击显示菜单的按钮时,您将希望阻止事件传播(您可以在我下面发布的代码中看到它是如何工作的)。该代码显示了您需要触摸的位置才能使其正常工作。
// 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
}
Now the important part.
现在是重要的部分。
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
}
And finally on your whole UL element:
最后关于你的整个 UL 元素:
//partly pesudocode
ul.onclick = function() { stop_event(); }
To explain again what this does:
再次解释它的作用:
1st. You hook your hideMenu function to body.onclick. This means that it will always hide the menus if we don't stop the event.
第一。您将 hideMenu 函数挂接到 body.onclick。这意味着如果我们不停止事件,它将始终隐藏菜单。
2nd. When you click the menu button, you show the menu and then we stop the event from going to the body. This way, the body.onclick will not fire and it will not hide the menu right after we opened it.
第二。当您单击菜单按钮时,您会显示菜单,然后我们阻止事件进入正文。这样, body.onclick 不会触发,也不会在我们打开菜单后立即隐藏它。
3rd. The ul.onclick means that the menu will not hide itself when we click on it (though if you want the menu to hide when you click the menu itself, you can remove this part).
第三。ul.onclick 意味着当我们点击它时菜单不会隐藏自己(尽管如果你想要在你点击菜单时隐藏菜单,你可以删除这部分)。

