Как я могу преобразовать вставленный код HTML в простой текст внутри contentedtiable div, исключая специальные элементы HTML? - PullRequest
0 голосов
/ 25 марта 2020

Я уже давно борюсь с чатом. Моя самая большая проблема, к сожалению, по-прежнему заключается в вводе сообщений, который выполняется с помощью contenteditable div.

К сожалению, у меня проблема в том, что при вставке кода он вставляется в виде кода вместо текста во входных данных, что часто разрушает ввод (например, применяются стили кода). Я пытался найти решение несколько раз, но я все еще не удовлетворен ситуацией. Поэтому я попытался медленно работать над этим вопросом и разработал следующий код:

jQuery(document).ready(function ($) {
    $("#input").on("paste", function (e) {
        let clipboardData, pastedData;

        e.stopPropagation();
        e.preventDefault();

        clipboardData = e.originalEvent.clipboardData || window.clipboardData;
        pastedData = clipboardData.getData("text");
        pastedData = pastedData.replace(/\t/g, "    ");
        pastedData = pastedData.replace(/<\s*([^\s>]+)(?:(?!\bclass="emoji")[^>])*>(.*?)(?:<\/\1>)|<\s*([^\s>]+)(?:(?!\bclass="emoji")[^>])*\/>/g, "$2");

        $("#input").html($("#input").html() + pastedData);
        placeCaretAtEnd($("#input")[0]);
    });
});

function placeCaretAtEnd(el) {
    el.focus();

    if (typeof window.getSelection !== "undefined" && typeof document.createRange !== "undefined") {
        let range = document.createRange();

        range.selectNodeContents(el);
        range.collapse(false);

        let sel = window.getSelection();

        sel.removeAllRanges();
        sel.addRange(range);
    } else if (typeof document.body.createTextRange !== "undefined") {
        let textRange = document.body.createTextRange();

        textRange.moveToElementText(el);
        textRange.collapse(false);
        textRange.select();
    }
}
[contenteditable=true] {
  border: 1px solid #aaaaaa;
  padding: 8px;
  border-radius: 12px;
  margin-bottom: 20px;
  white-space: pre-wrap;
  word-wrap: break-word;
}

.emoji {
  font-family: -apple-system, Segoe UI, Apple Color Emoji, Segoe UI Emoj, system-ui;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="input" contenteditable="true" spellcheck="true"></div>

С тех пор, как я создал свой чат как WhatsApp Web, у меня также есть смайлики, которые находятся в объекте-обертке. Этот объект не следует заменять при вводе при вставке, чего я мог бы достичь с помощью кода выше. Как только я вставлю следующий код, он будет вставлен как код, а не как текст:

<span class="emoji" contenteditable="false">?</span>

Но если я сейчас вставлю некоторый код, HTML удаляется вместо вставленного в виде простого текста:

This element shows you how it works <span class="emoji" contenteditable="false">?</span> <div class="insert-me-as-text">I need to be a text</div>

Таким образом, код становится:

This element shows you how it works ? I need to be a text

Но в итоге должно выглядеть так:

enter image description here enter image description here

А также нажатие Ctrl + Z должно работать снова.

1 Ответ

1 голос
/ 25 марта 2020

Попробуйте заменить элемент .insert-me-as-text на закодированный HTML

$('<div>').text('<div>...</div>').html() // encodes HTML as string

jQuery(document).ready(function($) {
  $("#input").on("paste", function(e) {
    let clipboardData, pastedData;

    e.stopPropagation();
    e.preventDefault();

    clipboardData = e.originalEvent.clipboardData || window.clipboardData;
    pastedData = clipboardData.getData("text");
    pastedData = pastedData.replace(/\t/g, "    ");
    
    let $wrap = $('<div/>').html(pastedData);    
    $wrap.find('.insert-me-as-text').replaceWith(function() {
      return $('<div>').text(this.outerHTML).html()
    })

    $("#input").html($("#input").html() + $wrap.html());
    placeCaretAtEnd($("#input")[0]);
  });
});

function placeCaretAtEnd(el) {
  el.focus();

  if (typeof window.getSelection !== "undefined" && typeof document.createRange !== "undefined") {
    let range = document.createRange();

    range.selectNodeContents(el);
    range.collapse(false);

    let sel = window.getSelection();

    sel.removeAllRanges();
    sel.addRange(range);
  } else if (typeof document.body.createTextRange !== "undefined") {
    let textRange = document.body.createTextRange();

    textRange.moveToElementText(el);
    textRange.collapse(false);
    textRange.select();
  }
}
[contenteditable=true] {
  border: 1px solid #aaaaaa;
  padding: 8px;
  border-radius: 12px;
  margin-bottom: 20px;
  white-space: pre-wrap;
  word-wrap: break-word;
}

.emoji {
  font-family: -apple-system, Segoe UI, Apple Color Emoji, Segoe UI Emoj, system-ui;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="input" contenteditable="true" spellcheck="true"></div>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...