Verhindern Sie das inhaltsbearbeitbare Hinzufügen von <div> in ENTER - Chrome


131

Ich habe ein contenteditableElement und wann immer ich etwas schreibe und treffeENTER , wird ein neues erstellt <div>und der neue Zeilentext dort eingefügt. Ich mag das kein bisschen.

Ist es möglich, dies zu verhindern oder zumindest einfach durch a zu ersetzen? <br> ?

Hier ist die Demo http://jsfiddle.net/jDvau/

Hinweis: Dies ist kein Problem in Firefox.


1
Firefox fügt <br> hinzu, Chrom - nicht, aber nach dem Korrigieren Ihrer Stile brechen zusätzliche Divs die linke Polsterung nicht. Die Frage ist, warum es dir nicht gefällt? Denke, es ist br ... jsfiddle.net/jDvau/1 Sie können auch das Ereignis DOMSubtreeModified verwenden, um diese Divs abzufangen und zu entfernen.
ViliusL

stackoverflow.com/questions/6024594/… das könnte dir helfen, viel Glück!
Sirikon

1
Für mich ist die Lösung von Blake Plumb die einfachste und bei weitem die beste hier unten.
Svassr

1
@svassr das ist nicht der Punkt, es sind nicht Sie oder ich, die es verwenden werden. Es ist ein Client, der möglicherweise nicht einmal weiß, was Schicht ist.
iConnor

2
In der Tat ändert es alles. Das heißt, es ist ein weit verbreitetes Verhalten und eine kleine Hilfemeldung würde nicht bewaffnen. "Geben Sie einem Mann einen Fisch und Sie füttern ihn für einen Tag. Bringen Sie einem Mann das Fischen bei und Sie füttern ihn ein Leben lang."
Svassr

Antworten:


161

Versuche dies:

$('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/>');
        // prevent the default behaviour of return key pressed
        return false;
    }
});

Klicken Sie hier für eine Demo


Aber ich finde hier einen kleinen Unterschied. Setzen Sie Ihren Cursor einfach auf die leere Zeile (oben unter "Geben Sie etwas ein") und drücken Sie die Eingabetaste. Der Cursor befindet sich jetzt direkt vor dem "Typ" und nicht mehr in der neuen Leerzeile.
Andrew

3
Dies funktioniert in IE11 nicht, da insertHTML nicht unterstützt wird. Siehe Antwort unten!
Webprogrammierer

4
Wenn Sie den Cursor zwischen Zeichen setzen, z. 'Ty [Cursor] pe einige Sachen' und drücken Sie die Eingabetaste, Sie erhalten 1 Zeile zu viele.
Chandrew

13
Die Antwort ist nicht akzeptabel. Die Lösung wäre, nur einen <br />
raoulinski

3
diese Rückkehr sowohl <br> als auch <div>
Nishad Up

51

Sie können dies mit nur einer CSS-Änderung tun:

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

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

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


1
Es gab ein Problem, als ich den Inline-Block verwendete und execCommand ("insertHTML", xxx) ausführte, um etwas einzufügen. Am Ende des eingefügten Elements wurde ein "<br>" hinzugefügt, das in Chrome33 getestet wurde.
Imskull

5
Schöner Fund. Leider funktioniert dies nicht auf Position: absolute Elemente oder Elemente, die direkte Kinder eines Elternteils mit Anzeige sind: flex. Sie können es hacken, um zu funktionieren, obwohl Sie dies berücksichtigen. Stellen Sie nur sicher, dass es sich nicht um ein direktes Kind von Flex-Elementen handelt. Wenn Sie es Position brauchen: absolut geben Sie es einfach ein zusätzliches Elternteil damit.
Skeptiker

@ReinoutvanKempen Begann bereits vor 3 Monaten mit flex. Ich denke, dieser Hack wird nicht funktionieren
Kittu

Dies ist eine wirklich, wirklich beste Lösung, es ist extrem sauber und klar, es wird nichts eingefügt, auch nicht br. und vor allem diese lösung ohne js.
Orca

2
Wow ... dies löst Chrome, lässt Firefox jedoch bei der Eingabe Divs hinzufügen, was standardmäßig nicht der Fall ist.
Entwickler

40

Stil hinzufügen , display:inline-block;um contenteditablees nicht zu generieren div, pund spanautomatisch in Chrome.


6
Dies ist eine großartige Lösung. *[contenteditable="true"]{display: inline-block;}
Ericjbasti

Ich

In IE11 wird dies ein Extra machen <p></p> :(
Betty St

1
aber es wird einen weiteren sehr nervigen Chrome-Fehler verursachen (was für ein beschissener Browser)
vsync

4
Funktioniert nicht mehr mit Chrome Version 63.0.3239.84
Mikaël Mayer

21

Versuche dies:

$('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/


Gut, funktioniert :) Ich werde mehr Aufmerksamkeit erwarten, bevor ich mich entscheide, danke.
iConnor

funktioniert nicht richtig auf Firefox. Es wird eine zusätzliche Zeile hinzugefügt.
agpt

Dadurch wird das inputnicht ausgelöst, wenn Sie die Eingabetaste drücken. Eine einfache Lösung: etw hinzufügen wie$(this).trigger('input')
LarsW

Die insertHTMLLösung macht einige seltsame Dinge, wenn es verschachtelte contenteditableElemente gibt. Ihre Lösung umgeht dies, aber es gibt noch einige weitere Probleme. Ich habe sie als neue mögliche Lösung hinzugefügt.
Skerit

Funktioniert nicht in Chrome. Wenn Sie zum ersten Mal am Ende der Zeichenfolge die Eingabetaste drücken, wird ein Leerzeichen hinzugefügt. Das zweite Mal funktioniert es allerdings.

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

Es überschreibt das Standardverhalten, stattdessen einen Absatz zu haben.

Auf Chrome lautet das Standardverhalten bei der Eingabe:

<div>
    <br>
</div>

Mit diesem Befehl wird es sein

<p>
    <br>
</p>

Jetzt, da es linearer ist, ist es einfach zu haben, nur <br>was Sie brauchen würden.


Wenn Sie die Eingabetaste drücken, haben Sie anstelle von div und br p und br im Browser. Versuch es.
Ced

Vielen Dank! Erklärungen sind immer hilfreich
jpaugh

@jpaugh np, ich habe meine Antwort weiter bearbeitet, damit sie besser erklärt wird.
Ced

Dies funktioniert nicht auf Firefox (ich habe nur in Chrom und Firefox getestet)
medBouzid

FireFox wurde behoben, um jetzt den defaultParagraphSeparator zu berücksichtigen. Meiner Meinung nach ist diese Antwort die beste, da alle Browser jetzt konsistent und mit der Spezifikation übereinstimmen. Wenn Sie dann nicht möchten, dass ein P-Tag einen Randabstand zum vorherigen Textblock im bearbeitbaren Inhalt hat, können Sie dies mithilfe von CSS ändern.
Blackmamba

9

Verwenden Sie shift+ enteranstatt enternur ein einzelnes <br>Tag einzufügen oder Ihren Text in <p>Tags zu verpacken .


9
+1 Danke, das ist sehr praktisch zu wissen, aber wenn Sie einen Kunden haben, der ein Buch schreibt, wird das im ***
iConnor

1
Dies hilft nicht, wenn Sie Inhalte
einfügen

5

Die Art und Weise, contenteditablewie Sie sich beim Drücken verhalten, enterhängt von den Browsern ab<div> ab. Dies geschieht im Webkit (Chrome, Safari) und im Internet Explorer.

Ich hatte vor ein paar Monaten damit zu kämpfen und habe es folgendermaßen korrigiert:

//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);
            }
        }
    });
}

Ich hoffe es wird helfen und entschuldige mein Englisch, wenn es nicht so klar wie nötig ist.

BEARBEITEN : Korrektur der entfernten jQuery-FunktionjQuery.browser


Nur um Sie wissen zu lassen, jQuery.browsergehört nicht mehr zu jQuery.
iConnor

Sie haben Recht, ich sollte dies erwähnen und so etwas wie navigator.userAgent.indexOf("msie") > 0undnavigator.userAgent.indexOf("webkit") > 0
Elie

1
if( ( e.keyCode || e.witch ) == 13 ) { ... }muss seinif (e.keyCode === 13 || e.which === 13) { ... }
Sebastian Sandqvist

5

Ich verwende Mousetrap gerne zum Behandeln von Hotkeys: https://craig.is/killing/mice

Dann fange ich einfach das enter-Ereignis ab und führe einen Befehl insertLineBreak aus :

Mousetrap.bindGlobal('enter', (e)=>{
  window.document.execCommand('insertLineBreak', false, null);
  e.preventDefault();
});

Alle Befehle: https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand

Es funktioniert mit Chrome 75 und dem folgenden bearbeitbaren Element:

<pre contenteditable="true"></pre>

Es ist auch möglich, insertHTML zu verwenden :

window.document.execCommand('insertHTML', false, "\n");

4

Fügen Sie dem div einen Verhindern-Standard hinzu

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

@connorspiracist Entschuldigung, es ist document.body.div(Sie müssen wahrscheinlich einen anderen Code eingeben, um darauf hinzuweisen, dass es divnur die allgemeine Idee ist)
Math Chiller

4

Ich würde Styling (Css) verwenden, um das Problem zu beheben.

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

Firefox fügt in der Tat einen Blockelementbruch hinzu
, während Chrome jeden Abschnitt in ein Tag einschließt. Sie CSS gibt Divs eine Auffüllung von 10px zusammen mit der Hintergrundfarbe.

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

Alternativ können Sie denselben gewünschten Effekt in jQuery replizieren:

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

Hier ist eine Gabel Ihrer Geige http://jsfiddle.net/R4Jdz/7/


1
Dies mag einigen Leuten helfen, aber ich war mehr besorgt über das unnötige Markup, da ich den endgültigen HTML- contenteditable
Code

4

Sie können <p>für jede Zeile separate Tags verwenden, anstatt <br>Tags zu verwenden, und sofort eine bessere Browserkompatibilität erzielen.

Fügen Sie dazu ein <p>Tag mit einem Standardtext in das inhaltsbearbeitbare div ein.

Zum Beispiel anstelle von:

<div contenteditable></div>

Verwenden:

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

jsfiddle

Getestet in Chrome, Firefox und Edge, und die zweite funktioniert jeweils gleich.

Der erste erstellt jedoch Divs in Chrome, erstellt Zeilenumbrüche in Firefox und in Edge erstellt Divs, und der Cursor wird am Anfang des aktuellen Divs zurückgesetzt, anstatt zum nächsten zu wechseln.

Getestet in Chrome, Firefox und Edge.


Dies ist eigentlich keine schlechte Lösung
AaronHS

3

Sie können Ihre Absätze mit einem <p>Tag umschließen, das beispielsweise in einer neuen Zeile anstelle von div angezeigt wird. Beispiel:
<div contenteditable="true"><p>Line</p></div>
Nach dem Einfügen einer neuen Zeichenfolge:
<div contenteditable="true"><p>Line</p><p>New Line</p></div>


3

Die inserHTMLBefehlslösung macht einige seltsame Dinge, wenn Sie verschachtelte contenteditableElemente haben.

Ich habe hier einige Ideen aus mehreren Antworten übernommen, und dies scheint vorerst meinen Bedürfnissen zu entsprechen:

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;
}


2

Zuerst müssen wir jeden Schlüssel erfassen, den Benutzer eingeben, um zu sehen, ob die Eingabetaste gedrückt wird. Dann verhindern wir die <div>Erstellung und erstellen unsere eigenen<br> Tag.

Es gibt ein Problem: Wenn wir es erstellen, bleibt unser Cursor an derselben Position, sodass wir die Auswahl-API verwenden , um unseren Cursor am Ende zu platzieren.

Vergessen Sie nicht, <br>am Ende Ihres Textes ein Tag hinzuzufügen, da sonst bei der ersten Eingabe keine neue Zeile erstellt wird.

$('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();
        }
    }
});

Geige


2

Dies ist ein browsergesteuerter HTML5-Editor. Sie können Ihren Text mit <p>...</p>umbrechen und erhalten dann jedes Mal, wenn Sie die EINGABETASTE drücken <p></p>. Außerdem funktioniert der Editor so, dass er bei jedem Drücken von UMSCHALT + EINGABE eingefügt wird <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>

Überprüfen Sie dies: http://jsfiddle.net/ZQztJ/


2

Dies funktioniert in allen gängigen Browsern (Chrome, Firefox, Safari, Edge).

document.addEventListener('keydown', event => {
  if (event.key === 'Enter') {
    document.execCommand('insertLineBreak')
    event.preventDefault()
  }
})
<div class="element" contenteditable="true">Sample text</div>
<p class="element" contenteditable="true">Sample text</p>

Es gibt eine Unannehmlichkeit. Nach Abschluss der Bearbeitung enthalten die Elemente möglicherweise eine Endung im <br>Inneren. Sie können jedoch Code hinzufügen, um dies bei Bedarf zu reduzieren.

Überprüfen Sie diese Antwort, um das nachfolgende https://stackoverflow.com/a/61237737/670839 zu entfernen<br>


Was zum Teufel? Wie kann die einzige Lösung, die tatsächlich für mich funktioniert hat, so weit unten auf der Seite sein? Vielen Dank.
user12861 vor

1
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>')

Wo thisist der tatsächliche Kontext, was bedeutet document.getElementById('test');.


0

Ein anderer Weg, es zu tun

$('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/


Der Cursor kann sich während der Eingabe nicht vorwärts bewegen.
Jack Lu

Das ist seltsam, ich habe es gerade in Chrome und IE 11 versucht und es funktioniert gut. Referenz Können Sie mir bitte mitteilen, welchen Browser Sie verwenden? Weitere Details zum Verhalten wären hilfreich, um das Problem zu lösen
MrAJ

0

Verhindern Sie die Erstellung neuer Divs in inhaltsbearbeitbaren Divs bei jeder Eingabetaste: Die Lösung, die ich gefunden habe, ist sehr einfach:

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

Dieser --- innerHTML-Inhalt verhindert die Erstellung neuer Divs in inhaltsbearbeitbaren Divs bei jeder Eingabetaste.


0

Im Entwurf des W3C-Editors finden Sie einige Informationen zum Hinzufügen von Status zu ContentEditable . Um zu verhindern, dass der Browser beim Drücken der Eingabetaste neue Elemente hinzufügt, können Sie diese verwenden plaintext-only.

<div contentEditable="plaintext-only"></div>

-1

Es ist möglich, dieses Verhalten vollständig zu verhindern.

Sehen Sie diese Geige

$('<div class="temp-contenteditable-el" contenteditable="true"></div>').appendTo('body').focus().remove();
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.