`. There are handlers on the parent that listen for `mouseover/out` events and output their details.
If you move the mouse from the parent to the child, you see two events: `mouseout [target: parent]` (left the parent) and `mouseover [target: child]` (came to the child, bubbled).
[codetabs height=360 src="mouseoverout-child"]
```
When we move from a parent element to a child, then two handlers trigger on the parent element: `mouseout` and `mouseover`:
```js
parent.onmouseout = function(event) {
/* event.target: parent element */
};
parent.onmouseover = function(event) {
/* event.target: child element (bubbled) */
};
```
If the code inside the handlers doesn't look at `target`, then it might think that the mouse left the `parent` element, and then came back over it. But it's not the case! The mouse never left, it just moved to the child element.
If there's some action upon leaving the element, e.g. animation runs, then such interpretation may bring unwanted side effects.
To avoid it, we can check `relatedTarget` and, if the mouse is still inside the element, then ignore such event.
Alternatively we can use other events: `mouseenter` и `mouseleave`, that we'll be covering now, as they don't have such problems.
## Events mouseenter and mouseleave
Events `mouseenter/mouseleave` are like `mouseover/mouseout`. They trigger when the mouse pointer enters/leaves the element.
But there are two important differences:
1. Transitions inside the element, to/from descendants, are not counted.
2. Events `mouseenter/mouseleave` do not bubble.
These events are extremely simple.
When the pointer enters an element -- `mouseenter` triggers. The exact location of the pointer inside the element or its descendants doesn't matter.
When the pointer leaves an element -- `mouseleave` triggers.
```online
This example is similar to the one above, but now the top element has `mouseenter/mouseleave` instead of `mouseover/mouseout`.
As you can see, the only generated events are the ones related to moving the pointer in and out of the top element. Nothing happens when the pointer goes to the child and back. Transitions between descendants are ignores
[codetabs height=340 src="mouseleave"]
```
## Event delegation
Events `mouseenter/leave` are very simple and easy to use. But they do not bubble. So we can't use event delegation with them.
Imagine we want to handle mouse enter/leave for table cells. And there are hundreds of cells.
The natural solution would be -- to set the handler on `
` and process events there. But `mouseenter/leave` don't bubble. So if such event happens on ``, then only a handler on that ` | ` is able to catch it.
Handlers for `mouseenter/leave` on `` only trigger when the pointer enters/leaves the table as a whole. It's impossible to get any information about transitions inside it.
So, let's use `mouseover/mouseout`.
Let's start with simple handlers that highlight the element under mouse:
```js
// let's highlight an element under the pointer
table.onmouseover = function(event) {
let target = event.target;
target.style.background = 'pink';
};
table.onmouseout = function(event) {
let target = event.target;
target.style.background = '';
};
```
```online
Here they are in action. As the mouse travels across the elements of this table, the current one is highlighted:
[codetabs height=480 src="mouseenter-mouseleave-delegation"]
```
In our case we'd like to handle transitions between table cells ``: entering a cell and leaving it. Other transitions, such as inside the cell or outside of any cells, don't interest us. Let's filter them out.
Here's what we can do:
- Remember the currently highlighted ` | ` in a variable, let's call it `currentElem`.
- On `mouseover` -- ignore the event if we're still inside the current ` | `.
- On `mouseout` -- ignore if we didn't leave the current ` | `.
Here's an example of code that accounts for all possible situations:
[js src="mouseenter-mouseleave-delegation-2/script.js"]
```online
Here's the full example with all details:
[codetabs height=380 src="mouseenter-mouseleave-delegation-2"]
Try to move the cursor in and out of table cells and inside them. Fast or slow -- doesn't matter. Only ` | ` as a whole is highlighted, unlike the example before.
```
## Summary
We covered events `mouseover`, `mouseout`, `mousemove`, `mouseenter` and `mouseleave`.
These things are good to note:
- A fast mouse move may skip intermediate elements.
- Events `mouseover/out` and `mouseenter/leave` have an additional property: `relatedTarget`. That's the element that we are coming from/to, complementary to `target`.
Events `mouseover/out` trigger even when we go from the parent element to a child element. The browser assumes that the mouse can be only over one element at one time -- the deepest one.
Events `mouseenter/leave` are different in that aspect: they only trigger when the mouse comes in and out the element as a whole. Also they do not bubble.
| |