JavaScript - 将 p 标签转换为文本区域并将更改的文本复制到剪贴板

JavaScript - Convert p tag to text area and copy changed text to clipboard

如何实现?在 HTML 页面中,有一个包含一些内容的 p 标签(但只有通过   的缩进和换行标签
)。 我想提供两个按钮:一个将p标签转换为文本区域,以便用户可以改编现有内容,一个复制内容(如果内容不改编,则应复制原始内容,如果改编,当然应该复制改编的代码)。 到目前为止,我已经准备了下面的代码。最终的功能应该是(大部分不是 working/implemented 在片段中;解决方案应该只是 JS):

还有什么想法吗?谢谢!

<button onclick="edit(this)">Adapt</button>
<p>some text 1<br>&nbsp;&nbsp;&nbsp;&nbsp;some text 2<br>&nbsp;some text 3&nbsp;&nbsp;some text 4 &amp;&amp; .... <br>&nbsp;&nbsp;..... <br>&nbsp;&nbsp;&nbsp;&nbsp;...... <br>&nbsp;&nbsp;...... <br>...... <br><br></p>
<button title="Copy to clipboard" onclick="copy_text(this)">Copy</button>

<script>
function edit(item) {
    var a = item.nextElementSibling;  
    a.outerHTML = a.outerHTML.replace(/<p>/g, '<textarea style="width: 100%; height: 100px ">').replace(/<\/p>/g, '</textarea>'); 
  }
</script>
<script>
    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);
  };
</script>

StackBlitz

这里测试

我不知道你打算如何找到 p 元素 idclassattribute 但对于这个答案我只是使用了标签.

查看此 了解我使用剪贴板的原因 API

ReplaceWith MDN

let original = '';
const buttons = [...document.querySelectorAll('button')];

function edit(button) {
  let paragraph = button.nextElementSibling.nextElementSibling;
  button.innerText = paragraph.tagName == 'P' ? 'Revert' : 'Adapt';

  if (paragraph.tagName == 'P') {
    original = paragraph.innerHTML;
    const textarea = Object.assign(document.createElement('textarea'), {
      innerHTML: paragraph.innerText, // I use the innerText so that the HTML tags will be stripped but the space and new lines will be kept
      style: 'width: 100%; height: 100px;' // Style for the textarea
    });

    paragraph.replaceWith(textarea); // Replace the p tag directly with the new textarea
  } else {
    const p = Object.assign(document.createElement('p'), {
      innerHTML: original
    });
    
    paragraph.replaceWith(p);
  }
}

function copy_text(button) {
  let paragraph = button.nextElementSibling;
  const str = paragraph.value || paragraph.innerText;

  navigator.clipboard.writeText(str).then(_ => {
    if (paragraph.tagName !== 'P') { // To convert the textarea back to the p
      const p = Object.assign(document.createElement('p'), {
        innerHTML: original // Convert the new lines back to br tag and the spaces to &nbsp
      });
      paragraph.replaceWith(p);
    }

    button.previousElementSibling.innerText = 'Adapt';
    alert('Copied');
  }, e => alert(`Failed: ${e}`));
};

// Event Listeners
buttons.forEach(button => button.addEventListener('click', e => {
  const buttonType = button.innerText.toLowerCase();
  if (['adapt', 'revert'].includes(buttonType)) edit(button);
  else if (buttonType == 'copy') copy_text(button);
}));
<h1>Paragraph 1</h1>
<button>Adapt</button>
<button title="Copy to clipboard">Copy</button>

<p>some text 1<br>&nbsp;&nbsp;&nbsp;&nbsp;some text 2<br>&nbsp;some text 3&nbsp;&nbsp;some text 4 &amp;&amp; .... <br>&nbsp;&nbsp;..... <br>&nbsp;&nbsp;&nbsp;&nbsp;...... <br>&nbsp;&nbsp;...... <br>...... <br><br></p>

<h1>Paragraph 2</h1>

<button>Adapt</button>
<button title="Copy to clipboard">Copy</button>

<p>some text 1<br>&nbsp;&nbsp;&nbsp;&nbsp;some text 2<br>&nbsp;some text 3&nbsp;&nbsp;some text 4 &amp;&amp; .... <br>&nbsp;&nbsp;..... <br>&nbsp;&nbsp;&nbsp;&nbsp;...... <br>&nbsp;&nbsp;...... <br>...... <br><br></p>