Данный раздел находится в разработке
Данный интерфейс предназначен для гарантированной отправки данных на сервер перед выгрузкой (перезагрузкой, закрытием) страницы. Он является альтернативой синхронного (блокирующего) XMLHttpRequest в колбеке обработчика события "unload" или "beforeunload" и, как правило, используется для отправки на сервер статистики (аналитики) об использовании страницы.
Сигнатура:
navigator.sendBeacon(url, data?)url- адрес сервераdata- данные в формате ArrayBuffer, ArrayBufferView, Blob, DOMString, FormData или объект "URLSearchParams" с данными для отправки
Общий пример:
document.addEventListener('visibilitychange', () => {
if (!('sendBeacon' in navigator)) return
if (document.visibilityState === 'hidden') {
navigator.sendBeacon('/log', someData)
}
})Пример с формой:
<!-- На самом деле, атрибуты action="/login" method="POST" enctype="multipart/form-data" позволяют обойтись без JS -->
<form>
<label>Email:
<input
type="email"
name="email"
placeholder="Email"
autofocus
autocomplete="off"
>
</label>
<label>Password:
<input
type="password"
name="password"
placeholder="Password"
pattern="^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$"
>
</label>
<input type="submit" value="Send">
</form>const form = document.forms[0]
form.onsubmit = async (e) => {
e.preventDefault()
const data = new FormData(form)
if ('sendBeacon' in navigator) {
navigator.sendBeacon('/login', data)
} else {
try {
const response = await fetch('/login', {
method: 'POST',
body: data,
headers: {
'Content-Type': 'multipart/form-data'
}
})
if (!response.ok) throw new Error(response.statusText)
} catch (err) {
console.error(err.message)
}
}
}Данный интерфейс позволяет устанавливать канал коммуникации между контекстами браузера (окна, вкладки, фреймы, iframe) и воркерами в пределах одного источника.
Сигнатура:
// Создание канала, name - название
const bc = new BroadcastChannel(name)
// Отправка сообщения, message - любой объект, все, что можно клонировать
// FormData отправить не получится
bc.postMessage(message)
// Получение и обработка сообщения
bc.onmessage = e => {
console.log(e)
}
// или
bc.addEventListener('message', e => {
console.log(e)
})
// MessageEvent {isTrusted: true, data: {…}, origin: "http://127.0.0.1:5500", ... }
// Закрытие канала
bc.close()Пример использования:
<!-- user.html -->
<form>
<label for="first">Firstname:</label>
<input type="text" id="first" value="John">
<label>Lastname:</label>
<input type="text" id="last" value="Smith">
<input type="submit" value="Send">
</form>
<script>
const form = document.forms[0]
const fisrt = document.getElementById('first')
const last = document.getElementById('last')
form.onsubmit = e => {
e.preventDefault()
const data = {
firstname: first.value.trim(),
lastname: last.value.trim()
}
const bc = new BroadcastChannel('username')
bc.postMessage(data)
bc.close()
}
</script><!-- index.html -->
<iframe src="./user.html" frameborder="0"></iframe>
<script>
const bc = new BroadcastChannel('username')
bc.onmessage = e => {
console.log(e)
const {firstname, lastname} = e.data
const template = `<h2>Hi, ${firstname} ${lastname}!</h2>`
document.body.insertAdjacentHTML('beforeend', template)
}
</script>Похожий интерфейс предоставляет Channel Messaging API. Он поддерживается лучше, чем BroadcastChannel API, но взаимодействие между контекстами реализуется не напрямую, а через порты.
Данный интерфейс предназначен для работы с буфером обмена. Он является альтернативой признанного устаревшим document.execCommand().
Сигнатура:
// Запись в буфер обмена
navigator.clipboard
.writeText()
.then(() => {
console.log('Success')
})
.catch((err) => {
console.error(err.message)
})
// Для записи других данных используется метод "write()" и ClipboardItem
// Чтение из буфера обмена
navigator.clipboard.readText().then(data => {
console.log(data)
}).catch(err => {
console.error(err.message)
})
// Для чтения других данных используется метод "read()"Пример использования:
<head>
<style>
#tooltip {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: #f0f0f0;
border-radius: 2px;
box-shadow: 0 1px 2px rgba(0, 0, 0, .3);
padding: .5rem;
}
</style>
</head>
<body>
<div>
<input type="text" value="Some text to copy" id="copy_input">
<button id="copy_button">Copy</button>
</div>
<br>
<div>
<input type="text" placeholder="Input to paste" id="paste_input">
<button id="paste_button">Paste</button>
</div>
</body>const getEl = (id, el = document) => el.getElementById(id)
const copyI = getEl('copy_input')
const copyB = getEl('copy_button')
const pasteI = getEl('paste_input')
const pasteB = getEl('paste_button')
const showTooltip = (msg) => {
const existingTooltip = getEl('tooltip')
if (existingTooltip) existingTooltip.remove()
const newTooltip = document.createElement('span')
newTooltip.id = 'tooltip'
newTooltip.textContent = msg
document.body.append(newTooltip)
const timerId = setTimeout(() => {
newTooltip.remove()
clearTimeout(timerId)
}, 1000)
}
copyB.onclick = async () => {
try {
await navigator.clipboard.writeText(copyI.value.trim())
showTooltip('Text has been copied to the clipboard')
} catch (err) {
showTooltip(err.message)
}
}
pasteB.onclick = async () => {
try {
const text = await navigator.clipboard.readText()
pasteI.value = text.toUpperCase()
showTooltip('Text has been pasted to the target element')
} catch (err) {
showTooltip(err.message)
}
}const SERVER_URL = 'http://localhost:5000/todos'
const POST = 'POST'
const PUT = 'PUT'
const DELETE = 'DELETE'
export const client = async (method, payload, endpoint = SERVER_URL) => {
let config = {}
if (method) {
config = {
method,
headers: {
'Content-Type': 'application/json'
}
}
if (method === POST || method === PUT) {
config.body = JSON.stringify(payload.body)
}
if (method === DELETE || method === PUT) {
endpoint = `${endpoint}/${payload.id}`
}
}
try {
const response = await fetch(endpoint, config)
if (response.ok) {
let message
switch (method) {
case POST: {
message = 'Data has been added'
break
}
case DELETE: {
message = 'Data has been removed'
break
}
case PUT: {
message = 'Data has been updated'
break
}
default: {
message = 'Data has been received'
}
}
console.log(message)
const result = await response.json()
return result
}
throw new Error(response.statusText)
} catch (err) {
console.error(err.message || err)
}
}
client.post = (payload, endpoint) => client(POST, payload, endpoint)
client.put = (payload, endpoint) => client(PUT, payload, endpoint)
client.delete = (payload, endpoint) => client(DELETE, payload, endpoint)export const storage = {
get: (key) => JSON.parse(window.localStorage.getItem(key)),
set: (key, value) => window.localStorage.setItem(key, JSON.stringify(value)),
remove: (key) => window.localStorage.removeItem(key),
clear: () => window.localStorage.clear()
}