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     var filter = WebInspector.settings.eventListenersFilter;
     50     if (filter === "all")
     51         this.settingsSelectElement[0].selected = true;
     52     else if (filter === "selected")
     53         this.settingsSelectElement[1].selected = true;
     54     this.settingsSelectElement.addEventListener("click", function(event) { event.stopPropagation() }, false);
     55     this.settingsSelectElement.addEventListener("change", this._changeSetting.bind(this), false);
     56 
     57     this.titleElement.appendChild(this.settingsSelectElement);
     58 }
     59 
     60 WebInspector.EventListenersSidebarPane.prototype = {
     61     update: function(node)
     62     {
     63         var body = this.bodyElement;
     64         body.removeChildren();
     65         this.sections = [];
     66 
     67         var self = this;
     68         function callback(error, eventListeners) {
     69             if (error)
     70                 return;
     71 
     72             var sectionNames = [];
     73             var sectionMap = {};
     74             for (var i = 0; i < eventListeners.length; ++i) {
     75                 var eventListener = eventListeners[i];
     76                 eventListener.node = WebInspector.domAgent.nodeForId(eventListener.nodeId);
     77                 delete eventListener.nodeId; // no longer needed
     78                 if (/^function _inspectorCommandLineAPI_logEvent\(/.test(eventListener.listenerBody.toString()))
     79                     continue; // ignore event listeners generated by monitorEvent
     80                 var type = eventListener.type;
     81                 var section = sectionMap[type];
     82                 if (!section) {
     83                     section = new WebInspector.EventListenersSection(type, node.id);
     84                     sectionMap[type] = section;
     85                     sectionNames.push(type);
     86                     self.sections.push(section);
     87                 }
     88                 section.addListener(eventListener);
     89             }
     90 
     91             if (sectionNames.length === 0) {
     92                 var div = document.createElement("div");
     93                 div.className = "info";
     94                 div.textContent = WebInspector.UIString("No Event Listeners");
     95                 body.appendChild(div);
     96                 return;
     97             }
     98 
     99             sectionNames.sort();
    100             for (var i = 0; i < sectionNames.length; ++i) {
    101                 var section = sectionMap[sectionNames[i]];
    102                 section.update();
    103                 body.appendChild(section.element);
    104             }
    105         }
    106 
    107         if (node)
    108             node.eventListeners(callback);
    109     },
    110 
    111     _changeSetting: function(event)
    112     {
    113         var selectedOption = this.settingsSelectElement[this.settingsSelectElement.selectedIndex];
    114         WebInspector.settings.eventListenersFilter = selectedOption.value;
    115 
    116         for (var i = 0; i < this.sections.length; ++i)
    117             this.sections[i].update();
    118     }
    119 }
    120 
    121 WebInspector.EventListenersSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;
    122 
    123 WebInspector.EventListenersSection = function(title, nodeId)
    124 {
    125     this.eventListeners = [];
    126     this._nodeId = nodeId;
    127     WebInspector.PropertiesSection.call(this, title);
    128 
    129     // Changed from a Properties List
    130     this.propertiesElement.parentNode.removeChild(this.propertiesElement);
    131     delete this.propertiesElement;
    132     delete this.propertiesTreeOutline;
    133 
    134     this.eventBars = document.createElement("div");
    135     this.eventBars.className = "event-bars";
    136     this.element.appendChild(this.eventBars);
    137 }
    138 
    139 WebInspector.EventListenersSection.prototype = {
    140     update: function()
    141     {
    142         // A Filtered Array simplifies when to create connectors
    143         var filteredEventListeners = this.eventListeners;
    144         if (WebInspector.settings.eventListenersFilter === "selected") {
    145             filteredEventListeners = [];
    146             for (var i = 0; i < this.eventListeners.length; ++i) {
    147                 var eventListener = this.eventListeners[i];
    148                 if (eventListener.node.id === this._nodeId)
    149                     filteredEventListeners.push(eventListener);
    150             }
    151         }
    152 
    153         this.eventBars.removeChildren();
    154         var length = filteredEventListeners.length;
    155         for (var i = 0; i < length; ++i) {
    156             var eventListener = filteredEventListeners[i];
    157             var eventListenerBar = new WebInspector.EventListenerBar(eventListener, this._nodeId);
    158             this.eventBars.appendChild(eventListenerBar.element);
    159         }
    160     },
    161 
    162     addListener: function(eventListener)
    163     {
    164         this.eventListeners.push(eventListener);
    165     }
    166 }
    167 
    168 WebInspector.EventListenersSection.prototype.__proto__ = WebInspector.PropertiesSection.prototype;
    169 
    170 WebInspector.EventListenerBar = function(eventListener, nodeId)
    171 {
    172     this.eventListener = eventListener;
    173     this._nodeId = nodeId;
    174     WebInspector.ObjectPropertiesSection.call(this);
    175     this._setNodeTitle();
    176     this._setFunctionSubtitle();
    177     this.editable = false;
    178     this.element.className = "event-bar"; /* Changed from "section" */
    179     this.headerElement.addStyleClass("source-code");
    180     this.propertiesElement.className = "event-properties properties-tree source-code"; /* Changed from "properties" */
    181 }
    182 
    183 WebInspector.EventListenerBar.prototype = {
    184     update: function()
    185     {
    186         function updateWithNodeObject(nodeObject)
    187         {
    188             var properties = [];
    189             if (nodeObject)
    190                 properties.push(new WebInspector.RemoteObjectProperty("node", nodeObject));
    191 
    192             for (var propertyName in this.eventListener) {
    193                 var value = WebInspector.RemoteObject.fromPrimitiveValue(this.eventListener[propertyName]);
    194                 properties.push(new WebInspector.RemoteObjectProperty(propertyName, value));
    195             }
    196             this.updateProperties(properties);
    197             if (nodeObject)
    198                 nodeObject.release();
    199         }
    200         var node = this.eventListener.node;
    201         delete this.eventListener.node;
    202         WebInspector.RemoteObject.resolveNode(node, updateWithNodeObject.bind(this));
    203     },
    204 
    205     _setNodeTitle: function()
    206     {
    207         var node = this.eventListener.node;
    208         if (!node)
    209             return;
    210 
    211         if (node.nodeType() === Node.DOCUMENT_NODE) {
    212             this.titleElement.textContent = "document";
    213             return;
    214         }
    215 
    216         if (node.id === this._nodeId) {
    217             this.titleElement.textContent = node.appropriateSelectorFor();
    218             return;
    219         }
    220 
    221         this.titleElement.removeChildren();
    222         this.titleElement.appendChild(WebInspector.panels.elements.linkifyNodeReference(this.eventListener.node));
    223     },
    224 
    225     _setFunctionSubtitle: function()
    226     {
    227         // Requires that Function.toString() return at least the function's signature.
    228         if (this.eventListener.sourceName) {
    229             this.subtitleElement.removeChildren();
    230             this.subtitleElement.appendChild(WebInspector.linkifyResourceAsNode(this.eventListener.sourceName, "scripts", this.eventListener.lineNumber));
    231         } else {
    232             var match = this.eventListener.listenerBody.match(/function ([^\(]+?)\(/);
    233             if (match)
    234                 this.subtitleElement.textContent = match[1];
    235             else
    236                 this.subtitleElement.textContent = WebInspector.UIString("(anonymous function)");
    237         }
    238     }
    239 }
    240 
    241 WebInspector.EventListenerBar.prototype.__proto__ = WebInspector.ObjectPropertiesSection.prototype;
    242