Я ранее написал о шаблоне для этого.
Он очень похож на решение, предложенное Pascal, хотя он перемещает все такие зависимости в выделенный репозиторий модуль, чтобы вам не пришлось повторять его везде, где используется зависимость, если это сборка с несколькими модулями.
Обновление: прочитайте ответ blmstr ниже, прежде чем использовать целую библиотеку обнаружения объектов в своем проекте. Обнаружение фактической поддержки касания является более сложным, и Modernizr охватывает только базовый вариант использования.
Modernizr - отличный, легкий способ сделать все виды обнаружения функций на любом сайте.
Он просто добавляет классы к элементу html для каждой функции.
Затем вы можете легко настроить эти функции в CSS и JS. Например:
html.touch div {
width: 480px;
}
html.no-touch div {
width: auto;
}
И Javascript (пример jQuery):
$('html.touch #popup').hide();
Я также много боролся с различными вариантами того, как определить в Javascript, отображается ли страница на устройстве с сенсорным экраном или нет. ИМО, на данный момент не существует никакой реальной возможности правильно ее определить. Браузеры либо сообщают о событиях касания на настольных компьютерах (поскольку ОС может быть готова к касанию), либо некоторые решения работают не на всех мобильных устройствах.
В конце я понял, что с самого начала придерживался неправильного подхода: если бы моя страница выглядела одинаково на сенсорных и не сенсорных устройствах, мне, возможно, не пришлось бы вообще беспокоиться об обнаружении свойства: Мой сценарий состоял в том, чтобы деактивировать всплывающие подсказки над кнопками на сенсорных устройствах, поскольку они приводили к двойному нажатию, когда я хотел одним нажатием активировать кнопку.
Мое решение заключалось в рефакторинге вида, чтобы не требовалось всплывающей подсказки над кнопкой, и в итоге мне не нужно было обнаруживать сенсорное устройство из Javascript с помощью методов, которые все имеют их недостатки .
Вы можете установить модернизатор и использовать простое сенсорное событие. Это очень эффективно и работает на каждом устройстве, на котором я его тестировал, включая поверхность Windows!
Я создал jsFiddle
function isTouchDevice(){
if(Modernizr.hasEvent('touchstart') || navigator.userAgent.search(/Touch/i) != -1){
alert("is touch");
return true;
}else{
alert("is not touch");
return false;
}
}
Практическим ответом является тот, который учитывает контекст:
1) Публичный сайт (без входа в систему)
Код пользовательского интерфейса для совместной работы с обоими параметрами .
2) Сайт входа
Захватите, произошло ли движение мыши в форме входа, и сохраните это в скрытом вводе. Значение передается с учетными данными для входа в систему и добавляется в сеанс пользователя , поэтому его можно использовать на время сеанса.
Jquery для добавления только на страницу входа:
$('#istouch').val(1); // <-- value will be submitted with login form
if (window.addEventListener) {
window.addEventListener('mousemove', function mouseMoveListener(){
// Update hidden input value to false, and stop listening
$('#istouch').val(0);
window.removeEventListener('mousemove', mouseMoveListener);
});
}
(от + 1 до @Dave Burt и от +1 до @Martin Lantzsch в ответах)
Это, кажется, работает хорошо для меня до сих пор:
//Checks if a touch screen
is_touch_screen = 'ontouchstart' in document.documentElement;
if (is_touch_screen) {
// Do something if a touch screen
}
else {
// Not a touch screen (i.e. desktop)
}
Экстент jQuery support
объект:
jQuery.support.touch = 'ontouchend' in document;
И теперь вы можете проверить его где угодно, например:
if( jQuery.support.touch )
// do touch stuff
Вы можете использовать следующий код:
function isTouchDevice() {
var el = document.createElement('div');
el.setAttribute('ongesturestart', 'return;'); // or try "ontouchstart"
return typeof el.ongesturestart === "function";
}
Источник: Обнаружение сенсорного просмотра и @mplungjan post .
Вышеупомянутое решение было основано на обнаружении поддержки событий без перехвата браузера статья.
Вы можете проверить результаты на следующей тестовой странице .
Обратите внимание, что приведенный выше код проверяет только наличие поддержки сенсорного экрана в браузере, а не на устройстве. Так что если у вас ноутбук с сенсорным экраном, ваш браузер может не иметь поддержки сенсорных событий. Недавний Chrome поддерживает сенсорные события , но другой браузер может этого не делать.
Вы также можете попробовать:
if (document.documentElement.ontouchmove) {
// ...
}
, но это может не работать на устройствах iPhone.
var isTouchDevice =
(('ontouchstart' in window) ||
(navigator.MaxTouchPoints > 0) ||
(navigator.msMaxTouchPoints > 0));
if(!isTouchDevice){
/* Code for touch device /*
}else{
/* Code for non touch device */
}
Веселись!
этот способ работает для меня, он ждет первого взаимодействия с пользователем, чтобы убедиться, что они на сенсорных устройствах
var touchEnabled = false;
$(document.body).one('touchstart',
function(e){
touchEnabled=true;
$(document.documentElement).addClass("touch");
// other touch related init
//
}
);
Мне нравится этот:
function isTouchDevice(){
return typeof window.ontouchstart !== 'undefined';
}
alert(isTouchDevice());
Используя все комментарии выше, я собрал следующий код, который работает для моих нужд:
var isTouch = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0));
Я протестировал это на iPad, Android (браузер и Chrome), Blackberry Playbook, iPhone 4s , Windows Phone 8, IE 10, IE 8, IE 10 (Windows 8 с сенсорным экраном), Opera, Chrome и Firefox.
В настоящее время происходит сбой на Windows Phone 7, и я пока не смог найти решение для этого браузера.
Надеюсь, кто-то найдет это полезным.
Я использую:
if(jQuery.support.touch){
alert('Touch enabled');
}
в jQuery mobile 1.0.1
Если вы используете Modernizr , очень просто использовать Modernizr.touch
, как упоминалось ранее.
Однако я предпочитаю использовать комбинацию Modernizr.touch
и тестирование пользовательского агента, просто чтобы быть в безопасности.
var deviceAgent = navigator.userAgent.toLowerCase();
var isTouchDevice = Modernizr.touch ||
(deviceAgent.match(/(iphone|ipod|ipad)/) ||
deviceAgent.match(/(android)/) ||
deviceAgent.match(/(iemobile)/) ||
deviceAgent.match(/iphone/i) ||
deviceAgent.match(/ipad/i) ||
deviceAgent.match(/ipod/i) ||
deviceAgent.match(/blackberry/i) ||
deviceAgent.match(/bada/i));
if (isTouchDevice) {
//Do something touchy
} else {
//Can't touch this
}
Если вы не используете Modernizr, вы можете просто заменить приведенную выше функцию Modernizr.touch
на ('ontouchstart' in document.documentElement)
Также обратите внимание, что тестирование пользовательского агента iemobile
даст вам более широкий диапазон обнаружил мобильные устройства Microsoft, чем Windows Phone
.
Краткое примечание для тех, у кого может возникнуть желание написать window.ontouchstart !== undefined
->, пожалуйста, используйте micnic ответ, поскольку undefined
не является ключевым словом в JavaScript. Большая проблема, если разработка пишет что-то вроде:
undefined = window.ontouchstart;
Разработчик может сделать неопределенным все, что он хочет, и вы также можете проверить, если window.ontouchstart = myNonExistingWord;
Нет неуважения к тем, кто дал этот ответ: Я уверен, что я написал это и в моем коде;)
Я добился этого вот так;
function isTouchDevice(){
return true == ("ontouchstart" in window || window.DocumentTouch && document instanceof DocumentTouch);
}
if(isTouchDevice()===true) {
alert('Touch Device'); //your logic for touch device
}
else {
alert('Not a Touch Device'); //your logic for non touch device
}
Посмотрите этот пост , он дает действительно хороший фрагмент кода для того, что делать при обнаружении сенсорных устройств или что делать, если вызывается событие сенсорного запуска:
$(function(){
if(window.Touch) {
touch_detect.auto_detected();
} else {
document.ontouchstart = touch_detect.surface;
}
}); // End loaded jQuery
var touch_detect = {
auto_detected: function(event){
/* add everything you want to do onLoad here (eg. activating hover controls) */
alert('this was auto detected');
activateTouchArea();
},
surface: function(event){
/* add everything you want to do ontouchstart here (eg. drag & drop) - you can fire this in both places */
alert('this was detected by touching');
activateTouchArea();
}
}; // touch_detect
function activateTouchArea(){
/* make sure our screen doesn't scroll when we move the "touchable area" */
var element = document.getElementById('element_id');
element.addEventListener("touchstart", touchStart, false);
}
function touchStart(event) {
/* modularize preventing the default behavior so we can use it again */
event.preventDefault();
}
С момента появления интерактивных медиа-функций вы просто можете сделать:
if(window.matchMedia("(any-pointer: coarse)").matches) {
// touchscreen
}
https://www.w3.org/TR / mediaqueries-4 / # descdef-медиа-любой-указатель
var isTouchScreen = 'createTouch' in document;
или
var isTouchScreen = 'createTouch' in document || screen.width <= 699 ||
ua.match(/(iPhone|iPod|iPad)/) || ua.match(/BlackBerry/) ||
ua.match(/Android/);
было бы более тщательной проверкой, я полагаю.
Поскольку Modernizr не обнаруживает IE10 в Windows Phone 8 / WinRT, простое кросс-браузерное решение выглядит следующим образом:
var supportsTouch = 'ontouchstart' in window || navigator.msMaxTouchPoints;
Вам нужно проверять только один раз, так как устройство не будет внезапно поддерживать или не поддерживает касание, поэтому просто сохраните его в переменной, чтобы вы могли использовать его несколько раз более эффективно.
Хотя это только альфа-версия, jquery mobile Framework стоит проверить. Это нормализует эти типы событий в мобильных браузерах. Возможно, посмотрите, что они делают. Я предполагаю, что jquery-mobile.js отличается от этого фреймворка.
Похоже, что Chrome 24 теперь поддерживает сенсорные события, вероятно, для Windows 8. Поэтому код, размещенный здесь, больше не работает. Вместо того, чтобы пытаться определить, поддерживается ли касание браузером, я теперь связываю события касания и щелчка и проверяю, вызывается ли только одно:
myCustomBind = function(controlName, callback) {
$(controlName).bind('touchend click', function(e) {
e.stopPropagation();
e.preventDefault();
callback.call();
});
};
И затем вызываю его:
myCustomBind('#mnuRealtime', function () { ... });
Надеюсь, это поможет!
Этот работает хорошо даже в планшетах Windows Surface !!!
function detectTouchSupport {
msGesture = window.navigator && window.navigator.msPointerEnabled && window.MSGesture,
touchSupport = (( "ontouchstart" in window ) || msGesture || window.DocumentTouch && document instanceof DocumentTouch);
if(touchSupport) {
$("html").addClass("ci_touch");
}
else {
$("html").addClass("ci_no_touch");
}
}
Когда мышь присоединена, можно предположить с довольно высокой скоростью (я бы сказал, практически 100%), что пользователь перемещает мышь по крайней мере на небольшое расстояние после того, как страница готова - без какого-либо щелчка. Механизм ниже обнаруживает это. В случае обнаружения я рассматриваю это как признак отсутствия поддержки касания или, если поддерживается, незначительной важности при использовании мыши. Предполагается, что сенсорное устройство не обнаружено.
РЕДАКТИРОВАТЬ Этот подход может не подходить для всех целей. Он может использоваться для управления функциональностью, которая активируется на основе взаимодействия с пользователем на загруженной странице, например, в программе просмотра изображений. Приведенный ниже код также оставит событие mousemove привязанным к устройствам без мыши, как сейчас. Другие подходы могут быть лучше.
Грубо говоря, это выглядит так (извините за jQuery, но похоже на чистый Javascript):
var mousedown, first, second = false;
var ticks = 10;
$(document).on('mousemove', (function(e) {
if(UI.mousechecked) return;
if(!first) {
first = e.pageX;
return;
}
if(!second && ticks-- === 0) {
second = e.pageX;
$(document).off('mousemove'); // or bind it to somewhat else
}
if(first && second && first !== second && !mousedown){
// set whatever flags you want
UI.hasmouse = true;
UI.touch = false;
UI.mousechecked = true;
}
return;
}));
$(document).one('mousedown', (function(e) {
mousedown = true;
return;
}));
$(document).one('mouseup', (function(e) {
mousedown = false;
return;
}));
Вы пытались использовать эту функцию? (Это то же самое, что использовал Modernizr.)
function is_touch_device() {
try {
document.createEvent("TouchEvent");
return true;
} catch (e) {
return false;
}
}
ОБНОВЛЕНИЕ 1
document.createEvent("TouchEvent")
начали возвращать true
в последнем хроме ( ст. 17). Modernizr обновил это некоторое время назад. Проверьте тест Модернизра здесь .
Обновите вашу функцию так, чтобы она работала:
function is_touch_device() {
return 'ontouchstart' in window;
}
ОБНОВЛЕНИЕ 2
Я обнаружил, что вышеупомянутое не работает на IE10 (возвращает false на поверхности MS). Вот исправление:
function is_touch_device() {
return 'ontouchstart' in window // works on most browsers
|| 'onmsgesturechange' in window; // works on IE10 with some false positives
};
ОБНОВЛЕНИЕ 3
'onmsgesturechange' in window
вернет true в некоторых версиях IE для настольных ПК, так что это ненадежно. Это работает несколько надежнее:
function is_touch_device() {
return 'ontouchstart' in window // works on most browsers
|| navigator.maxTouchPoints; // works on IE10/11 and Surface
};
ОБНОВЛЕНИЕ 2018
Время идет, и есть новые и лучшие способы проверить это. Я в основном извлек и упростил способ проверки Modernizr'а:
function is_touch_device() {
var prefixes = ' -webkit- -moz- -o- -ms- '.split(' ');
var mq = function(query) {
return window.matchMedia(query).matches;
}
if (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
return true;
}
// include the 'heartz' as a way to have a non matching MQ to help terminate the join
// https://git.io/vznFH
var query = ['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join('');
return mq(query);
}
Здесь они используют нестандартную touch-enabled
функцию медиазапроса, что, на мой взгляд, является странной и плохой практикой. Но эй, в реальном мире, я думаю, это работает. В будущем (когда они поддерживаются всеми) эти функции медиазапроса могут дать вам те же результаты: pointer
и hover
.
Проверьте источник того, как Модернизр делает это .
Хорошую статью, в которой объясняются проблемы с обнаружением касания, см. В Stu Cox: вы не можете обнаружить сенсорный экран .
Я бы не использовал ширину экрана, чтобы определить, является ли устройство сенсорным. Существуют сенсорные экраны, намного большие, чем 699 пикселей, подумайте о Windows 8. Navigatior.userAgent может быть хорошим, чтобы переопределить ложные предположения.
Я бы порекомендовал проверить этот вопрос на Modernizr.
Вы хотите проверить, поддерживает ли устройство сенсорные события или является сенсорным устройством. К сожалению, это не одно и то же.
Из-за гибридных устройств, которые используют комбинацию сенсорного и мышиного ввода, вы должны иметь возможность динамически изменять состояние / переменную, которая контролирует, должен ли фрагмент кода запускать, если пользователь сенсорный или нет.
Сенсорные устройства также запускают mousemove
при нажатии.
touchstart
, затем установите для него значение true. Протестировано на Safari iOS и Chrome для Android.
Примечание: не уверен на 100% в событиях указателя для MS Surface и т. Д.
<час>const supportsTouch = 'ontouchstart' in window;
let isUsingTouch = false;
// `touchstart`, `pointerdown`
const touchHandler = () => {
isUsingTouch = true;
document.addEventListener('mousemove', mousemoveHandler);
};
// use a simple closure to store previous time as internal state
const mousemoveHandler = (() => {
let time;
return () => {
const now = performance.now();
if (now - time < 20) {
isUsingTouch = false;
document.removeEventListener('mousemove', mousemoveHandler);
}
time = now;
}
})();
// add listeners
if (supportsTouch) {
document.addEventListener('touchstart', touchHandler);
} else if (navigator.maxTouchPoints || navigator.msMaxTouchPoints) {
document.addEventListener('pointerdown', touchHandler);
}
Многие из них работают, но либо требуют jQuery, либо строчки javascript жалуются на синтаксис. Учитывая, что ваш первоначальный вопрос требует "JavaScript" (не jQuery, не Modernizr) способа решения этой проблемы, вот простая функция, которая работает каждый раз. Это также как можно меньше.
function isTouchDevice() {
return !!window.ontouchstart;
}
console.log(isTouchDevice());
Еще одно преимущество, которое я упомяну, заключается в том, что этот код не зависит от инфраструктуры и устройств. Наслаждайтесь!
Я использовал фрагменты кода выше, чтобы определить, есть ли касание, поэтому мои фреймворки в fancybox будут отображаться на настольных компьютерах, а не на ощупь. Я заметил, что Opera Mini для Android 4.0 все еще регистрировалась как устройство без сенсорного ввода, когда использовался только код blmstr. (Кто-нибудь знает почему?)
Я закончил тем, что использовал:
<script>
$(document).ready(function() {
var ua = navigator.userAgent;
function is_touch_device() {
try {
document.createEvent("TouchEvent");
return true;
} catch (e) {
return false;
}
}
if ((is_touch_device()) || ua.match(/(iPhone|iPod|iPad)/)
|| ua.match(/BlackBerry/) || ua.match(/Android/)) {
// Touch browser
} else {
// Lightbox code
}
});
</script>
Есть что-то лучше, чем проверить, есть ли у них сенсорный экран, это проверить, используют ли они его, плюс это легче проверить.
if (window.addEventListener) {
var once = false;
window.addEventListener('touchstart', function(){
if (!once) {
once = true;
// Do what you need for touch-screens only
}
});
}