Как я могу сделать обычную вставку текста в contentEditable span без нарушения отмены?
Странно заданный вопрос, но у меня есть решение уже вставить обычный текст в <span contentEditable="true">
с помощью скрытого textarea
, который, кажется, работает очень хорошо, за исключением того, что он нарушает функцию отмены браузера. С самого начала я не беспокоюсь о кросс-браузерном решении; Я только забочусь о Chrome. Мой подход выглядит примерно так:
$('.editable').live('paste', function()
{
var $this = $(this);
//more code here to remember caret position, etc
$('#clipboard').val('').focus(); //put the focus in the hidden textarea so that, when the paste actually occurs, it auto-sanitized by the textarea
setTimeout(function() //then this will be executed immediately after the paste actually occurs
{
$this.focus();
document.execCommand('insertHTML', true, $('#clipboard').val());
});
});
Итак, это работает - я могу вставить что угодно, и он сводится к простому тексту, прежде чем перейти в мое поле contentEditable
, но если я попытаюсь отменить после вставки:
- Первая отмена отменяет пасту.
- Вторая отмена отменяет изменения в
#clipboard
, отводя фокус от моего contentEditable
.
Я пробовал все, что мог, чтобы браузер не пытался отменить изменения #clipboard
- переключать display:none
, когда он не активно используется, переключая readonly
и disabled
состояние, уничтожая он в конце и воссоздает его в начале события выше, различные другие хаки - но ничего не работает.
Это ужасный подход к дезинфекции? Это первая вещь, с которой мне удалось действительно работать - попытка очистить разметку после того, как вставка не работает, так как есть некоторые вещи (целые HTML-документы), которые при вставке вызывают крах браузера, который Я бы хотел избежать.
Можно ли отключить #clipboard
или любые другие предложения о том, как это сделать?
Изменить
Мне удалось немного улучшить ситуацию, добавив строку
$('#clipboard').val('');
Сразу после строки execCommand
. Это, похоже, полностью нейтрализует отмену: карет больше не выходит из поля contentEditable
, но ничего не отменяется вообще. Немного улучшения, но я все еще ищу подходящее решение.
Ответы
Ответ 1
CodeMirror 1 делает это, удаляя форматирование после вставки текста. CodeMirror 2 делает это, фактически имея невидимый textarea обрабатывать все, и визуализировать текст и курсор вручную.
Сайт CodeMirror описывает, как он работает более подробно: http://codemirror.net/internals.html
Помимо этого всегда есть исходный код CodeMirror. Вы можете сами решить, подходит ли подход CodeMirror 1 или CodeMirror 2 для ваших целей.:)
Ответ 2
Вы пытаетесь это сделать?
setTimeout(function() //then this will be executed immediately after the paste actually occurs
{
$this.focus();
document.execCommand('insertHTML', true, $('#clipboard').val());
var t = document.body.innerHTML;
document.execCommand("undo");
document.body.innerHTML = t;
});
Я думаю, это может помочь.
Но я думаю, вы должны использовать объект события. К сожалению, может возникнуть проблема, связанная с соображениями безопасности.
Ответ 3
В onpaste:
-
Сохраните текущий выбор.
var sel = window.getSelection();
var range = selObj.getRangeAt(0).cloneRange;
// Store the range object somewhere.
-
Измените объект выделения, чтобы указать на скрытую текстовую область.
-
Установите тайм-аут с задержкой 0 (происходит сразу после вставки).
-
В функции тайм-аута возьмите данные из скрытого текстового поля, а затем:
var sel = window.getSelection();
sel.removeAllRanges();
var range = // restore the range object from before.
sel.addRange(range);
document.execCommand("insertHTML", false, /* contents of your textarea here */);
Теперь, если вы хотите сделать это для фактического содержимого HTML, вы попадете в мир боли.
Ответ 4
Вставьте <pre contenteditable="true">...</pre>
. Насколько я помню, именно то, что я понимаю, вы хотите. (К сожалению, мне еще не разрешено присоединяться ко всем в комментариях, но я полагаю, что это попытка ответить в любом случае.)