Как определить, поддерживает ли устройство поддержку мыши?

В настоящее время я использую следующий тест (снятый с Modernizr) для обнаружения поддержки касания:

function is_touch_device() {
    var bool;
    if(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
        bool = true;
    } else {
        injectElementWithStyles(['@media (',prefixes.join('touch-enabled),('),mod,')','{#modernizr{top:9px;position:absolute}}'].join(''), function(node) {
            bool = node.offsetTop === 9;
        });
    }
    return bool;
}

Но некоторые устройства управляются прикосновением и мышью, поэтому я хочу, чтобы отдельная функция обнаруживала, поддерживает ли устройство поддержку мыши. Какой хороший способ сделать эту проверку?

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

if(is_touch_device())

if(has_mouse_support())

if(is_touch_device() && has_mouse_support())

Ответ 1

Там CSS-медиа только для этого!

Вы можете проверить, есть ли на каком-либо устройстве мышь, получив значение pointer CSS media media:

if (matchMedia('(pointer:fine)').matches) {
  // Device has a mouse
}

Поскольку это CSS, вам даже не нужно использовать JavaScript:

@media (pointer: fine) {
  /* Rules for devices with mouse here */
}

Ответ 2

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

$(window).bind('mousemove.hasMouse',function(){
    $(window).unbind('.hasMouse');
    agent.hasMouse=true;
}).bind('touchstart.hasMouse',function(){
    $(window).unbind('.hasMouse');
    agent.hasMouse=false;
});

Объяснение: Мышиные устройства (также ноутбуки с сенсорным экраном) сначала запускают mousemove, прежде чем они смогут запускать touchstart, а hasMouse - TRUE. Сенсорные устройства (также, например, iOS, который запускает mousemove) FIRST fire touchstart при щелчке, а затем mousemove. Тогда почему hasMouse будет установлен в FALSE.

Единственный улов в том, что это зависит от взаимодействия с пользователем, значение будет правильным только после перемещения мыши или сенсорного экрана, поэтому нельзя надеяться на использование при загрузке страницы.

Ответ 4

var clickHandler = (isMouseEventSupported('click') ? 'click' : 'touchstart');

function isMouseEventSupported(eventName) {
    var element = document.createElement('div');
    eventName = 'on' + eventName;
    var isSupported = (eventName in element);
    if (!isSupported) {
       element.setAttribute(eventName, 'return;');
       isSupported = typeof element[eventName] == 'function';
    }
    element = null;
    return isSupported;
}

Это код моего друга/коллеги, и он основывал его на: http://perfectionkills.com/detecting-event-support-without-browser-sniffing/

Ответ 5

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

Предполагая, что вы хотите обнаружить либо мышь, либо коснуться, вы можете сделать следующее: прослушать touchstart и mousemove (последняя может срабатывать на сенсорных устройствах без фактической мыши). Кто бы ни стрелял первым, на 99% должен быть тем, что вы ищете.

Это не принимает учетные устройства, которые на самом деле имеют оба.

document.addEventListener('mousemove', onMouseMove, true)
document.addEventListener('touchstart', onTouchStart, true)
function onTouchStart(){
  removeListeners()
  // touch detected: do stuff
}
function onMouseMove(){
  removeListeners()
  // mouse detected: do stuff
}
function removeListeners(){
  document.removeEventListener('mousemove', onMouseMove, true)
  document.removeEventListener('touchstart', onTouchStart, true)
}

Ответ 6

Ответ от @josemmo не работает для меня: на телефоне Android с подключенной мышью matchMedia('(pointer:fine)').matches не совпадает.

К счастью, у меня получился другой медиа-запрос: hover.

if (matchMedia('(hover:hover)').matches) {
  // Device has a mouse
}