Javascript - 在 HTML 标签中没有具体 ID 复制到剪贴板

Javascript - Copy to clipboard without concrete Id in HTML tag

在 HTML 页面上,代码标记中应该有多个片段。应该可以通过单击按钮将代码复制到剪贴板。我有一个代码标签的工作代码,使用 ID 对其进行引用。但是,如何更改 JavaScript 代码,以便复制不依赖于代码标记中手动预定义的 ID。当点击某个代码片段的复制到剪贴板按钮时,它应该自动复制预期代码块的内容——同时在页面上有许多其他代码标签具有相同的复制到剪贴板按钮。我的示例显示了一个具有预定义 ID 的代码块。如何避免JS代码中的ID使其独立工作?

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>

您可以将 this 传递给 copy_text() 方法调用,以便您的函数准确知道哪个按钮触发了 onclick event.然后你可以得到它的父容器的元素,假设每个 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>

请注意 document.execCommand 已被 clipboard 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 完全摆脱 id。在以下示例中,我动态生成按钮元素:

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>