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

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

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

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

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

Ответы

Ответ 1

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

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

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

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

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

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

Ответ 2

Рассмотрим это:

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

Ответ 3

//не совсем то, что вы просили, но эта функция может быть интересной, когда вы хотите заставить // другие браузеры 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/> 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