Browser Default Actions
Browser Default Actions (浏览器默认操作)
As a rule, events automatically bring certain actions, implemented by the browser. (通常,事件会自动带来某些操作,这些操作由浏览器实现。)
For example, clicking a link will initiate navigation to its URL or pressing a mouse button over a text, and moving it will select that text, and so on. (例如,单击链接将启动对其URL的导航或在文本上按鼠标按钮,移动它将选择该文本,依此类推。)
Sometimes, while handling events in JavaScript, you don’t want the matching browser action to occur. Instead of that, you want to perform another action. In this chapter, you will learn how to do it. (有时,在JavaScript中处理事件时,您不希望发生匹配的浏览器操作。 相反,您希望执行另一个操作。 在本章中,您将学习如何做到这一点。)
How to Prevent Browser Actions
How to Prevent Browser Actions (如何防止浏览器操作)
It is possible to prevent browser actions in two ways:
The main way is using the event object. There exists a event.preventDefault() method. In case the handler is assigned with on<event>, false will be returned in the same way.
In the following HTML example, clicking a link will not bring navigation, so browser does nothing:
<!DOCTYPE html>
<html>
<head>
<title>Title of the Document</title>
</head>
<body>
<a href="/" onclick="return false">Click here</a>
</body>
</html>
or (或)
<!DOCTYPE html>
<html>
<head>
<title>Title of the Document</title>
</head>
<body>
<a href="/" onclick="event.preventDefault()">Click here</a>
</body>
</html>
Usually, the value that is returned by an event handler, is ignored. But, there is an exception: return false from a handler assigned with on<event>. In the rest of the cases return is ignored.
Let’s check out an example of a site menu:
<ul id="menu" class="menu">
<li><a href="/html">HTML</a></li>
<li><a href="/css">CSS</a></li>
<li><a href="/javascript">JavaScript</a></li>
</ul>
The items of the menu are performed as HTML-links <a> rather than buttons. So, in the markup <a> is used. Normally, in JavaScript, developers try to handle clicks. So, the default browser action should be prevented, like in the example below:
<!DOCTYPE html>
<html>
<head>
<title>Title of the Document</title>
</head>
<body>
<ul id="menu" class="menu">
<li><a href="/html">HTML</a></li>
<li><a href="/css">CSS</a></li>
<li><a href="/javascript">JavaScript</a></li>
</ul>
<script>
menu.onclick = function(event) {
if(event.target.nodeName != 'A') {
return;
}
let href = event.target.getAttribute('href');
alert(href);
return false; // prevent url change
};
</script>
</body>
</html>
So, for making the menu more flexible, event delegation should be used.
You can also add nested listed to them, as well as style them with CSS to slide down.
(因此,为了使菜单更加灵活,应使用事件委托。
您还可以向它们添加嵌套列表,以及使用CSS设置它们的样式以向下滑动。)
Passive Handler
Passive Handler (被动处理程序)
On mobile devices, there are events like touchmove that lead to scrolling by default. It can be prevented by applying preventDefault() in the handler. So, anytime a handler detects an event like that, first of all, it performs all the handlers. Afterward, if the preventDefault is not called, it can implement with scrolling. As a consequence, unnecessary delays might happen in UI. The passive: true options inform the browser that the handler will not postpone scrolling.
For several browsers such as Chrome, Firefox by default passive is true for touchmove and touchstart events. (对于Chrome等多种浏览器,默认情况下,对于touchmove和touchstart事件, Firefox是被动的。)
Event.defaultPrevented
Event.defaultPrevented
This property is true when the browser default action is successfully prevented and false - if not. (成功阻止浏览器默认操作时,此属性为true ,否则为false。)
At times event.defaultPrevented can be applied for signaling other event handlers that the event has been handled. (有时, event.defaultPrevented可用于向其他事件处理程序发送已处理事件的信号。)
Here is an example where a default browser event is prevented:
<!DOCTYPE html>
<html>
<head>
<title>Title of the Document</title>
</head>
<body>
<button>Right click show browser context menu</button>
<button oncontextmenu="alert('Draw menu'); return false">
Right click show our context menu
(右键单击上下文菜单)
</button>
</body>
</html>
Then, in addition to the context menu, a document-wide context menu should be implemented:
<!DOCTYPE html>
<html>
<head>
<title>Title of the Document</title>
</head>
<body>
<p>Right click for the document context menu</p>
<button id="elem">Right click the button context menu</button>
<script>
elem.oncontextmenu = function(event) {
event.preventDefault();
alert("Button context menu");
};
document.oncontextmenu = function(event) {
event.preventDefault();
alert("Document context menu");
};
</script>
</body>
</html>
The problem is that two menus appear while clicking on elem . They are the button-level and the document-level menu. (问题是,单击elem时会出现两个菜单。它们是按钮级和文档级菜单。)
A solution to this problem is using event.stopPropagation() like this:
<!DOCTYPE html>
<html>
<head>
<title>Title of the Document</title>
</head>
<body>
<p>Right-click for the document menu</p>
<button id="elem">Right-click for the button menu (fixed with event.stopPropagation)</button>
<script>
elem.oncontextmenu = function(event) {
event.preventDefault();
event.stopPropagation();
alert("The button context menu");
};
document.oncontextmenu = function(event) {
event.preventDefault();
alert("The document context menu");
};
</script>
</body>
</html>
After running it, the button-level menu will work properly. But, in this case, the access to information about right-clicks for any outer code is denied forever. It is not wise, though. (运行后,按钮级菜单将正常工作。但是,在这种情况下,对任何外部代码的右键单击信息的访问将被永久拒绝。但这并不明智。)
But, there is an alternative solution: checking in the document handler whether the default action has been prevented or not. Here is how to act:
<!DOCTYPE html>
<html>
<head>
<title>Title of the Document</title>
</head>
<body>
<p>Right click on the document menu</p>
<button id="elem">Right click on the button menu</button>
<script>
elem.oncontextmenu = function(event) {
event.preventDefault();
alert("The button context menu");
};
document.oncontextmenu = function(event) {
if(event.defaultPrevented) return;
event.preventDefault();
alert("The document context menu");
};
</script>
</body>
</html>
So, now everything will work properly. (所以,现在一切都会正常工作。)
Also, there exist ways of implementing nested context menus. One way is having a single global object with a handler for document.oncontextmenu. Any right click will be caught by the object. It will look through the stored handlers, running the appropriate one. Then, any piece of code that intends to have a context menu must know about the object, using its help rather than the contextmenu handler. (此外,还有实现嵌套上下文菜单的方法。 一种方法是使用document.oncontextmenu的处理程序创建单个全局对象。 任何右键单击都将被对象捕获。 它将查看存储的处理程序,运行适当的处理程序。 然后,任何打算具有上下文菜单的代码都必须使用其帮助而不是上下文菜单处理程序来了解对象。)
Summary
Summary (概要)
All the default actions can be prevented in case you want to handle events exclusively by JavaScript. (如果您希望仅通过JavaScript处理事件,则可以阻止所有默认操作。)
So, for preventing a default action, you can use event.preventDefault() or return false. The latter operates only for the handlers that were assigned using on<event>.
In case the default action was prevented, the value of event.defaultPrevented is set true , if not- false. (如果阻止了默认操作,则event.defaultPrevented的值设置为true ,否则设置为false。)