1 /* 2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 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. 12 * 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. 24 */ 25 26 /** 27 * @constructor 28 * @param {WebInspector.BreakpointManager} breakpointManager 29 * @extends {WebInspector.SidebarPane} 30 */ 31 WebInspector.JavaScriptBreakpointsSidebarPane = function(breakpointManager, showSourceLineDelegate) 32 { 33 WebInspector.SidebarPane.call(this, WebInspector.UIString("Breakpoints")); 34 this.registerRequiredCSS("breakpointsList.css"); 35 36 this._breakpointManager = breakpointManager; 37 this._showSourceLineDelegate = showSourceLineDelegate; 38 39 this.listElement = document.createElement("ol"); 40 this.listElement.className = "breakpoint-list"; 41 42 this.emptyElement = document.createElement("div"); 43 this.emptyElement.className = "info"; 44 this.emptyElement.textContent = WebInspector.UIString("No Breakpoints"); 45 46 this.bodyElement.appendChild(this.emptyElement); 47 48 this._items = new Map(); 49 50 var breakpointLocations = this._breakpointManager.allBreakpointLocations(); 51 for (var i = 0; i < breakpointLocations.length; ++i) 52 this._addBreakpoint(breakpointLocations[i].breakpoint, breakpointLocations[i].uiLocation); 53 54 this._breakpointManager.addEventListener(WebInspector.BreakpointManager.Events.BreakpointAdded, this._breakpointAdded, this); 55 this._breakpointManager.addEventListener(WebInspector.BreakpointManager.Events.BreakpointRemoved, this._breakpointRemoved, this); 56 57 this.emptyElement.addEventListener("contextmenu", this._emptyElementContextMenu.bind(this), true); 58 } 59 60 WebInspector.JavaScriptBreakpointsSidebarPane.prototype = { 61 _emptyElementContextMenu: function(event) 62 { 63 var contextMenu = new WebInspector.ContextMenu(event); 64 var breakpointActive = WebInspector.debuggerModel.breakpointsActive(); 65 var breakpointActiveTitle = breakpointActive ? 66 WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Deactivate breakpoints" : "Deactivate Breakpoints") : 67 WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Activate breakpoints" : "Activate Breakpoints"); 68 contextMenu.appendItem(breakpointActiveTitle, WebInspector.debuggerModel.setBreakpointsActive.bind(WebInspector.debuggerModel, !breakpointActive)); 69 contextMenu.show(); 70 }, 71 72 /** 73 * @param {WebInspector.Event} event 74 */ 75 _breakpointAdded: function(event) 76 { 77 this._breakpointRemoved(event); 78 79 var breakpoint = /** @type {WebInspector.BreakpointManager.Breakpoint} */ (event.data.breakpoint); 80 var uiLocation = /** @type {WebInspector.UILocation} */ (event.data.uiLocation); 81 this._addBreakpoint(breakpoint, uiLocation); 82 }, 83 84 /** 85 * @param {WebInspector.BreakpointManager.Breakpoint} breakpoint 86 * @param {WebInspector.UILocation} uiLocation 87 */ 88 _addBreakpoint: function(breakpoint, uiLocation) 89 { 90 var element = document.createElement("li"); 91 element.addStyleClass("cursor-pointer"); 92 element.addEventListener("contextmenu", this._breakpointContextMenu.bind(this, breakpoint), true); 93 element.addEventListener("click", this._breakpointClicked.bind(this, uiLocation), false); 94 95 var checkbox = document.createElement("input"); 96 checkbox.className = "checkbox-elem"; 97 checkbox.type = "checkbox"; 98 checkbox.checked = breakpoint.enabled(); 99 checkbox.addEventListener("click", this._breakpointCheckboxClicked.bind(this, breakpoint), false); 100 element.appendChild(checkbox); 101 102 var labelElement = document.createTextNode(uiLocation.linkText()); 103 element.appendChild(labelElement); 104 105 var snippetElement = document.createElement("div"); 106 snippetElement.className = "source-text monospace"; 107 element.appendChild(snippetElement); 108 109 /** 110 * @param {?string} content 111 * @param {boolean} contentEncoded 112 * @param {string} mimeType 113 */ 114 function didRequestContent(content, contentEncoded, mimeType) 115 { 116 var lineEndings = content.lineEndings(); 117 if (uiLocation.lineNumber < lineEndings.length) 118 snippetElement.textContent = content.substring(lineEndings[uiLocation.lineNumber - 1], lineEndings[uiLocation.lineNumber]); 119 } 120 uiLocation.uiSourceCode.requestContent(didRequestContent.bind(this)); 121 122 element._data = uiLocation; 123 var currentElement = this.listElement.firstChild; 124 while (currentElement) { 125 if (currentElement._data && this._compareBreakpoints(currentElement._data, element._data) > 0) 126 break; 127 currentElement = currentElement.nextSibling; 128 } 129 this._addListElement(element, currentElement); 130 131 var breakpointItem = {}; 132 breakpointItem.element = element; 133 breakpointItem.checkbox = checkbox; 134 this._items.put(breakpoint, breakpointItem); 135 136 this.expand(); 137 }, 138 139 /** 140 * @param {WebInspector.Event} event 141 */ 142 _breakpointRemoved: function(event) 143 { 144 var breakpoint = /** @type {WebInspector.BreakpointManager.Breakpoint} */ (event.data.breakpoint); 145 var uiLocation = /** @type {WebInspector.UILocation} */ (event.data.uiLocation); 146 var breakpointItem = this._items.get(breakpoint); 147 if (!breakpointItem) 148 return; 149 this._items.remove(breakpoint); 150 this._removeListElement(breakpointItem.element); 151 }, 152 153 /** 154 * @param {WebInspector.BreakpointManager.Breakpoint} breakpoint 155 */ 156 highlightBreakpoint: function(breakpoint) 157 { 158 var breakpointItem = this._items.get(breakpoint); 159 if (!breakpointItem) 160 return; 161 breakpointItem.element.addStyleClass("breakpoint-hit"); 162 this._highlightedBreakpointItem = breakpointItem; 163 }, 164 165 clearBreakpointHighlight: function() 166 { 167 if (this._highlightedBreakpointItem) { 168 this._highlightedBreakpointItem.element.removeStyleClass("breakpoint-hit"); 169 delete this._highlightedBreakpointItem; 170 } 171 }, 172 173 _breakpointClicked: function(uiLocation, event) 174 { 175 this._showSourceLineDelegate(uiLocation.uiSourceCode, uiLocation.lineNumber); 176 }, 177 178 /** 179 * @param {WebInspector.BreakpointManager.Breakpoint} breakpoint 180 */ 181 _breakpointCheckboxClicked: function(breakpoint, event) 182 { 183 // Breakpoint element has it's own click handler. 184 event.consume(); 185 breakpoint.setEnabled(event.target.checked); 186 }, 187 188 /** 189 * @param {WebInspector.BreakpointManager.Breakpoint} breakpoint 190 */ 191 _breakpointContextMenu: function(breakpoint, event) 192 { 193 var breakpoints = this._items.values(); 194 var contextMenu = new WebInspector.ContextMenu(event); 195 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Remove breakpoint" : "Remove Breakpoint"), breakpoint.remove.bind(breakpoint)); 196 if (breakpoints.length > 1) { 197 var removeAllTitle = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Remove all breakpoints" : "Remove All Breakpoints"); 198 contextMenu.appendItem(removeAllTitle, this._breakpointManager.removeAllBreakpoints.bind(this._breakpointManager)); 199 } 200 201 contextMenu.appendSeparator(); 202 var breakpointActive = WebInspector.debuggerModel.breakpointsActive(); 203 var breakpointActiveTitle = breakpointActive ? 204 WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Deactivate breakpoints" : "Deactivate Breakpoints") : 205 WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Activate breakpoints" : "Activate Breakpoints"); 206 contextMenu.appendItem(breakpointActiveTitle, WebInspector.debuggerModel.setBreakpointsActive.bind(WebInspector.debuggerModel, !breakpointActive)); 207 208 function enabledBreakpointCount(breakpoints) 209 { 210 var count = 0; 211 for (var i = 0; i < breakpoints.length; ++i) { 212 if (breakpoints[i].checkbox.checked) 213 count++; 214 } 215 return count; 216 } 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"); 221 222 contextMenu.appendSeparator(); 223 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)); 226 } 227 228 contextMenu.show(); 229 }, 230 231 _addListElement: function(element, beforeElement) 232 { 233 if (beforeElement) 234 this.listElement.insertBefore(element, beforeElement); 235 else { 236 if (!this.listElement.firstChild) { 237 this.bodyElement.removeChild(this.emptyElement); 238 this.bodyElement.appendChild(this.listElement); 239 } 240 this.listElement.appendChild(element); 241 } 242 }, 243 244 _removeListElement: function(element) 245 { 246 this.listElement.removeChild(element); 247 if (!this.listElement.firstChild) { 248 this.bodyElement.removeChild(this.listElement); 249 this.bodyElement.appendChild(this.emptyElement); 250 } 251 }, 252 253 _compare: function(x, y) 254 { 255 if (x !== y) 256 return x < y ? -1 : 1; 257 return 0; 258 }, 259 260 _compareBreakpoints: function(b1, b2) 261 { 262 return this._compare(b1.uiSourceCode.originURL(), b2.uiSourceCode.originURL()) || this._compare(b1.lineNumber, b2.lineNumber); 263 }, 264 265 reset: function() 266 { 267 this.listElement.removeChildren(); 268 if (this.listElement.parentElement) { 269 this.bodyElement.removeChild(this.listElement); 270 this.bodyElement.appendChild(this.emptyElement); 271 } 272 this._items.clear(); 273 }, 274 275 __proto__: WebInspector.SidebarPane.prototype 276 } 277 278 /** 279 * @constructor 280 * @extends {WebInspector.NativeBreakpointsSidebarPane} 281 */ 282 WebInspector.XHRBreakpointsSidebarPane = function() 283 { 284 WebInspector.NativeBreakpointsSidebarPane.call(this, WebInspector.UIString("XHR Breakpoints")); 285 286 this._breakpointElements = {}; 287 288 var addButton = document.createElement("button"); 289 addButton.className = "pane-title-button add"; 290 addButton.addEventListener("click", this._addButtonClicked.bind(this), false); 291 addButton.title = WebInspector.UIString("Add XHR breakpoint"); 292 this.titleElement.appendChild(addButton); 293 294 this.emptyElement.addEventListener("contextmenu", this._emptyElementContextMenu.bind(this), true); 295 296 this._restoreBreakpoints(); 297 } 298 299 WebInspector.XHRBreakpointsSidebarPane.prototype = { 300 _emptyElementContextMenu: function(event) 301 { 302 var contextMenu = new WebInspector.ContextMenu(event); 303 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Add breakpoint" : "Add Breakpoint"), this._addButtonClicked.bind(this)); 304 contextMenu.show(); 305 }, 306 307 _addButtonClicked: function(event) 308 { 309 if (event) 310 event.consume(); 311 312 this.expand(); 313 314 var inputElementContainer = document.createElement("p"); 315 inputElementContainer.className = "breakpoint-condition"; 316 var inputElement = document.createElement("span"); 317 inputElementContainer.textContent = WebInspector.UIString("Break when URL contains:"); 318 inputElement.className = "editing"; 319 inputElement.id = "breakpoint-condition-input"; 320 inputElementContainer.appendChild(inputElement); 321 this._addListElement(inputElementContainer, this.listElement.firstChild); 322 323 function finishEditing(accept, e, text) 324 { 325 this._removeListElement(inputElementContainer); 326 if (accept) { 327 this._setBreakpoint(text, true); 328 this._saveBreakpoints(); 329 } 330 } 331 332 var config = new WebInspector.EditingConfig(finishEditing.bind(this, true), finishEditing.bind(this, false)); 333 WebInspector.startEditing(inputElement, config); 334 }, 335 336 _setBreakpoint: function(url, enabled) 337 { 338 if (url in this._breakpointElements) 339 return; 340 341 var element = document.createElement("li"); 342 element._url = url; 343 element.addEventListener("contextmenu", this._contextMenu.bind(this, url), true); 344 345 var checkboxElement = document.createElement("input"); 346 checkboxElement.className = "checkbox-elem"; 347 checkboxElement.type = "checkbox"; 348 checkboxElement.checked = enabled; 349 checkboxElement.addEventListener("click", this._checkboxClicked.bind(this, url), false); 350 element._checkboxElement = checkboxElement; 351 element.appendChild(checkboxElement); 352 353 var labelElement = document.createElement("span"); 354 if (!url) 355 labelElement.textContent = WebInspector.UIString("Any XHR"); 356 else 357 labelElement.textContent = WebInspector.UIString("URL contains \"%s\"", url); 358 labelElement.addStyleClass("cursor-auto"); 359 labelElement.addEventListener("dblclick", this._labelClicked.bind(this, url), false); 360 element.appendChild(labelElement); 361 362 var currentElement = this.listElement.firstChild; 363 while (currentElement) { 364 if (currentElement._url && currentElement._url < element._url) 365 break; 366 currentElement = currentElement.nextSibling; 367 } 368 this._addListElement(element, currentElement); 369 this._breakpointElements[url] = element; 370 if (enabled) 371 DOMDebuggerAgent.setXHRBreakpoint(url); 372 }, 373 374 _removeBreakpoint: function(url) 375 { 376 var element = this._breakpointElements[url]; 377 if (!element) 378 return; 379 380 this._removeListElement(element); 381 delete this._breakpointElements[url]; 382 if (element._checkboxElement.checked) 383 DOMDebuggerAgent.removeXHRBreakpoint(url); 384 }, 385 386 _contextMenu: function(url, event) 387 { 388 var contextMenu = new WebInspector.ContextMenu(event); 389 function removeBreakpoint() 390 { 391 this._removeBreakpoint(url); 392 this._saveBreakpoints(); 393 } 394 function removeAllBreakpoints() 395 { 396 for (var url in this._breakpointElements) 397 this._removeBreakpoint(url); 398 this._saveBreakpoints(); 399 } 400 var removeAllTitle = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Remove all breakpoints" : "Remove All Breakpoints"); 401 402 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Add breakpoint" : "Add Breakpoint"), this._addButtonClicked.bind(this)); 403 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Remove breakpoint" : "Remove Breakpoint"), removeBreakpoint.bind(this)); 404 contextMenu.appendItem(removeAllTitle, removeAllBreakpoints.bind(this)); 405 contextMenu.show(); 406 }, 407 408 _checkboxClicked: function(url, event) 409 { 410 if (event.target.checked) 411 DOMDebuggerAgent.setXHRBreakpoint(url); 412 else 413 DOMDebuggerAgent.removeXHRBreakpoint(url); 414 this._saveBreakpoints(); 415 }, 416 417 _labelClicked: function(url) 418 { 419 var element = this._breakpointElements[url]; 420 var inputElement = document.createElement("span"); 421 inputElement.className = "breakpoint-condition editing"; 422 inputElement.textContent = url; 423 this.listElement.insertBefore(inputElement, element); 424 element.addStyleClass("hidden"); 425 426 function finishEditing(accept, e, text) 427 { 428 this._removeListElement(inputElement); 429 if (accept) { 430 this._removeBreakpoint(url); 431 this._setBreakpoint(text, element._checkboxElement.checked); 432 this._saveBreakpoints(); 433 } else 434 element.removeStyleClass("hidden"); 435 } 436 437 WebInspector.startEditing(inputElement, new WebInspector.EditingConfig(finishEditing.bind(this, true), finishEditing.bind(this, false))); 438 }, 439 440 highlightBreakpoint: function(url) 441 { 442 var element = this._breakpointElements[url]; 443 if (!element) 444 return; 445 this.expand(); 446 element.addStyleClass("breakpoint-hit"); 447 this._highlightedElement = element; 448 }, 449 450 clearBreakpointHighlight: function() 451 { 452 if (this._highlightedElement) { 453 this._highlightedElement.removeStyleClass("breakpoint-hit"); 454 delete this._highlightedElement; 455 } 456 }, 457 458 _saveBreakpoints: function() 459 { 460 var breakpoints = []; 461 for (var url in this._breakpointElements) 462 breakpoints.push({ url: url, enabled: this._breakpointElements[url]._checkboxElement.checked }); 463 WebInspector.settings.xhrBreakpoints.set(breakpoints); 464 }, 465 466 _restoreBreakpoints: function() 467 { 468 var breakpoints = WebInspector.settings.xhrBreakpoints.get(); 469 for (var i = 0; i < breakpoints.length; ++i) { 470 var breakpoint = breakpoints[i]; 471 if (breakpoint && typeof breakpoint.url === "string") 472 this._setBreakpoint(breakpoint.url, breakpoint.enabled); 473 } 474 }, 475 476 __proto__: WebInspector.NativeBreakpointsSidebarPane.prototype 477 } 478 479 /** 480 * @constructor 481 * @extends {WebInspector.SidebarPane} 482 */ 483 WebInspector.EventListenerBreakpointsSidebarPane = function() 484 { 485 WebInspector.SidebarPane.call(this, WebInspector.UIString("Event Listener Breakpoints")); 486 this.registerRequiredCSS("breakpointsList.css"); 487 488 this.categoriesElement = document.createElement("ol"); 489 this.categoriesElement.tabIndex = 0; 490 this.categoriesElement.addStyleClass("properties-tree"); 491 this.categoriesElement.addStyleClass("event-listener-breakpoints"); 492 this.categoriesTreeOutline = new TreeOutline(this.categoriesElement); 493 this.bodyElement.appendChild(this.categoriesElement); 494 495 this._breakpointItems = {}; 496 // FIXME: uncomment following once inspector stops being drop targer in major ports. 497 // Otherwise, inspector page reacts on drop event and tries to load the event data. 498 // this._createCategory(WebInspector.UIString("Drag"), true, ["drag", "drop", "dragstart", "dragend", "dragenter", "dragleave", "dragover"]); 499 this._createCategory(WebInspector.UIString("Animation"), false, ["requestAnimationFrame", "cancelAnimationFrame", "animationFrameFired"]); 500 this._createCategory(WebInspector.UIString("Control"), true, ["resize", "scroll", "zoom", "focus", "blur", "select", "change", "submit", "reset"]); 501 this._createCategory(WebInspector.UIString("Clipboard"), true, ["copy", "cut", "paste", "beforecopy", "beforecut", "beforepaste"]); 502 this._createCategory(WebInspector.UIString("DOM Mutation"), true, ["DOMActivate", "DOMFocusIn", "DOMFocusOut", "DOMAttrModified", "DOMCharacterDataModified", "DOMNodeInserted", "DOMNodeInsertedIntoDocument", "DOMNodeRemoved", "DOMNodeRemovedFromDocument", "DOMSubtreeModified", "DOMContentLoaded"]); 503 this._createCategory(WebInspector.UIString("Device"), true, ["deviceorientation", "devicemotion"]); 504 this._createCategory(WebInspector.UIString("Keyboard"), true, ["keydown", "keyup", "keypress", "input"]); 505 this._createCategory(WebInspector.UIString("Load"), true, ["load", "unload", "abort", "error"]); 506 this._createCategory(WebInspector.UIString("Mouse"), true, ["click", "dblclick", "mousedown", "mouseup", "mouseover", "mousemove", "mouseout", "mousewheel"]); 507 this._createCategory(WebInspector.UIString("Timer"), false, ["setTimer", "clearTimer", "timerFired"]); 508 this._createCategory(WebInspector.UIString("Touch"), true, ["touchstart", "touchmove", "touchend", "touchcancel"]); 509 this._createCategory(WebInspector.UIString("WebGL"), false, ["webglErrorFired", "webglWarningFired"]); 510 511 this._restoreBreakpoints(); 512 } 513 514 WebInspector.EventListenerBreakpointsSidebarPane.categotyListener = "listener:"; 515 WebInspector.EventListenerBreakpointsSidebarPane.categotyInstrumentation = "instrumentation:"; 516 517 /** 518 * @param {string} eventName 519 * @param {Object=} auxData 520 * @return {string} 521 */ 522 WebInspector.EventListenerBreakpointsSidebarPane.eventNameForUI = function(eventName, auxData) 523 { 524 if (!WebInspector.EventListenerBreakpointsSidebarPane._eventNamesForUI) { 525 WebInspector.EventListenerBreakpointsSidebarPane._eventNamesForUI = { 526 "instrumentation:setTimer": WebInspector.UIString("Set Timer"), 527 "instrumentation:clearTimer": WebInspector.UIString("Clear Timer"), 528 "instrumentation:timerFired": WebInspector.UIString("Timer Fired"), 529 "instrumentation:requestAnimationFrame": WebInspector.UIString("Request Animation Frame"), 530 "instrumentation:cancelAnimationFrame": WebInspector.UIString("Cancel Animation Frame"), 531 "instrumentation:animationFrameFired": WebInspector.UIString("Animation Frame Fired"), 532 "instrumentation:webglErrorFired": WebInspector.UIString("WebGL Error Fired"), 533 "instrumentation:webglWarningFired": WebInspector.UIString("WebGL Warning Fired") 534 }; 535 } 536 if (auxData) { 537 if (eventName === "instrumentation:webglErrorFired" && auxData["webglErrorName"]) { 538 var errorName = auxData["webglErrorName"]; 539 // If there is a hex code of the error, display only this. 540 errorName = errorName.replace(/^.*(0x[0-9a-f]+).*$/i, "$1"); 541 return WebInspector.UIString("WebGL Error Fired (%s)", errorName); 542 } 543 } 544 return WebInspector.EventListenerBreakpointsSidebarPane._eventNamesForUI[eventName] || eventName.substring(eventName.indexOf(":") + 1); 545 } 546 547 WebInspector.EventListenerBreakpointsSidebarPane.prototype = { 548 _createCategory: function(name, isDOMEvent, eventNames) 549 { 550 var categoryItem = {}; 551 categoryItem.element = new TreeElement(name); 552 this.categoriesTreeOutline.appendChild(categoryItem.element); 553 categoryItem.element.listItemElement.addStyleClass("event-category"); 554 categoryItem.element.selectable = true; 555 556 categoryItem.checkbox = this._createCheckbox(categoryItem.element); 557 categoryItem.checkbox.addEventListener("click", this._categoryCheckboxClicked.bind(this, categoryItem), true); 558 559 categoryItem.children = {}; 560 for (var i = 0; i < eventNames.length; ++i) { 561 var eventName = (isDOMEvent ? WebInspector.EventListenerBreakpointsSidebarPane.categotyListener : WebInspector.EventListenerBreakpointsSidebarPane.categotyInstrumentation) + eventNames[i]; 562 563 var breakpointItem = {}; 564 var title = WebInspector.EventListenerBreakpointsSidebarPane.eventNameForUI(eventName); 565 breakpointItem.element = new TreeElement(title); 566 categoryItem.element.appendChild(breakpointItem.element); 567 var hitMarker = document.createElement("div"); 568 hitMarker.className = "breakpoint-hit-marker"; 569 breakpointItem.element.listItemElement.appendChild(hitMarker); 570 breakpointItem.element.listItemElement.addStyleClass("source-code"); 571 breakpointItem.element.selectable = false; 572 573 breakpointItem.checkbox = this._createCheckbox(breakpointItem.element); 574 breakpointItem.checkbox.addEventListener("click", this._breakpointCheckboxClicked.bind(this, eventName), true); 575 breakpointItem.parent = categoryItem; 576 577 this._breakpointItems[eventName] = breakpointItem; 578 categoryItem.children[eventName] = breakpointItem; 579 } 580 }, 581 582 _createCheckbox: function(treeElement) 583 { 584 var checkbox = document.createElement("input"); 585 checkbox.className = "checkbox-elem"; 586 checkbox.type = "checkbox"; 587 treeElement.listItemElement.insertBefore(checkbox, treeElement.listItemElement.firstChild); 588 return checkbox; 589 }, 590 591 _categoryCheckboxClicked: function(categoryItem) 592 { 593 var checked = categoryItem.checkbox.checked; 594 for (var eventName in categoryItem.children) { 595 var breakpointItem = categoryItem.children[eventName]; 596 if (breakpointItem.checkbox.checked === checked) 597 continue; 598 if (checked) 599 this._setBreakpoint(eventName); 600 else 601 this._removeBreakpoint(eventName); 602 } 603 this._saveBreakpoints(); 604 }, 605 606 _breakpointCheckboxClicked: function(eventName, event) 607 { 608 if (event.target.checked) 609 this._setBreakpoint(eventName); 610 else 611 this._removeBreakpoint(eventName); 612 this._saveBreakpoints(); 613 }, 614 615 _setBreakpoint: function(eventName) 616 { 617 var breakpointItem = this._breakpointItems[eventName]; 618 if (!breakpointItem) 619 return; 620 breakpointItem.checkbox.checked = true; 621 if (eventName.startsWith(WebInspector.EventListenerBreakpointsSidebarPane.categotyListener)) 622 DOMDebuggerAgent.setEventListenerBreakpoint(eventName.substring(WebInspector.EventListenerBreakpointsSidebarPane.categotyListener.length)); 623 else if (eventName.startsWith(WebInspector.EventListenerBreakpointsSidebarPane.categotyInstrumentation)) 624 DOMDebuggerAgent.setInstrumentationBreakpoint(eventName.substring(WebInspector.EventListenerBreakpointsSidebarPane.categotyInstrumentation.length)); 625 this._updateCategoryCheckbox(breakpointItem.parent); 626 }, 627 628 _removeBreakpoint: function(eventName) 629 { 630 var breakpointItem = this._breakpointItems[eventName]; 631 if (!breakpointItem) 632 return; 633 breakpointItem.checkbox.checked = false; 634 if (eventName.startsWith(WebInspector.EventListenerBreakpointsSidebarPane.categotyListener)) 635 DOMDebuggerAgent.removeEventListenerBreakpoint(eventName.substring(WebInspector.EventListenerBreakpointsSidebarPane.categotyListener.length)); 636 else if (eventName.startsWith(WebInspector.EventListenerBreakpointsSidebarPane.categotyInstrumentation)) 637 DOMDebuggerAgent.removeInstrumentationBreakpoint(eventName.substring(WebInspector.EventListenerBreakpointsSidebarPane.categotyInstrumentation.length)); 638 this._updateCategoryCheckbox(breakpointItem.parent); 639 }, 640 641 _updateCategoryCheckbox: function(categoryItem) 642 { 643 var hasEnabled = false, hasDisabled = false; 644 for (var eventName in categoryItem.children) { 645 var breakpointItem = categoryItem.children[eventName]; 646 if (breakpointItem.checkbox.checked) 647 hasEnabled = true; 648 else 649 hasDisabled = true; 650 } 651 categoryItem.checkbox.checked = hasEnabled; 652 categoryItem.checkbox.indeterminate = hasEnabled && hasDisabled; 653 }, 654 655 highlightBreakpoint: function(eventName) 656 { 657 var breakpointItem = this._breakpointItems[eventName]; 658 if (!breakpointItem) 659 return; 660 this.expand(); 661 breakpointItem.parent.element.expand(); 662 breakpointItem.element.listItemElement.addStyleClass("breakpoint-hit"); 663 this._highlightedElement = breakpointItem.element.listItemElement; 664 }, 665 666 clearBreakpointHighlight: function() 667 { 668 if (this._highlightedElement) { 669 this._highlightedElement.removeStyleClass("breakpoint-hit"); 670 delete this._highlightedElement; 671 } 672 }, 673 674 _saveBreakpoints: function() 675 { 676 var breakpoints = []; 677 for (var eventName in this._breakpointItems) { 678 if (this._breakpointItems[eventName].checkbox.checked) 679 breakpoints.push({ eventName: eventName }); 680 } 681 WebInspector.settings.eventListenerBreakpoints.set(breakpoints); 682 }, 683 684 _restoreBreakpoints: function() 685 { 686 var breakpoints = WebInspector.settings.eventListenerBreakpoints.get(); 687 for (var i = 0; i < breakpoints.length; ++i) { 688 var breakpoint = breakpoints[i]; 689 if (breakpoint && typeof breakpoint.eventName === "string") 690 this._setBreakpoint(breakpoint.eventName); 691 } 692 }, 693 694 __proto__: WebInspector.SidebarPane.prototype 695 } 696