【问题标题】:Wanted: acts_as_nested_set, AJAX drag and drop tutorial通缉:acts_as_nested_set,AJAX拖放教程
【发布时间】:2008-10-13 15:47:03
【问题描述】:

任何人都可以推荐一个教程或示例代码来实现嵌套集(或类似的有序树结构)以及便于拖放的相关 Javascript 吗?我正在寻找显示代码(视图)以及在更改时将树写入数据库的 AJAX 后端控制器。

我希望它代表一个多层菜单,其中项目的顺序和深度很重要。

【问题讨论】:

    标签: javascript ruby-on-rails prototypejs


    【解决方案1】:

    经过大量搜索,我找到了由 Sven Fuchs 编写的 this online example,它可以满足我 90% 的需求。

    【讨论】:

      【解决方案2】:
      【解决方案3】:

      这样的事情你真的不想为一个 jquery 插件打耳光。如果你在外面找不到任何东西,是时候给自己做一杯浓缩咖啡,然后自己深入研究代码了:)

      使用其他更成熟的代码作为示例点,但您自己编写它会最适合您的项目。同时寻找前端和后端代码也非常困难......除非你想从一篇博客文章中获得一些标题,比如“30 个用于 AJAXify 网站的 jquery 插件”,并且你想要垃圾 PHP 代码。 (在这种情况下,您似乎需要 RoR)

      这可能对你没有多大帮助,但这是我会做的。

      无论如何,我特别反对 jquery 插件......即使它完成了你想要的工作。很多代码都很臃肿。另外我倾向于不信任其他人:)

      【讨论】:

        【解决方案4】:

        我已经使用 www.dhtmlgoodies.com 的拖放文件夹树来执行此操作。它不是最新的 mootools/jquery/yourfavoriteframework javascript,但您不必看它,它作为一个组件很好地完成了工作,并带有一组漂亮的图像。

        我创建了一个小的 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 函数的包装器,die() 带有一个 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,但这应该让你开始吧?

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-09-06
          • 1970-01-01
          • 2018-08-21
          • 1970-01-01
          • 2012-09-08
          相关资源
          最近更新 更多