HierMenus CENTRAL: HierMenus In Progress. HM5 Status Report: Adding Opera (4/5)
The Missing MouseUp
HM utilizes multiple mouse-related events of Web pages to control the display and behavior of the menus themselves. The common mouseover and mouseout events, for example, are used to trigger the display of child menus when parent menu items are rolled over. The click event is utilized to trigger the display of a new menu or the following of a link from a menu item, depending on the configuration of the menus themselves. And the mousedown and mouseup events are used in conjunction with tall scrolling menus, allowing the user to scroll the menus by holding the mouse down on the scrollbars. We didn't run into any problems with Opera's implementation of the mouseover, mouseout, and click events; but the latter two items, mousedown and mouseup, did pose some difficulties.
We've tied two event handlers to the mouseup and mousedown handlers of this Web page. These handlers print a message in the form textarea box below; printing "Mouse is Down" for the mousedown event; and "Mouse is Up" for the mouseup event. Try clicking and releasing your mouse on this page (but not over links, of course, since you will then exit the page) to see how your browser responds to these events. (Most browsers will work with this example, but some older browsers may not).
In most browsers, the behavior is what you expect: click the mouse down, get a mouse down message; release the mouse, get a mouse up message. In Opera 7 this is also the case, but with one notable exception: if you click and then drag the mouse over selectable text (or a form input field which supports select events) then no mouseup is provided when the mouse is released. Try it, selecting some text from this paragraph. In Opera 7, no mouseup message is received; in other browsers supporting the mousedown and mouseup events, a mouseup is still received following the release of the mouse (and the selection of the actual text). At this moment, we don't know what's happening with the mouseup; whether it's not firing at all or is being canceled at an extremely low level of the document (the text nodes themselves, for example) such that it never bubbles up to the document level.
Either way (for HM), we weren't initially concerned with this issue, as the only time we look for mouseup events is when the user scrolls a scrollable menu; and at that point the mouse is over a scroll bar (at least initially) so we know we aren't over selectable text. Or do we?
It turns out this problem is actually quite tenacious. Consider the example of the box below, similar to our box from the previous page:
The code for this box is as follows:
<div id="outerBox" style="position:absolute; top:0px; left:0px; border:10px black solid; width:150px; height:90px; background-color:lightgrey; overflow:hidden"> <div id="innerBox" style="position:absolute; top:0px; left:0px; width:130px; height:70px; border:10px red solid; background-color:white"> </div> aaa bbb ccc ddd eee fff ggg hhh iii jjj kkk lll mmm nnn ooo ppp qqq rrr sss ttt uuu vvv www xxx yyy zzz </div>
This time we attached the mousehandlers directly to the inner div of the example (within the red border). Click your mouse within the white area of the box. Again, if the mouse does not move, then the mousedown and mouseup are reported as expected. If you do move the mouse, however, typically no mouseup is reported. Why? Presumably because the browser "sees" the text beneath the red bordered box (i.e., the "aaa bbb ccc..." text) and begins selection of that text, canceling the mouseup in the same manner as above--even though that text is not visible to the user. To confirm this, set up your own test with the box above, but remove the text in the outer div. You will find that the mouseup and mousedown then behave predictably; you can move the mouse within the white box while the mouse button is down and still receive the mouseup message when you release it.
Another way to trigger the problem is to move an element with text beneath the element the mouse handlers are assigned to. In this scenario, the user does not even have to move the mouse after pressing the mouse button; the text that moves beneath the mouse itself triggers the select action, canceling the mouseup event. As in the above example, it doesn't matter if the user can see the actual text that is moving, so long as it's in an element of the page that is not itself explicitly hidden (really "hidden," as opposed to simply covered by another element in higher z-order).
In HM, the result of all of this is the triggering of two potential problems, both of which can occur when scrollable menus are displayed:
- Once a menu begins scrolling, it may not stop until it reaches its ultimate top or bottom item. This is because we're looking for the document's mouseup to trigger the stop action for the scroller, which may never occur; either because the text of the menu items themselves trigger the select action as they scroll beneath the mouse, or because the user inadvertently moves the mouse while on the scroll bar and the scroll bar happens to appear over in-page text.
- As menu items pass beneath the scroll bar, the text of the menu items themselves may appear as selected items; indeed, this selection may even carry over to elements of the actual HTML page itself, depending on the positioning of the scrolling menu within the page.
Regrettably, we haven't discovered a graceful workaround for this specific problem; and we suspect we'll have to disable scrolling menu support in Opera entirely when we release version 5. On the next page, however, we discuss some of the things we tried in an effort to work around the issue.
Created: March 12, 2003
Revised: March 12, 2003