Cómo distinguir entre el clic izquierdo y derecho del mouse con jQuery

574

¿Cómo se obtiene el botón del mouse con jQuery?

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

Esto se activa por el clic derecho y el izquierdo, ¿cuál es la forma de capturar el clic derecho del mouse? Sería feliz si algo como a continuación existe:

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

Respuestas:

900

A partir de jQuery versión 1.1.3, se event.whichnormaliza event.keyCodey event.charCodeno tiene que preocuparse por problemas de compatibilidad del navegador. Documentación sobreevent.which

event.which dará 1, 2 o 3 para los botones izquierdo, medio y derecho del mouse respectivamente, entonces:

$('#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!');
    }
});
Bellota
fuente
44
@Jeff Hines: estaba tratando de detectar un clic derecho en Chrome y la implementación que se muestra aquí parecía funcionar bien, pero me di cuenta de que era solo porque la alerta () impidió que apareciera el menú contextual. :( boo
jinglesthula
15
Sigue desplazándote hacia abajo y asegúrate de leer la respuesta de @ JeffHines . Básicamente, jQuery tiene esto incorporado como el evento 'contextmenu'.
jpadvo
8
@jpadvo jQuery no lo creó como "contextmenu", contextmenues nativo del navegador. en JavaScript nativo puedes adjuntarlo al oncontextmenuevento.
Naftali aka Neal
66
ie8: No se puede obtener el valor de la propiedad 'which': el objeto es nulo o indefinido
Simon
2
¿Puedo evitar que aparezca el menú contextual después de que se active el evento?
kmoney12
251

Editar : lo cambié para que funcione para elementos agregados dinámicamente usando .on()jQuery 1.7 o superior:

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

Demostración: jsfiddle.net/Kn9s7/5

[Inicio de la publicación original] Esto es lo que funcionó para mí:

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

En caso de que estés en múltiples soluciones ^^

Editar : Tim Down trae a colación un buen punto de que no siempre será un evento right-clickque desencadena el contextmenuevento, sino también cuando se presiona la tecla del menú contextual (que posiblemente sea un reemplazo para a right-click)

Jeff Hines
fuente
28
Esta debería ser la respuesta aceptada. Este evento funciona en todos los navegadores y disparadores relevantes con un clic completo (mouse abajo + mouse arriba en proximidad).
Nick Retallack
3
Esta es la única solución que funcionó para mí con respecto a la captura del clic derecho en un <textarea>
styler1972
17
Sin embargo, hacer clic con el botón derecho no es la única forma de activar el menú contextual.
Tim Down
3
Creo que es un enfoque incorrecto porque la contextmenuactivación del evento no siempre implica que se hizo clic en el botón derecho del mouse. El enfoque correcto es obtener información del botón de un evento del mouse ( clicken este caso).
Tim Down
1
¡Oye! Gracias, esto se ve muy bien, pero no puedo lograr que se una a un elemento como una fila de la tabla o incluso al cuerpo. Funciona con $ (ventana). Estoy usando backbone.js para llenar un área # principal con nuevo contenido, etc.
Harry
84

Puede saber fácilmente qué botón del mouse se presionó al verificar la whichpropiedad del objeto de evento en los eventos del 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
fuente
3
En su e.button==2lugar, se está utilizando el complemento jQuery vinculado anteriormente .
ceejayoz
66
Sí. El uso del event.buttonnavegador cruzado es más problemático que el hecho de event.whichque los números utilizados para los botones event.buttonvarían. Eche un vistazo a este artículo de enero de 2009 - unixpapa.com/js/mouse.html
Russ Cam
1
¿No sería mejor mouseupverificar que una persona realmente haya hecho clic en el elemento? Hay muchas veces que si accidentalmente hago clic en algo, puedo evitarlo presionando el botón del mouse y arrastrando fuera del elemento.
Chris Marisic
1
@ChrisMarisic mouseupes probablemente un evento mejor, este es solo un ejemplo del uso de event.whichlos clics del botón del mouse
Russ Cam
39

También puede hacer bindque contextmenue return false:

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

Demostración: http://jsfiddle.net/maniator/WS9S2/

O puede hacer un complemento rápido que haga lo mismo:

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

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

  };
})( jQuery );

Demostración: 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.

Demostración: http://jsfiddle.net/maniator/WS9S2/283/

Naftali aka Neal
fuente
1
@Raynos sí, pero esa es la única forma de manejar un evento de clic derecho. Si el menú contextual todavía estaba allí, no podría hacer nada con un clic derecho.
Naftali aka Neal
1
@Raynos: hay muchos casos en los que su punto no es válido, como crear una herramienta interna o codificar algo para su uso personal ... Estoy seguro de que hay más
Vsync
1
Si realmente desea que actúe como uno de los controladores de eventos jQuery (como clic, por ejemplo), eso debería ser en method.call(this, e);lugar de method();esa forma, methodobtiene el valor correcto thisy también le pasa el objeto de evento correctamente.
Jeremy T
@JeremyT eso es cierto ... podrías manejar la devolución de llamada de la forma que quieras ^ _ ^
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");
    }
});

Actualización para el estado actual de las cosas:

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>

TheIdiot de la aldea
fuente
1
¿Es esto específico de msie? es decir, ¿es portátil en otros navegadores?
Taryn East
13
Este método ahora es innecesario, ya que event.whichse ha introducido, lo que elimina la compatibilidad entre navegadores.
Bellota
8
Sospecho que es un evento que en realidad elimina la incompatibilidad entre navegadores, pero solo soy yo.
DwB
18
$.event.special.rightclick = {
    bindType: "contextmenu",
    delegateType: "contextmenu"
};

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

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

Esailija
fuente
15

Hay muchas respuestas muy buenas, pero solo quiero mencionar una diferencia importante entre IE9 e IE <9 cuando uso event.button .

De acuerdo con la antigua especificación de Microsoft para event.buttonlos códigos difieren de los utilizados por W3C. El W3C considera solo 3 casos:

  1. Se hace clic con el botón izquierdo del mouse - event.button === 1
  2. Se hace clic con el botón derecho del mouse - event.button === 3
  3. Se hace clic en el botón central del mouse - event.button === 2

Sin embargo, en los exploradores de Internet más antiguos, Microsoft está cambiando un poco el botón presionado y hay 8 casos:

  1. No se hace clic en ningún botón - event.button === 0 o 000
  2. Se hace clic en el botón izquierdo - event.button === 1 o 001
  3. Se hace clic en el botón derecho - event.button === 2 o 010
  4. Se hace clic en los botones izquierdo y derecho - event.button === 3 o 011
  5. Se hace clic en el botón central - event.button === 4 o 100
  6. Se hace clic en los botones central e izquierdo - event.button === 5 o 101
  7. Se hace clic en los botones central y derecho - event.button === 6 o 110
  8. Se hace clic en los 3 botones, event.button === 7o 111

A pesar de que, en teoría, así es como debería funcionar, ningún Internet Explorer ha admitido los casos de dos o tres botones presionados simultáneamente. Lo estoy mencionando porque el estándar W3C ni siquiera teóricamente puede soportar esto.

Konstantin Dinev
fuente
66
así que, al presionar el botón, obtienes event.button === 0que no se hace clic en ningún botón, brillante IEಠ_ಠ
Sinan
Eso es en versiones de IE inferiores a 9.
Konstantin Dinev
Si los desarrolladores dejaran de elegir colectivamente el soporte, es decir, las personas tendrían que cambiar, y entonces los desarrolladores ya no tendrían que preocuparse por el soporte, es decir.
ahnbizcad
8

Me parece que una ligera adaptación de la respuesta de TheVillageIdiot sería más limpia:

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

EDITAR: JQuery proporciona un e.whichatributo, devolviendo 1, 2, 3 para el clic izquierdo, medio y derecho, respectivamente. Entonces también podrías usarif (e.which == 3) { alert("right click"); }

Consulte también: respuestas a "Activación de evento onclick con clic medio"

Dan Burton
fuente
3

event.which === 1 asegura que sea un clic izquierdo (cuando se usa jQuery).

Pero también debes pensar en las teclas modificadoras: ctrlcmdshiftalt

Si solo está interesado en capturar clics izquierdos simples y no modificados, puede hacer algo como esto:

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
fuente
1

Si está buscando "Mejores eventos de mouse Javascript" que permitan

  • mousedown izquierdo
  • mousedown medio
  • mousedown derecho
  • mouseup izquierdo
  • mouseup medio
  • mouseup derecho
  • click izquierdo
  • clic medio
  • botón derecho del ratón
  • mueve hacia arriba la ruleta del ratón
  • rueda del ratón hacia abajo

Eche un vistazo a este JavaScript normal entre navegadores que desencadena los eventos anteriores y elimina el dolor de cabeza. Simplemente cópielo y péguelo en el encabezado de su script, o inclúyalo en un archivo en el<head> su documento. Luego, vincule sus eventos, consulte el siguiente bloque de código a continuación que muestra un ejemplo jquery de capturar los eventos y activar las funciones que se les asignaron, aunque esto también funciona con el enlace normal de JavaScript.

Si está interesado en verlo funcionar, eche un vistazo a 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);
})();

Ejemplo de mejores eventos de clic del mouse (usa jquery para simplificar, pero lo anterior funcionará en varios navegadores y disparará los mismos nombres de eventos, IE los usa antes que los nombres)

<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>

Y para aquellos que necesitan la versión minificada ...

!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
fuente
1
$("body").on({
    click: function(){alert("left click");},
    contextmenu: function(){alert("right click");}   
});
Alaska
fuente
Probablemente debería agregar algunos detalles a por qué funciona. - Estoy de acuerdo en que sí, pero no estás explicando a un n00b por qué.
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;

    }


});
usuario2335866
fuente
@ Nitin.Katti: - Esto funciona en la punta del mouse y haga clic con el botón izquierdo si congela el botón izquierdo del mouse y luego detiene el cambio de tamaño.
user2335866
0

Con jquery puedes usar event object type

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

¡También hay una manera de hacerlo sin JQuery!

mira esto:

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
    }
});

fuente
El mouse central parecía 4 en mi PC (Ubuntu 14.04 - FireFox). Creo que a la izquierda y a la derecha juntos es 3 y el medio es 4 .. Tiene que haber un mejor "navegador cruzado", "plataforma cruzada" ...
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");
}); 
usuario3361174
fuente
0

Para aquellos que se preguntan si deberían usarlo o no event.whichen Vanilla JS o Angular : ahora está en desuso, así que prefieren usarlo en su event.buttonslugar.

Nota: Con este método y evento (mousedown) :

  • clic izquierdo se asocia a 1
  • clic derecho se asocia a 2
  • presionar el botón de desplazamiento está asociado con 4

y el evento (mouseup) NO devolverá los mismos números sino 0 en su lugar.

Fuente: https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons

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

   $(document).on("rightclick", "div", function() {
   console.log("hello");
    return false;
    });
Yip Man WingChun
fuente
1
Hola. Esta respuesta se marca como de baja calidad para su eliminación. Parece que ha agregado una respuesta a una pregunta que fue respondida hace algún tiempo. A menos que haya una explicación en la respuesta que explique cómo esta contribución mejora la respuesta aceptada, me inclino a votar para eliminar también.
Popnoodles
1
@popnoodles, está bien, pero nunca lo repitas.
Yip Man WingChun