null

JavaScript Clipboard API

В  заметке расскажу о том, как реализовать функцию 'скопировать в буфер обмена' в веб-приложении.

Предположим, что у вас есть поле ввода, содержащее URL, однако текст внутри значительно больше чем ширина поля. Для того, чтобы пользователь мог скопировать ссылку и переслать своему другу, ему придётся выделить необходимую область, после чего произвести копирование. Каждый, наверное, сталкивался с такой проблемой. Выделить текст, который шире чем поле ввода, достаточно затруднительно. Если эта операция выполняется с мобильного телефона, то пользователь задача усложняется настолько, что нередко приводит пользователя в бешенество.

Для решений этой проблемы в приложениях стали появляться специальные кнопки, которые позволяют скопировать определённый текст в буфер обмена или же произвести вставку из него. 

После этого возникает вопрос: "А как вообще взаимодействовать с буфером обмена?".

На сегодняшний день браузерами осуществляется поддержка различных механизмов, которые обеспечивают доступ к этом ресурсу.

 

Ниже приведён фрагмент кода, который использует 'старое API'.

button.addEventListener('click', e => {
  const input = document.createElement('input');
  document.body.appendChild(input);
  input.value = text;
  input.focus();
  input.select();
  const result = document.execCommand('copy');
  if (result === 'unsuccessful') {
    console.error('Failed to copy text.');
  }
})

Как видно для отправки в буфер данных используется функция execCommand, которой передаётся событие 'copy'. Данная команда копирует данные из DOM'елемента, который находится в фокусе. У этого подхода есть несколько недостатков. Во-первых, как было сказано, данные можно извлечь только из DOM элемента. Это не позволит вставить просто текст, без создания виртуального элемента и перевода фокуса на него. Другой проблемой является то, что процесс копирования происходит синхронно. Во время этого происходит блокировка страницы, что негативно влияет на удобство взаимодействия с пользователем, особенно при копирование большого объема данных.

Для решения этих проблем было создано новое Async Clipboard API.  Оно предоставляет асинхронный интерфейс, решающий описанные выше проблемы, а также предоставляет унифицированный доступ к разграничению прав. Копирование текста в буфер, используя это API будет выглядить следующим образом

 

navigator.clipboard.writeText('Text to be copied')
  .then(() => {
    console.log('Text copied to clipboard');
  })
  .catch(err => {
    // This can happen if the user denies clipboard permissions:
    console.error('Could not copy text: ', err);
  });

Как видно из примера выше в браузерах появился новый объект navigator.clipboard, у которого есть функции writeText(), и readText(), которые возвращают Promise, и соответственно работают асинхронно.

Однако поддержка браузерами нового API на 06.2018 достаточно слабая (в моём Chrome оно не работает). Так что используйте в зависимости от ваших потребностей. Проверить работает ли API в коде можно проверив является ли объект clipboard undefined или нет.

Надеюсь это статья вам поможет. На этом, пожалуй, откланяюсь.