Требуются: act_as_nested_set, учебник AJAX перетаскивания - PullRequest
0 голосов
/ 13 октября 2008

Может кто-нибудь предложить учебник или пример кода, который реализует вложенный набор (или подобную упорядоченную древовидную структуру) со связанным Javascript, который облегчает перетаскивание? Я ищу как код отображения (представление), так и внутренний контроллер AJAX, который записывает дерево в базу данных при изменении.

Я хочу, чтобы он представлял собой многослойное меню, в котором важен порядок и глубина элементов.

Ответы [ 4 ]

2 голосов
/ 23 октября 2008

После долгих поисков я нашел этот онлайн-пример , написанный Свеном Фуксом, который делает 90% того, что мне нужно.

0 голосов
/ 07 июля 2009
0 голосов
/ 14 октября 2008

Для этого я использовал дерево перетаскивания папок www.dhtmlgoodies.com . это не самый последний самый современный javascript для mootools / jquery / yourfavoriteframework, но вам не нужно смотреть на это, он прекрасно работает как компонент и поставляется с хорошим набором изображений.

Я создал небольшой класс оболочки Mootools 1.1:

window.addEvent('domready', function()
    {
        document.Treeview = new TreeView();
    });


TreeView = new Class({

    initialize: function()
    {
        treeObj = new JSDragDropTree();
        treeObj.setTreeId('treeview');
        treeObj.initTree();
        treeObj.showHideNode(true, 'node0');
        $$('.hiddennode').each(function(elm) { elm.setStyle('display','none'); });
        this.currentItem = false;
    },

    saveValues: function() 
    {
        saveString = treeObj.getNodeOrders();
        new Ajax('./menuitem/save', {postBody: 'order='+saveString, onComplete:function(){window.Growl(this.transport.responseText)}, multiple:false}).request();
    },

    addItem: function()
    {
        new Ajax('./menuitem/add', {update:'editPanel'}).request();     
    },

    loadMenuItem: function(id)
    {
        this.currentItem = id;
        new Ajax('./menuitem/edit/'+id, {update:'editPanel', onComplete:function(){new ScrollDing('editPanel');}}).request();
    },

    removeItem: function()
    {
        if(!this.currentItem)
        {
            alert('please select a menu item to delete.');
        }
        else
        {
        if(confirm('Are you sure you want to delete this menu item?'))
        { 
            // multiple: true is my little extension to mootools's Ajax class. 
        // It expects a JSON object with keys corresponding to element ID's
        // and updates their innerHTML
            new Ajax('./menuitem/delete/'+this.currentItem, {multiple:true}).request();
            this.currentItem = false;
        }
        }
    }

});

Есть класс PHP, который выполняет базовую настройку. Я упростил некоторые вещи для примера, но это должно помочь вам начать. Конечно, вам придется настроить его, чтобы использовать RoR :-P

/**
 * 
 * @package Pork
 * @author SchizoDuckie
 * @copyright SchizoDuckie 2008
 */
class TreeMenu
{
    private  $menuItems, $output;
    function __construct()
    {
        global $db;

        $input =  $db->fetchAll("SELECT * FROM menu ORDER BY intparent, intOrder");
        for ($i=0; $i<sizeof($input); $i++)
        {
            $array = $input[$i];
            $this->menuItems[ $array->intParent ][ ] = $array;
        }
    }

    function hasSubItems($node)
    {
        return (array_key_exists($node, $this->menuItems) && sizeof($this->menuItems[$node]) > 0) ? true : false;
    } 

    function displaytree($start=0, $noSiblings=false)
    {
        $output .= "<ul>";
        for ($i=0; $i<sizeof($this->menuItems[$start]); $i++)
        {

            $item = $this->menuItems[$start][$i];
            $siblings = ($noSiblings) ? "  " : '';
            $output .=  "<li id='node{$item->ID_Menu}'{$siblings}><a href='#' onclick='Treeview.loadMenuItem({$item->ID_Menu});return false;'>{$item->strMenuItem}</a>";
            if ($this->hasSubItems($item->ID_Menu))
            {
                $output .= $this->displayTree($item->ID_Menu, $noSiblings);
            }
            $output .=  "</li>";
        }       
       $output .=   "</ul>";
       return($output);
    }

    function getTreeInnerHTML()
    {
        return("<li id='node0' noDrag='true' noSiblings='true'><a href='#' onclick='return false'>Root</a>{$this->displaytree()}</li>");


    function display()
    {
        global $_TPL;

        $_TPL['styles'][] = './includes/drag-drop-folder-tree.css';
        $_TPL['scripts'][]= './includes/drag-drop-folder-tree.js';
        $_TPL['scripts'][]= './includes/pork.foldertree.js';

        return ("<div id='treebuttons'>
            <input type='button' onclick='Treeview.saveValues()' value='Save order'>
            <input type='button' onclick='Treeview.addItem()' value='Add'>
            <input type='button' onclick='Treeview.removeItem()' value='Remove'>
        </div>
        <ul id='treeview'>{$this->getTreeInnerHTML()}</ul>
        <div id='msgDiv'></div>

        <div id='editPanel'></div>
        ");
    }

}

использование:

$tv = new TreeView();
$_TPL['menu'] = $tv->display();

Вот также примеры для изменения порядка и того, что делают функции добавления, редактирования и удаления (упрощенный курс). JsObject - это просто оболочка с функцией отображения и функциями __get и __set, которая умирает () с массивом json_encoded. Очень удобно для запросов ajax;)

<?
global $_URI;

switch ($_URI[0])
{
    case 'menuitem':
        switch ($_URI[1])
        {
            case 'add':
                $item = new menuItem();
                die($item->displayEditor('Add Menu Item', "multiple:true"));
            break;
            case 'edit':
                $item = new menuItem($_URI[2]);
                $_SESSION['currentMenuItem'] = $_URI[2];
                die($item->displayEditor('Edit MenuItem', 'multiple:true'));
            break;
            case 'delete':
                $item = new menuItem($_URI[2]);
                $item->deleteYourSelf();
                $js = new jsObject();
                $js->editPanel = 'Menu Item '.$item->menuItem.' has been deleted.';

                $menu = new Menu();
                $js->treeview = $menu->getTreeInnerHTML();
                $js->script = "document.Treeview = new TreeView();";    
                $js->display();
            break;
            case 'save':
            $items = explode(",",$_POST['order']);
            for($i=0;$i<sizeof($items);$i++)
            {
                $tokens = explode("|",$items[$i]);
                $db->query("update menu set intParent='{$tokens[1]}', intOrder='{$i}' where ID_Menu='{$tokens[0]}'");
            }
            die('Saved the new order!');
        break;
        }
    break;
}

?>

Там у вас есть один урок с читаемым, не требующим пояснений кодом. Это не RoR и не Prototype, но это должно помочь вам правильно начать?

0 голосов
/ 13 октября 2008

Что-то вроде этого вы действительно не хотите шлепать плагин JQuery. Если вы не можете ничего найти, самое время приготовить себе эспрессо и погрузиться прямо в код :))

Используйте другой - более зрелый - код в качестве примера, но напишите его самостоятельно, и он действительно подойдет вашему проекту лучше всего. Поиск внешнего и внутреннего кода вместе тоже очень сложно ... если только вы не хотите что-то из поста в блоге, которое может быть озаглавлено как «30 плагинов jquery для AJAXify вашего сайта», и вы не хотите дерьмовый код PHP. (В данном случае кажется, что вы хотите RoR)

Возможно, это вам не сильно поможет, но я бы это сделал.

В любом случае, я особенно против плагина jQuery-плагинов ... даже если он делает то, что вам нужно. Большая часть этого кода раздувается. Плюс я не склонен доверять другим людям:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...