Empêcher Chrome d'envelopper le contenu de <p> avec un <span>

J'ai observé un comportement indésirable dans Chrome qui se produit lorsque l'on rejoint deux <p> en supprimant la séparation entre eux. Bien que les balises <p> soient jointes correctement, Chrome enveloppe le contenu de la balise <p> plus à droite avec un <span> .

Edit : cela se produit pour tous les éléments de blocs, pas seulement p tags.

Exemple :

Par exemple, lorsque la séparation </p><p> est supprimée du bloc suivant:

 <div contenteditable="true"><p>p one.</p><p>p two.</p></div> 

Il devient:

 <div contenteditable="true"><p>p one.<span style="font-size: 16px; line-height: 1.44;">p two.</span></p> 

Exemple dans un violon: le contenu de l'emballage Chrome est joint <p> avec un <span> .

Question :

Existe-t-il un moyen simple d'empêcher Chrome de faire cela? Il en résulte un marquage horrible dont j'aimerais beaucoup me débarrasser.

Il y a un moyen, mais vous devez définir activement quelques styles. L'idée est de dire à Chrome que les styles sont déjà pris en charge, donc il n'a pas besoin d'ajouter SPAN pour répondre aux exigences de styles. En principe, vous devez ajouter les styles ajoutés au chrome à une classe étendue sous votre div contentative (voir l'exemple ci-dessous).

Violon édité

Pour vous, exemple:

  • J'ai ajouté une classe "edit" au DIV contourné
  • J'ai ajouté un .edit p, span class dans le style

Cela devient:

 .edit { border: 1px solid gray; padding: 10px; } .edit p, span { line-height: 1.44; font-size: 16px; } 

Et le DIV:

 <div contenteditable="true" class="edit">...</div> 

Notez que vous n'avez normalement pas besoin de la font-size: 16px; la font-size: 16px; . J'avais besoin d'ajouter celui-ci parce que le violon définit une certaine taille de police en contentement. Sur une page indépendante, je n'en ai pas besoin.

Vous devez appliquer ce «patch» de Chrome à tous les éléments où cela se produit (alors, si vous avez besoin de UL, OL …, ajoutez ce qui est nécessaire à la suite de ma logique d'exemple ci-dessus)

Je sais que ce n'est pas vraiment une réponse pour le résoudre, mais un indice de la façon dont il pourrait être corrigé (mais il est long d'être un commentaire à Petah question de savoir comment je le résoudrais)

En général, vous vérifiez que de tels bogues pourraient se produire. Pour le cas de la création de l' span vous keydown tous keydown événements de keydown et de keypress et vérifiez si la clé est la touche de recul ou de suppression ou pour chaque touche qui insère des caractères s'il s'agit d'une sélection réelle.

Si tel est le cas, vous devez vérifier la sélection actuelle (soit la position de la marque d'insertion, soit la sélection réelle), alors vous savez quel est l'élément de texte ou le noeud suivant. Alors vous devez vérifier la suivante dans la suivante, keyup keypress et la keyup si une span créée directement après votre marque d'insertion. Selon le bug du navigateur, vous avez besoin d'une vérification supplémentaire. S'il y en a une, créez un nouveau contenu. Mutation événements de Mutation supplémentaires et les attributs d' assistance pourraient être utilisés.

Mais je dois dire que j'ai renoncé à faire cela moi-même et a changé pour ckeditor 4. la plupart des fonctionnalités dont je n'ai pas besoin et c'est une très grande bibliothèque. Mais à cause du grand nombre de ces bugs, je n'ai pas vu une autre solution pour moi.

EDIT Voici une mise à jour du js violon qui montre l'idée avec un événement Mutable: http://jsfiddle.net/THPmr/6/

Mais ce n'est pas à l'épreuve des balles, il suffit de montrer comment cela pourrait être obtenu (testé uniquement dans chrome 27.0.1422.0, et probablement ne fonctionnerait pas si plus d'un élément de texte est contenu dans la seconde p )

Le CSS influence la façon dont le balisage est effectué à l'intérieur contentable:

Div, pré {border: 1px solid grey; Rembourrage: 10px; Hauteur de ligne: 1,44; }

Supprimez la ligne ligne-hauteur et le problème ne se produit plus.

Il existe en général plusieurs bugs avec contentement liés au style par défaut: comment éviter le contenu WebKitEditable copier-coller en résultant CSS indésirable?

EDIT JsFiddle influence indirectement cela (la tinkerbin se comporte différemment) en raison de son 'CSS (normalize.css). Essaye ça:

  1. Exécutez votre violon
  2. Inspectez un <p>
  3. Désactiver toutes font-size déclarations de font-size dans la pile CSS – y compris votre hauteur de ligne
  4. Faire le recul
  5. Il n'y a pas de portée en ligne

Solution 1 : utilisez les classes et les identifiants.

Ne déclarez pas la taille de la police pour p ou div mais pour p.main-content , ou plus simplement, .main-content . Si la taille de police de vos éléments à l'intérieur de contentement provient du CSS par défaut interne du navigateur, Chrome n'ajoute pas de marquage supplémentaire / style inline.

Solution 2 : Utiliser un Sanitizer.

J'allais personnellement avec le n ° 1 car il n'est jamais recommandé de spécifier les tailles de police et les erreurs de frappe dans des étiquettes si génériques.

La meilleure façon de trouver jusqu'à présent est d'écouter DOMNodeInserted et de vérifier le tagName. Si c'est une portée, vous pouvez supprimer la balise et laisser le contenu. Cela maintient également le curseur à l'endroit correct.

 function unwrap(el, target) { if ( !target ) { target = el.parentNode; } while (el.firstChild) { target.appendChild(el.firstChild); } el.parentNode.removeChild(el); } var AutoFix = true; document.getElementById('editable') .addEventListener('DOMNodeInserted', function(ev) { if ( !AutoFix ) { return; } if ( ev.target.tagName=='SPAN' ) { unwrap(ev.target); } }); 

J'ai ajouté un «AutoFix» booléen afin que vous puissiez désactiver les changements de dom automatiques lorsque vous devez insérer un intervalle, car cet événement déclenche un changement de dom. Par exemple, si vous avez une barre d'outils qui permet à l'utilisateur d'insérer quelque chose comme <span class = "highlight"> … </ span>.

Le code n'a pas d'effets secondaires dans IE ou FireFox pour autant que je voie.

Voici ma façon de supprimer les limites supplémentaires

 document.querySelector('[contenteditable=true]') .addEventListener('DOMNodeInserted', function(event) { if (event.target.tagName == 'SPAN') { event.target.outerHTML = event.target.innerHTML; } }); 

Cela m'a irrité aussi, mais j'ai trouvé une solution qui fonctionne bien pour l'instant.

 $('#container span').filter(function() { $(this).removeAttr("style"); return $(this).html().trim().length == 0; }).remove(); 

Je retire simplement la balise de style de l'élément de portée et supprimez-le complètement s'il est vide. Vous pourriez probablement filtrer en fonction du style de l'attribut, mais comme je fais déjà une boucle pour vérifier les vides, je pensais qu'il était préférable de faire les deux en même temps.

Il crée un scintillement pour une microseconde lorsque chrome tente d'abord d'insérer le style hérité pour la portée, mais vous ne le voyez qu'une fois immédiatement après la suppression.

Ce n'est pas parfait, mais c'est rapide et concis.

Trouvé ce lien à partir d'un commentaire publié sur le blog de quelqu'un:

(Correction d'un bug où les dernières versions de WebKit produiraient l'élément span …) https://github.com/tinymce/tinymce/commit/8e6422aefa9b6cc526a218559eaf036f1d2868cf

Consultez les réponses ici: https://stackoverflow.com/a/24494280/2615633 Pour corriger le problème, vous pouvez simplement utiliser ce plugin: jquery.chromeinsertfix