Вставка в приемлемые результаты при случайной вставке тега

Я использую поле contentedittable в качестве пользовательского ввода, чтобы я мог использовать форматирование текста. К сожалению, я обнаружил, что когда пользователь вставляет в поле, появляется огромное количество ненужных HTML. Я хочу только простой текст из буфера обмена.

Почему это происходит?!

Усеченный пример:

<div><br></div><div><span class="Apple-style-span" style="font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; font-size: 13px; line-height: 12px; color: rgb(0, 0, 0); "><table style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 13px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; border-collapse: collapse; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; background-position: initial initial; background-repeat: initial initial; "><tbody style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 13px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; background-position: initial initial; background-repeat: initial initial; "><tr style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 13px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; background-position: initial initial; background-repeat: initial initial; "><td class="votecell" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 13px; vertical-align: top; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; width: 60px; background-position: initial initial; background-repeat: initial initial; "><div class="vote" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 13px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; text-align: center; background-position: initial initial; background-repeat: initial initial; "><span class="vote-count-post" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 31px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; display: block; color: rgb(128, 129, 133); font-weight: bold; background-position: initial initial; background-repeat: initial initial; ">1</span><a class="vote-down-off" title="This question does not show any research effort; it is unclear or not useful (click again to undo)" style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 1px; vertical-align: baseline; background-image: url(http://sstatic.net/stackru/img/sprites.png?v=3); background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: rgb(0, 119, 204); text-decoration: none; cursor: pointer; overflow-x: hidden; overflow-y: hidden; display: block; width: 41px; height: 25px; text-indent: -9999em; background-position: 0px -300px; background-repeat: no-repeat no-repeat; ">...

2 ответа

Вы можете получить только простой текст, используя взломать. Последние версии как TinyMCE, так и CKEditor используют эту технику в своих редакторах на основе iframe:

  1. Определить событие Ctrl-v / Shift-Insert с помощью обработчика события нажатия клавиши
  2. В этом обработчике сохраните текущее выделение пользователя, добавьте элемент texttarea за пределы экрана (скажем, слева -1000 пикселей) в документ, поверните contentEditable выключи и позвони focus() на текстовой области, таким образом перемещая каретку и эффективно перенаправляя пасту
  3. Установите очень короткий таймер (скажем, 1 миллисекунду) в обработчике событий для вызова другой функции, которая хранит значение текстовой области, удаляет текстовую область из документа, поворачивает contentEditable обратно, восстанавливает выбор пользователя и вставляет текст в.

Обратите внимание, что это будет работать только для событий вставки с клавиатуры, но не для вставки из контекстного меню или меню редактирования. paste Событие было бы лучше, но к тому времени, когда оно запускается, уже слишком поздно перенаправлять каретку в текстовую область в большинстве браузеров.

Вы получаете всю эту дополнительную ерунду, потому что contenteditable элемент поддерживает text/html MIME тип. Когда вы вставляете что-то из буфера обмена, часто возникает фаза согласования контента:

  • Цель вставки говорит: "Я поддерживаю следующие типы контента:...."
  • Затем менеджер буфера обмена обсуждает этот список с источником данных, чтобы получить вставленные данные в подходящем формате для цели вставки.
  • И, наконец, данные сбрасываются в ваш contenteditable элемент как text/html со всем этим дополнительным шумом.

Процесс может быть не совсем таким, как описано выше, но он будет похожим. Ваша лучшая ставка, вероятно, добавит обработчик для paste событие и использовать этот обработчик для преобразования вставленных данных в text/plain,

Другие вопросы по тегам