Как заставить разрывать строку в Firefox ContentEditable

У меня есть JavaScript-редактор WYSIWYG (не похож на CKEditor), запущенный на сайте.

У него есть параметр, который заставляет IE создавать разрывы строк, когда вы нажимаете Enter в редакторе.

Это отлично работает, но, к сожалению, Firefox (я тестировал 5 и 7) все равно генерирует элементы

и генерирует только s, только если вы используете Shift + Enter .

Есть ли способ заставить Firefox всегда генерировать элементы в contentEditable?

От взгляда на стандарты, похоже, что это действие – это способ, которым он должен быть обработан. Блоки прерываются, если модификатор не установлен на клавишу ввода, и используются при нажатии shift. [ Источник ].

Тем не менее, это не решает вашу проблему, поэтому давайте работать над этим. Эта строка должна делать

 document.execCommand('insertBrOnReturn', false, true); 

Установите его так, чтобы, когда вы просто нажимали return, он помещает только тег. Это поддерживается только FF , поэтому это не должно влиять на IE. Однако не знаю о других браузерах.

Примечание. Если пользователь нажимает Enter во второй раз, не набирая ничего, он создает новый абзац абзаца, вне зависимости от того, что. Чтобы предотвратить это, вы можете поймать Enter, используя событие keypress и остановить его, или вы можете вставить   прежде чем продолжить мероприятие (что я рекомендую).

Жесткая часть для вас с этой запиской проверяет состояние элемента при keypress . Ленивое решение (и тот, который я бы рекомендовал, если это не важно, чтобы это не делать) заключается в том, чтобы просто вставить его перед каждым клавишей Enter . Если вы хотите сделать это другим способом, я бы проверил элемент .innerHTML для элемента и посмотрел, будут ли последние несколько символов (без обрезки содержимого)
(так что, возможно, регулярное совпадение на /\
$/
).

Учти это:

HTML:

 

CSS:

 #input { border: 3px solid #07c; width: 300px; height: 200px; white-space: pre; } 

JavaScript:

 $( input ).keypress( function ( e ) { var sel, node, offset, text, textBefore, textAfter, range; sel = window.getSelection(); // the node that contains the caret node = sel.anchorNode; // if ENTER was pressed while the caret was inside the input field if ( node.parentNode === input && e.keyCode === 13 ) { // prevent the browsers from inserting 
,

, or
on their own e.preventDefault(); // the caret position inside the node offset = sel.anchorOffset; // insert a '\n' character at that position text = node.textContent; textBefore = text.slice( 0, offset ); textAfter = text.slice( offset ) || ' '; node.textContent = textBefore + '\n' + textAfter; // position the caret after that new-line character range = document.createRange(); range.setStart( node, offset + 1 ); range.setEnd( node, offset + 1 ); // update the selection sel.removeAllRanges(); sel.addRange( range ); } });

Демо-версия: http://jsfiddle.net/FhEf6/3/

Я использую символы '\n' вместо элементов BR (у DIV есть white-space:pre set). В результате, никакие элементы BR или P не добавляются в DIV при нажатии ENTER. Внутри DIV есть только один TextNode, и все новые строки представлены символами '\n' .

// не совсем то, что вы просили, но эта функция может быть интересной, когда вы хотите заставить // другую операционную браузеру, хром, интернет-проводник вставлять регулярный BR для ввода. // может быть лучше написано, но работает до сих пор

 enterBR = function(e) { var iframeElement=parent.window.$("wysiwyg"+n); e = e || iframeElement.contentWindow.event; // eventhandler inside iframe (!) var keyCode= e.keyCode? e.keyCode: e.which; // req. for IE below v8 if (keyCode==13) // if enter key gets pressed { if(IE) // internet explorer { e.preventDefault?e.preventDefault():e.returnValue=false; // block default handling ( i tell yo!) iframeElement.contentDocument.selection.createRange().pasteHTML("
"); // insert a br tag } if(OP||CR) // opera and chrome { iframeElement.contentWindow.document.execCommand('formatBlock',false,'p'); } // creates a paragraph around a br tag


replace with regExp //here the regExp to replace the unneeded paragraph tags and a detection if you have whatever xhtml compatible
's or not. HTML=iframeElement.contentWindow.document.body.innerHTML; HTML=HTML.replace(/


< \/p>/gi,'
'); HTML=HTML.replace(/
]?)([\/]?)>/mgi,"
\n"); } return false; } // finaly add an eventlistener. remember this is used inside an iframe so dont forget to advise the script to work from one dom layer above (parent.window) // but i think it can be easily rewritten for contenteditable div or something... addEventListener(parent.window.$("mywysiwygeditor").contentDocument,'keypress',enterBR);

// hf

Мое решение отлично работает в Firefox, хотя это произошло довольно неожиданно! Я также тестировал его в Edge и Chrome. Он основан на ответе @Ktash, заменяя nbsp тремя исчезающими узлами: пустой диапазон (с classом), a
в середине и span, содержащий   ,

JS:

 var isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1; var isChrome = navigator.userAgent.toLowerCase().indexOf('chrome') > -1; document.execCommand('insertBrOnReturn', false, true); var elements = document.getElementsByClassName('editable'); Array.from(elements).forEach( (el) => { el.addEventListener('keydown',function(e) { if (e.which == 13) { if (isFirefox) { document.execCommand('insertHTML', false, '
 '); e.preventDefault(); } else if (!isChrome) { document.execCommand('insertText', true, '\r\n'); document.execCommand('insertHTML', false, "
"); e.preventDefault(); } } }); if (isFirefox) { el.addEventListener('input',function(e) { var elements = document.getElementsByClassName('nbsp-break'); Array.from(elements).forEach( (el) => { el.parentNode.removeChild(el.nextSibling.nextSibling); el.parentNode.removeChild(el); }); }); } });

CSS:

 .nbsp-break + br + span { font-size: 0; }