home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (C) 2008 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.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. 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.
- */
-
- WebInspector.ObjectPropertiesSection = function(object, title, subtitle, emptyPlaceholder, ignoreHasOwnProperty, extraProperties, treeElementConstructor)
- {
- if (!title) {
- title = Object.describe(object);
- if (title.match(/Prototype$/)) {
- title = title.replace(/Prototype$/, "");
- if (!subtitle)
- subtitle = WebInspector.UIString("Prototype");
- }
- }
-
- this.emptyPlaceholder = (emptyPlaceholder || WebInspector.UIString("No Properties"));
- this.object = object;
- this.ignoreHasOwnProperty = ignoreHasOwnProperty;
- this.extraProperties = extraProperties;
- this.treeElementConstructor = treeElementConstructor || WebInspector.ObjectPropertyTreeElement;
- this.editable = true;
-
- WebInspector.PropertiesSection.call(this, title, subtitle);
- }
-
- WebInspector.ObjectPropertiesSection.prototype = {
- onpopulate: function()
- {
- this.update();
- },
-
- update: function()
- {
- var properties = [];
- for (var prop in this.object)
- properties.push(prop);
- if (this.extraProperties)
- for (var prop in this.extraProperties)
- properties.push(prop);
- properties.sort();
-
- this.propertiesTreeOutline.removeChildren();
-
- for (var i = 0; i < properties.length; ++i) {
- var object = this.object;
- var propertyName = properties[i];
- if (this.extraProperties && propertyName in this.extraProperties)
- object = this.extraProperties;
- if (propertyName === "__treeElementIdentifier")
- continue;
- if (!this.ignoreHasOwnProperty && "hasOwnProperty" in object && !object.hasOwnProperty(propertyName))
- continue;
- this.propertiesTreeOutline.appendChild(new this.treeElementConstructor(object, propertyName));
- }
-
- if (!this.propertiesTreeOutline.children.length) {
- var title = "<div class=\"info\">" + this.emptyPlaceholder + "</div>";
- var infoElement = new TreeElement(title, null, false);
- this.propertiesTreeOutline.appendChild(infoElement);
- }
- }
- }
-
- WebInspector.ObjectPropertiesSection.prototype.__proto__ = WebInspector.PropertiesSection.prototype;
-
- WebInspector.ObjectPropertyTreeElement = function(parentObject, propertyName)
- {
- this.parentObject = parentObject;
- this.propertyName = propertyName;
-
- // Pass an empty title, the title gets made later in onattach.
- TreeElement.call(this, "", null, false);
- }
-
- WebInspector.ObjectPropertyTreeElement.prototype = {
- safePropertyValue: function(object, propertyName)
- {
- if (object["__lookupGetter__"] && object.__lookupGetter__(propertyName))
- return;
- return object[propertyName];
- },
-
- onpopulate: function()
- {
- if (this.children.length && !this.shouldRefreshChildren)
- return;
-
- this.removeChildren();
-
- var childObject = this.safePropertyValue(this.parentObject, this.propertyName);
- var properties = Object.sortedProperties(childObject);
- for (var i = 0; i < properties.length; ++i) {
- var propertyName = properties[i];
- if (propertyName === "__treeElementIdentifier")
- continue;
- this.appendChild(new this.treeOutline.section.treeElementConstructor(childObject, propertyName));
- }
- },
-
- ondblclick: function(element, event)
- {
- this.startEditing();
- },
-
- onattach: function()
- {
- this.update();
- },
-
- update: function()
- {
- var childObject = this.safePropertyValue(this.parentObject, this.propertyName);
- var isGetter = ("__lookupGetter__" in this.parentObject && this.parentObject.__lookupGetter__(this.propertyName));
-
- var nameElement = document.createElement("span");
- nameElement.className = "name";
- nameElement.textContent = this.propertyName;
-
- this.valueElement = document.createElement("span");
- this.valueElement.className = "value";
- if (!isGetter) {
- this.valueElement.textContent = Object.describe(childObject, true);
- } else {
- // FIXME: this should show something like "getter" (bug 16734).
- this.valueElement.textContent = "\u2014"; // em dash
- this.valueElement.addStyleClass("dimmed");
- }
-
- this.listItemElement.removeChildren();
-
- this.listItemElement.appendChild(nameElement);
- this.listItemElement.appendChild(document.createTextNode(": "));
- this.listItemElement.appendChild(this.valueElement);
-
- var hasSubProperties = false;
- var type = typeof childObject;
- if (childObject && (type === "object" || type === "function")) {
- for (subPropertyName in childObject) {
- if (subPropertyName === "__treeElementIdentifier")
- continue;
- hasSubProperties = true;
- break;
- }
- }
-
- this.hasChildren = hasSubProperties;
- },
-
- updateSiblings: function()
- {
- if (this.parent.root)
- this.treeOutline.section.update();
- else
- this.parent.shouldRefreshChildren = true;
- },
-
- startEditing: function()
- {
- if (WebInspector.isBeingEdited(this.valueElement) || !this.treeOutline.section.editable)
- return;
-
- var context = { expanded: this.expanded };
-
- // Lie about our children to prevent expanding on double click and to collapse subproperties.
- this.hasChildren = false;
-
- this.listItemElement.addStyleClass("editing-sub-part");
-
- WebInspector.startEditing(this.valueElement, this.editingCommitted.bind(this), this.editingCancelled.bind(this), context);
- },
-
- editingEnded: function(context)
- {
- this.listItemElement.scrollLeft = 0;
- this.listItemElement.removeStyleClass("editing-sub-part");
- if (context.expanded)
- this.expand();
- },
-
- editingCancelled: function(element, context)
- {
- this.update();
- this.editingEnded(context);
- },
-
- editingCommitted: function(element, userInput, previousContent, context)
- {
- if (userInput === previousContent)
- return this.editingCancelled(element, context); // nothing changed, so cancel
-
- this.applyExpression(userInput, true);
-
- this.editingEnded(context);
- },
-
- evaluateExpression: function(expression, callback)
- {
- // Evaluate in the currently selected call frame if the debugger is paused.
- // Otherwise evaluate in against the inspected window.
- if (WebInspector.panels.scripts && WebInspector.panels.scripts.paused && this.treeOutline.section.editInSelectedCallFrameWhenPaused)
- return WebInspector.panels.scripts.evaluateInSelectedCallFrame(expression, false, callback);
- try {
- var result = InspectorController.inspectedWindow().eval(expression);
- callback(result);
- } catch (e) {
- callback(e, true);
- }
- },
-
- applyExpression: function(expression, updateInterface)
- {
- var expressionLength = expression.trimWhitespace().length;
-
- if (!expressionLength) {
- // The user deleted everything, so try to delete the property.
- delete this.parentObject[this.propertyName];
-
- if (updateInterface) {
- if (this.propertyName in this.parentObject) {
- // The property was not deleted, so update.
- this.update();
- } else {
- // The property was deleted, so remove this tree element.
- this.parent.removeChild(this);
- }
- }
-
- return;
- }
-
- try {
- // Surround the expression in parenthesis so the result of the eval is the result
- // of the whole expression not the last potential sub-expression.
- var result = this.evaluateExpression("(" + expression + ")");
-
- // Store the result in the property.
- this.parentObject[this.propertyName] = result;
- } catch(e) {
- try {
- // Try to update as a string
- var result = this.evaluateExpression("\"" + expression.escapeCharacters("\"") + "\"");
-
- // Store the result in the property.
- this.parentObject[this.propertyName] = result;
- } catch(e) {
- // The expression failed so don't change the value. So just update and return.
- if (updateInterface)
- this.update();
- return;
- }
- }
-
- if (updateInterface) {
- // Call updateSiblings since their value might be based on the value that just changed.
- this.updateSiblings();
- }
- }
- }
-
- WebInspector.ObjectPropertyTreeElement.prototype.__proto__ = TreeElement.prototype;
-