PHP + MySql + jQuery

Drag and Drop nestable меню на PHP и MySQL и jQuery

Занимаясь backend разработкой, каждый программист сталкивается с тем что любую древовидную структуру - будь то меню или список категорий нужно выводить на сайте не обычным выпадающим списком, а красиво оформленным, что бы пользователю было удобно пользоваться вашей CMS!

Можно красиво форматировать вывод блоков, делать отступы дочерних разделов, но упорядочить разделы будет все равно не удобно. В помощь приходит мощный jQuery плагин Nestable.

Скачать nestable его вы можете на сайте разработчика http://dbushell.github.io/Nestable/

Приступим к созданию древовидного меню сортируемого drag and drop: 

База данных будем иметь стандартную структуру. id, name, parent_id а также ячейку order для значений сортировки.

nestable jquery php mysql

 

 Итак сделаем выборку всех родительских категорий и поместим результат в массив:

$sql = "SELECT * FROM menu WHERE parent_id='0' ORDER BY order";
$result = mysql_query($sql, $connection);
$numRows = mysql_num_rows($result);

Теперь выведем на страницу блок с родительскими элементами

echo "
\n"; echo "
\n\n"; echo "
    \n"; while($row = mysql_fetch_array($result)) { echo "\n"; echo "
  1. "; echo "
    {$row['id']}: {$row['name']}
    "; menu_showNested($row['id']); echo "
  2. \n"; } echo "
\n\n"; echo "
\n"; echo "
\n\n"; // Блок должен быть здесь не перемещайте его echo "
\n";

Наверное вы заметили функцию menu_showNested ? Сейчас мы будем использовать рекурсивную функцию для вывода всех дочерних категорий.

function menu_showNested($parentID) {
	$sql = "SELECT * FROM menu WHERE parent_id='$parentID' ORDER BY order";
	$result = mysql_query($sql, $connection);
	$numRows = mysql_num_rows($result);
	
	if ($numRows > 0) {
		echo "\n";
		echo "
    \n"; while($row = mysql_fetch_array($result)) { echo "\n"; echo "
  1. \n"; echo "
    {$row['id']}: {$row['name']}
    \n"; menu_showNested($row['id']); echo "
  2. \n"; } echo "
\n"; } }

Все меню мы вывели.

Теперь самое сложное - создание и передача массива в формате json обработчику на сервере и сохранение данных в бд

//========================================== nestable script
function lagXHRobjekt() {
    var XHRobjekt = null;
    try {
        ajaxRequest = new XMLHttpRequest(); // Firefox, Opera, ...
    } catch(err1) {
        try {
            ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP"); // Noen IE v.
        } catch(err2) {
            try {
                ajaxRequest = new ActiveXObject("Msxml2.XMLHTTP"); // Noen IE v.
            } catch(err3) {
                ajaxRequest = false;
            }
        }
    }
    return ajaxRequest;
}

//функция отправки методом post массива с порядком в формате json
function menu_updatesort(jsonstring) {
    mittXHRobjekt = lagXHRobjekt();
    if (mittXHRobjekt) {
        mittXHRobjekt.onreadystatechange = function() {
            if(ajaxRequest.readyState == 4){
                var ajaxDisplay = document.getElementById('sortDBfeedback');
                ajaxDisplay.innerHTML = ajaxRequest.responseText;
            } else {
                // закомментируйте эту строку если не хотите выводить спинер загрузки
                document.getElementById('sortDBfeedback').innerHTML = "ajax-loader";
            }
        }
        var tosend = "jsonstring="+jsonstring;
        ajaxRequest.open("POST","/admin/menu/menu_sortable_save/",true);
        ajaxRequest.setRequestHeader("Content-type","application/x-www-form-urlencoded");
        ajaxRequest.send(tosend);
    }
}

$(document).ready(function()
{
    //функция обновления позиций меню
    var updateOutput = function(e)
    {
        var list   = e.length ? e : $(e.target),
            output = list.data('output');
        if (window.JSON) {
            output.val(window.JSON.stringify(list.nestable('serialize')));//, null, 2));
            menu_updatesort(window.JSON.stringify(list.nestable('serialize')));
        } else {
            output.val('JSON browser support required for this demo.');
        }
    };

    // вызываем функцию для записи изменения порядка меню в бд.
    $('#nestableMenu').nestable({group: 1}).on('change', updateOutput);

    // вывод начальной последовательности если элемент существует на странице
    var variable = $('#nestableMenu').data();
    if ( typeof variable !== "undefined" && variable) {
        updateOutput($('#nestableMenu').data('output', $('#nestableMenu-output')));
    }

    //кнопки развернуть светнуть меню
    $('#nestable-menu').on('click', function(e)
    {
        var target = $(e.target),
            action = target.data('action');
        if (action === 'expand-all') {
            $('.dd').nestable('expandAll');
        }
        if (action === 'collapse-all') {
            $('.dd').nestable('collapseAll');
        }
    });

    //fix позволяющий кликать на ссылки в nestable
    $(".dd a").on("mousedown", function(event) { // mousedown prevent nestable click
        event.preventDefault();
        return false;
    });
    $(".dd a").on("click", function(event) { // click event
        event.preventDefault();
        window.location = $(this).attr("href");
        return false;
    });

});

 

Как видно ничего сложного, я подробней остановлюсь на последних строках! Дело в том что наше меню использует технологию drag and drop следовательно для вызова любой ссылки с блока нашего меню приходится предотвращать выполнение функции drag and drop и выполнять действие перехода по ссылке.
Вот скриншот пример древовидного меню nestable menu

Теперь самое важное - это серверная часть нашего плагина, где собственно происходит сохранение, обработка и парсинг всех данных.

Следующий код показывает методы класса Menu, контроллера admin и адаптирован для фреймворка codeigniter, по просьбе могу выложить полностью работоспособный вариант этого плагина для codeigniter :

 

//сохранить порядок меню nestable
    function menu_sortable_save(){
        if ($this->input->post()) {
            $jsonstring = $this->input->post('jsonstring');
            // Декодируем в массив
            $jsonDecoded = json_decode($jsonstring, true, 64);
            function parseJsonArray($jsonArray, $parentID = 0)
            {
                $return = array();
                foreach ($jsonArray as $subArray) {
                    $returnSubSubArray = array();
                    if (isset($subArray['children'])) {
                        $returnSubSubArray = parseJsonArray($subArray['children'], $subArray['id']);
                    }
                    $return[] = array('id' => $subArray['id'], 'parentID' => $parentID);
                    $return = array_merge($return, $returnSubSubArray);
                }
                return $return;
            }
            $readbleArray = parseJsonArray($jsonDecoded);
            // циклом проходимся по массиву и сохраняем в бд
            foreach ($readbleArray as $key => $value) {
                if (is_array($value)) {
                    $data = array(
                        'order' => $key,
                        'parent_id' => $value['parentID']
                    );
                    $this->db->where('id', $value['id']);
                    $this->db->update('menu', $data) or $this->admin_lib->set_admin_alerts('alert_danger', 'Системное сообщение - Ошибка при сортировке записей', 'admin/menu/menu_list_sortable');;
                }
            }
            // вывод сообщения на страницу
            echo "Порядок категорий успешно сохранен в " . date("y-m-d H:i:s") . "!";
        }
    }

 

Итак, мы получили отличный плагин для вывода древовидного меню средствами jQuery PHP и MySQL. Результат:

Drag and drop nest menu php mysql jquery

Как и обещал исходники приложения и полные исходники модуля для codeigniter

6502 Просмотров Комментариев: 8

Mostak Shahid

Ответить

how to use полные исходники модуля для codeigniter.

Евгений Поляков

Ответить

MOSTAK SHAHID, исходники модуля - предполагают что вы используете свой движок на codeigniter с расширением hmvc. Просто скопировать папку и установить - не получится. Нужно разобраться в исходном коде и тогда можно использовать его по своему усмотрению. В данный момент уже есть три статьи по созданию движка на codeigniter 3 + HMVC. Этот модуль как раз будем создавать и разбирать код в одной из ближайших статей.

Павел

Ответить

Спасибо...

hipm

Ответить

Павел, в исходниках для codeigniter указана ссылка на библиотеку - 'admin/admin_lib', а ее там нет.....

Андрей

Ответить

Весь "косяк" этого метода в том, что при любом телодвижении, он делает UPDATE через foreach всей таблице. Для небольших таблиц такой метод приемлем. Но если таблица, например, содержит несколько тысяч записей - тормоза вам обеспечены. Проверял на таблице в 1800 записей. На локале выполнялся секунд 5. На реальном хостинге проверять, всё желание отпало -_-

Александр

Ответить

В исходниках для codeigniter указана ссылка на библиотеку - 'admin/admin_lib', я ее не нашел.

Виктор

Ответить

Nestable отключает все события с элементами списка. Вы не в курсе, как можно включить событие клика (или двойного клика) по элементу. Простое навешивание click не срабатывает.

Юрий

Ответить

Подружитесь с jQuery... там это куда проще и короче делается...

« Перейти к оглавлениюВсе статьи Следующая статья »Подключение платежной системы LiqPAY API на наш сайт Codeigniter