Home | History | Annotate | Download | only in elements
      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  */
     34 WebInspector.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     var refreshButton = this.titleElement.createChild("button", "pane-title-button refresh");
     42     refreshButton.addEventListener("click", this._refreshButtonClicked.bind(this), false);
     43     refreshButton.title = WebInspector.UIString("Refresh");
     44 
     45     this.settingsSelectElement = this.titleElement.createChild("select", "select-filter");
     46 
     47     var option = this.settingsSelectElement.createChild("option");
     48     option.value = "all";
     49     option.label = WebInspector.UIString("All Nodes");
     50 
     51     option = this.settingsSelectElement.createChild("option");
     52     option.value = "selected";
     53     option.label = WebInspector.UIString("Selected Node Only");
     54 
     55     var filter = WebInspector.settings.eventListenersFilter.get();
     56     if (filter === "all")
     57         this.settingsSelectElement[0].selected = true;
     58     else if (filter === "selected")
     59         this.settingsSelectElement[1].selected = true;
     60     this.settingsSelectElement.addEventListener("click", consumeEvent, false);
     61     this.settingsSelectElement.addEventListener("change", this._changeSetting.bind(this), false);
     62 
     63     this._linkifier = new WebInspector.Linkifier();
     64     this._refreshThrottler = new WebInspector.Throttler(0);
     65 }
     66 
     67 WebInspector.EventListenersSidebarPane._objectGroupName = "event-listeners-sidebar-pane";
     68 
     69 WebInspector.EventListenersSidebarPane.prototype = {
     70     /**
     71      * @param {?WebInspector.DOMNode} node
     72      */
     73     update: function(node)
     74     {
     75         this._selectedNode = node;
     76         this._refreshThrottler.schedule(this._refreshView.bind(this));
     77     },
     78 
     79     /**
     80      * @param {!WebInspector.Throttler.FinishCallback} finishCallback
     81      */
     82     _refreshView: function(finishCallback)
     83     {
     84         if (this._lastRequestedNode) {
     85             this._lastRequestedNode.target().runtimeAgent().releaseObjectGroup(WebInspector.EventListenersSidebarPane._objectGroupName);
     86             delete this._lastRequestedNode;
     87         }
     88 
     89         this._linkifier.reset();
     90 
     91         var body = this.bodyElement;
     92         body.removeChildren();
     93         this.sections = [];
     94 
     95         var node = this._selectedNode;
     96         if (!node) {
     97             finishCallback();
     98             return;
     99         }
    100 
    101         this._lastRequestedNode = node;
    102         node.eventListeners(WebInspector.EventListenersSidebarPane._objectGroupName, callback.bind(this));
    103 
    104         /**
    105          * @param {?Array.<!WebInspector.DOMModel.EventListener>} eventListeners
    106          * @this {WebInspector.EventListenersSidebarPane}
    107          */
    108         function callback(eventListeners)
    109         {
    110             if (!eventListeners) {
    111                 finishCallback();
    112                 return;
    113             }
    114 
    115             var selectedNodeOnly = "selected" === WebInspector.settings.eventListenersFilter.get();
    116             var sectionNames = [];
    117             var sectionMap = {};
    118             for (var i = 0; i < eventListeners.length; ++i) {
    119                 var eventListener = eventListeners[i];
    120                 if (selectedNodeOnly && (node.id !== eventListener.payload().nodeId))
    121                     continue;
    122                 if (/^function _inspectorCommandLineAPI_logEvent\(/.test(eventListener.payload().handlerBody.toString()))
    123                     continue; // ignore event listeners generated by monitorEvent
    124                 var type = eventListener.payload().type;
    125                 var section = sectionMap[type];
    126                 if (!section) {
    127                     section = new WebInspector.EventListenersSection(type, node.id, this._linkifier);
    128                     sectionMap[type] = section;
    129                     sectionNames.push(type);
    130                     this.sections.push(section);
    131                 }
    132                 section.addListener(eventListener);
    133             }
    134 
    135             if (sectionNames.length === 0) {
    136                 body.createChild("div", "info").textContent = WebInspector.UIString("No Event Listeners");
    137             } else {
    138                 sectionNames.sort();
    139                 for (var i = 0; i < sectionNames.length; ++i) {
    140                     var section = sectionMap[sectionNames[i]];
    141                     body.appendChild(section.element);
    142                 }
    143             }
    144 
    145             finishCallback();
    146         }
    147     },
    148 
    149     _refreshButtonClicked: function()
    150     {
    151         if (!this._selectedNode)
    152             return;
    153         this.update(this._selectedNode);
    154     },
    155 
    156     _changeSetting: function()
    157     {
    158         var selectedOption = this.settingsSelectElement[this.settingsSelectElement.selectedIndex];
    159         WebInspector.settings.eventListenersFilter.set(selectedOption.value);
    160         this.update(this._selectedNode);
    161     },
    162 
    163     __proto__: WebInspector.SidebarPane.prototype
    164 }
    165 
    166 /**
    167  * @constructor
    168  * @extends {WebInspector.PropertiesSection}
    169  */
    170 WebInspector.EventListenersSection = function(title, nodeId, linkifier)
    171 {
    172     this._nodeId = nodeId;
    173     this._linkifier = linkifier;
    174     WebInspector.PropertiesSection.call(this, title);
    175 
    176     // Changed from a Properties List
    177     this.propertiesElement.remove();
    178     delete this.propertiesElement;
    179     delete this.propertiesTreeOutline;
    180 
    181     this._eventBars = this.element.createChild("div", "event-bars");
    182 }
    183 
    184 WebInspector.EventListenersSection.prototype = {
    185     /**
    186      * @param {!WebInspector.DOMModel.EventListener} eventListener
    187      */
    188     addListener: function(eventListener)
    189     {
    190         var eventListenerBar = new WebInspector.EventListenerBar(eventListener, this._nodeId, this._linkifier);
    191         this._eventBars.appendChild(eventListenerBar.element);
    192     },
    193 
    194     __proto__: WebInspector.PropertiesSection.prototype
    195 }
    196 
    197 /**
    198  * @constructor
    199  * @extends {WebInspector.ObjectPropertiesSection}
    200  * @param {!WebInspector.DOMModel.EventListener} eventListener
    201  * @param {!DOMAgent.NodeId} nodeId
    202  * @param {!WebInspector.Linkifier} linkifier
    203  */
    204 WebInspector.EventListenerBar = function(eventListener, nodeId, linkifier)
    205 {
    206     var target = eventListener.target();
    207     WebInspector.ObjectPropertiesSection.call(this, target.runtimeModel.createRemoteObjectFromPrimitiveValue(""));
    208 
    209     this._runtimeModel = target.runtimeModel;
    210     this._eventListener = eventListener;
    211     this._nodeId = nodeId;
    212     this._setNodeTitle();
    213     this._setFunctionSubtitle(linkifier);
    214     this.editable = false;
    215     this.element.className = "event-bar"; /* Changed from "section" */
    216     this.headerElement.classList.add("source-code");
    217     this.propertiesElement.className = "event-properties properties-tree source-code"; /* Changed from "properties" */
    218 }
    219 
    220 WebInspector.EventListenerBar.prototype = {
    221     update: function()
    222     {
    223         /**
    224          * @param {?WebInspector.RemoteObject} nodeObject
    225          * @this {WebInspector.EventListenerBar}
    226          */
    227         function updateWithNodeObject(nodeObject)
    228         {
    229             var properties = [];
    230             var payload = this._eventListener.payload();
    231 
    232             properties.push(this._runtimeModel.createRemotePropertyFromPrimitiveValue("type", payload.type));
    233             properties.push(this._runtimeModel.createRemotePropertyFromPrimitiveValue("useCapture", payload.useCapture));
    234             properties.push(this._runtimeModel.createRemotePropertyFromPrimitiveValue("isAttribute", payload.isAttribute));
    235             if (nodeObject)
    236                 properties.push(new WebInspector.RemoteObjectProperty("node", nodeObject));
    237             if (typeof payload.handler !== "undefined") {
    238                 var remoteObject = this._runtimeModel.createRemoteObject(payload.handler);
    239                 properties.push(new WebInspector.RemoteObjectProperty("handler", remoteObject));
    240             }
    241             properties.push(this._runtimeModel.createRemotePropertyFromPrimitiveValue("listenerBody", payload.handlerBody));
    242             if (payload.sourceName)
    243                 properties.push(this._runtimeModel.createRemotePropertyFromPrimitiveValue("sourceName", payload.sourceName));
    244             properties.push(this._runtimeModel.createRemotePropertyFromPrimitiveValue("lineNumber", payload.location.lineNumber + 1));
    245 
    246             this.updateProperties(properties);
    247         }
    248         this._eventListener.node().resolveToObject(WebInspector.EventListenersSidebarPane._objectGroupName, updateWithNodeObject.bind(this));
    249     },
    250 
    251     _setNodeTitle: function()
    252     {
    253         var node = this._eventListener.node();
    254         if (!node)
    255             return;
    256 
    257         if (node.nodeType() === Node.DOCUMENT_NODE) {
    258             this.titleElement.textContent = "document";
    259             return;
    260         }
    261 
    262         if (node.id === this._nodeId) {
    263             this.titleElement.textContent = WebInspector.DOMPresentationUtils.simpleSelector(node);
    264             return;
    265         }
    266 
    267         this.titleElement.removeChildren();
    268         this.titleElement.appendChild(WebInspector.DOMPresentationUtils.linkifyNodeReference(node));
    269     },
    270 
    271     /**
    272      * @param {!WebInspector.Linkifier} linkifier
    273      */
    274     _setFunctionSubtitle: function(linkifier)
    275     {
    276         this.subtitleElement.removeChildren();
    277         var link = linkifier.linkifyRawLocation(this._eventListener.location(), this._eventListener.sourceName());
    278         this.subtitleElement.appendChild(link);
    279     },
    280 
    281     __proto__: WebInspector.ObjectPropertiesSection.prototype
    282 }
    283