防止Chrome在将HTML粘贴到contenteditable中时设置字体大小
P粉398117857
P粉398117857 2024-02-26 12:55:05
0
2
458

重现:

  1. 在 Firefox 桌面版和 Chrome 桌面版上运行 MVCE 代码段。
  2. 打开 FF 桌面,然后从源代码中复制“foobar”。
  3. 打开 Chrome 桌面,然后粘贴到目标(here: 中的冒号后面)

window.onload = function() {
  const info = document.querySelector('.info'),
    pinfo = document.querySelector('.paste-info'),
    target = document.querySelector('.target');
  setInterval(() => {
    const sel = ".source *, .target *"
    info.innerHTML = '';
    for (const elm of [...document.querySelectorAll(sel)]) {
      info.innerHTML += "TAG: " + elm.tagName + "; TEXT: " + elm.innerText +  "; FONTSIZE: " + window.getComputedStyle(elm)['font-size'] + "<br>";
    }
  }, 1000);
  target.addEventListener('paste', function(e) {
    pinfo.innerHTML += "PASTE HTML: <pre>" + e.clipboardData.getData('text/html').replaceAll('<', '<').replaceAll('>', '>') + '</pre><br>';
  });
};
div[contenteditable] {
  border: 1px solid black;
}
<div class="source" contenteditable=true>Source text: <b>foobar</b></div>

<div style="font-size: 14px">
  <div contenteditable=true class="target">Destination, <h1>paste here:</h1></div>
</div>

<div class="info"></div>
<div class="paste-info"></div>

您会注意到:

  1. 剪贴板数据包含 <b>foobar</b> (请参阅 PASTE HTML: 之后的内容),但是...
  2. 实际粘贴的 HTML 在 b 元素上设置了 style="font-size: 14px;" (14px 大小来自 contenteditable 的父级)。

我希望粘贴的 HTML 上没有设置任何字体大小,因为它们没有在源剪贴板数据中指定。

问题:当源 HTML 上没有字体大小时,如何强制 Chrome 不在粘贴的 HTML 上放置任何字体大小?

我尝试了一种解决方法:在源上设置 font-size: unset/revert ,但这会导致 font-size: unset 也出现在粘贴的 HTML 中。我不想在粘贴的 HTML 中出现任何字体大小。


此代码的上下文是 Chrome 扩展,我控制粘贴到目标中的文本/html 数据。我可以在目标 contenteditable 上附加粘贴事件侦听器,但在粘贴内容后我无法更改内容的 HTML/样式。

P粉398117857
P粉398117857

全部回复(2)
P粉668113768

也许可以拦截粘贴事件,并更改粘贴的内容以强制使用js将其粘贴为纯文本。

我在 contenteditable div 上添加了 id="editor" 的 id。并添加以下js代码:

const editorEle = document.getElementById('editor');

// Handle the paste event
editorEle.addEventListener('paste', function (e) {
    // Prevent the default action
    e.preventDefault();

    // Get the copied text from the clipboard
    const text = e.clipboardData
        ? (e.originalEvent || e).clipboardData.getData('text/plain')
        : // For IE
        window.clipboardData
        ? window.clipboardData.getData('Text')
        : '';

    if (document.queryCommandSupported('insertText')) {
        document.execCommand('insertText', false, text);
    } else {
        // Insert text at the current position of caret
        const range = document.getSelection().getRangeAt(0);
        range.deleteContents();

        const textNode = document.createTextNode(text);
        range.insertNode(textNode);
        range.selectNodeContents(textNode);
        range.collapse(false);

        const selection = window.getSelection();
        selection.removeAllRanges();
        selection.addRange(range);
    }
});

这是它运行的一个片段。让我知道这是否解决了您的问题:

const editorEle = document.getElementById('editor');

// Handle the `paste` event
editorEle.addEventListener('paste', function (e) {
    // Prevent the default action
    e.preventDefault();

    // Get the copied text from the clipboard
    const text = e.clipboardData
        ? (e.originalEvent || e).clipboardData.getData('text/plain')
        : // For IE
        window.clipboardData
        ? window.clipboardData.getData('Text')
        : '';

    if (document.queryCommandSupported('insertText')) {
        document.execCommand('insertText', false, text);
    } else {
        // Insert text at the current position of caret
        const range = document.getSelection().getRangeAt(0);
        range.deleteContents();

        const textNode = document.createTextNode(text);
        range.insertNode(textNode);
        range.selectNodeContents(textNode);
        range.collapse(false);

        const selection = window.getSelection();
        selection.removeAllRanges();
        selection.addRange(range);
    }
});




window.onload = function() {
  const info = document.querySelector('.info'),
    pinfo = document.querySelector('.paste-info'),
    target = document.querySelector('.target');
  setInterval(() => {
    const sel = ".source *, .target *"
    info.innerHTML = '';
    for (const elm of [...document.querySelectorAll(sel)]) {
      info.innerHTML += "TAG: " + elm.tagName + "; TEXT: " + elm.innerText +  "; FONTSIZE: " + window.getComputedStyle(elm)['font-size'] + "
"; } }, 1000); target.addEventListener('paste', function(e) { pinfo.innerHTML += "PASTE HTML:
" + e.clipboardData.getData('text/html').replaceAll('', '>') + '

'; }); };
div[contenteditable] {
  border: 1px solid black;
}
Source text: foobar
Destination,

paste here:

P粉658954914

您可以使用 选择API
步骤是

  • 在粘贴事件处理程序中,获取表示当前选择的 Range 对象。
  • 使用此 Range 对象将粘贴的 HTML 标记解析为 DocumentFragment 对象,这要归功于 createContextualFragment()方法。
  • 删除之前选择的内容 (Range#deleteContents() ).
  • 插入我们在以下位置创建的 DocumentFragment 对象第2步,光标所在位置。
  • 折叠当前 Range 对象,以便光标移至新粘贴内容的末尾。

手动执行所有这些步骤将阻止浏览器“智能”处理富文本内容;仅解析剪贴板中的内容。

window.onload = function() {
  const info = document.querySelector('.info'),
    pinfo = document.querySelector('.paste-info'),
    target = document.querySelector('.target');
  setInterval(() => {
    const sel = ".source *, .target *"
    info.innerHTML = '';
    for (const elm of [...document.querySelectorAll(sel)]) {
      info.innerHTML += "TAG: " + elm.tagName + "; TEXT: " + elm.innerText +  "; FONTSIZE: " + window.getComputedStyle(elm)['font-size'] + "
"; } }, 1000); target.addEventListener('paste', function(e) { pinfo.innerHTML += "PASTE HTML:
" + e.clipboardData.getData('text/html').replaceAll('', '>') + '

'; e.preventDefault(); const 标记 = e.clipboardData.getData("text/html") || e.clipboardData.getData(“文本/纯文本”); const sel = getSelection(); const range = sel.getRangeAt(0); const frag = range.createContextualFragment(markup); 范围.deleteContents(); 范围.insertNode(frag); 范围.collapse(); }); };
div[contenteditable] {
  border: 1px solid black;
}
Source text: foobar
Destination,

paste here:

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板