| Index: chrome_frame/tools/test/reference_build/chrome/resources/inspector/treeoutline.js | 
| =================================================================== | 
| --- chrome_frame/tools/test/reference_build/chrome/resources/inspector/treeoutline.js	(revision 0) | 
| +++ chrome_frame/tools/test/reference_build/chrome/resources/inspector/treeoutline.js	(revision 0) | 
| @@ -0,0 +1,849 @@ | 
| +/* | 
| + * Copyright (C) 2007 Apple Inc.  All rights reserved. | 
| + * | 
| + * Redistribution and use in source and binary forms, with or without | 
| + * modification, are permitted provided that the following conditions | 
| + * are met: | 
| + * | 
| + * 1.  Redistributions of source code must retain the above copyright | 
| + *     notice, this list of conditions and the following disclaimer. | 
| + * 2.  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. | 
| + * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of | 
| + *     its contributors may be used to endorse or promote products derived | 
| + *     from this software without specific prior written permission. | 
| + * | 
| + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS 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 APPLE OR ITS 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. | 
| + */ | 
| + | 
| +function TreeOutline(listNode) | 
| +{ | 
| +    this.children = []; | 
| +    this.selectedTreeElement = null; | 
| +    this._childrenListNode = listNode; | 
| +    this._childrenListNode.removeChildren(); | 
| +    this._knownTreeElements = []; | 
| +    this._treeElementsExpandedState = []; | 
| +    this.expandTreeElementsWhenArrowing = false; | 
| +    this.root = true; | 
| +    this.hasChildren = false; | 
| +    this.expanded = true; | 
| +    this.selected = false; | 
| +    this.treeOutline = this; | 
| +} | 
| + | 
| +TreeOutline._knownTreeElementNextIdentifier = 1; | 
| + | 
| +TreeOutline._appendChild = function(child) | 
| +{ | 
| +    if (!child) | 
| +        throw("child can't be undefined or null"); | 
| + | 
| +    var lastChild = this.children[this.children.length - 1]; | 
| +    if (lastChild) { | 
| +        lastChild.nextSibling = child; | 
| +        child.previousSibling = lastChild; | 
| +    } else { | 
| +        child.previousSibling = null; | 
| +        child.nextSibling = null; | 
| +    } | 
| + | 
| +    this.children.push(child); | 
| +    this.hasChildren = true; | 
| +    child.parent = this; | 
| +    child.treeOutline = this.treeOutline; | 
| +    child.treeOutline._rememberTreeElement(child); | 
| + | 
| +    var current = child.children[0]; | 
| +    while (current) { | 
| +        current.treeOutline = this.treeOutline; | 
| +        current.treeOutline._rememberTreeElement(current); | 
| +        current = current.traverseNextTreeElement(false, child, true); | 
| +    } | 
| + | 
| +    if (child.hasChildren && child.treeOutline._treeElementsExpandedState[child.identifier] !== undefined) | 
| +        child.expanded = child.treeOutline._treeElementsExpandedState[child.identifier]; | 
| + | 
| +    if (!this._childrenListNode) { | 
| +        this._childrenListNode = this.treeOutline._childrenListNode.ownerDocument.createElement("ol"); | 
| +        this._childrenListNode.parentTreeElement = this; | 
| +        this._childrenListNode.addStyleClass("children"); | 
| +        if (this.hidden) | 
| +            this._childrenListNode.addStyleClass("hidden"); | 
| +    } | 
| + | 
| +    child._attach(); | 
| +} | 
| + | 
| +TreeOutline._insertChild = function(child, index) | 
| +{ | 
| +    if (!child) | 
| +        throw("child can't be undefined or null"); | 
| + | 
| +    var previousChild = (index > 0 ? this.children[index - 1] : null); | 
| +    if (previousChild) { | 
| +        previousChild.nextSibling = child; | 
| +        child.previousSibling = previousChild; | 
| +    } else { | 
| +        child.previousSibling = null; | 
| +    } | 
| + | 
| +    var nextChild = this.children[index]; | 
| +    if (nextChild) { | 
| +        nextChild.previousSibling = child; | 
| +        child.nextSibling = nextChild; | 
| +    } else { | 
| +        child.nextSibling = null; | 
| +    } | 
| + | 
| +    this.children.splice(index, 0, child); | 
| +    this.hasChildren = true; | 
| +    child.parent = this; | 
| +    child.treeOutline = this.treeOutline; | 
| +    child.treeOutline._rememberTreeElement(child); | 
| + | 
| +    var current = child.children[0]; | 
| +    while (current) { | 
| +        current.treeOutline = this.treeOutline; | 
| +        current.treeOutline._rememberTreeElement(current); | 
| +        current = current.traverseNextTreeElement(false, child, true); | 
| +    } | 
| + | 
| +    if (child.hasChildren && child.treeOutline._treeElementsExpandedState[child.identifier] !== undefined) | 
| +        child.expanded = child.treeOutline._treeElementsExpandedState[child.identifier]; | 
| + | 
| +    if (!this._childrenListNode) { | 
| +        this._childrenListNode = this.treeOutline._childrenListNode.ownerDocument.createElement("ol"); | 
| +        this._childrenListNode.parentTreeElement = this; | 
| +        this._childrenListNode.addStyleClass("children"); | 
| +        if (this.hidden) | 
| +            this._childrenListNode.addStyleClass("hidden"); | 
| +    } | 
| + | 
| +    child._attach(); | 
| +} | 
| + | 
| +TreeOutline._removeChildAtIndex = function(childIndex) | 
| +{ | 
| +    if (childIndex < 0 || childIndex >= this.children.length) | 
| +        throw("childIndex out of range"); | 
| + | 
| +    var child = this.children[childIndex]; | 
| +    this.children.splice(childIndex, 1); | 
| + | 
| +    child.deselect(); | 
| + | 
| +    if (child.previousSibling) | 
| +        child.previousSibling.nextSibling = child.nextSibling; | 
| +    if (child.nextSibling) | 
| +        child.nextSibling.previousSibling = child.previousSibling; | 
| + | 
| +    if (child.treeOutline) { | 
| +        child.treeOutline._forgetTreeElement(child); | 
| +        child.treeOutline._forgetChildrenRecursive(child); | 
| +    } | 
| + | 
| +    child._detach(); | 
| +    child.treeOutline = null; | 
| +    child.parent = null; | 
| +    child.nextSibling = null; | 
| +    child.previousSibling = null; | 
| +} | 
| + | 
| +TreeOutline._removeChild = function(child) | 
| +{ | 
| +    if (!child) | 
| +        throw("child can't be undefined or null"); | 
| + | 
| +    var childIndex = this.children.indexOf(child); | 
| +    if (childIndex === -1) | 
| +        throw("child not found in this node's children"); | 
| + | 
| +    TreeOutline._removeChildAtIndex.call(this, childIndex); | 
| +} | 
| + | 
| +TreeOutline._removeChildren = function() | 
| +{ | 
| +    for (var i = 0; i < this.children.length; ++i) { | 
| +        var child = this.children[i]; | 
| +        child.deselect(); | 
| + | 
| +        if (child.treeOutline) { | 
| +            child.treeOutline._forgetTreeElement(child); | 
| +            child.treeOutline._forgetChildrenRecursive(child); | 
| +        } | 
| + | 
| +        child._detach(); | 
| +        child.treeOutline = null; | 
| +        child.parent = null; | 
| +        child.nextSibling = null; | 
| +        child.previousSibling = null; | 
| +    } | 
| + | 
| +    this.children = []; | 
| +} | 
| + | 
| +TreeOutline._removeChildrenRecursive = function() | 
| +{ | 
| +    var childrenToRemove = this.children; | 
| + | 
| +    var child = this.children[0]; | 
| +    while (child) { | 
| +        if (child.children.length) | 
| +            childrenToRemove = childrenToRemove.concat(child.children); | 
| +        child = child.traverseNextTreeElement(false, this, true); | 
| +    } | 
| + | 
| +    for (var i = 0; i < childrenToRemove.length; ++i) { | 
| +        var child = childrenToRemove[i]; | 
| +        child.deselect(); | 
| +        if (child.treeOutline) | 
| +            child.treeOutline._forgetTreeElement(child); | 
| +        child._detach(); | 
| +        child.children = []; | 
| +        child.treeOutline = null; | 
| +        child.parent = null; | 
| +        child.nextSibling = null; | 
| +        child.previousSibling = null; | 
| +    } | 
| + | 
| +    this.children = []; | 
| +} | 
| + | 
| +TreeOutline.prototype._rememberTreeElement = function(element) | 
| +{ | 
| +    if (!this._knownTreeElements[element.identifier]) | 
| +        this._knownTreeElements[element.identifier] = []; | 
| + | 
| +    // check if the element is already known | 
| +    var elements = this._knownTreeElements[element.identifier]; | 
| +    if (elements.indexOf(element) !== -1) | 
| +        return; | 
| + | 
| +    // add the element | 
| +    elements.push(element); | 
| +} | 
| + | 
| +TreeOutline.prototype._forgetTreeElement = function(element) | 
| +{ | 
| +    if (this._knownTreeElements[element.identifier]) | 
| +        this._knownTreeElements[element.identifier].remove(element, true); | 
| +} | 
| + | 
| +TreeOutline.prototype._forgetChildrenRecursive = function(parentElement) | 
| +{ | 
| +    var child = parentElement.children[0]; | 
| +    while (child) { | 
| +        this._forgetTreeElement(child); | 
| +        child = child.traverseNextTreeElement(false, this, true); | 
| +    } | 
| +} | 
| + | 
| +TreeOutline.prototype.getCachedTreeElement = function(representedObject) | 
| +{ | 
| +    if (!representedObject) | 
| +        return null; | 
| + | 
| +    if ("__treeElementIdentifier" in representedObject) { | 
| +        // If this representedObject has a tree element identifier, and it is a known TreeElement | 
| +        // in our tree we can just return that tree element. | 
| +        var elements = this._knownTreeElements[representedObject.__treeElementIdentifier]; | 
| +        if (elements) { | 
| +            for (var i = 0; i < elements.length; ++i) | 
| +                if (elements[i].representedObject === representedObject) | 
| +                    return elements[i]; | 
| +        } | 
| +    } | 
| +    return null; | 
| +} | 
| + | 
| +TreeOutline.prototype.findTreeElement = function(representedObject, isAncestor, getParent) | 
| +{ | 
| +    if (!representedObject) | 
| +        return null; | 
| + | 
| +    var cachedElement = this.getCachedTreeElement(representedObject); | 
| +    if (cachedElement) | 
| +        return cachedElement; | 
| + | 
| +    // The representedObject isn't know, so we start at the top of the tree and work down to find the first | 
| +    // tree element that represents representedObject or one of its ancestors. | 
| +    var item; | 
| +    var found = false; | 
| +    for (var i = 0; i < this.children.length; ++i) { | 
| +        item = this.children[i]; | 
| +        if (item.representedObject === representedObject || isAncestor(item.representedObject, representedObject)) { | 
| +            found = true; | 
| +            break; | 
| +        } | 
| +    } | 
| + | 
| +    if (!found) | 
| +        return null; | 
| + | 
| +    // Make sure the item that we found is connected to the root of the tree. | 
| +    // Build up a list of representedObject's ancestors that aren't already in our tree. | 
| +    var ancestors = []; | 
| +    var currentObject = representedObject; | 
| +    while (currentObject) { | 
| +        ancestors.unshift(currentObject); | 
| +        if (currentObject === item.representedObject) | 
| +            break; | 
| +        currentObject = getParent(currentObject); | 
| +    } | 
| + | 
| +    // For each of those ancestors we populate them to fill in the tree. | 
| +    for (var i = 0; i < ancestors.length; ++i) { | 
| +        // Make sure we don't call findTreeElement with the same representedObject | 
| +        // again, to prevent infinite recursion. | 
| +        if (ancestors[i] === representedObject) | 
| +            continue; | 
| +        // FIXME: we could do something faster than findTreeElement since we will know the next | 
| +        // ancestor exists in the tree. | 
| +        item = this.findTreeElement(ancestors[i], isAncestor, getParent); | 
| +        if (item && item.onpopulate) | 
| +            item.onpopulate(item); | 
| +    } | 
| + | 
| +    return this.getCachedTreeElement(representedObject); | 
| +} | 
| + | 
| +TreeOutline.prototype.treeElementFromPoint = function(x, y) | 
| +{ | 
| +    var node = this._childrenListNode.ownerDocument.elementFromPoint(x, y); | 
| +    var listNode = node.enclosingNodeOrSelfWithNodeNameInArray(["ol", "li"]); | 
| +    if (listNode) | 
| +        return listNode.parentTreeElement || listNode.treeElement; | 
| +    return null; | 
| +} | 
| + | 
| +TreeOutline.prototype.handleKeyEvent = function(event) | 
| +{ | 
| +    if (!this.selectedTreeElement || event.shiftKey || event.metaKey || event.ctrlKey) | 
| +        return false; | 
| + | 
| +    var handled = false; | 
| +    var nextSelectedElement; | 
| +    if (event.keyIdentifier === "Up" && !event.altKey) { | 
| +        nextSelectedElement = this.selectedTreeElement.traversePreviousTreeElement(true); | 
| +        while (nextSelectedElement && !nextSelectedElement.selectable) | 
| +            nextSelectedElement = nextSelectedElement.traversePreviousTreeElement(!this.expandTreeElementsWhenArrowing); | 
| +        handled = nextSelectedElement ? true : false; | 
| +    } else if (event.keyIdentifier === "Down" && !event.altKey) { | 
| +        nextSelectedElement = this.selectedTreeElement.traverseNextTreeElement(true); | 
| +        while (nextSelectedElement && !nextSelectedElement.selectable) | 
| +            nextSelectedElement = nextSelectedElement.traverseNextTreeElement(!this.expandTreeElementsWhenArrowing); | 
| +        handled = nextSelectedElement ? true : false; | 
| +    } else if (event.keyIdentifier === "Left") { | 
| +        if (this.selectedTreeElement.expanded) { | 
| +            if (event.altKey) | 
| +                this.selectedTreeElement.collapseRecursively(); | 
| +            else | 
| +                this.selectedTreeElement.collapse(); | 
| +            handled = true; | 
| +        } else if (this.selectedTreeElement.parent && !this.selectedTreeElement.parent.root) { | 
| +            handled = true; | 
| +            if (this.selectedTreeElement.parent.selectable) { | 
| +                nextSelectedElement = this.selectedTreeElement.parent; | 
| +                handled = nextSelectedElement ? true : false; | 
| +            } else if (this.selectedTreeElement.parent) | 
| +                this.selectedTreeElement.parent.collapse(); | 
| +        } | 
| +    } else if (event.keyIdentifier === "Right") { | 
| +        if (!this.selectedTreeElement.revealed()) { | 
| +            this.selectedTreeElement.reveal(); | 
| +            handled = true; | 
| +        } else if (this.selectedTreeElement.hasChildren) { | 
| +            handled = true; | 
| +            if (this.selectedTreeElement.expanded) { | 
| +                nextSelectedElement = this.selectedTreeElement.children[0]; | 
| +                handled = nextSelectedElement ? true : false; | 
| +            } else { | 
| +                if (event.altKey) | 
| +                    this.selectedTreeElement.expandRecursively(); | 
| +                else | 
| +                    this.selectedTreeElement.expand(); | 
| +            } | 
| +        } | 
| +    } | 
| + | 
| +    if (nextSelectedElement) { | 
| +        nextSelectedElement.reveal(); | 
| +        nextSelectedElement.select(); | 
| +    } | 
| + | 
| +    if (handled) { | 
| +        event.preventDefault(); | 
| +        event.stopPropagation(); | 
| +    } | 
| + | 
| +    return handled; | 
| +} | 
| + | 
| +TreeOutline.prototype.expand = function() | 
| +{ | 
| +    // this is the root, do nothing | 
| +} | 
| + | 
| +TreeOutline.prototype.collapse = function() | 
| +{ | 
| +    // this is the root, do nothing | 
| +} | 
| + | 
| +TreeOutline.prototype.revealed = function() | 
| +{ | 
| +    return true; | 
| +} | 
| + | 
| +TreeOutline.prototype.reveal = function() | 
| +{ | 
| +    // this is the root, do nothing | 
| +} | 
| + | 
| +TreeOutline.prototype.appendChild = TreeOutline._appendChild; | 
| +TreeOutline.prototype.insertChild = TreeOutline._insertChild; | 
| +TreeOutline.prototype.removeChild = TreeOutline._removeChild; | 
| +TreeOutline.prototype.removeChildAtIndex = TreeOutline._removeChildAtIndex; | 
| +TreeOutline.prototype.removeChildren = TreeOutline._removeChildren; | 
| +TreeOutline.prototype.removeChildrenRecursive = TreeOutline._removeChildrenRecursive; | 
| + | 
| +function TreeElement(title, representedObject, hasChildren) | 
| +{ | 
| +    this._title = title; | 
| +    this.representedObject = (representedObject || {}); | 
| + | 
| +    if (this.representedObject.__treeElementIdentifier) | 
| +        this.identifier = this.representedObject.__treeElementIdentifier; | 
| +    else { | 
| +        this.identifier = TreeOutline._knownTreeElementNextIdentifier++; | 
| +        this.representedObject.__treeElementIdentifier = this.identifier; | 
| +    } | 
| + | 
| +    this._hidden = false; | 
| +    this.expanded = false; | 
| +    this.selected = false; | 
| +    this.hasChildren = hasChildren; | 
| +    this.children = []; | 
| +    this.treeOutline = null; | 
| +    this.parent = null; | 
| +    this.previousSibling = null; | 
| +    this.nextSibling = null; | 
| +    this._listItemNode = null; | 
| +} | 
| + | 
| +TreeElement.prototype = { | 
| +    selectable: true, | 
| +    arrowToggleWidth: 10, | 
| + | 
| +    get listItemElement() { | 
| +        return this._listItemNode; | 
| +    }, | 
| + | 
| +    get childrenListElement() { | 
| +        return this._childrenListNode; | 
| +    }, | 
| + | 
| +    get title() { | 
| +        return this._title; | 
| +    }, | 
| + | 
| +    set title(x) { | 
| +        this._title = x; | 
| +        if (this._listItemNode) | 
| +            this._listItemNode.innerHTML = x; | 
| +    }, | 
| + | 
| +    get tooltip() { | 
| +        return this._tooltip; | 
| +    }, | 
| + | 
| +    set tooltip(x) { | 
| +        this._tooltip = x; | 
| +        if (this._listItemNode) | 
| +            this._listItemNode.title = x ? x : ""; | 
| +    }, | 
| + | 
| +    get hasChildren() { | 
| +        return this._hasChildren; | 
| +    }, | 
| + | 
| +    set hasChildren(x) { | 
| +        if (this._hasChildren === x) | 
| +            return; | 
| + | 
| +        this._hasChildren = x; | 
| + | 
| +        if (!this._listItemNode) | 
| +            return; | 
| + | 
| +        if (x) | 
| +            this._listItemNode.addStyleClass("parent"); | 
| +        else { | 
| +            this._listItemNode.removeStyleClass("parent"); | 
| +            this.collapse(); | 
| +        } | 
| +    }, | 
| + | 
| +    get hidden() { | 
| +        return this._hidden; | 
| +    }, | 
| + | 
| +    set hidden(x) { | 
| +        if (this._hidden === x) | 
| +            return; | 
| + | 
| +        this._hidden = x; | 
| + | 
| +        if (x) { | 
| +            if (this._listItemNode) | 
| +                this._listItemNode.addStyleClass("hidden"); | 
| +            if (this._childrenListNode) | 
| +                this._childrenListNode.addStyleClass("hidden"); | 
| +        } else { | 
| +            if (this._listItemNode) | 
| +                this._listItemNode.removeStyleClass("hidden"); | 
| +            if (this._childrenListNode) | 
| +                this._childrenListNode.removeStyleClass("hidden"); | 
| +        } | 
| +    }, | 
| + | 
| +    get shouldRefreshChildren() { | 
| +        return this._shouldRefreshChildren; | 
| +    }, | 
| + | 
| +    set shouldRefreshChildren(x) { | 
| +        this._shouldRefreshChildren = x; | 
| +        if (x && this.expanded) | 
| +            this.expand(); | 
| +    } | 
| +} | 
| + | 
| +TreeElement.prototype.appendChild = TreeOutline._appendChild; | 
| +TreeElement.prototype.insertChild = TreeOutline._insertChild; | 
| +TreeElement.prototype.removeChild = TreeOutline._removeChild; | 
| +TreeElement.prototype.removeChildAtIndex = TreeOutline._removeChildAtIndex; | 
| +TreeElement.prototype.removeChildren = TreeOutline._removeChildren; | 
| +TreeElement.prototype.removeChildrenRecursive = TreeOutline._removeChildrenRecursive; | 
| + | 
| +TreeElement.prototype._attach = function() | 
| +{ | 
| +    if (!this._listItemNode || this.parent._shouldRefreshChildren) { | 
| +        if (this._listItemNode && this._listItemNode.parentNode) | 
| +            this._listItemNode.parentNode.removeChild(this._listItemNode); | 
| + | 
| +        this._listItemNode = this.treeOutline._childrenListNode.ownerDocument.createElement("li"); | 
| +        this._listItemNode.treeElement = this; | 
| +        this._listItemNode.innerHTML = this._title; | 
| +        this._listItemNode.title = this._tooltip ? this._tooltip : ""; | 
| + | 
| +        if (this.hidden) | 
| +            this._listItemNode.addStyleClass("hidden"); | 
| +        if (this.hasChildren) | 
| +            this._listItemNode.addStyleClass("parent"); | 
| +        if (this.expanded) | 
| +            this._listItemNode.addStyleClass("expanded"); | 
| +        if (this.selected) | 
| +            this._listItemNode.addStyleClass("selected"); | 
| + | 
| +        this._listItemNode.addEventListener("mousedown", TreeElement.treeElementSelected, false); | 
| +        this._listItemNode.addEventListener("click", TreeElement.treeElementToggled, false); | 
| +        this._listItemNode.addEventListener("dblclick", TreeElement.treeElementDoubleClicked, false); | 
| + | 
| +        if (this.onattach) | 
| +            this.onattach(this); | 
| +    } | 
| + | 
| +    var nextSibling = null; | 
| +    if (this.nextSibling && this.nextSibling._listItemNode && this.nextSibling._listItemNode.parentNode === this.parent._childrenListNode) | 
| +        nextSibling = this.nextSibling._listItemNode; | 
| +    this.parent._childrenListNode.insertBefore(this._listItemNode, nextSibling); | 
| +    if (this._childrenListNode) | 
| +        this.parent._childrenListNode.insertBefore(this._childrenListNode, this._listItemNode.nextSibling); | 
| +    if (this.selected) | 
| +        this.select(); | 
| +    if (this.expanded) | 
| +        this.expand(); | 
| +} | 
| + | 
| +TreeElement.prototype._detach = function() | 
| +{ | 
| +    if (this._listItemNode && this._listItemNode.parentNode) | 
| +        this._listItemNode.parentNode.removeChild(this._listItemNode); | 
| +    if (this._childrenListNode && this._childrenListNode.parentNode) | 
| +        this._childrenListNode.parentNode.removeChild(this._childrenListNode); | 
| +} | 
| + | 
| +TreeElement.treeElementSelected = function(event) | 
| +{ | 
| +    var element = event.currentTarget; | 
| +    if (!element || !element.treeElement || !element.treeElement.selectable) | 
| +        return; | 
| + | 
| +    if (element.treeElement.isEventWithinDisclosureTriangle(event)) | 
| +        return; | 
| + | 
| +    element.treeElement.select(); | 
| +} | 
| + | 
| +TreeElement.treeElementToggled = function(event) | 
| +{ | 
| +    var element = event.currentTarget; | 
| +    if (!element || !element.treeElement) | 
| +        return; | 
| + | 
| +    if (!element.treeElement.isEventWithinDisclosureTriangle(event)) | 
| +        return; | 
| + | 
| +    if (element.treeElement.expanded) { | 
| +        if (event.altKey) | 
| +            element.treeElement.collapseRecursively(); | 
| +        else | 
| +            element.treeElement.collapse(); | 
| +    } else { | 
| +        if (event.altKey) | 
| +            element.treeElement.expandRecursively(); | 
| +        else | 
| +            element.treeElement.expand(); | 
| +    } | 
| +} | 
| + | 
| +TreeElement.treeElementDoubleClicked = function(event) | 
| +{ | 
| +    var element = event.currentTarget; | 
| +    if (!element || !element.treeElement) | 
| +        return; | 
| + | 
| +    if (element.treeElement.ondblclick) | 
| +        element.treeElement.ondblclick(element.treeElement, event); | 
| +    else if (element.treeElement.hasChildren && !element.treeElement.expanded) | 
| +        element.treeElement.expand(); | 
| +} | 
| + | 
| +TreeElement.prototype.collapse = function() | 
| +{ | 
| +    if (this._listItemNode) | 
| +        this._listItemNode.removeStyleClass("expanded"); | 
| +    if (this._childrenListNode) | 
| +        this._childrenListNode.removeStyleClass("expanded"); | 
| + | 
| +    this.expanded = false; | 
| +    if (this.treeOutline) | 
| +        this.treeOutline._treeElementsExpandedState[this.identifier] = true; | 
| + | 
| +    if (this.oncollapse) | 
| +        this.oncollapse(this); | 
| +} | 
| + | 
| +TreeElement.prototype.collapseRecursively = function() | 
| +{ | 
| +    var item = this; | 
| +    while (item) { | 
| +        if (item.expanded) | 
| +            item.collapse(); | 
| +        item = item.traverseNextTreeElement(false, this, true); | 
| +    } | 
| +} | 
| + | 
| +TreeElement.prototype.expand = function() | 
| +{ | 
| +    if (!this.hasChildren || (this.expanded && !this._shouldRefreshChildren && this._childrenListNode)) | 
| +        return; | 
| + | 
| +    if (this.treeOutline && (!this._childrenListNode || this._shouldRefreshChildren)) { | 
| +        if (this._childrenListNode && this._childrenListNode.parentNode) | 
| +            this._childrenListNode.parentNode.removeChild(this._childrenListNode); | 
| + | 
| +        this._childrenListNode = this.treeOutline._childrenListNode.ownerDocument.createElement("ol"); | 
| +        this._childrenListNode.parentTreeElement = this; | 
| +        this._childrenListNode.addStyleClass("children"); | 
| + | 
| +        if (this.hidden) | 
| +            this._childrenListNode.addStyleClass("hidden"); | 
| + | 
| +        if (this.onpopulate) | 
| +            this.onpopulate(this); | 
| + | 
| +        for (var i = 0; i < this.children.length; ++i) | 
| +            this.children[i]._attach(); | 
| + | 
| +        delete this._shouldRefreshChildren; | 
| +    } | 
| + | 
| +    if (this._listItemNode) { | 
| +        this._listItemNode.addStyleClass("expanded"); | 
| +        if (this._childrenListNode && this._childrenListNode.parentNode != this._listItemNode.parentNode) | 
| +            this.parent._childrenListNode.insertBefore(this._childrenListNode, this._listItemNode.nextSibling); | 
| +    } | 
| + | 
| +    if (this._childrenListNode) | 
| +        this._childrenListNode.addStyleClass("expanded"); | 
| + | 
| +    this.expanded = true; | 
| +    if (this.treeOutline) | 
| +        this.treeOutline._treeElementsExpandedState[this.identifier] = true; | 
| + | 
| +    if (this.onexpand) | 
| +        this.onexpand(this); | 
| +} | 
| + | 
| +TreeElement.prototype.expandRecursively = function(maxDepth) | 
| +{ | 
| +    var item = this; | 
| +    var info = {}; | 
| +    var depth = 0; | 
| + | 
| +    // The Inspector uses TreeOutlines to represents object properties, so recursive expansion | 
| +    // in some case can be infinite, since JavaScript objects can hold circular references. | 
| +    // So default to a recursion cap of 3 levels, since that gives fairly good results. | 
| +    if (typeof maxDepth === "undefined" || typeof maxDepth === "null") | 
| +        maxDepth = 3; | 
| + | 
| +    while (item) { | 
| +        if (depth < maxDepth) | 
| +            item.expand(); | 
| +        item = item.traverseNextTreeElement(false, this, (depth >= maxDepth), info); | 
| +        depth += info.depthChange; | 
| +    } | 
| +} | 
| + | 
| +TreeElement.prototype.hasAncestor = function(ancestor) { | 
| +    if (!ancestor) | 
| +        return false; | 
| + | 
| +    var currentNode = this.parent; | 
| +    while (currentNode) { | 
| +        if (ancestor === currentNode) | 
| +            return true; | 
| +        currentNode = currentNode.parent; | 
| +    } | 
| + | 
| +    return false; | 
| +} | 
| + | 
| +TreeElement.prototype.reveal = function() | 
| +{ | 
| +    var currentAncestor = this.parent; | 
| +    while (currentAncestor && !currentAncestor.root) { | 
| +        if (!currentAncestor.expanded) | 
| +            currentAncestor.expand(); | 
| +        currentAncestor = currentAncestor.parent; | 
| +    } | 
| + | 
| +    if (this.onreveal) | 
| +        this.onreveal(this); | 
| +} | 
| + | 
| +TreeElement.prototype.revealed = function() | 
| +{ | 
| +    var currentAncestor = this.parent; | 
| +    while (currentAncestor && !currentAncestor.root) { | 
| +        if (!currentAncestor.expanded) | 
| +            return false; | 
| +        currentAncestor = currentAncestor.parent; | 
| +    } | 
| + | 
| +    return true; | 
| +} | 
| + | 
| +TreeElement.prototype.select = function(supressOnSelect) | 
| +{ | 
| +    if (!this.treeOutline || !this.selectable || this.selected) | 
| +        return; | 
| + | 
| +    if (this.treeOutline.selectedTreeElement) | 
| +        this.treeOutline.selectedTreeElement.deselect(); | 
| + | 
| +    this.selected = true; | 
| +    this.treeOutline.selectedTreeElement = this; | 
| +    if (this._listItemNode) | 
| +        this._listItemNode.addStyleClass("selected"); | 
| + | 
| +    if (this.onselect && !supressOnSelect) | 
| +        this.onselect(this); | 
| +} | 
| + | 
| +TreeElement.prototype.deselect = function(supressOnDeselect) | 
| +{ | 
| +    if (!this.treeOutline || this.treeOutline.selectedTreeElement !== this || !this.selected) | 
| +        return; | 
| + | 
| +    this.selected = false; | 
| +    this.treeOutline.selectedTreeElement = null; | 
| +    if (this._listItemNode) | 
| +        this._listItemNode.removeStyleClass("selected"); | 
| + | 
| +    if (this.ondeselect && !supressOnDeselect) | 
| +        this.ondeselect(this); | 
| +} | 
| + | 
| +TreeElement.prototype.traverseNextTreeElement = function(skipHidden, stayWithin, dontPopulate, info) | 
| +{ | 
| +    if (!dontPopulate && this.hasChildren && this.onpopulate) | 
| +        this.onpopulate(this); | 
| + | 
| +    if (info) | 
| +        info.depthChange = 0; | 
| + | 
| +    var element = skipHidden ? (this.revealed() ? this.children[0] : null) : this.children[0]; | 
| +    if (element && (!skipHidden || (skipHidden && this.expanded))) { | 
| +        if (info) | 
| +            info.depthChange = 1; | 
| +        return element; | 
| +    } | 
| + | 
| +    if (this === stayWithin) | 
| +        return null; | 
| + | 
| +    element = skipHidden ? (this.revealed() ? this.nextSibling : null) : this.nextSibling; | 
| +    if (element) | 
| +        return element; | 
| + | 
| +    element = this; | 
| +    while (element && !element.root && !(skipHidden ? (element.revealed() ? element.nextSibling : null) : element.nextSibling) && element.parent !== stayWithin) { | 
| +        if (info) | 
| +            info.depthChange -= 1; | 
| +        element = element.parent; | 
| +    } | 
| + | 
| +    if (!element) | 
| +        return null; | 
| + | 
| +    return (skipHidden ? (element.revealed() ? element.nextSibling : null) : element.nextSibling); | 
| +} | 
| + | 
| +TreeElement.prototype.traversePreviousTreeElement = function(skipHidden, dontPopulate) | 
| +{ | 
| +    var element = skipHidden ? (this.revealed() ? this.previousSibling : null) : this.previousSibling; | 
| +    if (!dontPopulate && element && element.hasChildren && element.onpopulate) | 
| +        element.onpopulate(element); | 
| + | 
| +    while (element && (skipHidden ? (element.revealed() && element.expanded ? element.children[element.children.length - 1] : null) : element.children[element.children.length - 1])) { | 
| +        if (!dontPopulate && element.hasChildren && element.onpopulate) | 
| +            element.onpopulate(element); | 
| +        element = (skipHidden ? (element.revealed() && element.expanded ? element.children[element.children.length - 1] : null) : element.children[element.children.length - 1]); | 
| +    } | 
| + | 
| +    if (element) | 
| +        return element; | 
| + | 
| +    if (!this.parent || this.parent.root) | 
| +        return null; | 
| + | 
| +    return this.parent; | 
| +} | 
| + | 
| +TreeElement.prototype.isEventWithinDisclosureTriangle = function(event) | 
| +{ | 
| +    var left = this._listItemNode.totalOffsetLeft; | 
| +    return event.pageX >= left && event.pageX <= left + this.arrowToggleWidth && this.hasChildren; | 
| +} | 
|  |