web-dev-qa-db-fra.com

Empêcher l’ajout de <div> contenteditable sur ENTER - Chrome

J'ai un élément contenteditable et chaque fois que je tape des éléments et que je clique sur ENTER, un nouveau <div> est créé et le texte de la nouvelle ligne y est placé. Je n'aime pas ça un petit peu. 

Est-il possible d'empêcher cela ou du moins de le remplacer par un <br>?

Voici la démo http://jsfiddle.net/jDvau/

Remarque: Ce n'est pas un problème dans Firefox.

95
iConnor

Essaye ça

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

Démo ici

144
Ram G Athreya

Vous pouvez le faire avec juste un changement CSS:

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

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

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

41
airi

Ajoutez le style display:inline-block; à contenteditable. Il ne générera pas div, p et span automatiquement dans Chrome.

29
Le Tung Anh

Essaye ça:

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

20
Andrew

Utilisation shift+enter au lieu de enter insérer une seule balise <br> ou envelopper votre texte dans des balises <p>.

11
Blake Plumb
document.execCommand('defaultParagraphSeparator', false, 'p');

Il remplace le comportement par défaut pour avoir un paragraphe à la place.

Sur chrome, le comportement par défaut à entrer est:

<div>
    <br>
</div>

Avec cette commande ça va être

<p>
    <br>
</p>

Maintenant que c'est plus linéaire, il est facile de n'avoir que <br> dont vous auriez besoin.

10
Ced

La manière dont contenteditable se comporte lorsque vous appuyez sur enter dépend des navigateurs, le <div> arrive sur le Webkit (chrome, safari) et IE.

J'ai eu du mal avec cela il y a quelques mois et je l'ai corrigé de cette façon:

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

J'espère que cela vous aidera et désolé pour mon anglais si ce n'est pas aussi clair que nécessaire.

EDIT: Correction de la fonction jQuery supprimée jQuery.browser

6
Elie

J'utiliserais un style (Css) pour résoudre le problème.

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

Firefox ajoute en effet une rupture d'élément de bloc 
, alors que Chrome enveloppe chaque section dans une balise. Vous css donne à div un remplissage de 10px avec la couleur de fond.

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

Vous pouvez également répliquer le même effet souhaité dans jQuery:

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

Voici une fourchette de votre violon http://jsfiddle.net/R4Jdz/7/

4
cbayram

Vous pouvez avoir des balises <p> séparées pour chaque ligne plutôt que d'utiliser des balises <br> et obtenir une meilleure compatibilité avec les navigateurs.

Pour ce faire, insérez une balise <p> avec du texte par défaut à l'intérieur du div contenteditable.

Par exemple, au lieu de:

<div contenteditable></div>

Utilisation:

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

jsfiddle

Testé dans Chrome, Firefox et Edge, et le second fonctionne de la même manière dans chacun.

Le premier, cependant, crée des div dans Chrome, des sauts de ligne dans Firefox et, dans Edge, crée des divs et le curseur est replacé au début du div actuel au lieu de passer au suivant.

Testé sous Chrome, Firefox et Edge.

4
Josh Powlison

Essayez d'utiliser ckeditor. Il fournit également un formatage semblable à celui-ci dans les fichiers SOF.

https://github.com/galetahub/ckeditor

3
Dan Rey Oquindo

Vous pouvez envelopper vos paragraphes avec la balise <p>, par exemple, il apparaîtrait sur une nouvelle ligne au lieu de div .__
<div contenteditable="true"><p>Line</p></div> 
Après avoir inséré une nouvelle chaîne:
<div contenteditable="true"><p>Line</p><p>New Line</p></div> 

3
nes

Nous devons d’abord capturer chaque entrée d’utilisateur clé pour voir si elle est enfoncée, puis nous empêchons la création de <div> et nous créons notre propre balise <br>.

Il y a un problème, lorsque nous le créons, notre curseur reste à la même position et nous utilisons API de sélection pour placer notre curseur à la fin.

N'oubliez pas d'ajouter une balise <br> à la fin de votre texte car sinon, la première entrée ne créera pas de nouvelle ligne. 

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

Fiddle

2
L105
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 est le contexte réel qui signifie document.getElementById('test');.

2
webprogrammer

ajouter un empêchement par défaut à la div

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

C'est l'éditeur HTML5 dirigé par le navigateur. Vous pouvez envelopper votre texte avec <p>...</p>. Chaque fois que vous appuyez sur ENTREE, vous obtenez <p></p>. En outre, l'éditeur fonctionne de telle manière que chaque fois que vous appuyez sur SHIFT + ENTER, il insère <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>

Vérifiez ceci: http://jsfiddle.net/ZQztJ/

2
Mehdi

J'ai eu ce même problème et trouvé la solution (CHROME, MSIE, FIREFOX), suivez mon code dans le lien.

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

1
Fábio Zangirolami

Une autre façon de le faire

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

1
BlueUnicorn

Empêcher la création d'une nouvelle div dans le contenu éditable Div sur chaque touche d'entrée: Solution que j'ai trouvée est très simple:

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

Ce contenu --- innerHTML empêche la création d'une nouvelle div dans le contenu éditable div sur chaque touche Entrée.

1
DrShyam Babu Gupta

La solution de commande inserHTML fait des choses étranges lorsque vous avez imbriqué des éléments contenteditable.

J'ai pris quelques idées de réponses multiples ici, et cela semble répondre à mes besoins pour l'instant:

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

J'aime utiliser Mousetrap pour les raccourcis clavier: https://craig.is/killing/mice

Ensuite, je viens d'intercepter l'événement enter en exécutant une commande insertLineBreak :

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

Toutes les commandes: https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand

Cela fonctionne avec Chrome 75 et l'élément éditable suivant:

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

Il est également possible d'utiliser insertHTML :

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