Вариант определения мобильных устройств

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

Сразу хочу уточнить, что данная заметка к MODX особенного отношения не имеет. Это просто JS и CSS, но надеюсь, что все таки будет полезна читателям.

Конечно есть общепринятый способ это @media запросы, направленные в основном на выявление ширины окна и подстройки под это. Но лично для меня встречаются неудобные нюансы. Например 10 дюймовые планшеты имеют вполне себе такой же размер окна как и небольшие ноутбуки. При этом нужно как то понять доступно ли событие Hover или Touch.

Что же делаю я. Нашел для себя замечательную библиотеку detect.js, которая преобразует строку USER AGENT в удобный формат, например CSS классы Mobile и Desktop.

В чем суть.

Определить версию и тип браузера проще всего при помощи JavaScript, имеющий имеет стандартный объект под названием navigator, который содержит данные о браузере пользователя.

Объект navigator имеет много свойств, но в данном случае нас интересует свойство UserAgent — это строка содержит данные о браузере, операционной системе, и многое другое.

Если вы хотите увидеть значение navigator.userAgent, то можете написать следующий простейший код в вашем JS файле со скриптами.
console.log(navigator.userAgent);
Открыв консоль браузера, вы увидите примерно следующее
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
Честно говоря не понятно, каким образом можно использовать данную гигантскую строку. Но все станет проще если мы попробуем ее распарсить. В этом нам поможет библиотека Detect.js

Detect.js может разобрать значение строки в объект JavaScript для удобного восприятия человеком и последующего использования в работе.

Подключаем библиотеку и пишем несколько строк кода в нашем JS файле
//Создаем объект 'user', который будет содержать информацию Detect.js 
//Вызываем detect.parse() с navigator.userAgent в качестве аргумента
var user = detect.parse(navigator.userAgent);

// Выводим нужные значения в консоли браузера
console.log(
  user.browser.family,
  user.browser.version,
  user.os.name
)
Данный код покажет нам следующую информацию
Chrome 56 Windows 10
Как видим все стало гораздо проще и удобнее.

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

//Определение типа устройства
var user = detect.parse(navigator.userAgent);
var deviceType = user.device.type;
$('body').addClass(deviceType);
На выходе получаем
<body class="Mobile">

или

<body class="Desktop">

И с этим мы можем дальше работать используя различные стили CSS или подключая различные JS методы

Ниже приведена таблица всех анализируемых свойств:

Свойство	         Описание
browser.family	Имя браузера
browser.name	Имя браузера и его версия
browser.version	Полная версия браузер
browser.major	Основной номер версии браузера
browser.minor	Дополнительный номер версии браузера
browser.patch	Номер патча браузера
device.family	Имя устройства
device.name	Имя устройства и версия
device.version	Полная версия устройства
device.major	Основной номер версии устройства
device.major	Дополнительный номер версии устройства
device.patch	Номер патча устройства
device.type	Тип устройства (например, "Desktop" или "Mobile")
device.manufacturer	Производитель устройства
os.family	Название операционной системы
os.name	Полне имя операционной системы
os.version	Полная версия операционной системы
os.major	Основной номер версии операционной системы
os.minor	Дополнительный номер версии операционной системы
os.patch	Номер патча операционной системы

Моя заметка не претендует на уникальность, я лишь хочу поделиться собственным опытом и почитать в комментариях о Вашем опыте.
Николай Савин
16 февраля 2017, 09:39
modx.pro
17
22 977
+9
Поблагодарить автора Отправить деньги

Комментарии: 15

    Николай Савин
    16 февраля 2017, 17:10
    +1
    Посмотрел — прикольно.
    А при развороте планшета класс меняется с Landscape на Portrait или нужно перезапускать скрипт через window.resize?
      Илья Катасонов
      17 февраля 2017, 12:09
      1
      0
      Как вариант, но это не самый лучший способ, так как стандартный resize работает постоянно, и может дико просадить работу браузера. Лучше использовать window.resize, скрещенный с timeout. Проще говоря — smartresize какой-нибудь (https://github.com/louisremi/jquery-smartresize — например)

      Ну и, вкупе с device.js, конечно, modernizr не бывает лишним, на крупных проектах, требующих хорошей поддержки
    Дмитрий
    16 февраля 2017, 14:58
    0
    Большое спасибо, занятно!
      ck
      ck
      16 февраля 2017, 17:14
      +3
      Из готовых решений для MODX есть плагин MobileDetect на store.
        Илья Уткин
        17 февраля 2017, 08:18
        +2
        Да, кстати. И необязательно в нём полностью менять шаблон в зависимости от типа устройства. Можно так же заставить его лишь указать класс

        <body class="<mobile>Mobile</mobile><standard>Desktop</standard>">
          Волков Николай
          12 марта 2017, 14:21
          -1


          Не совсем понял прикола в значение класса прописывать именно в тэгах это. Можно объяснить?

          P.S. Сам уже давно через PHP определяю устройство. Удобно в плагине на OnHandleRequest в плэйсхолдер заносить тип устройства, а потом уже через тот же fenom играть с шаблоном.
          P.P.S. Для совсем крутых ребят AJAX или тот же React вообще вне конкуренции :-)
            Николай Савин
            13 марта 2017, 08:13
            0
            Давай уж с примерами тогда. Каким образом PHP определяет тип устройства?
              Волков Николай
              13 марта 2017, 08:20
              0
              Вот для примера такой код у соответствующей функции в WordPress:

              function wp_is_mobile() {
              	        if ( empty($_SERVER['HTTP_USER_AGENT']) ) {
              	                $is_mobile = false;
              	        } elseif ( strpos($_SERVER['HTTP_USER_AGENT'], 'Mobile') !== false // many mobile devices (all iPhone, iPad, etc.)
              	                || strpos($_SERVER['HTTP_USER_AGENT'], 'Android') !== false
              	                || strpos($_SERVER['HTTP_USER_AGENT'], 'Silk/') !== false
              	                || strpos($_SERVER['HTTP_USER_AGENT'], 'Kindle') !== false
              	                || strpos($_SERVER['HTTP_USER_AGENT'], 'BlackBerry') !== false
              	                || strpos($_SERVER['HTTP_USER_AGENT'], 'Opera Mini') !== false
              	                || strpos($_SERVER['HTTP_USER_AGENT'], 'Opera Mobi') !== false ) {
              	                        $is_mobile = true;
              	        } else {
              	                $is_mobile = false;
              	        }
              	
              	        return $is_mobile;
              	}
                Николай Савин
                13 марта 2017, 08:39
                0
                Да тоже самое, о чем я пишу в заметке. Только чуть проще.
                И там и там USER_AGENT парсится.
                  Волков Николай
                  13 марта 2017, 08:49
                  0
                  Ну да, оба варианта на USER_AGENT завязаны. Но все равно через PHP делать это имеет больше смысла, т.к. банально какие именно те же CSS и JS подключать еще на стороне сервера можно указывать и этим увеличить скорость загрузки мобильной версии.
          Николай Савин
          17 февраля 2017, 12:53
          +1
          Мне нравится вручную писать код, разбираясь в его архитектуре и понимая каждую используемую строчку. По этой же причине я не пользуюсь ajaxForm например, а использую свое решение, которое дополняю от проекта к проекту. Освоив процессоры я начал отказываться и от больших дополнений типа Office.
          Хотя конечно же признаю полезность готовых решений.
          Alexander V
          27 ноября 2017, 02:44
          0
          Честно говоря не знаю, где можно применить тип операционной системы и браузер, но для себя в работе я определяю тип устройства для дальнейшего использования.
          Тип ОС пригодится на сайте, где предлагается скачать приложение. Сейчас как раз такой делаю. Попробую ваш вариант.
            Дмитрий
            16 декабря 2023, 15:54
            1
            0
            Я использую простенький, но рабочий способ на JS:

            const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Windows Phone|Kindle|Silk|Opera Mini/i.test(navigator.userAgent) ? true : false;

            ну и далее используем переменную isMobile как угодно. Способ простой и не закрывает все потребности, но учитывая, что 98% посетителей сейчас — это Android или iPhone/iPad устройства — то для определения устройства посетителя этого вполне хватает.

            Вот думаю, есть ли смысл подключать MobileDetect или Detect.js, т.к. до сих пор не сталкивался с проблемами из-за такой реализации.
              Pandemic
              17 декабря 2023, 13:43
              0
              У меня такая вещь на js когда нужно что-то на фронте
              function mobileAndTabletCheck() {
              	let check = false;
              	(function(a) {
              		if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4))) check = true;
              	})(navigator.userAgent || navigator.vendor || window.opera);
              	return check;
              };
              А в модексе юзаю снипет

              <?php
              $isMobileDevice = preg_match("/(android|avantgo|blackberry|bolt|boost|cricket|docomo|fone|hiptop|mini|mobi|palm|phone|pie|tablet|up\.browser|up\.link|webos|wos)/i", $_SERVER["HTTP_USER_AGENT"]);
              if($isMobileDevice){
                  return 1;
              }
              else {
                  return 2;
              }
              Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
              15