Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2024)

Unified Diff: Source/devtools/front_end/components/EventListenersTreeOutline.js

Issue 1042853004: [DevTools] Event Listeners Sidebar shows window listeners (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Extracted eventListenersTreeOutline.css Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/devtools/devtools.gypi ('k') | Source/devtools/front_end/components/eventListenersTreeOutline.css » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/devtools/front_end/components/EventListenersTreeOutline.js
diff --git a/Source/devtools/front_end/components/EventListenersTreeOutline.js b/Source/devtools/front_end/components/EventListenersTreeOutline.js
new file mode 100644
index 0000000000000000000000000000000000000000..a56b4c133d830b29f32fbd6d339f57f3092b77ea
--- /dev/null
+++ b/Source/devtools/front_end/components/EventListenersTreeOutline.js
@@ -0,0 +1,406 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/** @typedef {WebInspector.DOMModel.DOMEventListener|WebInspector.RuntimeModel.ObjectEventListener} */
+WebInspector.ModelEventListener;
+
+/**
+ * @constructor
+ * @param {!Element} element
+ */
+WebInspector.EventListenersTreeOutline = function(element)
+{
+ this._element = element;
+
+ this._treeOutline = new TreeOutline(true);
+ this._treeOutline.element.classList.add("event-listener-tree", "outline-disclosure", "monospace");
+ element.appendChild(this._treeOutline.element);
+
+ this._linkifier = new WebInspector.Linkifier();
+ this._lastProviders = [];
+}
+
+WebInspector.EventListenersTreeOutline.prototype = {
+ /**
+ * @param {?function()} finishCallback
+ * @param {?Array<!WebInspector.ModelEventListener>} eventListeners
+ */
+ _onEventListeners: function(finishCallback, eventListeners)
+ {
+ if (!eventListeners) {
+ if (finishCallback)
+ finishCallback();
+ return;
+ }
+
+ var treeItemMap = new Map();
+ eventListeners.stableSort(compareListeners);
+
+ /**
+ * @param {!WebInspector.ModelEventListener} a
+ * @param {!WebInspector.ModelEventListener} b
+ * @return {number}
+ */
+ function compareListeners(a, b)
+ {
+ var aType = a.type();
+ var bType = b.type();
+ return aType === bType ? 0 :
+ aType > bType ? 1 : -1;
+ }
+
+ for (var i = 0; i < eventListeners.length; ++i) {
+ var eventListener = eventListeners[i];
+ var type = eventListener.type();
+ var treeItem = treeItemMap.get(type);
+ if (!treeItem) {
+ treeItem = new WebInspector.EventListenersTreeElement(type, this._linkifier);
+ treeItemMap.set(type, treeItem);
+ this._treeOutline.appendChild(treeItem);
+ }
+ treeItem.addListener(eventListener);
+ }
+ if (treeItemMap.size === 0)
+ this._element.createChild("div", "info").textContent = WebInspector.UIString("No Event Listeners");
+ else
+ this._element.appendChild(this._treeOutline.element);
+
+ if (finishCallback)
+ finishCallback();
+ },
+
+ /**
+ * @param {?function()} finishCallback
+ * @param {?Array<!WebInspector.EventListenersProvider>} providers
+ */
+ runProviders: function(finishCallback, providers)
+ {
+ this._lastProviders = providers;
+
+ /**
+ * @this {!WebInspector.EventListenersTreeOutline}
+ * @param {!Array<?Array<!WebInspector.ModelEventListener>>} listeners
+ */
+ function onEventListeners(listeners)
+ {
+ listeners = listeners.filter(function(x){
+ return x;
+ });
+ var allListeners = [];
+ this._onEventListeners(finishCallback, allListeners.concat.apply(allListeners, listeners));
+ }
+
+ Promise.all(providers.map(function(provider){
+ return provider.getFilteredEventListenersPromise();
+ })).then(onEventListeners.bind(this));
+ },
+
+ reset: function()
+ {
+ this._element.removeChildren();
+ this._treeOutline.removeChildren();
+
+ this._linkifier.reset();
+ for (var i = 0; i < this._lastProviders.length; ++i)
+ this._lastProviders[i].releaseListeners();
+ }
+}
+
+/**
+ * @constructor
+ * @extends {TreeElement}
+ * @param {string} type
+ * @param {!WebInspector.Linkifier} linkifier
+ */
+WebInspector.EventListenersTreeElement = function(type, linkifier)
+{
+ this._linkifier = linkifier;
+
+ TreeElement.call(this, type);
+ this.toggleOnClick = true;
+ this.selectable = false;
+}
+
+WebInspector.EventListenersTreeElement.prototype = {
+ /**
+ * @param {!WebInspector.ModelEventListener} eventListener
+ */
+ addListener: function(eventListener)
+ {
+ var treeElement;
+ if (eventListener.isDOMEventListener()) {
+ treeElement = new WebInspector.DOMEventListenerBar(/** @type {!WebInspector.DOMModel.DOMEventListener} */ (eventListener), this._linkifier);
+ } else if (eventListener.isObjectEventListener()) {
+ treeElement = new WebInspector.ObjectEventListenerBar(/** @type {!WebInspector.RuntimeModel.ObjectEventListener} */ (eventListener), this._linkifier);
+ }
+ this.appendChild(/** @type {!TreeElement} */ (treeElement));
+ },
+
+ __proto__: TreeElement.prototype
+}
+
+/**
+ * @constructor
+ * @template EventListener
+ * @param {?Array<string>} allowedTypes
+ */
+WebInspector.EventListenersProvider = function(allowedTypes)
+{
+ this._allowedTypes = allowedTypes ? new Set(allowedTypes) : null;
+}
+
+WebInspector.EventListenersProvider.prototype = {
+ /**
+ * @param {function(?Array<!EventListener>)} callback
+ */
+ getFilteredEventListeners: function(callback)
+ {
+ /**
+ * @this {!WebInspector.EventListenersProvider}
+ * @param {?Array<!EventListener>} listeners
+ */
+ function mycallback(listeners)
+ {
+ if (!listeners) {
+ callback(null);
+ return;
+ }
+
+ callback(listeners.filter(this._filterEventListener.bind(this)));
+ }
+ this._getEventListeners(mycallback.bind(this));
+ },
+
+ /**
+ * @return {!Promise<?Array<!EventListener>>}
+ */
+ getFilteredEventListenersPromise: function()
+ {
+ return new Promise(this.getFilteredEventListeners.bind(this));
+ },
+
+ /**
+ * @param {function(?Array.<!EventListener>)} callback
+ */
+ _getEventListeners: function(callback)
+ {
+ },
+
+ /**
+ * @param {!EventListener} eventListener
+ */
+ _filterEventListener: function(eventListener)
+ {
+ if (eventListener.location().script().isInternalScript())
+ return false;
+ if (this._allowedTypes && !this._allowedTypes.has(eventListener.type()))
+ return false;
+ return true;
+ },
+
+ releaseListeners: function()
+ {
+ }
+}
+
+/**
+ * @constructor
+ * @extends {WebInspector.EventListenersProvider<!WebInspector.DOMModel.DOMEventListener>}
+ * @param {?Array<string>} allowedTypes
+ * @param {!WebInspector.DOMNode} node
+ * @param {?WebInspector.DOMNode} selectedNode
+ */
+WebInspector.DOMEventListenersProvider = function(allowedTypes, node, selectedNode)
+{
+ WebInspector.EventListenersProvider.call(this, allowedTypes);
+ this._node = node;
+ this._selectedNode = selectedNode;
+}
+
+WebInspector.DOMEventListenersProvider._objectGroupName = "dom-event-listeners";
+
+WebInspector.DOMEventListenersProvider.prototype = {
+ /**
+ * @override
+ * @param {function(?Array<!WebInspector.DOMModel.DOMEventListener>)} callback
+ */
+ _getEventListeners: function(callback)
+ {
+ /**
+ * @param {?Array<!WebInspector.DOMModel.DOMEventListener>} listeners
+ */
+ function mycallback(listeners)
+ {
+ if (!listeners) {
+ callback(null);
+ return;
+ }
+ listeners = listeners.map(function(listener){
+ listener.isSelected = this._selectedNode && this._selectedNode.id === listener.payload().nodeId;
+ return listener
+ });
+ callback(listeners);
+ }
+ this._node.eventListeners(WebInspector.DOMEventListenersProvider._objectGroupName, callback);
+ },
+
+ /**
+ * @override
+ * @param {!WebInspector.DOMModel.DOMEventListener} eventListener
+ */
+ _filterEventListener: function(eventListener)
+ {
+ if (!WebInspector.EventListenersProvider.prototype._filterEventListener.call(this, eventListener))
+ return false;
+ if (this._selectedNode && this._selectedNode.id !== eventListener.payload().nodeId)
+ return false;
+ return true;
+ },
+
+ releaseListeners: function()
+ {
+ this._node.target().runtimeAgent().releaseObjectGroup(WebInspector.DOMEventListenersProvider._objectGroupName);
+ },
+
+ __proto__: WebInspector.EventListenersProvider.prototype
+}
+
+/**
+ * @constructor
+ * @extends {WebInspector.EventListenersProvider<!WebInspector.RuntimeModel.ObjectEventListener>}
+ * @param {?Array<string>} allowedTypes
+ * @param {!WebInspector.RemoteObject} object
+ */
+WebInspector.ObjectEventListenersProvider = function(allowedTypes, object)
+{
+ WebInspector.EventListenersProvider.call(this, allowedTypes);
+ this._object = object;
+}
+
+WebInspector.ObjectEventListenersProvider.objectGroupName = "object-event-listeners";
+
+WebInspector.ObjectEventListenersProvider.prototype = {
+ /**
+ * @override
+ * @param {function(?Array.<!WebInspector.RuntimeModel.ObjectEventListener>)} callback
+ */
+ _getEventListeners: function(callback)
+ {
+ this._object.getEventListeners(WebInspector.ObjectEventListenersProvider.objectGroupName, callback);
+ },
+
+ releaseListeners: function()
+ {
+ this._object.target().runtimeAgent().releaseObjectGroup(WebInspector.ObjectEventListenersProvider.objectGroupName);
+ },
+
+ __proto__: WebInspector.EventListenersProvider.prototype
+}
+
+/**
+ * @constructor
+ * @extends {TreeElement}
+ * @param {!WebInspector.DOMModel.DOMEventListener} eventListener
+ * @param {!WebInspector.Linkifier} linkifier
+ */
+WebInspector.DOMEventListenerBar = function(eventListener, linkifier)
+{
+ TreeElement.call(this, "", true);
+
+ var target = eventListener.target();
+ this._runtimeModel = target.runtimeModel;
+ this._eventListener = eventListener;
+ this._setNodeTitle(linkifier);
+ this.editable = false;
+}
+
+WebInspector.DOMEventListenerBar.prototype = {
+ onpopulate: function()
+ {
+ /**
+ * @this {!WebInspector.DOMEventListenerBar}
+ * @param {!Array<!WebInspector.RemoteObjectProperty>} properties
+ */
+ function populate(properties)
+ {
+ WebInspector.ObjectPropertyTreeElement.populateWithProperties(this, properties, [], true, null);
+ }
+ this._eventListener.getProperties(populate.bind(this), WebInspector.DOMEventListenersProvider._objectGroupName);
+ },
+
+ /**
+ * @param {!WebInspector.Linkifier} linkifier
+ */
+ _setNodeTitle: function(linkifier)
+ {
+ var node = this._eventListener.node();
+ if (!node)
+ return;
+
+ this.listItemElement.removeChildren();
+ var title = this.listItemElement.createChild("span");
+ var subtitle = this.listItemElement.createChild("span", "event-listener-tree-subtitle");
+ subtitle.appendChild(linkifier.linkifyRawLocation(this._eventListener.location(), this._eventListener.sourceName()));
+
+ if (node.nodeType() === Node.DOCUMENT_NODE) {
+ title.textContent = "document";
+ return;
+ }
+
+ if (this._eventListener.isSelected) {
+ title.textContent = WebInspector.DOMPresentationUtils.simpleSelector(node);
+ return;
+ }
+
+ title.appendChild(WebInspector.DOMPresentationUtils.linkifyNodeReference(node));
+ },
+
+ __proto__: TreeElement.prototype
+}
+
+/**
+ * @constructor
+ * @extends {TreeElement}
+ * @param {!WebInspector.RuntimeModel.ObjectEventListener} eventListener
+ * @param {!WebInspector.Linkifier} linkifier
+ */
+WebInspector.ObjectEventListenerBar = function(eventListener, linkifier)
+{
+ TreeElement.call(this, "", true);
+
+ var target = eventListener.target();
+ this._runtimeModel = target.runtimeModel;
+ this._eventListener = eventListener;
+ this._setNodeTitle(linkifier);
+ this.editable = false;
+}
+
+WebInspector.ObjectEventListenerBar.prototype = {
+ onpopulate: function()
+ {
+ /**
+ * @this {!WebInspector.ObjectEventListenerBar}
+ * @param {!Array<!WebInspector.RemoteObjectProperty>} properties
+ */
+ function populate(properties)
+ {
+ WebInspector.ObjectPropertyTreeElement.populateWithProperties(this, properties, [], true, null);
+ }
+ this._eventListener.getProperties(populate.bind(this), WebInspector.ObjectEventListenersProvider.objectGroupName);
+ },
+
+ /**
+ * @param {!WebInspector.Linkifier} linkifier
+ */
+ _setNodeTitle: function(linkifier)
+ {
+ this.listItemElement.removeChildren();
+ var title = this.listItemElement.createChild("span");
+ var subtitle = this.listItemElement.createChild("span", "event-listener-tree-subtitle");
+ subtitle.appendChild(linkifier.linkifyRawLocation(this._eventListener.location(), this._eventListener.sourceName()));
+ title.textContent = this._eventListener.description();
+ },
+
+ __proto__: TreeElement.prototype
+}
« no previous file with comments | « Source/devtools/devtools.gypi ('k') | Source/devtools/front_end/components/eventListenersTreeOutline.css » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698