Курсор в contenteditable не ведет себя должным образом в Chrome - PullRequest
0 голосов
/ 13 сентября 2018

У меня есть проблема, когда курсор переходит в неправильное место, когда пользователь щелкает внутри contenteditable div, но за пределами реального текста. Кажется, это проблема только в более новых версиях Chrome (а также Opera): по совпадению я проверил мой пример в более старом браузере (Chrome версии 55), и проблема вообще отсутствовала. Нет проблем в Edge / IE11 / FireFox.

Эта проблема возникает, только когда пользователь щелкает мышью за строкой текста или пустой строкой, которая находится между двумя желтыми divs с классом pagebreak. Курсор заканчивается над первым pagebreak div. И неважно, имеет ли это прямое отношение, я не знаю, но проблема исчезает при удалении div с классом flowbox. К сожалению, я не могу удалить это div с классом flowbox из приложения.

Я собрал пример, показывающий мою проблему в этой скрипке: https://jsfiddle.net/dymcn1ao/

<div class="textframe a">
    <div class="flowbox"></div>
    <article contenteditable="true">
        <p>
            <span>
                <span>Foo bar baz</span>
                <br>
                <span class="pagebreak" contenteditable="false" style="min-height: 80px"></span>
                <span>Foo bar baz</span>
                <br>
                <span>Lorem ipsum dolor sit amet, consectetur adi piscing elit.</span>
                <br>
                <br>
                <span class="pagebreak" contenteditable="false" style="min-height: 80px"></span>
                <br>
                <span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span>
            </span>
        </p>
    </article>
</div>

Текстовое поле слева имеет проблему, правое поле работает, как и ожидалось, поскольку .flowbox div был удален.

Редактировать 1:

Я создал новый пример, который, возможно, легче понять. Другие элементы в .textframe (например, элементы pagebreak и flowbox) действительно имеют конкретные цели, поэтому их нельзя игнорировать. Вот ссылка на улучшенную демонстрацию: https://jsfiddle.net/q4pu37dn/15/

Ответы [ 5 ]

0 голосов
/ 17 сентября 2018

Обновление 3 (Демо 3)


enter image description here

Изменения

Я заметил, что в больше не используется position: relative самый последний код операции , что хорошо, но я думаю, что это было забыто:

<span class='pagebreak spacer' contenteditable = "ложь" ></span>

Я полагаю, что вы изначально использовали contenteditable="false", чтобы придать вашим .pagebreak дополнительным функциональным возможностям, а также предотвратить их удаление, поэтому я добавил их обратно.


Сравнение

Демонстрация 3 содержит мое решение рядом с OP-кодом для сравнения поведения. Demo 3 также имеет 2 кнопки (по 1 для каждого редактора контента), которые выделяют каждый <span> текста. Ниже приведен список классов из кода OP (редактор содержимого справа) и список всех классов, равных по сравнению с моим кодом (редактор содержимого слева).

  1. div.textframe ................ section.editor
  2. p.textOutline ................ article.content
  3. span.flowbox.spacer ...... mark.vertRule
  4. span.pagebreak.spacer .. mark.breaker

Есть 2 требования, которые касаются ФП:

  1. При щелчке по пустым областям, окружающим <span>s, курсор переместится в угол области содержимого.

  2. Количество символов в строке должно соответствовать текущей емкости кода OP.

Эта проблема существовала годами, но причина - туманность, поэтому, если вы относитесь к этому аберрационному поведению как к простому поведению, вы можете просто противостоять ему, прививая другое поведение.

Demo2 и Demo3 отвечают этим требованиям, просто применяя следующие наборы стилей:

Демо 2

article p {display: table;...

Демо 3

.content {display:table-cell;...

Поведение ячеек таблиц жесткое и хорошо разработанное, и AFAIK - единственный не замененный элемент , который по умолчанию соответствует его содержимому и соответствует окружающим элементам таблицы. В качестве бонуса элемент с display: table-cell (не <td>) не обязательно должен быть вложен в <tr>, что в <table>.


Демо 3

.content { display: table-cell;...

Fiddle

/* Begin Defaults */

* {
  margin: 0;
  padding: 0;
  border: 0;
  box-sizing: border-box;
}

html,
body {
  background: white;
  font: 400 16px/1.45 Arial;
  height: 100%;
  width: 100%;
}

/* End Defaults */

/* Begin Optionak Layout */

#page01 {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-evenly;
  align-items: flex-start;
  background: rgba(45, 99, 198, 0.6);
  margin: 0 auto 20px;
  height: fit-content;
  min-width: 100%
}

/* End Optional Layout */

/* Begin Primary Styles */

.editor {
  width: 350px;
  height: 600px;
  border: 1px solid black;
  background: #fff;
}

.vertRule {
  float: right;
  clear: right;
  width: 30px;
  height: 600px;
}

.content {
  display: table-cell;
  word-break: break-word;
}

mark {
  display: block;
  pointer-events: none;
}

.break {
  min-height: 80px;
}

/* End Primary Styles */

/* Begin Control */

/* https://jsfiddle.net/q4pu37dn/15 */

.textframe {
  width: 350px;
  height: 600px;
  border: 1px solid black;
  background: #fff;
}

.flowbox {
  float: right;
  clear: right;
  width: 30px;
  height: 600px;
}

.spacer {
  background: yellow;
}

.pagebreak {
  display: block;
  min-height: 80px;
}

/* End Control */

/* Begin Demo Test */

.btn {
  display: inline-block;
  font: inherit;
  margin: 5px 10px;
  padding: 2px 5px;
  border: 5px outset grey;
  border-radius: 8px;
  color: #000;
  cursor: pointer;
}

[type='checkbox']:checked+label {
  background: rgba(255, 12, 34, 0.75);
  border: 5px inset grey;
  color: #fff;
}

#outline1:checked+label+#outline2+label+hr+#page01>.editor>.content *,
#outline2:checked+label+hr+#page01>.textframe>#textOutline *:not(.spacer) {
  color: #fff;
  background: tomato;
  outline: 2px solid red;
}

#outline1:checked+label+#outline2+label+hr+#page01>.editor>.content>.break,
#outline2:checked+label+hr+#page01>.textframe>#textOutline>.spacer {
  background: yellow;
  outline: none;
}

/* End Demo Test */
<!-- Begin Demo Test -->

<input id="outline1" type='checkbox' hidden>
<label for='outline1' class='btn'>Outline 1</label>

<input id="outline2" type='checkbox' hidden>
<label for='outline2' class='btn'>Outline 2</label>

<hr>

<!-- End Demo Test -->

<!-- Begin Optional Layout Part 1 -->

<main id='page01'>

  <!-- End Optional Layout Part 1 -->

  <!-- Begin Primary Markup -->

  <section class="editor" contenteditable='true'>
    <mark class="vertRule" contenteditable='false'></mark>
    <article class='content'>
      <span>
      Clicking here is not a problem
    </span>
      <br>
      <br>
      <span>
      Lorem ipsum
    </span>
      <mark class="break" contenteditable='false'></mark>
      <span>
      Clicking here (on empty space, not directly on text) will put the caret above the first .break element.
    </span>
      <br>
      <br>
      <span>
      Lorem ipsum
    </span>
      <mark class="break" contenteditable='false'></mark>
      <br>
      <span>
      Clicking here is not a problem
    </span>
      <br>
      <br>
    </article>
  </section>

  <!-- End Primary Markup -->

  <!-- Begin Control -->

  <div class="textframe" contenteditable>

    <p id='textOutline'>

      <span class="spacer flowbox"></span>
      <span>
      Clicking here is not a problem
    </span>
      <br>
      <br>
      <span>
      Lorem ipsum
    </span>
      <span class="spacer pagebreak"></span>
      <span>
      Clicking here (on empty space, not directly on text) will put the caret above the first .pagebreak element.
    </span>
      <br>
      <br>
      <span>
      Lorem ipsum
    </span>
      <span class="spacer pagebreak"></span>
      <br>
      <span>
      Clicking here is not a problem
    </span>
      <br>
      <br>
    </p>
  </div>

  <!-- End Control -->

  <!-- Begin Optional Layout Part 2 -->

</main>

<!-- End Optional Layout Part 2 -->


Обновление 2 (Демо 2)


ОП в отношении демонстрации 1:

"Вы решили это для моего надуманного примера, да. К сожалению, невозможно установить эти значения для элементов в реальном приложении, поток полностью выходит из строя."

См. Демо 2 , работает лучше, чем Демо 1 . Поскольку он использует только позиционированные элементы, в потоке нет конфликтов. Чтобы адаптировать Demo 2 к вашему приложению, все, что вам нужно сделать, это добавить position:relative к родительским элементам. Соответствующий стиль выглядит следующим образом:

article p {display: table;...

Необходимо было присвоить position:relative всему, что вложено в .textframe, иначе элементы static не будут взаимодействовать с позиционированными элементами. Существуют правила, которым придерживаются таблицы и их компоненты, которые применяются не только к его содержимому, но и к тому, как они взаимодействуют со своими соседними элементами.


Демо 2

article p {display: table...

.container {
  width: 400px;
  float: left
}

.textframe {
  width: 350px;
  height: 650px;
  outline: 2px dotted lightblue;
  overflow: hidden;
  margin: 0 15px 0 0;
  /* Needed for long words */
  word-break: break-word;
}

.textframe article {
  position: relative;
  height: 650px; 
}

article p {
  display: table;
  margin: 0;
  position:relative;
}

.flowbox {
  width: 2px;
  height: 650px;
  float: right;
  clear: right;
  outline: 1px solid red;
}

.pagebreak {
  display: block;
  pointer-events:none;
  position:relative;
}
<div class="container">
      <h4>
       article p {display: table; position: relative;}<br>
       all children of .textframe have: position: relative;  
      </h4>
      <div class="textframe a">
        <div class="flowbox"></div>
        <article contenteditable="true">
           <p>
            <span>
              <span>Foo bar baz</span>
            <br>
            <mark class="pagebreak" contenteditable="false" style="min-height: 80px"></mark>
            <span>Foo bar baz</span>
            <br>
            <span>Lorem ipsum dolor sit amet, consectetur adi piscing elit.</span>
            <br>
            <br>
            <mark class="pagebreak" contenteditable="false" style="min-height: 80px"></mark>
            <br>
            <span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span>
            </span>
          </p>
          <hr>
        </article>
      </div>
    </div>

Refences

MDN - число с плавающей запятой

MDN - Позиция

Фокусы CSS - абсолютное позиционирование внутри относительного позиционирования

CSS-хитрости - все о плаваниях

дисплей: таблица / ячейка таблицы

слово-брейк: брейк-слово


0 голосов
/ 17 сентября 2018

Я думаю, что проблема в span, если у вас есть пустой span.Я прошел через эту проблему, работая с contenteditable, поэтому курсор появляется там, но вы не можете заставить его двигаться.

Я предложу вам удалить span из вашего p для каждого абзаца, чтобы, если spanпусто, попробуйте удалить его на backspace / delete.

Или обратитесь к CKEDITOR , поскольку это решило эту проблему

article p, article div
{
    line-height: 1.25;
    margin-top: 12px;
    margin-bottom: 12px; /*  margin-bottom: 10px; removed for proper pagebreak 31-1-2017*/
    font-family: Helvetica;
}

.title {
  left: 20px;
}
.container {
  float: left;
  width: 400px;
}
.textframe {
  width: 311px;
  height: 650px;
  outline: 2px dotted lightblue;
  overflow: hidden;
  margin: 0 15px 0 0;
}
.textframe.b {
  left: 380px;
}
.textframe article {
  position: relative;
  height: 650px;
}
article p {
  margin: 0;
}
.pagebreak {
  display: block;
  position: relative;
  background: yellow;
}
.flowbox {
  width: 2px;
  height: 650px;
  float: right;
  clear: right;
  outline: 1px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <h4>
    With problem:
  </h4>
  <div class="textframe a">
    <div class="flowbox"></div>
    <article contenteditable="true">
      <p>
        <span>
          <span>Foo bar baz</span>
          <br>
          <span class="pagebreak" contenteditable="false" style="min-height: 80px"></span>
          <span>Foo bar baz</span>
          <br>
          <span>Lorem ipsum dolor sit amet, consectetur adi piscing elit.</span>
          <br>
          <br>
          <span class="pagebreak" contenteditable="false" style="min-height: 80px"></span>
          <br>
          <span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span>
        </span>
      </p>
    </article>
  </div>
</div>
<div class="container">
  <h4>
    Without problem:
  </h4>
  <div class="textframe b">
    <article contenteditable="true">
      <p>
        <span>
          <span>Foo bar baz</span>
          <br>
          <span class="pagebreak" contenteditable="false" style="min-height: 80px"></span>
          <span>Foo bar baz</span>
          <br>
          <span>Lorem ipsum dolor sit amet, consectetur adi piscing elit.</span>
          <br>
          <br>
          <span class="pagebreak" contenteditable="false" style="min-height: 80px"></span>
          <br>
          <span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span>
        </span>
      </p>
    </article>
  </div>
</div>
0 голосов
/ 17 сентября 2018

Я использую новейшую версию Chrome для Linux / Ubuntu, и это, похоже, решило проблему. Я только что удалил contenteditable из статьи и поместил его в промежутки, которые вы хотели редактировать.

<article>
      <p>
        <span>
          <span contenteditable="true">Foo bar baz</span>
          <br>
          <span class="pagebreak" contenteditable="false" style="min-height: 80px"></span>
          <span contenteditable="true">Foo bar baz</span>
          <br>
          <span contenteditable="true">Lorem ipsum dolor sit amet, consectetur adi piscing elit.</span>
          <br>
          <br>
          <span class="pagebreak" contenteditable="false" style="min-height: 80px"></span>
          <br>
          <span contenteditable="true">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span>
        </span>
      </p>
    </article>
0 голосов
/ 17 сентября 2018

Эта проблема возникает из-за того, что вы используете float: right;.

Не используйте свойство CSS float: right;, если оно вам не нужно. У вас может быть много проблем с этим. В твоем случае тебе это не нужно. Вместо этого вы используете элементы inline-block как <div class="flowbox"> и <article contenteditable="true">.

Минимальный пример с float:right (проблема СО)

.textframe {
    width: 311px;
    height: 650px;
    outline: 2px dotted lightblue;
    overflow: hidden;
    margin: 0 15px 0 0;
}
.flowbox {
    width: 2px;
    height: 650px;
    float: right;
    clear: right;
    outline: 1px solid red;
}
.pagebreak {
    display: block;
    position: relative;
    background: yellow;
}
<div class="container">
  <h4>
    With problem:
  </h4>
  <div class="textframe a">
    <div class="flowbox"></div>
    <article contenteditable="true">
      <p>
        <span>
          <span>Foo bar baz</span>
          <br>
          <span class="pagebreak" contenteditable="false" style="min-height: 80px"></span>
          <span>Foo bar baz</span><br>
          <span>Lorem ipsum CLICK ABOVE THIS WORDS sit amet, consectetur adi piscing elit.</span>
          <br>
          <br>
          <span class="pagebreak" contenteditable="false" style="min-height: 80px"></span>
          <br>
          <span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span>
        </span>
      </p>
    </article>
  </div>
</div>

Решение

Минимальный пример с display:inline-block (без проблем)

Примечание: теперь я поместил ваш <div class="flowbox"></div> после <article> элемента.

.textframe {
    width: 311px;
    height: 650px;
    outline: 2px dotted lightblue;
    overflow: hidden;
    margin: 0 15px 0 0;
}
.flowbox {
    width: 2px;
    height: 650px;
    outline: 1px solid red;
}
.pagebreak {
    display: block;
    position: relative;
    background: yellow;
}
.flowbox, article{display:inline-block;vertical-align:top;}
article{width: 305px;}
<div class="container">
  <h4>
    With problem:
  </h4>
  <div class="textframe a">
    <article contenteditable="true">
      <p>
        <span>
          <span>Foo bar baz</span>
          <br>
          <span class="pagebreak" contenteditable="false" style="min-height: 80px"></span>
          <span>Foo bar baz</span><br>
          <span>Lorem ipsum CLICK ABOVE THIS WORDS sit amet, consectetur adi piscing elit.</span>
          <br>
          <br>
          <span class="pagebreak" contenteditable="false" style="min-height: 80px"></span>
          <br>
          <span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span>
        </span>
      </p>
    </article>
    <div class="flowbox"></div>
  </div>
</div>
0 голосов
/ 17 сентября 2018

Проблема с дисплеем, я тоже новичок в этом, но когда я изменил ваш диапазон на div, он работал нормально, дайте мне знать, если это правильно, или я не смог правильно понять ваш вопрос.

Теперь я не уверен, почему это произошло, поэтому не могу дать вам подробное объяснение.

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

.title {
  left: 20px;
}
.container {
  float: left;
  width: 400px;
}
.textframe {
  width: 311px;
  height: 650px;
  outline: 2px dotted lightblue;
  overflow: hidden;
  margin: 0 15px 0 0;
}
.textframe.b {
  left: 380px;
}
.textframe article {
  position: relative;
  height: 650px;
}
article p {
  margin: 0;
}
.pagebreak {
  display: block;
  position: relative;
  background: yellow;
}
.flowbox {
  width: 2px;
  height: 650px;
  float: right;
  clear: right;
  outline: 1px solid red;
}
<div class="container">
  <h4>
    With problem:
  </h4>
  <div class="textframe a">
    <div class="flowbox"></div>
    <article contenteditable="true">
      <p>
        <span>
          <span>Foo bar baz</span>
          <br>
          <span class="pagebreak" contenteditable="false" style="min-height: 80px"></span>
          <div>Foo bar baz</div>
          <br>
          <div>Lorem ipsum dolor sit amet, consectetur adi piscing elit.</div>
          <br>
          <br>
          <span class="pagebreak" contenteditable="false" style="min-height: 80px"></span>
          <br>
          <span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span>
        </span>
      </p>
    </article>
  </div>
</div>
<div class="container">
  <h4>
    Without problem:
  </h4>
  <div class="textframe b">
    <article contenteditable="true">
      <p>
        <span>
          <span>Foo bar baz</span>
          <br>
          <span class="pagebreak" contenteditable="false" style="min-height: 80px"></span>
          <div>Foo bar baz</div>
          <br>
          <div>Lorem ipsum dolor sit amet, consectetur adi piscing elit.</div>
          <br>
          <br>
          <span class="pagebreak" contenteditable="false" style="min-height: 80px"></span>
          <br>
          <span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span>
        </span>
      </p>
    </article>
  </div>
</div>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...