Como distinguir entre clique esquerdo e direito do mouse com jQuery

574

Como você obtém o botão do mouse clicado usando o jQuery?

$('div').bind('click', function(){
    alert('clicked');
});

isso é acionado pelo clique direito e esquerdo, qual é a maneira de conseguir capturar o botão direito do mouse? Ficaria feliz se existir algo como abaixo:

$('div').bind('rightclick', function(){ 
    alert('right mouse button is pressed');
});
Sinan
fonte

Respostas:

900

A partir do jQuery versão 1.1.3, event.whichnormaliza event.keyCodee event.charCodevocê não precisa se preocupar com problemas de compatibilidade do navegador. Documentação emevent.which

event.which fornecerá 1, 2 ou 3 para os botões esquerdo, médio e direito do mouse, respectivamente:

$('#element').mousedown(function(event) {
    switch (event.which) {
        case 1:
            alert('Left Mouse button pressed.');
            break;
        case 2:
            alert('Middle Mouse button pressed.');
            break;
        case 3:
            alert('Right Mouse button pressed.');
            break;
        default:
            alert('You have a strange Mouse!');
    }
});
Bolota
fonte
4
@ Jeff Hines - Eu estava tentando detectar um clique direito no Chrome e a implementação mostrada aqui parecia funcionar bem, mas percebi que era apenas porque o alert () impedia a exibição do menu de contexto. :( boo
jinglesthula 28/11
15
Continue rolando para baixo e leia a resposta de @ JeffHines . Basicamente, o jQuery tem esse recurso incorporado como o evento 'contextmenu'.
jpadvo
8
@jpadvo O jQuery não o criou como "contextmenu", contextmenué nativo do navegador. em JavaScript nativo, você pode anexar ao oncontextmenuevento.
Naftali aka Neal
6
IE8: Não é possível obter o valor da propriedade 'que': objeto é nulo ou indefinido
Simon
2
Posso impedir que o menu de contexto seja exibido depois que o evento for disparado?
precisa
251

Edit : Eu mudei para trabalhar com elementos adicionados dinamicamente usando .on()no jQuery 1.7 ou superior:

$(document).on("contextmenu", ".element", function(e){
   alert('Context Menu event has fired!');
   return false;
});

Demonstração: jsfiddle.net/Kn9s7/5

[Início da postagem original] Foi o que funcionou para mim:

$('.element').bind("contextmenu",function(e){
   alert('Context Menu event has fired!');
   return false;
}); 

Caso você esteja em várias soluções ^^

Edit : Tim Down traz um bom ponto de vista que nem sempre será o right-clickque aciona o contextmenuevento, mas também quando a tecla do menu de contexto é pressionada (o que é provavelmente um substituto para um right-click)

Jeff Hines
fonte
28
Essa deve ser a resposta aceita. Este evento funciona em todos os navegadores relevantes e aciona um clique inteiro (mouse para baixo + mouse para cima).
precisa
3
Esta é a única solução que funcionou para mim com relação a capturar o clique direito em um <textarea>
styler1972
17
Clicar com o botão direito do mouse não é a única maneira de acionar o menu de contexto.
Tim Baixo
3
Eu acho que é a abordagem errada, porque o contextmenudisparo do evento nem sempre implica que o botão direito do mouse foi clicado. A abordagem correta é obter informações do botão de um evento de mouse ( clickneste caso).
Tim Baixo
1
Ei! Obrigado, isso parece ótimo, mas não consigo vincular um elemento como uma linha da tabela ou até o corpo. trabalha com $ (janela). Im usando Backbone.js para preencher um #main área com novos conteúdos etc.
Harry
84

Você pode dizer com facilidade qual botão do mouse foi pressionado verificando a whichpropriedade do objeto de evento nos eventos do mouse:

/*
  1 = Left   mouse button
  2 = Centre mouse button
  3 = Right  mouse button
*/

$([selector]).mousedown(function(e) {
    if (e.which === 3) {
        /* Right mouse button was clicked! */
    }
});
Russ Cam
fonte
3
O plugin jQuery vinculado acima está sendo usado e.button==2.
ceejayoz
6
Sim. Usar event.buttono navegador cruzado é mais um problema do event.whichque os números usados ​​para os botões event.buttonvariam. Dê uma olhada neste artigo de janeiro de 2009 - unixpapa.com/js/mouse.html
Russ Cam
1
Não seria melhor mouseupverificar se uma pessoa realmente clicou no item? Muitas vezes, se eu clicar acidentalmente em algo, sou capaz de impedir o clique pressionando o botão do mouse e arrastando para fora do elemento.
Chris Marisic
1
@ChrisMarisic mouseupé provavelmente um evento melhor, este é apenas um exemplo do uso de event.whichcliques no botão do mouse #
485 Russ Cam
39

Você também pode bindpara contextmenue return false:

$('selector').bind('contextmenu', function(e){
    e.preventDefault();
    //code
    return false;
});

Demonstração: http://jsfiddle.net/maniator/WS9S2/

Ou você pode criar um plugin rápido que faça o mesmo:

(function( $ ) {
  $.fn.rightClick = function(method) {

    $(this).bind('contextmenu rightclick', function(e){
        e.preventDefault();
        method();
        return false;
    });

  };
})( jQuery );

Demonstração: http://jsfiddle.net/maniator/WS9S2/2/


Usando .on(...)jQuery> = 1.7:

$(document).on("contextmenu", "selector", function(e){
    e.preventDefault();
    //code
    return false;
});  //does not have to use `document`, it could be any container element.

Demo: http://jsfiddle.net/maniator/WS9S2/283/

Naftali tcp Neal
fonte
1
@ Raynos sim, mas essa é a única maneira de lidar com um evento do botão direito. se o menu de contexto ainda estivesse lá, não seria possível fazer nada com o botão direito.
Naftali aka Neal,
1
@Raynos - há muitos casos em que o ponto não é válido, como a construção de uma ferramenta interna, ou codificação algo para seu próprio use..I'm pessoal certeza que existem mais
vsync
1
Se você realmente deseja que ele atue como um dos manipuladores de eventos do jQuery (como clique, por exemplo), isso deve ser em method.call(this, e);vez de method();Dessa forma, methodobtém o valor correto thise também tem o objeto de evento passado corretamente.
Jeremy T
@ JeremyT isso é verdade ... você pode lidar com o retorno de chamada da maneira que quiser ^ _ ^
Naftali aka Neal
30

$("#element").live('click', function(e) {
  if( (!$.browser.msie && e.button == 0) || ($.browser.msie && e.button == 1) ) {
       alert("Left Button");
    }
    else if(e.button == 2){
       alert("Right Button");
    }
});

Atualização para o estado atual das coisas:

var $log = $("div.log");
$("div.target").on("mousedown", function() {
  $log.text("Which: " + event.which);
  if (event.which === 1) {
    $(this).removeClass("right middle").addClass("left");
  } else if (event.which === 2) {
    $(this).removeClass("left right").addClass("middle");
  } else if (event.which === 3) {
    $(this).removeClass("left middle").addClass("right");
  }
});
div.target {
  border: 1px solid blue;
  height: 100px;
  width: 100px;
}

div.target.left {
  background-color: #0faf3d;
}

div.target.right {
  background-color: #f093df;
}

div.target.middle {
  background-color: #00afd3;
}

div.log {
  text-align: left;
  color: #f00;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="target"></div>
<div class="log"></div>

TheVillageIdiot
fonte
1
isso é específico para o msie? ou seja, é portátil em outros navegadores?
Taryn East
13
Agora, este método é desnecessário, pois event.whichfoi introduzido, o que elimina a compatibilidade entre navegadores.
Acorn
8
Eu suspeito que event.which realmente elimina a incompatibilidade entre navegadores, mas sou apenas eu.
DwB 27/01
18
$.event.special.rightclick = {
    bindType: "contextmenu",
    delegateType: "contextmenu"
};

$(document).on("rightclick", "div", function() {
    console.log("hello");
    return false;
});

http://jsfiddle.net/SRX3y/8/

Esailija
fonte
15

Há muitas respostas muito boas, mas eu só quero tocar em uma grande diferença entre o IE9 e o IE <9 ao usar event.button .

De acordo com a especificação antiga da Microsoft para event.buttonos códigos diferem dos usados ​​pelo W3C. O W3C considera apenas 3 casos:

  1. O botão esquerdo do mouse é clicado - event.button === 1
  2. O botão direito do mouse é clicado - event.button === 3
  3. O botão do meio do mouse é clicado - event.button === 2

No Internet Explorer mais antigo, no entanto, a Microsoft está pressionando um pouco o botão pressionado e há 8 casos:

  1. Nenhum botão é clicado - event.button === 0ou 000
  2. Clique no botão esquerdo - event.button === 1ou 001
  3. Clica no botão direito - event.button === 2ou 010
  4. Os botões esquerdo e direito são clicados - event.button === 3ou 011
  5. O botão do meio é clicado - event.button === 4ou 100
  6. Os botões do meio e esquerdo são clicados - event.button === 5ou 101
  7. Os botões do meio e do lado direito são clicados - event.button === 6 ou 110
  8. Todos os 3 botões são clicados - event.button === 7ou 111

Apesar de teoricamente ser assim que deve funcionar, nenhum Internet Explorer suportou os casos de dois ou três botões pressionados simultaneamente. Estou mencionando isso porque o padrão W3C não pode nem mesmo apoiar isso teoricamente.

Konstantin Dinev
fonte
6
então, ao pressionar o botão, você obtém o event.button === 0que não clica em nenhum botão. IEಠ_ಠ
Sinan
Isso está nas versões do IE menores que 9. #
Konstantin Dinev
Se os desenvolvedores parassem de optar por oferecer suporte, ou seja, as pessoas precisariam mudar, e então os desenvolvedores não precisariam mais se preocupar em oferecer suporte.
ahnbizcad
8

Parece-me que uma leve adaptação da resposta de TheVillageIdiot seria mais limpa:

$('#element').bind('click', function(e) {
  if (e.button == 2) {
    alert("Right click");
  }
  else {
    alert("Some other click");
  }
}

EDIT: JQuery fornece um e.whichatributo, retornando 1, 2, 3 para clique esquerdo, do meio e direito, respectivamente. Então você também pode usarif (e.which == 3) { alert("right click"); }

Consulte também: respostas para "Disparando o evento ao clicar usando o botão do meio"

Dan Burton
fonte
3

event.which === 1 garante um clique esquerdo (ao usar o jQuery).

Mas você também deve pensar nas teclas modificadoras: ctrlcmdshiftalt

Se você estiver interessado apenas em capturar cliques simples e não modificados, faça algo assim:

var isSimpleClick = function (event) {
  return !(
    event.which !== 1 || // not a left click
    event.metaKey ||     // "open link in new tab" (mac)
    event.ctrlKey ||     // "open link in new tab" (windows/linux)
    event.shiftKey ||    // "open link in new window"
    event.altKey         // "save link as"
  );
};

$('a').on('click', function (event) {
  if (isSimpleClick(event)) {
    event.preventDefault();
    // do something...
  }
});
callum
fonte
1

Se você está procurando "Eventos de mouse Javascript melhores", que permitem

  • ratoeira esquerda
  • meio do rato
  • mousedown direito
  • mouseup esquerdo
  • mouseup médio
  • mouseup direito
  • Clique esquerdo
  • clique do meio
  • clique direito
  • roda do mouse
  • roda do mouse para baixo

Dê uma olhada neste javascript normal em vários navegadores, que aciona os eventos acima e remove o trabalho de dor de cabeça. Apenas copie e cole no cabeçalho do seu script ou inclua-o em um arquivo no diretório<head> seu documento. Em seguida, vincule seus eventos, consulte o próximo bloco de código abaixo, que mostra um exemplo jquery de capturar os eventos e disparar as funções atribuídas a eles, embora isso funcione também com a ligação javascript normal.

Se você estiver interessado em vê-lo funcionar, consulte o jsFiddle: https://jsfiddle.net/BNefn/

/**
   Better Javascript Mouse Events
   Author: Casey Childers
**/
(function(){
    // use addEvent cross-browser shim: https://gist.github.com/dciccale/5394590/
    var addEvent = function(a,b,c){try{a.addEventListener(b,c,!1)}catch(d){a.attachEvent('on'+b,c)}};

    /* This function detects what mouse button was used, left, right, middle, or middle scroll either direction */
    function GetMouseButton(e) {
        e = window.event || e; // Normalize event variable

        var button = '';
        if (e.type == 'mousedown' || e.type == 'click' || e.type == 'contextmenu' || e.type == 'mouseup') {
            if (e.which == null) {
                button = (e.button < 2) ? "left" : ((e.button == 4) ? "middle" : "right");
            } else {
                button = (e.which < 2) ? "left" : ((e.which == 2) ? "middle" : "right");
            }
        } else {
            var direction = e.detail ? e.detail * (-120) : e.wheelDelta;
            switch (direction) {
                case 120:
                case 240:
                case 360:
                    button = "up";
                break;
                case -120:
                case -240:
                case -360:
                    button = "down";
                break;
            }
        }

        var type = e.type
        if(e.type == 'contextmenu') {type = "click";}
        if(e.type == 'DOMMouseScroll') {type = "mousewheel";}

        switch(button) {
            case 'contextmenu':
            case 'left':
            case 'middle':
            case 'up':
            case 'down':
            case 'right':
                if (document.createEvent) {
                  event = new Event(type+':'+button);
                  e.target.dispatchEvent(event);
                } else {
                  event = document.createEventObject();
                  e.target.fireEvent('on'+type+':'+button, event);
                }
            break;
        }
    }

    addEvent(window, 'mousedown', GetMouseButton);
    addEvent(window, 'mouseup', GetMouseButton);
    addEvent(window, 'click', GetMouseButton);
    addEvent(window, 'contextmenu', GetMouseButton);

    /* One of FireFox's browser versions doesn't recognize mousewheel, we account for that in this line */
    var MouseWheelEvent = (/Firefox/i.test(navigator.userAgent)) ? "DOMMouseScroll" : "mousewheel";
    addEvent(window, MouseWheelEvent, GetMouseButton);
})();

Exemplo de eventos com melhor clique do mouse (usa jquery por simplicidade, mas o acima funcionará em vários navegadores e disparará os mesmos nomes de eventos, o IE usa antes dos nomes)

<div id="Test"></div>
<script type="text/javascript">
    $('#Test').on('mouseup',function(e){$(this).append(e.type+'<br />');})
              .on('mouseup:left',function(e){$(this).append(e.type+'<br />');})
              .on('mouseup:middle',function(e){$(this).append(e.type+'<br />');})
              .on('mouseup:right',function(e){$(this).append(e.type+'<br />');})

              .on('click',function(e){$(this).append(e.type+'<br />');})
              .on('click:left',function(e){$(this).append(e.type+'<br />');})
              .on('click:middle',function(e){$(this).append(e.type+'<br />');})
              .on('click:right',function(e){$(this).append(e.type+'<br />');})

              .on('mousedown',function(e){$(this).html('').append(e.type+'<br />');})
              .on('mousedown:left',function(e){$(this).append(e.type+'<br />');})
              .on('mousedown:middle',function(e){$(this).append(e.type+'<br />');})
              .on('mousedown:right',function(e){$(this).append(e.type+'<br />');})

              .on('mousewheel',function(e){$(this).append(e.type+'<br />');})
              .on('mousewheel:up',function(e){$(this).append(e.type+'<br />');})
              .on('mousewheel:down',function(e){$(this).append(e.type+'<br />');})
              ;
</script>

E para aqueles que precisam da versão reduzida ...

!function(){function e(e){e=window.event||e;var t="";if("mousedown"==e.type||"click"==e.type||"contextmenu"==e.type||"mouseup"==e.type)t=null==e.which?e.button<2?"left":4==e.button?"middle":"right":e.which<2?"left":2==e.which?"middle":"right";else{var n=e.detail?-120*e.detail:e.wheelDelta;switch(n){case 120:case 240:case 360:t="up";break;case-120:case-240:case-360:t="down"}}var c=e.type;switch("contextmenu"==e.type&&(c="click"),"DOMMouseScroll"==e.type&&(c="mousewheel"),t){case"contextmenu":case"left":case"middle":case"up":case"down":case"right":document.createEvent?(event=new Event(c+":"+t),e.target.dispatchEvent(event)):(event=document.createEventObject(),e.target.fireEvent("on"+c+":"+t,event))}}var t=function(e,t,n){try{e.addEventListener(t,n,!1)}catch(c){e.attachEvent("on"+t,n)}};t(window,"mousedown",e),t(window,"mouseup",e),t(window,"click",e),t(window,"contextmenu",e);var n=/Firefox/i.test(navigator.userAgent)?"DOMMouseScroll":"mousewheel";t(window,n,e)}();
NinjaKC
fonte
1
$("body").on({
    click: function(){alert("left click");},
    contextmenu: function(){alert("right click");}   
});
AK
fonte
Você provavelmente deve adicionar alguns detalhes sobre o porquê disso funciona. - Concordo que sim, mas você não está explicando a um n00b o porquê.
Adam Copley
0
$(document).ready(function () {
    var resizing = false;
    var frame = $("#frame");
    var origHeightFrame = frame.height();
    var origwidthFrame = frame.width();
    var origPosYGrip = $("#frame-grip").offset().top;
    var origPosXGrip = $("#frame-grip").offset().left;
    var gripHeight = $("#frame-grip").height();
    var gripWidth = $("#frame-grip").width();

    $("#frame-grip").mouseup(function (e) {
        resizing = false;
    });

    $("#frame-grip").mousedown(function (e) {
        resizing = true;
    });
    document.onmousemove = getMousepoints;
    var mousex = 0, mousey = 0, scrollTop = 0, scrollLeft = 0;
    function getMousepoints() {
        if (resizing) {
            var MouseBtnClick = event.which;
            if (MouseBtnClick == 1) {
                scrollTop = document.documentElement ? document.documentElement.scrollTop : document.body.scrollTop;
                scrollLeft = document.documentElement ? document.documentElement.scrollLeft : document.body.scrollLeft;
                mousex = event.clientX + scrollLeft;
                mousey = event.clientY + scrollTop;

                frame.height(mousey);
                frame.width(mousex);
            }
            else {
                resizing = false;
            }
        }
        return true;

    }


});
user2335866
fonte
@ Nitin.Katti: - Isso funciona no ponto do mouse e clique com o botão esquerdo do mouse se congelar o botão esquerdo do mouse e, em seguida, interrompa o redimensionamento.
user2335866
0

Com jquery você pode usar event object type

jQuery(".element").on("click contextmenu", function(e){
   if(e.type == "contextmenu") {
       alert("Right click");
   }
});
Ari
fonte
0

também há uma maneira de fazer isso sem o JQuery!

Veja isso:

document.addEventListener("mousedown", function(evt) {
    switch(evt.buttons) {
      case 1: // left mouse
      case 2: // right mouse
      case 3: // middle mouse <- I didn't tested that, I just got a touchpad
    }
});

fonte
O mouse do meio parecia 4 no meu PC (Ubuntu 14.04 - FireFox). Eu acredito que esquerda e direita juntas são 3 e meio são 4 .. Tem que haver uma maneira "cross browser", "cross platform" melhor ...
Paul
0
$.fn.rightclick = function(func){
    $(this).mousedown(function(event){
        if(event.button == 2) {
            var oncontextmenu = document.oncontextmenu;
            document.oncontextmenu = function(){return false;};
            setTimeout(function(){document.oncontextmenu = oncontextmenu;},300);
            func(event);
            return false;
        }
    });
};

$('.item').rightclick(function(e){ 
    alert("item");
}); 
user3361174
fonte
0

Para aqueles que estão se perguntando se eles devem ou não usar event.whichem baunilha JS ou angular : É agora obsoleto por isso preferem usar event.buttonsem seu lugar.

Nota: Com este método e o evento (mousedown) :

  • clique esquerdo pressione está associado a 1
  • pressione o botão direito do mouse está associado a 2
  • pressionar o botão de rolagem está associado a 4

e o evento (mouseup) NÃO retornará os mesmos números, mas 0 .

Fonte: https://developer.mozilla.org/pt-BR/docs/Web/API/MouseEvent/buttons

Valink
fonte
-1
    $.event.special.rightclick = {
     bindType: "contextmenu",
        delegateType: "contextmenu"
      };

   $(document).on("rightclick", "div", function() {
   console.log("hello");
    return false;
    });
Yip Man WingChun
fonte
1
Oi. Esta resposta está sendo sinalizada como de baixa qualidade para exclusão. Parece que você adicionou uma resposta a uma pergunta que foi respondida há algum tempo. A menos que exista uma explicação na resposta que explique como essa contribuição melhora a resposta aceita, também estou inclinado a votar para excluir.
Popnoodles
1
@ popnoodles, tudo bem, mas nunca repeti-lo.
que você precisa