# 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` (not by `addEventListener`), then returning `false` also works the same. In this HTML a click on a link doesn't lead to navigation, browser doesn't do anything: ```html autorun height=60 no-beautify Click here or here ``` In the next example we'll use this technique to create a JavaScript-powered menu. ```warn header="Returning `false` from a handler is an exception" The value returned by an event handler is usually ignored. The only exception is `return false` from a handler assigned using `on`. In all other cases, `return` value is ignored. In particular, there's no sense in returning `true`. ``` ### Example: the menu Consider a site menu, like this: ```html ``` Here's how it looks with some CSS: [iframe height=70 src="menu" link edit] Menu items are implemented as HTML-links ``, not buttons ` ``` 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. ```html autorun height=80 no-beautify run

Right-click here for the document context menu

``` 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()`: ```html autorun height=80 no-beautify run

Right-click for the document menu

``` 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. ```html autorun height=80 no-beautify run

Right-click for the document menu (added a check for event.defaultPrevented)

``` 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. ```smart header="event.stopPropagation() and event.preventDefault()" As we can clearly see, `event.stopPropagation()` and `event.preventDefault()` (also known as `return false`) are two different things. They are not related to each other. ``` ```smart header="Nested context menus architecture" There are also alternative ways to implement nested context menus. One of them is to have a single global object with a handler for `document.oncontextmenu`, and also methods that allow us to store other handlers in it. The object will catch any right-click, look through stored handlers and run the appropriate one. But then each piece of code that wants a context menu should know about that object and use its help instead of the own `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`. The `passive: true` option of `addEventListener` tells the browser that the action is not going to be prevented. That's useful for some mobile events, like `touchstart` and `touchmove`, to tell the browser that it should not wait for all handlers to finish before scrolling. If the default action was prevented, the value of `event.defaultPrevented` becomes `true`, otherwise it's `false`. ```warn header="Stay semantic, don't abuse" Technically, by preventing default actions and adding JavaScript we can customize the behavior of any elements. For instance, we can make a link `
` work like a button, and a button `