Detect Mouse Button for FireFox in Javascript - javascript

What is the best way to go about detecting what button has been pressed in a DIV in FireFox using javascript?

There are two properties for finding out which mouse button has been clicked: which and button. Please note that these properties don’t always work on a click event. To safely detect a mouse button you have to use the mousedown or mouseup events.
which is an old Netscape property. Left button gives a value of 1, middle button (mouse wheel) gives 2, right button gives 3. No problems, except its meager support (and the fact that it’s also used for key detection).
Now button has been fouled up beyond all recognition. According to W3C its values should be:
* Left button – 0
* Middle button – 1
* Right button – 2
According to Microsoft its values should be:
* Left button – 1
* Middle button – 4
* Right button – 2
No doubt the Microsoft model is better than W3C’s. 0 should mean “no button pressed”, anything else is illogical.
Besides, only in the Microsoft model button values can be combined, so that 5 would mean “left and middle button”. Not even Explorer 6 actually supports this yet, but in the W3C model such a combination is theoretically impossible: you can never know whether the left button was also clicked.
In my opinion W3C has made some serious mistakes in defining button.
Right click
Fortunately you most often want to know if the right button has been clicked. Since W3C and Microsoft happen to agree on this one and give button a value of 2, you can still detect a right click.
function doSomething(e) {
var rightclick;
if (!e) var e = window.event;
if (e.which) rightclick = (e.which == 3);
else if (e.button) rightclick = (e.button == 2);
alert('Rightclick: ' + rightclick); // true or false
}
Please note that, although Macs have only one mouse button, Mozilla gives a Ctrl–Click a button value of 2, since Ctrl–Click also brings up the context menu. iCab doesn’t yet support mouse button properties at all and you cannot yet detect a right–click in Opera.

[jquery][1] mentions how you can detect the mouse button here:
http://api.jquery.com/mousedown/
The mousedown event is sent when any
mouse button is clicked. To act only
on specific buttons, we can use the
event object's which property. Not all
browsers support this property
(Internet Explorer uses button
instead), but jQuery normalizes the
property so that it is safe to use in
any browser. The value of which will
be 1 for the left button, 2 for the
middle button, or 3 for the right
button.

Related

window.open with _blank opens two tabs in Firefox

When this element is middle clicked:
// Allow middle button click to open client in another tab.
$(document).on('mousedown', '.clientlist-edit', function (event) {
if (event.which === 2) {
event.preventDefault();
var url = $(this).attr('href');
url = url.toLowerCase().replace('/addedit', '/clientindex');
window.open(url, '_blank');
return false;
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<a class="clientlist-edit" href="/Clients/Management/AddEdit/4ffac190-72d2-476a-b0be-a9d90097272a">
<i class="glyphicon glyphicon-pencil"></i> <strong class="title">Client Name</strong>
</a>
This handler is called and when it gets to window.open, two tabs are opened. The first is the URL (variable URL) which is desired. The second is the original href set on the anchor element which is undesired. I'm calling preventDefault. What am I missing?
It is reproducible. See the link below. Sometimes it is two middle clicks. It is a middle click. It only happens in Firefox.
https://jsfiddle.net/jsmunroe/eap1b6k7/3/
I'm using Firefox 68.0.2.
I guess your goal here is to intercept the user trying to open a link in a new tab and instead open a different link in a new tab. If I'm correct, then you're going to need to adjust your strategy in a few key ways:
Don't use mousedown
Click events are triggered by a mouse-down followed by a mouse-up event. That means that normally you have to press and release the button before any click-type thing happens, whether that's navigation (left-click), context menu (right-click) or open in new tab (middle-click). If you try to simulate this using mousedown, it's gonna feel weird - the action will happen too soon!
Also, as you've now observed, it won't work correctly: the corresponding click event will still happen after your handler runs, because you're not cancelling the right event. What does your preventDefault() / return false accomplish? Well, try holding the middle button down and dragging: most browser will probably pan around the view as you move your mouse, but if you try this on your "Middle Click Me" element... Nothing happens. Yep, you've only succeeded in making your page slightly more annoying to scroll around on.
DO use the auxclick event.
I'm guessing you went with mousedown in the first place because you observed that nothing fired for a middle click when you captured the click event. A few years ago, click would've worked fine - but now, click only fires for the primary mouse button. This is a good thing! Way too many people inadvertently blocked right- and middle-clicks by capturing click, when they only intended to capture left-clicks. Presumably if you're capturing auxclick, you know what you're doing and can be trusted to handle it properly. (so, y'know... Do be careful)
The w3c actually has rather good documentation on all of this, so I'd be remiss if I didn't link to it and quote the relevant bits here:
The click event should only be fired for the primary pointer button (i.e., when button value is 0, buttons value is 1). Secondary buttons (like the middle or right button on a standard mouse) MUST NOT fire click events. See auxclick for a corresponding event that is associated with the non-primary buttons.
The click event MAY be preceded by the mousedown and mouseup events on the same element, disregarding changes between other node types (e.g., text nodes). Depending upon the environment configuration, the click event MAY be dispatched if one or more of the event types mouseover, mousemove, and mouseout occur between the press and release of the pointing device button. The click event MAY also be followed by the dblclick event.
Finally, here's your snippet with the changes above, for your review (you can't actually test it here, since window.open is blocked in Snippets - but you'll get an error indicating this and not see any tabs open; paste it into your fiddle for a real test):
// Allow middle button click to open client in another tab.
$(document).on('auxclick', '.clientlist-edit', function (event) {
if (event.which === 2) {
event.preventDefault();
var url = $(this).attr('href');
url = url.toLowerCase().replace('/addedit', '/clientindex');
window.open(url, '_blank');
return false;
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<a class="clientlist-edit" href="/Clients/Management/AddEdit/4ffac190-72d2-476a-b0be-a9d90097272a">
<i class="glyphicon glyphicon-pencil"></i> <strong class="title">Client Name</strong>
</a>
Yep - the only change is mousedown -> auxclick! Enjoy...
Further reading
Middle button click event
UI Events - event type click - W3C Editor's Draft
Element: auxclick event on MDN

event.button not working properly in Chrome

I'm using JQuery event object's button property to get whether the left button of the mouse was clicked during a mouseout event:
$("#foo").on("mouseout", function(event){
if (event.button === "0"){
// do code
}
});
According to the specification button property gets the string value "0" if the left button was clicked, and it gets the value "-1" if none of the buttons.
My problem is that in Chrome (I haven't tried it on other browser yet) I get the value "0" whether left button is being clicked or none of the buttons are being clicked. If I clicked the right button, I get the proper value ("2") as in the specification. So I only have problem if none of the buttons are being clicked (it should give the "-1" value, but it gives the "0" value).
Do you have any clue?
I know there is a buttons (plural!) property two, but I use TypeScript and it cannot recognize this proprety for JQueryEventObject class. However in JavaScript buttons property works well for me.
I'm using JQuery event object's button property to get whether the left button of the mouse was clicked during a mouseout event.
But you are using a mouse event which is not in the list mouseout, but docs # MDN says this:
The MouseEvent interface represents events that occur due to the user interacting with a pointing device (such as a mouse). Common events using this interface include click, dblclick, mouseup, mousedown.

How to feature-detect event.which in mousemove listeners?

Chrome seems to have event.which === 1 in a mousemove listener if the left mouse button is currently depressed at the time of the move event.
But Firefox doesn't; it only sets event.which in mousedown and mouseup. I don't know about other browsers.
Can anyone think of a good way to feature-detect this behaviour?
Note: I know you can hack it using mousedown and mouseup listeners to update a mouseIsPressed variable, but this isn't a good hack in my situation (a drag interaction inside an iframed window, ie no way to catch the mouseup if it happens outside the iframe), so I want to use the native event.which where available.
DOM Level 3 defines MouseEvent#buttons, which Firefox supports. From the MDN article on mousemove:
The buttons being pressed when the mouse event was fired: Left button=1, Right button=2, Middle (wheel) button=4, 4th button (typically, "Browser Back" button)=8, 5th button (typically, "Browser Forward" button)=16. If two or more buttons are pressed, returns the logical sum of the values. E.g., if Left button and Right button are pressed, returns 3 (=1 | 2).

Pointer Events method of checking left- or right-click

I've configured Pointer Events through
pointerevents-polyfill.
There's an issue I have where I cannot differentiate between left- and right-clicks where right-clicking a nav item will do the same action as left-clicking instead of opening the right-click menu.
The specific event I'm using is pointerup.
Is there a way with Pointer Events to check if the event is a left- or right-click?
Looks like there is a property called button that has a value of 0 if it's the primary pointer (left mouse button).
I haven't used this library but from looking at the source and the W3C spec it would appear that way.
You can always print/debug the event and see what the property is.
I used event.type == 'click' (left) vs. event.type == 'contextmenu' (right).
The following code identifies “main button” type pointer events like left mouse click, touch.
if(e.pointerType !== 'mouse' || e.button === 0){
//Not mouse pointer or mouse pointer with left button
}
https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button
0: Main button pressed, usually the left button or the un-initialized state
1: Auxiliary button pressed, usually the wheel button or the middle button (if present)
2: Secondary button pressed, usually the right button
3: Fourth button, typically the Browser Back button
4: Fifth button, typically the Browser Forward button

Javascript detect when drop down list is closed

Because of the issue explained in this question I have a situation where I need to attach the mousewheel event to the drop down list only when it is expanded (I do this in the onclick event). However I need to remove the mousewheel event when the list collapses. How do I go about detecting this?
I can't just use the onchange event because the user may not have actually changed their selection. I've tried the onblur event but in most browsers (except IE) the drop list stays focused when the list is collapsed.
Cheers.
var list = document.getElementById("list");
list.onclick = function (e) {
// attach mousewheel
list.onmousewheel = function (e) {
// ...
}
// attach click off
// This event fires fine in all browsers except FF when the list is expanded.
// In firefox it only fires when anywhere in the document is clicked twice.
// The first click closes the drop down list as expected and the second one
// fires the event.
window.document.onclick = function (e) {
list.onmousewheel = null;
window.document.onclick = null
}
};
EDIT:
Unfortunately meder's solution doesnt work in firefox. The click event on the document doesn't get fired until i click twice off the drop down list. How do I get around that? It works fine in IE.
EDIT2:
I've done some more testing and the following browsers behave as expected
IE 7,
Chrome 3
Opera 10
Firefox requires 2 clicks in the window to make it work & Safari doesn't work at all.
It appears that even when you click off the drop down list firefox maintains focus on it. It's not until the second click occurs that the drop down list eventually loses it's focus.
Are you looking for something like this? If the user clicks anywhere that's not within #el, it will branch out and you can do what you want, though this requires jQuery but it would take far too many lines of DOM Scripting.
var dropdown = $('#el');
$(document).click(function(e){
if ( (!$(e.target).is(dropdown)) || !$(e.target).closest('#el').length ) {
// do what you need to
}
});
If not, can you be more specific and include an example?
PS - I did not test the snippet, sorry if it isn't what you want.
OK, I still have no idea what you're trying to achieve with such a tightly-scripted select box, but in general trying to change the internal working of a native <select> isn't fruitful. There's no standard that says how events flow internally to the form element, and browsers that implement select as an OS-level widget (IE) can't do much to support it anyway.
If you must have this behaviour, I'd suggest using scripting to replace the <select> box on-fly with a JavaScript-powered analogue made out of <div>s. Then you can control exactly how each mouse and keyboard interaction behaves. There are many libraries that do this already, though again if you need to be very specific about the exact behaviour they might not suit you.

Categories

Resources