Browser

Дешёвый детектор user-agent / платформы / возможностей. Полезен для runtime-ветвлений во фронтенд-коде.

Обзор

Browser — это синглтон (new BrowserManager()), экспортируемый из @bitrix24/b24jssdk. Он объединяет дешёвые проверки user-agent / платформы / возможностей, на которые SDK опирается внутри, и предоставляет их коду приложения:

  • Определение браузера — Opera, Internet Explorer (с 6 по 11, плюс числовой detectIEVersion), Safari, Firefox, Chrome.
  • Определение ОС / платформы — macOS, Windows, Linux, Android (с detectAndroidVersion), iPad, iPhone и объединённый isIOS.
  • ВозможностиisMobile, isRetina, isTouchDevice, isDoctype и isLocalStorageSupported.

Все проверки выводятся из строки UA уровня модуля — приведённого к нижнему регистру navigator.userAgent, захваченного один раз во время импорта — или из браузерных глобальных объектов (window, document, navigator, localStorage). Из-за этого Browser имеет смысл только в браузерном контексте.

import { Browser } from '@bitrix24/b24jssdk'

if (Browser.isMobile()) {
  // ...
}

if (Browser.isLocalStorageSupported()) {
  // ...
}

Сигнатура методов

Определение браузера

isOpera(): boolean                           // UA содержит 'opera'
isIE(): boolean                              // устаревший 'attachEvent' в document и не Opera
isIE6(): boolean                             // UA содержит 'msie 6'
isIE7(): boolean                             // UA содержит 'msie 7'
isIE8(): boolean                             // UA содержит 'msie 8'
isIE9(): boolean                             // document.documentMode >= 9
isIE10(): boolean                            // document.documentMode >= 10
isIE11(): boolean                            // detectIEVersion() >= 11
detectIEVersion(): number                    // числовая версия IE, -1 если не IE
isSafari(): boolean                          // UA содержит 'safari' и не 'chrome'
isFirefox(): boolean                         // UA содержит 'firefox'
isChrome(): boolean                          // UA содержит 'chrome'

Определение ОС / платформы

isMac(): boolean                             // UA содержит 'macintosh'
isWin(): boolean                             // UA содержит 'windows'
isLinux(): boolean                           // UA содержит 'linux' и не Android
isAndroid(): boolean                         // UA содержит 'android'
detectAndroidVersion(): number               // разобранная версия Android, 0 если не определена
isIPad(): boolean                            // UA содержит 'ipad;' или Mac + touch
isIPhone(): boolean                          // UA содержит 'iphone;'
isIOS(): boolean                             // isIPad() || isIPhone()

Возможности

isMobile(): boolean                          // UA iPhone / iPad / Android / 'mobile' / 'touch'
isRetina(): boolean                          // window.devicePixelRatio >= 2
isTouchDevice(): boolean                     // 'ontouchstart' in window или maxTouchPoints > 0
isDoctype(target?: any): boolean             // compatMode === 'CSS1Compat' (или запасной вариант)
isLocalStorageSupported(): boolean           // setItem/removeItem round-trip проходит успешно

Ключевые понятия

Browser читает navigator.userAgent в переменную UA уровня модуля один раз, во время импорта. Чтение обёрнуто в try/catch, поэтому импорт модуля в небраузерном окружении (например, Node/SSR) не выбрасывает исключение — UA просто откатывается к '?', и каждая проверка на основе UA возвращает false. Методы, напрямую обращающиеся к window, document или localStorage (isRetina, isTouchDevice, isDoctype, isLocalStorageSupported, isIE/isIE9/isIE10), всё же предполагают наличие этих глобальных объектов, поэтому их вызов вне браузера может выбросить исключение.
Это анализ user-agent (UA-sniffing), а не feature detection. Строки user agent можно подделать или обнулить, и браузеры всё чаще замораживают/урезают детали UA. Где возможно, предпочитайте feature detection (например, проверку именно того API, который вам нужен), и относитесь к Browser как к эвристике по принципу best-effort для косметических/UX-ветвлений, а не как к границе безопасности или корректности.
  • isIPad() покрывает современный iPadOS. Поскольку iPadOS сообщает о себе в строке UA как macOS, isIPad() также возвращает true для UA в стиле Mac, который при этом сообщает о поддержке touch (isTouchDevice()) — именно так он отличает iPad от настоящего десктопного Mac.
  • detectIEVersion() возвращает -1 для не-IE браузеров. Он замыкается на -1 для Opera, Safari, Firefox и Chrome до запуска специфичных для IE/Trident эвристик, поэтому его безопасно вызывать безусловно.
  • isDoctype(target?) принимает любой document-подобный объект. Передайте document из iframe (или подобный), чтобы проверить режим рендеринга его, а не верхнеуровневой страницы; при отсутствии target используется глобальный document.
  • isLocalStorageSupported() — это реальная проба записи/удаления, а не просто проверка typeof localStorage — она также ловит случаи, когда API существует, но выбрасывает исключение (режимы приватного просмотра, исчерпание квоты хранилища, отключение политикой).

Обработка ошибок

Browser рассчитан на браузерные runtime. Чтение user-agent уровня модуля и isLocalStorageSupported() обёрнуты в try/catch, но большинство проверок напрямую разыменовывают document / window / navigator (например, isIE, isIE9, isRetina, isTouchDevice, detectIEVersion, detectAndroidVersion) и выбрасывают ReferenceError, когда этих глобальных объектов нет. Оборачивайте любой вызов проверкой окружения (или вовсе избегайте Browser) в путях кода Node.js / SSR, которые могут выполниться до гидрации.

Примеры

Определение браузера:

import { Browser } from '@bitrix24/b24jssdk'

if (Browser.isChrome()) {
  // Поведение для Chrome
}

if (Browser.isIE()) {
  const version = Browser.detectIEVersion()
  console.log(`Running on Internet Explorer ${version}`)
}

Ветвление по ОС / платформе:

import { Browser } from '@bitrix24/b24jssdk'

if (Browser.isIOS()) {
  // Общая ветка iPhone / iPad
}

if (Browser.isAndroid()) {
  const version = Browser.detectAndroidVersion()
  console.log(`Android version: ${version}`)
}

Проверки возможностей:

import { Browser } from '@bitrix24/b24jssdk'

if (Browser.isMobile() && Browser.isTouchDevice()) {
  // Подстройка вёрстки / зон нажатия под touch
}

if (Browser.isRetina()) {
  // Отдавать ассеты высокого разрешения
}

Защита доступа к localStorage и проверка режима рендеринга документа:

import { Browser } from '@bitrix24/b24jssdk'

function persist(key: string, value: string): void {
  if (!Browser.isLocalStorageSupported()) {
    return
  }

  localStorage.setItem(key, value)
}

if (!Browser.isDoctype(document)) {
  console.warn('Page is rendered in quirks mode')
}

Альтернативы и рекомендации

  • Где возможно, предпочитайте feature detection анализу UA. Проверки Browser — это эвристики на основе navigator.userAgent, который можно подделать, заморозить или урезать в браузере. Например, предпочитайте прямую проверку 'ontouchstart' in window (или Browser.isTouchDevice(), который делает ровно это) выводу о поддержке touch из проверок платформы.
  • Используйте isMobile() / isTouchDevice() для решений по вёрстке, а не для блокировки функциональности. Относитесь к ним как к UX-подсказкам (например, крупнее зоны нажатия, упрощённая навигация), а не как к способу полностью отключить функции — десктопный браузер на ноутбуке с поддержкой touch — это легитимная комбинация.
  • Методы, связанные с IE (isIE*, detectIEVersion, isIE11), нацелены на давно снятые с поддержки браузеры. Держите их только для веток legacy-совместимости; новому коду под современные браузеры они, как правило, не нужны.
  • Проверки типов для значений (а не окружения) живут в Type. Browser отвечает на вопрос «в чём я выполняюсь», тогда как Type — «какой формы это значение».