Appartamento in Affitto Milano – Washington

ExtTree

This is a starting point for make a tree with the extjs (v 1.0) framework.

 1 # app/model/category.rb
 2 class Category < ActiveRecord::Base
 3   validates_presence_of :name
 4 
 5   belongs_to :image
 6 
 7   has_many :categorizations, :dependent => :destroy
 8   has_many :products, :through => :categorizations
 9 
10   acts_as_sluggable :with => :name
11 
12   acts_as_nested_set
13 
14   ...

In the view a script like that

  1 EditableCategories = function(){
  2     return {
  3      init : function(){
  4            // turn on quick tips
  5         Ext.QuickTips.init();
  6             // seeds for the new node suffix
  7         var cseed = 0, oseed = 0;
  8         // create the primary toolbar
  9 
 10             var tb = new Ext.Toolbar('toolbar');
 11         tb.add({
 12                     id:'add',
 13             text: 'Add',
 14                     disabled:false,
 15                     handler: add,
 16                     cls: 'x-btn-text-icon add',
 17                     tooltip: 'Add a new Menu'
 18             },'-',{
 19             id:'remove',
 20             text:'Delete',
 21             disabled:false,
 22             handler:removeNode,
 23             cls:'x-btn-text-icon remove',
 24             tooltip:'Delete the Menu'
 25         });
 26 
 27             layout = new Ext.BorderLayout("main", {
 28                north: {
 29                    split:false,
 30                    titlebar: false
 31                },
 32                west: {
 33                    split:false,
 34                    initialSize: 200,
 35                              border: ''
 36                },
 37                center: {
 38                            split:false,
 39                    autoScroll:true,
 40                    tabPosition:'top',
 41                              toolbar: tb    
 42                }
 43           });
 44 
 45          layout.beginUpdate();
 46 
 47          layout.add('north',  new Ext.ContentPanel('toolbar', 'Header'));
 48          layout.add('west',     new Ext.ContentPanel('content-items', {title: 'Menu', fitToFrame:true}));
 49        layout.add('center', new Ext.ContentPanel('form', {title: 'Contentuto', closable: false}));
 50 
 51        layout.restoreState();
 52        layout.endUpdate();
 53 
 54          Lipsiadmin.getLayout().add("center", new Ext.NestedLayoutPanel(layout));
 55 
 56         // for enabling and disabling
 57         var btns = tb.items.map;
 58 
 59             // editable ctree  
 60         var xt = Ext.tree;
 61 
 62         var ctree = new xt.TreePanel('content-items', {  
 63             animate:true,   
 64             loader: new xt.TreeLoader({dataUrl:'/admin/categories/data'}),  
 65             enableDD:true,  
 66             containerScroll: true  
 67         });  
 68 
 69             ctree.el.addKeyListener(Ext.EventObject.DELETE, removeNode);
 70 
 71         // set the root node  
 72         var croot = new xt.AsyncTreeNode({  
 73             text: 'Home',  
 74             draggable:false,  
 75             id:'source'  
 76         });  
 77 
 78             ctree.setRootNode(croot);  
 79 
 80         // render the ctree  
 81         ctree.render();  
 82         croot.expand(true);
 83 
 84         ctree.el.on('keypress', function(e){
 85             if(e.isNavKeyPress()){
 86                 e.stopEvent();
 87             }
 88         });
 89 
 90         // when the tree selection changes, enable/disable the toolbar buttons
 91         var sm = ctree.getSelectionModel();
 92         sm.on('selectionchange', function(){
 93             var n = sm.getSelectedNode();
 94             if(!n || !n.parentNode){
 95                 btns.remove.disable();
 96               return;
 97                     } else {
 98                         btns.remove.enable();
 99                         return;
100             }
101         });
102 
103             ctree.on('click', function(node){click(node)});
104             ctree.on('enddrag', save);
105 
106         // create the editor for the component ctree
107         var ge = new xt.TreeEditor(ctree, {
108             allowBlank:false,
109             blankText:'You must insert a name!',
110             selectOnFocus:true
111         });
112 
113             ge.on('complete', save);
114 
115             // add component handler
116         function add(){
117                 var id = guid('c-');
118           var text = 'Menu '+(++cseed);
119           var node = new xt.TreeNode({
120               text: text,
121               iconCls:'folder',
122               cls:'folder',
123               type:'folder',
124               allowDelete:true,
125               allowEdit:true
126           });
127           croot.appendChild(node);
128           node.expand(false, false);
129           node.select();
130           ge.triggerEdit(node);
131         }
132 
133             // remove handler
134         function removeNode(){
135                 var n = sm.getSelectedNode();
136                     if(n){
137                       Ext.get('main').mask('Sending data to server...', 'x-mask-loading');
138                             new Ajax.Request('/admin/categories/destroy', 
139                                                              {method:'post', parameters:'id='+n.id, onSuccess:refresh, onFailure:refresh});
140                     }
141         }
142 
143             function getChildren(c){
144                 var ch = [];
145 
146                 if (c.parentNode){
147                     var cld = {
148                         id: c.id,
149                         text:c.text,
150                         parent_id: c.parentNode.id
151                     }
152                 }
153 
154                 ch.push(cld)
155 
156                 if (c.childrenRendered){
157                     c.eachChild(function(o){
158                         getChildren(o).each(function(z){ch.push(z);});
159                     });
160                 }
161 
162                 return ch;
163             }
164 
165             // save to the server in a format usable in ruby
166         function save(){
167                 croot.expand(true) // WHY I NEED TO DO THAT? U KNOW A BETTER WAY?
168                 var ch = getChildren(croot);
169 
170           Ext.get('main').mask('Sending data to server...', 'x-mask-loading');
171 
172                 new Ajax.Request('/admin/categories/update', 
173                                                  {method:'post', parameters:'data='+encodeURIComponent(Ext.encode(ch)), onSuccess:refresh, onFailure:refresh});
174 
175         }
176 
177             function refresh(){
178                 Ext.get('main').unmask();
179                 croot.reload();
180                 croot.expand(true);
181             }
182 
183             // semi unique ids across edits
184         function guid(prefix){
185             return prefix+(new Date().getTime());
186         }
187 
188             function click(node){
189                 new Ajax.Request('/admin/categories/load_details/'+node.id, {asynchronous:true, evalScripts:true});
190             }
191         },
192 
193         refresh : function(id){
194             new Ajax.Request('/admin/categories/load_details/'+id, {asynchronous:true, evalScripts:true});
195         }
196     }
197 }();
198 
199 Ext.onReady(EditableCategories.init, EditableCategories, true);

Finally for get records in the controller some similar to this:

 1   def data  
 2     categories = Category.find_by_sql("select * from categories where parent_id is null")   
 3     data = get_tree(categories,nil)    
 4     render :text => data.to_json, :layout=>false  
 5   end   
 6 
 7   def get_tree(categories, parent)  
 8     data = Array.new  
 9     categories.each { |category|  
10       if !category.leaf?  
11         if data.empty?  
12           data =   [{"text"  =>  category.name, "id"  => category.id, "leaf"  => false,  
13                      "children" => get_tree(category.children,category) }]   
14         else  
15           data.concat([{"text"  =>  category.name, "id"  => category.id, "leaf"  => false,  
16                          "children" => get_tree(category.children,category)}])  
17         end  
18       else  
19         data.concat([{"text" => category.name, "id" => category.id, "cls" => "folder", "leaf" => false, "children" => []}])   
20       end  
21     }  
22     return data  
23   end

Also available in: HTML TXT