1 /* 2 * Copyright (C) 2011 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 /** 32 * @constructor 33 * @extends {WebInspector.PopoverHelper} 34 * @param {Element} panelElement 35 * @param {function(Element, Event):Element|undefined} getAnchor 36 * @param {function(Element, function(WebInspector.RemoteObject, boolean, Element=):undefined, string):undefined} queryObject 37 * @param {function()=} onHide 38 * @param {boolean=} disableOnClick 39 */ 40 WebInspector.ObjectPopoverHelper = function(panelElement, getAnchor, queryObject, onHide, disableOnClick) 41 { 42 WebInspector.PopoverHelper.call(this, panelElement, getAnchor, this._showObjectPopover.bind(this), this._onHideObjectPopover.bind(this), disableOnClick); 43 this._queryObject = queryObject; 44 this._onHideCallback = onHide; 45 this._popoverObjectGroup = "popover"; 46 panelElement.addEventListener("scroll", this.hidePopover.bind(this), true); 47 }; 48 49 WebInspector.ObjectPopoverHelper.prototype = { 50 /** 51 * @param {Element} element 52 * @param {WebInspector.Popover} popover 53 */ 54 _showObjectPopover: function(element, popover) 55 { 56 /** 57 * @param {WebInspector.RemoteObject} result 58 * @param {boolean} wasThrown 59 * @param {Element=} anchorOverride 60 */ 61 function showObjectPopover(result, wasThrown, anchorOverride) 62 { 63 if (popover.disposed) 64 return; 65 if (wasThrown) { 66 this.hidePopover(); 67 return; 68 } 69 70 var anchorElement = anchorOverride || element; 71 72 var popoverContentElement = null; 73 if (result.type !== "object") { 74 popoverContentElement = document.createElement("span"); 75 popoverContentElement.className = "monospace console-formatted-" + result.type; 76 popoverContentElement.style.whiteSpace = "pre"; 77 popoverContentElement.textContent = result.description; 78 if (result.type === "function") { 79 function didGetDetails(error, response) 80 { 81 if (error) { 82 console.error(error); 83 return; 84 } 85 var container = document.createElement("div"); 86 container.className = "inline-block"; 87 88 var title = container.createChild("div", "function-popover-title source-code"); 89 var functionName = title.createChild("span", "function-name"); 90 functionName.textContent = response.name || response.inferredName || response.displayName || WebInspector.UIString("(anonymous function)"); 91 92 this._linkifier = new WebInspector.Linkifier(); 93 var rawLocation = /** @type {WebInspector.DebuggerModel.Location} */ (response.location); 94 var link = this._linkifier.linkifyRawLocation(rawLocation, "function-location-link"); 95 if (link) 96 title.appendChild(link); 97 98 container.appendChild(popoverContentElement); 99 100 popover.show(container, anchorElement); 101 } 102 DebuggerAgent.getFunctionDetails(result.objectId, didGetDetails.bind(this)); 103 return; 104 } 105 if (result.type === "string") 106 popoverContentElement.textContent = "\"" + popoverContentElement.textContent + "\""; 107 popover.show(popoverContentElement, anchorElement); 108 } else { 109 if (result.subtype === "node") 110 result.highlightAsDOMNode(); 111 popoverContentElement = document.createElement("div"); 112 this._titleElement = document.createElement("div"); 113 this._titleElement.className = "source-frame-popover-title monospace"; 114 this._titleElement.textContent = result.description; 115 popoverContentElement.appendChild(this._titleElement); 116 117 var section = new WebInspector.ObjectPropertiesSection(result); 118 // For HTML DOM wrappers, append "#id" to title, if not empty. 119 if (result.description.substr(0, 4) === "HTML") { 120 this._sectionUpdateProperties = section.updateProperties.bind(section); 121 section.updateProperties = this._updateHTMLId.bind(this); 122 } 123 section.expanded = true; 124 section.element.addStyleClass("source-frame-popover-tree"); 125 section.headerElement.addStyleClass("hidden"); 126 popoverContentElement.appendChild(section.element); 127 128 const popoverWidth = 300; 129 const popoverHeight = 250; 130 popover.show(popoverContentElement, anchorElement, popoverWidth, popoverHeight); 131 } 132 } 133 this._queryObject(element, showObjectPopover.bind(this), this._popoverObjectGroup); 134 }, 135 136 _onHideObjectPopover: function() 137 { 138 WebInspector.domAgent.hideDOMNodeHighlight(); 139 if (this._linkifier) { 140 this._linkifier.reset(); 141 delete this._linkifier; 142 } 143 if (this._onHideCallback) 144 this._onHideCallback(); 145 RuntimeAgent.releaseObjectGroup(this._popoverObjectGroup); 146 }, 147 148 _updateHTMLId: function(properties, rootTreeElementConstructor, rootPropertyComparer) 149 { 150 for (var i = 0; i < properties.length; ++i) { 151 if (properties[i].name === "id") { 152 if (properties[i].value.description) 153 this._titleElement.textContent += "#" + properties[i].value.description; 154 break; 155 } 156 } 157 this._sectionUpdateProperties(properties, rootTreeElementConstructor, rootPropertyComparer); 158 }, 159 160 __proto__: WebInspector.PopoverHelper.prototype 161 } 162