diff options
author | ananta@chromium.org <ananta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-11 20:11:48 +0000 |
---|---|---|
committer | ananta@chromium.org <ananta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-11 20:11:48 +0000 |
commit | c08d4794dbfb2f100cac2a54dec5c7f327ecddfa (patch) | |
tree | a04d698a8ea0b9c9cd2d63c4ca05064f71f7147b /chrome/tools | |
parent | 26a323ff00cc293f835a801da8c60b7ecdd36472 (diff) | |
download | chromium_src-c08d4794dbfb2f100cac2a54dec5c7f327ecddfa.zip chromium_src-c08d4794dbfb2f100cac2a54dec5c7f327ecddfa.tar.gz chromium_src-c08d4794dbfb2f100cac2a54dec5c7f327ecddfa.tar.bz2 |
Updating reference build to revision 9586 to pick up the latest automation
framework changes.
TBR=nsylvain
Review URL: http://codereview.chromium.org/20272
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@9587 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/tools')
85 files changed, 5665 insertions, 2211 deletions
diff --git a/chrome/tools/test/reference_build/chrome/chrome.dll b/chrome/tools/test/reference_build/chrome/chrome.dll Binary files differindex cc3b602..4ebaa46 100644 --- a/chrome/tools/test/reference_build/chrome/chrome.dll +++ b/chrome/tools/test/reference_build/chrome/chrome.dll diff --git a/chrome/tools/test/reference_build/chrome/chrome.exe b/chrome/tools/test/reference_build/chrome/chrome.exe Binary files differindex d2d742c..8c20fc7 100644 --- a/chrome/tools/test/reference_build/chrome/chrome.exe +++ b/chrome/tools/test/reference_build/chrome/chrome.exe diff --git a/chrome/tools/test/reference_build/chrome/chrome_dll.pdb b/chrome/tools/test/reference_build/chrome/chrome_dll.pdb Binary files differindex 22037a0..ef5ad39 100644 --- a/chrome/tools/test/reference_build/chrome/chrome_dll.pdb +++ b/chrome/tools/test/reference_build/chrome/chrome_dll.pdb diff --git a/chrome/tools/test/reference_build/chrome/chrome_exe.pdb b/chrome/tools/test/reference_build/chrome/chrome_exe.pdb Binary files differindex 46f8634..4708dac 100644 --- a/chrome/tools/test/reference_build/chrome/chrome_exe.pdb +++ b/chrome/tools/test/reference_build/chrome/chrome_exe.pdb diff --git a/chrome/tools/test/reference_build/chrome/crash_service.exe b/chrome/tools/test/reference_build/chrome/crash_service.exe Binary files differindex 07935f7..8f0d510 100644 --- a/chrome/tools/test/reference_build/chrome/crash_service.exe +++ b/chrome/tools/test/reference_build/chrome/crash_service.exe diff --git a/chrome/tools/test/reference_build/chrome/icudt38.dll b/chrome/tools/test/reference_build/chrome/icudt38.dll Binary files differindex 4acc4c5..8cbc57f 100644 --- a/chrome/tools/test/reference_build/chrome/icudt38.dll +++ b/chrome/tools/test/reference_build/chrome/icudt38.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/ar.dll b/chrome/tools/test/reference_build/chrome/locales/ar.dll Binary files differindex a8bbd71..8063823 100644 --- a/chrome/tools/test/reference_build/chrome/locales/ar.dll +++ b/chrome/tools/test/reference_build/chrome/locales/ar.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/bg.dll b/chrome/tools/test/reference_build/chrome/locales/bg.dll Binary files differindex 913ee32..4bfa803 100644 --- a/chrome/tools/test/reference_build/chrome/locales/bg.dll +++ b/chrome/tools/test/reference_build/chrome/locales/bg.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/ca.dll b/chrome/tools/test/reference_build/chrome/locales/ca.dll Binary files differindex 6f07956..b1bdaad 100644 --- a/chrome/tools/test/reference_build/chrome/locales/ca.dll +++ b/chrome/tools/test/reference_build/chrome/locales/ca.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/cs.dll b/chrome/tools/test/reference_build/chrome/locales/cs.dll Binary files differindex f3983a5..a2e69bd 100644 --- a/chrome/tools/test/reference_build/chrome/locales/cs.dll +++ b/chrome/tools/test/reference_build/chrome/locales/cs.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/da.dll b/chrome/tools/test/reference_build/chrome/locales/da.dll Binary files differindex 40d9bbc..1b6f0e7 100644 --- a/chrome/tools/test/reference_build/chrome/locales/da.dll +++ b/chrome/tools/test/reference_build/chrome/locales/da.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/de.dll b/chrome/tools/test/reference_build/chrome/locales/de.dll Binary files differindex e084700..0de11d2 100644 --- a/chrome/tools/test/reference_build/chrome/locales/de.dll +++ b/chrome/tools/test/reference_build/chrome/locales/de.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/el.dll b/chrome/tools/test/reference_build/chrome/locales/el.dll Binary files differindex 23eeb0d..94c2f02 100644 --- a/chrome/tools/test/reference_build/chrome/locales/el.dll +++ b/chrome/tools/test/reference_build/chrome/locales/el.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/en-GB.dll b/chrome/tools/test/reference_build/chrome/locales/en-GB.dll Binary files differindex 9d88a58..633cc4d 100644 --- a/chrome/tools/test/reference_build/chrome/locales/en-GB.dll +++ b/chrome/tools/test/reference_build/chrome/locales/en-GB.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/en-US.dll b/chrome/tools/test/reference_build/chrome/locales/en-US.dll Binary files differindex 750bb0e..9687b08 100644 --- a/chrome/tools/test/reference_build/chrome/locales/en-US.dll +++ b/chrome/tools/test/reference_build/chrome/locales/en-US.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/es-419.dll b/chrome/tools/test/reference_build/chrome/locales/es-419.dll Binary files differindex 943d814..5408aee 100644 --- a/chrome/tools/test/reference_build/chrome/locales/es-419.dll +++ b/chrome/tools/test/reference_build/chrome/locales/es-419.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/es.dll b/chrome/tools/test/reference_build/chrome/locales/es.dll Binary files differindex e261285..b239a54 100644 --- a/chrome/tools/test/reference_build/chrome/locales/es.dll +++ b/chrome/tools/test/reference_build/chrome/locales/es.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/et.dll b/chrome/tools/test/reference_build/chrome/locales/et.dll Binary files differindex 2dcda0a..dd3230c 100644 --- a/chrome/tools/test/reference_build/chrome/locales/et.dll +++ b/chrome/tools/test/reference_build/chrome/locales/et.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/fi.dll b/chrome/tools/test/reference_build/chrome/locales/fi.dll Binary files differindex 37b8e3f..8e56e69 100644 --- a/chrome/tools/test/reference_build/chrome/locales/fi.dll +++ b/chrome/tools/test/reference_build/chrome/locales/fi.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/fil.dll b/chrome/tools/test/reference_build/chrome/locales/fil.dll Binary files differindex 015779e..584829b 100644 --- a/chrome/tools/test/reference_build/chrome/locales/fil.dll +++ b/chrome/tools/test/reference_build/chrome/locales/fil.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/fr.dll b/chrome/tools/test/reference_build/chrome/locales/fr.dll Binary files differindex 1a26f85..6528d4a 100644 --- a/chrome/tools/test/reference_build/chrome/locales/fr.dll +++ b/chrome/tools/test/reference_build/chrome/locales/fr.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/he.dll b/chrome/tools/test/reference_build/chrome/locales/he.dll Binary files differindex 2f3da9b..8000e3b 100644 --- a/chrome/tools/test/reference_build/chrome/locales/he.dll +++ b/chrome/tools/test/reference_build/chrome/locales/he.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/hi.dll b/chrome/tools/test/reference_build/chrome/locales/hi.dll Binary files differindex 79c53b4..18d7de1d 100644 --- a/chrome/tools/test/reference_build/chrome/locales/hi.dll +++ b/chrome/tools/test/reference_build/chrome/locales/hi.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/hr.dll b/chrome/tools/test/reference_build/chrome/locales/hr.dll Binary files differindex 66ad166..1ff7290 100644 --- a/chrome/tools/test/reference_build/chrome/locales/hr.dll +++ b/chrome/tools/test/reference_build/chrome/locales/hr.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/hu.dll b/chrome/tools/test/reference_build/chrome/locales/hu.dll Binary files differindex 223d521..9e6aace 100644 --- a/chrome/tools/test/reference_build/chrome/locales/hu.dll +++ b/chrome/tools/test/reference_build/chrome/locales/hu.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/id.dll b/chrome/tools/test/reference_build/chrome/locales/id.dll Binary files differindex f8c54a6..c81e508 100644 --- a/chrome/tools/test/reference_build/chrome/locales/id.dll +++ b/chrome/tools/test/reference_build/chrome/locales/id.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/it.dll b/chrome/tools/test/reference_build/chrome/locales/it.dll Binary files differindex 3597192..5d3c614 100644 --- a/chrome/tools/test/reference_build/chrome/locales/it.dll +++ b/chrome/tools/test/reference_build/chrome/locales/it.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/ja.dll b/chrome/tools/test/reference_build/chrome/locales/ja.dll Binary files differindex 44a1b70..9c0317c 100644 --- a/chrome/tools/test/reference_build/chrome/locales/ja.dll +++ b/chrome/tools/test/reference_build/chrome/locales/ja.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/ko.dll b/chrome/tools/test/reference_build/chrome/locales/ko.dll Binary files differindex 8689ba7..acfe496 100644 --- a/chrome/tools/test/reference_build/chrome/locales/ko.dll +++ b/chrome/tools/test/reference_build/chrome/locales/ko.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/lt.dll b/chrome/tools/test/reference_build/chrome/locales/lt.dll Binary files differindex c3c00e3..c3309cb 100644 --- a/chrome/tools/test/reference_build/chrome/locales/lt.dll +++ b/chrome/tools/test/reference_build/chrome/locales/lt.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/lv.dll b/chrome/tools/test/reference_build/chrome/locales/lv.dll Binary files differindex 346d347..bd9d4ec 100644 --- a/chrome/tools/test/reference_build/chrome/locales/lv.dll +++ b/chrome/tools/test/reference_build/chrome/locales/lv.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/nb.dll b/chrome/tools/test/reference_build/chrome/locales/nb.dll Binary files differindex 1a6e965..8ef7708 100644 --- a/chrome/tools/test/reference_build/chrome/locales/nb.dll +++ b/chrome/tools/test/reference_build/chrome/locales/nb.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/nl.dll b/chrome/tools/test/reference_build/chrome/locales/nl.dll Binary files differindex 8aa7fc2..5280634 100644 --- a/chrome/tools/test/reference_build/chrome/locales/nl.dll +++ b/chrome/tools/test/reference_build/chrome/locales/nl.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/pl.dll b/chrome/tools/test/reference_build/chrome/locales/pl.dll Binary files differindex ac87514..e968685 100644 --- a/chrome/tools/test/reference_build/chrome/locales/pl.dll +++ b/chrome/tools/test/reference_build/chrome/locales/pl.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/pt-BR.dll b/chrome/tools/test/reference_build/chrome/locales/pt-BR.dll Binary files differindex f64b9d7..b1f8f2f 100644 --- a/chrome/tools/test/reference_build/chrome/locales/pt-BR.dll +++ b/chrome/tools/test/reference_build/chrome/locales/pt-BR.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/pt-PT.dll b/chrome/tools/test/reference_build/chrome/locales/pt-PT.dll Binary files differindex 7cda96b..2257373 100644 --- a/chrome/tools/test/reference_build/chrome/locales/pt-PT.dll +++ b/chrome/tools/test/reference_build/chrome/locales/pt-PT.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/ro.dll b/chrome/tools/test/reference_build/chrome/locales/ro.dll Binary files differindex 9d5e843..6f54163 100644 --- a/chrome/tools/test/reference_build/chrome/locales/ro.dll +++ b/chrome/tools/test/reference_build/chrome/locales/ro.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/ru.dll b/chrome/tools/test/reference_build/chrome/locales/ru.dll Binary files differindex b5f47fa..fea12e3 100644 --- a/chrome/tools/test/reference_build/chrome/locales/ru.dll +++ b/chrome/tools/test/reference_build/chrome/locales/ru.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/sk.dll b/chrome/tools/test/reference_build/chrome/locales/sk.dll Binary files differindex c9ce389..abef9a8 100644 --- a/chrome/tools/test/reference_build/chrome/locales/sk.dll +++ b/chrome/tools/test/reference_build/chrome/locales/sk.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/sl.dll b/chrome/tools/test/reference_build/chrome/locales/sl.dll Binary files differindex 9ffb579..ea4df1e 100644 --- a/chrome/tools/test/reference_build/chrome/locales/sl.dll +++ b/chrome/tools/test/reference_build/chrome/locales/sl.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/sr.dll b/chrome/tools/test/reference_build/chrome/locales/sr.dll Binary files differindex 73fbac2..04f5a6f 100644 --- a/chrome/tools/test/reference_build/chrome/locales/sr.dll +++ b/chrome/tools/test/reference_build/chrome/locales/sr.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/sv.dll b/chrome/tools/test/reference_build/chrome/locales/sv.dll Binary files differindex ffed977..b969966 100644 --- a/chrome/tools/test/reference_build/chrome/locales/sv.dll +++ b/chrome/tools/test/reference_build/chrome/locales/sv.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/th.dll b/chrome/tools/test/reference_build/chrome/locales/th.dll Binary files differindex be57472..fd0a335 100644 --- a/chrome/tools/test/reference_build/chrome/locales/th.dll +++ b/chrome/tools/test/reference_build/chrome/locales/th.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/tr.dll b/chrome/tools/test/reference_build/chrome/locales/tr.dll Binary files differindex 58916f6..29336b2 100644 --- a/chrome/tools/test/reference_build/chrome/locales/tr.dll +++ b/chrome/tools/test/reference_build/chrome/locales/tr.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/uk.dll b/chrome/tools/test/reference_build/chrome/locales/uk.dll Binary files differindex f192d5f..224cb8c 100644 --- a/chrome/tools/test/reference_build/chrome/locales/uk.dll +++ b/chrome/tools/test/reference_build/chrome/locales/uk.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/vi.dll b/chrome/tools/test/reference_build/chrome/locales/vi.dll Binary files differindex 0df905f..04f7d21 100644 --- a/chrome/tools/test/reference_build/chrome/locales/vi.dll +++ b/chrome/tools/test/reference_build/chrome/locales/vi.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/zh-CN.dll b/chrome/tools/test/reference_build/chrome/locales/zh-CN.dll Binary files differindex b28e3f5..9d37e3e 100644 --- a/chrome/tools/test/reference_build/chrome/locales/zh-CN.dll +++ b/chrome/tools/test/reference_build/chrome/locales/zh-CN.dll diff --git a/chrome/tools/test/reference_build/chrome/locales/zh-TW.dll b/chrome/tools/test/reference_build/chrome/locales/zh-TW.dll Binary files differindex ecab53a..c2322cc 100644 --- a/chrome/tools/test/reference_build/chrome/locales/zh-TW.dll +++ b/chrome/tools/test/reference_build/chrome/locales/zh-TW.dll diff --git a/chrome/tools/test/reference_build/chrome/plugins/gears/gears.dll b/chrome/tools/test/reference_build/chrome/plugins/gears/gears.dll Binary files differindex 1184b5b..2e292b1 100644 --- a/chrome/tools/test/reference_build/chrome/plugins/gears/gears.dll +++ b/chrome/tools/test/reference_build/chrome/plugins/gears/gears.dll diff --git a/chrome/tools/test/reference_build/chrome/resources/Inspector/BreakpointsSidebarPane.js b/chrome/tools/test/reference_build/chrome/resources/Inspector/BreakpointsSidebarPane.js index 3bb33dc..2b8f3cd 100644 --- a/chrome/tools/test/reference_build/chrome/resources/Inspector/BreakpointsSidebarPane.js +++ b/chrome/tools/test/reference_build/chrome/resources/Inspector/BreakpointsSidebarPane.js @@ -26,10 +26,60 @@ WebInspector.BreakpointsSidebarPane = function() { WebInspector.SidebarPane.call(this, WebInspector.UIString("Breakpoints")); + + this.breakpoints = []; + + this.emptyElement = document.createElement("div"); + this.emptyElement.className = "info"; + this.emptyElement.textContent = WebInspector.UIString("No Breakpoints"); + + this.bodyElement.appendChild(this.emptyElement); } WebInspector.BreakpointsSidebarPane.prototype = { - + addBreakpoint: function(breakpoint) + { + this.breakpoints.push(breakpoint); + breakpoint.addEventListener("enabled", this._breakpointEnableChanged, this); + breakpoint.addEventListener("disabled", this._breakpointEnableChanged, this); + + // FIXME: add to the breakpoints UI. + + if (!InspectorController.debuggerEnabled() || !breakpoint.sourceID) + return; + + if (breakpoint.enabled) + InspectorController.addBreakpoint(breakpoint.sourceID, breakpoint.line); + }, + + removeBreakpoint: function(breakpoint) + { + this.breakpoints.remove(breakpoint); + breakpoint.removeEventListener("enabled", null, this); + breakpoint.removeEventListener("disabled", null, this); + + // FIXME: remove from the breakpoints UI. + + if (!InspectorController.debuggerEnabled() || !breakpoint.sourceID) + return; + + InspectorController.removeBreakpoint(breakpoint.sourceID, breakpoint.line); + }, + + _breakpointEnableChanged: function(event) + { + var breakpoint = event.target; + + // FIXME: change the breakpoint checkbox state in the UI. + + if (!InspectorController.debuggerEnabled() || !breakpoint.sourceID) + return; + + if (breakpoint.enabled) + InspectorController.addBreakpoint(breakpoint.sourceID, breakpoint.line); + else + InspectorController.removeBreakpoint(breakpoint.sourceID, breakpoint.line); + } } WebInspector.BreakpointsSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype; diff --git a/chrome/tools/test/reference_build/chrome/resources/Inspector/CallStackSidebarPane.js b/chrome/tools/test/reference_build/chrome/resources/Inspector/CallStackSidebarPane.js index 849e562d..a2c8bed 100644 --- a/chrome/tools/test/reference_build/chrome/resources/Inspector/CallStackSidebarPane.js +++ b/chrome/tools/test/reference_build/chrome/resources/Inspector/CallStackSidebarPane.js @@ -29,7 +29,82 @@ WebInspector.CallStackSidebarPane = function() } WebInspector.CallStackSidebarPane.prototype = { - + update: function(callFrame, sourceIDMap) + { + this.bodyElement.removeChildren(); + + this.placards = []; + delete this._selectedCallFrame; + + if (!callFrame) { + var infoElement = document.createElement("div"); + infoElement.className = "info"; + infoElement.textContent = WebInspector.UIString("Not Paused"); + this.bodyElement.appendChild(infoElement); + return; + } + + var title; + var subtitle; + var scriptOrResource; + + do { + switch (callFrame.type) { + case "function": + title = callFrame.functionName || WebInspector.UIString("(anonymous function)"); + break; + case "program": + title = WebInspector.UIString("(program)"); + break; + } + + scriptOrResource = sourceIDMap[callFrame.sourceID]; + subtitle = WebInspector.displayNameForURL(scriptOrResource.sourceURL || scriptOrResource.url); + + if (callFrame.line > 0) { + if (subtitle) + subtitle += ":" + callFrame.line; + else + subtitle = WebInspector.UIString("line %d", callFrame.line); + } + + var placard = new WebInspector.Placard(title, subtitle); + placard.callFrame = callFrame; + + placard.element.addEventListener("click", this._placardSelected.bind(this), false); + + this.placards.push(placard); + this.bodyElement.appendChild(placard.element); + + callFrame = callFrame.caller; + } while (callFrame); + }, + + get selectedCallFrame() + { + return this._selectedCallFrame; + }, + + set selectedCallFrame(x) + { + if (this._selectedCallFrame === x) + return; + + this._selectedCallFrame = x; + + for (var i = 0; i < this.placards.length; ++i) { + var placard = this.placards[i]; + placard.selected = (placard.callFrame === this._selectedCallFrame); + } + + this.dispatchEventToListeners("call frame selected"); + }, + + _placardSelected: function(event) + { + var placardElement = event.target.enclosingNodeOrSelfWithClass("placard"); + this.selectedCallFrame = placardElement.placard.callFrame; + } } WebInspector.CallStackSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype; diff --git a/chrome/tools/test/reference_build/chrome/resources/Inspector/Console.js b/chrome/tools/test/reference_build/chrome/resources/Inspector/Console.js index 1292531..c98d155 100644 --- a/chrome/tools/test/reference_build/chrome/resources/Inspector/Console.js +++ b/chrome/tools/test/reference_build/chrome/resources/Inspector/Console.js @@ -6,13 +6,13 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. + * documentation and/or other materials provided with the distribution. * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. + * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -36,12 +36,8 @@ WebInspector.Console = function() this.messagesElement.addEventListener("selectstart", this._messagesSelectStart.bind(this), false); this.messagesElement.addEventListener("click", this._messagesClicked.bind(this), true); - // The messagesElement is the focusable element so clicking anywhere in the - // console area will focus the prompt. - this.messagesElement.focused = this._messagesFocused.bind(this); - this.messagesElement.handleKeyEvent = this._promptKeyDown.bind(this); - this.promptElement = document.getElementById("console-prompt"); + this.promptElement.handleKeyEvent = this._promptKeyDown.bind(this); this.prompt = new WebInspector.TextPrompt(this.promptElement, this.completions.bind(this), " .=:[({;"); this.toggleButton = document.getElementById("console-status-bar-item"); @@ -52,6 +48,11 @@ WebInspector.Console = function() this.clearButton.title = WebInspector.UIString("Clear console log."); this.clearButton.addEventListener("click", this._clearButtonClicked.bind(this), false); + this.topGroup = new WebInspector.ConsoleGroup(null, 0); + this.messagesElement.insertBefore(this.topGroup.element, this.promptElement); + this.groupLevel = 0; + this.currentGroup = this.topGroup; + document.getElementById("main-status-bar").addEventListener("mousedown", this._startStatusBarDragging.bind(this), true); } @@ -71,13 +72,7 @@ WebInspector.Console.prototype = { document.body.addStyleClass("console-visible"); var anchoredItems = document.getElementById("anchored-status-bar-items"); - // Temporally set properties and classes to mimic the post-animation values so panels - // like Elements in their updateStatusBarItems call will size things to fit the final location. - document.getElementById("main-status-bar").style.setProperty("padding-left", (anchoredItems.offsetWidth - 1) + "px"); - document.body.removeStyleClass("console-visible"); - if ("updateStatusBarItems" in WebInspector.currentPanel) - WebInspector.currentPanel.updateStatusBarItems(); - document.body.addStyleClass("console-visible"); + var animations = [ {element: document.getElementById("main"), end: {bottom: this.element.offsetHeight}}, {element: document.getElementById("main-status-bar"), start: {"padding-left": anchoredItems.offsetWidth - 1}, end: {"padding-left": 0}}, @@ -91,7 +86,7 @@ WebInspector.Console.prototype = { { if ("updateStatusBarItems" in WebInspector.currentPanel) WebInspector.currentPanel.updateStatusBarItems(); - WebInspector.currentFocusElement = this.messagesElement; + WebInspector.currentFocusElement = this.promptElement; delete this._animating; } @@ -113,12 +108,19 @@ WebInspector.Console.prototype = { this.toggleButton.removeStyleClass("toggled-on"); this.toggleButton.title = WebInspector.UIString("Show console."); - if (WebInspector.currentFocusElement === this.messagesElement) - WebInspector.currentFocusElement = this._previousFocusElement; - delete this._previousFocusElement; + if (this.element === WebInspector.currentFocusElement || this.element.isAncestor(WebInspector.currentFocusElement)) + WebInspector.currentFocusElement = WebInspector.previousFocusElement; var anchoredItems = document.getElementById("anchored-status-bar-items"); + // Temporally set properties and classes to mimic the post-animation values so panels + // like Elements in their updateStatusBarItems call will size things to fit the final location. + document.getElementById("main-status-bar").style.setProperty("padding-left", (anchoredItems.offsetWidth - 1) + "px"); + document.body.removeStyleClass("console-visible"); + if ("updateStatusBarItems" in WebInspector.currentPanel) + WebInspector.currentPanel.updateStatusBarItems(); + document.body.addStyleClass("console-visible"); + var animations = [ {element: document.getElementById("main"), end: {bottom: 0}}, {element: document.getElementById("main-status-bar"), start: {"padding-left": 0}, end: {"padding-left": anchoredItems.offsetWidth - 1}}, @@ -139,55 +141,112 @@ WebInspector.Console.prototype = { addMessage: function(msg) { - if (msg.url in WebInspector.resourceURLMap) { - msg.resource = WebInspector.resourceURLMap[msg.url]; - WebInspector.panels.resources.addMessageToResource(msg.resource, msg); - } else { - // If the resource was loaded before the inspector, we still want to - // add to the global error/warning counts. Normally, this is done - // through the resource. + if (msg instanceof WebInspector.ConsoleMessage) { + msg.totalRepeatCount = msg.repeatCount; + msg.repeatDelta = msg.repeatCount; + + var messageRepeated = false; + + if (msg.isEqual && msg.isEqual(this.previousMessage)) { + // Because sometimes we get a large number of repeated messages and sometimes + // we get them one at a time, we need to know the difference between how many + // repeats we used to have and how many we have now. + msg.repeatDelta -= this.previousMessage.totalRepeatCount; + + if (!isNaN(this.repeatCountBeforeCommand)) + msg.repeatCount -= this.repeatCountBeforeCommand; + + if (!this.commandSincePreviousMessage) { + // Recreate the previous message element to reset the repeat count. + var messagesElement = this.currentGroup.messagesElement; + messagesElement.removeChild(messagesElement.lastChild); + messagesElement.appendChild(msg.toMessageElement()); + + messageRepeated = true; + } + } else + delete this.repeatCountBeforeCommand; + + // Increment the error or warning count switch (msg.level) { - case WebInspector.ConsoleMessage.MessageLevel.Warning: - ++WebInspector.warnings; - break; - case WebInspector.ConsoleMessage.MessageLevel.Error: - ++WebInspector.errors; - break; + case WebInspector.ConsoleMessage.MessageLevel.Warning: + WebInspector.warnings += msg.repeatDelta; + break; + case WebInspector.ConsoleMessage.MessageLevel.Error: + WebInspector.errors += msg.repeatDelta; + break; + } + + // Add message to the resource panel + if (msg.url in WebInspector.resourceURLMap) { + msg.resource = WebInspector.resourceURLMap[msg.url]; + if (WebInspector.panels.resources) + WebInspector.panels.resources.addMessageToResource(msg.resource, msg); + } + + this.commandSincePreviousMessage = false; + this.previousMessage = msg; + + if (messageRepeated) + return; + } else if (msg instanceof WebInspector.ConsoleCommand) { + if (this.previousMessage) { + this.commandSincePreviousMessage = true; + this.repeatCountBeforeCommand = this.previousMessage.totalRepeatCount; } } this.messages.push(msg); - var element = msg.toMessageElement(); - this.messagesElement.insertBefore(element, this.promptElement); + if (msg.level === WebInspector.ConsoleMessage.MessageLevel.EndGroup) { + if (this.groupLevel < 1) + return; + + this.groupLevel--; + + this.currentGroup = this.currentGroup.parentGroup; + } else { + if (msg.level === WebInspector.ConsoleMessage.MessageLevel.StartGroup) { + this.groupLevel++; + + var group = new WebInspector.ConsoleGroup(this.currentGroup, this.groupLevel); + this.currentGroup.messagesElement.appendChild(group.element); + this.currentGroup = group; + } + + this.currentGroup.addMessage(msg); + } + this.promptElement.scrollIntoView(false); }, - clearMessages: function() + clearMessages: function(clearInspectorController) { - WebInspector.panels.resources.clearMessages(); + if (clearInspectorController) + InspectorController.clearMessages(); + if (WebInspector.panels.resources) + WebInspector.panels.resources.clearMessages(); this.messages = []; - while (this.messagesElement.firstChild != this.promptElement) - this.messagesElement.removeChild(this.messagesElement.firstChild); - - // Note: If the resources are loaded, panels.resources.clearMessages() - // will reset each resource's warning/error count to 0, which will in - // turn reset the global counters. But if we don't have the resources - // loaded, then this needs to be done manually here. We could do this - // only in the case of !WebInspector.panels.resources, but there are - // edge cases to handle with some resources loaded and some not, and - // since this is just a reset to 0, its safe to do it twice. - WebInspector.warnings = 0; + this.groupLevel = 0; + this.currentGroup = this.topGroup; + this.topGroup.messagesElement.removeChildren(); + WebInspector.errors = 0; + WebInspector.warnings = 0; + + delete this.commandSincePreviousMessage; + delete this.repeatCountBeforeCommand; + delete this.previousMessage; }, completions: function(wordRange, bestMatchOnly) { - // Pass less characters to scanBackwards so the range will be a more complete expression. - var expression = this.prompt.scanBackwards(" =:{;", wordRange.startContainer, wordRange.startOffset); - var expressionString = expression.toString(); + // Pass less stop characters to rangeOfWord so the range will be a more complete expression. + const expressionStopCharacters = " =:{;"; + var expressionRange = wordRange.startContainer.rangeOfWord(wordRange.startOffset, expressionStopCharacters, this.promptElement, "backward"); + var expressionString = expressionRange.toString(); var lastIndex = expressionString.length - 1; var dotNotation = (expressionString[lastIndex] === "."); @@ -200,13 +259,20 @@ WebInspector.Console.prototype = { if (!expressionString && !prefix) return; - var result = InspectorController.inspectedWindow(); + var result; if (expressionString) { try { result = this._evalInInspectedWindow(expressionString); } catch(e) { // Do nothing, the prefix will be considered a window property. } + } else { + // There is no expressionString, so the completion should happen against global properties. + // Or if the debugger is paused, against properties in scope of the selected call frame. + if (WebInspector.panels.scripts && WebInspector.panels.scripts.paused) + result = WebInspector.panels.scripts.variablesInScopeForSelectedCallFrame(); + else + result = InspectorController.inspectedWindow(); } if (bracketNotation) { @@ -220,12 +286,21 @@ WebInspector.Console.prototype = { var properties = Object.sortedProperties(result); for (var i = 0; i < properties.length; ++i) { var property = properties[i]; - if (bracketNotation) - property = quoteUsed + property.escapeCharacters(quoteUsed + "\\") + quoteUsed + "]"; + + if (dotNotation && !/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(property)) + continue; + + if (bracketNotation) { + if (!/^[0-9]+$/.test(property)) + property = quoteUsed + property.escapeCharacters(quoteUsed + "\\") + quoteUsed; + property += "]"; + } + if (property.length < prefix.length) continue; if (property.indexOf(prefix) !== 0) continue; + results.push(property); if (bestMatchOnly) break; @@ -241,7 +316,7 @@ WebInspector.Console.prototype = { _clearButtonClicked: function() { - this.clearMessages(); + this.clearMessages(true); }, _messagesSelectStart: function(event) @@ -265,15 +340,8 @@ WebInspector.Console.prototype = { _messagesClicked: function(event) { var link = event.target.enclosingNodeOrSelfWithNodeName("a"); - if (!link) { + if (!link || !link.representedNode) return; - } else if (!link.representedNode) { - // TODO(jparent): Be more user friendly here. Can we at least - // navigate to a cached view of the resource? - alert("Please load this page with the inspector open to view resources."); - event.preventDefault(); - return; - } WebInspector.updateFocusedNode(link.representedNode); event.stopPropagation(); @@ -291,13 +359,6 @@ WebInspector.Console.prototype = { this.prompt.handleKeyEvent(event); }, - _messagesFocused: function(previousFocusElement) - { - this._previousFocusElement = previousFocusElement; - if (!this.prompt.isCaretInsidePrompt()) - this.prompt.moveCaretToEndOfPrompt(); - }, - _startStatusBarDragging: function(event) { if (!this.visible || event.target !== document.getElementById("main-status-bar")) @@ -335,7 +396,39 @@ WebInspector.Console.prototype = { _evalInInspectedWindow: function(expression) { - return InspectorController.inspectedWindow().eval(expression); + if (WebInspector.panels.scripts && WebInspector.panels.scripts.paused) + return WebInspector.panels.scripts.evaluateInSelectedCallFrame(expression); + var inspectedWindow = InspectorController.inspectedWindow(); + if (!inspectedWindow._inspectorCommandLineAPI) { + inspectedWindow.eval("window._inspectorCommandLineAPI = { \ + $: function() { return document.getElementById.apply(document, arguments) }, \ + $$: function() { return document.querySelectorAll.apply(document, arguments) }, \ + $x: function(xpath, context) { \ + var nodes = []; \ + try { \ + var doc = context || document; \ + var results = doc.evaluate(xpath, doc, null, XPathResult.ANY_TYPE, null); \ + var node; \ + while (node = results.iterateNext()) nodes.push(node); \ + } catch (e) {} \ + return nodes; \ + }, \ + dir: function() { return console.dir.apply(console, arguments) }, \ + dirxml: function() { return console.dirxml.apply(console, arguments) }, \ + keys: function(o) { var a = []; for (k in o) a.push(k); return a; }, \ + values: function(o) { var a = []; for (k in o) a.push(o[k]); return a; }, \ + profile: function() { return console.profile.apply(console, arguments) }, \ + profileEnd: function() { return console.profileEnd.apply(console, arguments) } \ + };"); + + inspectedWindow._inspectorCommandLineAPI.clear = InspectorController.wrapCallback(this.clearMessages.bind(this)); + } + + // Surround the expression in with statements to inject our command line API so that + // the window object properties still take more precedent than our API functions. + expression = "with (window._inspectorCommandLineAPI) { with (window) { " + expression + " } }"; + + return inspectedWindow.eval(expression); }, _enterKeyPressed: function(event) @@ -369,7 +462,21 @@ WebInspector.Console.prototype = { this.addMessage(new WebInspector.ConsoleCommand(str, result, this._format(result), level)); }, - _format: function(output, plaintext) + _mouseOverNode: function(event) + { + var anchorElement = event.target.enclosingNodeOrSelfWithNodeName("a"); + WebInspector.hoveredDOMNode = (anchorElement ? anchorElement.representedNode : null); + }, + + _mouseOutOfNode: function(event) + { + var nodeUnderMouse = document.elementFromPoint(event.pageX, event.pageY); + var anchorElement = nodeUnderMouse.enclosingNodeOrSelfWithNodeName("a"); + if (!anchorElement || !anchorElement.representedNode) + WebInspector.hoveredDOMNode = null; + }, + + _format: function(output, inline) { var type = Object.type(output, InspectorController.inspectedWindow()); if (type === "object") { @@ -401,53 +508,61 @@ WebInspector.Console.prototype = { var span = document.createElement("span"); span.addStyleClass("console-formatted-" + type); - this[formatter](output, span, plaintext); + this[formatter](output, span, inline); return span; }, - _formatvalue: function(val, elem, plaintext) + _formatvalue: function(val, elem, inline) { elem.appendChild(document.createTextNode(val)); }, - _formatstring: function(str, elem, plaintext) + _formatstring: function(str, elem, inline) { elem.appendChild(document.createTextNode("\"" + str + "\"")); }, - _formatregexp: function(re, elem, plaintext) + _formatregexp: function(re, elem, inline) { var formatted = String(re).replace(/([\\\/])/g, "\\$1").replace(/\\(\/[gim]*)$/, "$1").substring(1); elem.appendChild(document.createTextNode(formatted)); }, - _formatarray: function(arr, elem, plaintext) + _formatarray: function(arr, elem, inline) { elem.appendChild(document.createTextNode("[")); for (var i = 0; i < arr.length; ++i) { - elem.appendChild(this._format(arr[i])); + elem.appendChild(this._format(arr[i], true)); if (i < arr.length - 1) elem.appendChild(document.createTextNode(", ")); } elem.appendChild(document.createTextNode("]")); }, - _formatnode: function(node, elem, plaintext) + _formatnode: function(node, elem, inline) { var anchor = document.createElement("a"); + anchor.className = "inspectible-node"; anchor.innerHTML = nodeTitleInfo.call(node).title; anchor.representedNode = node; - anchor.addEventListener("mouseover", function() { WebInspector.highlightDOMNode(node) }, false); - anchor.addEventListener("mouseout", function() { WebInspector.hideDOMNodeHighlight() }, false); - elem.appendChild(anchor); + anchor.addEventListener("mouseover", this._mouseOverNode.bind(this), false); + anchor.addEventListener("mouseout", this._mouseOutOfNode.bind(this), false); + + if (inline) + elem.appendChild(anchor); + else + elem.appendChild(new WebInspector.ObjectPropertiesSection(node, anchor, null, null, true).element); }, - _formatobject: function(obj, elem, plaintext) + _formatobject: function(obj, elem, inline) { - elem.appendChild(document.createTextNode(Object.describe(obj))); + if (inline) + elem.appendChild(document.createTextNode(Object.describe(obj))); + else + elem.appendChild(new WebInspector.ObjectPropertiesSection(obj, null, null, null, true).element); }, - _formaterror: function(obj, elem, plaintext) + _formaterror: function(obj, elem, inline) { elem.appendChild(document.createTextNode(obj.name + ": " + obj.message + " ")); @@ -456,6 +571,7 @@ WebInspector.Console.prototype = { urlElement.className = "console-message-url webkit-html-resource-link"; urlElement.href = obj.sourceURL; urlElement.lineNumber = obj.line; + urlElement.preferredPanel = "scripts"; if (obj.line > 0) urlElement.textContent = WebInspector.UIString("%s (line %d)", obj.sourceURL, obj.line); @@ -469,32 +585,64 @@ WebInspector.Console.prototype = { WebInspector.Console.prototype.__proto__ = WebInspector.View.prototype; -WebInspector.ConsoleMessage = function(source, level, line, url) +WebInspector.ConsoleMessage = function(source, level, line, url, groupLevel, repeatCount) { this.source = source; this.level = level; this.line = line; this.url = url; - - // This _format call passes in true for the plainText argument. The result's textContent is - // used for inline message bubbles in SourceFrames, or other plain-text representations. - this.message = this._format(Array.prototype.slice.call(arguments, 4), true).textContent; - - // The formatedMessage property is used for the rich and interactive console. - this.formattedMessage = this._format(Array.prototype.slice.call(arguments, 4), false); + this.groupLevel = groupLevel; + this.repeatCount = repeatCount; + + switch (this.level) { + case WebInspector.ConsoleMessage.MessageLevel.Object: + var propertiesSection = new WebInspector.ObjectPropertiesSection(arguments[6], null, null, null, true); + propertiesSection.element.addStyleClass("console-message"); + this.propertiesSection = propertiesSection; + break; + case WebInspector.ConsoleMessage.MessageLevel.Node: + var node = arguments[6]; + if (!(node instanceof InspectorController.inspectedWindow().Node)) + return; + this.elementsTreeOutline = new WebInspector.ElementsTreeOutline(); + this.elementsTreeOutline.rootDOMNode = node; + break; + case WebInspector.ConsoleMessage.MessageLevel.Trace: + var span = document.createElement("span"); + span.addStyleClass("console-formatted-trace"); + var stack = Array.prototype.slice.call(arguments, 6); + var funcNames = stack.map(function(f) { + return f || WebInspector.UIString("(anonymous function)"); + }); + span.appendChild(document.createTextNode(funcNames.join("\n"))); + this.formattedMessage = span; + break; + default: + // The formatedMessage property is used for the rich and interactive console. + this.formattedMessage = this._format(Array.prototype.slice.call(arguments, 6)); + + // This is used for inline message bubbles in SourceFrames, or other plain-text representations. + this.message = this.formattedMessage.textContent; + break; + } } WebInspector.ConsoleMessage.prototype = { - _format: function(parameters, plaintext) + isErrorOrWarning: function() + { + return (this.level === WebInspector.ConsoleMessage.MessageLevel.Warning || this.level === WebInspector.ConsoleMessage.MessageLevel.Error); + }, + + _format: function(parameters) { - var formattedResult = document.createElement("span"); + var formattedResult = document.createElement("span"); if (!parameters.length) return formattedResult; - + function formatForConsole(obj) { - return WebInspector.console._format(obj, plainText); + return WebInspector.console._format(obj, true); } if (Object.type(parameters[0], InspectorController.inspectedWindow()) === "string") { @@ -510,36 +658,38 @@ WebInspector.ConsoleMessage.prototype = { function append(a, b) { if (!(b instanceof Node)) - b = document.createTextNode(b); - - a.appendChild(b); + a.appendChild(WebInspector.linkifyStringAsFragment(b.toString())); + else + a.appendChild(b); return a; } - var result = String.format(parameters[0], parameters.slice(1), formatters, formattedResult, append); + var result = String.format(parameters[0], parameters.slice(1), formatters, formattedResult, append); formattedResult = result.formattedResult; parameters = result.unusedSubstitutions; if (parameters.length) - formattedResult.appendChild(document.createTextNode(" ")); + formattedResult.appendChild(document.createTextNode(" ")); } for (var i = 0; i < parameters.length; ++i) { - formattedResult.appendChild(formatForConsole(parameters[i])); + if (typeof parameters[i] === "string") + formattedResult.appendChild(WebInspector.linkifyStringAsFragment(parameters[i])); + else if (parameters.length === 1) + formattedResult.appendChild(WebInspector.console._format(parameters[0])); + else + formattedResult.appendChild(formatForConsole(parameters[i])); if (i < parameters.length - 1) - formattedResult.appendChild(document.createTextNode(" ")); + formattedResult.appendChild(document.createTextNode(" ")); } - return formattedResult; - }, - get shortURL() - { - if (this.resource) - return this.resource.displayName; - return this.url; + return formattedResult; }, toMessageElement: function() { + if (this.propertiesSection) + return this.propertiesSection.element; + var element = document.createElement("div"); element.message = this; element.className = "console-message"; @@ -548,6 +698,9 @@ WebInspector.ConsoleMessage.prototype = { case WebInspector.ConsoleMessage.MessageSource.HTML: element.addStyleClass("console-html-source"); break; + case WebInspector.ConsoleMessage.MessageSource.WML: + element.addStyleClass("console-wml-source"); + break; case WebInspector.ConsoleMessage.MessageSource.XML: element.addStyleClass("console-xml-source"); break; @@ -574,14 +727,25 @@ WebInspector.ConsoleMessage.prototype = { break; case WebInspector.ConsoleMessage.MessageLevel.Error: element.addStyleClass("console-error-level"); + break; + case WebInspector.ConsoleMessage.MessageLevel.StartGroup: + element.addStyleClass("console-group-title-level"); } - var messageTextElement = document.createElement("span"); - messageTextElement.className = "console-message-text"; - messageTextElement.appendChild(this.formattedMessage); - element.appendChild(messageTextElement); + if (this.elementsTreeOutline) { + element.addStyleClass("outline-disclosure"); + element.appendChild(this.elementsTreeOutline.element); + return element; + } - element.appendChild(document.createTextNode(" ")); + if (this.repeatCount > 1) { + var messageRepeatCountElement = document.createElement("span"); + messageRepeatCountElement.className = "bubble"; + messageRepeatCountElement.textContent = this.repeatCount; + + element.appendChild(messageRepeatCountElement); + element.addStyleClass("repeated-message"); + } if (this.url && this.url !== "undefined") { var urlElement = document.createElement("a"); @@ -589,14 +753,22 @@ WebInspector.ConsoleMessage.prototype = { urlElement.href = this.url; urlElement.lineNumber = this.line; + if (this.source === WebInspector.ConsoleMessage.MessageSource.JS) + urlElement.preferredPanel = "scripts"; + if (this.line > 0) - urlElement.textContent = WebInspector.UIString("%s (line %d)", this.url, this.line); + urlElement.textContent = WebInspector.UIString("%s (line %d)", WebInspector.displayNameForURL(this.url), this.line); else - urlElement.textContent = this.url; + urlElement.textContent = WebInspector.displayNameForURL(this.url); element.appendChild(urlElement); } + var messageTextElement = document.createElement("span"); + messageTextElement.className = "console-message-text"; + messageTextElement.appendChild(this.formattedMessage); + element.appendChild(messageTextElement); + return element; }, @@ -607,6 +779,9 @@ WebInspector.ConsoleMessage.prototype = { case WebInspector.ConsoleMessage.MessageSource.HTML: sourceString = "HTML"; break; + case WebInspector.ConsoleMessage.MessageSource.WML: + sourceString = "WML"; + break; case WebInspector.ConsoleMessage.MessageSource.XML: sourceString = "XML"; break; @@ -635,26 +810,52 @@ WebInspector.ConsoleMessage.prototype = { case WebInspector.ConsoleMessage.MessageLevel.Error: levelString = "Error"; break; + case WebInspector.ConsoleMessage.MessageLevel.Object: + levelString = "Object"; + break; + case WebInspector.ConsoleMessage.MessageLevel.GroupTitle: + levelString = "GroupTitle"; + break; } return sourceString + " " + levelString + ": " + this.formattedMessage.textContent + "\n" + this.url + " line " + this.line; + }, + + isEqual: function(msg, disreguardGroup) + { + if (!msg) + return false; + + var ret = (this.source == msg.source) + && (this.level == msg.level) + && (this.line == msg.line) + && (this.url == msg.url) + && (this.message == msg.message); + + return (disreguardGroup ? ret : (ret && (this.groupLevel == msg.groupLevel))); } } -// Note: Keep these constants in sync with the ones in Chrome.h +// Note: Keep these constants in sync with the ones in Console.h WebInspector.ConsoleMessage.MessageSource = { HTML: 0, - XML: 1, - JS: 2, - CSS: 3, - Other: 4, + WML: 1, + XML: 2, + JS: 3, + CSS: 4, + Other: 5 } WebInspector.ConsoleMessage.MessageLevel = { Tip: 0, Log: 1, Warning: 2, - Error: 3 + Error: 3, + Object: 4, + Node: 5, + Trace: 6, + StartGroup: 7, + EndGroup: 8 } WebInspector.ConsoleCommand = function(command, result, formattedResultElement, level) @@ -699,3 +900,49 @@ WebInspector.ConsoleCommand.prototype = { return element; } } + +WebInspector.ConsoleGroup = function(parentGroup, level) +{ + this.parentGroup = parentGroup; + this.level = level; + + var element = document.createElement("div"); + element.className = "console-group"; + element.group = this; + this.element = element; + + var messagesElement = document.createElement("div"); + messagesElement.className = "console-group-messages"; + element.appendChild(messagesElement); + this.messagesElement = messagesElement; +} + +WebInspector.ConsoleGroup.prototype = { + addMessage: function(msg) + { + var element = msg.toMessageElement(); + + if (msg.level === WebInspector.ConsoleMessage.MessageLevel.StartGroup) { + this.messagesElement.parentNode.insertBefore(element, this.messagesElement); + element.addEventListener("click", this._titleClicked.bind(this), true); + } else + this.messagesElement.appendChild(element); + }, + + _titleClicked: function(event) + { + var groupTitleElement = event.target.enclosingNodeOrSelfWithClass("console-group-title-level"); + if (groupTitleElement) { + var groupElement = groupTitleElement.enclosingNodeOrSelfWithClass("console-group"); + if (groupElement) + if (groupElement.hasStyleClass("collapsed")) + groupElement.removeStyleClass("collapsed"); + else + groupElement.addStyleClass("collapsed"); + groupTitleElement.scrollIntoViewIfNeeded(true); + } + + event.stopPropagation(); + event.preventDefault(); + } +} diff --git a/chrome/tools/test/reference_build/chrome/resources/Inspector/DatabaseQueryView.js b/chrome/tools/test/reference_build/chrome/resources/Inspector/DatabaseQueryView.js index c5792af..122707f 100644 --- a/chrome/tools/test/reference_build/chrome/resources/Inspector/DatabaseQueryView.js +++ b/chrome/tools/test/reference_build/chrome/resources/Inspector/DatabaseQueryView.js @@ -29,17 +29,16 @@ WebInspector.DatabaseQueryView = function(database) this.database = database; - this.element.addStyleClass("database-view"); + this.element.addStyleClass("storage-view"); this.element.addStyleClass("query"); - this.element.addStyleClass("focusable"); + this.element.tabIndex = 0; this.element.addEventListener("selectstart", this._selectStart.bind(this), false); - this.element.focused = this._focused.bind(this); - this.element.handleKeyEvent = this._promptKeyDown.bind(this); this.promptElement = document.createElement("div"); this.promptElement.className = "database-query-prompt"; this.promptElement.appendChild(document.createElement("br")); + this.promptElement.handleKeyEvent = this._promptKeyDown.bind(this); this.element.appendChild(this.promptElement); this.prompt = new WebInspector.TextPrompt(this.promptElement, this.completions.bind(this), " "); @@ -100,13 +99,6 @@ WebInspector.DatabaseQueryView.prototype = { this.prompt.handleKeyEvent(event); }, - _focused: function(previousFocusElement) - { - this._previousFocusElement = previousFocusElement; - if (!this.prompt.isCaretInsidePrompt()) - this.prompt.moveCaretToEndOfPrompt(); - }, - _selectStart: function(event) { if (this._selectionTimeout) @@ -142,7 +134,7 @@ WebInspector.DatabaseQueryView.prototype = { function queryTransaction(tx) { - tx.executeSql(query, null, InspectorController.wrapCallback(this._queryFinished.bind(this, query)), InspectorController.wrapCallback(this._queryError.bind(this, query))); + tx.executeSql(query, null, InspectorController.wrapCallback(this._queryFinished.bind(this, query)), InspectorController.wrapCallback(this._executeSqlError.bind(this, query))); } this.database.database.transaction(InspectorController.wrapCallback(queryTransaction.bind(this)), InspectorController.wrapCallback(this._queryError.bind(this, query))); @@ -150,13 +142,15 @@ WebInspector.DatabaseQueryView.prototype = { _queryFinished: function(query, tx, result) { - this._appendQueryResult(query, WebInspector.panels.databases._tableForResult(result)); + var dataGrid = WebInspector.panels.databases.dataGridForResult(result); + dataGrid.element.addStyleClass("inline"); + this._appendQueryResult(query, dataGrid.element); if (query.match(/^create /i) || query.match(/^drop table /i)) WebInspector.panels.databases.updateDatabaseTables(this.database); }, - _queryError: function(query, tx, error) + _queryError: function(query, error) { if (error.code == 1) var message = error.message; @@ -168,6 +162,11 @@ WebInspector.DatabaseQueryView.prototype = { this._appendQueryResult(query, message, "error"); }, + _executeSqlError: function(query, tx, error) + { + this._queryError(query, error); + }, + _appendQueryResult: function(query, result, resultClassName) { var element = document.createElement("div"); diff --git a/chrome/tools/test/reference_build/chrome/resources/Inspector/DatabaseTableView.js b/chrome/tools/test/reference_build/chrome/resources/Inspector/DatabaseTableView.js index ccf7590..5d2bb88 100644 --- a/chrome/tools/test/reference_build/chrome/resources/Inspector/DatabaseTableView.js +++ b/chrome/tools/test/reference_build/chrome/resources/Inspector/DatabaseTableView.js @@ -30,7 +30,7 @@ WebInspector.DatabaseTableView = function(database, tableName) this.database = database; this.tableName = tableName; - this.element.addStyleClass("database-view"); + this.element.addStyleClass("storage-view"); this.element.addStyleClass("table"); } @@ -55,31 +55,16 @@ WebInspector.DatabaseTableView.prototype = { { this.element.removeChildren(); - var table = WebInspector.panels.databases._tableForResult(result); - if (!table) { + var dataGrid = WebInspector.panels.databases.dataGridForResult(result); + if (!dataGrid) { var emptyMsgElement = document.createElement("div"); - emptyMsgElement.className = "database-table-empty"; + emptyMsgElement.className = "storage-table-empty"; emptyMsgElement.textContent = WebInspector.UIString("The “%s”\ntable is empty.", this.tableName); this.element.appendChild(emptyMsgElement); return; } - var rowCount = table.getElementsByTagName("tr").length; - var columnCount = table.getElementsByTagName("tr").item(0).getElementsByTagName("th").length; - - var tr = document.createElement("tr"); - tr.className = "database-result-filler-row"; - table.appendChild(tr); - - if (!(rowCount % 2)) - tr.addStyleClass("alternate"); - - for (var i = 0; i < columnCount; ++i) { - var td = document.createElement("td"); - tr.appendChild(td); - } - - this.element.appendChild(table); + this.element.appendChild(dataGrid.element); }, _queryError: function(tx, error) @@ -87,7 +72,7 @@ WebInspector.DatabaseTableView.prototype = { this.element.removeChildren(); var errorMsgElement = document.createElement("div"); - errorMsgElement.className = "database-table-error"; + errorMsgElement.className = "storage-table-error"; errorMsgElement.textContent = WebInspector.UIString("An error occurred trying to\nread the “%s” table.", this.tableName); this.element.appendChild(errorMsgElement); }, diff --git a/chrome/tools/test/reference_build/chrome/resources/Inspector/DatabasesPanel.js b/chrome/tools/test/reference_build/chrome/resources/Inspector/DatabasesPanel.js index 79adab0..bafa54a 100644 --- a/chrome/tools/test/reference_build/chrome/resources/Inspector/DatabasesPanel.js +++ b/chrome/tools/test/reference_build/chrome/resources/Inspector/DatabasesPanel.js @@ -46,9 +46,21 @@ WebInspector.DatabasesPanel = function(database) this.sidebarTree = new TreeOutline(this.sidebarTreeElement); - this.databaseViews = document.createElement("div"); - this.databaseViews.id = "database-views"; - this.element.appendChild(this.databaseViews); + this.databasesListTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("DATABASES"), {}, true); + this.sidebarTree.appendChild(this.databasesListTreeElement); + this.databasesListTreeElement.expand(); + + this.localStorageListTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("LOCAL STORAGE"), {}, true); + this.sidebarTree.appendChild(this.localStorageListTreeElement); + this.localStorageListTreeElement.expand(); + + this.sessionStorageListTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("SESSION STORAGE"), {}, true); + this.sidebarTree.appendChild(this.sessionStorageListTreeElement); + this.sessionStorageListTreeElement.expand(); + + this.storageViews = document.createElement("div"); + this.storageViews.id = "storage-views"; + this.element.appendChild(this.storageViews); this.reset(); } @@ -81,8 +93,21 @@ WebInspector.DatabasesPanel.prototype = { this._databases = []; - this.sidebarTree.removeChildren(); - this.databaseViews.removeChildren(); + if (this._domStorage) { + var domStorageLength = this._domStorage.length; + for (var i = 0; i < domStorageLength; ++i) { + var domStorage = this._domStorage[i]; + + delete domStorage._domStorageView; + } + } + + this._domStorage = []; + + this.databasesListTreeElement.removeChildren(); + this.localStorageListTreeElement.removeChildren(); + this.sessionStorageListTreeElement.removeChildren(); + this.storageViews.removeChildren(); }, handleKeyEvent: function(event) @@ -96,8 +121,18 @@ WebInspector.DatabasesPanel.prototype = { var databaseTreeElement = new WebInspector.DatabaseSidebarTreeElement(database); database._databasesTreeElement = databaseTreeElement; + this.databasesListTreeElement.appendChild(databaseTreeElement); + }, - this.sidebarTree.appendChild(databaseTreeElement); + addDOMStorage: function(domStorage) + { + this._domStorage.push(domStorage); + var domStorageTreeElement = new WebInspector.DOMStorageSidebarTreeElement(domStorage); + domStorage._domStorageTreeElement = domStorageTreeElement; + if (domStorage.isLocalStorage) + this.localStorageListTreeElement.appendChild(domStorageTreeElement); + else + this.sessionStorageListTreeElement.appendChild(domStorageTreeElement); }, showDatabase: function(database, tableName) @@ -105,8 +140,8 @@ WebInspector.DatabasesPanel.prototype = { if (!database) return; - if (this.visibleDatabaseView) - this.visibleDatabaseView.hide(); + if (this.visibleView) + this.visibleView.hide(); var view; if (tableName) { @@ -125,16 +160,36 @@ WebInspector.DatabasesPanel.prototype = { } } - view.show(this.databaseViews); + view.show(this.storageViews); - this.visibleDatabaseView = view; + this.visibleView = view; + }, + + showDOMStorage: function(domStorage) + { + if (!domStorage) + return; + + if (this.visibleView) + this.visibleView.hide(); + + var view; + view = domStorage._domStorageView; + if (!view) { + view = new WebInspector.DOMStorageItemsView(domStorage); + domStorage._domStorageView = view; + } + + view.show(this.storageViews); + + this.visibleView = view; }, closeVisibleView: function() { - if (this.visibleDatabaseView) - this.visibleDatabaseView.hide(); - delete this.visibleDatabaseView; + if (this.visibleView) + this.visibleView.hide(); + delete this.visibleView; }, updateDatabaseTables: function(database) @@ -155,86 +210,73 @@ WebInspector.DatabasesPanel.prototype = { for (var tableName in database._tableViews) { if (!(tableName in tableNamesHash)) { - if (this.visibleDatabaseView === database._tableViews[tableName]) + if (this.visibleView === database._tableViews[tableName]) this.closeVisibleView(); delete database._tableViews[tableName]; } } }, - _tableForResult: function(result) + dataGridForResult: function(result) { if (!result.rows.length) return null; - var rows = result.rows; - var length = rows.length; - var columnWidths = []; - - var table = document.createElement("table"); - table.className = "database-result-table"; - - var headerRow = document.createElement("tr"); - table.appendChild(headerRow); + var columns = {}; - var j = 0; - for (var column in rows.item(0)) { - var th = document.createElement("th"); - headerRow.appendChild(th); - - var div = document.createElement("div"); - div.textContent = column; - div.title = column; - th.appendChild(div); + var rows = result.rows; + for (var columnIdentifier in rows.item(0)) { + var column = {}; + column.width = columnIdentifier.length; + column.title = columnIdentifier; - columnWidths[j++] = column.length; + columns[columnIdentifier] = column; } + var nodes = []; + var length = rows.length; for (var i = 0; i < length; ++i) { + var data = {}; + var row = rows.item(i); - var tr = document.createElement("tr"); - if (i % 2) - tr.className = "alternate"; - table.appendChild(tr); - - var j = 0; - for (var column in row) { - var td = document.createElement("td"); - tr.appendChild(td); - - var text = row[column]; - var div = document.createElement("div"); - div.textContent = text; - div.title = text; - td.appendChild(div); - - if (text.length > columnWidths[j]) - columnWidths[j] = text.length; - ++j; + for (var columnIdentifier in row) { + // FIXME: (Bug 19439) We should specially format SQL NULL here + // (which is represented by JavaScript null here, and turned + // into the string "null" by the String() function). + var text = String(row[columnIdentifier]); + data[columnIdentifier] = text; + if (text.length > columns[columnIdentifier].width) + columns[columnIdentifier].width = text.length; } + + var node = new WebInspector.DataGridNode(data, false); + node.selectable = false; + nodes.push(node); } var totalColumnWidths = 0; - length = columnWidths.length; - for (var i = 0; i < length; ++i) - totalColumnWidths += columnWidths[i]; + for (var columnIdentifier in columns) + totalColumnWidths += columns[columnIdentifier].width; // Calculate the percentage width for the columns. - var minimumPrecent = 5; + const minimumPrecent = 5; var recoupPercent = 0; - for (var i = 0; i < length; ++i) { - columnWidths[i] = Math.round((columnWidths[i] / totalColumnWidths) * 100); - if (columnWidths[i] < minimumPrecent) { - recoupPercent += (minimumPrecent - columnWidths[i]); - columnWidths[i] = minimumPrecent; + for (var columnIdentifier in columns) { + var width = columns[columnIdentifier].width; + width = Math.round((width / totalColumnWidths) * 100); + if (width < minimumPrecent) { + recoupPercent += (minimumPrecent - width); + width = minimumPrecent; } + + columns[columnIdentifier].width = width; } // Enforce the minimum percentage width. while (recoupPercent > 0) { - for (var i = 0; i < length; ++i) { - if (columnWidths[i] > minimumPrecent) { - --columnWidths[i]; + for (var columnIdentifier in columns) { + if (columns[columnIdentifier].width > minimumPrecent) { + --columns[columnIdentifier].width; --recoupPercent; if (!recoupPercent) break; @@ -242,13 +284,69 @@ WebInspector.DatabasesPanel.prototype = { } } - length = headerRow.childNodes.length; - for (var i = 0; i < length; ++i) { - var th = headerRow.childNodes[i]; - th.style.width = columnWidths[i] + "%"; + // Change the width property to a string suitable for a style width. + for (var columnIdentifier in columns) + columns[columnIdentifier].width += "%"; + + var dataGrid = new WebInspector.DataGrid(columns); + var length = nodes.length; + for (var i = 0; i < length; ++i) + dataGrid.appendChild(nodes[i]); + + return dataGrid; + }, + + dataGridForDOMStorage: function(domStorage) + { + if (!domStorage.length) + return null; + + var columns = {}; + columns[0] = {}; + columns[1] = {}; + columns[0].title = WebInspector.UIString("Key"); + columns[0].width = columns[0].title.length; + columns[1].title = WebInspector.UIString("Value"); + columns[1].width = columns[0].title.length; + + var nodes = []; + + var length = domStorage.length; + for (index = 0; index < domStorage.length; index++) { + var data = {}; + + var key = String(domStorage.key(index)); + data[0] = key; + if (key.length > columns[0].width) + columns[0].width = key.length; + + var value = String(domStorage.getItem(key)); + data[1] = value; + if (value.length > columns[1].width) + columns[1].width = value.length; + var node = new WebInspector.DataGridNode(data, false); + node.selectable = false; + nodes.push(node); } - return table; + var totalColumnWidths = columns[0].width + columns[1].width; + width = Math.round((columns[0].width * 100) / totalColumnWidths); + const minimumPrecent = 10; + if (width < minimumPrecent) + width = minimumPrecent; + if (width > 100 - minimumPrecent) + width = 100 - minimumPrecent; + columns[0].width = width; + columns[1].width = 100 - width; + columns[0].width += "%"; + columns[1].width += "%"; + + var dataGrid = new WebInspector.DataGrid(columns); + var length = nodes.length; + for (var i = 0; i < length; ++i) + dataGrid.appendChild(nodes[i]); + + return dataGrid; }, _startSidebarDragging: function(event) @@ -271,8 +369,8 @@ WebInspector.DatabasesPanel.prototype = { _updateSidebarWidth: function(width) { if (this.sidebarElement.offsetWidth <= 0) { - // The stylesheet hasn't loaded yet, so we need to update later. - setTimeout(this._updateSidebarWidth.bind(this), 0, width); + // The stylesheet hasn't loaded yet or the window is closed, + // so we can't calculate what is need. Return early. return; } @@ -287,7 +385,7 @@ WebInspector.DatabasesPanel.prototype = { this._currentSidebarWidth = width; this.sidebarElement.style.width = width + "px"; - this.databaseViews.style.left = width + "px"; + this.storageViews.style.left = width + "px"; this.sidebarResizeElement.style.left = (width - 3) + "px"; } } @@ -365,3 +463,42 @@ WebInspector.SidebarDatabaseTableTreeElement.prototype = { } WebInspector.SidebarDatabaseTableTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype; + +WebInspector.DOMStorageSidebarTreeElement = function(domStorage) +{ + + this.domStorage = domStorage; + + WebInspector.SidebarTreeElement.call(this, "domstorage-sidebar-tree-item", domStorage, "", null, false); + + this.refreshTitles(); +} + +WebInspector.DOMStorageSidebarTreeElement.prototype = { + onselect: function() + { + WebInspector.panels.databases.showDOMStorage(this.domStorage); + }, + + get mainTitle() + { + return this.domStorage.domain; + }, + + set mainTitle(x) + { + // Do nothing. + }, + + get subtitle() + { + return ""; //this.database.displayDomain; + }, + + set subtitle(x) + { + // Do nothing. + } +} + +WebInspector.DOMStorageSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype; diff --git a/chrome/tools/test/reference_build/chrome/resources/Inspector/ElementsPanel.js b/chrome/tools/test/reference_build/chrome/resources/Inspector/ElementsPanel.js index 6a5978a..3c9be54 100644 --- a/chrome/tools/test/reference_build/chrome/resources/Inspector/ElementsPanel.js +++ b/chrome/tools/test/reference_build/chrome/resources/Inspector/ElementsPanel.js @@ -1,5 +1,6 @@ /* * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -36,29 +37,37 @@ WebInspector.ElementsPanel = function() this.contentElement.id = "elements-content"; this.contentElement.className = "outline-disclosure"; - function clearNodeHighlight(event) + this.treeOutline = new WebInspector.ElementsTreeOutline(); + this.treeOutline.panel = this; + this.treeOutline.includeRootDOMNode = false; + this.treeOutline.selectEnabled = true; + + this.treeOutline.focusedNodeChanged = function(forceUpdate) { - if (!event.relatedTarget || - !this.contentElement.isAncestor(event.relatedTarget) && - !this.crumbsElement.isAncestor(event.relatedTarget)) { - WebInspector.hideDOMNodeHighlight(); - } - } + if (this.panel.visible && WebInspector.currentFocusElement !== document.getElementById("search")) + WebInspector.currentFocusElement = document.getElementById("main-panels"); - this.treeListElement = document.createElement("ol"); - this.treeListElement.addEventListener("mousedown", this._onmousedown.bind(this), false); - this.treeListElement.addEventListener("dblclick", this._ondblclick.bind(this), false); - this.treeListElement.addEventListener("mousemove", this._onmousemove.bind(this), false); - this.treeListElement.addEventListener("mouseout", clearNodeHighlight.bind(this), false); + this.panel.updateBreadcrumb(forceUpdate); - this.treeOutline = new TreeOutline(this.treeListElement); - this.treeOutline.panel = this; + for (var pane in this.panel.sidebarPanes) + this.panel.sidebarPanes[pane].needsUpdate = true; - this.contentElement.appendChild(this.treeListElement); + this.panel.updateStyles(true); + this.panel.updateMetrics(); + this.panel.updateProperties(); + + if (InspectorController.searchingForNode()) { + InspectorController.toggleNodeSearch(); + this.panel.nodeSearchButton.removeStyleClass("toggled-on"); + } + }; + + this.contentElement.appendChild(this.treeOutline.element); this.crumbsElement = document.createElement("div"); this.crumbsElement.className = "crumbs"; - this.crumbsElement.addEventListener("mouseout", clearNodeHighlight.bind(this), false); + this.crumbsElement.addEventListener("mousemove", this._mouseMovedInCrumbs.bind(this), false); + this.crumbsElement.addEventListener("mouseout", this._mouseMovedOutOfCrumbs.bind(this), false); this.sidebarPanes = {}; this.sidebarPanes.styles = new WebInspector.StylesSidebarPane(); @@ -71,6 +80,10 @@ WebInspector.ElementsPanel = function() this.sidebarPanes.styles.expanded = true; + this.sidebarPanes.styles.addEventListener("style edited", this._stylesPaneEdited, this); + this.sidebarPanes.styles.addEventListener("style property toggled", this._stylesPaneEdited, this); + this.sidebarPanes.metrics.addEventListener("metrics edited", this._metricsPaneEdited, this); + this.sidebarElement = document.createElement("div"); this.sidebarElement.id = "elements-sidebar"; @@ -82,10 +95,23 @@ WebInspector.ElementsPanel = function() this.sidebarResizeElement.className = "sidebar-resizer-vertical"; this.sidebarResizeElement.addEventListener("mousedown", this.rightSidebarResizerDragStart.bind(this), false); + this.nodeSearchButton = document.createElement("button"); + this.nodeSearchButton.title = WebInspector.UIString("Select an element in the page to inspect it."); + this.nodeSearchButton.id = "node-search-status-bar-item"; + this.nodeSearchButton.className = "status-bar-item"; + this.nodeSearchButton.addEventListener("click", this._nodeSearchButtonClicked.bind(this), false); + + this.searchingForNode = false; + this.element.appendChild(this.contentElement); this.element.appendChild(this.sidebarElement); this.element.appendChild(this.sidebarResizeElement); + this._mutationMonitoredWindows = []; + this._nodeInsertedEventListener = InspectorController.wrapCallback(this._nodeInserted.bind(this)); + this._nodeRemovedEventListener = InspectorController.wrapCallback(this._nodeRemoved.bind(this)); + this._contentLoadedEventListener = InspectorController.wrapCallback(this._contentLoaded.bind(this)); + this.reset(); } @@ -99,7 +125,7 @@ WebInspector.ElementsPanel.prototype = { get statusBarItems() { - return [this.crumbsElement]; + return [this.nodeSearchButton, this.crumbsElement]; }, updateStatusBarItems: function() @@ -112,18 +138,26 @@ WebInspector.ElementsPanel.prototype = { WebInspector.Panel.prototype.show.call(this); this.sidebarResizeElement.style.right = (this.sidebarElement.offsetWidth - 3) + "px"; this.updateBreadcrumb(); - this.updateTreeSelection(); + this.treeOutline.updateSelection(); + if (this.recentlyModifiedNodes.length) + this._updateModifiedNodes(); }, hide: function() { WebInspector.Panel.prototype.hide.call(this); - WebInspector.hideDOMNodeHighlight(); + + WebInspector.hoveredDOMNode = null; + + if (InspectorController.searchingForNode()) { + InspectorController.toggleNodeSearch(); + this.nodeSearchButton.removeStyleClass("toggled-on"); + } }, resize: function() { - this.updateTreeSelection(); + this.treeOutline.updateSelection(); this.updateBreadcrumbSizes(); }, @@ -132,140 +166,521 @@ WebInspector.ElementsPanel.prototype = { this.rootDOMNode = null; this.focusedDOMNode = null; + WebInspector.hoveredDOMNode = null; + + if (InspectorController.searchingForNode()) { + InspectorController.toggleNodeSearch(); + this.nodeSearchButton.removeStyleClass("toggled-on"); + } + + this.recentlyModifiedNodes = []; + this.unregisterAllMutationEventListeners(); + + delete this.currentQuery; + this.searchCanceled(); + var inspectedWindow = InspectorController.inspectedWindow(); if (!inspectedWindow || !inspectedWindow.document) return; if (!inspectedWindow.document.firstChild) { - // FIXME: This whole if block can be simplified once we can add an event listener to - // the inspected page and have it get called in the Inspector's context. - - var elementsPanel = this; - /* We don't implement wrapCallback yet (if ever) - var contentLoaded = InspectorController.wrapCallback(function() - { - // This function will be called in the inspected page's context. - elementsPanel._domContentLoaded = true; - }); - */ - var contentLoaded = function() + function contentLoaded() { - // This function will be called in the inspected page's context. - elementsPanel._domContentLoaded = true; - }; + inspectedWindow.document.removeEventListener("DOMContentLoaded", contentLoadedCallback, false); - function checkContentLoaded() - { - if (!this._domContentLoaded) - return; this.reset(); - inspectedWindow.document.removeEventListener("DOMContentLoaded", contentLoaded, false); - clearInterval(contentLoadedPollingInterval); - delete this._domContentLoaded; } - this._domContentLoaded = false; - var contentLoadedPollingInterval = setInterval(checkContentLoaded.bind(this), 100); - - inspectedWindow.document.addEventListener("DOMContentLoaded", contentLoaded, false); + var contentLoadedCallback = InspectorController.wrapCallback(contentLoaded.bind(this)); + inspectedWindow.document.addEventListener("DOMContentLoaded", contentLoadedCallback, false); return; } + // If the window isn't visible, return early so the DOM tree isn't built + // and mutation event listeners are not added. + if (!InspectorController.isWindowVisible()) + return; + + this.registerMutationEventListeners(inspectedWindow); + var inspectedRootDocument = inspectedWindow.document; this.rootDOMNode = inspectedRootDocument; var canidateFocusNode = inspectedRootDocument.body || inspectedRootDocument.documentElement; if (canidateFocusNode) { + this.treeOutline.suppressSelectHighlight = true; this.focusedDOMNode = canidateFocusNode; + this.treeOutline.suppressSelectHighlight = false; + if (this.treeOutline.selectedTreeElement) this.treeOutline.selectedTreeElement.expand(); } }, - updateTreeSelection: function() + includedInSearchResultsPropertyName: "__includedInInspectorSearchResults", + + searchCanceled: function() + { + if (this._searchResults) { + const searchResultsProperty = this.includedInSearchResultsPropertyName; + for (var i = 0; i < this._searchResults.length; ++i) { + var node = this._searchResults[i]; + + // Remove the searchResultsProperty since there might be an unfinished search. + delete node[searchResultsProperty]; + + var treeElement = this.treeOutline.findTreeElement(node); + if (treeElement) + treeElement.highlighted = false; + } + } + + WebInspector.updateSearchMatchesCount(0, this); + + if (this._currentSearchChunkIntervalIdentifier) { + clearInterval(this._currentSearchChunkIntervalIdentifier); + delete this._currentSearchChunkIntervalIdentifier; + } + + this._currentSearchResultIndex = 0; + this._searchResults = []; + }, + + performSearch: function(query) + { + // Call searchCanceled since it will reset everything we need before doing a new search. + this.searchCanceled(); + + const whitespaceTrimmedQuery = query.trimWhitespace(); + if (!whitespaceTrimmedQuery.length) + return; + + var tagNameQuery = whitespaceTrimmedQuery; + var attributeNameQuery = whitespaceTrimmedQuery; + var startTagFound = (tagNameQuery.indexOf("<") === 0); + var endTagFound = (tagNameQuery.lastIndexOf(">") === (tagNameQuery.length - 1)); + + if (startTagFound || endTagFound) { + var tagNameQueryLength = tagNameQuery.length; + tagNameQuery = tagNameQuery.substring((startTagFound ? 1 : 0), (endTagFound ? (tagNameQueryLength - 1) : tagNameQueryLength)); + } + + // Check the tagNameQuery is it is a possibly valid tag name. + if (!/^[a-zA-Z0-9\-_:]+$/.test(tagNameQuery)) + tagNameQuery = null; + + // Check the attributeNameQuery is it is a possibly valid tag name. + if (!/^[a-zA-Z0-9\-_:]+$/.test(attributeNameQuery)) + attributeNameQuery = null; + + const escapedQuery = query.escapeCharacters("'"); + const escapedTagNameQuery = (tagNameQuery ? tagNameQuery.escapeCharacters("'") : null); + const escapedWhitespaceTrimmedQuery = whitespaceTrimmedQuery.escapeCharacters("'"); + const searchResultsProperty = this.includedInSearchResultsPropertyName; + + var updatedMatchCountOnce = false; + var matchesCountUpdateTimeout = null; + + function updateMatchesCount() + { + WebInspector.updateSearchMatchesCount(this._searchResults.length, this); + matchesCountUpdateTimeout = null; + updatedMatchCountOnce = true; + } + + function updateMatchesCountSoon() + { + if (!updatedMatchCountOnce) + return updateMatchesCount.call(this); + if (matchesCountUpdateTimeout) + return; + // Update the matches count every half-second so it doesn't feel twitchy. + matchesCountUpdateTimeout = setTimeout(updateMatchesCount.bind(this), 500); + } + + function addNodesToResults(nodes, length, getItem) + { + if (!length) + return; + + for (var i = 0; i < length; ++i) { + var node = getItem.call(nodes, i); + // Skip this node if it already has the property. + if (searchResultsProperty in node) + continue; + + if (!this._searchResults.length) { + this._currentSearchResultIndex = 0; + this.focusedDOMNode = node; + } + + node[searchResultsProperty] = true; + this._searchResults.push(node); + + // Highlight the tree element to show it matched the search. + // FIXME: highlight the substrings in text nodes and attributes. + var treeElement = this.treeOutline.findTreeElement(node); + if (treeElement) + treeElement.highlighted = true; + } + + updateMatchesCountSoon.call(this); + } + + function matchExactItems(doc) + { + matchExactId.call(this, doc); + matchExactClassNames.call(this, doc); + matchExactTagNames.call(this, doc); + matchExactAttributeNames.call(this, doc); + } + + function matchExactId(doc) + { + const result = doc.__proto__.getElementById.call(doc, whitespaceTrimmedQuery); + addNodesToResults.call(this, result, (result ? 1 : 0), function() { return this }); + } + + function matchExactClassNames(doc) + { + const result = doc.__proto__.getElementsByClassName.call(doc, whitespaceTrimmedQuery); + addNodesToResults.call(this, result, result.length, result.item); + } + + function matchExactTagNames(doc) + { + if (!tagNameQuery) + return; + const result = doc.__proto__.getElementsByTagName.call(doc, tagNameQuery); + addNodesToResults.call(this, result, result.length, result.item); + } + + function matchExactAttributeNames(doc) + { + if (!attributeNameQuery) + return; + const result = doc.__proto__.querySelectorAll.call(doc, "[" + attributeNameQuery + "]"); + addNodesToResults.call(this, result, result.length, result.item); + } + + function matchPartialTagNames(doc) + { + if (!tagNameQuery) + return; + const result = doc.__proto__.evaluate.call(doc, "//*[contains(name(), '" + escapedTagNameQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); + addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem); + } + + function matchStartOfTagNames(doc) + { + if (!tagNameQuery) + return; + const result = doc.__proto__.evaluate.call(doc, "//*[starts-with(name(), '" + escapedTagNameQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); + addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem); + } + + function matchPartialTagNamesAndAttributeValues(doc) + { + if (!tagNameQuery) { + matchPartialAttributeValues.call(this, doc); + return; + } + + const result = doc.__proto__.evaluate.call(doc, "//*[contains(name(), '" + escapedTagNameQuery + "') or contains(@*, '" + escapedQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); + addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem); + } + + function matchPartialAttributeValues(doc) + { + const result = doc.__proto__.evaluate.call(doc, "//*[contains(@*, '" + escapedQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); + addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem); + } + + function matchStyleSelector(doc) + { + const result = doc.__proto__.querySelectorAll.call(doc, whitespaceTrimmedQuery); + addNodesToResults.call(this, result, result.length, result.item); + } + + function matchPlainText(doc) + { + const result = doc.__proto__.evaluate.call(doc, "//text()[contains(., '" + escapedQuery + "')] | //comment()[contains(., '" + escapedQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); + addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem); + } + + function matchXPathQuery(doc) + { + const result = doc.__proto__.evaluate.call(doc, whitespaceTrimmedQuery, doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); + addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem); + } + + function finishedSearching() + { + // Remove the searchResultsProperty now that the search is finished. + for (var i = 0; i < this._searchResults.length; ++i) + delete this._searchResults[i][searchResultsProperty]; + } + + const mainFrameDocument = InspectorController.inspectedWindow().document; + const searchDocuments = [mainFrameDocument]; + + if (tagNameQuery && startTagFound && endTagFound) + const searchFunctions = [matchExactTagNames, matchPlainText]; + else if (tagNameQuery && startTagFound) + const searchFunctions = [matchStartOfTagNames, matchPlainText]; + else if (tagNameQuery && endTagFound) { + // FIXME: we should have a matchEndOfTagNames search function if endTagFound is true but not startTagFound. + // This requires ends-with() support in XPath, WebKit only supports starts-with() and contains(). + const searchFunctions = [matchPartialTagNames, matchPlainText]; + } else if (whitespaceTrimmedQuery === "//*" || whitespaceTrimmedQuery === "*") { + // These queries will match every node. Matching everything isn't useful and can be slow for large pages, + // so limit the search functions list to plain text and attribute matching. + const searchFunctions = [matchPartialAttributeValues, matchPlainText]; + } else + const searchFunctions = [matchExactItems, matchStyleSelector, matchPartialTagNamesAndAttributeValues, matchPlainText, matchXPathQuery]; + + // Find all frames, iframes and object elements to search their documents. + const querySelectorAllFunction = InspectorController.inspectedWindow().Document.prototype.querySelectorAll; + const subdocumentResult = querySelectorAllFunction.call(mainFrameDocument, "iframe, frame, object"); + + for (var i = 0; i < subdocumentResult.length; ++i) { + var element = subdocumentResult.item(i); + if (element.contentDocument) + searchDocuments.push(element.contentDocument); + } + + const panel = this; + var documentIndex = 0; + var searchFunctionIndex = 0; + var chunkIntervalIdentifier = null; + + // Split up the work into chunks so we don't block the UI thread while processing. + + function processChunk() + { + var searchDocument = searchDocuments[documentIndex]; + var searchFunction = searchFunctions[searchFunctionIndex]; + + if (++searchFunctionIndex > searchFunctions.length) { + searchFunction = searchFunctions[0]; + searchFunctionIndex = 0; + + if (++documentIndex > searchDocuments.length) { + if (panel._currentSearchChunkIntervalIdentifier === chunkIntervalIdentifier) + delete panel._currentSearchChunkIntervalIdentifier; + clearInterval(chunkIntervalIdentifier); + finishedSearching.call(panel); + return; + } + + searchDocument = searchDocuments[documentIndex]; + } + + if (!searchDocument || !searchFunction) + return; + + try { + searchFunction.call(panel, searchDocument); + } catch(err) { + // ignore any exceptions. the query might be malformed, but we allow that. + } + } + + processChunk(); + + chunkIntervalIdentifier = setInterval(processChunk, 25); + this._currentSearchChunkIntervalIdentifier = chunkIntervalIdentifier; + }, + + jumpToNextSearchResult: function() { - if (!this.treeOutline || !this.treeOutline.selectedTreeElement) + if (!this._searchResults || !this._searchResults.length) return; - var element = this.treeOutline.selectedTreeElement; - element.updateSelection(); + if (++this._currentSearchResultIndex >= this._searchResults.length) + this._currentSearchResultIndex = 0; + this.focusedDOMNode = this._searchResults[this._currentSearchResultIndex]; }, - get rootDOMNode() + jumpToPreviousSearchResult: function() { - return this._rootDOMNode; + if (!this._searchResults || !this._searchResults.length) + return; + if (--this._currentSearchResultIndex < 0) + this._currentSearchResultIndex = (this._searchResults.length - 1); + this.focusedDOMNode = this._searchResults[this._currentSearchResultIndex]; }, - set rootDOMNode(x) + inspectedWindowCleared: function(window) + { + if (InspectorController.isWindowVisible()) + this.updateMutationEventListeners(window); + }, + + _addMutationEventListeners: function(monitoredWindow) { - if (this._rootDOMNode === x) + monitoredWindow.document.addEventListener("DOMNodeInserted", this._nodeInsertedEventListener, true); + monitoredWindow.document.addEventListener("DOMNodeRemoved", this._nodeRemovedEventListener, true); + if (monitoredWindow.frameElement) + monitoredWindow.addEventListener("DOMContentLoaded", this._contentLoadedEventListener, true); + }, + + _removeMutationEventListeners: function(monitoredWindow) + { + if (monitoredWindow.frameElement) + monitoredWindow.removeEventListener("DOMContentLoaded", this._contentLoadedEventListener, true); + if (!monitoredWindow.document) return; + monitoredWindow.document.removeEventListener("DOMNodeInserted", this._nodeInsertedEventListener, true); + monitoredWindow.document.removeEventListener("DOMNodeRemoved", this._nodeRemovedEventListener, true); + }, + + updateMutationEventListeners: function(monitoredWindow) + { + this._addMutationEventListeners(monitoredWindow); + }, - this._rootDOMNode = x; + registerMutationEventListeners: function(monitoredWindow) + { + if (!monitoredWindow || this._mutationMonitoredWindows.indexOf(monitoredWindow) !== -1) + return; + this._mutationMonitoredWindows.push(monitoredWindow); + if (InspectorController.isWindowVisible()) + this._addMutationEventListeners(monitoredWindow); + }, - this.updateBreadcrumb(); - this.updateTreeOutline(); + unregisterMutationEventListeners: function(monitoredWindow) + { + if (!monitoredWindow || this._mutationMonitoredWindows.indexOf(monitoredWindow) === -1) + return; + this._mutationMonitoredWindows.remove(monitoredWindow); + this._removeMutationEventListeners(monitoredWindow); + }, + + unregisterAllMutationEventListeners: function() + { + for (var i = 0; i < this._mutationMonitoredWindows.length; ++i) + this._removeMutationEventListeners(this._mutationMonitoredWindows[i]); + this._mutationMonitoredWindows = []; + }, + + get rootDOMNode() + { + return this.treeOutline.rootDOMNode; + }, + + set rootDOMNode(x) + { + this.treeOutline.rootDOMNode = x; }, get focusedDOMNode() { - return this._focusedDOMNode; + return this.treeOutline.focusedDOMNode; }, set focusedDOMNode(x) { - if (this._focusedDOMNode === x) { - var nodeItem = this.revealNode(x); - if (nodeItem) - nodeItem.select(); + this.treeOutline.focusedDOMNode = x; + }, + + _contentLoaded: function(event) + { + this.recentlyModifiedNodes.push({node: event.target, parent: event.target.defaultView.frameElement, replaced: true}); + if (this.visible) + this._updateModifiedNodesSoon(); + }, + + _nodeInserted: function(event) + { + this.recentlyModifiedNodes.push({node: event.target, parent: event.relatedNode, inserted: true}); + if (this.visible) + this._updateModifiedNodesSoon(); + }, + + _nodeRemoved: function(event) + { + this.recentlyModifiedNodes.push({node: event.target, parent: event.relatedNode, removed: true}); + if (this.visible) + this._updateModifiedNodesSoon(); + }, + + _updateModifiedNodesSoon: function() + { + if ("_updateModifiedNodesTimeout" in this) return; + this._updateModifiedNodesTimeout = setTimeout(this._updateModifiedNodes.bind(this), 0); + }, + + _updateModifiedNodes: function() + { + if ("_updateModifiedNodesTimeout" in this) { + clearTimeout(this._updateModifiedNodesTimeout); + delete this._updateModifiedNodesTimeout; } - this._focusedDOMNode = x; + var updatedParentTreeElements = []; + var updateBreadcrumbs = false; - this._focusedNodeChanged(); + for (var i = 0; i < this.recentlyModifiedNodes.length; ++i) { + var replaced = this.recentlyModifiedNodes[i].replaced; + var parent = this.recentlyModifiedNodes[i].parent; + if (!parent) + continue; + + var parentNodeItem = this.treeOutline.findTreeElement(parent, null, null, objectsAreSame); + if (parentNodeItem && !parentNodeItem.alreadyUpdatedChildren) { + parentNodeItem.updateChildren(replaced); + parentNodeItem.alreadyUpdatedChildren = true; + updatedParentTreeElements.push(parentNodeItem); + } - var nodeItem = this.revealNode(x); - if (nodeItem) - nodeItem.select(); + if (!updateBreadcrumbs && (objectsAreSame(this.focusedDOMNode, parent) || isAncestorIncludingParentFrames(this.focusedDOMNode, parent))) + updateBreadcrumbs = true; + } + + for (var i = 0; i < updatedParentTreeElements.length; ++i) + delete updatedParentTreeElements[i].alreadyUpdatedChildren; + + this.recentlyModifiedNodes = []; + + if (updateBreadcrumbs) + this.updateBreadcrumb(true); }, - _focusedNodeChanged: function(forceUpdate) + _stylesPaneEdited: function() { - this.updateBreadcrumb(forceUpdate); - - for (var pane in this.sidebarPanes) - this.sidebarPanes[pane].needsUpdate = true; + this.sidebarPanes.metrics.needsUpdate = true; + this.updateMetrics(); + }, + _metricsPaneEdited: function() + { + this.sidebarPanes.styles.needsUpdate = true; this.updateStyles(true); - this.updateMetrics(); - this.updateProperties(); }, - revealNode: function(node) + _mouseMovedInCrumbs: function(event) { - var nodeItem = this.treeOutline.findTreeElement(node, this._isAncestorIncludingParentFrames.bind(this), this._parentNodeOrFrameElement.bind(this)); - if (!nodeItem) - return; + var nodeUnderMouse = document.elementFromPoint(event.pageX, event.pageY); + var crumbElement = nodeUnderMouse.enclosingNodeOrSelfWithClass("crumb"); + + WebInspector.hoveredDOMNode = (crumbElement ? crumbElement.representedObject : null); - nodeItem.reveal(); - return nodeItem; + if ("_mouseOutOfCrumbsTimeout" in this) { + clearTimeout(this._mouseOutOfCrumbsTimeout); + delete this._mouseOutOfCrumbsTimeout; + } }, - updateTreeOutline: function() + _mouseMovedOutOfCrumbs: function(event) { - this.treeOutline.removeChildrenRecursive(); - - if (!this.rootDOMNode) + var nodeUnderMouse = document.elementFromPoint(event.pageX, event.pageY); + if (nodeUnderMouse.isDescendant(this.crumbsElement)) return; - // FIXME: this could use findTreeElement to reuse a tree element if it already exists - var node = (Preferences.ignoreWhitespace ? firstChildSkippingWhitespace.call(this.rootDOMNode) : this.rootDOMNode.firstChild); - while (node) { - this.treeOutline.appendChild(new WebInspector.DOMNodeTreeElement(node)); - node = Preferences.ignoreWhitespace ? nextSiblingSkippingWhitespace.call(node) : node.nextSibling; - } + WebInspector.hoveredDOMNode = null; - this.updateTreeSelection(); + this._mouseOutOfCrumbsTimeout = setTimeout(this.updateBreadcrumbSizes.bind(this), 1000); }, updateBreadcrumb: function(forceUpdate) @@ -279,7 +694,7 @@ WebInspector.ElementsPanel.prototype = { var foundRoot = false; var crumb = crumbs.firstChild; while (crumb) { - if (crumb.representedObject === this.rootDOMNode) + if (objectsAreSame(crumb.representedObject, this.rootDOMNode)) foundRoot = true; if (foundRoot) @@ -287,7 +702,7 @@ WebInspector.ElementsPanel.prototype = { else crumb.removeStyleClass("dimmed"); - if (crumb.representedObject === this.focusedDOMNode) { + if (objectsAreSame(crumb.representedObject, this.focusedDOMNode)) { crumb.addStyleClass("selected"); handled = true; } else { @@ -307,7 +722,9 @@ WebInspector.ElementsPanel.prototype = { crumbs.removeChildren(); var panel = this; - var selectCrumbFunction = function(event) { + + function selectCrumbFunction(event) + { var crumb = event.currentTarget; if (crumb.hasStyleClass("collapsed")) { // Clicking a collapsed crumb will expose the hidden crumbs. @@ -334,60 +751,21 @@ WebInspector.ElementsPanel.prototype = { panel.focusedDOMNode = crumb.representedObject; } - WebInspector.currentFocusElement = document.getElementById("main-panels"); - event.preventDefault(); - }; - - var mouseOverCrumbFunction = function(event) { - if (event.currentTarget.isDescendant(event.relatedTarget)) { - return; - } - panel.mouseOverCrumb = true; - - WebInspector.highlightDOMNode(event.currentTarget.representedObject); - - if ("mouseOutTimeout" in panel) { - clearTimeout(panel.mouseOutTimeout); - delete panel.mouseOutTimeout; - } - }; - - var mouseOutCrumbFunction = function(event) { - if (event.currentTarget.isDescendant(event.relatedTarget) || - event.relatedTarget && event.relatedTarget.representedObject) { - return; - } - - delete panel.mouseOverCrumb; - - if ("mouseOutTimeout" in panel) { - clearTimeout(panel.mouseOutTimeout); - delete panel.mouseOutTimeout; - } - - var timeoutFunction = function() { - if (!panel.mouseOverCrumb) - panel.updateBreadcrumbSizes(); - }; - - panel.mouseOutTimeout = setTimeout(timeoutFunction, 500); - }; + } foundRoot = false; - for (var current = this.focusedDOMNode; current; current = this._parentNodeOrFrameElement(current)) { + for (var current = this.focusedDOMNode; current; current = parentNodeOrFrameElement(current)) { if (current.nodeType === Node.DOCUMENT_NODE) continue; - if (current === this.rootDOMNode) + if (objectsAreSame(current, this.rootDOMNode)) foundRoot = true; var crumb = document.createElement("span"); crumb.className = "crumb"; crumb.representedObject = current; crumb.addEventListener("mousedown", selectCrumbFunction, false); - crumb.addEventListener("mouseover", mouseOverCrumbFunction.bind(crumb), false); - crumb.addEventListener("mouseout", mouseOutCrumbFunction, false); var crumbTitle; switch (current.nodeType) { @@ -464,7 +842,7 @@ WebInspector.ElementsPanel.prototype = { if (foundRoot) crumb.addStyleClass("dimmed"); - if (current === this.focusedDOMNode) + if (objectsAreSame(current, this.focusedDOMNode)) crumb.addStyleClass("selected"); if (!crumbs.childNodes.length) crumb.addStyleClass("end"); @@ -484,8 +862,8 @@ WebInspector.ElementsPanel.prototype = { return; if (document.body.offsetWidth <= 0) { - // The stylesheet hasn't loaded yet, so we need to update later. - setTimeout(this.updateBreadcrumbSizes.bind(this), 0); + // The stylesheet hasn't loaded yet or the window is closed, + // so we can't calculate what is need. Return early. return; } @@ -501,13 +879,13 @@ WebInspector.ElementsPanel.prototype = { var i = 0; var crumb = crumbs.firstChild; while (crumb) { - // Find the selected crumb and index. + // Find the selected crumb and index. if (!selectedCrumb && crumb.hasStyleClass("selected")) { selectedCrumb = crumb; selectedIndex = i; } - // Find the focused crumb index. + // Find the focused crumb index. if (crumb === focusedCrumb) focusedIndex = i; @@ -534,9 +912,9 @@ WebInspector.ElementsPanel.prototype = { function crumbsAreSmallerThanContainer() { var rightPadding = 20; - var errorWarningElement = document.getElementById("error-warning-count"); - if (!WebInspector.console.visible && errorWarningElement) - rightPadding += errorWarningElement.offsetWidth; + var errorWarningElement = document.getElementById("error-warning-count"); + if (!WebInspector.console.visible && errorWarningElement) + rightPadding += errorWarningElement.offsetWidth; return ((crumbs.totalOffsetLeft + crumbs.offsetWidth + rightPadding) < window.innerWidth); } @@ -616,7 +994,7 @@ WebInspector.ElementsPanel.prototype = { while (crumb) { var hidden = crumb.hasStyleClass("hidden"); if (!hidden) { - var collapsed = crumb.hasStyleClass("collapsed"); + var collapsed = crumb.hasStyleClass("collapsed"); if (collapsedRun && collapsed) { crumb.addStyleClass("hidden"); crumb.removeStyleClass("compact"); @@ -809,374 +1187,20 @@ WebInspector.ElementsPanel.prototype = { this.contentElement.style.right = newWidth + "px"; this.sidebarResizeElement.style.right = (newWidth - 3) + "px"; - this.updateTreeSelection(); + this.treeOutline.updateSelection(); event.preventDefault(); }, - _getDocumentForNode: function(node) - { - return node.nodeType == Node.DOCUMENT_NODE ? node : node.ownerDocument; - }, - - _parentNodeOrFrameElement: function(node) - { - var parent = node.parentNode; - if (parent) - return parent; - - var document = this._getDocumentForNode(node); - return document.defaultView.frameElement; - }, - - _isAncestorIncludingParentFrames: function(a, b) - { - for (var node = b; node; node = this._getDocumentForNode(node).defaultView.frameElement) - if (isAncestorNode.call(a, node)) - return true; - return false; - }, - - _treeElementFromEvent: function(event) - { - var outline = this.treeOutline; - - var root = this.treeListElement; - - // We choose this X coordinate based on the knowledge that our list - // items extend nearly to the right edge of the outer <ol>. - var x = root.totalOffsetLeft + root.offsetWidth - 20; - - var y = event.pageY; - - // Our list items have 1-pixel cracks between them vertically. We avoid - // the cracks by checking slightly above and slightly below the mouse - // and seeing if we hit the same element each time. - var elementUnderMouse = outline.treeElementFromPoint(x, y); - var elementAboveMouse = outline.treeElementFromPoint(x, y - 2); - var element; - if (elementUnderMouse === elementAboveMouse) - element = elementUnderMouse; - else - element = outline.treeElementFromPoint(x, y + 2); - - return element; - }, - - _ondblclick: function(event) + _nodeSearchButtonClicked: function(event) { - var element = this._treeElementFromEvent(event); + InspectorController.toggleNodeSearch(); - if (!element) - return; - - element.ondblclick(); - }, - - _onmousedown: function(event) - { - var element = this._treeElementFromEvent(event); - - if (!element || element.isEventWithinDisclosureTriangle(event)) - return; - - element.select(); - }, - - _onmousemove: function(event) - { - var element = this._treeElementFromEvent(event); - if (element) - WebInspector.highlightDOMNode(element.representedObject); + if (InspectorController.searchingForNode()) + this.nodeSearchButton.addStyleClass("toggled-on"); else - WebInspector.hideDOMNodeHighlight(); - }, + this.nodeSearchButton.removeStyleClass("toggled-on"); + } } WebInspector.ElementsPanel.prototype.__proto__ = WebInspector.Panel.prototype; - -WebInspector.DOMNodeTreeElement = function(node) -{ - var hasChildren = node.contentDocument || (Preferences.ignoreWhitespace ? (firstChildSkippingWhitespace.call(node) ? true : false) : node.hasChildNodes()); - var titleInfo = nodeTitleInfo.call(node, hasChildren, WebInspector.linkifyURL); - - if (titleInfo.hasChildren) - this.whitespaceIgnored = Preferences.ignoreWhitespace; - - TreeElement.call(this, titleInfo.title, node, titleInfo.hasChildren); -} - -WebInspector.DOMNodeTreeElement.prototype = { - updateSelection: function() - { - var listItemElement = this.listItemElement; - if (!listItemElement) - return; - - if (document.body.offsetWidth <= 0) { - // The stylesheet hasn't loaded yet, so we need to update later. - setTimeout(this.updateSelection.bind(this), 0); - return; - } - - if (!this.selectionElement) { - this.selectionElement = document.createElement("div"); - this.selectionElement.className = "selection selected"; - listItemElement.insertBefore(this.selectionElement, listItemElement.firstChild); - } - - this.selectionElement.style.height = listItemElement.offsetHeight + "px"; - }, - - onattach: function() - { - this.listItemElement.addEventListener("mousedown", this.onmousedown.bind(this), false); - - this._makeURLsActivateOnModifiedClick(); - }, - - _makeURLsActivateOnModifiedClick: function() - { - var links = this.listItemElement.querySelectorAll("li > .webkit-html-tag > .webkit-html-attribute > .webkit-html-external-link, li > .webkit-html-tag > .webkit-html-attribute > .webkit-html-resource-link"); - if (!links) - return; - - var isMac = InspectorController.platform().indexOf("mac") == 0; - - for (var i = 0; i < links.length; ++i) { - var link = links[i]; - var isExternal = link.hasStyleClass("webkit-html-external-link"); - var href = link.getAttribute("href"); - var title; - if (isMac) { - if (isExternal) - title = WebInspector.UIString("Option-click to visit %s.", href); - else - title = WebInspector.UIString("Option-click to show %s.", href); - } else { - if (isExternal) - title = WebInspector.UIString("Alt-click to visit %s.", href); - else - title = WebInspector.UIString("Alt-click to show %s.", href); - } - link.setAttribute("title", title); - link.followOnAltClick = true; - } - }, - - onpopulate: function() - { - if (this.children.length || this.whitespaceIgnored !== Preferences.ignoreWhitespace) - return; - - this.removeChildren(); - this.whitespaceIgnored = Preferences.ignoreWhitespace; - - var treeElement = this; - function appendChildrenOfNode(node) - { - var child = (Preferences.ignoreWhitespace ? firstChildSkippingWhitespace.call(node) : node.firstChild); - while (child) { - treeElement.appendChild(new WebInspector.DOMNodeTreeElement(child)); - child = Preferences.ignoreWhitespace ? nextSiblingSkippingWhitespace.call(child) : child.nextSibling; - } - } - - if (this.representedObject.contentDocument) - appendChildrenOfNode(this.representedObject.contentDocument); - - appendChildrenOfNode(this.representedObject); - - if (this.representedObject.nodeType == Node.ELEMENT_NODE) { - var title = "<span class=\"webkit-html-tag close\"></" + this.representedObject.nodeName.toLowerCase().escapeHTML() + "></span>"; - var item = new TreeElement(title, this.representedObject, false); - item.selectable = false; - this.appendChild(item); - } - }, - - onexpand: function() - { - this.treeOutline.panel.updateTreeSelection(); - }, - - oncollapse: function() - { - this.treeOutline.panel.updateTreeSelection(); - }, - - onreveal: function() - { - if (this.listItemElement) - this.listItemElement.scrollIntoViewIfNeeded(false); - }, - - onselect: function() - { - this._selectedByCurrentMouseDown = true; - this.treeOutline.panel.focusedDOMNode = this.representedObject; - this.updateSelection(); - }, - - onmousedown: function(event) - { - if (this._editing) - return; - - if (this._selectedByCurrentMouseDown) - delete this._selectedByCurrentMouseDown; - else if (this._startEditing(event)) { - event.preventDefault(); - return; - } - - // Prevent selecting the nearest word on double click. - if (event.detail >= 2) - event.preventDefault(); - }, - - ondblclick: function(treeElement, event) - { - if (this._editing) - return; - - var panel = this.treeOutline.panel; - panel.rootDOMNode = this.parent.representedObject; - panel.focusedDOMNode = this.representedObject; - - if (this.hasChildren && !this.expanded) - this.expand(); - }, - - _startEditing: function(event) - { - if (this.treeOutline.panel.focusedDOMNode != this.representedObject) - return; - - if (this.representedObject.nodeType != Node.ELEMENT_NODE && this.representedObject.nodeType != Node.TEXT_NODE) - return false; - - var textNode = event.target.enclosingNodeOrSelfWithClass("webkit-html-text-node"); - if (textNode) - return this._startEditingTextNode(textNode); - - var attribute = event.target.enclosingNodeOrSelfWithClass("webkit-html-attribute"); - if (attribute) - return this._startEditingAttribute(attribute, event); - - return false; - }, - - _startEditingAttribute: function(attribute, event) - { - if (WebInspector.isBeingEdited(attribute)) - return true; - - var attributeNameElement = attribute.getElementsByClassName("webkit-html-attribute-name")[0]; - if (!attributeNameElement) - return false; - - var isURL = event.target.enclosingNodeOrSelfWithClass("webkit-html-external-link") || event.target.enclosingNodeOrSelfWithClass("webkit-html-resource-link"); - if (isURL && event.altKey) - return false; - - var attributeName = attributeNameElement.innerText; - - function removeZeroWidthSpaceRecursive(node) - { - if (node.nodeType === Node.TEXT_NODE) { - node.nodeValue = node.nodeValue.replace(/\u200B/g, ""); - return; - } - - if (node.nodeType !== Node.ELEMENT_NODE) - return; - - for (var child = node.firstChild; child; child = child.nextSibling) - removeZeroWidthSpaceRecursive(child); - } - - // Remove zero-width spaces that were added by nodeTitleInfo. - removeZeroWidthSpaceRecursive(attribute); - - this._editing = true; - - WebInspector.startEditing(attribute, this._attributeEditingCommitted.bind(this), this._editingCancelled.bind(this), attributeName); - window.getSelection().setBaseAndExtent(event.target, 0, event.target, 1); - - return true; - }, - - _startEditingTextNode: function(textNode) - { - if (WebInspector.isBeingEdited(textNode)) - return true; - - this._editing = true; - - WebInspector.startEditing(textNode, this._textNodeEditingCommitted.bind(this), this._editingCancelled.bind(this)); - window.getSelection().setBaseAndExtent(textNode, 0, textNode, 1); - - return true; - }, - - _attributeEditingCommitted: function(element, newText, oldText, attributeName) - { - delete this._editing; - - var parseContainerElement = document.createElement("span"); - parseContainerElement.innerHTML = "<span " + newText + "></span>"; - var parseElement = parseContainerElement.firstChild; - if (!parseElement || !parseElement.hasAttributes()) { - editingCancelled(element, context); - return; - } - - var foundOriginalAttribute = false; - for (var i = 0; i < parseElement.attributes.length; ++i) { - var attr = parseElement.attributes[i]; - foundOriginalAttribute = foundOriginalAttribute || attr.name === attributeName; - InspectorController.inspectedWindow().Element.prototype.setAttribute.call(this.representedObject, attr.name, attr.value); - } - - if (!foundOriginalAttribute) - InspectorController.inspectedWindow().Element.prototype.removeAttribute.call(this.representedObject, attributeName); - - this._updateTitle(); - this.treeOutline.panel._focusedNodeChanged(true); - }, - - _textNodeEditingCommitted: function(element, newText) - { - delete this._editing; - - var textNode; - if (this.representedObject.nodeType == Node.ELEMENT_NODE) { - // We only show text nodes inline in elements if the element only - // has a single child, and that child is a text node. - textNode = this.representedObject.firstChild; - } else if (this.representedObject.nodeType == Node.TEXT_NODE) - textNode = this.representedObject; - - textNode.nodeValue = newText; - this._updateTitle(); - }, - - - _editingCancelled: function(element, context) - { - delete this._editing; - - this._updateTitle(); - }, - - _updateTitle: function() - { - this.title = nodeTitleInfo.call(this.representedObject, this.hasChildren, WebInspector.linkifyURL).title; - delete this.selectionElement; - this.updateSelection(); - this._makeURLsActivateOnModifiedClick(); - }, -} - -WebInspector.DOMNodeTreeElement.prototype.__proto__ = TreeElement.prototype; diff --git a/chrome/tools/test/reference_build/chrome/resources/Inspector/FontView.js b/chrome/tools/test/reference_build/chrome/resources/Inspector/FontView.js index 2059c04..4e1c931 100644 --- a/chrome/tools/test/reference_build/chrome/resources/Inspector/FontView.js +++ b/chrome/tools/test/reference_build/chrome/resources/Inspector/FontView.js @@ -34,6 +34,10 @@ WebInspector.FontView = function(resource) var uniqueFontName = "WebInspectorFontPreview" + this.resource.identifier; + this.fontStyleElement = document.createElement("style"); + this.fontStyleElement.textContent = "@font-face { font-family: \"" + uniqueFontName + "\"; src: url(" + this.resource.url + "); }"; + document.getElementsByTagName("head").item(0).appendChild(this.fontStyleElement); + this.fontPreviewElement = document.createElement("div"); this.fontPreviewElement.className = "preview"; this.contentElement.appendChild(this.fontPreviewElement); @@ -45,9 +49,9 @@ WebInspector.FontView = function(resource) } WebInspector.FontView.prototype = { - show: function() + show: function(parentElement) { - WebInspector.ResourceView.prototype.show.call(this); + WebInspector.ResourceView.prototype.show.call(this, parentElement); this.updateFontPreviewSize(); }, @@ -71,10 +75,12 @@ WebInspector.FontView.prototype = { var height = this.fontPreviewElement.offsetHeight; var width = this.fontPreviewElement.offsetWidth; - var containerHeight = this.contentElement.offsetHeight; var containerWidth = this.contentElement.offsetWidth; - if (!height || !width || !containerHeight || !containerWidth) { + // Subtract some padding. This should match the padding in the CSS plus room for the scrollbar. + containerWidth -= 40; + + if (!height || !width || !containerWidth) { this.fontPreviewElement.style.removeProperty("font-size"); this.fontPreviewElement.style.removeProperty("position"); this.fontPreviewElement.addStyleClass("preview"); @@ -85,12 +91,7 @@ WebInspector.FontView.prototype = { var realLineHeight = Math.floor(height / lineCount); var fontSizeLineRatio = measureFontSize / realLineHeight; var widthRatio = containerWidth / width; - var heightRatio = containerHeight / height; - - if (heightRatio < widthRatio) - var finalFontSize = Math.floor(realLineHeight * heightRatio * fontSizeLineRatio) - 1; - else - var finalFontSize = Math.floor(realLineHeight * widthRatio * fontSizeLineRatio) - 1; + var finalFontSize = Math.floor(realLineHeight * widthRatio * fontSizeLineRatio) - 1; this.fontPreviewElement.style.setProperty("font-size", finalFontSize + "px", null); this.fontPreviewElement.style.setProperty("height", this.fontPreviewElement.offsetHeight + "px", null); diff --git a/chrome/tools/test/reference_build/chrome/resources/Inspector/Images/databasesIcon.png b/chrome/tools/test/reference_build/chrome/resources/Inspector/Images/databasesIcon.png Binary files differindex 8ae9ef6..79c7bb3 100644 --- a/chrome/tools/test/reference_build/chrome/resources/Inspector/Images/databasesIcon.png +++ b/chrome/tools/test/reference_build/chrome/resources/Inspector/Images/databasesIcon.png diff --git a/chrome/tools/test/reference_build/chrome/resources/Inspector/Images/elementsIcon.png b/chrome/tools/test/reference_build/chrome/resources/Inspector/Images/elementsIcon.png Binary files differindex cd38af1..fde3db9 100644 --- a/chrome/tools/test/reference_build/chrome/resources/Inspector/Images/elementsIcon.png +++ b/chrome/tools/test/reference_build/chrome/resources/Inspector/Images/elementsIcon.png diff --git a/chrome/tools/test/reference_build/chrome/resources/Inspector/Images/glossyHeader.png b/chrome/tools/test/reference_build/chrome/resources/Inspector/Images/glossyHeader.png Binary files differindex 8c80b6b..6cbefb7 100644 --- a/chrome/tools/test/reference_build/chrome/resources/Inspector/Images/glossyHeader.png +++ b/chrome/tools/test/reference_build/chrome/resources/Inspector/Images/glossyHeader.png diff --git a/chrome/tools/test/reference_build/chrome/resources/Inspector/Images/glossyHeaderPressed.png b/chrome/tools/test/reference_build/chrome/resources/Inspector/Images/glossyHeaderPressed.png Binary files differindex 6b0dd60..1153506 100644 --- a/chrome/tools/test/reference_build/chrome/resources/Inspector/Images/glossyHeaderPressed.png +++ b/chrome/tools/test/reference_build/chrome/resources/Inspector/Images/glossyHeaderPressed.png diff --git a/chrome/tools/test/reference_build/chrome/resources/Inspector/Images/resourcesIcon.png b/chrome/tools/test/reference_build/chrome/resources/Inspector/Images/resourcesIcon.png Binary files differindex f7d79e3..982424d 100644 --- a/chrome/tools/test/reference_build/chrome/resources/Inspector/Images/resourcesIcon.png +++ b/chrome/tools/test/reference_build/chrome/resources/Inspector/Images/resourcesIcon.png diff --git a/chrome/tools/test/reference_build/chrome/resources/Inspector/Images/scriptsIcon.png b/chrome/tools/test/reference_build/chrome/resources/Inspector/Images/scriptsIcon.png Binary files differindex 31eb1c0e..213b31e 100644 --- a/chrome/tools/test/reference_build/chrome/resources/Inspector/Images/scriptsIcon.png +++ b/chrome/tools/test/reference_build/chrome/resources/Inspector/Images/scriptsIcon.png diff --git a/chrome/tools/test/reference_build/chrome/resources/Inspector/MetricsSidebarPane.js b/chrome/tools/test/reference_build/chrome/resources/Inspector/MetricsSidebarPane.js index e805560..a22a000 100644 --- a/chrome/tools/test/reference_build/chrome/resources/Inspector/MetricsSidebarPane.js +++ b/chrome/tools/test/reference_build/chrome/resources/Inspector/MetricsSidebarPane.js @@ -38,7 +38,12 @@ WebInspector.MetricsSidebarPane.prototype = { body.removeChildren(); - if (!node) + if (node) + this.node = node; + else + node = this.node; + + if (!node || !node.ownerDocument.defaultView) return; var style; @@ -50,12 +55,21 @@ WebInspector.MetricsSidebarPane.prototype = { var metricsElement = document.createElement("div"); metricsElement.className = "metrics"; - function boxPartValue(style, name, suffix) + function createBoxPartElement(style, name, side, suffix) { - var value = style.getPropertyValue(name + suffix); - if (value === "" || value === "0px") + var propertyName = (name !== "position" ? name + "-" : "") + side + suffix; + var value = style.getPropertyValue(propertyName); + if (value === "" || (name !== "position" && value === "0px")) + value = "\u2012"; + else if (name === "position" && value === "auto") value = "\u2012"; - return value.replace(/px$/, ""); + value = value.replace(/px$/, ""); + + var element = document.createElement("div"); + element.className = side; + element.textContent = value; + element.addEventListener("dblclick", this.startEditing.bind(this, element, name, propertyName), false); + return element; } // Display types for which margin is ignored. @@ -79,8 +93,13 @@ WebInspector.MetricsSidebarPane.prototype = { "table-row-group": true }; - var boxes = ["content", "padding", "border", "margin"]; - var boxLabels = [WebInspector.UIString("content"), WebInspector.UIString("padding"), WebInspector.UIString("border"), WebInspector.UIString("margin")]; + // Position types for which top, left, bottom and right are ignored. + var noPositionType = { + "static": true + }; + + var boxes = ["content", "padding", "border", "margin", "position"]; + var boxLabels = [WebInspector.UIString("content"), WebInspector.UIString("padding"), WebInspector.UIString("border"), WebInspector.UIString("margin"), WebInspector.UIString("position")]; var previousBox; for (var i = 0; i < boxes.length; ++i) { var name = boxes[i]; @@ -89,14 +108,26 @@ WebInspector.MetricsSidebarPane.prototype = { continue; if (name === "padding" && noPaddingDisplayType[style.display]) continue; + if (name === "position" && noPositionType[style.position]) + continue; var boxElement = document.createElement("div"); boxElement.className = name; if (name === "content") { var width = style.width.replace(/px$/, ""); + var widthElement = document.createElement("span"); + widthElement.textContent = width; + widthElement.addEventListener("dblclick", this.startEditing.bind(this, widthElement, "width", "width"), false); + var height = style.height.replace(/px$/, ""); - boxElement.textContent = width + " \u00D7 " + height; + var heightElement = document.createElement("span"); + heightElement.textContent = height; + heightElement.addEventListener("dblclick", this.startEditing.bind(this, heightElement, "height", "height"), false); + + boxElement.appendChild(widthElement); + boxElement.appendChild(document.createTextNode(" \u00D7 ")); + boxElement.appendChild(heightElement); } else { var suffix = (name === "border" ? "-width" : ""); @@ -105,28 +136,16 @@ WebInspector.MetricsSidebarPane.prototype = { labelElement.textContent = boxLabels[i]; boxElement.appendChild(labelElement); - var topElement = document.createElement("div"); - topElement.className = "top"; - topElement.textContent = boxPartValue(style, name + "-top", suffix); - boxElement.appendChild(topElement); - - var leftElement = document.createElement("div"); - leftElement.className = "left"; - leftElement.textContent = boxPartValue(style, name + "-left", suffix); - boxElement.appendChild(leftElement); + boxElement.appendChild(createBoxPartElement.call(this, style, name, "top", suffix)); + boxElement.appendChild(document.createElement("br")); + boxElement.appendChild(createBoxPartElement.call(this, style, name, "left", suffix)); if (previousBox) boxElement.appendChild(previousBox); - var rightElement = document.createElement("div"); - rightElement.className = "right"; - rightElement.textContent = boxPartValue(style, name + "-right", suffix); - boxElement.appendChild(rightElement); - - var bottomElement = document.createElement("div"); - bottomElement.className = "bottom"; - bottomElement.textContent = boxPartValue(style, name + "-bottom", suffix); - boxElement.appendChild(bottomElement); + boxElement.appendChild(createBoxPartElement.call(this, style, name, "right", suffix)); + boxElement.appendChild(document.createElement("br")); + boxElement.appendChild(createBoxPartElement.call(this, style, name, "bottom", suffix)); } previousBox = boxElement; @@ -134,6 +153,42 @@ WebInspector.MetricsSidebarPane.prototype = { metricsElement.appendChild(previousBox); body.appendChild(metricsElement); + }, + + startEditing: function(targetElement, box, styleProperty) + { + if (WebInspector.isBeingEdited(targetElement)) + return; + + var context = { box: box, styleProperty: styleProperty }; + + WebInspector.startEditing(targetElement, this.editingCommitted.bind(this), this.editingCancelled.bind(this), context); + }, + + editingCancelled: function(element, context) + { + this.update(); + }, + + editingCommitted: function(element, userInput, previousContent, context) + { + if (userInput === previousContent) + return this.editingCancelled(element, context); // nothing changed, so cancel + + if (context.box !== "position" && (!userInput || userInput === "\u2012")) + userInput = "0px"; + else if (context.box === "position" && (!userInput || userInput === "\u2012")) + userInput = "auto"; + + // Append a "px" unit if the user input was just a number. + if (/^\d+$/.test(userInput)) + userInput += "px"; + + this.node.style.setProperty(context.styleProperty, userInput, ""); + + this.dispatchEventToListeners("metrics edited"); + + this.update(); } } diff --git a/chrome/tools/test/reference_build/chrome/resources/Inspector/Panel.js b/chrome/tools/test/reference_build/chrome/resources/Inspector/Panel.js index edf5751..5046f6b 100644 --- a/chrome/tools/test/reference_build/chrome/resources/Inspector/Panel.js +++ b/chrome/tools/test/reference_build/chrome/resources/Inspector/Panel.js @@ -41,7 +41,7 @@ WebInspector.Panel.prototype = { // Sample toolbar item as markup: // <button class="toolbar-item resources toggleable"> - // <img class="toolbar-icon"> + // <div class="toolbar-icon"></div> // <div class="toolbar-label">Resources</div> // </button> @@ -52,7 +52,7 @@ WebInspector.Panel.prototype = { if ("toolbarItemClass" in this) this._toolbarItem.addStyleClass(this.toolbarItemClass); - var iconElement = document.createElement("img"); + var iconElement = document.createElement("div"); iconElement.className = "toolbar-icon"; this._toolbarItem.appendChild(iconElement); @@ -97,7 +97,176 @@ WebInspector.Panel.prototype = { attach: function() { - document.getElementById("main-panels").appendChild(this.element); + if (!this.element.parentNode) + document.getElementById("main-panels").appendChild(this.element); + }, + + searchCanceled: function(startingNewSearch) + { + if (this._searchResults) { + for (var i = 0; i < this._searchResults.length; ++i) { + var view = this._searchResults[i]; + if (view.searchCanceled) + view.searchCanceled(); + delete view.currentQuery; + } + } + + WebInspector.updateSearchMatchesCount(0, this); + + if (this._currentSearchChunkIntervalIdentifier) { + clearInterval(this._currentSearchChunkIntervalIdentifier); + delete this._currentSearchChunkIntervalIdentifier; + } + + this._totalSearchMatches = 0; + this._currentSearchResultIndex = 0; + this._searchResults = []; + }, + + performSearch: function(query) + { + // Call searchCanceled since it will reset everything we need before doing a new search. + this.searchCanceled(true); + + var searchableViews = this.searchableViews; + if (!searchableViews || !searchableViews.length) + return; + + var parentElement = this.viewsContainerElement; + var visibleView = this.visibleView; + var sortFuction = this.searchResultsSortFunction; + + var matchesCountUpdateTimeout = null; + + function updateMatchesCount() + { + WebInspector.updateSearchMatchesCount(this._totalSearchMatches, this); + matchesCountUpdateTimeout = null; + } + + function updateMatchesCountSoon() + { + if (matchesCountUpdateTimeout) + return; + // Update the matches count every half-second so it doesn't feel twitchy. + matchesCountUpdateTimeout = setTimeout(updateMatchesCount.bind(this), 500); + } + + function finishedCallback(view, searchMatches) + { + if (!searchMatches) + return; + + this._totalSearchMatches += searchMatches; + this._searchResults.push(view); + + if (sortFuction) + this._searchResults.sort(sortFuction); + + if (this.searchMatchFound) + this.searchMatchFound(view, searchMatches); + + updateMatchesCountSoon.call(this); + + if (view === visibleView) + view.jumpToFirstSearchResult(); + } + + var i = 0; + var panel = this; + var boundFinishedCallback = finishedCallback.bind(this); + var chunkIntervalIdentifier = null; + + // Split up the work into chunks so we don't block the + // UI thread while processing. + + function processChunk() + { + var view = searchableViews[i]; + + if (++i >= searchableViews.length) { + if (panel._currentSearchChunkIntervalIdentifier === chunkIntervalIdentifier) + delete panel._currentSearchChunkIntervalIdentifier; + clearInterval(chunkIntervalIdentifier); + } + + if (!view) + return; + + if (view.element.parentNode !== parentElement && view.element.parentNode && parentElement) + view.detach(); + + view.currentQuery = query; + view.performSearch(query, boundFinishedCallback); + } + + processChunk(); + + chunkIntervalIdentifier = setInterval(processChunk, 25); + this._currentSearchChunkIntervalIdentifier = chunkIntervalIdentifier; + }, + + jumpToNextSearchResult: function() + { + if (!this.showView || !this._searchResults || !this._searchResults.length) + return; + + var showFirstResult = false; + + this._currentSearchResultIndex = this._searchResults.indexOf(this.visibleView); + if (this._currentSearchResultIndex === -1) { + this._currentSearchResultIndex = 0; + showFirstResult = true; + } + + var currentView = this._searchResults[this._currentSearchResultIndex]; + + if (currentView.showingLastSearchResult()) { + if (++this._currentSearchResultIndex >= this._searchResults.length) + this._currentSearchResultIndex = 0; + currentView = this._searchResults[this._currentSearchResultIndex]; + showFirstResult = true; + } + + if (currentView !== this.visibleView) + this.showView(currentView); + + if (showFirstResult) + currentView.jumpToFirstSearchResult(); + else + currentView.jumpToNextSearchResult(); + }, + + jumpToPreviousSearchResult: function() + { + if (!this.showView || !this._searchResults || !this._searchResults.length) + return; + + var showLastResult = false; + + this._currentSearchResultIndex = this._searchResults.indexOf(this.visibleView); + if (this._currentSearchResultIndex === -1) { + this._currentSearchResultIndex = 0; + showLastResult = true; + } + + var currentView = this._searchResults[this._currentSearchResultIndex]; + + if (currentView.showingFirstSearchResult()) { + if (--this._currentSearchResultIndex < 0) + this._currentSearchResultIndex = (this._searchResults.length - 1); + currentView = this._searchResults[this._currentSearchResultIndex]; + showLastResult = true; + } + + if (currentView !== this.visibleView) + this.showView(currentView); + + if (showLastResult) + currentView.jumpToLastSearchResult(); + else + currentView.jumpToPreviousSearchResult(); } } diff --git a/chrome/tools/test/reference_build/chrome/resources/Inspector/PropertiesSection.js b/chrome/tools/test/reference_build/chrome/resources/Inspector/PropertiesSection.js index 160dae4..a4b2fba 100644 --- a/chrome/tools/test/reference_build/chrome/resources/Inspector/PropertiesSection.js +++ b/chrome/tools/test/reference_build/chrome/resources/Inspector/PropertiesSection.js @@ -55,7 +55,7 @@ WebInspector.PropertiesSection = function(title, subtitle) this.title = title; this.subtitle = subtitle; - this.expanded = false; + this._expanded = false; } WebInspector.PropertiesSection.prototype = { @@ -69,7 +69,12 @@ WebInspector.PropertiesSection.prototype = { if (this._title === x) return; this._title = x; - this.titleElement.textContent = x; + + if (x instanceof Node) { + this.titleElement.removeChildren(); + this.titleElement.appendChild(x); + } else + this.titleElement.textContent = x; }, get subtitle() diff --git a/chrome/tools/test/reference_build/chrome/resources/Inspector/PropertiesSidebarPane.js b/chrome/tools/test/reference_build/chrome/resources/Inspector/PropertiesSidebarPane.js index 0266d53..70db805 100644 --- a/chrome/tools/test/reference_build/chrome/resources/Inspector/PropertiesSidebarPane.js +++ b/chrome/tools/test/reference_build/chrome/resources/Inspector/PropertiesSidebarPane.js @@ -52,88 +52,3 @@ WebInspector.PropertiesSidebarPane.prototype = { } WebInspector.PropertiesSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype; - -WebInspector.ObjectPropertiesSection = function(object) -{ - var title = Object.describe(object); - var subtitle; - if (title.match(/Prototype$/)) { - title = title.replace(/Prototype$/, ""); - subtitle = WebInspector.UIString("Prototype"); - } - - this.object = object; - - WebInspector.PropertiesSection.call(this, title, subtitle); -} - -WebInspector.ObjectPropertiesSection.prototype = { - onpopulate: function() - { - var properties = Object.sortedProperties(this.object); - for (var i = 0; i < properties.length; ++i) { - var propertyName = properties[i]; - if (!this.object.hasOwnProperty(propertyName) || propertyName === "__treeElementIdentifier") - continue; - this.propertiesTreeOutline.appendChild(new WebInspector.ObjectPropertyTreeElement(this.object, propertyName)); - } - } -} - -WebInspector.ObjectPropertiesSection.prototype.__proto__ = WebInspector.PropertiesSection.prototype; - -WebInspector.ObjectPropertyTreeElement = function(parentObject, propertyName) -{ - this.parentObject = parentObject; - this.propertyName = propertyName; - - var childObject = this.safePropertyValue(parentObject, propertyName); - var isGetter = parentObject.__lookupGetter__(propertyName); - - var title = "<span class=\"name\">" + propertyName.escapeHTML() + "</span>: "; - if (!isGetter) - title += "<span class=\"value\">" + Object.describe(childObject, true).escapeHTML() + "</span>"; - else - // FIXME: this should show something like "getter" once we can change localization (bug 16734). - title += "<span class=\"value dimmed\">—</span>"; - - var hasSubProperties = false; - var type = typeof childObject; - if (childObject && (type === "object" || type === "function")) { - for (subPropertyName in childObject) { - if (subPropertyName === "__treeElementIdentifier") - continue; - hasSubProperties = true; - break; - } - } - - TreeElement.call(this, title, null, hasSubProperties); -} - -WebInspector.ObjectPropertyTreeElement.prototype = { - safePropertyValue: function(object, propertyName) - { - var getter = object.__lookupGetter__(propertyName); - if (getter) - return; - return object[propertyName]; - }, - - onpopulate: function() - { - if (this.children.length) - return; - - var childObject = this.safePropertyValue(this.parentObject, this.propertyName); - var properties = Object.sortedProperties(childObject); - for (var i = 0; i < properties.length; ++i) { - var propertyName = properties[i]; - if (propertyName === "__treeElementIdentifier") - continue; - this.appendChild(new WebInspector.ObjectPropertyTreeElement(childObject, propertyName)); - } - } -} - -WebInspector.ObjectPropertyTreeElement.prototype.__proto__ = TreeElement.prototype; diff --git a/chrome/tools/test/reference_build/chrome/resources/Inspector/Resource.js b/chrome/tools/test/reference_build/chrome/resources/Inspector/Resource.js index b21cebd..058f232 100644 --- a/chrome/tools/test/reference_build/chrome/resources/Inspector/Resource.js +++ b/chrome/tools/test/reference_build/chrome/resources/Inspector/Resource.js @@ -93,7 +93,12 @@ WebInspector.Resource.prototype = { var oldURL = this._url; this._url = x; + + // FIXME: We should make the WebInspector object listen for the "url changed" event. + // Then resourceURLChanged can be removed. WebInspector.resourceURLChanged(this, oldURL); + + this.dispatchEventToListeners("url changed"); }, get domain() @@ -126,7 +131,9 @@ WebInspector.Resource.prototype = { var title = this.lastPathComponent; if (!title) title = this.displayDomain; - if (!title) + if (!title && this.url) + title = this.url.trimURL(WebInspector.mainResource ? WebInspector.mainResource.domain : ""); + if (title === "/") title = this.url; return title; }, @@ -141,7 +148,7 @@ WebInspector.Resource.prototype = { get startTime() { - return this._startTime; + return this._startTime || -1; }, set startTime(x) @@ -157,7 +164,7 @@ WebInspector.Resource.prototype = { get responseReceivedTime() { - return this._responseReceivedTime; + return this._responseReceivedTime || -1; }, set responseReceivedTime(x) @@ -173,7 +180,7 @@ WebInspector.Resource.prototype = { get endTime() { - return this._endTime; + return this._endTime || -1; }, set endTime(x) @@ -187,9 +194,23 @@ WebInspector.Resource.prototype = { WebInspector.panels.resources.refreshResource(this); }, + get duration() + { + if (this._endTime === -1 || this._startTime === -1) + return -1; + return this._endTime - this._startTime; + }, + + get latency() + { + if (this._responseReceivedTime === -1 || this._startTime === -1) + return -1; + return this._responseReceivedTime - this._startTime; + }, + get contentLength() { - return this._contentLength; + return this._contentLength || 0; }, set contentLength(x) @@ -205,7 +226,7 @@ WebInspector.Resource.prototype = { get expectedContentLength() { - return this._expectedContentLength; + return this._expectedContentLength || 0; }, set expectedContentLength(x) @@ -230,6 +251,7 @@ WebInspector.Resource.prototype = { if (x) { this._checkTips(); this._checkWarnings(); + this.dispatchEventToListeners("finished"); } }, @@ -340,8 +362,7 @@ WebInspector.Resource.prototype = { this._requestHeaders = x; delete this._sortedRequestHeaders; - if (WebInspector.panels.resources) - WebInspector.panels.resources.refreshResource(this); + this.dispatchEventToListeners("requestHeaders changed"); }, get sortedRequestHeaders() @@ -372,8 +393,7 @@ WebInspector.Resource.prototype = { this._responseHeaders = x; delete this._sortedResponseHeaders; - if (WebInspector.panels.resources) - WebInspector.panels.resources.refreshResource(this); + this.dispatchEventToListeners("responseHeaders changed"); }, get sortedResponseHeaders() @@ -389,37 +409,65 @@ WebInspector.Resource.prototype = { return this._sortedResponseHeaders; }, + get scripts() + { + if (!("_scripts" in this)) + this._scripts = []; + return this._scripts; + }, + + addScript: function(script) + { + if (!script) + return; + this.scripts.unshift(script); + script.resource = this; + }, + + removeAllScripts: function() + { + if (!this._scripts) + return; + + for (var i = 0; i < this._scripts.length; ++i) { + if (this._scripts[i].resource === this) + delete this._scripts[i].resource; + } + + delete this._scripts; + }, + + removeScript: function(script) + { + if (!script) + return; + + if (script.resource === this) + delete script.resource; + + if (!this._scripts) + return; + + this._scripts.remove(script); + }, + get errors() { - if (!("_errors" in this)) - this._errors = 0; - return this._errors; + return this._errors || 0; }, set errors(x) { - if (this._errors === x) - return; - - var difference = x - this._errors; - WebInspector.errors += difference; this._errors = x; }, get warnings() { - if (!("_warnings" in this)) - this._warnings = 0; - return this._warnings; + return this._warnings || 0; }, set warnings(x) { - if (this._warnings === x) - return; - - var difference = x - this._warnings; - WebInspector.warnings += difference; this._warnings = x; }, @@ -441,8 +489,8 @@ WebInspector.Resource.prototype = { // Otherwise, we flood the Console with too many tips. /* var msg = new WebInspector.ConsoleMessage(WebInspector.ConsoleMessage.MessageSource.Other, - WebInspector.ConsoleMessage.MessageLevel.Tip, -1, this.url, tip.message); - WebInspector.consolePanel.addMessage(msg); + WebInspector.ConsoleMessage.MessageLevel.Tip, -1, this.url, null, 1, tip.message); + WebInspector.console.addMessage(msg); */ }, @@ -501,9 +549,9 @@ WebInspector.Resource.prototype = { case WebInspector.Warnings.IncorrectMIMEType.id: if (!this._mimeTypeIsConsistentWithType()) msg = new WebInspector.ConsoleMessage(WebInspector.ConsoleMessage.MessageSource.Other, - WebInspector.ConsoleMessage.MessageLevel.Warning, -1, this.url, - String.sprintf(WebInspector.Warnings.IncorrectMIMEType.message, - WebInspector.Resource.Type.toString(this.type), this.mimeType)); + WebInspector.ConsoleMessage.MessageLevel.Warning, -1, this.url, null, 1, + String.sprintf(WebInspector.Warnings.IncorrectMIMEType.message, + WebInspector.Resource.Type.toString(this.type), this.mimeType)); break; } @@ -512,16 +560,36 @@ WebInspector.Resource.prototype = { } } -WebInspector.Resource.CompareByTime = function(a, b) +WebInspector.Resource.prototype.__proto__ = WebInspector.Object.prototype; + +WebInspector.Resource.CompareByStartTime = function(a, b) +{ + if (a.startTime < b.startTime) + return -1; + if (a.startTime > b.startTime) + return 1; + return 0; +} + +WebInspector.Resource.CompareByResponseReceivedTime = function(a, b) { + if (a.responseReceivedTime === -1 && b.responseReceivedTime !== -1) + return 1; + if (a.responseReceivedTime !== -1 && b.responseReceivedTime === -1) + return -1; if (a.responseReceivedTime < b.responseReceivedTime) return -1; if (a.responseReceivedTime > b.responseReceivedTime) return 1; - if (a.startTime < b.startTime) - return -1; - if (a.startTime > b.startTime) + return 0; +} + +WebInspector.Resource.CompareByEndTime = function(a, b) +{ + if (a.endTime === -1 && b.endTime !== -1) return 1; + if (a.endTime !== -1 && b.endTime === -1) + return -1; if (a.endTime < b.endTime) return -1; if (a.endTime > b.endTime) @@ -529,16 +597,29 @@ WebInspector.Resource.CompareByTime = function(a, b) return 0; } -WebInspector.Resource.CompareBySize = function(a, b) +WebInspector.Resource.CompareByDuration = function(a, b) { - if (a.contentLength < b.contentLength) + if (a.duration < b.duration) return -1; - if (a.contentLength > b.contentLength) + if (a.duration > b.duration) return 1; return 0; } -WebInspector.Resource.CompareByDescendingSize = function(a, b) +WebInspector.Resource.CompareByLatency = function(a, b) { - return this.CompareBySize(a, b) * -1; + if (a.latency < b.latency) + return -1; + if (a.latency > b.latency) + return 1; + return 0; +} + +WebInspector.Resource.CompareBySize = function(a, b) +{ + if (a.contentLength < b.contentLength) + return -1; + if (a.contentLength > b.contentLength) + return 1; + return 0; } diff --git a/chrome/tools/test/reference_build/chrome/resources/Inspector/ResourceCategory.js b/chrome/tools/test/reference_build/chrome/resources/Inspector/ResourceCategory.js index c5591ea..fc508d0 100644 --- a/chrome/tools/test/reference_build/chrome/resources/Inspector/ResourceCategory.js +++ b/chrome/tools/test/reference_build/chrome/resources/Inspector/ResourceCategory.js @@ -58,13 +58,7 @@ WebInspector.ResourceCategory.prototype = { removeResource: function(resource) { - var resourcesLength = this.resources.length; - for (var i = 0; i < resourcesLength; ++i) { - if (this.resources[i] === resource) { - this.resources.splice(i, 1); - break; - } - } + this.resources.remove(resource, true); }, removeAllResources: function(resource) diff --git a/chrome/tools/test/reference_build/chrome/resources/Inspector/ResourceView.js b/chrome/tools/test/reference_build/chrome/resources/Inspector/ResourceView.js index 46d8a66..b480362 100644 --- a/chrome/tools/test/reference_build/chrome/resources/Inspector/ResourceView.js +++ b/chrome/tools/test/reference_build/chrome/resources/Inspector/ResourceView.js @@ -34,15 +34,106 @@ WebInspector.ResourceView = function(resource) this.resource = resource; + this.headersElement = document.createElement("div"); + this.headersElement.className = "resource-view-headers"; + this.element.appendChild(this.headersElement); + this.contentElement = document.createElement("div"); this.contentElement.className = "resource-view-content"; this.element.appendChild(this.contentElement); + + this.headersListElement = document.createElement("ol"); + this.headersListElement.className = "outline-disclosure"; + this.headersElement.appendChild(this.headersListElement); + + this.headersTreeOutline = new TreeOutline(this.headersListElement); + this.headersTreeOutline.expandTreeElementsWhenArrowing = true; + + this.urlTreeElement = new TreeElement("", null, false); + this.urlTreeElement.selectable = false; + this.headersTreeOutline.appendChild(this.urlTreeElement); + + this.requestHeadersTreeElement = new TreeElement("", null, true); + this.requestHeadersTreeElement.expanded = false; + this.requestHeadersTreeElement.selectable = false; + this.headersTreeOutline.appendChild(this.requestHeadersTreeElement); + + this.responseHeadersTreeElement = new TreeElement("", null, true); + this.responseHeadersTreeElement.expanded = false; + this.responseHeadersTreeElement.selectable = false; + this.headersTreeOutline.appendChild(this.responseHeadersTreeElement); + + this.headersVisible = true; + + resource.addEventListener("url changed", this._refreshURL, this); + resource.addEventListener("requestHeaders changed", this._refreshRequestHeaders, this); + resource.addEventListener("responseHeaders changed", this._refreshResponseHeaders, this); + + this._refreshURL(); + this._refreshRequestHeaders(); + this._refreshResponseHeaders(); } WebInspector.ResourceView.prototype = { + get headersVisible() + { + return this._headersVisible; + }, + + set headersVisible(x) + { + if (x === this._headersVisible) + return; + + this._headersVisible = x; + + if (x) + this.element.addStyleClass("headers-visible"); + else + this.element.removeStyleClass("headers-visible"); + }, + attach: function() { - document.getElementById("resource-views").appendChild(this.element); + if (!this.element.parentNode) { + var parentElement = (document.getElementById("resource-views") || document.getElementById("script-resource-views")); + if (parentElement) + parentElement.appendChild(this.element); + } + }, + + _refreshURL: function() + { + this.urlTreeElement.title = this.resource.url.escapeHTML(); + }, + + _refreshRequestHeaders: function() + { + this._refreshHeaders(WebInspector.UIString("Request Headers"), this.resource.sortedRequestHeaders, this.requestHeadersTreeElement); + }, + + _refreshResponseHeaders: function() + { + this._refreshHeaders(WebInspector.UIString("Response Headers"), this.resource.sortedResponseHeaders, this.responseHeadersTreeElement); + }, + + _refreshHeaders: function(title, headers, headersTreeElement) + { + headersTreeElement.removeChildren(); + + var length = headers.length; + headersTreeElement.title = title.escapeHTML() + "<span class=\"header-count\">" + WebInspector.UIString(" (%d)", length) + "</span>"; + headersTreeElement.hidden = !length; + + var length = headers.length; + for (var i = 0; i < length; ++i) { + var title = "<div class=\"header-name\">" + headers[i].header.escapeHTML() + ":</div>"; + title += "<div class=\"header-value\">" + headers[i].value.escapeHTML() + "</div>" + + var headerTreeElement = new TreeElement(title, null, false); + headerTreeElement.selectable = false; + headersTreeElement.appendChild(headerTreeElement); + } } } diff --git a/chrome/tools/test/reference_build/chrome/resources/Inspector/ResourcesPanel.js b/chrome/tools/test/reference_build/chrome/resources/Inspector/ResourcesPanel.js index 57c45c7..e02baf3 100644 --- a/chrome/tools/test/reference_build/chrome/resources/Inspector/ResourcesPanel.js +++ b/chrome/tools/test/reference_build/chrome/resources/Inspector/ResourcesPanel.js @@ -1,5 +1,6 @@ /* * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008 Anthony Ricaud (rik24d@gmail.com) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,9 +33,9 @@ WebInspector.ResourcesPanel = function() this.element.addStyleClass("resources"); - this.resourceViews = document.createElement("div"); - this.resourceViews.id = "resource-views"; - this.element.appendChild(this.resourceViews); + this.viewsContainerElement = document.createElement("div"); + this.viewsContainerElement.id = "resource-views"; + this.element.appendChild(this.viewsContainerElement); this.containerElement = document.createElement("div"); this.containerElement.id = "resources-container"; @@ -59,6 +60,10 @@ WebInspector.ResourcesPanel = function() this.summaryElement.id = "resources-summary"; this.containerContentElement.appendChild(this.summaryElement); + this.resourcesGraphsElement = document.createElement("div"); + this.resourcesGraphsElement.id = "resources-graphs"; + this.containerContentElement.appendChild(this.resourcesGraphsElement); + this.dividersElement = document.createElement("div"); this.dividersElement.id = "resources-dividers"; this.containerContentElement.appendChild(this.dividersElement); @@ -84,14 +89,30 @@ WebInspector.ResourcesPanel = function() this.sidebarTree = new TreeOutline(this.sidebarTreeElement); var timeGraphItem = new WebInspector.SidebarTreeElement("resources-time-graph-sidebar-item", WebInspector.UIString("Time")); - timeGraphItem.calculator = new WebInspector.ResourceTransferTimeCalculator(); timeGraphItem.onselect = this._graphSelected.bind(this); - timeGraphItem.calculator._graphsTreeElement = timeGraphItem; + + var transferTimeCalculator = new WebInspector.ResourceTransferTimeCalculator(); + var transferDurationCalculator = new WebInspector.ResourceTransferDurationCalculator(); + + timeGraphItem.sortingOptions = [ + { name: WebInspector.UIString("Sort by Start Time"), sortingFunction: WebInspector.ResourceSidebarTreeElement.CompareByAscendingStartTime, calculator: transferTimeCalculator }, + { name: WebInspector.UIString("Sort by Response Time"), sortingFunction: WebInspector.ResourceSidebarTreeElement.CompareByAscendingResponseReceivedTime, calculator: transferTimeCalculator }, + { name: WebInspector.UIString("Sort by End Time"), sortingFunction: WebInspector.ResourceSidebarTreeElement.CompareByAscendingEndTime, calculator: transferTimeCalculator }, + { name: WebInspector.UIString("Sort by Duration"), sortingFunction: WebInspector.ResourceSidebarTreeElement.CompareByDescendingDuration, calculator: transferDurationCalculator }, + { name: WebInspector.UIString("Sort by Latency"), sortingFunction: WebInspector.ResourceSidebarTreeElement.CompareByDescendingLatency, calculator: transferDurationCalculator }, + ]; + + timeGraphItem.selectedSortingOptionIndex = 1; var sizeGraphItem = new WebInspector.SidebarTreeElement("resources-size-graph-sidebar-item", WebInspector.UIString("Size")); - sizeGraphItem.calculator = new WebInspector.ResourceTransferSizeCalculator(); sizeGraphItem.onselect = this._graphSelected.bind(this); - sizeGraphItem.calculator._graphsTreeElement = sizeGraphItem; + + var transferSizeCalculator = new WebInspector.ResourceTransferSizeCalculator(); + sizeGraphItem.sortingOptions = [ + { name: WebInspector.UIString("Sort by Size"), sortingFunction: WebInspector.ResourceSidebarTreeElement.CompareByDescendingSize, calculator: transferSizeCalculator }, + ]; + + sizeGraphItem.selectedSortingOptionIndex = 0; this.graphsTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("GRAPHS"), {}, true); this.sidebarTree.appendChild(this.graphsTreeElement); @@ -108,25 +129,13 @@ WebInspector.ResourcesPanel = function() this.largerResourcesButton = document.createElement("button"); this.largerResourcesButton.id = "resources-larger-resources-status-bar-item"; this.largerResourcesButton.className = "status-bar-item toggled-on"; - this.largerResourcesButton.title = WebInspector.UIString("Use large resource rows."); + this.largerResourcesButton.title = WebInspector.UIString("Use small resource rows."); this.largerResourcesButton.addEventListener("click", this._toggleLargerResources.bind(this), false); this.sortingSelectElement = document.createElement("select"); this.sortingSelectElement.className = "status-bar-item"; this.sortingSelectElement.addEventListener("change", this._changeSortingFunction.bind(this), false); - var sortingOption = document.createElement("option"); - sortingOption.label = WebInspector.UIString("Sort by Time"); - sortingOption.sortingFunction = WebInspector.ResourceSidebarTreeElement.CompareByTime; - this.sortingSelectElement.appendChild(sortingOption); - - sortingOption = document.createElement("option"); - sortingOption.label = WebInspector.UIString("Sort by Size"); - sortingOption.sortingFunction = WebInspector.ResourceSidebarTreeElement.CompareByDescendingSize; - this.sortingSelectElement.appendChild(sortingOption); - - this.sortingFunction = WebInspector.ResourceSidebarTreeElement.CompareByTime; - this.reset(); timeGraphItem.select(); @@ -148,22 +157,104 @@ WebInspector.ResourcesPanel.prototype = { show: function() { WebInspector.Panel.prototype.show.call(this); + this._updateDividersLabelBarPosition(); this._updateSidebarWidth(); this.refreshIfNeeded(); + + var visibleView = this.visibleView; + if (visibleView) { + visibleView.headersVisible = true; + visibleView.show(this.viewsContainerElement); + } + + // Hide any views that are visible that are not this panel's current visible view. + // This can happen when a ResourceView is visible in the Scripts panel then switched + // to the this panel. + var resourcesLength = this._resources.length; + for (var i = 0; i < resourcesLength; ++i) { + var resource = this._resources[i]; + var view = resource._resourcesView; + if (!view || view === visibleView) + continue; + view.visible = false; + } }, resize: function() { this._updateGraphDividersIfNeeded(); - this._updateGraphBars(); - var visibleResourceView = this.visibleResourceView; - if (visibleResourceView && "resize" in visibleResourceView) - visibleResourceView.resize(); + var visibleView = this.visibleView; + if (visibleView && "resize" in visibleView) + visibleView.resize(); + }, + + get searchableViews() + { + var views = []; + + const visibleView = this.visibleView; + if (visibleView && visibleView.performSearch) + views.push(visibleView); + + var resourcesLength = this._resources.length; + for (var i = 0; i < resourcesLength; ++i) { + var resource = this._resources[i]; + if (!resource._resourcesTreeElement) + continue; + var resourceView = this.resourceViewForResource(resource); + if (!resourceView.performSearch || resourceView === visibleView) + continue; + views.push(resourceView); + } + + return views; + }, + + get searchResultsSortFunction() + { + const resourceTreeElementSortFunction = this.sortingFunction; + + function sortFuction(a, b) + { + return resourceTreeElementSortFunction(a.resource._resourcesTreeElement, b.resource._resourcesTreeElement); + } + + return sortFuction; + }, + + searchMatchFound: function(view, matches) + { + view.resource._resourcesTreeElement.searchMatches = matches; + }, + + searchCanceled: function(startingNewSearch) + { + WebInspector.Panel.prototype.searchCanceled.call(this, startingNewSearch); + + if (startingNewSearch || !this._resources) + return; + + for (var i = 0; i < this._resources.length; ++i) { + var resource = this._resources[i]; + if (resource._resourcesTreeElement) + resource._resourcesTreeElement.updateErrorsAndWarnings(); + } + }, + + performSearch: function(query) + { + for (var i = 0; i < this._resources.length; ++i) { + var resource = this._resources[i]; + if (resource._resourcesTreeElement) + resource._resourcesTreeElement.resetBubble(); + } + + WebInspector.Panel.prototype.performSearch.call(this, query); }, - get visibleResourceView() + get visibleView() { if (this.visibleResource) return this.visibleResource._resourcesView; @@ -177,12 +268,14 @@ WebInspector.ResourcesPanel.prototype = { set calculator(x) { + if (!x || this._calculator === x) + return; + this._calculator = x; - if (this._calculator) - this._calculator.reset(); - this._refreshAllResources(false, true, true); - this._updateGraphDividersIfNeeded(true); - this._updateSummaryGraph(); + this._calculator.reset(); + + this._staleResources = this._resources; + this.refresh(); }, get sortingFunction() @@ -196,24 +289,33 @@ WebInspector.ResourcesPanel.prototype = { this._sortResourcesIfNeeded(); }, - get needsRefresh() - { - return this._needsRefresh; - }, + get needsRefresh() + { + return this._needsRefresh; + }, + + set needsRefresh(x) + { + if (this._needsRefresh === x) + return; + + this._needsRefresh = x; - set needsRefresh(x) - { - if (this._needsRefresh === x) - return; - this._needsRefresh = x; - if (x && this.visible) - this.refresh(); + if (x) { + if (this.visible && !("_refreshTimeout" in this)) + this._refreshTimeout = setTimeout(this.refresh.bind(this), 500); + } else { + if ("_refreshTimeout" in this) { + clearTimeout(this._refreshTimeout); + delete this._refreshTimeout; + } + } }, - refreshIfNeeded: function() - { - if (this.needsRefresh) - this.refresh(); + refreshIfNeeded: function() + { + if (this.needsRefresh) + this.refresh(); }, refresh: function() @@ -221,8 +323,33 @@ WebInspector.ResourcesPanel.prototype = { this.needsRefresh = false; var staleResourcesLength = this._staleResources.length; + var boundariesChanged = false; + + for (var i = 0; i < staleResourcesLength; ++i) { + var resource = this._staleResources[i]; + if (!resource._resourcesTreeElement) { + // Create the resource tree element and graph. + resource._resourcesTreeElement = new WebInspector.ResourceSidebarTreeElement(resource); + resource._resourcesTreeElement._resourceGraph = new WebInspector.ResourceGraph(resource); + + this.resourcesTreeElement.appendChild(resource._resourcesTreeElement); + this.resourcesGraphsElement.appendChild(resource._resourcesTreeElement._resourceGraph.graphElement); + } + + resource._resourcesTreeElement.refresh(); + + if (this.calculator.updateBoundaries(resource)) + boundariesChanged = true; + } + + if (boundariesChanged) { + // The boundaries changed, so all resource graphs are stale. + this._staleResources = this._resources; + staleResourcesLength = this._staleResources.length; + } + for (var i = 0; i < staleResourcesLength; ++i) - this.refreshResource(this._staleResources[i], false, true, true); + this._staleResources[i]._resourcesTreeElement._resourceGraph.refresh(this.calculator); this._staleResources = []; @@ -235,6 +362,11 @@ WebInspector.ResourcesPanel.prototype = { { this.closeVisibleResource(); + this.containerElement.scrollTop = 0; + + delete this.currentQuery; + this.searchCanceled(); + if (this._calculator) this._calculator.reset(); @@ -255,7 +387,9 @@ WebInspector.ResourcesPanel.prototype = { this._staleResources = []; this.resourcesTreeElement.removeChildren(); - this.resourceViews.removeChildren(); + this.viewsContainerElement.removeChildren(); + this.resourcesGraphsElement.removeChildren(); + this.legendElement.removeChildren(); this._updateGraphDividersIfNeeded(true); @@ -265,37 +399,28 @@ WebInspector.ResourcesPanel.prototype = { addResource: function(resource) { this._resources.push(resource); - - var resourceTreeElement = new WebInspector.ResourceSidebarTreeElement(resource); - resource._resourcesTreeElement = resourceTreeElement; - - resourceTreeElement.updateGraphSideWidth(this.dividersElement.offsetWidth); - - this.resourcesTreeElement.appendChild(resourceTreeElement); - this.refreshResource(resource); }, removeResource: function(resource) { - if (this.visibleResourceView === resource._resourcesView) + if (this.visibleView === resource._resourcesView) this.closeVisibleResource(); - var resourcesLength = this._resources.length; - for (var i = 0; i < resourcesLength; ++i) { - if (this._resources[i] === resource) { - this._resources.splice(i, 1); - break; - } - } + this._resources.remove(resource, true); - this.resourcesTreeElement.removeChild(resource._resourcesTreeElement); + if (resource._resourcesTreeElement) { + this.resourcesTreeElement.removeChild(resource._resourcesTreeElement); + this.resourcesGraphsElement.removeChild(resource._resourcesTreeElement._resourceGraph.graphElement); + } resource.warnings = 0; resource.errors = 0; delete resource._resourcesTreeElement; delete resource._resourcesView; + + this._adjustScrollPosition(); }, addMessageToResource: function(resource, msg) @@ -305,16 +430,17 @@ WebInspector.ResourcesPanel.prototype = { switch (msg.level) { case WebInspector.ConsoleMessage.MessageLevel.Warning: - ++resource.warnings; + resource.warnings += msg.repeatDelta; break; case WebInspector.ConsoleMessage.MessageLevel.Error: - ++resource.errors; + resource.errors += msg.repeatDelta; break; } - resource._resourcesTreeElement.updateErrorsAndWarnings(); + if (!this.currentQuery && resource._resourcesTreeElement) + resource._resourcesTreeElement.updateErrorsAndWarnings(); - var view = this._resourceView(resource); + var view = this.resourceViewForResource(resource); if (view.addMessage) view.addMessage(msg); }, @@ -327,7 +453,8 @@ WebInspector.ResourcesPanel.prototype = { resource.warnings = 0; resource.errors = 0; - resource._resourcesTreeElement.updateErrorsAndWarnings(); + if (!this.currentQuery && resource._resourcesTreeElement) + resource._resourcesTreeElement.updateErrorsAndWarnings(); var view = resource._resourcesView; if (!view || !view.clearMessages) @@ -336,42 +463,10 @@ WebInspector.ResourcesPanel.prototype = { } }, - refreshResource: function(resource, skipBoundaryUpdate, skipSort, immediate) + refreshResource: function(resource) { - if (!this.visible) { - this._staleResources.push(resource); - this.needsRefresh = true; - return; - } - - if (!skipBoundaryUpdate) { - if (this._updateGraphBoundriesIfNeeded(resource, immediate)) - return; // _updateGraphBoundriesIfNeeded refreshes all resources if it returns true, so just return. - } - - if (!skipSort) { - if (immediate) - this._sortResourcesIfNeeded(); - else - this._sortResourcesSoonIfNeeded(); - } - - this._updateSummaryGraphSoon(); - - if (!resource._resourcesTreeElement) - return; - - resource._resourcesTreeElement.refresh(); - - var percentages = this.calculator.computeBarGraphPercentages(resource); - - var barLeftElement = resource._resourcesTreeElement.barLeftElement; - barLeftElement.style.left = percentages.start + "%"; - barLeftElement.style.right = (100 - percentages.end) + "%"; - - var barRightElement = resource._resourcesTreeElement.barRightElement; - barRightElement.style.left = percentages.middle + "%"; - barRightElement.style.right = (100 - percentages.end) + "%"; + this._staleResources.push(resource); + this.needsRefresh = true; }, recreateViewForResourceIfNeeded: function(resource) @@ -386,17 +481,20 @@ WebInspector.ResourcesPanel.prototype = { resource.warnings = 0; resource.errors = 0; - resource._resourcesTreeElement.updateErrorsAndWarnings(); + if (!this.currentQuery && resource._resourcesTreeElement) + resource._resourcesTreeElement.updateErrorsAndWarnings(); + + var oldView = resource._resourcesView; resource._resourcesView.detach(); delete resource._resourcesView; resource._resourcesView = newView; - if (resource !== this.visibleResource) - return; + newView.headersVisible = oldView.headersVisible; - newView.show(); + if (oldView.visible && oldView.element.parentNode) + newView.show(oldView.element.parentNode); }, showResource: function(resource, line) @@ -409,11 +507,16 @@ WebInspector.ResourcesPanel.prototype = { if (this.visibleResource && this.visibleResource._resourcesView) this.visibleResource._resourcesView.hide(); - var view = this._resourceView(resource); - view.show(); + var view = this.resourceViewForResource(resource); + view.headersVisible = true; + view.show(this.viewsContainerElement); - if (line && view.showLine) - view.showLine(line); + if (line) { + if (view.revealLine) + view.revealLine(line); + if (view.highlightLine) + view.highlightLine(line); + } if (resource._resourcesTreeElement) { resource._resourcesTreeElement.reveal(); @@ -425,6 +528,13 @@ WebInspector.ResourcesPanel.prototype = { this._updateSidebarWidth(); }, + showView: function(view) + { + if (!view) + return; + this.showResource(view.resource); + }, + closeVisibleResource: function() { this.containerElement.removeStyleClass("viewing-resource"); @@ -434,15 +544,24 @@ WebInspector.ResourcesPanel.prototype = { this.visibleResource._resourcesView.hide(); delete this.visibleResource; - if (this._calculator && this._calculator._graphsTreeElement) - this._calculator._graphsTreeElement.select(true); + if (this._lastSelectedGraphTreeElement) + this._lastSelectedGraphTreeElement.select(true); this._updateSidebarWidth(); }, + resourceViewForResource: function(resource) + { + if (!resource) + return null; + if (!resource._resourcesView) + resource._resourcesView = this._createResourceView(resource); + return resource._resourcesView; + }, + sourceFrameForResource: function(resource) { - var view = this._resourceView(resource); + var view = this.resourceViewForResource(resource); if (!view) return null; @@ -454,7 +573,7 @@ WebInspector.ResourcesPanel.prototype = { this.attach(); view.setupSourceFrameIfNeeded(); - return view.frameElement; + return view.sourceFrame; }, handleKeyEvent: function(event) @@ -496,20 +615,8 @@ WebInspector.ResourcesPanel.prototype = { return legendElement; }, - _sortResourcesSoonIfNeeded: function() - { - if ("_sortResourcesTimeout" in this) - return; - this._sortResourcesTimeout = setTimeout(this._sortResourcesIfNeeded.bind(this), 500); - }, - _sortResourcesIfNeeded: function() { - if ("_sortResourcesTimeout" in this) { - clearTimeout(this._sortResourcesTimeout); - delete this._sortResourcesTimeout; - } - var sortedElements = [].concat(this.resourcesTreeElement.children); sortedElements.sort(this.sortingFunction); @@ -518,50 +625,28 @@ WebInspector.ResourcesPanel.prototype = { var treeElement = sortedElements[i]; if (treeElement === this.resourcesTreeElement.children[i]) continue; + + var wasSelected = treeElement.selected; this.resourcesTreeElement.removeChild(treeElement); this.resourcesTreeElement.insertChild(treeElement, i); - } - }, - - _updateGraphBoundriesIfNeeded: function(resource, immediate) - { - var didChange = this.calculator.updateBoundries(resource); + if (wasSelected) + treeElement.select(true); - if (didChange) { - if (immediate) { - this._refreshAllResources(true, true, immediate); - this._updateGraphDividersIfNeeded(); - } else { - this._refreshAllResourcesSoon(true, true, immediate); - this._updateGraphDividersSoonIfNeeded(); - } + var graphElement = treeElement._resourceGraph.graphElement; + this.resourcesGraphsElement.insertBefore(graphElement, this.resourcesGraphsElement.children[i]); } - - return didChange; - }, - - _updateGraphDividersSoonIfNeeded: function() - { - if ("_updateGraphDividersTimeout" in this) - return; - this._updateGraphDividersTimeout = setTimeout(this._updateGraphDividersIfNeeded.bind(this), 500); }, _updateGraphDividersIfNeeded: function(force) { - if ("_updateGraphDividersTimeout" in this) { - clearTimeout(this._updateGraphDividersTimeout); - delete this._updateGraphDividersTimeout; - } - if (!this.visible) { this.needsRefresh = true; return; } if (document.body.offsetWidth <= 0) { - // The stylesheet hasn't loaded yet, so we need to update later. - setTimeout(this._updateGraphDividersIfNeeded.bind(this), 0); + // The stylesheet hasn't loaded yet or the window is closed, + // so we can't calculate what is need. Return early. return; } @@ -582,15 +667,7 @@ WebInspector.ResourcesPanel.prototype = { divider.addStyleClass("last"); divider.style.left = ((i / dividerCount) * 100) + "%"; - this.dividersElement.appendChild(divider); - } - - for (var i = 1; i <= dividerCount; ++i) { - var divider = document.createElement("div"); - divider.className = "resources-divider"; - if (i === dividerCount) - divider.addStyleClass("last"); - divider.style.left = ((i / dividerCount) * 100) + "%"; + this.dividersElement.appendChild(divider.cloneNode()); var label = document.createElement("div"); label.className = "resources-divider-label"; @@ -602,48 +679,6 @@ WebInspector.ResourcesPanel.prototype = { } }, - _updateGraphBars: function() - { - if (!this.visible) { - this.needsRefresh = true; - return; - } - - if (document.body.offsetWidth <= 0) { - // The stylesheet hasn't loaded yet, so we need to update later. - setTimeout(this._updateGraphBars.bind(this), 0); - return; - } - - var dividersElementWidth = this.dividersElement.offsetWidth; - var resourcesLength = this._resources.length; - for (var i = 0; i < resourcesLength; ++i) { - var resourceTreeItem = this._resources[i]._resourcesTreeElement; - if (!resourceTreeItem) - continue; - resourceTreeItem.updateGraphSideWidth(dividersElementWidth); - } - }, - - _refreshAllResourcesSoon: function(skipBoundaryUpdate, skipSort, immediate) - { - if ("_refreshAllResourcesTimeout" in this) - return; - this._refreshAllResourcesTimeout = setTimeout(this._refreshAllResources.bind(this), 500, skipBoundaryUpdate, skipSort, immediate); - }, - - _refreshAllResources: function(skipBoundaryUpdate, skipSort, immediate) - { - if ("_refreshAllResourcesTimeout" in this) { - clearTimeout(this._refreshAllResourcesTimeout); - delete this._refreshAllResourcesTimeout; - } - - var resourcesLength = this._resources.length; - for (var i = 0; i < resourcesLength; ++i) - this.refreshResource(this._resources[i], skipBoundaryUpdate, skipSort, immediate); - }, - _fadeOutRect: function(ctx, x, y, w, h, a1, a2) { ctx.save(); @@ -881,20 +916,8 @@ WebInspector.ResourcesPanel.prototype = { this._fadeOutRect(ctx, x, y + h + 1, w, h, 0.5, 0.0); }, - _updateSummaryGraphSoon: function() - { - if ("_updateSummaryGraphTimeout" in this) - return; - this._updateSummaryGraphTimeout = setTimeout(this._updateSummaryGraph.bind(this), (this._showingEmptySummaryGraph ? 0 : 500)); - }, - _updateSummaryGraph: function() { - if ("_updateSummaryGraphTimeout" in this) { - clearTimeout(this._updateSummaryGraphTimeout); - delete this._updateSummaryGraphTimeout; - } - var graphInfo = this.calculator.computeSummaryValues(this._resources); var categoryOrder = ["documents", "stylesheets", "images", "scripts", "xhr", "fonts", "other"]; @@ -903,9 +926,6 @@ WebInspector.ResourcesPanel.prototype = { this.legendElement.removeChildren(); - if (this.totalLegendLabel) - this.totalLegendLabel.parentNode.removeChild(this.totalLegendLabel); - for (var i = 0; i < categoryOrder.length; ++i) { var category = categoryOrder[i]; var size = graphInfo.categoryValues[category]; @@ -941,7 +961,24 @@ WebInspector.ResourcesPanel.prototype = { _graphSelected: function(treeElement) { - this.calculator = treeElement.calculator; + if (this._lastSelectedGraphTreeElement) + this._lastSelectedGraphTreeElement.selectedSortingOptionIndex = this.sortingSelectElement.selectedIndex; + + this._lastSelectedGraphTreeElement = treeElement; + + this.sortingSelectElement.removeChildren(); + for (var i = 0; i < treeElement.sortingOptions.length; ++i) { + var sortingOption = treeElement.sortingOptions[i]; + var option = document.createElement("option"); + option.label = sortingOption.name; + option.sortingFunction = sortingOption.sortingFunction; + option.calculator = sortingOption.calculator; + this.sortingSelectElement.appendChild(option); + } + + this.sortingSelectElement.selectedIndex = treeElement.selectedSortingOptionIndex; + this._changeSortingFunction(); + this.closeVisibleResource(); this.containerElement.scrollTop = 0; }, @@ -951,28 +988,32 @@ WebInspector.ResourcesPanel.prototype = { if (!this.resourcesTreeElement._childrenListNode) return; - if (this.resourcesTreeElement._childrenListNode.hasStyleClass("small")) { - this.resourcesTreeElement._childrenListNode.removeStyleClass("small"); - this.largerResourcesButton.addStyleClass("toggled-on"); - } else { - this.resourcesTreeElement._childrenListNode.addStyleClass("small"); + this.resourcesTreeElement.smallChildren = !this.resourcesTreeElement.smallChildren; + + if (this.resourcesTreeElement.smallChildren) { + this.resourcesGraphsElement.addStyleClass("small"); + this.largerResourcesButton.title = WebInspector.UIString("Use large resource rows."); this.largerResourcesButton.removeStyleClass("toggled-on"); + this._adjustScrollPosition(); + } else { + this.resourcesGraphsElement.removeStyleClass("small"); + this.largerResourcesButton.title = WebInspector.UIString("Use small resource rows."); + this.largerResourcesButton.addStyleClass("toggled-on"); } }, - _changeSortingFunction: function() + _adjustScrollPosition: function() { - var selectedOption = this.sortingSelectElement[this.sortingSelectElement.selectedIndex]; - this.sortingFunction = selectedOption.sortingFunction; + // Prevent the container from being scrolled off the end. + if ((this.containerElement.scrollTop + this.containerElement.offsetHeight) > this.sidebarElement.offsetHeight) + this.containerElement.scrollTop = (this.sidebarElement.offsetHeight - this.containerElement.offsetHeight); }, - _resourceView: function(resource) + _changeSortingFunction: function() { - if (!resource) - return null; - if (!resource._resourcesView) - resource._resourcesView = this._createResourceView(resource); - return resource._resourcesView; + var selectedOption = this.sortingSelectElement[this.sortingSelectElement.selectedIndex]; + this.sortingFunction = selectedOption.sortingFunction; + this.calculator = selectedOption.calculator; }, _createResourceView: function(resource) @@ -1012,8 +1053,8 @@ WebInspector.ResourcesPanel.prototype = { _updateSidebarWidth: function(width) { if (this.sidebarElement.offsetWidth <= 0) { - // The stylesheet hasn't loaded yet, so we need to update later. - setTimeout(this._updateSidebarWidth.bind(this), 0, width); + // The stylesheet hasn't loaded yet or the window is closed, + // so we can't calculate what is need. Return early. return; } @@ -1036,11 +1077,14 @@ WebInspector.ResourcesPanel.prototype = { } this.containerContentElement.style.left = width + "px"; - this.resourceViews.style.left = width + "px"; + this.viewsContainerElement.style.left = width + "px"; this.sidebarResizeElement.style.left = (width - 3) + "px"; - this._updateGraphBars(); this._updateGraphDividersIfNeeded(); + + var visibleView = this.visibleView; + if (visibleView && "resize" in visibleView) + visibleView.resize(); } } @@ -1076,12 +1120,21 @@ WebInspector.ResourceCalculator.prototype = { return {start: 0, middle: 0, end: (this._value(resource) / this.boundarySpan) * 100}; }, + computeBarGraphLabels: function(resource) + { + const label = this.formatValue(this._value(resource)); + var tooltip = label; + if (resource.cached) + tooltip = WebInspector.UIString("%s (from cache)", tooltip); + return {left: label, right: label, tooltip: tooltip}; + }, + get boundarySpan() { return this.maximumBoundary - this.minimumBoundary; }, - updateBoundries: function(resource) + updateBoundaries: function(resource) { this.minimumBoundary = 0; @@ -1111,12 +1164,13 @@ WebInspector.ResourceCalculator.prototype = { } } -WebInspector.ResourceTransferTimeCalculator = function() +WebInspector.ResourceTimeCalculator = function(startAtZero) { WebInspector.ResourceCalculator.call(this); + this.startAtZero = startAtZero; } -WebInspector.ResourceTransferTimeCalculator.prototype = { +WebInspector.ResourceTimeCalculator.prototype = { computeSummaryValues: function(resources) { var resourcesByCategory = {}; @@ -1177,31 +1231,69 @@ WebInspector.ResourceTransferTimeCalculator.prototype = { if (resource.startTime !== -1) var start = ((resource.startTime - this.minimumBoundary) / this.boundarySpan) * 100; else - var start = 100; - + var start = 0; + if (resource.responseReceivedTime !== -1) var middle = ((resource.responseReceivedTime - this.minimumBoundary) / this.boundarySpan) * 100; else - var middle = 100; - + var middle = (this.startAtZero ? start : 100); + if (resource.endTime !== -1) var end = ((resource.endTime - this.minimumBoundary) / this.boundarySpan) * 100; else - var end = 100; + var end = (this.startAtZero ? middle : 100); + + if (this.startAtZero) { + end -= start; + middle -= start; + start = 0; + } return {start: start, middle: middle, end: end}; }, - updateBoundries: function(resource) + computeBarGraphLabels: function(resource) + { + var leftLabel = ""; + if (resource.latency > 0) + leftLabel = this.formatValue(resource.latency); + + var rightLabel = ""; + if (resource.responseReceivedTime !== -1 && resource.endTime !== -1) + rightLabel = this.formatValue(resource.endTime - resource.responseReceivedTime); + + if (leftLabel && rightLabel) { + var total = this.formatValue(resource.duration); + var tooltip = WebInspector.UIString("%s latency, %s download (%s total)", leftLabel, rightLabel, total); + } else if (leftLabel) + var tooltip = WebInspector.UIString("%s latency", leftLabel); + else if (rightLabel) + var tooltip = WebInspector.UIString("%s download", rightLabel); + + if (resource.cached) + tooltip = WebInspector.UIString("%s (from cache)", tooltip); + + return {left: leftLabel, right: rightLabel, tooltip: tooltip}; + }, + + updateBoundaries: function(resource) { var didChange = false; - if (resource.startTime !== -1 && (typeof this.minimumBoundary === "undefined" || resource.startTime < this.minimumBoundary)) { - this.minimumBoundary = resource.startTime; + + var lowerBound; + if (this.startAtZero) + lowerBound = 0; + else + lowerBound = this._lowerBound(resource); + + if (lowerBound !== -1 && (typeof this.minimumBoundary === "undefined" || lowerBound < this.minimumBoundary)) { + this.minimumBoundary = lowerBound; didChange = true; } - if (resource.endTime !== -1 && (typeof this.maximumBoundary === "undefined" || resource.endTime > this.maximumBoundary)) { - this.maximumBoundary = resource.endTime; + var upperBound = this._upperBound(resource); + if (upperBound !== -1 && (typeof this.maximumBoundary === "undefined" || upperBound > this.maximumBoundary)) { + this.maximumBoundary = upperBound; didChange = true; } @@ -1211,10 +1303,63 @@ WebInspector.ResourceTransferTimeCalculator.prototype = { formatValue: function(value) { return Number.secondsToString(value, WebInspector.UIString.bind(WebInspector)); + }, + + _lowerBound: function(resource) + { + return 0; + }, + + _upperBound: function(resource) + { + return 0; + }, +} + +WebInspector.ResourceTimeCalculator.prototype.__proto__ = WebInspector.ResourceCalculator.prototype; + +WebInspector.ResourceTransferTimeCalculator = function() +{ + WebInspector.ResourceTimeCalculator.call(this, false); +} + +WebInspector.ResourceTransferTimeCalculator.prototype = { + formatValue: function(value) + { + return Number.secondsToString(value, WebInspector.UIString.bind(WebInspector)); + }, + + _lowerBound: function(resource) + { + return resource.startTime; + }, + + _upperBound: function(resource) + { + return resource.endTime; + } +} + +WebInspector.ResourceTransferTimeCalculator.prototype.__proto__ = WebInspector.ResourceTimeCalculator.prototype; + +WebInspector.ResourceTransferDurationCalculator = function() +{ + WebInspector.ResourceTimeCalculator.call(this, true); +} + +WebInspector.ResourceTransferDurationCalculator.prototype = { + formatValue: function(value) + { + return Number.secondsToString(value, WebInspector.UIString.bind(WebInspector)); + }, + + _upperBound: function(resource) + { + return resource.duration; } } -WebInspector.ResourceTransferTimeCalculator.prototype.__proto__ = WebInspector.ResourceCalculator.prototype; +WebInspector.ResourceTransferDurationCalculator.prototype.__proto__ = WebInspector.ResourceTimeCalculator.prototype; WebInspector.ResourceTransferSizeCalculator = function() { @@ -1239,24 +1384,11 @@ WebInspector.ResourceSidebarTreeElement = function(resource) { this.resource = resource; + this.createIconElement(); + WebInspector.SidebarTreeElement.call(this, "resource-sidebar-tree-item", "", "", resource); this.refreshTitles(); - - this.graphSideElement = document.createElement("div"); - this.graphSideElement.className = "resources-graph-side"; - - this.barAreaElement = document.createElement("div"); - this.barAreaElement.className = "resources-graph-bar-area"; - this.graphSideElement.appendChild(this.barAreaElement); - - this.barLeftElement = document.createElement("div"); - this.barLeftElement.className = "resources-graph-bar waiting"; - this.barAreaElement.appendChild(this.barLeftElement); - - this.barRightElement = document.createElement("div"); - this.barRightElement.className = "resources-graph-bar"; - this.barAreaElement.appendChild(this.barRightElement); } WebInspector.ResourceSidebarTreeElement.prototype = { @@ -1264,7 +1396,6 @@ WebInspector.ResourceSidebarTreeElement.prototype = { { WebInspector.SidebarTreeElement.prototype.onattach.call(this); - this._listItemNode.appendChild(this.graphSideElement); this._listItemNode.addStyleClass("resources-category-" + this.resource.category.name); }, @@ -1301,54 +1432,218 @@ WebInspector.ResourceSidebarTreeElement.prototype = { // Do nothing. }, + createIconElement: function() + { + var previousIconElement = this.iconElement; + + if (this.resource.category === WebInspector.resourceCategories.images) { + var previewImage = document.createElement("img"); + previewImage.className = "image-resource-icon-preview"; + previewImage.src = this.resource.url; + + this.iconElement = document.createElement("div"); + this.iconElement.className = "icon"; + this.iconElement.appendChild(previewImage); + } else { + this.iconElement = document.createElement("img"); + this.iconElement.className = "icon"; + } + + if (previousIconElement) + previousIconElement.parentNode.replaceChild(this.iconElement, previousIconElement); + }, + refresh: function() { this.refreshTitles(); - var newClassName = "sidebar-tree-item resource-sidebar-tree-item resources-category-" + this.resource.category.name; - if (this._listItemNode && this._listItemNode.className !== newClassName) - this._listItemNode.className = newClassName; + if (!this._listItemNode.hasStyleClass("resources-category-" + this.resource.category.name)) { + this._listItemNode.removeMatchingStyleClasses("resources-category-\\w+"); + this._listItemNode.addStyleClass("resources-category-" + this.resource.category.name); + + this.createIconElement(); + } + }, + + resetBubble: function() + { + this.bubbleText = ""; + this.bubbleElement.removeStyleClass("search-matches"); + this.bubbleElement.removeStyleClass("warning"); + this.bubbleElement.removeStyleClass("error"); + }, + + set searchMatches(matches) + { + this.resetBubble(); + + if (!matches) + return; + + this.bubbleText = matches; + this.bubbleElement.addStyleClass("search-matches"); }, updateErrorsAndWarnings: function() { + this.resetBubble(); + if (this.resource.warnings || this.resource.errors) this.bubbleText = (this.resource.warnings + this.resource.errors); - else - this.bubbleText = ""; if (this.resource.warnings) this.bubbleElement.addStyleClass("warning"); - else - this.bubbleElement.removeStyleClass("warning"); if (this.resource.errors) this.bubbleElement.addStyleClass("error"); - else - this.bubbleElement.removeStyleClass("error"); - }, - - updateGraphSideWidth: function(width) - { - width += 1; // Add one to account for the sidebar border width. - this.graphSideElement.style.right = -width + "px"; - this.graphSideElement.style.width = width + "px"; } } -WebInspector.ResourceSidebarTreeElement.CompareByTime = function(a, b) +WebInspector.ResourceSidebarTreeElement.CompareByAscendingStartTime = function(a, b) { - return WebInspector.Resource.CompareByTime(a.resource, b.resource); + return WebInspector.Resource.CompareByStartTime(a.resource, b.resource) + || WebInspector.Resource.CompareByEndTime(a.resource, b.resource) + || WebInspector.Resource.CompareByResponseReceivedTime(a.resource, b.resource); } -WebInspector.ResourceSidebarTreeElement.CompareBySize = function(a, b) +WebInspector.ResourceSidebarTreeElement.CompareByAscendingResponseReceivedTime = function(a, b) { - return WebInspector.Resource.CompareBySize(a.resource, b.resource); + return WebInspector.Resource.CompareByResponseReceivedTime(a.resource, b.resource) + || WebInspector.Resource.CompareByStartTime(a.resource, b.resource) + || WebInspector.Resource.CompareByEndTime(a.resource, b.resource); +} + +WebInspector.ResourceSidebarTreeElement.CompareByAscendingEndTime = function(a, b) +{ + return WebInspector.Resource.CompareByEndTime(a.resource, b.resource) + || WebInspector.Resource.CompareByStartTime(a.resource, b.resource) + || WebInspector.Resource.CompareByResponseReceivedTime(a.resource, b.resource); +} + +WebInspector.ResourceSidebarTreeElement.CompareByDescendingDuration = function(a, b) +{ + return -1 * WebInspector.Resource.CompareByDuration(a.resource, b.resource); +} + +WebInspector.ResourceSidebarTreeElement.CompareByDescendingLatency = function(a, b) +{ + return -1 * WebInspector.Resource.CompareByLatency(a.resource, b.resource); } WebInspector.ResourceSidebarTreeElement.CompareByDescendingSize = function(a, b) { - return WebInspector.Resource.CompareByDescendingSize(a.resource, b.resource); + return -1 * WebInspector.Resource.CompareBySize(a.resource, b.resource); } WebInspector.ResourceSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype; + +WebInspector.ResourceGraph = function(resource) +{ + this.resource = resource; + + this._graphElement = document.createElement("div"); + this._graphElement.className = "resources-graph-side"; + this._graphElement.addEventListener("mouseover", this.refreshLabelPositions.bind(this), false); + + if (resource.cached) + this._graphElement.addStyleClass("resource-cached"); + + this._barAreaElement = document.createElement("div"); + this._barAreaElement.className = "resources-graph-bar-area hidden"; + this._graphElement.appendChild(this._barAreaElement); + + this._barLeftElement = document.createElement("div"); + this._barLeftElement.className = "resources-graph-bar waiting"; + this._barAreaElement.appendChild(this._barLeftElement); + + this._barRightElement = document.createElement("div"); + this._barRightElement.className = "resources-graph-bar"; + this._barAreaElement.appendChild(this._barRightElement); + + this._labelLeftElement = document.createElement("div"); + this._labelLeftElement.className = "resources-graph-label waiting"; + this._barAreaElement.appendChild(this._labelLeftElement); + + this._labelRightElement = document.createElement("div"); + this._labelRightElement.className = "resources-graph-label"; + this._barAreaElement.appendChild(this._labelRightElement); + + this._graphElement.addStyleClass("resources-category-" + resource.category.name); +} + +WebInspector.ResourceGraph.prototype = { + get graphElement() + { + return this._graphElement; + }, + + refreshLabelPositions: function() + { + this._labelLeftElement.style.removeProperty("left"); + this._labelLeftElement.style.removeProperty("right"); + this._labelLeftElement.removeStyleClass("before"); + this._labelLeftElement.removeStyleClass("hidden"); + + this._labelRightElement.style.removeProperty("left"); + this._labelRightElement.style.removeProperty("right"); + this._labelRightElement.removeStyleClass("after"); + this._labelRightElement.removeStyleClass("hidden"); + + const labelPadding = 10; + const rightBarWidth = (this._barRightElement.offsetWidth - labelPadding); + const leftBarWidth = ((this._barLeftElement.offsetWidth - this._barRightElement.offsetWidth) - labelPadding); + + var labelBefore = (this._labelLeftElement.offsetWidth > leftBarWidth); + var labelAfter = (this._labelRightElement.offsetWidth > rightBarWidth); + + if (labelBefore) { + if ((this._graphElement.offsetWidth * (this._percentages.start / 100)) < (this._labelLeftElement.offsetWidth + 10)) + this._labelLeftElement.addStyleClass("hidden"); + this._labelLeftElement.style.setProperty("right", (100 - this._percentages.start) + "%"); + this._labelLeftElement.addStyleClass("before"); + } else { + this._labelLeftElement.style.setProperty("left", this._percentages.start + "%"); + this._labelLeftElement.style.setProperty("right", (100 - this._percentages.middle) + "%"); + } + + if (labelAfter) { + if ((this._graphElement.offsetWidth * ((100 - this._percentages.end) / 100)) < (this._labelRightElement.offsetWidth + 10)) + this._labelRightElement.addStyleClass("hidden"); + this._labelRightElement.style.setProperty("left", this._percentages.end + "%"); + this._labelRightElement.addStyleClass("after"); + } else { + this._labelRightElement.style.setProperty("left", this._percentages.middle + "%"); + this._labelRightElement.style.setProperty("right", (100 - this._percentages.end) + "%"); + } + }, + + refresh: function(calculator) + { + var percentages = calculator.computeBarGraphPercentages(this.resource); + var labels = calculator.computeBarGraphLabels(this.resource); + + this._percentages = percentages; + + this._barAreaElement.removeStyleClass("hidden"); + + if (!this._graphElement.hasStyleClass("resources-category-" + this.resource.category.name)) { + this._graphElement.removeMatchingStyleClasses("resources-category-\\w+"); + this._graphElement.addStyleClass("resources-category-" + this.resource.category.name); + } + + this._barLeftElement.style.setProperty("left", percentages.start + "%"); + this._barLeftElement.style.setProperty("right", (100 - percentages.end) + "%"); + + this._barRightElement.style.setProperty("left", percentages.middle + "%"); + this._barRightElement.style.setProperty("right", (100 - percentages.end) + "%"); + + this._labelLeftElement.textContent = labels.left; + this._labelRightElement.textContent = labels.right; + + var tooltip = (labels.tooltip || ""); + this._barLeftElement.title = tooltip; + this._labelLeftElement.title = tooltip; + this._labelRightElement.title = tooltip; + this._barRightElement.title = tooltip; + } +} diff --git a/chrome/tools/test/reference_build/chrome/resources/Inspector/ScriptsPanel.js b/chrome/tools/test/reference_build/chrome/resources/Inspector/ScriptsPanel.js index dbc0e4c..38a6a96 100644 --- a/chrome/tools/test/reference_build/chrome/resources/Inspector/ScriptsPanel.js +++ b/chrome/tools/test/reference_build/chrome/resources/Inspector/ScriptsPanel.js @@ -40,6 +40,7 @@ WebInspector.ScriptsPanel = function() this.backButton.title = WebInspector.UIString("Show the previous script resource."); this.backButton.disabled = true; this.backButton.appendChild(document.createElement("img")); + this.backButton.addEventListener("click", this._goBack.bind(this), false); this.topStatusBar.appendChild(this.backButton); this.forwardButton = document.createElement("button"); @@ -48,17 +49,21 @@ WebInspector.ScriptsPanel = function() this.forwardButton.title = WebInspector.UIString("Show the next script resource."); this.forwardButton.disabled = true; this.forwardButton.appendChild(document.createElement("img")); + this.forwardButton.addEventListener("click", this._goForward.bind(this), false); this.topStatusBar.appendChild(this.forwardButton); this.filesSelectElement = document.createElement("select"); this.filesSelectElement.className = "status-bar-item"; this.filesSelectElement.id = "scripts-files"; + this.filesSelectElement.addEventListener("change", this._changeVisibleFile.bind(this), false); this.topStatusBar.appendChild(this.filesSelectElement); this.functionsSelectElement = document.createElement("select"); this.functionsSelectElement.className = "status-bar-item"; this.functionsSelectElement.id = "scripts-functions"; - this.topStatusBar.appendChild(this.functionsSelectElement); + + // FIXME: append the functions select element to the top status bar when it is implemented. + // this.topStatusBar.appendChild(this.functionsSelectElement); this.sidebarButtonsElement = document.createElement("div"); this.sidebarButtonsElement.id = "scripts-sidebar-buttons"; @@ -70,6 +75,7 @@ WebInspector.ScriptsPanel = function() this.pauseButton.title = WebInspector.UIString("Pause script execution."); this.pauseButton.disabled = true; this.pauseButton.appendChild(document.createElement("img")); + this.pauseButton.addEventListener("click", this._togglePause.bind(this), false); this.sidebarButtonsElement.appendChild(this.pauseButton); this.stepOverButton = document.createElement("button"); @@ -77,6 +83,7 @@ WebInspector.ScriptsPanel = function() this.stepOverButton.id = "scripts-step-over"; this.stepOverButton.title = WebInspector.UIString("Step over next function call."); this.stepOverButton.disabled = true; + this.stepOverButton.addEventListener("click", this._stepOverClicked.bind(this), false); this.stepOverButton.appendChild(document.createElement("img")); this.sidebarButtonsElement.appendChild(this.stepOverButton); @@ -85,6 +92,7 @@ WebInspector.ScriptsPanel = function() this.stepIntoButton.id = "scripts-step-into"; this.stepIntoButton.title = WebInspector.UIString("Step into next function call."); this.stepIntoButton.disabled = true; + this.stepIntoButton.addEventListener("click", this._stepIntoClicked.bind(this), false); this.stepIntoButton.appendChild(document.createElement("img")); this.sidebarButtonsElement.appendChild(this.stepIntoButton); @@ -93,6 +101,7 @@ WebInspector.ScriptsPanel = function() this.stepOutButton.id = "scripts-step-out"; this.stepOutButton.title = WebInspector.UIString("Step out of current function."); this.stepOutButton.disabled = true; + this.stepOutButton.addEventListener("click", this._stepOutClicked.bind(this), false); this.stepOutButton.appendChild(document.createElement("img")); this.sidebarButtonsElement.appendChild(this.stepOutButton); @@ -100,8 +109,8 @@ WebInspector.ScriptsPanel = function() this.debuggerStatusElement.id = "scripts-debugger-status"; this.sidebarButtonsElement.appendChild(this.debuggerStatusElement); - this.scriptResourceViews = document.createElement("div"); - this.scriptResourceViews.id = "script-resource-views"; + this.viewsContainerElement = document.createElement("div"); + this.viewsContainerElement.id = "script-resource-views"; this.sidebarElement = document.createElement("div"); this.sidebarElement.id = "scripts-sidebar"; @@ -117,19 +126,42 @@ WebInspector.ScriptsPanel = function() this.sidebarPanes = {}; this.sidebarPanes.callstack = new WebInspector.CallStackSidebarPane(); + this.sidebarPanes.scopechain = new WebInspector.ScopeChainSidebarPane(); this.sidebarPanes.breakpoints = new WebInspector.BreakpointsSidebarPane(); for (var pane in this.sidebarPanes) this.sidebarElement.appendChild(this.sidebarPanes[pane].element); - this.element.appendChild(this.scriptResourceViews); + // FIXME: remove the following line of code when the Breakpoints pane has content. + this.sidebarElement.removeChild(this.sidebarPanes.breakpoints.element); + + this.sidebarPanes.callstack.expanded = true; + this.sidebarPanes.callstack.addEventListener("call frame selected", this._callFrameSelected, this); + + this.sidebarPanes.scopechain.expanded = true; + + var panelEnablerHeading = WebInspector.UIString("You need to enable debugging before you can use the Scripts panel."); + var panelEnablerDisclaimer = WebInspector.UIString("Enabling debugging will make scripts run slower."); + var panelEnablerButton = WebInspector.UIString("Enable Debugging"); + + this.panelEnablerView = new WebInspector.PanelEnablerView("scripts", panelEnablerHeading, panelEnablerDisclaimer, panelEnablerButton); + this.panelEnablerView.addEventListener("enable clicked", this._enableDebugging, this); + + this.element.appendChild(this.panelEnablerView.element); + this.element.appendChild(this.viewsContainerElement); this.element.appendChild(this.sidebarElement); this.element.appendChild(this.sidebarResizeElement); - this.debuggingButton = document.createElement("button"); - this.debuggingButton.id = "scripts-debugging-status-bar-item"; - this.debuggingButton.className = "status-bar-item"; - this.debuggingButton.addEventListener("click", this._toggleDebugging.bind(this), false); + this.enableToggleButton = document.createElement("button"); + this.enableToggleButton.className = "enable-toggle-status-bar-item status-bar-item"; + this.enableToggleButton.addEventListener("click", this._toggleDebugging.bind(this), false); + + this.pauseOnExceptionButton = document.createElement("button"); + this.pauseOnExceptionButton.id = "scripts-pause-on-exceptions-status-bar-item"; + this.pauseOnExceptionButton.className = "status-bar-item"; + this.pauseOnExceptionButton.addEventListener("click", this._togglePauseOnExceptions.bind(this), false); + + this._breakpointsURLMap = {}; this.reset(); } @@ -144,18 +176,443 @@ WebInspector.ScriptsPanel.prototype = { get statusBarItems() { - return [this.debuggingButton]; + return [this.enableToggleButton, this.pauseOnExceptionButton]; + }, + + get paused() + { + return this._paused; }, show: function() { WebInspector.Panel.prototype.show.call(this); this.sidebarResizeElement.style.right = (this.sidebarElement.offsetWidth - 3) + "px"; + + if (this.visibleView) { + if (this.visibleView instanceof WebInspector.ResourceView) + this.visibleView.headersVisible = false; + this.visibleView.show(this.viewsContainerElement); + } + + // Hide any views that are visible that are not this panel's current visible view. + // This can happen when a ResourceView is visible in the Resources panel then switched + // to the this panel. + for (var sourceID in this._sourceIDMap) { + var scriptOrResource = this._sourceIDMap[sourceID]; + var view = this._sourceViewForScriptOrResource(scriptOrResource); + if (!view || view === this.visibleView) + continue; + view.visible = false; + } }, - reset: function() + get searchableViews() + { + var views = []; + + const visibleView = this.visibleView; + if (visibleView && visibleView.performSearch) { + visibleView.alreadySearching = true; + views.push(visibleView); + } + + for (var sourceID in this._sourceIDMap) { + var scriptOrResource = this._sourceIDMap[sourceID]; + var view = this._sourceViewForScriptOrResource(scriptOrResource); + if (!view || !view.performSearch || view.alreadySearching) + continue; + + view.alreadySearching = true; + views.push(view); + } + + for (var i = 0; i < views.length; ++i) + delete views[i].alreadySearching; + + return views; + }, + + addScript: function(sourceID, sourceURL, source, startingLine, errorLine, errorMessage) + { + var script = new WebInspector.Script(sourceID, sourceURL, source, startingLine, errorLine, errorMessage); + + if (sourceURL in WebInspector.resourceURLMap) { + var resource = WebInspector.resourceURLMap[sourceURL]; + resource.addScript(script); + } + + if (sourceURL in this._breakpointsURLMap && sourceID) { + var breakpoints = this._breakpointsURLMap[sourceURL]; + var breakpointsLength = breakpoints.length; + for (var i = 0; i < breakpointsLength; ++i) { + var breakpoint = breakpoints[i]; + if (startingLine <= breakpoint.line) { + breakpoint.sourceID = sourceID; + if (breakpoint.enabled) + InspectorController.addBreakpoint(breakpoint.sourceID, breakpoint.line); + } + } + } + + if (sourceID) + this._sourceIDMap[sourceID] = (resource || script); + + this._addScriptToFilesMenu(script); + }, + + addBreakpoint: function(breakpoint) + { + this.sidebarPanes.breakpoints.addBreakpoint(breakpoint); + + var sourceFrame; + if (breakpoint.url) { + if (!(breakpoint.url in this._breakpointsURLMap)) + this._breakpointsURLMap[breakpoint.url] = []; + this._breakpointsURLMap[breakpoint.url].unshift(breakpoint); + + if (breakpoint.url in WebInspector.resourceURLMap) { + var resource = WebInspector.resourceURLMap[breakpoint.url]; + sourceFrame = this._sourceFrameForScriptOrResource(resource); + } + } + + if (breakpoint.sourceID && !sourceFrame) { + var object = this._sourceIDMap[breakpoint.sourceID] + sourceFrame = this._sourceFrameForScriptOrResource(object); + } + + if (sourceFrame) + sourceFrame.addBreakpoint(breakpoint); + }, + + removeBreakpoint: function(breakpoint) + { + this.sidebarPanes.breakpoints.removeBreakpoint(breakpoint); + + var sourceFrame; + if (breakpoint.url && breakpoint.url in this._breakpointsURLMap) { + var breakpoints = this._breakpointsURLMap[breakpoint.url]; + breakpoints.remove(breakpoint); + if (!breakpoints.length) + delete this._breakpointsURLMap[breakpoint.url]; + + if (breakpoint.url in WebInspector.resourceURLMap) { + var resource = WebInspector.resourceURLMap[breakpoint.url]; + sourceFrame = this._sourceFrameForScriptOrResource(resource); + } + } + + if (breakpoint.sourceID && !sourceFrame) { + var object = this._sourceIDMap[breakpoint.sourceID] + sourceFrame = this._sourceFrameForScriptOrResource(object); + } + + if (sourceFrame) + sourceFrame.removeBreakpoint(breakpoint); + }, + + evaluateInSelectedCallFrame: function(code, updateInterface) + { + var selectedCallFrame = this.sidebarPanes.callstack.selectedCallFrame; + if (!this._paused || !selectedCallFrame) + return; + if (typeof updateInterface === "undefined") + updateInterface = true; + var result = selectedCallFrame.evaluate(code); + if (updateInterface) + this.sidebarPanes.scopechain.update(selectedCallFrame); + return result; + }, + + variablesInScopeForSelectedCallFrame: function() { + var selectedCallFrame = this.sidebarPanes.callstack.selectedCallFrame; + if (!this._paused || !selectedCallFrame) + return {}; + + var result = {}; + var scopeChain = selectedCallFrame.scopeChain; + for (var i = 0; i < scopeChain.length; ++i) { + var scopeObject = scopeChain[i]; + for (var property in scopeObject) + result[property] = true; + } + + return result; + }, + + debuggerPaused: function() + { + this._paused = true; + this._waitingToPause = false; + this._stepping = false; + this._updateDebuggerButtons(); + + var callStackPane = this.sidebarPanes.callstack; + var currentFrame = InspectorController.currentCallFrame(); + callStackPane.update(currentFrame, this._sourceIDMap); + callStackPane.selectedCallFrame = currentFrame; + + WebInspector.currentPanel = this; + window.focus(); + }, + + debuggerWasEnabled: function() + { + this.reset(); + }, + + debuggerWasDisabled: function() + { + this.reset(); + }, + + reset: function() + { + this.visibleView = null; + + delete this.currentQuery; + this.searchCanceled(); + + if (!InspectorController.debuggerEnabled()) { + this._paused = false; + this._waitingToPause = false; + this._stepping = false; + } + + this._clearInterface(); + + this._backForwardList = []; + this._currentBackForwardIndex = -1; + this._updateBackAndForwardButtons(); + + this._scriptsForURLsInFilesSelect = {}; + this.filesSelectElement.removeChildren(); + this.functionsSelectElement.removeChildren(); + this.viewsContainerElement.removeChildren(); + + if (this._sourceIDMap) { + for (var sourceID in this._sourceIDMap) { + var object = this._sourceIDMap[sourceID]; + if (object instanceof WebInspector.Resource) + object.removeAllScripts(); + } + } + + this._sourceIDMap = {}; + }, + + get visibleView() + { + return this._visibleView; + }, + + set visibleView(x) + { + if (this._visibleView === x) + return; + + if (this._visibleView) + this._visibleView.hide(); + + this._visibleView = x; + + if (x) + x.show(this.viewsContainerElement); + }, + + canShowResource: function(resource) + { + return resource && resource.scripts.length && InspectorController.debuggerEnabled(); + }, + + showScript: function(script, line) + { + this._showScriptOrResource(script, line, true); + }, + + showResource: function(resource, line) + { + this._showScriptOrResource(resource, line, true); + }, + + showView: function(view) + { + if (!view) + return; + this._showScriptOrResource((view.resource || view.script)); + }, + + scriptViewForScript: function(script) + { + if (!script) + return null; + if (!script._scriptView) + script._scriptView = new WebInspector.ScriptView(script); + return script._scriptView; + }, + + sourceFrameForScript: function(script) + { + var view = this.scriptViewForScript(script); + if (!view) + return null; + + // Setting up the source frame requires that we be attached. + if (!this.element.parentNode) + this.attach(); + + view.setupSourceFrameIfNeeded(); + return view.sourceFrame; + }, + + _sourceViewForScriptOrResource: function(scriptOrResource) + { + if (scriptOrResource instanceof WebInspector.Resource) { + if (!WebInspector.panels.resources) + return null; + return WebInspector.panels.resources.resourceViewForResource(scriptOrResource); + } + if (scriptOrResource instanceof WebInspector.Script) + return this.scriptViewForScript(scriptOrResource); + }, + + _sourceFrameForScriptOrResource: function(scriptOrResource) + { + if (scriptOrResource instanceof WebInspector.Resource) { + if (!WebInspector.panels.resources) + return null; + return WebInspector.panels.resources.sourceFrameForResource(scriptOrResource); + } + if (scriptOrResource instanceof WebInspector.Script) + return this.sourceFrameForScript(scriptOrResource); + }, + + _showScriptOrResource: function(scriptOrResource, line, shouldHighlightLine, fromBackForwardAction) + { + if (!scriptOrResource) + return; + + var view; + if (scriptOrResource instanceof WebInspector.Resource) { + if (!WebInspector.panels.resources) + return null; + view = WebInspector.panels.resources.resourceViewForResource(scriptOrResource); + view.headersVisible = false; + + if (scriptOrResource.url in this._breakpointsURLMap) { + var sourceFrame = this._sourceFrameForScriptOrResource(scriptOrResource); + if (sourceFrame && !sourceFrame.breakpoints.length) { + var breakpoints = this._breakpointsURLMap[scriptOrResource.url]; + var breakpointsLength = breakpoints.length; + for (var i = 0; i < breakpointsLength; ++i) + sourceFrame.addBreakpoint(breakpoints[i]); + } + } + } else if (scriptOrResource instanceof WebInspector.Script) + view = this.scriptViewForScript(scriptOrResource); + + if (!view) + return; + + if (!fromBackForwardAction) { + var oldIndex = this._currentBackForwardIndex; + if (oldIndex >= 0) + this._backForwardList.splice(oldIndex + 1, this._backForwardList.length - oldIndex); + + // Check for a previous entry of the same object in _backForwardList. + // If one is found, remove it and update _currentBackForwardIndex to match. + var previousEntryIndex = this._backForwardList.indexOf(scriptOrResource); + if (previousEntryIndex !== -1) { + this._backForwardList.splice(previousEntryIndex, 1); + --this._currentBackForwardIndex; + } + + this._backForwardList.push(scriptOrResource); + ++this._currentBackForwardIndex; + + this._updateBackAndForwardButtons(); + } + + this.visibleView = view; + + if (line) { + if (view.revealLine) + view.revealLine(line); + if (view.highlightLine && shouldHighlightLine) + view.highlightLine(line); + } + + var option; + if (scriptOrResource instanceof WebInspector.Script) { + option = scriptOrResource.filesSelectOption; + console.assert(option); + } else { + var url = scriptOrResource.url; + var script = this._scriptsForURLsInFilesSelect[url]; + if (script) + option = script.filesSelectOption; + } + + if (option) + this.filesSelectElement.selectedIndex = option.index; + }, + + _addScriptToFilesMenu: function(script) + { + if (script.resource && this._scriptsForURLsInFilesSelect[script.sourceURL]) + return; + + this._scriptsForURLsInFilesSelect[script.sourceURL] = script; + + var select = this.filesSelectElement; + + // FIXME: Append in some meaningful order. + var option = document.createElement("option"); + option.representedObject = (script.resource || script); + option.text = (script.sourceURL ? WebInspector.displayNameForURL(script.sourceURL) : WebInspector.UIString("(program)")); + select.appendChild(option); + + script.filesSelectOption = option; + + // Call _showScriptOrResource if the option we just appended ended up being selected. + // This will happen for the first item added to the menu. + if (select.options[select.selectedIndex] === option) + this._showScriptOrResource(option.representedObject); + }, + + _clearCurrentExecutionLine: function() + { + if (this._executionSourceFrame) + this._executionSourceFrame.executionLine = 0; + delete this._executionSourceFrame; + }, + + _callFrameSelected: function() + { + this._clearCurrentExecutionLine(); + + var callStackPane = this.sidebarPanes.callstack; + var currentFrame = callStackPane.selectedCallFrame; + if (!currentFrame) + return; + + this.sidebarPanes.scopechain.update(currentFrame); + + var scriptOrResource = this._sourceIDMap[currentFrame.sourceID]; + this._showScriptOrResource(scriptOrResource, currentFrame.line); + + this._executionSourceFrame = this._sourceFrameForScriptOrResource(scriptOrResource); + if (this._executionSourceFrame) + this._executionSourceFrame.executionLine = currentFrame.line; + }, + + _changeVisibleFile: function(event) + { + var select = this.filesSelectElement; + this._showScriptOrResource(select.options[select.selectedIndex].representedObject); }, _startSidebarResizeDrag: function(event) @@ -182,34 +639,172 @@ WebInspector.ScriptsPanel.prototype = { this.sidebarElement.style.width = newWidth + "px"; this.sidebarButtonsElement.style.width = newWidth + "px"; - this.scriptResourceViews.style.right = newWidth + "px"; + this.viewsContainerElement.style.right = newWidth + "px"; this.sidebarResizeWidgetElement.style.right = newWidth + "px"; this.sidebarResizeElement.style.right = (newWidth - 3) + "px"; event.preventDefault(); }, + _updatePauseOnExceptionsButton: function() + { + if (InspectorController.pauseOnExceptions()) { + this.pauseOnExceptionButton.title = WebInspector.UIString("Don't pause on exceptions."); + this.pauseOnExceptionButton.addStyleClass("toggled-on"); + } else { + this.pauseOnExceptionButton.title = WebInspector.UIString("Pause on exceptions."); + this.pauseOnExceptionButton.removeStyleClass("toggled-on"); + } + }, + _updateDebuggerButtons: function() { - if (InspectorController.debuggerAttached()) { - this.debuggingButton.title = WebInspector.UIString("Stop debugging."); - this.debuggingButton.addStyleClass("toggled-on"); + if (InspectorController.debuggerEnabled()) { + this.enableToggleButton.title = WebInspector.UIString("Debugging enabled. Click to disable."); + this.enableToggleButton.addStyleClass("toggled-on"); + this.pauseOnExceptionButton.removeStyleClass("hidden"); + this.panelEnablerView.visible = false; + } else { + this.enableToggleButton.title = WebInspector.UIString("Debugging disabled. Click to enable."); + this.enableToggleButton.removeStyleClass("toggled-on"); + this.pauseOnExceptionButton.addStyleClass("hidden"); + this.panelEnablerView.visible = true; + } + + this._updatePauseOnExceptionsButton(); + + if (this._paused) { + this.pauseButton.addStyleClass("paused"); + this.pauseButton.disabled = false; + this.stepOverButton.disabled = false; + this.stepIntoButton.disabled = false; + this.stepOutButton.disabled = false; + + this.debuggerStatusElement.textContent = WebInspector.UIString("Paused"); } else { - this.debuggingButton.title = WebInspector.UIString("Start debugging and reload inspected page."); - this.debuggingButton.removeStyleClass("toggled-on"); - this.pauseButton.disabled = true; + this.pauseButton.removeStyleClass("paused"); + + this.pauseButton.disabled = this._waitingToPause; + this.stepOverButton.disabled = true; + this.stepIntoButton.disabled = true; + this.stepOutButton.disabled = true; + + if (this._waitingToPause) + this.debuggerStatusElement.textContent = WebInspector.UIString("Pausing"); + else if (this._stepping) + this.debuggerStatusElement.textContent = WebInspector.UIString("Stepping"); + else + this.debuggerStatusElement.textContent = ""; + } + }, + + _updateBackAndForwardButtons: function() + { + this.backButton.disabled = this._currentBackForwardIndex <= 0; + this.forwardButton.disabled = this._currentBackForwardIndex >= (this._backForwardList.length - 1); + }, + + _clearInterface: function() + { + this.sidebarPanes.callstack.update(null); + this.sidebarPanes.scopechain.update(null); + + this._clearCurrentExecutionLine(); + this._updateDebuggerButtons(); + }, + + _goBack: function() + { + if (this._currentBackForwardIndex <= 0) { + console.error("Can't go back from index " + this._currentBackForwardIndex); + return; } + + this._showScriptOrResource(this._backForwardList[--this._currentBackForwardIndex], null, false, true); + this._updateBackAndForwardButtons(); + }, + + _goForward: function() + { + if (this._currentBackForwardIndex >= this._backForwardList.length - 1) { + console.error("Can't go forward from index " + this._currentBackForwardIndex); + return; + } + + this._showScriptOrResource(this._backForwardList[++this._currentBackForwardIndex], null, false, true); + this._updateBackAndForwardButtons(); + }, + + _enableDebugging: function() + { + if (InspectorController.debuggerEnabled()) + return; + this._toggleDebugging(); }, _toggleDebugging: function() { - if (InspectorController.debuggerAttached()) - InspectorController.stopDebugging(); + this._paused = false; + this._waitingToPause = false; + this._stepping = false; + + if (InspectorController.debuggerEnabled()) + InspectorController.disableDebugger(); else - InspectorController.startDebuggingAndReloadInspectedPage(); - this._updateDebuggerButtons(); + InspectorController.enableDebugger(); }, + + _togglePauseOnExceptions: function() + { + InspectorController.setPauseOnExceptions(!InspectorController.pauseOnExceptions()); + this._updatePauseOnExceptionsButton(); + }, + + _togglePause: function() + { + if (this._paused) { + this._paused = false; + this._waitingToPause = false; + InspectorController.resumeDebugger(); + } else { + this._stepping = false; + this._waitingToPause = true; + InspectorController.pauseInDebugger(); + } + + this._clearInterface(); + }, + + _stepOverClicked: function() + { + this._paused = false; + this._stepping = true; + + this._clearInterface(); + + InspectorController.stepOverStatementInDebugger(); + }, + + _stepIntoClicked: function() + { + this._paused = false; + this._stepping = true; + + this._clearInterface(); + + InspectorController.stepIntoStatementInDebugger(); + }, + + _stepOutClicked: function() + { + this._paused = false; + this._stepping = true; + + this._clearInterface(); + + InspectorController.stepOutOfFunctionInDebugger(); + } } WebInspector.ScriptsPanel.prototype.__proto__ = WebInspector.Panel.prototype; diff --git a/chrome/tools/test/reference_build/chrome/resources/Inspector/SidebarPane.js b/chrome/tools/test/reference_build/chrome/resources/Inspector/SidebarPane.js index 53f9d6d..af9e5f9 100644 --- a/chrome/tools/test/reference_build/chrome/resources/Inspector/SidebarPane.js +++ b/chrome/tools/test/reference_build/chrome/resources/Inspector/SidebarPane.js @@ -121,3 +121,5 @@ WebInspector.SidebarPane.prototype = { this.expanded = !this.expanded; } } + +WebInspector.SidebarPane.prototype.__proto__ = WebInspector.Object.prototype; diff --git a/chrome/tools/test/reference_build/chrome/resources/Inspector/SidebarTreeElement.js b/chrome/tools/test/reference_build/chrome/resources/Inspector/SidebarTreeElement.js index 3d3ba4c..c08b0ef 100644 --- a/chrome/tools/test/reference_build/chrome/resources/Inspector/SidebarTreeElement.js +++ b/chrome/tools/test/reference_build/chrome/resources/Inspector/SidebarTreeElement.js @@ -31,6 +31,24 @@ WebInspector.SidebarSectionTreeElement = function(title, representedObject, hasC WebInspector.SidebarSectionTreeElement.prototype = { selectable: false, + get smallChildren() + { + return this._smallChildren; + }, + + set smallChildren(x) + { + if (this._smallChildren === x) + return; + + this._smallChildren = x; + + if (this._smallChildren) + this._childrenListNode.addStyleClass("small"); + else + this._childrenListNode.removeStyleClass("small"); + }, + onattach: function() { this._listItemNode.addStyleClass("sidebar-tree-section"); @@ -54,6 +72,11 @@ WebInspector.SidebarTreeElement = function(className, title, subtitle, represent this.disclosureButton.className = "disclosure-button"; } + if (!this.iconElement) { + this.iconElement = document.createElement("img"); + this.iconElement.className = "icon"; + } + this.statusElement = document.createElement("div"); this.statusElement.className = "status"; @@ -74,6 +97,23 @@ WebInspector.SidebarTreeElement = function(className, title, subtitle, represent } WebInspector.SidebarTreeElement.prototype = { + get small() + { + return this._small; + }, + + set small(x) + { + this._small = x; + + if (this._listItemNode) { + if (this._small) + this._listItemNode.addStyleClass("small"); + else + this._listItemNode.removeStyleClass("small"); + } + }, + get mainTitle() { return this._mainTitle; @@ -140,13 +180,13 @@ WebInspector.SidebarTreeElement.prototype = { if (this.className) this._listItemNode.addStyleClass(this.className); + if (this.small) + this._listItemNode.addStyleClass("small"); + if (this.hasChildren && this.disclosureButton) this._listItemNode.appendChild(this.disclosureButton); - var iconElement = document.createElement("img"); - iconElement.className = "icon"; - - this._listItemNode.appendChild(iconElement); + this._listItemNode.appendChild(this.iconElement); this._listItemNode.appendChild(this.statusElement); this._listItemNode.appendChild(this.titlesElement); }, diff --git a/chrome/tools/test/reference_build/chrome/resources/Inspector/SourceView.js b/chrome/tools/test/reference_build/chrome/resources/Inspector/SourceView.js index 8d888e4..309027e 100644 --- a/chrome/tools/test/reference_build/chrome/resources/Inspector/SourceView.js +++ b/chrome/tools/test/reference_build/chrome/resources/Inspector/SourceView.js @@ -28,134 +28,275 @@ WebInspector.SourceView = function(resource) { + // Set the sourceFrame first since WebInspector.ResourceView will set headersVisible + // and our override of headersVisible needs the sourceFrame. + this.sourceFrame = new WebInspector.SourceFrame(null, this._addBreakpoint.bind(this)); + WebInspector.ResourceView.call(this, resource); + resource.addEventListener("finished", this._resourceLoadingFinished, this); + this.element.addStyleClass("source"); - this.messages = []; this._frameNeedsSetup = true; - this.frameElement = document.createElement("iframe"); - this.frameElement.className = "source-view-frame"; - this.frameElement.setAttribute("viewsource", "true"); - this.contentElement.appendChild(this.frameElement); + this.contentElement.appendChild(this.sourceFrame.element); + + var gutterElement = document.createElement("div"); + gutterElement.className = "webkit-line-gutter-backdrop"; + this.element.appendChild(gutterElement); } WebInspector.SourceView.prototype = { - show: function() + set headersVisible(x) + { + if (x === this._headersVisible) + return; + + var superSetter = WebInspector.ResourceView.prototype.__lookupSetter__("headersVisible"); + if (superSetter) + superSetter.call(this, x); + + this.sourceFrame.autoSizesToFitContentHeight = x; + }, + + show: function(parentElement) { - WebInspector.ResourceView.prototype.show.call(this); + WebInspector.ResourceView.prototype.show.call(this, parentElement); this.setupSourceFrameIfNeeded(); }, - setupSourceFrameIfNeeded: function() + hide: function() { - if (this.resource.finished && !this.resource.failed && this._frameNeedsSetup) { - delete this._frameNeedsSetup; + WebInspector.View.prototype.hide.call(this); + this._currentSearchResultIndex = -1; + }, - this.attach(); + resize: function() + { + if (this.sourceFrame.autoSizesToFitContentHeight) + this.sourceFrame.sizeToFitContentHeight(); + }, - InspectorController.addSourceToFrame(this.resource.identifier, this.frameElement); - WebInspector.addMainEventListeners(this.frameElement.contentDocument); + detach: function() + { + WebInspector.ResourceView.prototype.detach.call(this); - var length = this.messages.length; - for (var i = 0; i < length; ++i) - this._addMessageToSource(this.messages[i]); - } + // FIXME: We need to mark the frame for setup on detach because the frame DOM is cleared + // when it is removed from the document. Is this a bug? + this._frameNeedsSetup = true; + this._sourceFrameSetup = false; }, - sourceRow: function(lineNumber) + setupSourceFrameIfNeeded: function() { - if (!lineNumber) + if (!this._frameNeedsSetup) return; - this.setupSourceFrameIfNeeded(); + this.attach(); - var doc = this.frameElement.contentDocument; - var rows = doc.getElementsByTagName("table")[0].rows; + if (!InspectorController.addResourceSourceToFrame(this.resource.identifier, this.sourceFrame.element)) + return; - // Line numbers are a 1-based index, but the rows collection is 0-based. - --lineNumber; - if (lineNumber >= rows.length) - lineNumber = rows.length - 1; + delete this._frameNeedsSetup; - return rows[lineNumber]; + if (this.resource.type === WebInspector.Resource.Type.Script) { + this.sourceFrame.addEventListener("syntax highlighting complete", this._syntaxHighlightingComplete, this); + this.sourceFrame.syntaxHighlightJavascript(); + } else + this._sourceFrameSetupFinished(); }, - showLine: function(lineNumber) + _resourceLoadingFinished: function(event) { - var row = this.sourceRow(lineNumber); - if (!row) - return; - row.scrollIntoViewIfNeeded(true); + this._frameNeedsSetup = true; + this._sourceFrameSetup = false; + if (this.visible) + this.setupSourceFrameIfNeeded(); + this.resource.removeEventListener("finished", this._resourceLoadingFinished, this); }, - addMessage: function(msg) + _addBreakpoint: function(line) { - this.messages.push(msg); - if (!this._frameNeedsSetup) - this._addMessageToSource(msg); + var sourceID = null; + var closestStartingLine = 0; + var scripts = this.resource.scripts; + for (var i = 0; i < scripts.length; ++i) { + var script = scripts[i]; + if (script.startingLine <= line && script.startingLine >= closestStartingLine) { + closestStartingLine = script.startingLine; + sourceID = script.sourceID; + } + } + + if (WebInspector.panels.scripts) { + var breakpoint = new WebInspector.Breakpoint(this.resource.url, line, sourceID); + WebInspector.panels.scripts.addBreakpoint(breakpoint); + } }, - clearMessages: function() + // The rest of the methods in this prototype need to be generic enough to work with a ScriptView. + // The ScriptView prototype pulls these methods into it's prototype to avoid duplicate code. + + searchCanceled: function() + { + this._currentSearchResultIndex = -1; + this._searchResults = []; + delete this._delayedFindSearchMatches; + }, + + performSearch: function(query, finishedCallback) { - this.messages = []; + // Call searchCanceled since it will reset everything we need before doing a new search. + this.searchCanceled(); + + var lineQueryRegex = /(^|\s)(?:#|line:\s*)(\d+)(\s|$)/i; + var lineQueryMatch = query.match(lineQueryRegex); + if (lineQueryMatch) { + var lineToSearch = parseInt(lineQueryMatch[2]); + + // If there was a space before and after the line query part, replace with a space. + // Otherwise replace with an empty string to eat the prefix or postfix space. + var lineQueryReplacement = (lineQueryMatch[1] && lineQueryMatch[3] ? " " : ""); + var filterlessQuery = query.replace(lineQueryRegex, lineQueryReplacement); + } + + this._searchFinishedCallback = finishedCallback; + + function findSearchMatches(query, finishedCallback) + { + if (isNaN(lineToSearch)) { + // Search the whole document since there was no line to search. + this._searchResults = (InspectorController.search(this.sourceFrame.element.contentDocument, query) || []); + } else { + var sourceRow = this.sourceFrame.sourceRow(lineToSearch); + if (sourceRow) { + if (filterlessQuery) { + // There is still a query string, so search for that string in the line. + this._searchResults = (InspectorController.search(sourceRow, filterlessQuery) || []); + } else { + // Match the whole line, since there was no remaining query string to match. + var rowRange = this.sourceFrame.element.contentDocument.createRange(); + rowRange.selectNodeContents(sourceRow); + this._searchResults = [rowRange]; + } + } + + // Attempt to search for the whole query, just incase it matches a color like "#333". + var wholeQueryMatches = InspectorController.search(this.sourceFrame.element.contentDocument, query); + if (wholeQueryMatches) + this._searchResults = this._searchResults.concat(wholeQueryMatches); + } + + if (this._searchResults) + finishedCallback(this, this._searchResults.length); + } + + if (!this._sourceFrameSetup) { + // The search is performed in _sourceFrameSetupFinished by calling _delayedFindSearchMatches. + this._delayedFindSearchMatches = findSearchMatches.bind(this, query, finishedCallback); + this.setupSourceFrameIfNeeded(); + return; + } + + findSearchMatches.call(this, query, finishedCallback); + }, - if (this._frameNeedsSetup) + jumpToFirstSearchResult: function() + { + if (!this._searchResults || !this._searchResults.length) return; + this._currentSearchResultIndex = 0; + this._jumpToSearchResult(this._currentSearchResultIndex); + }, - var bubbles = this.frameElement.contentDocument.querySelectorAll(".webkit-html-message-bubble"); - if (!bubbles) + jumpToLastSearchResult: function() + { + if (!this._searchResults || !this._searchResults.length) return; + this._currentSearchResultIndex = (this._searchResults.length - 1); + this._jumpToSearchResult(this._currentSearchResultIndex); + }, - for (var i = 0; i < bubbles.length; ++i) { - var bubble = bubbles[i]; - bubble.parentNode.removeChild(bubble); - } + jumpToNextSearchResult: function() + { + if (!this._searchResults || !this._searchResults.length) + return; + if (++this._currentSearchResultIndex >= this._searchResults.length) + this._currentSearchResultIndex = 0; + this._jumpToSearchResult(this._currentSearchResultIndex); }, - _addMessageToSource: function(msg) + jumpToPreviousSearchResult: function() { - var row = this.sourceRow(msg.line); - if (!row) + if (!this._searchResults || !this._searchResults.length) return; + if (--this._currentSearchResultIndex < 0) + this._currentSearchResultIndex = (this._searchResults.length - 1); + this._jumpToSearchResult(this._currentSearchResultIndex); + }, - var doc = this.frameElement.contentDocument; - var cell = row.getElementsByTagName("td")[1]; + showingFirstSearchResult: function() + { + return (this._currentSearchResultIndex === 0); + }, - var errorDiv = cell.lastChild; - if (!errorDiv || errorDiv.nodeName.toLowerCase() !== "div" || !errorDiv.hasStyleClass("webkit-html-message-bubble")) { - errorDiv = doc.createElement("div"); - errorDiv.className = "webkit-html-message-bubble"; - cell.appendChild(errorDiv); - } + showingLastSearchResult: function() + { + return (this._searchResults && this._currentSearchResultIndex === (this._searchResults.length - 1)); + }, - var imageURL; - switch (msg.level) { - case WebInspector.ConsoleMessage.MessageLevel.Error: - errorDiv.addStyleClass("webkit-html-error-message"); - imageURL = "Images/errorIcon.png"; - break; - case WebInspector.ConsoleMessage.MessageLevel.Warning: - errorDiv.addStyleClass("webkit-html-warning-message"); - imageURL = "Images/warningIcon.png"; - break; - } + revealLine: function(lineNumber) + { + this.setupSourceFrameIfNeeded(); + this.sourceFrame.revealLine(lineNumber); + }, - var lineDiv = doc.createElement("div"); - lineDiv.className = "webkit-html-message-line"; - errorDiv.appendChild(lineDiv); + highlightLine: function(lineNumber) + { + this.setupSourceFrameIfNeeded(); + this.sourceFrame.highlightLine(lineNumber); + }, + + addMessage: function(msg) + { + this.sourceFrame.addMessage(msg); + }, + + clearMessages: function() + { + this.sourceFrame.clearMessages(); + }, + + _jumpToSearchResult: function(index) + { + var foundRange = this._searchResults[index]; + if (!foundRange) + return; + + var selection = window.getSelection(); + selection.removeAllRanges(); + selection.addRange(foundRange); - // Create the image element in the Inspector's document so we can use relative image URLs. - var image = document.createElement("img"); - image.src = imageURL; - image.className = "webkit-html-message-icon"; + if (foundRange.startContainer.scrollIntoViewIfNeeded) + foundRange.startContainer.scrollIntoViewIfNeeded(true); + else if (foundRange.startContainer.parentNode) + foundRange.startContainer.parentNode.scrollIntoViewIfNeeded(true); + }, - // Adopt the image element since it wasn't created in doc. - image = doc.adoptNode(image); - lineDiv.appendChild(image); + _sourceFrameSetupFinished: function() + { + this._sourceFrameSetup = true; + if (this._delayedFindSearchMatches) { + this._delayedFindSearchMatches(); + delete this._delayedFindSearchMatches; + } + }, - lineDiv.appendChild(doc.createTextNode(msg.message)); + _syntaxHighlightingComplete: function(event) + { + this._sourceFrameSetupFinished(); + this.sourceFrame.removeEventListener("syntax highlighting complete", null, this); } } diff --git a/chrome/tools/test/reference_build/chrome/resources/Inspector/StylesSidebarPane.js b/chrome/tools/test/reference_build/chrome/resources/Inspector/StylesSidebarPane.js index d68d604..f0a9afb 100644 --- a/chrome/tools/test/reference_build/chrome/resources/Inspector/StylesSidebarPane.js +++ b/chrome/tools/test/reference_build/chrome/resources/Inspector/StylesSidebarPane.js @@ -90,7 +90,7 @@ WebInspector.StylesSidebarPane.prototype = { } } - if (node.style && node.style.length) { + if (node.style && (node.style.length || Object.hasProperties(node.style.__disabledProperties))) { var inlineStyle = { selectorText: WebInspector.UIString("Inline Style Attribute"), style: node.style }; inlineStyle.subtitle = WebInspector.UIString("element’s “%s” attribute", "style"); styleRules.push(inlineStyle); @@ -106,7 +106,20 @@ WebInspector.StylesSidebarPane.prototype = { } } + function deleteDisabledProperty(style, name) + { + if (!style || !name) + return; + if (style.__disabledPropertyValues) + delete style.__disabledPropertyValues[name]; + if (style.__disabledPropertyPriorities) + delete style.__disabledPropertyPriorities[name]; + if (style.__disabledProperties) + delete style.__disabledProperties[name]; + } + var usedProperties = {}; + var disabledComputedProperties = {}; var priorityUsed = false; // Walk the style rules and make a list of all used and overloaded properties. @@ -140,12 +153,22 @@ WebInspector.StylesSidebarPane.prototype = { styleRule.usedProperties["font-weight"] = true; styleRule.usedProperties["line-height"] = true; } + + // Delete any disabled properties, since the property does exist. + // This prevents it from showing twice. + deleteDisabledProperty(style, name); + deleteDisabledProperty(style, style.getPropertyShorthand(name)); } // Add all the properties found in this style to the used properties list. // Do this here so only future rules are affect by properties used in this rule. for (var name in styleRules[i].usedProperties) usedProperties[name] = true; + + // Remember all disabled properties so they show up in computed style. + if (style.__disabledProperties) + for (var name in style.__disabledProperties) + disabledComputedProperties[name] = true; } if (priorityUsed) { @@ -178,6 +201,8 @@ WebInspector.StylesSidebarPane.prototype = { for (var i = 0; i < styleRules.length; ++i) { var styleRule = styleRules[i]; var section = styleRule.section; + if (styleRule.computedStyle) + section.disabledComputedProperties = disabledComputedProperties; section._usedProperties = (styleRule.usedProperties || usedProperties); section.update((section === editedSection) || styleRule.computedStyle); } @@ -202,9 +227,17 @@ WebInspector.StylesSidebarPane.prototype = { editable = true; var section = new WebInspector.StylePropertiesSection(styleRule, subtitle, computedStyle, (ruleUsedProperties || usedProperties), editable); - section.expanded = true; + if (computedStyle) + section.disabledComputedProperties = disabledComputedProperties; section.pane = this; + if (Preferences.styleRulesExpandedState && section.identifier in Preferences.styleRulesExpandedState) + section.expanded = Preferences.styleRulesExpandedState[section.identifier]; + else if (computedStyle) + section.collapse(true); + else + section.expand(true); + body.appendChild(section.element); this.sections.push(section); } @@ -222,13 +255,17 @@ WebInspector.StylePropertiesSection = function(styleRule, subtitle, computedStyl this.computedStyle = computedStyle; this.editable = (editable && !computedStyle); - // Prevent editing the user agent rules. - if (this.styleRule.parentStyleSheet && !this.styleRule.parentStyleSheet.ownerNode && !this.styleRule.parentStyleSheet.href) + // Prevent editing the user agent and user rules. + var isUserAgent = this.styleRule.parentStyleSheet && !this.styleRule.parentStyleSheet.ownerNode && !this.styleRule.parentStyleSheet.href; + var isUser = this.styleRule.parentStyleSheet && this.styleRule.parentStyleSheet.ownerNode && this.styleRule.parentStyleSheet.ownerNode.nodeName == '#document'; + if (isUserAgent || isUser) this.editable = false; this._usedProperties = usedProperties; if (computedStyle) { + this.element.addStyleClass("computed-style"); + if (Preferences.showInheritedComputedStyleProperties) this.element.addStyleClass("show-inherited"); @@ -256,16 +293,22 @@ WebInspector.StylePropertiesSection = function(styleRule, subtitle, computedStyl if (!subtitle) { if (this.styleRule.parentStyleSheet && this.styleRule.parentStyleSheet.href) { var url = this.styleRule.parentStyleSheet.href; - subtitle = WebInspector.linkifyURL(url, url.trimURL(WebInspector.mainResource ? WebInspector.mainResource.domain : "").escapeHTML()); + subtitle = WebInspector.linkifyURL(url, WebInspector.displayNameForURL(url)); this.subtitleElement.addStyleClass("file"); - } else if (this.styleRule.parentStyleSheet && !this.styleRule.parentStyleSheet.ownerNode) + } else if (isUserAgent) subtitle = WebInspector.UIString("user agent stylesheet"); + else if (isUser) + subtitle = WebInspector.UIString("user stylesheet"); else subtitle = WebInspector.UIString("inline stylesheet"); } this.subtitle = subtitle; } + + this.identifier = styleRule.selectorText; + if (this.subtitle) + this.identifier += ":" + this.subtitleElement.textContent; } WebInspector.StylePropertiesSection.prototype = { @@ -280,13 +323,35 @@ WebInspector.StylePropertiesSection.prototype = { this.update(); }, + expand: function(dontRememberState) + { + WebInspector.PropertiesSection.prototype.expand.call(this); + if (dontRememberState) + return; + + if (!Preferences.styleRulesExpandedState) + Preferences.styleRulesExpandedState = {}; + Preferences.styleRulesExpandedState[this.identifier] = true; + }, + + collapse: function(dontRememberState) + { + WebInspector.PropertiesSection.prototype.collapse.call(this); + if (dontRememberState) + return; + + if (!Preferences.styleRulesExpandedState) + Preferences.styleRulesExpandedState = {}; + Preferences.styleRulesExpandedState[this.identifier] = false; + }, + isPropertyInherited: function(property) { if (!this.computedStyle || !this._usedProperties) return false; // These properties should always show for Computed Style. var alwaysShowComputedProperties = { "display": true, "height": true, "width": true }; - return !(property in this.usedProperties) && !(property in alwaysShowComputedProperties); + return !(property in this.usedProperties) && !(property in alwaysShowComputedProperties) && !(property in this.disabledComputedProperties); }, isPropertyOverloaded: function(property, shorthand) @@ -327,16 +392,23 @@ WebInspector.StylePropertiesSection.prototype = { onpopulate: function() { var style = this.styleRule.style; - if (!style.length) - return; var foundShorthands = {}; var uniqueProperties = getUniqueStyleProperties(style); + var disabledProperties = style.__disabledPropertyValues || {}; + + for (var name in disabledProperties) + uniqueProperties.push(name); + uniqueProperties.sort(); for (var i = 0; i < uniqueProperties.length; ++i) { var name = uniqueProperties[i]; - var shorthand = style.getPropertyShorthand(name); + var disabled = name in disabledProperties; + if (!disabled && this.disabledComputedProperties && !(name in this.usedProperties) && name in this.disabledComputedProperties) + disabled = true; + + var shorthand = !disabled ? style.getPropertyShorthand(name) : null; if (shorthand && shorthand in foundShorthands) continue; @@ -350,7 +422,7 @@ WebInspector.StylePropertiesSection.prototype = { var inherited = this.isPropertyInherited(name); var overloaded = this.isPropertyOverloaded(name, isShorthand); - var item = new WebInspector.StylePropertyTreeElement(style, name, isShorthand, inherited, overloaded); + var item = new WebInspector.StylePropertyTreeElement(style, name, isShorthand, inherited, overloaded, disabled); this.propertiesTreeOutline.appendChild(item); } } @@ -358,13 +430,14 @@ WebInspector.StylePropertiesSection.prototype = { WebInspector.StylePropertiesSection.prototype.__proto__ = WebInspector.PropertiesSection.prototype; -WebInspector.StylePropertyTreeElement = function(style, name, shorthand, inherited, overloaded) +WebInspector.StylePropertyTreeElement = function(style, name, shorthand, inherited, overloaded, disabled) { this.style = style; this.name = name; this.shorthand = shorthand; this._inherited = inherited; this._overloaded = overloaded; + this._disabled = disabled; // Pass an empty title, the title gets made later in onattach. TreeElement.call(this, "", null, shorthand); @@ -397,6 +470,33 @@ WebInspector.StylePropertyTreeElement.prototype = { this.updateState(); }, + get disabled() + { + return this._disabled; + }, + + set disabled(x) + { + if (x === this._disabled) + return; + this._disabled = x; + this.updateState(); + }, + + get priority() + { + if (this.disabled && this.style.__disabledPropertyPriorities && this.name in this.style.__disabledPropertyPriorities) + return this.style.__disabledPropertyPriorities[this.name]; + return (this.shorthand ? getShorthandPriority(this.style, this.name) : this.style.getPropertyPriority(this.name)); + }, + + get value() + { + if (this.disabled && this.style.__disabledPropertyValues && this.name in this.style.__disabledPropertyValues) + return this.style.__disabledPropertyValues[this.name]; + return (this.shorthand ? getShorthandValue(this.style, this.name) : this.style.getPropertyValue(this.name)); + }, + onattach: function() { this.updateTitle(); @@ -423,8 +523,8 @@ WebInspector.StylePropertyTreeElement.prototype = { "rgb(0, 255, 255)": "cyan" }; - var priority = (this.shorthand ? getShorthandPriority(this.style, this.name) : this.style.getPropertyPriority(this.name)); - var value = (this.shorthand ? getShorthandValue(this.style, this.name) : this.style.getPropertyValue(this.name)); + var priority = this.priority; + var value = this.value; var htmlValue = value; if (priority && !priority.length) @@ -449,6 +549,12 @@ WebInspector.StylePropertyTreeElement.prototype = { this.updateState(); + var enabledCheckboxElement = document.createElement("input"); + enabledCheckboxElement.className = "enabled-button"; + enabledCheckboxElement.type = "checkbox"; + enabledCheckboxElement.checked = !this.disabled; + enabledCheckboxElement.addEventListener("change", this.toggleEnabled.bind(this), false); + var nameElement = document.createElement("span"); nameElement.className = "name"; nameElement.textContent = this.name; @@ -465,6 +571,9 @@ WebInspector.StylePropertyTreeElement.prototype = { this.listItemElement.removeChildren(); + // Append the checkbox for root elements of an editable section. + if (this.treeOutline.section && this.treeOutline.section.editable && this.parent.root) + this.listItemElement.appendChild(enabledCheckboxElement); this.listItemElement.appendChild(nameElement); this.listItemElement.appendChild(document.createTextNode(": ")); this.listItemElement.appendChild(valueElement); @@ -493,13 +602,64 @@ WebInspector.StylePropertyTreeElement.prototype = { this.tooltip = this.name + ": " + (valueNicknames[value] || value) + (priority ? " " + priority : ""); }, + updateAll: function(updateAllRules) + { + if (updateAllRules && this.treeOutline.section && this.treeOutline.section.pane) + this.treeOutline.section.pane.update(null, this.treeOutline.section); + else if (this.treeOutline.section) + this.treeOutline.section.update(true); + else + this.updateTitle(); // FIXME: this will not show new properties. But we don't hit his case yet. + }, + + toggleEnabled: function(event) + { + var disabled = !event.target.checked; + + if (disabled) { + if (!this.style.__disabledPropertyValues || !this.style.__disabledPropertyPriorities) { + var inspectedWindow = InspectorController.inspectedWindow(); + this.style.__disabledProperties = new inspectedWindow.Object; + this.style.__disabledPropertyValues = new inspectedWindow.Object; + this.style.__disabledPropertyPriorities = new inspectedWindow.Object; + } + + this.style.__disabledPropertyValues[this.name] = this.value; + this.style.__disabledPropertyPriorities[this.name] = this.priority; + + if (this.shorthand) { + var longhandProperties = getLonghandProperties(this.style, this.name); + for (var i = 0; i < longhandProperties.length; ++i) { + this.style.__disabledProperties[longhandProperties[i]] = true; + this.style.removeProperty(longhandProperties[i]); + } + } else { + this.style.__disabledProperties[this.name] = true; + this.style.removeProperty(this.name); + } + } else { + this.style.setProperty(this.name, this.value, this.priority); + delete this.style.__disabledProperties[this.name]; + delete this.style.__disabledPropertyValues[this.name]; + delete this.style.__disabledPropertyPriorities[this.name]; + } + + // Set the disabled property here, since the code above replies on it not changing + // until after the value and priority are retrieved. + this.disabled = disabled; + + if (this.treeOutline.section && this.treeOutline.section.pane) + this.treeOutline.section.pane.dispatchEventToListeners("style property toggled"); + + this.updateAll(true); + }, + updateState: function() { if (!this.listItemElement) return; - var value = (this.shorthand ? getShorthandValue(this.style, this.name) : this.style.getPropertyValue(this.name)); - if (this.style.isPropertyImplicit(this.name) || value === "initial") + if (this.style.isPropertyImplicit(this.name) || this.value === "initial") this.listItemElement.addStyleClass("implicit"); else this.listItemElement.removeStyleClass("implicit"); @@ -513,6 +673,11 @@ WebInspector.StylePropertyTreeElement.prototype = { this.listItemElement.addStyleClass("overloaded"); else this.listItemElement.removeStyleClass("overloaded"); + + if (this.disabled) + this.listItemElement.addStyleClass("disabled"); + else + this.listItemElement.removeStyleClass("disabled"); }, onpopulate: function() @@ -549,47 +714,155 @@ WebInspector.StylePropertyTreeElement.prototype = { if (WebInspector.isBeingEdited(this.listItemElement) || (this.treeOutline.section && !this.treeOutline.section.editable)) return; - var wasExpanded = this.expanded; - this.collapse(); - // Lie about out children to prevent toggling on click. + var context = { expanded: this.expanded, hasChildren: this.hasChildren }; + + // Lie about our children to prevent expanding on double click and to collapse shorthands. this.hasChildren = false; if (!selectElement) selectElement = this.listItemElement; + this.listItemElement.handleKeyEvent = this.editingKeyDown.bind(this); + + WebInspector.startEditing(this.listItemElement, this.editingCommitted.bind(this), this.editingCancelled.bind(this), context); window.getSelection().setBaseAndExtent(selectElement, 0, selectElement, 1); + }, + + editingKeyDown: function(event) + { + var arrowKeyPressed = (event.keyIdentifier === "Up" || event.keyIdentifier === "Down"); + var pageKeyPressed = (event.keyIdentifier === "PageUp" || event.keyIdentifier === "PageDown"); + if (!arrowKeyPressed && !pageKeyPressed) + return; + + var selection = window.getSelection(); + if (!selection.rangeCount) + return; + + var selectionRange = selection.getRangeAt(0); + if (selectionRange.commonAncestorContainer !== this.listItemElement && !selectionRange.commonAncestorContainer.isDescendant(this.listItemElement)) + return; + + const styleValueDelimeters = " \t\n\"':;,/()"; + var wordRange = selectionRange.startContainer.rangeOfWord(selectionRange.startOffset, styleValueDelimeters, this.listItemElement); + var wordString = wordRange.toString(); + var replacementString = wordString; + + var matches = /(.*?)(-?\d+(?:\.\d+)?)(.*)/.exec(wordString); + if (matches && matches.length) { + var prefix = matches[1]; + var number = parseFloat(matches[2]); + var suffix = matches[3]; + + // If the number is near zero or the number is one and the direction will take it near zero. + var numberNearZero = (number < 1 && number > -1); + if (number === 1 && event.keyIdentifier === "Down") + numberNearZero = true; + else if (number === -1 && event.keyIdentifier === "Up") + numberNearZero = true; + + if (numberNearZero && event.altKey && arrowKeyPressed) { + if (event.keyIdentifier === "Down") + number = Math.ceil(number - 1); + else + number = Math.floor(number + 1); + } else { + // Jump by 10 when shift is down or jump by 0.1 when near zero or Alt/Option is down. + // Also jump by 10 for page up and down, or by 100 if shift is held with a page key. + var changeAmount = 1; + if (event.shiftKey && pageKeyPressed) + changeAmount = 100; + else if (event.shiftKey || pageKeyPressed) + changeAmount = 10; + else if (event.altKey || numberNearZero) + changeAmount = 0.1; + + if (event.keyIdentifier === "Down" || event.keyIdentifier === "PageDown") + changeAmount *= -1; + + // Make the new number and constrain it to a precision of 6, this matches numbers the engine returns. + // Use the Number constructor to forget the fixed precision, so 1.100000 will print as 1.1. + number = Number((number + changeAmount).toFixed(6)); + } + + replacementString = prefix + number + suffix; + } else { + // FIXME: this should cycle through known keywords for the current property name. + return; + } - WebInspector.startEditing(this.listItemElement, this.editingCommitted.bind(this), this.editingCancelled.bind(this), wasExpanded); + var replacementTextNode = document.createTextNode(replacementString); + + wordRange.deleteContents(); + wordRange.insertNode(replacementTextNode); + + var finalSelectionRange = document.createRange(); + finalSelectionRange.setStart(replacementTextNode, 0); + finalSelectionRange.setEnd(replacementTextNode, replacementString.length); + + selection.removeAllRanges(); + selection.addRange(finalSelectionRange); + + event.preventDefault(); + event.handled = true; + + if (!this.originalCSSText) { + // Remember the rule's original CSS text, so it can be restored + // if the editing is canceled and before each apply. + this.originalCSSText = getStyleTextWithShorthands(this.style); + } else { + // Restore the original CSS text before applying user changes. This is needed to prevent + // new properties from sticking around if the user adds one, then removes it. + this.style.cssText = this.originalCSSText; + } + + this.applyStyleText(this.listItemElement.textContent); }, - editingEnded: function(wasExpanded) + editingEnded: function(context) { - this.hasChildren = (this.children.length ? true : false); - if (wasExpanded) + this.hasChildren = context.hasChildren; + if (context.expanded) this.expand(); + delete this.listItemElement.handleKeyEvent; + delete this.originalCSSText; }, - editingCancelled: function(e, wasExpanded) + editingCancelled: function(element, context) { - this.editingEnded(wasExpanded); - this.updateTitle(); + if (this.originalCSSText) { + this.style.cssText = this.originalCSSText; + + if (this.treeOutline.section && this.treeOutline.section.pane) + this.treeOutline.section.pane.dispatchEventToListeners("style edited"); + + this.updateAll(); + } else + this.updateTitle(); + + this.editingEnded(context); }, - editingCommitted: function(e, userInput, previousContent, wasExpanded) + editingCommitted: function(element, userInput, previousContent, context) { - this.editingEnded(); + this.editingEnded(context); if (userInput === previousContent) return; // nothing changed, so do nothing else - var userInputLength = userInput.trimWhitespace().length; + this.applyStyleText(userInput, true); + }, + + applyStyleText: function(styleText, updateInterface) + { + var styleTextLength = styleText.trimWhitespace().length; // Create a new element to parse the user input CSS. var parseElement = document.createElement("span"); - parseElement.setAttribute("style", userInput); + parseElement.setAttribute("style", styleText); - var userInputStyle = parseElement.style; - if (userInputStyle.length || !userInputLength) { + var tempStyle = parseElement.style; + if (tempStyle.length || !styleTextLength) { // The input was parsable or the user deleted everything, so remove the // original property from the real style declaration. If this represents // a shorthand remove all the longhand properties. @@ -601,39 +874,42 @@ WebInspector.StylePropertyTreeElement.prototype = { this.style.removeProperty(this.name); } - if (!userInputLength) { - // The user deleted the everything, so remove the tree element and update. - if (this.treeOutline.section && this.treeOutline.section.pane) - this.treeOutline.section.pane.update(); - this.parent.removeChild(this); + if (!styleTextLength) { + if (updateInterface) { + // The user deleted the everything, so remove the tree element and update. + if (this.treeOutline.section && this.treeOutline.section.pane) + this.treeOutline.section.pane.update(); + this.parent.removeChild(this); + } return; } - if (!userInputStyle.length) { + if (!tempStyle.length) { // The user typed something, but it didn't parse. Just abort and restore // the original title for this property. - this.updateTitle(); + if (updateInterface) + this.updateTitle(); return; } // Iterate of the properties on the test element's style declaration and // add them to the real style declaration. We take care to move shorthands. var foundShorthands = {}; - var uniqueProperties = getUniqueStyleProperties(userInputStyle); + var uniqueProperties = getUniqueStyleProperties(tempStyle); for (var i = 0; i < uniqueProperties.length; ++i) { var name = uniqueProperties[i]; - var shorthand = userInputStyle.getPropertyShorthand(name); + var shorthand = tempStyle.getPropertyShorthand(name); if (shorthand && shorthand in foundShorthands) continue; if (shorthand) { - var value = getShorthandValue(userInputStyle, shorthand); - var priority = getShorthandPriority(userInputStyle, shorthand); + var value = getShorthandValue(tempStyle, shorthand); + var priority = getShorthandPriority(tempStyle, shorthand); foundShorthands[shorthand] = true; } else { - var value = userInputStyle.getPropertyValue(name); - var priority = userInputStyle.getPropertyPriority(name); + var value = tempStyle.getPropertyValue(name); + var priority = tempStyle.getPropertyPriority(name); } // Set the property on the real style declaration. @@ -641,11 +917,10 @@ WebInspector.StylePropertyTreeElement.prototype = { } if (this.treeOutline.section && this.treeOutline.section.pane) - this.treeOutline.section.pane.update(null, this.treeOutline.section); - else if (this.treeOutline.section) - this.treeOutline.section.update(true); - else - this.updateTitle(); // FIXME: this will not show new properties. But we don't hit his case yet. + this.treeOutline.section.pane.dispatchEventToListeners("style edited"); + + if (updateInterface) + this.updateAll(true); } } diff --git a/chrome/tools/test/reference_build/chrome/resources/Inspector/TextPrompt.js b/chrome/tools/test/reference_build/chrome/resources/Inspector/TextPrompt.js index 264cb4c..61e1b52db 100644 --- a/chrome/tools/test/reference_build/chrome/resources/Inspector/TextPrompt.js +++ b/chrome/tools/test/reference_build/chrome/resources/Inspector/TextPrompt.js @@ -151,8 +151,7 @@ WebInspector.TextPrompt.prototype = { if (auto && !this.isCaretAtEndOfPrompt()) return; - var wordPrefixRange = this.scanBackwards(this.completionStopCharacters, selectionRange.startContainer, selectionRange.startOffset, this.element); - + var wordPrefixRange = selectionRange.startContainer.rangeOfWord(selectionRange.startOffset, this.completionStopCharacters, this.element, "backward"); var completions = this.completions(wordPrefixRange, auto); if (!completions || !completions.length) @@ -219,47 +218,6 @@ WebInspector.TextPrompt.prototype = { selection.addRange(finalSelectionRange); }, - scanBackwards: function(stopCharacters, endNode, endOffset, stayWithinElement) - { - var startNode; - var startOffset = 0; - var node = endNode; - - if (!stayWithinElement) - stayWithinElement = this.element; - - while (node) { - if (node === stayWithinElement) { - if (!startNode) - startNode = stayWithinElement; - break; - } - - if (node.nodeType === Node.TEXT_NODE) { - var start = (node === endNode ? endOffset : node.nodeValue.length); - for (var i = (start - 1); i >= 0; --i) { - var character = node.nodeValue[i]; - if (stopCharacters.indexOf(character) !== -1) { - startNode = node; - startOffset = i + 1; - break; - } - } - } - - if (startNode) - break; - - node = node.traversePreviousNode(); - } - - var result = document.createRange(); - result.setStart(startNode, startOffset); - result.setEnd(endNode, endOffset); - - return result; - }, - isCaretInsidePrompt: function() { return this.element.isInsertionCaretInside(); diff --git a/chrome/tools/test/reference_build/chrome/resources/Inspector/View.js b/chrome/tools/test/reference_build/chrome/resources/Inspector/View.js index 9e22482..632a61ae 100644 --- a/chrome/tools/test/reference_build/chrome/resources/Inspector/View.js +++ b/chrome/tools/test/reference_build/chrome/resources/Inspector/View.js @@ -49,8 +49,10 @@ WebInspector.View.prototype = { show: function(parentElement) { this._visible = true; - if (!this.element.parentNode && parentElement) + if (parentElement && parentElement !== this.element.parentNode) { + this.detach(); parentElement.appendChild(this.element); + } if (!this.element.parentNode && this.attach) this.attach(); this.element.addStyleClass("visible"); @@ -68,3 +70,5 @@ WebInspector.View.prototype = { this.element.parentNode.removeChild(this.element); } } + +WebInspector.View.prototype.__proto__ = WebInspector.Object.prototype; diff --git a/chrome/tools/test/reference_build/chrome/resources/Inspector/inspector.css b/chrome/tools/test/reference_build/chrome/resources/Inspector/inspector.css index 946a4b1..c7ca669 100644 --- a/chrome/tools/test/reference_build/chrome/resources/Inspector/inspector.css +++ b/chrome/tools/test/reference_build/chrome/resources/Inspector/inspector.css @@ -42,6 +42,14 @@ body { -webkit-box-sizing: border-box; } +:focus { + outline: none; +} + +input[type="search"]:focus, input[type="text"]:focus { + outline: auto 5px -webkit-focus-ring-color; +} + iframe, a img { border: none; } @@ -51,7 +59,7 @@ img { } .hidden { - display: none !important; + display: none !important; } #toolbar { @@ -62,8 +70,7 @@ img { height: 56px; display: -webkit-box; padding: 0 5px; - /*background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(191, 191, 191)), to(rgb(151, 151, 151)));*/ - background-color: rgb(191, 191, 191); + background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(191, 191, 191)), to(rgb(151, 151, 151))); border-bottom: 1px solid rgb(80, 80, 80); -webkit-box-orient: horizontal; -webkit-background-origin: padding; @@ -71,14 +78,25 @@ img { } body.inactive #toolbar { - /*background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(233, 233, 233)), to(rgb(207, 207, 207)));*/ - background-color: rgb(233, 233, 233); + background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(233, 233, 233)), to(rgb(207, 207, 207))); + border-bottom: 1px solid rgb(64%, 64%, 64%); } body.detached.platform-mac-leopard #toolbar { background: transparent !important; } +body.attached #toolbar { + height: 34px; + border-top: 1px solid rgb(100, 100, 100); + cursor: row-resize; + padding-left: 0; +} + +body.attached.inactive #toolbar { + border-top: 1px solid rgb(64%, 64%, 64%); +} + .toolbar-item { display: -webkit-box; padding: 4px 6px; @@ -86,7 +104,6 @@ body.detached.platform-mac-leopard #toolbar { background-color: transparent; border-style: none; border-color: transparent; - outline: none; -webkit-box-orient: vertical; -webkit-box-align: center; -webkit-box-pack: end; @@ -108,8 +125,24 @@ body.detached.platform-mac-leopard #toolbar { } .toolbar-icon { + display: inline-block; width: 32px; height: 32px; + -webkit-background-size: 100% auto; +} + +body.attached .toolbar-icon { + width: 24px; + height: 24px; + vertical-align: middle; +} + +.toolbar-item:active .toolbar-icon { + background-position: 0 32px; +} + +body.attached .toolbar-item:active .toolbar-icon { + background-position: 0 24px; } .toolbar-label { @@ -118,78 +151,81 @@ body.detached.platform-mac-leopard #toolbar { text-shadow: rgba(255, 255, 255, 0.5) 0 1px 0; } -.toolbar-item.elements .toolbar-icon { - content: url(Images/elementsIcon.png); +.toolbar-item.toggleable:active .toolbar-label { + text-shadow: none; } -.toolbar-item.resources .toolbar-icon { - content: url(Images/resourcesIcon.png); +body.attached .toolbar-label { + display: inline-block; + vertical-align: middle; + margin-left: 3px; } -.toolbar-item.scripts .toolbar-icon { - content: url(Images/scriptsIcon.png); +body.attached #search-toolbar-label { + display: none; } -.toolbar-item.databases .toolbar-icon { - content: url(Images/databasesIcon.png); +#search { + width: 205px; + font-size: 16px; + margin-bottom: 5px; } -#searchResults { - position: absolute; - top: -100px; - left: 0; - right: 0; - height: 100px; - z-index: -1; - background-color: white; - border-bottom: 1px solid rgb(180, 180, 180); - overflow-y: auto; - overflow-x: hidden; - -webkit-box-sizing: border-box; +body.attached #search { + font-size: 11px; + margin-bottom: 8px; } -.search-results-section { - color: gray; - width: 28px; - float: left; - margin-left: -45px; - text-align: right; - font-size: 10px; - margin-top: 1px; - white-space: nowrap; +#search-results-matches { + font-size: 11px; + text-shadow: rgba(255, 255, 255, 0.5) 0 1px 0; + margin-bottom: 22px; } -.selected .search-results-section { - color: rgba(255, 255, 255, 0.8); +body.attached #search-results-matches { + margin-bottom: 6px; } -body.inactive .focused .selected .search-results-section { - color: rgba(0, 0, 0, 0.5); +.toolbar-item.elements .toolbar-icon { + background-image: url(Images/elementsIcon.png); } -.blurred .selected .search-results-section { - color: rgba(0, 0, 0, 0.5); +.toolbar-item.resources .toolbar-icon { + background-image: url(Images/resourcesIcon.png); } -#searchResults > ol > ol > li { - padding-left: 45px; - white-space: nowrap; +.toolbar-item.scripts .toolbar-icon { + background-image: url(Images/scriptsIcon.png); +} + +.toolbar-item.databases .toolbar-icon { + background-image: url(Images/databasesIcon.png); } -.search-matched-string { - background-color: #ff8; +.toolbar-item.profiles .toolbar-icon { + background-image: url(Images/profilesIcon.png); } -.selected .search-matched-string { +#close-button { + width: 14px; + height: 14px; + background-image: url(Images/closeButtons.png); + background-position: 0 0; background-color: transparent; + border: 0 none transparent; + margin: 5px 0; } -#searchResultsResizer { - position: absolute; - height: 5px; - left: 0; - right: 0; - cursor: row-resize; +#close-button:hover { + background-position: 14px 0; +} + +#close-button:active { + background-position: 28px 0; +} + +body.detached .toolbar-item.close { + display: none; } #main { @@ -203,6 +239,10 @@ body.inactive .focused .selected .search-results-section { background-color: white; } +body.attached #main { + top: 34px; +} + #main-panels { position: absolute; top: 0; @@ -270,7 +310,6 @@ button.status-bar-item { width: 32px; background-image: url(Images/statusbarButtons.png); background-position: 0 0; - outline: none; } button.status-bar-item:active { @@ -278,13 +317,13 @@ button.status-bar-item:active { } button.status-bar-item:disabled { + opacity: 0.5; background-position: 0 0 !important; } select.status-bar-item { min-width: 48px; border-width: 0 17px 0 2px; - outline: none; padding: 0 2px 0 6px; font-weight: bold; color: rgb(48, 48, 48); @@ -339,38 +378,38 @@ body.detached #dock-status-bar-item.toggled-on:active { background-position: 32px 0; } -#error-warning-count { - position: absolute; - right: 16px; - top: 0; - cursor: pointer; - padding: 6px 2px; - font-size: 10px; - height: 19px; -} - -#error-warning-count:hover { - border-bottom: 1px solid rgb(96, 96, 96); -} - -#error-count::before { - content: url(Images/errorIcon.png); - width: 10px; - height: 10px; - vertical-align: -1px; - margin-right: 2px; -} - -#error-count + #warning-count { - margin-left: 6px; -} - -#warning-count::before { - content: url(Images/warningIcon.png); - width: 10px; - height: 10px; - vertical-align: -1px; - margin-right: 2px; +#error-warning-count { + position: absolute; + right: 16px; + top: 0; + cursor: pointer; + padding: 6px 2px; + font-size: 10px; + height: 19px; +} + +#error-warning-count:hover { + border-bottom: 1px solid rgb(96, 96, 96); +} + +#error-count::before { + content: url(Images/errorIcon.png); + width: 10px; + height: 10px; + vertical-align: -1px; + margin-right: 2px; +} + +#error-count + #warning-count { + margin-left: 6px; +} + +#warning-count::before { + content: url(Images/warningIcon.png); + width: 10px; + height: 10px; + vertical-align: -1px; + margin-right: 2px; } #console { @@ -414,7 +453,6 @@ body.console-visible #console { #console-prompt { position: relative; - outline: none; padding: 1px 22px 1px 24px; min-height: 16px; white-space: pre-wrap; @@ -429,10 +467,10 @@ body.console-visible #console { position: relative; border-bottom: 1px solid rgb(240, 240, 240); padding: 1px 22px 1px 24px; - min-height: 16px; + min-height: 16px; } -.console-message::before, .console-user-command::before, #console-prompt::before { +.console-message::before, .console-user-command::before, #console-prompt::before, .console-group-title-level::before { position: absolute; display: block; content: ""; @@ -444,10 +482,59 @@ body.console-visible #console { -webkit-user-select: none; } +.console-message .bubble { + display: inline-block; + height: 14px; + background-color: rgb(128, 151, 189); + vertical-align: middle; + white-space: nowrap; + padding: 1px 4px; + margin-top: -2px; + margin-right: 4px; + text-align: left; + font-size: 11px; + font-family: Helvetia, Arial, sans-serif; + font-weight: bold; + text-shadow: none; + color: white; + -webkit-border-radius: 7px; +} + .console-message-text { white-space: pre-wrap; } +.repeated-message { + padding-left: 6px; +} + +.repeated-message.console-error-level::before, .repeated-message.console-warning-level:before { + visibility: hidden; +} + +.console-group .console-group > .console-group-messages { + margin-left: 16px; +} + +.console-group-title-level { + font-weight: bold; +} + +.console-group-title-level::before { + background-image: url(Images/disclosureTriangleSmallDown.png); + top: 0.6em; + width: 11px; + height: 12px; +} + +.console-group.collapsed .console-group-title-level::before { + background-image: url(Images/disclosureTriangleSmallRight.png); +} + +.console-group.collapsed > .console-group-messages { + display: none; +} + .console-error-level .console-message-text { color: red; } @@ -477,17 +564,7 @@ body.console-visible #console { .console-message-url { color: rgb(33%, 33%, 33%) !important; cursor: pointer; -} - -.console-message-url::after { - display: inline-block; - content: url(Images/goArrow.png); - margin-left: 3px; - width: 12px; - height: 12px; - vertical-align: top; - opacity: 0.75; - -webkit-user-select: none; + float: right; } .console-message-url:hover { @@ -498,12 +575,66 @@ body.console-visible #console { opacity: 1; } +.console-group-messages .section { + margin: 0; +} + +.console-group-messages .section .header { + padding: 0 8px 0 0; + background-image: none; + border: none; + min-height: 16px; +} + +.console-group-messages .section .header::before { + position: absolute; + top: 1px; + left: 12px; + width: 8px; + height: 8px; + content: url(Images/treeRightTriangleBlack.png); +} + +.console-group-messages .section.expanded .header::before { + content: url(Images/treeDownTriangleBlack.png); +} + +.console-group-messages .section .header .title { + color: black; +} + +.console-group-messages .outline-disclosure, .console-group-messages .outline-disclosure ol { + font-size: inherit; + line-height: 1em; +} + +.console-group-messages .outline-disclosure li { + padding-top: 2px; + padding-bottom: 2px; +} + +.console-group-messages .outline-disclosure li .selection { + z-index: 0; + margin-top: -1px; +} + +.console-formatted-object .section, .console-formatted-node .section { + position: static; +} + .auto-complete-text { color: rgb(128, 128, 128); -webkit-user-select: none; -webkit-user-modify: read-only; } +.inspectible-node:hover { + background-color: rgba(56, 121, 217, 0.1); + -webkit-border-radius: 5px; + padding: 0 5px 1px; + margin: 0 -5px -1px; +} + .panel { display: none; overflow: hidden; @@ -526,12 +657,63 @@ body.console-visible #console { left: 0; right: 0; bottom: 0; + overflow: hidden; } .resource-view.visible { display: block; } +.resource-view.headers-visible { + overflow-y: auto; + overflow-x: hidden; +} + +.resource-view-headers { + display: none; + padding: 6px; + border-bottom: 1px solid rgb(64%, 64%, 64%); + background-color: white; + -webkit-user-select: text; +} + +.resource-view-headers .outline-disclosure .parent { + -webkit-user-select: none; + font-weight: bold; +} + +.resource-view.headers-visible .resource-view-headers { + display: block; +} + +.resource-view-headers .outline-disclosure .children li { + white-space: nowrap; +} + +.resource-view-headers .outline-disclosure li.expanded .header-count { + display: none; +} + +.resource-view-headers .outline-disclosure .header-name { + color: rgb(33%, 33%, 33%); + display: inline-block; + width: 105px; + text-align: right; + margin-right: 0.5em; + font-weight: bold; + vertical-align: top; + overflow: hidden; + text-overflow: ellipsis; +} + +.resource-view-headers .outline-disclosure .header-value { + display: inline-block; + white-space: normal; + word-break: break-word; + vertical-align: top; + margin-right: 100px; +} + .resource-view .resource-view-content { position: absolute; top: 0; @@ -540,48 +722,57 @@ body.console-visible #console { bottom: 0; } -.resource-view.font { - font-size: 60px; - white-space: pre-wrap; - word-wrap: break-word; - text-align: center; +.resource-view.headers-visible .resource-view-content { + position: relative; + top: auto; + right: auto; + left: auto; + bottom: auto; } -.resource-view.font .preview { +.resource-view.headers-visible .source-view-frame { + height: auto; + vertical-align: top; +} + +.webkit-line-gutter-backdrop { + /* Keep this in sync with view-source.css (.webkit-line-gutter-backdrop) */ + width: 31px; + background-color: rgb(240, 240, 240); + border-right: 1px solid rgb(187, 187, 187); position: absolute; - margin-top: auto; - margin-bottom: auto; - top: 0; + z-index: -1; left: 0; - right: 0; - bottom: 0; + top: 0; + height: 100% +} + +.resource-view.font .resource-view-content { + font-size: 60px; + white-space: pre-wrap; + word-wrap: break-word; + text-align: center; + padding: 15px; } .resource-view.image .resource-view-content > .image { - position: relative; - height: 70%; - padding: 20px; + padding: 20px 20px 10px 20px; + text-align: center; } .resource-view.image .resource-view-content > .info { - position: relative; - height: 30%; - padding-top: 10px; - overflow: auto; + padding-bottom: 10px; font-size: 11px; + -webkit-user-select: text; } .resource-view.image img { - margin: auto; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - max-width: 80%; - max-height: 80%; + max-width: 100%; + max-height: 1000px; background-image: url(Images/checker.png); -webkit-box-shadow: 0px 5px 10px rgba(0, 0, 0, 0.5); + -webkit-user-select: text; + -webkit-user-drag: auto; } .resource-view.image .title { @@ -598,11 +789,12 @@ body.console-visible #console { display: inline-block; width: 50%; text-align: right; + color: rgb(76, 76, 76); } .resource-view.image .infoList dd { display: inline-block; - padding-left: 10px; + padding-left: 8px; width: 50%; text-align: left; margin: 0; @@ -630,13 +822,14 @@ body.console-visible #console { right: 0; bottom: 0; width: 225px; - background-color: rgb(232, 232, 232); + background-color: rgb(245, 245, 245); border-left: 1px solid rgb(64%, 64%, 64%); cursor: default; overflow: auto; } .crumbs { + display: inline-block; font-size: 11px; line-height: 19px; text-shadow: rgba(255, 255, 255, 0.75) 0 1px 0; @@ -712,6 +905,27 @@ body.console-visible #console { -webkit-border-image: url(Images/segmentHoverEnd.png) 0 2 0 2; } +.outline-disclosure li.hovered:not(.selected) .selection { + display: block; + left: 3px; + right: 3px; + background-color: rgba(56, 121, 217, 0.1); + -webkit-border-radius: 5px; +} + +.outline-disclosure li.highlighted .highlight { + background-color: rgb(255, 230, 179); + -webkit-border-radius: 4px; + padding-bottom: 2px; + margin-bottom: -2px; +} + +.outline-disclosure li.selected.highlighted .highlight { + background-color: transparent; + padding-bottom: 0; + margin-bottom: 0; +} + .outline-disclosure li .selection { display: none; position: absolute; @@ -723,16 +937,13 @@ body.console-visible #console { .outline-disclosure li.selected .selection { display: block; + background-color: rgb(212, 212, 212); } -.focused .outline-disclosure li.selected .selection { +:focus .outline-disclosure li.selected .selection { background-color: rgb(56, 121, 217); } -.blurred .outline-disclosure li.selected .selection, body.inactive .outline-disclosure li.selected .selection { - background-color: rgb(212, 212, 212); -} - .outline-disclosure > ol { position: relative; padding: 2px 6px !important; @@ -757,19 +968,19 @@ body.console-visible #console { text-indent: -2px } -.blurred .outline-disclosure li.selected, body.inactive .outline-disclosure li.selected { - color: black; +:focus .outline-disclosure li.selected { + color: white; } -.outline-disclosure li.selected { - color: white; +:focus .outline-disclosure li.selected * { + color: inherit; } .outline-disclosure li.parent { text-indent: -12px } -.elements.panel .outline-disclosure li .webkit-html-tag.close { +.outline-disclosure li .webkit-html-tag.close { margin-left: -12px; } @@ -782,23 +993,19 @@ body.console-visible #console { padding-right: 2px; } -.blurred .outline-disclosure li.parent.selected::before, body.inactive .outline-disclosure li.parent.selected::before { +.outline-disclosure li.parent::before { content: url(Images/treeRightTriangleBlack.png); } -.outline-disclosure li.parent.selected::before { +:focus .outline-disclosure li.parent.selected::before { content: url(Images/treeRightTriangleWhite.png); } -.blurred .outline-disclosure li.parent.expanded.selected::before, body.inactive .outline-disclosure li.parent.expanded.selected::before { - content: url(Images/treeDownTriangleBlack.png); -} - .outline-disclosure li.parent.expanded::before { content: url(Images/treeDownTriangleBlack.png); } -.outline-disclosure li.parent.expanded.selected::before { +:focus .outline-disclosure li.parent.expanded.selected::before { content: url(Images/treeDownTriangleWhite.png); } @@ -850,7 +1057,62 @@ body.console-visible #console { text-decoration: underline; } -body:not(.inactive) .focused .outline-disclosure li.selected * { +.placard { + position: relative; + margin-top: 1px; + padding: 3px 8px 4px 18px; + min-height: 18px; + white-space: nowrap; +} + +.placard:nth-of-type(2n) { + background-color: rgb(234, 243, 255); +} + +.placard.selected { + border-top: 1px solid rgb(145, 160, 192); + background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(162, 177, 207)), to(rgb(120, 138, 177))); + -webkit-background-origin: padding; + -webkit-background-clip: padding; +} + +:focus .placard.selected { + border-top: 1px solid rgb(68, 128, 200); + background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(92, 147, 213)), to(rgb(21, 83, 170))); +} + +body.inactive .placard.selected { + border-top: 1px solid rgb(151, 151, 151); + background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(180, 180, 180)), to(rgb(138, 138, 138))); +} + +.placard .title { + color: black; + font-weight: normal; + word-wrap: break-word; + white-space: normal; +} + +.placard.selected .title { + color: white; + font-weight: bold; +} + +.placard .subtitle { + float: right; + font-size: 10px; + margin-left: 5px; + max-width: 55%; + color: rgba(0, 0, 0, 0.7); + text-overflow: ellipsis; + overflow: hidden; +} + +.placard.selected .subtitle { + color: rgba(255, 255, 255, 0.7); +} + +.placard .subtitle a { color: inherit; } @@ -859,18 +1121,24 @@ body:not(.inactive) .focused .outline-disclosure li.selected * { margin-top: 1px; } +.section:nth-last-of-type(1) { + margin-bottom: 1px; +} + .section .header { - padding: 3px 8px 4px 16px; - /*background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(160, 172, 205)), to(rgb(132, 146, 190)));*/ - background-color: rgb(160, 172, 205); + padding: 2px 8px 4px 18px; + border-top: 1px solid rgb(145, 160, 192); + background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(162, 177, 207)), to(rgb(120, 138, 177))); min-height: 18px; white-space: nowrap; + -webkit-background-origin: padding; + -webkit-background-clip: padding; } .section .header::before { position: absolute; top: 4px; - left: 6px; + left: 7px; width: 8px; height: 8px; content: url(Images/treeRightTriangleWhite.png); @@ -921,7 +1189,7 @@ body:not(.inactive) .focused .outline-disclosure li.selected * { .section .properties { display: none; margin: 0; - padding: 2px 6px 5px; + padding: 2px 6px 3px; list-style: none; background-color: white; } @@ -931,17 +1199,16 @@ body:not(.inactive) .focused .outline-disclosure li.selected * { } .section .properties li { - margin-left: 10px; + margin-left: 12px; white-space: nowrap; text-overflow: ellipsis; overflow: hidden; -webkit-user-select: text; cursor: auto; - outline: none; } .section .properties li.parent { - margin-left: 0; + margin-left: 1px; } .section .properties ol { @@ -962,7 +1229,7 @@ body:not(.inactive) .focused .outline-disclosure li.selected * { width: 8px; height: 8px; margin-top: 0; - padding-right: 2px; + padding-right: 3px; -webkit-user-select: none; cursor: default; } @@ -972,6 +1239,11 @@ body:not(.inactive) .focused .outline-disclosure li.selected * { margin-top: 1px; } +.section .properties li .info { + padding-top: 4px; + padding-bottom: 3px; +} + .editing { -webkit-user-select: text; -webkit-box-shadow: rgba(0, 0, 0, .5) 3px 3px 4px; @@ -980,29 +1252,43 @@ body:not(.inactive) .focused .outline-disclosure li.selected * { -webkit-user-modify: read-write-plaintext-only; text-overflow: clip; padding-left: 2px; + margin-left: -2px; + padding-right: 2px; + margin-right: -2px; margin-bottom: -1px; padding-bottom: 1px; - text-decoration: none !important; opacity: 1.0 !important; } .editing, .editing * { color: black !important; + text-decoration: none !important; } .section .properties li.editing { - margin-left: 8px; + margin-left: 10px; text-overflow: clip; } -.section .properties li.editing.parent::before { - display: none; +li.editing .swatch, li.editing .enabled-button { + display: none !important; } -.section .properties .overloaded { +.section .properties li.editing-sub-part { + padding: 3px 6px 8px 18px; + margin: -3px -6px -8px -6px; + text-overflow: clip; +} + +.section .properties .overloaded, .section .properties .disabled { text-decoration: line-through; } +.section.computed-style .properties .disabled { + text-decoration: none; + opacity: 0.5; +} + .section .properties .implicit, .section .properties .inherited { opacity: 0.5; } @@ -1011,6 +1297,20 @@ body:not(.inactive) .focused .outline-disclosure li.selected * { display: none; } +.section .properties .enabled-button { + display: none; + float: right; + font-size: 10px; + margin: 0 0 0 4px; + vertical-align: top; + position: relative; + z-index: 1; +} + +.section:hover .properties .enabled-button { + display: block; +} + .section .properties .name { color: rgb(136, 19, 145); } @@ -1045,55 +1345,68 @@ body:not(.inactive) .focused .outline-disclosure li.selected * { border: 1px solid rgb(180, 180, 180); } -.pane { - margin-top: 1px; +.pane:not(.expanded) + .pane, .pane:first-of-type { + margin-top: -1px; } .pane > .title { - /*background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(221, 226, 239)), color-stop(0.5, rgb(220, 225, 238)), color-stop(0.5, rgb(194, 203, 219)), to(rgb(217, 222, 234)));*/ - background-color: rgb(221, 226, 239); - height: 16px; - padding: 0 6px; - border-top: 1px solid rgb(129, 129, 129); - border-bottom: 1px solid rgb(129, 129, 129); + background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(243, 243, 243)), color-stop(0.05, rgb(243, 243, 243)), color-stop(0.05, rgb(230, 230, 230)), to(rgb(209, 209, 209))); + height: 20px; + padding: 0 5px; + border-top: 1px solid rgb(189, 189, 189); + border-bottom: 1px solid rgb(189, 189, 189); font-weight: bold; - font-size: 11px; - color: rgb(85, 85, 85); + font-size: 12px; + line-height: 18px; + color: rgb(110, 110, 110); + text-shadow: white 0 1px 0; -webkit-background-origin: padding; -webkit-background-clip: padding; } .pane > .title:active { - /*background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(186, 191, 202)), color-stop(0.5, rgb(185, 190, 201)), color-stop(0.5, rgb(163, 171, 185)), to(rgb(183, 187, 197)));*/ - background-color: rgb(186, 191, 202); + background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(231, 231, 231)), color-stop(0.05, rgb(231, 231, 231)), color-stop(0.05, rgb(207, 207, 207)), to(rgb(186, 186, 186))); + border-top: 1px solid rgb(178, 178, 178); + border-bottom: 1px solid rgb(178, 178, 178); } .pane > .title::before { - content: url(Images/treeRightTriangleBlack.png); - opacity: 0.75; + content: url(Images/disclosureTriangleSmallRightBlack.png); float: left; - width: 8px; - height: 8px; - margin-right: 3px; - margin-top: 0; + width: 11px; + height: 12px; + margin-right: 2px; + margin-top: 1px; } .pane.expanded > .title::before { - margin-top: 1px; - content: url(Images/treeDownTriangleBlack.png); + content: url(Images/disclosureTriangleSmallDownBlack.png); } .pane > .body { position: relative; display: none; + background-color: white; overflow-y: auto; overflow-x: hidden; } +.pane > .body .info { + text-align: center; + font-style: italic; + font-size: 10px; + padding: 6px; + color: gray; +} + .pane.expanded > .body, .pane.expanded > .growbar { display: block; } +.pane.expanded:nth-last-of-type(1) { + border-bottom: 1px solid rgb(189, 189, 189); +} + .pane > .growbar { display: none; background-image: url(Images/paneGrowHandleLine.png), url(Images/paneBottomGrow.png); @@ -1114,15 +1427,25 @@ body:not(.inactive) .focused .outline-disclosure li.selected * { margin-top: -10px; font-size: 9px; color: grey; - background-color: rgb(232, 232, 232); + background-color: white; margin-left: 3px; padding-left: 2px; padding-right: 2px; } +.metrics .position { + border: 1px rgb(66%, 66%, 66%) dotted; + display: inline-block; + text-align: center; + padding: 3px; + margin: 3px; +} + .metrics .margin { border: 1px dashed; display: inline-block; + text-align: center; + vertical-align: middle; padding: 3px; margin: 3px; } @@ -1130,6 +1453,7 @@ body:not(.inactive) .focused .outline-disclosure li.selected * { .metrics .border { border: 1px black solid; display: inline-block; + text-align: center; vertical-align: middle; padding: 3px; margin: 3px; @@ -1138,6 +1462,7 @@ body:not(.inactive) .focused .outline-disclosure li.selected * { .metrics .padding { border: 1px grey dashed; display: inline-block; + text-align: center; vertical-align: middle; padding: 3px; margin: 3px; @@ -1147,6 +1472,7 @@ body:not(.inactive) .focused .outline-disclosure li.selected * { position: static; border: 1px grey solid; display: inline-block; + text-align: center; vertical-align: middle; padding: 3px; margin: 3px; @@ -1155,24 +1481,31 @@ body:not(.inactive) .focused .outline-disclosure li.selected * { overflow: visible; } +.metrics .content span { + display: inline-block; +} + +.metrics .editing { + position: relative; + z-index: 100; +} + .metrics .left { display: inline-block; - text-align: center; vertical-align: middle; } .metrics .right { display: inline-block; - text-align: center; vertical-align: middle; } .metrics .top { - text-align: center; + display: inline-block; } .metrics .bottom { - text-align: center; + display: inline-block; } .sidebar { @@ -1191,8 +1524,6 @@ body.inactive .sidebar { background-color: rgb(232, 232, 232); } -/** - Comment back in to support databases .database-sidebar-tree-item .icon { content: url(Images/database.png); } @@ -1201,7 +1532,11 @@ body.inactive .sidebar { content: url(Images/databaseTable.png); } -#database-views { +.domstorage-sidebar-tree-item .icon { + content: url(Images/domStorage.png); +} + +#storage-views { position: absolute; top: 0; right: 0; @@ -1209,7 +1544,7 @@ body.inactive .sidebar { bottom: 0; } -.database-view { +.storage-view { display: none; overflow: hidden; position: absolute; @@ -1219,22 +1554,20 @@ body.inactive .sidebar { bottom: 0; } -.database-view.visible { +.storage-view.visible { display: block; } -.database-view.table { - font-size: 10px; - overflow-y: auto; - overflow-x: hidden; +.storage-view.table { + overflow: hidden; } -.database-view.table .database-result-table { +.storage-view.table .data-grid { border: none; height: 100%; } -.database-view.table .database-table-empty, .database-view.table .database-table-error { +.storage-view.table .storage-table-empty, .storage-view.table .storage-table-error { position: absolute; top: 0; bottom: 25%; @@ -1252,69 +1585,199 @@ body.inactive .sidebar { white-space: pre-wrap; } -.database-view.table .database-table-error { +.storage-view.table .storage-table-error { color: rgb(66%, 33%, 33%); } -.database-result-table .database-result-filler-row { - height: auto; +.data-grid { + position: relative; + border: 1px solid #aaa; } -.database-result-table .database-result-filler-row.alternate td { - background-position-y: 16px; +.data-grid .highlight { + background-color: rgb(255, 230, 179); } -.database-result-filler-row td { - //background-image: -webkit-gradient(linear, left top, left bottom, from(white), color-stop(0.5, white), color-stop(0.5, rgb(234, 243, 255)), to(rgb(234, 243, 255))); - background-color: white; - -webkit-background-size: auto 32px; - -webkit-background-origin: padding; - -webkit-background-clip: padding; +.data-grid tr.selected .highlight { + background-color: transparent; } -.database-result-table { - border: 1px solid #aaa; +.data-grid table { table-layout: fixed; border-spacing: 0; border-collapse: collapse; width: 100%; + font-size: 10px; + font-family: Lucida Grande, sans-serif; } -.database-result-table th { +.data-grid .data-container { + position: absolute; + top: 16px; + bottom: 0; + left: 0; + right: 0; + padding-right: 14px; + overflow-x: hidden; + overflow-y: overlay; + background-image: -webkit-gradient(linear, left top, left bottom, from(white), color-stop(0.5, white), color-stop(0.5, rgb(234, 243, 255)), to(rgb(234, 243, 255))); + -webkit-background-size: 1px 32px; +} + +.data-grid.inline .data-container { + position: static; +} + +.data-grid th { text-align: left; - background: url(Images/glossyHeader.png) repeat-x; - border-right: 1px solid #aaa; + background-image: url(Images/glossyHeader.png); + background-repeat: repeat-x; + border-right: 1px solid rgb(179, 179, 179); + border-bottom: 1px solid rgb(179, 179, 179); height: 15px; - border-bottom: 1px solid #aaa; font-weight: normal; vertical-align: middle; padding: 0 4px; white-space: nowrap; } -.database-result-table tr { - height: 16px; +.data-grid th.corner { + width: 15px; + border-right: 0 none transparent; +} + +.data-grid tr.filler { + display: table-row !important; + height: auto !important; } -.database-result-table tr.alternate { - background-color: rgb(236, 243, 254); +.data-grid tr.filler td { + height: auto !important; + padding: 0 !important; } -.database-result-table td { +.data-grid table.data { + position: absolute; + left: 0; + top: 0; + right: 16px; + bottom: 0; + height: 100%; + border-top: 0 none transparent; + background-image: -webkit-gradient(linear, left top, left bottom, from(white), color-stop(0.5, white), color-stop(0.5, rgb(234, 243, 255)), to(rgb(234, 243, 255))); + -webkit-background-size: 1px 32px; +} + +.data-grid.inline table.data { + position: static; +} + +.data-grid table.data tr { + display: none; +} + +.data-grid table.data tr.revealed { + display: table-row; +} + +.data-grid td { vertical-align: top; + height: 12px; padding: 2px 4px; white-space: nowrap; border-right: 1px solid #aaa; -webkit-user-select: text; } -.database-result-table td > div, .database-result-table th > div { +.data-grid td > div, .data-grid th > div { white-space: nowrap; text-overflow: ellipsis; overflow: hidden; } -.database-view.query { +.data-grid th.sortable div { + position: relative; +} + +.data-grid th.sortable:active { + background-image: url(Images/glossyHeaderPressed.png); +} + +.data-grid th.sort-ascending, .data-grid th.sort-descending { + border-right: 1px solid rgb(107, 140, 196); + border-bottom: 1px solid rgb(107, 140, 196); + background-image: url(Images/glossyHeaderSelected.png); + background-repeat: repeat-x; +} + +.data-grid th.sortable.sort-ascending:active, .data-grid th.sortable.sort-descending:active { + background-image: url(Images/glossyHeaderSelectedPressed.png); +} + +.data-grid th.sort-ascending div::after { + position: absolute; + top: 0; + right: 0; + width: 8px; + height: 8px; + content: url(Images/treeUpTriangleBlack.png); +} + +.data-grid th.sort-descending div::after { + position: absolute; + top: 0; + right: 0; + margin-top: 1px; + width: 8px; + height: 8px; + content: url(Images/treeDownTriangleBlack.png); +} + +body.inactive .data-grid th.sort-ascending, body.inactive .data-grid th.sort-descending { + background-image: url(Images/glossyHeader.png); + border-right: 1px solid rgb(179, 179, 179); + border-bottom: 1px solid rgb(179, 179, 179); +} + +.data-grid tr.parent td.disclosure::before { + float: left; + content: url(Images/treeRightTriangleBlack.png); + width: 8px; + height: 8px; + margin-right: 2px; + -webkit-user-select: none; +} + +.data-grid tr.expanded td.disclosure::before { + content: url(Images/treeDownTriangleBlack.png); + width: 8px; + height: 8px; + margin-top: 1px; +} + +.data-grid tr.selected { + background-color: rgb(212, 212, 212); + color: inherit; +} + +.data-grid:focus tr.selected { + background-color: rgb(56, 121, 217); + color: white; +} + +.data-grid:focus tr.parent.selected td.disclosure::before { + content: url(Images/treeRightTriangleWhite.png); +} + +.data-grid:focus tr.expanded.selected td.disclosure::before { + content: url(Images/treeDownTriangleWhite.png); +} + +.data-grid tr:not(.parent) td.disclosure { + text-indent: 10px; +} + +.storage-view.query { font-size: 10px; font-family: Monaco, Lucida Console, monospace; padding: 2px 0; @@ -1325,7 +1788,6 @@ body.inactive .sidebar { .database-query-prompt { position: relative; - outline: none; padding: 1px 22px 1px 24px; min-height: 16px; white-space: pre-wrap; @@ -1351,7 +1813,7 @@ body.inactive .sidebar { .database-user-query { position: relative; - border-bottom: 1px solid rgb(240, 240, 240); + border-bottom: 1px solid rgb(245, 245, 245); padding: 1px 22px 1px 24px; min-height: 16px; } @@ -1380,21 +1842,154 @@ body.inactive .sidebar { .database-query-result.error::before { background-image: url(Images/errorIcon.png); -}*/ +} + +.panel-enabler-view { + z-index: 1000; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: white; + font-size: 13px; + text-align: center; + overflow-x: hidden; + overflow-y: overlay; + display: none; +} + +.panel-enabler-view.visible { + display: block; +} + +.panel-enabler-view .panel-enabler-view-content { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + max-height: 390px; + margin: auto; + white-space: nowrap; +} + +.panel-enabler-view h1 { + color: rgb(110, 116, 128); + font-size: 16px; + line-height: 20px; + font-weight: normal; + margin-top: 0; +} + +.panel-enabler-disclaimer { + font-size: 10px; + color: rgb(110, 116, 128); + margin-bottom: 12px; +} + +.panel-enabler-disclaimer:empty { + display: none; +} + +.panel-enabler-view img { + height: 100%; + min-height: 200px; + max-width: 100%; + top: 0; + bottom: 0; + padding: 20px 0 20px 20px; + margin: auto; + vertical-align: middle; +} + +.panel-enabler-view img.hidden { + display: initial !important; + width: 0; +} + +.panel-enabler-view form { + display: inline-block; + vertical-align: middle; + width: 330px; + margin: 0; + padding: 15px; + white-space: normal; +} + +.panel-enabler-view label { + position: relative; + display: block; + text-align: left; + margin-left: 50px; + margin-bottom: 6px; + line-height: 18px; + word-break: break-word; +} + +.panel-enabler-view button { + font-size: 13px; + margin: 6px 0 0 0; + padding: 3px 20px; + color: rgb(6, 6, 6); + height: 24px; + background-color: transparent; + border: 1px solid rgb(165, 165, 165); + background-color: rgb(237, 237, 237); + background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(252, 252, 252)), to(rgb(223, 223, 223))); + -webkit-border-radius: 12px; + -webkit-appearance: none; +} + +.panel-enabler-view button:active { + background-color: rgb(215, 215, 215); + background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(194, 194, 194)), to(rgb(239, 239, 239))); +} + +body.inactive .panel-enabler-view button, .panel-enabler-view button:disabled { + color: rgb(130, 130, 130); + border-color: rgb(212, 212, 212); + background-color: rgb(239, 239, 239); + background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(250, 250, 250)), to(rgb(235, 235, 235))); +} + +.panel-enabler-view.scripts img { + content: url(Images/scriptsSilhouette.png); +} + +.panel-enabler-view.profiles img { + content: url(Images/profilesSilhouette.png); +} + +button.enable-toggle-status-bar-item { + background-image: url(Images/enableButtons.png); +} -#scripts-debugging-status-bar-item { - background-image: url(Images/debuggingButtons.png); +button.enable-toggle-status-bar-item:active { + background-position: 32px 0; +} + +button.enable-toggle-status-bar-item.toggled-on { + background-position: 0 24px; +} + +button.enable-toggle-status-bar-item.toggled-on:active { + background-position: 32px 24px; } -#scripts-debugging-status-bar-item:active { +#scripts-pause-on-exceptions-status-bar-item { + background-image: url(Images/pauseOnExceptionButtons.png); +} + +#scripts-pause-on-exceptions-status-bar-item:active { background-position: 32px 0; } -#scripts-debugging-status-bar-item.toggled-on { +#scripts-pause-on-exceptions-status-bar-item.toggled-on { background-position: 0 24px; } -#scripts-debugging-status-bar-item.toggled-on:active { +#scripts-pause-on-exceptions-status-bar-item.toggled-on:active { background-position: 32px 24px; } @@ -1406,12 +2001,16 @@ body.inactive .sidebar { height: 24px; } -#scripts-status-bar .status-bar-item img { - margin-top: 2px; +#scripts-files { + max-width: 250px; } -#scripts-status-bar .status-bar-item:disabled img { - opacity: 0.5; +#scripts-functions { + max-width: 150px; +} + +#scripts-status-bar .status-bar-item img { + margin-top: 2px; } #scripts-back img { @@ -1426,6 +2025,10 @@ body.inactive .sidebar { content: url(Images/debuggerPause.png); } +#scripts-pause.paused img { + content: url(Images/debuggerContinue.png); +} + #scripts-step-over img { content: url(Images/debuggerStepOver.png); } @@ -1445,10 +2048,6 @@ body.inactive .sidebar { right: 8px; } -#scripts-debugger-status:empty { - display: none; -} - #scripts-sidebar-resizer-widget { position: absolute; top: 0; @@ -1482,13 +2081,27 @@ body.inactive .sidebar { bottom: 0; } +.script-view { + display: none; + overflow: hidden; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; +} + +.script-view.visible { + display: block; +} + #scripts-sidebar { position: absolute; top: 23px; right: 0; bottom: 0; width: 225px; - background-color: rgb(232, 232, 232); + background-color: rgb(245, 245, 245); border-left: 1px solid rgb(64%, 64%, 64%); cursor: default; overflow: auto; @@ -1560,8 +2173,7 @@ body.inactive .sidebar { margin-left: -1px; border-left: 1px solid rgb(102, 102, 102); background-color: rgb(101, 111, 130); - /*background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, 0)), to(rgba(0, 0, 0, 0.5)));*/ - background-color: transparent; + background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, 0)), to(rgba(0, 0, 0, 0.5))); background-repeat: repeat-x; background-position: bottom; text-align: center; @@ -1608,10 +2220,6 @@ body.inactive .sidebar { margin-right: 3px; } -.resources-summary-graph { - vertical-align: middle; -} - #resources-dividers { position: absolute; left: 0; @@ -1654,12 +2262,68 @@ body.inactive .sidebar { white-space: nowrap; } +.resources-graph-label { + position: absolute; + top: 0; + bottom: 0; + margin: auto -7px; + height: 13px; + line-height: 13px; + font-size: 9px; + color: rgba(0, 0, 0, 0.75); + text-shadow: rgba(255, 255, 255, 0.25) 1px 0 0, rgba(255, 255, 255, 0.25) -1px 0 0, rgba(255, 255, 255, 0.333) 0 1px 0, rgba(255, 255, 255, 0.25) 0 -1px 0; + z-index: 150; + overflow: hidden; + text-align: center; + font-weight: bold; + opacity: 0; + -webkit-transition: opacity 250ms ease-in-out; +} + +.resources-graph-side:hover .resources-graph-label { + opacity: 1; +} + +.resources-graph-label:empty { + display: none; +} + +.resources-graph-label.waiting { + margin-right: 5px; +} + +.resources-graph-label.before { + color: rgba(0, 0, 0, 0.7); + text-shadow: none; + text-align: right; + margin-right: 2px; +} + +.resources-graph-label.before::after { + padding-left: 2px; + height: 6px; + content: url(Images/graphLabelCalloutLeft.png); +} + +.resources-graph-label.after { + color: rgba(0, 0, 0, 0.7); + text-shadow: none; + text-align: left; + margin-left: 2px; +} + +.resources-graph-label.after::before { + padding-right: 2px; + height: 6px; + content: url(Images/graphLabelCalloutRight.png); +} + .resources-graph-bar { position: absolute; top: 0; bottom: 0; margin: auto -7px; - border-width: 6px 7px 6px 7px; + border-width: 6px 7px; height: 13px; min-width: 14px; opacity: 0.65; @@ -1670,30 +2334,58 @@ body.inactive .sidebar { opacity: 0.35; } -.resource-sidebar-tree-item.resources-category-documents .resources-graph-bar { +.resource-cached .resources-graph-bar { + -webkit-border-image: url(Images/timelineHollowPillGray.png) 6 7 6 7; +} + +.resources-category-documents .resources-graph-bar { -webkit-border-image: url(Images/timelinePillBlue.png) 6 7 6 7; } -.resource-sidebar-tree-item.resources-category-stylesheets .resources-graph-bar { +.resources-category-documents.resource-cached .resources-graph-bar { + -webkit-border-image: url(Images/timelineHollowPillBlue.png) 6 7 6 7; +} + +.resources-category-stylesheets .resources-graph-bar { -webkit-border-image: url(Images/timelinePillGreen.png) 6 7 6 7; } -.resource-sidebar-tree-item.resources-category-images .resources-graph-bar { +.resources-category-stylesheets.resource-cached .resources-graph-bar { + -webkit-border-image: url(Images/timelineHollowPillGreen.png) 6 7 6 7; +} + +.resources-category-images .resources-graph-bar { -webkit-border-image: url(Images/timelinePillPurple.png) 6 7 6 7; } -.resource-sidebar-tree-item.resources-category-fonts .resources-graph-bar { +.resources-category-images.resource-cached .resources-graph-bar { + -webkit-border-image: url(Images/timelineHollowPillPurple.png) 6 7 6 7; +} + +.resources-category-fonts .resources-graph-bar { -webkit-border-image: url(Images/timelinePillRed.png) 6 7 6 7; } -.resource-sidebar-tree-item.resources-category-scripts .resources-graph-bar { +.resources-category-fonts.resource-cached .resources-graph-bar { + -webkit-border-image: url(Images/timelineHollowPillRed.png) 6 7 6 7; +} + +.resources-category-scripts .resources-graph-bar { -webkit-border-image: url(Images/timelinePillOrange.png) 6 7 6 7; } -.resource-sidebar-tree-item.resources-category-xhr .resources-graph-bar { +.resources-category-scripts.resource-cached .resources-graph-bar { + -webkit-border-image: url(Images/timelineHollowPillOrange.png) 6 7 6 7; +} + +.resources-category-xhr .resources-graph-bar { -webkit-border-image: url(Images/timelinePillYellow.png) 6 7 6 7; } +.resources-category-xhr.resource-cached .resources-graph-bar { + -webkit-border-image: url(Images/timelineHollowPillYellow.png) 6 7 6 7; +} + .tip-button { background-image: url(Images/tipIcon.png); border: none; @@ -1810,6 +2502,10 @@ body.inactive .sidebar { padding-left: 37px; } +.sidebar-tree > .children > .children > .sidebar-tree-item { + padding-left: 37px; +} + .sidebar-tree.hide-disclosure-buttons > .children { display: none; } @@ -1917,7 +2613,7 @@ body.inactive .sidebar-tree-item .disclosure-button:active { color: rgb(132, 154, 190) !important; } -.focused .sidebar-tree-item.selected .status .bubble { +:focus .sidebar-tree-item.selected .status .bubble { color: rgb(36, 98, 172) !important; } @@ -1925,9 +2621,8 @@ body.inactive .sidebar-tree-item.selected .status .bubble { color: rgb(159, 159, 159) !important; } -.sidebar-tree.small .sidebar-tree-item, .sidebar-tree .children.small .sidebar-tree-item, .sidebar-tree-item.small { +.sidebar-tree.small .sidebar-tree-item, .sidebar-tree .children.small .sidebar-tree-item, .sidebar-tree-item.small, .small .resources-graph-side { height: 20px; - line-height: 18px; } .sidebar-tree.small .sidebar-tree-item .icon, .sidebar-tree .children.small .sidebar-tree-item .icon, .sidebar-tree-item.small .icon { @@ -1942,24 +2637,21 @@ body.inactive .sidebar-tree-item.selected .status .bubble { .sidebar-tree-item.selected { color: white; border-top: 1px solid rgb(145, 160, 192); - /*background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(162, 177, 207)), to(rgb(120, 138, 177)));*/ - background-color: rgb(162, 177, 207); + background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(162, 177, 207)), to(rgb(120, 138, 177))); text-shadow: rgba(0, 0, 0, 0.33) 0 1px 0; font-weight: bold; -webkit-background-origin: padding; -webkit-background-clip: padding; } -.focused .sidebar-tree-item.selected { +:focus .sidebar-tree-item.selected { border-top: 1px solid rgb(68, 128, 200); - /*background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(92, 147, 213)), to(rgb(21, 83, 170)));*/ - background-color: rgb(92, 147, 213); + background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(92, 147, 213)), to(rgb(21, 83, 170))); } body.inactive .sidebar-tree-item.selected { border-top: 1px solid rgb(151, 151, 151); - /*background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(180, 180, 180)), to(rgb(138, 138, 138)));*/ - background-color: rgb(180, 180, 180); + background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(180, 180, 180)), to(rgb(138, 138, 138))); } .sidebar-tree-item .titles { @@ -1999,14 +2691,25 @@ body.inactive .sidebar-tree-item.selected { color: rgba(255, 255, 255, 0.9); } -.sidebar-tree-item .resources-graph-side { +#resources-graphs { position: absolute; - height: 100%; - top: 0; + left: 0; right: 0; + max-height: 100%; + top: 112px; +} + +.resources-graph-side { + position: relative; + height: 36px; + padding: 0 5px; + white-space: nowrap; + margin-top: 1px; + border-top: 1px solid transparent; + overflow: hidden; } -.sidebar-tree-item .resources-graph-bar-area { +.resources-graph-bar-area { position: absolute; top: 0; bottom: 0; @@ -2018,14 +2721,10 @@ body.inactive .sidebar-tree-item.selected { background-color: rgba(0, 0, 0, 0.05); } -#resources-container:not(.viewing-resource) .resource-sidebar-tree-item:nth-of-type(2n) .resources-graph-side { +#resources-container:not(.viewing-resource) .resources-graph-side:nth-of-type(2n) { background-color: rgba(0, 0, 0, 0.05); } -#resources-container.viewing-resource #resources-sidebar .sidebar-tree-item .resources-graph-side { - display: none; -} - .resources-time-graph-sidebar-item .icon { content: url(Images/resourcesTimeGraphIcon.png); } @@ -2063,11 +2762,37 @@ body.inactive .sidebar-tree-item.selected { } .resource-sidebar-tree-item.resources-category-images .icon { - content: url(Images/resourcePlainIcon.png); + position: relative; + background-image: url(Images/resourcePlainIcon.png); + background-repeat: no-repeat; + content: ""; +} + +.resource-sidebar-tree-item.resources-category-images .image-resource-icon-preview { + position: absolute; + margin: auto; + top: 3px; + bottom: 4px; + left: 5px; + right: 5px; + max-width: 18px; + max-height: 21px; + min-width: 1px; + min-height: 1px; } .children.small .resource-sidebar-tree-item.resources-category-images .icon { - content: url(Images/resourcePlainIconSmall.png); + background-image: url(Images/resourcePlainIconSmall.png); + content: ""; +} + +.children.small .resource-sidebar-tree-item.resources-category-images .image-resource-icon-preview { + top: 2px; + bottom: 1px; + left: 3px; + right: 3px; + max-width: 8px; + max-height: 11px; } .resource-sidebar-tree-item.resources-category-fonts .icon { @@ -2094,10 +2819,186 @@ body.inactive .sidebar-tree-item.selected { content: url(Images/resourceDocumentIconSmall.png); } -.resource-sidebar-tree-item .bubble.warning { - background-color: rgb(232, 164, 0); +.bubble.warning, .console-warning-level .bubble { + background-color: rgb(232, 164, 0) !important; } -.resource-sidebar-tree-item .bubble.error { - background-color: rgb(216, 35, 35); +.bubble.error, .console-error-level .bubble { + background-color: rgb(216, 35, 35) !important; +} + +.bubble.search-matches { + background-image: url(Images/searchSmallWhite.png); + background-repeat: no-repeat; + background-position: 3px 2px; + padding-left: 13px !important; +} + +.sidebar-tree-item.selected .bubble.search-matches { + background-image: url(Images/searchSmallBlue.png); +} + +:focus .sidebar-tree-item.selected .bubble.search-matches { + background-image: url(Images/searchSmallBrightBlue.png); +} + +body.inactive .sidebar-tree-item.selected .bubble.search-matches { + background-image: url(Images/searchSmallGray.png); +} + +/* Profiler Style */ + +#profile-views { + position: absolute; + top: 0; + right: 0; + left: 200px; + bottom: 0; +} + +#profile-view-status-bar-items { + position: absolute; + top: 0; + bottom: 0; + left: 200px; + overflow: hidden; + border-left: 1px solid rgb(184, 184, 184); + margin-left: -1px; +} + +.profile-sidebar-tree-item .icon { + content: url(Images/profileIcon.png); +} + +.profile-sidebar-tree-item.small .icon { + content: url(Images/profileSmallIcon.png); +} + +.profile-group-sidebar-tree-item .icon { + content: url(Images/profileGroupIcon.png); +} + +.profile-view { + display: none; + overflow: hidden; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; +} + +.profile-view.visible { + display: block; +} + +.profile-view .data-grid { + border: none; + height: 100%; +} + +.profile-view .data-grid th.self-column { + text-align: center; +} + +.profile-view .data-grid td.self-column { + text-align: right; +} + +.profile-view .data-grid th.total-column { + text-align: center; +} + +.profile-view .data-grid td.total-column { + text-align: right; +} + +.profile-view .data-grid .calls-column { + text-align: center; +} + +.profile-node-file { + float: right; + color: gray; + margin-top: -1px; +} + +.data-grid tr.selected .profile-node-file { + color: rgb(33%, 33%, 33%); +} + +.data-grid:focus tr.selected .profile-node-file { + color: white; +} + +#record-profile-status-bar-item { + background-image: url(Images/recordButtons.png); +} + +#record-profile-status-bar-item:active { + background-position: 32px 0; +} + +#record-profile-status-bar-item.toggled-on { + background-position: 0 24px; +} + +#record-profile-status-bar-item.toggled-on:active { + background-position: 32px 24px; +} + +#node-search-status-bar-item { + background-image: url(Images/nodeSearchButtons.png); +} + +#node-search-status-bar-item:active { + background-position: 32px 0; +} + +#node-search-status-bar-item.toggled-on { + background-position: 0 24px; +} + +#node-search-status-bar-item.toggled-on:active { + background-position: 32px 24px; +} + +.percent-time-status-bar-item { + background-image: url(Images/percentButtons.png) !important; +} + +.percent-time-status-bar-item:active { + background-position: 32px 0; +} + +.percent-time-status-bar-item.toggled-on { + background-position: 0 24px; +} + +.percent-time-status-bar-item.toggled-on:active { + background-position: 32px 24px; +} + +.focus-profile-node-status-bar-item { + background-image: url(Images/focusButtons.png) !important; +} + +.focus-profile-node-status-bar-item:active { + background-position: 32px 0; +} + +.exclude-profile-node-status-bar-item { + background-image: url(Images/excludeButtons.png) !important; +} + +.exclude-profile-node-status-bar-item:active { + background-position: 32px 0; +} + +.reset-profile-status-bar-item { + background-image: url(Images/reloadButtons.png) !important; +} + +.reset-profile-status-bar-item:active { + background-position: 32px 0; } diff --git a/chrome/tools/test/reference_build/chrome/resources/Inspector/inspector.html b/chrome/tools/test/reference_build/chrome/resources/Inspector/inspector.html index 1c0d49e..db1e28b 100644 --- a/chrome/tools/test/reference_build/chrome/resources/Inspector/inspector.html +++ b/chrome/tools/test/reference_build/chrome/resources/Inspector/inspector.html @@ -33,45 +33,60 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. <script type="text/javascript" src="utilities.js"></script> <script type="text/javascript" src="treeoutline.js"></script> <script type="text/javascript" src="inspector.js"></script> + <script type="text/javascript" src="Object.js"></script> <script type="text/javascript" src="TextPrompt.js"></script> + <script type="text/javascript" src="Placard.js"></script> <script type="text/javascript" src="View.js"></script> <script type="text/javascript" src="Console.js"></script> <script type="text/javascript" src="Resource.js"></script> <script type="text/javascript" src="ResourceCategory.js"></script> <script type="text/javascript" src="Database.js"></script> + <script type="text/javascript" src="DOMStorage.js"></script> + <script type="text/javascript" src="DOMStorageItemsView.js"></script> + <script type="text/javascript" src="DataGrid.js"></script> + <script type="text/javascript" src="Script.js"></script> + <script type="text/javascript" src="Breakpoint.js"></script> <script type="text/javascript" src="SidebarPane.js"></script> + <script type="text/javascript" src="ElementsTreeOutline.js"></script> <script type="text/javascript" src="SidebarTreeElement.js"></script> <script type="text/javascript" src="PropertiesSection.js"></script> + <script type="text/javascript" src="ObjectPropertiesSection.js"></script> <script type="text/javascript" src="BreakpointsSidebarPane.js"></script> <script type="text/javascript" src="CallStackSidebarPane.js"></script> + <script type="text/javascript" src="ScopeChainSidebarPane.js"></script> <script type="text/javascript" src="MetricsSidebarPane.js"></script> <script type="text/javascript" src="PropertiesSidebarPane.js"></script> <script type="text/javascript" src="StylesSidebarPane.js"></script> <script type="text/javascript" src="Panel.js"></script> + <script type="text/javascript" src="PanelEnablerView.js"></script> <script type="text/javascript" src="ElementsPanel.js"></script> <script type="text/javascript" src="ResourcesPanel.js"></script> <script type="text/javascript" src="ScriptsPanel.js"></script> - <!--script type="text/javascript" src="DatabasesPanel.js"></script--> + <script type="text/javascript" src="DatabasesPanel.js"></script> + <script type="text/javascript" src="ProfilesPanel.js"></script> <script type="text/javascript" src="ResourceView.js"></script> + <script type="text/javascript" src="SourceFrame.js"></script> <script type="text/javascript" src="SourceView.js"></script> <script type="text/javascript" src="FontView.js"></script> <script type="text/javascript" src="ImageView.js"></script> - <!--script type="text/javascript" src="DatabaseTableView.js"></script> - <script type="text/javascript" src="DatabaseQueryView.js"></script--> + <script type="text/javascript" src="DatabaseTableView.js"></script> + <script type="text/javascript" src="DatabaseQueryView.js"></script> + <script type="text/javascript" src="ScriptView.js"></script> + <script type="text/javascript" src="ProfileView.js"></script> </head> <body class="detached"> <div id="toolbar"> + <div class="toolbar-item close"><button id="close-button"></button></div> <div class="toolbar-item flexable-space"></div> - <div class="toolbar-item"><input id="search" type="search" results="20" incremental="incremental" onsearch="WebInspector.performSearch(this.value)"><div id="search-toolbar-label" class="toolbar-label"></div></div> + <div class="toolbar-item hidden" id="search-results-matches"></div> + <div class="toolbar-item"><input id="search" type="search" incremental results="0"><div id="search-toolbar-label" class="toolbar-label"></div></div> </div> <div id="main"> - <div id="searchResults" class="focusable hidden"></div> - <div id="searchResultsResizer" class="hidden"></div> - <div id="main-panels" class="focusable focused"></div> - <div id="main-status-bar" class="status-bar"><div id="anchored-status-bar-items"><button id="dock-status-bar-item" class="status-bar-item toggled"></button><button id="console-status-bar-item" class="status-bar-item"></button><div id="error-warning-count" class="hidden"></div></div></div> + <div id="main-panels" tabindex="0"></div> + <div id="main-status-bar" class="status-bar"><div id="anchored-status-bar-items"><button id="dock-status-bar-item" class="status-bar-item toggled"></button><button id="console-status-bar-item" class="status-bar-item"></button><div id="error-warning-count" class="hidden"></div></div></div> </div> <div id="console"> - <div id="console-messages" class="focusable blurred"><div id="console-prompt"><br></div></div> + <div id="console-messages"><div id="console-prompt"><br></div></div> <div id="console-status-bar" class="status-bar"><div id="other-console-status-bar-items"><button id="clear-console-status-bar-item" class="status-bar-item"></button></div></div> </div> </body> diff --git a/chrome/tools/test/reference_build/chrome/resources/Inspector/inspector.js b/chrome/tools/test/reference_build/chrome/resources/Inspector/inspector.js index a1e1805a..759684f 100644 --- a/chrome/tools/test/reference_build/chrome/resources/Inspector/inspector.js +++ b/chrome/tools/test/reference_build/chrome/resources/Inspector/inspector.js @@ -7,13 +7,13 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. + * documentation and/or other materials provided with the distribution. * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. + * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -31,22 +31,25 @@ var Preferences = { ignoreWhitespace: true, showUserAgentStyles: true, maxInlineTextChildLength: 80, - maxTextSearchResultLength: 80, minConsoleHeight: 75, minSidebarWidth: 100, minElementsSidebarWidth: 200, minScriptsSidebarWidth: 200, showInheritedComputedStyleProperties: false, + styleRulesExpandedState: {}, showMissingLocalizedStrings: false } var WebInspector = { resources: [], resourceURLMap: {}, - searchResultsHeight: 100, - localizedStrings: {}, missingLocalizedStrings: {}, + get previousFocusElement() + { + return this._previousFocusElement; + }, + get currentFocusElement() { return this._currentFocusElement; @@ -54,28 +57,12 @@ var WebInspector = { set currentFocusElement(x) { - if (!x || this._currentFocusElement === x) - return; - - if (this._currentFocusElement) { - this._currentFocusElement.removeStyleClass("focused"); - this._currentFocusElement.addStyleClass("blurred"); - if (this._currentFocusElement.blur) - this._currentFocusElement.blur(); - if (this._currentFocusElement.blurred) - this._currentFocusElement.blurred(x); - } - - var previousFocusElement = this._currentFocusElement; + if (this._currentFocusElement !== x) + this._previousFocusElement = this._currentFocusElement; this._currentFocusElement = x; - if (x) { - x.addStyleClass("focused"); - x.removeStyleClass("blurred"); - if (this._currentFocusElement.focus) - this._currentFocusElement.focus(); - if (this._currentFocusElement.focused) - this._currentFocusElement.focused(previousFocusElement); + if (this._currentFocusElement) { + this._currentFocusElement.focus(); // Make a caret selection inside the new element if there isn't a range selection and // there isn't already a caret selection inside. @@ -88,7 +75,8 @@ var WebInspector = { selection.removeAllRanges(); selection.addRange(selectionRange); } - } + } else if (this._previousFocusElement) + this._previousFocusElement.blur(); }, get currentPanel() @@ -106,8 +94,29 @@ var WebInspector = { this._currentPanel = x; - if (x) + this.updateSearchLabel(); + + if (x) { x.show(); + + if (this.currentQuery) { + if (x.performSearch) { + function performPanelSearch() + { + this.updateSearchMatchesCount(); + + x.currentQuery = this.currentQuery; + x.performSearch(this.currentQuery); + } + + // Perform the search on a timeout so the panel switches fast. + setTimeout(performPanelSearch.bind(this), 0); + } else { + // Update to show Not found for panels that can't be searched. + this.updateSearchMatchesCount(); + } + } + } }, get attached() @@ -122,6 +131,8 @@ var WebInspector = { this._attached = x; + this.updateSearchLabel(); + var dockToggleButton = document.getElementById("dock-status-bar-item"); var body = document.body; @@ -138,131 +149,128 @@ var WebInspector = { } }, - get showingSearchResults() + get errors() { - return this._showingSearchResults; + return this._errors || 0; }, - set showingSearchResults(x) + set errors(x) { - if (this._showingSearchResults === x) + x = Math.max(x, 0); + + if (this._errors === x) return; + this._errors = x; + this._updateErrorAndWarningCounts(); + }, - this._showingSearchResults = x; + get warnings() + { + return this._warnings || 0; + }, - var resultsContainer = document.getElementById("searchResults"); - var searchResultsResizer = document.getElementById("searchResultsResizer"); + set warnings(x) + { + x = Math.max(x, 0); - if (x) { - resultsContainer.removeStyleClass("hidden"); - searchResultsResizer.removeStyleClass("hidden"); + if (this._warnings === x) + return; + this._warnings = x; + this._updateErrorAndWarningCounts(); + }, + + _updateErrorAndWarningCounts: function() + { + var errorWarningElement = document.getElementById("error-warning-count"); + if (!errorWarningElement) + return; + + if (!this.errors && !this.warnings) { + errorWarningElement.addStyleClass("hidden"); + return; + } - var animations = [ - {element: resultsContainer, end: {top: 0}}, - {element: searchResultsResizer, end: {top: WebInspector.searchResultsHeight - 3}}, - {element: document.getElementById("main-panels"), end: {top: WebInspector.searchResultsHeight}} - ]; + errorWarningElement.removeStyleClass("hidden"); - WebInspector.animateStyle(animations, 250); + errorWarningElement.removeChildren(); + + if (this.errors) { + var errorElement = document.createElement("span"); + errorElement.id = "error-count"; + errorElement.textContent = this.errors; + errorWarningElement.appendChild(errorElement); + } + + if (this.warnings) { + var warningsElement = document.createElement("span"); + warningsElement.id = "warning-count"; + warningsElement.textContent = this.warnings; + errorWarningElement.appendChild(warningsElement); + } + + if (this.errors) { + if (this.warnings) { + if (this.errors == 1) { + if (this.warnings == 1) + errorWarningElement.title = WebInspector.UIString("%d error, %d warning", this.errors, this.warnings); + else + errorWarningElement.title = WebInspector.UIString("%d error, %d warnings", this.errors, this.warnings); + } else if (this.warnings == 1) + errorWarningElement.title = WebInspector.UIString("%d errors, %d warning", this.errors, this.warnings); + else + errorWarningElement.title = WebInspector.UIString("%d errors, %d warnings", this.errors, this.warnings); + } else if (this.errors == 1) + errorWarningElement.title = WebInspector.UIString("%d error", this.errors); + else + errorWarningElement.title = WebInspector.UIString("%d errors", this.errors); + } else if (this.warnings == 1) + errorWarningElement.title = WebInspector.UIString("%d warning", this.warnings); + else if (this.warnings) + errorWarningElement.title = WebInspector.UIString("%d warnings", this.warnings); + else + errorWarningElement.title = null; + }, + + get hoveredDOMNode() + { + return this._hoveredDOMNode; + }, + + set hoveredDOMNode(x) + { + if (objectsAreSame(this._hoveredDOMNode, x)) + return; + + this._hoveredDOMNode = x; + + if (this._hoveredDOMNode) + this._updateHoverHighlightSoon(this.showingDOMNodeHighlight ? 50 : 500); + else + this._updateHoverHighlight(); + }, + + _updateHoverHighlightSoon: function(delay) + { + if ("_updateHoverHighlightTimeout" in this) + clearTimeout(this._updateHoverHighlightTimeout); + this._updateHoverHighlightTimeout = setTimeout(this._updateHoverHighlight.bind(this), delay); + }, + + _updateHoverHighlight: function() + { + if ("_updateHoverHighlightTimeout" in this) { + clearTimeout(this._updateHoverHighlightTimeout); + delete this._updateHoverHighlightTimeout; + } + + if (this._hoveredDOMNode) { + InspectorController.highlightDOMNode(this._hoveredDOMNode); + this.showingDOMNodeHighlight = true; } else { - searchResultsResizer.addStyleClass("hidden"); - - var animations = [ - {element: resultsContainer, end: {top: -WebInspector.searchResultsHeight}}, - {element: searchResultsResizer, end: {top: 0}}, - {element: document.getElementById("main-panels"), end: {top: 0}} - ]; - - var animationFinished = function() - { - resultsContainer.addStyleClass("hidden"); - resultsContainer.removeChildren(); - delete this.searchResultsTree; - }; - - WebInspector.animateStyle(animations, 250, animationFinished); + InspectorController.hideDOMNodeHighlight(); + this.showingDOMNodeHighlight = false; } - }, - get errors() - { - return this._errors || 0; - }, - - set errors(x) - { - x = Math.max(x, 0); - - if (this._errors === x) - return; - this._errors = x; - this._updateErrorAndWarningCounts(); - }, - - get warnings() - { - return this._warnings || 0; - }, - - set warnings(x) - { - x = Math.max(x, 0); - - if (this._warnings === x) - return; - this._warnings = x; - this._updateErrorAndWarningCounts(); - }, - - _updateErrorAndWarningCounts: function() - { - var errorWarningElement = document.getElementById("error-warning-count"); - if (!errorWarningElement) - return; - if (!this.errors && !this.warnings) { - errorWarningElement.addStyleClass("hidden"); - return; - } - - errorWarningElement.removeStyleClass("hidden"); - - errorWarningElement.removeChildren(); - - if (this.errors) { - var errorElement = document.createElement("span"); - errorElement.id = "error-count"; - errorElement.textContent = this.errors; - errorWarningElement.appendChild(errorElement); - } - - if (this.warnings) { - var warningsElement = document.createElement("span"); - warningsElement.id = "warning-count"; - warningsElement.textContent = this.warnings; - errorWarningElement.appendChild(warningsElement); - } - - if (this.errors) { - if (this.warnings) { - if (this.errors == 1) { - if (this.warnings == 1) - errorWarningElement.title = WebInspector.UIString("%d error, %d warning", this.errors, this.warnings); - else - errorWarningElement.title = WebInspector.UIString("%d error, %d warnings", this.errors, this.warnings); - } else if (this.warnings == 1) - errorWarningElement.title = WebInspector.UIString("%d errors, %d warning", this.errors, this.warnings); - else - errorWarningElement.title = WebInspector.UIString("%d errors, %d warnings", this.errors, this.warnings); - } else if (this.errors == 1) - errorWarningElement.title = WebInspector.UIString("%d error", this.errors); - else - errorWarningElement.title = WebInspector.UIString("%d errors", this.errors); - } else if (this.warnings == 1) - errorWarningElement.title = WebInspector.UIString("%d warning", this.warnings); - else if (this.warnings) - errorWarningElement.title = WebInspector.UIString("%d warnings", this.warnings); - else - errorWarningElement.title = null; - } + } } WebInspector.loaded = function() @@ -271,15 +279,18 @@ WebInspector.loaded = function() document.body.addStyleClass("platform-" + platform); this.console = new WebInspector.Console(); - this.panels = { elements: new WebInspector.ElementsPanel(), - resources: new WebInspector.ResourcesPanel() - // We don't use the databases tab, so don't show it. - // , databases: new WebInspector.DatabasesPanel() + resources: new WebInspector.ResourcesPanel(), + // We don't use next tabs, so don't show them. + //scripts: new WebInspector.ScriptsPanel(), + //profiles: new WebInspector.ProfilesPanel(), + //databases: new WebInspector.DatabasesPanel() }; var toolbarElement = document.getElementById("toolbar"); + var previousToolbarItem = toolbarElement.children[0]; + for (var panelName in this.panels) { var panel = this.panels[panelName]; var panelToolbarItem = panel.toolbarItem; @@ -288,7 +299,7 @@ WebInspector.loaded = function() toolbarElement.insertBefore(panelToolbarItem, previousToolbarItem.nextSibling); else toolbarElement.insertBefore(panelToolbarItem, toolbarElement.firstChild); - var previousToolbarItem = panelToolbarItem; + previousToolbarItem = panelToolbarItem; } this.currentPanel = this.panels.elements; @@ -316,19 +327,21 @@ WebInspector.loaded = function() window.addEventListener("unload", this.windowUnload.bind(this), true); window.addEventListener("resize", this.windowResize.bind(this), true); - document.addEventListener("mousedown", this.changeFocus.bind(this), true); - document.addEventListener("focus", this.changeFocus.bind(this), true); + document.addEventListener("focus", this.focusChanged.bind(this), true); document.addEventListener("keydown", this.documentKeyDown.bind(this), true); + document.addEventListener("keyup", this.documentKeyUp.bind(this), true); document.addEventListener("beforecopy", this.documentCanCopy.bind(this), true); document.addEventListener("copy", this.documentCopy.bind(this), true); - document.getElementById("searchResultsResizer").addEventListener("mousedown", this.searchResultsResizerDragStart, true); - var mainPanelsElement = document.getElementById("main-panels"); mainPanelsElement.handleKeyEvent = this.mainKeyDown.bind(this); + mainPanelsElement.handleKeyUpEvent = this.mainKeyUp.bind(this); mainPanelsElement.handleCopyEvent = this.mainCopy.bind(this); - this.currentFocusElement = mainPanelsElement; + // Focus the mainPanelsElement in a timeout so it happens after the initial focus, + // so it doesn't get reset to the first toolbar button. This initial focus happens + // on Mac when the window is made key and the WebHTMLView becomes the first responder. + setTimeout(function() { WebInspector.currentFocusElement = mainPanelsElement }, 0); var dockToggleButton = document.getElementById("dock-status-bar-item"); dockToggleButton.addEventListener("click", this.toggleAttach.bind(this), false); @@ -338,13 +351,17 @@ WebInspector.loaded = function() else dockToggleButton.title = WebInspector.UIString("Dock to main window."); - var errorWarningCount = document.getElementById("error-warning-count"); - errorWarningCount.addEventListener("click", this.console.show.bind(this.console), false); - this._updateErrorAndWarningCounts(); - document.getElementById("search-toolbar-label").textContent = WebInspector.UIString("Search"); + var errorWarningCount = document.getElementById("error-warning-count"); + errorWarningCount.addEventListener("click", this.console.show.bind(this.console), false); + this._updateErrorAndWarningCounts(); + + var searchField = document.getElementById("search"); + searchField.addEventListener("keydown", this.searchKeyDown.bind(this), false); + searchField.addEventListener("keyup", this.searchKeyUp.bind(this), false); + searchField.addEventListener("search", this.performSearch.bind(this), false); // when the search is emptied - if (platform === "mac-leopard") - document.getElementById("toolbar").addEventListener("mousedown", this.toolbarDragStart, true); + document.getElementById("toolbar").addEventListener("mousedown", this.toolbarDragStart, true); + document.getElementById("close-button").addEventListener("click", this.close, true); InspectorController.loaded(); } @@ -388,24 +405,21 @@ WebInspector.windowBlured = function(event) { if (event.target.nodeType === Node.DOCUMENT_NODE) document.body.addStyleClass("inactive"); - this.hideDOMNodeHighlight(); } -WebInspector.changeFocus = function(event) +WebInspector.focusChanged = function(event) { - var nextFocusElement; - - var current = event.target; - while (current) { - if (current.nodeName.toLowerCase() === "input") - nextFocusElement = current; - current = current.parentNode; - } + this.currentFocusElement = event.target; +} - if (!nextFocusElement) - nextFocusElement = event.target.enclosingNodeOrSelfWithClass("focusable"); +WebInspector.setAttachedWindow = function(attached) +{ + this.attached = attached; +} - this.currentFocusElement = nextFocusElement; +WebInspector.close = function(event) +{ + InspectorController.closeWindow(); } WebInspector.documentClick = function(event) @@ -414,18 +428,39 @@ WebInspector.documentClick = function(event) if (!anchor) return; - if (anchor.followOnAltClick && !event.altKey) { - event.preventDefault(); - return; + // Prevent the link from navigating, since we don't do any navigation by following links normally. + event.preventDefault(); + + function followLink() + { + // FIXME: support webkit-html-external-link links here. + if (anchor.href in WebInspector.resourceURLMap) { + if (anchor.hasStyleClass("webkit-html-external-link")) { + anchor.removeStyleClass("webkit-html-external-link"); + anchor.addStyleClass("webkit-html-resource-link"); + } + + WebInspector.showResourceForURL(anchor.href, anchor.lineNumber, anchor.preferredPanel); + } else { + var profileStringRegEx = new RegExp("webkit-profile://.+/([0-9]+)"); + var profileString = profileStringRegEx.exec(anchor.href); + if (profileString) + WebInspector.showProfileById(profileString[1]) + } } - if (!anchor.hasStyleClass("webkit-html-resource-link")) - return; + if (WebInspector.followLinkTimeout) + clearTimeout(WebInspector.followLinkTimeout); - if (WebInspector.showResourceForURL(anchor.href, anchor.lineNumber)) { - event.preventDefault(); - event.stopPropagation(); + if (anchor.preventFollowOnDoubleClick) { + // Start a timeout if this is the first click, if the timeout is canceled + // before it fires, then a double clicked happened or another link was clicked. + if (event.detail === 1) + WebInspector.followLinkTimeout = setTimeout(followLink, 333); + return; } + + followLink(); } WebInspector.documentKeyDown = function(event) @@ -438,15 +473,56 @@ WebInspector.documentKeyDown = function(event) WebInspector[this.currentFocusElement.id + "KeyDown"](event); if (!event.handled) { + var isMac = InspectorController.platform().indexOf("mac-") === 0; + switch (event.keyIdentifier) { case "U+001B": // Escape key this.console.visible = !this.console.visible; event.preventDefault(); break; + + case "U+0046": // F key + if (isMac) + var isFindKey = event.metaKey && !event.ctrlKey && !event.altKey && !event.shiftKey; + else + var isFindKey = event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey; + + if (isFindKey) { + var searchField = document.getElementById("search"); + searchField.focus(); + searchField.select(); + event.preventDefault(); + } + + break; + + case "U+0047": // G key + if (isMac) + var isFindAgainKey = event.metaKey && !event.ctrlKey && !event.altKey; + else + var isFindAgainKey = event.ctrlKey && !event.metaKey && !event.altKey; + + if (isFindAgainKey) { + if (event.shiftKey) { + if (this.currentPanel.jumpToPreviousSearchResult) + this.currentPanel.jumpToPreviousSearchResult(); + } else if (this.currentPanel.jumpToNextSearchResult) + this.currentPanel.jumpToNextSearchResult(); + event.preventDefault(); + } + + break; } } } +WebInspector.documentKeyUp = function(event) +{ + if (!this.currentFocusElement || !this.currentFocusElement.handleKeyUpEvent) + return; + this.currentFocusElement.handleKeyUpEvent(event); +} + WebInspector.documentCanCopy = function(event) { if (!this.currentFocusElement) @@ -474,16 +550,16 @@ WebInspector.mainKeyDown = function(event) this.currentPanel.handleKeyEvent(event); } -WebInspector.mainCopy = function(event) +WebInspector.mainKeyUp = function(event) { - if (this.currentPanel && this.currentPanel.handleCopyEvent) - this.currentPanel.handleCopyEvent(event); + if (this.currentPanel && this.currentPanel.handleKeyUpEvent) + this.currentPanel.handleKeyUpEvent(event); } -WebInspector.searchResultsKeyDown = function(event) +WebInspector.mainCopy = function(event) { - if (this.searchResultsTree) - this.searchResultsTree.handleKeyEvent(event); + if (this.currentPanel && this.currentPanel.handleCopyEvent) + this.currentPanel.handleCopyEvent(event); } WebInspector.animateStyle = function(animations, duration, callback, complete) @@ -560,6 +636,20 @@ WebInspector.animateStyle = function(animations, duration, callback, complete) callback(); } +WebInspector.updateSearchLabel = function() +{ + if (!this.currentPanel) + return; + + var newLabel = WebInspector.UIString("Search %s", this.currentPanel.toolbarItemLabel); + if (this.attached) + document.getElementById("search").setAttribute("placeholder", newLabel); + else { + document.getElementById("search").removeAttribute("placeholder"); + document.getElementById("search-toolbar-label").textContent = newLabel; + } +} + WebInspector.toggleAttach = function() { this.attached = !this.attached; @@ -567,7 +657,7 @@ WebInspector.toggleAttach = function() WebInspector.toolbarDragStart = function(event) { - if (WebInspector.attached) + if (!WebInspector.attached && InspectorController.platform() !== "mac-leopard") return; var target = event.target; @@ -581,68 +671,43 @@ WebInspector.toolbarDragStart = function(event) toolbar.lastScreenX = event.screenX; toolbar.lastScreenY = event.screenY; - document.addEventListener("mousemove", WebInspector.toolbarDrag, true); - document.addEventListener("mouseup", WebInspector.toolbarDragEnd, true); - document.body.style.cursor = "default"; - - event.preventDefault(); + WebInspector.elementDragStart(toolbar, WebInspector.toolbarDrag, WebInspector.toolbarDragEnd, event, (WebInspector.attached ? "row-resize" : "default")); } WebInspector.toolbarDragEnd = function(event) { var toolbar = document.getElementById("toolbar"); - delete toolbar.lastScreenX; - delete toolbar.lastScreenY; - document.removeEventListener("mousemove", WebInspector.toolbarDrag, true); - document.removeEventListener("mouseup", WebInspector.toolbarDragEnd, true); - document.body.style.removeProperty("cursor"); + WebInspector.elementDragEnd(event); - event.preventDefault(); + delete toolbar.lastScreenX; + delete toolbar.lastScreenY; } WebInspector.toolbarDrag = function(event) { var toolbar = document.getElementById("toolbar"); - var x = event.screenX - toolbar.lastScreenX; - var y = event.screenY - toolbar.lastScreenY; + if (WebInspector.attached) { + var height = window.innerHeight - (event.screenY - toolbar.lastScreenY); - toolbar.lastScreenX = event.screenX; - toolbar.lastScreenY = event.screenY; - - // We cannot call window.moveBy here because it restricts the movement of the window - // at the edges. - InspectorController.moveByUnrestricted(x, y); - - event.preventDefault(); -} - -WebInspector.searchResultsResizerDragStart = function(event) -{ - WebInspector.elementDragStart(document.getElementById("searchResults"), WebInspector.searchResultsResizerDrag, WebInspector.searchResultsResizerDragEnd, event, "row-resize"); -} - -WebInspector.searchResultsResizerDragEnd = function(event) -{ - WebInspector.elementDragEnd(event); -} - -WebInspector.searchResultsResizerDrag = function(event) -{ - var y = event.pageY - document.getElementById("main").offsetTop; - var newHeight = Number.constrain(y, 100, window.innerHeight - 100); + InspectorController.setAttachedWindowHeight(height); + } else { + var x = event.screenX - toolbar.lastScreenX; + var y = event.screenY - toolbar.lastScreenY; - WebInspector.searchResultsHeight = newHeight; + // We cannot call window.moveBy here because it restricts the movement + // of the window at the edges. + InspectorController.moveByUnrestricted(x, y); + } - document.getElementById("searchResults").style.height = WebInspector.searchResultsHeight + "px"; - document.getElementById("main-panels").style.top = newHeight + "px"; - document.getElementById("searchResultsResizer").style.top = (newHeight - 3) + "px"; + toolbar.lastScreenX = event.screenX; + toolbar.lastScreenY = event.screenY; event.preventDefault(); } -WebInspector.elementDragStart = function(element, dividerDrag, elementDragEnd, event, cursor) +WebInspector.elementDragStart = function(element, dividerDrag, elementDragEnd, event, cursor) { if (this._elementDraggingEventListener || this._elementEndDraggingEventListener) this.elementDragEnd(event); @@ -676,11 +741,31 @@ WebInspector.showConsole = function() this.console.show(); } -WebInspector.showTimeline = function() +WebInspector.showElementsPanel = function() +{ + this.currentPanel = this.panels.elements; +} + +WebInspector.showResourcesPanel = function() { this.currentPanel = this.panels.resources; } +WebInspector.showScriptsPanel = function() +{ + this.currentPanel = this.panels.scripts; +} + +WebInspector.showProfilesPanel = function() +{ + this.currentPanel = this.panels.profiles; +} + +WebInspector.showDatabasesPanel = function() +{ + this.currentPanel = this.panels.databases; +} + WebInspector.addResource = function(resource) { this.resources.push(resource); @@ -691,7 +776,8 @@ WebInspector.addResource = function(resource) this.panels.elements.reset(); } - this.panels.resources.addResource(resource); + if (this.panels.resources) + this.panels.resources.addResource(resource); } WebInspector.removeResource = function(resource) @@ -699,21 +785,64 @@ WebInspector.removeResource = function(resource) resource.category.removeResource(resource); delete this.resourceURLMap[resource.url]; - var resourcesLength = this.resources.length; - for (var i = 0; i < resourcesLength; ++i) { - if (this.resources[i] === resource) { - this.resources.splice(i, 1); - break; - } - } + this.resources.remove(resource, true); - this.panels.resources.removeResource(resource); + if (this.panels.resources) + this.panels.resources.removeResource(resource); } WebInspector.addDatabase = function(database) { - if (this.panels.databases) - this.panels.databases.addDatabase(database); + this.panels.databases.addDatabase(database); +} + +WebInspector.addDOMStorage = function(domStorage) +{ + this.panels.databases.addDOMStorage(domStorage); +} + +WebInspector.debuggerWasEnabled = function() +{ + this.panels.scripts.debuggerWasEnabled(); +} + +WebInspector.debuggerWasDisabled = function() +{ + this.panels.scripts.debuggerWasDisabled(); +} + +WebInspector.profilerWasEnabled = function() +{ + this.panels.profiles.profilerWasEnabled(); +} + +WebInspector.profilerWasDisabled = function() +{ + this.panels.profiles.profilerWasDisabled(); +} + +WebInspector.parsedScriptSource = function(sourceID, sourceURL, source, startingLine) +{ + this.panels.scripts.addScript(sourceID, sourceURL, source, startingLine); +} + +WebInspector.failedToParseScriptSource = function(sourceURL, source, startingLine, errorLine, errorMessage) +{ + this.panels.scripts.addScript(null, sourceURL, source, startingLine, errorLine, errorMessage); +} + +WebInspector.pausedScript = function() +{ + this.panels.scripts.debuggerPaused(); +} + +WebInspector.populateInterface = function() +{ + for (var panelName in this.panels) { + var panel = this.panels[panelName]; + if ("populateInterface" in panel) + panel.populateInterface(); + } } WebInspector.reset = function() @@ -729,12 +858,18 @@ WebInspector.reset = function() this.resources = []; this.resourceURLMap = {}; + this.hoveredDOMNode = null; delete this.mainResource; this.console.clearMessages(); } +WebInspector.inspectedWindowCleared = function(inspectedWindow) +{ + this.panels.elements.inspectedWindowCleared(inspectedWindow); +} + WebInspector.resourceURLChanged = function(resource, oldURL) { delete this.resourceURLMap[oldURL]; @@ -746,6 +881,16 @@ WebInspector.addMessageToConsole = function(msg) this.console.addMessage(msg); } +WebInspector.addProfile = function(profile) +{ + this.panels.profiles.addProfile(profile); +} + +WebInspector.setRecordingProfile = function(isProfiling) +{ + this.panels.profiles.setRecordingProfile(isProfiling); +} + WebInspector.drawLoadingPieChart = function(canvas, percent) { var g = canvas.getContext("2d"); var darkColor = "rgb(122, 168, 218)"; @@ -755,7 +900,7 @@ WebInspector.drawLoadingPieChart = function(canvas, percent) { var r = 7; g.beginPath(); - g.arc(cx, cy, r, 0, Math.PI * 2, false); + g.arc(cx, cy, r, 0, Math.PI * 2, false); g.closePath(); g.lineWidth = 1; @@ -769,7 +914,7 @@ WebInspector.drawLoadingPieChart = function(canvas, percent) { g.beginPath(); g.moveTo(cx, cy); - g.arc(cx, cy, r, startangle, endangle, false); + g.arc(cx, cy, r, startangle, endangle, false); g.closePath(); g.fillStyle = darkColor; @@ -786,8 +931,23 @@ WebInspector.updateFocusedNode = function(node) this.panels.elements.focusedDOMNode = node; } +WebInspector.displayNameForURL = function(url) +{ + if (!url) + return ""; + var resource = this.resourceURLMap[url]; + if (resource) + return resource.displayName; + return url.trimURL(WebInspector.mainResource ? WebInspector.mainResource.domain : ""); +} + WebInspector.resourceForURL = function(url) { + if (url in this.resourceURLMap) + return this.resourceURLMap[url]; + + // No direct match found. Search for resources that contain + // a substring of the URL. for (var resourceURL in this.resourceURLMap) { if (resourceURL.hasSubstring(url)) return this.resourceURLMap[resourceURL]; @@ -796,25 +956,89 @@ WebInspector.resourceForURL = function(url) return null; } -WebInspector.showResourceForURL = function(url, line) +WebInspector.showResourceForURL = function(url, line, preferredPanel) { var resource = this.resourceForURL(url); if (!resource) return false; - this.currentPanel = this.panels.resources; - this.panels.resources.showResource(resource, line); + if (preferredPanel && preferredPanel in WebInspector.panels) { + var panel = this.panels[preferredPanel]; + if (!("showResource" in panel)) + panel = null; + else if ("canShowResource" in panel && !panel.canShowResource(resource)) + panel = null; + } + + this.currentPanel = panel || this.panels.resources; + if (!this.currentPanel) + return false; + this.currentPanel.showResource(resource, line); return true; } -WebInspector.linkifyURL = function(url, linkText, classes, isExternal) +WebInspector.linkifyStringAsFragment = function(string) { - if (linkText === undefined) - linkText = url.escapeHTML(); - classes = (classes === undefined) ? "" : classes + " "; + var container = document.createDocumentFragment(); + var linkStringRegEx = new RegExp("(?:[a-zA-Z][a-zA-Z0-9+.-]{2,}://|www\\.)[\\w$\\-_+*'=\\|/\\\\(){}[\\]%@&#~,:;.!?]{2,}[\\w$\\-_+*=\\|/\\\\({%@&#~]"); + + while (string) { + var linkString = linkStringRegEx.exec(string); + if (!linkString) + break; + + linkString = linkString[0]; + var title = linkString; + var linkIndex = string.indexOf(linkString); + var nonLink = string.substring(0, linkIndex); + container.appendChild(document.createTextNode(nonLink)); + + var profileStringRegEx = new RegExp("webkit-profile://(.+)/[0-9]+"); + var profileStringMatches = profileStringRegEx.exec(title); + var profileTitle; + if (profileStringMatches) + profileTitle = profileStringMatches[1]; + if (profileTitle) + title = WebInspector.panels.profiles.displayTitleForProfileLink(profileTitle); + + var realURL = (linkString.indexOf("www.") === 0 ? "http://" + linkString : linkString); + container.appendChild(WebInspector.linkifyURLAsNode(realURL, title, null, (realURL in WebInspector.resourceURLMap))); + string = string.substring(linkIndex + linkString.length, string.length); + } + + if (string) + container.appendChild(document.createTextNode(string)); + + return container; +} + +WebInspector.showProfileById = function(uid) { + WebInspector.showProfilesPanel(); + WebInspector.panels.profiles.showProfileById(uid); +} + +WebInspector.linkifyURLAsNode = function(url, linkText, classes, isExternal) +{ + if (!linkText) + linkText = url; + classes = (classes ? classes + " " : ""); classes += isExternal ? "webkit-html-external-link" : "webkit-html-resource-link"; - var link = "<a href=\"" + url + "\" class=\"" + classes + "\" title=\"" + url + "\" target=\"_blank\">" + linkText + "</a>"; - return link; + + var a = document.createElement("a"); + a.href = url; + a.className = classes; + a.title = url; + a.target = "_blank"; + a.textContent = linkText; + + return a; +} + +WebInspector.linkifyURL = function(url, linkText, classes, isExternal) +{ + // Use the DOM version of this function so as to avoid needing to escape attributes. + // FIXME: Get rid of linkifyURL entirely. + return WebInspector.linkifyURLAsNode(url, linkText, classes, isExternal).outerHTML; } WebInspector.addMainEventListeners = function(doc) @@ -824,194 +1048,102 @@ WebInspector.addMainEventListeners = function(doc) doc.addEventListener("click", this.documentClick.bind(this), true); } -WebInspector.performSearch = function(query) +WebInspector.searchKeyDown = function(event) { - if (!query || !query.length) { - this.showingSearchResults = false; + if (event.keyIdentifier !== "Enter") return; - } - - var resultsContainer = document.getElementById("searchResults"); - resultsContainer.removeChildren(); - - var isXPath = query.indexOf("/") !== -1; - - var xpathQuery; - if (isXPath) - xpathQuery = query; - else { - var escapedQuery = query.escapeCharacters("'"); - xpathQuery = "//*[contains(name(),'" + escapedQuery + "') or contains(@*,'" + escapedQuery + "')] | //text()[contains(.,'" + escapedQuery + "')] | //comment()[contains(.,'" + escapedQuery + "')]"; - } - - var resourcesToSearch = [].concat(this.resourceCategories.documents.resources, this.resourceCategories.stylesheets.resources, this.resourceCategories.scripts.resources, this.resourceCategories.other.resources); - var files = []; - for (var i = 0; i < resourcesToSearch.length; ++i) { - var resource = resourcesToSearch[i]; + // Call preventDefault since this was the Enter key. This prevents a "search" event + // from firing for key down. We handle the Enter key on key up in searchKeyUp. This + // stops performSearch from being called twice in a row. + event.preventDefault(); +} - var sourceResults = []; - if (!isXPath) { - var sourceFrame = this.panels.resources.sourceFrameForResource(resource); - if (sourceFrame) - sourceResults = InspectorController.search(sourceFrame.contentDocument, query); - } +WebInspector.searchKeyUp = function(event) +{ + if (event.keyIdentifier !== "Enter") + return; - var domResults = []; - const searchResultsProperty = "__includedInInspectorSearchResults"; - function addNodesToDOMResults(nodes, length, getItem) - { - for (var i = 0; i < length; ++i) { - var node = getItem(nodes, i); - if (searchResultsProperty in node) - continue; - node[searchResultsProperty] = true; - domResults.push(node); - } - } + // Select all of the text so the user can easily type an entirely new query. + event.target.select(); - function cleanUpDOMResultsNodes() - { - for (var i = 0; i < domResults.length; ++i) - delete domResults[i][searchResultsProperty]; - } + // Only call performSearch if the Enter key was pressed. Otherwise the search + // performance is poor because of searching on every key. The search field has + // the incremental attribute set, so we still get incremental searches. + this.performSearch(event); +} - if (resource.category === this.resourceCategories.documents) { - var doc = resource.documentNode; - try { - var result = InspectorController.inspectedWindow().Document.prototype.evaluate.call(doc, xpathQuery, doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); - addNodesToDOMResults(result, result.snapshotLength, function(l, i) { return l.snapshotItem(i); }); - } catch(err) { - // ignore any exceptions. the query might be malformed, but we allow that. - } +WebInspector.performSearch = function(event) +{ + var query = event.target.value; + var forceSearch = event.keyIdentifier === "Enter"; - var result = InspectorController.inspectedWindow().Document.prototype.querySelectorAll.call(doc, query); - addNodesToDOMResults(result, result.length, function(l, i) { return l.item(i); }); + if (!query || !query.length || (!forceSearch && query.length < 3)) { + delete this.currentQuery; - cleanUpDOMResultsNodes(); + for (var panelName in this.panels) { + var panel = this.panels[panelName]; + if (panel.currentQuery && panel.searchCanceled) + panel.searchCanceled(); + delete panel.currentQuery; } - if ((!sourceResults || !sourceResults.length) && !domResults.length) - continue; + this.updateSearchMatchesCount(); - files.push({resource: resource, sourceResults: sourceResults, domResults: domResults}); + return; } - if (!files.length) + if (query === this.currentPanel.currentQuery && this.currentPanel.currentQuery === this.currentQuery) { + // When this is the same query and a forced search, jump to the next + // search result for a good user experience. + if (forceSearch && this.currentPanel.jumpToNextSearchResult) + this.currentPanel.jumpToNextSearchResult(); return; + } - this.showingSearchResults = true; - - var fileList = document.createElement("ol"); - fileList.className = "outline-disclosure"; - resultsContainer.appendChild(fileList); + this.currentQuery = query; - this.searchResultsTree = new TreeOutline(fileList); - this.searchResultsTree.expandTreeElementsWhenArrowing = true; + this.updateSearchMatchesCount(); - var sourceResultSelected = function(element) - { - var selection = window.getSelection(); - selection.removeAllRanges(); - selection.addRange(element.representedObject.range); + if (!this.currentPanel.performSearch) + return; - var oldFocusElement = this.currentFocusElement; - this.currentPanel = this.panels.resources; - this.currentFocusElement = oldFocusElement; + this.currentPanel.currentQuery = query; + this.currentPanel.performSearch(query); +} - this.panels.resources.showResource(element.representedObject.resource); +WebInspector.updateSearchMatchesCount = function(matches, panel) +{ + if (!panel) + panel = this.currentPanel; - element.representedObject.line.scrollIntoViewIfNeeded(true); - element.listItemElement.scrollIntoViewIfNeeded(false); - } + panel.currentSearchMatches = matches; - var domResultSelected = function(element) - { - var oldFocusElement = this.currentFocusElement; - this.currentPanel = this.panels.elements; - this.currentFocusElement = oldFocusElement; + if (panel !== this.currentPanel) + return; - this.panels.elements.focusedDOMNode = element.representedObject.node; - element.listItemElement.scrollIntoViewIfNeeded(false); + if (!this.currentPanel.currentQuery) { + document.getElementById("search-results-matches").addStyleClass("hidden"); + return; } - for (var i = 0; i < files.length; ++i) { - var file = files[i]; - - var fileItem = new TreeElement(file.resource.displayName, {}, true); - fileItem.expanded = true; - fileItem.selectable = false; - this.searchResultsTree.appendChild(fileItem); - - if (file.sourceResults && file.sourceResults.length) { - for (var j = 0; j < file.sourceResults.length; ++j) { - var range = file.sourceResults[j]; - var sourceDocument = range.startContainer.ownerDocument; - - var line = range.startContainer; - while (line.parentNode && line.nodeName.toLowerCase() != "tr") - line = line.parentNode; - var lineRange = sourceDocument.createRange(); - lineRange.selectNodeContents(line); - - // Don't include any error bubbles in the search result - var end = line.lastChild.lastChild; - if (end.nodeName.toLowerCase() == "div" && end.hasStyleClass("webkit-html-message-bubble")) { - while (end && end.nodeName.toLowerCase() == "div" && end.hasStyleClass("webkit-html-message-bubble")) - end = end.previousSibling; - lineRange.setEndAfter(end); - } - - var beforeRange = sourceDocument.createRange(); - beforeRange.setStart(lineRange.startContainer, lineRange.startOffset); - beforeRange.setEnd(range.startContainer, range.startOffset); - - var afterRange = sourceDocument.createRange(); - afterRange.setStart(range.endContainer, range.endOffset); - afterRange.setEnd(lineRange.endContainer, lineRange.endOffset); - - var beforeText = beforeRange.toString().trimLeadingWhitespace(); - var text = range.toString(); - var afterText = afterRange.toString().trimTrailingWhitespace(); - - var length = beforeText.length + text.length + afterText.length; - if (length > Preferences.maxTextSearchResultLength) { - var beforeAfterLength = (Preferences.maxTextSearchResultLength - text.length) / 2; - if (beforeText.length > beforeAfterLength) - beforeText = "\u2026" + beforeText.substr(-beforeAfterLength); - if (afterText.length > beforeAfterLength) - afterText = afterText.substr(0, beforeAfterLength) + "\u2026"; - } - - var title = "<div class=\"selection selected\"></div>"; - if (j == 0) - title += "<div class=\"search-results-section\">" + WebInspector.UIString("Source") + "</div>"; - title += beforeText.escapeHTML() + "<span class=\"search-matched-string\">" + text.escapeHTML() + "</span>" + afterText.escapeHTML(); - var item = new TreeElement(title, {resource: file.resource, line: line, range: range}, false); - item.onselect = sourceResultSelected.bind(this); - fileItem.appendChild(item); - } - } + if (matches) { + if (matches === 1) + var matchesString = WebInspector.UIString("1 match"); + else + var matchesString = WebInspector.UIString("%d matches", matches); + } else + var matchesString = WebInspector.UIString("Not Found"); - if (file.domResults.length) { - for (var j = 0; j < file.domResults.length; ++j) { - var node = file.domResults[j]; - var title = "<div class=\"selection selected\"></div>"; - if (j == 0) - title += "<div class=\"search-results-section\">" + WebInspector.UIString("DOM") + "</div>"; - title += nodeTitleInfo.call(node).title; - var item = new TreeElement(title, {resource: file.resource, node: node}, false); - item.onselect = domResultSelected.bind(this); - fileItem.appendChild(item); - } - } - } + var matchesToolbarElement = document.getElementById("search-results-matches"); + matchesToolbarElement.removeStyleClass("hidden"); + matchesToolbarElement.textContent = matchesString; } WebInspector.UIString = function(string) { - if (string in this.localizedStrings) - string = this.localizedStrings[string]; + if (window.localizedStrings && string in window.localizedStrings) + string = window.localizedStrings[string]; else { if (!(string in this.missingLocalizedStrings)) { console.error("Localized string \"" + string + "\" not found."); @@ -1037,24 +1169,31 @@ WebInspector.startEditing = function(element, committedCallback, cancelledCallba element.__editing = true; var oldText = element.textContent; - var handleKeyEvent = element.handleKeyEvent; - var blurred = element.blurred; + var oldHandleKeyEvent = element.handleKeyEvent; element.addStyleClass("editing"); - element.addStyleClass("focusable"); - var previousFocusElement = WebInspector.currentFocusElement; + var oldTabIndex = element.tabIndex; + if (element.tabIndex < 0) + element.tabIndex = 0; + + function blurEventListener() { + editingCommitted.call(element); + } function cleanUpAfterEditing() { delete this.__editing; this.removeStyleClass("editing"); - this.removeStyleClass("focusable"); + this.tabIndex = oldTabIndex; + this.scrollTop = 0; + this.scrollLeft = 0; - this.handleKeyEvent = handleKeyEvent; - this.blurred = blurred; + this.handleKeyEvent = oldHandleKeyEvent; + element.removeEventListener("blur", blurEventListener, false); - WebInspector.currentFocusElement = previousFocusElement; + if (element === WebInspector.currentFocusElement || element.isAncestor(WebInspector.currentFocusElement)) + WebInspector.currentFocusElement = WebInspector.previousFocusElement; } function editingCancelled() { @@ -1072,6 +1211,11 @@ WebInspector.startEditing = function(element, committedCallback, cancelledCallba } element.handleKeyEvent = function(event) { + if (oldHandleKeyEvent) + oldHandleKeyEvent(event); + if (event.handled) + return; + if (event.keyIdentifier === "Enter") { editingCommitted.call(element); event.preventDefault(); @@ -1082,7 +1226,7 @@ WebInspector.startEditing = function(element, committedCallback, cancelledCallba } } - element.blurred = function() { editingCancelled.call(element); } + element.addEventListener("blur", blurEventListener, false); WebInspector.currentFocusElement = element; } @@ -1128,56 +1272,32 @@ WebInspector.MIMETypes = { "text/livescript": {4: true}, } -/** - * This is used to keep track of the timer that is being used to highlight a - * node. - * @type {number} - * @private - */ -WebInspector._showTimerId = 0; -/** - * Whether we are currently highlighting any node at the moment. - * @type {boolean} - * @private - */ -WebInspector._highlightIsShown = false; +// Stubs for some methods called in ElementsPanel.js which are not yet +// supported by Chrome version of InspectorController +InspectorController.wrapCallback = function f(a) { + return a; +}; -/** - * The time to wait before showing the highlighting of a node. - * @type {number} - */ -WebInspector._showHighlightDelayMs = 300; +InspectorController.searchingForNode = function() { + return false; +}; -/** - * Highlights the given node after a short timeout. If there is already a shown - * node then the current node is highlighted immediately. - * @param {Node} node The node to highlight. - */ -WebInspector.highlightDOMNode = function(node) { - if (this._highlightIsShown) { - InspectorController.highlightDOMNode(node); - } else { - if (this._showTimerId) { - clearTimeout(this._showTimerId); - } - this._showTimerId = setTimeout((function() { - InspectorController.highlightDOMNode(node); - this._highlightIsShown = true; - }).bind(this), this._showHighlightDelayMs); - } +InspectorController.toggleNodeSearch = function() { }; -/** - * Removes the highlight of the current node. - */ -WebInspector.hideDOMNodeHighlight = function() -{ - if (this._highlightIsShown) { - InspectorController.hideDOMNodeHighlight(); - this._highlightIsShown = false; - } - if (this._showTimerId) { - clearTimeout(this._showTimerId); - } +InspectorController.isWindowVisible = function() { + return true; +}; + +InspectorController.closeWindow = function() { +}; + +InspectorController.clearMessages = function() { +}; + +InspectorController.setAttachedWindowHeight = function(height) { +}; + +InspectorController.moveByUnrestricted = function(x, y) { }; diff --git a/chrome/tools/test/reference_build/chrome/resources/Inspector/treeoutline.js b/chrome/tools/test/reference_build/chrome/resources/Inspector/treeoutline.js index 1248055..579e7fb 100644 --- a/chrome/tools/test/reference_build/chrome/resources/Inspector/treeoutline.js +++ b/chrome/tools/test/reference_build/chrome/resources/Inspector/treeoutline.js @@ -133,17 +133,13 @@ TreeOutline._insertChild = function(child, index) child._attach(); } -TreeOutline._removeChild = function(child) +TreeOutline._removeChildAtIndex = function(childIndex) { - if (!child) - throw("child can't be undefined or null"); + if (childIndex < 0 || childIndex >= this.children.length) + throw("childIndex out of range"); - for (var i = 0; i < this.children.length; ++i) { - if (this.children[i] === child) { - this.children.splice(i, 1); - break; - } - } + var child = this.children[childIndex]; + this.children.splice(childIndex, 1); child.deselect(); @@ -152,8 +148,11 @@ TreeOutline._removeChild = function(child) if (child.nextSibling) child.nextSibling.previousSibling = child.previousSibling; - if (child.treeOutline) + if (child.treeOutline) { child.treeOutline._forgetTreeElement(child); + child.treeOutline._forgetChildrenRecursive(child); + } + child._detach(); child.treeOutline = null; child.parent = null; @@ -161,13 +160,29 @@ TreeOutline._removeChild = function(child) child.previousSibling = null; } +TreeOutline._removeChild = function(child) +{ + if (!child) + throw("child can't be undefined or null"); + + var childIndex = this.children.indexOf(child); + if (childIndex === -1) + throw("child not found in this node's children"); + + TreeOutline._removeChildAtIndex.call(this, childIndex); +} + TreeOutline._removeChildren = function() { for (var i = 0; i < this.children.length; ++i) { var child = this.children[i]; child.deselect(); - if (child.treeOutline) + + if (child.treeOutline) { child.treeOutline._forgetTreeElement(child); + child.treeOutline._forgetChildrenRecursive(child); + } + child._detach(); child.treeOutline = null; child.parent = null; @@ -176,9 +191,6 @@ TreeOutline._removeChildren = function() } this.children = []; - - if (this._childrenListNode) - this._childrenListNode.offsetTop; // force layout } TreeOutline._removeChildrenRecursive = function() @@ -215,9 +227,8 @@ TreeOutline.prototype._rememberTreeElement = function(element) // check if the element is already known var elements = this._knownTreeElements[element.identifier]; - for (var i = 0; i < elements.length; ++i) - if (elements[i] === element) - return; + if (elements.indexOf(element) !== -1) + return; // add the element elements.push(element); @@ -225,28 +236,34 @@ TreeOutline.prototype._rememberTreeElement = function(element) TreeOutline.prototype._forgetTreeElement = function(element) { - if (!this._knownTreeElements[element.identifier]) - return; + if (this._knownTreeElements[element.identifier]) + this._knownTreeElements[element.identifier].remove(element, true); +} - var elements = this._knownTreeElements[element.identifier]; - for (var i = 0; i < elements.length; ++i) { - if (elements[i] === element) { - elements.splice(i, 1); - break; - } +TreeOutline.prototype._forgetChildrenRecursive = function(parentElement) +{ + var child = parentElement.children[0]; + while (child) { + this._forgetTreeElement(child); + child = child.traverseNextTreeElement(false, this, true); } } -TreeOutline.prototype.findTreeElement = function(representedObject, isAncestor, getParent) +TreeOutline.prototype.findTreeElement = function(representedObject, isAncestor, getParent, equal) { if (!representedObject) return null; + if (!equal) + equal = function(a, b) { return a === b }; + if ("__treeElementIdentifier" in representedObject) { + // If this representedObject has a tree element identifier, and it is a known TreeElement + // in our tree we can just return that tree element. var elements = this._knownTreeElements[representedObject.__treeElementIdentifier]; if (elements) { for (var i = 0; i < elements.length; ++i) - if (elements[i].representedObject === representedObject) + if (equal(elements[i].representedObject, representedObject)) return elements[i]; } } @@ -254,11 +271,13 @@ TreeOutline.prototype.findTreeElement = function(representedObject, isAncestor, if (!isAncestor || !(isAncestor instanceof Function) || !getParent || !(getParent instanceof Function)) return null; + // The representedObject isn't know, so we start at the top of the tree and work down to find the first + // tree element that represents representedObject or one of its ancestors. var item; var found = false; for (var i = 0; i < this.children.length; ++i) { item = this.children[i]; - if (item.representedObject === representedObject || isAncestor(item.representedObject, representedObject)) { + if (equal(item.representedObject, representedObject) || isAncestor(item.representedObject, representedObject)) { found = true; break; } @@ -267,22 +286,33 @@ TreeOutline.prototype.findTreeElement = function(representedObject, isAncestor, if (!found) return null; + // Make sure the item that we found is connected to the root of the tree. + // Build up a list of representedObject's ancestors that aren't already in our tree. var ancestors = []; var currentObject = representedObject; while (currentObject) { ancestors.unshift(currentObject); - if (currentObject === item.representedObject) + if (equal(currentObject, item.representedObject)) break; currentObject = getParent(currentObject); } + // For each of those ancestors we populate them to fill in the tree. for (var i = 0; i < ancestors.length; ++i) { - item = this.findTreeElement(ancestors[i], isAncestor, getParent); - if (ancestors[i] !== representedObject && item && item.onpopulate) + // Make sure we don't call findTreeElement with the same representedObject + // again, to prevent infinite recursion. + if (equal(ancestors[i], representedObject)) + continue; + // FIXME: we could do something faster than findTreeElement since we will know the next + // ancestor exists in the tree. + item = this.findTreeElement(ancestors[i], isAncestor, getParent, equal); + if (item && item.onpopulate) item.onpopulate(item); } - return item; + // Now that all the ancestors are populated, try to find the representedObject again. This time + // without the isAncestor and getParent functions to prevent an infinite recursion if it isn't found. + return this.findTreeElement(representedObject, null, null, equal); } TreeOutline.prototype.treeElementFromPoint = function(x, y) @@ -380,6 +410,7 @@ TreeOutline.prototype.reveal = function() TreeOutline.prototype.appendChild = TreeOutline._appendChild; TreeOutline.prototype.insertChild = TreeOutline._insertChild; TreeOutline.prototype.removeChild = TreeOutline._removeChild; +TreeOutline.prototype.removeChildAtIndex = TreeOutline._removeChildAtIndex; TreeOutline.prototype.removeChildren = TreeOutline._removeChildren; TreeOutline.prototype.removeChildrenRecursive = TreeOutline._removeChildrenRecursive; @@ -439,6 +470,27 @@ TreeElement.prototype = { this._listItemNode.title = x ? x : ""; }, + get hasChildren() { + return this._hasChildren; + }, + + set hasChildren(x) { + if (this._hasChildren === x) + return; + + this._hasChildren = x; + + if (!this._listItemNode) + return; + + if (x) + this._listItemNode.addStyleClass("parent"); + else { + this._listItemNode.removeStyleClass("parent"); + this.collapse(); + } + }, + get hidden() { return this._hidden; }, @@ -476,6 +528,7 @@ TreeElement.prototype = { TreeElement.prototype.appendChild = TreeOutline._appendChild; TreeElement.prototype.insertChild = TreeOutline._insertChild; TreeElement.prototype.removeChild = TreeOutline._removeChild; +TreeElement.prototype.removeChildAtIndex = TreeOutline._removeChildAtIndex; TreeElement.prototype.removeChildren = TreeOutline._removeChildren; TreeElement.prototype.removeChildrenRecursive = TreeOutline._removeChildrenRecursive; @@ -507,7 +560,10 @@ TreeElement.prototype._attach = function() this.onattach(this); } - this.parent._childrenListNode.insertBefore(this._listItemNode, (this.nextSibling ? this.nextSibling._listItemNode : null)); + var nextSibling = null; + if (this.nextSibling && this.nextSibling._listItemNode && this.nextSibling._listItemNode.parentNode === this.parent._childrenListNode) + nextSibling = this.nextSibling._listItemNode; + this.parent._childrenListNode.insertBefore(this._listItemNode, nextSibling); if (this._childrenListNode) this.parent._childrenListNode.insertBefore(this._childrenListNode, this._listItemNode.nextSibling); if (this.selected) @@ -600,7 +656,7 @@ TreeElement.prototype.expand = function() if (!this.hasChildren || (this.expanded && !this._shouldRefreshChildren && this._childrenListNode)) return; - if (!this._childrenListNode || this._shouldRefreshChildren) { + if (this.treeOutline && (!this._childrenListNode || this._shouldRefreshChildren)) { if (this._childrenListNode && this._childrenListNode.parentNode) this._childrenListNode.parentNode.removeChild(this._childrenListNode); @@ -622,7 +678,7 @@ TreeElement.prototype.expand = function() if (this._listItemNode) { this._listItemNode.addStyleClass("expanded"); - if (this._childrenListNode.parentNode != this._listItemNode.parentNode) + if (this._childrenListNode && this._childrenListNode.parentNode != this._listItemNode.parentNode) this.parent._childrenListNode.insertBefore(this._childrenListNode, this._listItemNode.nextSibling); } @@ -637,13 +693,38 @@ TreeElement.prototype.expand = function() this.onexpand(this); } -TreeElement.prototype.expandRecursively = function() +TreeElement.prototype.expandRecursively = function(maxDepth) { var item = this; + var info = {}; + var depth = 0; + + // The Inspector uses TreeOutlines to represents object properties, so recursive expansion + // in some case can be infinite, since JavaScript objects can hold circular references. + // So default to a recursion cap of 3 levels, since that gives fairly good results. + if (typeof maxDepth === "undefined" || typeof maxDepth === "null") + maxDepth = 3; + while (item) { - item.expand(); - item = item.traverseNextTreeElement(false, this); + if (depth < maxDepth) + item.expand(); + item = item.traverseNextTreeElement(false, this, (depth >= maxDepth), info); + depth += info.depthChange; + } +} + +TreeElement.prototype.hasAncestor = function(ancestor) { + if (!ancestor) + return false; + + var currentNode = this.parent; + while (currentNode) { + if (ancestor === currentNode) + return true; + currentNode = currentNode.parent; } + + return false; } TreeElement.prototype.reveal = function() @@ -702,14 +783,20 @@ TreeElement.prototype.deselect = function(supressOnDeselect) this.ondeselect(this); } -TreeElement.prototype.traverseNextTreeElement = function(skipHidden, stayWithin, dontPopulate) +TreeElement.prototype.traverseNextTreeElement = function(skipHidden, stayWithin, dontPopulate, info) { if (!dontPopulate && this.hasChildren && this.onpopulate) this.onpopulate(this); + if (info) + info.depthChange = 0; + var element = skipHidden ? (this.revealed() ? this.children[0] : null) : this.children[0]; - if (element && (!skipHidden || (skipHidden && this.expanded))) + if (element && (!skipHidden || (skipHidden && this.expanded))) { + if (info) + info.depthChange = 1; return element; + } if (this === stayWithin) return null; @@ -719,8 +806,11 @@ TreeElement.prototype.traverseNextTreeElement = function(skipHidden, stayWithin, return element; element = this; - while (element && !element.root && !(skipHidden ? (element.revealed() ? element.nextSibling : null) : element.nextSibling) && element.parent !== stayWithin) + while (element && !element.root && !(skipHidden ? (element.revealed() ? element.nextSibling : null) : element.nextSibling) && element.parent !== stayWithin) { + if (info) + info.depthChange -= 1; element = element.parent; + } if (!element) return null; diff --git a/chrome/tools/test/reference_build/chrome/resources/Inspector/utilities.js b/chrome/tools/test/reference_build/chrome/resources/Inspector/utilities.js index 5d295d4..8f86504 100644 --- a/chrome/tools/test/reference_build/chrome/resources/Inspector/utilities.js +++ b/chrome/tools/test/reference_build/chrome/resources/Inspector/utilities.js @@ -54,6 +54,15 @@ Object.type = function(obj, win) return type; } +Object.hasProperties = function(obj) +{ + if (typeof obj === "undefined" || typeof obj === "null") + return false; + for (var name in obj) + return true; + return false; +} + Object.describe = function(obj, abbreviated) { var type1 = Object.type(obj); @@ -98,6 +107,93 @@ Function.prototype.bind = function(thisObject) return function() { return func.apply(thisObject, args.concat(Array.prototype.slice.call(arguments, 0))) }; } +Node.prototype.rangeOfWord = function(offset, stopCharacters, stayWithinNode, direction) +{ + var startNode; + var startOffset = 0; + var endNode; + var endOffset = 0; + + if (!stayWithinNode) + stayWithinNode = this; + + if (!direction || direction === "backward" || direction === "both") { + var node = this; + while (node) { + if (node === stayWithinNode) { + if (!startNode) + startNode = stayWithinNode; + break; + } + + if (node.nodeType === Node.TEXT_NODE) { + var start = (node === this ? (offset - 1) : (node.nodeValue.length - 1)); + for (var i = start; i >= 0; --i) { + if (stopCharacters.indexOf(node.nodeValue[i]) !== -1) { + startNode = node; + startOffset = i + 1; + break; + } + } + } + + if (startNode) + break; + + node = node.traversePreviousNode(false, stayWithinNode); + } + + if (!startNode) { + startNode = stayWithinNode; + startOffset = 0; + } + } else { + startNode = this; + startOffset = offset; + } + + if (!direction || direction === "forward" || direction === "both") { + node = this; + while (node) { + if (node === stayWithinNode) { + if (!endNode) + endNode = stayWithinNode; + break; + } + + if (node.nodeType === Node.TEXT_NODE) { + var start = (node === this ? offset : 0); + for (var i = start; i < node.nodeValue.length; ++i) { + if (stopCharacters.indexOf(node.nodeValue[i]) !== -1) { + endNode = node; + endOffset = i; + break; + } + } + } + + if (endNode) + break; + + node = node.traverseNextNode(false, stayWithinNode); + } + + if (!endNode) { + endNode = stayWithinNode; + endOffset = stayWithinNode.nodeType === Node.TEXT_NODE ? stayWithinNode.nodeValue.length : stayWithinNode.childNodes.length; + } + } else { + endNode = this; + endOffset = offset; + } + + var result = this.ownerDocument.createRange(); + result.setStart(startNode, startOffset); + result.setEnd(endNode, endOffset); + + return result; +} + Element.prototype.removeStyleClass = function(className) { // Test for the simple case before using a RegExp. @@ -106,7 +202,12 @@ Element.prototype.removeStyleClass = function(className) return; } - var regex = new RegExp("(^|\\s+)" + className.escapeForRegExp() + "($|\\s+)"); + this.removeMatchingStyleClasses(className.escapeForRegExp()); +} + +Element.prototype.removeMatchingStyleClasses = function(classNameRegex) +{ + var regex = new RegExp("(^|\\s+)" + classNameRegex + "($|\\s+)"); if (regex.test(this.className)) this.className = this.className.replace(regex, " "); } @@ -130,7 +231,7 @@ Element.prototype.hasStyleClass = function(className) Node.prototype.enclosingNodeOrSelfWithNodeNameInArray = function(nameArray) { - for (var node = this; node && (node !== document); node = node.parentNode) + for (var node = this; node && !objectsAreSame(node, this.ownerDocument); node = node.parentNode) for (var i = 0; i < nameArray.length; ++i) if (node.nodeName.toLowerCase() === nameArray[i].toLowerCase()) return node; @@ -144,7 +245,7 @@ Node.prototype.enclosingNodeOrSelfWithNodeName = function(nodeName) Node.prototype.enclosingNodeOrSelfWithClass = function(className) { - for (var node = this; node && (node !== document); node = node.parentNode) + for (var node = this; node && !objectsAreSame(node, this.ownerDocument); node = node.parentNode) if (node.nodeType === Node.ELEMENT_NODE && node.hasStyleClass(className)) return node; return null; @@ -159,7 +260,7 @@ Node.prototype.enclosingNodeWithClass = function(className) Element.prototype.query = function(query) { - return document.evaluate(query, this, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; + return this.ownerDocument.evaluate(query, this, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; } Element.prototype.removeChildren = function() @@ -277,6 +378,37 @@ String.prototype.trimURL = function(baseURLDomain) return result; } +function getStyleTextWithShorthands(style) +{ + var cssText = ""; + var foundProperties = {}; + for (var i = 0; i < style.length; ++i) { + var individualProperty = style[i]; + var shorthandProperty = style.getPropertyShorthand(individualProperty); + var propertyName = (shorthandProperty || individualProperty); + + if (propertyName in foundProperties) + continue; + + if (shorthandProperty) { + var value = getShorthandValue(style, shorthandProperty); + var priority = getShorthandPriority(style, shorthandProperty); + } else { + var value = style.getPropertyValue(individualProperty); + var priority = style.getPropertyPriority(individualProperty); + } + + foundProperties[propertyName] = true; + + cssText += propertyName + ": " + value; + if (priority) + cssText += " !" + priority; + cssText += "; "; + } + + return cssText; +} + function getShorthandValue(style, shorthandProperty) { var value = style.getPropertyValue(shorthandProperty); @@ -486,6 +618,21 @@ function nodeContentPreview() return preview.collapseWhitespace(); } +function objectsAreSame(a, b) +{ + // FIXME: Make this more generic so is works with any wrapped object, not just nodes. + // This function is used to compare nodes that might be JSInspectedObjectWrappers, since + // JavaScript equality is not true for JSInspectedObjectWrappers of the same node wrapped + // with different global ExecStates, we use isSameNode to compare them. + if (a === b) + return true; + if (!a || !b) + return false; + if (a.isSameNode && b.isSameNode) + return a.isSameNode(b); + return false; +} + function isAncestorNode(ancestor) { if (!this || !ancestor) @@ -493,7 +640,7 @@ function isAncestorNode(ancestor) var currentNode = ancestor.parentNode; while (currentNode) { - if (this === currentNode) + if (objectsAreSame(this, currentNode)) return true; currentNode = currentNode.parentNode; } @@ -514,13 +661,13 @@ function firstCommonNodeAncestor(node) var node1 = this.parentNode; var node2 = node.parentNode; - if ((!node1 || !node2) || node1 !== node2) + if ((!node1 || !node2) || !objectsAreSame(node1, node2)) return null; while (node1 && node2) { if (!node1.parentNode || !node2.parentNode) break; - if (node1 !== node2) + if (!objectsAreSame(node1, node2)) break; node1 = node1.parentNode; @@ -579,7 +726,7 @@ function traverseNextNode(skipWhitespace, stayWithin) if (node) return node; - if (stayWithin && this === stayWithin) + if (stayWithin && objectsAreSame(this, stayWithin)) return null; node = skipWhitespace ? nextSiblingSkippingWhitespace.call(this) : this.nextSibling; @@ -587,7 +734,7 @@ function traverseNextNode(skipWhitespace, stayWithin) return node; node = this; - while (node && !(skipWhitespace ? nextSiblingSkippingWhitespace.call(node) : node.nextSibling) && (!stayWithin || !node.parentNode || node.parentNode !== stayWithin)) + while (node && !(skipWhitespace ? nextSiblingSkippingWhitespace.call(node) : node.nextSibling) && (!stayWithin || !node.parentNode || !objectsAreSame(node.parentNode, stayWithin))) node = node.parentNode; if (!node) return null; @@ -595,10 +742,12 @@ function traverseNextNode(skipWhitespace, stayWithin) return skipWhitespace ? nextSiblingSkippingWhitespace.call(node) : node.nextSibling; } -function traversePreviousNode(skipWhitespace) +function traversePreviousNode(skipWhitespace, stayWithin) { if (!this) return; + if (stayWithin && objectsAreSame(this, stayWithin)) + return null; var node = skipWhitespace ? previousSiblingSkippingWhitespace.call(this) : this.previousSibling; while (node && (skipWhitespace ? lastChildSkippingWhitespace.call(node) : node.lastChild) ) node = skipWhitespace ? lastChildSkippingWhitespace.call(node) : node.lastChild; @@ -635,15 +784,17 @@ function nodeTitleInfo(hasChildren, linkify) if (this.hasAttributes()) { for (var i = 0; i < this.attributes.length; ++i) { var attr = this.attributes[i]; - var value = attr.value.escapeHTML(); - value = value.replace(/([\/;:\)\]\}])/g, "$1​"); - info.title += " <span class=\"webkit-html-attribute\"><span class=\"webkit-html-attribute-name\">" + attr.name.escapeHTML() + "</span>=​\""; - if (linkify && (attr.name === "src" || attr.name === "href")) + var value = attr.value; + if (linkify && (attr.name === "src" || attr.name === "href")) { + var value = value.replace(/([\/;:\)\]\}])/g, "$1\u200B"); info.title += linkify(attr.value, value, "webkit-html-attribute-value", this.nodeName.toLowerCase() == "a"); - else + } else { + var value = value.escapeHTML(); + value = value.replace(/([\/;:\)\]\}])/g, "$1​"); info.title += "<span class=\"webkit-html-attribute-value\">" + value + "</span>"; + } info.title += "\"</span>"; } } @@ -692,13 +843,36 @@ function nodeTitleInfo(hasChildren, linkify) return info; } -Number.secondsToString = function(seconds, formatterFunction) +function getDocumentForNode(node) { + return node.nodeType == Node.DOCUMENT_NODE ? node : node.ownerDocument; +} + +function parentNodeOrFrameElement(node) { + var parent = node.parentNode; + if (parent) + return parent; + + return getDocumentForNode(node).defaultView.frameElement; +} + +function isAncestorIncludingParentFrames(a, b) { + if (objectsAreSame(a, b)) + return false; + for (var node = b; node; node = getDocumentForNode(node).defaultView.frameElement) + if (objectsAreSame(a, node) || isAncestorNode.call(a, node)) + return true; + return false; +} + +Number.secondsToString = function(seconds, formatterFunction, higherResolution) { if (!formatterFunction) formatterFunction = String.sprintf; var ms = seconds * 1000; - if (ms < 1000) + if (higherResolution && ms < 1000) + return formatterFunction("%.3fms", ms); + else if (ms < 1000) return formatterFunction("%.0fms", ms); if (seconds < 60) @@ -747,6 +921,22 @@ HTMLTextAreaElement.prototype.moveCursorToEnd = function() this.setSelectionRange(length, length); } +Array.prototype.remove = function(value, onlyFirst) +{ + if (onlyFirst) { + var index = this.indexOf(value); + if (index !== -1) + this.splice(index, 1); + return; + } + + var length = this.length; + for (var i = 0; i < length; ++i) { + if (this[i] === value) + this.splice(i, 1); + } +} + String.sprintf = function(format) { return String.vsprintf(format, Array.prototype.slice.call(arguments, 1)); diff --git a/chrome/tools/test/reference_build/chrome/themes/default.dll b/chrome/tools/test/reference_build/chrome/themes/default.dll Binary files differindex 2e19026..023dfcf 100644 --- a/chrome/tools/test/reference_build/chrome/themes/default.dll +++ b/chrome/tools/test/reference_build/chrome/themes/default.dll diff --git a/chrome/tools/test/reference_build/chrome/wow_helper.exe b/chrome/tools/test/reference_build/chrome/wow_helper.exe Binary files differindex 163270a..f9bfb4b 100644 --- a/chrome/tools/test/reference_build/chrome/wow_helper.exe +++ b/chrome/tools/test/reference_build/chrome/wow_helper.exe |