Я работаю над мобильным веб-сайтом, который должен работать на разных устройствах. В настоящий момент у меня болит голова, это BlackBerry.
Нам нужно поддерживать как нажатия клавиш, так и сенсорные события.
В идеале я бы просто использовал:
$thing.click(function(){...})
но проблема, с которой мы сталкиваемся, заключается в том, что некоторые из этих устройств Blackberry имеют очень раздражающую задержку с момента касания до того, как он запускает щелчок.
Вместо этого можно использовать Touchstart:
$thing.bind('touchstart', function(event){...})
Но как мне связать оба события, но только одно? Мне все еще нужно событие click для клавиатурных устройств, но, разумеется, я не хочу, чтобы событие click срабатывало, если я использую сенсорное устройство.
Дополнительный вопрос: есть ли возможность сделать это и дополнительно разместить браузеры, у которых даже нет события сенсорного запуска? При исследовании этого, похоже, что BlackBerry OS5 не поддерживает сенсорный запуск, поэтому для этого браузера также необходимо полагаться на события нажатия.
ДОПОЛНЕНИЕ:
Возможно, более полный вопрос:
С jQuery возможно / рекомендуется обрабатывать как прикосновения, так и взаимодействия мыши с одними и теми же привязками?
В идеале ответ - да. Если нет, у меня есть несколько вариантов:
1) Мы используем WURFL для получения информации об устройстве, чтобы создать собственную матрицу устройств. В зависимости от устройства мы будем использовать сенсорный запуск или щелчок.
2) Обнаружение сенсорной поддержки в браузере с помощью JS (мне нужно провести дополнительное исследование по этому вопросу, но кажется, что это выполнимо).
Однако это все еще оставляет одну проблему: как насчет устройств, которые поддерживают ОБА. Некоторые из поддерживаемых нами телефонов (а именно Nokias и BlackBerries) имеют сенсорные экраны и клавиатуры. Так что я снова возвращаюсь к первоначальному вопросу ... есть ли способ как-то учесть оба сразу?
.bind('touchstart mouseup')
решит это (основываясь на одном из комментариев ниже)Ответы:
Обновление : ознакомьтесь с проектом Polyfill jQuery Pointer Events, который позволяет вам связывать события «указателя» вместо выбора между мышью и касанием.
Привязать к обоим, но сделать флаг, чтобы функция срабатывает только один раз в 100 мс или около того.
источник
click
измените его наmousedown
... может быть, большая задержка - это разница междуmousedown
и тем,mouseup
какclick
определяется a .touchend
, применяя классtouched
. Это срабатывает до вызова события click. Затем я добавляю событие click, которое сначала проверяет существование этого класса. Если он есть, мы предполагаем, что сенсорные события сработали, и мы ничего не делаем с щелчком, кроме удаления имени класса, чтобы «сбросить» его для следующего взаимодействия. Если класса нет, то мы предполагаем, что они использовали клавиатуру, чтобы щелкнуть по элементу, и запустить функцию оттуда.Это исправление, которое я «создаю», оно извлекает GhostClick и реализует FastClick. Попробуйте сами и сообщите нам, сработало ли это для вас.
источник
event.handled
будет равнятьсяundefined
каждый раз, когда событие инициируется. Вот решение: установите флаг handled в самом целевом элементе, используяjQuery.data()
.event.stopPropagation();
и,event.preventDefault();
насколько я понимаю (и тестирую), событие может быть запущено только один раз. так зачем даже проверятьif(event.handled !== true)
? Для меня это не нужно или я что-то упускаю?event.handled
быть проверены на значениеtrue
? Насколько я могу сказать, это никогдаfalse
. Это начинается какundefined
, и затем вы хотите сказать, было ли это установлено вtrue
.Вы можете попробовать что-то вроде этого:
источник
Обычно это работает также:
источник
Простое добавление
return false;
в концеon("click touchstart")
функции события может решить эту проблему.Из документации по jQuery .on ()
источник
Я должен был сделать что-то подобное. Вот упрощенная версия того, что сработало для меня. Если событие касания обнаружено, удалите привязку щелчка.
В моем случае событие click было привязано к
<a>
элементу, поэтому мне пришлось удалить привязку click и повторно привязать событие click, что предотвратило действие по умолчанию для<a>
элемента.источник
Мне удалось следующим образом.
Очень просто...
источник
e
параметр вfunction()
Я считаю, что наилучшей практикой сейчас является использование:
ПРИМЕР
РЕДАКТИРОВАТЬ (2017)
С 2017 года браузеры, начиная с Chrome и делающие шаги к тому, чтобы сделать событие щелчка
.on("click")
более совместимым как для мыши, так и для касания, устраняя задержку, создаваемую событиями касания при запросах на нажатие.Это приводит к выводу, что возвращение к использованию только события click было бы самым простым решением для продвижения вперед.
Я еще не проводил кросс-браузерное тестирование, чтобы увидеть, насколько это практично.
источник
mouseup
непредсказуемые результаты, особенно при использовании трекпада вместо традиционной мыши.Как правило, вы не хотите смешивать API по умолчанию для сенсорного и не сенсорного (щелчка). Перейдя в сенсорный мир, вам будет проще работать только с сенсорными функциями. Ниже приведен псевдокод, который будет делать то, что вы хотите.
Если вы подключаетесь к событию touchmove и отслеживаете местоположения, вы можете добавить дополнительные элементы в функцию doTouchLogic для обнаружения жестов и тому подобного.
источник
проверяйте быстрые кнопки и простые клики с Google https://developers.google.com/mobile/articles/fast_buttons
источник
Ну ... Все это очень сложно.
Если у вас есть Modernizr, это не просто.
источник
Еще одна реализация для лучшего обслуживания. Тем не менее, этот метод также будет делать event.stopPropagation (). Клик не фиксируется ни на одном другом элементе, который кликал в течение 100 мс.
источник
Просто для целей документирования, вот что я сделал для самого быстрого / самого отзывчивого клика на рабочем столе / касания мобильного решения, о котором я мог подумать:
Я заменил
on
функцию jQuery на модифицированную, которая всякий раз, когда браузер поддерживает сенсорные события, заменяла все мои события клика сенсорным запуском.Использование чем было бы точно так же, как и раньше, например:
Но он будет использовать сенсорный запуск, когда доступно, нажмите, когда нет. Никаких задержек не требуется: D
источник
Мне просто пришла в голову идея запоминать, если
ontouchstart
когда-либо срабатывал. В этом случае мы находимся на устройстве, которое поддерживает его и хотим игнорироватьonclick
событие. Так какontouchstart
всегда должен запускаться раньшеonclick
, я использую это:источник
Вы можете попробовать вот так:
источник
В моем случае это работало отлично:
Основная проблема заключалась в том, что вместо того, чтобы использовать мышку, я попытался щелкнуть, на сенсорных устройствах одновременно сработали щелчок и касание. Если я использую щелчок, некоторые функции на мобильных устройствах вообще не работают. Проблема с щелчком состоит в том, что это глобальное событие, которое запускает остальную часть события, включая touchend.
источник
Это сработало для меня, мобильный телефон слушает оба, так что предотвратите тот, который является сенсорным событием. Рабочий стол только слушать мышь.
источник
Будучи для меня лучшим ответом, который дал Мотти, я просто пытаюсь сделать его код более пригодным для повторного использования, так что это мой вклад:
источник
Я также работаю над веб-приложением для Android / iPad, и кажется, что для «перемещения компонентов» достаточно использовать только «touchmove» (нет необходимости в touchstart). Отключив сенсорный запуск, вы можете использовать .click (); из jQuery. Это на самом деле работает, потому что он не был перегружен Touchstart.
Наконец, вы можете binb .live ("touchstart", function (e) {e.stopPropagation ();}); чтобы попросить событие touchstart прекратить распространение, нажмите кнопку (), чтобы вызвать событие.
Это сработало для меня.
источник
touchstart
?Есть много вещей, которые необходимо учитывать при попытке решить эту проблему. Большинство решений либо прерывают прокрутку, либо неправильно обрабатывают события призрачного щелчка.
Полное решение см. На странице https://developers.google.com/mobile/articles/fast_buttons.
NB. Вы не можете обрабатывать события призрачных щелчков для каждого элемента. Отложенный щелчок запускается в зависимости от местоположения экрана, поэтому, если ваши события касания каким-либо образом изменяют страницу, событие щелчка будет отправлено в новую версию страницы.
источник
Может быть эффективно назначать событиям
'touchstart mousedown'
или'touchend mouseup'
избегать нежелательных побочных эффектов использованияclick
.источник
Воспользовавшись тем фактом, что щелчок всегда будет следовать за событием касания, вот что я сделал, чтобы избавиться от «призрачного щелчка» без использования таймаутов или глобальных флагов.
По сути, всякий раз, когда
ontouchstart
событие срабатывает на элемент, флаг устанавливает и затем впоследствии удаляется (и игнорируется), когда происходит щелчок.источник
Почему бы не использовать jQuery Event API?
http://learn.jquery.com/events/event-extensions/
Я использовал это простое событие с успехом. Он чистый, пространственный и достаточно гибкий, чтобы его можно было улучшить.
источник
Если вы используете jQuery, для меня это сработало:
Другие решения также хороши, но я связывал несколько событий в цикле, и мне требовалась функция самовызова для создания соответствующего замыкания. Кроме того, я не хотел отключать привязку, поскольку хотел, чтобы она была доступна для вызова при следующем щелчке / прикосновении.
Может помочь кому-то в подобной ситуации!
источник
Для простых функций, просто распознать касание или нажмите Я использую следующий код:
Это вернет «touch», если определено событие touchstart, и «no touch», если нет. Как я уже сказал, это простой подход для событий щелчка / касания.
источник
Я пытаюсь это, и пока это работает (но я только на Android / PhoneGap, так что будьте бдительны)
Мне не нравится тот факт, что я перепривязываю обработчики при каждом касании, но все рассматриваемые прикосновения происходят не очень часто (в компьютерное время!)
У меня есть МНОЖЕСТВО обработчиков, подобных тому, что используется для «#keypad», поэтому, имея такую простую функцию, которая позволяет мне справиться с проблемой без лишнего кода, я пошел по этому пути.
источник
Попробуйте использовать
Virtual Mouse (vmouse) Bindings
сjQuery Mobile
. Это виртуальное событие специально для вашего случая:http://api.jquerymobile.com/vclick/
Список поддержки браузера: http://jquerymobile.com/browser-support/1.4/
источник
РЕДАКТИРОВАТЬ: Мой прежний ответ (на основе ответов в этой теме) не был путь для меня. Я хотел, чтобы подменю расширялось при щелчке мышью при вводе или касании и сворачивалось при отпускании или щелчке мышью. Поскольку события мыши обычно запускаются после событий касания, было довольно сложно написать обработчики событий, которые одновременно поддерживают ввод данных с сенсорного экрана и мыши.
Плагин jQuery: Touch Or Mouse
Я закончил тем, что написал плагин jQuery под названием « Touch Or Mouse » (минимизировано 897 байт), который может определять, было ли событие вызвано сенсорным экраном или мышью (без проверки поддержки сенсорного ввода!). Это позволяет поддержку как сенсорный экран и мышь одновременно и полностью отделить свои события.
Таким образом, OP может использовать
touchstart
илиtouchend
для быстрого реагирования на сенсорные нажатия иclick
для кликов, вызываемых только мышью.демонстрация
Сначала нужно сделать то есть. элементы тела отслеживают события касания:
Мышиные события связаны с элементами по умолчанию, и с помощью вызова
$body.touchOrMouse('get', e)
мы можем узнать, было ли событие вызвано сенсорным экраном или мышью.Смотрите плагин на работе на http://jsfiddle.net/lmeurs/uo4069nh .
объяснение
touchstart
иtouchend
событий, таким образом,touchend
событие не должно запускаться по элементу триггера (то есть по ссылке или кнопке). Между этими двумя событиями касания этот плагин считает, что любое событие мыши вызывается касанием.touchend
, как , когда событие мышиghostEventDelay
сработало в (опция, 1000 мс по умолчанию) послеtouchend
, этот плагин считает, что событие мыши вызывается прикосновением.:active
состояние.mouseleave
Событие вызывается только после того , как элемент теряет это состояние , т.е.. нажав на другой элемент. Поскольку это может быть через несколько секунд (или минут!) После того, какmouseenter
событие было запущено, этот плагин отслеживает последнееmouseenter
событие элемента : если последнееmouseenter
событие было вызвано касанием, следующееmouseleave
событие также считается вызванным касанием.источник
Вот простой способ сделать это:
Вы в основном сохраняете первый тип события, которое запускается, в свойство 'trigger' в объекте данных jQuery, который присоединен к корневому документу, и выполняете только тогда, когда тип события равен значению в 'trigger'. На сенсорных устройствах цепочка событий, скорее всего, будет «touchstart» с последующим «щелчком»; однако обработчик «щелчка» не будет выполнен, потому что «щелчок» не соответствует исходному типу события, сохраненному в «триггере» («сенсорный запуск»).
Предположение, и я считаю, что оно безопасное, состоит в том, что ваш смартфон не будет самопроизвольно переходить с сенсорного устройства на устройство мыши, иначе касание никогда не будет регистрироваться, поскольку тип события «триггер» сохраняется только один раз за загрузка страницы и «клик» никогда не будут совпадать с «touchstart».
Вот кодекс, с которым вы можете поиграть (попробуйте нажать на кнопку на сенсорном устройстве - не должно быть задержки нажатия): http://codepen.io/thdoan/pen/xVVrOZ
Я также реализовал это как простой плагин jQuery, который также поддерживает фильтрацию потомков jQuery путем передачи строки селектора:
Codepen: http://codepen.io/thdoan/pen/GZrBdo/
источник
$.data()
для хранения данных, которые могут быть доступны для нескольких функций, но не относятся к глобальной области. Плюс в том, что, поскольку я храню его в элементе, он, естественно, предоставляет мне больше контекста.Лучший метод, который я нашел, это написать событие касания и заставить это событие вызывать событие обычного щелчка программно. Таким образом, у вас есть все ваши обычные события нажатия, а затем вам нужно добавить только один обработчик событий для всех событий касания. Для каждого узла, который вы хотите сделать сенсорным, просто добавьте в него класс «сенсорный», чтобы вызвать сенсорный обработчик. С Jquery это работает так с некоторой логикой, чтобы удостовериться, что это настоящее событие касания, а не ложное срабатывание.
источник