Работа с разрывами строк в contentEditable DIV

У меня проблема с contenteditable разрывами строк в SAFARI / CHROME. Когда я нажимаю "возврат" в contentEditable <div>, вместо создания <br> (например, Firefox) они создают новый <div>:

<div>Something</div>
<div>Something</div>

Это выглядит так (на contentEditable DIV):

Something
Something

Но после дезинфекции (удаления <div>) получаю следующее:

SomethingSomething

В Firefox contenteditable:

Something
<br>
Something

И это после дезинфекции выглядит так же:

Something
Something

Есть ли какое-нибудь решение "нормализовать" это в браузерах?

Я нашел этот код на Сделайте ‹br› вместо ‹div› ‹/div›, нажав Enter на контентном планшете.

$(function(){

  $("#editable")

  // make sure br is always the lastChild of contenteditable
  .live("keyup mouseup", function(){
    if (!this.lastChild || this.lastChild.nodeName.toLowerCase() != "br") {
      this.appendChild(document.createChild("br"));
     }
  })

  // use br instead of div div
  .live("keypress", function(e){
    if (e.which == 13) {
      if (window.getSelection) {
        var selection = window.getSelection(),
          range = selection.getRangeAt(0),
          br = document.createElement("br");
        range.deleteContents();
        range.insertNode(br);
        range.setStartAfter(br);
        range.setEndAfter(br);
        range.collapse(false);
        selection.removeAllRanges();
        selection.addRange(range);
        return false;
      }
    }
  });
});

Это работает, но (в SAFARI и CHROME) мне нужно дважды нажать клавишу «возврат», чтобы получить новую строку ...

Любая идея?

Изменить: код, который я нашел (внизу этого вопроса), работает нормально, за исключением функции, которая «гарантирует, что элемент <br> всегда является последним ребенком ... Есть идеи, как это исправить?

Изменить 2: Я получаю эту ошибку на консоли: Uncaught TypeError: Object #<HTMLDocument> has no method 'createChild'

Редактировать 3: Хорошо, я изменил document.createChild("br"); на document.createElement("br");, и я думаю, что он работает в FF / Safari / Chrome ... Все возвращают <br> для новых строк ...

Проблема в том, что когда я нахожусь в упорядоченном или неупорядоченном списке, мне нужно получить новую строку без _18 _...

Редактировать 4: Если кого-то интересует решение последнего редактирования: Избегайте использования функции createElement, если она находится внутри элемента ‹LI› (contentEditable)


person Santiago    schedule 16.05.2011    source источник
comment
как выглядит ваш метод дезинфекции?   -  person MikeM    schedule 17.05.2011
comment
@mdmullinax Он просто удаляет все ‹div› ... Я использую github.com/gbirke/Sanitize .js Проблема в том, что Safari / Chrome, когда я нажимаю return, они просто создают новый DIV вместо того, чтобы создавать ‹BR›, как Firefox   -  person Santiago    schedule 17.05.2011
comment
Возможно, вы можете использовать $ (div: empty) .replaceWith (‹br/›);   -  person Anders Lindén    schedule 05.08.2012
comment
Нашли ли вы что-нибудь полезное из-за ошибки двух клавиш возврата? Я столкнулся с той же проблемой, единственное, что я, кажется, могу сделать, это взломать (добавить пустой текст и выбрать его, чтобы, если вы продолжите писать, он автоматически исчезнет), я буду размещать в этой теме на всякий случай. Это не идеально, но работает.   -  person Micaël Félix    schedule 18.10.2012
comment
Теперь у Firefox есть гибридный подход: он оборачивает ‹br› внутри ‹div›. Это заставляет его вести себя аналогично Chrome, я думаю, потому что response полностью удаляет ‹div›, включая ‹br›.   -  person trysis    schedule 18.01.2019


Ответы (8)


Этот метод, по-видимому, позволяет избежать ошибки Chrome, которая показывает BR в первый раз (с кодом, который вы упомянули, вам нужно дважды нажать клавишу Enter).

Это не идеальный взлом, но он работает: он добавляет пробел после вашего BR, чтобы он отображался правильно. Однако вы увидите, что добавление только пробела "" ничего не изменит, это работает с другими буквами. Браузер не покажет это, вероятно, потому что это как пустое место внутри html-страницы, это просто ничего не значит. Чтобы избавиться от этой ошибки, я создал div с помощью jQuery, который включает тег &nbsp;, и я беру свойство text(), чтобы поместить его в текстовый узел, иначе это не сработает.

$editables = $('[contenteditable=true]');

$editables.filter("p,span").on('keypress',function(e){
 if(e.keyCode==13){ //enter && shift

  e.preventDefault(); //Prevent default browser behavior
  if (window.getSelection) {
      var selection = window.getSelection(),
          range = selection.getRangeAt(0),
          br = document.createElement("br"),
          textNode = document.createTextNode("\u00a0"); //Passing " " directly will not end up being shown correctly
      range.deleteContents();//required or not?
      range.insertNode(br);
      range.collapse(false);
      range.insertNode(textNode);
      range.selectNodeContents(textNode);

      selection.removeAllRanges();
      selection.addRange(range);
      return false;
  }

   }
});
person Micaël Félix    schedule 18.10.2012
comment
Добавить range.deleteContents (); перед selection.removeAllRanges (); чтобы избавиться от этих надоедливых вещей, сохранив при этом всю работу ^^ - person seahorsepip; 06.10.2014
comment
Добавление document.execCommand ('delete') непосредственно перед возвратом false делает трюк и не показывает выделенный выбор пробелов. - person SomberTuna; 27.06.2018

Прослушивание нажатий клавиш кажется большой работой. Возможно ли такое простое:

var html = $('.content').html().replace(/<div>/gi,'<br>').replace(/<\/div>/gi,'');

Демо JSFiddle здесь.

Кроме того, похоже, что sanitize.js допускает индивидуальную конфигурацию. Вы пробовали добавить div в качестве разрешенного элемента?

Разрешить HTML / CSS опасно, поэтому будьте особенно осторожны.

РЕДАКТИРОВАТЬ: удалены комментарии на стороне сервера. Санитарная обработка происходит во время использования - если клиент хочет обойти это локально, это может быть сделано на его страх и риск. Благодарим Винсента Макнабба за указание на это.

person Kurt    schedule 05.08.2012
comment
Похоже, что дезинфекция выполняется в целях отображения, а не в целях безопасности, и в этом случае вполне разумно провести ее на клиенте. Они могут обойти его, если захотят, и все, что он сделает, это заставит их выглядеть уродливо для них. - person Vincent McNabb; 10.12.2013
comment
Я считаю, что дезинфекция выполняется в целях безопасности во время использования (например, удаление небезопасных токенов для вывода HTML). Вы прекрасно замечаете, что если клиент хочет обойти это локально, это может быть сделано на его страх и риск. - person Kurt; 18.01.2015

Вы можете просто использовать следующую команду document.execCommand('insertHTML',false,'<br>');

Эта команда предотвратит поведение по умолчанию и добавит желаемый тег. Все, 1 строчка кода

И даже более простой подход.

ТОЛЬКО CSS.

К вам contenteditable element примените display:inline-block rule, и это добавит только br s

person Karb    schedule 06.12.2017
comment
Этот подход css потрясающий! Приветствую @Karb - person nevada_scout; 27.09.2018
comment
Ни одно из этих двух решений не работает для меня. Пробовал с нажатиями клавиш, нажатиями клавиш и клавишами, а также с этими двумя решениями одновременно. Но Firefox все еще создает DIVS: / - person Loarg Ann; 15.05.2019

Webkits не будет отображать один br, если это последний (непустой) дочерний элемент контейнера. Для Safari обычное нажатие клавиш для вставки разрыва строки - Ctrl + Return. Если вы присмотритесь, то заметите, что Safari на самом деле вставляет два br при визуализации только одного; однако он вставит одиночный br, если есть некоторый завершающий текст, или избавится от двойных br, когда вы введете какой-то (если были двойные).

По-видимому, решение для Webkits состоит в том, чтобы вставить двойные br, как они сами, и позволить им справиться с остальным.

person Klim Lee    schedule 12.03.2013

Возможно, вы захотите проверить свойство css white-space. Установка стиля на white-space: pre-wrap позволяет избавиться от всего этого javascript, потому что он изменяет поведение пробелов для отображения вместо сворачивания.

И посмотрите этот ответ: HTML - символ новой строки в редактируемом содержимом DIV?

person B T    schedule 13.08.2014
comment
Эта проблема по-прежнему возникает независимо от того, какое пустое пространство установлено, это связано с contentEditable. - person rtaft; 06.09.2017


Вы можете использовать:

document.execCommand("defaultParagraphSeparator", false, "br");

Полная ссылка находится здесь

person Saeed    schedule 18.07.2019

Вариант использования обычно возникает, когда вы предварительно заполняете данные в редактируемом содержимом div и повторно отправляете их на сервер.

Например. - Подобно редактированию сообщения на веб-сайте социальной сети, чтобы смягчить это, я создал новый div для каждой новой строки.

let conD =data.postDescription.split('\n');
let conH = "";
conD.forEach((d)=>{
        conH +=`<div>${d}</div>`;
       });
$("#contentbox").html(conH);
person Moonis Abidi    schedule 22.03.2021