Before beginning...

Now that we've covered the basics of events in JavaScript we can finally move on to consider some real events, besides the fairly monotonous click. In this chapter we'll take a look over the mouse category of events i.e all the events dispatched by a mouse.

Specifically we'll examine the events mousedown, mouseup, click, contextmenu followed by mouseover, mouseout and finally mouseenter and mouseleave. So why are we waiting here?

The click cycle

A mouse click (which refers to the left button's click) is essentially comprised of a sequence of events, instead of just the click event, happening at different intervals of time, depending on the configuration of the mouse button at that moment.

First the button goes down, and then obviously comes back up again. The former action corresponds with the event mousedown while the latter goes with mouseup.

The names are pretty descriptive so you won't have a hard time remembering them, or recalling the action needed to dispatch them.

Once both these events are fired, and when some conditions are met, the click event is dispatched, to end with. This is the whole cycle of a mouse click.

If you didn't understand a word here, don't worry - let's examine it all even more closely.

The mousedown event

The mousedown event simply accounts for the mouse button going down.

For a given element, such as <div>, it will fire when the mouse button is pressed down and while the pointer is over the element.

It's harder to explain all this, than to visually see it in action, in an example. So likewise let's consider one.

In the following example we first select the <div> element using getElementById(), and then assign a handler to its property onmousedown, to monitor the corresponding event, and make an alert whenever it occurs.

<div id="mouse-area"></div>
var ele = document.getElementById("mouse-area");
ele.onmousedown = function() {
    alert("The mouse is down");
}
To provide a large area for mouse interaction, we've styled this element by giving it a custom 150px of height and a 1px dashed grey border. To learn CSS, check our our CSS Course.

Below we have a live example.

Go on and try to press your mouse's button down over this <div>, making sure you don't leave off the button - otherwise it'll be difficult for you to judge the difference between all the three aformentioned events.

The mouseup event

In contrary to mousedown and always occuring after it, the mouseup event accounts for the mouse button going up.

For a given element, it fires when the mouse button is released and while the pointer is over the element.

Unlike click, as we'll see below, mouseup doesn't take into account the place where the click originated i.e it doesn't care as to where the mousedown event took place.

Once again, it's harder to explain the working of this event in words, instead of showing an actual example to it. Consider the following code:

var ele = document.getElementById("mouse-area");
ele.onmouseup = function() {
    alert("The mouse is up");
}

Everything is the same here as in the code above, except for the event that we're handling. Below you can interact with a live example.

Go on, start from anywhere outside this region, and then move into it, while leaving off the mouse button. Just try to originate your click somewhere else from this element and then come into it - you'll see the magic!

A touchscreen won't be able to distinguish between these events so consider using a mouse, or any other pointing device such as a trackpad.

The click event

Although we've not noticed it as of yet, the click event is merely a more sophisticated version of mouseup, with a few conditions to fire.

An elements dispatches a click event whenever someone clicks on it. However, this stands as an insufficient description of the event?

Technically, an element dispatches a click event whenever the mouse button is released over it and the preceding mousedown event also took place within it.

In simple words, when both mousedown and onmouseup fire within an element - it constitutes a click.

Consider the following code:

var ele = document.getElementById("mouse-area");
ele.onclick = function() {
    alert("You just clicked");
}

As before, below we have a live version of this example.

Try pressing your mouse down in the region above and then leaving it off somewhere outside it. You won't get any alert because in this case, mouseup doesn't fire inside the div. Similarly try going the other way round - starting from the outside and moving inside - even then no alert will be made!

If you think of it naturally, the idea sounds sensible - when you click a button, like on a keyboard, you go down and up right within the domain of that key, without moving much. This is just the concept behind click and the reason to why we call it click!

While working with these live instances and moving around with the mouse key held down, you might encounter the blocked pointer. This can arise when you originate your mousedown event on a piece of text and then move from that point - the browser realises this as a drag event and thus cancels the operation. To prevent this from happening use the preventDefault() method.

Right click?

You might be wondering that for the right mouse button, JavaScript would have an event spelling something like onrightclick. If you did think so, then you predicted the wrong name, but fortunately a feature that JavaScript does indeed provide.

The event is called contextmenu. The reason it's called this is because when we right-click the mouse, typically, a menu appears - referred to by the term context menu.

Consider the basic illustration of this below:

var ele = document.getElementById("mouse-area");
ele.oncontextmenu = function() {
    alert('Right-click detected');
}

As before, first we select the <div> element, and then handle its contextmenu event; popping an alert "Right-click detected" each time it occurs.

Go ahead and try right-clicking inside this element - you'll surely get the alert!

Talking about the practical significance of this event, if you want to design a custom context menu for your application and get it to be displayed rather than the conventional and typical, you could use this event to your advantage.

Just call the event's preventDefault() method to stop the default menu from appearing, and then carry on with whatever code you want to get executed thereafter. To get an idea check out the exercise that follows.

Suppose you have the following <div> element preselected in the variable menu, using document.getElementById("menu").

<div id="menu">Menu</div>

The element is to serve the purpose of a context menu, and therefore has the following styles applied to make it look like one:

#menu {
    position: absolute;
    width: 200px;
    height: 100px;
    border: 1px solid grey;
    border-radius: 4px;
    box-shadow: 20px 20px 50px -30px grey;
    padding: 5px;
    display: none;
}
/* this class will be used to show the #menu */
.show {
    display: block;
}

Your task is to show this element, in place of the default context menu, on the contextmenu event of window; and then hide it once its mousedown event fires outside of this element.

To show the menu, just add the class show to it using classList.add(); and similarly to hide it, just remove the class using classList.remove().

As stated, to show and hide the menu we'll have to use classList.add("show") and classList.remove("show") methods respectively on it.

Furthermore, to make sure that the menu appears right at the pointer's position in the document, we have to get the event's pageX and pageY properties and assign them to its left and top CSS properties using the style object.

And don't forget to call the event's preventDefault() method to prevent the default behaviour of the event, which in this case is the apperance of the context menu.

To hide the menu on mousedown for window, simply check if the event's target is the menu element - if it isn't then we know we have clicked somewhere outside the menu and can thus hide it.

Summing it all together, we get the code below:

// assume menu holds the #menu element

window.oncontextmenu = function(e) {
    e.preventDefault();
    menu.style.left = e.pageX + "px";
    menu.style.top = e.pageY + "px";
    menu.classList.add("show");
}

window.onmousedown = function(e) {
    if (e.target !== menu) {
        menu.classList.remove("show");
    }
}

Mouse enters and leaves

Another common concern of applications is to track exactly when does the mouse pointer enter or leave a given element. The mouseenter and mouseleave events come to the rescue in these cases, respectively.

For a given element:

A mouseenter event fires on it the moment the pointer is brought inside it or its children.

Similarly,

A mouseleave event fires when the pointer is taken outside the element or its children.

Let's consider an example.

Say you want to change the background color of the following paragraph, with initial background color equal to #ddd, to yellow the moment you bring the mouse pointer inside it.

A paragraph

You would write code similar to the following:

var p = document.getElementsByTagName("p")[0];

p.onmouseenter = function() {
    this.style.backgroundColor = "yellow";
}

Try bringing the mouse pointer inside the paragraph shown below. You'll see how it'll change its background color.

A paragraph

Amazing!

Notice one thing in the example above. When we bring the pointer into the element, its background color changes. So far, so good. However when we bring the pointer out of it, its background color doesn't reset to its initial value.

We shall now solve this problem using onmouseleave. The idea is really simple - change the background color back to #ddd inside the onmouseleave handler.

var p = document.getElementsByTagName("p")[0];

p.onmouseenter = function() {
    this.style.backgroundColor = "yellow";
}

// reset to initial value
p.onmouseleave = function() {
    this.style.backgroundColor = "#ddd";
}

A paragraph

The above task could've been accomplished more cleanly and efficiently in CSS, using the :hover pseudo class. However, remember that this doesn't apply to all tasks! Some do require handling mouseenter and mouseleave.

Mouse over and out

Besides mouseenter and mouseleave, there exist two other similar, yet confusing, events namely mouseover and mouseout.

For a given element,

The mouseover event fires when the pointer is brought inside it or its children. The event refires when the pointer is brought from the parent to the child or vice-versa.

At the same time:

The mouseout event fires when the pointer is brought inside the element or its children. The event refires when the pointer is taken from the parent to the child or vice-versa.

The main difference between the set mouseenter and mouseleave and the set mouseover and mouseout lies in the word 'refires'. The example below will clarify what this means.

Suppose you have the following HTML, with a <div> element and a <span> element within it.

<div>A <span>span</span> in a div</div>

Further suppose that the following CSS is in action:

div {
    background-color: #ddd;
    padding: 10px;
}
span {
    display: inline-block;
    padding: 15px;
    background-color: orange;
    color: white
}

.blue {
    background-color: blue
}

Here's how the output looks:

A span in a div

Now with all this in place, let's first investigate the mouseenter and mouseleave events. What we'll be doing is toggling the CSS class blue on the <div> element each time the pointer is brought into it and out of it.

If the class is set on the <div>, it'll be removed; likewise, if it's not set, it'll be added.

Consider the code below:

var div = document.getElementsByTagName("div")[0];

div.onmouseenter = function() {
    this.classList.toggle("blue");
}

Try experimenting around with the live example shown below.

A span in a div

When you move your mouse pointer into the <div> element, its background changes to pink. Now when you take the pointer out and then again into the element, its background changes back to #ddd.

Moreover, when you enter the div, and then hover over <span> nothing happens. This is because the mouseenter event does NOT refire.

But, as we've seen, the mouseover and mouseout events do. Handling them would showcase an interesting behaviour.

Consider the code below. This time we're not handling mouseenter, but rather its refiring counterpart - mouseover.

div.onmouseover = function() {
    this.classList.toggle("blue");
}
A span in a div

When you move the pointer into the div element, as before, its background changes to pink. But if you now go over the <span> element, you'll see that the background color of div changes back to #ddd.

Then when you move out of <span>, the background goes to pink, once again. Moving into it again, will result in the same background style change.

What's happening over here!

Well this might both sound and seem confusing, but if you take a closer look at it, you'll find that everything works pretty sensibly.

Recall our earlier definition:

The mouseover event fires on an element each time the mouse pointer is brought over it or one of its children.

In the last example above, when we brought the pointer into <div> from outside, its mouseover event fired and consequently the background color changed to pink.

Then when we moved into the <span> element, the mouseover event fired again, (since we've moved from <div> to its child <span>), and so the background color changed back to #ddd.

Moving out of the <span> caused another mouseover event (since we've moved from a child of <div> to itself) resulting in the background color changing again to pink.

This change keeps on happening as long as we keep on moving the pointer between the <div> and <span> elements; as on each movement, we either move from a child to its parent, or from a parent to its child which dispatches a mouseover event on <div>.

A similar result will be achieved with mouseout, as can be seen below:

div.onmouseout = function() {
    this.classList.toggle("blue");
}
A span in a div

As a rule of thumb, remember that for a given element:

The mouseover and mouseout events fire on it each time the pointer is brought into the element or its child or brought out of it or its child, respectively.

The target property

One useful thing about these events is that when either of them fires, their event object's target property points to the element which specifically caused the event.

For example, in the example above using mouseover, when we moved into <span>, logging the event object's target property would've returned this element since the pointer went inside it and resulted in the mouseover event.

Consider the following code:

<p>Mouse pointer went inside <code id="tag"></code></p>
<div>A <span>span</span> in a div</div>
var tag = document.getElementById("tag");

div.onmouseover = function(e) {
    tag.innerText = e.target.nodeName;
}

Mouse pointer went inside

A span in a div

We log the target's tag name that specifically causes the mouseover event.

The question is, why would anyone want to handle mouseover and mouseout?

Let's consider a more practical example.

Say you are working on an online wireframing application that allows one to create elements and then inspect their properties by hovering over them. The following illustration shows a part of the artboard of a user:

A div
A sub div
A sub-sub div

You have to accomplish a very simple-sounding task. When the user moves his pointer into any element, a dashed outline shall appear around it. Conversely, when he moves his pointer away from the element, the outline shall go away.

How will you approach such a problem?

If we didn't have the mouseover event in our inventory, we would have to handle mouseenter on every element in the document, which could become really inefficient. The go-to solution for this problem is to use mouseover and mouseout.

We'll handle these events on the main body element. The result - our problem solved!

document.body.onmouseover = function(e) {
    e.target.style.outline = "1px dashed red";
}

document.body.onmouseout = function(e) {
    e.target.style.outline = "none";
}
A div
A sub div
A sub-sub div

Mouse moving

The last event left to be explored in this chapter is mousemove.

As the name might suggest:

The mousemove event fires continuously while the pointer moves over an element.

Generally, when this event is handled on any element, the coordinates of the mouse pointer are required inside the handler. That is, the clientX and clientY properties of the event's argument object are called upon.

Consider the simple example below:

<p>Coordinates of pointer: (<code id="x-pos"></code>, <code id="y-pos"></code>)</p>

<div>Move the mouse here</div>

Coordinates of pointer: (, )

Move the mouse here

As we move the pointer inside the <div>, we'll log the coordinates of the pointer in the respective <code> elements.

var div = document.getElementsByTagName("div")[0],
     xPos = document.getElementById("x-pos"),
     yPos = document.getElementById("y-pos");

div.onmousemove = function(e) {
    xPos.innerText = e.clientX;
    yPos.innerText = e.clientY;
}

Live Example

And with this we are done with mouse events!