Привет, друзья! Представляю вашему вниманию перевод этой замечательной статьи, посвященной 4 малоизвестным API, которые в некоторых ситуациях могут оказаться весьма полезными: Код примеров на GitHub. Данный интерфейс позволяет определять, когда пользователь покидает страницу. Точнее, он вызывает событие при каждом изменении состояния видимости (visibility status) страницы, например, когда пользователь сворачивает/разворачивает окно, переходит на другую вкладку и т.д. Раньше для этого приходилось прибегать к таким уловкам, как обработка событий blur и focus. Соответствующий код выглядел так: Приведенный код работает, но не совсем так, как ожидается. Поскольку событие blur вызывается, когда страница теряет фокус, оно может возникнуть, когда пользователь нажимает на поиск, диалоговое окно (alert), консоль или границу окна. События blur и focus сообщают нам о том, что страница активна, но не о том, видим или скрыт ее контент. Page Visibility API может использоваться для предотвращения выполнения операций, которые имеют значение, только когда пользователь видит страницу, или для выполнения фоновых операций. Еще несколько кейсов: Page Visibility API предоставляет 2 свойства и одно событие для получения доступа к состоянию видимости страницы: В качестве примера рассмотрим приостановку видео и прекращение получения ресурсов из API, когда пользователь покидает страницу. Создаем шаблон проекта с помощью Vite и Yarn: Переходим в созданную директорию, устанавливаем зависимости и запускаем сервер для разработки: Приложение доступно по адресу http://localhost:3000. Удаляем шаблонный код из файла main.js и добавляем элемент video в файле index.html: Возвращаемся к main.js. Добавляем обработчик события visibilitychange объекта document: Попробуйте свернуть/развернуть окно или переключиться на другую вкладку, чтобы увидеть изменения состояния видимости страницы. Получаем ссылку на элемент video и управляем воспроизведением видео в зависимости от видимости страницы: Прим. пер.: приведенный код работать не будет: получаем ошибку Uncaught (in promise) DOMException: play() failed because the user didn't interact with the document first.. Это объясняется тем, что вызов video.play() при изменении состояния видимости страницы на visible равносилен наличию у элемента video атрибута autoplay. Современные браузеры допускают автоматическое (без участия пользователя) воспроизведение видео только в режиме без звука. Соответственно, для того, чтобы код работал, как ожидается, элементу video необходимо добавить атрибут muted. Когда пользователь покидает страницу, воспроизведение видео приостанавливается. Когда пользователь возвращается на страницу, воспроизведение видео продолжается. Теперь рассмотрим пример прекращения выполнения запросов к API. Для этого напишем функцию, запрашивающую цитату из quotable.io. Добавляем в index.html элемент div для хранения цитаты: Определяем в main.js функцию для получения произвольной цитаты с помощью Fetch API: Приведенный код работает, но функция getQuote вызывается только один раз. Обернем ее в setInterval с интервалом в 10 секунд: Если пользователь свернет окно или перейдет на другую вкладку, запросы все равно будут отправляться каждые 10 секунд. Давайте это исправим: Теперь запросы будут выполняться только при условии, что страница находится в видимом состоянии. Поддержка — 98.24%. Web Share API предоставляет разработчикам доступ к встроенному механизму совместного использования (native sharing mechanism) операционной системы, что особенно актуально для мобильных телефонов. Данный интерфейс позволяет делиться текстом, ссылками и файлами без создания собственного механизма или использования сторонних решений. Web Share API позволяет делиться содержимым страницы в соцсетях или копировать его в буфер обмена пользователя. Web Share API предоставляет 2 метода: navigator.canShare(data): принимает данные для совместного использования и возвращает логическое значение — индикатор того, можно ли этими данными поделиться; navigator.share(data): возвращает промис, который разрешается в случае успешного шаринга (sharing) данных. Данный метод вызывает нативный механизм и принимает данные для шаринга. Обратите внимание: этот метод может вызываться только в ответ на действие пользователя (нажатие кнопки, переход по ссылке и т.п.) (требуется кратковременная активация). data — это объект со следующими свойствами: url — ссылка для шаринга; text — текст; title — заголовок; files — массив объектов File. Возьмем последний пример и добавим возможность делиться цитатой. Добавляем соответствующую кнопку в index.html: В main.js получаем ссылку на эту кнопку и определяем функцию для шаринга данных: Нам также потребуется глобальная переменная для хранения содержимого текущей цитаты: Определяем обработчик нажатия кнопки: Обратите внимание: Web Share API работает только в безопасном окружении. Это означает, что страница должна обслуживаться по протоколу https или wss. Поддержка — 89.82%. Broadcast Channel API позволяет контекстам браузера (browser contexts) обмениваться данными друг с другом. К браузерным контекстам относятся такие элементы, как окно, вкладка, iframe и т.д. По причинам безопасности контексты, обменивающиеся данными, должны принадлежать одному источнику (same origin). Один источник означает одинаковый протокол, домен и порт. Broadcast Channel API обычно используется для синхронизации окон и вкладок браузера для улучшения пользовательского опыта или повышения безопасности. Он также может применяться для уведомления одного контекста о завершении процесса в другом контексте. Другие примеры: Broadcast Channel API предоставляет объект BroadcastChannel, позволяющий обмениваться сообщениями с другими контекстами. Конструктор этого объекта принимает единственный аргумент: строку — идентификатор канала (channel identifier): BroadcastChannel предоставляет 2 метода: При получении сообщения возникает событие message. Это событие содержит свойство data с отправленными данными, а также другие свойства, позволяющие идентифицировать отправителя, такие как origin, lastEventId, source и ports: Возьмем последний пример, создадим новый контекст и добавим возможность обмена цитатами между существующим и новым контекстами. Создаем директорию new-context в корне проекта. Создаем в ней файл index.html следующего содержания: Создаем файл new-context/main.js. Получаем ссылку на div и создаем новый канал коммуникации: Добавляем обработчик события message: Создаем канал в основном main.js и редактируем функцию getQuote: Прим. пер.: для того, чтобы запустить данный пример локально, необходимо сделать следующее: Поддержка — 92.3%. Шпаргалка по Internationalization API При разработке приложения иногда требуется переводить его содержимое на другие языки. Однако простого перевода часто оказывается недостаточно, поскольку такие вещи, как даты, числа, единицы измерения и др. могут различаться в разных странах. Неправильный перевод таких вещей может привести к плохому пользовательскому опыту. Предположим, что мы хотим отобразить на странице "10 ноября 2022 года" как "11/10/22". Эта дата в разных странах будет выглядеть по-разному: Здесь на помощь приходит Internationalization API (или I18n). Данный интерфейс позволяет решить несколько групп задач, связанных с интернационализацией и локализацией, но в этой статье мы не будем погружаться в него слишком глубоко. Для определения страны пользователя в I18n используется идентификатор локали (или просто локаль) (locale identifier, locale). Локаль — это строка, представляющая страну, регион, диалект и другие характеристики. Если точнее, локаль — это строка, состоящая из подтегов (subtags), разделенных дефисом, например: Полный список подтегов можно найти в этом RFC. I18n предоставляет объект Intl, который, в свою очередь, предоставляет несколько специальных конструкторов для работы с чувствительными к языку данными, наиболее интересными из которых являются следующие: В качестве примера рассмотрим использование конструктора Intl.DateTimeFormat для форматирование свойства dateAdded цитат. Данный конструктор принимает 2 аргумента: строку locale для определения правил форматирование даты и объект options для кастомизации форматирования. Прим. пер.: в качестве первого аргумента Intl.DateTimeFormat также принимает массив локалей. Например, для установки дефолтной локали пользователя в конструктор передается пустой массив (). Объект, возвращаемый Intl.DateTimeFormat, предоставляет метод format, который принимает объект Date с датой для форматирования и объект options для кастомизации отображения форматированной даты: Обратите внимание: мы установили настройку timeZone в значение UTC для того, чтобы при форматировании даты не учитывалось локальное время пользователя. Определяем в main.js функцию для форматирования даты: Вызываем эту функцию внутри функции getQuote для форматирования свойства dateAdded: Поддержка — 97.74%. Прим. пер.: на днях использовал Intl.DateTimeFormat для отображения даты и времени в коротком формате: Надеюсь, что вы, как и я, узнали что-то новое и не зря потратили время. Благодарю за внимание и happy coding!  JavaScript Developer