От автора: Создание встроенного текстового редактора требует определенных усилий. Начать можно с переключения элемента в режим редактирования с помощью полей input или textarea. Чтобы переключение было плавным вам придется придать элементам одинаковые стили. После того, как пользователь закончил редактирование, необходимо заменить весь текст и опять переключить элементы. Атрибут contentEditable сильно облегчает эту задачу.
Необходимо лишь задать этому атрибуту значение true, и HTML5 теги можно будет редактировать. В этом уроке с помощью данного атрибута мы создадим редактор форматированного текста.
Основы
Атрибут принимает три возможных значения: true, false и inherit. True означает, что элемент можно редактировать. Пустое значение также расценивается, как true. False говорит о том, что элемент нельзя редактировать. По умолчанию задано значение inherit, которое означает, что элемент можно отредактировать в том случае, если его ближайший родительский контейнер также можно отредактировать. Это означает, что если сделать элемент редактируемым, то и все его дочерние элементы, в том числе и не ближайшие, будут также редактируемыми. Исключение составляют дочерние элементы, у которых задано contentEditable = false.
Значения можно изменять динамически с помощью JavaScript. Если задать некорректное значение, выскочит исключение SyntaxError.
Создаем редактор
Чтобы создать встроенный редактор, нужно уметь изменять значение атрибута contentEditable в любое время.
Во время переключения атрибута contentEditable необходимо знать, какое значение он хранит на данный момент. Для этого можно воспользоваться свойством isContentEditable. Если isContentEditable возвращает true, элемент находится в режиме редактирования и наоборот. Чуть ниже мы будем с помощью этого свойства определять состояние нескольких элементов в документе.
Сначала необходимо создать кнопку переключения в режим редактирования и сам текст.
1 2 3 4 5 6 7 |
<button id="editBtn" type="button">Edit Document</button> <div id="editor"> <h1 id="title">A Nice Heading.</h1> <p>Last Edited By - <span id="author">Monty Shokeen</span></p> <p id="content">Some content that needs correction.</p> </div> |
Все элементы, которые будут редактироваться, должны иметь свой уникальный id. Идентификаторы помогут нам при сохранении изменений, или когда нам потребуется сохранить текст для дальнейшей его замены в каждом элементе. Код JS ниже редактирует и сохраняет изменения.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
var editBtn = document.getElementById('editBtn'); var editables = document.querySelectorAll('#title, #author, #content') editBtn.addEventListener('click', function(e) { if (!editables[0].isContentEditable) { editables[0].contentEditable = 'true'; editables[1].contentEditable = 'true'; editables[2].contentEditable = 'true'; editBtn.innerHTML = 'Save Changes'; editBtn.style.backgroundColor = '#6F9'; } else { // выключаем режим редактирования editables[0].contentEditable = 'false'; editables[1].contentEditable = 'false'; editables[2].contentEditable = 'false'; // изменяем текст и цвет кнопки editBtn.innerHTML = 'Enable Editing'; editBtn.style.backgroundColor = '#F96'; // сохраняем данные в localStorage for (var i = 0; i < editables.length; i++) { localStorage.setItem(editables[i].getAttribute('id'), editables[i].innerHTML); } } }); |
Для хранения отредактированного текста в переменной можно воспользоваться querySelectorAll(). Данный метод возвращает NodeList, в котором хранятся все элементы документа, заданные по определенному селектору. С помощью данного метода намного легче отслеживать редактируемые элементы в одной переменной. К примеру, получить доступ к заголовку документа можно с помощью editables[0], что мы сейчас и сделаем.
Теперь необходимо привязать к событию клика по кнопке обработчик. Во время каждого клика по кнопке пользователем мы проверяем заголовок на режим редактирования. Если заголовок нельзя редактировать, всем редактируемым элементам мы задаем свойство contentEditable в true. А текст кнопки ‘Edit Document’ меняем на ‘Save Changes’. После того, как пользователь внес необходимые изменения, он кликает на кнопку ‘Save Changes’, что приводит к моментальному сохранению изменений.
Если заголовок редактируется, всем элементам задается свойство contentEditable в false. На данном этапе мы может сохранять контент документа на сервере, чтобы воспользоваться им позже, а можем синхронизировать изменения с копией документа. В этом уроке я все буду сохранять в localStorage. Чтобы случайно не перезаписать данные при сохранении в localStorage, я использую id каждого элемента. CodePen демо
Получение сохраненного контента
Если вы в демо выше внесете какие-либо изменения и перезагрузите страницу, то все изменения пропадут. Это происходит потому, что не прописан код, который бы восстанавливал сохраненные данные. После сохранения данных в localStorage нам необходимо их восстановить, когда пользователь снова откроет страницу.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
if (typeof(Storage) !== "undefined") { if (localStorage.getItem('title') !== null) { editables[0].innerHTML = localStorage.getItem('title'); } if (localStorage.getItem('author') !== null) { editables[1].innerHTML = localStorage.getItem('author'); } if (localStorage.getItem('content') !== null) { editables[2].innerHTML = localStorage.getItem('content'); } } |
В коде выше проверяется, существуют ли в localStorage данные о заголовке, авторе и контенте. Если они там есть, в innerHTML соответствующих элементов заносятся эти данные. Еще одно CodePen демо
Делаем редактор более дружелюбным
Нам нужно внести два изменения в наш редактор. Необходимо сделать так, чтобы пользователь понимал, что можно редактировать, а что нельзя. Сделать это можно, изменив стили CSS конкретных элементов: это могут быть изменения шрифта или цвета. Отобрать элементы для добавления новых стилей можно с помощью селектора [contenteditable=»true»].
1 2 3 4 |
[contenteditable="true"] { font-family: "Rajdhani"; color: #C00; } |
Второе изменение – автосохранение данных. Сделать это можно по-разному. Можно сохранять данные каждые 5 секунд.
1 2 3 4 5 |
setInterval(function() { for (var i = 0; i < editables.length; i++) { localStorage.setItem(editables[i].getAttribute('id'), editables[i].innerHTML); } }, 5000); |
Можно сохранять данные по каждому событию keydown.
1 2 3 4 5 |
document.addEventListener('keydown', function(e) { for (var i = 0; i < editables.length; i++) { localStorage.setItem(editables[i].getAttribute('id'), editables[i].innerHTML); } }); |
В этой статье я использовал первый метод. Вы можете сохранять данные по любому событию, которое сочтете нужным. CodePen демо
Редактирование всей страницы с помощью свойства Design Mode
contentEditable полезен, когда нужно изменить несколько элементов на веб-странице. Если же вам нужно изменить все или почти все элементы на странице, то тут вам поможет свойство designMode. Данное свойство применяется ко всему документу. Для включения и отключения используются соответственно document.designMode = ‘on’; и document.designMode = ‘off’;.
Данное свойство доказало свою полезность в ситуациях, когда вы дизайнер и работаете с контент-менеджером. Вы создаете дизайн страницы и заполняете ее пробным текстом, а контент-менеджеры заменяют этот текст на нормальный. Чтобы посмотреть designMode в действии, откройте консоль в панели разработчика браузера, введите document.designMode = ‘on’; и нажмите Enter. Теперь все на странице можно редактировать.
Заключительные мысли
Атрибут contentEditable удобен в тех ситуациях, когда нужно быстро отредактировать статью или позволить пользователям быстро изменить их комментарий. Впервые данная функция была реализована в IE 5.5, позже она была стандартизирована в WHATWG. Поддержка в браузерах тоже довольно неплохая. Атрибут поддерживается во всех основных браузерах, за исключением Opera Mini.
JavaScript де-факто стал одним из языков работы в интернете. Данный язык требует тщательного изучения. Также вам могут пригодиться различные фреймворки и библиотеки. Если вы ищите дополнительные источники для изучения или хотите начать использовать данный язык в своих работах, загляните на Envato marketplace.
В данном уроке вы узнали об основах атрибута contentEditable и о том, как его использовать для создания простых встроенных редакторов текста. В следующем уроке вы научитесь создавать панель инструментов и добавлять различные функции в редактор текста.
Автор: Monty Shokeen
Источник: //code.tutsplus.com/
Редакция: Команда webformyself.
Комментарии (2)