1/* 2 * Copyright (C) 2007 Apple Inc. All rights reserved. 3 * Copyright (C) 2009 Joseph Pecoraro 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 15 * its contributors may be used to endorse or promote products derived 16 * from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30/** 31 * @constructor 32 * @extends {WebInspector.SidebarPane} 33 */ 34WebInspector.EventListenersSidebarPane = function() 35{ 36 WebInspector.SidebarPane.call(this, WebInspector.UIString("Event Listeners")); 37 this.bodyElement.classList.add("events-pane"); 38 39 this.sections = []; 40 41 this.settingsSelectElement = document.createElement("select"); 42 this.settingsSelectElement.className = "select-filter"; 43 44 var option = document.createElement("option"); 45 option.value = "all"; 46 option.label = WebInspector.UIString("All Nodes"); 47 this.settingsSelectElement.appendChild(option); 48 49 option = document.createElement("option"); 50 option.value = "selected"; 51 option.label = WebInspector.UIString("Selected Node Only"); 52 this.settingsSelectElement.appendChild(option); 53 54 var filter = WebInspector.settings.eventListenersFilter.get(); 55 if (filter === "all") 56 this.settingsSelectElement[0].selected = true; 57 else if (filter === "selected") 58 this.settingsSelectElement[1].selected = true; 59 this.settingsSelectElement.addEventListener("click", function(event) { event.consume() }, false); 60 this.settingsSelectElement.addEventListener("change", this._changeSetting.bind(this), false); 61 62 this.titleElement.appendChild(this.settingsSelectElement); 63 64 this._linkifier = new WebInspector.Linkifier(); 65} 66 67WebInspector.EventListenersSidebarPane._objectGroupName = "event-listeners-sidebar-pane"; 68 69WebInspector.EventListenersSidebarPane.prototype = { 70 update: function(node) 71 { 72 RuntimeAgent.releaseObjectGroup(WebInspector.EventListenersSidebarPane._objectGroupName); 73 this._linkifier.reset(); 74 75 var body = this.bodyElement; 76 body.removeChildren(); 77 this.sections = []; 78 79 var self = this; 80 function callback(error, eventListeners) { 81 if (error) 82 return; 83 84 var selectedNodeOnly = "selected" === WebInspector.settings.eventListenersFilter.get(); 85 var sectionNames = []; 86 var sectionMap = {}; 87 for (var i = 0; i < eventListeners.length; ++i) { 88 var eventListener = eventListeners[i]; 89 if (selectedNodeOnly && (node.id !== eventListener.nodeId)) 90 continue; 91 eventListener.node = WebInspector.domAgent.nodeForId(eventListener.nodeId); 92 delete eventListener.nodeId; // no longer needed 93 if (/^function _inspectorCommandLineAPI_logEvent\(/.test(eventListener.handlerBody.toString())) 94 continue; // ignore event listeners generated by monitorEvent 95 var type = eventListener.type; 96 var section = sectionMap[type]; 97 if (!section) { 98 section = new WebInspector.EventListenersSection(type, node.id, self._linkifier); 99 sectionMap[type] = section; 100 sectionNames.push(type); 101 self.sections.push(section); 102 } 103 section.addListener(eventListener); 104 } 105 106 if (sectionNames.length === 0) { 107 var div = document.createElement("div"); 108 div.className = "info"; 109 div.textContent = WebInspector.UIString("No Event Listeners"); 110 body.appendChild(div); 111 return; 112 } 113 114 sectionNames.sort(); 115 for (var i = 0; i < sectionNames.length; ++i) { 116 var section = sectionMap[sectionNames[i]]; 117 body.appendChild(section.element); 118 } 119 } 120 121 if (node) 122 node.eventListeners(WebInspector.EventListenersSidebarPane._objectGroupName, callback); 123 this._selectedNode = node; 124 }, 125 126 willHide: function() 127 { 128 delete this._selectedNode; 129 }, 130 131 _changeSetting: function() 132 { 133 var selectedOption = this.settingsSelectElement[this.settingsSelectElement.selectedIndex]; 134 WebInspector.settings.eventListenersFilter.set(selectedOption.value); 135 this.update(this._selectedNode); 136 }, 137 138 __proto__: WebInspector.SidebarPane.prototype 139} 140 141/** 142 * @constructor 143 * @extends {WebInspector.PropertiesSection} 144 */ 145WebInspector.EventListenersSection = function(title, nodeId, linkifier) 146{ 147 this.eventListeners = []; 148 this._nodeId = nodeId; 149 this._linkifier = linkifier; 150 WebInspector.PropertiesSection.call(this, title); 151 152 // Changed from a Properties List 153 this.propertiesElement.remove(); 154 delete this.propertiesElement; 155 delete this.propertiesTreeOutline; 156 157 this._eventBars = document.createElement("div"); 158 this._eventBars.className = "event-bars"; 159 this.element.appendChild(this._eventBars); 160} 161 162WebInspector.EventListenersSection.prototype = { 163 addListener: function(eventListener) 164 { 165 var eventListenerBar = new WebInspector.EventListenerBar(eventListener, this._nodeId, this._linkifier); 166 this._eventBars.appendChild(eventListenerBar.element); 167 }, 168 169 __proto__: WebInspector.PropertiesSection.prototype 170} 171 172/** 173 * @constructor 174 * @extends {WebInspector.ObjectPropertiesSection} 175 */ 176WebInspector.EventListenerBar = function(eventListener, nodeId, linkifier) 177{ 178 WebInspector.ObjectPropertiesSection.call(this, WebInspector.RemoteObject.fromPrimitiveValue("")); 179 180 this.eventListener = eventListener; 181 this._nodeId = nodeId; 182 this._setNodeTitle(); 183 this._setFunctionSubtitle(linkifier); 184 this.editable = false; 185 this.element.className = "event-bar"; /* Changed from "section" */ 186 this.headerElement.classList.add("source-code"); 187 this.propertiesElement.className = "event-properties properties-tree source-code"; /* Changed from "properties" */ 188} 189 190WebInspector.EventListenerBar.prototype = { 191 update: function() 192 { 193 /** 194 * @param {?WebInspector.RemoteObject} nodeObject 195 * @this {WebInspector.EventListenerBar} 196 */ 197 function updateWithNodeObject(nodeObject) 198 { 199 var properties = []; 200 201 if (this.eventListener.type) 202 properties.push(WebInspector.RemoteObjectProperty.fromPrimitiveValue("type", this.eventListener.type)); 203 if (typeof this.eventListener.useCapture !== "undefined") 204 properties.push(WebInspector.RemoteObjectProperty.fromPrimitiveValue("useCapture", this.eventListener.useCapture)); 205 if (typeof this.eventListener.isAttribute !== "undefined") 206 properties.push(WebInspector.RemoteObjectProperty.fromPrimitiveValue("isAttribute", this.eventListener.isAttribute)); 207 if (nodeObject) 208 properties.push(new WebInspector.RemoteObjectProperty("node", nodeObject)); 209 if (typeof this.eventListener.handler !== "undefined") { 210 var remoteObject = WebInspector.RemoteObject.fromPayload(this.eventListener.handler); 211 properties.push(new WebInspector.RemoteObjectProperty("handler", remoteObject)); 212 } 213 if (typeof this.eventListener.handlerBody !== "undefined") 214 properties.push(WebInspector.RemoteObjectProperty.fromPrimitiveValue("listenerBody", this.eventListener.handlerBody)); 215 if (this.eventListener.sourceName) 216 properties.push(WebInspector.RemoteObjectProperty.fromPrimitiveValue("sourceName", this.eventListener.sourceName)); 217 if (this.eventListener.location) 218 properties.push(WebInspector.RemoteObjectProperty.fromPrimitiveValue("lineNumber", this.eventListener.location.lineNumber + 1)); 219 220 this.updateProperties(properties); 221 } 222 WebInspector.RemoteObject.resolveNode(this.eventListener.node, WebInspector.EventListenersSidebarPane._objectGroupName, updateWithNodeObject.bind(this)); 223 }, 224 225 _setNodeTitle: function() 226 { 227 var node = this.eventListener.node; 228 if (!node) 229 return; 230 231 if (node.nodeType() === Node.DOCUMENT_NODE) { 232 this.titleElement.textContent = "document"; 233 return; 234 } 235 236 if (node.id === this._nodeId) { 237 this.titleElement.textContent = WebInspector.DOMPresentationUtils.appropriateSelectorFor(node); 238 return; 239 } 240 241 this.titleElement.removeChildren(); 242 this.titleElement.appendChild(WebInspector.DOMPresentationUtils.linkifyNodeReference(this.eventListener.node)); 243 }, 244 245 _setFunctionSubtitle: function(linkifier) 246 { 247 // Requires that Function.toString() return at least the function's signature. 248 if (this.eventListener.location) { 249 this.subtitleElement.removeChildren(); 250 var urlElement; 251 if (this.eventListener.location.scriptId) 252 urlElement = linkifier.linkifyRawLocation(this.eventListener.location); 253 if (!urlElement) { 254 var url = this.eventListener.sourceName; 255 var lineNumber = this.eventListener.location.lineNumber; 256 var columnNumber = 0; 257 urlElement = linkifier.linkifyLocation(url, lineNumber, columnNumber); 258 } 259 this.subtitleElement.appendChild(urlElement); 260 } else { 261 var match = this.eventListener.handlerBody.match(/function ([^\(]+?)\(/); 262 if (match) 263 this.subtitleElement.textContent = match[1]; 264 else 265 this.subtitleElement.textContent = WebInspector.UIString("(anonymous function)"); 266 } 267 }, 268 269 __proto__: WebInspector.ObjectPropertiesSection.prototype 270} 271