| « Поставить закладку » « Сделать стартовой » | |||
|
|||
|
Скрипт управления деревом
В предыдущих статьях, мы рассмотрели теорию хранения и управления древовидных структур данных, а так же реализовали Perl модуль для облегчения управления ими. Теперь напишем небольшой скрипт упраления (администрирования). Идея скрипта проста - требуется легко и непринужденно, с помощью скрипта, управлять деревом каталогов. Возьмем стандартную таблицу в которой будет хранится наше дерево каталогов, в ней мы будем хранить только одно дерево, реализацию принципа работы, при котором количество деревьев неограничено, я рассмотрю в следующих статьях. Итак, наша таблица: CREATE TABLE my_tree ( id INT(11) NOT NULL AUTO_INCREMENT, left_key INT(11) NOT NULL DEFAULT 0, right_key INT(11) NOT NULL DEFAULT 0, level INT(11) NOT NULL DEFAULT 1, name VARCHAR(150) NOT NULL, PRIMARY KEY id (id), INDEX left_key (left_key, right_key, level) ); Конечно, количество дополнительных полей (одно из них - name) может быть неограничено. КонцепцияДля начала определим, какие функции должен выполнять наш скрипт:
Ограничение доступа - вообще не учитывал, то есть авторизация скрипта, проверка доступа - просто отсутсвуют. Оставлю это на Вашей совести. А вообще, проще всего, просто запаролировать директирию скрипта .htaccess и все... HTML шаблон*, я все-таки вынес из скрипта - терпеть не могу править HTML в скрипте, и Вам того не советую. Шаблон состоит из трех частей:
* Эта структура шаблонов была придумана "на ходу", поэтому не будем заострять внимание на её правильности, не это важно. HTML-код шаблонов:header.html <html><head>
<title>Скрипт управления деревом каталогов</title>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<script language="javascript">
function EditCat (IdCat, NameCat, ParentCat) {
document.getElementById('TitleForm').innerHTML = 'ИЗМЕНИТЬ КАТЕГОРИЮ';
document.getElementById('buttonForm').value = 'Изменить';
document.FormCategory.id.value = IdCat;
document.FormCategory.name.value = NameCat;
document.FormCategory.parent.options[ParentCat].selected = true;
document.FormCategory.doing.value = 'edit';
}
function ClearFormEdit () {
document.getElementById('TitleForm').innerHTML = 'ДОБАВИТЬ КАТЕГОРИЮ';
document.getElementById('buttonForm').value = 'Добавить';
document.FormCategory.id.value = 'xx';
document.FormCategory.name.value = 'Новая категория';
document.FormCategory.doing.value = 'new';
}
</script>
</head>
<body>
<h1>Скрипт управления деревом каталогов</h1>
<h2>Список категорий фирм</h2>
<table width="100%" border="0" cellpadding="0" cellspacing="0">
row.html <tr>
<td>[$prefix$] [$name$]</td>
<td width="80">
<a href="#form" onClick="javascript: EditCat ('[$id$]','[$name$]','[$par$]');">
изменить
</a>
</td>
<td width="80"><a href="?ac=[$ac$]&doing=delete&id=[$id$]">удалить</a></td>
<td width="80"><a href="?ac=[$ac$]&doing=level_up&id=[$id$]">влево</a></td>
<td width="80"><a href="?ac=[$ac$]&doing=level_down&id=[$id$]">вправо</a></td>
<td width="80"><a href="?ac=[$ac$]&doing=order_up&id=[$id$]">вверх</a></td>
<td width="80"><a href="?ac=[$ac$]&doing=order_down&id=[$id$]">вниз</a></td>
</tr>
footer.html </table> <a name="form"></a> <table align="center" width="95%" border="0" cellpadding="0" cellspacing="0"> <form action="?" method="post" name="FormCategory"> <tr><td colspan="2"><h1 id="TitleForm">ДОБАВИТЬ КАТЕГОРИЮ</h1></td></tr> <tr> <td>Название категории</td> <td><input type="text" value="Новая категория" name="name" size="60"></td> </tr> <tr> <td>Подчинение категории</td> <td><select name="parent"> <option value="root">-- Без подчинения --</option> [$list_select$] </select></td> </tr> <tr> <td colspan="2"> <input type="hidden" name="id" value="xx"> <input type="hidden" name="doing" value="new"> <input type="hidden" name="ac" value="[$ac$]"> </td> </tr> <tr> <td colspan="2" align="center"> <input type="submit" name="buttonForm" id="buttonForm" value="Добавить"> <input type="reset" value="Вернуть" onClick="javascript: ClearFormEdit ();"> </td> </tr> </form> </table> </body></html> Вот так, если эти три файла сложить в один, как есть, то получится одна страница с таблицей в центре состоящей из одной строки. ![]() Теперь поясню отдельные моменты:
Код скриптаДля начала определим где какие файлы у нас будут лежать:
Что за файл NestedSets.pm, я думаю, объяснять не нужно (это модуль описанный в предыдущих статьях), с .html файлами - тоже понятно, остался только один файл - admin.pl, его мы как раз и опишем. Итак, код скрипта: #!/usr/bin/perl
# Подключение основных модулей
use strict;
use CGI;
use DBI;
use vars '$query',
'$dbh', # объект подключения в базе данных
'$nested', # объект работы с деревои NestedSets
'%user_vars'; # Глобальные пользовательские переменные
# Подключаем модуль для работы с деревои NestedSets
use lib 'lib/';
use Global::NestedSets;
# Указываем переменные пользовательские переменные
$user_vars{'table'} = 'my_tree'; # Имя таблицы БД
# Коннект к базе
$dbh = 'DBI'->connect('DBI:mysql:database=mybase:host=localhost:port=3306',
'user', 'password') || die $DBI::errstr;
# Выбираем переданные данные
$query = new CGI;
$user_vars{'id'} = $query->param('id') || undef; # Идентификатор узла
$user_vars{'doing'} = $query->param('doing') || undef; # Производимое действие
# Определяем объект Global::NestedSets
$nested = new Global::NestedSets {DBI=>$dbh, table=>$user_vars{'table'}};
# Если производится какое-либо действие
if ($user_vars{'doing'}) {
# Действие - поднять узел на уровень вверх
if ($user_vars{'doing'} eq 'level_up') {
$nested->set_unit_level(unit=>$user_vars{'id'}, move=>'up');
# Действие - опустить узел на уровень вниз
} elsif ($user_vars{'doing'} eq 'level_down') {
$nested->set_unit_level(unit=>$user_vars{'id'}, move=>'down');
# Действие - поднять узел на порядок вверх
} elsif ($user_vars{'doing'} eq 'order_up') {
$nested->set_unit_order(unit=>$user_vars{'id'}, move=>'up');
# Действие - опустить узел на порядок вниз
} elsif ($user_vars{'doing'} eq 'order_down') {
$nested->set_unit_order(unit=>$user_vars{'id'}, move=>'down');
# Действие - удалить узел
} elsif ($user_vars{'doing'} eq 'delete') {
$nested->delete_unit(unit=>$user_vars{'id'});
# Действие - создать узел
} elsif ($user_vars{'doing'} eq 'new') {
# Выбираем данные формы
$user_vars{'name'} = $query->param('name') || 'Новая';
$user_vars{'parent'} = $query->param('parent') || 'root';
# Создаем узел в дереве и получаем его ID
$user_vars{'id'} = $nested->insert_unit(under=>$user_vars{'parent'});
# Обновляем дополнительные поля узла
$dbh->do('UPDATE '.$user_vars{'table'}.
' SET name = ''.$user_vars{'name'}.''
WHERE id = '.$user_vars{'id'}) || die $DBI::errstr;
# Действие - отредактировать
} elsif ($user_vars{'doing'} eq 'edit') {
# Выбираем данные формы
$user_vars{'name'} = $query->param('name') || 'Новая';
$user_vars{'parent'} = $query->param('parent') || 'root';
# Выбираем ID родителя редактируемого узла
my $check = ($nested->get_parent_id(unit=>$user_vars{'id'}))->[0];
# Если меняется родительский узел, то производим перемещение
if ($check ne $user_vars{'parent'}) {
$nested->set_unit_under(unit => $user_vars{'id'},
under => $user_vars{'parent'})
}
# Обновляем дополнительные поля узла
$dbh->do('UPDATE '.$user_vars{'table'}.
' SET name = ''.$user_vars{'name'}.''
WHERE id = '.$user_vars{'id'}) || die $DBI::errstr;
}
}
# Выдаем заголовок браузеру
print "Content-type: text/html; charset=windows-1251nn";
# Открываем шаблон верхней части страницы и выводим его на экран
open (HTML, './template/header.html') || die 'Can not open file header.html!';
print <HTML>;
close HTML;
# Открываем шаблон строки списка и заносим его в переменную
open (HTML, './template/row.html') || die 'Can not open file row.html!';
my $line = join('', <HTML>);
close HTML;
# Выбираем полностью все дерево и сортируем по левому ключу
my $sql = 'SELECT id, name, level
FROM '.$user_vars{'table'}.'
ORDER BY left_key';
my $sth = $dbh->prepare($sql); $sth->execute() || die $DBI::errstr;
# Объявляем хеш и переменную (счетчик) с помощью которого будем определять
# порядок родительского узла в списке select формы
my %par = (0 => '0', root => '0'); my $i = 1;
# Объявляем переменную для формирования списка select формы
my $list_select;
while (my $row = $sth->fetchrow_hashref()) {
# Копируем шаблон строки во временную переменную
my $temp_line = $line;
# Формируем переменную для "антикеша"
$$row{'ac'} = time;
# Формируем отступ перед названием узла
$$row{'prefix'} = ' ' x ($$row{'level'} - 1);
# Определяем порядок родительского узла в списке select формы
$$row{'par'} = $par{($nested->get_parent_id(unit=>$$row{'id'}))->[0]};
$par{$$row{'id'}} = $i; $i++;
# Обрабатываем строку заменяя соотвествующие
$temp_line =~s /[$(w+)$]/$$row{$1}/g;
print $temp_line;
$list_select .= '<option value="'.$$row{'id'}.'">'.
$$row{'prefix'}.$$row{'name'}.'</option>';
}
$sth->finish();
# Открываем шаблон нижней части страницы и записываем его в переменную
open (HTML, './template/footer.html') || die 'Can not open file footer.html!';
my $footer = join('', <HTML>);
close HTML;
# Вносиим в шаблон список select формы
$footer =~s /[$list_select$]/$list_select/g;
# ... и выводим на экран
print $footer;
# Все...
exit;
1;
Вот собственно и все. Как видно, никаких сложностей нет, сам скрипт размером менее чем сто строк благодаря использованию модуля. Конечно, нужно еще проверить данные формы, может быть, некоторые операции... Автор: Сергей Томулевич (aka Phoinix) Источник: http://phoinix.ucoz.ru/ Рубрика: Perl
Подгрузка через AJAX HTML-кода, содержащег....
При разработке CMS S.Builder наша команда активно использовала AJAX. Теперь вот решили поделиться накопленным опытом. Начнем с этого хабратопика. Не буду здесь затрагивать различные фреймворки и библиотеки. Свой код всегда роднее. Для работы с AJAX-ом в S.Builder написана библиотека sbAJAX. Можете качать и пользоваться :). В этом файле есть функция sbEvalJS. Для тех, кто не знает, объясню. При подгрузке через AJAX и вставке на страницу HTML-кода, содержащего JavaScript, JavaScript выполняться не будет или полезут баги. Эта функция как раз решает поставленную задачу.
Подробнее... |
Рубрика: AJAX
| Добавлено: 19.11.2008
Обзор нового релиза самой мощной Ajax библ....
Хотя наш обзор немного запоздал, оригинальный Dojo 1.2 вышел в релизной версии ещё 6-го октября, но сейчас мы наверстаем упущенное. И так, Dojo Toolkit — это самая мощная и гибкая ajax-библиотека из всех, что есть на рынке, она активно развивается и имеет большое комьюнити. Кстати, это самое комьюнити, совместно с компанией Sitepen, имеет ещё несколько проектов, среди которых и Cometd и некоторые другие, не менее интересные, о которых мы скоро вам расскажем. Сегодня же все внимание на флагманский продукт — Dojo 1.2.
Подробнее... |
Рубрика: AJAX
| Добавлено: 19.11.2008
Firebug 1.3 и 1.4 alpha — что нового и инт....
Если вы профессиональный веб-разработчик и постоянно имеете дело с разработкой и отладкой сложных AJAX приложений, то наверняка знаете и используете Firebug — плагин для браузера Firefox, предназначенный для отладки и исследования веб-приложений. Текущая его версия, 1.2х достаточно стабильная и функциональна, чтобы помочь в 99% проблем, которые могут возникнуть при разработке. Но и этот инструмент не лишён если не недостатков, то некоторых фич, которые могли бы облегчить работу. И даже идеальный инструмент можно сделать ещё более идеальным, как бы это не звучало.
Подробнее... |
Рубрика: Вебмастеру
| Добавлено: 19.11.2008
Остальные статьи: |
Цитата дня (все,добавить):
|
Realcoding.NET
© 2003-2008 |
Контакты |
Реклама на сайте
|