2 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * @extends {WebInspector.SidebarPane}
29 * @param {!WebInspector.BreakpointManager} breakpointManager
30 * @param {function(!WebInspector.UISourceCode, number=, number=, boolean=)} showSourceLineDelegate
32 WebInspector.JavaScriptBreakpointsSidebarPane = function(breakpointManager, showSourceLineDelegate)
34 WebInspector.SidebarPane.call(this, WebInspector.UIString("Breakpoints"));
35 this.registerRequiredCSS("breakpointsList.css");
37 this._breakpointManager = breakpointManager;
38 this._showSourceLineDelegate = showSourceLineDelegate;
40 this.listElement = document.createElementWithClass("ol", "breakpoint-list");
42 this.emptyElement = this.bodyElement.createChild("div", "info");
43 this.emptyElement.textContent = WebInspector.UIString("No Breakpoints");
45 this._items = new Map();
47 var breakpointLocations = this._breakpointManager.allBreakpointLocations();
48 for (var i = 0; i < breakpointLocations.length; ++i)
49 this._addBreakpoint(breakpointLocations[i].breakpoint, breakpointLocations[i].uiLocation);
51 this._breakpointManager.addEventListener(WebInspector.BreakpointManager.Events.BreakpointAdded, this._breakpointAdded, this);
52 this._breakpointManager.addEventListener(WebInspector.BreakpointManager.Events.BreakpointRemoved, this._breakpointRemoved, this);
54 this.emptyElement.addEventListener("contextmenu", this._emptyElementContextMenu.bind(this), true);
57 WebInspector.JavaScriptBreakpointsSidebarPane.prototype = {
58 _emptyElementContextMenu: function(event)
60 var contextMenu = new WebInspector.ContextMenu(event);
61 this._appendBreakpointActiveItem(contextMenu);
66 * @param {!WebInspector.ContextMenu} contextMenu
68 _appendBreakpointActiveItem: function(contextMenu)
70 var breakpointActive = this._breakpointManager.breakpointsActive();
71 var breakpointActiveTitle = breakpointActive ?
72 WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Deactivate breakpoints" : "Deactivate Breakpoints") :
73 WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Activate breakpoints" : "Activate Breakpoints");
74 contextMenu.appendItem(breakpointActiveTitle, this._breakpointManager.setBreakpointsActive.bind(this._breakpointManager, !breakpointActive));
78 * @param {!WebInspector.Event} event
80 _breakpointAdded: function(event)
82 this._breakpointRemoved(event);
84 var breakpoint = /** @type {!WebInspector.BreakpointManager.Breakpoint} */ (event.data.breakpoint);
85 var uiLocation = /** @type {!WebInspector.UILocation} */ (event.data.uiLocation);
86 this._addBreakpoint(breakpoint, uiLocation);
90 * @param {!WebInspector.BreakpointManager.Breakpoint} breakpoint
91 * @param {!WebInspector.UILocation} uiLocation
93 _addBreakpoint: function(breakpoint, uiLocation)
95 var element = document.createElementWithClass("li", "cursor-pointer");
96 element.addEventListener("contextmenu", this._breakpointContextMenu.bind(this, breakpoint), true);
97 element.addEventListener("click", this._breakpointClicked.bind(this, uiLocation), false);
99 var checkbox = element.createChild("input", "checkbox-elem");
100 checkbox.type = "checkbox";
101 checkbox.checked = breakpoint.enabled();
102 checkbox.addEventListener("click", this._breakpointCheckboxClicked.bind(this, breakpoint), false);
104 element.createTextChild(uiLocation.linkText());
106 var snippetElement = element.createChild("div", "source-text monospace");
109 * @param {?string} content
111 function didRequestContent(content)
113 var lineNumber = uiLocation.lineNumber
114 var columnNumber = uiLocation.columnNumber;
115 var contentString = new String(content);
116 if (lineNumber < contentString.lineCount()) {
117 var lineText = contentString.lineAt(lineNumber);
118 var maxSnippetLength = 200;
119 var snippetStartIndex = columnNumber > 100 ? columnNumber : 0;
120 snippetElement.textContent = lineText.substr(snippetStartIndex).trimEnd(maxSnippetLength);
124 uiLocation.uiSourceCode.requestContent(didRequestContent);
126 element._data = uiLocation;
127 var currentElement = this.listElement.firstChild;
128 while (currentElement) {
129 if (currentElement._data && this._compareBreakpoints(currentElement._data, element._data) > 0)
131 currentElement = currentElement.nextSibling;
133 this._addListElement(element, currentElement);
135 var breakpointItem = { element: element, checkbox: checkbox };
136 this._items.set(breakpoint, breakpointItem);
142 * @param {!WebInspector.Event} event
144 _breakpointRemoved: function(event)
146 var breakpoint = /** @type {!WebInspector.BreakpointManager.Breakpoint} */ (event.data.breakpoint);
147 var uiLocation = /** @type {!WebInspector.UILocation} */ (event.data.uiLocation);
148 var breakpointItem = this._items.get(breakpoint);
151 this._items.remove(breakpoint);
152 this._removeListElement(breakpointItem.element);
156 * @param {!WebInspector.BreakpointManager.Breakpoint} breakpoint
158 highlightBreakpoint: function(breakpoint)
160 var breakpointItem = this._items.get(breakpoint);
163 breakpointItem.element.classList.add("breakpoint-hit");
164 this._highlightedBreakpointItem = breakpointItem;
167 clearBreakpointHighlight: function()
169 if (this._highlightedBreakpointItem) {
170 this._highlightedBreakpointItem.element.classList.remove("breakpoint-hit");
171 delete this._highlightedBreakpointItem;
175 _breakpointClicked: function(uiLocation, event)
177 this._showSourceLineDelegate(uiLocation.uiSourceCode, uiLocation.lineNumber);
181 * @param {!WebInspector.BreakpointManager.Breakpoint} breakpoint
182 * @param {!Event} event
184 _breakpointCheckboxClicked: function(breakpoint, event)
186 // Breakpoint element has it's own click handler.
188 breakpoint.setEnabled(event.target.checked);
192 * @param {!WebInspector.BreakpointManager.Breakpoint} breakpoint
193 * @param {!Event} event
195 _breakpointContextMenu: function(breakpoint, event)
197 var breakpoints = this._items.values();
198 var contextMenu = new WebInspector.ContextMenu(event);
199 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Remove breakpoint" : "Remove Breakpoint"), breakpoint.remove.bind(breakpoint));
200 if (breakpoints.length > 1) {
201 var removeAllTitle = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Remove all breakpoints" : "Remove All Breakpoints");
202 contextMenu.appendItem(removeAllTitle, this._breakpointManager.removeAllBreakpoints.bind(this._breakpointManager));
205 contextMenu.appendSeparator();
206 this._appendBreakpointActiveItem(contextMenu);
208 function enabledBreakpointCount(breakpoints)
211 for (var i = 0; i < breakpoints.length; ++i) {
212 if (breakpoints[i].checkbox.checked)
217 if (breakpoints.length > 1) {
218 var enableBreakpointCount = enabledBreakpointCount(breakpoints);
219 var enableTitle = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Enable all breakpoints" : "Enable All Breakpoints");
220 var disableTitle = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Disable all breakpoints" : "Disable All Breakpoints");
222 contextMenu.appendSeparator();
224 contextMenu.appendItem(enableTitle, this._breakpointManager.toggleAllBreakpoints.bind(this._breakpointManager, true), !(enableBreakpointCount != breakpoints.length));
225 contextMenu.appendItem(disableTitle, this._breakpointManager.toggleAllBreakpoints.bind(this._breakpointManager, false), !(enableBreakpointCount > 1));
231 _addListElement: function(element, beforeElement)
234 this.listElement.insertBefore(element, beforeElement);
236 if (!this.listElement.firstChild) {
237 this.bodyElement.removeChild(this.emptyElement);
238 this.bodyElement.appendChild(this.listElement);
240 this.listElement.appendChild(element);
244 _removeListElement: function(element)
246 this.listElement.removeChild(element);
247 if (!this.listElement.firstChild) {
248 this.bodyElement.removeChild(this.listElement);
249 this.bodyElement.appendChild(this.emptyElement);
253 _compare: function(x, y)
256 return x < y ? -1 : 1;
260 _compareBreakpoints: function(b1, b2)
262 return this._compare(b1.uiSourceCode.originURL(), b2.uiSourceCode.originURL()) || this._compare(b1.lineNumber, b2.lineNumber);
267 this.listElement.removeChildren();
268 if (this.listElement.parentElement) {
269 this.bodyElement.removeChild(this.listElement);
270 this.bodyElement.appendChild(this.emptyElement);
275 __proto__: WebInspector.SidebarPane.prototype
280 * @extends {WebInspector.NativeBreakpointsSidebarPane}
281 * @implements {WebInspector.TargetManager.Observer}
283 WebInspector.XHRBreakpointsSidebarPane = function()
285 WebInspector.NativeBreakpointsSidebarPane.call(this, WebInspector.UIString("XHR Breakpoints"));
287 // FIXME: Use StringMap.
288 this._breakpointElements = { __proto__: null };
290 var addButton = this.titleElement.createChild("button", "pane-title-button add");
291 addButton.title = WebInspector.UIString("Add XHR breakpoint");
292 addButton.addEventListener("click", this._addButtonClicked.bind(this), false);
294 this.emptyElement.addEventListener("contextmenu", this._emptyElementContextMenu.bind(this), true);
296 WebInspector.targetManager.observeTargets(this);
299 WebInspector.XHRBreakpointsSidebarPane.prototype = {
301 * @param {!WebInspector.Target} target
303 targetAdded: function(target)
305 this._restoreBreakpoints(target);
309 * @param {!WebInspector.Target} target
311 targetRemoved: function(target) { },
313 _emptyElementContextMenu: function(event)
315 var contextMenu = new WebInspector.ContextMenu(event);
316 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Add breakpoint" : "Add Breakpoint"), this._addButtonClicked.bind(this));
320 _addButtonClicked: function(event)
327 var inputElementContainer = document.createElementWithClass("p", "breakpoint-condition");
328 inputElementContainer.textContent = WebInspector.UIString("Break when URL contains:");
330 var inputElement = inputElementContainer.createChild("span", "editing");
331 inputElement.id = "breakpoint-condition-input";
332 this.addListElement(inputElementContainer, /** @type {?Element} */ (this.listElement.firstChild));
335 * @param {boolean} accept
336 * @param {!Element} e
337 * @param {string} text
338 * @this {WebInspector.XHRBreakpointsSidebarPane}
340 function finishEditing(accept, e, text)
342 this.removeListElement(inputElementContainer);
344 this._setBreakpoint(text, true);
345 this._saveBreakpoints();
349 var config = new WebInspector.InplaceEditor.Config(finishEditing.bind(this, true), finishEditing.bind(this, false));
350 WebInspector.InplaceEditor.startEditing(inputElement, config);
354 * @param {string} url
355 * @param {boolean} enabled
356 * @param {!WebInspector.Target=} target
358 _setBreakpoint: function(url, enabled, target)
361 this._updateBreakpointOnTarget(url, true, target);
363 if (url in this._breakpointElements)
366 var element = document.createElement("li");
368 element.addEventListener("contextmenu", this._contextMenu.bind(this, url), true);
370 var checkboxElement = element.createChild("input", "checkbox-elem");
371 checkboxElement.type = "checkbox";
372 checkboxElement.checked = enabled;
373 checkboxElement.addEventListener("click", this._checkboxClicked.bind(this, url), false);
374 element._checkboxElement = checkboxElement;
376 var labelElement = element.createChild("span", "cursor-auto");
378 labelElement.textContent = WebInspector.UIString("Any XHR");
380 labelElement.textContent = WebInspector.UIString("URL contains \"%s\"", url);
381 labelElement.addEventListener("dblclick", this._labelClicked.bind(this, url), false);
383 var currentElement = /** @type {?Element} */ (this.listElement.firstChild);
384 while (currentElement) {
385 if (currentElement._url && currentElement._url < element._url)
387 currentElement = /** @type {?Element} */ (currentElement.nextSibling);
389 this.addListElement(element, currentElement);
390 this._breakpointElements[url] = element;
394 * @param {string} url
395 * @param {!WebInspector.Target=} target
397 _removeBreakpoint: function(url, target)
399 var element = this._breakpointElements[url];
403 this.removeListElement(element);
404 delete this._breakpointElements[url];
405 if (element._checkboxElement.checked)
406 this._updateBreakpointOnTarget(url, false, target);
410 * @param {string} url
411 * @param {boolean} enable
412 * @param {!WebInspector.Target=} target
414 _updateBreakpointOnTarget: function(url, enable, target)
416 var targets = target ? [target] : WebInspector.targetManager.targets();
417 for (var i = 0; i < targets.length; ++i) {
419 targets[i].domdebuggerAgent().setXHRBreakpoint(url);
421 targets[i].domdebuggerAgent().removeXHRBreakpoint(url);
425 _contextMenu: function(url, event)
427 var contextMenu = new WebInspector.ContextMenu(event);
430 * @this {WebInspector.XHRBreakpointsSidebarPane}
432 function removeBreakpoint()
434 this._removeBreakpoint(url);
435 this._saveBreakpoints();
439 * @this {WebInspector.XHRBreakpointsSidebarPane}
441 function removeAllBreakpoints()
443 for (var url in this._breakpointElements)
444 this._removeBreakpoint(url);
445 this._saveBreakpoints();
447 var removeAllTitle = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Remove all breakpoints" : "Remove All Breakpoints");
449 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Add breakpoint" : "Add Breakpoint"), this._addButtonClicked.bind(this));
450 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Remove breakpoint" : "Remove Breakpoint"), removeBreakpoint.bind(this));
451 contextMenu.appendItem(removeAllTitle, removeAllBreakpoints.bind(this));
455 _checkboxClicked: function(url, event)
457 this._updateBreakpointOnTarget(url, event.target.checked);
458 this._saveBreakpoints();
461 _labelClicked: function(url)
463 var element = this._breakpointElements[url];
464 var inputElement = document.createElementWithClass("span", "breakpoint-condition editing");
465 inputElement.textContent = url;
466 this.listElement.insertBefore(inputElement, element);
467 element.classList.add("hidden");
470 * @param {boolean} accept
471 * @param {!Element} e
472 * @param {string} text
473 * @this {WebInspector.XHRBreakpointsSidebarPane}
475 function finishEditing(accept, e, text)
477 this.removeListElement(inputElement);
479 this._removeBreakpoint(url);
480 this._setBreakpoint(text, element._checkboxElement.checked);
481 this._saveBreakpoints();
483 element.classList.remove("hidden");
486 WebInspector.InplaceEditor.startEditing(inputElement, new WebInspector.InplaceEditor.Config(finishEditing.bind(this, true), finishEditing.bind(this, false)));
489 highlightBreakpoint: function(url)
491 var element = this._breakpointElements[url];
495 element.classList.add("breakpoint-hit");
496 this._highlightedElement = element;
499 clearBreakpointHighlight: function()
501 if (this._highlightedElement) {
502 this._highlightedElement.classList.remove("breakpoint-hit");
503 delete this._highlightedElement;
507 _saveBreakpoints: function()
509 var breakpoints = [];
510 for (var url in this._breakpointElements)
511 breakpoints.push({ url: url, enabled: this._breakpointElements[url]._checkboxElement.checked });
512 WebInspector.settings.xhrBreakpoints.set(breakpoints);
516 * @param {!WebInspector.Target} target
518 _restoreBreakpoints: function(target)
520 var breakpoints = WebInspector.settings.xhrBreakpoints.get();
521 for (var i = 0; i < breakpoints.length; ++i) {
522 var breakpoint = breakpoints[i];
523 if (breakpoint && typeof breakpoint.url === "string")
524 this._setBreakpoint(breakpoint.url, breakpoint.enabled, target);
528 __proto__: WebInspector.NativeBreakpointsSidebarPane.prototype
533 * @extends {WebInspector.SidebarPane}
534 * @implements {WebInspector.TargetManager.Observer}
536 WebInspector.EventListenerBreakpointsSidebarPane = function()
538 WebInspector.SidebarPane.call(this, WebInspector.UIString("Event Listener Breakpoints"));
539 this.registerRequiredCSS("breakpointsList.css");
541 this.categoriesElement = this.bodyElement.createChild("ol", "properties-tree event-listener-breakpoints");
542 this.categoriesElement.tabIndex = 0;
543 this.categoriesTreeOutline = new TreeOutline(this.categoriesElement);
545 this._categoryItems = [];
546 // FIXME: uncomment following once inspector stops being drop targer in major ports.
547 // Otherwise, inspector page reacts on drop event and tries to load the event data.
548 // this._createCategory(WebInspector.UIString("Drag"), ["drag", "drop", "dragstart", "dragend", "dragenter", "dragleave", "dragover"]);
549 this._createCategory(WebInspector.UIString("Animation"), ["requestAnimationFrame", "cancelAnimationFrame", "animationFrameFired"], true);
550 this._createCategory(WebInspector.UIString("Control"), ["resize", "scroll", "zoom", "focus", "blur", "select", "change", "submit", "reset"]);
551 this._createCategory(WebInspector.UIString("Clipboard"), ["copy", "cut", "paste", "beforecopy", "beforecut", "beforepaste"]);
552 this._createCategory(WebInspector.UIString("DOM Mutation"), ["DOMActivate", "DOMFocusIn", "DOMFocusOut", "DOMAttrModified", "DOMCharacterDataModified", "DOMNodeInserted", "DOMNodeInsertedIntoDocument", "DOMNodeRemoved", "DOMNodeRemovedFromDocument", "DOMSubtreeModified", "DOMContentLoaded"]);
553 this._createCategory(WebInspector.UIString("Device"), ["deviceorientation", "devicemotion"]);
554 this._createCategory(WebInspector.UIString("Drag / drop"), ["dragenter", "dragover", "dragleave", "drop"]);
555 this._createCategory(WebInspector.UIString("Keyboard"), ["keydown", "keyup", "keypress", "input"]);
556 this._createCategory(WebInspector.UIString("Load"), ["load", "beforeunload", "unload", "abort", "error", "hashchange", "popstate"]);
557 this._createCategory(WebInspector.UIString("Media"), ["play", "pause", "playing", "canplay", "canplaythrough", "seeking", "seeked", "timeupdate", "ended", "ratechange", "durationchange", "volumechange", "loadstart", "progress", "suspend", "abort", "error", "emptied", "stalled", "loadedmetadata", "loadeddata", "waiting"], false, ["audio", "video"]);
558 this._createCategory(WebInspector.UIString("Mouse"), ["click", "dblclick", "mousedown", "mouseup", "mouseover", "mousemove", "mouseout", "mousewheel", "wheel"]);
559 this._createCategory(WebInspector.UIString("Promise"), ["newPromise", "promiseResolved", "promiseRejected"], true);
560 this._createCategory(WebInspector.UIString("Timer"), ["setTimer", "clearTimer", "timerFired"], true);
561 this._createCategory(WebInspector.UIString("Touch"), ["touchstart", "touchmove", "touchend", "touchcancel"]);
562 this._createCategory(WebInspector.UIString("XHR"), ["readystatechange", "load", "loadstart", "loadend", "abort", "error", "progress", "timeout"], false, ["XMLHttpRequest", "XMLHttpRequestUpload"]);
563 this._createCategory(WebInspector.UIString("WebGL"), ["webglErrorFired", "webglWarningFired"], true);
564 this._createCategory(WebInspector.UIString("Window"), ["close"], true);
566 WebInspector.targetManager.observeTargets(this);
569 WebInspector.EventListenerBreakpointsSidebarPane.categoryListener = "listener:";
570 WebInspector.EventListenerBreakpointsSidebarPane.categoryInstrumentation = "instrumentation:";
571 WebInspector.EventListenerBreakpointsSidebarPane.eventTargetAny = "*";
574 * @param {string} eventName
575 * @param {!Object=} auxData
578 WebInspector.EventListenerBreakpointsSidebarPane.eventNameForUI = function(eventName, auxData)
580 if (!WebInspector.EventListenerBreakpointsSidebarPane._eventNamesForUI) {
581 WebInspector.EventListenerBreakpointsSidebarPane._eventNamesForUI = {
582 "instrumentation:setTimer": WebInspector.UIString("Set Timer"),
583 "instrumentation:clearTimer": WebInspector.UIString("Clear Timer"),
584 "instrumentation:timerFired": WebInspector.UIString("Timer Fired"),
585 "instrumentation:newPromise": WebInspector.UIString("Promise Created"),
586 "instrumentation:promiseResolved": WebInspector.UIString("Promise Resolved"),
587 "instrumentation:promiseRejected": WebInspector.UIString("Promise Rejected"),
588 "instrumentation:requestAnimationFrame": WebInspector.UIString("Request Animation Frame"),
589 "instrumentation:cancelAnimationFrame": WebInspector.UIString("Cancel Animation Frame"),
590 "instrumentation:animationFrameFired": WebInspector.UIString("Animation Frame Fired"),
591 "instrumentation:webglErrorFired": WebInspector.UIString("WebGL Error Fired"),
592 "instrumentation:webglWarningFired": WebInspector.UIString("WebGL Warning Fired")
596 if (eventName === "instrumentation:webglErrorFired" && auxData["webglErrorName"]) {
597 var errorName = auxData["webglErrorName"];
598 // If there is a hex code of the error, display only this.
599 errorName = errorName.replace(/^.*(0x[0-9a-f]+).*$/i, "$1");
600 return WebInspector.UIString("WebGL Error Fired (%s)", errorName);
603 return WebInspector.EventListenerBreakpointsSidebarPane._eventNamesForUI[eventName] || eventName.substring(eventName.indexOf(":") + 1);
606 WebInspector.EventListenerBreakpointsSidebarPane.prototype = {
608 * @param {!WebInspector.Target} target
610 targetAdded: function(target)
612 this._restoreBreakpoints(target);
616 * @param {!WebInspector.Target} target
618 targetRemoved: function(target) { },
621 * @param {string} name
622 * @param {!Array.<string>} eventNames
623 * @param {boolean=} isInstrumentationEvent
624 * @param {!Array.<string>=} targetNames
626 _createCategory: function(name, eventNames, isInstrumentationEvent, targetNames)
628 var labelNode = document.createElement("label");
629 labelNode.textContent = name;
631 var categoryItem = {};
632 categoryItem.element = new TreeElement(labelNode);
633 this.categoriesTreeOutline.appendChild(categoryItem.element);
634 categoryItem.element.listItemElement.classList.add("event-category");
635 categoryItem.element.selectable = true;
637 categoryItem.checkbox = this._createCheckbox(labelNode);
638 categoryItem.checkbox.addEventListener("click", this._categoryCheckboxClicked.bind(this, categoryItem), true);
640 categoryItem.targetNames = this._stringArrayToLowerCase(targetNames || [WebInspector.EventListenerBreakpointsSidebarPane.eventTargetAny]);
641 categoryItem.children = {};
642 var category = (isInstrumentationEvent ? WebInspector.EventListenerBreakpointsSidebarPane.categoryInstrumentation : WebInspector.EventListenerBreakpointsSidebarPane.categoryListener);
643 for (var i = 0; i < eventNames.length; ++i) {
644 var eventName = category + eventNames[i];
646 var breakpointItem = {};
647 var title = WebInspector.EventListenerBreakpointsSidebarPane.eventNameForUI(eventName);
649 labelNode = document.createElement("label");
650 labelNode.textContent = title;
652 breakpointItem.element = new TreeElement(labelNode);
653 categoryItem.element.appendChild(breakpointItem.element);
655 breakpointItem.element.listItemElement.createChild("div", "breakpoint-hit-marker");
656 breakpointItem.element.listItemElement.classList.add("source-code");
657 breakpointItem.element.selectable = false;
659 breakpointItem.checkbox = this._createCheckbox(labelNode);
660 breakpointItem.checkbox.addEventListener("click", this._breakpointCheckboxClicked.bind(this, eventName, categoryItem.targetNames), true);
661 breakpointItem.parent = categoryItem;
663 categoryItem.children[eventName] = breakpointItem;
665 this._categoryItems.push(categoryItem);
669 * @param {!Array.<string>} array
670 * @return {!Array.<string>}
672 _stringArrayToLowerCase: function(array)
674 return array.map(function(value) {
675 return value.toLowerCase();
680 * @param {!Element} labelNode
683 _createCheckbox: function(labelNode)
685 var checkbox = document.createElementWithClass("input", "checkbox-elem");
686 checkbox.type = "checkbox";
687 labelNode.insertBefore(checkbox, labelNode.firstChild);
691 _categoryCheckboxClicked: function(categoryItem)
693 var checked = categoryItem.checkbox.checked;
694 for (var eventName in categoryItem.children) {
695 var breakpointItem = categoryItem.children[eventName];
696 if (breakpointItem.checkbox.checked === checked)
699 this._setBreakpoint(eventName, categoryItem.targetNames);
701 this._removeBreakpoint(eventName, categoryItem.targetNames);
703 this._saveBreakpoints();
707 * @param {string} eventName
708 * @param {!Array.<string>} targetNames
709 * @param {!Event} event
711 _breakpointCheckboxClicked: function(eventName, targetNames, event)
713 if (event.target.checked)
714 this._setBreakpoint(eventName, targetNames);
716 this._removeBreakpoint(eventName, targetNames);
717 this._saveBreakpoints();
721 * @param {string} eventName
722 * @param {?Array.<string>=} eventTargetNames
723 * @param {!WebInspector.Target=} target
725 _setBreakpoint: function(eventName, eventTargetNames, target)
727 eventTargetNames = eventTargetNames || [WebInspector.EventListenerBreakpointsSidebarPane.eventTargetAny];
728 for (var i = 0; i < eventTargetNames.length; ++i) {
729 var eventTargetName = eventTargetNames[i];
730 var breakpointItem = this._findBreakpointItem(eventName, eventTargetName);
733 breakpointItem.checkbox.checked = true;
734 breakpointItem.parent.dirtyCheckbox = true;
735 this._updateBreakpointOnTarget(eventName, eventTargetName, true, target);
737 this._updateCategoryCheckboxes();
741 * @param {string} eventName
742 * @param {?Array.<string>=} eventTargetNames
743 * @param {!WebInspector.Target=} target
745 _removeBreakpoint: function(eventName, eventTargetNames, target)
747 eventTargetNames = eventTargetNames || [WebInspector.EventListenerBreakpointsSidebarPane.eventTargetAny];
748 for (var i = 0; i < eventTargetNames.length; ++i) {
749 var eventTargetName = eventTargetNames[i];
750 var breakpointItem = this._findBreakpointItem(eventName, eventTargetName);
753 breakpointItem.checkbox.checked = false;
754 breakpointItem.parent.dirtyCheckbox = true;
755 this._updateBreakpointOnTarget(eventName, eventTargetName, false, target);
757 this._updateCategoryCheckboxes();
761 * @param {string} eventName
762 * @param {string} eventTargetName
763 * @param {boolean} enable
764 * @param {!WebInspector.Target=} target
766 _updateBreakpointOnTarget: function(eventName, eventTargetName, enable, target)
768 var targets = target ? [target] : WebInspector.targetManager.targets();
769 for (var i = 0; i < targets.length; ++i) {
770 if (eventName.startsWith(WebInspector.EventListenerBreakpointsSidebarPane.categoryListener)) {
771 var protocolEventName = eventName.substring(WebInspector.EventListenerBreakpointsSidebarPane.categoryListener.length);
773 targets[i].domdebuggerAgent().setEventListenerBreakpoint(protocolEventName, eventTargetName);
775 targets[i].domdebuggerAgent().removeEventListenerBreakpoint(protocolEventName, eventTargetName);
776 } else if (eventName.startsWith(WebInspector.EventListenerBreakpointsSidebarPane.categoryInstrumentation)) {
777 var protocolEventName = eventName.substring(WebInspector.EventListenerBreakpointsSidebarPane.categoryInstrumentation.length);
779 targets[i].domdebuggerAgent().setInstrumentationBreakpoint(protocolEventName);
781 targets[i].domdebuggerAgent().removeInstrumentationBreakpoint(protocolEventName);
786 _updateCategoryCheckboxes: function()
788 for (var i = 0; i < this._categoryItems.length; ++i) {
789 var categoryItem = this._categoryItems[i];
790 if (!categoryItem.dirtyCheckbox)
792 categoryItem.dirtyCheckbox = false;
793 var hasEnabled = false;
794 var hasDisabled = false;
795 for (var eventName in categoryItem.children) {
796 var breakpointItem = categoryItem.children[eventName];
797 if (breakpointItem.checkbox.checked)
802 categoryItem.checkbox.checked = hasEnabled;
803 categoryItem.checkbox.indeterminate = hasEnabled && hasDisabled;
808 * @param {string} eventName
809 * @param {string=} targetName
812 _findBreakpointItem: function(eventName, targetName)
814 targetName = (targetName || WebInspector.EventListenerBreakpointsSidebarPane.eventTargetAny).toLowerCase();
815 for (var i = 0; i < this._categoryItems.length; ++i) {
816 var categoryItem = this._categoryItems[i];
817 if (categoryItem.targetNames.indexOf(targetName) === -1)
819 var breakpointItem = categoryItem.children[eventName];
821 return breakpointItem;
827 * @param {string} eventName
828 * @param {string=} targetName
830 highlightBreakpoint: function(eventName, targetName)
832 var breakpointItem = this._findBreakpointItem(eventName, targetName);
833 if (!breakpointItem || !breakpointItem.checkbox.checked)
834 breakpointItem = this._findBreakpointItem(eventName, WebInspector.EventListenerBreakpointsSidebarPane.eventTargetAny);
838 breakpointItem.parent.element.expand();
839 breakpointItem.element.listItemElement.classList.add("breakpoint-hit");
840 this._highlightedElement = breakpointItem.element.listItemElement;
843 clearBreakpointHighlight: function()
845 if (this._highlightedElement) {
846 this._highlightedElement.classList.remove("breakpoint-hit");
847 delete this._highlightedElement;
851 _saveBreakpoints: function()
853 var breakpoints = [];
854 for (var i = 0; i < this._categoryItems.length; ++i) {
855 var categoryItem = this._categoryItems[i];
856 for (var eventName in categoryItem.children) {
857 var breakpointItem = categoryItem.children[eventName];
858 if (breakpointItem.checkbox.checked)
859 breakpoints.push({ eventName: eventName, targetNames: categoryItem.targetNames });
862 WebInspector.settings.eventListenerBreakpoints.set(breakpoints);
866 * @param {!WebInspector.Target} target
868 _restoreBreakpoints: function(target)
870 var breakpoints = WebInspector.settings.eventListenerBreakpoints.get();
871 for (var i = 0; i < breakpoints.length; ++i) {
872 var breakpoint = breakpoints[i];
873 if (breakpoint && typeof breakpoint.eventName === "string")
874 this._setBreakpoint(breakpoint.eventName, breakpoint.targetNames, target);
878 __proto__: WebInspector.SidebarPane.prototype