Cách phân biệt nhấp chuột trái và chuột phải với jQuery


574

Làm thế nào để bạn có được nút chuột được nhấp bằng jQuery?

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

Điều này được kích hoạt bởi cả nhấp chuột phải và nhấp chuột trái, cách để có thể bắt được nhấp chuột phải là gì? Tôi sẽ rất vui nếu có một cái gì đó như dưới đây tồn tại:

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

Câu trả lời:


900

Kể từ phiên bản jQuery 1.1.3, event.whichbình thường hóa event.keyCodeevent.charCodedo đó bạn không phải lo lắng về các vấn đề tương thích trình duyệt. Tài liệu vềevent.which

event.which sẽ cung cấp 1, 2 hoặc 3 cho các nút chuột trái, giữa và phải tương ứng như vậy:

$('#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!');
    }
});

4
@Jeff Hines - Tôi đã cố gắng phát hiện một nhấp chuột phải trong Chrome và việc triển khai được hiển thị ở đây có vẻ hoạt động tốt, nhưng tôi nhận ra rằng đó chỉ là do cảnh báo () ngăn menu ngữ cảnh xuất hiện. :( boo
jinglểula

15
Tiếp tục cuộn xuống và đảm bảo đọc câu trả lời của @ JeffHines . Về cơ bản, jQuery có tích hợp sẵn này dưới dạng sự kiện 'bối cảnh'.
jpadvo

8
@jpadvo jQuery không xây dựng nó dưới dạng "bối cảnh", contextmenulà nguồn gốc của trình duyệt. trong JavaScript gốc, bạn có thể đính kèm vào oncontextmenusự kiện.
Naftali aka Neal

6
eg8: Không thể nhận giá trị của thuộc tính 'which': đối tượng là null hoặc không xác định
Simon

2
Tôi có thể ngăn menu ngữ cảnh xuất hiện sau khi sự kiện được kích hoạt không?
kmoney12

251

Chỉnh sửa : Tôi đã thay đổi nó để hoạt động cho các phần tử được thêm động bằng cách sử dụng .on()trong jQuery 1.7 trở lên:

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

Bản demo: jsfiddle.net/Kn9s7/5

[Bắt đầu bài viết gốc] Đây là những gì làm việc cho tôi:

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

Trong trường hợp bạn tham gia vào nhiều giải pháp ^^

Chỉnh sửa : Tim Down đưa ra một điểm tốt là không phải lúc nào nó cũng sẽ right-clickphát sinh contextmenusự kiện, mà cả khi nhấn phím menu ngữ cảnh (được cho là sự thay thế cho a right-click)


28
Đây phải là câu trả lời được chấp nhận. Sự kiện này hoạt động trong tất cả các trình duyệt có liên quan và kích hoạt trên toàn bộ nhấp chuột (di chuột xuống + chuột lên gần).
Nick Retallack

3
Đây là giải pháp duy nhất phù hợp với tôi trong việc nắm bắt nhấp chuột phải vào <textarea>
styler1972

17
Nhấp chuột phải không phải là cách duy nhất để kích hoạt menu ngữ cảnh.
Tim Down

3
Tôi nghĩ rằng đó là cách tiếp cận sai bởi vì việc contextmenubắn sự kiện không phải lúc nào cũng ngụ ý rằng nút chuột phải đã được nhấp. Cách tiếp cận đúng là lấy thông tin nút từ một sự kiện chuột ( clicktrong trường hợp này).
Tim Down

1
Chào! Cảm ơn, điều này có vẻ tuyệt vời, nhưng tôi không thể làm cho nó liên kết với một yếu tố như một hàng bàn hoặc thậm chí là cơ thể. nó hoạt động với $ (cửa sổ). Tôi đang sử dụng backbone.js để điền vào khu vực #main với nội dung mới, v.v.
Harry

84

Bạn có thể dễ dàng biết nút chuột nào đã được nhấn bằng cách kiểm tra thuộc whichtính của đối tượng sự kiện trên các sự kiện chuột:

/*
  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! */
    }
});

3
Các plugin jQuery được liên kết ở trên đang sử dụng e.button==2thay thế.
ceejayoz

6
Vâng. Sử dụng event.buttontrình duyệt chéo là một vấn đề nhiều hơn event.whichlà số lượng được sử dụng cho các nút event.buttonkhác nhau. Hãy xem bài viết này từ tháng 1 năm 2009 - unixpapa.com/js/mouse.html
Russ Cam

1
Điều này có tốt hơn không mouseupkhi xác minh một người thực sự nhấp vào mục đó? Có rất nhiều lần nếu tôi vô tình nhấp vào thứ gì đó tôi có thể ngăn nhấp bằng cách giữ nút chuột và kéo bên ngoài phần tử.
Chris Marisic

1
@ChrisMarisic mouseupcó lẽ là một sự kiện tốt hơn, đây chỉ là một ví dụ về việc sử dụng event.whichcho các lần nhấp chuột
Russ Cam

39

Bạn cũng có thể bindđến contextmenureturn false:

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

Bản trình diễn: http://jsfiddle.net/manenser/WS9S2/

Hoặc bạn có thể tạo một plugin nhanh tương tự:

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

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

  };
})( jQuery );

Bản trình diễn: http://jsfiddle.net/manenser/WS9S2/2/


Sử dụng .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.

Bản trình diễn: http://jsfiddle.net/manenser/WS9S2/283/


1
@Raynos có, nhưng đó là cách duy nhất để xử lý một sự kiện nhấp chuột phải. nếu menu ngữ cảnh vẫn còn đó thì bạn không thể làm gì khi nhấp chuột phải.
Naftali aka Neal

1
@Raynos - có nhiều trường hợp quan điểm của bạn không hợp lệ, chẳng hạn như xây dựng một công cụ nội bộ hoặc mã hóa thứ gì đó cho mục đích sử dụng cá nhân của bạn..Tôi chắc chắn có nhiều hơn
vsync

1
Nếu bạn thực sự muốn nó đóng vai trò như một trong những xử lý sự kiện jQuery (như nhấp chuột, ví dụ), mà nên method.call(this, e);thay vì method();cách đó, methodnhận được giá trị chính xác cho thisvà cũng có đối tượng sự kiện được truyền cho nó một cách chính xác.
Jeremy T

@JeremyT đó là sự thật ... bạn có thể xử lý cuộc gọi lại theo bất kỳ cách nào bạn muốn ^ _ ^
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");
    }
});

Cập nhật cho trạng thái hiện tại của những điều:

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>


1
cái này cụ thể là msie? tức là nó có thể di động trên các trình duyệt khác?
Taryn Đông

13
Phương pháp này hiện không cần thiết vì event.whichđã được giới thiệu giúp loại bỏ khả năng tương thích trình duyệt chéo.
Acorn

8
Tôi nghi ngờ event.những gì thực sự loại bỏ sự không tương thích giữa các trình duyệt, nhưng đó chỉ là tôi.
DwB

18
$.event.special.rightclick = {
    bindType: "contextmenu",
    delegateType: "contextmenu"
};

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

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


15

Có rất nhiều câu trả lời rất hay, nhưng tôi chỉ muốn chạm vào một điểm khác biệt chính giữa IE9 và IE <9 khi sử dụng event.button .

Theo đặc điểm kỹ thuật cũ của Microsoft cho event.buttoncác mã khác với mã được sử dụng bởi W3C. W3C chỉ xem xét 3 trường hợp:

  1. Nút chuột trái được nhấp - event.button === 1
  2. Nút chuột phải được nhấp - event.button === 3
  3. Nút chuột giữa được nhấp - event.button === 2

Tuy nhiên, trong Internet Explorers cũ hơn, Microsoft đang lật một chút cho nút nhấn và có 8 trường hợp:

  1. Không có nút nào được nhấp - event.button === 0 hoặc 000
  2. Nút trái được nhấp - event.button === 1 hoặc 001
  3. Nút phải được nhấp - event.button === 2 hoặc 010
  4. Các nút trái và phải được bấm - event.button === 3 hoặc 011
  5. Nút giữa được nhấp - event.button === 4 hoặc 100
  6. Các nút giữa và trái được nhấp - event.button === 5 hoặc 101
  7. Các nút giữa và phải được nhấp - event.button === 6 hoặc 110
  8. Tất cả 3 nút được nhấp - event.button === 7hoặc 111

Mặc dù thực tế đây là lý thuyết nên hoạt động như thế nào, nhưng không có Internet Explorer nào hỗ trợ các trường hợp nhấn hai hoặc ba nút đồng thời. Tôi đang đề cập đến nó bởi vì tiêu chuẩn W3C thậm chí không thể hỗ trợ về mặt lý thuyết này.


6
Vì vậy, khi nhấn nút, bạn không nhận được event.button === 0nút nào, IE tuyệt vờiಠ_ಠ
Sinan

Đó là trong các phiên bản IE thấp hơn 9.
Konstantin Dinev

Nếu các nhà phát triển cùng nhau dừng lựa chọn hỗ trợ tức là mọi người sẽ phải chuyển đổi, và sau đó các nhà phát triển sẽ không còn phải lo lắng về việc hỗ trợ tức là.
ahnbizcad 16/2/2015

8

Dường như với tôi rằng một sự điều chỉnh nhỏ cho câu trả lời của TheVillageIdiot sẽ sạch hơn:

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

EDIT: JQuery cung cấp một e.whichthuộc tính, trả về 1, 2, 3 cho lần nhấp chuột trái, giữa và phải tương ứng. Vì vậy, bạn cũng có thể sử dụngif (e.which == 3) { alert("right click"); }

Xem thêm: câu trả lời cho "Kích hoạt sự kiện onclick bằng cách sử dụng nhấp chuột giữa"


3

event.which === 1 đảm bảo đó là một cú nhấp chuột trái (khi sử dụng jQuery).

Nhưng bạn cũng nên nghĩ về các phím bổ trợ: ctrlcmdshiftalt

Nếu bạn chỉ quan tâm đến việc bắt các nhấp chuột trái đơn giản, không sửa đổi, bạn có thể làm một cái gì đó như thế này:

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

1

Nếu bạn đang tìm kiếm "Sự kiện chuột Javascript tốt hơn" cho phép

  • mousedown trái
  • mousedown giữa
  • mousedown phải
  • chuột trái
  • chuột giữa
  • chuột phải
  • ấn chuột trái
  • Nhấp chuột giữa
  • nhấp chuột phải
  • di chuột lên
  • chuột xuống

Hãy xem javascript thông thường trên trình duyệt này sẽ kích hoạt các sự kiện trên và loại bỏ công việc đau đầu. Chỉ cần sao chép và dán nó vào phần đầu của tập lệnh của bạn hoặc đưa nó vào một tệp trong phần<head> tài liệu của bạn. Sau đó liên kết các sự kiện của bạn, tham khảo khối mã tiếp theo bên dưới để hiển thị một ví dụ thú vị về việc nắm bắt các sự kiện và thực hiện các chức năng được gán cho chúng, mặc dù điều này cũng hoạt động với liên kết javascript thông thường.

Nếu bạn quan tâm đến việc xem nó hoạt động, hãy xem 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);
})();

Ví dụ về các sự kiện nhấp chuột tốt hơn (sử dụng jquery để đơn giản, nhưng ở trên sẽ hoạt động trên trình duyệt chéo và kích hoạt cùng tên sự kiện, IE sử dụng trước các tên)

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

Và đối với những người đang cần phiên bản rút gọn ...

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

1
$("body").on({
    click: function(){alert("left click");},
    contextmenu: function(){alert("right click");}   
});

Bạn có lẽ nên thêm một số chi tiết tại sao nó hoạt động. - Tôi đồng ý rằng có, nhưng bạn không giải thích cho n00b tại sao.
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;

    }


});

@ Nitin.Katti: - Đây là hoạt động của điểm chuột và nhấp chuột trái nếu đóng băng nút chuột trái sau đó dừng kích thước lại.
user2335866

0

Với jquery bạn có thể sử dụng event object type

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

0

đó cũng là một cách để làm điều đó mà không cần JQuery!

kiểm tra này:

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

Chuột giữa dường như 4 trên PC của tôi (Ubuntu 14.04 - FireFox). Tôi tin rằng trái và phải với nhau là 3 và giữa là 4 .. Phải có một "trình duyệt chéo", "đa nền tảng" tốt hơn ...
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");
}); 

0

Đối với những người đang tự hỏi liệu họ nên hay không sử dụng event.whichtrong vanilla JS hoặc Angular : Hiện tại nó không được dùng nữa nên thích sử dụng hơn event.buttons.

Lưu ý: Với phương thức này và sự kiện (mousedown) :

  • bấm chuột trái được liên kết với 1
  • nhấn chuột phải được liên kết với 2
  • nhấn nút cuộn được liên kết với 4

và sự kiện (mouseup) sẽ KHÔNG trả về cùng một số mà thay vào đó là 0 .

Nguồn: https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons


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

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

1
Chào. Câu trả lời này đang được gắn cờ là chất lượng thấp để xóa. Có vẻ như bạn đã thêm một câu trả lời cho một câu hỏi đã được trả lời một thời gian trước đây. Trừ khi có một lời giải thích trong câu trả lời giải thích cách đóng góp này cải thiện câu trả lời được chấp nhận, tôi cũng có xu hướng bỏ phiếu để xóa.
Popnoodles

1
@popnoodles, không sao nhưng không bao giờ lặp lại.
Yip Man WingChun
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.