This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.
This covers a few things related to MouseEvents. In order to get rid of OnContextMenu and to supply a standard way to deal with the middle mouse button mouseup should have its "Default action" defined in the specification. The button for MouseEvent already has the comment: "During mouse events caused by the depression or release of a mouse button, button shall be used to indicate which pointer device button changed state. 0 must indicate the primary button of the device (in general, the left button or the only button on single-button devices, used to activate a user interface control or select text). 2 must indicate the secondary button (in general, the right button, often used to display a context menu). 1 must indicate the auxiliary button (in general, the middle button, often combined with a mouse wheel). Some mice may provide or simulate more buttons, and values higher than 2 may be used to represent such buttons." - http://dev.w3.org/2006/webapi/DOM-Level-3-Events/html/DOM3-Events.html#events-Events-MouseEvent-button So we have 0 - Left Mouse Button 1 - Middle Mouse Button 2 - Right Mouse Button Since the event "click" already handles buttons and links and has a prevent default that means for mousedown and mouseup the left mouse button doesn't require any changes. However, middle mouse button does have a default action whether the specification says so or not. In many browsers it creates a scroll icon allowing the user to scroll by moving the mouse. This behavior should be denoted as the default action when button = 1. For button = 2 (right mouse button) the context menu should be denoted as the default action. Using the preventDefault should allow one to cancel these default actions at the browser level. http://dev.w3.org/2006/webapi/DOM-Level-3-Events/html/DOM3-Events.html#events-event-type-preventDefault This should clear up any confusion about mouse buttons and should allow for a seamless transition into web applications. With this the left, middle, and right mouse buttons can be utilized. How browsers implement or override this functionality is up to them, but right now this is a mess and it needs to be specified.
A few other problems with the w3c event.button API design: 1) behaves differently than a preexisting IE feature[1] of the same name 2) does not provide information for "no button depressed" Proposals: (1) Too late to fix this one, but avoid the same kind of mistake in the future. (2) provide a number for "no button depressed" It might be worth considering deprecating event.button in favor of a new property, such as deviceButton to more closely match IE's event.button model. [1]http://msdn.microsoft.com/en-us/library/ms533544%28VS.85%29.aspx
(In reply to comment #1) > A few other problems with the w3c event.button API design: > > 1) behaves differently than a preexisting IE feature[1] of the same name > 2) does not provide information for "no button depressed" > > Proposals: > (1) Too late to fix this one, but avoid the same kind of mistake in the future. > (2) provide a number for "no button depressed" > > It might be worth considering deprecating event.button in favor of a new > property, such as deviceButton to more closely match IE's event.button model. > > [1]http://msdn.microsoft.com/en-us/library/ms533544%28VS.85%29.aspx > I was hoping someone wasn't going to mention this. I can't stand the IE model. It makes detecting mouse events so much more awkward. The users presses the left mouse button and then you want to display a right mouse button action but instead you get button 3 so you have to check if you had left down to see if you got right. It's just a horrible idea. You can intuitively figure this out by placing booleans and tracking the mouse button states. if (e.button == 1 && rightMouseDown && e.button == 2 && leftMouseDown) { // Both left and right are down } Also I don't think a new property should be added. The current "button" one works. It's intuitive too. Also what do you mean no button depressed? The mousedown fires when a button is pressed. mouseup fires when a button is depressed. Can you give an example situation where this would be needed?
oh whoops I shouldn't post in the morning. I mean: (I added parenthesis for clarity, assuming this is a perfect world of DOM) http://pastebin.com/f615f0358 Something else I forgot to mention. Do you think that DOM should always make sure a mousedown comes before a mouseup? I found that odd that you can drag your mouse in from the side of the screen and release and it activates a mouseup. Seems like an edge case not many developers would plan for. Also mouseup needs to be called when a page loses focus. Basically right now this is browser implementation specific. It should be given a specified behavior. 1) A mousedown event should always happen before a mouseup. (When dragging in from outside a page and releasing a mousedown event should be dispatched before a mouseup). Basically a mouseup event is impossible without first having a mousedown event first. 2) When a browser loses focus a mouseup event should be dispatched if a mousedown event was dispatched prior to losing focus. The MouseEvent uses the screenX, screenY, clientX, and clientY should be the same as the previous mousedown event. I feel these changes along with the previous ones mentioned would help to simplify coding for developers.
(In reply to comment #2) > (In reply to comment #1) > Also what do you mean no button depressed? The mousedown fires when a button is > pressed. mouseup fires when a button is depressed. Can you give an example > situation where this would be needed? > For example, in Firefox, Opera, Safari, event.button is 0 for a mousemove with no button depressed. The problem this causes is that it is not possible to determine between "left" mouse button and "no" mouse button. Example: 1) document.onmousemove = function(ev){ console.log(ev.button); }; 1) Move the mouse over the document with no button depressed The result is a stream of "0" being logged to Firebug. The specification should provide a value for no mouse button being depressed.
(In reply to comment #4) > (In reply to comment #2) > > (In reply to comment #1) > > > Also what do you mean no button depressed? The mousedown fires when a button is > > pressed. mouseup fires when a button is depressed. Can you give an example > > situation where this would be needed? > > > > For example, in Firefox, Opera, Safari, event.button is 0 for a mousemove with > no button depressed. > > The problem this causes is that it is not possible to determine between "left" > mouse button and "no" mouse button. Example: > > 1) document.onmousemove = function(ev){ > console.log(ev.button); > }; > 1) Move the mouse over the document with no button depressed > > The result is a stream of "0" being logged to Firebug. > > The specification should provide a value for no mouse button being depressed. > o-m-g... I see your point. That system makes a lot more sense. For some reason I didn't think people used the button property in the mousemove event. Also this is going to sound silly, but it just clicked that it's 3 bit flags for each of the 3 mouse buttons in the IE system. DOM should change to the IE way then since it's logically better. I've never liked backwards compatibility since it tends to make things like this messy when changes need to be made. > Proposals: > (1) Too late to fix this one, but avoid the same kind of mistake in the future. > (2) provide a number for "no button depressed" Deprecating "button" seems odd since it's like the perfect name also adding extra things would complicate things. Too bad people value backwards compatibility. Has anyone ever suggested breaking all the javascript web pages to make changes? I mean this would be a quick implementation for browser developers to throw out and patch. Sure unless they all do it at the same time people might be confused. However once developers realize that their javascript mouse event stuff stopped working they'd make the necessary changes hopefully. Also seeing as a lot of people use libraries those libraries would just need to be patched like jquery. hmm maybe that's a bad idea though. Would be cool.
(In reply to comment #4) > (In reply to comment #2) > > (In reply to comment #1) > > > Also what do you mean no button depressed? The mousedown fires when a button is > > pressed. mouseup fires when a button is depressed. Can you give an example > > situation where this would be needed? > > A situation where it is needed is when the mouse moves outside of the event target, then back over the event target. The mousemove event would not know if the mouse button had been released. The mouse button could have been released outside of the document. In some recent browsers, mouseup outside of the viewport fires mouseup for document when the user has mousedown inside the document. step 1) Run this code: document.onmouseup = function(ev){ console.log(ev.clientX); }; step 2) mousedown in document step 3) mouseup outside window (to left of window) Result may be something like: -87 This behavior is implementation dependent. The browsers that exhibit this behavior also fire mousemove outside of window when mousedown on document has occurred. In IE, AFAIK, no mouse events will fire after cursor has left window. FOrtunately IE has event.button 0 meaning "no button", but unfortunately the event.button property requires a less-direct inference test, because there are two different meanings (at least) to event.button. > [snip] > > Deprecating "button" seems odd since it's like the perfect name also adding > extra things would complicate things. Too bad people value backwards > compatibility. Has anyone ever suggested breaking all the javascript web pages > to make changes? That have disastrous consequences. Please see below. I mean this would be a quick implementation for browser > developers to throw out and patch. Sure unless they all do it at the same time > people might be confused. However once developers realize that their javascript > mouse event stuff stopped working they'd make the necessary changes hopefully. > Also seeing as a lot of people use libraries those libraries would just need to > be patched like jquery. Optins for adding new values: 1) change values of existing property 2) add values to existing property 3) create a new property (1) Changing existing values of event.button would break a lot of scripts/pages. Firefox 2, Seamonkey 1, Safari 2, BLackberry, various other versions of Webkit continue to exist and are still used. Changing the meaning of existing values from: (2) Adding new values seems less likely to break any scripts. The problem with this is what should be the value for "no button depressed"? "0" already means default button, the spec provides a provision for additional buttons. Defining "4" to mean "no button" would require testing on several browsers, using different kinds of hardware, plus discussion with implementers. Giving a very large number to mean "no button" could work, but would be quite odd. if(event.button === 100) { // that means no button depressed. } (3) Creating a new property allows scripts to feature test the new property, as: if(typeof event.mouseButton == "number") { // use this one. } else { //... } If a new property is created, then event.button should be deprecated.
(In reply to comment #6) > (In reply to comment #4) > > (In reply to comment #2) > > > (In reply to comment #1) > > > > > Also what do you mean no button depressed? The mousedown fires when a button is > > > pressed. mouseup fires when a button is depressed. Can you give an example > > > situation where this would be needed? > > > > > A situation where it is needed is when the mouse moves outside of the event > target, then back over the event target. The mousemove event would not know if > the mouse button had been released. The mouse button could have been released > outside of the document. > > In some recent browsers, mouseup outside of the viewport fires mouseup for > document when the user has mousedown inside the document. > > > step 1) Run this code: > document.onmouseup = function(ev){ > console.log(ev.clientX); > }; > > step 2) mousedown in document > > step 3) mouseup outside window (to left of window) > > Result may be something like: > -87 > > This behavior is implementation dependent. The browsers that exhibit this > behavior also fire mousemove outside of window when mousedown on document has > occurred. > > In IE, AFAIK, no mouse events will fire after cursor has left window. > FOrtunately IE has event.button 0 meaning "no button", but unfortunately the > event.button property requires a less-direct inference test, because there are > two different meanings (at least) to event.button. Well that seems like something that could be described in the spec then. However which is better? Allow the button to go outside of the window? Mouse up isn't even detected if you mousedown in the document then alt-tab. I'm proposing that the mousemove be allowed to run if it leaves the window since someone might hold down to do something on the edge of the screen and slip off. However if the user doesn't have a mouse button down and moves off the screen the mouse move event should stop. If the user loses focus of the window by alt-tabbing or it gets minimized it should release the mouse button if it's down by dispatching a mouseup with the last known mouse coordinates. That should encompass all of the problems listed. I mean if that was in the spec and browsers followed it then it would be good. (In reply to comment #6) > (2) Adding new values seems less likely to break any scripts. The problem with > this is what should be the value for "no button depressed"? "0" already means > default button, the spec provides a provision for additional buttons. Defining > "4" to mean "no button" would require testing on several browsers, using > different kinds of hardware, plus discussion with implementers. Giving a very > large number to mean "no button" could work, but would be quite odd. > > if(event.button === 100) { > // that means no button depressed. > } > > (3) Creating a new property allows scripts to feature test the new property, > as: > > if(typeof event.mouseButton == "number") { > // use this one. > } else { > //... > } > > If a new property is created, then event.button should be deprecated. > Well if a new property would be made then it seems sensible to handle things with bit flags such that there are 3 bit flags 1st bit primary button (left) 2nd bit secondary button (right) 3rd bit auxillary button (middle) The nice thing is that this could be expanded with more bit flags later for more buttons. So the value 0 would mean none of the buttons are pressed just like the IE model. Actually nothing would change from the IE model. Since it's a bit field users can just & to see which buttons are set. What would the new property be called though? I would really prefer it to be called mousebutton since it looks like it belongs there. button would then be deprecated. Any problems with these ideas? I think that after this comment and after Garrett and others say stuff I'll make a new comment listing all of the proposed changes and clarifications to the spec so that all the ideas are in one list.
Actually now that I'm thinking about it. Just because a user loses focus with the mousedown doesn't mean they meant to mouseup in a random place. You know what would be better. Just have the user handle it themselves? <html> <head> <script type=text/javascript> function MouseDown(e) { console.log("MouseDown"); } function MouseUp(e) { console.log("MouseUp"); } function LostFocus(e) { console.log("LostFocus"); e.stopPropogation(); } function Initialize() { window.addEventListener("mousedown", MouseDown, false); window.addEventListener("mouseup", MouseUp, false); window.addEventListener("blur", LostFocus, false); } </script> </head> <body onLoad="Initialize()"> </body> </html> Yeah this is basic code that detect when a user loses focus using the blur. So ignore my comment about losing focus and dispatching a mouseup. It's unneeded.
Assigning to myself to take action on these open bugs.
Summary of the comments in this bug: ------------------------------------------------------ 1 Note the [de facto] middle mouse button's default behavior (mouse-based scroll) 2 Note the default action for the right mouse button (context menu) 3 Force mousedown messages before mouseup 4 Force mouseup messages when mouse leaves browser window 5 The specification should provide a value for no mouse button being depressed 6 If a new property (for button) is created, then event.button should be deprecated. ------------------------------------------------------ This specification generally doesn't concern itself with the envirnment of the user agent (e.g., whether it's windowed, full-screen, etc.). Thus, IMHO, attempting to specify things that should/shouldn't happen when pointing devices leave/enter the scope of the user agent is out of its purview. (items 3 & 4 -- though Comment 8 made it sound like you wanted to retract these recommendations?) I'm happy to add (non-normative) text describing the default actions of mouseup with various button states, which seems useful for authors (Items 1 & 2) Since the time this bug was filed, a new property "buttons" has been added that uses the "IE" bitmask approach. I believe this satisfies item 5. http://dev.w3.org/2006/webapi/DOM-Level-3-Events/html/DOM3-Events.html#events-MouseEvent-buttons Item 6: currently the spec does not deprecate either the "button" attribute or the "buttons" attribute (which is new) on MouseEvent. Given the long history and significant adoption of the "button" attribute, I don't believe it would be appropriate to indicate that it is deprecated. In fact, I like that the standard offers both options in this case. Depending on the specific scenario you may choose one or the other.
(In reply to comment #10) > This specification generally doesn't concern itself with the envirnment of the > user agent (e.g., whether it's windowed, full-screen, etc.). Thus, IMHO, > attempting to specify things that should/shouldn't happen when pointing devices > leave/enter the scope of the user agent is out of its purview. (items 3 & 4 -- > though Comment 8 made it sound like you wanted to retract these > recommendations?) It's been a while since I submitted this bug. I thought maybe browsers were just taking a while to get similar functionality for this. 3 and 4 are important for making programming easy and intuitive. Currently in most implementations if you hold down the left (primary) mouse button on a window then release it outside of the window it generates a mouse up which is logical for the program to know. However, if you do the same operation with the right or middle mouse button it differs between browsers. In Firefox no mouseup is generated. In Chrome a mouseup is generated. Ideally the specification should state explicitly what you wrote: "Force mouseup messages when mouse leaves browser window". That is if a page gets a mousedown it should always get a mouseup such that the two are pairs. This allows a developer to intuitively handle if a user selects to drag an object and releases off of the window among other operations where the developer wishes to know if the user released outside of the window by checking clientX and clientY. This goes along with the other concept: "Force mousedown messages before mouseup" Firefox for instance allows you to just mousedown outside then mouse up inside of the window. For a developer this can be unintuitive. Standardizing this now will make future implementations much more predictable which is what this bug report was mostly about. > I'm happy to add (non-normative) text describing the default actions of mouseup > with various button states, which seems useful for authors (Items 1 & 2) Yes this is a big one. Ideally on all browsers the following should prevent a context menu, middle mouse scroll, and mouse wheel scroll. In many implementations releasing the right mouse button with any other mouse buttons pressed causes a context menu to display. Calling preventDefault should stop that. The current specification does not cover this. The non-standard "contextmenu" event is implemented in most browsers, but this change would make a mandatory and intuitive implementation for preventing the behavior. The same goes for preventing the mouse scroll where a user holds the middle mouse wheel button down and drags around or they press the button to turn on the scroll feature. Calling preventDefault in the mouse down event should prevent both operations. The current specification does not cover this. The last one is when a user scrolls by rotating their middle mouse wheel. If preventDefault is called then no scrolling action should be taken by the implementation. (In this scenario the developer probably wants the scroll data for their own uses). The current specification already covers this in depth so no changes are needed. <!doctype html> <html> <head> <script type=text/javascript> function MouseDown(event) { if (event.buttons & 4 == 4) { // Middle button was pressed. Prevent the scroll operation from starting even if the middle mouse button was pressed event.preventDefault(); } console.log("mouseup"); } function MouseUp(event) { if (event.buttons & 2 == 2) { // Right button was released. Prevent the context menu from displaying event.preventDefault(); } console.log("mouseup"); } function Wheel(event) { // Prevent the middle mouse wheel scroll operation event.preventDefault(); console.log("wheel"); } function Initialize() { window.addEventListener("mousedown", MouseDown, false); window.addEventListener("mouseup", MouseUp, false); window.addEventListener("wheel", Wheel, false); for (var i = 0; i < 200; ++i) { document.body.innerHTML += i + "<br>"; } } </script> </head> <body onLoad="Initialize()"> </body> </html> > Since the time this bug was filed, a new property "buttons" has been added that > uses the "IE" bitmask approach. I believe this satisfies item 5. > http://dev.w3.org/2006/webapi/DOM-Level-3-Events/html/DOM3-Events.html#events-MouseEvent-buttons Yeah I got them to add that a while back, so that's done. > Item 6: currently the spec does not deprecate either the "button" attribute or > the "buttons" attribute (which is new) on MouseEvent. Given the long history > and significant adoption of the "button" attribute, I don't believe it would be > appropriate to indicate that it is deprecated. In fact, I like that the > standard offers both options in this case. Depending on the specific scenario > you may choose one or the other.
I'll get started on the default actions for middle/right mouse button down. However, it is likely not to be as strong a statement as you would like, because: 1. This specification does not define the "contextmenu" event from HTML5. Thus, it won't be appropriate for me to exactly describe the interaction between the mouse events and this event, though I can imply the behavior with non-normative notes. Sames goes for the middle-button panning. 2. Not all implementations of this spec MUST have that behavior, and some user agents may not have more than one button anyway--so it's inappropriate to use conformance statements for these suggestions. I do like having them in there for completeness though. (In reply to comment #11) > (In reply to comment #10) > > This specification generally doesn't concern itself with the envirnment of the > > user agent (e.g., whether it's windowed, full-screen, etc.). Thus, IMHO, > > attempting to specify things that should/shouldn't happen when pointing devices > > leave/enter the scope of the user agent is out of its purview. (items 3 & 4 ) > It's been a while since I submitted this bug. I thought maybe browsers were > just taking a while to get similar functionality for this. 3 and 4 are > important for making programming easy and intuitive. Currently in most > implementations if you hold down the left (primary) mouse button on a window > then release it outside of the window it generates a mouse up which is logical > for the program to know. However, if you do the same operation with the right > or middle mouse button it differs between browsers. In Firefox no mouseup is > generated. In Chrome a mouseup is generated. > > Ideally the specification should state explicitly what you wrote: > "Force mouseup messages when mouse leaves browser window". > That is if a page gets a mousedown it should always get a mouseup such that the > two are pairs. This allows a developer to intuitively handle if a user selects > to drag an object and releases off of the window among other operations where > the developer wishes to know if the user released outside of the window by > checking clientX and clientY. > > This goes along with the other concept: > "Force mousedown messages before mouseup" > Firefox for instance allows you to just mousedown outside then mouse up inside > of the window. For a developer this can be unintuitive. Standardizing this now > will make future implementations much more predictable which is what this bug > report was mostly about. It is true that most browsers allow the mouseup event to be triggered in the browser even when the mouse leaves the browser window. This concept is implemented using a technique called "mouse capture". Mouse capture is a formalism that this spec has avoided in the past due to some of the complexities surrounding it. I think at best I could describe this behavior in the spec as a note, since it's interesting for authors to be aware of, but lands outside the scope since it deals with concepts of a windowing environment, and needs to account for behavior with Iframes, and security, etc. I don't believe that specifying the "always force mousedown messages before mouseup" is appropriate. My first concern is that no implementation currently does this, and so any tests for this feature would fail, and so this makes it extremely hard to wrap up this spec, and get it to REC, which is my goal. Second, this likely would pose a compatibility risk since OS's allow these messages to be sent as they happen directly to browsers--browser pass them on directly to web sites, which means that web sites already maintain somewhat elaborate state machines to handle these cases (if they are important). Changing this behavior to automatically inject a mousedown when an up occurs will likely break these web-page-specific state machines. Notably, I can imagine a mousedown handler that resets all state, then a move handler that establishes state, and the mouseup handler that commits it. If a mousedown were auto-injected into the page after the user had recieved numerous mousemoves, then the state would be cleared and then committed (with no data) rather than committing the accumulated data if no mousedown were recieved (as happens today).
I've added the notes around: 1. events that still fire during drag operations outside of the window (mousemove/mouseup) 2. Default actions for mousedown and mouseup (in the table, and in the individual event descriptions) Please let me know if this is satisfactory. http://dev.w3.org/2006/webapi/DOM-Level-3-Events/html/DOM3-Events.html#event-type-mousedown
(In reply to comment #13) > I've added the notes around: > 1. events that still fire during drag operations outside of the window > (mousemove/mouseup) > 2. Default actions for mousedown and mouseup (in the table, and in the > individual event descriptions) > > Please let me know if this is satisfactory. > > http://dev.w3.org/2006/webapi/DOM-Level-3-Events/html/DOM3-Events.html#event-type-mousedown Wow that quick. Yeah that's exactly what I wanted. Thanks.
Super. Thanks
Someone brought up some confusion in the "buttons" member for MouseEvent. This is regarding the behavior of MouseEvent with multiple devices. Not sure if it's possible, but could you explicitly state that the MouseEvent buttons property represents the binary ORed result of all mouse device buttons. As an example if a person have both a laptop trackpad and a USB mouse if they hold both primary mouse buttons and release one the bit for the primary mouse button will still be set.
(In reply to comment #16) > Someone brought up some confusion in the "buttons" member for MouseEvent. This > is regarding the behavior of MouseEvent with multiple devices. Not sure if it's > possible, but could you explicitly state that the MouseEvent buttons property > represents the binary ORed result of all mouse device buttons. > > As an example if a person have both a laptop trackpad and a USB mouse if they > hold both primary mouse buttons and release one the bit for the primary mouse > button will still be set. I don't think that I'll note this in the spec. Here's why: Most (all?) operating systems that incorporate a mouse-driven pointing device, have only a single mouse input stack. Even if you plug in two mice or use a mouse + trackpad, as in your example, the underlying operating system is going to merge these inputs into one stack as best it can. For example, when moving each of these mice, you'll notice that each mouse does not maintain it's original position on screen relative to the last position it was moved to. Rather, movements of each mouse are relative to the current pointer position because their inputs are being merged. When using the mouse buttons, a similar merging will occur. This technique (by the way) will likely break most web-page-based state machines for tracking the mouse... If you press down on the primary mouse button of one device the OS will disptch a mousedown event to the system. Then if you press down on the primary mouse button of another device, the operating system will simply blindly (unless a specific OS handles this scenario better) dispatch another mousedown event! The button state that is reported by the DOM event in these cases is pretty dependent on how the OS exposes this information. When you release one of these buttons, my guess (not having two mice to check against on my windows-based box) is that the mouse-up event and related button are fed into the mouse state machine, and will report that no buttons are now pressed even though you're still holding down the other mouse button! These type of scenarios are much better suited for multi-point input, such as touch events, which have a different programming pattern in general. In such scenarios, web developers will know to _expect_ simultaneous input -- happily our fingers don't have buttons on them :-) I'm resolving as Fixed to avoid confusing this re-activation for a different issue with the resolution of the original issue. Please file a new bug if you have further feedback or issues with the spec :)