Почему в некоторых случаях средний щелчок не запускает 'click'?

Здесь JSFiddle поведения, которое я вижу, относящегося к среднему клику и событию click в Chrome и FF.

'click' kinda sorta works

Подход 1: привязать обработчик click непосредственно к элементу a, а средний щелчок вызовет обработчик в Chrome, но не в FF.

$('div a').on('click', function(ev) {
    // middle click triggers this handler
});

Подход 2: привязать делегированный обработчик click к div, который содержит один или несколько a. Средний клик не будет запускать этот обработчик в Chrome или FF.

$('div').on('click', 'a', function(ev) {
    // middle click doesn't trigger this handler
});

Этот подход чрезвычайно ценен, если div начинается пустым, а элементы a заполняются позже вызовом AJAX или в результате ввода какого-либо пользователя.

'mouseup' работает

Использование mouseup вместо click приводит к тому, что оба подхода 1 и 2 работают в обоих браузерах.

// Approach 1 w/ mouseup
$('div a').on('mouseup', function(ev) {
    // middle click **does** trigger this handler in Chrome and FF
});

// Approach 2 w/ mouseup
$('div').on('mouseup', 'a', function(ev) {
    // middle click **does** trigger this handler in Chrome and FF
});

Здесь JSFiddle с mouseup.

Это интересно и может быть полезно в некоторых случаях, потому что mouseup почти click. Но mouseup не click, а я после поведения click. Я не хочу создавать hacky mousedown; setTimeout; mouseup моделирования click.

Я уверен, что ответ "nope", но есть ли кросс-браузерный способ вызвать средний щелчок для запуска обработчиков click? Если нет, то в чем причины?

Ответ 1

Событие клика обычно запускается левой кнопкой мыши, однако в зависимости от браузера событие клика может или не может появиться для правой и/или средней кнопки.

В Internet Explorer и Firefox событие клика не запускается для правой или средней кнопки.

Поэтому мы не можем надежно использовать событие click для обработчиков событий на средней или правой кнопке.

Вместо этого, чтобы различать кнопки мыши, мы должны использовать события mousedown и mouseup, поскольку большинство браузеров запускают mousedown и mouseup события для любой кнопки мыши.

в Firefox и Chrome event.which должен содержать номер, указывающий, какая кнопка мыши была нажата (1 слева, 2 - средний, 3 - правый).

В Internet Explorer, с другой стороны, event.button указывает, какая кнопка мыши была нажата (1 слева, 4 - посередине, 2 - справа);

event.button должен также работать в Firefox и других браузерах, но цифры могут быть немного разными (0 слева, 1 - средний, 2 - правый).

Итак, чтобы собрать это вместе, мы обычно делаем что-то вроде этого:

document.onmousedown = function(e) {
    var evt = e==null ? event : e;

    if (evt.which) { // if e.which, use 2 for middle button
        if (evt.which === 2) {
            // middle button clicked
        }
    } else if (evt.button) { // and if e.button, use 4
        if (evt.button === 4) {
            // middle button clicked
        }
    }
}

Поскольку jQuery нормализует event.which, вам нужно использовать его только в обработчиках событий jQuery и, как таковые, делать:

$('div a').on('mousedown', function(e) {
    if (e.which === 2) {
        // middle button clicked           
    }
});

Другими словами, вы не можете использовать событие onclick, поэтому для его имитации вы можете использовать как mousedown, так и mouseup.

Вы можете добавить таймер, чтобы ограничить время, разрешенное между событием mousedown и mouseup, или даже выбросить обработчик mousemove для ограничения перемещения между событием mousedown и mouseup и сделать обработчик события не срабатывающим, если указатель мыши перемещается более десяти пикселей и т.д. возможности практически бесконечны, поэтому это не должно быть проблемой.

$('#test').on({
    mousedown: function(e) {
        if (e.which === 2) {
            $(this).data('down', true);
        }
    },
    mouseup: function(e) {
        if (e.which === 2 && $(this).data('down')) {
            alert('middle button clicked');
            $(this).data('down', false);
        }
    }
});

Ответ 2

Короткий ответ: Нет.

Вопрос в том, для чего вы хотите захватить средние клики? Средний клик не предназначен для взаимодействия с текущей страницей, а скорее для открытия ссылки на новой вкладке.

В настоящее время Chrome также работает над тем, как это сделать: https://code.google.com/p/chromium/issues/detail?id=255

И в настоящее время существует общая дискуссия по списку рассылки w3c по этой теме: http://lists.w3.org/Archives/Public/www-dom/2013JulSep/0203.html


Пока вы можете поймать middleclicks в Firefox на уровне документа:

$(document).on('click', function(e){
    console.log(e);
});