В этой статье мы продолжаем разработку виджета для работы с короткими заметками. Если вы не читали предыдущую часть, то очень советую бегло её просмотреть. В ней мы подробно описаны постановка задачи и реализована серверная часть виджета, т.е. весь PHP код.
Для того, чтобы виджет заработал нам осталось написать клиентскую часть.
Думаю, очевидно, что для виджета отправка и получение данных должна выполняться с помощью AJAX запросов. Ведь вряд ли кому-то понравиться, если каждая операция с виджетом будет приводить к перезагрузке всей страницы.
Поэтому основную часть клиентской части у нас будет занимать JavaScript код. А чтобы его сократить мы используем библиотеку jQuery с несколькими плагинами.
Кстати, есть демонстрационная страничка с этим виджетом.
DemoИ, как и обещал, выкладываю архив с исходниками.
SourceПрежде всего, рассмотрим разметку страницы (index.html).
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <title>Notes Widget</title> <meta http-equiv="content-type" content="text/html;charset=utf-8" /> <meta http-equiv="Content-Style-Type" content="text/css" /> <link rel="stylesheet" type="text/css" href="pagestyles.css" /> <link rel="stylesheet" type="text/css" href="widgetstyles.css" /> </head> <body> <div id="content"> …. Содержимое страницы… </div> <div id="notesWidget"> <div id="notesHeader">Мои заметки</div> <div id="notes"> </div> <form id="fAddNote" action="savenote.php" method="post"> <input type="text" id="addNote" name="addNote" value="" /> <input type="submit" name="bAddNote" id="bAddNote" value="" /> </form> </div> <script type="text/javascript" src="js/jquery-1.3.2.min.js"></script> <script type="text/javascript" src="js/jquery-ui-1.7.1.custom.min.js"></script> <script type="text/javascript" src="js/jquery.jeditable.mini.js"></script> <script type="text/javascript" src="js/custom.js"></script> </body> </html>
В заголовке страницы мы подключаем файлы с CSS стилями (строки 13 и 14). Я вынес все стили, которые относятся к виджету в отдельный файл (widgetstyles.css), чтобы они не путались со стилями основной страницы.
Внутри страницы у нас находится 2 блока: основное содержимое (<div id="content">
) и виджет (<div id="notesWidget">
).
Первый блок нас не интересует, а вот на втором остановимся подробнее. Он состоит из трёх частей:
— заголовок (<div id="notesHeader">
);
— блок заметок (<div id="notes">
);
— блок с формой добавления заметки (<form id="fAddNote"
).
Обратите внимание, что блок заметок не заполнен. Внутрь него мы будем вставлять список заметок, полученный от сервера.
И в конце страницы мы подключаем jQuery, плагины и файл с нашими скриптами.
Сразу же рассмотрим используемые плагины.
1) jQuery UI. Это скорее не плагин, а целая библиотека. На её сайте вы можете выбрать необходимые компоненты и скачать архив с ними. Для нашего виджета нужны Core UI и Draggable. С их помощью мы сможем свободно перемещать виджет по странице.
2) Jeditable. С помощью этого плагина мы будем создавать in-line редакторы. Т.е. сделаем список с нашими заметками редактируемым. При клике по тексту заметки будет появляться поле ввода с помощью которого пользователь сможет изменить текст.
Теперь рассмотрим CSS стили минимально необходимые для работы плагина. Полный файл со стилями вы можете посмотреть в архиве с исходниками. К тому же при использовании виджета его оформление наверняка придется подстраивать под дизайн страницы.
#notesWidget { position: absolute; top: 200px; left: 0; width: 200px; height: 300px; …. } #notesHeader { cursor: move; …. } #notes { overflow: scroll; …. }
Для того, чтобы виджет можно было перемещать по странице, он должен иметь абсолютное позиционирование. При этом необходимо задать его размеры и положение.
Чтобы пользователь без наших подсказок мог догадаться, что это перемещаемый блок, мы изменим вид курсора для заголовка виджета.
И, т.к. заметок может быть много, добавим прокрутку в блок notes
.
Теперь переходим к самой интересной части – нашему JavaScript файлу (custom.js).
$(function() { //делаем виджет перемещаемым $('#notesWidget').draggable({ handle: '#notesHeader' , containment: 'parent' }); //обработчик нажатия на кнопку добавления новой записи $('#bAddNote').click(function() { if ($('#addNote').val() != '') { //сохраняем запись $.post('savenote.php', {value:$('#addNote').val(), bAddNote:true}, function(noteid) { //добавляем запись в список var curDate = new Date(); var noteData = {id:noteid, note_text:$('#addNote').val(), note_date:curDate.toString()}; var note = $(createListElement(noteData)); $('#notes ul').prepend(note); $('.edit').editable('savenote.php'); note.children('.remove').click(function() {addRemove(this);}); refreshClasses(); }); } else { alert('Вы ничего не написали'); } return false; }); //загружаем список записей $.getJSON('getnotes.php', {}, function(data, status) { if (data.status == 'OK') { //формируем список var notesList = '<ul>'; $.each(data.notes, function(i, note) { notesList += createListElement(note); }); notesList += '</ul>'; $('#notes').html(notesList); //делаем записи редактируемыми $('.edit').editable('savenote.php'); //добавляем обработчики нажатия на кнопку удаления записи $('.remove').click(function() {addRemove(this);}); refreshClasses(); } else { //вывод сообщения об ошибке $('#notes').html('<p>Не могу загрузить список записей</p>'); } }); }); function createListElement(note) { return '<li>' + '<img src="images/removenote.gif" alt="Удалить" class="remove" />' + '<div class="edit" id="note_' + note.id + '">' + note.note_text + '</div>' + '<div class="notedate">' + note.note_date + '</div>' + '</li>'; } function addRemove(element) { var noteid = $(element).next().attr('id'); //удаляем запись $.post('removenote.php', {id:noteid}, function() { //убираем данную запись из списка $(element).parent().slideUp("slow", function() { $(this).remove(); refreshClasses(); }); }); } function refreshClasses() { var odds = $('#notes ul li:odd'); odds.removeClass('even'); odds.addClass('odd'); var evens = $('#notes ul li:even'); evens.removeClass('odd'); evens.addClass('even'); }
Рассмотрим его подробнее.
Прежде всего, сделаем виджет перемещаемым (строки 3-6). Параметр handle
указывает, что блок можно будет перемещать только за заголовок, а containment
– запрещает выводить блок за пределы страницы.
Затем, мы создаем обработчик нажатия на кнопку «Добавить» (строки 8-30). В нём мы проверяем, ввел ли пользователь текст новой заметки и отправляем AJAX запрос.
После получения ответа будет вызвана анонимная функция (строки 12-23), которая:
1) создает элемент списка с новой записью (с помощью функции createListElement
, её мы рассмотрим чуть ниже);
2) вставляет его в начало общего списка;
3) делает редактируемым (с помощью метода editable
);
4) добавляет обработчик нажатия на кнопку «Удалить» (вызывает функцию addRemove
);
5) и обновляет цвет фона записей (с помощью функции refreshClasses
).
Теперь рассмотрим функцию createListElement (строки 59-66). Её основная задача – создать разметку новой записи.
Запись состоит из текста, кнопки «Удалить» (точнее это обычный рисунок, которому назначается обработчик события click
), и даты. Оформление записи выполняется с помощью CSS стилей, но на них я останавливаться не буду, в них ничего примечательного нет, к тому же они в любом случае должны сочетаться с конкретной страницей (если интересно, качайте архив с виджетом).
В разметке записи стоит обратить внимание на два момента.
1) Тексту записи присваивается класс edit
(<div class="edit"…
). С его помощью мы выбираем элементы для которых создаются in-line редакторы.
2) Этому же элементу мы присваиваем атрибут id
в формате (note_№
), его значение используется при изменении и удалении заметок.
Следующая функция addRemove (строки 68-79).
Здесь выполняется AJAX запрос на удаление заметки (строка 72) и после этого заметка удаляется из списка. При этом используется эффект slideUp
.
Теперь рассмотрим функцию refreshClasses
(строки 81-88).
Она работает следующим образом.
1) Находим все нечетные элементы в списке заметок.
2) Устанавливаем для них класс odd
и убираем even
(если он был установлен).
3) Находим все четные элементы списка и устанавливаем для них класс even.
Стили для классов odd
и even
указаны в CSS файле (widgetstyles.css). Т.е. с помощью этой функции мы всегда можем обновить расцветку списка после добавления или удаления элементов.
Теперь рассмотрим загрузку полного списка записей (строки 32-56). Она выполняется сразу после загрузки страницы.
Мы отправляем AJAX запрос (с помощью метода getJSON
) и после получения ответа формируем HTML список с заметками. Точно также как и при добавлении заметки устанавливаем обработчики нажатия на кнопку «Удалить», делаем записи редактируемыми и обновляем стили.
На этом можно остановиться. Общий принцип работы виджета мы рассмотрели, а если есть вопросы или замечания, пишите в комментариях, постараюсь ответить.
P.S. В архиве с исходниками есть файл notes.sql с помощью которого можно создать таблицу в базе данных.
Интересно почитать: