Положение каретки и высота выделения для встроенных элементов в Chrome - PullRequest
8 голосов
/ 21 апреля 2020

Я пытаюсь создать редактор с Slate или ProseMirror и вижу странное поведение с Chrome вокруг позиции каретки и области выделения при использовании встроенного элемента. Выпуск 1 показан на первом рисунке ниже. Когда позиция текстового курсора находится позади «f», каретка отображается вверху изображения. Проблема 2 на втором изображении - выделение текста показывает выделенную область, такую ​​же высокую, как у встроенного элемента. Есть ли способ контролировать это поведение и вместо этого показывать каретку в позиции текста и только выделять пространство вокруг текста (даже если встроенное изображение увеличивает высоту строки) caret position too high selection area too big

Я бы хотел имитировать поведение c здесь, начиная с firefox: enter image description here enter image description here

Примеры изображений были получены с использованием демонстрации ProseMirror здесь: https://prosemirror.net/examples/basic/

Минимальный пример (спасибо @Kaiido) с JSBin :

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

Не уверен, как это ведет себя в других операционных системах, но я использую macOS Catalina.

Ответы [ 3 ]

4 голосов
/ 25 апреля 2020

Вы можете исправить проблему выбора, используя flexbox. Первоначально я пытался использовать align-items: flex-end, но у меня получалось странное поведение клавиш со стрелками. align-items: baseline, кажется, работает на данный момент.

Проблема с изображением очень странная. Я заметил, что Chrome переходит элементы SVG не так, как элементы IMG. На данный момент последняя версия Chrome «ждет», прежде чем пропустить IMG, но позволяет пользователю пропустить SVG, как и любой другой символ (стрелка влево пропускает символ, ближайший к svg). Это может быть вызвано базовыми стилями по умолчанию, но я не знаю.

Я собирался опубликовать свои выводы, но понял, что Firefox не работает так же. Firefox имеет странное поведение клавиш со стрелками при использовании SVG и / или Flexbox. Курсор перемещается над изображением, но только при нажатии клавиши со стрелкой вправо.

Однако Firefox отлично работает с обычным элементом IMG.

Короче говоря, вам придется отображать различные элементы изображения на основе браузера.

// chrome contenteditable ads spaces between spans.
// firefox does not, so you have to add them manually.
if (navigator.userAgent.indexOf("Firefox") > 0) {
  Array.from(document.querySelectorAll('#editable span')).forEach(el => {
    el.innerHTML += " "
  })
}
.flexit {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
}

span {
 display: inline-block;
 white-space: pre;
}

.img-wrapper, .img-wrapper + span {
display: inline;
}
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>

<body>
  <h1>chrome</h1>
  <div contenteditable="true" class="flexit">
    <span>test</span><svg width="200" height="200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">       
  <image href="https://mdn.mozillademos.org/files/6457/mdn_logo_only_color.png" height="200" width="200"/>
    </svg><span>Here</span><span>is</span><span>a</span><span>longer</span><span>sentence.</span><span>Notice</span><span>I</span><span>wrapped</span><span>each</span><span>word</span><span>in</span><span>a</span><span>span.</span><span>This</span><span>makes</span><span>the</span><span>text</span><span>appear</span><span>like</span><span>it</span><span>is</span><span>inline.</span>
  </div>

  <h1>firefox</h1>
  <div contenteditable="true" id="editable">
    <span>test</span><span class="img-wrapper"><img src="https://mdn.mozillademos.org/files/6457/mdn_logo_only_color.png" height="200" width="200" /></span><span>test</span><span>Here</span><span>is</span><span>a</span><span>longer</span><span>sentence.</span><span>Notice</span><span>I</span><span>wrapped</span><span>each</span><span>word</span><span>in</span><span>a</span><span>span.</span><span>This</span><span>makes</span><span>the</span><span>text</span><span>appear</span><span>like</span><span>it</span><span>is</span><span>inline.</span>


  </div>
</body>

</html>

PS Многие редакторы, которые я использовал по умолчанию для полноразмерных изображений.

Редактировать: я только что понял, что оно появляется Мое Firefox решение также работает в последней Chrome. Я думаю, что это работает, потому что я обернул текстовые узлы в элементы SPAN. Элемент SVG по-прежнему работает по-другому в Chrome, но перенос текста в SPAN, похоже, решает большинство проблем.

0 голосов
/ 26 апреля 2020

Во-первых, не манипулируйте DOM ProseMirror, как показано в примере JQuery. На самом деле вы, скорее всего, столкнетесь с проблемами DOM или контента. ProseMirror использует свой собственный узел DOM и схему разметки. Если вы хотите управлять DOM ProseMirror или добавить плагин, взгляните на разметку, плагин и Node Apis. Я приложил простой пример текста разметки кода разметки. Примечание: причина, по которой Grammarly и другие не имеют подключаемых модулей ProseMirror, заключается в подходе / моделях DOM. Я должен добавить, что ProseMirror очень хорош, но, честно говоря, это скорее продвинутое решение для разработчиков.

Кроме хороших новостей, проблемы у вас чисто CSS. ProseMirror удаляет все классы и сбрасывает DOM / CSS, так что если вы импортируете документ или вырезаете и вставляете все / большинство ваших классов пропадет. div и назначьте класс для div, затем добавьте стили и дочерние стили для этого класса. Причина этого заключается в том, что селекторы css, такие как img, p, h, et c, будут применяться только к тегам внутри класса редактора. Без этого вы получите очевидные конфликты CSS.

CSS

  1. Не используйте flexbox для встроенных изображений, поскольку flexbox не является сеткой система. На самом деле, если я вспомню, вы не можете встроить прямые дочерние элементы flex-контейнера.
  2. , встроенный в теги p, и img не будет переносить текст, и вы столкнетесь с проблемами, перечисленными выше.
  3. если вы хотите по-настоящему обернуть и удалить проблему с курсором, то вам нужно использовать поплавки, например float: left; (рекомендуемый подход)
  4. добавить небольшие или большие отступы и рамку для рамки, чтобы помочь с сворачивание краев, а также помогает с разделением изображения и текста
  5. проблема с курсором, которую вы испытываете, заключается в том, что когда вы внутри блока изображения, он вертикально выровнен по верху, который вы можете исправить с помощью vertical-align: baseline;, но без поплавков вы будете все еще есть курсор, который соответствует высоте изображения, а не текста. Кроме того, если вы не используете поплавки, курсор будет удлинен, так как высота линии фактически равна высоте изображения. Синий цвет - просто селектор, который вы также можете изменить, используя 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>

Пример расширения узла

Пример расширения узла для выравнивания текста, которое можно добавить в качестве панели инструментов. Гораздо дольше публиковать, но даже если вы создали Node / плагин для изображений, вам придется иметь дело с тем, как он рендерит, то есть base64 против url и т. Д. c. что, кстати, вполне понятно, почему они это сделали, но просто добавьте сложности разработчикам, которые ищут SEO, и т. д. c.

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 голосов
/ 25 апреля 2020

Я попытался сделать небольшой хак с HTML и css.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>

<div contenteditable><p class="new1" contenteditable>Hello</p><div contenteditable> 
<img src="https://upload.wikimedia.org/wikipedia/en/9/9b/Yoda_Empire_Strikes_Back.png"></div> 
<p class="new2">Testing</p>
</div>
</body>
</html>

// css

.new2{


font-size:30px;
margin-top:-35px;
margin-left:252px;
padding-left:79px;
}


img{
margin-left:75px;
padding-left:5px;
padding-right:5px;
margin-top:-300px;
}

.new1{
text-overflow:hidden;
padding-top:260px;
margin-bottom:-20px;
font-size:30px;
padding-right:10px;
}

Вот jsfiddle https://jsfiddle.net/wtekxavm/1/

...