web-dev-qa-db-fra.com

Traitement des coupures de ligne sur le contenuEditable DIV

J'ai un problème avec les sauts de ligne contenteditable sur SAFARI/CHROME. Lorsque j'appuie sur "return" sur un contentEditable <div>, au lieu de créer un <br> (comme Firefox), ils créent un nouveau <div>:

<div>Something</div>
<div>Something</div>

Cela ressemble à (sur le contentEditable DIV):

Something
Something

Mais après la désinfection (en retirant <div>), je reçois ceci:

SomethingSomething

Dans Firefox, la contenteditable est:

Something
<br>
Something

Et cela après la désinfection est le même:

Something
Something

Existe-t-il une solution pour "normaliser" cette opération sur les navigateurs?

J'ai trouvé ce code sur Créez un texte au lieu de <div> </ div> en appuyant sur Entrée sur un contenu modifiable

$(function(){

  $("#editable")

  // make sure br is always the lastChild of contenteditable
  .live("keyup mouseup", function(){
    if (!this.lastChild || this.lastChild.nodeName.toLowerCase() != "br") {
      this.appendChild(document.createChild("br"));
     }
  })

  // use br instead of div div
  .live("keypress", function(e){
    if (e.which == 13) {
      if (window.getSelection) {
        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);
        return false;
      }
    }
  });
});

Cela fonctionne, mais (dans SAFARI et CHROME) je dois appuyer deux fois sur la touche "retour" pour obtenir une nouvelle ligne ... 

Une idée?

Edit: Avec le code que j'ai trouvé (au bas de cette question), ça fonctionne très bien sauf que la fonction "s'assure qu'un élément <br> est toujours le lastChild ... Une idée sur la façon de résoudre ce problème?

Edit 2: Je reçois cette erreur sur la console: Uncaught TypeError: Object #<HTMLDocument> has no method 'createChild'

Edit 3: Ok, j'ai changé le document.createChild("br"); en document.createElement("br"); et je pense que je l'ai obtenu dans FF/Safari/Chrome ... Tous renvoient <br> pour les nouvelles lignes ... 

Le problème est maintenant que lorsque je suis dans une liste ordonnée ou non ordonnée, je dois obtenir une nouvelle ligne sans <br>...

Edit 4: Si quelqu'un est intéressé par la solution de la dernière modification: Evitez la fonction createElement si elle se trouve dans un élément <LI> (contentEditable)

50
Santiago

Cette technique semble éviter le bogue de Chrome qui montre les BR la première fois (avec le code que vous avez mentionné, vous devez appuyer deux fois sur la touche Entrée).

Ce n'est pas un hack parfait mais ça marche: il ajoute un espace après votre BR, ainsi il s'affiche correctement . Cependant, vous verrez que l'ajout d'un espace "" ne changera rien, cela fonctionnera avec d'autres lettres. Le navigateur ne l'affichera pas, probablement parce que c'est comme un espace vide à l'intérieur d'une page html, cela ne veut tout simplement rien dire. Pour me débarrasser de ce bogue, j'ai créé une div avec jQuery qui inclut une balise &nbsp; et je prends la propriété text() pour la mettre dans le nœud textnode, sinon cela ne fonctionne pas.

$editables = $('[contenteditable=true]');

$editables.filter("p,span").on('keypress',function(e){
 if(e.keyCode==13){ //enter && shift

  e.preventDefault(); //Prevent default browser behavior
  if (window.getSelection) {
      var selection = window.getSelection(),
          range = selection.getRangeAt(0),
          br = document.createElement("br"),
          textNode = document.createTextNode("\u00a0"); //Passing " " directly will not end up being shown correctly
      range.deleteContents();//required or not?
      range.insertNode(br);
      range.collapse(false);
      range.insertNode(textNode);
      range.selectNodeContents(textNode);

      selection.removeAllRanges();
      selection.addRange(range);
      return false;
  }

   }
});
27
Micaël Félix

L'écoute des frappes semble beaucoup de travail. Quelque chose d'aussi simple que cela serait réalisable:

var html = $('.content').html().replace(/<div>/gi,'<br>').replace(/<\/div>/gi,'');

JSFiddle demo ici .

En outre, il semble que sanitize.js autorise une configuration personnalisée. Avez-vous essayé d'ajouter div en tant qu'élément autorisé?

Autoriser le langage HTML/CSS est dangereux, assurez-vous donc d'être extrêmement prudent.

EDIT: Suppression des commentaires côté serveur. La désinfection a lieu au moment de l’utilisation. Si le client souhaite éviter ce problème localement, il peut le faire à ses propres risques. Merci Vincent McNabb pour l'avoir signalé.

13
Kurt

Vous pouvez simplement utiliser la commande suivante document.execCommand('insertHTML',false,'<br>');

Cette commande empêchera le comportement par défaut et ajoutera une balise que vous souhaitez . C'est tout, 1 ligne de code

Et encore plus facile approche.

CSS SEULEMENT.

Pour vous, élément contenteditable, appliquez la règle display:inline-block Cela n’ajoutera que br s

6
Karb

Les webkits ne rendent pas un seul br s'il s'agit du dernier enfant (non vide) d'un conteneur. Pour Safari, la frappe d'origine pour insérer un saut de ligne est Ctrl + Retour. Si vous regardez de plus près, vous remarquerez que Safari insère en réalité deux brs tout en n'en rendant qu'un. cependant, il insérera un seul br s'il y a du texte de fin ou se débarrassera du double brs une fois que vous en aurez entré (s'il y avait des doubles).

Apparemment, il semble que la solution pour les kits Web consiste à insérer les doubles br comme ils le font eux-mêmes et à les laisser gérer le reste.

2
Klim Lee

Vous voudrez peut-être consulter la propriété css white-space. Définir le style sur white-space: pre-wrap vous permet de vous débarrasser de tout ce que javascript, car il modifie le comportement des espaces à afficher au lieu de les réduire.

Et voyez cette réponse: HTML - Un caractère Newline dans un contenu DIV modifiable?

1
B T
0
user10