Jak odróżnić lewy i prawy przycisk myszy za pomocą jQuery

574

Jak uzyskać kliknięty przycisk myszy za pomocą jQuery?

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

jest to wywoływane przez kliknięcie prawym i lewym przyciskiem myszy, jaki jest sposób na złapanie prawego przycisku myszy? Byłbym szczęśliwy, gdyby istniało coś takiego:

$('div').bind('rightclick', function(){ 
    alert('right mouse button is pressed');
});
Sinan
źródło

Odpowiedzi:

900

Począwszy od wersji 1.1.3 jQuery, event.whichnormalizuje event.keyCodea event.charCodewięc nie trzeba się martwić o problemy ze zgodnością przeglądarki. Dokumentacja w sprawieevent.which

event.which da 1, 2 lub 3 odpowiednio dla lewego, środkowego i prawego przycisku myszy, więc:

$('#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!');
    }
});
Żołądź
źródło
4
@Jeff Hines - Próbowałem wykryć kliknięcie prawym przyciskiem w Chrome i pokazana tutaj implementacja wyglądała dobrze, ale zdałem sobie sprawę, że to tylko dlatego, że alert () uniemożliwił wyświetlenie menu kontekstowego. :( boo
jinglesthula
15
Przechowywać przewijanie w dół i upewnij się, aby przeczytać @ JeffHines męska odpowiedź . Zasadniczo jQuery ma tę wbudowaną funkcję „kontekstowego menu” zdarzenia.
jpadvo
8
@jpadvo jQuery nie zbudował go jako „menu kontekstowe”, contextmenupochodzi z przeglądarki. w natywnym JavaScript możesz dołączyć do oncontextmenuwydarzenia.
Naftali alias Neal
6
ie8: Nie można uzyskać wartości właściwości „która”: obiekt jest zerowy lub niezdefiniowany
Simon
2
Czy mogę zapobiec wyświetlaniu menu kontekstowego po uruchomieniu zdarzenia?
kmoney12
251

Edycja : Zmieniłem go, aby działał dla dynamicznie dodawanych elementów za pomocą .on()jQuery 1.7 lub nowszego:

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

Demo: jsfiddle.net/Kn9s7/5

[Początek oryginalnego postu] To działało dla mnie:

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

Jeśli jesteś w wielu rozwiązaniach ^^

Edycja : Tim Down podnosi dobrą rację, że nie zawsze będzie to, right-clickco uruchamia contextmenuzdarzenie, ale także po naciśnięciu klawisza menu kontekstowego (który prawdopodobnie jest zamiennikiem a right-click)

Jeff Hines
źródło
28
To powinna być zaakceptowana odpowiedź. To zdarzenie działa we wszystkich odpowiednich przeglądarkach i uruchamia się po jednym kliknięciu (mysz w dół + mysz w górę w pobliżu).
Nick Retallack,
3
Jest to jedyne rozwiązanie, które działało dla mnie w zakresie rejestrowania kliknięcia prawym przyciskiem myszy <textarea>
styler1972
17
Kliknięcie prawym przyciskiem nie jest jednak jedynym sposobem na wywołanie menu kontekstowego.
Tim Down
3
Myślę, że to niewłaściwe podejście, ponieważ contextmenuodpalanie zdarzeń nie zawsze oznacza kliknięcie prawym przyciskiem myszy. Prawidłowe podejście to uzyskanie informacji o przycisku ze zdarzenia myszy ( clickw tym przypadku).
Tim Down
1
Hej! Dzięki, wygląda to świetnie, ale nie mogę go powiązać z elementem takim jak rząd tabeli, a nawet ciało. działa z $ (okno). Używam backbone.js, aby zapełnić obszar #main nowymi treściami itp.
Harry
84

Możesz łatwo stwierdzić, który przycisk myszy został naciśnięty, sprawdzając whichwłaściwość obiektu zdarzenia na zdarzeniach myszy:

/*
  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
źródło
3
e.button==2Zamiast tego używa się powyższej wtyczki jQuery .
ceejayoz
6
tak. Korzystanie z event.buttonwielu przeglądarek to większy problem niżevent.whichevent.button różne liczby przycisków . Spójrz na ten artykuł od stycznia 2009 r. - unixpapa.com/js/mouse.html
Russ Cam
1
Czy nie lepiej byłoby mouseupzweryfikować, czy osoba naprawdę kliknęła element? Jest wiele razy, jeśli przypadkowo kliknę coś, jestem w stanie zapobiec kliknięciu, przytrzymując przycisk myszy i przeciągając poza element.
Chris Marisic,
1
@ChrisMarisic mouseupjest prawdopodobnie lepszym wydarzeniem, jest to tylko przykład użycia event.whichkliknięć przyciskiem myszy
Russ Cam
39

Można również binddo contextmenui return false:

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

Próbny: http://jsfiddle.net/maniator/WS9S2/

Możesz też zrobić szybką wtyczkę, która robi to samo:

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

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

  };
})( jQuery );

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


Za pomocą .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 alias Neal
źródło
1
@Raynos tak, ale to jedyny sposób na obsługę zdarzenia kliknięcia prawym przyciskiem myszy. jeśli menu kontekstowe wciąż tam było, nie można nic zrobić za pomocą prawego kliknięcia.
Naftali alias Neal,
1
@Raynos - istnieje wiele przypadków, w których twój punkt jest nieważny, takich jak budowanie wewnętrznego narzędzia lub kodowanie czegoś na własny użytek. Jestem pewien, że jest więcej
vsync
1
Jeśli naprawdę chciałeś, aby zachowywał się jak jeden z programów obsługi zdarzeń jQuery (na przykład kliknięcie), to powinno być method.call(this, e);zamiast method();W ten sposób, methodpobiera poprawną wartość, thisa także poprawnie przekazuje obiekt zdarzenia.
Jeremy T
@JeremyT to prawda ... możesz oddzwonić w dowolny sposób ^ _ ^
Naftali vel 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");
    }
});

Zaktualizuj aktualny stan rzeczy:

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
źródło
1
czy to jest specyficzne dla Msie? tzn. czy jest przenośny w innych przeglądarkach?
Taryn East
13
Ta metoda jest teraz niepotrzebna, ponieważ event.whichzostała wprowadzona, co eliminuje zgodność między przeglądarkami.
Acorn
8
Podejrzewam zdarzenie. Które faktycznie eliminuje niezgodność między przeglądarkami, ale to tylko ja.
DwB 27.01.11
18
$.event.special.rightclick = {
    bindType: "contextmenu",
    delegateType: "contextmenu"
};

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

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

Esailija
źródło
15

Istnieje wiele bardzo dobrych odpowiedzi, ale chcę tylko dotknąć jednej zasadniczej różnicy między IE9 a IE <9 podczas używania event.button .

Zgodnie ze starą specyfikacją Microsoft event.buttonkody różnią się od używanych przez W3C. W3C rozpatruje tylko 3 przypadki:

  1. Kliknięto lewy przycisk myszy - event.button === 1
  2. Kliknięto prawy przycisk myszy - event.button === 3
  3. Kliknięcie środkowym przyciskiem myszy - event.button === 2

Jednak w starszych przeglądarkach internetowych Microsoft przerzuca nieco wciśnięty przycisk i jest 8 przypadków:

  1. Nie kliknięto żadnego przycisku - event.button === 0 lub 000
  2. Kliknięto lewy przycisk - event.button === 1 lub 001
  3. Kliknięto prawy przycisk - event.button === 2lub 010
  4. Kliknięto lewy i prawy przycisk - event.button === 3lub 011
  5. Kliknięto środkowy przycisk - event.button === 4lub 100
  6. Kliknięto środkowy i lewy przycisk - event.button === 5lub 101
  7. Kliknięcie środkowego i prawego przycisku - event.button === 6 lub 110
  8. Kliknięto wszystkie 3 przyciski - event.button === 7lub 111

Pomimo tego, że teoretycznie tak powinno to działać, żaden Internet Explorer nigdy nie obsługiwał przypadków jednoczesnego naciśnięcia dwóch lub trzech przycisków. Wspominam o tym, ponieważ standard W3C nie może nawet teoretycznie to poprzeć.

Konstantin Dinev
źródło
6
więc po naciśnięciu przycisku dostajesz, event.button === 0który nie jest kliknięty, genialny IEಠ_ಠ
Sinan
Tak jest w wersjach IE niższych niż 9.
Konstantin Dinev,
Gdyby programiści zbiorowo przestali wybierać wsparcie, tzn. Ludzie musieliby się zmienić, a następnie programiści nie musieliby się martwić o wsparcie tj.
ahnbizcad
8

Wydaje mi się, że lekka adaptacja odpowiedzi TheVillageIdiot byłaby czystsza:

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

EDYCJA: JQuery zapewnia e.which atrybut, zwracający odpowiednio 1, 2, 3 dla lewego, środkowego i prawego kliknięcia. Więc możesz również użyćif (e.which == 3) { alert("right click"); }

Zobacz także: odpowiedzi na „Wyzwalanie zdarzenia kliknięcia za pomocą środkowego kliknięcia”

Dan Burton
źródło
3

event.which === 1 zapewnia kliknięcie lewym przyciskiem (podczas korzystania z jQuery).

Ale powinieneś również pomyśleć o klawiszach modyfikujących: ctrlcmdshiftalt

Jeśli chcesz tylko łapać proste, niezmodyfikowane kliknięcia lewym przyciskiem myszy, możesz zrobić coś takiego:

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...
  }
});
kalus
źródło
1

Jeśli szukasz „Lepszych zdarzeń myszy JavaScript”, które pozwalają

  • opuścił mousedown
  • środkowy mousedown
  • tuż obok
  • lewy przycisk myszy
  • środkowy kursor myszy
  • prawy przycisk myszy
  • lewy przycisk myszy
  • środkowe kliknięcie
  • kliknij prawym przyciskiem myszy
  • Kółko myszy w górę
  • kółko myszy w dół

Spójrz na ten zwykły javascript w różnych przeglądarkach, który wyzwala powyższe zdarzenia i usuwa ból głowy. Po prostu skopiuj i wklej go w nagłówku skryptu lub dołącz do pliku w pliku<head> dokumencie. Następnie powiąż swoje zdarzenia, zapoznaj się z następnym blokiem kodu poniżej, który pokazuje jquery przykład przechwytywania zdarzeń i uruchamiania przypisanych im funkcji, chociaż działa to również z normalnym wiązaniem javascript.

Jeśli chcesz zobaczyć, jak działa, zajrzyj na stronę 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);
})();

Przykład zdarzenia Lepsze kliknięcie myszą (dla uproszczenia używa jquery, ale powyższe będzie działać w różnych przeglądarkach i uruchamiać te same nazwy zdarzeń, IE używa przed nimi)

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

A dla tych, którzy potrzebują zminimalizowanej wersji ...

!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
źródło
1
$("body").on({
    click: function(){alert("left click");},
    contextmenu: function(){alert("right click");}   
});
AK
źródło
Prawdopodobnie powinieneś dodać kilka szczegółów, aby wyjaśnić, dlaczego to działa. - Zgadzam się, że tak, ale nie wyjaśniasz dlaczego n00b.
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;

    }


});
użytkownik2335866
źródło
@ Nitin.Katti: - To działa na punkt myszy i kliknięcie lewym przyciskiem, jeśli zatrzymasz lewy przycisk myszy, to zatrzyma zmianę rozmiaru.
user2335866 30.04.13
0

Z jquery możesz korzystać event object type

jQuery(".element").on("click contextmenu", function(e){
   if(e.type == "contextmenu") {
       alert("Right click");
   }
});
Ari
źródło
0

jest też sposób, aby to zrobić bez JQuery!

Sprawdź to:

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

źródło
Środkowa mysz wydawała się 4 na moim komputerze (Ubuntu 14.04 - FireFox). Wierzę, że lewy i prawy razem jest 3 i środkowy jest 4 .. Musi być lepiej „cross browser”, „cross platform” sposób ...
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");
}); 
użytkownik3361174
źródło
0

Dla tych, którzy zastanawiają się, czy powinni używać event.whichw waniliowym JS lub Angular : Teraz jest to przestarzałe, więc wolę używać event.buttonszamiast tego.

Uwaga: za pomocą tej metody i zdarzenia (mousedown) :

  • lewy przycisk myszy jest powiązany z 1
  • Prasa z prawym przyciskiem myszy jest powiązana z 2
  • naciśnięcie przycisku przewijania jest związane z 4

a zdarzenie (mouseup) NIE zwróci tych samych liczb, ale 0 zamiast tego.

Źródło: https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons

Valink
źródło
-1
    $.event.special.rightclick = {
     bindType: "contextmenu",
        delegateType: "contextmenu"
      };

   $(document).on("rightclick", "div", function() {
   console.log("hello");
    return false;
    });
Yip Man WingChun
źródło
1
Cześć. Ta odpowiedź jest oznaczana jako niska jakość do usunięcia. Wygląda na to, że dodałeś odpowiedź na pytanie, na które odpowiedziano jakiś czas temu. O ile w odpowiedzi nie ma wyjaśnienia wyjaśniającego, w jaki sposób ten wkład poprawia przyjętą odpowiedź, jestem skłonny głosować również za usunięciem.
Popnoodles
1
@pnnoodles, jest w porządku, ale nigdy go nie powtarzaj.
Yip Man WingChun