От автора: в этом и следующем уроках мы познакомимся с одним из новых атрибутов в HTML5 под названием contenteditable. Из самого названия понятно, что данный атрибут как-то связан с редактированием контента. И действительно, он позволяет редактировать содержимое элементов прямо на странице.
Думаю, вы уже догадались, где это может пригодиться и строите планы на использование этого атрибута. Использование данного атрибута очень удобно, скажем, для некоторых разделов админки сайта, где необходимо производить быстрое редактирование заголовков, настроек и т.п.
В этих уроках мы рассмотрим практическое использование атрибута contenteditable и реализуем редактирование настроек сайта буквально «на лету». Для примера воспользуемся простой таблицей в БД с настройками какого-либо сайта (дамп таблицы вы найдете в исходниках к уроку).

JavaScript. Быстрый старт
Изучите основы JavaScript на практическом примере по созданию веб-приложения
Узнать подробнееСоздадим 3 файла: index.php, config.php и functions.php. В индексный файл будем выводить таблицу с настройками, в файле config.php будем хранить подключение к БД, а в файле functions.php опишем функции для работы с данными.
Подключимся к БД в файле config.php, используя необходимые настройки:
1 2 3 4 5 6 7 | define("DBHOST", 'localhost'); define("DBUSER", 'root'); define("DBPASS", ''); define("DBNAME", 'crafter'); $db = @mysqli_connect(DBHOST, DBUSER, DBPASS, DBNAME) or die("Нет соединения с БД"); mysqli_set_charset($db, "utf8") or die("Не установлена кодировка соединения"); |
Сам файл конфигурации, а заодно и файл функций, подключим вверху файла index.php:
1 2 3 4 | <?php require_once 'config.php'; require_once 'functions.php'; ?> |
Теперь в файле функций опишем несложную функцию, получающую данные из таблицы настроек:

JavaScript. Быстрый старт
Изучите основы JavaScript на практическом примере по созданию веб-приложения
Узнать подробнее 1 2 3 4 5 6 7 8 9 10 11 12 13 | /** * получение настроек **/ function get_options(){ global $db; $query = "SELECT * FROM options"; $res = mysqli_query($db, $query); $options = array(); while($row = mysqli_fetch_assoc($res)){ $options[$row['id']] = $row; } return $options; } |
Получим результат работы функции в индексном файле в массив $options:
1 2 3 4 5 6 7 | <?php require_once 'config.php'; require_once 'functions.php'; $options = get_options(); ?> |
Далее в индексном файле создадим простую разметку и выведем в цикле настройки в таблицу. Заодно подключим библиотеку jQuery и наш будущий файл скрипта script.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 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | <?php require_once 'config.php'; require_once 'functions.php'; $options = get_options(); ?> <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Редактируемый контент</title> <link rel="stylesheet" href="css/style.css"> </head> <body> <table class="zebra"> <thead> <tr> <th>ID</th> <th>Системное название</th> <th>Название опции</th> <th>Значение</th> </tr> </thead> <tbody> <?php foreach($options as $option): ?> <tr> <td><?=$option['id']?></td> <td><?=$option['title']?></td> <td><?=$option['name']?></td> <td><div class="edit" data-id="<?=$option['id']?>" contenteditable><?=$option['value']?></div></td> </tr> <?php endforeach; ?> </tbody> </table> <script src="//code.jquery.com/jquery-latest.js"></script> <script src="js/script.js"></script> </body> </html> |
Как видим, здесь мы в последнюю ячейку со значениями опций поместили элемент div с атрибутом contenteditable. Теперь содержимое данного элемента будет доступно для редактирования. Далее оформим таблицу с помощью стилей:
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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | .zebra{ width: 70%; margin: 20px auto; border-collapse: collapse; } .zebra th{ background: #555; color: #fff; text-align: left; } .zebra .foot{ background: #d5d5d5; color: #000; text-align: left; } .zebra input{ width: 100%; transition: all .5s; } .zebra input:focus{ box-shadow: 0 0 5px #000; } .zebra th, .zebra td{ border-bottom: 1px solid #ccc; padding: 5px; vertical-align: middle; padding: 12px 5px; } .zebra tr{ transition: all .5s; } .zebra tr:hover{ /*background: #f1f1f1;*/ } .edit{ padding: 3px; transition: all .5s; border: 1px solid rgba(82, 168, 236, .5); } .edit:focus{ border: 1px solid rgba(82, 168, 236, 1); box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset, 0 0 8px rgba(82, 168, 236, 0.9); outline: 0 none; } |
И, наконец, напишем несколько строк клиентского кода в файле script.js:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | $(function(){ var oldVal, newVal, id; $('.edit').keypress(function(e){ if(e.which == 13){ return false; } }); $('.edit').focus(function(){ oldVal = $(this).text(); id = $(this).data('id'); console.log(oldVal + '|' + id); }); }); |
Данными строками мы отслеживаем событие нажатия клавиш и при нажатии клавиши Enter мы запрещаем ее поведение по умолчанию, т.е. запрещаем перенос строк для редактируемого контента. Также при получении фокуса для того или иного элемента с настройкой, мы получаем текущее значение настройки и ID опции. ID нам понадобится в будущем для запроса к БД, а вот текущее значение настройки необходимо для того, чтобы сравнить его со значением после потери элементом фокуса. Если эти значения будут отличаться, значит, пользователь изменял настройку, и нам необходим запрос к БД для сохранения нового значения.
На этом мы завершим текущий урок. Удачи и до новых встреч!

JavaScript. Быстрый старт
Изучите основы JavaScript на практическом примере по созданию веб-приложения
Узнать подробнее
Разработка веб-приложения на PHP
Скачайте видеокурс и узнайте, как создать веб-приложение на PHP
Скачать
Благодарю Вас Андрей за ваши уроки, в этом году я посветил изучением ваших курсов…. хотел бы так же знать языки программирования как и вы )). Огромное Вам Спасибо!
Анатолий, Вам спасибо за теплые слова
Успехов в изучении!
Где у вас кнопка перехода к следующему уроку?
Такой кнопки нет и второй урок на сайте пока не публиковался, его можно найти пока только на нашем канале YouTube.
Доброго дня!
Андрей, пытаюсь найти, какой плагин вы поставили для программы sublime text 2 для быстрого подключения jquery
и какую комбинацию сделали ….
Спасибо за помощь!
Здравствуйте, Анатолий.
Это не плагин, это сниппет, т.е. сохраненный код, который вызывается горячей клавишей (Tab). Здесь, к примеру, можно прочесть, как создать сниппет.
Андрей, спасибо за прекрасные уроки.
Твой сайт у меня на первом месте.
И вдогонку вопрос:
Можно ли сделать все это, но только на текстовых файлах?
Пожалуйста)
Да, в качестве хранилища данных, конечно же, может выступать текстовый файл. Если интересует вопрос реализации, то в одном из следующих уроков можно показать принцип реализации.
Андрей Кудлай Если интересует вопрос реализации, то в одном из следующих уроков можно показать принцип реализации.
Да, очень интересует.
Недавно, при переезде на новый хостинг потерял половину базы данных.
Теперь решил освоить текстовые базы. С твоей помощью, конечно.
С уважением…
Хорошо, в одном из следующих уроков покажу работу с файлами.
Спасибо!
Жду с нетерпением
Андрей здравствуйте, очень вам благодарна, ваш урок — ценный вклад в мои знания по web-программированию, подскажите пожалуйста а как теперь эти изменения в таблице сохранить в БД?
Простите, нашла. Шикарные уроки!!!
Подскажите можно как то сделать что бы в contenteditable был хотя бы 1 символ, т.е можно удалять все кроме одного.
Можно. Как вариант, средствами JS считать количество символов в поле и, если значение станет равно единице, тогда с каждым нажатие кнопок, связанных с удалением (Backspace, Delete), сообщать пользователю о необходимости наличия хотя бы одного символа. Также можно и без JS просто на сервере проверять поле и, если оно окажется пустым — возвращать пользователю соответствующее сообщение. Есть и другие варианты решения.
Отличный урок! Спасибо огромное, многое узнал — и по самой теме, и заодно по css и js! Очень радует, что есть видеоурок и исходники. Прикрутил все к своему сайту, все работает! Радует также подробность рассказа, все доступно и просто. Автору респект, продолжай доброе дело!!!
К сожалению,не понял,как сделать,чтобы данные сохранялись в базе данных. Ввожу значения,но после обновления страницы они не сохраняются. Подскажите пожалуйста,что делать?
Сохранение значения показано во втором уроке.