зеркало из https://github.com/mozilla/gecko-dev.git
merge m-c to fx-team
This commit is contained in:
Коммит
9e6e319f9c
|
@ -492,7 +492,8 @@ DebuggerUI.prototype = {
|
|||
_onLoadSource: function DebuggerUI__onLoadSource(aEvent) {
|
||||
let gBrowser = this.aWindow.gBrowser;
|
||||
|
||||
let url = aEvent.detail;
|
||||
let url = aEvent.detail.url;
|
||||
let showOptions = aEvent.detail.options;
|
||||
let scheme = Services.io.extractScheme(url);
|
||||
switch (scheme) {
|
||||
case "file":
|
||||
|
@ -505,7 +506,7 @@ DebuggerUI.prototype = {
|
|||
}
|
||||
let source = NetUtil.readInputStreamToString(aStream, aStream.available());
|
||||
aStream.close();
|
||||
this._onSourceLoaded(url, source);
|
||||
this._onSourceLoaded(url, source, showOptions);
|
||||
}.bind(this));
|
||||
} catch (ex) {
|
||||
return this.logError(url, ex.name);
|
||||
|
@ -529,7 +530,8 @@ DebuggerUI.prototype = {
|
|||
return this.logError(url, aStatusCode);
|
||||
}
|
||||
|
||||
this._onSourceLoaded(url, chunks.join(""), channel.contentType);
|
||||
this._onSourceLoaded(url, chunks.join(""), channel.contentType,
|
||||
showOptions);
|
||||
}.bind(this)
|
||||
};
|
||||
|
||||
|
@ -555,20 +557,23 @@ DebuggerUI.prototype = {
|
|||
/**
|
||||
* Called when source has been loaded.
|
||||
*
|
||||
* @private
|
||||
* @param string aSourceUrl
|
||||
* The URL of the source script.
|
||||
* @param string aSourceText
|
||||
* The text of the source script.
|
||||
* @param string aContentType
|
||||
* The content type of the source script.
|
||||
* @param object [aOptions]
|
||||
* Additional options for showing the script (optional). Supported
|
||||
* options:
|
||||
* - targetLine: place the editor at the given line number.
|
||||
*/
|
||||
_onSourceLoaded: function DebuggerUI__onSourceLoaded(aSourceUrl,
|
||||
aSourceText,
|
||||
aContentType) {
|
||||
aContentType,
|
||||
aOptions) {
|
||||
let dbg = this.getDebugger(this.aWindow.gBrowser.selectedTab);
|
||||
dbg.debuggerWindow.SourceScripts.setEditorMode(aSourceUrl, aContentType);
|
||||
dbg.editor.setText(aSourceText);
|
||||
dbg.editor.resetUndo();
|
||||
let doc = dbg.frame.contentDocument;
|
||||
let scripts = doc.getElementById("scripts");
|
||||
let elt = scripts.getElementsByAttribute("value", aSourceUrl)[0];
|
||||
|
@ -577,8 +582,8 @@ DebuggerUI.prototype = {
|
|||
script.text = aSourceText;
|
||||
script.contentType = aContentType;
|
||||
elt.setUserData("sourceScript", script, null);
|
||||
dbg._updateEditorBreakpoints();
|
||||
dbg.debuggerWindow.StackFrames.updateEditor();
|
||||
|
||||
dbg.debuggerWindow.SourceScripts._onShowScript(script, aOptions);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -272,13 +272,13 @@ var StackFrames = {
|
|||
if (!frame) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Move the editor's caret to the proper line.
|
||||
if (DebuggerView.Scripts.isSelected(frame.where.url) && frame.where.line) {
|
||||
window.editor.setCaretPosition(frame.where.line - 1);
|
||||
window.editor.setDebugLocation(frame.where.line - 1);
|
||||
} else if (DebuggerView.Scripts.contains(frame.where.url)) {
|
||||
DebuggerView.Scripts.selectScript(frame.where.url);
|
||||
SourceScripts.onChange({ target: DebuggerView.Scripts._scripts });
|
||||
window.editor.setCaretPosition(frame.where.line - 1);
|
||||
} else {
|
||||
window.editor.setDebugLocation(-1);
|
||||
|
@ -523,8 +523,7 @@ var SourceScripts = {
|
|||
return;
|
||||
}
|
||||
let script = scripts.selectedItem.getUserData("sourceScript");
|
||||
this.setEditorMode(script.url, script.contentType);
|
||||
this._showScript(script);
|
||||
this.showScript(script);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -628,28 +627,64 @@ var SourceScripts = {
|
|||
DebuggerView.Scripts.addScript(this._getScriptLabel(aScript.url), aScript);
|
||||
|
||||
if (window.editor.getCharCount() == 0) {
|
||||
this._showScript(aScript);
|
||||
this.showScript(aScript);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Load the editor with the script text if available, otherwise fire an event
|
||||
* to load and display the script text.
|
||||
*
|
||||
* @param object aScript
|
||||
* The script object coming from the active thread.
|
||||
* @param object [aOptions]
|
||||
* Additional options for showing the script (optional). Supported
|
||||
* options:
|
||||
* - targetLine: place the editor at the given line number.
|
||||
*/
|
||||
_showScript: function SS_showScript(aScript) {
|
||||
showScript: function SS_showScript(aScript, aOptions) {
|
||||
if (!aScript.loaded) {
|
||||
// Notify the chrome code that we need to load a script file.
|
||||
var evt = document.createEvent("CustomEvent");
|
||||
evt.initCustomEvent("Debugger:LoadSource", true, false, aScript.url);
|
||||
evt.initCustomEvent("Debugger:LoadSource", true, false,
|
||||
{url: aScript.url, options: aOptions});
|
||||
document.documentElement.dispatchEvent(evt);
|
||||
window.editor.setMode(SourceEditor.MODES.TEXT);
|
||||
window.editor.setText(DebuggerView.getStr("loadingText"));
|
||||
window.editor.resetUndo();
|
||||
} else {
|
||||
window.editor.setText(aScript.text);
|
||||
window.updateEditorBreakpoints();
|
||||
StackFrames.updateEditor();
|
||||
this._onShowScript(aScript, aOptions);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Display the script source once it loads.
|
||||
*
|
||||
* @private
|
||||
* @param object aScript
|
||||
* The script object coming from the active thread.
|
||||
* @param object [aOptions]
|
||||
* Additional options for showing the script (optional). Supported
|
||||
* options:
|
||||
* - targetLine: place the editor at the given line number.
|
||||
*/
|
||||
_onShowScript: function SS__onShowScript(aScript, aOptions) {
|
||||
aOptions = aOptions || {};
|
||||
this.setEditorMode(aScript.url, aScript.contentType);
|
||||
window.editor.setText(aScript.text);
|
||||
window.updateEditorBreakpoints();
|
||||
StackFrames.updateEditor();
|
||||
if (aOptions.targetLine) {
|
||||
window.editor.setCaretPosition(aOptions.targetLine - 1);
|
||||
}
|
||||
window.editor.resetUndo();
|
||||
}
|
||||
|
||||
// Notify the chrome code that we shown script file.
|
||||
let evt = document.createEvent("CustomEvent");
|
||||
evt.initCustomEvent("Debugger:ScriptShown", true, false,
|
||||
{url: aScript.url});
|
||||
document.documentElement.dispatchEvent(evt);
|
||||
},
|
||||
};
|
||||
|
||||
SourceScripts.onScripts = SourceScripts.onScripts.bind(SourceScripts);
|
||||
|
|
|
@ -21,20 +21,39 @@ function test()
|
|||
let tempScope = {};
|
||||
Cu.import("resource:///modules/source-editor.jsm", tempScope);
|
||||
let SourceEditor = tempScope.SourceEditor;
|
||||
let scriptShown = false;
|
||||
let framesAdded = false;
|
||||
|
||||
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
|
||||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.debuggerWindow;
|
||||
|
||||
gPane.activeThread.addOneTimeListener("framesadded", function() {
|
||||
Services.tm.currentThread.dispatch({ run: onScriptsAdded }, 0);
|
||||
framesAdded = true;
|
||||
runTest();
|
||||
});
|
||||
|
||||
gDebuggee.firstCall();
|
||||
});
|
||||
|
||||
function onScriptsAdded()
|
||||
window.addEventListener("Debugger:ScriptShown", function _onEvent(aEvent) {
|
||||
let url = aEvent.detail.url;
|
||||
if (url.indexOf("-02.js") != -1) {
|
||||
scriptShown = true;
|
||||
window.removeEventListener(aEvent.type, _onEvent);
|
||||
runTest();
|
||||
}
|
||||
});
|
||||
|
||||
function runTest()
|
||||
{
|
||||
if (scriptShown && framesAdded) {
|
||||
Services.tm.currentThread.dispatch({ run: onScriptShown }, 0);
|
||||
}
|
||||
}
|
||||
|
||||
function onScriptShown()
|
||||
{
|
||||
gScripts = gDebugger.DebuggerView.Scripts;
|
||||
|
||||
|
@ -48,7 +67,7 @@ function test()
|
|||
isnot(gEditor.getText().indexOf("debugger"), -1,
|
||||
"The correct script was loaded initially.");
|
||||
isnot(gScripts.selected, gScripts.scriptLocations()[0],
|
||||
"the correct sccript is selected");
|
||||
"the correct script is selected");
|
||||
|
||||
gBreakpoints = gPane.breakpoints;
|
||||
is(Object.keys(gBreakpoints), 0, "no breakpoints");
|
||||
|
@ -56,8 +75,6 @@ function test()
|
|||
|
||||
is(gEditor.getBreakpoints().length, 0, "no breakpoints in the editor");
|
||||
|
||||
|
||||
info("add the first breakpoint");
|
||||
gEditor.addEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE,
|
||||
onEditorBreakpointAddFirst);
|
||||
let location = {url: gScripts.selected, line: 6};
|
||||
|
|
|
@ -19,6 +19,8 @@ function test()
|
|||
let SourceEditor = tempScope.SourceEditor;
|
||||
|
||||
let contextMenu = null;
|
||||
let scriptShown = false;
|
||||
let framesAdded = false;
|
||||
|
||||
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
|
||||
gTab = aTab;
|
||||
|
@ -27,12 +29,29 @@ function test()
|
|||
gDebugger = gPane.debuggerWindow;
|
||||
|
||||
gPane.activeThread.addOneTimeListener("framesadded", function() {
|
||||
Services.tm.currentThread.dispatch({ run: onScriptsAdded }, 0);
|
||||
framesAdded = true;
|
||||
runTest();
|
||||
});
|
||||
gDebuggee.firstCall();
|
||||
});
|
||||
|
||||
function onScriptsAdded()
|
||||
window.addEventListener("Debugger:ScriptShown", function _onEvent(aEvent) {
|
||||
let url = aEvent.detail.url;
|
||||
if (url.indexOf("-02.js") != -1) {
|
||||
scriptShown = true;
|
||||
window.removeEventListener(aEvent.type, _onEvent);
|
||||
runTest();
|
||||
}
|
||||
});
|
||||
|
||||
function runTest()
|
||||
{
|
||||
if (scriptShown && framesAdded) {
|
||||
Services.tm.currentThread.dispatch({ run: onScriptShown }, 0);
|
||||
}
|
||||
}
|
||||
|
||||
function onScriptShown()
|
||||
{
|
||||
let scripts = gDebugger.DebuggerView.Scripts._scripts;
|
||||
|
||||
|
|
|
@ -25,15 +25,27 @@ function test()
|
|||
|
||||
function testFrameParameters()
|
||||
{
|
||||
dump("Started testFrameParameters!\n");
|
||||
|
||||
gDebugger.addEventListener("Debugger:FetchedParameters", function test() {
|
||||
dump("Entered Debugger:FetchedParameters!\n");
|
||||
|
||||
gDebugger.removeEventListener("Debugger:FetchedParameters", test, false);
|
||||
Services.tm.currentThread.dispatch({ run: function() {
|
||||
|
||||
dump("After currentThread.dispatch!\n");
|
||||
|
||||
var frames = gDebugger.DebuggerView.Stackframes._frames,
|
||||
childNodes = frames.childNodes,
|
||||
localScope = gDebugger.DebuggerView.Properties.localScope,
|
||||
localNodes = localScope.querySelector(".details").childNodes;
|
||||
|
||||
dump("Got our variables:\n");
|
||||
dump("frames - " + frames.constructor + "\n");
|
||||
dump("childNodes - " + childNodes.constructor + "\n");
|
||||
dump("localScope - " + localScope.constructor + "\n");
|
||||
dump("localNodes - " + localNodes.constructor + "\n");
|
||||
|
||||
is(gDebugger.StackFrames.activeThread.state, "paused",
|
||||
"Should only be getting stack frames while paused.");
|
||||
|
||||
|
|
|
@ -25,14 +25,25 @@ function test()
|
|||
|
||||
function testFrameParameters()
|
||||
{
|
||||
dump("Started testFrameParameters!\n");
|
||||
|
||||
gDebugger.addEventListener("Debugger:FetchedParameters", function test() {
|
||||
dump("Entered Debugger:FetchedParameters!\n");
|
||||
|
||||
gDebugger.removeEventListener("Debugger:FetchedParameters", test, false);
|
||||
Services.tm.currentThread.dispatch({ run: function() {
|
||||
|
||||
dump("After currentThread.dispatch!\n");
|
||||
|
||||
var frames = gDebugger.DebuggerView.Stackframes._frames,
|
||||
localScope = gDebugger.DebuggerView.Properties.localScope,
|
||||
localNodes = localScope.querySelector(".details").childNodes;
|
||||
|
||||
dump("Got our variables:\n");
|
||||
dump("frames - " + frames.constructor + "\n");
|
||||
dump("localScope - " + localScope.constructor + "\n");
|
||||
dump("localNodes - " + localNodes.constructor + "\n");
|
||||
|
||||
is(gDebugger.StackFrames.activeThread.state, "paused",
|
||||
"Should only be getting stack frames while paused.");
|
||||
|
||||
|
@ -87,9 +98,9 @@ function testFrameParameters()
|
|||
}}, 0);
|
||||
}, false);
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(content.document.querySelector("button"),
|
||||
{},
|
||||
content.window);
|
||||
EventUtils.sendMouseEvent({ type: "click" },
|
||||
content.document.querySelector("button"),
|
||||
content.window);
|
||||
}
|
||||
|
||||
function resumeAndFinish() {
|
||||
|
|
|
@ -15,72 +15,91 @@ var gDebuggee = null;
|
|||
var gDebugger = null;
|
||||
|
||||
function test() {
|
||||
let scriptShown = false;
|
||||
let framesAdded = false;
|
||||
|
||||
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
|
||||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.debuggerWindow;
|
||||
|
||||
testRecurse();
|
||||
gPane.activeThread.addOneTimeListener("framesadded", function() {
|
||||
framesAdded = true;
|
||||
runTest();
|
||||
});
|
||||
|
||||
gDebuggee.firstCall();
|
||||
});
|
||||
|
||||
window.addEventListener("Debugger:ScriptShown", function _onEvent(aEvent) {
|
||||
let url = aEvent.detail.url;
|
||||
if (url.indexOf("-02.js") != -1) {
|
||||
scriptShown = true;
|
||||
window.removeEventListener(aEvent.type, _onEvent);
|
||||
runTest();
|
||||
}
|
||||
});
|
||||
|
||||
function runTest()
|
||||
{
|
||||
if (scriptShown && framesAdded) {
|
||||
Services.tm.currentThread.dispatch({ run: testRecurse }, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function testRecurse() {
|
||||
gPane.activeThread.addOneTimeListener("framesadded", function() {
|
||||
Services.tm.currentThread.dispatch({ run: function() {
|
||||
let frames = gDebugger.DebuggerView.Stackframes._frames;
|
||||
let childNodes = frames.childNodes;
|
||||
function testRecurse()
|
||||
{
|
||||
let frames = gDebugger.DebuggerView.Stackframes._frames;
|
||||
let childNodes = frames.childNodes;
|
||||
|
||||
is(frames.querySelectorAll(".dbg-stackframe").length, 4,
|
||||
"Correct number of frames.");
|
||||
is(frames.querySelectorAll(".dbg-stackframe").length, 4,
|
||||
"Correct number of frames.");
|
||||
|
||||
is(childNodes.length, frames.querySelectorAll(".dbg-stackframe").length,
|
||||
"All children should be frames.");
|
||||
is(childNodes.length, frames.querySelectorAll(".dbg-stackframe").length,
|
||||
"All children should be frames.");
|
||||
|
||||
ok(frames.querySelector("#stackframe-0").classList.contains("selected"),
|
||||
"First frame should be selected by default.");
|
||||
ok(frames.querySelector("#stackframe-0").classList.contains("selected"),
|
||||
"First frame should be selected by default.");
|
||||
|
||||
ok(!frames.querySelector("#stackframe-2").classList.contains("selected"),
|
||||
"Third frame should not be selected.");
|
||||
ok(!frames.querySelector("#stackframe-2").classList.contains("selected"),
|
||||
"Third frame should not be selected.");
|
||||
|
||||
is(gDebugger.editor.getDebugLocation(), 5,
|
||||
"editor debugger location is correct.");
|
||||
is(gDebugger.editor.getDebugLocation(), 5,
|
||||
"editor debugger location is correct.");
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "click" },
|
||||
frames.querySelector("#stackframe-2"),
|
||||
gDebugger);
|
||||
EventUtils.sendMouseEvent({ type: "click" },
|
||||
frames.querySelector("#stackframe-2"),
|
||||
gDebugger);
|
||||
|
||||
ok(!frames.querySelector("#stackframe-0").classList.contains("selected"),
|
||||
"First frame should not be selected after click.");
|
||||
ok(!frames.querySelector("#stackframe-0").classList.contains("selected"),
|
||||
"First frame should not be selected after click.");
|
||||
|
||||
ok(frames.querySelector("#stackframe-2").classList.contains("selected"),
|
||||
"Third frame should be selected after click.");
|
||||
ok(frames.querySelector("#stackframe-2").classList.contains("selected"),
|
||||
"Third frame should be selected after click.");
|
||||
|
||||
is(gDebugger.editor.getDebugLocation(), 4,
|
||||
"editor debugger location is correct after click.");
|
||||
is(gDebugger.editor.getDebugLocation(), 4,
|
||||
"editor debugger location is correct after click.");
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "click" },
|
||||
frames.querySelector("#stackframe-0 .dbg-stackframe-name"),
|
||||
gDebugger);
|
||||
EventUtils.sendMouseEvent({ type: "click" },
|
||||
frames.querySelector("#stackframe-0 .dbg-stackframe-name"),
|
||||
gDebugger);
|
||||
|
||||
ok(frames.querySelector("#stackframe-0").classList.contains("selected"),
|
||||
"First frame should be selected after click inside the first frame.");
|
||||
ok(frames.querySelector("#stackframe-0").classList.contains("selected"),
|
||||
"First frame should be selected after click inside the first frame.");
|
||||
|
||||
ok(!frames.querySelector("#stackframe-2").classList.contains("selected"),
|
||||
"Third frame should not be selected after click inside the first frame.");
|
||||
ok(!frames.querySelector("#stackframe-2").classList.contains("selected"),
|
||||
"Third frame should not be selected after click inside the first frame.");
|
||||
|
||||
is(gDebugger.editor.getDebugLocation(), 5,
|
||||
"editor debugger location is correct (frame 0 again).");
|
||||
is(gDebugger.editor.getDebugLocation(), 5,
|
||||
"editor debugger location is correct (frame 0 again).");
|
||||
|
||||
gDebugger.StackFrames.activeThread.resume(function() {
|
||||
is(gDebugger.editor.getDebugLocation(), -1,
|
||||
"editor debugger location is correct after resume.");
|
||||
closeDebuggerAndFinish(gTab);
|
||||
});
|
||||
}}, 0);
|
||||
gDebugger.StackFrames.activeThread.resume(function() {
|
||||
is(gDebugger.editor.getDebugLocation(), -1,
|
||||
"editor debugger location is correct after resume.");
|
||||
closeDebuggerAndFinish(gTab);
|
||||
});
|
||||
|
||||
gDebuggee.firstCall();
|
||||
}
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
|
|
|
@ -939,27 +939,6 @@ InspectorUI.prototype = {
|
|||
this.cssRuleViewBoundCSSLinkClicked = this.ruleViewCSSLinkClicked.bind(this);
|
||||
this.ruleView.element.addEventListener("CssRuleViewCSSLinkClicked",
|
||||
this.cssRuleViewBoundCSSLinkClicked);
|
||||
this.cssRuleViewBoundMouseDown = this.ruleViewMouseDown.bind(this);
|
||||
this.ruleView.element.addEventListener("mousedown",
|
||||
this.cssRuleViewBoundMouseDown);
|
||||
this.cssRuleViewBoundMouseUp = this.ruleViewMouseUp.bind(this);
|
||||
this.ruleView.element.addEventListener("mouseup",
|
||||
this.cssRuleViewBoundMouseUp);
|
||||
this.cssRuleViewBoundMouseMove = this.ruleViewMouseMove.bind(this);
|
||||
this.cssRuleViewBoundMenuUpdate = this.ruleViewMenuUpdate.bind(this);
|
||||
|
||||
this.cssRuleViewBoundCopy = this.ruleViewCopy.bind(this);
|
||||
iframe.addEventListener("copy", this.cssRuleViewBoundCopy);
|
||||
|
||||
this.cssRuleViewBoundCopyRule = this.ruleViewCopyRule.bind(this);
|
||||
this.cssRuleViewBoundCopyDeclaration =
|
||||
this.ruleViewCopyDeclaration.bind(this);
|
||||
this.cssRuleViewBoundCopyProperty = this.ruleViewCopyProperty.bind(this);
|
||||
this.cssRuleViewBoundCopyPropertyValue =
|
||||
this.ruleViewCopyPropertyValue.bind(this);
|
||||
|
||||
// Add the rule view's context menu.
|
||||
this.ruleViewAddContextMenu();
|
||||
|
||||
doc.documentElement.appendChild(this.ruleView.element);
|
||||
this.ruleView.highlight(this.selection);
|
||||
|
@ -1050,364 +1029,24 @@ InspectorUI.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* This is the mousedown handler for the rule view. We use it to track whether
|
||||
* text is currently getting selected.
|
||||
* .
|
||||
* @param aEvent The event object
|
||||
*/
|
||||
ruleViewMouseDown: function IUI_ruleViewMouseDown(aEvent)
|
||||
{
|
||||
this.ruleView.element.addEventListener("mousemove",
|
||||
this.cssRuleViewBoundMouseMove);
|
||||
},
|
||||
|
||||
/**
|
||||
* This is the mouseup handler for the rule view. We use it to track whether
|
||||
* text is currently getting selected.
|
||||
* .
|
||||
* @param aEvent The event object
|
||||
*/
|
||||
ruleViewMouseUp: function IUI_ruleViewMouseUp(aEvent)
|
||||
{
|
||||
this.ruleView.element.removeEventListener("mousemove",
|
||||
this.cssRuleViewBoundMouseMove);
|
||||
this.ruleView._selectionMode = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* This is the mousemove handler for the rule view. We use it to track whether
|
||||
* text is currently getting selected.
|
||||
* .
|
||||
* @param aEvent The event object
|
||||
*/
|
||||
ruleViewMouseMove: function IUI_ruleViewMouseMove(aEvent)
|
||||
{
|
||||
this.ruleView._selectionMode = true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a context menu to the rule view.
|
||||
*/
|
||||
ruleViewAddContextMenu: function IUI_ruleViewAddContextMenu()
|
||||
{
|
||||
let iframe = this.getToolIframe(this.ruleViewObject);
|
||||
let popupSet = this.chromeDoc.getElementById("mainPopupSet");
|
||||
let menu = this.chromeDoc.createElement("menupopup");
|
||||
menu.addEventListener("popupshowing", this.cssRuleViewBoundMenuUpdate);
|
||||
menu.id = "rule-view-context-menu";
|
||||
|
||||
// Copy selection
|
||||
let label = styleInspectorStrings
|
||||
.GetStringFromName("rule.contextmenu.copyselection");
|
||||
let accessKey = styleInspectorStrings
|
||||
.GetStringFromName("rule.contextmenu.copyselection.accesskey");
|
||||
let item = this.chromeDoc.createElement("menuitem");
|
||||
item.id = "rule-view-copy";
|
||||
item.setAttribute("label", label);
|
||||
item.setAttribute("accesskey", accessKey);
|
||||
item.addEventListener("command", this.cssRuleViewBoundCopy);
|
||||
menu.appendChild(item);
|
||||
|
||||
// Copy rule
|
||||
label = styleInspectorStrings.
|
||||
GetStringFromName("rule.contextmenu.copyrule");
|
||||
accessKey = styleInspectorStrings.
|
||||
GetStringFromName("rule.contextmenu.copyrule.accesskey");
|
||||
item = this.chromeDoc.createElement("menuitem");
|
||||
item.id = "rule-view-copy-rule";
|
||||
item.setAttribute("label", label);
|
||||
item.setAttribute("accesskey", accessKey);
|
||||
item.addEventListener("command", this.cssRuleViewBoundCopyRule);
|
||||
menu.appendChild(item);
|
||||
|
||||
// Copy declaration
|
||||
label = styleInspectorStrings.
|
||||
GetStringFromName("rule.contextmenu.copydeclaration");
|
||||
accessKey = styleInspectorStrings.
|
||||
GetStringFromName("rule.contextmenu.copydeclaration.accesskey");
|
||||
item = this.chromeDoc.createElement("menuitem");
|
||||
item.id = "rule-view-copy-declaration";
|
||||
item.setAttribute("label", label);
|
||||
item.setAttribute("accesskey", accessKey);
|
||||
item.addEventListener("command", this.cssRuleViewBoundCopyDeclaration);
|
||||
menu.appendChild(item);
|
||||
|
||||
// Copy property name
|
||||
label = styleInspectorStrings.
|
||||
GetStringFromName("rule.contextmenu.copyproperty");
|
||||
accessKey = styleInspectorStrings.
|
||||
GetStringFromName("rule.contextmenu.copyproperty.accesskey");
|
||||
item = this.chromeDoc.createElement("menuitem");
|
||||
item.id = "rule-view-copy-property";
|
||||
item.setAttribute("label", label);
|
||||
item.setAttribute("accesskey", accessKey);
|
||||
item.addEventListener("command", this.cssRuleViewBoundCopyProperty);
|
||||
menu.appendChild(item);
|
||||
|
||||
// Copy property value
|
||||
label = styleInspectorStrings.
|
||||
GetStringFromName("rule.contextmenu.copypropertyvalue");
|
||||
accessKey = styleInspectorStrings.
|
||||
GetStringFromName("rule.contextmenu.copypropertyvalue.accesskey");
|
||||
item = this.chromeDoc.createElement("menuitem");
|
||||
item.id = "rule-view-copy-property-value";
|
||||
item.setAttribute("label", label);
|
||||
item.setAttribute("accesskey", accessKey);
|
||||
item.addEventListener("command", this.cssRuleViewBoundCopyPropertyValue);
|
||||
menu.appendChild(item);
|
||||
|
||||
popupSet.appendChild(menu);
|
||||
|
||||
iframe.setAttribute("context", menu.id);
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the rule view's context menu by disabling irrelevant menuitems and
|
||||
* enabling relevant ones.
|
||||
*
|
||||
* @param aEvent The event object
|
||||
*/
|
||||
ruleViewMenuUpdate: function IUI_ruleViewMenuUpdate(aEvent)
|
||||
{
|
||||
let iframe = this.getToolIframe(this.ruleViewObject);
|
||||
let win = iframe.contentWindow;
|
||||
|
||||
// Copy selection.
|
||||
let disable = win.getSelection().isCollapsed;
|
||||
let menuitem = this.chromeDoc.getElementById("rule-view-copy");
|
||||
menuitem.disabled = disable;
|
||||
|
||||
// Copy property, copy property name & copy property value.
|
||||
let node = this.chromeDoc.popupNode;
|
||||
if (!node.classList.contains("ruleview-property") &&
|
||||
!node.classList.contains("ruleview-computed")) {
|
||||
while (node = node.parentElement) {
|
||||
if (node.classList.contains("ruleview-property") ||
|
||||
node.classList.contains("ruleview-computed")) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
let disablePropertyItems = !node || (node &&
|
||||
!node.classList.contains("ruleview-property") &&
|
||||
!node.classList.contains("ruleview-computed"));
|
||||
|
||||
menuitem = this.chromeDoc.querySelector("#rule-view-copy-declaration");
|
||||
menuitem.disabled = disablePropertyItems;
|
||||
menuitem = this.chromeDoc.querySelector("#rule-view-copy-property");
|
||||
menuitem.disabled = disablePropertyItems;
|
||||
menuitem = this.chromeDoc.querySelector("#rule-view-copy-property-value");
|
||||
menuitem.disabled = disablePropertyItems;
|
||||
},
|
||||
|
||||
/**
|
||||
* Copy selected text from the rule view.
|
||||
*
|
||||
* @param aEvent The event object
|
||||
*/
|
||||
ruleViewCopy: function IUI_ruleViewCopy(aEvent)
|
||||
{
|
||||
let iframe = this.getToolIframe(this.ruleViewObject);
|
||||
let win = iframe.contentWindow;
|
||||
let text = win.getSelection().toString();
|
||||
|
||||
// Remove any double newlines.
|
||||
text = text.replace(/(\r?\n)\r?\n/g, "$1");
|
||||
|
||||
// Remove "inline"
|
||||
let inline = styleInspectorStrings.GetStringFromName("rule.sourceInline");
|
||||
let rx = new RegExp("^" + inline + "\\r?\\n?", "g");
|
||||
text = text.replace(rx, "");
|
||||
|
||||
// Remove file:line
|
||||
text = text.replace(/[\w\.]+:\d+(\r?\n)/g, "$1");
|
||||
|
||||
// Remove inherited from: line
|
||||
let inheritedFrom = styleInspectorStrings
|
||||
.GetStringFromName("rule.inheritedSource");
|
||||
inheritedFrom = inheritedFrom.replace(/\s%S\s\(%S\)/g, "");
|
||||
rx = new RegExp("(\r?\n)" + inheritedFrom + ".*", "g");
|
||||
text = text.replace(rx, "$1");
|
||||
|
||||
clipboardHelper.copyString(text);
|
||||
|
||||
if (aEvent) {
|
||||
aEvent.preventDefault();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Copy a rule from the rule view.
|
||||
*
|
||||
* @param aEvent The event object
|
||||
*/
|
||||
ruleViewCopyRule: function IUI_ruleViewCopyRule(aEvent)
|
||||
{
|
||||
let node = this.chromeDoc.popupNode;
|
||||
if (node.className != "ruleview-code") {
|
||||
if (node.className == "ruleview-rule-source") {
|
||||
node = node.nextElementSibling;
|
||||
} else {
|
||||
while (node = node.parentElement) {
|
||||
if (node.className == "ruleview-code") {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (node.className == "ruleview-code") {
|
||||
// We need to strip expanded properties from the node because we use
|
||||
// node.textContent below, which also gets text from hidden nodes. The
|
||||
// simplest way to do this is to clone the node and remove them from the
|
||||
// clone.
|
||||
node = node.cloneNode();
|
||||
let computed = node.querySelector(".ruleview-computedlist");
|
||||
if (computed) {
|
||||
computed.parentNode.removeChild(computed);
|
||||
}
|
||||
let autosizer = node.querySelector(".autosizer");
|
||||
if (autosizer) {
|
||||
autosizer.parentNode.removeChild(autosizer);
|
||||
}
|
||||
}
|
||||
|
||||
let text = node.textContent;
|
||||
|
||||
// Format the rule
|
||||
if (osString == "WINNT") {
|
||||
text = text.replace(/{/g, "{\r\n ");
|
||||
text = text.replace(/;/g, ";\r\n ");
|
||||
text = text.replace(/\s*}/g, "\r\n}");
|
||||
} else {
|
||||
text = text.replace(/{/g, "{\n ");
|
||||
text = text.replace(/;/g, ";\n ");
|
||||
text = text.replace(/\s*}/g, "\n}");
|
||||
}
|
||||
|
||||
clipboardHelper.copyString(text);
|
||||
},
|
||||
|
||||
/**
|
||||
* Copy a declaration from the rule view.
|
||||
*
|
||||
* @param aEvent The event object
|
||||
*/
|
||||
ruleViewCopyDeclaration: function IUI_ruleViewCopyDeclaration(aEvent)
|
||||
{
|
||||
let node = this.chromeDoc.popupNode;
|
||||
if (!node.classList.contains("ruleview-property") &&
|
||||
!node.classList.contains("ruleview-computed")) {
|
||||
while (node = node.parentElement) {
|
||||
if (node.classList.contains("ruleview-property") ||
|
||||
node.classList.contains("ruleview-computed")) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We need to strip expanded properties from the node because we use
|
||||
// node.textContent below, which also gets text from hidden nodes. The
|
||||
// simplest way to do this is to clone the node and remove them from the
|
||||
// clone.
|
||||
node = node.cloneNode();
|
||||
let computed = node.querySelector(".ruleview-computedlist");
|
||||
if (computed) {
|
||||
computed.parentNode.removeChild(computed);
|
||||
}
|
||||
clipboardHelper.copyString(node.textContent);
|
||||
},
|
||||
|
||||
/**
|
||||
* Copy a property name from the rule view.
|
||||
*
|
||||
* @param aEvent The event object
|
||||
*/
|
||||
ruleViewCopyProperty: function IUI_ruleViewCopyProperty(aEvent)
|
||||
{
|
||||
let node = this.chromeDoc.popupNode;
|
||||
|
||||
if (!node.classList.contains("ruleview-propertyname")) {
|
||||
node = node.querySelector(".ruleview-propertyname");
|
||||
}
|
||||
|
||||
if (node) {
|
||||
clipboardHelper.copyString(node.textContent);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Copy a property value from the rule view.
|
||||
*
|
||||
* @param aEvent The event object
|
||||
*/
|
||||
ruleViewCopyPropertyValue: function IUI_ruleViewCopyPropertyValue(aEvent)
|
||||
{
|
||||
let node = this.chromeDoc.popupNode;
|
||||
|
||||
if (!node.classList.contains("ruleview-propertyvalue")) {
|
||||
node = node.querySelector(".ruleview-propertyvalue");
|
||||
}
|
||||
|
||||
if (node) {
|
||||
clipboardHelper.copyString(node.textContent);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Destroy the rule view.
|
||||
*/
|
||||
destroyRuleView: function IUI_destroyRuleView()
|
||||
{
|
||||
let iframe = this.getToolIframe(this.ruleViewObject);
|
||||
iframe.removeEventListener("copy", this.cssRuleViewBoundCopy);
|
||||
iframe.parentNode.removeChild(iframe);
|
||||
|
||||
if (this.ruleView) {
|
||||
let menu = this.chromeDoc.querySelector("#rule-view-context-menu");
|
||||
if (menu) {
|
||||
// Copy
|
||||
let menuitem = this.chromeDoc.querySelector("#rule-view-copy");
|
||||
menuitem.removeEventListener("command", this.cssRuleViewBoundCopy);
|
||||
|
||||
// Copy rule
|
||||
menuitem = this.chromeDoc.querySelector("#rule-view-copy-rule");
|
||||
menuitem.removeEventListener("command", this.cssRuleViewBoundCopyRule);
|
||||
|
||||
// Copy property
|
||||
menuitem = this.chromeDoc.querySelector("#rule-view-copy-declaration");
|
||||
menuitem.removeEventListener("command",
|
||||
this.cssRuleViewBoundCopyDeclaration);
|
||||
|
||||
// Copy property name
|
||||
menuitem = this.chromeDoc.querySelector("#rule-view-copy-property");
|
||||
menuitem.removeEventListener("command",
|
||||
this.cssRuleViewBoundCopyProperty);
|
||||
|
||||
// Copy property value
|
||||
menuitem = this.chromeDoc.querySelector("#rule-view-copy-property-value");
|
||||
menuitem.removeEventListener("command",
|
||||
this.cssRuleViewBoundCopyPropertyValue);
|
||||
|
||||
menu.removeEventListener("popupshowing", this.cssRuleViewBoundMenuUpdate);
|
||||
menu.parentNode.removeChild(menu);
|
||||
}
|
||||
|
||||
this.ruleView.element.removeEventListener("CssRuleViewChanged",
|
||||
this.boundRuleViewChanged);
|
||||
this.ruleView.element.removeEventListener("CssRuleViewCSSLinkClicked",
|
||||
this.cssRuleViewBoundCSSLinkClicked);
|
||||
this.ruleView.element.removeEventListener("mousedown",
|
||||
this.cssRuleViewBoundMouseDown);
|
||||
this.ruleView.element.removeEventListener("mouseup",
|
||||
this.cssRuleViewBoundMouseUp);
|
||||
this.ruleView.element.removeEventListener("mousemove",
|
||||
this.cssRuleViewBoundMouseMove);
|
||||
delete boundRuleViewChanged;
|
||||
this.ruleView.clear();
|
||||
delete this.boundRuleViewChanged;
|
||||
delete this.cssRuleViewBoundCSSLinkClicked;
|
||||
this.ruleView.destroy();
|
||||
delete this.ruleView;
|
||||
}
|
||||
|
||||
let iframe = this.getToolIframe(this.ruleViewObject);
|
||||
iframe.parentNode.removeChild(iframe);
|
||||
},
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
@ -2631,12 +2270,3 @@ XPCOMUtils.defineLazyGetter(this, "clipboardHelper", function() {
|
|||
return Cc["@mozilla.org/widget/clipboardhelper;1"].
|
||||
getService(Ci.nsIClipboardHelper);
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "styleInspectorStrings", function() {
|
||||
return Services.strings.createBundle(
|
||||
"chrome://browser/locale/devtools/styleinspector.properties");
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "osString", function() {
|
||||
return Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS;
|
||||
});
|
||||
|
|
|
@ -90,7 +90,9 @@ function inspectorFocusTab1()
|
|||
is(InspectorUI.selection, div, "selection matches the div element");
|
||||
ok(InspectorUI.isSidebarOpen, "sidebar is open");
|
||||
ok(InspectorUI.isRuleViewOpen(), "rule view is open");
|
||||
is(InspectorUI.ruleView.doc.documentElement.children.length, 1, "RuleView elements.length == 1");
|
||||
|
||||
// The rule view element plus its popupSet
|
||||
is(InspectorUI.ruleView.doc.documentElement.children.length, 2, "RuleView elements.length == 2");
|
||||
|
||||
requestLongerTimeout(4);
|
||||
executeSoon(function() {
|
||||
|
|
|
@ -40,6 +40,7 @@ function test()
|
|||
testNew();
|
||||
testSavedFile();
|
||||
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
content.location = "data:text/html,<p>test scratchpad save file prompt on closing";
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ function test()
|
|||
testRestoreFromFileSaved();
|
||||
testRestoreFromFileUnsaved();
|
||||
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
content.location = "data:text/html,<p>test star* UI for unsaved file changes";
|
||||
}
|
||||
|
||||
|
|
|
@ -64,6 +64,7 @@ const CSS_PROP_RE = /\s*([^:\s]*)\s*:\s*(.*?)\s*(?:! (important))?;?$/;
|
|||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource:///modules/devtools/CssLogic.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
var EXPORTED_SYMBOLS = ["CssRuleView",
|
||||
"_ElementStyle",
|
||||
|
@ -699,12 +700,55 @@ function CssRuleView(aDoc, aStore)
|
|||
this.element.setAttribute("tabindex", "0");
|
||||
this.element.classList.add("ruleview");
|
||||
this.element.flex = 1;
|
||||
this._selectionMode = false;
|
||||
|
||||
this._boundMouseDown = this._onMouseDown.bind(this);
|
||||
this.element.addEventListener("mousedown",
|
||||
this._boundMouseDown);
|
||||
this._boundMouseUp = this._onMouseUp.bind(this);
|
||||
this.element.addEventListener("mouseup",
|
||||
this._boundMouseUp);
|
||||
this._boundMouseMove = this._onMouseMove.bind(this);
|
||||
|
||||
this._boundCopy = this._onCopy.bind(this);
|
||||
this.element.addEventListener("copy", this._boundCopy);
|
||||
|
||||
this._createContextMenu();
|
||||
}
|
||||
|
||||
CssRuleView.prototype = {
|
||||
// The element that we're inspecting.
|
||||
_viewedElement: null,
|
||||
|
||||
destroy: function CssRuleView_destroy()
|
||||
{
|
||||
this.clear();
|
||||
|
||||
this.element.removeEventListener("copy", this._boundCopy);
|
||||
this._copyItem.removeEventListener("command", this._boundCopy);
|
||||
delete this._boundCopy;
|
||||
|
||||
this._ruleItem.removeEventListener("command", this._boundCopyRule);
|
||||
delete this._boundCopyRule;
|
||||
|
||||
this._declarationItem.removeEventListener("command", this._boundCopyDeclaration);
|
||||
delete this._boundCopyDeclaration;
|
||||
|
||||
this._propertyItem.removeEventListener("command", this._boundCopyProperty);
|
||||
delete this._boundCopyProperty;
|
||||
|
||||
this._propertyValueItem.removeEventListener("command", this._boundCopyPropertyValue);
|
||||
delete this._boundCopyPropertyValue;
|
||||
|
||||
this._contextMenu.removeEventListener("popupshowing", this._boundMenuUpdate);
|
||||
delete this._boundMenuUpdate;
|
||||
delete this._contextMenu;
|
||||
|
||||
if (this.element.parentNode) {
|
||||
this.element.parentNode.removeChild(this.element);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the highlighted element.
|
||||
*
|
||||
|
@ -813,6 +857,262 @@ CssRuleView.prototype = {
|
|||
this.element.appendChild(editor.element);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a context menu to the rule view.
|
||||
*/
|
||||
_createContextMenu: function CssRuleView_createContextMenu()
|
||||
{
|
||||
let popupSet = this.doc.createElement("popupset");
|
||||
this.doc.documentElement.appendChild(popupSet);
|
||||
|
||||
let menu = this.doc.createElement("menupopup");
|
||||
menu.id = "rule-view-context-menu";
|
||||
|
||||
this._boundMenuUpdate = this._onMenuUpdate.bind(this);
|
||||
menu.addEventListener("popupshowing", this._boundMenuUpdate);
|
||||
|
||||
// Copy selection
|
||||
this._copyItem = createMenuItem(menu, {
|
||||
label: "rule.contextmenu.copyselection",
|
||||
accesskey: "rule.contextmenu.copyselection.accesskey",
|
||||
command: this._boundCopy
|
||||
});
|
||||
|
||||
// Copy rule
|
||||
this._boundCopyRule = this._onCopyRule.bind(this);
|
||||
this._ruleItem = createMenuItem(menu, {
|
||||
label: "rule.contextmenu.copyrule",
|
||||
accesskey: "rule.contextmenu.copyrule.accesskey",
|
||||
command: this._boundCopyRule
|
||||
});
|
||||
|
||||
// Copy declaration
|
||||
this._boundCopyDeclaration = this._onCopyDeclaration.bind(this);
|
||||
this._declarationItem = createMenuItem(menu, {
|
||||
label: "rule.contextmenu.copydeclaration",
|
||||
accesskey: "rule.contextmenu.copydeclaration.accesskey",
|
||||
command: this._boundCopyDeclaration
|
||||
});
|
||||
|
||||
this._boundCopyProperty = this._onCopyProperty.bind(this);
|
||||
this._propertyItem = createMenuItem(menu, {
|
||||
label: "rule.contextmenu.copyproperty",
|
||||
accesskey: "rule.contextmenu.copyproperty.accesskey",
|
||||
command: this._boundCopyProperty
|
||||
});
|
||||
|
||||
this._boundCopyPropertyValue = this._onCopyPropertyValue.bind(this);
|
||||
this._propertyValueItem = createMenuItem(menu,{
|
||||
label: "rule.contextmenu.copypropertyvalue",
|
||||
accesskey: "rule.contextmenu.copypropertyvalue.accesskey",
|
||||
command: this._boundCopyPropertyValue
|
||||
});
|
||||
|
||||
popupSet.appendChild(menu);
|
||||
this.element.setAttribute("context", menu.id);
|
||||
|
||||
this._contextMenu = menu;
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the rule view's context menu by disabling irrelevant menuitems and
|
||||
* enabling relevant ones.
|
||||
*
|
||||
* @param aEvent The event object
|
||||
*/
|
||||
_onMenuUpdate: function CssRuleView_onMenuUpdate(aEvent)
|
||||
{
|
||||
// Copy selection.
|
||||
let disable = this.doc.defaultView.getSelection().isCollapsed;
|
||||
this._copyItem.disabled = disable;
|
||||
|
||||
// Copy property, copy property name & copy property value.
|
||||
let node = this.doc.popupNode;
|
||||
if (!node.classList.contains("ruleview-property") &&
|
||||
!node.classList.contains("ruleview-computed")) {
|
||||
while (node = node.parentElement) {
|
||||
if (node.classList.contains("ruleview-property") ||
|
||||
node.classList.contains("ruleview-computed")) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
let disablePropertyItems = !node || (node &&
|
||||
!node.classList.contains("ruleview-property") &&
|
||||
!node.classList.contains("ruleview-computed"));
|
||||
|
||||
this._declarationItem.disabled = disablePropertyItems;
|
||||
this._propertyItem.disabled = disablePropertyItems;
|
||||
this._propertyValueItem.disabled = disablePropertyItems;
|
||||
|
||||
dump("Done updating menu!\n");
|
||||
},
|
||||
|
||||
_onMouseDown: function CssRuleView_onMouseDown()
|
||||
{
|
||||
this.element.addEventListener("mousemove", this._boundMouseMove);
|
||||
},
|
||||
|
||||
_onMouseUp: function CssRuleView_onMouseUp()
|
||||
{
|
||||
this.element.removeEventListener("mousemove", this._boundMouseMove);
|
||||
this._selectionMode = false;
|
||||
},
|
||||
|
||||
_onMouseMove: function CssRuleView_onMouseMove()
|
||||
{
|
||||
this._selectionMode = true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Copy selected text from the rule view.
|
||||
*
|
||||
* @param aEvent The event object
|
||||
*/
|
||||
_onCopy: function CssRuleView_onCopy(aEvent)
|
||||
{
|
||||
let win = this.doc.defaultView;
|
||||
let text = win.getSelection().toString();
|
||||
|
||||
// Remove any double newlines.
|
||||
text = text.replace(/(\r?\n)\r?\n/g, "$1");
|
||||
|
||||
// Remove "inline"
|
||||
let inline = _strings.GetStringFromName("rule.sourceInline");
|
||||
let rx = new RegExp("^" + inline + "\\r?\\n?", "g");
|
||||
text = text.replace(rx, "");
|
||||
|
||||
// Remove file:line
|
||||
text = text.replace(/[\w\.]+:\d+(\r?\n)/g, "$1");
|
||||
|
||||
// Remove inherited from: line
|
||||
let inheritedFrom = _strings.
|
||||
GetStringFromName("rule.inheritedSource");
|
||||
inheritedFrom = inheritedFrom.replace(/\s%S\s\(%S\)/g, "");
|
||||
rx = new RegExp("(\r?\n)" + inheritedFrom + ".*", "g");
|
||||
text = text.replace(rx, "$1");
|
||||
|
||||
clipboardHelper.copyString(text);
|
||||
|
||||
if (aEvent) {
|
||||
aEvent.preventDefault();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Copy a rule from the rule view.
|
||||
*
|
||||
* @param aEvent The event object
|
||||
*/
|
||||
_onCopyRule: function CssRuleView_onCopyRule(aEvent)
|
||||
{
|
||||
let node = this.doc.popupNode;
|
||||
if (node.className != "ruleview-code") {
|
||||
if (node.className == "ruleview-rule-source") {
|
||||
node = node.nextElementSibling;
|
||||
} else {
|
||||
while (node = node.parentElement) {
|
||||
if (node.className == "ruleview-code") {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (node.className == "ruleview-code") {
|
||||
// We need to strip expanded properties from the node because we use
|
||||
// node.textContent below, which also gets text from hidden nodes. The
|
||||
// simplest way to do this is to clone the node and remove them from the
|
||||
// clone.
|
||||
node = node.cloneNode();
|
||||
let computed = node.querySelector(".ruleview-computedlist");
|
||||
if (computed) {
|
||||
computed.parentNode.removeChild(computed);
|
||||
}
|
||||
}
|
||||
|
||||
let text = node.textContent;
|
||||
|
||||
// Format the rule
|
||||
if (osString == "WINNT") {
|
||||
text = text.replace(/{/g, "{\r\n ");
|
||||
text = text.replace(/;/g, ";\r\n ");
|
||||
text = text.replace(/\s*}/g, "\r\n}");
|
||||
} else {
|
||||
text = text.replace(/{/g, "{\n ");
|
||||
text = text.replace(/;/g, ";\n ");
|
||||
text = text.replace(/\s*}/g, "\n}");
|
||||
}
|
||||
|
||||
clipboardHelper.copyString(text);
|
||||
},
|
||||
|
||||
/**
|
||||
* Copy a declaration from the rule view.
|
||||
*
|
||||
* @param aEvent The event object
|
||||
*/
|
||||
_onCopyDeclaration: function CssRuleView_onCopyDeclaration(aEvent)
|
||||
{
|
||||
let node = this.doc.popupNode;
|
||||
if (!node.classList.contains("ruleview-property") &&
|
||||
!node.classList.contains("ruleview-computed")) {
|
||||
while (node = node.parentElement) {
|
||||
if (node.classList.contains("ruleview-property") ||
|
||||
node.classList.contains("ruleview-computed")) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We need to strip expanded properties from the node because we use
|
||||
// node.textContent below, which also gets text from hidden nodes. The
|
||||
// simplest way to do this is to clone the node and remove them from the
|
||||
// clone.
|
||||
node = node.cloneNode();
|
||||
let computed = node.querySelector(".ruleview-computedlist");
|
||||
if (computed) {
|
||||
computed.parentNode.removeChild(computed);
|
||||
}
|
||||
clipboardHelper.copyString(node.textContent);
|
||||
},
|
||||
|
||||
/**
|
||||
* Copy a property name from the rule view.
|
||||
*
|
||||
* @param aEvent The event object
|
||||
*/
|
||||
_onCopyProperty: function CssRuleView_onCopyProperty(aEvent)
|
||||
{
|
||||
let node = this.doc.popupNode;
|
||||
|
||||
if (!node.classList.contains("ruleview-propertyname")) {
|
||||
node = node.querySelector(".ruleview-propertyname");
|
||||
}
|
||||
|
||||
if (node) {
|
||||
clipboardHelper.copyString(node.textContent);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Copy a property value from the rule view.
|
||||
*
|
||||
* @param aEvent The event object
|
||||
*/
|
||||
_onCopyPropertyValue: function CssRuleView_onCopyPropertyValue(aEvent)
|
||||
{
|
||||
let node = this.doc.popupNode;
|
||||
|
||||
if (!node.classList.contains("ruleview-propertyvalue")) {
|
||||
node = node.querySelector(".ruleview-propertyvalue");
|
||||
}
|
||||
|
||||
if (node) {
|
||||
clipboardHelper.copyString(node.textContent);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1569,6 +1869,18 @@ function createChild(aParent, aTag, aAttributes)
|
|||
return elt;
|
||||
}
|
||||
|
||||
function createMenuItem(aMenu, aAttributes)
|
||||
{
|
||||
let item = aMenu.ownerDocument.createElementNS(XUL_NS, "menuitem");
|
||||
item.setAttribute("label", _strings.GetStringFromName(aAttributes.label));
|
||||
item.setAttribute("accesskey", _strings.GetStringFromName(aAttributes.accesskey));
|
||||
item.addEventListener("command", aAttributes.command);
|
||||
|
||||
aMenu.appendChild(item);
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a text node to an element.
|
||||
*/
|
||||
|
@ -1598,3 +1910,18 @@ function moveFocus(aWin, aDirection)
|
|||
let fm = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager);
|
||||
fm.moveFocus(aWin, null, aDirection, 0);
|
||||
}
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "clipboardHelper", function() {
|
||||
return Cc["@mozilla.org/widget/clipboardhelper;1"].
|
||||
getService(Ci.nsIClipboardHelper);
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "_strings", function() {
|
||||
return Services.strings.createBundle(
|
||||
"chrome://browser/locale/devtools/styleinspector.properties");
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "osString", function() {
|
||||
return Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS;
|
||||
});
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ function testClip()
|
|||
InspectorUI.INSPECTOR_NOTIFICATIONS.RULEVIEWREADY, false);
|
||||
|
||||
executeSoon(function() {
|
||||
info("Checking that InspectorUI.ruleViewCopyRule() returns " +
|
||||
info("Checking that _onCopyRule() returns " +
|
||||
"the correct clipboard value");
|
||||
let expectedPattern = "element {[\\r\\n]+" +
|
||||
" margin: 10em;[\\r\\n]+" +
|
||||
|
@ -106,12 +106,12 @@ function checkCopyRule() {
|
|||
EventUtils.synthesizeMouse(prop, 1, 1, { type: "contextmenu", button: 2 },
|
||||
ruleView.contentWindow);
|
||||
|
||||
InspectorUI.ruleViewCopyRule();
|
||||
InspectorUI.ruleView._boundCopyRule();
|
||||
}
|
||||
|
||||
function checkCopyProperty()
|
||||
{
|
||||
info("Checking that InspectorUI.cssRuleViewBoundCopyDeclaration() returns " +
|
||||
info("Checking that _onCopyDeclaration() returns " +
|
||||
"the correct clipboard value");
|
||||
let expectedPattern = "font-family: helvetica,sans-serif;";
|
||||
info("Expected pattern: " + expectedPattern);
|
||||
|
@ -119,13 +119,13 @@ function checkCopyProperty()
|
|||
SimpleTest.waitForClipboard(function IUI_boundCopyPropCheck() {
|
||||
return checkClipboardData(expectedPattern);
|
||||
},
|
||||
InspectorUI.cssRuleViewBoundCopyDeclaration,
|
||||
InspectorUI.ruleView._boundCopyDeclaration,
|
||||
checkCopyPropertyName, checkCopyPropertyName);
|
||||
}
|
||||
|
||||
function checkCopyPropertyName()
|
||||
{
|
||||
info("Checking that InspectorUI.cssRuleViewBoundCopyProperty() returns " +
|
||||
info("Checking that _onCopyProperty() returns " +
|
||||
"the correct clipboard value");
|
||||
let expectedPattern = "font-family";
|
||||
info("Expected pattern: " + expectedPattern);
|
||||
|
@ -133,13 +133,13 @@ function checkCopyPropertyName()
|
|||
SimpleTest.waitForClipboard(function IUI_boundCopyPropNameCheck() {
|
||||
return checkClipboardData(expectedPattern);
|
||||
},
|
||||
InspectorUI.cssRuleViewBoundCopyProperty,
|
||||
InspectorUI.ruleView._boundCopyProperty,
|
||||
checkCopyPropertyValue, checkCopyPropertyValue);
|
||||
}
|
||||
|
||||
function checkCopyPropertyValue()
|
||||
{
|
||||
info("Checking that InspectorUI.cssRuleViewBoundCopyPropertyValue() " +
|
||||
info("Checking that _onCopyPropertyValue() " +
|
||||
" returns the correct clipboard value");
|
||||
let expectedPattern = "helvetica,sans-serif";
|
||||
info("Expected pattern: " + expectedPattern);
|
||||
|
@ -147,7 +147,7 @@ function checkCopyPropertyValue()
|
|||
SimpleTest.waitForClipboard(function IUI_boundCopyPropValueCheck() {
|
||||
return checkClipboardData(expectedPattern);
|
||||
},
|
||||
InspectorUI.cssRuleViewBoundCopyPropertyValue,
|
||||
InspectorUI.ruleView._boundCopyPropertyValue,
|
||||
checkCopySelection, checkCopySelection);
|
||||
}
|
||||
|
||||
|
@ -162,7 +162,7 @@ function checkCopySelection()
|
|||
range.setEnd(props[4], 8);
|
||||
ruleView.contentWindow.getSelection().addRange(range);
|
||||
|
||||
info("Checking that InspectorUI.cssRuleViewBoundCopy() returns the correct" +
|
||||
info("Checking that _onCopy() returns the correct" +
|
||||
"clipboard value");
|
||||
let expectedPattern = " margin: 10em;[\\r\\n]+" +
|
||||
" font-size: 14pt;[\\r\\n]+" +
|
||||
|
@ -175,7 +175,7 @@ function checkCopySelection()
|
|||
|
||||
SimpleTest.waitForClipboard(function IUI_boundCopyCheck() {
|
||||
return checkClipboardData(expectedPattern);
|
||||
},InspectorUI.cssRuleViewBoundCopy, finishup, finishup);
|
||||
},InspectorUI.ruleView._boundCopy, finishup, finishup);
|
||||
}
|
||||
|
||||
function checkClipboardData(aExpectedPattern)
|
||||
|
|
Загрузка…
Ссылка в новой задаче