Запретить contenteditable добавление на ENTER-Chrome

у меня есть contenteditable элемент, и всякий раз, когда я набираю некоторые вещи и нажимаю ENTER он создает новый <div> и помещает туда новый текст строки. Мне это совсем не нравится.

можно ли предотвратить или хотя бы просто заменить <br>?

вот демо http://jsfiddle.net/jDvau/

Примечание: это не проблема в Firefox.

20 ответов


попробуй такое

$('div[contenteditable]').keydown(function(e) {
    // trap the return key being pressed
    if (e.keyCode === 13) {
      // insert 2 br tags (if only one br tag is inserted the cursor won't go to the next line)
      document.execCommand('insertHTML', false, '<br><br>');
      // prevent the default behaviour of return key pressed
      return false;
    }
  });

Демо Здесь


вы можете сделать это только с изменением CSS:

div{
    background: skyblue;
    padding:10px;
    display: inline-block;
}

pre{
    white-space: pre-wrap;
    background: #EEE;
}

http://jsfiddle.net/ayiem999/HW43Q/


добавить стиль display:inline-block; до contenteditable, это не будет генерировать div, p и span автоматически в Chrome.


попробуйте это:

$('div[contenteditable="true"]').keypress(function(event) {

    if (event.which != 13)
        return true;

    var docFragment = document.createDocumentFragment();

    //add a new line
    var newEle = document.createTextNode('\n');
    docFragment.appendChild(newEle);

    //add the br, or p, or something else
    newEle = document.createElement('br');
    docFragment.appendChild(newEle);

    //make the br replace selection
    var range = window.getSelection().getRangeAt(0);
    range.deleteContents();
    range.insertNode(docFragment);

    //create a new range
    range = document.createRange();
    range.setStartAfter(newEle);
    range.collapse(true);

    //make the cursor there
    var sel = window.getSelection();
    sel.removeAllRanges();
    sel.addRange(range);

    return false;
});

http://jsfiddle.net/rooseve/jDvau/3/


использовать shift+enter вместо enter просто поставить один <br> тег в или обернуть текст в <p> теги.


document.execCommand('defaultParagraphSeparator', false, 'p');

Он переопределяет поведение по умолчанию для пункта.

в chrome поведение по умолчанию при вводе:

<div>
    <br>
</div>

С этой командой это будет

<p>
    <br>
</p>

теперь, когда он более линейный, легко иметь только <br> будет нужно.


как это contenteditable ведет себя при нажатии enter зависит от браузеров,<div> происходит на webkit (chrome, safari) и IE.

я боролся с этим несколько месяцев назад и я исправил это так :

//I recommand you trigger this in case of focus on your contenteditable
if( navigator.userAgent.indexOf("msie") > 0 || navigator.userAgent.indexOf("webkit") > 0 ) {
    //Add <br> to the end of the field for chrome and safari to allow further insertion
    if(navigator.userAgent.indexOf("webkit") > 0)
    {
        if ( !this.lastChild || this.lastChild.nodeName.toLowerCase() != "br" ) {
            $(this).html( $(this).html()+'<br />' );
        }
    }

    $(this).keypress( function(e) {
        if( ( e.keyCode || e.witch ) == 13 ) {
            e.preventDefault();

            if( navigator.userAgent.indexOf("msie") > 0 ) {
                insertHtml('<br />');
            }
            else {
              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);
            }
        }
    });
}

Я надеюсь, что это поможет, и извините за мой английский, если это не ясно, как это необходимо.

редактировать: коррекция удаленной функции jQuery jQuery.browser


Я бы использовал стиль (Css), чтобы исправить эту проблему.

div[contenteditable=true] > div {
  padding: 0;
} 

Firefox действительно добавляет разрыв элемента блока
, в то время как Chrome обертывает каждый раздел тегом. Вы css дает divs заполнение значение 10px вместе с цветом фона.

div{
  background: skyblue;
  padding:10px;
}

кроме того, вы можете повторить тот же желаемый эффект в jQuery:

var style = $('<style>p[contenteditable=true] > div { padding: 0;}</style>');
$('html > head').append(style);

вот вилка вашей скрипки http://jsfiddle.net/R4Jdz/7/


попробуйте использовать ckeditor. Он также обеспечивает форматирование, как это в SOF.

https://github.com/galetahub/ckeditor


вы можете обернуть свои абзацы с <p> тег, например, он будет появляться на новой строке вместо div Пример:
<div contenteditable="true"><p>Line</p></div>
После вставки новой строки:
<div contenteditable="true"><p>Line</p><p>New Line</p></div>


вы можете иметь отдельные <p> теги для каждой строки, а не с помощью <br> теги и получить большую совместимость с браузерами "из коробки".

для этого поставьте <p> тег с некоторым текстом по умолчанию внутри contenteditable div.

например, вместо:

<div contenteditable></div>

использование:

<div contenteditable>
   <p>Replace this text with something awesome!</p>
</div>

jsfiddle

протестировано в Chrome, Firefox и Edge, а второй работает одинаково в каждом.

в сначала, однако, создает divs в Chrome, создает разрывы строк в Firefox, а в Edge создает divs и курсор помещается обратно в начале текущего div вместо перехода в следующий.

протестировано в Chrome, Firefox и Edge.


добавьте значение по умолчанию prevent в div

document.body.div.onkeydown = function(e) {
    if ( e.keycode == 13 ){
        e.preventDefault();
            //add a <br>
        div = document.getElementById("myDiv");
        div.innerHTML += "<br>";
    }
}

Сначала нам нужно захватить каждый ключ пользователя введите, чтобы увидеть, если enter нажата, то мы предотвращаем <div> создание и мы создаем нашу собственную <br> тег.

есть одна проблема, когда мы создаем его, наш курсор остается в том же положении, поэтому мы используем API выбора чтобы поместить наш курсор в конце.

не забудьте добавить <br> тег в конце текста, потому что если вы не первый ввод не будет делать новую строку.

$('div[contenteditable]').on('keydown', function(e) {
    var key = e.keyCode,
        el  = $(this)[0];
    // If Enter    
    if (key === 13) {
        e.preventDefault(); // Prevent the <div /> creation.
        $(this).append('<br>'); // Add the <br at the end

        // Place selection at the end 
        // http://stackoverflow.com/questions/4233265/contenteditable-set-caret-at-the-end-of-the-text-cross-browser
        if (typeof window.getSelection != "undefined"
            && typeof document.createRange != "undefined") {
            var range = document.createRange();
            range.selectNodeContents(el);
            range.collapse(false);
            var sel = window.getSelection();
            sel.removeAllRanges();
            sel.addRange(range);
        } else if (typeof document.body.createTextRange != "undefined") {
            var textRange = document.body.createTextRange();
            textRange.moveToElementText(el);
            textRange.collapse(false);
            textRange.select();
        }
    }
});

Скрипка


это браузер направленный редактор HTML5. Вы можете обернуть текст с помощью <p>...</p>, затем всякий раз, когда вы нажимаете ENTER, вы получаете <p></p>. Кроме того, редактор работает таким образом, что при нажатии SHIFT + ENTER он вставляет <br />.

<div contenteditable="true"><p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolor veniam asperiores laudantium repudiandae doloremque sed perferendis obcaecati delectus autem perspiciatis aut excepturi et nesciunt error ad incidunt impedit quia dolores rerum animi provident dolore corporis libero sunt enim. Ad magnam omnis quidem qui voluptas ut minima similique obcaecati doloremque atque!
<br /><br />
Type some stuff, hit ENTER a few times, then press the button.
</p>
</div>

проверить это: http://jsfiddle.net/ZQztJ/


if (navigator.userAgent.toLowerCase().indexOf('msie') > -1) {
   var range = document.getSelection();
   range.pasteHTML(range.htmlText + '<br><br>');
}
else if(navigator.userAgent.toLocaleLowerCase().indexOf('trident') > -1)                           {
   var range = document.getSelection().getRangeAt(0); //get caret
   var nnode = document.createElement('br');
   var bnode = document.createTextNode('\u00A0'); //&nbsp;
   range.insertNode(nnode);
   this.appendChild(bnode);
   range.insertNode(nnode);                                
}
else
   document.execCommand('insertHTML', false, '<br><br>')

здесь this - это фактический контекст, который означает document.getElementById('test');.


другой способ сделать это

$('button').click(function(){
    $('pre').text($('div')[0].outerHTML)
});

$("#content-edit").keydown(function(e) {
    if(e.which == 13) {
       $(this).find("div").prepend('<br />').contents().unwrap();
      }
});

http://jsfiddle.net/jDvau/11/


У меня была такая же проблема и я нашел решение (CHROME, MSIE, FIREFOX), следуйте моему коду по ссылке.

$(document).on('click','#myButton',function() {
    if (navigator.userAgent.toLowerCase().indexOf('chrome') > -1)
        var str = $('#myDiv').html().replace(/<br>/gi,'').replace(/<div>/gi,'<br>').replace(/<\/div>/gi,'');
    else if (navigator.userAgent.toLowerCase().indexOf("firefox") > -1)
        var str = $('#myDiv').html().replace(/<\/br>/gi,'').replace(/<br>/gi,'<br>').replace(/<\/br>/gi,'');
    else if (navigator.userAgent.toLowerCase().indexOf("msie") == -1)
        var str = $('#myDiv').html().replace(/<br>/gi,'').replace(/<p>/gi,'<br>').replace(/<\/p>/gi,'');    
    $('#myDiv2').removeClass('invisible').addClass('visible').text(str);
    $('#myDiv3').removeClass('invisible').addClass('visible').html(str);
});

https://jsfiddle.net/kzkxo70L/1/


предотвратить создание нового Div в редактируемом содержимом Div на каждом ключе ввода: решение, которое я нашел, очень просто:

var newdiv = document.createElement("div"); 
newdiv.innerHTML = "Your content of div goes here";
myEditablediv.appendChild(newdiv);

это - - - содержимое innerHTML предотвращает создание нового Div в редактируемом содержимом Div на каждом ключе ввода.


на inserHTML командное решение делает некоторые странные вещи, когда вы вложили contenteditable элементы.

Я взял некоторые идеи из нескольких ответов здесь, и это, похоже, соответствует моим потребностям на данный момент:

element.addEventListener('keydown', function onKeyDown(e) {

    // Only listen for plain returns, without any modifier keys
    if (e.which != 13 || e.shiftKey || e.ctrlKey || e.altKey) {
        return;
    }

    let doc_fragment = document.createDocumentFragment();

    // Create a new break element
    let new_ele = document.createElement('br');
    doc_fragment.appendChild(new_ele);

    // Get the current selection, and make sure the content is removed (if any)
    let range = window.getSelection().getRangeAt(0);
    range.deleteContents();

    // See if the selection container has any next siblings
    // If not: add another break, otherwise the cursor won't move
    if (!hasNextSibling(range.endContainer)) {
        let extra_break = document.createElement('br');
        doc_fragment.appendChild(extra_break);
    }

    range.insertNode(doc_fragment);

    //create a new range
    range = document.createRange();
    range.setStartAfter(new_ele);
    range.collapse(true);

    //make the cursor there
    let sel = window.getSelection();
    sel.removeAllRanges();
    sel.addRange(range);

    e.stopPropagation();
    e.preventDefault();

    return false;
});

// See if the given node has a next sibling.
// Either any element or a non-empty node
function hasNextSibling(node) {

    if (node.nextElementSibling) {
        return true;
    }

    while (node.nextSibling) {
        node = node.nextSibling;

        if (node.length > 0) {
            return true;
        }
    }

    return false;
}

можно полностью предотвратить это поведение.

видите эту скрипку

$('<div class="temp-contenteditable-el" contenteditable="true"></div>').appendTo('body').focus().remove();