От автора: в данном уроке мы рассмотрим создание динамического меню, с помощью технологии AJAX. Если Вы работали с CMS WordPress, то, наверное, знакомы с такой штукой, как виджеты WordPress. В данном случае виджеты — это блоки, которые можно перемещать в режиме Drag and Drop («тащи и бросай»). При этом, после перемещения блока, он сохраняет свою позицию, т.е., к примеру, в сайдбаре сайта у нас имеется блок поиска, под которым размещен блок с произвольным текстом… мы захотели поменять их позиции… нет ничего проще — перетащили блок с поиском под блок с текстом и… вуаля — на сайте эти изменения расположения блоков вступили в силу. Согласитесь, динамическое меню — это быстро, удобно и эффектно.
1. Постановка задач. Создание БД
Для начала сформулируем задачу. Вместо блоков у нас будет меню, пункты которого у нас и будут перетаскиваемыми блоками. Для чего вообще это нужно? Допустим, мы хотим изменить сортировку пунктов меню, т.е. сделать так, чтобы из БД пункты меню выводились не отсортированными по идентификатору пункта меню, а по, к примеру, полю position. Для этого, конечно же, можно написать несложный скрипт, который будет выводить текущую позицию каждого из пунктов меню в числовом виде (1, 2, 3 и т.д.). Далее мы сможем для конкретного пункта задать новую числовую позицию и сохранить изменения в БД. Но гораздо быстрее и красивее будет выглядеть реализация, когда мы просто возьмем пункт меню и перетащим его на новое место… все — он сохранит свою позицию.
Итак, мы создаем меню и через административную часть сайта сможем изменять позицию его пунктов. Давайте теперь определимся с тем, что нам понадобится. Прежде всего, нам понадобятся 2 библиотеки jQuery:
собственно сама библиотека jQuery;
библиотека jQuery User Inteface.
Взять их можно на офф сайте jQuery. Также Вы найдете эти скрипты в исходниках к уроку. Также нам понадобится файл стилей для оформления пунктов меню, который Вы можете сгенерировать на сайте jQuery в разделе jQueryUI или найти в исходниках к уроку (или написать стили для пунктов меню самостоятельно в зависимости от дизайна Вашего сайта).
У нас будет 2 файла. Первый файл (index.php) — это страница сайта для общего доступа. Второй файл (admin.php) — это страница админки, на которой мы сможем изменять позицию пунктов меню. Конечно же, доступ к админке должен быть ограничен (как это сделать Вы можете узнать из предыдущих уроков). Основное отличие файла admin.php состоит в том, что мы подключили в него 2 указанных скрипта:
1 2 |
<script src="scripts/jquery-1.6.2.min.js" type="text/javascript"></script> <script src="scripts/jquery-ui-1.8.14.custom.min.js" type="text/javascript"></script> |
В файл index.php эти библиотеки подключать не нужно.
Также в оба файла мы подключим файл стилей:
1 |
<link type="text/css" href="css/jquery-ui-1.8.14.custom.css" rel="stylesheet" /> |
И напишем несколько правил в стилях на странице index.php:
1 2 3 4 5 |
<style> #sortable { list-style-type: none; margin: 0; padding: 0; width: 200px; } #sortable li { margin: 0 3px 3px 3px; padding: 0.4em; padding-left: 1.5em; font-size: 1.4em; height: 15px; cursor: pointer;} #sortable li span { position: absolute; margin-left: -1.3em; } </style> |
И на странице admin.php:
1 2 3 4 5 6 |
<style> #sortable { list-style-type: none; margin: 0; padding: 15px 40px 15px 0; width: 200px; } #sortable li { margin: 0 3px 3px 3px; padding: 0.4em; padding-left: 1.5em; font-size: 1.4em; height: 15px; cursor:move} #sortable li span { position: absolute; margin-left: -1.3em; } .block{/*border:1px solid #ccc;*/ width:200px;} </style> |
Следующее, что нам понадобится — это БД, в которой будут храниться названия каждого из пунктов меню и их текущая позиция на сайте. Чтобы не создавать БД вручную, Вы можете импортировать дамп БД из исходников (файл test.sql).
БД я назову test и создам в ней таблицу sortable, для которой понадобится всего 3 поля:
id, тип INT, первичный ключ, автоинкремент;
name, тип VARCHAR, длина 255 символов;
position, тип INT.
Теперь занесем в созданную таблицу 3 тестовых пункта меню:
Пункт 1 с позицией 1;
Пункт 2 с позицией 2;
Пункт 3 с позицией 3;
Отлично! БД готова.
2. Выводим меню из БД
БД создана и теперь можно вывести меню на сайт. Прежде, чем сделать это создадим файл с подключением к БД. Этот файл мы будем включать на индексную и админскую страницы сайта. Я назову файл db.php. Как подключаться к серверу БД и выбирать необходимую для работы БД мы уже знаем, поскольку неоднократно это делали:
1 2 3 4 5 6 |
<?php mysql_connect("localhost", "root", "") or die("No connect to server"); mysql_select_db("test") or die("No select DB"); ?> |
Теперь подключим этот файл в самом верху индексной и админской страницы:
1 |
<?php require_once 'db.php'; ?> |
Отлично! Теперь выведем пункты меню на сайт. Для этого создадим заявку (запрос), которой выберем из таблицы sortable все, что там есть, и отсортируем выбранное по полю position в порядке возрастания (таким образом, пункты меню будут выведены традиционно — 1, 2, 3). С запросами мы уже также работали, поэтому ничего нового здесь быть для Вас не должно.
Открываем конструкцию PHP в том месте, где должно быть выведено меню и пишем код:
1 2 3 4 5 6 7 8 9 10 |
<?php $res = mysql_query("SELECT * FROM `sortable` ORDER BY `position`") or die(mysql_error()); echo "<ul id='sortable'>\r\n"; while($row = mysql_fetch_assoc($res)){ echo "<li id='{$row['id']}' class='ui-state-default'>{$row['name']}</li>\r\n"; } echo "</ul>"; ?> |
Здесь мы выводим пункты меню списком. При этом стоит обратить внимание на то, что каждый из пунктов имеет свой идентификатор, значением которого является идентификатор конкретного поля в БД. Этот идентификатор нам понадобится для того, чтобы уникализировать каждый из пунктов меню.
Отлично!
Пункты меню выбраны из БД и появились на сайте.
3. Реализуем сортировку без сохранения
С файло index.php мы закончили и теперь можно перейти к админке. Для начала просто скопируем код вывода меню из индексного файла. Теперь, если посмотреть в браузере страницу admin.php, то увидим аналогичное меню за одним исключением — при наведении на пункты меню курсор приобретает крестовидную форму, что говорит о том, что данные пункты можно перетаскивать. Реализуется такая форма курсора правилом в стилях:
1 |
cursor:move |
Это правило мы прописали ранее. Курсор изменяет свою форму, но пункты меню пока что невозможно перетаскивать. Для того, чтобы это было возможно сделать, пропишем простой скрипт в блоке head:
1 2 3 4 5 6 7 |
<script type="text/javascript"> $(document).ready(function(){ $('#sortable').sortable({ }); }); </script> |
Все…
Теперь мы уже можем перетаскивать пункты меню. Это реализовано благодаря работе тех двух библиотек, которые мы подключили ранее. Здесь же мы просто взяли в набор jQuery элемент с идентификатором sortable и вызвали для него метод sortable. Если Вы не знакомы с основами jQuery, то рекомендую Вам обратиться к предыдущим урокам на сайте, где мы знакомились с основами работы jQuery. Сам метод sortable, к которому мы обратились, описан в библиотеке jQuery UI. Он имеет множество параметров, событий и методов, некоторыми из которых мы сейчас и воспользуемся. Прежде всего, давайте ограничим перемещение блоков только осью Y (только по вертикали). Для этого обратимся к опции axis:
1 2 3 4 5 6 7 |
<script type="text/javascript"> $(document).ready(function(){ $('#sortable').sortable({ axis: 'y' }); }); </script> |
Теперь давайте уменьшим непрозрачность перетаскиваемого элемента до 50%:
1 2 3 4 5 6 7 8 |
<script type="text/javascript"> $(document).ready(function(){ $('#sortable').sortable({ axis: 'y', opacity: 0.5 }); }); </script> |
Отлично!
Теперь надо сделать так, чтобы мы могли получить текущую позицию каждого из элементов после того, как мы завершим перемещение. Для этого обратимся к событию stop и методу (функции) toArray:
1 2 3 4 5 6 7 8 9 10 11 12 |
<script type="text/javascript"> $(document).ready(function(){ $('#sortable').sortable({ axis: 'y', opacity: 0.5, stop: function(){ var arr = $('#sortable').sortable("toArray"); alert(arr); } }); }); </script> |
Итак, что мы здесь сделали? После наступления события stop (когда завершено перетаскивание элемента) мы обращаемся к элементу с id sortable (это наше меню) и вызываем функцию toArray. Данная функция получает id каждого из отсортированных элементов и помещает его в массив в виде строки, где значения разделены запятой. Результат помещаем в переменную arr. Таким образом, если мы изменим изначальную позицию пунктов 1 и 2, то в переменной arr будет содержаться вот такая строка — 2, 1, 3. Для наглядности можно вывести методом alert значение переменной arr после каждого из перетаскиваний.
4. Обращаемся к методу ajax
Мы выполнили часть задачи — пункты меню можно теперь перетаскивать. Но они не сохраняют своей позиции в БД и после обновления страницы, все встает на круги своя. Для того, чтобы обновления были внесены в БД, необходимо передать значение переменной arr в скрипт PHP, который бы занес обновленные данные в БД. Сделать это, обратившись к методу jQuery под названием ajax(). Итак, пропишем его со всеми необходимыми нам параметрами:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<script type="text/javascript"> $(document).ready(function(){ $('#sortable').sortable({ axis: 'y', opacity: 0.5, stop: function(){ var arr = $('#sortable').sortable("toArray"); //alert(arr); $.ajax({ url: 'save.php', type: 'POST', data: {masiv:arr}, error: function(){ $('#res').text("Ошибка!"); }, success: function(){ $('#res').text("Сохранено!"); } }); } }); }); </script> |
Пройдемся по параметрам:
url: указываем имя файла, который примет данные из скрипта (аналог атрибута action в форме);
type: тип передаваемых данных (аналог атрибута method в форме);
data: передаваемые данные в формате {переменная:значение};
error и success: события ошибки и успеха запроса соответственно.
Таким образом, мы передаем значение переменной masiv методом POST в файл save.php. В случае успеха в блок с идентификатором res будет добавлен текст "Сохранено!", в случае ошибки — «Ошибка!».
Все просто…
5. Реализуем сохранение сортировки
Осталось написать скрипт для файла save.php, который бы принимал данные. Создадим файл save.php и запишем в него следующий код:
1 2 3 4 5 6 7 8 9 10 11 |
<?php require_once 'db.php'; $pos_new = 1; foreach($_POST['masiv'] as $item){ $res = mysql_query("UPDATE `sortable` SET `position`='{$pos_new}' WHERE `id`='{$item}'"); $pos_new++; } ?> |
Теперь давайте попробуем разобраться в работе того, что мы написали только что.
6. Логика работы скрипта
Поскольку мы принимаем массив данных — используем цикл foreach для того, чтобы пройтись по каждому из элементов массива. До начала цикла создадим переменную $pos_new со значением 1, которая будет новым значением позиции для каждого из пунктов меню. В теле цикла мы будем с каждым шагом цикла увеличивать значение переменной на единицу. Таким образом, ее значение последовательно будет изменяться от 1 до 3. Также в теле цикла указываем запрос, которым устанавливаем текущее значение переменной $pos_new значением поля position. Но делаем мы это для того поля, в котором значение поля id будет равно текущему значению перебираемого элемента массива, который мы получили. Здесь важно понять саму логику работы запроса. Поскольку мы передаем в массиве идентификаторы каждого из пунктов меню, то логично, что они будут соответствовать идентификаторам пунктов меню в БД. Именно поэтому для полученного идентификатора мы установим текущее значение переменной $pos_new в БД.
Вам проще будет уяснить работу скрипта, если Вы при помощи метода alert будете видеть что отсылается и наблюдать изменения в БД.
7. Добавляем юзабельности
Осталось добавить некоторые улучшения, которые сделают более приятной работу со скриптом. Например, мы можем после каждого сохранения только на время показывать текст "Сохранено!", а затем сделать так, чтобы он исчезал. Также сделаем так, чтобы место блока, который мы захватили, подсвечивалось:
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 |
<script type="text/javascript"> $(document).ready(function(){ $('#sortable').sortable({ axis: 'y', opacity: 0.5, placeholder: 'ui-state-default', containment: '.block', stop: function(){ var arr = $('#sortable').sortable("toArray"); //alert(arr); $.ajax({ url: 'save.php', type: 'POST', data: {masiv:arr}, error: function(){ $('#res').text("Ошибка!"); }, success: function(){ $('#res').show().text("Сохранено!").fadeOut(1000); } }); } }); }); </script> |
Теперь гораздо лучше. Вот и все. Наша задача реализована.
Заключение урока по созданию динамического меню для сайта
Пункты динамического меню после перетаскивания сохраняют свою позицию в БД. Стоит только напомнить о безопасности. В принципе, об этом я уже неоднократно говорил в предыдущих уроках, но напомню основное правило безопасности: все данные, принимаемые от пользователя, должны соответствующим образом быть обработаны. Здесь, конечно, в этом особого смысла нет, поскольку работа с БД осуществляется на уровне админки, но если бы мы принимали данные из пользовательской части, то каждый из элементов массива необходимо было бы привести к явному целочисленному типу функцией (int) или intval(), чтобы в запрос гарантированно попадало число.
На этом наш урок по созданию динамического меню завершен. Ваши вопросы и отзывы всегда будем рады видеть в комментариях. Удачи в Ваших разработках и до новых встреч!
Автор: Кудлай Андрей. Команда webformyself.
Комментарии (36)