Javascript Madness: Mouse Events
http://unixpapa.com/js/mouse.html
Javascript Madness: Mouse Events
Jan Wolter
Aug 12, 2011
Note: I have stopped updating this page. At this point nearly all popular browsers are have achieved a good level of compatibility on most of these features, and their behavior with respect to them just isn't changing much anymore. The only thing web designers really need to still watch out for is IE8, which is lingering due to the fact that it is the best version of IE that works on windows XP. |
Introduction
This document summarizes the results of some browser tests done during the development of Web Paint-by-Number, a Javascript application that makes intense use of mouse events. It documents inconsistancies in the way different browsers implement mouse events.
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 | 9.0.8112.16421 | 5.2 | - |
Firefox | 5.0 (Gecko 5.0) |
5.0.1 (Gecko 5.0.1) |
4.0 (Gecko 2.0) |
Opera | 11.00 | 9.10 | 11.50 |
Safari | 5.1 (Webkit 534.50) |
5.0.2 (WebKit 533.18.1) |
- |
Chrome | 13.0.782.112 (Webkit 535.1) |
14.0.835.35 (Webkit 535.1) |
5.0.375.127 (Webkit 533.4) |
Epiphany | - | - | 2.28.2 (Webkit 531.2+) |
Konqueror | - | - | 4.3.1 |
Tests were also performed on Netscape, Mozilla, Camino, Seamonkey and K-Meleon. 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, just as Safari, Chrome, and Ephiphay all use the WebKit engine. In this article we will generally refer to Gecko and Webkit version numbers instead of any particular Gecko-based browser version numbers. See the Gecko/Webkit version table for the mapping between browser version numbers and layout engine version numbers.
This document is growing rapidly less imporant, as current versions of most leading browsers have converged on sensible and compatible behaviors. Internet Explorer still has deficiencies, but current versions of Firefox, Safari, Chrome and Opera are pretty consistant and sane for most things, though middle button mouse events still don't work in Firefox or Opera. The tables in this document have "correct" behavior highlighted in green.
Previous versions of this document included coverage of the iCab 3 browser, but more recent versions of iCab use WebKit, and so presumably behave exactly like the other WebKit browsers. Since it is unlikely that many web developers will want to go out of their way to support iCab 3, that material has been removed from this document and archived in a separate report on iCab 3.
The script used to collect the test results reported here is available at http://unixpapa.com/js/testmouse.html.
Mouse Buttons and Default Events
When you click on something displayed by your browser, the browser generates some mouse events. Normally these events trigger some default action by the browser, like following a link or bringing up a context menu. But it is possible to set up Javascript event handler functions that called get instead. These can perform some special action, and then they can either cancel the default action, or allow it to go forward.
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 code below, which should cover all browsers. (Note that if you doing Level 0 event handling, that is not using addEventListener() to set up your event handlers, then just returning false is sufficient.)
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 Javascript. 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 not be disabled. You can change what the default action is by editing the middlemouse settings on the "about:config" URL, but Javascript can't cancel them.
The middle and right mouse buttons have had a long history of being broken in Opera. The right mouse button now works correctly by default, but has had a long history of being broken in different ways:
- 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" (renamed to "Allow scripts to detect context menu events" in Opera 10). This option moved to at least three different places in subsequent releases. In Opera 11 it is at "Settings > Preferences > Advanced > Content > Javascript Options".
However, initially 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 disabled not only over that link, but over the entire page. Furthermore, only mousedown events were sent, never mouseup.
- Sometime between the 7.54 and 8.5 release this was fixed, but only sort of. If you enable the right click option, Javascript receives the right click events, but the default action can not be disabled. The context menu always comes up. Without being able to disable the default action, being able to capture the event was almost completely useless.
- In version 10.50, right clicks were fixed the rest of the way. The option to allow Javascript to capture context menu events now defaults on, and, as long as it is on, right click events fire correctly, and the default action can be disabled from Javascript.
So all is well now with right clicks in Opera—unless mouse gestures are turned on. This causes all sorts of side effects when the mouse is moved with the right button depressed, none of them cancelable from Javascript. Oh well.
The middle mouse button in Opera is broken too. It triggers an events, but the default action cannot be disabled. No fiddling with the manner of its brokeness has occured so far.
None of the WebKit browsers seem to have any problem with this. All mouse buttons can be used on all platforms.
So here's the final score card:
Can default mouse actions be disabled?
Left Button | Middle Button | Right Button | |
Internet Explorer WebKit Konqueror |
Yes | Yes | Yes |
Gecko | Yes | No | Yes |
Opera ≥ 10.50 | Yes | No | Yes |
Opera < 7.23 Opera 8.5 - 9.63 |
Yes | No | No |
Opera 7.23 - 7.54 | Yes | No | Only if user has enabled an obscure option |
Types of Mouse Events
The events that are associated with mouse clicks are:
- mousedown - A mouse button has been pressed down.
- mouseup - A mouse button has been released.
- click - A mouse button has been clicked.
- dblclick - A mouse button has been double-clicked.
- contextmenu - Some action to trigger a context menu has occured.
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. Similarly, a dblclick event is triggered by two consecutive click events on the same object. object.
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.
It is important for programmers to remember that you cannot, in general, count on the full sequence of events firing. There is no guarantee that a mousedown will be followed by a mouseup, or that a mouseup event will be preceded by amousedown event. If the user does a mousedown over the object you have set your event handler on, and then moves it away before releasing it, you will not see the mouseup event. If he moves it out of the browser window, there simply won't be one.
Event Triggering - Single Clicks
If you do a single mouse click of the left mouse botton, every modern 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.
Single Click of Left Mouse Button
All Browsers | |
DOWN | mousedown |
UP | mouseup click |
So, here's what happens when you do click on the right mouse button:
Single Click of Right Mouse Button
Gecko ≥ 2.0 (Win) Internet Explorer Chrome ≥ 1.0 (Win) Opera ≥10.50 |
Gecko < 2.0 (Win) Gecko (Linux) Safari Chrome (Linux, Mac) |
Gecko (Mac) Konqueror |
Chrome 0.2 | Opera < 10.50 (default) |
Opera 7.23-7.54 (option enabled) |
Opera 8.0-9.63 (option enabled) |
Ephiphany 2.28 | |
DOWN | mousedown | mousedown contextmenu |
mousedown | mousedown | - | mousedown | mousedown | contextmenu |
UP | mouseup contextmenu |
mouseup | mouseup | contextmenu mouseup |
- | - | mouseup | mouseup |
There are no click events for right button clicks in any browser.
Opera normally generates no events for the right mouse button. For some time there has been an option that turns those events on and recently they have even started working correctly when it is enabled, but I believe that that option still defaults off.
Notice that the contextmenu event does not exist in all browsers, though some of the ones missing it still have a context menu that appears by default on right button clicks. It also occurs at different times in different browsers. I think this relates to the different behavior of the context menus in different browsers. In some browsers the context menu comes up when the mouse key is depressed, while in others it appears when it is realeased. This seems to change a lot between different browser versions. I think older versions of Safari had it fire on mouseup, but I don't know what versions. Probably it is risky to depend on any particular behavior from this event.
There is not a lot of consistency in the behavior of the WebKit browsers on this, though the only one that is distinctly bad is Epiphany, which fails to send a mousedown. The others vary only on the timing of the contextmenu event.
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, Konqueror, and the WebKit browsers does the middle mouse button really work.
Single Click of Middle Mouse Button
Internet Explorer WebKit |
Gecko Opera ≥ 8.0 Konqueror |
Opera < 8.0 | |
DOWN | mousedown | mousedown | mousedown |
UP | mouseup click |
mouseup | - |
Note that there is some disagreement about whether or not there should be a click event for middle buttons and older versions of Opera were broken, but otherwise things are pretty sensible.
Event Triggering - Double-Clicks
Now let's turn our attention to double-clicks. Even if you just want to treat double-clicks as two consecutive clicks, you need to pay attention to the weirdnesses here, because strange things happened in many older browsers when two clicks happen to be close enough together to register as a double-click. Here's what we see with a double-click on the left mouse button:
Double-Click of Left Mouse Button
IE ≥ 9.0 Gecko ≥ 1.7 Opera ≥ 9.10 WebKit ≥ 412 (Win & Mac) WebKit ≥ 533.4 (Linux) |
IE < 9.0 | Gecko 1.6 (Windows and Linux) Webkit ≤ 532.5 (Linux) |
Konqueror Webkit 312 (Mac) |
Opera ≥ 8.0 < 9.10 | Opera < 8.0 | |
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 | dblclick click |
click dblclick |
UP | mouseup click dblclick |
mouseup dblclick |
mouseup click dblclick |
mouseup dblclick |
mouseup | mouseup |
Until recently, Internet Explorer has the annoying property of not giving a mousedown on the second click of a double click. In fact there was no event fired then at all.
Ancient versions of the Mozilla browsers made up for IE's lack of a mousedown event on the second click by sending two, so that overall, a double click sent three mousedown events. Macintosh versions of Gecko never had this problem.
Curiously, many years later, the first WebKit browsers for Linux, Chrome and Epiphany, revived the exact same double mousedown bug on double-clicks. This has been fixed in newer versions of Chrome, but likely not yet in Epiphany, since they are still using an older version of WebKit.
What older versions of Opera were up to is hard to imagine. That the first click event was on a mouseup, but the second was on mousedown was 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 wisely chose this as one of their rare instances of incompatibility with IE and chose to emulate Gecko instead. And now even Microsoft has belatedly gotten things right. Hurrah!
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.
Double-Click of Right Mouse Button
Gecko ≥ 2.0 (Win) Internet Explorer Opera ≥ 10.50 |
2.0 > Gecko ≥ 1.7 (Win) Gecko ≥ 1.7 (Linux) Safari Chrome ≥ 1.0 (Win & Mac) Chrome ≥ 5.0 (Linux) |
Chrome 0.2 | Gecko 1.6 (Windows and Linux) Chrome 4.0 (Linux) |
Epiphany 2.28 | Gecko ≥ 1.7 (Mac) Konqueror |
|
DOWN | mousedown | mousedown contextmenu |
mousedown | mousedown contextmenu |
contextmenu | mousedown |
UP | mouseup contextmenu |
mouseup | contextmenu mouseup |
mouseup | mouseup | mouseup |
DOWN | mousedown | mousedown contextmenu |
mousedown | mousedown contextmenu mousedown contextmenu |
contextmenu contextmenu |
mousedown |
UP | mouseup contextmenu |
mouseup | contextmenu mouseup |
mouseup | mouseup | mouseup |
Happily, IE doesn't omit the second mousedown event in this case, but old versions of Gecko and new Linux WebKit browsers stutter on it just as they do on all the other buttons. Epiphany combines the stutter with missing mousedown events to achieve glorious new levels of brokeness.
If we ignore the stutters, then all browsers treat this simply as two clicks in a row, not a doubleclick.
Opera used to only trigger right click events if an obscure option was enabled by the user. In those versions, double right clicks were not possible because even if you enabled the option, context menu would always appear on the first click, so you couldn't perform a second one.
Finally, here are the events for double-clicks on the middle button, a button that isn't actually usable Gecko and Opera. Like the right click case, this is mostly just treated as two single clicks.
Double-Click of Middle Mouse Button
Internet Explorer | WebKit (Win & Mac) Webkit ≥ 433.4 (Linux) |
Gecko ≥ 1.7 Opera ≥ 8.0 Konqueror |
Gecko 1.6 (Windows and Linux) |
WebKit ≤ 532.5 (Linux) |
Opera < 8.0 | |
DOWN | mousedown | mousedown | mousedown | mousedown | mousedown | mousedown |
UP | mouseup click |
mouseup click |
mouseup | mouseup click |
mouseup | - |
DOWN | mousedown | mousedown | mousedown | mousedown mousedown |
mousedown mousedown |
mousedown |
UP | mouseup click |
mouseup click dblclick |
mouseup | mouseup | mouseup click dblclick |
- |
This is pretty much what you'd expect except that here, for once, the WebKit browsers do not perfectly emulate IE. Of course, it makes perfect sense that dblclick should be fired if click is, and firing an extra event is unlikely to cause compatibility problems, so this is probably a good choice.
It should be noted that double-clicks can be awkward to work with. If you want different things to happen on single-clicks and double-clicks then you will have to deal with the problem that both events will be firing when the user double-clicks. Your click handler is going to be called once or twice before your dblclick handler, and possibly once afterwards (on old versions of Opera). You are going to have a heck of a time suppressing the single-click action during a double-click. You can try various kludgy things with timers, but I don't think there is any reliable way to do this.
But if you are having this problem, then it is probably a case of bad interface design on your part. There is always a danger of what the user intends as a double-click being interpreted as two single-clicks. This is inherent in the idea of a double-click. So the single-click action shouldn't ever be something utterly different from the double-click action unless you really like annoying your users. An example of an appropriate use of double-click would be if a single-click selects a file icon, and a double-click opens it. In that case it doesn't matter of the file gets selected once or twice before being opened, because the double-click action is an extension of the single-click action. If your design doesn't fit into this pattern, then probably you should be use right-clicks or shift-clicks or clicks on different elements rather than double-clicks.
Identifying Mouse Buttons
When Javascript recieves a mouse click event, it is generally interesting to know which mouse button was clicked. The event object that is passed to Javascript contains two fields that may be used to check this, event.which and event.button. These will contain numerical values to identify the mouse button.
It used to be that every browser used a different combination of values to indicate the buttons, but there has been a gradual convergence on a standard now, so all browsers except IE work alike:
Mouse button ID values in various browser
IE < 9.0 IE with attachEvent |
Netscape 4 | IE ≥ 9.0 Gecko ≥ 1.0 Webkit ≥ 523 Opera ≥ 8.0 Konqueror ≥ 4.3 |
Gecko 0.9 | Opera < 8.0 | Konqueror ≤ 3.5 | Webit 412 | ||
event.button | LEFT BUTTON |
1* | undefined | 0 | 1 | 1 | 1 | 1 |
MIDDLE BUTTON |
4* | undefined | 1 | 2 | 3 | 4 | ||
RIGHT BUTTON |
2* | undefined | 2 | 3 | 2 | 2 | ||
event.which | LEFT BUTTON |
undefined | 1 | 1 | 1 | 1 | 1 | 1 |
MIDDLE BUTTON |
undefined | 2 | 2 | 2 | 3 | 2 | ||
RIGHT BUTTON |
undefined | 3 | 3 | 3 | 2 | 3 |
* for mousedown and mouseup only, zero for click, dblclick and contextmenu events.
Newer versions of all browsers have converged on column three of this table, but for older browsers this is a pretty serious mess.
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. Event.button was an especially hopeless mess, with different browsers returning 1, 2, 3 or 4 for a middle mouse click. Event.which is better, except that old versions of Opera got the middle and right mouse buttons mixed up, and, until recently, IE didn't return it at all.
It appears that in version 9.0, Microsoft did a lot of fixing here, so that usually it behaves just like all the other browsers. Microsoft seems to be keeping this a secret for now, as their documentation only describes the old behavior. And if you set your event handlers up using Microsoft's old, non-standard's compliant attachEvent() function, then you still get the old behavior in IE 9.0. If you set it up any other way, then you get the standards compliant behavior. So depending on how you wrote your workarounds for old IE bugs, you may or may not be seeing the fixed behavior of IE 9:
If you did:
if (elem.addEventListener) IE 9.0 obeys the standard! |
If you did:
if (elem.attachEvent) IE 9.0 acts like old IE |
Note that older versions of IE returned useful values in event.button only on mousedown and mouseup events. It was not possible to identify the mouse button for a click, dblclick or contextmenu event because event.button will be zero regardless of which button was pressed. This remains true of IE 9 when event handlers are set up with attachEvent().
A oddity in the old IE behavior became apparent if you held down more than one mouse button at a time. On mousedown events, IE returned the boolean-or of the values for all mouse buttons currently depressed. So if you held down both the left and right mouse buttons, the second mousedown event would have event.button=3. Note that in this case you cannot tell which of the two buttons triggered the current event. Your only hope is if you caught the previous mousedown event when the first of the two buttons were pressed and remembered which it was, and even that won't work if the user depressed one mouse button before moving it into your browser window. IE did not do this on mouseup events, and no other browser ever did this on any events. Again, you still see this with IE 9 if you set up your event handlers with attachEvent(), but not if you set them up any other way.
The DOM 3 Events Specification defines button identification attributes for mouse events. One is event.button which works the way most browsers now implement it. The other is event.buttons which is very similar to IE's old handling of event.button, with values 1, 2, 4 adding up if more than one button is held at the same time. Internet Explorer 9.0 is the first browser I've seen implement this, though only if you did not register the event handler with attachEvent().
Note that event.buttons is included on click, dblclick and contextmenu events, Also it's behavior on mouseup events differs from the old Microsoft event.button values. It always gives the button state after the event, so on a mouseup after an ordinary click of just one button, event.buttons would be zero, because no buttons are down.
Some mice now have more than three buttons. The DOM3 standard says these should be treated pretty much like the other buttons, assigning additional button numbers to them consecutively. I have done only a little testing of this. Most browsers now seem to take the fourth and fifth buttons as "BACK" and "FORWARD" commands, but generate no Javascript events. The older versions of Konqueror I tested generated events with values of 65536 for button and which, which is probably intended as an error code, not a key identifier.
The end result of all this? While there is no browser-independent way to recognize which mouse button is which for all the browsers surveyed, you can come extremely close. The following test works for all browsers except Opera 7. (It mixes up the right and middle mouse buttons in Opera 7, but Opera 7 is pretty old, there were only a few versions where the right and middle buttons even worked, and then only if the user set an obscure option, so you really don't care.) It also doesn't correctly handle simultaneous clicks of multiple mouse buttons in IE. To do that your application needs to track which buttons were reported to be down in previous mousedown events so it can figure out which one was added.
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");
Click here with various mouse buttons to test
If you don't have any other compelling reason to prefer one event over another, it's probably generally best to attach your event handlers to mouseup. IE versions before 9.0 had annoying little problems with the others (click doesn't identify the mouse button, and mousedown ORs together mouse button values and isn't fired on the second click of a double-click) and WebKit versions of Epiphany fail to send mousedown. Triggering on mouseup also means that users get a last chance to change their mind about clicking on something - they can move their mouse off the control before releasing the button.
Detecting Modifier Keys
Being able to attach different actions to different mouse buttons is great, except for your users with one-button mice. On those the convention is to use shift-clicks or control-clicks instead, clicking the mouse button while holding down a keyboard modifier. One might assume that you'd need to track both keyboard events and mouse events to be able to recognize this, but it turns out that you're in luck, mouse events include information about the current status of the keyboard modifier keys.
For all modern browsers, all mouse events include the booleans event.shiftKey, event.ctrlKey, and event.altKey. These are true if that key was down during the mouse event.
I haven't been tracking these as carefully as other aspects of mouse events, but I think the last browser that didn't support these was Netscape 4, which used the e.modifiers field instead. To check if the shift key was down, you check if(e.modifiers & Event.SHIFT_MASK) != 0 was true. For the other keys you would use Event.CONTROL_MASK or Event.ALT_MASK in the same way. I think you can safely file this under the category of "Irrelevant Historical Trivial" though.
Finding Mouse Positions
So, you want to know the coordinates where a mouse click occurred? The mouse event object does include coordinates. In fact there may be as many as six different sets of coordinates in some browsers, and, naturally, they are a swamp of browser incompatibilities. Luckily, I don't have to document them in detail, because Quirksmode already has. I will however give you the short answer, which depends on which coordinates you want:
- Screen Coordinates: These are coordinates measured from the top left corner of the user's computer screen. You'd rarely get coordinates (0,0) because that is usually outside the browser window. About the only time you'd want these coordinates is if you want to position a newly created browser window at the point where the user clicked.
In all browsers these are in event.screenX and event.screenY.
- Window Coordinates: These are coordinates measured from the top left corner of the browser's content area. If the window is scrolled, vertically or horizontally, this will be different from the top left corner of the document. This is rarely what you want.
In all browsers these are in event.clientX and event.clientY.
- Document Coordinates: These are coordinates measured from the top left corner of the HTML Document. These are the coordinates that you most frequently want, since that is the coordinate system in which the document is defined.
In most browsers these coordinates are returned in event.pageX and event.pageY. But IE does not implement these. For IE, you need to compute them by adding the current scrolling offset to the the window coordinates. Unfortunately, the scrolling offset is stored in different places in different versions of IE, so this gets a bit complex. The following works in all browsers:
if (event.pageX == null)
{
// IE case
var d= (document.documentElement &&
document.documentElement.scrollLeft != null) ?
document.documentElement : document.body;
docX= event.clientX + d.scrollLeft;
docY= event.clientY + d.scrollTop;
}
else
{
// all other browsers
docX= event.pageX;
docY= event.pageY;
}A demo of this code is available.
- Target Coordinates: These are coordinates measured within the HTML element that is the target of the event. If you wanted to know where on a element the user clicked, then this is what you'd want.
Theoretically, the event.offsetX and event.offsetY values are supposed to contain this, but forget it. There are so many bugs and incompatibilities in these values that they are essentially completely useless.
Instead you'll need to subtract the document coordinates of the target element from the document coordinates of the mouse click. (If you are computing the coordinates of the target element, remember that offsetLeft and offsetTop are relative to offsetParent which is not necessarily the document. You may need to climb the chain of offsetParents adding up offsets as you go.)
Mouseover and Mouseout
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, however no other browser supports these events. They might do so in the future, as the DOM 3 standard mandates them.
Safari 3 and other modern Webkit browsers seem to handle mouseover and mouseout 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, you 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.
Drag and Text Selection Events
Some browsers have special support for dragging and dropping HTML options using the mouse. I've done minimal study of these. They seem to be targetted primarily toward dragging object between browser windows, possibly from one application to an unrelated one. For simply dragging things around within your application, they seem rather clumsy. Reading the Mozilla drag and drop documentation might be a start for those interested in this.
However, even if you don't want to drop and drag anything, it is worth knowing a bit about these things, because they can interfere with ordinary mousing around. Sometimes the browser will decide that the user is trying to do a drag, and everything will go wrong. Events like mousemove and mouseover stop firing when the browser thinks a drag is in progress.
In most browsers, just disabling the browser default action on the mousedown event (see above for how to do this). seems to disable this. I'm pretty sure that in older versions of gecko it was necessary to disable the default action on thedragstart event, but this no longer seems necessary.
There are also events fired in some browsers when text is selected with the mouse. These also may be undesirable if you are trying to have something else happen with mouse clicks. Disabling the default action on mousedown for the page body seems to solve this for most modern browsers, but this didn't always work on older browers. I've heard that canceling the browser default on the selectstart event helped with this on some browsers.
Last Update: Thu Aug 30 11:49:11 EDT 2012
Javascript Madness: Mouse Events的更多相关文章
- javascript code snippet -- Forwarding Mouse Events Through Layers
Anyone who has worked with web apps has likely created a masking element at some point, and the grea ...
- javascript - Show mouse cursor in phantom.js - Stack Overflow
javascript - Show mouse cursor in phantom.js - Stack Overflow Show mouse cursor in phantom.js
- Electron mouse events 参数解析
1.https://electronjs.org/docs/api/web-contents 2.通常用: monitorEvents(document.body, 'mouse') 检测正常的值: ...
- Simulating Mouse Events in JavaScript
http://marcgrabanski.com/simulating-mouse-click-events-in-javascript/
- JavaScript Madness: Dynamic Script Loading
Introduction I've developed some pretty seriously Javascript intensive sites, where the sheer quanti ...
- Eloquent JavaScript #12# Handling Events
索引 Notes onclick removeEventListener Event objects stopPropagation event.target Default actions Key ...
- FusionCharts JavaScript API - Events 全局事件处理
FusionCharts JavaScript API - Events 全局事件处理 Home > FusionCharts XT and JavaScript > API Refere ...
- javascript 手势缩放 旋转 拖动支持:hammer.js
原文: https://cdn.rawgit.com/hammerjs/hammer.js/master/tests/manual/visual.html /*! Hammer.JS - v2.0.4 ...
- 25、Javascript 事件
Javascript 事件 是指 Javascript 捕获到用户的操作,并做出正确的相应. Javascript 事件一般与DOM元素绑定. Javascript处理事件的基本机制 1.对DOM元素 ...
随机推荐
- Asp.Net MVC EF之一:使用Database类在EF框架中执行Sql语句
引言 从EF6开始,增加了DateBase类,他通过从 DbContext 对象获取此类的实例.可用于管理支持数据库上下文或连接的实际数据库.这包括创建.删除和检查数据库的存在. 在6以前,我们使用E ...
- OpenStack kolla 多 region 部署配置
region one: cat /etc/kolla/globals.yml openstack_region_name: "RegionOne" multiple_regions ...
- 程序媛计划——python socket通信
定义 socket 是进程间的一种通信方式,可以实现不同主机间的数据传输 #写服务期端程序server.py #实现服务器向客户端连接 #!/usr/bin/env python #coding:ut ...
- XCode - vmware虚拟机安装XCode进行iPhone真机调试
1.vmware安装黑苹果,然后在appStore安装XCode http://blog.csdn.net/forgot2015/article/details/51104329 2.真机调试证书等申 ...
- uiautomator2
uiautomator2 该项目正在火热的开发中 uiautomator2 是一个可以使用Python对Android设备进行UI自动化的库.其底层基于Google uiautomator,Go ...
- jzoj5804
這道題n-m很小,可以從此入手 記f[i][j]為i個字符括號綜合為j的合法方案數 則第i個括號可以枚舉為(和),所以f[i][j]=f[i-1][j-1]+f[i-1][j+1],小心越界 再記a為 ...
- Topological Sor-207. Course Schedule
There are a total of n courses you have to take, labeled from 0 to n - 1. Some courses may have prer ...
- 简述在MySQL数据库中MyISAM和InnoDB的区别
区别主要有以下几点: (1)构成上,MyISAM的表在磁盘中有三个文件组成,分别是表定义文件(.frm).数据文件(.MYD).索引文件(.MYI),而InnoDB的表由表定义文件(.frm).表空间 ...
- myeclipse注册码生成
import java.io.*; /** * <一句话功能简述> * <功能详细描述> * * @author 程松 * @date 2013-11-8上午8:50:34 * ...
- 【BZOJ3456】轩辕朗的城市规划 EGF+多项式求ln
我们构造$f(i)$和$g(i)$. 其中$f(x)$表示由$x$个节点构成的无向简单连通图的个数. $g(x)$表示有$x$个节点构成的无向简单图(不要求连通)的个数. 显然,由$x$个节点构成的无 ...