The Mousepoint Event

The mousepoint event is the first half of the point-and-click gesture.  The event occurs when the mouse stops moving and points to a new target. This event is preferable to the mouseover event for use in heavily populated tool tips and nested menus, since use of the mouseover event can cause a flurry of unintended activity as the mouse crosses over irrelevant material before getting to a desired element or menu. This web page presents a demo, specification, and multi-browser implementation of the mousepoint event; a discussion of related work is included at the end.

The mousepoint event in action

This is a div element with a mousepoint event handler that darkens the background.  The paragraph inside this div has a mousepoint handler that lightens its background.  Moving the mouse directly into the inner paragraph doesn't affect the outer div because the handler for the inner paragraph stops the mousepoint event from propagating up to its parent div element.  There is also an event handler for the body element that restores these elements to their original colors when the mouse stops pointing at them. 

This inner mousepoint handler uses mousepoint.stopPropagaton. 

Use-Capture Semantics

As with other events, one can specify that events associated with containing parent elements are handled before events associated with the smaller elements they contain, allowing one to drill down from the general to the specific.  For example, pointing to the word "penguins" in the following sentence allows one to drill down via use‑capturing event handlers that underline the sentence, its trailing conjunct, and the word penguin, in that order, with the underline for "penguin" coming out on top:

   Birds fly,   but not   penguins  

Here is the same sentence with event bubbling in place of event capturing:

   Birds fly,   but not   penguins  

Event Logging
To see the details behind the above examples, activate the event logger by
clicking on this paragraph, and then retry the examples.

The + or − signs mark the success or refusal of the co-events used to restore elements to a previous state.  See co-event discussion below.

Requirements Test

Click to add an event listener whose purpose is to test some of the mousepoint event attributes, and also the implementation requirement that mousepoint event handlers be called within 60 milliseconds. Notice that different parts of this paragraph give different results, depending on where the mouse stops and points.  Notice that the display technique used by this event lilstener wouldn't work if the mouseover event were used instead, as the alert message would pop up at the first opportunity, well before the cursor gets to the element that is to be studied.  To remove this paragraph's event listener, click on the following "Specification" title:

Specification

The mousepoint event fires when the mouse moves from one element to another and stops.  By definition, the properties and methods of the mousepoint event  include all of the standard mouse event fields.  The relatedTarget field holds the target of the previous mousepoint event, if there was one, and is null otherwise.  Notice that the relatedTarget and target fields are never equal, as the mousepoint event occurs only when pointing to a new target.

The sequencing of the mousepoint event relative to other mouse events is as follows:

mouseover → mousepoint → mousedown → mouseup → click → mouseout

Mousepoint co-events.  Mouse events tend to occur in co-event pairs, with the second event undoing what the first accomplished.  For example, a mouseout event might undo the effect of a mouseover.  In this document, mousepoint serves as its own co-event.  The above logging function illustrates this phenomenon by logging the "undo" functions used to restore elements after a given mousepoint has passed on to the next mousepoint  [details]

In the application script for this document, there is a single generic mousepoint coEventHandler that manages a relevantCoEvent stack.  If the effect of a given mousepoint event is to be undone at a future mousepoint event, an event-specific undo function is pushed onto the relevantCoEvent stack when the given event fires.  At the beginning of the next mousepoint event, the coEventHandler calls each undo function on the relevantCoEvent stack.  If the undo function considers the call to be premature, it refuses to act, and the coEventHandler returns the undo function to the relevantCoEvent stack. 

The logger traces the coEventHandler indirectly by tracing the undo functions it calls and by attaching a + or a − according to the response of the undo function.  These traces clearly show that the coEventHandler has achieved simplicity at the expense of redundant behavior.

Implementation constraints

As should be plain from the above simple examples and the accompanying code at the end of this page, it is indeed possible to implement mousepoint as a user-defined event and to then attach event listeners in the usual way.  Moreover, the dispatched mousepoint event does contain all of the event information one would expect from a mouse event.  However, there are some glitches.

1.    HTML event assignment.  The tag <p onmousepoint="doSomething"> is not valid HTML because the known event names were immutably hardwired into HTML prior to the introduction of user-defined events.

2.    Element property assignment.  The ability to assign new properties to HTML objects is under attack from standards bodies, in direct conflict with assignments of the form element.onmousepoint = doSomething.  The given implementation doesn't support this method of assigning event handlers.

3.    Tracking the location of the cursor.  The most efficient implementation strategy for detecting the mousepoint event would be to employ setIntereval to poll the locations of the cursor as it moves and then stops.  But there appears to be no way of sensing the location of the cursor without waiting for user-initiated events. [details]

The fall-back is to monitor the mousemove events and then wait, via setTimeout, a half-second after they stop. This causes a noticeable delay in recognizing the event.  It also forces one to repeatedly construct tentative mousepoint events in response to each mousemove event, until the "real" one comes along. 

Compared with the present implementation, the hoverintent jQuery plugin gets a faster response by triggering the hoverintent event as soon as the mouse slows sufficiently.  Unfortunately, this alternative can also cause unintended triggering, especially with lightweight mice whose momentum is insufficient to insure smooth motion.

Tan, Tien, Forster, and Atkins were able to improve both speed and accuracy through a software implementation of a mouse whose sensitivity increased as it slowed down.

4.    No testing has been done on programmatic triggering of mousepoint events.

5.    Accommodations for standards-based browsers.  The script adds a global variable, an event object named mousepoint, that has been augmented with auxiliary methods pertaining to the mousepoint event.  This variable is itself not part of the specification [details].

The initial implementation relied on a single mousepoint event that was reinitialized and recycled.  But when bubbling is cancelled on an event, Chrome and Safari disable the event in a way that isn't recoverable.  To efficiently create a new event on each dispatch, the script uses a Mousepoint prototype that, in essence, is a subclass of the MouseEvent class.

6.    Accommodations for Internet Explorer 8.  A worthy goal in accommodating Internet Explorer is to provide a browser-independent interface.  However, a javascript implementation of the actual standard event interface is not really feasible [details].  However, we can achieve browser independence by permuting some method arguments, like so:

Attempts to use prototypes to add standards compliant event-related methods have been going on for some time; Jason Karl Davis records a four-year pyrrhic victory at codeforum.com.

mousepoint.addEventListener(element, handler, useCapture)  =
element.addEventListener("mousepoint", handler, useCapture)

mousepoint.removeEventListener(element, handler, useCapture) =
element.removeEventListener("mousepoint", handler, useCapture)

mousepoint.dispatchEvent(element) =
element.dispatchEvent(mousepoint)

mousepoint.stopPropagation()
(No permutation necessary, works as is.)

mousepoint.preventDefault()
(No default behavior, this is a no-op.)

These mousepoint methods are redundant in the case of standards‑based browsers.  Their advantage is that they also work in Internet Explorer [details].

This is a fairly tall claim.  The IE fireEvent method analogous to dispatchEvent doesn't support programmer-supplied event names — and lots of others [details].  IE doesn't support the event.currentTarget attribute.  IE doesn't support useCapture.  In view of these hurdles, the implementation builds IE's mousepoint event methods largely from scratch rather than relying on IE's event handling mechanism. 

But there is one thing that didn't get fixed:  There's no way to define event.button from event.repeat.  Didn't even try to fix that one.

In addition to programmer supplied names such as onmousepoint, fireEvent also returns the Invalid Argument error for twenty predefined names:  onabort, onafterprint, onbeforeprint, onbeforeunload, onbounce, onchange, onerror, onfinish, onhashchange, onload, onmessage, onoffline, ononline, onreset, onselect, onselectionchange, onstart, onstop, onsubmit, and onunload.

7.    Accommodations for Internet Explorer 9.  This was a relative breeze, with only one hitch.  The IE9 .initMouseEvent method won't allow the related-target field to be undefined, so now the first relatedTarget is null instead.

8.    Design of the test routines.  The design of the logging function revealed a javascript discrepancy:  Firefox and Internet Explorer correctly handle function attributes, whereas Chrome, Opera, and Safari do not. [details]

The logger needs to know the names of the functions it logs, or in the case of anonymous functions, the name of their function factory.  Initially, I just attached the name to the function itself, believing that such "first-class objects" must have have attributes.  That worked fine in Firefox and Internet Explorer, but, especially in the case of anonymous functions, not Opera, Chrome, or Safari.  So I assigned the name attributes to functions' prototype instead.  That actually worked. 

Opera often refuses to display the underlines in the birds fly example, and the problem has to do with the complexity of the example.  However, the log function can be used to show that the mousepoint mechanism itself is not at fault and indeed is working correctly in Opera.

Reliability

The mousepoint script used in this document has been successfully tested in Firefox 3.6.7, Internet Explorer 8.0.6001.187021C, Opera 10.60, Safari 5.0, and Chrome 5.0.375.99.  

Background and Related work

The mousepoint event can be observed in the menus of any modern browser.  In Firefox, for example, click on the View menu and scroll down to the sidebar item; what you don't see is the toolbars submenu because, although you probably moused over it, you didn't actually point to it.

At some time the WindowsXP operating system also switched from mouseovers to mousepoints for displaying menus, but the change was not accompanied by public fanfare or discussion.

As pointed out by azoomer, the mousepoint event is similar to the hoverintent jQuery plugin, but without depending on jQuery.   However, as a jQuery event, hoverintent doesn't support the distinction between target and currentTarget, nor does it support use-capture semantics.  As explained above, the implementation approach is also somewhat different.

Mouse gestures are currently an area of active development and research.  Viewed as a gesture, the mouse-point event is arguably the most physically efficient, due to its emphasis on absence of motion.

Licensing and Copyright Information

Several other products and companies use the terms "mousepoint" or "mouse point."  I am unaware of any connection between the present notion of a mousepoint event and these other endeavors.  In most of these other cases, the term mouse point is used as a shorthand for mouse cursor location.  I invite discussion and further contributions to this idea and would be happy to coauthor improvements. 

Creative Commons License 2010. The Mousepoint Event by Jim Williams is licensed under a Creative Commons Attribution License; the corresponding mousepoint script is available under the GNU General Public License, version 3.0 or later.

Version of 3/19/2011 Valid XHTML 1.0 Transitional 
Previous Version 9/04/2010