forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			639 lines
		
	
	
	
		
			18 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			639 lines
		
	
	
	
		
			18 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /*
 | |
|  * Software License Agreement (BSD License)
 | |
|  *
 | |
|  * Copyright (c) 2007, Parakey Inc.
 | |
|  * All rights reserved.
 | |
|  * 
 | |
|  * Redistribution and use of this software in source and binary forms, with or without modification,
 | |
|  * are permitted provided that the following conditions are met:
 | |
|  * 
 | |
|  * * Redistributions of source code must retain the above
 | |
|  *   copyright notice, this list of conditions and the
 | |
|  *   following disclaimer.
 | |
|  * 
 | |
|  * * Redistributions in binary form must reproduce the above
 | |
|  *   copyright notice, this list of conditions and the
 | |
|  *   following disclaimer in the documentation and/or other
 | |
|  *   materials provided with the distribution.
 | |
|  * 
 | |
|  * * Neither the name of Parakey Inc. nor the names of its
 | |
|  *   contributors may be used to endorse or promote products
 | |
|  *   derived from this software without specific prior
 | |
|  *   written permission of Parakey Inc.
 | |
|  * 
 | |
|  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
 | |
|  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 | |
|  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 | |
|  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | |
|  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
|  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
 | |
|  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 | |
|  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
|  */
 | |
| 
 | |
| /*
 | |
|  * Creator:
 | |
|  *  Joe Hewitt
 | |
|  * Contributors
 | |
|  *  John J. Barton (IBM Almaden)
 | |
|  *  Jan Odvarko (Mozilla Corp.)
 | |
|  *  Max Stepanov (Aptana Inc.)
 | |
|  *  Rob Campbell (Mozilla Corp.)
 | |
|  *  Hans Hillen (Paciello Group, Mozilla)
 | |
|  *  Curtis Bartley (Mozilla Corp.)
 | |
|  *  Mike Collins (IBM Almaden)
 | |
|  *  Kevin Decker
 | |
|  *  Mike Ratcliffe (Comartis AG)
 | |
|  *  Hernan Rodríguez Colmeiro
 | |
|  *  Austin Andrews
 | |
|  *  Christoph Dorn
 | |
|  *  Steven Roussey (AppCenter Inc, Network54)
 | |
|  */
 | |
| 
 | |
| ///////////////////////////////////////////////////////////////////////////
 | |
| //// InsideOutBox
 | |
| 
 | |
| /**
 | |
|  * InsideOutBoxView is a simple interface definition for views implementing
 | |
|  * InsideOutBox controls. All implementors must define these methods.
 | |
|  * Implemented in InspectorUI.
 | |
|  */
 | |
| 
 | |
| /*
 | |
| InsideOutBoxView = {
 | |
|   //
 | |
|    * Retrieves the parent object for a given child object.
 | |
|    * @param aChild
 | |
|    *        The child node to retrieve the parent object for.
 | |
|    * @returns a DOM node | null
 | |
|    //
 | |
|   getParentObject: function(aChild) {},
 | |
| 
 | |
|   //
 | |
|    * Retrieves a given child node.
 | |
|    *
 | |
|    * If both index and previousSibling are passed, the implementation
 | |
|    * may assume that previousSibling will be the return for getChildObject
 | |
|    * with index-1.
 | |
|    * @param aParent
 | |
|    *        The parent object of the child object to retrieve.
 | |
|    * @param aIndex
 | |
|    *        The index of the child object to retrieve from aParent.
 | |
|    * @param aPreviousSibling
 | |
|    *        The previous sibling of the child object to retrieve.
 | |
|    *        Supercedes aIndex.
 | |
|    * @returns a DOM object | null
 | |
|    //
 | |
|   getChildObject: function(aParent, aIndex, aPreviousSibling) {},
 | |
| 
 | |
|   //
 | |
|    * Renders the HTML representation of the object. Should return an HTML
 | |
|    * object which will be displayed to the user.
 | |
|    * @param aObject
 | |
|    *        The object to create the box object for.
 | |
|    * @param aIsRoot
 | |
|    *        Is the object the root object. May not be used in all
 | |
|    *        implementations.
 | |
|    * @returns an object box | null
 | |
|    //
 | |
|   createObjectBox: function(aObject, aIsRoot) {},
 | |
| 
 | |
|   //
 | |
|   * Convenience wrappers for classList API.
 | |
|   * @param aObject
 | |
|   *        DOM node to query/set.
 | |
|   * @param aClassName
 | |
|   *        String containing the class name to query/set.
 | |
|   //
 | |
|   hasClass: function(aObject, aClassName) {},
 | |
|   addClass: function(aObject, aClassName) {},
 | |
|   removeClass: function(aObject, aClassName) {}
 | |
| };
 | |
| */
 | |
| 
 | |
| /**
 | |
|  * Creates a tree based on objects provided by a separate "view" object.
 | |
|  *
 | |
|  * Construction uses an "inside-out" algorithm, meaning that the view's job is
 | |
|  * first to tell us the ancestry of each object, and secondarily its
 | |
|  * descendants.
 | |
|  *
 | |
|  * Constructor
 | |
|  * @param aView
 | |
|  *        The view requiring the InsideOutBox.
 | |
|  * @param aBox
 | |
|  *        The box object containing the InsideOutBox. Required to add/remove
 | |
|  *        children during box manipulation (toggling opened or closed).
 | |
|  */
 | |
| function InsideOutBox(aView, aBox)
 | |
| {
 | |
|   this.view = aView;
 | |
|   this.box = aBox;
 | |
| 
 | |
|   this.rootObject = null;
 | |
| 
 | |
|   this.rootObjectBox = null;
 | |
|   this.selectedObjectBox = null;
 | |
|   this.highlightedObjectBox = null;
 | |
|   this.scrollIntoView = false;
 | |
| };
 | |
| 
 | |
| InsideOutBox.prototype =
 | |
| {
 | |
|   /**
 | |
|    * Highlight the given object node in the tree.
 | |
|    * @param aObject
 | |
|    *        the object to highlight.
 | |
|    * @returns objectBox
 | |
|    */
 | |
|   highlight: function IOBox_highlight(aObject)
 | |
|   {
 | |
|     let objectBox = this.createObjectBox(aObject);
 | |
|     this.highlightObjectBox(objectBox);
 | |
|     return objectBox;
 | |
|   },
 | |
| 
 | |
|   /**
 | |
|    * Open the given object node in the tree.
 | |
|    * @param aObject
 | |
|    *        The object node to open.
 | |
|    * @returns objectBox
 | |
|    */
 | |
|   openObject: function IOBox_openObject(aObject)
 | |
|   {
 | |
|     let object = aObject;
 | |
|     let firstChild = this.view.getChildObject(object, 0);
 | |
|     if (firstChild)
 | |
|       object = firstChild;
 | |
| 
 | |
|     return this.openToObject(object);
 | |
|   },
 | |
| 
 | |
|   /**
 | |
|    * Open the tree up to the given object node.
 | |
|    * @param aObject
 | |
|    *        The object in the tree to open to.
 | |
|    * @returns objectBox
 | |
|    */
 | |
|   openToObject: function IOBox_openToObject(aObject)
 | |
|   {
 | |
|     let objectBox = this.createObjectBox(aObject);
 | |
|     this.openObjectBox(objectBox);
 | |
|     return objectBox;
 | |
|   },
 | |
| 
 | |
|   /**
 | |
|    * Select the given object node in the tree.
 | |
|    * @param aObject
 | |
|    *        The object node to select.
 | |
|    * @param makeBoxVisible
 | |
|    *        Boolean. Open the object box in the tree?
 | |
|    * @param forceOpen
 | |
|    *        Force the object box open by expanding all elements in the tree?
 | |
|    * @param scrollIntoView
 | |
|    *        Scroll the objectBox into view?
 | |
|    * @returns objectBox
 | |
|    */
 | |
|   select:
 | |
|   function IOBox_select(aObject, makeBoxVisible, forceOpen, scrollIntoView)
 | |
|   {
 | |
|     let objectBox = this.createObjectBox(aObject);
 | |
|     this.selectObjectBox(objectBox, forceOpen);
 | |
|     if (makeBoxVisible) {
 | |
|       this.openObjectBox(objectBox);
 | |
|       if (scrollIntoView) {
 | |
|         objectBox.scrollIntoView(true);
 | |
|       }
 | |
|     }
 | |
|     return objectBox;
 | |
|   },
 | |
| 
 | |
|   /**
 | |
|    * Expands/contracts the given object, depending on its state.
 | |
|    * @param aObject
 | |
|    *        The tree node to expand/contract.
 | |
|    */
 | |
|   toggleObject: function IOBox_toggleObject(aObject)
 | |
|   {
 | |
|     let box = this.createObjectBox(aObject);
 | |
|     if (!(this.view.hasClass(box, "open")))
 | |
|       this.expandObjectBox(box);
 | |
|     else
 | |
|       this.contractObjectBox(box);
 | |
|   },
 | |
| 
 | |
|   /**
 | |
|    * Expand the given object in the tree.
 | |
|    * @param aObject
 | |
|    *        The tree node to expand.
 | |
|    */
 | |
|   expandObject: function IOBox_expandObject(aObject)
 | |
|   {
 | |
|     let objectBox = this.createObjectBox(aObject);
 | |
|     if (objectBox)
 | |
|       this.expandObjectBox(objectBox);
 | |
|   },
 | |
| 
 | |
|   /**
 | |
|    * Contract the given object in the tree.
 | |
|    * @param aObject
 | |
|    *        The tree node to contract.
 | |
|    */
 | |
|   contractObject: function IOBox_contractObject(aObject)
 | |
|   {
 | |
|     let objectBox = this.createObjectBox(aObject);
 | |
|     if (objectBox)
 | |
|       this.contractObjectBox(objectBox);
 | |
|   },
 | |
| 
 | |
|   /**
 | |
|    * General method for iterating over an object's ancestors and performing
 | |
|    * some function.
 | |
|    * @param aObject
 | |
|    *        The object whose ancestors we wish to iterate over.
 | |
|    * @param aCallback
 | |
|    *        The function to call with the object as argument.
 | |
|    */
 | |
| 
 | |
|   iterateObjectAncestors: function IOBox_iterateObjectAncesors(aObject, aCallback)
 | |
|   {
 | |
|     let object = aObject;
 | |
|     if (!(aCallback && typeof(aCallback) == "function")) {
 | |
|       this.view._log("Illegal argument in IOBox.iterateObjectAncestors");
 | |
|       return;
 | |
|     }
 | |
|     while ((object = this.getParentObjectBox(object)))
 | |
|       aCallback(object);
 | |
|   },
 | |
| 
 | |
|   /**
 | |
|    * Highlight the given objectBox in the tree.
 | |
|    * @param aObjectBox
 | |
|    *        The objectBox to highlight.
 | |
|    */
 | |
|   highlightObjectBox: function IOBox_highlightObjectBox(aObjectBox)
 | |
|   {
 | |
|     let self = this;
 | |
| 
 | |
|     if (!aObjectBox)
 | |
|       return;
 | |
| 
 | |
|     if (this.highlightedObjectBox) {
 | |
|       this.view.removeClass(this.highlightedObjectBox, "highlighted");
 | |
|       this.iterateObjectAncestors(this.highlightedObjectBox, function (box) {
 | |
|         self.view.removeClass(box, "highlightOpen");
 | |
|       });
 | |
|     }
 | |
| 
 | |
|     this.highlightedObjectBox = aObjectBox;
 | |
| 
 | |
|     this.view.addClass(aObjectBox, "highlighted");
 | |
|     this.iterateObjectAncestors(this.highlightedObjectBox, function (box) {
 | |
|       self.view.addClass(box, "highlightOpen");
 | |
|     });
 | |
| 
 | |
|     aObjectBox.scrollIntoView(true);
 | |
|   },
 | |
| 
 | |
|   /**
 | |
|    * Select the given objectBox in the tree, forcing it to be open if necessary.
 | |
|    * @param aObjectBox
 | |
|    *        The objectBox to select.
 | |
|    * @param forceOpen
 | |
|    *        Force the box (subtree) to be open?
 | |
|    */
 | |
|   selectObjectBox: function IOBox_selectObjectBox(aObjectBox, forceOpen)
 | |
|   {
 | |
|     let isSelected = this.selectedObjectBox &&
 | |
|       aObjectBox == this.selectedObjectBox;
 | |
| 
 | |
|     // aObjectBox is already selected, return
 | |
|     if (isSelected)
 | |
|       return;
 | |
| 
 | |
|     if (this.selectedObjectBox)
 | |
|       this.view.removeClass(this.selectedObjectBox, "selected");
 | |
| 
 | |
|     this.selectedObjectBox = aObjectBox;
 | |
| 
 | |
|     if (aObjectBox) {
 | |
|       this.view.addClass(aObjectBox, "selected");
 | |
| 
 | |
|       // Force it open the first time it is selected
 | |
|       if (forceOpen)
 | |
|         this.expandObjectBox(aObjectBox, true);
 | |
|     }
 | |
|   },
 | |
| 
 | |
|   /**
 | |
|    * Open the ancestors of the given object box.
 | |
|    * @param aObjectBox
 | |
|    *        The object box to open.
 | |
|    */
 | |
|   openObjectBox: function IOBox_openObjectBox(aObjectBox)
 | |
|   {
 | |
|     if (!aObjectBox)
 | |
|       return;
 | |
| 
 | |
|     let self = this;
 | |
|     this.iterateObjectAncestors(aObjectBox, function (box) {
 | |
|       self.view.addClass(box, "open");
 | |
|       let labelBox = box.querySelector(".nodeLabelBox");
 | |
|       if (labelBox)
 | |
|         labelBox.setAttribute("aria-expanded", "true");
 | |
|    });
 | |
|   },
 | |
| 
 | |
|   /**
 | |
|    * Expand the given object box.
 | |
|    * @param aObjectBox
 | |
|    *        The object box to expand.
 | |
|    */
 | |
|   expandObjectBox: function IOBox_expandObjectBox(aObjectBox)
 | |
|   {
 | |
|     let nodeChildBox = this.getChildObjectBox(aObjectBox);
 | |
| 
 | |
|     // no children means nothing to expand, return
 | |
|     if (!nodeChildBox)
 | |
|       return;
 | |
| 
 | |
|     if (!aObjectBox.populated) {
 | |
|       let firstChild = this.view.getChildObject(aObjectBox.repObject, 0);
 | |
|       this.populateChildBox(firstChild, nodeChildBox);
 | |
|     }
 | |
|     let labelBox = aObjectBox.querySelector(".nodeLabelBox");
 | |
|     if (labelBox)
 | |
|       labelBox.setAttribute("aria-expanded", "true");
 | |
|     this.view.addClass(aObjectBox, "open");
 | |
|   },
 | |
| 
 | |
|   /**
 | |
|    * Contract the given object box.
 | |
|    * @param aObjectBox
 | |
|    *        The object box to contract.
 | |
|    */
 | |
|   contractObjectBox: function IOBox_contractObjectBox(aObjectBox)
 | |
|   {
 | |
|     this.view.removeClass(aObjectBox, "open");
 | |
|     let nodeLabel = aObjectBox.querySelector(".nodeLabel");
 | |
|     let labelBox = nodeLabel.querySelector(".nodeLabelBox");
 | |
|     if (labelBox)
 | |
|       labelBox.setAttribute("aria-expanded", "false");
 | |
|   },
 | |
| 
 | |
|   /**
 | |
|    * Toggle the given object box, forcing open if requested.
 | |
|    * @param aObjectBox
 | |
|    *        The object box to toggle.
 | |
|    * @param forceOpen
 | |
|    *        Force the objectbox open?
 | |
|    */
 | |
|   toggleObjectBox: function IOBox_toggleObjectBox(aObjectBox, forceOpen)
 | |
|   {
 | |
|     let isOpen = this.view.hasClass(aObjectBox, "open");
 | |
| 
 | |
|     if (!forceOpen && isOpen)
 | |
|       this.contractObjectBox(aObjectBox);
 | |
|     else if (!isOpen)
 | |
|       this.expandObjectBox(aObjectBox);
 | |
|   },
 | |
| 
 | |
|   /**
 | |
|    * Creates all of the boxes for an object, its ancestors, and siblings.
 | |
|    * @param aObject
 | |
|    *        The tree node to create the object boxes for.
 | |
|    * @returns anObjectBox or null
 | |
|    */
 | |
|   createObjectBox: function IOBox_createObjectBox(aObject)
 | |
|   {
 | |
|     if (!aObject)
 | |
|       return null;
 | |
| 
 | |
|     this.rootObject = this.getRootNode(aObject) || aObject;
 | |
| 
 | |
|     // Get or create all of the boxes for the target and its ancestors
 | |
|     let objectBox = this.createObjectBoxes(aObject, this.rootObject);
 | |
| 
 | |
|     if (!objectBox)
 | |
|       return null;
 | |
| 
 | |
|     if (aObject == this.rootObject)
 | |
|       return objectBox;
 | |
| 
 | |
|     return this.populateChildBox(aObject, objectBox.parentNode);
 | |
|   },
 | |
| 
 | |
|   /**
 | |
|    * Creates all of the boxes for an object, its ancestors, and siblings up to
 | |
|    * a root.
 | |
|    * @param aObject
 | |
|    *        The tree's object node to create the object boxes for.
 | |
|    * @param aRootObject
 | |
|    *        The root object at which to stop building object boxes.
 | |
|    * @returns an object box or null
 | |
|    */
 | |
|   createObjectBoxes: function IOBox_createObjectBoxes(aObject, aRootObject)
 | |
|   {
 | |
|     if (!aObject)
 | |
|       return null;
 | |
| 
 | |
|     if (aObject == aRootObject) {
 | |
|       if (!this.rootObjectBox || this.rootObjectBox.repObject != aRootObject) {
 | |
|         if (this.rootObjectBox) {
 | |
|           try {
 | |
|             this.box.removeChild(this.rootObjectBox);
 | |
|           } catch (exc) {
 | |
|             InspectorUI._log("this.box.removeChild(this.rootObjectBox) FAILS " +
 | |
|               this.box + " must not contain " + this.rootObjectBox);
 | |
|           }
 | |
|         }
 | |
| 
 | |
|         this.highlightedObjectBox = null;
 | |
|         this.selectedObjectBox = null;
 | |
|         this.rootObjectBox = this.view.createObjectBox(aObject, true);
 | |
|         this.box.appendChild(this.rootObjectBox);
 | |
|       }
 | |
|       return this.rootObjectBox;
 | |
|     }
 | |
| 
 | |
|     let parentNode = this.view.getParentObject(aObject);
 | |
|     let parentObjectBox = this.createObjectBoxes(parentNode, aRootObject);
 | |
| 
 | |
|     if (!parentObjectBox)
 | |
|       return null;
 | |
| 
 | |
|     let parentChildBox = this.getChildObjectBox(parentObjectBox);
 | |
| 
 | |
|     if (!parentChildBox)
 | |
|       return null;
 | |
| 
 | |
|     let childObjectBox = this.findChildObjectBox(parentChildBox, aObject);
 | |
| 
 | |
|     return childObjectBox ? childObjectBox
 | |
|       : this.populateChildBox(aObject, parentChildBox);
 | |
|   },
 | |
| 
 | |
|   /**
 | |
|    * Locate the object box for a given object node.
 | |
|    * @param aObject
 | |
|    *        The given object node in the tree.
 | |
|    * @returns an object box or null.
 | |
|    */
 | |
|   findObjectBox: function IOBox_findObjectBox(aObject)
 | |
|   {
 | |
|     if (!aObject)
 | |
|       return null;
 | |
| 
 | |
|     if (aObject == this.rootObject)
 | |
|       return this.rootObjectBox;
 | |
| 
 | |
|     let parentNode = this.view.getParentObject(aObject);
 | |
|     let parentObjectBox = this.findObjectBox(parentNode);
 | |
|     if (!parentObjectBox)
 | |
|       return null;
 | |
| 
 | |
|     let parentChildBox = this.getChildObjectBox(parentObjectBox);
 | |
|     if (!parentChildBox)
 | |
|       return null;
 | |
| 
 | |
|     return this.findChildObjectBox(parentChildBox, aObject);
 | |
|   },
 | |
| 
 | |
|   getAncestorByClass: function IOBox_getAncestorByClass(node, className)
 | |
|   {
 | |
|     for (let parent = node; parent; parent = parent.parentNode) {
 | |
|       if (this.view.hasClass(parent, className))
 | |
|         return parent;
 | |
|     }
 | |
| 
 | |
|     return null;
 | |
|   },
 | |
| 
 | |
|   /**
 | |
|    * We want all children of the parent of repObject.
 | |
|    */
 | |
|   populateChildBox: function IOBox_populateChildBox(repObject, nodeChildBox)
 | |
|   {
 | |
|     if (!repObject)
 | |
|       return null;
 | |
| 
 | |
|     let parentObjectBox = this.getAncestorByClass(nodeChildBox, "nodeBox");
 | |
| 
 | |
|     if (parentObjectBox.populated)
 | |
|       return this.findChildObjectBox(nodeChildBox, repObject);
 | |
| 
 | |
|     let lastSiblingBox = this.getChildObjectBox(nodeChildBox);
 | |
|     let siblingBox = nodeChildBox.firstChild;
 | |
|     let targetBox = null;
 | |
|     let view = this.view;
 | |
|     let targetSibling = null;
 | |
|     let parentNode = view.getParentObject(repObject);
 | |
| 
 | |
|     for (let i = 0; 1; ++i) {
 | |
|       targetSibling = view.getChildObject(parentNode, i, targetSibling);
 | |
|       if (!targetSibling)
 | |
|         break;
 | |
| 
 | |
|       // Check if we need to start appending, or continue to insert before
 | |
|       if (lastSiblingBox && lastSiblingBox.repObject == targetSibling)
 | |
|         lastSiblingBox = null;
 | |
| 
 | |
|       if (!siblingBox || siblingBox.repObject != targetSibling) {
 | |
|         let newBox = view.createObjectBox(targetSibling);
 | |
|         if (newBox) {
 | |
|           if (lastSiblingBox)
 | |
|             nodeChildBox.insertBefore(newBox, lastSiblingBox);
 | |
|           else
 | |
|             nodeChildBox.appendChild(newBox);
 | |
|         }
 | |
| 
 | |
|         siblingBox = newBox;
 | |
|       }
 | |
| 
 | |
|       if (targetSibling == repObject)
 | |
|         targetBox = siblingBox;
 | |
| 
 | |
|       if (siblingBox && siblingBox.repObject == targetSibling)
 | |
|         siblingBox = siblingBox.nextSibling;
 | |
|     }
 | |
| 
 | |
|     if (targetBox)
 | |
|       parentObjectBox.populated = true;
 | |
| 
 | |
|     return targetBox;
 | |
|   },
 | |
| 
 | |
|   /**
 | |
|    * Get the parent object box of a given object box.
 | |
|    * @params aObjectBox
 | |
|    *         The object box of the parent.
 | |
|    * @returns an object box or null
 | |
|    */
 | |
|   getParentObjectBox: function IOBox_getParentObjectBox(aObjectBox)
 | |
|   {
 | |
|     let parent = aObjectBox.parentNode ? aObjectBox.parentNode.parentNode : null;
 | |
|     return parent && parent.repObject ? parent : null;
 | |
|   },
 | |
| 
 | |
|   /**
 | |
|    * Get the child object box of a given object box.
 | |
|    * @param aObjectBox
 | |
|    *        The object box whose child you want.
 | |
|    * @returns an object box or null
 | |
|    */
 | |
|   getChildObjectBox: function IOBox_getChildObjectBox(aObjectBox)
 | |
|   {
 | |
|     return aObjectBox.querySelector(".nodeChildBox");
 | |
|   },
 | |
| 
 | |
|   /**
 | |
|    * Find the child object box for a given repObject within the subtree
 | |
|    * rooted at aParentNodeBox.
 | |
|    * @param aParentNodeBox
 | |
|    *        root of the subtree in which to search for repObject.
 | |
|    * @param aRepObject
 | |
|    *        The object you wish to locate in the subtree.
 | |
|    * @returns an object box or null
 | |
|    */
 | |
|   findChildObjectBox: function IOBox_findChildObjectBox(aParentNodeBox, aRepObject)
 | |
|   {
 | |
|     let childBox = aParentNodeBox.firstChild;
 | |
|     while (childBox) {
 | |
|       if (childBox.repObject == aRepObject)
 | |
|         return childBox;
 | |
|       childBox = childBox.nextSibling;
 | |
|     }
 | |
|     return null; // not found
 | |
|   },
 | |
| 
 | |
|   /**
 | |
|    * Determines if the given node is an ancestor of the current root.
 | |
|    * @param aNode
 | |
|    *        The node to look for within the tree.
 | |
|    * @returns boolean
 | |
|    */
 | |
|   isInExistingRoot: function IOBox_isInExistingRoot(aNode)
 | |
|   {
 | |
|     let parentNode = aNode;
 | |
|     while (parentNode && parentNode != this.rootObject) {
 | |
|       parentNode = this.view.getParentObject(parentNode);
 | |
|     }
 | |
|     return parentNode == this.rootObject;
 | |
|   },
 | |
| 
 | |
|   /**
 | |
|    * Get the root node of a given node.
 | |
|    * @param aNode
 | |
|    *        The node whose root you wish to retrieve.
 | |
|    * @returns a root node or null
 | |
|    */
 | |
|   getRootNode: function IOBox_getRootNode(aNode)
 | |
|   {
 | |
|     let node = aNode;
 | |
|     let tmpNode;
 | |
|     while ((tmpNode = this.view.getParentObject(node)))
 | |
|       node = tmpNode;
 | |
| 
 | |
|     return node;
 | |
|   },
 | |
| };
 | 
