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 WebInspector.EventListenersSidebarPane = function() 31 { 32 WebInspector.SidebarPane.call(this, WebInspector.UIString("Event Listeners")); 33 this.bodyElement.addStyleClass("events-pane"); 34 35 this.sections = []; 36 37 this.settingsSelectElement = document.createElement("select"); 38 39 var option = document.createElement("option"); 40 option.value = "all"; 41 option.label = WebInspector.UIString("All Nodes"); 42 this.settingsSelectElement.appendChild(option); 43 44 option = document.createElement("option"); 45 option.value = "selected"; 46 option.label = WebInspector.UIString("Selected Node Only"); 47 this.settingsSelectElement.appendChild(option); 48 49 WebInspector.settings.addEventListener("loaded", this._settingsLoaded, this); 50 this.settingsSelectElement.addEventListener("click", function(event) { event.stopPropagation() }, false); 51 this.settingsSelectElement.addEventListener("change", this._changeSetting.bind(this), false); 52 53 this.titleElement.appendChild(this.settingsSelectElement); 54 } 55 56 WebInspector.EventListenersSidebarPane.prototype = { 57 _settingsLoaded: function() 58 { 59 var filter = WebInspector.settings.eventListenersFilter; 60 if (filter === "all") 61 this.settingsSelectElement[0].selected = true; 62 if (filter === "selected") 63 this.settingsSelectElement[1].selected = true; 64 }, 65 66 update: function(node) 67 { 68 var body = this.bodyElement; 69 body.removeChildren(); 70 this.sections = []; 71 72 var self = this; 73 function callback(nodeId, eventListeners) { 74 var sectionNames = []; 75 var sectionMap = {}; 76 for (var i = 0; i < eventListeners.length; ++i) { 77 var eventListener = eventListeners[i]; 78 eventListener.node = WebInspector.domAgent.nodeForId(eventListener.nodeId); 79 delete eventListener.nodeId; // no longer needed 80 if (/^function _inspectorCommandLineAPI_logEvent\(/.test(eventListener.listener.toString())) 81 continue; // ignore event listeners generated by monitorEvent 82 var type = eventListener.type; 83 var section = sectionMap[type]; 84 if (!section) { 85 section = new WebInspector.EventListenersSection(type, nodeId); 86 sectionMap[type] = section; 87 sectionNames.push(type); 88 self.sections.push(section); 89 } 90 section.addListener(eventListener); 91 } 92 93 if (sectionNames.length === 0) { 94 var div = document.createElement("div"); 95 div.className = "info"; 96 div.textContent = WebInspector.UIString("No Event Listeners"); 97 body.appendChild(div); 98 return; 99 } 100 101 sectionNames.sort(); 102 for (var i = 0; i < sectionNames.length; ++i) { 103 var section = sectionMap[sectionNames[i]]; 104 section.update(); 105 body.appendChild(section.element); 106 } 107 } 108 109 WebInspector.EventListeners.getEventListenersForNodeAsync(node, callback); 110 }, 111 112 _changeSetting: function(event) 113 { 114 var selectedOption = this.settingsSelectElement[this.settingsSelectElement.selectedIndex]; 115 WebInspector.settings.eventListenersFilter = selectedOption.value; 116 117 for (var i = 0; i < this.sections.length; ++i) 118 this.sections[i].update(); 119 } 120 } 121 122 WebInspector.EventListenersSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype; 123 124 WebInspector.EventListenersSection = function(title, nodeId) 125 { 126 this.eventListeners = []; 127 this._nodeId = nodeId; 128 WebInspector.PropertiesSection.call(this, title); 129 130 // Changed from a Properties List 131 this.propertiesElement.parentNode.removeChild(this.propertiesElement); 132 delete this.propertiesElement; 133 delete this.propertiesTreeOutline; 134 135 this.eventBars = document.createElement("div"); 136 this.eventBars.className = "event-bars"; 137 this.element.appendChild(this.eventBars); 138 } 139 140 WebInspector.EventListenersSection.prototype = { 141 update: function() 142 { 143 // A Filtered Array simplifies when to create connectors 144 var filteredEventListeners = this.eventListeners; 145 if (WebInspector.settings.eventListenersFilter === "selected") { 146 filteredEventListeners = []; 147 for (var i = 0; i < this.eventListeners.length; ++i) { 148 var eventListener = this.eventListeners[i]; 149 if (eventListener.node.id === this._nodeId) 150 filteredEventListeners.push(eventListener); 151 } 152 } 153 154 this.eventBars.removeChildren(); 155 var length = filteredEventListeners.length; 156 for (var i = 0; i < length; ++i) { 157 var eventListener = filteredEventListeners[i]; 158 var eventListenerBar = new WebInspector.EventListenerBar(eventListener); 159 if (i < length - 1) { 160 var connector = document.createElement("div"); 161 connector.className = "event-bar-connector"; 162 eventListenerBar.element.appendChild(connector); 163 } 164 165 this.eventBars.appendChild(eventListenerBar.element); 166 } 167 }, 168 169 addListener: function(eventListener) 170 { 171 this.eventListeners.push(eventListener); 172 } 173 } 174 175 WebInspector.EventListenersSection.prototype.__proto__ = WebInspector.PropertiesSection.prototype; 176 177 WebInspector.EventListenerBar = function(eventListener) 178 { 179 this.eventListener = eventListener; 180 WebInspector.ObjectPropertiesSection.call(this, null, this._getFunctionDisplayName(), this._getNodeDisplayName()); 181 this.editable = false; 182 this.element.className = "event-bar"; /* Changed from "section" */ 183 this.propertiesElement.className = "event-properties"; /* Changed from "properties" */ 184 } 185 186 WebInspector.EventListenerBar.prototype = { 187 update: function() 188 { 189 var properties = []; 190 for (var propertyName in this.eventListener) { 191 // Just build properties in place - no need to reach out for injected script. 192 var value = this.eventListener[propertyName]; 193 if (value instanceof WebInspector.DOMNode) 194 value = new WebInspector.ObjectProxy(value.injectedScriptId, value.id, [], 0, appropriateSelectorForNode(value), true); 195 else 196 value = WebInspector.ObjectProxy.wrapPrimitiveValue(value); 197 properties.push(new WebInspector.ObjectPropertyProxy(propertyName, value)); 198 } 199 this.updateProperties(properties); 200 }, 201 202 _getNodeDisplayName: function() 203 { 204 var node = this.eventListener.node; 205 if (!node) 206 return ""; 207 208 if (node.nodeType === Node.DOCUMENT_NODE) 209 return "document"; 210 211 return appropriateSelectorForNode(node); 212 }, 213 214 _getFunctionDisplayName: function() 215 { 216 // Requires that Function.toString() return at least the function's signature. 217 var match = this.eventListener.listener.toString().match(/function ([^\(]+?)\(/); 218 return (match ? match[1] : WebInspector.UIString("(anonymous function)")); 219 } 220 } 221 222 WebInspector.EventListenerBar.prototype.__proto__ = WebInspector.ObjectPropertiesSection.prototype; 223