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

Я разрабатываю webapp (а не веб-сайт со страницами интересного текста) с совершенно другим интерфейсом для касания (ваш палец скрывает экран при нажатии) и мышь (в значительной степени зависит от предварительного просмотра hover). Как я могу обнаружить, что у моего пользователя нет мыши, чтобы представить ему правильный интерфейс? Я планирую оставить переключатель для людей с мышью и касанием (например, с некоторыми ноутбуками).

Функция сенсорного события в браузере фактически не означает, что пользователь использует сенсорное устройство (например, Modernizr не сокращает его). Код, который правильно отвечает на вопрос, должен возвращать значение false, если устройство имеет мышь, в противном случае - true. Для устройств с мышью и прикосновением он должен возвращать false (только не касаться)

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

Чтобы сделать необходимость более ясной, вот API, который я ищу для реализации:

// Level 1


// The current answers provide a way to do that.
hasTouch();

// Returns true if a mouse is expected.
// Note: as explained by the OP, this is not !hasTouch()
// I don't think we have this in the answers already, that why I offer a bounty
hasMouse();

// Level 2 (I don't think it possible, but maybe I'm wrong, so why not asking)

// callback is called when the result of "hasTouch()" changes.
listenHasTouchChanges(callback);

// callback is called when the result of "hasMouse()" changes.
listenHasMouseChanges(callback);

Ответ 1

Основная проблема заключается в том, что у вас есть следующие классы устройств/варианты использования:

  • Мышь и клавиатура (рабочий стол)
  • Только сенсорный (телефон/планшет)
  • Мышь, клавиатура и сенсорный экран (сенсорные ноутбуки)
  • Touch и клавиатура (клавиатура bluetooth на планшете)
  • Только мышь (отключено предпочтение пользователя/браузера)
  • Только для клавиатуры (отключено предпочтение пользователя/браузера)
  • Прикосновение и мышь (т.е. наведение событий из ручки Galaxy Note 2)

Что еще хуже, так это то, что можно перейти от некоторых из этих классов к другим (подключится к мыши, подключается к клавиатуре), или пользователь может APPEAR находиться на обычном ноутбуке, пока не достигнут и не коснется экрана.

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

Например, скажите, что вы обнаружили, что пользователь выпустил реальную mousemove (а не ложную из событий касания, см. http://www.html5rocks.com/en/mobile/touchandmouse/).

Тогда что?

Вы включаете стили hover? Вы добавляете больше кнопок?

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

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

В пулевой форме, цитируя stucox на https://github.com/Modernizr/Modernizr/issues/869#issuecomment-15264101

  • Мы хотим обнаружить наличие мыши
  • Вероятно, Ae не может обнаружить до того, как событие будет запущено.
  • Таким образом, мы обнаруживаем, что мышь использовалась в этом сеансе - это не будет сразу от загрузки страницы.
  • Мы, вероятно, также не можем обнаружить, что нет мыши - это будет undefined до true (я думаю, что это имеет больше смысла, чем установка это ложно, пока не будет доказано)
  • И мы, вероятно, не можем определить, отключена ли мышь в середине сеанса - это будет неотличимо от пользователя, просто отказавшись от своих мышь

В стороне: браузер знает, когда пользователь подключается к мыши/подключается к клавиатуре, но не подвергает ее JavaScript. dang!

Это приведет вас к следующему:

Отслеживание текущих возможностей данного пользователя является сложным, ненадежным и сомнительным достоинством

Идея прогрессивного улучшения здесь довольно неплохая. Создайте опыт, который работает плавно независимо от контекста пользователя. Затем сделайте предположения на основе функций браузера/медиа-запросов, чтобы добавить функциональность, которая будет относительной в предполагаемом контексте. Наличие мыши - всего лишь один из множества способов, которыми различные пользователи на разных устройствах используют ваш сайт. Создайте что-то с достоинством в своем ядре и не беспокойтесь о том, как люди нажимают кнопки.

Ответ 2

Как насчет прослушивания события mousemove в документе. Затем, пока вы не услышите это событие, вы не предполагаете, что устройство касается только клавиатуры или клавиатуры.

var mouseDetected = false;
function onMouseMove(e) {
  unlisten('mousemove', onMouseMove, false);
  mouseDetected = true;
  // initializeMouseBehavior();
}
listen('mousemove', onMouseMove, false);

(Где listen и unlisten делегировать на addEventListener или attachEvent по мере необходимости.)

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

Ответ 3

@Wyatt ответ велик и дает нам много о чем подумать.

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

Учитывая заданный порядок обработки событий:

  • touchstart
  • TouchMove
  • touchend
  • Наведите курсор мыши на
  • MouseMove
  • MouseDown
  • MouseUp
  • выберите

Мы можем предположить, что если событие мыши запускается до касания, это реальное событие мыши, а не эмулированное. Пример (с помощью jQuery):

$(document).ready(function() {
    var $body = $('body');
    var detectMouse = function(e){
        if (e.type === 'mousedown') {
            alert('Mouse interaction!');
        }
        else if (e.type === 'touchstart') {
            alert('Touch interaction!');
        }
        // remove event bindings, so it only runs once
        $body.off('mousedown touchstart', detectMouse);
    }
    // attach both events to body
    $body.on('mousedown touchstart', detectMouse);
});

Это сработало для меня

Ответ 4

Начиная с 2018 года, существует хороший и надежный способ определить, есть ли в браузере мышь (или подобное устройство ввода): функции взаимодействия со средой CSS4, которые теперь поддерживаются практически любым современным браузером (кроме IE 11 и специальных мобильных браузеров).

W3C:

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

Смотрите следующие варианты:

    /* The primary input mechanism of the device includes a 
pointing device of limited accuracy. */
    @media (pointer: coarse) { ... }

    /* The primary input mechanism of the device 
includes an accurate pointing device. */
    @media (pointer: fine) { ... }

    /* The primary input mechanism of the 
device does not include a pointing device. */
    @media (pointer: none) { ... }

    /* Primary input mechanism system can 
       hover over elements with ease */
    @media (hover: hover) { ... }

    /* Primary input mechanism cannot hover 
       at all or cannot conveniently hover 
       (e.g., many mobile devices emulate hovering
       when the user performs an inconvenient long tap), 
       or there is no primary pointing input mechanism */
    @media (hover: none) { ... }

    /* One or more available input mechanism(s) 
       can hover over elements with ease */
    @media (any-hover: hover) { ... }


    /* One or more available input mechanism(s) cannot 
       hover (or there are no pointing input mechanisms) */
    @media (any-hover: none) { ... }

Медиа-запросы также могут быть использованы в JS:

if(window.matchMedia("(any-hover: none)").matches) {
    // do sth
}

Связанные с:

Официальный рабочий проект: https://drafts.csswg.org/mediaqueries/#mf-interaction

Поддержка браузера: https://caniuse.com/#search=media%20features

Аналогичная проблема: определить, поддерживает ли клиентское устройство состояния: hover и: focus

Ответ 5

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

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

Для обнаружения кросс-браузера с сенсорной способностью:

function hasTouch() {
    return (('ontouchstart' in window) ||       // html5 browsers
            (navigator.maxTouchPoints > 0) ||   // future IE
            (navigator.msMaxTouchPoints > 0));  // current IE10
}

Затем можно использовать это для проверки:

if (!hasTouch()) alert('Sorry, need touch!);

или выбрать, какое событие прослушать, либо:

var eventName = hasTouch() ? 'touchend' : 'click';
someElement.addEventListener(eventName , handlerFunction, false);

или использовать отдельные подходы для touch и non-touch:

if (hasTouch() === true) {
    someElement.addEventListener('touchend' , touchHandler, false);

} else {
    someElement.addEventListener('click' , mouseHandler, false);

}
function touchHandler(e) {
    /// stop event somehow
    e.stopPropagation();
    e.preventDefault();
    window.event.cancelBubble = true;
    // ...
    return false; // :-)
}
function mouseHandler(e) {
    // sorry, touch only - or - do something useful and non-restrictive for user
}

Для мыши можно определить только, используется ли мышь, а не если она существует или нет. Можно установить глобальный флаг, чтобы указать, что мышь была обнаружена с помощью использования (аналогично существующему ответу, но немного упрощена):

var hasMouse = false;

window.onmousemove = function() {
    hasMouse = true;
}

(нельзя включать mouseup или mousedown, так как это событие также может срабатывать при нажатии)

Браузеры ограничивают доступ к низкоуровневым системным API, которые необходимы для обнаружения таких функций, как аппаратные возможности используемой системы.

Существует возможность, возможно, написать плагин/расширение для доступа к ним, но с помощью JavaScript и DOM такое обнаружение ограничено для этой цели, и нужно будет написать плагин, определенный для различных платформ ОС.

Итак, в заключение: такое обнаружение может быть оценено только "хорошей догадкой".

Ответ 6

Когда "Медиа-запросы уровня 4" доступны в браузерах, мы сможем использовать "указатель" и "навести" запросы для обнаружения устройств с помощью мыши.

Если мы действительно хотим передать эту информацию в Javascript, мы могли бы использовать запрос CSS для установки определенных стилей в соответствии с типом устройства, а затем использовать getComputedStyle в Javascript для чтения этого стиля и получить исходный тип устройства из он.

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

Ответ 7

Поскольку вы планируете предлагать способ переключения между интерфейсами в любом случае, было бы просто попросить пользователя нажать ссылку или кнопку на "enter" правильную версию приложения? Тогда вы могли бы помнить свое предпочтение будущим посещениям. Это не высокотехнологичный, но он на 100% надежный: -)

Ответ 8

@SamuelRossille. К сожалению, браузеры, о которых я не знаю, могут обнаружить (или их отсутствие) мышь.

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

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

//namespace
window.ns = {};

// for starters, we'll briefly assume if touch exists, they are using it - default behavior
ns.usingTouch = ko.observable(Modernizr.touch); //using Modernizr here for brevity.  Substitute any touch detection method you desire

// now, let sort out the mouse
ns.usingMouse = ko.computed(function () {
    //touch
    if (ns.usingTouch()) {
        //first, kill the base mousemove event
        //I really wish browsers would stop trying to handle this within touch events in the first place
        window.document.body.addEventListener('mousemove', function (e) {
            e.preventDefault();
            e.stopImmediatePropagation();
        }, true);

        //remove mouse class from body
        $('body').removeClass("mouse");

        //switch off touch listener
        $(document).off(".ns-touch");

        // switch on a mouse listener
        $(document).on('mousemove.ns-mouse', function (e) {
            if (Math.abs(window.lastX - e.clientX) > 0 || window.lastY !== e.clientY) {
                ns.usingTouch(false);  //this will trigger re-evaluation of ns.usingMouse() and result in ns.usingMouse() === true
            }
        });

        return false;
    }
    //mouse
    else {
        //add mouse class to body for styling
        $('body').addClass("mouse");

        //switch off mouse listener
        $(document).off(".ns-mouse");

        //switch on a touch listener
        $(document).on('touchstart.ns-touch', function () { ns.usingTouch(true) });

        return true;
    }
});

//tests:
//ns.usingMouse()
//$('body').hasClass('mouse');

Теперь вы можете связывать/подписываться на использованиеMouse() и usingTouch() и/или стилизовать свой интерфейс с помощью класса body.mouse, Интерфейс будет переключаться назад и вперед, как только будет обнаружен курсор мыши и на сенсорном экране.

Надеюсь, у нас скоро появятся лучшие варианты поставщиков браузеров.

Ответ 9

Tera-WURFL может рассказать вам о возможностях устройства, посещающего ваш сайт, сравнивая подпись браузера с его базой данных. Дайте ему посмотреть, бесплатно!

Ответ 10

Почему бы вам просто не определить, есть ли у него способность ощущать прикосновения и/или реагировать на движения мыши?

// This will also return false on
// touch-enabled browsers like Chrome
function has_touch() {
  return !!('ontouchstart' in window);
}

function has_mouse() {
  return !!('onmousemove' in window);
}

Ответ 11

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

var mousedown = false;
var mousemovecount = 0;
function onMouseDown(e){
    mousemovecount = 0;
    mousedown = true;
}
function onMouseUp(e){
    mousedown = false;
    mousemovecount = 0;
}
function onMouseMove(e) {
    if(!mousedown) {
        mousemovecount++;
        if(mousemovecount > 5){
            window.removeEventListener('mousemove', onMouseMove, false);
            console.log("mouse moved");
            $('body').addClass('has-mouse');
        }
    } else {
        mousemovecount = 0;
    }
}
window.addEventListener('mousemove', onMouseMove, false);
window.addEventListener('mousedown', onMouseDown, false);
window.addEventListener('mouseup', onMouseUp, false);

Ответ 12

Основная проблема, которую я вижу здесь, заключается в том, что большинство сенсорных устройств запускают событие мыши вместе с соответствующим сенсорным касанием (touchstart → mousedown, touchmove → mousemove и т.д.). Для клавиатуры только одни, наконец, для современных, у них есть общий браузер, поэтому вы даже не можете обнаружить присутствие класса MouseEvent.

Менее болезненным решением было бы, по-моему, отобразить меню при запуске (с управлением "alt" только для пользователей с клавиатурой) и, возможно, сохранить выбор с помощью localStorage/cookies/serverside или сохранить салм выбор в следующий раз, когда посетитель придет.

Ответ 14

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

Коснитесь событий и событий мыши исключительны. Таким образом, это может несколько помочь в принятии различных действий. Проблема заключается в том, что события касания ближе к событиям мыши вверх/вниз/перемещения, а также запускают событие щелчка.

Из вашего вопроса вы говорите, что хотите иметь зависание для предварительного просмотра. Кроме того, я не знаю других особенностей вашего интерфейса. Я предполагаю, что с отсутствием мыши вы хотите прослушивать, пока клик делает другое действие из-за предварительного просмотра hover.

Если это так, вы можете сделать несколько ленивый подход к обнаружению:

Событию onclick всегда будет предшествовать событие onmouseover с помощью мыши. Поэтому обратите внимание, что мышь находится над элементом, который был нажат.

Вы можете сделать это с помощью события onmousemove для всего документа. Вы можете использовать event.target для записи того элемента, на котором находится мышь. Затем внутри ваших событий onclick вы можете проверить, действительно ли мышь над щелчком элемента (или дочерним элементом этого элемента).

Оттуда вы можете выбрать либо полагаться на событие click для обоих, либо выполнить действие A или B в зависимости от результата. Действие B может быть ничем, если некоторые сенсорные устройства не выдают событие щелчка (вместо этого вам придется полагаться на события ontouch *).

Ответ 15

Я не считаю возможным идентифицировать сенсорное устройство (насколько мне известно). Основная проблема заключается в том, что все мыши и клавиатурные события запускаются сенсорными устройствами. См. Следующий пример: оба предупреждения возвращают true для сенсорных устройств.

function is_touch_present() {
  return ('ontouchstart' in window) || ('onmsgesturechange' in window);
}

function is_mouse_present() {
  return (('onmousedown' in window) && ('onmouseup' in window) && ('onmousemove' in window) && ('onclick' in window) && ('ondblclick' in window) && ('onmousemove' in window) && ('onmouseover' in window) && ('onmouseout' in window) && ('oncontextmenu' in window));
}

alert("Touch Present: " + is_touch_present());
alert("Mouse Present: " + is_mouse_present());

Ответ 16

Лучшей идеей, на мой взгляд, является слушатель mousemove (в настоящее время главный ответ). Я считаю, что этот метод нужно немного подкорректировать. Это правда, что сенсорные браузеры эмулируют даже событие mousemove, как вы можете видеть в это обсуждение iOS, поэтому мы должны быть осторожны.

Имеет смысл, что сенсорные браузеры будут эмулировать это событие только тогда, когда пользователь удаляет экран (палец пользователя не работает). Это означает, что мы должны добавить тест во время нашего обработчика mousemove, чтобы увидеть, какая кнопка мыши недоступна (если есть) во время события. Если кнопка мыши не нажата, мы можем с уверенностью предположить, что настоящая мышь присутствует. Если кнопка мыши не работает, тест остается неубедительным.

Итак, как это будет реализовано? Этот question показывает, что самый надежный метод проверки того, какая кнопка мыши отключена во время mousemove, - это фактически прослушать 3 события на уровне документа: mousemove, mousedown и mouseup, В верхней и нижней частях будет установлен только глобальный логический флаг. Этот шаг выполнит тест. Если у вас есть движение и логическое значение false, мы можем предположить, что мышь присутствует. См. Вопрос для точных примеров кода.

Один последний комментарий. Этот тест не идеален, потому что он не может быть выполнен во время загрузки. Поэтому я бы использовал метод прогрессивного улучшения, как было предложено ранее. По умолчанию отображается версия, которая не поддерживает интерфейс зависания мыши. Если мышь обнаружена, включите этот режим во время выполнения с помощью JS. Это должно выглядеть как можно проще для пользователя.

Чтобы поддерживать изменения в пользовательской конфигурации (т.е. мышь была отключена), вы можете периодически повторять проверку. Хотя я считаю, что в этом случае будет лучше просто уведомить пользователя о двух режимах и позволить пользователям вручную переключаться между ними (как и выбор мобильного/настольного ПК, который всегда можно изменить).

Ответ 17

Проведите несколько тестов на разных ПК, Linux, iPhone, телефонах Android и вкладках. Странно, что нет простого пуленепробиваемого решения. Проблема возникает, когда некоторые, у которых есть Touch, и никакая мышь по-прежнему не присутствуют в приложении события Touch и Mouse. Поскольку вы хотите поддерживать только мыши, а также только для сенсорных экземпляров, вы хотите обработать их, но это вызывает двойное появление пользовательских взаимодействий. Если может знать, что мышь отсутствует на устройстве, то может знать, что игнорировать поддельные/вставленные события мыши. Пробовал флаг установки, если MouseMove встречается, но некоторые браузеры бросают поддельные MouseMove, а также MouseUp и MouseDown. Пробовал проверять временные метки, но считал, что это слишком рискованно. Итог: я обнаружил, что браузеры, создавшие фальшивые события мыши, всегда вставляли один MouseMove непосредственно перед вставленным MouseDown. В 99,99% моих случаев, когда вы работаете в системе с реальной мышью, есть несколько последовательных событий MouseMove - как минимум два. Итак, отслеживайте, сталкивается ли система с двумя последовательными событиями MouseMove и объявляет, что при условии, что это условие никогда не выполняется, нет мыши. Это, наверное, слишком просто, но он работает над всеми моими тестовыми настройками. Думаю, я буду придерживаться этого, пока не найду лучшее решение. - Джим W

Ответ 18

Простое решение в jQuery для обнаружения использования мыши, которое решает проблему, когда мобильные устройства также запускают событие mousemove. Просто добавьте слушателя touchstart, чтобы удалить прослушиватель mousemove, чтобы он не срабатывал при касании.

$('body').one('touchstart.test', function(e) {
  // Remove the mousemove listener for touch devices
  $('body').off('mousemove.test');
}).one('mousemove.test', function(e) {
  // MOUSE!
});

Конечно, устройство все еще может касаться мыши и мыши, но вышеупомянутое гарантирует, что используется настоящая мышь.

Ответ 19

Просто нашел решение, которое я считаю довольно элегантным.

// flag as mouse interaction by default
var isMouse = true;

// detect a touch event start and flag it
$(window).on('touchstart', function () {
  // if triggers touchstart, toggle flag
  // since touch events come before mouse event / click
  // callback of mouse event will get in callback
  // `isMouse === false`
  isMouse = false;
});

// now the code that you want to write
// should also work with `mouse*` events
$('a.someClass').on('click', function () {
  if (isMouse) {
    // interaction with mouse event
    // ...
  } else {
    // reset for the next event detection
    // this is crucial for devices that have both
    // touch screen and mouse
    isMouse = true;

    // interaction with touch event
    // ...
  }
});

Ответ 20

Я столкнулся с той же самой проблемой, где одно касание было также зарегистрировано как щелчок. После того, как я прочитал комментарии самых популярных ответов, я нашел собственное решение:

var body = document.getElementsByTagName('body')[0];
var mouseCount = 0;

// start in an undefined state 
// (i use this to blend in elements once we decide what input is used)
var interactionMode = 'undefined';


var registerMouse = function() {
  // count up mouseCount every time, the mousemove event is triggered
  mouseCount++;

  // but dont set it instantly. 
  // instead wait 20 miliseconds (seems to be a good value for multiple move actions), 
  // if another mousemove event accoures switch to mouse as interaction 
  setTimeout(function() {
    // a touch event triggers also exactly 1 mouse move event.
    // So only if mouseCount is higher than 1 we are really moving the cursor by mouse.
    if (mouseCount > 1) {
      body.removeEventListener('mousemove', registerMouse);
      body.removeEventListener('touchend', registerTouch);

      interactionMode = 'mouse';
      console.log('now mousing');
      listenTouch();
    }

    // set the counter to zero again
    mouseCount = 0;
  }, 20);
};

var registerTouch = function() {
  body.removeEventListener('mousemove', registerMouse);
  body.removeEventListener('touchend', registerTouch);

  interactionMode = 'touch';
  console.log('now touching');
  mouseCount = 0;

  listenMouse();
};

var listenMouse = function() {
  body.addEventListener("mousemove", registerMouse);
};
var listenTouch = function() {
  body.addEventListener("touchend", registerTouch);
};

listenMouse();
listenTouch();

// after one second without input, assume, that we are touching
// could be adjusted to several seconds or deleted
// without this, the interactionMode would stay 'undefined' until first mouse or touch event
setTimeout(function() {
  if (!body.classList.contains('mousing') || body.classList.contains('touching')) {
    registerTouch();
  }
}, 1000);
/* fix, so that scrolling is possible */

html,
body {
  height: 110%;
}
Mouse or touch me

Ответ 21

Я часами разбирался с этой проблемой для своего приложения Phonegap и придумал этот хак. Он генерирует консольное предупреждение, если вызванное событие является "пассивным" событием, то есть оно не вызывает никаких изменений, но работает! Я был бы заинтересован в любых идеях для улучшения или лучшего метода. Но это эффективно позволяет мне использовать $.touch() повсеместно.

$(document).ready(function(){
  $("#aButton").touch(function(origElement, origEvent){
    console.log('Original target ID: ' + $(origEvent.target).attr('id'));
  });
});

$.fn.touch = function (callback) {
    var touch = false;
    $(this).on("click", function(e){
        if (!touch)
        {
            console.log("I click!");
            let callbackReal = callback.bind(this);
            callbackReal(this, e);
        }else{
            touch = true;
        }
        touch = false;
    });
    $(this).on("touchstart", function(e){
        if (typeof e.touches != typeof undefined)
        {
            e.preventDefault();
            touch = true;
            console.log("I touch!");
            let callbackReal = callback.bind(this);
            callbackReal(this, e);
        }
    });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<button id="aButton">A Button</button>

Ответ 22

Я бы настоятельно рекомендовал против такого подхода. Рассмотрим сенсорные экраны, устройства размером с настольный компьютер, и у вас есть другой набор проблем для решения.

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

Ответ 23

Хотел бы рекомендовать script, который помог мне:

Я прочитал и попробовал все, что было предложено, без достаточных результатов.

Затем я исследовал еще несколько и нашел этот код - device.js

Я использую это на своем клиентском веб-сайте, чтобы обнаружить существование мыши:
(<html> должен иметь класс desktop), и это выглядит довольно хорошо, а для поддержки touch я просто выполняю регулярную проверку 'ontouchend' in document и использую информацию из обоих детектировок, чтобы принять конкретную вещь, в которой я нуждаюсь.

Ответ 24

Как правило, лучше понять, поддерживает ли функция мыши, а не обнаруживает тип ОС/браузера. Вы можете сделать это просто следующим образом:

if (element.mouseover) {
    //Supports the mouseover event
}

Убедитесь, что не выполните следующие действия:

if (element.mouseover()) {
    // Supports the mouseover event
}

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

Вы можете прочитать больше здесь: http://www.quirksmode.org/js/support.html