# Browser default actions Many events automatically lead to browser actions. For instance: - A click on a link -- initiates going to its URL. - A click on submit button inside a form -- 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, often we don't want browser actions. Fortunately, it can be prevented. ## 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 we can also return `false` from it. In the example below a click to links doesn't lead to URL change: ```html autorun height=60 no-beautify Click here or here ``` ```warn header="Not necessary to return `true`" 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` is not needed and it's not processed anyhow. ``` ### 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 links ``, not buttons. There are several benefits, for instance: - Many people like to use "right click" -- "open in a new window". If we use ` ``` 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 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 `