Вырезание, копирование и вставка в JavaScript с помощью API буфера обмена

Лучшие проекты JavaScript для начинающих Программирование и разработка

Лучшие проекты JavaScript для начинающих

Доступ к буферу обмена ОС с помощью браузера JavaScript возможен уже несколько лет document.execCommand().

К сожалению, есть некоторые проблемы:

  • доступ к буферу обмена является синхронным, что влияет на производительность и безопасность;
  • поддержка неоднородна, особенно в старых версиях Safari на macOS и iOS;
  • доступ к разрешениям различается в зависимости от браузера;
  • API никогда не мог считаться элегантным;

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

Зачем приложению нужен доступ к буферу обмена?

Как разработчик вы знаете, как работает буфер обмена, и регулярно используете следующие сочетания клавиш:

  • Ctrl| Cmd+ C копировать.
  • Ctrl| Cmd+ X вырезать.
  • А также Ctrl| Cmd+ V вставить.

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

Кроме того, вы можете изменить содержимое после завершения действия с буфером обмена, например, добавления или удаления форматирования.

Доступ к буферу обмена опасен!

Программный доступ к буферу обмена вызывает несколько проблем с безопасностью:

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

Чтобы избежать потенциальных проблем, API буфера обмена можно использовать только на страницах, обслуживаемых через HTTPS ( localhostтакже разрешено). При запуске в iframe родительская страница также должна предоставлять clipboard-readи / или clipboard-writeразрешения:

<iframe
  src="childpage.html"
  allow="clipboard-read; clipboard-write"
></iframe>

API доступен только для активной вкладки браузера (не для фоновых вкладок) и может быть запущен только при взаимодействии с пользователем, например, щелчком. При необходимости пользователю будет предложено разрешение на чтение данных из буфера обмена:

чтение данных из буфера обмена

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

Обнаружение функции API буфера обмена

API буфера обмена доступен, когда navigator.clipboardвозвращает правдивый результат. Например:

if (navigator.clipboard) {

  console.log('Clipboard API available');

}

Однако это не гарантирует, что браузер поддерживает все функции, поэтому необходимо выполнить дополнительные проверки. Например, на момент написания Chrome поддерживает метод API readText (), а Firefox — нет.

Читайте также:  Java или C++ - что выбрать

Копировать и вставить текст

Копирование и вставка текста будет полезным вариантом в большинстве приложений. API очень прост:

// copy text TO the clipboard
await navigator.clipboard.writeText('This text is now in the clipboard');

// get text FROM the clipboard
let text = await navigator.clipboard.readText();

Вам потребуется значительно больше кода для обнаружения поддержки и обработки ошибок.

В этом примере реализуется копирование текста, когда к data-copyатрибуту добавляется любой элемент HTML, например кнопка. Вы можете установить это значение на одно из следующих значений:

  • Жёстко запрограммированная строка, например data-copy=»copy this to the clipboard».
  • Селектор CSS, например data-copy=»#mysection«. Затем копируется текстовое содержимое первого совпадающего элемента.

При желании вы можете установить собственное сообщение об успешном завершении в data-done атрибуте:

<button data-copy="#mysection" data-done="section copied">
  copy text from #mysection
</button>

Кнопка отображается только тогда, когда navigator.clipboard.writeText()поддерживается. При нажатии обработчик событий JavaScript находит текст, копирует его в буфер обмена и показывает анимированное сообщение об успешном завершении.

Кнопка вставки текста очень похожа, за исключением того, что она определяет data-pasteатрибут, который должен указывать на узел DOM:

<textarea id="pastehere"></textarea>
<button data-paste="#pastehere">paste</button>

Копировать и вставлять данные

Clipboard API, readText()и writeText()варианта удобства для более общих read()и write()методов. У них меньше поддержки браузером, но они могут копировать и вставлять любые типы данных, например двоичные изображения.

Для копирования требуются данные большого двоичного объекта, обычно возвращаемые методом fetch()или canvas.toBlob(). Это передаётся ClipboardItemконструктору, чтобы его можно было записать в буфер обмена:

const
  image = await fetch('myimage.png'),
  blob = await image.blob();

await navigator.clipboard.write([
  new ClipboardItem({ [blob.type]: blob })
]);

Вставка более сложна, поскольку ClipboardItemможно возвращать несколько объектов с разными типами содержимого. Поэтому необходимо перебирать каждый тип, пока не будет найден полезный формат. Например:

const clipboardItems = await navigator.clipboard.read();

for (const clipboardItem of clipboardItems) {

  for (const type of clipboardItem.types) {

    if (type === 'image/png') {

      // return PNG blob
      return await clipboardItem.getType(type);

    }

  }

}

Это работает аналогично текстовой демонстрации, в этой копии и вставить кнопки должны указывать на элементы DOM, используя селектор CSS в data-copyblobи data-pasteblobатрибутов. Например:

Читайте также:  Как расширить вектор в C++?

<!-- copy image -->
<img id="myimage" src="myimage.png" alt="any image" />

<button data-copyblob="#myimage" data-done="image copied">
  copy image
</button>

<!-- paste into DOM -->
<div id="imagelist"></div>

<button data-pasteblob="#imagelist">
  paste image
</button>

Попробуйте скопировать данные изображения из графического приложения, затем используйте кнопку вставки.

Вырезать, скопировать и вставить события

События cut, copyи pasteсрабатывают всякий раз, когда пользователь инициирует действие с буфером обмена в браузере — обычно с помощью контекстного меню или сочетаний клавиш, упомянутых выше. Это поддерживается в большинстве браузеров, и функции обработчика могут перехватывать события для внесения изменений с использованием clipboardDataобъекта, переданного в качестве параметра.

Следующая функция переводит весь вырезанный или скопированный текст в верхний регистр. Обратите внимание, что это e.preventDefault() останавливает действие вырезания / копирования по умолчанию, которое переопределит его:

body.addEventListener('cut', cutCopyHandler);
body.addEventListener('copy', cutCopyHandler);

// cut or copy event handler
function cutCopyHandler(e) {

  const selection = document.getSelection();

  // send uppercase text to clipboard
  e.clipboardData.setData(
    'text/plain',
    selection.toString().toUpperCase()
  );

  if (e.type === 'cut') selection.deleteFromDocument();

  // stop default cut/copy
  e.preventDefault();

}

Следующий код прикрепляет обработчик вставки к определенному <textarea>полю. Функция очищает существующее содержимое и добавляет префиксы к тексту «pasted:»:

document.getElementById(‘field1’).addEventListener(‘paste’, pasteEvent);

document.getElementById('field1').addEventListener('paste', pasteEvent);

// paste event handler
function pasteEvent(e) {

  // add 'pasted:' to pasted text
  const paste = 'pasted:\n' +
    (e.clipboardData || window.clipboardData).getData('text');

  e.target.value = paste;

  // stop default paste
  e.preventDefault();
}

Заключение

API буфера обмена является новым, но имеет разумную поддержку браузера и кажется более надежным, чем старый document.execCommand()вариант.

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

Оцените статью
bestprogrammer.ru
Добавить комментарий