Довольно часто приходится сталкиваться с необходимостью записать некий текст, а иногда и html-код из JS в какой-либо элемент html-разметки. Существует несколько способов это сделать. Давайте рассмотрим их подробнее.
Способ 1. Использование метода document.write
Метод document.write
существует в JavaScript с незапамятных времен и позволяет вывести не только текст, но и любые теги разметки на вашу html-страницу, например:
1 2 3 4 5 6 7 8 | <style> .my-div {max-width: 300px; padding: 10px; margin: 10px 0; border: 3px solid red; } </style> <script> document.write("Просто текст и перевод строки<br>Вторая строка текста"); document.write('<p style="color: red; font-family: Cambria, serif">Абзац со стилевыми свойствами</p>'); document.write('<div class="my-div">Div c классом .my-div</div>'); </script> |
Результат внедрения этого скрипта будет таким:
Все бы хорошо, но у этого метода есть одна особенность - он хорошо работает в процессе загрузки html-страницы. Метод document.write
вставляет текст в то место html-разметки, где был вызван, ещё до формирования DOM-структуры, которую браузер строит в процессе парсинга страницы. Поэтому строки, записанные тем кодом, который приведен выше, внедряется в html-документ так, как если бы они присутствовали изначально в разметке.
Хуже обстоит дело с попытками использовать метод document.write
при клике на кнопку, например. В этом случае текущая страница заменяется на новую с тем текстом, который вы использовали внутри скобок document.write
. Попробуйте сами в примере ниже.
Существует также метод document.writeln()
, который отличается от document.write()
тем, что добавляет символ перевода строки "\n"
. В большинстве случаев это никак визуально не видно, т.к. в html-коде для перевода строки нужен тег <br>
, а не перевод строки символом \n
. Разницу можно заметить в таком элементе формы, как textarea
, где перевод строки как раз выполняется с помощью этого символа.
Для сравнения сделаем несколько строк текста без всяких тегов с помощью обоих методов, а затем применим их для вывода текста внутри textarea
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <h2>Метод document.write</h2> <script> document.write("Первая строка текста в структуре html"); document.write("Вторая строка текста в структуре html"); document.write("<textarea>"); document.write("Первая строка текста"); document.write("Вторая строка текста"); document.write("</textarea>"); </script> <h2>Метод document.writeln</h2> <script> document.writeln("Первая строка текста в структуре html"); document.writeln("Вторая строка текста в структуре html"); document.writeln("<textarea>"); document.writeln("Первая строка текста"); document.writeln("Вторая строка текста"); document.writeln("</textarea>"); </script> |
В примере можно заметить, что при использовании document.writeln()
появляется дополнительный пробел между двумя строками в обычном тексте и перевод строки внутри textarea
.
Метод document.write
Метод document.writeln
Оба этих метода можно использовать, когда вы учите JavaScript, для того чтобы вывести массив, например, или какую-либо разметку на страницу, а не в консоль. На html-странице, которая уже сформирована, вряд ли стоит применять document.write()
или document.writeln()
, т.к. они перезапишут ее содержимое.
И мы опять возвращаемся к популярному вопросу "Как записать строку из JS в HTML?". И переходим к свойству innerHTML
.
Способ 2. Использование свойства innerHTML
Для любого элемента можно получить и записать свойство innerHTML
, которое в соответствии с переводом с английского позволяет управлять внутренним html-кодом выбранного элемента. Это свойство замещает весь html-код, который был внутри выбранного элемента, на тот, который вы присвоили ему в качестве значения.
Например, такой код сотрет все содержимое данной статьи:
1 2 3 4 | let section = document.querySelector('section'); section.innerHTML = ''; section.innerHTML += `<button class="btn" onclick="location.reload()" type="button"> Обновить страницу</button>`; |
Поскольку свойство innerHTML
принимает в качестве значения строку, вы вполне можете воспользоваться оператором "+" для конкатенации строк и формировать содержимое элемента таким образом:
1 2 3 | elem.innerHTML = "Первая строка текста<br>"; elem.innerHTML += "Вторая строка текста<br>"; elem.innerHTML += "Третья строка текста"; |
Следующий пример позволяет заменить внутреннее содержимое элемента (абзаца) с id="temp-text"
, который содержит внутренние теги, на другой текст с внутренней разметкой.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <p id="temp-text">Текст с <strong>жирным</strong> и <em>курсивным</em> форматированием.</p> <button type="button" class="btn" onclick="getHTML()">Получить html-разметку абзаца</button> <button type="button" class="btn" onclick="changeHTML()">Изменить html-разметку абзаца</button> <script> let elem = document.getElementById('temp-text'); function getHTML(){ alert(elem.innerHTML); } function changeHTML(){ elem.innerHTML =`<span style="color: red; font-style: italic">Измененный текст</span> абзаца с <strong style="color: blue;">html-разметкой</strong>`; } </script> |
Нажмите на кнопку "Получить html-разметку абзаца" до и после замены текста - и вы увидите внутренние теги, которые при добавлении внутрь выбранного абзаца отображаются в соответствии с правилами css и html.
Текст с жирным и курсивным форматированием.
Есть еще одно отличие свойства innerHTML
от метода document.write
. Оно заключается в том, что при ошибочном добавлении тегов, в innerHTML
браузер скорректирует синтаксис так, чтобы все теги были закрыты.
В предыдущем примере была допущена такая ошибка - не закрыт тег <strong>
,- и браузер это исправил, добавив 2 по сути ненужных тега, но при этом сохранив валидность html-кода.
Особенности поведения свойства innerHTML
Нельзя вставлять с помощью innerHTML
теги <script>
- такой код не выполнится. Хотя есть и обходной способ, когда можно использовать для этой цели события. Подробнее можно прочитать в статье на MDN.
Также свойство innerHTML
отсутствует у элементов без содержимого (изображения, <br>
, <input>
), оно может использоваться только для элементов с открывающим и закрывающим тегом.
В приведенном ниже примере мы попытаемся заместить изображение абзацем, но безуспешно.
1 2 3 4 5 6 7 8 9 10 11 12 | <div class="test"> <img src="images/headphones-02.jpg" alt="headphones" id="headphones" style="display:block; margin-bottom: 15px; box-shadow: 0 0 6px #000;"> <button class="btn btn-primary" onclick="innerImg()" type="button"> Заменить изображение</button> <script> let headphones= document.getElementById('headphones'); function innerImg(){ headphones.innerHTML = '<p>Теперь это абзац</p>'; } </script> </div> |
Попробуйте сами. Ничего не происходит, не так ли?
Способ 3. Свойство textContent
В том случае, когда вам НЕ нужно записывать строку из JS в html с дополнительной разметкой в виде html-тегов, лучше воспользоваться свойством textContent
. Оно позволяет манипулировать только текстом элемента.
В примере ниже вы можете добавить текст с тегами в текстовом поле. Этот текст отобразится в блоке с рамкой, когда вы будете печатать. Если нажать на кнопку "innerHTML"
, вы увидите преобразование тегов в текст с форматированием.
Так выглядит этот пример при применении свойства textContent
Тот же текст + теги, но при применении свойства innerHTML
Особенности поведения свойства textContent
textContent
вернетnull
, если элемент является документом, типом документа, или его описанием. Для получения всего текста и CDATA-данных во всём документе можно использовать это свойство в таком виде:document.documentElement.textContent
.- Если элемент представляет собой CDATA, комментарий или текстовый элемент, свойство
textContent
возвращает текст внутри узла в виде строки (т.н.nodeValue
). - Для элементов других типов
textContent
возвращает конкатенацию свойствtextContent
всех дочерних узлов, исключая комментарии и строки кода. Т.е. происходит склеивание текста всех вложенных элементов. Если узел не имеет дочерних узлов, будет возвращена пустая строка. - Установка данного значения удаляет все дочерние узлы и заменяет их единичным текстовым узлом с указанным значением.
Пример ниже демонстрирует, каким образом отображается текст блока со вложенными (дочерними) элементами при использовании свойства textContent
.
Block Header
Lorem ipsum dolor sit amet, consectetur adipisicing elit.
Consequuntur maxime, cumque facilis eos itaque inventore rerum.
Код примера:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <div id="textBlock"> <h3>Block Header</h3> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p> <p>Consequuntur maxime, cumque facilis eos itaque inventore rerum.</p> </div> <input type="button" id="btnBlock" value="Показать контент блока"> <div id="output"></div> <script> let textBlock = document.getElementById('textBlock'), output = document.getElementById('output'), btnBlock = document.getElementById('btnBlock'); btnBlock.onclick = function(){ output.textContent = textBlock.textContent } </script> |
Способ 4. Свойство innerText
Свойство innerText
подобно innerHTML
, но не подразумевает вставку html-тегов, только текст. И с этой точки зрения оно работает так же, как и свойство textContent
. Только у них несколько разная поддержка браузерами. По данным caniuse.com innerText поддерживает большинство браузеров, за исключением Firefox до 44 версии, доля использования которого в мире на данный момент составляет 0,17%.
Свойство textContent
имеет также очень приличную поддержку браузерами, но не работает в IE версий 6-8, которыми на данный момент пользуется 0,17% от всех компьютеров в мире.
Свойство innerText
было введено в свое время Internet Explorer-ом, а затем в 2016 было внедрено в стандарт HTML после адаптации всеми ведущими браузерами. По своим функциям это свойство подобно тексту, полученному пользователем при выделении содержимого элемента курсором и копировании его в буфер обмена. Работает innerText
по тому же принципу, что и textContent
, но есть некоторые отличия:
textContent
получает содержимое всех элементов, включая<script>
и<style>
, тогда какinnerText
этого не делает.innerText
умеет считывать стили и не возвращает содержимое скрытых элементов, тогда какtextContent
этого не делает.- Метод
innerText
позволяет получить CSS, аtextContent
— нет.
Способ 5. Свойство outerHTML
Свойство outerHTML
также, как и innerText
, было введено в InternetExplorer и является нестандартным, хотя на данный момент.
Давайте посмотрим, что нам вернет свойство outerHTML
на примере.
outerHTML property
Lorem ipsum dolor sit amet, consectetur adipisicing elit.
Consequuntur maxime, cumque facilis eos itaque inventore rerum.
Код данного примера:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | <style> #myBlock {border: 3px double blue; padding: 10px; background-color: #cde; } .innerMyBlock {margin: 5px 10px; border: 2px dashed #005aff; padding: 7px; } #myOutput {margin-top: 10px;} </style> <div class="test"> <div id="myBlock"> <div class="innerMyBlock"> <h3>outerHTML property</h3> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p> <p>Consequuntur maxime, cumque facilis eos itaque inventore rerum.</p> </div> </div> <input type="button" class="btn btn-primary" id="showOuterBtn" value="Показать контент outerHTML"> <input type="button" class="btn btn-primary" id="showInnerBtn" value="Показать контент innerHTML"> <div id="myOutput"></div> <script> let myBlock= document.getElementById('myBlock'), myOutpu1t = document.getElementById('myOutput'), outerBtn= document.getElementById('showOuterBtn'), innerBtn= document.getElementById('showInnerBtn'); outerBtn.onclick = function(){ myOutput.innerHTML = myBlock.outerHTML; } innerBtn.onclick = function(){ myOutput.innerHTML = myBlock.innerHTML; } </script> </div> |
При нажатии кнопки "Показать контент outerHTML" мы увидим контент, идентичный верхнему блоку, т.е. в нижний <div id="myOutput">
перенесется <div id="myBlock">
со всем содержимым. Зато при нажатии кнопки "Показать контент innerHTML" в нижнем блоке отобразится только контент вложенного <div class="innerMyBlock">
. Об этом свидетельсвует отсутствие двойной рамки и голубого фона.
Вывод: стоит использовать outerHTML
, если вы хотите полностью заменить элемент и его содержимое, а innerHTML
- если вы хотите заменить только содержимое элемента.
Способ 6. Метод insertAdjacentHTML()
В том случае, если вам не нужно заменять один текст на другой, а необходимо вставить дополнительный элемент или текст до или после нужного элемента или до или после текста этого элемента, необходимо использовать метод insertAdjacentHTML()
, имеющий такой синтаксис
1 | элемент.insertAdjacentHTML(способ вставки, код для вставки); |
Способ вставки в этом случае - это специальные строки, или ключевые слова:
- "beforeBegin" - перед элементом.
- "afterBegin" - внутрь элемента, в самое начало, т.е. сразу за открывающим тегом.
- "beforeEnd" - внутрь элемента, в конец, т.е. перед закрывающим тегом.
- "afterEnd" - после элемента.
Рассмотрим, как мы можем вставить элементы в различные до и после параграфа и его внутреннего текста с помощью примера:
Тестируем метод insertAdjacentHTML()
Абзац с текстом, вокруг которого можно вставить строки текста
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <div id="my-insert"> <h2>Тестируем метод insertAdjacentHTML()</h2> <p id="testParagraph">Абзац с текстом, вокруг которого можно вставить строки текста</p> </div> <form name="insert1"> <select name="where" id="where"> <option value="<blockquote>Цитата, вставленная beforeBegin</blockquote>">beforeBegin</option> <option value="<span style='color: red'>Отличная вставка текста beforeEnd</span>">beforeEnd</option> <option value="<span style='color: green'>Вставка текста afterBegin</span>">afterBegin</option> <option value="<div style='border: 3px dotted violet; padding: 10px; margin: 5px 0;'> Добавляем div с помощью afterEnd</div>">afterEnd</option> </select> </form> <script> let sel = document.insert1.where, par = document.getElementById('testParagraph'); sel.onchange = function() { let position = this.options[this.selectedIndex].text; par.insertAdjacentHTML(position, this.value); } </script> |
Посмотрим на результаты такого рода вставки строки из JavaScript в HTML:
С помощью Инспектора свойств (F12) можно сделать вывод, что ключевое слово beforeBegin добавляет элемент или текст ДО целевого элемента, afterEnd вставляет элемент или текст ПОСЛЕ целевого элемента, а afterBegin и beforeEnd добавляют текст или элементы внутрь целевого элемента до и после его текста соответственно.
Посмотреть другие примеры вы можете в сатье Создание html-элементов в JavaScript.
Способ 7. Использование методов jQuery html() и text()
Метод jQuery html()
использует нативное свойство innerHTML
. Некоторые браузеры могут возвратить результат не совсем в таком виде, в котором он присутствует на странице. К примеру, Internet Explorer иногда упускает кавычки у значений атрибутов.
В примере ниже при первом клике на любом из абзацев мы будем изменять текст на тот, в котором присутствуют html-теги, а при повторном клике увидим обычный текст без тегов:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <p class='jq-example'>Lorem ipsum</p> <p class='jq-example'>Dolor sit amet</p> <p class='jq-example'>Example text</p> <script> (function($) { let flag = true; $('.jq-example').on('click', function(){ if (flag) { $(this).html('I <b>changed</b> this <code>text</code>'); flag=false; } else { $(this).html('Text, only text'); flag=true; } }); })( jQuery ); </script> |
Попробуйте сами, сделав хотя бы 2 клика на каждом абзаце:
Lorem ipsum
Dolor sit amet
Example text
Метод jQuery text()
аналогично свойству innerText
изменяет только текст элемента, но не позволяет применить теги, т.к. они будут отображаться как текст, а не как теги.
В примере ниже мы можем ввести текст в поле ввода и при клике на кнопке изменить текст абзаца.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <p id='jq-text'>Измените <strong>текст</strong> абзаца</p> <p> <input type="text" name="change-text" id="change-text"> <button id="btn-change-text">Изменяем только текст</button> </p> <script> (function($) { $('#btn-change-text').on('click', function(){ let newText = $('#change-text').val(); $('#jq-text').text(newText ); }); $('#jq-text').click(function(){ alert($(this).html()); }); })( jQuery ); </script> |
Попробуйте вставить в поле ввода просто текст и текст с тегами.
Измените текст абзаца
Обратите внимание, что при попытке ввести теги в поле ввода, они просто отображаются в тексте без применения форматирования.
При клике на тексте абзаца вы увидите диалоговое окно, в котором все угловые скобки тегов заменены на html-спецсимволы < и >
Если вы вводите текст, разницы между использованием методов jQuery text()
и html()
вы не увидите.
Статья super! Столько способов, оказывается, есть для добавления строк и контента с помощью JS!