web-dev-qa-db-fra.com

Position du curseur et hauteur de sélection pour les éléments en ligne dans Chrome

Je cherche à créer un éditeur avec Slate ou ProseMirror et je vois un comportement étrange avec Chrome autour de la position du curseur et de la zone de sélection lorsque en utilisant un élément intégré. Le problème 1 est illustré dans la première image ci-dessous. Lorsque la position du curseur de texte est derrière le "f", le curseur apparaît en haut de l'image. Le problème 2 se trouve dans la deuxième image - la sélection du texte affiche une zone en surbrillance qui est aussi haute que dans l'élément en ligne. Existe-t-il un moyen de contrôler ce comportement et d'afficher à la place le curseur à la position du texte et de ne mettre en évidence que l'espace autour du texte (même si l'image en ligne crée la ligne hauteur plus grande) caret position too highselection area too big

J'aimerais imiter le comportement ici, de Firefox: enter image description hereenter image description here

Des exemples d'images ont été produits à l'aide de la démo ProseMirror ici: https://prosemirror.net/examples/basic/

Un exemple minimum (merci @Kaiido) avec JSBin :

<div contenteditable>Test text<img src="https://upload.wikimedia.org/wikipedia/en/9/9b/Yoda_Empire_Strikes_Back.png">Testing</div>

Je ne sais pas comment cela se comporte sur d'autres systèmes d'exploitation, mais j'utilise macOS Catalina.

8
mowwwalker

Tout d'abord, ne manipulez pas le DOM ProseMirror comme indiqué dans l'exemple JQuery. En fait, vous rencontrerez probablement des problèmes de DOM ou de contenu. ProseMirror utilise son propre nœud DOM et son propre schéma de balisage. Si vous souhaitez manipuler le DOM ProseMirror ou ajouter un plugin, jetez un œil à Markup, Plugin & Node Apis. J'ai joint un exemple simple de code de marquage d'alignement de texte. Note latérale, la raison Grammarly et d'autres n'ont pas de plugins ProseMirror à cause de l'approche/des modèles DOM.

Cela mis à part, la bonne nouvelle, les problèmes que vous avez un CSS purement. ProseMirror supprime toutes les classes et réinitialise le DOM/CSS donc si vous importez un document ou que vous coupez et collez la totalité/la plupart de vos classes auront disparu.

L'approche la plus simple pour résoudre ce problème consiste à envelopper l'éditeur dans un div et à affecter une classe au div, puis à ajouter des styles et des styles enfants à cette classe. La raison de l'encapsuler est que les sélecteurs css tels que img, p, h, etc. ne s'appliqueront qu'aux balises à l'intérieur de la classe d'éditeur. Sans cela, vous vous retrouvez avec des conflits CSS évidents.

CSS

  1. N'utilisez pas flexbox pour les images en ligne comme flexbox n'est pas un système de grille. En fait, si je me souviens bien, vous ne pouvez pas insérer les enfants directs du conteneur flex).
  2. inline sur les balises p et img n'enveloppera pas le texte et vous vous retrouverez avec les problèmes énumérés ci-dessus.
  3. si vous voulez vraiment envelopper et supprimer le problème de curseur que vous avez, vous devez utiliser des flotteurs, par exemple. float: left; (approche recommandée)
  4. ajouter un rembourrage petit ou grand et un encadrement de bordure pour aider à réduire les bords et aider également à la séparation de l'image et du texte
  5. le problème du curseur que vous rencontrez est dû au fait que lorsque vous à l'intérieur du bloc d'image, il est aligné verticalement vers le haut, ce que vous pouvez résoudre avec vertical-align: baseline; mais sans flotteurs, vous aurez toujours un curseur qui correspond à la hauteur de l'image et non au texte. De plus, si vous n'utilisez pas de flotteurs, le curseur sera allongé car la hauteur de la ligne est effectivement la même hauteur que l'image. La couleur bleue est juste un sélecteur, que vous modifiez également en utilisant CSS.
<html>
    <div class="editor">
        <!--        <editor></editor>-->
    </div>
</html>

<style>
    .editor {
        position: relative;
        display: block;
        padding: 10px;
    }

    .editor p {
        font-weight: 400;
        font-size: 1rem;
        font-family: Roboto, Arial, serif;
        color: #777777;
        display: inline;
        vertical-align: baseline;
    }

    .editor img {
        width: 50px;
        float: left;
        padding: 20px;
    }

</style>

Exemple d'extension de nœud

Exemple de Node extension pour l'alignement de texte qui peut être ajouté comme barre d'outils. Article beaucoup plus long, mais même si vous avez créé un Node/plugin pour les images que vous doivent gérer la manière dont il est rendu, c'est-à-dire base64 par rapport à l'URL, etc.

export default class Paragraph extends Node {
    get name() {
        return 'paragraph';
    }

    get defaultOptions() {
        return {
            textAlign: ['left', 'center', 'right'],
        }
    }

    inputRules({ type }) {
        return [
            markInputRule(/(?:\*\*|__)([^*_]+)(?:\*\*|__)$/, type),
        ]
    }

    get schema() {
        return {
            attrs: {
                textAlign: {
                    default: 'left'
                }
            },
            content: 'inline*',
            group: 'block',
            draggable: false,
            inclusive: false,
            defining : true,
            parseDOM: [
                {
                    tag: 'p',
                    style: 'text-align',
                    getAttrs: value => value
                }
            ],

            toDOM: (node) => [ 'p', {
                style: 'text-align:' + node.attrs.textAlign,
                class: `type--base type--std text-` + node.attrs.textAlign
            }, 0 ]

        };
    }

    commands ({ type }) {
        return (attrs) => updateMark(type, attrs)
    }
}

0
Nolan