【问题标题】:JavaScript - Convert p tag to text area and copy changed text to clipboardJavaScript - 将 p 标签转换为文本区域并将更改的文本复制到剪贴板
【发布时间】:2021-04-13 10:29:42
【问题描述】:

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

  • 点击复制:如果未改编,则复制更改的内容或原始内容
  • 点击适配:将p标签变成文本区域,用户可以对文本进行适配
  • 文本区域应保留原始格式:缩进和换行,但不应显示 HTML 标记(例如
    )
  • 当点击复制后复制改编的内容时,文本区域应该消失,并且应该重新显示原始内容(原来的p标签,而不是文本区域),即所有更改都应该恢复
  • 当单击 Adapt 然后再次单击 Adapt 时,所有更改都应还原并再次显示原始 p(否则,文本区域在页面重新加载之前不会消失)。思路:当 Adapt 按钮被点击时,按钮的名称应该变成类似“Revert”的名称,点击“Revert”后,原来的 p 和“Adapt”按钮可以再次显示。
  • 如何首先放置复制按钮,然后将调整按钮放置在它旁边?那么如何引用 p 标签呢?它必须在没有预定义 ID 的情况下工作。

还有什么想法吗?谢谢!

<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>

【问题讨论】:

    标签: javascript replace textarea clipboard


    【解决方案1】:

    在StackBlitz这里测试它

    我不知道您打算如何找到 p 元素、id 或 class 或 attribute,但对于这个答案,我只使用了标签。

    查看answer 了解我使用剪贴板 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>

    【讨论】:

    • 非常接近。谢谢。 1.没有变化,只是复制:剪贴板文本=“未定义”。 2.调整内容,复制,很好。但是一旦点击了复制按钮,显示的内容也应该恢复为原始代码 3.按钮可以没有ID吗?为什么:相同的按钮不止一次出现(页面上的几个类似这样的文本 sn-ps,每个都应该像这样适应和复制)。 4. 在页面上多次使用相同的代码:document.querySelector('p');很可能不适用于我的目的。有没有机会通过 nextElementSibling 等来实现它?你能支持吗?
    • No change, just Copy: clipboard text = "undefined"是什么意思那么在什么情况下内容会发生变化呢?是的,我们可以使用nextElementSibling。看我链接的链接
    • 那么当你点击copy按钮的时候,是不是要复制框中的文字,然后再还原成原来的样子?或复制原件并仍还原为原件
    • 当我转移您的 sn-p 并运行它时(使用 jsfiddle 和其他人,我看到由于某些问题“失败:NotAllowedError:剪贴板 API 已被阻止,因为权限策略应用于当前文档”),然后我立即单击复制而不先单击调整(假设随后复制了原始的、未调整的代码),剪贴板中的内容不是预期的内容。它只是将“未定义”作为文本吐出
    • 太好了,a.mola!非常感谢您的热心帮助和专业知识!
    猜你喜欢
    • 2021-01-11
    • 1970-01-01
    • 2015-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-01
    • 2017-11-20
    • 1970-01-01
    相关资源
    最近更新 更多