На HTML-странице должно быть несколько фрагментов кода в тегах. Должна быть возможность скопировать код в буфер обмена нажатием кнопки. У меня есть рабочий код для одного тега кода, ссылка на который сделана с использованием идентификатора. Однако как изменить код JavaScript, чтобы копирование не зависело от предварительно определенного вручную идентификатора в теге кода. При нажатии кнопки копирования в буфер обмена для определенного фрагмента кода он должен автоматически копировать содержимое предполагаемого блока кода - при наличии многих других тегов кода с такой же кнопкой копирования в буфер обмена на странице. В моем примере показан один блок кода с предопределенным идентификатором. Как избежать идентификатора в JS-коде, чтобы он работал независимо?
function copy_text() {
const str = document.getElementById("copy_code").innerText; const el = document.createElement("textarea");
el.value = str; el.setAttribute("readonly", ""); el.style.position = "absolute";
el.style.left = '-9999px'; document.body.appendChild(el);
el.select(); document.execCommand("copy"); document.body.removeChild(el);
};<code id = "copy_code">some code 1<br>some code 2<br>some code 3</code>
<button onclick = "copy_text()">Copy to clipboard</button>


![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вы можете передать this в вызов метода copy_text(), чтобы ваша функция точно знала, какая кнопка активировала onclickevent. Затем вы можете получить элементы его родительского контейнера, предполагая, что каждый блок code и его button находятся внутри родительского контейнера:
function copy_text(item) {
const str = item.parentNode.querySelector('code').innerText;
const el = document.createElement("textarea");
el.value = str;
el.setAttribute("readonly", "");
el.style.position = "absolute";
el.style.left = '-9999px';
document.body.appendChild(el);
el.select(); document.execCommand("copy");
document.body.removeChild(el);
};<div>
<code>1<br>2<br>3</code>
<button onclick = "copy_text(this)">copy</button>
</div>
<div>
<code>4<br>5<br>6</code>
<button onclick = "copy_text(this)">copy</button>
</div>В случае, если каждый блок code и его button не находятся внутри какого-либо родительского контейнера и вводятся в HTML точно так же, как в вопросе, вы можете использовать
const str = item.previousElementSibling.innerText;
вместо
const str = item.parentNode.querySelector('code').innerText;
function copy_text(item) {
const str = item.previousElementSibling.innerText;
const el = document.createElement("textarea");
el.value = str;
el.setAttribute("readonly", "");
el.style.position = "absolute";
el.style.left = '-9999px';
document.body.appendChild(el);
el.select(); document.execCommand("copy");
document.body.removeChild(el);
};<code>1<br>2<br>3</code>
<button onclick = "copy_text(this)">copy</button>
<br>
<code>4<br>5<br>6</code>
<button onclick = "copy_text(this)">copy</button>Спасибо @ Ivan86. Но что не так? Для обоих в вашем фрагменте 123 копируется в буфер обмена.
@jennab извини, должно быть, я случайно удалил div
@jennab Я отредактировал, чтобы включить фрагмент и для другого случая (элемент кода и кнопка не находятся внутри родительского контейнера).
просто восхитительно. Благодарность!
Во-первых, вам нужно использовать аргумент для передачи этого аргумента через функцию. Также используйте previousElementSibling для нацеливания на предыдущий элемент.
Я продублировал кнопку и скопировал для вас ресурс.
function copy_text(element) {
const str = element.previousElementSibling.innerText;
const el = document.createElement("textarea");
el.value = str; el.setAttribute("readonly", ""); el.style.position = "absolute";
el.style.left = '-9999px'; document.body.appendChild(el);
el.select(); document.execCommand("copy"); document.body.removeChild(el);
};<code id = "copy_code">some code 1<br>some code 2<br>some code 3</code>
<button onclick = "copy_text(this)">Copy to clipboard</button>
<br>
<br>
<code id = "copy_code_two">some code 4<br>some code 5<br>some code 6</code>
<button onclick = "copy_text(this)">Copy to clipboard</button>
<br>
<br>спасибо, но мне это понадобится без вручную определенного идентификатора
@jennab, я исправил решение, указав разные ID для тегов <code>. Рад помочь.
замечательный. Благодарность!
Обратите внимание, что document.execCommand заменяется буфер обмена API.
Просто передайте id элемента, над которым он должен работать, обработчику копирования. Это сохраняет его независимость от структуры DOM и способа размещения кнопки и соответствующего блока кода в DOM относительно друг друга.
function copy_text(id) {
if (!id) return;
const code = document.getElementById(id);
if (!code) return;
if (navigator && navigator.clipboard) { // need to check because it's only available on https and localohost
navigator.clipboard.writeText(code.innerHTML);
}
};<code id = "foo">some code 1<br>some code 2<br>some code 3</code>
<button onclick = "copy_text('foo')">Copy to clipboard</button>
<br/>
<code id = "bar">some code 3<br>some code 4<br>some code 5</code>
<button onclick = "copy_text('bar')">Copy to clipboard</button>
<textarea placeholder = "Try to paste here to see if it works"></textarea>Если структура DOM все равно исправлена (за блоком кода всегда следует кнопка копирования), вы можете полностью избавиться от идентификатора с помощью element.previousElementSibling. В следующем примере я динамически генерирую элементы кнопки:
function copy_text(e) {
const code = e.target.previousElementSibling;
if (!code) return;
if (navigator && navigator.clipboard) { // need to check because it's only available on https and localohost
navigator.clipboard.writeText(code.innerHTML);
}
}
document.addEventListener('DOMContentLoaded', function() {
const snippets = document.querySelectorAll('.copyable-snippet');
for (const snippet of snippets) {
const button = document.createElement('button');
button.type = 'button';
button.textContent = 'Copy to clipboard';
button.addEventListener('click', copy_text);
snippet.parentElement.insertBefore(button, snippet.nextSibling);
}
});<code class = "copyable-snippet">some code 1<br>some code 2<br>some code 3</code>
<code class = "copyable-snippet">some code 3<br>some code 4<br>some code 5</code>
<textarea placeholder = "Try to paste here to see if it works"></textarea>Скажите, пожалуйста, почему ваш код у меня не работает?
navigator.clipboard доступен только в том случае, если страница работает в безопасном контексте (то есть https или localhost), как указано в источнике при проверке if (navigator && navigator.clipboard). В небезопасных ситуациях вам вообще не следует пытаться получить доступ к буферу обмена.
Теперь понятно. Спасибо.
почему бы вам просто не создать отдельные элементы <code> и <button> для каждого кода? или сопоставьте их каким-либо образом и просто добавьте номер индекса к id, например "copy_code_1", "copy_code_2" или что-то в этом роде