Заставить IE contentEditable элемент для создания разрывов строки на клавишу Enter, не нарушая отменить

в Internet Explorer, contentEditable DIV создает новый абзац (<p></p>) каждый раз, когда вы нажимаете Enter, В то время как Firefox создает <br/> тег.

как обсуждалось здесь, можно использовать JavaScript для перехвата нажатия клавиши Enter и использовать диапазон.pasteHTML для создания <br/> вместо. Но это нарушает меню отмены; как только вы нажмете Enter, Вы больше не сможете отменить эту точку.

как я могу заставить элемент contentEditable создать одиночная строка ломается на Enter, не нарушая отмены?

7 ответов


не точное решение, но другое решение. Если вы используете разметку:

<div contenteditable="true">
<div>
content
</div>
<div>
клавишей enter создать новый div теги вместо p теги.

удерживайте shift при нажатии enter для перерывов, не удерживайте его для полных абзацев. Это поведение одинаково по умолчанию в Firefox, учитывая contenteditable область, содержащую абзац: т. е.

<div contenteditable="true">
    <p>If you are typing here</p>
<div>

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

Я также предполагаю, что вы будете знать какие именно элементы DIV будут удовлетворены. Перед отправкой формы вы можете запустить каждый contentEditable div через такую функцию:

function cleanContentEditableDiv(div) {
  var htmlString = div.innerHTML;
  htmlString     = htmlString.replace(/<\/p>/gim,"<br/>");
  htmlString     = htmlString.replace(/<p>/gim,"");
  return htmlString;
}

и вы называете это в цикле (который повторяет все contentEditable DIVs, используя массив, который я буду называть ceDivs), например:

ceDivs[i].contentEditable = false; // to make sure IE doesn't try to coerce the contents again

и затем:

ceDivs[i].innerHTML = cleanContentEditableDiv(ceDivs[i]);

улучшение этого (особенно, если вы не хотите делать это прямо во время отправки), может быть, чтобы очистить содержимое каждого такой div в любое другое время (onblur, что угодно) и назначьте содержимое каждого ceDiv своему невидимому элементу формы для последующего представления. Используется в сочетании с вашим собственным предложением CSS выше, это может сработать для вас. Он не сохраняет ваши буквальные требования к букве (т. е. он не получает Javascript, чтобы заставить IE вести себя иначе, чем он был закодирован под обложками, чтобы вести себя), но для всех практических целей эффект одинаков. Пользователи получают то, что хотят, а вы получаете что ты хочешь.

пока вы на нем, вы также можете очистить строки пространства в IE. Если пользователь вводит несколько пробелов (как некоторые все еще делают после периодов), то IE вставляет не [пробел][пробел], а [пробел], начальный символ пробела (строка.fromCharCode (32)) плюс столько сущностей, сколько осталось в пробеле.


использовать <BR> вместо <P> (протестировано в IE9. Может быть!--3--> требуется в более старых версиях после <BR> (pasteHTML("<br>&nbsp;")) )

используйте его на событии keydown:

if (e.keyCode == 13) {
 var range = document.selection.createRange();
 range.pasteHTML("<br> ");
 range.moveStart("character", 0);
 range.moveEnd("character", -1);
 range.select();
 return false;
}

Это может быть невозможно получить это право. Тем не менее, можно сделать <p> теги посмотреть как разрывы одной строки, удалив встроенное поле вокруг тегов абзаца, используя CSS:

p { margin: 0; }

существует недостаток этого подхода: если пользователю необходимо скопировать / вставить текст в элемент contentEditable, текст может показаться одинарным внутри элемента, но двойным вне элемента.

хуже, по крайней мере в некоторых случаях, т. е. будет автоматически обнаруживать разрывы двойной строки во время вставки, заменяя их на <p> теги; это испортит форматирование вставленного текста.


IE связывает текстовый узел с <p> tag on Enter нажмите клавишу. Для достижения разрыва линии Shift+Enter. В Firefox добавляет <br> tag on Enter нажмите клавишу. Чтобы сделать поведение общим для обоих браузеров, вы можете сделать следующее:

предположим следующую разметку:

<div id="editableDiv" contentEditable="true"></div>

Javascript [предположим, что приведенный ниже код находится в закрытии функции, чтобы вы не раздували страницу globals]:

 (function () {
     //Initialize _shiftKeyPressed to false
     var _shiftKeyPressed = false;
     $('#editableDiv').live('keydown', function (e) {
         if (e.keyCode == 16) {
             // SHIFT key is pressed
             _shiftKeyPressed = true;
         }
     }).live('keyup', function (e) {
         if (e.keyCode == 16) {
             // SHIFT key is release
             _shiftKeyPressed = false;
         }
     }).live('keypress', function (e) {
         if (e.keyCode == 13 && !_shiftKeyPressed && !jQuery.browser.msie) {
             // Insert a PARAGRAPH in Firefox instead of a BR
             // Ignores SHIFT + ENTER
             document.execCommand("insertParagraph", false, true);
         }
     })
 })();

Примечание: этот скрипт предшествует jQuery $.browser


рассмотрите возможность использования <span contenteditable="true"></span> при использовании Internet Explorer. Вы не можете сделать это с Chrome, потому что фокус выглядит смешно. Вы, вероятно, захотите реализовать свой собственный onfocus и onblur код.