Как различить щелчок левой и правой кнопкой мыши с помощью jQuery

574

Как вы получаете нажатие кнопки мыши с помощью jQuery?

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

это вызывается как правым, так и левым щелчком, как можно поймать правый щелчок мыши? Я был бы счастлив, если бы существовало что-то вроде ниже:

$('div').bind('rightclick', function(){ 
    alert('right mouse button is pressed');
});
Синан
источник

Ответы:

900

Начиная с версии jQuery 1.1.3, event.whichнормализуется, event.keyCodeи event.charCodeвам не нужно беспокоиться о проблемах совместимости браузера. Документация поevent.which

event.which даст 1, 2 или 3 для левой, средней и правой кнопок мыши соответственно так:

$('#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 - я пытался обнаружить щелчок правой кнопкой мыши в Chrome, и показанная здесь реализация работала нормально, но я понял, что это только потому, что alert () препятствовал появлению контекстного меню. :( boo
jinglesthula
15
Прокрутите вниз и обязательно прочитайте ответ @ JeffHines . По сути, в jQuery это встроено как событие contextmenu.
Jpadvo
8
@jpadvo jQuery не создавал его как «contextmenu», contextmenuявляется родным для браузера. в нативном JavaScript вы можете прикрепить к oncontextmenuсобытию.
Нафтали ака Нил
6
ie8: невозможно получить значение свойства 'which': объект нулевой или неопределенный
Simon
2
Могу ли я предотвратить появление контекстного меню после запуска события?
kmoney12
251

Изменить : я изменил его для работы с динамически добавленными элементами, используя .on()в JQuery 1.7 или выше:

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

Демо: jsfiddle.net/Kn9s7/5

[Начало оригинального сообщения] Вот что сработало для меня:

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

Если у вас есть несколько решений ^^

Редактировать : Тим Даун поднимает хороший вопрос, что это не всегда будет событие, right-clickкоторое запускает contextmenuсобытие, но также и при нажатии клавиши контекстного меню (что, возможно, является заменой для right-click)

Джефф Хайнс
источник
28
Это должен быть принятый ответ. Это событие работает во всех соответствующих браузерах и запускается одним щелчком мыши (мышь вниз + мышь вверх рядом).
Ник Реталлак
3
Это единственное решение, которое сработало для меня в отношении захвата правой кнопки мыши на <textarea>
styler1972
17
Щелчок правой кнопкой мыши - не единственный способ вызвать контекстное меню.
Тим Даун
3
Я думаю, что это неправильный подход, потому что contextmenuзапуск события не всегда подразумевает, что была нажата правая кнопка мыши. Правильный подход - получить информацию о кнопке из события мыши ( clickв данном случае).
Тим Даун
1
Привет! Спасибо, это выглядит великолепно, но я не могу связать его с таким элементом, как строка таблицы или даже тело. это работает с $ (окно). Я использую backbone.js, чтобы заполнить область #main новым контентом и т. Д.
Harry
84

Вы можете легко определить, какая кнопка мыши была нажата, проверив whichсвойство объекта события на событиях мыши:

/*
  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
e.button==2Вместо этого используется плагин jQuery, указанный выше .
ceejayoz
6
Ага. Использование event.buttonкроссбраузера - более сложная задача, чем event.whichцифры, используемые для кнопок event.button. Посмотрите на эту статью с января 2009 года - unixpapa.com/js/mouse.html
Russ Cam
1
Разве это не было бы лучше, чтобы mouseupубедиться, что человек действительно нажал на элемент? Часто, если я случайно щелкаю что-то, я могу предотвратить щелчок, удерживая кнопку мыши и перетаскивая за пределы элемента.
Крис Марисик
1
@ChrisMarisic mouseup, вероятно, является лучшим событием, это всего лишь пример использования event.whichнажатий кнопок мыши
Russ Cam
39

Вы также bindможете contextmenuи return false:

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

Демо: http://jsfiddle.net/maniator/WS9S2/

Или вы можете сделать быстрый плагин, который делает то же самое:

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

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

  };
})( jQuery );

Демо: http://jsfiddle.net/maniator/WS9S2/2/


Используя .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.

Демо: http://jsfiddle.net/maniator/WS9S2/283/

Нафтали ака Нил
источник
1
@Raynos да, но это единственный способ обработать событие правого клика. если контекстное меню все еще там, вы не можете ничего сделать по щелчку правой кнопкой мыши.
Нафтали ака Нил
1
@Raynos - во многих случаях ваша точка зрения недействительна, например, создание внутреннего инструмента или кодирование чего-либо для вашего личного использования. Я уверен, что есть и другие
vsync
1
Если вы на самом деле хотели, чтобы он действовал как один из обработчиков событий jQuery (например, click), он должен быть method.call(this, e);вместо method();This way, methodполучает правильное значение thisи также правильно передает объект события ему.
Джереми Т
@JeremyT, это правда ... вы можете обрабатывать обратный вызов любым способом, каким захотите ^ _ ^
Нафтали, он же Нил,
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");
    }
});

Обновление для текущего состояния вещей:

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
источник
1
это специфично для msie? то есть переносим ли он через другие браузеры?
Тарын Восток
13
Этот метод теперь не нужен, поскольку event.whichбыл введен, что устраняет кросс-браузерную совместимость.
Желудь
8
Я подозреваю событие. Которое фактически устраняет кросс-браузерную несовместимость, но это только я.
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
источник
15

Есть много очень хороших ответов, но я просто хочу коснуться одного существенного различия между IE9 и IE <9 при использовании event.button.

Согласно старой спецификации Microsoft для event.buttonкодов отличаются от тех, которые используются W3C. W3C рассматривает только 3 случая:

  1. Левая кнопка мыши нажата - event.button === 1
  2. Правая кнопка мыши нажата - event.button === 3
  3. Средняя кнопка мыши нажата - event.button === 2

В старых Internet Explorer, однако, Microsoft немного переключается на нажатую кнопку, и есть 8 случаев:

  1. Ни одна кнопка не нажата - event.button === 0или 000
  2. Левая кнопка нажата - event.button === 1или 001
  3. Правая кнопка нажата - event.button === 2или 010
  4. Левая и правая кнопки нажаты - event.button === 3или 011
  5. Средняя кнопка нажата - event.button === 4или 100
  6. Средняя и левая кнопки нажаты - event.button === 5или 101
  7. Средняя и правая кнопки нажаты - event.button === 6или 110
  8. Все 3 кнопки нажаты - event.button === 7или 111

Несмотря на то, что это теоретически так и должно работать, ни один Internet Explorer никогда не поддерживал случаи одновременного нажатия двух или трех кнопок. Я упоминаю об этом, потому что стандарт W3C даже теоретически не может это поддержать.

Константин Динев
источник
6
так что после нажатия кнопки вы получаете то, event.button === 0что не нажата кнопка, блестящий IEಠ_ಠ
Sinan
Это в версиях IE ниже 9.
Константин Динев
Если бы разработчики коллективно перестали выбирать поддержку, то есть люди должны были бы переключиться, и тогда разработчикам больше не пришлось бы беспокоиться о поддержке, т.е.
ahnbizcad
8

Мне кажется, что небольшая адаптация ответа TheVillageIdiot будет чище:

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

РЕДАКТИРОВАТЬ: JQuery предоставляет e.whichатрибут, возвращая 1, 2, 3 для левого, среднего и правого щелчка соответственно. Таким образом, вы также можете использоватьif (e.which == 3) { alert("right click"); }

Смотрите также: ответы на «Запуск события onclick с помощью среднего щелчка»

Дэн Бертон
источник
3

event.which === 1 обеспечивает щелчок левой кнопкой мыши (при использовании jQuery).

Но вы также должны подумать о клавишах-модификаторах: ctrlcmdshiftalt

Если вы заинтересованы только в ловле простых неизмененных левых кликов, вы можете сделать что-то вроде этого:

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

Если вы ищете "Лучшие события мыши Javascript", которые позволяют

  • левый moussedown
  • средний mousedown
  • прямо в музее
  • левая мышка
  • средняя мышка
  • правая мышка
  • щелчок левой кнопкой мыши
  • средний щелчок
  • щелкните правой кнопкой мыши
  • мышка вверх
  • колесо мыши вниз

Посмотрите на этот кросс-браузерный обычный javascript, который запускает вышеописанные события и удаляет головную боль. Просто скопируйте и вставьте его в заголовок вашего скрипта или включите в файл <head>документа. Затем свяжите ваши события, обратитесь к следующему блоку кода ниже, который показывает пример jquery для захвата событий и запуска назначенных им функций, хотя это работает и с обычным связыванием javascript.

Если вам интересно посмотреть, как это работает, взгляните на 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);
})();

Пример улучшенных событий щелчка мышью (для простоты используется jquery, но приведенный выше будет работать в разных браузерах и запускать те же имена событий, которые использует IE перед именами)

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

А для тех, кто нуждается в минимизированной версии ...

!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
источник
1
$("body").on({
    click: function(){alert("left click");},
    contextmenu: function(){alert("right click");}   
});
Аляска
источник
Вы, вероятно, должны добавить некоторые детали, почему это работает. - Я согласен, что это так, но вы не объясняете, почему.
Адам Копли
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
источник
@ Nitin.Katti: - Это работает на точке мыши и щелчок левой кнопкой мыши, если заморозить левую кнопку мыши, то он останавливает изменение размера.
user2335866
0

С JQuery вы можете использовать event object type

jQuery(".element").on("click contextmenu", function(e){
   if(e.type == "contextmenu") {
       alert("Right click");
   }
});
Ari
источник
0

Есть также способ сделать это без JQuery!

проверить это:

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

источник
Средняя мышь показалась на моем ПК 4 (Ubuntu 14.04 - FireFox). Я полагаю, что левый и правый вместе - это 3, а середина - 4 .. Должен быть лучший способ «кросс-браузер», «кросс-платформенный» ...
Пол
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
источник
0

Для тех , кто задается вопросом, должны ли они или не использовать event.whichв ванильным JS или угловому : Это теперь осуждается так предпочитают использовать event.buttonsвместо этого.

Примечание. С помощью этого метода и события (mousedown) :

  • нажатие левой кнопки мыши связано с 1
  • нажатие правой кнопки мыши связано с 2
  • нажатие кнопки прокрутки связано с 4

Событие and (mouseup) НЕ возвращает те же числа, но 0 вместо этого.

Источник: https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons

Valink
источник
-1
    $.event.special.rightclick = {
     bindType: "contextmenu",
        delegateType: "contextmenu"
      };

   $(document).on("rightclick", "div", function() {
   console.log("hello");
    return false;
    });
Yip Man WingChun
источник
1
Привет. Этот ответ помечается как низкокачественный для удаления. Кажется, вы добавили ответ на вопрос, на который ответили некоторое время назад. Если в ответе нет объяснения, объясняющего, как этот вклад улучшает принятый ответ, я также склонен голосовать за удаление.
Popnoodles
1
@popnoodles, все хорошо, но никогда не повторяй это.
Ип Ман WingChun