Запретить удаление всех тегов <li> в редактируемом содержимом <ul>

Когда вы полностью переместитесь в начало тега <li> в теге <ul>, редактируемом для контента, все остальные теги <li> будут удалены.

<ul contenteditable="true">
    <li>Hello</li>
    <li>World</li>
</ul>

jsfiddle: http://jsfiddle.net/8Q53V/

Поместите курсор после "d" в мире и обратно на весь путь до начала строки. Когда вы снова нажмете backspace, он также удалит элемент списка "Hello". Как вы можете предотвратить это поведение?

UPDATE: похоже, что это поведение существует только в Chrome

Ответ 1

Вот что я нашел:

Отброшенное поведение контентных списков в Opera и Chrome происходит только в том случае, если за родительским элементом ul не следует какой-либо другой элемент с минимальным размером рендеринга 1px x 1px. Значение display элемента не имеет значения, если оно не пустое или имеет размер высоты установки с CSS.

Таким образом, добавление простого <div style="height: 1px;"> ответит на ваш самый прямой вопрос.

Однако вы не можете надежно использовать contenteditable списки в HTML во время запроса.

Этот вопрос заинтриговал меня, и я тестировал его на Moz FF 29-30, Opera 21, Google Chrome 35 и IE 11, на Win 8.1. Я тестировал простые клавиши типа Enter, Backspace и Delete.

TL; DR: IE 11 полностью испорчен, Opera и Chrome очень хороши, если за ul следует элемент с отображенным размером, а Moz FF вставляет странный <br type="_moz"></br> тег. Вам понадобится e.preventDefault(), e.keyCode/charCode и Selection и Range JS API для создания настраиваемого списка контента, который будет работать последовательно во всех браузерах. Однако эти предварительные требования уже не работают последовательно во всех браузерах. Лучшее решение: используйте существующие редакторы или невидимый ввод текста для ввода.

Это подробные сведения:


Нажатие Enter для добавления нового li добавит следующую разметку:

  • Opera и Google Chrome: <li><br><li>
  • Moz FF: <li><br type="_moz"></br>
  • IE 11: если активный li не пуст: <li><br></li>, если он пуст, IE полностью запутывает и вставляет p, а затем дублирует пустой <ul contenteditable=""> после него, только с <br> тег внутри. Этот пустой ul будет добавлен после элемента, следующего за исходным элементом, если таковой имеется.

Нажатие Backspace для удаления li:not(:first-child) сделает следующее:

  • Opera и Google Chrome: если за ul не будет следовать элемент с размером рендеринга, все li будут удалены. Если это так, ожидается ожидаемое поведение. (удаляется один li).
  • Moz FF: ожидается ожидаемое поведение (удаляется один li). Однако Moz FF выведет курсор из области, пригодной для контента, после удаления li.
  • IE 11: То же поведение, что и при нажатии Enter.

Нажатие Backspace для удаления первой li должно быть предотвращено любой ценой.

Для каждого проверенного браузера это разбивает список. Все новые образы Enter генерируют div как прямые дочерние элементы списка.


Нажатие Delete для удаления последующего li работает последовательно во всех проверенных браузерах. Последующий li будет удален, и любое содержимое внутри него будет перенесено в текущий li


Ввод первой буквы в пустой li будет делать следующее:

  • Opera, IE11 и Google Chrome: письмо печатается. Автоматически вставленный тег <br> удаляется.
  • Moz FF: письмо печатается. Пользовательский тег <br type="_moz"> удален не.

Удаление единственной буквы в пустой li сделает следующее:

  • Opera, IE11 и Google Chrome: добавлен другой тег <br>.
  • Moz FF: Ничего. Пользовательский <br type="_moz"> все еще присутствует.

Fiddle: http://jsfiddle.net/8Q53V/8/ (первая строка ul с пользовательским кодированным поведением, не совершенная, вторая ul является стандартной)

Ответ 2

Вам нужно использовать contenteditable для каждого тега li

Демо

Если вы не хотите назначать атрибут самостоятельно, вы можете использовать Javascript setAttribute(), который позаботится об этом - ( Вы отметили Javascript в своем вопросе, поэтому я предполагаю, что вы открыты для решения Javascript)

var elm = document.querySelectorAll('ul li');
for (var i=0; i < elm.length; i++) {
    elm[i].setAttribute("contenteditable", "true");
}

Демо (присвоение атрибута с помощью Javascript)

Просто возьмите записку здесь, селектор, использующий в querySelectorAll(), является слишком общим, будет соответствовать всем элементам ul в ваш документ, поэтому, если вы хотите создать определенную группу элементов li для редактирования, чем назначить class или id вашему элементу ul и соответствующим образом определить уникальный селектор.

Если вы хотите, чтобы несколько ul li редактировались, было бы лучше определить class вместо id, поскольку id должен быть уникальным... Таким образом, было бы громоздко определить уникальный каждый раз, когда вы хотите, чтобы группа li была доступна для редактирования.