Метод select() и execCommand(), Clipboard API. Копируем текст в буфер обмена

5 (100%) 4 vote[s]

Реализовать копирование в буфер обмена можно при помощи методов select() и execCommand(). В спецификации сказано, что «Метод HTMLInputElement.select() выбирает весь текст в виде элемента <textarea> или в качестве элемента <input> , который включает в себя текстовое поле.» Таким образом, мы можем выбрать только текст из textarea или из текстового поля input (обязательно с type="text"). Для копирования можно использовать метод document.execCommand() (не поддерживается в IE8 ). Хотя метод execCommand() считается устаревшим и не рекомендуется для использования, он работает и для целей копирования его используют повсеместно. В качестве альтернативы устаревшему execCommand() рекомендуется использовать Clipboard API.



Использование для копирования в буфер обмена select() и execCommand()

На w3schools есть пример, как реализовать копирование в буфер обмена с select() и execCommand():

<!-- The text field -->
<input type="text" value="Hello World" id="myInput">

<!-- The button used to copy the text -->
<button onclick="myFunction()">Copy text</button>
<script>
function myFunction() {
  /* Get the text field */
  var copyText = document.getElementById("myInput");

  /* Select the text field */
  copyText.select();
  copyText.setSelectionRange(0, 99999); /*For mobile devices*/

  /* Copy the text inside the text field */
  document.execCommand("copy");

  /* Alert the copied text */
  alert("Copied the text: " + copyText.value);
}
</script>

Вот как он работает:

Но скопировать текст из текстового блока так не получится. Для этого используется костыль суть которого заключается в следующем: получаем текст элемента, затем создаем элемент textarea или input (createElement, body.appendChild(textarea)), вставляем в textarea этот текст при помощи textarea.textContent= (а в input вставляем текст как атрибут value — input.value = ). Затем при помощи select() выбираем текст в созданном элементе и при помощи execCommand копируем в буфер обмена. В завершении удаляем созданный временный элемент при помощи body.removeChild(textarea) .

<p id="myInput">Hello</p>
<button id="btn" onclick="Copy('#myInput')">Copy text</button>
<script>
  function Copy(element) {
var copyText = document.querySelector('#myInput').textContent;
var copyText1 = document.querySelector('#myInput');
  var textarea = document.createElement("textarea");
  textarea.textContent = copyText;
  textarea.style.position = "fixed"; // Запретить прокрутку вниз страницы в MS Edge.
  document.body.appendChild(textarea);
  textarea.select();
  document.execCommand("copy");
  copyText1.style.background = "grey";
  document.body.removeChild(textarea);
  alert('Скопирован текст: ' +  copyText); 
  }
</script>

Или c на jQuery (c input и textarea):

<!--временный input-->
<script>
function Copy(element) {
  var $temp = $("<input>");
  $("body").append($temp);
  $temp.val($(element).text()).select();
  document.execCommand("copy");
  $temp.remove();
  alert('Скопирован текст: ' +  copyText); 
}
</script>
<!--временный textarea-->
<script>
function Copy(element) {
  var $temp = $("<textarea>");
  $("body").append($temp);
  $temp.val($(element).text()).select();
  document.execCommand("copy");
  $temp.remove();
}
</script>

Использование для копирования Clipboard API

Смотрим, что пишется в документации:

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

Этот API предназначен для замены доступа к буферу обмена с помощью document.execCommand(). Почему было решено отказаться от него? Основной недостаток document.execCommand() в том, что эта операция синхронная (блокирующая — браузер блокирует страницу при запросе доступа к буферу обмена) и поддерживает только text/plain тип данных (см. таблицу поддержки браузеров).

В Clipboard API запись данных в буфер реализует метод объекта clipboard.writeText (в нашем случае writeText это частный случай clipboard.write, упрощающий задачу и явно указывающий, что это текст). Чтение — метод readText. Работает с буфером обмена на промисах и позволяет работать с другими данными, отличными от обычного текста (например, с изображениями). 

<div>
  <input type="text" class="WhatCopy" placeholder="Type something..." aria-label="Type something">
  <button class="btn" id="btn">Копировать в буфер обмена</button>
</div>

<div>
  <p class="Results"></p>
  <button class="btn" id="btn2">Вставить из буфера обмена</button>
</div>
<script>
const Read = document.querySelector('#btn2');
const Write = document.querySelector('#btn');

const Result = document.querySelector('.Results');
const TextInput = document.querySelector('.WhatCopy');

//Вставляем из буфера
Read.addEventListener('click', async(e)=> {
  e.preventDefault(); //предотвратить поведение по умолчанию в пользу вашей собственной логики
   try {
    const text = await navigator.clipboard.readText();
	Result.innerText = text;
    console.log('Вставлено: ', text);
  } catch (err) {
    console.error('Не удалось прочитать содержимое буфера обмена: ', err);
  }

});
  //Копируем в буфер
Write.addEventListener('click', () => {
  const inputValue = TextInput.value.trim();// trim () - это строковый метод, который используется для удаления пробельных символов в начале и в конце строки
  if (inputValue) { //Условие - Проверяем, есть ли что копировать, если нет - ничего не происходит
    navigator.clipboard.writeText(inputValue)
      .then(() => {      //Метод then() возвращает Promise
        TextInput.value = ''; // Очищаем текстовое поле в input
        if (Write.innerText !== 'Скопировано!') {//Проверяем текст кнопки
          const originalText = Write.innerText;//Записываем оригинальный исходный текст "Скопировать в буфер"
          Write.innerText = 'Скопировано!';//Меняем текст на "Скопировано!"
          setTimeout(() => { //Задержка, чтобы заменить текст кнопки на исходный
            Write.innerText = originalText;
             }, 1500);
        }
      })
      .catch(err => {
        console.log('Something went wrong', err);
      })
  }
});

</script>

Более подробно можно почитать в этой статье.

Чем заменить устаревший тег <marqee> (как сделать бегущую строку) читайте здесь.

Читайте больше по теме:

Подписаться
Уведомление о
guest
0 Комментарий
Inline Feedbacks
View all comments
Просмотры: 71

Популярные записи