mirror of
https://git.tt-rss.org/git/tt-rss.git
synced 2025-12-15 18:35:57 +00:00
upgrade Dojo to 1.6.1
This commit is contained in:
@@ -1,145 +1,381 @@
|
||||
/*
|
||||
Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
|
||||
Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
|
||||
Available via Academic Free License >= 2.1 OR the modified BSD license.
|
||||
see: http://dojotoolkit.org/license for details
|
||||
*/
|
||||
|
||||
|
||||
if(!dojo._hasResource["dijit.tree.TreeStoreModel"]){
|
||||
dojo._hasResource["dijit.tree.TreeStoreModel"]=true;
|
||||
if(!dojo._hasResource["dijit.tree.TreeStoreModel"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit.tree.TreeStoreModel"] = true;
|
||||
dojo.provide("dijit.tree.TreeStoreModel");
|
||||
dojo.declare("dijit.tree.TreeStoreModel",null,{store:null,childrenAttrs:["children"],newItemIdAttr:"id",labelAttr:"",root:null,query:null,deferItemLoadingUntilExpand:false,constructor:function(_1){
|
||||
dojo.mixin(this,_1);
|
||||
this.connects=[];
|
||||
var _2=this.store;
|
||||
if(!_2.getFeatures()["dojo.data.api.Identity"]){
|
||||
throw new Error("dijit.Tree: store must support dojo.data.Identity");
|
||||
}
|
||||
if(_2.getFeatures()["dojo.data.api.Notification"]){
|
||||
this.connects=this.connects.concat([dojo.connect(_2,"onNew",this,"onNewItem"),dojo.connect(_2,"onDelete",this,"onDeleteItem"),dojo.connect(_2,"onSet",this,"onSetItem")]);
|
||||
}
|
||||
},destroy:function(){
|
||||
dojo.forEach(this.connects,dojo.disconnect);
|
||||
},getRoot:function(_3,_4){
|
||||
if(this.root){
|
||||
_3(this.root);
|
||||
}else{
|
||||
this.store.fetch({query:this.query,onComplete:dojo.hitch(this,function(_5){
|
||||
if(_5.length!=1){
|
||||
throw new Error(this.declaredClass+": query "+dojo.toJson(this.query)+" returned "+_5.length+" items, but must return exactly one item");
|
||||
}
|
||||
this.root=_5[0];
|
||||
_3(this.root);
|
||||
}),onError:_4});
|
||||
}
|
||||
},mayHaveChildren:function(_6){
|
||||
return dojo.some(this.childrenAttrs,function(_7){
|
||||
return this.store.hasAttribute(_6,_7);
|
||||
},this);
|
||||
},getChildren:function(_8,_9,_a){
|
||||
var _b=this.store;
|
||||
if(!_b.isItemLoaded(_8)){
|
||||
var _c=dojo.hitch(this,arguments.callee);
|
||||
_b.loadItem({item:_8,onItem:function(_d){
|
||||
_c(_d,_9,_a);
|
||||
},onError:_a});
|
||||
return;
|
||||
}
|
||||
var _e=[];
|
||||
for(var i=0;i<this.childrenAttrs.length;i++){
|
||||
var _f=_b.getValues(_8,this.childrenAttrs[i]);
|
||||
_e=_e.concat(_f);
|
||||
}
|
||||
var _10=0;
|
||||
if(!this.deferItemLoadingUntilExpand){
|
||||
dojo.forEach(_e,function(_11){
|
||||
if(!_b.isItemLoaded(_11)){
|
||||
_10++;
|
||||
}
|
||||
});
|
||||
}
|
||||
if(_10==0){
|
||||
_9(_e);
|
||||
}else{
|
||||
dojo.forEach(_e,function(_12,idx){
|
||||
if(!_b.isItemLoaded(_12)){
|
||||
_b.loadItem({item:_12,onItem:function(_13){
|
||||
_e[idx]=_13;
|
||||
if(--_10==0){
|
||||
_9(_e);
|
||||
}
|
||||
},onError:_a});
|
||||
}
|
||||
});
|
||||
}
|
||||
},isItem:function(_14){
|
||||
return this.store.isItem(_14);
|
||||
},fetchItemByIdentity:function(_15){
|
||||
this.store.fetchItemByIdentity(_15);
|
||||
},getIdentity:function(_16){
|
||||
return this.store.getIdentity(_16);
|
||||
},getLabel:function(_17){
|
||||
if(this.labelAttr){
|
||||
return this.store.getValue(_17,this.labelAttr);
|
||||
}else{
|
||||
return this.store.getLabel(_17);
|
||||
}
|
||||
},newItem:function(_18,_19,_1a){
|
||||
var _1b={parent:_19,attribute:this.childrenAttrs[0],insertIndex:_1a};
|
||||
if(this.newItemIdAttr&&_18[this.newItemIdAttr]){
|
||||
this.fetchItemByIdentity({identity:_18[this.newItemIdAttr],scope:this,onItem:function(_1c){
|
||||
if(_1c){
|
||||
this.pasteItem(_1c,null,_19,true,_1a);
|
||||
}else{
|
||||
this.store.newItem(_18,_1b);
|
||||
}
|
||||
}});
|
||||
}else{
|
||||
this.store.newItem(_18,_1b);
|
||||
}
|
||||
},pasteItem:function(_1d,_1e,_1f,_20,_21){
|
||||
var _22=this.store,_23=this.childrenAttrs[0];
|
||||
if(_1e){
|
||||
dojo.forEach(this.childrenAttrs,function(_24){
|
||||
if(_22.containsValue(_1e,_24,_1d)){
|
||||
if(!_20){
|
||||
var _25=dojo.filter(_22.getValues(_1e,_24),function(x){
|
||||
return x!=_1d;
|
||||
});
|
||||
_22.setValues(_1e,_24,_25);
|
||||
}
|
||||
_23=_24;
|
||||
}
|
||||
});
|
||||
}
|
||||
if(_1f){
|
||||
if(typeof _21=="number"){
|
||||
var _26=_22.getValues(_1f,_23).slice();
|
||||
_26.splice(_21,0,_1d);
|
||||
_22.setValues(_1f,_23,_26);
|
||||
}else{
|
||||
_22.setValues(_1f,_23,_22.getValues(_1f,_23).concat(_1d));
|
||||
}
|
||||
}
|
||||
},onChange:function(_27){
|
||||
},onChildrenChange:function(_28,_29){
|
||||
},onDelete:function(_2a,_2b){
|
||||
},onNewItem:function(_2c,_2d){
|
||||
if(!_2d){
|
||||
return;
|
||||
}
|
||||
this.getChildren(_2d.item,dojo.hitch(this,function(_2e){
|
||||
this.onChildrenChange(_2d.item,_2e);
|
||||
}));
|
||||
},onDeleteItem:function(_2f){
|
||||
this.onDelete(_2f);
|
||||
},onSetItem:function(_30,_31,_32,_33){
|
||||
if(dojo.indexOf(this.childrenAttrs,_31)!=-1){
|
||||
this.getChildren(_30,dojo.hitch(this,function(_34){
|
||||
this.onChildrenChange(_30,_34);
|
||||
}));
|
||||
}else{
|
||||
this.onChange(_30);
|
||||
}
|
||||
}});
|
||||
|
||||
|
||||
dojo.declare(
|
||||
"dijit.tree.TreeStoreModel",
|
||||
null,
|
||||
{
|
||||
// summary:
|
||||
// Implements dijit.Tree.model connecting to a store with a single
|
||||
// root item. Any methods passed into the constructor will override
|
||||
// the ones defined here.
|
||||
|
||||
// store: dojo.data.Store
|
||||
// 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
|
||||
|
||||
dojo.mixin(this, args);
|
||||
|
||||
this.connects = [];
|
||||
|
||||
var store = this.store;
|
||||
if(!store.getFeatures()['dojo.data.api.Identity']){
|
||||
throw new Error("dijit.Tree: 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([
|
||||
dojo.connect(store, "onNew", this, "onNewItem"),
|
||||
dojo.connect(store, "onDelete", this, "onDeleteItem"),
|
||||
dojo.connect(store, "onSet", this, "onSetItem")
|
||||
]);
|
||||
}
|
||||
},
|
||||
|
||||
destroy: function(){
|
||||
dojo.forEach(this.connects, dojo.disconnect);
|
||||
// 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: dojo.hitch(this, function(items){
|
||||
if(items.length != 1){
|
||||
throw new Error(this.declaredClass + ": query " + dojo.toJson(this.query) + " returned " + items.length +
|
||||
" items, but must return exactly one item");
|
||||
}
|
||||
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 dojo.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 = dojo.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){
|
||||
dojo.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
|
||||
dojo.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(/* dojo.dnd.Item */ args, /*Item*/ parent, /*int?*/ insertIndex){
|
||||
// summary:
|
||||
// Creates a new item. See `dojo.data.api.Write` for details on args.
|
||||
// Used in drag & drop when item from external source dropped onto tree.
|
||||
// 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){
|
||||
dojo.forEach(this.childrenAttrs, function(attr){
|
||||
if(store.containsValue(oldParentItem, attr, childItem)){
|
||||
if(!bCopy){
|
||||
var values = dojo.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(/*dojo.data.Item*/ parent, /*dojo.data.Item[]*/ newChildrenList){
|
||||
// summary:
|
||||
// Callback to do notifications about new, updated, or deleted items.
|
||||
// tags:
|
||||
// callback
|
||||
},
|
||||
|
||||
onDelete: function(/*dojo.data.Item*/ parent, /*dojo.data.Item[]*/ newChildrenList){
|
||||
// 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, dojo.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 */ item,
|
||||
/* attribute-name-string */ attribute,
|
||||
/* object | array */ oldValue,
|
||||
/* object | array */ 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.
|
||||
// tags:
|
||||
// extension
|
||||
|
||||
if(dojo.indexOf(this.childrenAttrs, attribute) != -1){
|
||||
// item's children list changed
|
||||
this.getChildren(item, dojo.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);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user