22

I have a list with a tags to play some mp3 files onclick. It is working fine when binding on the 'click' event with jQuery:

$oo.data({'__mp3play':true,'wapiHandle':h+0,'wapiIndex':o.ajaxPlayList[h].length})
           .bind( 'click', function()
            { var wh = $j(this).data('wapiHandle');
              if( typeof o.regObjects[wh] == 'object' && o.regObjects[wh].play(this.href))
               { return false; }
            });

When clicking the left mouse button: It disables default handling when my flash plugin is loaded otherwise it will be opened normally.

BUT: When I use the scrollbutton of the mouse and click on it, the click event will not fired and the link opens normally.

I have tried to use mousedown or mouseup events but doesn't help, the link always opens normally with the side effect that the music starts playing also with the flash player.

Also preventDefault() does not work at all.

Can somebody tell me how to detect the middle mouse button click (scroll button click)?

Thank you for your comments.

PS: I have already tried other solutions about the 'middle button' available on this site.

Tested in all kind of browsers with the same result.

EDIT: This also does not work, the link will be opened normally when using the middle mouse button. When using the left mouse button, nothing happen.

$oo.bind( 'mousedown click mouseup', function(e)
{ e.preventDefault(); e.stopPropagation(); return false; });
Richie Cotton
  • 118,240
  • 47
  • 247
  • 360
Codebeat
  • 6,501
  • 6
  • 57
  • 99
  • 3
    Why would you expect `click` to be invoked for a middle-click? They're not the same - you wouldn't expect it for right-click would you? And what did you try with the `mousedown` approach? Did you check the `event.which` property to identify which button had been pressed? – no.good.at.coding Mar 22 '11 at 14:09
  • The middle-click will be handled the same as a left-mouse-click, the A-tag will be opened so you can assume that a left-mouse-click is the same as a middle-click. If not, like you just said, what is the name of the middle-click event? Event.which does not make any difference, you can test if the middle button is pressed but you cannot suppress the default behaviour of the middle button because there is another event involved? The link is still opened normally. – Codebeat Mar 22 '11 at 14:24
  • Your assumption is false - just because the left mouse click shows behaviour similar to the middle click doesn't mean that they're the same internally. In fact, they're not - `click` is not fired when the middle mouse button is clicked. However, it turns out you're correct about the `preventDefault()` and `stopPropagation()` not having any effect and I can't think of any workaround at the moment. Here's a [fiddle](http://jsfiddle.net/nogoodatcoding/QNUU2/) that shows how far I got with this using `mousedown` and `mouseup` – no.good.at.coding Mar 22 '11 at 15:05
  • check out my answer and fiddle below, I found a forum post that suggested a way to get this to work. – no.good.at.coding Mar 22 '11 at 15:18
  • Does this answer your question? [Jquery: detect if middle or right mouse button is clicked, if so, do this:](https://stackoverflow.com/questions/4007482/jquery-detect-if-middle-or-right-mouse-button-is-clicked-if-so-do-this) – Advait Junnarkar Mar 02 '20 at 04:40
  • 1
    @AdvaitJunnarkar No, because the accepted answer provides the same solution (of detection) and also suppress a behaviour of IE only (detection only wasn't enough). This is a pretty old question, 8 years old and partly IE related. IE is dead, history, so why bother with a 'new' solution? There is already a solution and is better, more advanced. – Codebeat Mar 02 '20 at 19:52
  • @Codebeat Neither the question nor the accepted answer mentions IE. This question might be old and your specific problem may not be common anymore, but this general problem is still relevant. SO is supposed to be like a wiki so there's nothing wrong with updating old articles. – Advait Junnarkar Mar 02 '20 at 23:36
  • @AdvaitJunnarkar: 1. At the accepted answer: "As you can see IE needs some more......". 2. SO is not (supposed to be) a wiki, it is a QA site. 3. The accepted answer provides the same solution of detection and is more advanched so yours is not an update. – Codebeat Mar 04 '20 at 01:49

7 Answers7

56

Well after a quick test it seems that the three are ordered as follows:

  • Left - 1
  • Middle - 2
  • Right - 3

So if you had:

$(document).mousedown(function(e){
    switch(e.which)
    {
        case 1:
            //left Click
        break;
        case 2:
            //middle Click
        break;
        case 3:
            //right Click
        break;
    }
    return true;// to allow the browser to know that we handled it.
});
Syden
  • 8,425
  • 5
  • 26
  • 45
RobertPitt
  • 56,863
  • 21
  • 114
  • 161
17

Please don't fire click actions during the mousedown event. It ignores the rest of the event pipeline and goes against current user expectations and design practices.

Problem

Here's a look at the normal order of events that fire for each click type:

$(document).on("mousedown mouseup click focus blur",function(e) {
  console.log("{" + e.which + ":" + e.type + "}"); 
});    

Click Events

Typically, we handle the very last click event because it signifies the users final intent to proceed with the current action.

The click event is fired when a pointing device button (usually a mouse's primary button) is pressed and released on a single element.

Unfortunately, middle mouse presses do not fire such an event (probably because doing so would force developers listening to the click event to distinguish between multiple possible invocations). But if we want to wire up actions against the middle click, we should follow the same UX expectations.

Solution

We'll listen for mousedown events and immediately attach a one time use handler for mouseup events. If the middle key was pressed and if the elements match, we'll trigger our own custom event with type middleclick, which we'll seed from the original event.

$(document).on("mousedown", function (e1) {
  $(document).one("mouseup", function (e2) {
    if (e1.which == 2 && e1.target == e2.target) {
      var e3 = $.event.fix(e2);
      e3.type = "middleclick";
      $(e2.target).trigger(e3)
    }
  });
});

That'll help separate out determining if the middle button was clicked with how we we want to handle it in that case, so we can setup a listener for our custom event type like this:

$(document).on("middleclick", function (e) {
    console.log("{" + e.target.nodeName.toLowerCase() + ":" + e.type + "}"); 
});

Working Demo in jsFiddle and Stack Snippets:

$(document).on("mousedown", function (e1) {
  $(document).one("mouseup", function (e2) {
    if (e1.which == 2 && e1.target == e2.target) {
     var e3 = $.event.fix(e2);
      e3.type = "middleclick";
      $(e2.target).trigger(e3)
    }
  });
});

$(document).on("middleclick", function (e) {
  console.log("{" + e.target.nodeName.toLowerCase() + ":" + e.type + "}"); 
});

$(document).on("mousedown mouseup click focus blur",function(e) {
  console.log("{" + e.which + ":" + e.type + "}"); 
}); 
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"></script>

<div  style="background:#31965a;color:white;width:100px;height:100px;line-height:100px;text-align:center;">
  Click Me!
</div>

* Tested in Chrome, FF, Edge, & IE11

KyleMit
  • 30,350
  • 66
  • 462
  • 664
  • Appreciate your answer however there are some issues. You wrote; "Please don't fire click actions during the mousedown event. It ignores the rest of the event pipeline and goes against current user expectations and design practices." Eh, at first, it doesn't fire anything, it doesn't cause a hardware event by itself and doesn't fire a click event however it handles an event and can cancel an event. And because you don't cancel anything in the route to a click it can lead to unpredictable results when there are other attached event handlers. I have already posted a solution/workaround 2 this. – Codebeat Apr 06 '18 at 04:46
  • @Codebeat, I appreciate the comment (but not sure about the downvote). I'm not sure our solutions are looking to address the same issue. My point is that this answers actually handles a middle *mouse **click*** event, not just a middle *mouse **mousedown*** event. Click events happen when the user has clicked down and released on the same element. When you middle mouse click on a link, in *all browsers* it will open that link when you've let go, not when you've depressed the button. It gives you time to cancel out. If you're looking to replicate this functionality, you'll need this asr – KyleMit Apr 06 '18 at 11:59
  • This question is 7 years old and also the answer, I believe I did '$.browser.msie ? "mousedown" : "click"' for a reason. Also I use the document element (like you do) to preview actions so before the event reaches the focused element. That's why I cancel the event. If you cancel an event all other related events will be ignored and because of that there is no click at all because the action has not been completed. In your example, you don't cancel anything and that's why you still receive all events on the document and focussed element. Goal was to suppress behavior be4 the action willb proce. – Codebeat Apr 06 '18 at 18:48
  • I see a downvote on my question and answer on yesterday, hopefully your not the one who did this because you are angry in all frustration. I don't know what exactly your problem is and why you want to do want you want to do, with an extra handler and such.. Your answer must be a comment. There was a reason for the differences in mousedown (iE) and click (others) 7 years ago. Again, the goal was to suppress a hardware behavior before the action will be processed on any link (and IE requires that 7 years ago) and to avoid the need to bind an extra event handler on every element. ..... – Codebeat Apr 08 '18 at 23:43
  • ........ If you don't cancel the event, it doesn't work at all. And I don't fire click and such. Really, I don't understand what your point must be, maybe you don't understand how events works. And also, it isn't an answer to the question. You want to discus the answer and not the question and that could be a comment. – Codebeat Apr 08 '18 at 23:47
  • Aha (ploink), I think you don't understand this line: '$.browser.msie ? "mousedown" : "click"' which is actually an if-then-else statement. I don't bind an event on mousedown and click at the same time. For IE I do it on "mousedown" and for others I do it on "click". That is what your point is about, you think that I handle both and that's not true. – Codebeat Apr 08 '18 at 23:58
8

Ok, I think I've got it. Here's a fiddle that seems to work. The trick (at least with FF4) seems to be to bind a click handler to the document and have it stop the propagation.

$(document).click(function(e){
        //not checking for the right click will prevent the context-menu from showing, you may or may not want to do that
        if (e.which != 3) { 
            e.preventDefault();
            return false;
        }
    });

This solution was found on this forum page.

no.good.at.coding
  • 20,221
  • 2
  • 60
  • 51
3

Okay guys,

Thank you for your input. '@no.good.at.coding' has a nice solution but does not work on IE (see later on this writing) but is a good starting point. I change his code to this:

// Avoid relations will be opened in extra tab when clicking middle-scroll-button to open it
$(document).bind($.browser.msie ? "mousedown" : "click", function(e)
{
    if (e.which == 2 && e.target.tagName == 'A') 
    {
        var bIE = $.browser.msie,
            $o = $(e.target),
            oe = $o.data('events'),
            b = true,
            f = function(){};

        if (typeof oe == 'object' && oe['click']) {
            f = function(){ $o.trigger('click'); }
        } else {
            b = (typeof $o[0].href == 'string' && ($o[0].target == undefined || $o[0].target == '' || $o[0].target == '_self'));
            if (b) { 
                f = function () { window.location.href=$o[0].href; };
            }
        }

        if (!b) { return; }

        e.stopImmediatePropagation();
        e.stopPropagation();
        e.preventDefault();

        if (bIE)
        {
            if (!window.__swcp__) { 
                window.__swcp__= $('<div style="position:fixed;top:0px;left:0px;width:100%;height:100%;background:#000;display:block;z-index:9999;opacity:0.01;filter:alpha(opacity:1);" />').appendTo('body'); 
            }
            window.__swcp__.show();
        }

        setTimeout(f, 50);
        if (bIE) { 
            setTimeout( function() { window.__swcp__.hide(); }, 1000 );
        }

        return false;
    }
});

The middle-button acts now like the left-button of a mouse. As you can see IE needs some more, we must unfocus the link tag for 1 second to avoid that it will be opened in an extra tab. I use here a simple way to do this, create a 'for the eye" transparent div (opacity = 0.01) that will be placed over the window content so any link on the page will be unfocused. The user will not notice any difference except that the mouse pointer can change from pointer to default and after one second it change back to pointer (IE only). I can live with that.

I accept this as an answer, but if you have better idea's let me know.

Pang
  • 9,564
  • 146
  • 81
  • 122
Codebeat
  • 6,501
  • 6
  • 57
  • 99
  • 1
    Note that jquery.browser has since become deprecated. http://api.jquery.com/jQuery.browser/ – Frisbetarian-Support Palestine Sep 17 '13 at 14:31
  • Frisberarian < Thanks for the additional info. At the time IE9 was around for the first time I discover some problems with newer versions of jQuery higher than v1.5.1. That's the reason I still use a slightly modified version of v1.5.1 today that is working okay in all browsers of today (including the old and mobile ones). Also some older code and plugins doesn't work with the newer jQuery versions because there are so many changes (= too much extra work), i will stay at v1.5.1 until it is really necessary to change. – Codebeat Sep 19 '13 at 19:27
  • Sorry if my edit seems aggressive, but it was just so hard to make sense of. I tried to leave the variables as is, but they really should be renamed and I think some refactoring, such as reuse of the browser checking might be a good idea. – Joel Peltonen Jan 23 '15 at 09:03
  • Thanks Nenotiep. Well, some things are the style you prefer. I don't like the accolade style, always difficult to read because you cannot see statements directly, never understood why they are not aligned to each-other. Variables, I know, but it javascript must be compact for speed. Nowadays I use google enclosure compiler to minify the scripts. Besides, it is always important to look at what happen in the code instead of look at the variable names. Sure, a clear variable name can clearify things, because javascript has no declaration type it can be anything. Don't rely 2 much on var names. – Codebeat Jan 29 '15 at 02:22
  • ..... (continue comment above) When you can read this, you can read almost anything. I use always var names starting with the expected type (letter) of the variable. o = object, $ = jQuery object, b = boolean, s = string, i = integer, e = event, f = function etc. – Codebeat Jan 29 '15 at 02:26
  • ..... (continue comment above) When you can read this, you can read almost anything. I use always var names starting with the expected type (letter) of the variable. o = object, $ = jQuery object, b = boolean, s = string, i = integer, e = event, f = function etc. I bet, you can now read it easier knowing this. A hint to an expected type is, to me, more useful than a beautiful variable name as long the function name is clear enough. Power of jQuery = compact. if you cannot handle that, use another framework lib. – Codebeat Jan 29 '15 at 02:32
1

The correct way to do this with HTML5 is to use auxclick event.

For example, to fully disable middle mouse button click on an element

    $element.on("auxclick.disablemiddleclick", function(e)
    {
        // https://developer.mozilla.org/en-US/docs/Web/API/Element/auxclick_event
        if (e.which === 2 && e.cancelable) // disable middle button click
        {
            e.preventDefault();
            e.stopPropagation();
            e.stopImmediatePropagation();
            console.log("disabled middle click, e=", e);
        }
    });

(The suffix on "auxclick" handler name is meant to allow for easy removal of this handler with $element.off("auxclick.disablemiddleclick") without keeping track of the function reference.)

Mikko Rantalainen
  • 14,132
  • 10
  • 74
  • 112
  • Valid answer for nowadays (take a look at the support version numbers) however this question is almost 10 years old! 10 years ago this was not supported by IE for example. – Codebeat Mar 24 '21 at 19:21
  • Yeah, the only way MSIE and HTML5 fit is the sentence "MSIE doesn't support HTML5". – Mikko Rantalainen Mar 27 '21 at 08:01
-1

e.which should do it:

Simple example:

$(document).ready(function(){
    $(document).mousedown(function(e){
         alert(e.which); // ##=> left
    }) 
})
no.good.at.coding
  • 20,221
  • 2
  • 60
  • 51
Yule
  • 9,668
  • 3
  • 51
  • 72
  • 5
    This is not the answer to the question and also not an answer at all – Codebeat Mar 22 '11 at 15:14
  • No, it doesn't - the trouble is that the browser handles the middle click and it *still* opens a new tab/window when a link is middle clicked. See my fiddle in the comments above. – no.good.at.coding Mar 22 '11 at 15:15
-3

If you, (like me) found this because of weird-o middle click bugs from clients. And you just want any middle or right click to behave like a left click

Forget all that lame code for IE.

Short and sweet:

$(document).click(function(e){
  // checking for any non left click and convert to left click.
  if (e.which != 1) { 
    e.which = 1;
  }
});

Obviously if you need a little more discrimination, you can do something like:

$('a.no-non-left-clickies').click(function(e){
  // checking for any non left click and convert to left click.
  if (e.which != 1) { 
    e.which = 1;
  }
});
  • Well, I looked in more detail at your initial question, and I see that you do need more IE junk than I mentioned, however, my statement still stands, in general. If you want a quick-o-change-o convert middle or right click into a left click, the above simple code will work on all browsers I've tested on. – Drupal Development Costa Rica Mar 15 '13 at 17:15
  • Have not tried your solution but does it also avoid that a new page is opened? – Codebeat Mar 15 '13 at 20:40