Копирование текста в буфер обмена с разметкой Bootstrap 5 и Tooltips (Clipboard Bootstrap 5)

Часто встречаются сайты, на которых можно скопировать текст при помощи специальной кнопки. Для качественной вёрстки страниц я обычно применяю набор инструментов от Twitter Bootstrap 5, новая версия которого успешно выпущена и полностью готова к полноценной разработке. В этом наборе не хватает только выше упомянутой кнопки, но её можно реализовать используя код на JavaScript.

Разработчики Bootstrap в новом решении надумали отказаться от библиотеки jQuery, поэтому я напишу код на чистом JS. Для всплывающих подсказок применю модуль Tooltips «из коробки», а также добавлю для красоты немного иконок из набора «Bootstrap Icons».

Разметка HTML

В минимальном исполнении разметку можно выполнить так:

<div class="copy-clipboard text-center text-muted mt-5">
	<span>Скопировать строку</span><button title="Скопировать" class="btn btn-outline-secondary btn-sm shadow-none ms-3">Скопировать</button>
</div>

Здесь важно указать контейнеру класс .copy-clipboard, а внутри него расположить строку <span> и кнопку <button>. При нажатии на кнопку строка будет скопирована в буфер обмена (Clipboard).

Примечание:

размножать необходимо именно контейнеры <div> с классом .copy-clipboard

Код JavaScript

Теперь создадим непосредственно сам код, который отвечает за всю процедуру копирования.

Пример:

let copyList  = document.querySelectorAll( '.copy-clipboard' );
let copyArray = Array.prototype.slice.call( copyList );

function tooltipUpdate( button, tooltip, title ) {
	tooltip.dispose();
	button.setAttribute( 'title', title );
	tooltip = new bootstrap.Tooltip( button );
	tooltip.show();

	return tooltip;
}

copyArray.map( function ( copy ) {
	let text    = copy.querySelector( 'span' ).innerText;
	let button  = copy.querySelector( 'button' );
	let tooltip = new bootstrap.Tooltip( button );

	button.addEventListener( 'mouseover', function () {
		tooltip = tooltipUpdate( button, tooltip, 'Скопировать' );
	} );

	button.addEventListener( 'click', function () {
		window.navigator.clipboard.writeText( text );
		tooltip = tooltipUpdate( button, tooltip, 'Готово!' );
	} );
} );

Ранее для копирования текста применялась функция document.execCommand('copy'). Она устарела, официально не поддерживается, но многие сайты продолжают её использовать. Особенность функции в том, что кроме поля <input> она ничего не могла скопировать и приходилось интерактивно создавать это поле, помещать в него текст, а затем удалять.

Теперь можно применить конструкцию window.navigator.clipboard.writeText(text) для копирования текста напрямую из других тегов, таких как <span>, <p>, <div> и др.

Посмотрите упрощённый пример по ссылке.

Пример Bootstrap 5 и Tooltips

Приведу практический пример разметки для Twitter Bootstrap 5. Здесь подключены различные библиотеки для наведения красоты, но все они из линейки продуктов Bootstrap. В коде есть небольшие изменения: вместо кнопки используется иконка <i>, а в остальном – просто более наглядный вариант.

Интерактивный пример можно посмотреть по данной ссылке.

<!doctype html>
<html lang="ru">
	<head>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, initial-scale=1">
		<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css" integrity="sha256-z8OR40MowJ8GgK6P89Y+hiJK5+cclzFHzLhFQLL92bg=" crossorigin="anonymous">
		<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css" integrity="sha256-PDJQdTN7dolQWDASIoBVrjkuOEaI137FI15sqI3Oxu8=" crossorigin="anonymous">
		<title>Пример копирования текста с применением Twitter Bootstrap 5 Tooltips | onstartup.ru</title>
	</head>
	<body class="bg-light">
		<div class="container">
			<div class="row justify-content-center">
				<div class="col-auto py-5">
					<div class="card shadow">
						<div class="card-header text-center">
							<h1 class="display-6">Пример копирования текста<br>Twitter Bootstrap 5 Tooltips</h1>
						</div>
						<div class="card-body">
							<div class="table-responsive">
								<table class="table table-borderless mb-0">
									<tbody>
										<tr>
											<th scope="row">ПРИМЕР&nbsp;1:</th>
											<td>
												<div class="copy-clipboard d-flex justify-content-between">
													<span class="lead h5">Скопировать&nbsp;строку&nbsp;1</span><i class="bi bi-clipboard-plus btn p-1 pt-0" data-bs-toggle="tooltip" title="Скопировать"></i>
												</div>
											</td>
										</tr>
										<tr>
											<th scope="row">ПРИМЕР&nbsp;2:</th>
											<td>
												<div class="copy-clipboard d-flex justify-content-between">
													<span class="lead h5">Скопировать&nbsp;строку&nbsp;2</span><i class="bi bi-clipboard-plus btn p-1 pt-0" data-bs-toggle="tooltip" title="Скопировать"></i>
												</div>
											</td>
										</tr>
									</tbody>
								</table>
							</div>
						</div>
					</div>
				</div>
			</div>
		</div>
		<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/js/bootstrap.bundle.min.js" integrity="sha256-KuvCVS19rfTjoLgMyDDCdOkRRlhNrY4psEM4uezts2M=" crossorigin="anonymous"></script>
		<script>
			let copyList  = document.querySelectorAll( '.copy-clipboard' );
			let copyArray = Array.prototype.slice.call( copyList );

			function tooltipUpdate( button, tooltip, title ) {
				tooltip.dispose();
				button.setAttribute( 'title', title );
				tooltip = new bootstrap.Tooltip( button );
				tooltip.show();

				return tooltip;
			}

			copyArray.map( function ( copy ) {
				let text    = copy.querySelector( 'span' ).innerText;
				let button  = copy.querySelector( 'i' );
				let tooltip = new bootstrap.Tooltip( button );

				button.addEventListener( 'mouseover', function () {
					tooltip = tooltipUpdate( button, tooltip, 'Скопировать' );
					this.classList.remove( 'bi-clipboard-check' );
					this.classList.add( 'bi-clipboard-plus' );
				} );

				button.addEventListener( 'click', function () {
					window.navigator.clipboard.writeText( text );
					tooltip = tooltipUpdate( button, tooltip, 'Готово!' );
					this.classList.remove( 'bi-clipboard-plus' );
					this.classList.add( 'bi-clipboard-check' );
				} );
			} );
		</script>
	</body>
</html>

Узнайте о том, как подключить Bootstrap к WordPress через CDN.