Browser default actions
Many events automatically lead to certain actions performed by the browser. For instance: - A click on a link - initiates navigation to its URL. - A click on a form submit button - initiates its submission to the server. - Pressing a mouse button over a text and moving it - selects the text. If we handle an event in JavaScript, we may not want the corresponding browser action to happen, and want to implement another behavior instead.
Preventing browser actions
There are two ways to tell the browser we don’t want it to act:
- The main way is to use the event object. There’s a method event.preventDefault().
- If the handler is assigned using on
Example: the menu
Consider a site menu, like this: Here’s how it looks with some CSS: [iframe height=70 src=“menu” link edit] Menu items are implemented as HTML-links , not buttons
The “passive” handler option
The optional passive: true option of addEventListener signals the browser that the handler is not going to call preventDefault(). Why might that be needed? There are some events like touchmove on mobile devices (when the user moves their finger across the screen), that cause scrolling by default, but that scrolling can be prevented using preventDefault() in the handler. So when the browser detects such event, it has first to process all handlers, and then if preventDefault is not called anywhere, it can proceed with scrolling. That may cause unnecessary delays and “jitters” in the UI. The passive: true options tells the browser that the handler is not going to cancel scrolling. Then browser scrolls immediately providing a maximally fluent experience, and the event is handled by the way. For some browsers (Firefox, Chrome), passive is true by default for touchstart and touchmove events.
event.defaultPrevented
The property event.defaultPrevented is true if the default action was prevented, and false otherwise. There’s an interesting use case for it. You remember in the chapter info:bubbling-and-capturing we talked about event.stopPropagation() and why stopping bubbling is bad? Sometimes we can use event.defaultPrevented instead, to signal other event handlers that the event was handled. Let’s see a practical example. By default the browser on contextmenu event (right mouse click) shows a context menu with standard options. We can prevent it and show our own, like this: Now, in addition to that context menu we’d like to implement document-wide context menu. Upon right click, the closest context menu should show up. The problem is that when we click on elem, we get two menus: the button-level and (the event bubbles up) the document-level menu. How to fix it? One of solutions is to think like: “When we handle right-click in the button handler, let’s stop its bubbling” and use event.stopPropagation(): Now the button-level menu works as intended. But the price is high. We forever deny access to information about right-clicks for any outer code, including counters that gather statistics and so on. That’s quite unwise. An alternative solution would be to check in the document handler if the default action was prevented? If it is so, then the event was handled, and we don’t need to react on it. Now everything also works correctly. If we have nested elements, and each of them has a context menu of its own, that would also work. Just make sure to check for event.defaultPrevented in each contextmenu handler.
Summary
There are many default browser actions:
- mousedown – starts the selection (move the mouse to select).
- click on – checks/unchecks the input.
- submit – clicking an or hitting key:Enter inside a form field causes this event to happen, and the browser submits the form after it.
- keydown – pressing a key may lead to adding a character into a field, or other actions.
- contextmenu – the event happens on a right-click, the action is to show the browser context menu.
- …there are more…
All the default actions can be prevented if we want to handle the event exclusively by JavaScript.
To prevent a default action – use either event.preventDefault() or return false. The second method works only for handlers assigned with on
<a href="/" onclick="return false">Click here</a> or <a href="/" onclick="event.preventDefault()">here</a>
Follow the lesson from Microsoft Web-Dev-For-Beginners course