| /* |
| * Copyright (C) 2013 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. 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 INC. 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. |
| */ |
| |
| WebInspector.DOMNodeDetailsSidebarPanel = function() { |
| WebInspector.DOMDetailsSidebarPanel.call(this, "dom-node-details", WebInspector.UIString("Node"), WebInspector.UIString("Node"), "Images/NavigationItemAngleBrackets.svg", "2"); |
| |
| WebInspector.domTreeManager.addEventListener(WebInspector.DOMTreeManager.Event.AttributeModified, this._attributesChanged, this); |
| WebInspector.domTreeManager.addEventListener(WebInspector.DOMTreeManager.Event.AttributeRemoved, this._attributesChanged, this); |
| |
| this.element.classList.add(WebInspector.DOMNodeDetailsSidebarPanel.StyleClassName); |
| |
| this._identityNodeTypeRow = new WebInspector.DetailsSectionSimpleRow(WebInspector.UIString("Type")); |
| this._identityNodeNameRow = new WebInspector.DetailsSectionSimpleRow(WebInspector.UIString("Name")); |
| this._identityNodeValueRow = new WebInspector.DetailsSectionSimpleRow(WebInspector.UIString("Value")); |
| |
| var identityGroup = new WebInspector.DetailsSectionGroup([this._identityNodeTypeRow, this._identityNodeNameRow, this._identityNodeValueRow]); |
| var identitySection = new WebInspector.DetailsSection("dom-node-identity", WebInspector.UIString("Identity"), [identityGroup]); |
| |
| this._attributesDataGridRow = new WebInspector.DetailsSectionDataGridRow(null, WebInspector.UIString("No Attributes")); |
| |
| var attributesGroup = new WebInspector.DetailsSectionGroup([this._attributesDataGridRow]); |
| var attributesSection = new WebInspector.DetailsSection("dom-node-attributes", WebInspector.UIString("Attributes"), [attributesGroup]); |
| |
| this._propertiesRow = new WebInspector.DetailsSectionRow; |
| |
| var propertiesGroup = new WebInspector.DetailsSectionGroup([this._propertiesRow]); |
| var propertiesSection = new WebInspector.DetailsSection("dom-node-properties", WebInspector.UIString("Properties"), [propertiesGroup]); |
| |
| this._eventListenersSectionGroup = new WebInspector.DetailsSectionGroup; |
| var eventListenersSection = new WebInspector.DetailsSection("dom-node-event-listeners", WebInspector.UIString("Event Listeners"), [this._eventListenersSectionGroup]); |
| |
| this.element.appendChild(identitySection.element); |
| this.element.appendChild(attributesSection.element); |
| this.element.appendChild(propertiesSection.element); |
| this.element.appendChild(eventListenersSection.element); |
| }; |
| |
| WebInspector.DOMNodeDetailsSidebarPanel.StyleClassName = "dom-node"; |
| WebInspector.DOMNodeDetailsSidebarPanel.PropertiesObjectGroupName = "dom-node-details-sidebar-properties-object-group"; |
| |
| WebInspector.DOMNodeDetailsSidebarPanel.prototype = { |
| constructor: WebInspector.DOMNodeDetailsSidebarPanel, |
| |
| // Public |
| |
| refresh: function() |
| { |
| var domNode = this.domNode; |
| if (!domNode) |
| return; |
| |
| this._identityNodeTypeRow.value = this._nodeTypeDisplayName(); |
| this._identityNodeNameRow.value = domNode.nodeNameInCorrectCase(); |
| this._identityNodeValueRow.value = domNode.nodeValue(); |
| |
| this._refreshAttributes(); |
| this._refreshProperties(); |
| this._refreshEventListeners(); |
| }, |
| |
| // Private |
| |
| _refreshAttributes: function() |
| { |
| this._attributesDataGridRow.dataGrid = this._createAttributesDataGrid(); |
| }, |
| |
| _refreshProperties: function() |
| { |
| var domNode = this.domNode; |
| if (!domNode) |
| return; |
| |
| RuntimeAgent.releaseObjectGroup(WebInspector.DOMNodeDetailsSidebarPanel.PropertiesObjectGroupName); |
| WebInspector.RemoteObject.resolveNode(domNode, WebInspector.DOMNodeDetailsSidebarPanel.PropertiesObjectGroupName, nodeResolved.bind(this)); |
| |
| function nodeResolved(object) |
| { |
| if (!object) |
| return; |
| |
| // Bail if the DOM node changed while we were waiting for the async response. |
| if (this.domNode !== domNode) |
| return; |
| |
| function collectPrototypes() |
| { |
| // This builds an object with numeric properties. This is easier than dealing with arrays |
| // with the way RemoteObject works. Start at 1 since we use parseInt later and parseInt |
| // returns 0 for non-numeric strings make it ambiguous. |
| var prototype = this; |
| var result = []; |
| var counter = 1; |
| |
| while (prototype) { |
| result[counter++] = prototype; |
| prototype = prototype.__proto__; |
| } |
| |
| return result; |
| } |
| |
| object.callFunction(collectPrototypes, undefined, nodePrototypesReady.bind(this)); |
| object.release(); |
| } |
| |
| function nodePrototypesReady(object) |
| { |
| if (!object) |
| return; |
| |
| // Bail if the DOM node changed while we were waiting for the async response. |
| if (this.domNode !== domNode) |
| return; |
| |
| object.getOwnProperties(fillSection.bind(this)); |
| } |
| |
| function fillSection(prototypes) |
| { |
| if (!prototypes) |
| return; |
| |
| // Bail if the DOM node changed while we were waiting for the async response. |
| if (this.domNode !== domNode) |
| return; |
| |
| var element = this._propertiesRow.element; |
| element.removeChildren(); |
| |
| // Get array of prototype user-friendly names. |
| for (var i = 0; i < prototypes.length; ++i) { |
| // The only values we care about are numeric, as assigned in collectPrototypes. |
| if (!parseInt(prototypes[i].name, 10)) |
| continue; |
| |
| var prototype = prototypes[i].value; |
| var title = prototype.description; |
| if (title.match(/Prototype$/)) |
| title = title.replace(/Prototype$/, WebInspector.UIString(" (Prototype)")); |
| else if (title === "Object") |
| title = title + WebInspector.UIString(" (Prototype)"); |
| |
| var propertiesSection = new WebInspector.ObjectPropertiesSection(prototype); |
| |
| var detailsSection = new WebInspector.DetailsSection(prototype.description.hash + "-prototype-properties", title, null, null, true); |
| detailsSection.groups[0].rows = [new WebInspector.DetailsSectionPropertiesRow(propertiesSection)]; |
| |
| element.appendChild(detailsSection.element); |
| } |
| } |
| }, |
| |
| _refreshEventListeners: function() |
| { |
| var domNode = this.domNode; |
| if (!domNode) |
| return; |
| |
| domNode.eventListeners(eventListenersCallback.bind(this)); |
| |
| function eventListenersCallback(error, eventListeners) |
| { |
| if (error) |
| return; |
| |
| // Bail if the DOM node changed while we were waiting for the async response. |
| if (this.domNode !== domNode) |
| return; |
| |
| var eventListenerTypes = []; |
| var eventListenerSections = {}; |
| for (var i = 0; i < eventListeners.length; ++i) { |
| var eventListener = eventListeners[i]; |
| eventListener.node = WebInspector.domTreeManager.nodeForId(eventListener.nodeId); |
| |
| var type = eventListener.type; |
| var section = eventListenerSections[type]; |
| if (!section) { |
| section = new WebInspector.EventListenerSection(type, domNode.id); |
| eventListenerSections[type] = section; |
| eventListenerTypes.push(type); |
| } |
| |
| section.addListener(eventListener); |
| } |
| |
| if (!eventListenerTypes.length) { |
| var emptyRow = new WebInspector.DetailsSectionRow(WebInspector.UIString("No Event Listeners")); |
| emptyRow.showEmptyMessage(); |
| this._eventListenersSectionGroup.rows = [emptyRow]; |
| return; |
| } |
| |
| eventListenerTypes.sort(); |
| |
| var rows = []; |
| for (var i = 0; i < eventListenerTypes.length; ++i) |
| rows.push(eventListenerSections[eventListenerTypes[i]]); |
| this._eventListenersSectionGroup.rows = rows; |
| } |
| }, |
| |
| _attributesChanged: function(event) |
| { |
| if (event.data.node !== this.domNode) |
| return; |
| this._refreshAttributes(); |
| }, |
| |
| _nodeTypeDisplayName: function() |
| { |
| switch (this.domNode.nodeType()) { |
| case Node.ELEMENT_NODE: |
| return WebInspector.UIString("Element"); |
| case Node.TEXT_NODE: |
| return WebInspector.UIString("Text Node"); |
| case Node.COMMENT_NODE: |
| return WebInspector.UIString("Comment"); |
| case Node.DOCUMENT_NODE: |
| return WebInspector.UIString("Document"); |
| case Node.DOCUMENT_TYPE_NODE: |
| return WebInspector.UIString("Document Type"); |
| case Node.DOCUMENT_FRAGMENT_NODE: |
| return WebInspector.UIString("Document Fragment"); |
| case Node.CDATA_SECTION_NODE: |
| return WebInspector.UIString("Character Data"); |
| case Node.PROCESSING_INSTRUCTION_NODE: |
| return WebInspector.UIString("Processing Instruction"); |
| default: |
| console.error("Unknown DOM node type: ", this.domNode.nodeType()); |
| return this.domNode.nodeType(); |
| } |
| }, |
| |
| _createAttributesDataGrid: function() |
| { |
| var domNode = this.domNode; |
| if (!domNode || !domNode.hasAttributes()) |
| return null; |
| |
| var columns = {name: {title: WebInspector.UIString("Name"), width: "30%"}, value: {title: WebInspector.UIString("Value")}}; |
| var dataGrid = new WebInspector.DataGrid(columns); |
| |
| var attributes = domNode.attributes(); |
| for (var i = 0; i < attributes.length; ++i) { |
| var attribute = attributes[i]; |
| |
| var node = new WebInspector.DataGridNode({name: attribute.name, value: attribute.value || ""}, false); |
| node.selectable = true; |
| |
| dataGrid.appendChild(node); |
| } |
| |
| return dataGrid; |
| } |
| }; |
| |
| WebInspector.DOMNodeDetailsSidebarPanel.prototype.__proto__ = WebInspector.DOMDetailsSidebarPanel.prototype; |