В прошлой статье я начал рассказывать о создании редактируемого html списка с возможностью сортировки записей. Мы рассмотрели структуру БД, создали страницу со списком, подключили JS скрипты и разобрали добавление записей.
Осталось немного доделать 😉
Демо-версия находится здесь
DemoТакже вы можете скачать архив с этим примером
SourceУдаление существующих записей
Рассмотрим серверную часть removenote.php
.
try { if (!isset($_POST['id'])) { throw new Exception('Не указан id записи'); } //подключаемся к базе require_once('db.php'); //удаляем запись (id записи приходит в формате note_id, приставку note_ вырезаем) $dbh->exec('DELETE FROM notes WHERE id='.$dbh->quote(substr($_POST['id'], 5))); $result = array(); $result['id'] = $_POST['id']; //отправляет отчет браузеру echo json_encode($result); } catch(Exception $e) { echo json_encode(array('err'=>'Ошибка: '.$e->getMessage())); }
Для удаления записи нам нужно знать только её id
. После того, как он получен, выполняем запрос на удаление.
Клиентская часть немного сложнее.
Ссылкам «Удалить» назначается обработчик события click
.
.click(removeLi) function removeLi() { //определяем id текущей записи var noteId = $(this).parent().attr('id'); //запрашиваем подтверждение if (confirm('Точно удалить?')) { //отправляем запрос $.post('removenote.php', {'id':noteId}, function(data) { var response = eval('('+data+')'); if (response['err'] != null) { alert(response['err']); } else { $('#' + response['id']).detach(); //проверяем, остались ли записи в списке var notes = $('#sortable li'); if (notes.length == 0) { //удаляем сам список и форму сортировки записей $('#sortable').detach(); $('#changeOrder').detach(); //добавляем сообщение "Записи отсутствуют" $('<h2>Записи отстутствуют</h2>').insertAfter('#addNewNote'); } } }); } return false; }
Этот обработчик определяет id
тега li
, в котором расположена ссылка, запрашивает подтверждение удаления и отправляет ajax запрос серверу.
После получения ответа от сервера, он удаляет запись из списка с помощью метода .detach()
и проверяет, остались ли в списке другие записи. Если не осталось – список вместе с формой сортировки записей также удаляется.
Изменение текста записей
Как и раньше, начинаем с серверной части. Скрипт update.php.
try { //проверяем, пришли данные или нет if (!isset($_POST['value']) || '' == $_POST['value'] || !isset($_POST['id']) || '' == $_POST['id']) { throw new Exception('Не указаны данные записи'); } //подключаемся к базе require_once('db.php'); //защита от XSS $note = htmlspecialchars($_POST['value']); //формируем запрос на изменение записи... $stmt = $dbh->prepare('UPDATE notes SET note=:note WHERE id=:id'); //... и выполняем его $stmt->execute(array(':note'=>$note, ':id'=>substr($_POST['id'], 2))); $dbh = null; //тут мы не используем JSON формат, т.к. это требование плагина jeditable echo $note; } catch(Exception $e) { echo 'Ошибка: '.$e->getMessage(); }
От браузера скрипт получает id
записи и новый текст.
После выполнения обычных проверок, мы подключаемся к БД и отправляем запрос на изменение записи. При этом с помощью функции htmlspecialchars
мы заменяем теги на их эскейп последовательности (защита от XSS). Защита от SQL Injection выполняется с помощью стандартных средств PDO.
Обратите внимание, что в этом случае мы отправляем ответ браузеру в виде обычного текста. Это требование плагина jeditable.
Клиентская часть.
Чтобы сделать текст записей редактируемым, мы для каждого тега span (который находится внутри li) выполняем метод editable.
var editableOptions = { indicator : 'Сохраняю...', tooltip : 'Сделайте двойной клик, чтобы изменить текст', event : 'dblclick', cancel : 'Отмена', submit : 'Сохранить' }; $('span.note').editable('update.php', editableOptions);
В параметрах этого метода передаём адрес скрипта, который выполняет обновление записи на сервере, и объект editableOptions
, который содержит настройки плагина. В данном случае мы указываем (параметр event
), что плагин должен вставить форму редактирования при двойном клике по тексту. Одинарный клик, который используется по-умолчанию, нам не подходит, т.к. в этом случае форма будет появляться при каждой попытке перемещения записи.
Кроме события (dblclick
) которое открывает форму редактирования, указанного в параметре event, для настройки плагина мы указали только надписи на кнопках и текст подсказок.
Запрос серверу плагин отправляет сам, после клика по кнопке «Сохранить».
Изменение порядка записей
Самая интересная часть 🙂
Принцип довольно простой. После того, как пользователь рассортирует записи в нужном порядке, он нажимает кнопку «Сохранить сортировку». При этом запускается обработчик, который формирует массив с записями вида
{ 'id':'id записи', 'order': порядковый_номер_записи_в_отсортированном_списке }
Затем этот массив преобразовывается в форма JSON и отправляется серверу.
Примечание. Для преобразования в формат JSON используется плагин jquery-json.
Выглядит клиентская часть следующим образом.
function updateOrder() { var notes = $('ul#sortable li'); //проверяем количество записей в списке if (notes.length > 0) { var order = []; //формируем массив //просматриваем список в обратном порядке, т.к. записи выводятся в порядке //убывания значений в поле note_order (это позволяет при создании записи //присваивать ей максимальный порядковый номер и размещать в начале списка). $.each(notes.get().reverse(), function(index, value) { order.push({'id': $(value).attr('id'), 'order': index}); }); //отправка запроса (метод toJSON добавлен плагином json-2.2) $.post('changeorder.php', {'neworder':$.toJSON(order)}, function(data) { var response = eval('('+data+')'); if (response.status == 'OK') { $('ul#sortable').effect("highlight", {}, 3000); } else { alert(response.mes); } }); } return false; }
Обратите внимание, мы обрабатываем массив с элементами списка в обратном порядке (используется метод .reverse()
). Это сделано потому, что записи выводятся в порядке убывания значений в поле note_order
. Как я объяснял ранее, такой подход позволяет упростить определение номеров сортировки при создании новых записей.
Если данные успешно сохранены, подсвечиваем список, в противном случае – выводим сообщение об ошибке.
Серверный скрипт (changeorder.php).
try { //проверяем полученные данные if (!isset($_POST['neworder']) || count($_POST['neworder']) > 5000) { throw new Exception('Недопустимые данные'); } //подключаемся к БД require_once('db.php'); //создаём запрос на обновление $stmt = $dbh->prepare('UPDATE notes SET note_order=:note_order WHERE id=:id'); //преобразовываем строку в JSON формате в массив объектов $data = json_decode($_POST['neworder']); if (null == $data) { throw new Exception('Недопустимый формат'); } //обновляем записи foreach ($data as $note) { $stmt->execute(array(':note_order'=>$note->order, ':id'=>substr($note->id, 5))); } $dbh = null; //отправляем отчет браузеру echo json_encode(array('status'=>'OK')); } catch(Exception $e) { echo json_encode(array('status'=>'ERR', 'mes'=>'Ошибка: '.$e->getMessage())); }
Здесь мы проверяем полученные данные и в цикле обновляем все записи. Используется обычный UPDATE
запрос. Преобразование из JSON формата в PHP массив выполняется с помощью функции json_decode
.
Как видите, пример получился довольно объёмный, но большая часть кода относится к различным проверкам. Поэтому, надеюсь, общую идею вы поняли 😉
Если у вас будут вопросы или замечания, пишите, буду рад обсудить!