]> git.wh0rd.org - tt-rss.git/blobdiff - lib/dijit/tree/ForestStoreModel.js
upgrade Dojo to 1.6.1
[tt-rss.git] / lib / dijit / tree / ForestStoreModel.js
index aa51b0023464f44800951bbdb5d563d1258b8b82..5e1b25efb55608bed895f7d595fdd9983c56b67d 100644 (file)
 /*
-       Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
+       Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
        Available via Academic Free License >= 2.1 OR the modified BSD license.
        see: http://dojotoolkit.org/license for details
 */
 
 
-if(!dojo._hasResource["dijit.tree.ForestStoreModel"]){
-dojo._hasResource["dijit.tree.ForestStoreModel"]=true;
+if(!dojo._hasResource["dijit.tree.ForestStoreModel"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.tree.ForestStoreModel"] = true;
 dojo.provide("dijit.tree.ForestStoreModel");
 dojo.require("dijit.tree.TreeStoreModel");
-dojo.declare("dijit.tree.ForestStoreModel",dijit.tree.TreeStoreModel,{rootId:"$root$",rootLabel:"ROOT",query:null,constructor:function(_1){
-this.root={store:this,root:true,id:_1.rootId,label:_1.rootLabel,children:_1.rootChildren};
-},mayHaveChildren:function(_2){
-return _2===this.root||this.inherited(arguments);
-},getChildren:function(_3,_4,_5){
-if(_3===this.root){
-if(this.root.children){
-_4(this.root.children);
-}else{
-this.store.fetch({query:this.query,onComplete:dojo.hitch(this,function(_6){
-this.root.children=_6;
-_4(_6);
-}),onError:_5});
-}
-}else{
-this.inherited(arguments);
-}
-},isItem:function(_7){
-return (_7===this.root)?true:this.inherited(arguments);
-},fetchItemByIdentity:function(_8){
-if(_8.identity==this.root.id){
-var _9=_8.scope?_8.scope:dojo.global;
-if(_8.onItem){
-_8.onItem.call(_9,this.root);
-}
-}else{
-this.inherited(arguments);
-}
-},getIdentity:function(_a){
-return (_a===this.root)?this.root.id:this.inherited(arguments);
-},getLabel:function(_b){
-return (_b===this.root)?this.root.label:this.inherited(arguments);
-},newItem:function(_c,_d,_e){
-if(_d===this.root){
-this.onNewRootItem(_c);
-return this.store.newItem(_c);
-}else{
-return this.inherited(arguments);
-}
-},onNewRootItem:function(_f){
-},pasteItem:function(_10,_11,_12,_13,_14){
-if(_11===this.root){
-if(!_13){
-this.onLeaveRoot(_10);
-}
-}
-dijit.tree.TreeStoreModel.prototype.pasteItem.call(this,_10,_11===this.root?null:_11,_12===this.root?null:_12,_13,_14);
-if(_12===this.root){
-this.onAddToRoot(_10);
-}
-},onAddToRoot:function(_15){
-},onLeaveRoot:function(_16){
-},_requeryTop:function(){
-var _17=this.root.children||[];
-this.store.fetch({query:this.query,onComplete:dojo.hitch(this,function(_18){
-this.root.children=_18;
-if(_17.length!=_18.length||dojo.some(_17,function(_19,idx){
-return _18[idx]!=_19;
-})){
-this.onChildrenChange(this.root,_18);
-}
-})});
-},onNewItem:function(_1a,_1b){
-this._requeryTop();
-this.inherited(arguments);
-},onDeleteItem:function(_1c){
-if(dojo.indexOf(this.root.children,_1c)!=-1){
-this._requeryTop();
-}
-this.inherited(arguments);
-}});
+
+
+dojo.declare("dijit.tree.ForestStoreModel", dijit.tree.TreeStoreModel, {
+       // summary:
+       //              Interface between a dijit.Tree and a dojo.data store that doesn't have a root item,
+       //              a.k.a. a store that has multiple "top level" items.
+       //
+       // description
+       //              Use this class to wrap a dojo.data store, making all the items matching the specified query
+       //              appear as children of a fabricated "root item".  If no query is specified then all the
+       //              items returned by fetch() on the underlying store become children of the root item.
+       //              This class allows dijit.Tree to assume a single root item, even if the store doesn't have one.
+       //
+       //              When using this class the developer must override a number of methods according to their app and
+       //              data, including:
+       //                      - onNewRootItem
+       //                      - onAddToRoot
+       //                      - onLeaveRoot
+       //                      - onNewItem
+       //                      - onSetItem
+
+       // Parameters to constructor
+
+       // rootId: String
+       //              ID of fabricated root item
+       rootId: "$root$",
+
+       // rootLabel: String
+       //              Label of fabricated root item
+       rootLabel: "ROOT",
+
+       // query: String
+       //              Specifies the set of children of the root item.
+       // example:
+       //      |       {type:'continent'}
+       query: null,
+
+       // End of parameters to constructor
+
+       constructor: function(params){
+               // summary:
+               //              Sets up variables, etc.
+               // tags:
+               //              private
+
+               // Make dummy root item
+               this.root = {
+                       store: this,
+                       root: true,
+                       id: params.rootId,
+                       label: params.rootLabel,
+                       children: params.rootChildren   // optional param
+               };
+       },
+
+       // =======================================================================
+       // Methods for traversing hierarchy
+
+       mayHaveChildren: function(/*dojo.data.Item*/ item){
+               // summary:
+               //              Tells if an item has or may have children.  Implementing logic here
+               //              avoids showing +/- expando icon for nodes that we know don't have children.
+               //              (For efficiency reasons we may not want to check if an element actually
+               //              has children until user clicks the expando node)
+               // tags:
+               //              extension
+               return item === this.root || this.inherited(arguments);
+       },
+
+       getChildren: function(/*dojo.data.Item*/ parentItem, /*function(items)*/ callback, /*function*/ onError){
+               // summary:
+               //              Calls onComplete() with array of child items of given parent item, all loaded.
+               if(parentItem === this.root){
+                       if(this.root.children){
+                               // already loaded, just return
+                               callback(this.root.children);
+                       }else{
+                               this.store.fetch({
+                                       query: this.query,
+                                       onComplete: dojo.hitch(this, function(items){
+                                               this.root.children = items;
+                                               callback(items);
+                                       }),
+                                       onError: onError
+                               });
+                       }
+               }else{
+                       this.inherited(arguments);
+               }
+       },
+
+       // =======================================================================
+       // Inspecting items
+
+       isItem: function(/* anything */ something){
+               return (something === this.root) ? true : this.inherited(arguments);
+       },
+
+       fetchItemByIdentity: function(/* object */ keywordArgs){
+               if(keywordArgs.identity == this.root.id){
+                       var scope = keywordArgs.scope?keywordArgs.scope:dojo.global;
+                       if(keywordArgs.onItem){
+                               keywordArgs.onItem.call(scope, this.root);
+                       }
+               }else{
+                       this.inherited(arguments);
+               }
+       },
+
+       getIdentity: function(/* item */ item){
+               return (item === this.root) ? this.root.id : this.inherited(arguments);
+       },
+
+       getLabel: function(/* item */ item){
+               return  (item === this.root) ? this.root.label : this.inherited(arguments);
+       },
+
+       // =======================================================================
+       // Write interface
+
+       newItem: function(/* dojo.dnd.Item */ args, /*Item*/ parent, /*int?*/ insertIndex){
+               // summary:
+               //              Creates a new item.   See dojo.data.api.Write for details on args.
+               //              Used in drag & drop when item from external source dropped onto tree.
+               if(parent === this.root){
+                       this.onNewRootItem(args);
+                       return this.store.newItem(args);
+               }else{
+                       return this.inherited(arguments);
+               }
+       },
+
+       onNewRootItem: function(args){
+               // summary:
+               //              User can override this method to modify a new element that's being
+               //              added to the root of the tree, for example to add a flag like root=true
+       },
+
+       pasteItem: function(/*Item*/ childItem, /*Item*/ oldParentItem, /*Item*/ newParentItem, /*Boolean*/ bCopy, /*int?*/ insertIndex){
+               // summary:
+               //              Move or copy an item from one parent item to another.
+               //              Used in drag & drop
+               if(oldParentItem === this.root){
+                       if(!bCopy){
+                               // It's onLeaveRoot()'s responsibility to modify the item so it no longer matches
+                               // this.query... thus triggering an onChildrenChange() event to notify the Tree
+                               // that this element is no longer a child of the root node
+                               this.onLeaveRoot(childItem);
+                       }
+               }
+               dijit.tree.TreeStoreModel.prototype.pasteItem.call(this, childItem,
+                       oldParentItem === this.root ? null : oldParentItem,
+                       newParentItem === this.root ? null : newParentItem,
+                       bCopy,
+                       insertIndex
+               );
+               if(newParentItem === this.root){
+                       // It's onAddToRoot()'s responsibility to modify the item so it matches
+                       // this.query... thus triggering an onChildrenChange() event to notify the Tree
+                       // that this element is now a child of the root node
+                       this.onAddToRoot(childItem);
+               }
+       },
+
+       // =======================================================================
+       // Handling for top level children
+
+       onAddToRoot: function(/* item */ item){
+               // summary:
+               //              Called when item added to root of tree; user must override this method
+               //              to modify the item so that it matches the query for top level items
+               // example:
+               //      |       store.setValue(item, "root", true);
+               // tags:
+               //              extension
+               console.log(this, ": item ", item, " added to root");
+       },
+
+       onLeaveRoot: function(/* item */ item){
+               // summary:
+               //              Called when item removed from root of tree; user must override this method
+               //              to modify the item so it doesn't match the query for top level items
+               // example:
+               //      |       store.unsetAttribute(item, "root");
+               // tags:
+               //              extension
+               console.log(this, ": item ", item, " removed from root");
+       },
+
+       // =======================================================================
+       // Events from data store
+
+       _requeryTop: function(){
+               // reruns the query for the children of the root node,
+               // sending out an onSet notification if those children have changed
+               var oldChildren = this.root.children || [];
+               this.store.fetch({
+                       query: this.query,
+                       onComplete: dojo.hitch(this, function(newChildren){
+                               this.root.children = newChildren;
+
+                               // If the list of children or the order of children has changed...
+                               if(oldChildren.length != newChildren.length ||
+                                       dojo.some(oldChildren, function(item, idx){ return newChildren[idx] != item;})){
+                                       this.onChildrenChange(this.root, newChildren);
+                               }
+                       })
+               });
+       },
+
+       onNewItem: function(/* dojo.data.Item */ item, /* Object */ parentInfo){
+               // summary:
+               //              Handler for when new items appear in the store.  Developers should override this
+               //              method to be more efficient based on their app/data.
+               // description:
+               //              Note that the default implementation requeries the top level items every time
+               //              a new item is created, since any new item could be a top level item (even in
+               //              addition to being a child of another item, since items can have multiple parents).
+               //
+               //              If developers can detect which items are possible top level items (based on the item and the
+               //              parentInfo parameters), they should override this method to only call _requeryTop() for top
+               //              level items.  Often all top level items have parentInfo==null, but
+               //              that will depend on which store you use and what your data is like.
+               // tags:
+               //              extension
+               this._requeryTop();
+
+               this.inherited(arguments);
+       },
+
+       onDeleteItem: function(/*Object*/ item){
+               // summary:
+               //              Handler for delete notifications from underlying store
+
+               // check if this was a child of root, and if so send notification that root's children
+               // have changed
+               if(dojo.indexOf(this.root.children, item) != -1){
+                       this._requeryTop();
+               }
+
+               this.inherited(arguments);
+       },
+
+       onSetItem: function(/* item */ item,
+                                       /* attribute-name-string */ attribute,
+                                       /* object | array */ oldValue,
+                                       /* object | array */ newValue){
+               // summary:
+               //              Updates the tree view according to changes to an item in the data store.
+               //              Developers should override this method to be more efficient based on their app/data.
+               // description:
+               //              Handles updates to an item's children by calling onChildrenChange(), and
+               //              other updates to an item by calling onChange().
+               //
+               //              Also, any change to any item re-executes the query for the tree's top-level items,
+               //              since this modified item may have started/stopped matching the query for top level items.
+               //
+               //              If possible, developers should override this function to only call _requeryTop() when
+               //              the change to the item has caused it to stop/start being a top level item in the tree.
+               // tags:
+               //              extension
+
+               this._requeryTop();
+               this.inherited(arguments);
+       }
+
+});
+
 }