mirror of
https://git.tt-rss.org/git/tt-rss.git
synced 2025-12-29 22:21:29 +00:00
upgrade dojo to 1.8.3 (refs #570)
This commit is contained in:
@@ -1,2 +1,2 @@
|
||||
//>>built
|
||||
define("dijit/tree/ForestStoreModel",["dojo/_base/array","dojo/_base/declare","dojo/_base/lang","dojo/_base/window","./TreeStoreModel"],function(_1,_2,_3,_4,_5){return _2("dijit.tree.ForestStoreModel",_5,{rootId:"$root$",rootLabel:"ROOT",query:null,constructor:function(_6){this.root={store:this,root:true,id:_6.rootId,label:_6.rootLabel,children:_6.rootChildren};},mayHaveChildren:function(_7){return _7===this.root||this.inherited(arguments);},getChildren:function(_8,_9,_a){if(_8===this.root){if(this.root.children){_9(this.root.children);}else{this.store.fetch({query:this.query,onComplete:_3.hitch(this,function(_b){this.root.children=_b;_9(_b);}),onError:_a});}}else{this.inherited(arguments);}},isItem:function(_c){return (_c===this.root)?true:this.inherited(arguments);},fetchItemByIdentity:function(_d){if(_d.identity==this.root.id){var _e=_d.scope?_d.scope:_4.global;if(_d.onItem){_d.onItem.call(_e,this.root);}}else{this.inherited(arguments);}},getIdentity:function(_f){return (_f===this.root)?this.root.id:this.inherited(arguments);},getLabel:function(_10){return (_10===this.root)?this.root.label:this.inherited(arguments);},newItem:function(_11,_12,_13){if(_12===this.root){this.onNewRootItem(_11);return this.store.newItem(_11);}else{return this.inherited(arguments);}},onNewRootItem:function(){},pasteItem:function(_14,_15,_16,_17,_18){if(_15===this.root){if(!_17){this.onLeaveRoot(_14);}}this.inherited(arguments,[_14,_15===this.root?null:_15,_16===this.root?null:_16,_17,_18]);if(_16===this.root){this.onAddToRoot(_14);}},onAddToRoot:function(_19){},onLeaveRoot:function(_1a){},_requeryTop:function(){var _1b=this.root.children||[];this.store.fetch({query:this.query,onComplete:_3.hitch(this,function(_1c){this.root.children=_1c;if(_1b.length!=_1c.length||_1.some(_1b,function(_1d,idx){return _1c[idx]!=_1d;})){this.onChildrenChange(this.root,_1c);}})});},onNewItem:function(_1e,_1f){this._requeryTop();this.inherited(arguments);},onDeleteItem:function(_20){if(_1.indexOf(this.root.children,_20)!=-1){this._requeryTop();}this.inherited(arguments);},onSetItem:function(_21,_22,_23,_24){this._requeryTop();this.inherited(arguments);}});});
|
||||
define("dijit/tree/ForestStoreModel",["dojo/_base/array","dojo/_base/declare","dojo/_base/kernel","dojo/_base/lang","./TreeStoreModel"],function(_1,_2,_3,_4,_5){return _2("dijit.tree.ForestStoreModel",_5,{rootId:"$root$",rootLabel:"ROOT",query:null,constructor:function(_6){this.root={store:this,root:true,id:_6.rootId,label:_6.rootLabel,children:_6.rootChildren};},mayHaveChildren:function(_7){return _7===this.root||this.inherited(arguments);},getChildren:function(_8,_9,_a){if(_8===this.root){if(this.root.children){_9(this.root.children);}else{this.store.fetch({query:this.query,onComplete:_4.hitch(this,function(_b){this.root.children=_b;_9(_b);}),onError:_a});}}else{this.inherited(arguments);}},isItem:function(_c){return (_c===this.root)?true:this.inherited(arguments);},fetchItemByIdentity:function(_d){if(_d.identity==this.root.id){var _e=_d.scope||_3.global;if(_d.onItem){_d.onItem.call(_e,this.root);}}else{this.inherited(arguments);}},getIdentity:function(_f){return (_f===this.root)?this.root.id:this.inherited(arguments);},getLabel:function(_10){return (_10===this.root)?this.root.label:this.inherited(arguments);},newItem:function(_11,_12,_13){if(_12===this.root){this.onNewRootItem(_11);return this.store.newItem(_11);}else{return this.inherited(arguments);}},onNewRootItem:function(){},pasteItem:function(_14,_15,_16,_17,_18){if(_15===this.root){if(!_17){this.onLeaveRoot(_14);}}this.inherited(arguments,[_14,_15===this.root?null:_15,_16===this.root?null:_16,_17,_18]);if(_16===this.root){this.onAddToRoot(_14);}},onAddToRoot:function(_19){},onLeaveRoot:function(_1a){},_requeryTop:function(){var _1b=this.root.children||[];this.store.fetch({query:this.query,onComplete:_4.hitch(this,function(_1c){this.root.children=_1c;if(_1b.length!=_1c.length||_1.some(_1b,function(_1d,idx){return _1c[idx]!=_1d;})){this.onChildrenChange(this.root,_1c);}})});},onNewItem:function(_1e,_1f){this._requeryTop();this.inherited(arguments);},onDeleteItem:function(_20){if(_1.indexOf(this.root.children,_20)!=-1){this._requeryTop();}this.inherited(arguments);},onSetItem:function(_21,_22,_23,_24){this._requeryTop();this.inherited(arguments);}});});
|
||||
279
lib/dijit/tree/ForestStoreModel.js.uncompressed.js
Normal file
279
lib/dijit/tree/ForestStoreModel.js.uncompressed.js
Normal file
@@ -0,0 +1,279 @@
|
||||
define("dijit/tree/ForestStoreModel", [
|
||||
"dojo/_base/array", // array.indexOf array.some
|
||||
"dojo/_base/declare", // declare
|
||||
"dojo/_base/kernel", // global
|
||||
"dojo/_base/lang", // lang.hitch
|
||||
"./TreeStoreModel"
|
||||
], function(array, declare, kernel, lang, TreeStoreModel){
|
||||
|
||||
// module:
|
||||
// dijit/tree/ForestStoreModel
|
||||
|
||||
return declare("dijit.tree.ForestStoreModel", 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: lang.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 || kernel.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(/* dijit/tree/dndSource.__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(/* dijit/tree/dndSource.__Item */ /*===== 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);
|
||||
}
|
||||
}
|
||||
this.inherited(arguments, [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: lang.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 ||
|
||||
array.some(oldChildren, function(item, idx){ return newChildren[idx] != item;})){
|
||||
this.onChildrenChange(this.root, newChildren);
|
||||
}
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
onNewItem: function(/* dojo/data/api/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(array.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);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
2
lib/dijit/tree/ObjectStoreModel.js
Normal file
2
lib/dijit/tree/ObjectStoreModel.js
Normal file
@@ -0,0 +1,2 @@
|
||||
//>>built
|
||||
define("dijit/tree/ObjectStoreModel",["dojo/_base/array","dojo/aspect","dojo/_base/declare","dojo/_base/lang","dojo/when"],function(_1,_2,_3,_4,_5){return _3("dijit.tree.ObjectStoreModel",null,{store:null,labelAttr:"name",root:null,query:null,constructor:function(_6){_4.mixin(this,_6);this.childrenCache={};},destroy:function(){for(var id in this.childrenCache){this.childrenCache[id].close&&this.childrenCache[id].close();}},getRoot:function(_7,_8){if(this.root){_7(this.root);}else{var _9;_5(_9=this.store.query(this.query),_4.hitch(this,function(_a){if(_a.length!=1){throw new Error("dijit.tree.ObjectStoreModel: root query returned "+_a.length+" items, but must return exactly one");}this.root=_a[0];_7(this.root);if(_9.observe){_9.observe(_4.hitch(this,function(_b){this.onChange(_b);}),true);}}),_8);}},mayHaveChildren:function(){return true;},getChildren:function(_c,_d,_e){var id=this.store.getIdentity(_c);if(this.childrenCache[id]){_5(this.childrenCache[id],_d,_e);return;}var _f=this.childrenCache[id]=this.store.getChildren(_c);_5(_f,_d,_e);if(_f.observe){_f.observe(_4.hitch(this,function(obj,_10,_11){this.onChange(obj);if(_10!=_11){_5(_f,_4.hitch(this,"onChildrenChange",_c));}}),true);}},isItem:function(){return true;},fetchItemByIdentity:function(_12){this.store.get(_12.identity).then(_4.hitch(_12.scope,_12.onItem),_4.hitch(_12.scope,_12.onError));},getIdentity:function(_13){return this.store.getIdentity(_13);},getLabel:function(_14){return _14[this.labelAttr];},newItem:function(_15,_16,_17,_18){return this.store.put(_15,{parent:_16,before:_18});},pasteItem:function(_19,_1a,_1b,_1c,_1d,_1e){if(!_1c){var _1f=[].concat(this.childrenCache[this.getIdentity(_1a)]),_20=_1.indexOf(_1f,_19);_1f.splice(_20,1);this.onChildrenChange(_1a,_1f);}return this.store.put(_19,{overwrite:true,parent:_1b,before:_1e});},onChange:function(){},onChildrenChange:function(){},onDelete:function(){}});});
|
||||
250
lib/dijit/tree/ObjectStoreModel.js.uncompressed.js
Normal file
250
lib/dijit/tree/ObjectStoreModel.js.uncompressed.js
Normal file
@@ -0,0 +1,250 @@
|
||||
define("dijit/tree/ObjectStoreModel", [
|
||||
"dojo/_base/array", // array.filter array.forEach array.indexOf array.some
|
||||
"dojo/aspect", // aspect.before, aspect.after
|
||||
"dojo/_base/declare", // declare
|
||||
"dojo/_base/lang", // lang.hitch
|
||||
"dojo/when"
|
||||
], function(array, aspect, declare, lang, when){
|
||||
|
||||
// module:
|
||||
// dijit/tree/ObjectStoreModel
|
||||
|
||||
return declare("dijit.tree.ObjectStoreModel", null, {
|
||||
// summary:
|
||||
// Implements dijit/tree/model connecting dijit/Tree to a dojo/store/api/Store that implements
|
||||
// getChildren().
|
||||
//
|
||||
// If getChildren() returns an array with an observe() method, then it will be leveraged to reflect
|
||||
// store updates to the tree. So, this class will work best when:
|
||||
//
|
||||
// 1. the store implements dojo/store/Observable
|
||||
// 2. getChildren() is implemented as a query to the server (i.e. it calls store.query())
|
||||
//
|
||||
// Drag and Drop: To support drag and drop, besides implementing getChildren()
|
||||
// and dojo/store/Observable, the store must support the parent option to put().
|
||||
// And in order to have child elements ordered according to how the user dropped them,
|
||||
// put() must support the before option.
|
||||
|
||||
// store: dojo/store/api/Store
|
||||
// Underlying store
|
||||
store: null,
|
||||
|
||||
// labelAttr: String
|
||||
// Get label for tree node from this attribute
|
||||
labelAttr: "name",
|
||||
|
||||
// root: [readonly] Object
|
||||
// Pointer to the root item from the dojo/store/api/Store (read only, not a parameter)
|
||||
root: null,
|
||||
|
||||
// query: anything
|
||||
// Specifies datastore query to return the root item for the tree.
|
||||
// Must only return a single item. Alternately can just pass in pointer
|
||||
// to root item.
|
||||
// example:
|
||||
// | {id:'ROOT'}
|
||||
query: null,
|
||||
|
||||
constructor: function(/* Object */ args){
|
||||
// summary:
|
||||
// Passed the arguments listed above (store, etc)
|
||||
// tags:
|
||||
// private
|
||||
|
||||
lang.mixin(this, args);
|
||||
|
||||
this.childrenCache = {}; // map from id to array of children
|
||||
},
|
||||
|
||||
destroy: function(){
|
||||
// TODO: should cancel any in-progress processing of getRoot(), getChildren()
|
||||
for(var id in this.childrenCache){
|
||||
this.childrenCache[id].close && this.childrenCache[id].close();
|
||||
}
|
||||
},
|
||||
|
||||
// =======================================================================
|
||||
// Methods for traversing hierarchy
|
||||
|
||||
getRoot: function(onItem, onError){
|
||||
// summary:
|
||||
// Calls onItem with the root item for the tree, possibly a fabricated item.
|
||||
// Calls onError on error.
|
||||
if(this.root){
|
||||
onItem(this.root);
|
||||
}else{
|
||||
var res;
|
||||
when(res = this.store.query(this.query),
|
||||
lang.hitch(this, function(items){
|
||||
//console.log("queried root: ", res);
|
||||
if(items.length != 1){
|
||||
throw new Error("dijit.tree.ObjectStoreModel: root query returned " + items.length +
|
||||
" items, but must return exactly one");
|
||||
}
|
||||
this.root = items[0];
|
||||
onItem(this.root);
|
||||
|
||||
// Setup listener to detect if root item changes
|
||||
if(res.observe){
|
||||
res.observe(lang.hitch(this, function(obj){
|
||||
// Presumably removedFrom == insertedInto == 1, and this call indicates item has changed.
|
||||
//console.log("root changed: ", obj);
|
||||
this.onChange(obj);
|
||||
}), true); // true to listen for updates to obj
|
||||
}
|
||||
}),
|
||||
onError
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
mayHaveChildren: function(/*===== 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).
|
||||
//
|
||||
// Application code should override this method based on the data, for example
|
||||
// it could be `return item.leaf == true;`.
|
||||
// item: Object
|
||||
// Item from the dojo/store
|
||||
return true;
|
||||
},
|
||||
|
||||
getChildren: function(/*Object*/ parentItem, /*function(items)*/ onComplete, /*function*/ onError){
|
||||
// summary:
|
||||
// Calls onComplete() with array of child items of given parent item.
|
||||
// parentItem:
|
||||
// Item from the dojo/store
|
||||
|
||||
var id = this.store.getIdentity(parentItem);
|
||||
if(this.childrenCache[id]){
|
||||
when(this.childrenCache[id], onComplete, onError);
|
||||
return;
|
||||
}
|
||||
|
||||
var res = this.childrenCache[id] = this.store.getChildren(parentItem);
|
||||
|
||||
// User callback
|
||||
when(res, onComplete, onError);
|
||||
|
||||
// Setup listener in case children list changes, or the item(s) in the children list are
|
||||
// updated in some way.
|
||||
if(res.observe){
|
||||
res.observe(lang.hitch(this, function(obj, removedFrom, insertedInto){
|
||||
//console.log("observe on children of ", id, ": ", obj, removedFrom, insertedInto);
|
||||
|
||||
// If removedFrom == insertedInto, this call indicates that the item has changed.
|
||||
// Even if removedFrom != insertedInto, the item may have changed.
|
||||
this.onChange(obj);
|
||||
|
||||
if(removedFrom != insertedInto){
|
||||
// Indicates an item was added, removed, or re-parented. The children[] array (returned from
|
||||
// res.then(...)) has already been updated (like a live collection), so just use it.
|
||||
when(res, lang.hitch(this, "onChildrenChange", parentItem));
|
||||
}
|
||||
}), true); // true means to notify on item changes
|
||||
}
|
||||
},
|
||||
|
||||
// =======================================================================
|
||||
// Inspecting items
|
||||
|
||||
isItem: function(/*===== something =====*/){
|
||||
return true; // Boolean
|
||||
},
|
||||
|
||||
fetchItemByIdentity: function(/* object */ keywordArgs){
|
||||
this.store.get(keywordArgs.identity).then(
|
||||
lang.hitch(keywordArgs.scope, keywordArgs.onItem),
|
||||
lang.hitch(keywordArgs.scope, keywordArgs.onError)
|
||||
);
|
||||
},
|
||||
|
||||
getIdentity: function(/* item */ item){
|
||||
return this.store.getIdentity(item); // Object
|
||||
},
|
||||
|
||||
getLabel: function(/*dojo/data/Item*/ item){
|
||||
// summary:
|
||||
// Get the label for an item
|
||||
return item[this.labelAttr]; // String
|
||||
},
|
||||
|
||||
// =======================================================================
|
||||
// Write interface, for DnD
|
||||
|
||||
newItem: function(/* dijit/tree/dndSource.__Item */ args, /*Item*/ parent, /*int?*/ insertIndex, /*Item*/ before){
|
||||
// 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.
|
||||
|
||||
return this.store.put(args, {
|
||||
parent: parent,
|
||||
before: before
|
||||
});
|
||||
},
|
||||
|
||||
pasteItem: function(/*Item*/ childItem, /*Item*/ oldParentItem, /*Item*/ newParentItem,
|
||||
/*Boolean*/ bCopy, /*int?*/ insertIndex, /*Item*/ before){
|
||||
// summary:
|
||||
// Move or copy an item from one parent item to another.
|
||||
// Used in drag & drop
|
||||
|
||||
if(!bCopy){
|
||||
// In order for DnD moves to work correctly, childItem needs to be orphaned from oldParentItem
|
||||
// before being adopted by newParentItem. That way, the TreeNode is moved rather than
|
||||
// an additional TreeNode being created, and the old TreeNode subsequently being deleted.
|
||||
// The latter loses information such as selection and opened/closed children TreeNodes.
|
||||
// Unfortunately simply calling this.store.put() will send notifications in a random order, based
|
||||
// on when the TreeNodes in question originally appeared, and not based on the drag-from
|
||||
// TreeNode vs. the drop-onto TreeNode.
|
||||
|
||||
var oldParentChildren = [].concat(this.childrenCache[this.getIdentity(oldParentItem)]), // concat to make copy
|
||||
index = array.indexOf(oldParentChildren, childItem);
|
||||
oldParentChildren.splice(index, 1);
|
||||
this.onChildrenChange(oldParentItem, oldParentChildren);
|
||||
}
|
||||
|
||||
return this.store.put(childItem, {
|
||||
overwrite: true,
|
||||
parent: newParentItem,
|
||||
before: before
|
||||
});
|
||||
},
|
||||
|
||||
// =======================================================================
|
||||
// Callbacks
|
||||
|
||||
onChange: function(/*dojo/data/Item*/ /*===== item =====*/){
|
||||
// summary:
|
||||
// Callback whenever an item has changed, so that Tree
|
||||
// can update the label, icon, etc. Note that changes
|
||||
// to an item's children or parent(s) will trigger an
|
||||
// onChildrenChange() so you can ignore those changes here.
|
||||
// tags:
|
||||
// callback
|
||||
},
|
||||
|
||||
onChildrenChange: function(/*===== parent, newChildrenList =====*/){
|
||||
// summary:
|
||||
// Callback to do notifications about new, updated, or deleted items.
|
||||
// parent: dojo/data/Item
|
||||
// newChildrenList: Object[]
|
||||
// Items from the store
|
||||
// tags:
|
||||
// callback
|
||||
},
|
||||
|
||||
onDelete: function(/*dojo/data/Item*/ /*===== item =====*/){
|
||||
// summary:
|
||||
// Callback when an item has been deleted.
|
||||
// Actually we have no way of knowing this with the new dojo.store API,
|
||||
// so this method is never called (but it's left here since Tree connects
|
||||
// to it).
|
||||
// tags:
|
||||
// callback
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,2 +1,2 @@
|
||||
//>>built
|
||||
define("dijit/tree/TreeStoreModel",["dojo/_base/array","dojo/aspect","dojo/_base/declare","dojo/_base/json","dojo/_base/lang"],function(_1,_2,_3,_4,_5){return _3("dijit.tree.TreeStoreModel",null,{store:null,childrenAttrs:["children"],newItemIdAttr:"id",labelAttr:"",root:null,query:null,deferItemLoadingUntilExpand:false,constructor:function(_6){_5.mixin(this,_6);this.connects=[];var _7=this.store;if(!_7.getFeatures()["dojo.data.api.Identity"]){throw new Error("dijit.Tree: store must support dojo.data.Identity");}if(_7.getFeatures()["dojo.data.api.Notification"]){this.connects=this.connects.concat([_2.after(_7,"onNew",_5.hitch(this,"onNewItem"),true),_2.after(_7,"onDelete",_5.hitch(this,"onDeleteItem"),true),_2.after(_7,"onSet",_5.hitch(this,"onSetItem"),true)]);}},destroy:function(){var h;while(h=this.connects.pop()){h.remove();}},getRoot:function(_8,_9){if(this.root){_8(this.root);}else{this.store.fetch({query:this.query,onComplete:_5.hitch(this,function(_a){if(_a.length!=1){throw new Error(this.declaredClass+": query "+_4.stringify(this.query)+" returned "+_a.length+" items, but must return exactly one item");}this.root=_a[0];_8(this.root);}),onError:_9});}},mayHaveChildren:function(_b){return _1.some(this.childrenAttrs,function(_c){return this.store.hasAttribute(_b,_c);},this);},getChildren:function(_d,_e,_f){var _10=this.store;if(!_10.isItemLoaded(_d)){var _11=_5.hitch(this,arguments.callee);_10.loadItem({item:_d,onItem:function(_12){_11(_12,_e,_f);},onError:_f});return;}var _13=[];for(var i=0;i<this.childrenAttrs.length;i++){var _14=_10.getValues(_d,this.childrenAttrs[i]);_13=_13.concat(_14);}var _15=0;if(!this.deferItemLoadingUntilExpand){_1.forEach(_13,function(_16){if(!_10.isItemLoaded(_16)){_15++;}});}if(_15==0){_e(_13);}else{_1.forEach(_13,function(_17,idx){if(!_10.isItemLoaded(_17)){_10.loadItem({item:_17,onItem:function(_18){_13[idx]=_18;if(--_15==0){_e(_13);}},onError:_f});}});}},isItem:function(_19){return this.store.isItem(_19);},fetchItemByIdentity:function(_1a){this.store.fetchItemByIdentity(_1a);},getIdentity:function(_1b){return this.store.getIdentity(_1b);},getLabel:function(_1c){if(this.labelAttr){return this.store.getValue(_1c,this.labelAttr);}else{return this.store.getLabel(_1c);}},newItem:function(_1d,_1e,_1f){var _20={parent:_1e,attribute:this.childrenAttrs[0]},_21;if(this.newItemIdAttr&&_1d[this.newItemIdAttr]){this.fetchItemByIdentity({identity:_1d[this.newItemIdAttr],scope:this,onItem:function(_22){if(_22){this.pasteItem(_22,null,_1e,true,_1f);}else{_21=this.store.newItem(_1d,_20);if(_21&&(_1f!=undefined)){this.pasteItem(_21,_1e,_1e,false,_1f);}}}});}else{_21=this.store.newItem(_1d,_20);if(_21&&(_1f!=undefined)){this.pasteItem(_21,_1e,_1e,false,_1f);}}},pasteItem:function(_23,_24,_25,_26,_27){var _28=this.store,_29=this.childrenAttrs[0];if(_24){_1.forEach(this.childrenAttrs,function(_2a){if(_28.containsValue(_24,_2a,_23)){if(!_26){var _2b=_1.filter(_28.getValues(_24,_2a),function(x){return x!=_23;});_28.setValues(_24,_2a,_2b);}_29=_2a;}});}if(_25){if(typeof _27=="number"){var _2c=_28.getValues(_25,_29).slice();_2c.splice(_27,0,_23);_28.setValues(_25,_29,_2c);}else{_28.setValues(_25,_29,_28.getValues(_25,_29).concat(_23));}}},onChange:function(){},onChildrenChange:function(){},onDelete:function(){},onNewItem:function(_2d,_2e){if(!_2e){return;}this.getChildren(_2e.item,_5.hitch(this,function(_2f){this.onChildrenChange(_2e.item,_2f);}));},onDeleteItem:function(_30){this.onDelete(_30);},onSetItem:function(_31,_32){if(_1.indexOf(this.childrenAttrs,_32)!=-1){this.getChildren(_31,_5.hitch(this,function(_33){this.onChildrenChange(_31,_33);}));}else{this.onChange(_31);}}});});
|
||||
define("dijit/tree/TreeStoreModel",["dojo/_base/array","dojo/aspect","dojo/_base/declare","dojo/_base/lang"],function(_1,_2,_3,_4){return _3("dijit.tree.TreeStoreModel",null,{store:null,childrenAttrs:["children"],newItemIdAttr:"id",labelAttr:"",root:null,query:null,deferItemLoadingUntilExpand:false,constructor:function(_5){_4.mixin(this,_5);this.connects=[];var _6=this.store;if(!_6.getFeatures()["dojo.data.api.Identity"]){throw new Error("dijit.tree.TreeStoreModel: store must support dojo.data.Identity");}if(_6.getFeatures()["dojo.data.api.Notification"]){this.connects=this.connects.concat([_2.after(_6,"onNew",_4.hitch(this,"onNewItem"),true),_2.after(_6,"onDelete",_4.hitch(this,"onDeleteItem"),true),_2.after(_6,"onSet",_4.hitch(this,"onSetItem"),true)]);}},destroy:function(){var h;while(h=this.connects.pop()){h.remove();}},getRoot:function(_7,_8){if(this.root){_7(this.root);}else{this.store.fetch({query:this.query,onComplete:_4.hitch(this,function(_9){if(_9.length!=1){throw new Error("dijit.tree.TreeStoreModel: root query returned "+_9.length+" items, but must return exactly one");}this.root=_9[0];_7(this.root);}),onError:_8});}},mayHaveChildren:function(_a){return _1.some(this.childrenAttrs,function(_b){return this.store.hasAttribute(_a,_b);},this);},getChildren:function(_c,_d,_e){var _f=this.store;if(!_f.isItemLoaded(_c)){var _10=_4.hitch(this,arguments.callee);_f.loadItem({item:_c,onItem:function(_11){_10(_11,_d,_e);},onError:_e});return;}var _12=[];for(var i=0;i<this.childrenAttrs.length;i++){var _13=_f.getValues(_c,this.childrenAttrs[i]);_12=_12.concat(_13);}var _14=0;if(!this.deferItemLoadingUntilExpand){_1.forEach(_12,function(_15){if(!_f.isItemLoaded(_15)){_14++;}});}if(_14==0){_d(_12);}else{_1.forEach(_12,function(_16,idx){if(!_f.isItemLoaded(_16)){_f.loadItem({item:_16,onItem:function(_17){_12[idx]=_17;if(--_14==0){_d(_12);}},onError:_e});}});}},isItem:function(_18){return this.store.isItem(_18);},fetchItemByIdentity:function(_19){this.store.fetchItemByIdentity(_19);},getIdentity:function(_1a){return this.store.getIdentity(_1a);},getLabel:function(_1b){if(this.labelAttr){return this.store.getValue(_1b,this.labelAttr);}else{return this.store.getLabel(_1b);}},newItem:function(_1c,_1d,_1e){var _1f={parent:_1d,attribute:this.childrenAttrs[0]},_20;if(this.newItemIdAttr&&_1c[this.newItemIdAttr]){this.fetchItemByIdentity({identity:_1c[this.newItemIdAttr],scope:this,onItem:function(_21){if(_21){this.pasteItem(_21,null,_1d,true,_1e);}else{_20=this.store.newItem(_1c,_1f);if(_20&&(_1e!=undefined)){this.pasteItem(_20,_1d,_1d,false,_1e);}}}});}else{_20=this.store.newItem(_1c,_1f);if(_20&&(_1e!=undefined)){this.pasteItem(_20,_1d,_1d,false,_1e);}}},pasteItem:function(_22,_23,_24,_25,_26){var _27=this.store,_28=this.childrenAttrs[0];if(_23){_1.forEach(this.childrenAttrs,function(_29){if(_27.containsValue(_23,_29,_22)){if(!_25){var _2a=_1.filter(_27.getValues(_23,_29),function(x){return x!=_22;});_27.setValues(_23,_29,_2a);}_28=_29;}});}if(_24){if(typeof _26=="number"){var _2b=_27.getValues(_24,_28).slice();_2b.splice(_26,0,_22);_27.setValues(_24,_28,_2b);}else{_27.setValues(_24,_28,_27.getValues(_24,_28).concat(_22));}}},onChange:function(){},onChildrenChange:function(){},onDelete:function(){},onNewItem:function(_2c,_2d){if(!_2d){return;}this.getChildren(_2d.item,_4.hitch(this,function(_2e){this.onChildrenChange(_2d.item,_2e);}));},onDeleteItem:function(_2f){this.onDelete(_2f);},onSetItem:function(_30,_31){if(_1.indexOf(this.childrenAttrs,_31)!=-1){this.getChildren(_30,_4.hitch(this,function(_32){this.onChildrenChange(_30,_32);}));}else{this.onChange(_30);}}});});
|
||||
379
lib/dijit/tree/TreeStoreModel.js.uncompressed.js
Normal file
379
lib/dijit/tree/TreeStoreModel.js.uncompressed.js
Normal file
@@ -0,0 +1,379 @@
|
||||
define("dijit/tree/TreeStoreModel", [
|
||||
"dojo/_base/array", // array.filter array.forEach array.indexOf array.some
|
||||
"dojo/aspect", // aspect.after
|
||||
"dojo/_base/declare", // declare
|
||||
"dojo/_base/lang" // lang.hitch
|
||||
], function(array, aspect, declare, lang){
|
||||
|
||||
// module:
|
||||
// dijit/tree/TreeStoreModel
|
||||
|
||||
return declare("dijit.tree.TreeStoreModel", null, {
|
||||
// summary:
|
||||
// Implements dijit/Tree/model connecting to a dojo.data store with a single
|
||||
// root item. Any methods passed into the constructor will override
|
||||
// the ones defined here.
|
||||
|
||||
// store: dojo/data/api/Read
|
||||
// Underlying store
|
||||
store: null,
|
||||
|
||||
// childrenAttrs: String[]
|
||||
// One or more attribute names (attributes in the dojo.data item) that specify that item's children
|
||||
childrenAttrs: ["children"],
|
||||
|
||||
// newItemIdAttr: String
|
||||
// Name of attribute in the Object passed to newItem() that specifies the id.
|
||||
//
|
||||
// If newItemIdAttr is set then it's used when newItem() is called to see if an
|
||||
// item with the same id already exists, and if so just links to the old item
|
||||
// (so that the old item ends up with two parents).
|
||||
//
|
||||
// Setting this to null or "" will make every drop create a new item.
|
||||
newItemIdAttr: "id",
|
||||
|
||||
// labelAttr: String
|
||||
// If specified, get label for tree node from this attribute, rather
|
||||
// than by calling store.getLabel()
|
||||
labelAttr: "",
|
||||
|
||||
// root: [readonly] dojo/data/Item
|
||||
// Pointer to the root item (read only, not a parameter)
|
||||
root: null,
|
||||
|
||||
// query: anything
|
||||
// Specifies datastore query to return the root item for the tree.
|
||||
// Must only return a single item. Alternately can just pass in pointer
|
||||
// to root item.
|
||||
// example:
|
||||
// | {id:'ROOT'}
|
||||
query: null,
|
||||
|
||||
// deferItemLoadingUntilExpand: Boolean
|
||||
// Setting this to true will cause the TreeStoreModel to defer calling loadItem on nodes
|
||||
// until they are expanded. This allows for lazying loading where only one
|
||||
// loadItem (and generally one network call, consequently) per expansion
|
||||
// (rather than one for each child).
|
||||
// This relies on partial loading of the children items; each children item of a
|
||||
// fully loaded item should contain the label and info about having children.
|
||||
deferItemLoadingUntilExpand: false,
|
||||
|
||||
constructor: function(/* Object */ args){
|
||||
// summary:
|
||||
// Passed the arguments listed above (store, etc)
|
||||
// tags:
|
||||
// private
|
||||
|
||||
lang.mixin(this, args);
|
||||
|
||||
this.connects = [];
|
||||
|
||||
var store = this.store;
|
||||
if(!store.getFeatures()['dojo.data.api.Identity']){
|
||||
throw new Error("dijit.tree.TreeStoreModel: store must support dojo.data.Identity");
|
||||
}
|
||||
|
||||
// if the store supports Notification, subscribe to the notification events
|
||||
if(store.getFeatures()['dojo.data.api.Notification']){
|
||||
this.connects = this.connects.concat([
|
||||
aspect.after(store, "onNew", lang.hitch(this, "onNewItem"), true),
|
||||
aspect.after(store, "onDelete", lang.hitch(this, "onDeleteItem"), true),
|
||||
aspect.after(store, "onSet", lang.hitch(this, "onSetItem"), true)
|
||||
]);
|
||||
}
|
||||
},
|
||||
|
||||
destroy: function(){
|
||||
var h;
|
||||
while(h = this.connects.pop()){ h.remove(); }
|
||||
// TODO: should cancel any in-progress processing of getRoot(), getChildren()
|
||||
},
|
||||
|
||||
// =======================================================================
|
||||
// Methods for traversing hierarchy
|
||||
|
||||
getRoot: function(onItem, onError){
|
||||
// summary:
|
||||
// Calls onItem with the root item for the tree, possibly a fabricated item.
|
||||
// Calls onError on error.
|
||||
if(this.root){
|
||||
onItem(this.root);
|
||||
}else{
|
||||
this.store.fetch({
|
||||
query: this.query,
|
||||
onComplete: lang.hitch(this, function(items){
|
||||
if(items.length != 1){
|
||||
throw new Error("dijit.tree.TreeStoreModel: root query returned " + items.length +
|
||||
" items, but must return exactly one");
|
||||
}
|
||||
this.root = items[0];
|
||||
onItem(this.root);
|
||||
}),
|
||||
onError: onError
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
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)
|
||||
return array.some(this.childrenAttrs, function(attr){
|
||||
return this.store.hasAttribute(item, attr);
|
||||
}, this);
|
||||
},
|
||||
|
||||
getChildren: function(/*dojo/data/Item*/ parentItem, /*function(items)*/ onComplete, /*function*/ onError){
|
||||
// summary:
|
||||
// Calls onComplete() with array of child items of given parent item, all loaded.
|
||||
|
||||
var store = this.store;
|
||||
if(!store.isItemLoaded(parentItem)){
|
||||
// The parent is not loaded yet, we must be in deferItemLoadingUntilExpand
|
||||
// mode, so we will load it and just return the children (without loading each
|
||||
// child item)
|
||||
var getChildren = lang.hitch(this, arguments.callee);
|
||||
store.loadItem({
|
||||
item: parentItem,
|
||||
onItem: function(parentItem){
|
||||
getChildren(parentItem, onComplete, onError);
|
||||
},
|
||||
onError: onError
|
||||
});
|
||||
return;
|
||||
}
|
||||
// get children of specified item
|
||||
var childItems = [];
|
||||
for(var i=0; i<this.childrenAttrs.length; i++){
|
||||
var vals = store.getValues(parentItem, this.childrenAttrs[i]);
|
||||
childItems = childItems.concat(vals);
|
||||
}
|
||||
|
||||
// count how many items need to be loaded
|
||||
var _waitCount = 0;
|
||||
if(!this.deferItemLoadingUntilExpand){
|
||||
array.forEach(childItems, function(item){ if(!store.isItemLoaded(item)){ _waitCount++; } });
|
||||
}
|
||||
|
||||
if(_waitCount == 0){
|
||||
// all items are already loaded (or we aren't loading them). proceed...
|
||||
onComplete(childItems);
|
||||
}else{
|
||||
// still waiting for some or all of the items to load
|
||||
array.forEach(childItems, function(item, idx){
|
||||
if(!store.isItemLoaded(item)){
|
||||
store.loadItem({
|
||||
item: item,
|
||||
onItem: function(item){
|
||||
childItems[idx] = item;
|
||||
if(--_waitCount == 0){
|
||||
// all nodes have been loaded, send them to the tree
|
||||
onComplete(childItems);
|
||||
}
|
||||
},
|
||||
onError: onError
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// =======================================================================
|
||||
// Inspecting items
|
||||
|
||||
isItem: function(/* anything */ something){
|
||||
return this.store.isItem(something); // Boolean
|
||||
},
|
||||
|
||||
fetchItemByIdentity: function(/* object */ keywordArgs){
|
||||
this.store.fetchItemByIdentity(keywordArgs);
|
||||
},
|
||||
|
||||
getIdentity: function(/* item */ item){
|
||||
return this.store.getIdentity(item); // Object
|
||||
},
|
||||
|
||||
getLabel: function(/*dojo/data/Item*/ item){
|
||||
// summary:
|
||||
// Get the label for an item
|
||||
if(this.labelAttr){
|
||||
return this.store.getValue(item,this.labelAttr); // String
|
||||
}else{
|
||||
return this.store.getLabel(item); // String
|
||||
}
|
||||
},
|
||||
|
||||
// =======================================================================
|
||||
// Write interface
|
||||
|
||||
newItem: function(/* dijit/tree/dndSource.__Item */ args, /*dojo/data/api/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.
|
||||
// description:
|
||||
// Developers will need to override this method if new items get added
|
||||
// to parents with multiple children attributes, in order to define which
|
||||
// children attribute points to the new item.
|
||||
|
||||
var pInfo = {parent: parent, attribute: this.childrenAttrs[0]}, LnewItem;
|
||||
|
||||
if(this.newItemIdAttr && args[this.newItemIdAttr]){
|
||||
// Maybe there's already a corresponding item in the store; if so, reuse it.
|
||||
this.fetchItemByIdentity({identity: args[this.newItemIdAttr], scope: this, onItem: function(item){
|
||||
if(item){
|
||||
// There's already a matching item in store, use it
|
||||
this.pasteItem(item, null, parent, true, insertIndex);
|
||||
}else{
|
||||
// Create new item in the tree, based on the drag source.
|
||||
LnewItem=this.store.newItem(args, pInfo);
|
||||
if(LnewItem && (insertIndex!=undefined)){
|
||||
// Move new item to desired position
|
||||
this.pasteItem(LnewItem, parent, parent, false, insertIndex);
|
||||
}
|
||||
}
|
||||
}});
|
||||
}else{
|
||||
// [as far as we know] there is no id so we must assume this is a new item
|
||||
LnewItem=this.store.newItem(args, pInfo);
|
||||
if(LnewItem && (insertIndex!=undefined)){
|
||||
// Move new item to desired position
|
||||
this.pasteItem(LnewItem, parent, parent, false, insertIndex);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
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
|
||||
var store = this.store,
|
||||
parentAttr = this.childrenAttrs[0]; // name of "children" attr in parent item
|
||||
|
||||
// remove child from source item, and record the attribute that child occurred in
|
||||
if(oldParentItem){
|
||||
array.forEach(this.childrenAttrs, function(attr){
|
||||
if(store.containsValue(oldParentItem, attr, childItem)){
|
||||
if(!bCopy){
|
||||
var values = array.filter(store.getValues(oldParentItem, attr), function(x){
|
||||
return x != childItem;
|
||||
});
|
||||
store.setValues(oldParentItem, attr, values);
|
||||
}
|
||||
parentAttr = attr;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// modify target item's children attribute to include this item
|
||||
if(newParentItem){
|
||||
if(typeof insertIndex == "number"){
|
||||
// call slice() to avoid modifying the original array, confusing the data store
|
||||
var childItems = store.getValues(newParentItem, parentAttr).slice();
|
||||
childItems.splice(insertIndex, 0, childItem);
|
||||
store.setValues(newParentItem, parentAttr, childItems);
|
||||
}else{
|
||||
store.setValues(newParentItem, parentAttr,
|
||||
store.getValues(newParentItem, parentAttr).concat(childItem));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// =======================================================================
|
||||
// Callbacks
|
||||
|
||||
onChange: function(/*dojo/data/Item*/ /*===== item =====*/){
|
||||
// summary:
|
||||
// Callback whenever an item has changed, so that Tree
|
||||
// can update the label, icon, etc. Note that changes
|
||||
// to an item's children or parent(s) will trigger an
|
||||
// onChildrenChange() so you can ignore those changes here.
|
||||
// tags:
|
||||
// callback
|
||||
},
|
||||
|
||||
onChildrenChange: function(/*===== parent, newChildrenList =====*/){
|
||||
// summary:
|
||||
// Callback to do notifications about new, updated, or deleted items.
|
||||
// parent: dojo/data/Item
|
||||
// newChildrenList: dojo/data/Item[]
|
||||
// tags:
|
||||
// callback
|
||||
},
|
||||
|
||||
onDelete: function(/*dojo/data/Item*/ /*===== item =====*/){
|
||||
// summary:
|
||||
// Callback when an item has been deleted.
|
||||
// description:
|
||||
// Note that there will also be an onChildrenChange() callback for the parent
|
||||
// of this item.
|
||||
// tags:
|
||||
// callback
|
||||
},
|
||||
|
||||
// =======================================================================
|
||||
// Events from data store
|
||||
|
||||
onNewItem: function(/* dojo/data/Item */ item, /* Object */ parentInfo){
|
||||
// summary:
|
||||
// Handler for when new items appear in the store, either from a drop operation
|
||||
// or some other way. Updates the tree view (if necessary).
|
||||
// description:
|
||||
// If the new item is a child of an existing item,
|
||||
// calls onChildrenChange() with the new list of children
|
||||
// for that existing item.
|
||||
//
|
||||
// tags:
|
||||
// extension
|
||||
|
||||
// We only care about the new item if it has a parent that corresponds to a TreeNode
|
||||
// we are currently displaying
|
||||
if(!parentInfo){
|
||||
return;
|
||||
}
|
||||
|
||||
// Call onChildrenChange() on parent (ie, existing) item with new list of children
|
||||
// In the common case, the new list of children is simply parentInfo.newValue or
|
||||
// [ parentInfo.newValue ], although if items in the store has multiple
|
||||
// child attributes (see `childrenAttr`), then it's a superset of parentInfo.newValue,
|
||||
// so call getChildren() to be sure to get right answer.
|
||||
this.getChildren(parentInfo.item, lang.hitch(this, function(children){
|
||||
this.onChildrenChange(parentInfo.item, children);
|
||||
}));
|
||||
},
|
||||
|
||||
onDeleteItem: function(/*Object*/ item){
|
||||
// summary:
|
||||
// Handler for delete notifications from underlying store
|
||||
this.onDelete(item);
|
||||
},
|
||||
|
||||
onSetItem: function(item, attribute /*===== , oldValue, newValue =====*/){
|
||||
// summary:
|
||||
// Updates the tree view according to changes in the data store.
|
||||
// description:
|
||||
// Handles updates to an item's children by calling onChildrenChange(), and
|
||||
// other updates to an item by calling onChange().
|
||||
//
|
||||
// See `onNewItem` for more details on handling updates to an item's children.
|
||||
// item: Item
|
||||
// attribute: attribute-name-string
|
||||
// oldValue: Object|Array
|
||||
// newValue: Object|Array
|
||||
// tags:
|
||||
// extension
|
||||
|
||||
if(array.indexOf(this.childrenAttrs, attribute) != -1){
|
||||
// item's children list changed
|
||||
this.getChildren(item, lang.hitch(this, function(children){
|
||||
// See comments in onNewItem() about calling getChildren()
|
||||
this.onChildrenChange(item, children);
|
||||
}));
|
||||
}else{
|
||||
// item's label/icon/etc. changed.
|
||||
this.onChange(item);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,2 +1,2 @@
|
||||
//>>built
|
||||
define("dijit/tree/_dndContainer",["dojo/aspect","dojo/_base/declare","dojo/dom-class","dojo/_base/event","dojo/_base/lang","dojo/mouse","dojo/on"],function(_1,_2,_3,_4,_5,_6,on){return _2("dijit.tree._dndContainer",null,{constructor:function(_7,_8){this.tree=_7;this.node=_7.domNode;_5.mixin(this,_8);this.current=null;this.containerState="";_3.add(this.node,"dojoDndContainer");this.events=[on(this.node,_6.enter,_5.hitch(this,"onOverEvent")),on(this.node,_6.leave,_5.hitch(this,"onOutEvent")),_1.after(this.tree,"_onNodeMouseEnter",_5.hitch(this,"onMouseOver"),true),_1.after(this.tree,"_onNodeMouseLeave",_5.hitch(this,"onMouseOut"),true),on(this.node,"dragstart",_5.hitch(_4,"stop")),on(this.node,"selectstart",_5.hitch(_4,"stop"))];},destroy:function(){var h;while(h=this.events.pop()){h.remove();}this.node=this.parent=null;},onMouseOver:function(_9){this.current=_9;},onMouseOut:function(){this.current=null;},_changeState:function(_a,_b){var _c="dojoDnd"+_a;var _d=_a.toLowerCase()+"State";_3.replace(this.node,_c+_b,_c+this[_d]);this[_d]=_b;},_addItemClass:function(_e,_f){_3.add(_e,"dojoDndItem"+_f);},_removeItemClass:function(_10,_11){_3.remove(_10,"dojoDndItem"+_11);},onOverEvent:function(){this._changeState("Container","Over");},onOutEvent:function(){this._changeState("Container","");}});});
|
||||
define("dijit/tree/_dndContainer",["dojo/aspect","dojo/_base/declare","dojo/dom-class","dojo/_base/event","dojo/_base/lang","dojo/on","dojo/touch"],function(_1,_2,_3,_4,_5,on,_6){return _2("dijit.tree._dndContainer",null,{constructor:function(_7,_8){this.tree=_7;this.node=_7.domNode;_5.mixin(this,_8);this.current=null;this.containerState="";_3.add(this.node,"dojoDndContainer");this.events=[on(this.node,_6.enter,_5.hitch(this,"onOverEvent")),on(this.node,_6.leave,_5.hitch(this,"onOutEvent")),_1.after(this.tree,"_onNodeMouseEnter",_5.hitch(this,"onMouseOver"),true),_1.after(this.tree,"_onNodeMouseLeave",_5.hitch(this,"onMouseOut"),true),on(this.node,"dragstart",_5.hitch(_4,"stop")),on(this.node,"selectstart",_5.hitch(_4,"stop"))];},destroy:function(){var h;while(h=this.events.pop()){h.remove();}this.node=this.parent=null;},onMouseOver:function(_9){this.current=_9;},onMouseOut:function(){this.current=null;},_changeState:function(_a,_b){var _c="dojoDnd"+_a;var _d=_a.toLowerCase()+"State";_3.replace(this.node,_c+_b,_c+this[_d]);this[_d]=_b;},_addItemClass:function(_e,_f){_3.add(_e,"dojoDndItem"+_f);},_removeItemClass:function(_10,_11){_3.remove(_10,"dojoDndItem"+_11);},onOverEvent:function(){this._changeState("Container","Over");},onOutEvent:function(){this._changeState("Container","");}});});
|
||||
165
lib/dijit/tree/_dndContainer.js.uncompressed.js
Normal file
165
lib/dijit/tree/_dndContainer.js.uncompressed.js
Normal file
@@ -0,0 +1,165 @@
|
||||
define("dijit/tree/_dndContainer", [
|
||||
"dojo/aspect", // aspect.after
|
||||
"dojo/_base/declare", // declare
|
||||
"dojo/dom-class", // domClass.add domClass.remove domClass.replace
|
||||
"dojo/_base/event", // event.stop
|
||||
"dojo/_base/lang", // lang.mixin lang.hitch
|
||||
"dojo/on",
|
||||
"dojo/touch"
|
||||
], function(aspect, declare,domClass, event, lang, on, touch){
|
||||
|
||||
// module:
|
||||
// dijit/tree/_dndContainer
|
||||
|
||||
/*=====
|
||||
var __Args = {
|
||||
// summary:
|
||||
// A dict of parameters for Tree source configuration.
|
||||
// isSource: Boolean?
|
||||
// Can be used as a DnD source. Defaults to true.
|
||||
// accept: String[]
|
||||
// List of accepted types (text strings) for a target; defaults to
|
||||
// ["text", "treeNode"]
|
||||
// copyOnly: Boolean?
|
||||
// Copy items, if true, use a state of Ctrl key otherwise,
|
||||
// dragThreshold: Number
|
||||
// The move delay in pixels before detecting a drag; 0 by default
|
||||
// betweenThreshold: Integer
|
||||
// Distance from upper/lower edge of node to allow drop to reorder nodes
|
||||
};
|
||||
=====*/
|
||||
|
||||
return declare("dijit.tree._dndContainer", null, {
|
||||
|
||||
// summary:
|
||||
// This is a base class for `dijit/tree/_dndSelector`, and isn't meant to be used directly.
|
||||
// It's modeled after `dojo/dnd/Container`.
|
||||
// tags:
|
||||
// protected
|
||||
|
||||
/*=====
|
||||
// current: DomNode
|
||||
// The currently hovered TreeNode.rowNode (which is the DOM node
|
||||
// associated w/a given node in the tree, excluding it's descendants)
|
||||
current: null,
|
||||
=====*/
|
||||
|
||||
constructor: function(tree, params){
|
||||
// summary:
|
||||
// A constructor of the Container
|
||||
// tree: Node
|
||||
// Node or node's id to build the container on
|
||||
// params: __Args
|
||||
// A dict of parameters, which gets mixed into the object
|
||||
// tags:
|
||||
// private
|
||||
this.tree = tree;
|
||||
this.node = tree.domNode; // TODO: rename; it's not a TreeNode but the whole Tree
|
||||
lang.mixin(this, params);
|
||||
|
||||
// class-specific variables
|
||||
this.current = null; // current TreeNode's DOM node
|
||||
|
||||
// states
|
||||
this.containerState = "";
|
||||
domClass.add(this.node, "dojoDndContainer");
|
||||
|
||||
// set up events
|
||||
this.events = [
|
||||
// Mouse (or touch) enter/leave on Tree itself
|
||||
on(this.node, touch.enter, lang.hitch(this, "onOverEvent")),
|
||||
on(this.node, touch.leave, lang.hitch(this, "onOutEvent")),
|
||||
|
||||
// switching between TreeNodes
|
||||
aspect.after(this.tree, "_onNodeMouseEnter", lang.hitch(this, "onMouseOver"), true),
|
||||
aspect.after(this.tree, "_onNodeMouseLeave", lang.hitch(this, "onMouseOut"), true),
|
||||
|
||||
// cancel text selection and text dragging
|
||||
on(this.node, "dragstart", lang.hitch(event, "stop")),
|
||||
on(this.node, "selectstart", lang.hitch(event, "stop"))
|
||||
];
|
||||
},
|
||||
|
||||
destroy: function(){
|
||||
// summary:
|
||||
// Prepares this object to be garbage-collected
|
||||
|
||||
var h;
|
||||
while(h = this.events.pop()){ h.remove(); }
|
||||
|
||||
// this.clearItems();
|
||||
this.node = this.parent = null;
|
||||
},
|
||||
|
||||
// mouse events
|
||||
onMouseOver: function(widget /*===== , evt =====*/){
|
||||
// summary:
|
||||
// Called when mouse is moved over a TreeNode
|
||||
// widget: TreeNode
|
||||
// evt: Event
|
||||
// tags:
|
||||
// protected
|
||||
this.current = widget;
|
||||
},
|
||||
|
||||
onMouseOut: function(/*===== widget, evt =====*/){
|
||||
// summary:
|
||||
// Called when mouse is moved away from a TreeNode
|
||||
// widget: TreeNode
|
||||
// evt: Event
|
||||
// tags:
|
||||
// protected
|
||||
this.current = null;
|
||||
},
|
||||
|
||||
_changeState: function(type, newState){
|
||||
// summary:
|
||||
// Changes a named state to new state value
|
||||
// type: String
|
||||
// A name of the state to change
|
||||
// newState: String
|
||||
// new state
|
||||
var prefix = "dojoDnd" + type;
|
||||
var state = type.toLowerCase() + "State";
|
||||
//domClass.replace(this.node, prefix + newState, prefix + this[state]);
|
||||
domClass.replace(this.node, prefix + newState, prefix + this[state]);
|
||||
this[state] = newState;
|
||||
},
|
||||
|
||||
_addItemClass: function(node, type){
|
||||
// summary:
|
||||
// Adds a class with prefix "dojoDndItem"
|
||||
// node: Node
|
||||
// A node
|
||||
// type: String
|
||||
// A variable suffix for a class name
|
||||
domClass.add(node, "dojoDndItem" + type);
|
||||
},
|
||||
|
||||
_removeItemClass: function(node, type){
|
||||
// summary:
|
||||
// Removes a class with prefix "dojoDndItem"
|
||||
// node: Node
|
||||
// A node
|
||||
// type: String
|
||||
// A variable suffix for a class name
|
||||
domClass.remove(node, "dojoDndItem" + type);
|
||||
},
|
||||
|
||||
onOverEvent: function(){
|
||||
// summary:
|
||||
// This function is called once, when mouse is over our container
|
||||
// tags:
|
||||
// protected
|
||||
this._changeState("Container", "Over");
|
||||
},
|
||||
|
||||
onOutEvent: function(){
|
||||
// summary:
|
||||
// This function is called once, when mouse is out of our container
|
||||
// tags:
|
||||
// protected
|
||||
this._changeState("Container", "");
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,2 +1,2 @@
|
||||
//>>built
|
||||
define("dijit/tree/_dndSelector",["dojo/_base/array","dojo/_base/connect","dojo/_base/declare","dojo/_base/lang","dojo/mouse","dojo/on","dojo/touch","dojo/_base/window","./_dndContainer"],function(_1,_2,_3,_4,_5,on,_6,_7,_8){return _3("dijit.tree._dndSelector",_8,{constructor:function(){this.selection={};this.anchor=null;this.tree.domNode.setAttribute("aria-multiselect",!this.singular);this.events.push(on(this.tree.domNode,_6.press,_4.hitch(this,"onMouseDown")),on(this.tree.domNode,_6.release,_4.hitch(this,"onMouseUp")),on(this.tree.domNode,_6.move,_4.hitch(this,"onMouseMove")));},singular:false,getSelectedTreeNodes:function(){var _9=[],_a=this.selection;for(var i in _a){_9.push(_a[i]);}return _9;},selectNone:function(){this.setSelection([]);return this;},destroy:function(){this.inherited(arguments);this.selection=this.anchor=null;},addTreeNode:function(_b,_c){this.setSelection(this.getSelectedTreeNodes().concat([_b]));if(_c){this.anchor=_b;}return _b;},removeTreeNode:function(_d){this.setSelection(this._setDifference(this.getSelectedTreeNodes(),[_d]));return _d;},isTreeNodeSelected:function(_e){return _e.id&&!!this.selection[_e.id];},setSelection:function(_f){var _10=this.getSelectedTreeNodes();_1.forEach(this._setDifference(_10,_f),_4.hitch(this,function(_11){_11.setSelected(false);if(this.anchor==_11){delete this.anchor;}delete this.selection[_11.id];}));_1.forEach(this._setDifference(_f,_10),_4.hitch(this,function(_12){_12.setSelected(true);this.selection[_12.id]=_12;}));this._updateSelectionProperties();},_setDifference:function(xs,ys){_1.forEach(ys,function(y){y.__exclude__=true;});var ret=_1.filter(xs,function(x){return !x.__exclude__;});_1.forEach(ys,function(y){delete y["__exclude__"];});return ret;},_updateSelectionProperties:function(){var _13=this.getSelectedTreeNodes();var _14=[],_15=[];_1.forEach(_13,function(_16){_15.push(_16);_14.push(_16.getTreePath());});var _17=_1.map(_15,function(_18){return _18.item;});this.tree._set("paths",_14);this.tree._set("path",_14[0]||[]);this.tree._set("selectedNodes",_15);this.tree._set("selectedNode",_15[0]||null);this.tree._set("selectedItems",_17);this.tree._set("selectedItem",_17[0]||null);},onMouseDown:function(e){if(!this.current||this.tree.isExpandoNode(e.target,this.current)){return;}if(!_5.isLeft(e)){return;}e.preventDefault();var _19=this.current,_1a=_2.isCopyKey(e),id=_19.id;if(!this.singular&&!e.shiftKey&&this.selection[id]){this._doDeselect=true;return;}else{this._doDeselect=false;}this.userSelect(_19,_1a,e.shiftKey);},onMouseUp:function(e){if(!this._doDeselect){return;}this._doDeselect=false;this.userSelect(this.current,_2.isCopyKey(e),e.shiftKey);},onMouseMove:function(){this._doDeselect=false;},_compareNodes:function(n1,n2){if(n1===n2){return 0;}if("sourceIndex" in document.documentElement){return n1.sourceIndex-n2.sourceIndex;}else{if("compareDocumentPosition" in document.documentElement){return n1.compareDocumentPosition(n2)&2?1:-1;}else{if(document.createRange){var r1=doc.createRange();r1.setStartBefore(n1);var r2=doc.createRange();r2.setStartBefore(n2);return r1.compareBoundaryPoints(r1.END_TO_END,r2);}else{throw Error("dijit.tree._compareNodes don't know how to compare two different nodes in this browser");}}}},userSelect:function(_1b,_1c,_1d){if(this.singular){if(this.anchor==_1b&&_1c){this.selectNone();}else{this.setSelection([_1b]);this.anchor=_1b;}}else{if(_1d&&this.anchor){var cr=this._compareNodes(this.anchor.rowNode,_1b.rowNode),_1e,end,_1f=this.anchor;if(cr<0){_1e=_1f;end=_1b;}else{_1e=_1b;end=_1f;}var _20=[];while(_1e!=end){_20.push(_1e);_1e=this.tree._getNextNode(_1e);}_20.push(end);this.setSelection(_20);}else{if(this.selection[_1b.id]&&_1c){this.removeTreeNode(_1b);}else{if(_1c){this.addTreeNode(_1b,true);}else{this.setSelection([_1b]);this.anchor=_1b;}}}}},getItem:function(key){var _21=this.selection[key];return {data:_21,type:["treeNode"]};},forInSelectedItems:function(f,o){o=o||_7.global;for(var id in this.selection){f.call(o,this.getItem(id),id,this);}}});});
|
||||
define("dijit/tree/_dndSelector",["dojo/_base/array","dojo/_base/connect","dojo/_base/declare","dojo/_base/Deferred","dojo/_base/kernel","dojo/_base/lang","dojo/cookie","dojo/mouse","dojo/on","dojo/touch","./_dndContainer"],function(_1,_2,_3,_4,_5,_6,_7,_8,on,_9,_a){return _3("dijit.tree._dndSelector",_a,{constructor:function(){this.selection={};this.anchor=null;if(!this.cookieName&&this.tree.id){this.cookieName=this.tree.id+"SaveSelectedCookie";}this.events.push(on(this.tree.domNode,_9.press,_6.hitch(this,"onMouseDown")),on(this.tree.domNode,_9.release,_6.hitch(this,"onMouseUp")),on(this.tree.domNode,_9.move,_6.hitch(this,"onMouseMove")));},singular:false,getSelectedTreeNodes:function(){var _b=[],_c=this.selection;for(var i in _c){_b.push(_c[i]);}return _b;},selectNone:function(){this.setSelection([]);return this;},destroy:function(){this.inherited(arguments);this.selection=this.anchor=null;},addTreeNode:function(_d,_e){this.setSelection(this.getSelectedTreeNodes().concat([_d]));if(_e){this.anchor=_d;}return _d;},removeTreeNode:function(_f){this.setSelection(this._setDifference(this.getSelectedTreeNodes(),[_f]));return _f;},isTreeNodeSelected:function(_10){return _10.id&&!!this.selection[_10.id];},setSelection:function(_11){var _12=this.getSelectedTreeNodes();_1.forEach(this._setDifference(_12,_11),_6.hitch(this,function(_13){_13.setSelected(false);if(this.anchor==_13){delete this.anchor;}delete this.selection[_13.id];}));_1.forEach(this._setDifference(_11,_12),_6.hitch(this,function(_14){_14.setSelected(true);this.selection[_14.id]=_14;}));this._updateSelectionProperties();},_setDifference:function(xs,ys){_1.forEach(ys,function(y){y.__exclude__=true;});var ret=_1.filter(xs,function(x){return !x.__exclude__;});_1.forEach(ys,function(y){delete y["__exclude__"];});return ret;},_updateSelectionProperties:function(){var _15=this.getSelectedTreeNodes();var _16=[],_17=[],_18=[];_1.forEach(_15,function(_19){var ary=_19.getTreePath(),_1a=this.tree.model;_17.push(_19);_16.push(ary);ary=_1.map(ary,function(_1b){return _1a.getIdentity(_1b);},this);_18.push(ary.join("/"));},this);var _1c=_1.map(_17,function(_1d){return _1d.item;});this.tree._set("paths",_16);this.tree._set("path",_16[0]||[]);this.tree._set("selectedNodes",_17);this.tree._set("selectedNode",_17[0]||null);this.tree._set("selectedItems",_1c);this.tree._set("selectedItem",_1c[0]||null);if(this.tree.persist&&_18.length>0){_7(this.cookieName,_18.join(","),{expires:365});}},_getSavedPaths:function(){var _1e=this.tree;if(_1e.persist&&_1e.dndController.cookieName){var _1f,_20=[];_1f=_7(_1e.dndController.cookieName);if(_1f){_20=_1.map(_1f.split(","),function(_21){return _21.split("/");});}return _20;}},onMouseDown:function(e){if(!this.current||this.tree.isExpandoNode(e.target,this.current)){return;}if(_8.isLeft(e)){e.preventDefault();}else{if(e.type!="touchstart"){return;}}var _22=this.current,_23=_2.isCopyKey(e),id=_22.id;if(!this.singular&&!e.shiftKey&&this.selection[id]){this._doDeselect=true;return;}else{this._doDeselect=false;}this.userSelect(_22,_23,e.shiftKey);},onMouseUp:function(e){if(!this._doDeselect){return;}this._doDeselect=false;this.userSelect(this.current,_2.isCopyKey(e),e.shiftKey);},onMouseMove:function(){this._doDeselect=false;},_compareNodes:function(n1,n2){if(n1===n2){return 0;}if("sourceIndex" in document.documentElement){return n1.sourceIndex-n2.sourceIndex;}else{if("compareDocumentPosition" in document.documentElement){return n1.compareDocumentPosition(n2)&2?1:-1;}else{if(document.createRange){var r1=doc.createRange();r1.setStartBefore(n1);var r2=doc.createRange();r2.setStartBefore(n2);return r1.compareBoundaryPoints(r1.END_TO_END,r2);}else{throw Error("dijit.tree._compareNodes don't know how to compare two different nodes in this browser");}}}},userSelect:function(_24,_25,_26){if(this.singular){if(this.anchor==_24&&_25){this.selectNone();}else{this.setSelection([_24]);this.anchor=_24;}}else{if(_26&&this.anchor){var cr=this._compareNodes(this.anchor.rowNode,_24.rowNode),_27,end,_28=this.anchor;if(cr<0){_27=_28;end=_24;}else{_27=_24;end=_28;}var _29=[];while(_27!=end){_29.push(_27);_27=this.tree._getNextNode(_27);}_29.push(end);this.setSelection(_29);}else{if(this.selection[_24.id]&&_25){this.removeTreeNode(_24);}else{if(_25){this.addTreeNode(_24,true);}else{this.setSelection([_24]);this.anchor=_24;}}}}},getItem:function(key){var _2a=this.selection[key];return {data:_2a,type:["treeNode"]};},forInSelectedItems:function(f,o){o=o||_5.global;for(var id in this.selection){f.call(o,this.getItem(id),id,this);}}});});
|
||||
356
lib/dijit/tree/_dndSelector.js.uncompressed.js
Normal file
356
lib/dijit/tree/_dndSelector.js.uncompressed.js
Normal file
@@ -0,0 +1,356 @@
|
||||
define("dijit/tree/_dndSelector", [
|
||||
"dojo/_base/array", // array.filter array.forEach array.map
|
||||
"dojo/_base/connect", // connect.isCopyKey
|
||||
"dojo/_base/declare", // declare
|
||||
"dojo/_base/Deferred", // Deferred
|
||||
"dojo/_base/kernel", // global
|
||||
"dojo/_base/lang", // lang.hitch
|
||||
"dojo/cookie", // cookie
|
||||
"dojo/mouse", // mouse.isLeft
|
||||
"dojo/on",
|
||||
"dojo/touch",
|
||||
"./_dndContainer"
|
||||
], function(array, connect, declare, Deferred, kernel, lang, cookie, mouse, on, touch, _dndContainer){
|
||||
|
||||
// module:
|
||||
// dijit/tree/_dndSelector
|
||||
|
||||
|
||||
return declare("dijit.tree._dndSelector", _dndContainer, {
|
||||
// summary:
|
||||
// This is a base class for `dijit/tree/dndSource` , and isn't meant to be used directly.
|
||||
// It's based on `dojo/dnd/Selector`.
|
||||
// tags:
|
||||
// protected
|
||||
|
||||
/*=====
|
||||
// selection: Object
|
||||
// (id to DomNode) map for every TreeNode that's currently selected.
|
||||
// The DOMNode is the TreeNode.rowNode.
|
||||
selection: {},
|
||||
=====*/
|
||||
|
||||
constructor: function(){
|
||||
// summary:
|
||||
// Initialization
|
||||
// tags:
|
||||
// private
|
||||
|
||||
this.selection={};
|
||||
this.anchor = null;
|
||||
|
||||
if(!this.cookieName && this.tree.id){
|
||||
this.cookieName = this.tree.id + "SaveSelectedCookie";
|
||||
}
|
||||
|
||||
this.events.push(
|
||||
on(this.tree.domNode, touch.press, lang.hitch(this,"onMouseDown")),
|
||||
on(this.tree.domNode, touch.release, lang.hitch(this,"onMouseUp")),
|
||||
on(this.tree.domNode, touch.move, lang.hitch(this,"onMouseMove"))
|
||||
);
|
||||
},
|
||||
|
||||
// singular: Boolean
|
||||
// Allows selection of only one element, if true.
|
||||
// Tree hasn't been tested in singular=true mode, unclear if it works.
|
||||
singular: false,
|
||||
|
||||
// methods
|
||||
getSelectedTreeNodes: function(){
|
||||
// summary:
|
||||
// Returns a list of selected node(s).
|
||||
// Used by dndSource on the start of a drag.
|
||||
// tags:
|
||||
// protected
|
||||
var nodes=[], sel = this.selection;
|
||||
for(var i in sel){
|
||||
nodes.push(sel[i]);
|
||||
}
|
||||
return nodes;
|
||||
},
|
||||
|
||||
selectNone: function(){
|
||||
// summary:
|
||||
// Unselects all items
|
||||
// tags:
|
||||
// private
|
||||
|
||||
this.setSelection([]);
|
||||
return this; // self
|
||||
},
|
||||
|
||||
destroy: function(){
|
||||
// summary:
|
||||
// Prepares the object to be garbage-collected
|
||||
this.inherited(arguments);
|
||||
this.selection = this.anchor = null;
|
||||
},
|
||||
addTreeNode: function(/*dijit/Tree._TreeNode*/ node, /*Boolean?*/isAnchor){
|
||||
// summary:
|
||||
// add node to current selection
|
||||
// node: Node
|
||||
// node to add
|
||||
// isAnchor: Boolean
|
||||
// Whether the node should become anchor.
|
||||
|
||||
this.setSelection(this.getSelectedTreeNodes().concat( [node] ));
|
||||
if(isAnchor){ this.anchor = node; }
|
||||
return node;
|
||||
},
|
||||
removeTreeNode: function(/*dijit/Tree._TreeNode*/ node){
|
||||
// summary:
|
||||
// remove node from current selection
|
||||
// node: Node
|
||||
// node to remove
|
||||
this.setSelection(this._setDifference(this.getSelectedTreeNodes(), [node]));
|
||||
return node;
|
||||
},
|
||||
isTreeNodeSelected: function(/*dijit/Tree._TreeNode*/ node){
|
||||
// summary:
|
||||
// return true if node is currently selected
|
||||
// node: Node
|
||||
// the node to check whether it's in the current selection
|
||||
|
||||
return node.id && !!this.selection[node.id];
|
||||
},
|
||||
setSelection: function(/*dijit/Tree._TreeNode[]*/ newSelection){
|
||||
// summary:
|
||||
// set the list of selected nodes to be exactly newSelection. All changes to the
|
||||
// selection should be passed through this function, which ensures that derived
|
||||
// attributes are kept up to date. Anchor will be deleted if it has been removed
|
||||
// from the selection, but no new anchor will be added by this function.
|
||||
// newSelection: Node[]
|
||||
// list of tree nodes to make selected
|
||||
var oldSelection = this.getSelectedTreeNodes();
|
||||
array.forEach(this._setDifference(oldSelection, newSelection), lang.hitch(this, function(node){
|
||||
node.setSelected(false);
|
||||
if(this.anchor == node){
|
||||
delete this.anchor;
|
||||
}
|
||||
delete this.selection[node.id];
|
||||
}));
|
||||
array.forEach(this._setDifference(newSelection, oldSelection), lang.hitch(this, function(node){
|
||||
node.setSelected(true);
|
||||
this.selection[node.id] = node;
|
||||
}));
|
||||
this._updateSelectionProperties();
|
||||
},
|
||||
_setDifference: function(xs,ys){
|
||||
// summary:
|
||||
// Returns a copy of xs which lacks any objects
|
||||
// occurring in ys. Checks for membership by
|
||||
// modifying and then reading the object, so it will
|
||||
// not properly handle sets of numbers or strings.
|
||||
|
||||
array.forEach(ys, function(y){ y.__exclude__ = true; });
|
||||
var ret = array.filter(xs, function(x){ return !x.__exclude__; });
|
||||
|
||||
// clean up after ourselves.
|
||||
array.forEach(ys, function(y){ delete y['__exclude__'] });
|
||||
return ret;
|
||||
},
|
||||
_updateSelectionProperties: function(){
|
||||
// summary:
|
||||
// Update the following tree properties from the current selection:
|
||||
// path[s], selectedItem[s], selectedNode[s]
|
||||
|
||||
var selected = this.getSelectedTreeNodes();
|
||||
var paths = [], nodes = [], selects = [];
|
||||
array.forEach(selected, function(node){
|
||||
var ary = node.getTreePath(), model = this.tree.model;
|
||||
nodes.push(node);
|
||||
paths.push(ary);
|
||||
ary = array.map(ary, function(item){
|
||||
return model.getIdentity(item);
|
||||
}, this);
|
||||
selects.push(ary.join("/"))
|
||||
}, this);
|
||||
var items = array.map(nodes,function(node){ return node.item; });
|
||||
this.tree._set("paths", paths);
|
||||
this.tree._set("path", paths[0] || []);
|
||||
this.tree._set("selectedNodes", nodes);
|
||||
this.tree._set("selectedNode", nodes[0] || null);
|
||||
this.tree._set("selectedItems", items);
|
||||
this.tree._set("selectedItem", items[0] || null);
|
||||
if (this.tree.persist && selects.length > 0) {
|
||||
cookie(this.cookieName, selects.join(","), {expires:365});
|
||||
}
|
||||
},
|
||||
_getSavedPaths: function(){
|
||||
// summary:
|
||||
// Returns paths of nodes that were selected previously and saved in the cookie.
|
||||
|
||||
var tree = this.tree;
|
||||
if(tree.persist && tree.dndController.cookieName){
|
||||
var oreo, paths = [];
|
||||
oreo = cookie(tree.dndController.cookieName);
|
||||
if(oreo){
|
||||
paths = array.map(oreo.split(","), function(path){
|
||||
return path.split("/");
|
||||
})
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
},
|
||||
// mouse events
|
||||
onMouseDown: function(e){
|
||||
// summary:
|
||||
// Event processor for onmousedown/ontouchstart
|
||||
// e: Event
|
||||
// onmousedown/ontouchstart event
|
||||
// tags:
|
||||
// protected
|
||||
|
||||
// ignore click on expando node
|
||||
if(!this.current || this.tree.isExpandoNode(e.target, this.current)){ return; }
|
||||
|
||||
if(mouse.isLeft(e)){
|
||||
// Prevent text selection while dragging on desktop, see #16328. But don't call preventDefault()
|
||||
// for mobile because it will break things completely, see #15838.
|
||||
e.preventDefault();
|
||||
}else if(e.type != "touchstart"){
|
||||
// Ignore right click
|
||||
return;
|
||||
}
|
||||
|
||||
var treeNode = this.current,
|
||||
copy = connect.isCopyKey(e), id = treeNode.id;
|
||||
|
||||
// if shift key is not pressed, and the node is already in the selection,
|
||||
// delay deselection until onmouseup so in the case of DND, deselection
|
||||
// will be canceled by onmousemove.
|
||||
if(!this.singular && !e.shiftKey && this.selection[id]){
|
||||
this._doDeselect = true;
|
||||
return;
|
||||
}else{
|
||||
this._doDeselect = false;
|
||||
}
|
||||
this.userSelect(treeNode, copy, e.shiftKey);
|
||||
},
|
||||
|
||||
onMouseUp: function(e){
|
||||
// summary:
|
||||
// Event processor for onmouseup/ontouchend
|
||||
// e: Event
|
||||
// onmouseup/ontouchend event
|
||||
// tags:
|
||||
// protected
|
||||
|
||||
// _doDeselect is the flag to indicate that the user wants to either ctrl+click on
|
||||
// a already selected item (to deselect the item), or click on a not-yet selected item
|
||||
// (which should remove all current selection, and add the clicked item). This can not
|
||||
// be done in onMouseDown, because the user may start a drag after mousedown. By moving
|
||||
// the deselection logic here, the user can drags an already selected item.
|
||||
if(!this._doDeselect){ return; }
|
||||
this._doDeselect = false;
|
||||
this.userSelect(this.current, connect.isCopyKey(e), e.shiftKey);
|
||||
},
|
||||
onMouseMove: function(/*===== e =====*/){
|
||||
// summary:
|
||||
// event processor for onmousemove/ontouchmove
|
||||
// e: Event
|
||||
// onmousemove/ontouchmove event
|
||||
this._doDeselect = false;
|
||||
},
|
||||
|
||||
_compareNodes: function(n1, n2){
|
||||
if(n1 === n2){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if('sourceIndex' in document.documentElement){ //IE
|
||||
//TODO: does not yet work if n1 and/or n2 is a text node
|
||||
return n1.sourceIndex - n2.sourceIndex;
|
||||
}else if('compareDocumentPosition' in document.documentElement){ //FF, Opera
|
||||
return n1.compareDocumentPosition(n2) & 2 ? 1: -1;
|
||||
}else if(document.createRange){ //Webkit
|
||||
var r1 = doc.createRange();
|
||||
r1.setStartBefore(n1);
|
||||
|
||||
var r2 = doc.createRange();
|
||||
r2.setStartBefore(n2);
|
||||
|
||||
return r1.compareBoundaryPoints(r1.END_TO_END, r2);
|
||||
}else{
|
||||
throw Error("dijit.tree._compareNodes don't know how to compare two different nodes in this browser");
|
||||
}
|
||||
},
|
||||
|
||||
userSelect: function(node, multi, range){
|
||||
// summary:
|
||||
// Add or remove the given node from selection, responding
|
||||
// to a user action such as a click or keypress.
|
||||
// multi: Boolean
|
||||
// Indicates whether this is meant to be a multi-select action (e.g. ctrl-click)
|
||||
// range: Boolean
|
||||
// Indicates whether this is meant to be a ranged action (e.g. shift-click)
|
||||
// tags:
|
||||
// protected
|
||||
|
||||
if(this.singular){
|
||||
if(this.anchor == node && multi){
|
||||
this.selectNone();
|
||||
}else{
|
||||
this.setSelection([node]);
|
||||
this.anchor = node;
|
||||
}
|
||||
}else{
|
||||
if(range && this.anchor){
|
||||
var cr = this._compareNodes(this.anchor.rowNode, node.rowNode),
|
||||
begin, end, anchor = this.anchor;
|
||||
|
||||
if(cr < 0){ //current is after anchor
|
||||
begin = anchor;
|
||||
end = node;
|
||||
}else{ //current is before anchor
|
||||
begin = node;
|
||||
end = anchor;
|
||||
}
|
||||
var nodes = [];
|
||||
//add everything betweeen begin and end inclusively
|
||||
while(begin != end){
|
||||
nodes.push(begin);
|
||||
begin = this.tree._getNextNode(begin);
|
||||
}
|
||||
nodes.push(end);
|
||||
|
||||
this.setSelection(nodes);
|
||||
}else{
|
||||
if( this.selection[ node.id ] && multi ){
|
||||
this.removeTreeNode( node );
|
||||
}else if(multi){
|
||||
this.addTreeNode(node, true);
|
||||
}else{
|
||||
this.setSelection([node]);
|
||||
this.anchor = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
getItem: function(/*String*/ key){
|
||||
// summary:
|
||||
// Returns the dojo/dnd/Container._Item (representing a dragged node) by it's key (id).
|
||||
// Called by dojo/dnd/Source.checkAcceptance().
|
||||
// tags:
|
||||
// protected
|
||||
|
||||
var widget = this.selection[key];
|
||||
return {
|
||||
data: widget,
|
||||
type: ["treeNode"]
|
||||
}; // dojo/dnd/Container._Item
|
||||
},
|
||||
|
||||
forInSelectedItems: function(/*Function*/ f, /*Object?*/ o){
|
||||
// summary:
|
||||
// Iterates over selected items;
|
||||
// see `dojo/dnd/Container.forInItems()` for details
|
||||
o = o || kernel.global;
|
||||
for(var id in this.selection){
|
||||
// console.log("selected item id: " + id);
|
||||
f.call(o, this.getItem(id), id, this);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
File diff suppressed because one or more lines are too long
564
lib/dijit/tree/dndSource.js.uncompressed.js
Normal file
564
lib/dijit/tree/dndSource.js.uncompressed.js
Normal file
@@ -0,0 +1,564 @@
|
||||
define("dijit/tree/dndSource", [
|
||||
"dojo/_base/array", // array.forEach array.indexOf array.map
|
||||
"dojo/_base/connect", // isCopyKey
|
||||
"dojo/_base/declare", // declare
|
||||
"dojo/dom-class", // domClass.add
|
||||
"dojo/dom-geometry", // domGeometry.position
|
||||
"dojo/_base/lang", // lang.mixin lang.hitch
|
||||
"dojo/on", // subscribe
|
||||
"dojo/touch",
|
||||
"dojo/topic",
|
||||
"dojo/dnd/Manager", // DNDManager.manager
|
||||
"./_dndSelector"
|
||||
], function(array, connect, declare, domClass, domGeometry, lang, on, touch, topic, DNDManager, _dndSelector){
|
||||
|
||||
// module:
|
||||
// dijit/tree/dndSource
|
||||
// summary:
|
||||
// Handles drag and drop operations (as a source or a target) for `dijit.Tree`
|
||||
|
||||
/*=====
|
||||
var __Item = {
|
||||
// summary:
|
||||
// New item to be added to the Tree, like:
|
||||
// id: Anything
|
||||
id: "",
|
||||
// name: String
|
||||
name: ""
|
||||
};
|
||||
=====*/
|
||||
|
||||
var dndSource = declare("dijit.tree.dndSource", _dndSelector, {
|
||||
// summary:
|
||||
// Handles drag and drop operations (as a source or a target) for `dijit.Tree`
|
||||
|
||||
// isSource: Boolean
|
||||
// Can be used as a DnD source.
|
||||
isSource: true,
|
||||
|
||||
// accept: String[]
|
||||
// List of accepted types (text strings) for the Tree; defaults to
|
||||
// ["text"]
|
||||
accept: ["text", "treeNode"],
|
||||
|
||||
// copyOnly: [private] Boolean
|
||||
// Copy items, if true, use a state of Ctrl key otherwise
|
||||
copyOnly: false,
|
||||
|
||||
// dragThreshold: Number
|
||||
// The move delay in pixels before detecting a drag; 5 by default
|
||||
dragThreshold: 5,
|
||||
|
||||
// betweenThreshold: Integer
|
||||
// Distance from upper/lower edge of node to allow drop to reorder nodes
|
||||
betweenThreshold: 0,
|
||||
|
||||
// Flag used by Avatar.js to signal to generate text node when dragging
|
||||
generateText: true,
|
||||
|
||||
constructor: function(/*dijit/Tree*/ tree, /*dijit/tree/dndSource*/ params){
|
||||
// summary:
|
||||
// a constructor of the Tree DnD Source
|
||||
// tags:
|
||||
// private
|
||||
if(!params){ params = {}; }
|
||||
lang.mixin(this, params);
|
||||
var type = params.accept instanceof Array ? params.accept : ["text", "treeNode"];
|
||||
this.accept = null;
|
||||
if(type.length){
|
||||
this.accept = {};
|
||||
for(var i = 0; i < type.length; ++i){
|
||||
this.accept[type[i]] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// class-specific variables
|
||||
this.isDragging = false;
|
||||
this.mouseDown = false;
|
||||
this.targetAnchor = null; // DOMNode corresponding to the currently moused over TreeNode
|
||||
this.targetBox = null; // coordinates of this.targetAnchor
|
||||
this.dropPosition = ""; // whether mouse is over/after/before this.targetAnchor
|
||||
this._lastX = 0;
|
||||
this._lastY = 0;
|
||||
|
||||
// states
|
||||
this.sourceState = "";
|
||||
if(this.isSource){
|
||||
domClass.add(this.node, "dojoDndSource");
|
||||
}
|
||||
this.targetState = "";
|
||||
if(this.accept){
|
||||
domClass.add(this.node, "dojoDndTarget");
|
||||
}
|
||||
|
||||
// set up events
|
||||
this.topics = [
|
||||
topic.subscribe("/dnd/source/over", lang.hitch(this, "onDndSourceOver")),
|
||||
topic.subscribe("/dnd/start", lang.hitch(this, "onDndStart")),
|
||||
topic.subscribe("/dnd/drop", lang.hitch(this, "onDndDrop")),
|
||||
topic.subscribe("/dnd/cancel", lang.hitch(this, "onDndCancel"))
|
||||
];
|
||||
},
|
||||
|
||||
// methods
|
||||
checkAcceptance: function(/*===== source, nodes =====*/){
|
||||
// summary:
|
||||
// Checks if the target can accept nodes from this source
|
||||
// source: dijit/tree/dndSource
|
||||
// The source which provides items
|
||||
// nodes: DOMNode[]
|
||||
// Array of DOM nodes corresponding to nodes being dropped, dijitTreeRow nodes if
|
||||
// source is a dijit/Tree.
|
||||
// tags:
|
||||
// extension
|
||||
return true; // Boolean
|
||||
},
|
||||
|
||||
copyState: function(keyPressed){
|
||||
// summary:
|
||||
// Returns true, if we need to copy items, false to move.
|
||||
// It is separated to be overwritten dynamically, if needed.
|
||||
// keyPressed: Boolean
|
||||
// The "copy" control key was pressed
|
||||
// tags:
|
||||
// protected
|
||||
return this.copyOnly || keyPressed; // Boolean
|
||||
},
|
||||
destroy: function(){
|
||||
// summary:
|
||||
// Prepares the object to be garbage-collected.
|
||||
this.inherited(arguments);
|
||||
var h;
|
||||
while(h = this.topics.pop()){ h.remove(); }
|
||||
this.targetAnchor = null;
|
||||
},
|
||||
|
||||
_onDragMouse: function(e, firstTime){
|
||||
// summary:
|
||||
// Helper method for processing onmousemove/onmouseover events while drag is in progress.
|
||||
// Keeps track of current drop target.
|
||||
// e: Event
|
||||
// The mousemove event.
|
||||
// firstTime: Boolean?
|
||||
// If this flag is set, this is the first mouse move event of the drag, so call m.canDrop() etc.
|
||||
// even if newTarget == null because the user quickly dragged a node in the Tree to a position
|
||||
// over Tree.containerNode but not over any TreeNode (#7971)
|
||||
|
||||
var m = DNDManager.manager(),
|
||||
oldTarget = this.targetAnchor, // the TreeNode corresponding to TreeNode mouse was previously over
|
||||
newTarget = this.current, // TreeNode corresponding to TreeNode mouse is currently over
|
||||
oldDropPosition = this.dropPosition; // the previous drop position (over/before/after)
|
||||
|
||||
// calculate if user is indicating to drop the dragged node before, after, or over
|
||||
// (i.e., to become a child of) the target node
|
||||
var newDropPosition = "Over";
|
||||
if(newTarget && this.betweenThreshold > 0){
|
||||
// If mouse is over a new TreeNode, then get new TreeNode's position and size
|
||||
if(!this.targetBox || oldTarget != newTarget){
|
||||
this.targetBox = domGeometry.position(newTarget.rowNode, true);
|
||||
}
|
||||
if((e.pageY - this.targetBox.y) <= this.betweenThreshold){
|
||||
newDropPosition = "Before";
|
||||
}else if((e.pageY - this.targetBox.y) >= (this.targetBox.h - this.betweenThreshold)){
|
||||
newDropPosition = "After";
|
||||
}
|
||||
}
|
||||
|
||||
if(firstTime || newTarget != oldTarget || newDropPosition != oldDropPosition){
|
||||
if(oldTarget){
|
||||
this._removeItemClass(oldTarget.rowNode, oldDropPosition);
|
||||
}
|
||||
if(newTarget){
|
||||
this._addItemClass(newTarget.rowNode, newDropPosition);
|
||||
}
|
||||
|
||||
// Check if it's ok to drop the dragged node on/before/after the target node.
|
||||
if(!newTarget){
|
||||
m.canDrop(false);
|
||||
}else if(newTarget == this.tree.rootNode && newDropPosition != "Over"){
|
||||
// Can't drop before or after tree's root node; the dropped node would just disappear (at least visually)
|
||||
m.canDrop(false);
|
||||
}else{
|
||||
// Guard against dropping onto yourself (TODO: guard against dropping onto your descendant, #7140)
|
||||
var sameId = false;
|
||||
if(m.source == this){
|
||||
for(var dragId in this.selection){
|
||||
var dragNode = this.selection[dragId];
|
||||
if(dragNode.item === newTarget.item){
|
||||
sameId = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(sameId){
|
||||
m.canDrop(false);
|
||||
}else if(this.checkItemAcceptance(newTarget.rowNode, m.source, newDropPosition.toLowerCase())
|
||||
&& !this._isParentChildDrop(m.source, newTarget.rowNode)){
|
||||
m.canDrop(true);
|
||||
}else{
|
||||
m.canDrop(false);
|
||||
}
|
||||
}
|
||||
|
||||
this.targetAnchor = newTarget;
|
||||
this.dropPosition = newDropPosition;
|
||||
}
|
||||
},
|
||||
|
||||
onMouseMove: function(e){
|
||||
// summary:
|
||||
// Called for any onmousemove/ontouchmove events over the Tree
|
||||
// e: Event
|
||||
// onmousemouse/ontouchmove event
|
||||
// tags:
|
||||
// private
|
||||
if(this.isDragging && this.targetState == "Disabled"){ return; }
|
||||
this.inherited(arguments);
|
||||
var m = DNDManager.manager();
|
||||
if(this.isDragging){
|
||||
this._onDragMouse(e);
|
||||
}else{
|
||||
if(this.mouseDown && this.isSource &&
|
||||
(Math.abs(e.pageX-this._lastX)>=this.dragThreshold || Math.abs(e.pageY-this._lastY)>=this.dragThreshold)){
|
||||
var nodes = this.getSelectedTreeNodes();
|
||||
if(nodes.length){
|
||||
if(nodes.length > 1){
|
||||
//filter out all selected items which has one of their ancestor selected as well
|
||||
var seen = this.selection, i = 0, r = [], n, p;
|
||||
nextitem: while((n = nodes[i++])){
|
||||
for(p = n.getParent(); p && p !== this.tree; p = p.getParent()){
|
||||
if(seen[p.id]){ //parent is already selected, skip this node
|
||||
continue nextitem;
|
||||
}
|
||||
}
|
||||
//this node does not have any ancestors selected, add it
|
||||
r.push(n);
|
||||
}
|
||||
nodes = r;
|
||||
}
|
||||
nodes = array.map(nodes, function(n){return n.domNode});
|
||||
m.startDrag(this, nodes, this.copyState(connect.isCopyKey(e)));
|
||||
this._onDragMouse(e, true); // because this may be the only mousemove event we get before the drop
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onMouseDown: function(e){
|
||||
// summary:
|
||||
// Event processor for onmousedown/ontouchstart
|
||||
// e: Event
|
||||
// onmousedown/ontouchend event
|
||||
// tags:
|
||||
// private
|
||||
this.mouseDown = true;
|
||||
this.mouseButton = e.button;
|
||||
this._lastX = e.pageX;
|
||||
this._lastY = e.pageY;
|
||||
this.inherited(arguments);
|
||||
},
|
||||
|
||||
onMouseUp: function(e){
|
||||
// summary:
|
||||
// Event processor for onmouseup/ontouchend
|
||||
// e: Event
|
||||
// onmouseup/ontouchend event
|
||||
// tags:
|
||||
// private
|
||||
if(this.mouseDown){
|
||||
this.mouseDown = false;
|
||||
this.inherited(arguments);
|
||||
}
|
||||
},
|
||||
|
||||
onMouseOut: function(){
|
||||
// summary:
|
||||
// Event processor for when mouse is moved away from a TreeNode
|
||||
// tags:
|
||||
// private
|
||||
this.inherited(arguments);
|
||||
this._unmarkTargetAnchor();
|
||||
},
|
||||
|
||||
checkItemAcceptance: function(/*===== target, source, position =====*/){
|
||||
// summary:
|
||||
// Stub function to be overridden if one wants to check for the ability to drop at the node/item level
|
||||
// description:
|
||||
// In the base case, this is called to check if target can become a child of source.
|
||||
// When betweenThreshold is set, position="before" or "after" means that we
|
||||
// are asking if the source node can be dropped before/after the target node.
|
||||
// target: DOMNode
|
||||
// The dijitTreeRoot DOM node inside of the TreeNode that we are dropping on to
|
||||
// Use dijit.getEnclosingWidget(target) to get the TreeNode.
|
||||
// source: dijit/tree/dndSource
|
||||
// The (set of) nodes we are dropping
|
||||
// position: String
|
||||
// "over", "before", or "after"
|
||||
// tags:
|
||||
// extension
|
||||
return true;
|
||||
},
|
||||
|
||||
// topic event processors
|
||||
onDndSourceOver: function(source){
|
||||
// summary:
|
||||
// Topic event processor for /dnd/source/over, called when detected a current source.
|
||||
// source: Object
|
||||
// The dijit/tree/dndSource / dojo/dnd/Source which has the mouse over it
|
||||
// tags:
|
||||
// private
|
||||
if(this != source){
|
||||
this.mouseDown = false;
|
||||
this._unmarkTargetAnchor();
|
||||
}else if(this.isDragging){
|
||||
var m = DNDManager.manager();
|
||||
m.canDrop(false);
|
||||
}
|
||||
},
|
||||
onDndStart: function(source, nodes, copy){
|
||||
// summary:
|
||||
// Topic event processor for /dnd/start, called to initiate the DnD operation
|
||||
// source: Object
|
||||
// The dijit/tree/dndSource / dojo/dnd/Source which is providing the items
|
||||
// nodes: DomNode[]
|
||||
// The list of transferred items, dndTreeNode nodes if dragging from a Tree
|
||||
// copy: Boolean
|
||||
// Copy items, if true, move items otherwise
|
||||
// tags:
|
||||
// private
|
||||
|
||||
if(this.isSource){
|
||||
this._changeState("Source", this == source ? (copy ? "Copied" : "Moved") : "");
|
||||
}
|
||||
var accepted = this.checkAcceptance(source, nodes);
|
||||
|
||||
this._changeState("Target", accepted ? "" : "Disabled");
|
||||
|
||||
if(this == source){
|
||||
DNDManager.manager().overSource(this);
|
||||
}
|
||||
|
||||
this.isDragging = true;
|
||||
},
|
||||
|
||||
itemCreator: function(nodes /*===== , target, source =====*/){
|
||||
// summary:
|
||||
// Returns objects passed to `Tree.model.newItem()` based on DnD nodes
|
||||
// dropped onto the tree. Developer must override this method to enable
|
||||
// dropping from external sources onto this Tree, unless the Tree.model's items
|
||||
// happen to look like {id: 123, name: "Apple" } with no other attributes.
|
||||
// description:
|
||||
// For each node in nodes[], which came from source, create a hash of name/value
|
||||
// pairs to be passed to Tree.model.newItem(). Returns array of those hashes.
|
||||
// nodes: DomNode[]
|
||||
// target: DomNode
|
||||
// source: dojo/dnd/Source
|
||||
// returns: __Item[]
|
||||
// Array of name/value hashes for each new item to be added to the Tree
|
||||
// tags:
|
||||
// extension
|
||||
|
||||
// TODO: for 2.0 refactor so itemCreator() is called once per drag node, and
|
||||
// make signature itemCreator(sourceItem, node, target) (or similar).
|
||||
|
||||
return array.map(nodes, function(node){
|
||||
return {
|
||||
"id": node.id,
|
||||
"name": node.textContent || node.innerText || ""
|
||||
};
|
||||
}); // Object[]
|
||||
},
|
||||
|
||||
onDndDrop: function(source, nodes, copy){
|
||||
// summary:
|
||||
// Topic event processor for /dnd/drop, called to finish the DnD operation.
|
||||
// description:
|
||||
// Updates data store items according to where node was dragged from and dropped
|
||||
// to. The tree will then respond to those data store updates and redraw itself.
|
||||
// source: Object
|
||||
// The dijit/tree/dndSource / dojo/dnd/Source which is providing the items
|
||||
// nodes: DomNode[]
|
||||
// The list of transferred items, dndTreeNode nodes if dragging from a Tree
|
||||
// copy: Boolean
|
||||
// Copy items, if true, move items otherwise
|
||||
// tags:
|
||||
// protected
|
||||
if(this.containerState == "Over"){
|
||||
var tree = this.tree,
|
||||
model = tree.model,
|
||||
target = this.targetAnchor;
|
||||
|
||||
this.isDragging = false;
|
||||
|
||||
// Compute the new parent item
|
||||
var newParentItem;
|
||||
var insertIndex;
|
||||
var before; // drop source before (aka previous sibling) of target
|
||||
newParentItem = (target && target.item) || tree.item;
|
||||
if(this.dropPosition == "Before" || this.dropPosition == "After"){
|
||||
// TODO: if there is no parent item then disallow the drop.
|
||||
// Actually this should be checked during onMouseMove too, to make the drag icon red.
|
||||
newParentItem = (target.getParent() && target.getParent().item) || tree.item;
|
||||
// Compute the insert index for reordering
|
||||
insertIndex = target.getIndexInParent();
|
||||
if(this.dropPosition == "After"){
|
||||
insertIndex = target.getIndexInParent() + 1;
|
||||
before = target.getNextSibling() && target.getNextSibling().item;
|
||||
}else{
|
||||
before = target.item;
|
||||
}
|
||||
}else{
|
||||
newParentItem = (target && target.item) || tree.item;
|
||||
}
|
||||
|
||||
// If necessary, use this variable to hold array of hashes to pass to model.newItem()
|
||||
// (one entry in the array for each dragged node).
|
||||
var newItemsParams;
|
||||
|
||||
array.forEach(nodes, function(node, idx){
|
||||
// dojo/dnd/Item representing the thing being dropped.
|
||||
// Don't confuse the use of item here (meaning a DnD item) with the
|
||||
// uses below where item means dojo.data item.
|
||||
var sourceItem = source.getItem(node.id);
|
||||
|
||||
// Information that's available if the source is another Tree
|
||||
// (possibly but not necessarily this tree, possibly but not
|
||||
// necessarily the same model as this Tree)
|
||||
if(array.indexOf(sourceItem.type, "treeNode") != -1){
|
||||
var childTreeNode = sourceItem.data,
|
||||
childItem = childTreeNode.item,
|
||||
oldParentItem = childTreeNode.getParent().item;
|
||||
}
|
||||
|
||||
if(source == this){
|
||||
// This is a node from my own tree, and we are moving it, not copying.
|
||||
// Remove item from old parent's children attribute.
|
||||
// TODO: dijit/tree/dndSelector should implement deleteSelectedNodes()
|
||||
// and this code should go there.
|
||||
|
||||
if(typeof insertIndex == "number"){
|
||||
if(newParentItem == oldParentItem && childTreeNode.getIndexInParent() < insertIndex){
|
||||
insertIndex -= 1;
|
||||
}
|
||||
}
|
||||
model.pasteItem(childItem, oldParentItem, newParentItem, copy, insertIndex, before);
|
||||
}else if(model.isItem(childItem)){
|
||||
// Item from same model
|
||||
// (maybe we should only do this branch if the source is a tree?)
|
||||
model.pasteItem(childItem, oldParentItem, newParentItem, copy, insertIndex, before);
|
||||
}else{
|
||||
// Get the hash to pass to model.newItem(). A single call to
|
||||
// itemCreator() returns an array of hashes, one for each drag source node.
|
||||
if(!newItemsParams){
|
||||
newItemsParams = this.itemCreator(nodes, target.rowNode, source);
|
||||
}
|
||||
|
||||
// Create new item in the tree, based on the drag source.
|
||||
model.newItem(newItemsParams[idx], newParentItem, insertIndex, before);
|
||||
}
|
||||
}, this);
|
||||
|
||||
// Expand the target node (if it's currently collapsed) so the user can see
|
||||
// where their node was dropped. In particular since that node is still selected.
|
||||
this.tree._expandNode(target);
|
||||
}
|
||||
this.onDndCancel();
|
||||
},
|
||||
|
||||
onDndCancel: function(){
|
||||
// summary:
|
||||
// Topic event processor for /dnd/cancel, called to cancel the DnD operation
|
||||
// tags:
|
||||
// private
|
||||
this._unmarkTargetAnchor();
|
||||
this.isDragging = false;
|
||||
this.mouseDown = false;
|
||||
delete this.mouseButton;
|
||||
this._changeState("Source", "");
|
||||
this._changeState("Target", "");
|
||||
},
|
||||
|
||||
// When focus moves in/out of the entire Tree
|
||||
onOverEvent: function(){
|
||||
// summary:
|
||||
// This method is called when mouse is moved over our container (like onmouseenter)
|
||||
// tags:
|
||||
// private
|
||||
this.inherited(arguments);
|
||||
DNDManager.manager().overSource(this);
|
||||
},
|
||||
onOutEvent: function(){
|
||||
// summary:
|
||||
// This method is called when mouse is moved out of our container (like onmouseleave)
|
||||
// tags:
|
||||
// private
|
||||
this._unmarkTargetAnchor();
|
||||
var m = DNDManager.manager();
|
||||
if(this.isDragging){
|
||||
m.canDrop(false);
|
||||
}
|
||||
m.outSource(this);
|
||||
|
||||
this.inherited(arguments);
|
||||
},
|
||||
|
||||
_isParentChildDrop: function(source, targetRow){
|
||||
// summary:
|
||||
// Checks whether the dragged items are parent rows in the tree which are being
|
||||
// dragged into their own children.
|
||||
//
|
||||
// source:
|
||||
// The DragSource object.
|
||||
//
|
||||
// targetRow:
|
||||
// The tree row onto which the dragged nodes are being dropped.
|
||||
//
|
||||
// tags:
|
||||
// private
|
||||
|
||||
// If the dragged object is not coming from the tree this widget belongs to,
|
||||
// it cannot be invalid.
|
||||
if(!source.tree || source.tree != this.tree){
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
var root = source.tree.domNode;
|
||||
var ids = source.selection;
|
||||
|
||||
var node = targetRow.parentNode;
|
||||
|
||||
// Iterate up the DOM hierarchy from the target drop row,
|
||||
// checking of any of the dragged nodes have the same ID.
|
||||
while(node != root && !ids[node.id]){
|
||||
node = node.parentNode;
|
||||
}
|
||||
|
||||
return node.id && ids[node.id];
|
||||
},
|
||||
|
||||
_unmarkTargetAnchor: function(){
|
||||
// summary:
|
||||
// Removes hover class of the current target anchor
|
||||
// tags:
|
||||
// private
|
||||
if(!this.targetAnchor){ return; }
|
||||
this._removeItemClass(this.targetAnchor.rowNode, this.dropPosition);
|
||||
this.targetAnchor = null;
|
||||
this.targetBox = null;
|
||||
this.dropPosition = null;
|
||||
},
|
||||
|
||||
_markDndStatus: function(copy){
|
||||
// summary:
|
||||
// Changes source's state based on "copy" status
|
||||
this._changeState("Source", copy ? "Copied" : "Moved");
|
||||
}
|
||||
});
|
||||
|
||||
/*=====
|
||||
dndSource.__Item = __Item;
|
||||
=====*/
|
||||
|
||||
return dndSource;
|
||||
});
|
||||
@@ -1 +1,2 @@
|
||||
//>>built
|
||||
define("dijit/tree/model",["dojo/_base/declare"],function(_1){return _1("dijit.tree.model",null,{destroy:function(){},getRoot:function(_2){},mayHaveChildren:function(_3){},getChildren:function(_4,_5){},isItem:function(_6){},fetchItemByIdentity:function(_7){},getIdentity:function(_8){},getLabel:function(_9){},newItem:function(_a,_b,_c,_d){},pasteItem:function(_e,_f,_10,_11,_12,_13){},onChange:function(_14){},onChildrenChange:function(_15,_16){}});});
|
||||
150
lib/dijit/tree/model.js.uncompressed.js
Normal file
150
lib/dijit/tree/model.js.uncompressed.js
Normal file
@@ -0,0 +1,150 @@
|
||||
define("dijit/tree/model", ["dojo/_base/declare"], function(declare){
|
||||
|
||||
return declare(
|
||||
"dijit.tree.model",
|
||||
null,
|
||||
{
|
||||
// summary:
|
||||
// Contract for any data provider object for the tree.
|
||||
// description:
|
||||
// Tree passes in values to the constructor to specify the callbacks.
|
||||
// "item" is typically a dojo/data/Item but it's just a black box so
|
||||
// it could be anything.
|
||||
//
|
||||
// This (like `dojo/data/api/Read`) is just documentation, and not meant to be used.
|
||||
|
||||
destroy: function(){
|
||||
// summary:
|
||||
// Destroys this object, releasing connections to the store
|
||||
// tags:
|
||||
// extension
|
||||
},
|
||||
|
||||
// =======================================================================
|
||||
// Methods for traversing hierarchy
|
||||
|
||||
getRoot: function(onItem){
|
||||
// summary:
|
||||
// Calls onItem with the root item for the tree, possibly a fabricated item.
|
||||
// Throws exception on error.
|
||||
// tags:
|
||||
// extension
|
||||
},
|
||||
|
||||
mayHaveChildren: function(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)
|
||||
// item: dojo/data/Item
|
||||
// tags:
|
||||
// extension
|
||||
},
|
||||
|
||||
getChildren: function(parentItem, onComplete){
|
||||
// summary:
|
||||
// Calls onComplete() with array of child items of given parent item, all loaded.
|
||||
// Throws exception on error.
|
||||
// parentItem: dojo/data/Item
|
||||
// onComplete: function(items)
|
||||
// tags:
|
||||
// extension
|
||||
},
|
||||
|
||||
// =======================================================================
|
||||
// Inspecting items
|
||||
|
||||
isItem: function(something){
|
||||
// summary:
|
||||
// Returns true if *something* is an item and came from this model instance.
|
||||
// Returns false if *something* is a literal, an item from another model instance,
|
||||
// or is any object other than an item.
|
||||
// tags:
|
||||
// extension
|
||||
},
|
||||
|
||||
fetchItemByIdentity: function(keywordArgs){
|
||||
// summary:
|
||||
// Given the identity of an item, this method returns the item that has
|
||||
// that identity through the onItem callback. Conforming implementations
|
||||
// should return null if there is no item with the given identity.
|
||||
// Implementations of fetchItemByIdentity() may sometimes return an item
|
||||
// from a local cache and may sometimes fetch an item from a remote server.
|
||||
// tags:
|
||||
// extension
|
||||
},
|
||||
|
||||
getIdentity: function(item){
|
||||
// summary:
|
||||
// Returns identity for an item
|
||||
// tags:
|
||||
// extension
|
||||
},
|
||||
|
||||
getLabel: function(item){
|
||||
// summary:
|
||||
// Get the label for an item
|
||||
// tags:
|
||||
// extension
|
||||
},
|
||||
|
||||
// =======================================================================
|
||||
// Write interface
|
||||
|
||||
newItem: function(args, parent, insertIndex, before){
|
||||
// summary:
|
||||
// Creates a new item. See `dojo/data/api/Write` for details on args.
|
||||
// args: dijit/tree/dndSource.__Item
|
||||
// parent: Item
|
||||
// insertIndex: int?
|
||||
// Allows to insert the new item as the n'th child of `parent`.
|
||||
// before: Item?
|
||||
// Insert the new item as the previous sibling of this item. `before` must be a child of `parent`.
|
||||
// tags:
|
||||
// extension
|
||||
},
|
||||
|
||||
pasteItem: function(childItem, oldParentItem, newParentItem, bCopy, insertIndex, before){
|
||||
// summary:
|
||||
// Move or copy an item from one parent item to another.
|
||||
// Used in drag & drop.
|
||||
// If oldParentItem is specified and bCopy is false, childItem is removed from oldParentItem.
|
||||
// If newParentItem is specified, childItem is attached to newParentItem.
|
||||
// childItem: Item
|
||||
// oldParentItem: Item
|
||||
// newParentItem: Item
|
||||
// bCopy: Boolean
|
||||
// insertIndex: int?
|
||||
// Allows to insert the new item as the n'th child of `parent`.
|
||||
// before: Item?
|
||||
// Insert the new item as the previous sibling of this item. `before` must be a child of `parent`.
|
||||
// tags:
|
||||
// extension
|
||||
},
|
||||
|
||||
// =======================================================================
|
||||
// Callbacks
|
||||
|
||||
onChange: function(item){
|
||||
// summary:
|
||||
// Callback whenever an item has changed, so that Tree
|
||||
// can update the label, icon, etc. Note that changes
|
||||
// to an item's children or parent(s) will trigger an
|
||||
// onChildrenChange() so you can ignore those changes here.
|
||||
// item: dojo/data/Item
|
||||
// tags:
|
||||
// callback
|
||||
},
|
||||
|
||||
onChildrenChange: function(parent, newChildrenList){
|
||||
// summary:
|
||||
// Callback to do notifications about new, updated, or deleted items.
|
||||
// parent: dojo/data/Item
|
||||
// newChildrenList: dojo/data/Item[]
|
||||
// tags:
|
||||
// callback
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
Reference in New Issue
Block a user