Существует более 97 Web API, и вы используете только 5% из них. Давайте разблокируем остальные 95%!
После долгой прогулки по темным просторам спецификаций я понял, что существует так много технологий, которые остаются без внимания.
Моя цель в этой статье — вывести их на свет. И я докажу вам на практических примерах, что некоторые API действительно стоят того, чтобы попробовать!
В каждом разделе будет подробно рассмотрен каждый API и приведен забавный пример, прекрасно демонстрирующий практическое применение.
- Реклама: Любите халяву? 🤑
- 📑 Оглавление
- Предупреждение о портретном режиме
- API ориентации экрана
- Определение ориентации экрана
- Блокировка ориентации экрана
- Создание полноэкранного режима на вашем сайте
- Вход в полноэкранный режим
- Выход из полноэкранного режима
- Проверка того, находится ли пользователь в полноэкранном режиме
- Анимация элемента при его входе в область просмотра
- Создание наблюдателя
- Обработка событий пересечения
- Предотвращение перехода экрана в темное состояние
- Приобретение wakelock
- Освобождение wakelock
- Запись вашего экрана
- Совместимость с браузером
- Захват начального экрана
- Предварительный просмотр записи
- Остановка захвата экрана
- Хранение табличных данных в базе данных на устройстве
- Использование IndexedDB
- Хранение текстовых данных на устройстве, даже когда пользователь уходит
- Использование локального хранилища
- Создание эффекта пульсации с учетом местоположения
- Логика JavaScript
- Ворклет Paint
- Регистрация заготовки для рисования
- Показ встроенного меню совместного доступа
- Совместное использование URL-адресов
- Копирование текста в буфер обмена
- Использование API буфера обмена
- Общий доступ к выделенному тексту
- Получение выделенного текста
- Изменение заголовка, когда пользователь покидает вкладку
- Определение видимости страницы
- Заключение
- Почетные упоминания
- Любите халяву? 🤑
- Eluda
Реклама: Любите халяву? 🤑
Я сделал пакет из 100 бесплатных hover-анимаций. Получите его сейчас, поделитесь им и делайте с ним все, что захотите. Он ваш навсегда! ❤️
📑 Оглавление
- 🤳 API ориентации экрана
- 📺️ Fullscreen API
- 📲 API наблюдателя перекрестков
- 💤 API блокировки экрана при пробуждении
- 💻️ API захвата экрана
- 📔 API IndexedDB
- 🧠 API локального и сеансового хранения данных
- 🎨 Houdini API
- 🕸️ Web Share API
- 📋️ Clipboard API
- ✒️ Selection API
- 👀 API видимости страницы
Предупреждение о портретном режиме
Экран слишком узкий. Попробуйте использовать альбомный режим.
Некоторые приложения, например, редакторы нелинейного видео, не предназначались для вертикальных устройств: они просто не работают на узких экранах!
Конечно, веб должен быть отзывчивым, но не всегда стоит переносить весь широкий макет на узкий экран.
Разве не было бы здорово, если бы мы могли предупреждать наших пользователей, когда их устройство повернуто в неправильном направлении? Позвольте представить вам… API ориентации экрана!
Чтобы избежать ошибок, важно проверить поддержку API Screen Orientation. Это делается очень просто: if ('orientation' in screen)
. Вы будете видеть этот шаблон снова и снова на протяжении всей этой статьи.
API ориентации экрана
Браузеры предоставляют глобальную переменную screen
, которую мы будем использовать для доступа к нужной нам информации. Доступ к экземпляру [ScreenOrientation](https://developer.mozilla.org/en-US/docs/Web/API/ScreenOrientation)
можно получить с помощью screen.orientation
. Мы будем работать с этим объектом на протяжении всего этого раздела.
Определение ориентации экрана
Типы и углы ориентации экрана: https://w3c.github.io/screen-orientation/#dfn-screen-orientation-values-table
Вопреки распространенному мнению, существует четыре способа ориентации экрана, как показано на рисунке выше. Но нас интересует только то, в каком режиме находится экран — портретном или альбомном, и легко написать функцию, которая скажет нам именно это:
function getOrientation() {
const isPortrait = screen.orientation.type.startswith('portrait')
return isPortrait ? 'portrait' : 'landscape'
}
Блокировка ориентации экрана
Нативные приложения, такие как Instagram, блокируют ориентацию экрана во время его использования. Поскольку грань между PWA и нативными приложениями с каждым днем становится все более размытой, неудивительно, что эта функция появилась и в Интернете.
Хотя она поддерживается в меньшей степени, заблокировать и разблокировать ориентацию экрана можно с помощью этого фрагмента кода:
screen.orientation.lock(orientation)
Не забудьте также обработать ошибки, поскольку, как я уже говорил, эта функция не очень хорошо поддерживается.
Создание полноэкранного режима на вашем сайте
Браузеры покрывают наши сайты множеством элементов пользовательского интерфейса, отвлекая пользователя от важного.
Скриншот мобильного Chrome, подчеркивающий элементы пользовательского интерфейса браузера.
Это особенно проблематично, когда речь идет о захватывающем контенте, таком как:
- фильмы,
- игры,
- максимизация изображений.
и список можно продолжать и продолжать.
К счастью, Fullscreen API приходит и спасает ситуацию!
Эта функция очень хорошо поддерживается во всех современных браузерах, поэтому не стоит беспокоиться о ее использовании.
Вход в полноэкранный режим
Удивительно, но любой элемент DOM может войти в полноэкранный режим:
el.requestFullscreen()
Однако чаще всего мы хотим, чтобы вся страница перешла в полноэкранный режим. Корневой элемент документа —<html>
— может быть доступен в JavaScript с помощью document.documentElement
.
Поэтому нет ничего необычного в том, чтобы увидеть этот фрагмент кода в Интернете:
document.documentElement.requestFullscreen()
Выход из полноэкранного режима
Существует множество способов выхода из полноэкранного режима. Некоторые из них являются комбинациями клавиш по умолчанию в браузере: ESC
и F11
.
Также есть возможность выйти, переключая вкладки Ctrl+Tab
или перескакивая окна Alt+Tab
.
Однако наиболее важным механизмом выхода является тот, который предоставляете вы — разработчик. Вы можете программно выйти из полноэкранного режима следующим образом:
document.exitFullscreen()
В среде развертывания, однако, важно избежать ошибок, проверив, существует ли эта функция, прежде чем вызывать ее:
if (document.exitFullscreen) {
document.exitFullscreen()
}
Проверка того, находится ли пользователь в полноэкранном режиме
Если бы мы хотели реализовать полноэкранный режим, как показано в Codepen в самом начале, нам бы понадобился способ определить, активен ли полноэкранный режим.
Это вполне возможно с помощью следующего фрагмента кода:
document.fullscreenElement // returns 'null' or the fullscreen-enabled DOM element
Для лучшей совместимости с браузерами мы должны проверить наличие нескольких атрибутов:
document.fullscreenElement
|| document.mozFullscreenElement
|| document.msFullscreenElement
|| document.webkitFullscreenElement
Имея это на руках, мы можем реализовать полноэкранный режим:
function toggleFullScreen() {
if (!document.fullscreenElement) {
document.documentElement.requestFullscreen();
} else {
if (document.exitFullscreen) {
document.exitFullscreen();
}
}
}
Анимация элемента при его входе в область просмотра
Вспомните все случаи, когда вам нужно было что-то сделать, когда элемент попадал в поле зрения:
- Анимировать его,
- Загрузка дополнительного содержимого (бесконечная прокрутка),
- Ленивая загрузка изображения,
- Регистрация доходов от рекламы.
Одним из наивных решений является вызов getBoundingClientRect
при каждом событии прокрутки. И я хочу сказать… это работает!
Однако это ужасно неэффективно. Он выполняется в основном потоке, поэтому чем больше слушателей событий мы регистрируем, тем медленнее работает наше приложение.
К счастью, инженеры браузеров благословили нас API Intersection Observer: эффективное решение, которое делегирует все оптимизации браузеру, чтобы мы — веб-разработчики — могли сосредоточиться на главном.
Мы собираемся сделать довольно крутой эффект, при котором элементы текста выделяются только тогда, когда они попадают в поле зрения, создавая изящную и современную анимацию, которую по достоинству оценят наши читатели. Посмотрите на это своими глазами в Codepen выше.
Создание наблюдателя
Прежде чем начать прослушивать события пересечения, мы должны создать объект-наблюдатель, который будет выполнять все фоновые задачи:
const options = {
root: null, // use viewport
threshold: 0.75
}
const observer = new IntersectionObserver(callback, options)
Возможно, вы заметили threshold
. Это опция, которая указывает браузеру, что события пересечения будут происходить только тогда, когда N% элемента будет видимым.
Обработка событий пересечения
Давайте определим callback — функцию, которая будет вызываться при возникновении события пересечения.
Мы хотим обрабатывать событие только тогда, когда элемент отображается в области просмотра не менее чем на N%:
function callback(entry) {
if (entry.intersectionRatio > 0.75) {
// ...
}
}
Пришло время решить, что делать с элементом, когда он попадает в поле зрения. В данном случае мы просто присвоим ему имя класса .active
, а обязанности по анимации передадим CSS.
function callback(entry) {
if (entry.intersectionRatio > 0.75) {
entry.target.classList.add('active')
}
}
Мы также можем «отменить» этот эффект, как только он покинет экран:
function callback(entry) {
if (entry.intersectionRatio > 0.75) {
entry.target.classList.add('active')
} else {
entry.target.classList.remove('active')
}
}
Для более глубокого знакомства с API IntersectionObserver прочитайте эту замечательную статью Дениса Мишунова.
Предотвращение перехода экрана в темное состояние
Видеоролик с космической паузой на Youtube, показывающий элементы управления видеоплеера.
Длинные видео требуют, чтобы экран оставался включенным даже без какого-либо взаимодействия. Такое поведение обычно наблюдается в нативных приложениях, но с API Screen Wake Lock оно доступно и в Интернете!
Существует множество других вариантов использования этого API:
- Онлайн-игры,
- презентации,
- Рисование на холсте,
- Камера,
- потоковое вещание,
- Таймеры.
И этот список не прекращается.
Давайте углубимся в его внутреннюю работу!
Firefox и Safari пока не поддерживают эту функцию. Поэтому всегда полезно сначала проверить ее наличие, чтобы избежать всевозможных ошибок: if (‘wakelock’ in navigator)
Приобретение wakelock
Видеоплеер, например, Youtube, может получить wakelock в своей функции play
:
let wakelock = null
async function play() {
// …
wakelock = await navigator.wakeLock.request('screen')
}
Если батарея пользователя слишком разряжена, ожидайте отказа.
Освобождение wakelock
Плохая практика — держать wakelock включенным вечно, так как это вредит батарее пользователя и может даже снизить производительность. Поэтому всегда снимайте блокировку, когда это возможно:
async function pause() {
// ...
await wakelock.release()
}
Когда пользователь покидает вкладку вашего сайта, блокировка wakelock автоматически снимается.
В этом случае вы должны снова заблокировать его, прослушивая событие visibilitychange
, о котором мы узнаем больше в другом разделе.
Но в двух словах, оно срабатывает, когда пользователь покидает/входит на вкладку сайта.
document.addEventListener('visibilitychange', async () => {
if (wadocument.addEventListener('visibilitychange', async () => {
if (wakelock !== null && document.visibilityState === 'visible') {
wakelock = await navigator.wakeLock.request('screen')
}
})
Запись вашего экрана
В Интернете появляется все больше приложений для записи экрана. Но как именно они это делают? Ответ на удивление прост.
Секрет их успеха — Screen Capture API, простой в использовании интерфейс, который позволяет пользователям записывать экран самыми разными способами:
- Весь экран,
- конкретное окно,
- конкретная вкладка.
Он также поставляется с дополнительными возможностями, включая, но не ограничиваясь ими:
- размытие/прикрытие перекрывающихся окон, чтобы избежать случайного обмена конфиденциальной информацией,
- скрытие/показ курсора,
- запись звука.
Совместимость с браузером
Не хотелось бы сообщать плохие новости, но пока ни один мобильный браузер не поддерживает этот API.
С другой стороны, его очень хорошо поддерживают современные настольные навигаторы! (кроме Internet Explorer, конечно).
Захват начального экрана
С этим восхитительным API запись экрана становится до безобразия простой:
const options = {
video: {
cursor: 'always' // show the cursor
},
audio: false // don't record audio
}
navigator.mediaDevices.getDisplayMedia(options) // returns a promise
Вы поверите мне, если я скажу, что это все? Ну, я никогда не вру.
Подсказка захвата экрана показывает 3 типа: весь экран, окно, вкладка.
Приведенная выше функция указывает браузеру показать подсказку для выбора желаемой поверхности записи, как показано на изображении выше. (попробуйте сделать это сами в кодепене в начале этого раздела).
Предварительный просмотр записи
Было бы неплохо, если бы мы могли видеть, что именно видит веб-сайт. К счастью, это очень просто сделать:
<video autoplay id="preview"></video>
И это все, что касается HTML. Теперь перейдем к логике JavaScript:
previewElem = document.getElementById('preview')
previewElem.srcObject = await navigator.mediaDevices.getDisplayMedia(options)
Вот и все! Теперь вы можете видеть, что записывается, в реальном времени.
Остановка захвата экрана
С помощью одного метода мы можем добиться всего! Обратите внимание, что важно сначала создать элемент предварительного просмотра, как было показано в последнем подразделе.
let tracks = previewElem.srcObject.getTracks()
tracks.forEach(() => track.stop())
previewElem.srcObject = null
Хранение табличных данных в базе данных на устройстве
Прямо в вашем браузере спрятана целая система баз данных NoSQL, доступ к которой осуществляется с помощью API IndexedDB!
Каждая операция является асинхронной, поэтому она никогда не замедляет выполнение других операций. Она также очищается, как только пользователь удаляет кэш браузера или локально сохраненные данные.
В дополнение ко всему этому, он также поддерживает обычные действия поиска, получения и размещения, с транзакциями на стороне. Он может хранить практически все виды данных, включая, но не ограничиваясь File
, изображения и видео в виде Blob
, и, конечно, String
.
К сожалению, не все браузеры согласны с тем, какой тип данных должен поддерживаться. Safari на iOS, например, не может хранить данные Blob. Однако все остальные форматы можно преобразовать в
ArrayBuffer
, который очень хорошо поддерживается всеми платформами.
Ограничение по объему хранилища не является проблемой, так как большинство браузеров выделяют кучу места, которое ваши сайты могут свободно потреблять. Кроме того, каждая база данных привязана не только к доменному имени, но и к совершенно конкретному поддомену. Ко всему прочему, совместимость браузеров вообще не является проблемой, даже в IE11.
С помощью этого API мы можем сделать многое, включая, но не ограничиваясь этим:
- Хранение структурированных данных для автономного использования,
- Ускорение времени загрузки при повторных посещениях,
- Кэширование данных, созданных пользователями,
- временное сохранение данных перед их загрузкой на сервер.
Давайте посмотрим, как мы можем хранить контактные данные в IndexedDB!
Использование IndexedDB
Прежде чем мы сможем что-либо сделать, мы должны использовать библиотеку-обертку поверх IndexedDB, потому что по умолчанию она слишком сложна; она использует события вместо обещаний.
import { openDB } from 'idb';
const db = await openDB('contacts', 1, {
// Creates a new database if it doesn't exist.
upgrade(db) {
db.createObjectStore('contacts', {
// The 'id' property of the object will be the key.
keyPath: 'id',
// If it isn't explicitly set, create a value by auto incrementing.
autoIncrement: true,
})
// Create an index on the 'name' property of the objects.
store.createIndex('name', 'name');
}
})
И вот все готово, мы можем приступить к хранению структурированных данных, как будто это никого не касается!
await db.add('contacts', {
name: 'John Doe',
age: 25,
email: 'johndoe@john.doe'
})
И мы можем так же легко получить все эти данные:
// Get all contacts in name order:
const contacts = await db.getAllFromIndex('contacts', 'name')
Это все, что нам нужно знать для нашего простого случая. Но если вам все еще интересно, вы можете углубиться в документацию.
Хранение текстовых данных на устройстве, даже когда пользователь уходит
Хотя мы можем использовать IndexedDB для хранения больших и сложных данных в браузере, важно учитывать и другие моменты, когда все, что нам нужно сохранить, — это простая пара ключ-значение:
- Информация о входе в систему,
- состояние подписки на рассылку новостей,
- согласие на использование Cookies,
- пиксели отслеживания Analytics.
Важно отметить, что конфиденциальная информация (пароли, данные кредитных карт, номера социального страхования и т.д.) НИКОГДА не должна сохраняться в браузере, поскольку она уязвима для XSS-атак и других эксплойтов.
Для таких простых случаев существует специальный инструмент, который называется Web Storage API. Как и IndexedDB, он привязан к конкретному субдомену. Он также очищается, если пользователь очищает кэш браузера или данные.
В этом API вы найдете два типа хранилищ: localStorage
и sessionStorage
. Они предлагают различные преимущества:
- Локальное хранилище сохраняет данные, даже когда пользователь покидает сайт, в отличие от сеансового хранилища, которое очищает все данные, как только вкладка закрывается.
- Локальное хранилище может хранить больше данных, в отличие от сеансового хранилища, максимальный размер которого составляет 5 МБ.
Использование локального хранилища
Допустим, мы создаем форму подписки на рассылку новостей. Мы не хотим продолжать показывать ее пользователю даже после того, как он подписался, поэтому мы используем глобальную переменную localStorage
для условного отображения:
function subscribe() {
// ...
localStorage.setItem('is-newsletter-subscribed', true)
}
Теперь вы можете использовать DevTools для просмотра нового элемента, сохраненного прямо на вашем компьютере.
А теперь давайте напишем функцию, которая решает, показывать или нет форму подписки:
function isSubscribed() {
return localStorage.hasOwnProperty('is-newsletter-subscribed') ? localStorage.getItem('is-newsletter-subscribed') : false
}
Как вы видите, сначала мы проверяем, существует ли элемент newsletter-subscribed
. Если он существует, мы просто возвращаем его значение с помощью getItem()
, в противном случае мы возвращаем false
, потому что пользователь еще не подписался.
Создание эффекта пульсации с учетом местоположения
С развитием интернета выросли и специальные эффекты. В наши дни свойств CSS просто недостаточно, чтобы реализовать наши самые смелые мечты.
Раньше нашим последним средством были GIF-файлы и изображения, но с API CSS Painting это больше не так!
Теперь мы можем использовать все стильные эффекты, которые поставляются с HTML Canvas, чтобы нарисовать что угодно на фоне элемента.
Совместимость с браузерами не очень хорошая. Firefox и Safari на iOS пока не поддерживают его. Поэтому очень важно выполнить следующее: if ('paintWorklet' в CSS)
.
Давайте построим эффект пульсации без псевдоэлементов, вдохновившись собственной реализацией Google.
Логика JavaScript
Чтобы этот эффект работал, нам нужно использовать события JavaScript для получения позиций курсора x
и y
:
// index.js
button.addEventListener('click', (e) => {
const {x: offsetX, y: offsetY} = button.getBoundingClientRect()
const [x, y] = [e.clientX - offsetX, e.clientY - offsetY]
button.style.setProperty('--x', x)
button.style.setProperty('--y', y)
// ...
})
Поскольку эффект пульсации — это анимация, которая развивается во времени, нам нужно отслеживать ее временную шкалу с помощью переменной tick
:
// index.js
button.addEventListener('click', (e) => {
// ...
const start = performance.now()
requestAnimationFrame(function step(now) {
const tick = Math.floor(now - start)
button.style.setProperty('--tick', tick)
// Continue animation
requestAnimationFrame(step)
})
})
Приведенный выше код использует [requestAnimationFrame](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame)
для создания эффективной и оптимизированной анимации. Во время каждого шага анимации мы вычисляем «тик» и присваиваем его свойству CSS.
Если мы оставим все как есть, анимация будет идти вечно. Поэтому давайте добавим «условие окончания», чтобы завершить анимацию. Мы остановим ее, когда она достигнет 1 секунды (что означает 1000 миллисекунд):
// index.js
button.addEventListener('click', (e) => {
// ...
requestAnimationFrame(function step(now) {
const tick = Math.floor(now - start)
button.style.setProperty('--tick', tick)
// Stop the animation after 1 second
if (tick > 1000) {
button.style.setProperty('--tick', 0)
return
}
// Continue animation
requestAnimationFrame(step)
})
})
И это все для логики!
Ворклет Paint
Давайте создадим настоящий эффект пульсации, используя API Paint.
Этот эффект должен находиться в отдельном файле, который мы назовем ripple.js
.
Начнем с получения свойств CSS, которые мы только что определили:
// ripple.js
registerPaint('ripple', class {
static get inputProperties() {
return ['--x', '--y', '--tick']
}
})
Затем мы воспользуемся API Canvas, чтобы нарисовать круг на фоне кнопки:
// ripple.js
registerPaint('ripple', class {
//...
paint(ctx, {width}, props) {
// Retrieve props
const x = parseFloat(props.get('--x').toString())
const y = parseFloat(props.get('--y').toString())
let tick = parseFloat(props.get('--tick').toString())
// Clamp tick in [0, 1000]
if (tick < 0) tick = 0
if (tick > 1000) tick = 1000
// Draw ripple
const rippleColor = 'rgba(255,255,255,0.54)'
ctx.fillStyle = rippleColor
ctx.globalAlpha = 1 - tick/1000
ctx.arc(
x, y, // center
width * tick/1000, // radius
0, 2 * Math.PI // full circle
)
ctx.fill()
}
})
Регистрация заготовки для рисования
Вернитесь в файл index.js
и добавьте следующий код:
// index.js
if ('paintWorklet' in CSS) {
CSS.paintWorklet.addModule('ripple.js')
}
Сначала он проверит, поддерживается ли CSS Paint API, и только после этого свяжет эффект пульсации.
И мы закончили! Осталось только использовать этот эффект. Поэтому добавьте следующий код в свой CSS:
button {
background-color: #0d1117;
background-image: paint(ripple);
}
Для более глубокого знакомства с API CSS Paint прочитайте эту замечательную статью Адриана Биса.
Показ встроенного меню совместного доступа
В Интернете так много контента, которым мы можем захотеть поделиться с другими:
- ссылки,
- изображения,
- абзацы.
И этот список никогда не заканчивается.
Обычно разработчик внедряет собственную систему обмена со ссылками на Twitter, Facebook и другие социальные сети.
Однако эти компоненты всегда проигрывают своим родным аналогам, которые обладают огромным количеством возможностей:
- обмен с контактами,
- обмен с другими приложениями,
- обмен через bluetooth,
- копирование в буфер обмена.
И список, опять же, никогда не заканчивается.
Раньше эти родные меню обмена были эксклюзивными для родных приложений, но с Web Share API это больше не так.
Совместимость с браузерами превосходна в мобильных браузерах, но немного затруднена, когда дело доходит до Firefox на настольных компьютерах.
Попробуйте сами в Codepen выше, а если он не поддерживается на вашем устройстве, вот как он может выглядеть:
Меню общего доступа с множеством опций, включая Gmail, Messages, Reddit и LinkedIn.
Совместное использование URL-адресов
Метод, который следует искать, — navigator.share
. Он принимает объект, содержащий заголовок, строку текста и URL.
const shareData = {
title: 'Smashing Magazine',
text: 'Smashing Magazine — For Web Designers And Developers',
url: 'https://www.smashingmagazine.com/'
}
await navigator.share(shareData)
Обратите внимание, что эта функция защищена переходной активацией, то есть для ее выполнения требуется событие пользовательского интерфейса (например, щелчок).
Копирование текста в буфер обмена
Буфер обмена — одна из самых недооцененных функций в современных компьютерах. Выжили бы мы, разработчики, без постоянного Ctrl+C
‘ing кода из Stackoverflow? Сомневаюсь.
Клипборды позволяют перемещать цифровую информацию из точки А в точку Б. Единственная альтернатива — переписывать содержимое вручную, что дает огромную возможность для ошибок. Современные буферы обмена также позволяют копировать изображения и другие виды медиа.
С появлением API буфера обмена разработчики могут продемонстрировать пользователям красоту UX, программно копируя важную информацию в буфер обмена пользователя. Эту функцию можно увидеть повсюду, от кода на сайте MDN до Twitter. Она отсутствует только в Stackoverflow, и на то есть веские причины.
Совместимость с браузерами также отличная, кроме IE, конечно.
Использование API буфера обмена
Копирование текста чрезвычайно просто:
await navigator.clipboard.writeText('Howdy, partner!')
И читать его так же просто:
const text = await navigator.clipboard.readText()
Общий доступ к выделенному тексту
Выделенный текст в блоге с всплывающей подсказкой для совместного использования.
Множество блогов, таких как Medium, позволяют пользователям без особых усилий делиться выделенным текстом с другими социальными платформами.
Будучи такой полезной функцией, она поощряет обмен контентом, в результате чего блог разрастается до огромных размеров.
В предыдущем разделе мы уже рассмотрели, как вызвать встроенное меню обмена, поэтому давайте просто сосредоточимся на выделении текста.
Также мы не будем рассматривать, как добавить всплывающую подсказку поверх выделенного текста, но мы углубимся в использование Selection API для получения выделенной части текста, потому что вся эта статья посвящена API и их использованию.
И не нужно беспокоиться о совместимости с браузерами, потому что все просто идеально!
Получение выделенного текста
Сделать это очень просто:
const text = window.getSelection().toString()
Вот и все! Теперь воспользуйтесь предыдущим разделом об API Web Share, чтобы вызвать меню совместного доступа, определяемое ОС, и дайте своим пользователям разгуляться!
Изменение заголовка, когда пользователь покидает вкладку
Заголовок сайта меняется с «Сайт покупок» на «Пожалуйста, останьтесь», когда пользователь покидает вкладку.
С помощью API «Видимость страницы» можно определить, просматривается ли сайт или нет.
Хотя я не рекомендую использовать Page Visibility API для привлечения внимания пользователя с помощью назойливых сообщений, у него есть много положительных примеров использования:
- показ новых уведомлений,
- составление отчетов по анализу вовлеченности,
- приостановка видео и аудио,
- остановка карусели изображений.
Совместимость с браузерами не является проблемой.
Определение видимости страницы
Мы можем получить состояние видимости страницы в любое время с помощью следующего кода:
document.visibilityState // 'visible' or 'hidden'
Но реальные случаи использования требуют прослушивания событий и соответствующего изменения поведения.
К сожалению, название события в разных браузерах разное, поэтому нам придется сделать следующее:
let hidden;
let visibilityChange;
if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support
hidden = "hidden";
visibilityChange = "visibilitychange";
} else if (typeof document.msHidden !== "undefined") {
hidden = "msHidden";
visibilityChange = "msvisibilitychange";
} else if (typeof document.webkitHidden !== "undefined") {
hidden = "webkitHidden";
visibilityChange = "webkitvisibilitychange";
}
Затем мы можем прослушивать события видимости страницы, как показано ниже:
document.addEventListener(visibilityChange, handleVisibilityChange);
function handleVisibilityChange() {
if (document[hidden]) {
// page is hidden
} else {
// page is visible
}
}
Для целей нашей демонстрации мы просто изменим заголовок документа:
function handleVisibilityChange() {
if (document[hidden]) {
document.title = 'Please stay!!!'
} else {
document.title = 'Shopping website'
}
}
Обратите внимание, что я не рекомендую делать это, так как это просто раздражает пользователя и является фундаментальным нарушением этики веб-дизайна.
Заключение
Веб-интерфейсы API в наши дни преодолевают разрыв между веб-приложениями и «родными» приложениями.
Веб начинает представлять реальную угрозу для монополий, созданных App Store и Google Play Store, и это не имеет никаких признаков остановки. Давайте обсудим это в разделе комментариев ниже!
Есть еще много API, которые мы еще не изучили, и некоторые из них могут делать невероятные вещи, такие как сканирование штрих-кодов и даже распознавание речи! Так что следите за новостями во второй части! ❤️
Почетные упоминания
Было бы стыдно не упомянуть еще одну группу API, которые очень редко используются, но имеют так много интересных и практичных применений:
- API геолокации
- API датчиков
- API вибрации
- API производительности
- API изменения размера наблюдателя
Любите халяву? 🤑
Я сделал пакет из 100 бесплатных анимаций наведения. Получите его сейчас, поделитесь им и делайте с ним все, что захотите. Он ваш навсегда! ❤️

Eluda