Как получить один и тот же текст из этих 2 доступных для редактирования разделов с одинаковым содержимым, но разными структурами?

#javascript #html

#javascript #HTML

Вопрос:

Вот в чем дело:

Редактируемые содержимое плохие. Firefox обрабатывает это чем-то вроде div1 и Chrome делает это так div2 .

Оба имеют одинаковое текстовое содержимое (с точки зрения пользователя), но они структурированы по-разному.

Когда я получаю оба текстовых содержимого с помощью innerText , я получаю разные результаты из-за того, как они структурированы.

Есть ли способ получить эти тексты и вернуть ту же строку (поскольку они выводят точно такой же текст на экран)?

Что-то вроде:

div1 = div2 = "Line1nLine2nnLine3nnnLine4" (фактически, это div1 результат, поскольку он состоит только из текста и разрывов). div2 в этом случае проблема.

Псевдокод того, что мне нужно:

«Получите мое текстовое содержимое этих файлов div с количеством разрывов на основе того, что отображается на экране».

Конечная цель:

Чтобы последовательно вставлять новый текст в обе структуры, мне нужен способ обрабатывать их одинаково.

 const div1 = document.getElementById('div1');
const div2 = document.getElementById('div2');
const p1 = document.getElementById('p1');
const p2 = document.getElementById('p2');

p1.innerText = JSON.stringify(div1.innerText);
p2.innerText = JSON.stringify(div2.innerText);  
 #div1 {
  border: 1px dotted blue;
}

#div2 {
  margin-top: 40px;
  border: 1px dotted red;
}  
 <div id="div1" contenteditable>
  Line1
  <br>
  Line2
  <br>
  <br>
  Line3
  <br>
  <br>
  <br>
  Line4
</div>

<p><b>Div1 innerText:</b></p>
<p id="p1"></p>

<div id="div2" contenteditable>
  <div>Line1</div>
  <div>Line2</div>
  <div><br></div>
  <div>Line3</div>
  <div><br></div>
  <div><br></div>
  <div>Line4</div>
</div>

<p><b>Div2 innerText:</b></p>
<p id="p2"></p>  

Комментарии:

1. Любое закрытие </div> добавит n , а также любой <br>

2. Почему бы вам не использовать <textarea> вместо contenteditable ?

3. @iArcadia Мне нужно оформить некоторые части содержимого в системе «отмеченных упоминаний пользователей».

4. Все еще возможно. Вы могли бы преобразовать свой <div> контент в <textarea> по щелчку мыши, а затем изменить его при нажатии снаружи. Просто идея.

5. @iArcadia как я могу преобразовать div содержимое a в textarea ? div Было бы contenteditable ли это? У вас есть какой-нибудь пример кода для этого? Спасибо!

Ответ №1:

Я предложил вам в комментариях преобразовать ваш <div> контент в <textarea> элемент. Это решение позволяет избежать различий в поведении между Firefox и Chrome.

Ниже приведен простой пример того, как этого можно достичь. Я думаю, вы сможете адаптировать его к тому, что именно вы хотите (например, переключившись <p> на <div> ).

 const contentEditable = document.querySelector('#content-editable'),
  htmlPreview = document.querySelector('#html-preview');

htmlPreview.innerText = contentEditable.innerHTML;

contentEditable.addEventListener('click', contentEditableHtmlToTextarea);

/**
 * Converts HTML of #content-editable into <textarea>.
 */
function contentEditableHtmlToTextarea() {
  const textarea = document.createElement('textarea'),
    height = contentEditable.offsetHeight;
  
  // Converts <p> tags to rn.
  textarea.value = this.innerHTML
    .replace(/^s*/gm, '')
    .replace(/<p>(.*?)</p>/g, '$1rn')
    .trim();
    
  // Updates #content-editable HTML.
  this.innerHTML = '';
  this.appendChild(textarea);
  
  textarea.style.height = `${height}px`;
  htmlPreview.style.display = 'none';
  
  this.removeEventListener('click', contentEditableHtmlToTextarea);
  
  // A bit tricky, but without timeout, the callback is directly called.
  setTimeout(() => {
    document.addEventListener('click', contentEditableTextareaToHtml);
  }, 0);
}

/**
 * Converts <textarea>'s value into HTML for #content-editable.
 */
function contentEditableTextareaToHtml(e) {
  const textarea = contentEditable.querySelector('textarea'),
    // Converts lines into <p> tags.
    html = textarea.value.replace(/^(. ?)$/gm, '<p>$1</p>');
    
  // Checks if the mouse click is outside the <textarea>.
  if (e.target !== textarea) {
    // Updates #content-editable HTML.
    textarea.remove();
    contentEditable.innerHTML = html;
    htmlPreview.innerText = contentEditable.innerHTML;
    
    htmlPreview.style.display = 'block';
    
    document.removeEventListener('click', contentEditableTextareaToHtml);
    contentEditable.addEventListener('click', contentEditableHtmlToTextarea);
  }
}  
 div {
  padding: 3px;
  
  border: 1px solid #000;
}

textarea {
  margin: 0 auto;
  display: block;

  width: 98%;
}  
 <div id="content-editable">
  <p>Line 1</p>
  <p>Line 2</p>
  <p>Line 3</p>
</div>

<pre id="html-preview"></pre>