Разработка web приложений. Как сделать редактор списка в стиле Web 2.0 (главная страница)

Владимир | | Ajax, JavaScript, PHP.

Скриншот WebListEditor
В прошлый раз мы начали создание web приложения, позволяющего редактировать простой список. На данный момент мы разобрали общую структуру приложения и функцию подключения к базе данных (БД).

Примечание. Вы можете посмотреть демонстрационную версию редактора или скачать архив с файлами проекта.

Теперь переходим к созданию главной страницы (index.php). Html разметку постараемся максимально упростить, т.к. нам придется изменять ее в процессе работы web приложения.
Заголовок страницы, в общем-то, обычный

<?php
require_once("scripts/dbdata.php");
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN">
<html xmlns="http://www.w3.org/1999/xhtml" lang="ru">
<head>
<title>WebListEditor</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" type="text/css" href="css/styles.css" />
<script type="text/javascript" src="scripts/libs/prototype.js"></script>
<script type="text/javascript" src="scripts/libs/scriptaculous.js?load=effects,controls"></script>
<script type="text/javascript" src="scripts/tasks.js"></script>
</head>

Прежде всего, мы подключаем файл dbdata.php с функцией подключения к БД, затем указываем тип страницы, кодировку, размещения файлов с таблицей стилей и JavaScript библиотеками.

Обратите внимание на то, как подключена библиотека Scriptaculous (строка 11). Эта библиотека состоит из семи файлов (версия 1.7.0), большинство из которых мы не используем. Поэтому с помощью параметра load указываем, какие файлы нужно загрузить. В данном случае нам нужна библиотека эффектов (effects) для подсветки вставленных элементов и библиотека элементов управления (controls) для создания встраиваемого редактора.

Теперь рассмотрим основную часть страницы.
Т.к. страница получилась довольно длинной, я разбил ее на три части.

Первая часть выполняет подключение к БД (с помощью функции connect() из файла dbdata.php) и отправляет запрос получения списка.

<?php $con = connect(); ?>
<div id="content">
<?php
$res = mysql_query("SELECT * FROM listitems");
if ($res === FALSE) {
	echo "Ошибка при отправке запроса к БД:".mysql_error();
}
elseif (mysql_num_rows($res) == 0) {
	echo "<div id=\"noItems\">Записей нет</div>";
}
else {
?>

Если ошибок не было, результаты выполнения запроса будут находиться в переменной $res.

Вторая часть самая интересная. Здесь мы формируем блок со списком.

<p>Список:</p>
<ul id="list">
<?php
	$i = 0;
	while ($item = mysql_fetch_array($res, MYSQL_ASSOC)) {
		$i++;
?>
<li id="listNum_<?php echo $i - 1; ?>">
<div class='itemNum'><?php echo $i; ?></div>
<div class='itemValue' onclick='closeOtherEditors(<?php echo $i - 1; ?>)'
id="itemId_<?php echo $item['id']; ?>"><?php echo $item['item']; ?></div>
<a href="#" class="deleteLink" onclick="deleteItem(<?php echo $item['id']; ?>)">
<img src="css/images/delete.gif" alt="Удалить" title="Удалить" />
</a>
<script type="text/javascript">
editors.push(addEditor("itemId_<?php echo $item['id'];?>",
	"<?php echo $item['id'];?>"));
</script>
</li>
<?php
	}
?>
</ul>
<?php
}
?>
</div>
<?php
mysql_free_result($res);
mysql_close($con);
?>

Основной цикл, который вставляет элементы списка, находится в строках с 5 по 21. Это обычный while цикл, в котором с помощью функции mysql_fetch_array мы получаем результаты запроса и формируем разметку списка.

Обратите внимание на имена атрибутов тегов списка. Для тега li установлен атрибут вида listNum_номер_записи (это порядковый номер записи в списке, а не id в БД).
Внутри тега li находятся три блока (теги div). В первом блоке находится номер элемента списка. Во втором – текст записи. Атрибут id этого элемента имеет вид itemId_номер_в_БД (здесь используется значение поля id из БД). В третьем блоке находится ссылка «Удалить» с картинкой.

В строках 15-18 мы вставили немного JavaScript кода. Он создает встраиваемый текстовый редактор для текущего элемента и добавляет его в массив (с помощью функции push).

Рассмотрим функцию addEditor подробнее (она находится в файле tasks.js).

var editors = [];

function addEditor(item, id) {
	return new Ajax.InPlaceEditor(item,
		"scripts/updateitem.php",
		{
			formId: "listForm",
			okText: "Обновить",
			cancelText: "Отмена",
			highlightcolor: "#ffffff",
			size: "30",
			savingText: "Сохраняю...",
			callback: function(form, value) {
				return "value=" + value + "&id=" + id;
			}
		});
}

В самом начале скрипта мы объявили глобальный массив (editors), в котором будем хранить встраиваемые редакторы (как вы, наверное, догадались, эти редакторы должны быть созданы отдельно для каждого элемента списка).
Функция addEditor выполняет только одну операцию: создает и настраивает встраиваемый редактор для заданного элемента списка. В первом параметре функции указываем id блока, к которому будет присоединен редактор, второй параметр – id записи в БД.

На скриншоте в начале статьи показан активированный встроенный редактор. Принцип его действия заключается в следующем. При щелчке по блоку, для которого установлен редактор, этот блок заменяется формой, содержащей текстовое поле, кнопку «Обновить» и ссылку «Отмена».

Редактор создается с помощью функции InPlaceEditor() объекта Ajax из библиотеки Scriptaculous. В первом параметре этой функции мы указываем имя php скрипта (updateitem.php), которому будут отправлены данные после нажатия на кнопку «Сохранить». Во втором параметре – массив с настройками редактора. Рассмотрим их по порядку:
formId – значение атрибута id формы редактора (используется для установки стилей);
okText – текст на кнопке;
cancelText – текст ссылки «Отмена»;
highlightcolor – цвет подсветки (при появлении формы к ней автоматически применяется эффект highlight, о котором я писал в статье «Подсветка элементов web страницы»);
size – размер текстового поля формы;
savingText – текст, который отображается пока идет обновление данных;
callback – функция, выполняющая отправку данных серверному скрипту.

На последнем параметре остановимся подробнее. Если его опустить, то при обновлении данных редактор отправит только значение, введенное в текстовое поле. Такое поведение нас не устраивает, т.к. нам нужно знать id записи, которую нужно обновить, а не только ее значение. Поэтому мы объявили свою собственную анонимную функцию, которая добавляет в запрос id выбранного элемента в БД.

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

Если вы внимательно читали разметку html страницы, то заметили, что при щелчке по тексту записи вызывается функция closeOtherEditors(). Этой функции передается номер выбранной записи.

Посмотрим на ее исходный код

function closeOtherEditors(curEditor) {
	editors.each(
		function(editor, index) {
			if (index != curEditor) {
				editor.leaveEditMode();
			}
		}
	);
}

Как видите, эта функция переводит все встроенные редакторы, кроме указанного, в неактивное состояние (с помощью leaveEditMode()). Дело в том, что созданные нами редакторы не зависят один от другого, и по-умолчанию они закрываются только при нажатии на ссылку «Отмена». Это не очень удобно, поэтому в этой функции мы закрываем все редакторы кроме выбранного.

Третья часть страницы содержит форму для добавления новой записи в список. При нажатии на кнопку «Добавить» будет вызвана функция addItem(), размещенная в файле tasks.js.

<form action="#" id="add_item_form">
<p>
<label for="item_value"></label>
<input type="text" id="item_value" size="30" />
<input type="button" value="Добавить" onclick="addItem()" />
</p>
</form>

Подведем небольшой итог. Формирование страницы включает следующие этапы:
1) создание html разметки;
2) получение данных из БД;
3) создание встроенных редакторов для всех записей списка.

В следующий раз мы рассмотрим добавление новых записей в список.