The tests were done with the intention of learning just enough to write the code I needed to write. Many, many browsers have been tested over the years. The most recent test on each platform were done with the browser versions in the table below.
| Windows | Macintosh | Linux | |
| Internet Explorer | 7.0.5730.11 | 5.2 | - |
| Firefox | 2.0.0.1 (Gecko 1.8.1.1 |
2.0.0.1 (Gecko 1.8.1.1 |
2.0.0.2 (Gecko 1.8.1.2) |
| Safari | 3.1.1 | 3.1.1 | - |
| Opera | 9.10 | 9.10 | 9.27 |
| Konqueror | - | - | 3.5.7 |
| iCab | - | 3.0.3 | - |
Tests were also performed on Netscape, Mozilla, Camino, Seamonkey, and Epiphany/Galeon. These all use the same layout engine as Firefox, called "Gecko" and behave the same way as versions of Firefox with the same Gecko version. In this article we will generally refer to Gecko version numbers instead of any particular Gecko-based browser version numbers. See the Gecko version table for the mapping.
The script used to collect the test results reported here is available at http://unixpapa.com/js/testmouse.html.
All browsers let you disable the default action of the left mouse button. I typically do this by ending the event handling function with the following code, which should cover all browsers:
if (event.preventDefault)
event.preventDefault();
else
event.returnValue= false;
return false;
However, in some browsers the default actions of the right and middle mouse buttons cannot be disabled, or can only be disabled by changing browser settings. Such changes to browser settings typically effect all pages viewed through the browser, and typically cannot be done from Javascripts. Since few users will want to do this, it pretty much means that the those mouse events are not usable from Javascript.
Netscape 4 pioneered this philosophy by making it impossible to disable the URL paste that occurs with a middle click, and requiring a config file edit to disable the context menus that come up with a right click. Firefox and the other Gecko browsers have released control of the right mouse button, but the default action of a middle click can only be disabled by a config file edit.
It's the Opera browser that raises this to a high art form. In Opera versions before 7.23 right click events were never sent to Javascript. In Opera 7.23, possibly as a result of complaints by yours truly, they added a preference option that can be checked to "Allow Javascript to receive right clicks". This option moved to at least three different places in subsequent releases. When I last looked it was in
Tools > Preferences > Advanced > Content > Javascript OptionsHowever, this option was over generous. If you set up a event handler on any part of the page (like on the link on my mouse event test page then the context menu would be disable not only over that link, but over the entire page. Furthermore, only mousedown events were sent, not mouseup.
The Opera people fixed this sometime between the 7.54 and 8.5 release. But only sort of. Now if you enable the "Allow Javascript to receive right clicks" option, Javascript does receive the right clicks, but the default action cannot be disabled. It always comes up. Without being able to disable the default action, capturing the event is now completely useless, and they might as well just remove the option, since it doesn't do anyone any good at all. The same problems occur for middle mouse buttons.
Macintosh versions of Safari and iCab, of course, are immune to these problems, because Macintoshes only have one mouse button. Windows versions of Safari allow all buttons to be used.
So here's the final score card:
| Left Button | Middle Button | Right Button | |
| Internet Explorer | Yes | Yes | Yes |
| Firefox | Yes | Config file edit only | Yes |
| Mac Safari and iCab | Yes | No such buttons | |
| Windows Safari | Yes | Yes | Yes |
| Opera 7.23-7.54 | Yes | Only if user has enabled an obscure option | |
| Other Opera Versions | Yes | No | No |
| Konqueror | Yes | Yes | Yes |
| Netscape 4 | Yes | Config file edit only | |
The mousedown and mouseup events are meant mostly for situations where you depress the mouse button, move the mouse and then release it, say when a section of text is selected or when an object is dragged.
The click and dblclick events are meant mostly for situations where you are simply clicking on a link or a button. A click event normally occurs if there is a mousedown and a mouseup event on the same object. If you move the mouse to point to something else between mousedown and mouseup, then there will be no click event.
The contextmenu event is triggered on some browsers when you right click on something and it's default action is to bring up the browser's standard context menu. I think that in theory this event isn't really a mouse event. It might also be triggered by a keyboard shortcut. However it is usually associated with mouse clicks in practice.
If you do a single mouse click of the left mouse botton, every browser I've checked does exactly the same thing. When the mouse goes down, a mousedown event is triggered. When the mouse goes back up, first a mouseup event and then a click event is triggered. Very nice.
| All Browsers | |
| DOWN | mousedown |
| UP | mouseup click |
So, here's what happens when you do click on the right mouse button, which is actually usable in IE, Firefox, and Konqueror:
| Internet Explorer Windows Safari |
Gecko Browsers | Opera 9 and Konqueror |
Opera 7 and Netscape 4 |
|
| DOWN | mousedown | mousedown contextmenu |
mousedown | mousedown |
| UP | mouseup contextmenu |
mouseup | mouseup | - |
First notice that there are no click events for right button clicks in any browser.
Second, notice that the contextmenu event exists only in Gecko browsers, IE and Safari, but it happens at different times in these browsers. This relates to the different behavior of the context menus in IE and Gecko browsers. In Firefox, they come up when the mouse key is depressed, while in IE, they don't come up until the mouse is released.
The browsers that give you no mouseup are not that much a concern because they are old and the default actions of right clicks can't be disabled from Javascript anyway.
The question of what happens on middle clicks is less academic than it used to be. In the olden days, only Unix machines commonly had three button mice. But now most Windows mice have a scroll wheel between the two buttons that can be clicked and acts as a middle button. However, Firefox and Opera still have default actions associated with middle mouse buttons that cannot be disabled from Javascript, So only in Internet Explorer and Konqueror does the middle mouse button really work.
| Internet Explorer and Windows Safari |
Opera 9, Konqueror, Gecko browsers |
Opera 7 | |
| DOWN | mousedown | mousedown | mousedown |
| UP | mouseup click |
mouseup | - |
Note that only IE and Safari have click events for middle buttons and older versions of Opera were broken, but otherwise things are pretty sensible.
| Internet Explorer | Gecko 1.7 or newer Opera 9 or newer Safari 2.0 or newer |
Gecko 1.6 or older on Windows and Linux |
Konqueror, Safari 1.3, and iCab 3 |
Opera 7 | Netscape 4 | |
| DOWN | mousedown | mousedown | mousedown | mousedown | mousedown | mousedown |
| UP | mouseup click |
mouseup click |
mouseup click |
mouseup click |
mouseup click |
mouseup click |
| DOWN | - | mousedown | mousedown mousedown |
mousedown | click dblclick |
mousedown |
| UP | mouseup dblclick |
mouseup click dblclick |
mouseup click dblclick |
mouseup dblclick |
mouseup | mouseup click |
Internet Explorer has the annoying property of not giving a mousedown on the second click of a double click. In fact there is no event fired then at all.
Older versions of the Mozilla browsers (except on Macintoshes) made up for IE's lack of a mousedown event on the second click by sending two, so that overall, a double click sends three mousedown events. What older versions of Opera were up to is hard to imagine. That the first click event is on a mouseup, but the second is on mousedown is just the beginning of the madness.
Luckily, recent versions of the Mozilla browser and Opera have adopted sane behaviors, and the older versions are mostly out of circulation by now (Gecko 1.6 was last used in Firefox 0.8). The Safari developers intelligently chose this as one of their rare instances of incompatibility with IE and chose to emulate Gecko instead.
Right button double click events are listed in the next table. Newer versions of Opera are not listed here, because it is no longer possible to execute a right button double click in Opera. The first click cannot be stopped from activating the context menu, so the second click is caught by the context window, not the browser window. Mac Safari, of course, is omitted because Macintoshs don't have right mouse buttons.
| Internet Explorer Windows Safari |
Gecko 1.6 or older on Windows and Linux |
Gecko 1.7 or newer and Opera 9 or newer |
Konqueror | Opera 7 and Netscape 4 |
|
| DOWN | mousedown | mousedown contextmenu |
mousedown contextmenu |
mousedown | mousedown |
| UP | mouseup contextmenu |
mouseup | mouseup | mouseup | - |
| DOWN | mousedown | mousedown contextmenu mousedown contextmenu |
mousedown contextmenu |
mousedown | mousedown |
| UP | mouseup contextmenu |
mouseup | mouseup | mouseup | - |
Happily, IE doesn't omit the second mousedown event in this case, but old versions of Gecko stuttered on it just as the did on all the other buttons.
Except for the habitual stutter in old versions of the Mozilla browsers, all browsers treat this simply as two clicks in a row, not a doubleclick.
Finally, here are the events for double-clicks on the middle button, a button that isn't actually usable except in IE, Konqueror and Windows Safari. Like the right click case, this is mostly just treated as two single clicks.
| Internet Explorer | Windows Safari | Gecko 1.6 or older on Windows and Linux |
Gecko 1.7 or newer, Opera 9 or newer, and Konqueror |
Opera 7 and Netscape 4 |
|
| DOWN | mousedown | mousedown | mousedown | mousedown | mousedown |
| UP | mouseup click |
mouseup click |
mouseup | mouseup | - |
| DOWN | mousedown | mousedown | mousedown mousedown |
mousedown | mousedown |
| UP | mouseup click |
mouseup click dblclick |
mouseup | mouseup | - |
Sadly, there is little cross browser compatibility as far as which number represents which button. Here's the chart:
| Internet Explorer | Netscape 4 | Gecko 1.0 or later Safari 3 and Opera 9 |
Gecko 0.9 | Opera 7 | Konqueror | Safari 2 | iCab | ||
| LEFT BUTTON |
event.which | undefined | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
| event.button | 1 | undefined | 0 | 1 | 1 | 1 | 1 | 0 | |
| MIDDLE BUTTON |
event.which | undefined | 2 | 2 | 2 | 3 | 2 | ||
| event.button | 4 | undefined | 1 | 2 | 3 | 4 | |||
| RIGHT BUTTON |
event.which | undefined | 3 | 3 | 2 | 3 | 3 | ||
| event.button | 2 | undefined | 2 | 3 | 2 | 2 | |||
The event.which value was originally used in Netscape, and the event.button value was originally used in Internet Explorer. Later browers used both, and messed them both up. Old versions of Opera mixed up the left and right button values for event.which. The newer Mozilla browsers entirely rearranged the event.button values. Old version of Opera messed them up a different way, then newer versions duplicated the value sent by Mozilla. Konqueror simply combines the classic Netscape and IE values.
Newer versions of most browsers except IE seem to be converging toward column three of this table. It's encouraging to see increasing standardization.
Some mice now have more buttons than three buttons. I've done a few tests of this on a Linux system with a five button mouse. In Gecko and Opera, the extra buttons have the same values as the left mouse button, event.which=1, and event.button=0. In Konqueror both extra buttons give event.which=65536, and event.button=0, which are at least different from any of the other three buttons, but may well be intended as error codes.
The end result? There is no browser-independent way to recognize which mouse button is which for all browsers. To handle all cases, you have to sense the browser type and use different algorithms for different browsers.
However, the following test comes pretty close. It mixes up the right and middle mouse buttons in Opera 7, but there were only a few versions of Opera 7 where the left and middle buttons even worked, and then only if the user set an obscure option, so maybe we don't care anymore.
if (event.which == null)
/* IE case */
button= (event.button < 2) ? "LEFT" :
((event.button == 4) ? "MIDDLE" : "RIGHT");
else
/* All others */
button= (event.which < 2) ? "LEFT" :
((event.which == 2) ? "MIDDLE" : "RIGHT");
There are some other mouse events. The mouseover and mouseout events are triggered whenever the mouse moves on to or off of an object. The mousemove event is triggered whenever the mouse is moved. These events are handled pretty consistently in different browsers so far as I have been able to tell, but there are some oddities.
A test script for the mouseover and mouseout events is available at http://unixpapa.com/js/testover.html. The test script shows two nested <DIV> blocks, with some text inside the inner one. It's important to note that in all browsers, when the mouse moves from the outer block into the inner block, there is a mouseout event fired for the outer block. The concept is that the mouse is never "in" more than one object at a time, and the one it is "in" is the frontmost of those in whose enclosing box it falls.
Internet Explorer has some additional events, mouseenter and mouseleave which fire only when you cross the outer boundaries of objects. These are more convenient for many applications, but no other browser supports this however.
Safari 3 seems to handle this correctly, but older versions of Safari had real problems. They also generated mouseover and mouseout events for text nodes. So, on the test page, when you moved the mouse over the text inside the inner <DIV> you would get a mouseout event on the <DIV> and then a mouseover event on the text. I don't think other browsers can even fire events on text nodes.
In Safari 1.3, the mouseover event fires when the mouse pointer enters the rectangular box surrounding the text. This was strange but understandable. In Safari 2.0, when you swept the mouse pointer over some text in a <DIV> you would get dozens and dozens of mouseover and mouseout events. At first I thought they were triggering events on the actual boundaries of the letters, but that didn't seem to be the case. Then I noticed that on the text you get only mouseout events, and on the <DIV> you only get mouseover events, so basically the firing of these events as you go over text was just completely wacky.
In applications it's usually the spurious mouseout events on the <DIV> that cause problems. In Safari 2.0, only get spurious mouseover events, which are usually less of a problem. The best general solution I've found for Safari 1.3 is to have the event handler on the <DIV> check if the mouse is still actually within the bounds of the <DIV> and ignore the event if it is. Since finding mouse coordinates and block borders is pretty browser dependent too, and takes a bit of computation, I tend to perform that test only on Safari.