Home | History | Annotate | Download | only in front-end
      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