dojo.provide("dijit._Container"); dojo.declare("dijit._Container", null, { // summary: // Mixin for widgets that contain a set of widget children. // description: // Use this mixin for widgets that needs to know about and // keep track of their widget children. Suitable for widgets like BorderContainer // and TabContainer which contain (only) a set of child widgets. // // It's not suitable for widgets like ContentPane // which contains mixed HTML (plain DOM nodes in addition to widgets), // and where contained widgets are not necessarily directly below // this.containerNode. In that case calls like addChild(node, position) // wouldn't make sense. // isContainer: [protected] Boolean // Just a flag indicating that this widget descends from dijit._Container isContainer: true, buildRendering: function(){ this.inherited(arguments); if(!this.containerNode){ // all widgets with descendants must set containerNode this.containerNode = this.domNode; } }, addChild: function(/*Widget*/ widget, /*int?*/ insertIndex){ // summary: // Makes the given widget a child of this widget. // description: // Inserts specified child widget's dom node as a child of this widget's // container node, and possibly does other processing (such as layout). var refNode = this.containerNode; if(insertIndex && typeof insertIndex == "number"){ var children = this.getChildren(); if(children && children.length >= insertIndex){ refNode = children[insertIndex-1].domNode; insertIndex = "after"; } } dojo.place(widget.domNode, refNode, insertIndex); // If I've been started but the child widget hasn't been started, // start it now. Make sure to do this after widget has been // inserted into the DOM tree, so it can see that it's being controlled by me, // so it doesn't try to size itself. if(this._started && !widget._started){ widget.startup(); } }, removeChild: function(/*Widget or int*/ widget){ // summary: // Removes the passed widget instance from this widget but does // not destroy it. You can also pass in an integer indicating // the index within the container to remove if(typeof widget == "number" && widget > 0){ widget = this.getChildren()[widget]; } // If we cannot find the widget, just return if(!widget || !widget.domNode){ return; } var node = widget.domNode; node.parentNode.removeChild(node); // detach but don't destroy }, _nextElement: function(node){ // summary: // Find the next (non-text, non-comment etc) node // tags: // private do{ node = node.nextSibling; }while(node && node.nodeType != 1); return node; }, _firstElement: function(node){ // summary: // Find the first (non-text, non-comment etc) node // tags: // private node = node.firstChild; if(node && node.nodeType != 1){ node = this._nextElement(node); } return node; }, getChildren: function(){ // summary: // Returns array of children widgets. // description: // Returns the widgets that are directly under this.containerNode. return dojo.query("> [widgetId]", this.containerNode).map(dijit.byNode); // Widget[] }, hasChildren: function(){ // summary: // Returns true if widget has children, i.e. if this.containerNode contains something. return !!this._firstElement(this.containerNode); // Boolean }, destroyDescendants: function(/*Boolean*/ preserveDom){ // summary: // Destroys all the widgets inside this.containerNode, // but not this widget itself dojo.forEach(this.getChildren(), function(child){ child.destroyRecursive(preserveDom); }); }, _getSiblingOfChild: function(/*Widget*/ child, /*int*/ dir){ // summary: // Get the next or previous widget sibling of child // dir: // if 1, get the next sibling // if -1, get the previous sibling // tags: // private var node = child.domNode; var which = (dir>0 ? "nextSibling" : "previousSibling"); do{ node = node[which]; }while(node && (node.nodeType != 1 || !dijit.byNode(node))); return node ? dijit.byNode(node) : null; }, getIndexOfChild: function(/*Widget*/ child){ // summary: // Gets the index of the child in this container or -1 if not found var children = this.getChildren(); for(var i=0, c; c=children[i]; i++){ if(c == child){ return i; // int } } return -1; // int } } );