搜尋

首頁  >  問答  >  主體

防止Chrome在將HTML貼到contenteditable時設定字體大小

重現:

  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粉398117857P粉398117857277 天前461

全部回覆(2)我來回復

  • P粉668113768

    P粉6681137682024-02-27 11:16:48

    也許可以攔截貼上事件,並更改貼上的內容以強制使用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');
    
    // 處理`paste`事件
    editorEle.addEventListener('貼上', function (e) {
        // 阻止預設操作
        e.preventDefault();
    
        // 取得剪貼簿中複製的文本
        常數文字 = e.clipboardData
            ? (e.originalEvent || e).clipboardData.getData('text/plain')
            : // 對於 IE
            視窗.剪貼簿數據
            ? window.clipboardData.getData('文字')
            : '';
    
        if (document.queryCommandSupported('insertText')) {
            document.execCommand('insertText', false, 文字);
        } 別的 {
            // 在插入符號的目前位置插入文字
            const range = document.getSelection().getRangeAt(0);
            範圍.deleteContents();
    
            const textNode = document.createTextNode(text);
            range.insertNode(textNode);
            range.selectNodeContents(textNode);
            範圍.折疊(假);
    
            const Selection = window.getSelection();
            選擇.removeAllRanges();
            選擇.addRange(範圍);
        }
    });
    
    
    
    
    視窗.onload = 函數() {
      const info = document.querySelector('.info'),
        pinfo = document.querySelector('.paste-info'),
        目標 = document.querySelector('.target');
      設定間隔(()=> {
        const sel =“.源*,.目標*”
        訊息.innerHTML = '';
        for (const elm of [...document.querySelectorAll(sel)]) {
          info.innerHTML = "TAG: " elm.tagName "; TEXT: " elm.innerText "; FONTSIZE: " window.getCompulatedStyle(elm)['font-size'] "
    "; } }, 1000); target.addEventListener('貼上', 函數(e) { pinfo.innerHTML = "貼上 HTML:
    " e.clipboardData.getData('text/html').replaceAll('<', '<').replaceAll('>', '>') '

    '; }); };
    div[內容可編輯] {
      邊框:1px 純黑;
    }
    來源文字:foobar
    #
    目的地,

    貼在這裡:

    回覆
    0
  • P粉658954914

    P粉6589549142024-02-27 00:36:47

    您可以使用 選擇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('<', '<').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:

    #

    回覆
    0
  • 取消回覆