Атрибут contenteditable

Джек Осборн 9 марта 2012

Мы уже давно используем различные технологии для редактирования и хранения текста в браузере. С атрибутом contenteditable это становится намного проще. В этой статье я расскажу для чего этот атрибут, как он работает и куда нам двигаться дальше.

Основы

Давайте обратимся к спецификации:

Атрибут contenteditable обладает фиксированным набором значений, он может быть пустой строкой, true или false. Пустая строка или true обозначают, что элемент доступен для редактирования. false обозначает, что элемент недоступен для редактирования. Есть еще третье состояние — inherit, это значение атрибута по умолчанию и оно означает, что значение наследуется от родительского элемента.

— WHATWG

В основном, атрибут contenteditable должен был обеспечивать работу WYSIWYG-редакторов. Скорее всего, вы встречали его в инструментах подобных Symphony или на cайтах вроде Flickr, где вы начинаете редактировать материалы, просто кликнув в определенную область.

Как упоминалось выше, contenteditable может быть в трёх возможных состояниях:

  1. contenteditable="" или contenteditable="true" означает, что элемент доступен для редактирования
  2. contenteditable="false" означает, что элемент недоступен для редактирования
  3. contenteditable="inherit" означает, что элемент доступен для редактирования в случае, если его непосредственный родитель доступен для редактирования. Это значение атрибута по умолчанию.

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

Пример кода

<div id="example-one" contenteditable="true">
    <style scoped>
        #example-one {
            margin:12px 0;
            }
        #example-one[contenteditable="true"] {
            padding:10px;
            outline:3px dashed #CCC;
            }
        #example-one[contenteditable="true"]:hover {
            outline:3px dashed #2B8BAD;
            }
    </style>
    <p>Всё что находится в этом блоке, доступно для редактирования в браузерах, поддерживающих <code>HTML5</code>. Давайте, попробуйте: кликните для начала редактирования.</p>
</div>

Демонстрация

Вот два простых примера, показывающие работу contenteditable:

Пример №1

Всё, что находится в этом блоке, доступно для редактирования в браузерах, поддерживающих HTML5. Давайте, попробуйте: кликните для начала редактирования.

Редактирование текста

Я использовал CSS для создания оформления, показывающего, что текст доступен для редактирования. Обратите внимание на ориентированное на будущее использование <style scoped>, которое описано в моей предыдущей статье.

Пример №2

Крис Койер рассказывал на CSS-Tricks, что вы можете позволить вашим пользователям редактировать CSS в реальном времени, так как <style> элемент имеет display:none по умолчанию, но ведь значение можно изменить на block.

Попробуйте отредактировать CSS, приведенный ниже:

Редактирование таблицы стилей

Поддержка браузерами

Поддержка атрибута contenteditable браузерами на удивление хороша:

Браузер Версия
Chrome 4.0+
Safari 3.1+
Mobile Safari 5.0+
Firefox 3.5+
Opera 9.0+
Opera Mini/Mobile Нет
Internet Explorer 5.5+
Android 3.0+

Поддержка браузерами свойства contenteditable

Должен отметить, что появлением и отличной поддержкой атрибута мы обязаны IE 5.5, хотя на самом деле ранний вариант contenteditable был разработан и внедрен Microsoft в июле 2000 года.

Более подробную таблицу совместимости можно увидеть тут: When Can I Use.

Сохранение изменений

Для написания этого раздела я обратился за помощью к доктору Реми, так как он гораздо более сведущ во всём, что касается хранения данных всего на свете.

В зависимости от сложности блока ваш код может отлавливать нажатие Enter (код 13) для сохранения изменения и Esc (код 27) для их отмены.

Когда пользователь нажимает Enter (предполагаем, что редактируем однострочные данные), получаем innerHTML редактируемого блока и посылаем AJAX-запрос с изменениями на сервер.

Простой пример можно увидеть тут: Сохранение данных из элемента с сontenteditable при помощи AJAX.

— Реми Шарп

Заключение

В своих статьях я неоднократно упоминал этот подход: спецификация наконец-то сделала официальным то, что внедрено в браузерах много лет назад.

Атрибут contenteditable — один из самых малоизвестных, но могу поспорить, что вы будете использовать его чаще, чем думаете.

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

Если у вас есть идеи, как использовать этот атрибут — расскажите нам об этом в комментариях.

Читать дальше

Перевод оригинальной статьи «The contenteditable attribute» Джека Осборна (Jack Osborne), опубликованной на сайте «HTML5 Doctor».

Перевод выполнил Антон Немцев (SilentImp).

Теги: , , ,

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

  1. Vasiliy Aksyonov 9 марта 2012 в 15:30

    У меня довольно большой опыт работы ContentEditable областями, поэтому хотелось бы поделиться своими мыслями на этот счёт.

    На самом деле не всё так просто, как кажется — реализация редактирования во всех браузерах своя (т.к. никакого стандарта по сути нет) и чтобы добиться одинакового поведения (одинакового ux, одинакового генерируемого кода) придётся очень постараться (особенно если мы говорим о ситуации, когда внутри редактируемого содержимого появляется нередактируемое — тут браузерам сносит башню совсем). Как раз такой унификацией пытаются заниматься всякие WYSIWYG-редакторы типа TinyMCE или CKEditor, но делают они это очень неприглядным способом (в большинстве случаев они работают с DOM API лишь на уровне innerHTML, т.е. процессят текст, а не DOM), что затрудняет создание с их помощью чего-либо более сложного, чем редактор текста. Чтобы добиться качественного результата (создать качественный редактор) с помощью ContentEditable придётся потратить куда больше усилий и нервов, чем при создании такого редактора с нуля, как это сделал Google в своём Kix (который используется в Google Docs). К сожалению, Kix — единственная реализация редактора, не использующего ContentEditable и использующая в качестве движка отображения HTML (хотя есть редакторы, использующие Canvas и само собой Flash) и лицензия этого редактора не позволяет его использовать вне Google Docs (хотя это и так очевидно, т.к. они до сих пор не заопенсорсили его).

  2. SilentImp 9 марта 2012 в 16:43

    1. Стандарт есть. Наконец то :)
    Собственно свойство: http://dev.w3.org/html5/spec/Overview.html#editing-0
    То как браузеры должны с ним работать: http://dvcs.w3.org/hg/editing/raw-file/tip/editing.html
    Осталось дождаться имплементации в браузерах второго, самого важного из стандартов. Начата работа над ним в феврале 2011. В июне представлен на всеобщее обозрение

  3. SilentImp 9 марта 2012 в 16:49

    2. Я думаю что тривиальные редакторы (а большего как правило и не надо) можно пробовать реализовывать. Но да, помучаться придеться.
    3. Кроме того есть тесты, созданные для проверки соответствия поведения браузеров стандарту. http://dvcs.w3.org/hg/editing/raw-file/tip/implementation.js Их можно использовать для написания полифила. Мое восхижение и уважение тому герою, который бы попробовал это сделать.
    4. Я как то докладывался на эту тему. Слайды доклада: http://wsd.websaints.net/2011/ И видеозапись доклада: https://vimeo.com/channels/wstdays/33214437
    Может быть кому то будут полезны :)

  4. Vasiliy Aksyonov 9 марта 2012 в 20:56

    1. О, это замечательно! Но к сожалению придётся подождать от трёх до пяти лет, пока всё заработает по стандарту.
    2. Тривиальных редакторов уже много есть. Пару я перечислил, но они, правда, создают iframe-песочницу для своего контента. Хотя я видел и те, которые так не делеют.

    А пока я мечтаю написать свой редактор с блекджеком ;)

  5. SilentImp 9 марта 2012 в 21:03

    Если надумаете — поставьте меня в известность. Очень хочется редактор с блекджеком.
    Кроме того я бы рекомендовал подумать о работе на основе полифилов … в результате через 3-5 лет ваш редактор не станет обросшим костылями монстром, а наоборот — сможет эти костыли отбросить.
    Беда существующих редакторов:
    1. они тащат груз прошлых лет. страшный. ужасающий. например iframe был нужен так как FF не умел contenteditable. только designmode. уже умеет. но мы до сих пор видем и будем видеть его в том же tiny(фига-себе тини…)MCE. Там вообще ктати execCommand отсутствует как класс, если что.
    2. если они сделаны без соответствия стандарту, то это синоним того что они сделаны через, простите, жопу. Пока стандарта не было, это был единственный путь. Но сейчас у нас появляется альтернатива. Ею стоит воспрользоваться.

    А можно ваш твиттер или еще чего то хорошего, что бы я мог пристально следить за вами в смутной надежде на блек-джек?

  6. mihdan 11 марта 2012 в 11:59

    SilentImp, смотрите левый сайдбар (блок "Ссылки") - там все контакты.

  7. SilentImp 11 марта 2012 в 14:32

    mihdan, ссылки на контактную информацию Василия Аксенова? Я был бы несколько удивлен…

  8. inmuch 12 марта 2012 в 11:22

    Благодарю ! Статья интересная.

  9. SilentImp 12 марта 2012 в 19:03

    Рад быть полезным.

  10. Vasiliy Aksyonov 12 марта 2012 в 20:07

    1. execCommand в тини как раз таки есть, они его перекрывают и расширяют, позволяют вызывать ещё кучу команд и добавлять свои
    2. Если бы они были сделаны так как они сделаны и при этом соответствовали стандарту — они всё равно были бы адом :D

    Если вдруг что-то будет, то я обязательно об этом напишу, как минимум на хабре, так что пропустить будет наверное сложно. Но на всякий случай можно подписаться на RSS моих постов: http://habrahabr.ru/users/artyv/

    По поводу костылей — отказ от использования в основе редактора ContentEditable API в пользу старого-доброго стабильного DOM API позволит избежать костылей и всё реализовать достаточно прилично (т.е. вообще не включать ContentEditable как в Google Docs).

  11. SilentImp 12 марта 2012 в 20:16

    По поводу последнего — не уверен. Методы реализованные на уровне браузера скорее-всего будут выполняться значительно быстрее, чем те, которые будут реализованы на уровне скрипта. Или я ошибаюсь?

    Если работать через полифил, то в конечном итоге именно к ним все и сведется. То есть, со временем редактор будет работать лучше а не хуже и объем его кода уменьшится, а не увеличится. По крайней мере теоретически.

  12. DevBlog 19 сентября 2014 в 21:54

    Да, действительно полезный атрибут. К стати с помощью этого атрибута делают красивые редакторы текста)

Перейти к началу