Как заставить <br>разрыв строки в Firefox ContentEditable - PullRequest
14 голосов
/ 26 октября 2011

У меня на сайте работает редактор JavaScript WYSIWYG (похожий на CKEditor).

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

Это прекрасно работает, но, к сожалению, Firefox (я тестировал с 5 и 7) все равно будет генерировать <p> элементов и генерировать <br> s, только если вы используете Shift + Enter .

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

Ответы [ 4 ]

16 голосов
/ 31 октября 2011

Если посмотреть на стандарты, то похоже, что это действие - способ, которым оно должно обрабатываться.Блоки разбиваются, когда на клавише ввода не установлен модификатор, а <br> используются при нажатии Shift.[ Источник ].

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

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

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

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

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

9 голосов
/ 31 октября 2011

Учтите это:

HTML:

<div contentEditable id="input"></div>

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 <div>, <p>, or <br> 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). В результате при нажатии клавиши ENTER элементы BR или P не добавляются в DIV. Внутри DIV всегда находится только один TextNode, и все новые строки представлены '\n' символами.

0 голосов
/ 01 мая 2018

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

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, '<span class="nbsp-break"></span><br><span>&nbsp;</span>');
                e.preventDefault();
            } else if (!isChrome) {
                document.execCommand('insertText', true, '\r\n');
                document.execCommand('insertHTML', false, "<br>");
                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;
}
0 голосов
/ 06 февраля 2014

// не совсем то, что вы просили, но эта функция может быть интересна, когда вы хотите форсировать // другие браузеры Opera, Chrome, Internet Explorer для вставки обычного 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("<br/>");  // insert a br tag
     }

     if(OP||CR)  // opera and chrome
     { 
      iframeElement.contentWindow.document.execCommand('formatBlock',false,'p');
     } // creates a paragraph around a br tag <p><br/></p> replace with regExp

    //here the regExp to replace the unneeded paragraph tags and a detection if you have whatever xhtml compatible <br/>'s or not.
    HTML=iframeElement.contentWindow.document.body.innerHTML;
    HTML=HTML.replace(/<p><br([\/]?)><\/p>/gi,'<br/>');
    HTML=HTML.replace(/<br(.*?|\s*[^\/]+[^>]?)([\/]?)>/mgi,"<br$1/>\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

...