| OLD | NEW | 
|---|
|  | (Empty) | 
| 1 /* |  | 
| 2  * Copyright (C) 2007, 2008 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 const ExpressionStopCharacters = " =:[({;,!+-*/&|^<>"; |  | 
| 31 |  | 
| 32 WebInspector.ConsoleView = function(drawer) |  | 
| 33 { |  | 
| 34     WebInspector.View.call(this, document.getElementById("console-view")); |  | 
| 35 |  | 
| 36     this.messages = []; |  | 
| 37     this.drawer = drawer; |  | 
| 38 |  | 
| 39     this.clearButton = document.getElementById("clear-console-status-bar-item"); |  | 
| 40     this.clearButton.title = WebInspector.UIString("Clear console log."); |  | 
| 41     this.clearButton.addEventListener("click", this._clearButtonClicked.bind(thi
     s), false); |  | 
| 42 |  | 
| 43     this.messagesElement = document.getElementById("console-messages"); |  | 
| 44     this.messagesElement.addEventListener("selectstart", this._messagesSelectSta
     rt.bind(this), false); |  | 
| 45     this.messagesElement.addEventListener("click", this._messagesClicked.bind(th
     is), true); |  | 
| 46 |  | 
| 47     this.promptElement = document.getElementById("console-prompt"); |  | 
| 48     this.promptElement.handleKeyEvent = this._promptKeyDown.bind(this); |  | 
| 49     this.prompt = new WebInspector.TextPrompt(this.promptElement, this.completio
     ns.bind(this), ExpressionStopCharacters + "."); |  | 
| 50 |  | 
| 51     this.topGroup = new WebInspector.ConsoleGroup(null, 0); |  | 
| 52     this.messagesElement.insertBefore(this.topGroup.element, this.promptElement)
     ; |  | 
| 53     this.groupLevel = 0; |  | 
| 54     this.currentGroup = this.topGroup; |  | 
| 55 |  | 
| 56     this.toggleConsoleButton = document.getElementById("console-status-bar-item"
     ); |  | 
| 57     this.toggleConsoleButton.title = WebInspector.UIString("Show console."); |  | 
| 58     this.toggleConsoleButton.addEventListener("click", this._toggleConsoleButton
     Clicked.bind(this), false); |  | 
| 59 |  | 
| 60     var anchoredStatusBar = document.getElementById("anchored-status-bar-items")
     ; |  | 
| 61     anchoredStatusBar.appendChild(this.toggleConsoleButton); |  | 
| 62 |  | 
| 63     // Will hold the list of filter elements |  | 
| 64     this.filterBarElement = document.getElementById("console-filter"); |  | 
| 65 |  | 
| 66     function createDividerElement() { |  | 
| 67         var dividerElement = document.createElement("div"); |  | 
| 68 |  | 
| 69         dividerElement.addStyleClass("divider"); |  | 
| 70 |  | 
| 71         this.filterBarElement.appendChild(dividerElement); |  | 
| 72     } |  | 
| 73 |  | 
| 74     function createFilterElement(category) { |  | 
| 75         var categoryElement = document.createElement("li"); |  | 
| 76         categoryElement.category = category; |  | 
| 77 |  | 
| 78         categoryElement.addStyleClass(categoryElement.category); |  | 
| 79 |  | 
| 80         var label = category.toString(); |  | 
| 81         categoryElement.appendChild(document.createTextNode(label)); |  | 
| 82 |  | 
| 83         categoryElement.addEventListener("click", this._updateFilter.bind(this),
      false); |  | 
| 84 |  | 
| 85         this.filterBarElement.appendChild(categoryElement); |  | 
| 86         return categoryElement; |  | 
| 87     } |  | 
| 88 |  | 
| 89     this.allElement = createFilterElement.call(this, "All"); |  | 
| 90 |  | 
| 91     createDividerElement.call(this); |  | 
| 92 |  | 
| 93     this.errorElement = createFilterElement.call(this, "Errors"); |  | 
| 94     this.warningElement = createFilterElement.call(this, "Warnings"); |  | 
| 95     this.logElement = createFilterElement.call(this, "Logs"); |  | 
| 96 |  | 
| 97     this.filter(this.allElement); |  | 
| 98 } |  | 
| 99 |  | 
| 100 WebInspector.ConsoleView.prototype = { |  | 
| 101 |  | 
| 102     _updateFilter: function(e) |  | 
| 103     { |  | 
| 104         this.filter(e.target); |  | 
| 105     }, |  | 
| 106 |  | 
| 107     filter: function(target) |  | 
| 108     { |  | 
| 109         if (target.category == "All") { |  | 
| 110             if (target.hasStyleClass("selected")) { |  | 
| 111                 // We can't unselect all, so we break early here |  | 
| 112                 return; |  | 
| 113             } |  | 
| 114 |  | 
| 115             this.errorElement.removeStyleClass("selected"); |  | 
| 116             this.warningElement.removeStyleClass("selected"); |  | 
| 117             this.logElement.removeStyleClass("selected"); |  | 
| 118 |  | 
| 119             document.getElementById("console-messages").removeStyleClass("filter
     -errors"); |  | 
| 120             document.getElementById("console-messages").removeStyleClass("filter
     -warnings"); |  | 
| 121             document.getElementById("console-messages").removeStyleClass("filter
     -logs"); |  | 
| 122         } else { |  | 
| 123             // Something other than all is being selected, so we want to unselec
     t all |  | 
| 124             if (this.allElement.hasStyleClass("selected")) { |  | 
| 125                 this.allElement.removeStyleClass("selected"); |  | 
| 126                 document.getElementById("console-messages").removeStyleClass("fi
     lter-all"); |  | 
| 127             } |  | 
| 128         } |  | 
| 129 |  | 
| 130         if (target.hasStyleClass("selected")) { |  | 
| 131             target.removeStyleClass("selected"); |  | 
| 132             var newClass = "filter-" + target.category.toLowerCase(); |  | 
| 133             var filterElement = document.getElementById("console-messages"); |  | 
| 134             filterElement.removeStyleClass(newClass); |  | 
| 135         } else { |  | 
| 136             target.addStyleClass("selected"); |  | 
| 137             var newClass = "filter-" + target.category.toLowerCase(); |  | 
| 138             var filterElement = document.getElementById("console-messages"); |  | 
| 139             filterElement.addStyleClass(newClass); |  | 
| 140         } |  | 
| 141     }, |  | 
| 142 |  | 
| 143     _toggleConsoleButtonClicked: function() |  | 
| 144     { |  | 
| 145         this.drawer.visibleView = this; |  | 
| 146     }, |  | 
| 147 |  | 
| 148     attach: function(mainElement, statusBarElement) |  | 
| 149     { |  | 
| 150         mainElement.appendChild(this.element); |  | 
| 151         statusBarElement.appendChild(this.clearButton); |  | 
| 152         statusBarElement.appendChild(this.filterBarElement); |  | 
| 153     }, |  | 
| 154 |  | 
| 155     show: function() |  | 
| 156     { |  | 
| 157         this.toggleConsoleButton.addStyleClass("toggled-on"); |  | 
| 158         this.toggleConsoleButton.title = WebInspector.UIString("Hide console."); |  | 
| 159         if (!this.prompt.isCaretInsidePrompt()) |  | 
| 160             this.prompt.moveCaretToEndOfPrompt(); |  | 
| 161     }, |  | 
| 162 |  | 
| 163     afterShow: function() |  | 
| 164     { |  | 
| 165         WebInspector.currentFocusElement = this.promptElement; |  | 
| 166     }, |  | 
| 167 |  | 
| 168     hide: function() |  | 
| 169     { |  | 
| 170         this.toggleConsoleButton.removeStyleClass("toggled-on"); |  | 
| 171         this.toggleConsoleButton.title = WebInspector.UIString("Show console."); |  | 
| 172     }, |  | 
| 173 |  | 
| 174     addMessage: function(msg) |  | 
| 175     { |  | 
| 176         if (msg instanceof WebInspector.ConsoleMessage && !(msg instanceof WebIn
     spector.ConsoleCommandResult)) { |  | 
| 177             msg.totalRepeatCount = msg.repeatCount; |  | 
| 178             msg.repeatDelta = msg.repeatCount; |  | 
| 179 |  | 
| 180             var messageRepeated = false; |  | 
| 181 |  | 
| 182             if (msg.isEqual && msg.isEqual(this.previousMessage)) { |  | 
| 183                 // Because sometimes we get a large number of repeated messages 
     and sometimes |  | 
| 184                 // we get them one at a time, we need to know the difference bet
     ween how many |  | 
| 185                 // repeats we used to have and how many we have now. |  | 
| 186                 msg.repeatDelta -= this.previousMessage.totalRepeatCount; |  | 
| 187 |  | 
| 188                 if (!isNaN(this.repeatCountBeforeCommand)) |  | 
| 189                     msg.repeatCount -= this.repeatCountBeforeCommand; |  | 
| 190 |  | 
| 191                 if (!this.commandSincePreviousMessage) { |  | 
| 192                     // Recreate the previous message element to reset the repeat
      count. |  | 
| 193                     var messagesElement = this.currentGroup.messagesElement; |  | 
| 194                     messagesElement.removeChild(messagesElement.lastChild); |  | 
| 195                     messagesElement.appendChild(msg.toMessageElement()); |  | 
| 196 |  | 
| 197                     messageRepeated = true; |  | 
| 198                 } |  | 
| 199             } else |  | 
| 200                 delete this.repeatCountBeforeCommand; |  | 
| 201 |  | 
| 202             // Increment the error or warning count |  | 
| 203             switch (msg.level) { |  | 
| 204             case WebInspector.ConsoleMessage.MessageLevel.Warning: |  | 
| 205                 WebInspector.warnings += msg.repeatDelta; |  | 
| 206                 break; |  | 
| 207             case WebInspector.ConsoleMessage.MessageLevel.Error: |  | 
| 208                 WebInspector.errors += msg.repeatDelta; |  | 
| 209                 break; |  | 
| 210             } |  | 
| 211 |  | 
| 212             // Add message to the resource panel |  | 
| 213             if (msg.url in WebInspector.resourceURLMap) { |  | 
| 214                 msg.resource = WebInspector.resourceURLMap[msg.url]; |  | 
| 215                 if (WebInspector.panels.resources) |  | 
| 216                     WebInspector.panels.resources.addMessageToResource(msg.resou
     rce, msg); |  | 
| 217             } |  | 
| 218 |  | 
| 219             this.commandSincePreviousMessage = false; |  | 
| 220             this.previousMessage = msg; |  | 
| 221 |  | 
| 222             if (messageRepeated) |  | 
| 223                 return; |  | 
| 224         } else if (msg instanceof WebInspector.ConsoleCommand) { |  | 
| 225             if (this.previousMessage) { |  | 
| 226                 this.commandSincePreviousMessage = true; |  | 
| 227                 this.repeatCountBeforeCommand = this.previousMessage.totalRepeat
     Count; |  | 
| 228             } |  | 
| 229         } |  | 
| 230 |  | 
| 231         this.messages.push(msg); |  | 
| 232 |  | 
| 233         if (msg.type === WebInspector.ConsoleMessage.MessageType.EndGroup) { |  | 
| 234             if (this.groupLevel < 1) |  | 
| 235                 return; |  | 
| 236 |  | 
| 237             this.groupLevel--; |  | 
| 238 |  | 
| 239             this.currentGroup = this.currentGroup.parentGroup; |  | 
| 240         } else { |  | 
| 241             if (msg.type === WebInspector.ConsoleMessage.MessageType.StartGroup)
      { |  | 
| 242                 this.groupLevel++; |  | 
| 243 |  | 
| 244                 var group = new WebInspector.ConsoleGroup(this.currentGroup, thi
     s.groupLevel); |  | 
| 245                 this.currentGroup.messagesElement.appendChild(group.element); |  | 
| 246                 this.currentGroup = group; |  | 
| 247             } |  | 
| 248 |  | 
| 249             this.currentGroup.addMessage(msg); |  | 
| 250         } |  | 
| 251 |  | 
| 252         this.promptElement.scrollIntoView(false); |  | 
| 253     }, |  | 
| 254 |  | 
| 255     clearMessages: function(clearInspectorController) |  | 
| 256     { |  | 
| 257         if (clearInspectorController) |  | 
| 258             InspectorController.clearMessages(false); |  | 
| 259         if (WebInspector.panels.resources) |  | 
| 260             WebInspector.panels.resources.clearMessages(); |  | 
| 261 |  | 
| 262         this.messages = []; |  | 
| 263 |  | 
| 264         this.groupLevel = 0; |  | 
| 265         this.currentGroup = this.topGroup; |  | 
| 266         this.topGroup.messagesElement.removeChildren(); |  | 
| 267 |  | 
| 268         WebInspector.errors = 0; |  | 
| 269         WebInspector.warnings = 0; |  | 
| 270 |  | 
| 271         delete this.commandSincePreviousMessage; |  | 
| 272         delete this.repeatCountBeforeCommand; |  | 
| 273         delete this.previousMessage; |  | 
| 274     }, |  | 
| 275 |  | 
| 276     completions: function(wordRange, bestMatchOnly, completionsReadyCallback) |  | 
| 277     { |  | 
| 278         // Pass less stop characters to rangeOfWord so the range will be a more 
     complete expression. |  | 
| 279         var expressionRange = wordRange.startContainer.rangeOfWord(wordRange.sta
     rtOffset, ExpressionStopCharacters, this.promptElement, "backward"); |  | 
| 280         var expressionString = expressionRange.toString(); |  | 
| 281         var lastIndex = expressionString.length - 1; |  | 
| 282 |  | 
| 283         var dotNotation = (expressionString[lastIndex] === "."); |  | 
| 284         var bracketNotation = (expressionString[lastIndex] === "["); |  | 
| 285 |  | 
| 286         if (dotNotation || bracketNotation) |  | 
| 287             expressionString = expressionString.substr(0, lastIndex); |  | 
| 288 |  | 
| 289         var prefix = wordRange.toString(); |  | 
| 290         if (!expressionString && !prefix) |  | 
| 291             return; |  | 
| 292 |  | 
| 293         var reportCompletions = this._reportCompletions.bind(this, bestMatchOnly
     , completionsReadyCallback, dotNotation, bracketNotation, prefix); |  | 
| 294         // Collect comma separated object properties for the completion. |  | 
| 295 |  | 
| 296         var includeInspectorCommandLineAPI = (!dotNotation && !bracketNotation); |  | 
| 297         if (WebInspector.panels.scripts && WebInspector.panels.scripts.paused) |  | 
| 298             var callFrameId = WebInspector.panels.scripts.selectedCallFrameId(); |  | 
| 299         InjectedScriptAccess.getCompletions(expressionString, includeInspectorCo
     mmandLineAPI, callFrameId, reportCompletions); |  | 
| 300     }, |  | 
| 301 |  | 
| 302     _reportCompletions: function(bestMatchOnly, completionsReadyCallback, dotNot
     ation, bracketNotation, prefix, result, isException) { |  | 
| 303         if (isException) |  | 
| 304             return; |  | 
| 305 |  | 
| 306         if (bracketNotation) { |  | 
| 307             if (prefix.length && prefix[0] === "'") |  | 
| 308                 var quoteUsed = "'"; |  | 
| 309             else |  | 
| 310                 var quoteUsed = "\""; |  | 
| 311         } |  | 
| 312 |  | 
| 313         var results = []; |  | 
| 314         var properties = Object.sortedProperties(result); |  | 
| 315 |  | 
| 316         for (var i = 0; i < properties.length; ++i) { |  | 
| 317             var property = properties[i]; |  | 
| 318 |  | 
| 319             if (dotNotation && !/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(property)) |  | 
| 320                 continue; |  | 
| 321 |  | 
| 322             if (bracketNotation) { |  | 
| 323                 if (!/^[0-9]+$/.test(property)) |  | 
| 324                     property = quoteUsed + property.escapeCharacters(quoteUsed +
      "\\") + quoteUsed; |  | 
| 325                 property += "]"; |  | 
| 326             } |  | 
| 327 |  | 
| 328             if (property.length < prefix.length) |  | 
| 329                 continue; |  | 
| 330             if (property.indexOf(prefix) !== 0) |  | 
| 331                 continue; |  | 
| 332 |  | 
| 333             results.push(property); |  | 
| 334             if (bestMatchOnly) |  | 
| 335                 break; |  | 
| 336         } |  | 
| 337         completionsReadyCallback(results); |  | 
| 338     }, |  | 
| 339 |  | 
| 340     _clearButtonClicked: function() |  | 
| 341     { |  | 
| 342         this.clearMessages(true); |  | 
| 343     }, |  | 
| 344 |  | 
| 345     _messagesSelectStart: function(event) |  | 
| 346     { |  | 
| 347         if (this._selectionTimeout) |  | 
| 348             clearTimeout(this._selectionTimeout); |  | 
| 349 |  | 
| 350         this.prompt.clearAutoComplete(); |  | 
| 351 |  | 
| 352         function moveBackIfOutside() |  | 
| 353         { |  | 
| 354             delete this._selectionTimeout; |  | 
| 355             if (!this.prompt.isCaretInsidePrompt() && window.getSelection().isCo
     llapsed) |  | 
| 356                 this.prompt.moveCaretToEndOfPrompt(); |  | 
| 357             this.prompt.autoCompleteSoon(); |  | 
| 358         } |  | 
| 359 |  | 
| 360         this._selectionTimeout = setTimeout(moveBackIfOutside.bind(this), 100); |  | 
| 361     }, |  | 
| 362 |  | 
| 363     _messagesClicked: function(event) |  | 
| 364     { |  | 
| 365         var link = event.target.enclosingNodeOrSelfWithNodeName("a"); |  | 
| 366         if (!link || !link.representedNode) |  | 
| 367             return; |  | 
| 368 |  | 
| 369         WebInspector.updateFocusedNode(link.representedNode.id); |  | 
| 370         event.stopPropagation(); |  | 
| 371         event.preventDefault(); |  | 
| 372     }, |  | 
| 373 |  | 
| 374     _promptKeyDown: function(event) |  | 
| 375     { |  | 
| 376         switch (event.keyIdentifier) { |  | 
| 377             case "Enter": |  | 
| 378                 this._enterKeyPressed(event); |  | 
| 379                 return; |  | 
| 380         } |  | 
| 381 |  | 
| 382         this.prompt.handleKeyEvent(event); |  | 
| 383     }, |  | 
| 384 |  | 
| 385     evalInInspectedWindow: function(expression, objectGroup, callback) |  | 
| 386     { |  | 
| 387         if (WebInspector.panels.scripts && WebInspector.panels.scripts.paused) { |  | 
| 388             WebInspector.panels.scripts.evaluateInSelectedCallFrame(expression, 
     false, objectGroup, callback); |  | 
| 389             return; |  | 
| 390         } |  | 
| 391         this.doEvalInWindow(expression, objectGroup, callback); |  | 
| 392     }, |  | 
| 393 |  | 
| 394     doEvalInWindow: function(expression, objectGroup, callback) |  | 
| 395     { |  | 
| 396         if (!expression) { |  | 
| 397             // There is no expression, so the completion should happen against g
     lobal properties. |  | 
| 398             expression = "this"; |  | 
| 399         } |  | 
| 400 |  | 
| 401         function evalCallback(result) |  | 
| 402         { |  | 
| 403             callback(result.value, result.isException); |  | 
| 404         }; |  | 
| 405         InjectedScriptAccess.evaluate(expression, objectGroup, evalCallback); |  | 
| 406     }, |  | 
| 407 |  | 
| 408     _enterKeyPressed: function(event) |  | 
| 409     { |  | 
| 410         if (event.altKey) |  | 
| 411             return; |  | 
| 412 |  | 
| 413         event.preventDefault(); |  | 
| 414         event.stopPropagation(); |  | 
| 415 |  | 
| 416         this.prompt.clearAutoComplete(true); |  | 
| 417 |  | 
| 418         var str = this.prompt.text; |  | 
| 419         if (!str.length) |  | 
| 420             return; |  | 
| 421 |  | 
| 422         var commandMessage = new WebInspector.ConsoleCommand(str); |  | 
| 423         this.addMessage(commandMessage); |  | 
| 424 |  | 
| 425         var self = this; |  | 
| 426         function printResult(result, exception) |  | 
| 427         { |  | 
| 428             self.prompt.history.push(str); |  | 
| 429             self.prompt.historyOffset = 0; |  | 
| 430             self.prompt.text = ""; |  | 
| 431             self.addMessage(new WebInspector.ConsoleCommandResult(result, except
     ion, commandMessage)); |  | 
| 432         } |  | 
| 433         this.evalInInspectedWindow(str, "console", printResult); |  | 
| 434     }, |  | 
| 435 |  | 
| 436     _format: function(output, forceObjectFormat) |  | 
| 437     { |  | 
| 438         var isProxy = (output != null && typeof output === "object"); |  | 
| 439 |  | 
| 440         if (forceObjectFormat) |  | 
| 441             var type = "object"; |  | 
| 442         else |  | 
| 443             var type = Object.proxyType(output); |  | 
| 444 |  | 
| 445         if (isProxy && type !== "object" && type !== "function" && type !== "arr
     ay" && type !== "node") { |  | 
| 446             // Unwrap primitive value, skip decoration. |  | 
| 447             output = output.description; |  | 
| 448             type = "undecorated" |  | 
| 449         } |  | 
| 450 |  | 
| 451         // We don't perform any special formatting on these types, so we just |  | 
| 452         // pass them through the simple _formatvalue function. |  | 
| 453         var undecoratedTypes = { |  | 
| 454             "undefined": 1, |  | 
| 455             "null": 1, |  | 
| 456             "boolean": 1, |  | 
| 457             "number": 1, |  | 
| 458             "undecorated": 1 |  | 
| 459         }; |  | 
| 460 |  | 
| 461         var formatter; |  | 
| 462         if (forceObjectFormat) |  | 
| 463             formatter = "_formatobject"; |  | 
| 464         else if (type in undecoratedTypes) |  | 
| 465             formatter = "_formatvalue"; |  | 
| 466         else { |  | 
| 467             formatter = "_format" + type; |  | 
| 468             if (!(formatter in this)) { |  | 
| 469                 formatter = "_formatobject"; |  | 
| 470                 type = "object"; |  | 
| 471             } |  | 
| 472         } |  | 
| 473 |  | 
| 474         var span = document.createElement("span"); |  | 
| 475         span.addStyleClass("console-formatted-" + type); |  | 
| 476         this[formatter](output, span); |  | 
| 477         return span; |  | 
| 478     }, |  | 
| 479 |  | 
| 480     _formatvalue: function(val, elem) |  | 
| 481     { |  | 
| 482         elem.appendChild(document.createTextNode(val)); |  | 
| 483     }, |  | 
| 484 |  | 
| 485     _formatfunction: function(func, elem) |  | 
| 486     { |  | 
| 487         elem.appendChild(document.createTextNode(func.description)); |  | 
| 488     }, |  | 
| 489 |  | 
| 490     _formatdate: function(date, elem) |  | 
| 491     { |  | 
| 492         elem.appendChild(document.createTextNode(date)); |  | 
| 493     }, |  | 
| 494 |  | 
| 495     _formatstring: function(str, elem) |  | 
| 496     { |  | 
| 497         elem.appendChild(document.createTextNode("\"" + str + "\"")); |  | 
| 498     }, |  | 
| 499 |  | 
| 500     _formatregexp: function(re, elem) |  | 
| 501     { |  | 
| 502         var formatted = String(re.description).replace(/([\\\/])/g, "\\$1").repl
     ace(/\\(\/[gim]*)$/, "$1").substring(1); |  | 
| 503         elem.appendChild(document.createTextNode(formatted)); |  | 
| 504     }, |  | 
| 505 |  | 
| 506     _formatarray: function(arr, elem) |  | 
| 507     { |  | 
| 508         InjectedScriptAccess.getProperties(arr, false, this._printArray.bind(thi
     s, elem)); |  | 
| 509     }, |  | 
| 510 |  | 
| 511     _printArray: function(elem, properties) |  | 
| 512     { |  | 
| 513         if (!properties) |  | 
| 514             return; |  | 
| 515         var elements = []; |  | 
| 516         for (var i = 0; i < properties.length; ++i) { |  | 
| 517             var name = properties[i].name; |  | 
| 518             if (name == parseInt(name)) |  | 
| 519                 elements[name] = this._format(properties[i].value); |  | 
| 520         } |  | 
| 521 |  | 
| 522         elem.appendChild(document.createTextNode("[")); |  | 
| 523         for (var i = 0; i < elements.length; ++i) { |  | 
| 524             var element = elements[i]; |  | 
| 525             if (element) |  | 
| 526                 elem.appendChild(element); |  | 
| 527             else |  | 
| 528                 elem.appendChild(document.createTextNode("undefined")) |  | 
| 529             if (i < elements.length - 1) |  | 
| 530                 elem.appendChild(document.createTextNode(", ")); |  | 
| 531         } |  | 
| 532         elem.appendChild(document.createTextNode("]")); |  | 
| 533     }, |  | 
| 534 |  | 
| 535     _formatnode: function(object, elem) |  | 
| 536     { |  | 
| 537         function printNode(nodeId) |  | 
| 538         { |  | 
| 539             if (!nodeId) |  | 
| 540                 return; |  | 
| 541             var treeOutline = new WebInspector.ElementsTreeOutline(); |  | 
| 542             treeOutline.showInElementsPanelEnabled = true; |  | 
| 543             treeOutline.rootDOMNode = WebInspector.domAgent.nodeForId(nodeId); |  | 
| 544             treeOutline.element.addStyleClass("outline-disclosure"); |  | 
| 545             if (!treeOutline.children[0].hasChildren) |  | 
| 546                 treeOutline.element.addStyleClass("single-node"); |  | 
| 547             elem.appendChild(treeOutline.element); |  | 
| 548         } |  | 
| 549         InjectedScriptAccess.pushNodeToFrontend(object, printNode); |  | 
| 550     }, |  | 
| 551 |  | 
| 552     _formatobject: function(obj, elem) |  | 
| 553     { |  | 
| 554         elem.appendChild(new WebInspector.ObjectPropertiesSection(obj, obj.descr
     iption, null, true).element); |  | 
| 555     }, |  | 
| 556 |  | 
| 557     _formaterror: function(obj, elem) |  | 
| 558     { |  | 
| 559         var messageElement = document.createElement("span"); |  | 
| 560         messageElement.className = "error-message"; |  | 
| 561         messageElement.textContent = obj.name + ": " + obj.message; |  | 
| 562         elem.appendChild(messageElement); |  | 
| 563 |  | 
| 564         if (obj.sourceURL) { |  | 
| 565             var urlElement = document.createElement("a"); |  | 
| 566             urlElement.className = "webkit-html-resource-link"; |  | 
| 567             urlElement.href = obj.sourceURL; |  | 
| 568             urlElement.lineNumber = obj.line; |  | 
| 569             urlElement.preferredPanel = "scripts"; |  | 
| 570 |  | 
| 571             if (obj.line > 0) |  | 
| 572                 urlElement.textContent = WebInspector.displayNameForURL(obj.sour
     ceURL) + ":" + obj.line; |  | 
| 573             else |  | 
| 574                 urlElement.textContent = WebInspector.displayNameForURL(obj.sour
     ceURL); |  | 
| 575 |  | 
| 576             elem.appendChild(document.createTextNode(" (")); |  | 
| 577             elem.appendChild(urlElement); |  | 
| 578             elem.appendChild(document.createTextNode(")")); |  | 
| 579         } |  | 
| 580     } |  | 
| 581 } |  | 
| 582 |  | 
| 583 WebInspector.ConsoleView.prototype.__proto__ = WebInspector.View.prototype; |  | 
| 584 |  | 
| 585 WebInspector.ConsoleMessage = function(source, type, level, line, url, groupLeve
     l, repeatCount) |  | 
| 586 { |  | 
| 587     this.source = source; |  | 
| 588     this.type = type; |  | 
| 589     this.level = level; |  | 
| 590     this.line = line; |  | 
| 591     this.url = url; |  | 
| 592     this.groupLevel = groupLevel; |  | 
| 593     this.repeatCount = repeatCount; |  | 
| 594     if (arguments.length > 7) |  | 
| 595         this.setMessageBody(Array.prototype.slice.call(arguments, 7)); |  | 
| 596 } |  | 
| 597 |  | 
| 598 WebInspector.ConsoleMessage.prototype = { |  | 
| 599     setMessageBody: function(args) |  | 
| 600     { |  | 
| 601         switch (this.type) { |  | 
| 602             case WebInspector.ConsoleMessage.MessageType.Trace: |  | 
| 603                 var span = document.createElement("span"); |  | 
| 604                 span.addStyleClass("console-formatted-trace"); |  | 
| 605                 var stack = Array.prototype.slice.call(args); |  | 
| 606                 var funcNames = stack.map(function(f) { |  | 
| 607                     return f || WebInspector.UIString("(anonymous function)"); |  | 
| 608                 }); |  | 
| 609                 span.appendChild(document.createTextNode(funcNames.join("\n"))); |  | 
| 610                 this.formattedMessage = span; |  | 
| 611                 break; |  | 
| 612             case WebInspector.ConsoleMessage.MessageType.Object: |  | 
| 613                 this.formattedMessage = this._format(["%O", args[0]]); |  | 
| 614                 break; |  | 
| 615             default: |  | 
| 616                 this.formattedMessage = this._format(args); |  | 
| 617                 break; |  | 
| 618         } |  | 
| 619 |  | 
| 620         // This is used for inline message bubbles in SourceFrames, or other pla
     in-text representations. |  | 
| 621         this.message = this.formattedMessage.textContent; |  | 
| 622     }, |  | 
| 623 |  | 
| 624     isErrorOrWarning: function() |  | 
| 625     { |  | 
| 626         return (this.level === WebInspector.ConsoleMessage.MessageLevel.Warning 
     || this.level === WebInspector.ConsoleMessage.MessageLevel.Error); |  | 
| 627     }, |  | 
| 628 |  | 
| 629     _format: function(parameters) |  | 
| 630     { |  | 
| 631         var formattedResult = document.createElement("span"); |  | 
| 632 |  | 
| 633         if (!parameters.length) |  | 
| 634             return formattedResult; |  | 
| 635 |  | 
| 636         // Formatting code below assumes that parameters are all wrappers wherea
     s frontend console |  | 
| 637         // API allows passing arbitrary values as messages (strings, numberts, e
     tc.). Wrap them here. |  | 
| 638         for (var i = 0; i < parameters.length; ++i) { |  | 
| 639             if (typeof parameters[i] !== "object" && typeof parameters[i] !== "f
     unction") |  | 
| 640                 parameters[i] = WebInspector.ObjectProxy.wrapPrimitiveValue(para
     meters[i]); |  | 
| 641         } |  | 
| 642 |  | 
| 643         function formatForConsole(obj) |  | 
| 644         { |  | 
| 645             return WebInspector.console._format(obj); |  | 
| 646         } |  | 
| 647 |  | 
| 648         function formatAsObjectForConsole(obj) |  | 
| 649         { |  | 
| 650             return WebInspector.console._format(obj, true); |  | 
| 651         } |  | 
| 652 |  | 
| 653         if (Object.proxyType(parameters[0]) === "string") { |  | 
| 654             var formatters = {} |  | 
| 655             for (var i in String.standardFormatters) |  | 
| 656                 formatters[i] = String.standardFormatters[i]; |  | 
| 657 |  | 
| 658             // Firebug uses %o for formatting objects. |  | 
| 659             formatters.o = formatForConsole; |  | 
| 660             // Firebug allows both %i and %d for formatting integers. |  | 
| 661             formatters.i = formatters.d; |  | 
| 662             // Support %O to force object formating, instead of the type-based %
     o formatting. |  | 
| 663             formatters.O = formatAsObjectForConsole; |  | 
| 664 |  | 
| 665             function append(a, b) |  | 
| 666             { |  | 
| 667                 if (!(b instanceof Node)) |  | 
| 668                     a.appendChild(WebInspector.linkifyStringAsFragment(b.toStrin
     g())); |  | 
| 669                 else |  | 
| 670                     a.appendChild(b); |  | 
| 671                 return a; |  | 
| 672             } |  | 
| 673 |  | 
| 674             var result = String.format(parameters[0].description, parameters.sli
     ce(1), formatters, formattedResult, append); |  | 
| 675             formattedResult = result.formattedResult; |  | 
| 676             parameters = result.unusedSubstitutions; |  | 
| 677             if (parameters.length) |  | 
| 678                 formattedResult.appendChild(document.createTextNode(" ")); |  | 
| 679         } |  | 
| 680 |  | 
| 681         for (var i = 0; i < parameters.length; ++i) { |  | 
| 682             if (Object.proxyType(parameters[i]) === "string") |  | 
| 683                 formattedResult.appendChild(WebInspector.linkifyStringAsFragment
     (parameters[i].description)); |  | 
| 684             else |  | 
| 685                 formattedResult.appendChild(formatForConsole(parameters[i])); |  | 
| 686 |  | 
| 687             if (i < parameters.length - 1) |  | 
| 688                 formattedResult.appendChild(document.createTextNode(" ")); |  | 
| 689         } |  | 
| 690 |  | 
| 691         return formattedResult; |  | 
| 692     }, |  | 
| 693 |  | 
| 694     toMessageElement: function() |  | 
| 695     { |  | 
| 696         if (this.propertiesSection) |  | 
| 697             return this.propertiesSection.element; |  | 
| 698 |  | 
| 699         var element = document.createElement("div"); |  | 
| 700         element.message = this; |  | 
| 701         element.className = "console-message"; |  | 
| 702 |  | 
| 703         switch (this.source) { |  | 
| 704             case WebInspector.ConsoleMessage.MessageSource.HTML: |  | 
| 705                 element.addStyleClass("console-html-source"); |  | 
| 706                 break; |  | 
| 707             case WebInspector.ConsoleMessage.MessageSource.WML: |  | 
| 708                 element.addStyleClass("console-wml-source"); |  | 
| 709                 break; |  | 
| 710             case WebInspector.ConsoleMessage.MessageSource.XML: |  | 
| 711                 element.addStyleClass("console-xml-source"); |  | 
| 712                 break; |  | 
| 713             case WebInspector.ConsoleMessage.MessageSource.JS: |  | 
| 714                 element.addStyleClass("console-js-source"); |  | 
| 715                 break; |  | 
| 716             case WebInspector.ConsoleMessage.MessageSource.CSS: |  | 
| 717                 element.addStyleClass("console-css-source"); |  | 
| 718                 break; |  | 
| 719             case WebInspector.ConsoleMessage.MessageSource.Other: |  | 
| 720                 element.addStyleClass("console-other-source"); |  | 
| 721                 break; |  | 
| 722         } |  | 
| 723 |  | 
| 724         switch (this.level) { |  | 
| 725             case WebInspector.ConsoleMessage.MessageLevel.Tip: |  | 
| 726                 element.addStyleClass("console-tip-level"); |  | 
| 727                 break; |  | 
| 728             case WebInspector.ConsoleMessage.MessageLevel.Log: |  | 
| 729                 element.addStyleClass("console-log-level"); |  | 
| 730                 break; |  | 
| 731             case WebInspector.ConsoleMessage.MessageLevel.Debug: |  | 
| 732                 element.addStyleClass("console-debug-level"); |  | 
| 733                 break; |  | 
| 734             case WebInspector.ConsoleMessage.MessageLevel.Warning: |  | 
| 735                 element.addStyleClass("console-warning-level"); |  | 
| 736                 break; |  | 
| 737             case WebInspector.ConsoleMessage.MessageLevel.Error: |  | 
| 738                 element.addStyleClass("console-error-level"); |  | 
| 739                 break; |  | 
| 740         } |  | 
| 741 |  | 
| 742         if (this.type === WebInspector.ConsoleMessage.MessageType.StartGroup) { |  | 
| 743             element.addStyleClass("console-group-title"); |  | 
| 744         } |  | 
| 745 |  | 
| 746         if (this.elementsTreeOutline) { |  | 
| 747             element.addStyleClass("outline-disclosure"); |  | 
| 748             element.appendChild(this.elementsTreeOutline.element); |  | 
| 749             return element; |  | 
| 750         } |  | 
| 751 |  | 
| 752         if (this.repeatCount > 1) { |  | 
| 753             var messageRepeatCountElement = document.createElement("span"); |  | 
| 754             messageRepeatCountElement.className = "bubble"; |  | 
| 755             messageRepeatCountElement.textContent = this.repeatCount; |  | 
| 756 |  | 
| 757             element.appendChild(messageRepeatCountElement); |  | 
| 758             element.addStyleClass("repeated-message"); |  | 
| 759         } |  | 
| 760 |  | 
| 761         if (this.url && this.url !== "undefined") { |  | 
| 762             var urlElement = document.createElement("a"); |  | 
| 763             urlElement.className = "console-message-url webkit-html-resource-lin
     k"; |  | 
| 764             urlElement.href = this.url; |  | 
| 765             urlElement.lineNumber = this.line; |  | 
| 766 |  | 
| 767             if (this.source === WebInspector.ConsoleMessage.MessageSource.JS) |  | 
| 768                 urlElement.preferredPanel = "scripts"; |  | 
| 769 |  | 
| 770             if (this.line > 0) |  | 
| 771                 urlElement.textContent = WebInspector.displayNameForURL(this.url
     ) + ":" + this.line; |  | 
| 772             else |  | 
| 773                 urlElement.textContent = WebInspector.displayNameForURL(this.url
     ); |  | 
| 774 |  | 
| 775             element.appendChild(urlElement); |  | 
| 776         } |  | 
| 777 |  | 
| 778         var messageTextElement = document.createElement("span"); |  | 
| 779         messageTextElement.className = "console-message-text"; |  | 
| 780         messageTextElement.appendChild(this.formattedMessage); |  | 
| 781         element.appendChild(messageTextElement); |  | 
| 782 |  | 
| 783         return element; |  | 
| 784     }, |  | 
| 785 |  | 
| 786     toString: function() |  | 
| 787     { |  | 
| 788         var sourceString; |  | 
| 789         switch (this.source) { |  | 
| 790             case WebInspector.ConsoleMessage.MessageSource.HTML: |  | 
| 791                 sourceString = "HTML"; |  | 
| 792                 break; |  | 
| 793             case WebInspector.ConsoleMessage.MessageSource.WML: |  | 
| 794                 sourceString = "WML"; |  | 
| 795                 break; |  | 
| 796             case WebInspector.ConsoleMessage.MessageSource.XML: |  | 
| 797                 sourceString = "XML"; |  | 
| 798                 break; |  | 
| 799             case WebInspector.ConsoleMessage.MessageSource.JS: |  | 
| 800                 sourceString = "JS"; |  | 
| 801                 break; |  | 
| 802             case WebInspector.ConsoleMessage.MessageSource.CSS: |  | 
| 803                 sourceString = "CSS"; |  | 
| 804                 break; |  | 
| 805             case WebInspector.ConsoleMessage.MessageSource.Other: |  | 
| 806                 sourceString = "Other"; |  | 
| 807                 break; |  | 
| 808         } |  | 
| 809 |  | 
| 810         var typeString; |  | 
| 811         switch (this.type) { |  | 
| 812             case WebInspector.ConsoleMessage.MessageType.Log: |  | 
| 813                 typeString = "Log"; |  | 
| 814                 break; |  | 
| 815             case WebInspector.ConsoleMessage.MessageType.Object: |  | 
| 816                 typeString = "Object"; |  | 
| 817                 break; |  | 
| 818             case WebInspector.ConsoleMessage.MessageType.Trace: |  | 
| 819                 typeString = "Trace"; |  | 
| 820                 break; |  | 
| 821             case WebInspector.ConsoleMessage.MessageType.StartGroup: |  | 
| 822                 typeString = "Start Group"; |  | 
| 823                 break; |  | 
| 824             case WebInspector.ConsoleMessage.MessageType.EndGroup: |  | 
| 825                 typeString = "End Group"; |  | 
| 826                 break; |  | 
| 827         } |  | 
| 828 |  | 
| 829         var levelString; |  | 
| 830         switch (this.level) { |  | 
| 831             case WebInspector.ConsoleMessage.MessageLevel.Tip: |  | 
| 832                 levelString = "Tip"; |  | 
| 833                 break; |  | 
| 834             case WebInspector.ConsoleMessage.MessageLevel.Log: |  | 
| 835                 levelString = "Log"; |  | 
| 836                 break; |  | 
| 837             case WebInspector.ConsoleMessage.MessageLevel.Warning: |  | 
| 838                 levelString = "Warning"; |  | 
| 839                 break; |  | 
| 840             case WebInspector.ConsoleMessage.MessageLevel.Debug: |  | 
| 841                 levelString = "Debug"; |  | 
| 842                 break; |  | 
| 843             case WebInspector.ConsoleMessage.MessageLevel.Error: |  | 
| 844                 levelString = "Error"; |  | 
| 845                 break; |  | 
| 846         } |  | 
| 847 |  | 
| 848         return sourceString + " " + typeString + " " + levelString + ": " + this
     .formattedMessage.textContent + "\n" + this.url + " line " + this.line; |  | 
| 849     }, |  | 
| 850 |  | 
| 851     isEqual: function(msg, disreguardGroup) |  | 
| 852     { |  | 
| 853         if (!msg) |  | 
| 854             return false; |  | 
| 855 |  | 
| 856         var ret = (this.source == msg.source) |  | 
| 857             && (this.type == msg.type) |  | 
| 858             && (this.level == msg.level) |  | 
| 859             && (this.line == msg.line) |  | 
| 860             && (this.url == msg.url) |  | 
| 861             && (this.message == msg.message); |  | 
| 862 |  | 
| 863         return (disreguardGroup ? ret : (ret && (this.groupLevel == msg.groupLev
     el))); |  | 
| 864     } |  | 
| 865 } |  | 
| 866 |  | 
| 867 // Note: Keep these constants in sync with the ones in Console.h |  | 
| 868 WebInspector.ConsoleMessage.MessageSource = { |  | 
| 869     HTML: 0, |  | 
| 870     WML: 1, |  | 
| 871     XML: 2, |  | 
| 872     JS: 3, |  | 
| 873     CSS: 4, |  | 
| 874     Other: 5 |  | 
| 875 } |  | 
| 876 |  | 
| 877 WebInspector.ConsoleMessage.MessageType = { |  | 
| 878     Log: 0, |  | 
| 879     Object: 1, |  | 
| 880     Trace: 2, |  | 
| 881     StartGroup: 3, |  | 
| 882     EndGroup: 4 |  | 
| 883 } |  | 
| 884 |  | 
| 885 WebInspector.ConsoleMessage.MessageLevel = { |  | 
| 886     Tip: 0, |  | 
| 887     Log: 1, |  | 
| 888     Warning: 2, |  | 
| 889     Error: 3, |  | 
| 890     Debug: 4 |  | 
| 891 } |  | 
| 892 |  | 
| 893 WebInspector.ConsoleCommand = function(command) |  | 
| 894 { |  | 
| 895     this.command = command; |  | 
| 896 } |  | 
| 897 |  | 
| 898 WebInspector.ConsoleCommand.prototype = { |  | 
| 899     toMessageElement: function() |  | 
| 900     { |  | 
| 901         var element = document.createElement("div"); |  | 
| 902         element.command = this; |  | 
| 903         element.className = "console-user-command"; |  | 
| 904 |  | 
| 905         var commandTextElement = document.createElement("span"); |  | 
| 906         commandTextElement.className = "console-message-text"; |  | 
| 907         commandTextElement.textContent = this.command; |  | 
| 908         element.appendChild(commandTextElement); |  | 
| 909 |  | 
| 910         return element; |  | 
| 911     } |  | 
| 912 } |  | 
| 913 |  | 
| 914 WebInspector.ConsoleTextMessage = function(text, level) |  | 
| 915 { |  | 
| 916     level = level || WebInspector.ConsoleMessage.MessageLevel.Log; |  | 
| 917     WebInspector.ConsoleMessage.call(this, WebInspector.ConsoleMessage.MessageSo
     urce.JS, WebInspector.ConsoleMessage.MessageType.Log, level, 0, null, null, 1, t
     ext); |  | 
| 918 } |  | 
| 919 |  | 
| 920 WebInspector.ConsoleTextMessage.prototype.__proto__ = WebInspector.ConsoleMessag
     e.prototype; |  | 
| 921 |  | 
| 922 WebInspector.ConsoleCommandResult = function(result, exception, originatingComma
     nd) |  | 
| 923 { |  | 
| 924     var level = (exception ? WebInspector.ConsoleMessage.MessageLevel.Error : We
     bInspector.ConsoleMessage.MessageLevel.Log); |  | 
| 925     var message = result; |  | 
| 926     var line = (exception ? result.line : -1); |  | 
| 927     var url = (exception ? result.sourceURL : null); |  | 
| 928 |  | 
| 929     WebInspector.ConsoleMessage.call(this, WebInspector.ConsoleMessage.MessageSo
     urce.JS, WebInspector.ConsoleMessage.MessageType.Log, level, line, url, null, 1,
      message); |  | 
| 930 |  | 
| 931     this.originatingCommand = originatingCommand; |  | 
| 932 } |  | 
| 933 |  | 
| 934 WebInspector.ConsoleCommandResult.prototype = { |  | 
| 935     toMessageElement: function() |  | 
| 936     { |  | 
| 937         var element = WebInspector.ConsoleMessage.prototype.toMessageElement.cal
     l(this); |  | 
| 938         element.addStyleClass("console-user-command-result"); |  | 
| 939         return element; |  | 
| 940     } |  | 
| 941 } |  | 
| 942 |  | 
| 943 WebInspector.ConsoleCommandResult.prototype.__proto__ = WebInspector.ConsoleMess
     age.prototype; |  | 
| 944 |  | 
| 945 WebInspector.ConsoleGroup = function(parentGroup, level) |  | 
| 946 { |  | 
| 947     this.parentGroup = parentGroup; |  | 
| 948     this.level = level; |  | 
| 949 |  | 
| 950     var element = document.createElement("div"); |  | 
| 951     element.className = "console-group"; |  | 
| 952     element.group = this; |  | 
| 953     this.element = element; |  | 
| 954 |  | 
| 955     var messagesElement = document.createElement("div"); |  | 
| 956     messagesElement.className = "console-group-messages"; |  | 
| 957     element.appendChild(messagesElement); |  | 
| 958     this.messagesElement = messagesElement; |  | 
| 959 } |  | 
| 960 |  | 
| 961 WebInspector.ConsoleGroup.prototype = { |  | 
| 962     addMessage: function(msg) |  | 
| 963     { |  | 
| 964         var element = msg.toMessageElement(); |  | 
| 965 |  | 
| 966         if (msg.type === WebInspector.ConsoleMessage.MessageType.StartGroup) { |  | 
| 967             this.messagesElement.parentNode.insertBefore(element, this.messagesE
     lement); |  | 
| 968             element.addEventListener("click", this._titleClicked.bind(this), tru
     e); |  | 
| 969         } else |  | 
| 970             this.messagesElement.appendChild(element); |  | 
| 971 |  | 
| 972         if (element.previousSibling && msg.originatingCommand && element.previou
     sSibling.command === msg.originatingCommand) |  | 
| 973             element.previousSibling.addStyleClass("console-adjacent-user-command
     -result"); |  | 
| 974     }, |  | 
| 975 |  | 
| 976     _titleClicked: function(event) |  | 
| 977     { |  | 
| 978         var groupTitleElement = event.target.enclosingNodeOrSelfWithClass("conso
     le-group-title"); |  | 
| 979         if (groupTitleElement) { |  | 
| 980             var groupElement = groupTitleElement.enclosingNodeOrSelfWithClass("c
     onsole-group"); |  | 
| 981             if (groupElement) |  | 
| 982                 if (groupElement.hasStyleClass("collapsed")) |  | 
| 983                     groupElement.removeStyleClass("collapsed"); |  | 
| 984                 else |  | 
| 985                     groupElement.addStyleClass("collapsed"); |  | 
| 986             groupTitleElement.scrollIntoViewIfNeeded(true); |  | 
| 987         } |  | 
| 988 |  | 
| 989         event.stopPropagation(); |  | 
| 990         event.preventDefault(); |  | 
| 991     } |  | 
| 992 } |  | 
| OLD | NEW | 
|---|