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

Side by Side Diff: Source/devtools/front_end/components/EventListenersView.js

Issue 1268353005: [DevTools] Support JQuery event listeners (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 5 years, 3 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 unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 /** 5 /**
6 * @typedef {Array<{object: !WebInspector.RemoteObject, eventListeners: ?Array<! WebInspector.EventListener>, frameworkEventListeners: ?Array<!WebInspector.Event Listener>, frameworkInternalHandlers: ?WebInspector.RemoteSet, isInternal: ?Arra y<boolean>}>}
7 */
8 WebInspector.EventListenersResult;
9
10 /**
6 * @constructor 11 * @constructor
7 * @param {!Element} element 12 * @param {!Element} element
8 */ 13 */
9 WebInspector.EventListenersView = function(element) 14 WebInspector.EventListenersView = function(element)
10 { 15 {
11 this._element = element; 16 this._element = element;
12 this._treeOutline = new TreeOutlineInShadow("event-listener-tree"); 17 this._treeOutline = new TreeOutlineInShadow("event-listener-tree");
13 this._treeOutline.registerRequiredCSS("components/objectValue.css"); 18 this._treeOutline.registerRequiredCSS("components/objectValue.css");
14 this._treeOutline.registerRequiredCSS("components/eventListenersView.css"); 19 this._treeOutline.registerRequiredCSS("components/eventListenersView.css");
15 this._treeOutline.setComparator(WebInspector.EventListenersTreeElement.compa rator); 20 this._treeOutline.setComparator(WebInspector.EventListenersTreeElement.compa rator);
16 this._treeOutline.element.classList.add("monospace"); 21 this._treeOutline.element.classList.add("monospace");
17 this._element.appendChild(this._treeOutline.element) 22 this._element.appendChild(this._treeOutline.element)
18 this._emptyHolder = createElementWithClass("div", "info"); 23 this._emptyHolder = createElementWithClass("div", "info");
19 this._emptyHolder.textContent = WebInspector.UIString("No Event Listeners"); 24 this._emptyHolder.textContent = WebInspector.UIString("No Event Listeners");
20 this._linkifier = new WebInspector.Linkifier(); 25 this._linkifier = new WebInspector.Linkifier();
21 /** @type {!Map<string, !WebInspector.EventListenersTreeElement>} */ 26 /** @type {!Map<string, !WebInspector.EventListenersTreeElement>} */
22 this._treeItemMap = new Map(); 27 this._treeItemMap = new Map();
23 } 28 }
24 29
25 WebInspector.EventListenersView.prototype = { 30 WebInspector.EventListenersView.prototype = {
26 /** 31 /**
27 * @param {!Array<!WebInspector.RemoteObject>} objects 32 * @param {!Array<!WebInspector.RemoteObject>} objects
28 * @return {!Promise<undefined>} 33 * @return {!Promise<undefined>}
29 */ 34 */
30 addObjects: function(objects) 35 addObjects: function(objects)
pfeldman 2015/08/27 01:30:38 I am trying to understand what it does and it is s
31 { 36 {
32 var promises = []; 37 var promises = [];
33 for (var i = 0; i < objects.length; ++i) 38 var results = [];
34 promises.push(objects[i].eventListeners()); 39 for (var i = 0; i < objects.length; ++i) {
35 return Promise.all(promises).then(listenersCallback.bind(this)); 40 var result = {object: objects[i]};
41 results.push(result);
42 promises.push(objects[i].eventListeners().then(WebInspector.storeTo. bind(null, result, "eventListeners")));
pfeldman 2015/08/27 01:21:31 What's storeTo?
43 promises.push(objects[i].frameworkEventListeners(WebInspector.EventL istenersView._frameworkEventListenersGetter)
pfeldman 2015/08/27 01:30:38 In here we call remote objects' frameworkEventList
44 .then(WebInspector.storeTo.bind(null, result , "frameworkEventListeners")));
45 promises.push(objects[i].frameworkInternalHandlers(WebInspector.Even tListenersView._frameworkInternalHandlersGetter)
46 .then(WebInspector.storeTo.bind(null, result , "frameworkInternalHandlers")));
47 }
48 return Promise.all(promises).then(listenersCallback.bind(this, results)) ;
36 /** 49 /**
37 * @param {!Array<?Array<!WebInspector.EventListener>>} listeners 50 * @param {!WebInspector.EventListenersResult} results
38 * @this {WebInspector.EventListenersView} 51 * @this {WebInspector.EventListenersView}
39 */ 52 */
40 function listenersCallback(listeners) 53 function listenersCallback(results)
41 { 54 {
42 this.reset(); 55 this.reset();
43 for (var i = 0; i < listeners.length; ++i) 56 var promises = [];
44 this._addObjectEventListeners(objects[i], listeners[i]); 57 for (var i = 0; i < results.length; ++i) {
58 results[i].isInternal = [];
59 for (var j = 0; j < results[i].eventListeners.length; ++j) {
60 var handler = results[i].eventListeners[j].handler();
61 if (handler) {
62 promises.push(results[i].frameworkInternalHandlers.has(h andler)
63 .then( WebInspector.storeTo.bind(null, results[i].isInternal, j)));
64 }
65 }
66 }
67 return Promise.all(promises).then(addResults.bind(this, results));
68 }
69
70 /**
71 * @param {!WebInspector.EventListenersResult} results
72 * @this {WebInspector.EventListenersView}
73 */
74 function addResults(results)
75 {
76 for (var i = 0; i < results.length; ++i) {
77 this._addObjectEventListeners(results[i].object, results[i].even tListeners, "normal", results[i].isInternal);
78 this._addObjectEventListeners(results[i].object, results[i].fram eworkEventListeners, "frameworkUser", null);
79 }
45 this.addEmptyHolderIfNeeded(); 80 this.addEmptyHolderIfNeeded();
46 this._eventListenersArrivedForTest(); 81 this._eventListenersArrivedForTest();
47 } 82 }
48 }, 83 },
49 84
50 /** 85 /**
86 * @param {boolean} showFramework
87 */
88 showFrameworkListeners: function(showFramework)
89 {
90 var eventTypes = this._treeOutline.rootElement().children();
91 for (var eventType of eventTypes) {
92 for (var listenerElement of eventType.children()) {
93 var listenerType = listenerElement.listenerType();
94 var hidden = false;
95 if (listenerType === "frameworkUser" && !showFramework)
96 hidden = true;
97 if (listenerType === "frameworkInternal" && showFramework)
98 hidden = true;
99 listenerElement.hidden = hidden;
100 }
101 }
102 },
103
104 /**
51 * @param {!WebInspector.RemoteObject} object 105 * @param {!WebInspector.RemoteObject} object
52 * @param {?Array<!WebInspector.EventListener>} eventListeners 106 * @param {?Array<!WebInspector.EventListener>} eventListeners
107 * @param {string} listenerType
108 * @param {?Array<boolean>} isInternal
53 */ 109 */
54 _addObjectEventListeners: function(object, eventListeners) 110 _addObjectEventListeners: function(object, eventListeners, listenerType, isI nternal)
55 { 111 {
56 if (!eventListeners) 112 if (!eventListeners)
57 return; 113 return;
58 for (var eventListener of eventListeners) { 114 for (var i = 0; i < eventListeners.length; ++i) {
59 var treeItem = this._getOrCreateTreeElementForType(eventListener.typ e()); 115 var treeItem = this._getOrCreateTreeElementForType(eventListeners[i] .type());
60 treeItem.addObjectEventListener(eventListener, object); 116 treeItem.addObjectEventListener(eventListeners[i], object, isInterna l && isInternal[i] ? "frameworkInternal" : listenerType);
61 } 117 }
62 }, 118 },
63 119
64 /** 120 /**
65 * @param {string} type 121 * @param {string} type
66 * @return {!WebInspector.EventListenersTreeElement} 122 * @return {!WebInspector.EventListenersTreeElement}
67 */ 123 */
68 _getOrCreateTreeElementForType: function(type) 124 _getOrCreateTreeElementForType: function(type)
69 { 125 {
70 var treeItem = this._treeItemMap.get(type); 126 var treeItem = this._treeItemMap.get(type);
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
117 WebInspector.EventListenersTreeElement.comparator = function(element1, element2) { 173 WebInspector.EventListenersTreeElement.comparator = function(element1, element2) {
118 if (element1.title === element2.title) 174 if (element1.title === element2.title)
119 return 0; 175 return 0;
120 return element1.title > element2.title ? 1 : -1; 176 return element1.title > element2.title ? 1 : -1;
121 } 177 }
122 178
123 WebInspector.EventListenersTreeElement.prototype = { 179 WebInspector.EventListenersTreeElement.prototype = {
124 /** 180 /**
125 * @param {!WebInspector.EventListener} eventListener 181 * @param {!WebInspector.EventListener} eventListener
126 * @param {!WebInspector.RemoteObject} object 182 * @param {!WebInspector.RemoteObject} object
183 * @param {string} listenerType
127 */ 184 */
128 addObjectEventListener: function(eventListener, object) 185 addObjectEventListener: function(eventListener, object, listenerType)
129 { 186 {
130 var treeElement = new WebInspector.ObjectEventListenerBar(eventListener, object, this._linkifier); 187 var treeElement = new WebInspector.ObjectEventListenerBar(eventListener, object, this._linkifier, listenerType);
131 this.appendChild(/** @type {!TreeElement} */ (treeElement)); 188 this.appendChild(/** @type {!TreeElement} */ (treeElement));
132 }, 189 },
133 190
134 __proto__: TreeElement.prototype 191 __proto__: TreeElement.prototype
135 } 192 }
136 193
137 /** 194 /**
138 * @constructor 195 * @constructor
139 * @extends {TreeElement} 196 * @extends {TreeElement}
140 * @param {!WebInspector.EventListener} eventListener 197 * @param {!WebInspector.EventListener} eventListener
141 * @param {!WebInspector.RemoteObject} object 198 * @param {!WebInspector.RemoteObject} object
142 * @param {!WebInspector.Linkifier} linkifier 199 * @param {!WebInspector.Linkifier} linkifier
200 * @param {string} listenerType
143 */ 201 */
144 WebInspector.ObjectEventListenerBar = function(eventListener, object, linkifier) 202 WebInspector.ObjectEventListenerBar = function(eventListener, object, linkifier, listenerType)
145 { 203 {
146 TreeElement.call(this, "", true); 204 TreeElement.call(this, "", true);
147 this._eventListener = eventListener; 205 this._eventListener = eventListener;
148 this.editable = false; 206 this.editable = false;
149 this.selectable = false; 207 this.selectable = false;
150 this._setTitle(object, linkifier); 208 this._setTitle(object, linkifier);
209 this._listenerType = listenerType;
151 } 210 }
152 211
153 WebInspector.ObjectEventListenerBar.prototype = { 212 WebInspector.ObjectEventListenerBar.prototype = {
154 onpopulate: function() 213 onpopulate: function()
155 { 214 {
156 var properties = []; 215 var properties = [];
157 var eventListener = this._eventListener; 216 var eventListener = this._eventListener;
158 var runtimeModel = eventListener.target().runtimeModel; 217 var runtimeModel = eventListener.target().runtimeModel;
159 properties.push(runtimeModel.createRemotePropertyFromPrimitiveValue("use Capture", eventListener.useCapture())); 218 properties.push(runtimeModel.createRemotePropertyFromPrimitiveValue("use Capture", eventListener.useCapture()));
160 if (typeof eventListener.handler() !== "undefined") 219 if (typeof eventListener.handler() !== "undefined")
161 properties.push(new WebInspector.RemoteObjectProperty("handler", eve ntListener.handler())); 220 properties.push(new WebInspector.RemoteObjectProperty("handler", eve ntListener.handler()));
162 WebInspector.ObjectPropertyTreeElement.populateWithProperties(this, prop erties, [], true, null); 221 WebInspector.ObjectPropertyTreeElement.populateWithProperties(this, prop erties, [], true, null);
163 }, 222 },
164 223
165 /** 224 /**
166 * @param {!WebInspector.RemoteObject} object 225 * @param {!WebInspector.RemoteObject} object
167 * @param {!WebInspector.Linkifier} linkifier 226 * @param {!WebInspector.Linkifier} linkifier
168 */ 227 */
169 _setTitle: function(object, linkifier) 228 _setTitle: function(object, linkifier)
170 { 229 {
171 var title = this.listItemElement.createChild("span"); 230 var title = this.listItemElement.createChild("span");
172 var subtitle = this.listItemElement.createChild("span", "event-listener- tree-subtitle"); 231 var subtitle = this.listItemElement.createChild("span", "event-listener- tree-subtitle");
173 subtitle.appendChild(linkifier.linkifyRawLocation(this._eventListener.lo cation(), this._eventListener.sourceURL())); 232 subtitle.appendChild(linkifier.linkifyRawLocation(this._eventListener.lo cation(), this._eventListener.sourceURL()));
174 title.appendChild(WebInspector.ObjectPropertiesSection.createValueElemen t(object, false)); 233 title.appendChild(WebInspector.ObjectPropertiesSection.createValueElemen t(object, false));
175 }, 234 },
176 235
236 /**
237 * @return {string}
238 */
239 listenerType: function()
240 {
241 return this._listenerType;
242 },
243
177 __proto__: TreeElement.prototype 244 __proto__: TreeElement.prototype
178 } 245 }
246
247 /**
248 * @return {!Array<!{handler:function(), useCapture: boolean, type:string}>}
249 * @this {Object}
250 */
251 WebInspector.EventListenersView._frameworkEventListenersGetter = function()
252 {
253 var listeners = [];
254 var getters = [jQueryEventListeners];
255 try {
256 if (self.devtoolsFrameworkEventListeners && isArrayLike(self.devtoolsFra meworkEventListeners))
257 getters = getters.concat(self.devtoolsFrameworkEventListeners);
258 } catch (e) {
259 }
260
261 for (var i = 0; i < getters.length; ++i) {
262 try {
263 listeners = listeners.concat(getters[i](this));
264 } catch (e) {
265 }
266 }
267 return listeners;
268
269 /**
270 * @param {?Object} obj
271 * @return {boolean}
272 */
273 function isArrayLike(obj)
274 {
275 if (!obj || typeof obj !== "object")
276 return false;
277 try {
278 if (typeof obj.splice === "function") {
279 var len = obj.length;
280 return typeof len === "number" && (len >>> 0 === len && (len > 0 || 1 / len > 0));
281 }
282 } catch (e) {
283 }
284 return false;
285 }
286
287 /**
288 * @param {?Object} node
289 * @return {!Array<!{handler:function(), useCapture: boolean, type:string}>}
290 */
291 function jQueryEventListeners(node)
292 {
293 if (!node || !(node instanceof Node))
294 return [];
295 var hasJQuery = (typeof jQuery !== 'undefined') && jQuery.fn;
296 if (!hasJQuery)
297 return [];
298 var listeners = [];
299 var data = jQuery._data || jQuery.data;
300 if (typeof data === "function") {
301 var events = data(node, "events");
302 for (var type in events) {
303 for (var key in events[type]) {
304 var frameworkListener = events[type][key];
305 if (typeof frameworkListener === "object" || typeof framewor kListener === "function") {
306 var listener = {
307 handler: frameworkListener.handler || frameworkListe ner,
308 useCapture: true,
309 type: type
310 };
311 listeners.push(listener);
312 }
313 }
314 }
315 }
316 var entry = jQuery(node)[0];
317 if (entry) {
318 var entryEvents = entry["$events"];
319 for (var type in entryEvents) {
320 var events = entryEvents[type];
321 for (var key in events) {
322 if (typeof events[key] === "function") {
323 var listener = {
324 handler: events[key],
325 useCapture: true,
326 type: type
327 };
328 listeners.push(listener);
329 }
330 }
331 }
332 }
333 return listeners;
334 }
335 }
336
337 /**
338 * @return {!Array<function()>}
339 * @this {Object}
340 */
341 WebInspector.EventListenersView._frameworkInternalHandlersGetter = function()
pfeldman 2015/08/27 01:30:38 Can we do these two in one pass and return the str
342 {
343 var handlers = [];
344 var getters = [jQueryInternalHandlers];
345 try {
346 if (self.devtoolsFrameworkInternalHandlers && isArrayLike(self.devtoolsF rameworkInternalHandlers))
347 getters = getters.concat(self.devtoolsFrameworkInternalHandlers);
348 } catch (e) {
349 }
350
351 for (var i = 0; i < getters.length; ++i) {
352 try {
353 handlers = handlers.concat(getters[i](this));
354 } catch (e) {
355 }
356 }
357 return handlers;
358
359 /**
360 * @param {?Object} obj
361 * @return {boolean}
362 */
363 function isArrayLike(obj)
364 {
365 if (!obj || typeof obj !== "object")
366 return false;
367 try {
368 if (typeof obj.splice === "function") {
369 var len = obj.length;
370 return typeof len === "number" && (len >>> 0 === len && (len > 0 || 1 / len > 0));
371 }
372 } catch (e) {
373 }
374 return false;
375 }
376
377 /**
378 * @param {?Object} node
379 * @return {!Array<function()>}
380 */
381 function jQueryInternalHandlers(node)
382 {
383 if (!(node instanceof Node))
384 return [];
385 var hasJQuery = (typeof jQuery !== 'undefined') && jQuery.fn;
386 if (!hasJQuery)
387 return [];
388 var handlers = [];
389 var data = jQuery._data || jQuery.data;
390 if (typeof data === "function") {
391 var nodeData = data(node);
392 if (typeof nodeData.handle === "function")
393 handlers.push(nodeData.handle);
394 }
395 var entry = jQuery(node)[0];
396 if (entry && entry["$handle"])
397 handlers.push(entry["$handle"]);
398 return handlers;
399 }
400 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698