CodeIgniter и Ajax
Решил провести полный рефакторинг своей CMS (да-да, каждый вебразработчик просто обязан написать свою систему управления контентом), и заодно сделать панель управления удобнее.
Задача такая: есть дерево меню сайта в админке. Рядом с каждым пунктом меню – кнопка, нажав её, переходим на страницу редактирования свойств пункта меню: ссылки, активности, картинки. Задача следующая – не переходить на другую страницу, как в "суровые девяностые", а используя AJAX открыть тут же, в псевдо всплывающем окне, типа лайтбокса, который заполонил весь инет.
Начнём, как говорят "37 signals", с проектирования интерфейса. Использовать плагины и чужие скрипты не хочется, люблю, чтобы страницы загружались быстро. Поэтому обойдёмся без лайтбокса и jquery tools. Всплывающее окно будет у нас слоем с абсолютным позиционированием и следующими свойствами:
Copy Source | Copy HTML
- #divedit
- {
- position: absolute;
- z-index:0;
- background: silver;
- display: none;
- top:50%;
- left:50%;
- width: 400px;
- height: 274px;
- margin-left: -200px;
- margin-top: -137px;
- border: gray solid;
- }
Copy Source | Copy HTML
- <div id="divedit">
- <div class="box content">
- <form id="editform" name="editform" method="post" action="{base}cms/menu/edit">
- <input type="hidden" value="1" name="old_parent"/>
- <input type="hidden" value="2" name="lft"/>
- <label>Название: </label>
- <input type="text" style="width: 50%;" name="title" id="title"/>
- <br/>
- <br/>
- <label>Ссылка: </label>
- <input type="text" style="width: 50%;" value="" name="alias"/>
- <br/>
- <br/>
- <label>Родитель: </label>
- <div id="parent"></div>
- <br/>
- <br/>
- <label>Включён: </label>
- <div id="visible"></div>
- <br/>
- <br/>
- <label>Картинка: </label>
- <br/>
- <div id="picture" align="center"></div>
- <br/>
- <div align="center">
- <input class="subm i-accept" type="submit" value="Сохранить" name="submit_edit"/>
- <input class="subm i-cancel" type="button" value="Отмена" id="cancel_ed" name="cancel_ed"/>
- </div>
- </form>
- </div>
- </div>
Напишем функцию контроллера, которая должна будет передавать данные о пункте меню:
Copy Source | Copy HTML
- function ajaxitemdata()
- {
- if ($this->input->post('id'))
- {
- $id = $this->input->post('id');
- $this->MPTtree->set_table('menu_tree');
- $node = $this->MPTtree->get_ORM($id);
- $parent = $node->parent();
- $arr = array(
- 'title' => $node->get('title'),
- 'alias' => $node->get('alias'),
- 'parent' => $this->MPTtree->display_as_select(1,$parent->get('lft'),'parent'),
- 'visible' => form_checkbox('visible', 'visible',$node->get('visible')),
- 'picture' => img($this->Menu_model->get_pic_by_id($node->get('id')))
- );
- echo json_encode($arr);
- }
- else
- {
- $arr = array('title' => 'Error');
- echo json_encode($arr);
- }
- }
В CodeIgniter для хранения деревьев я использую модель MPTtree, реализующую алгоритм Nested Sets. Надеюсь, вы в своих проектах не используете рекурсивное построение дерева сотней запросов в цикле? display_as_select – метод, выводящий сразу HTML код выпадающего списка со всеми пунктами меню, чтобы не парсить на стороне клиента каждую опцию. Результат выводится в формате JSON, легко читаемом и гораздо быстрее обрабатываемым, чем XML.
Следующий пример показывает JSON-представление объекта, описывающего человека. В объекте есть строковые поля имени и фамилии, объект, описывающий адрес, и массив, содержащий список телефонов.
{ "firstName": "Иван", "lastName": "Иванов", "address": { "streetAddress": "Московское ш., 101, кв.101", "city": "Ленинград", "postalCode": 101101 }, "phoneNumbers": [ "812 123-1234", "916 123-4567" ] }На языке XML подобная структура выглядела бы примерно так:
<person> <firstName>Иван</firstName> <lastName>Иванов</lastName> <address> <streetAddress>Московское ш., 101, кв.101</streetAddress> <city>Ленинград</city> <postalCode>101101</postalCode> </address> <phoneNumbers> <phoneNumber>812 123-1234</phoneNumber> <phoneNumber>916 123-4567</phoneNumber> </phoneNumbers> </person>
Теперь нужно вызвать эту функцию со стороны клиента:
- $("button[name*='edit']").click(function() {
- $.post("{base}cms/menu/ajaxitemdata/", {id: this.value}, getitem, "json");
- });
При нажатии на кнопку, имя которой начинается с ‘edit’, отправляем POST запрос к серверу со значением id, равному value кнопки. Так же передаём имя callback функции (она выполнится после запроса и будет обрабатывать ответ) и указываем формат ответа – json.
Код callback функции:
- function getitem(data)
- {
- document.editform.title.value = data.title;
- document.editform.alias.value = data.alias;
- $("#parent").html(data.parent);
- $("#visible").html(data.visible);
- $("#picture").html(data.picture);
- $("#divedit").show("slow");
- }
Значения полей ввода подставляем прямо в атрибут value элемента формы, для выпадающего списка, флажка и картинки – в пустые слои формы с соответствующими id подставляем html код. После этого открываем слой со спецэффектом.
Далее форма либо сабмитится, либо слой закрывается при нажатии на кнопку отмены. Для этого вешаем на неё обработчик:
- $("#cancel_ed").click(function() {
- $("#divedit").hide("slow");
- });
Всё просто.