require({cache:{ 'url:dijit/templates/TreeNode.html':"
\"\"\n\t\t\t\"\"\n\t\t
\n\t
\n
\n", 'url:dijit/templates/Tree.html':"
\n\t
\n
\n"}}); define("dijit/Tree", [ "dojo/_base/array", // array.filter array.forEach array.map "dojo/_base/connect", // connect.isCopyKey() "dojo/cookie", // cookie "dojo/_base/declare", // declare "dojo/Deferred", // Deferred "dojo/DeferredList", // DeferredList "dojo/dom", // dom.isDescendant "dojo/dom-class", // domClass.add domClass.remove domClass.replace domClass.toggle "dojo/dom-geometry", // domGeometry.setMarginBox domGeometry.position "dojo/dom-style",// domStyle.set "dojo/_base/event", // event.stop "dojo/errors/create", // createError "dojo/fx", // fxUtils.wipeIn fxUtils.wipeOut "dojo/_base/kernel", // kernel.deprecated "dojo/keys", // arrows etc. "dojo/_base/lang", // lang.getObject lang.mixin lang.hitch "dojo/on", // on(), on.selector() "dojo/topic", "dojo/touch", "dojo/when", "./focus", "./registry", // registry.byNode(), registry.getEnclosingWidget() "./_base/manager", // manager.defaultDuration "./_Widget", "./_TemplatedMixin", "./_Container", "./_Contained", "./_CssStateMixin", "dojo/text!./templates/TreeNode.html", "dojo/text!./templates/Tree.html", "./tree/TreeStoreModel", "./tree/ForestStoreModel", "./tree/_dndSelector" ], function(array, connect, cookie, declare, Deferred, DeferredList, dom, domClass, domGeometry, domStyle, event, createError, fxUtils, kernel, keys, lang, on, topic, touch, when, focus, registry, manager, _Widget, _TemplatedMixin, _Container, _Contained, _CssStateMixin, treeNodeTemplate, treeTemplate, TreeStoreModel, ForestStoreModel, _dndSelector){ // module: // dijit/Tree // Back-compat shim Deferred = declare(Deferred, { addCallback: function(callback){ this.then(callback); }, addErrback: function(errback){ this.then(null, errback); } }); var TreeNode = declare( "dijit._TreeNode", [_Widget, _TemplatedMixin, _Container, _Contained, _CssStateMixin], { // summary: // Single node within a tree. This class is used internally // by Tree and should not be accessed directly. // tags: // private // item: [const] Item // the dojo.data entry this tree represents item: null, // isTreeNode: [protected] Boolean // Indicates that this is a TreeNode. Used by `dijit.Tree` only, // should not be accessed directly. isTreeNode: true, // label: String // Text of this tree node label: "", _setLabelAttr: {node: "labelNode", type: "innerText"}, // isExpandable: [private] Boolean // This node has children, so show the expando node (+ sign) isExpandable: null, // isExpanded: [readonly] Boolean // This node is currently expanded (ie, opened) isExpanded: false, // state: [private] String // Dynamic loading-related stuff. // When an empty folder node appears, it is "UNCHECKED" first, // then after dojo.data query it becomes "LOADING" and, finally "LOADED" state: "UNCHECKED", templateString: treeNodeTemplate, baseClass: "dijitTreeNode", // For hover effect for tree node, and focus effect for label cssStateNodes: { rowNode: "dijitTreeRow" }, // Tooltip is defined in _WidgetBase but we need to handle the mapping to DOM here _setTooltipAttr: {node: "rowNode", type: "attribute", attribute: "title"}, buildRendering: function(){ this.inherited(arguments); // set expand icon for leaf this._setExpando(); // set icon and label class based on item this._updateItemClasses(this.item); if(this.isExpandable){ this.labelNode.setAttribute("aria-expanded", this.isExpanded); } //aria-selected should be false on all selectable elements. this.setSelected(false); }, _setIndentAttr: function(indent){ // summary: // Tell this node how many levels it should be indented // description: // 0 for top level nodes, 1 for their children, 2 for their // grandchildren, etc. // Math.max() is to prevent negative padding on hidden root node (when indent == -1) var pixels = (Math.max(indent, 0) * this.tree._nodePixelIndent) + "px"; domStyle.set(this.domNode, "backgroundPosition", pixels + " 0px"); // TODOC: what is this for??? domStyle.set(this.indentNode, this.isLeftToRight() ? "paddingLeft" : "paddingRight", pixels); array.forEach(this.getChildren(), function(child){ child.set("indent", indent+1); }); this._set("indent", indent); }, markProcessing: function(){ // summary: // Visually denote that tree is loading data, etc. // tags: // private this.state = "LOADING"; this._setExpando(true); }, unmarkProcessing: function(){ // summary: // Clear markup from markProcessing() call // tags: // private this._setExpando(false); }, _updateItemClasses: function(item){ // summary: // Set appropriate CSS classes for icon and label dom node // (used to allow for item updates to change respective CSS) // tags: // private var tree = this.tree, model = tree.model; if(tree._v10Compat && item === model.root){ // For back-compat with 1.0, need to use null to specify root item (TODO: remove in 2.0) item = null; } this._applyClassAndStyle(item, "icon", "Icon"); this._applyClassAndStyle(item, "label", "Label"); this._applyClassAndStyle(item, "row", "Row"); this.tree._startPaint(true); // signifies paint started and finished (synchronously) }, _applyClassAndStyle: function(item, lower, upper){ // summary: // Set the appropriate CSS classes and styles for labels, icons and rows. // // item: // The data item. // // lower: // The lower case attribute to use, e.g. 'icon', 'label' or 'row'. // // upper: // The upper case attribute to use, e.g. 'Icon', 'Label' or 'Row'. // // tags: // private var clsName = "_" + lower + "Class"; var nodeName = lower + "Node"; var oldCls = this[clsName]; this[clsName] = this.tree["get" + upper + "Class"](item, this.isExpanded); domClass.replace(this[nodeName], this[clsName] || "", oldCls || ""); domStyle.set(this[nodeName], this.tree["get" + upper + "Style"](item, this.isExpanded) || {}); }, _updateLayout: function(){ // summary: // Set appropriate CSS classes for this.domNode // tags: // private var parent = this.getParent(); if(!parent || !parent.rowNode || parent.rowNode.style.display == "none"){ /* if we are hiding the root node then make every first level child look like a root node */ domClass.add(this.domNode, "dijitTreeIsRoot"); }else{ domClass.toggle(this.domNode, "dijitTreeIsLast", !this.getNextSibling()); } }, _setExpando: function(/*Boolean*/ processing){ // summary: // Set the right image for the expando node // tags: // private var styles = ["dijitTreeExpandoLoading", "dijitTreeExpandoOpened", "dijitTreeExpandoClosed", "dijitTreeExpandoLeaf"], _a11yStates = ["*","-","+","*"], idx = processing ? 0 : (this.isExpandable ? (this.isExpanded ? 1 : 2) : 3); // apply the appropriate class to the expando node domClass.replace(this.expandoNode, styles[idx], styles); // provide a non-image based indicator for images-off mode this.expandoNodeText.innerHTML = _a11yStates[idx]; }, expand: function(){ // summary: // Show my children // returns: // Deferred that fires when expansion is complete // If there's already an expand in progress or we are already expanded, just return if(this._expandDeferred){ return this._expandDeferred; // dojo/_base/Deferred } // cancel in progress collapse operation if(this._collapseDeferred){ this._collapseDeferred.cancel(); delete this._collapseDeferred; } // All the state information for when a node is expanded, maybe this should be // set when the animation completes instead this.isExpanded = true; this.labelNode.setAttribute("aria-expanded", "true"); if(this.tree.showRoot || this !== this.tree.rootNode){ this.containerNode.setAttribute("role", "group"); } domClass.add(this.contentNode,'dijitTreeContentExpanded'); this._setExpando(); this._updateItemClasses(this.item); if(this == this.tree.rootNode && this.tree.showRoot){ this.tree.domNode.setAttribute("aria-expanded", "true"); } var def, wipeIn = fxUtils.wipeIn({ node: this.containerNode, duration: manager.defaultDuration, onEnd: function(){ def.resolve(true); } }); // Deferred that fires when expand is complete def = (this._expandDeferred = new Deferred(function(){ // Canceller wipeIn.stop(); })); wipeIn.play(); return def; // dojo/_base/Deferred }, collapse: function(){ // summary: // Collapse this node (if it's expanded) if(this._collapseDeferred){ // Node is already collapsed, or there's a collapse in progress, just return that Deferred return this._collapseDeferred; } // cancel in progress expand operation if(this._expandDeferred){ this._expandDeferred.cancel(); delete this._expandDeferred; } this.isExpanded = false; this.labelNode.setAttribute("aria-expanded", "false"); if(this == this.tree.rootNode && this.tree.showRoot){ this.tree.domNode.setAttribute("aria-expanded", "false"); } domClass.remove(this.contentNode,'dijitTreeContentExpanded'); this._setExpando(); this._updateItemClasses(this.item); var def, wipeOut = fxUtils.wipeOut({ node: this.containerNode, duration: manager.defaultDuration, onEnd: function(){ def.resolve(true); } }); // Deferred that fires when expand is complete def = (this._collapseDeferred = new Deferred(function(){ // Canceller wipeOut.stop(); })); wipeOut.play(); return def; // dojo/_base/Deferred }, // indent: Integer // Levels from this node to the root node indent: 0, setChildItems: function(/* Object[] */ items){ // summary: // Sets the child items of this node, removing/adding nodes // from current children to match specified items[] array. // Also, if this.persist == true, expands any children that were previously // opened. // returns: // Deferred object that fires after all previously opened children // have been expanded again (or fires instantly if there are no such children). var tree = this.tree, model = tree.model, defs = []; // list of deferreds that need to fire before I am complete // Orphan all my existing children. // If items contains some of the same items as before then we will reattach them. // Don't call this.removeChild() because that will collapse the tree etc. var oldChildren = this.getChildren(); array.forEach(oldChildren, function(child){ _Container.prototype.removeChild.call(this, child); }, this); // All the old children of this TreeNode are subject for destruction if // 1) they aren't listed in the new children array (items) // 2) they aren't immediately adopted by another node (DnD) this.defer(function(){ array.forEach(oldChildren, function(node){ if(!node._destroyed && !node.getParent()){ // If node is in selection then remove it. tree.dndController.removeTreeNode(node); // Deregister mapping from item id --> this node var id = model.getIdentity(node.item), ary = tree._itemNodesMap[id]; if(ary.length == 1){ delete tree._itemNodesMap[id]; }else{ var index = array.indexOf(ary, node); if(index != -1){ ary.splice(index, 1); } } // And finally we can destroy the node node.destroyRecursive(); } }); }); this.state = "LOADED"; if(items && items.length > 0){ this.isExpandable = true; // Create _TreeNode widget for each specified tree node, unless one already // exists and isn't being used (presumably it's from a DnD move and was recently // released array.forEach(items, function(item){ // MARKER: REUSE NODE var id = model.getIdentity(item), existingNodes = tree._itemNodesMap[id], node; if(existingNodes){ for(var i=0;i