mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1024693 - [rule view] Copy CSS declarations r=pbrosset
This commit is contained in:
parent
3276349f43
commit
9227dd3edd
@ -958,6 +958,21 @@ Rule.prototype = {
|
||||
} else {
|
||||
aTextProperty.rule.editor.closeBrace.focus();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Return a string representation of the rule.
|
||||
*/
|
||||
stringifyRule: function() {
|
||||
let selectorText = this.selectorText;
|
||||
let cssText = "";
|
||||
let terminator = osString == "WINNT" ? "\r\n" : "\n";
|
||||
|
||||
for (let textProp of this.textProps) {
|
||||
cssText += "\t" + textProp.stringifyProperty() + terminator;
|
||||
}
|
||||
|
||||
return selectorText + " {" + terminator + cssText + "}";
|
||||
}
|
||||
};
|
||||
|
||||
@ -1083,6 +1098,21 @@ TextProperty.prototype = {
|
||||
|
||||
remove: function() {
|
||||
this.rule.removeProperty(this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Return a string representation of the rule property.
|
||||
*/
|
||||
stringifyProperty: function() {
|
||||
// Get the displayed property value
|
||||
let declaration = this.name + ": " + this.editor.committed.value + ";";
|
||||
|
||||
// Comment out property declarations that are not enabled
|
||||
if (!this.enabled) {
|
||||
declaration = "/* " + declaration + " */";
|
||||
}
|
||||
|
||||
return declaration;
|
||||
}
|
||||
};
|
||||
|
||||
@ -1136,6 +1166,12 @@ function CssRuleView(aInspector, aDoc, aStore, aPageStyle) {
|
||||
this._onCopy = this._onCopy.bind(this);
|
||||
this._onCopyColor = this._onCopyColor.bind(this);
|
||||
this._onCopyImageDataUrl = this._onCopyImageDataUrl.bind(this);
|
||||
this._onCopyLocation = this._onCopyLocation.bind(this);
|
||||
this._onCopyPropertyDeclaration = this._onCopyPropertyDeclaration.bind(this);
|
||||
this._onCopyPropertyName = this._onCopyPropertyName.bind(this);
|
||||
this._onCopyPropertyValue = this._onCopyPropertyValue.bind(this);
|
||||
this._onCopyRule = this._onCopyRule.bind(this);
|
||||
this._onCopySelector = this._onCopySelector.bind(this);
|
||||
this._onToggleOrigSources = this._onToggleOrigSources.bind(this);
|
||||
this._onShowMdnDocs = this._onShowMdnDocs.bind(this);
|
||||
this._onFilterStyles = this._onFilterStyles.bind(this);
|
||||
@ -1223,31 +1259,70 @@ CssRuleView.prototype = {
|
||||
this._contextmenu.addEventListener("popupshowing", this._contextMenuUpdate);
|
||||
this._contextmenu.id = "rule-view-context-menu";
|
||||
|
||||
this.menuitemAddRule = createMenuItem(this._contextmenu, {
|
||||
label: "ruleView.contextmenu.addNewRule",
|
||||
accesskey: "ruleView.contextmenu.addNewRule.accessKey",
|
||||
command: this._onAddRule
|
||||
});
|
||||
this.menuitemSelectAll = createMenuItem(this._contextmenu, {
|
||||
label: "ruleView.contextmenu.selectAll",
|
||||
accesskey: "ruleView.contextmenu.selectAll.accessKey",
|
||||
command: this._onSelectAll
|
||||
});
|
||||
this.menuitemCopy = createMenuItem(this._contextmenu, {
|
||||
label: "ruleView.contextmenu.copy",
|
||||
accesskey: "ruleView.contextmenu.copy.accessKey",
|
||||
command: this._onCopy
|
||||
});
|
||||
|
||||
this.menuitemCopyLocation = createMenuItem(this._contextmenu, {
|
||||
label: "ruleView.contextmenu.copyLocation",
|
||||
command: this._onCopyLocation
|
||||
});
|
||||
|
||||
this.menuitemCopyRule = createMenuItem(this._contextmenu, {
|
||||
label: "ruleView.contextmenu.copyRule",
|
||||
command: this._onCopyRule
|
||||
});
|
||||
|
||||
this.menuitemCopyColor = createMenuItem(this._contextmenu, {
|
||||
label: "ruleView.contextmenu.copyColor",
|
||||
accesskey: "ruleView.contextmenu.copyColor.accessKey",
|
||||
command: this._onCopyColor
|
||||
});
|
||||
|
||||
this.menuitemCopyImageDataUrl = createMenuItem(this._contextmenu, {
|
||||
label: "styleinspector.contextmenu.copyImageDataUrl",
|
||||
accesskey: "styleinspector.contextmenu.copyImageDataUrl.accessKey",
|
||||
command: this._onCopyImageDataUrl
|
||||
});
|
||||
|
||||
this.menuitemCopyPropertyDeclaration = createMenuItem(this._contextmenu, {
|
||||
label: "ruleView.contextmenu.copyPropertyDeclaration",
|
||||
command: this._onCopyPropertyDeclaration
|
||||
});
|
||||
|
||||
this.menuitemCopyPropertyName = createMenuItem(this._contextmenu, {
|
||||
label: "ruleView.contextmenu.copyPropertyName",
|
||||
command: this._onCopyPropertyName
|
||||
});
|
||||
|
||||
this.menuitemCopyPropertyValue = createMenuItem(this._contextmenu, {
|
||||
label: "ruleView.contextmenu.copyPropertyValue",
|
||||
command: this._onCopyPropertyValue
|
||||
});
|
||||
|
||||
this.menuitemCopySelector = createMenuItem(this._contextmenu, {
|
||||
label: "ruleView.contextmenu.copySelector",
|
||||
command: this._onCopySelector
|
||||
});
|
||||
|
||||
createMenuSeparator(this._contextmenu);
|
||||
|
||||
this.menuitemSelectAll = createMenuItem(this._contextmenu, {
|
||||
label: "ruleView.contextmenu.selectAll",
|
||||
accesskey: "ruleView.contextmenu.selectAll.accessKey",
|
||||
command: this._onSelectAll
|
||||
});
|
||||
|
||||
createMenuSeparator(this._contextmenu);
|
||||
|
||||
this.menuitemAddRule = createMenuItem(this._contextmenu, {
|
||||
label: "ruleView.contextmenu.addNewRule",
|
||||
accesskey: "ruleView.contextmenu.addNewRule.accessKey",
|
||||
command: this._onAddRule
|
||||
});
|
||||
|
||||
this.menuitemSources = createMenuItem(this._contextmenu, {
|
||||
label: "ruleView.contextmenu.showOrigSources",
|
||||
accesskey: "ruleView.contextmenu.showOrigSources.accessKey",
|
||||
@ -1360,6 +1435,23 @@ CssRuleView.prototype = {
|
||||
* appropriate.
|
||||
*/
|
||||
_contextMenuUpdate: function() {
|
||||
this._enableCopyMenuItems(this.doc.popupNode.parentNode);
|
||||
|
||||
this.menuitemAddRule.disabled = this.inspector.selection.isAnonymousNode();
|
||||
|
||||
this.menuitemShowMdnDocs.hidden = !this.enableMdnDocsTooltip ||
|
||||
!this.doc.popupNode.parentNode
|
||||
.classList.contains(PROPERTY_NAME_CLASS);
|
||||
|
||||
let showOrig = Services.prefs.getBoolPref(PREF_ORIG_SOURCES);
|
||||
this.menuitemSources.setAttribute("checked", showOrig);
|
||||
},
|
||||
|
||||
/**
|
||||
* Display the necessary copy context menu items depending on the clicked
|
||||
* node and selection in the rule view.
|
||||
*/
|
||||
_enableCopyMenuItems: function(target) {
|
||||
let win = this.doc.defaultView;
|
||||
|
||||
// Copy selection.
|
||||
@ -1382,18 +1474,31 @@ CssRuleView.prototype = {
|
||||
copy = false;
|
||||
}
|
||||
|
||||
this.menuitemCopy.hidden = !copy;
|
||||
this.menuitemCopyColor.hidden = !this._isColorPopup();
|
||||
this.menuitemCopyImageDataUrl.hidden = !this._isImageUrlPopup();
|
||||
this.menuitemCopy.disabled = !copy;
|
||||
|
||||
let showOrig = Services.prefs.getBoolPref(PREF_ORIG_SOURCES);
|
||||
this.menuitemSources.setAttribute("checked", showOrig);
|
||||
this.menuitemCopyLocation.hidden = true;
|
||||
this.menuitemCopyPropertyDeclaration.hidden = true;
|
||||
this.menuitemCopyPropertyName.hidden = true;
|
||||
this.menuitemCopyPropertyValue.hidden = true;
|
||||
this.menuitemCopySelector.hidden = true;
|
||||
|
||||
this.menuitemShowMdnDocs.hidden = !this.enableMdnDocsTooltip ||
|
||||
!this.doc.popupNode.parentNode
|
||||
.classList.contains(PROPERTY_NAME_CLASS);
|
||||
this._clickedNodeInfo = this.getNodeInfo(target);
|
||||
|
||||
this.menuitemAddRule.disabled = this.inspector.selection.isAnonymousNode();
|
||||
if (!this._clickedNodeInfo) {
|
||||
return;
|
||||
} else if (this._clickedNodeInfo.type == overlays.VIEW_NODE_PROPERTY_TYPE) {
|
||||
this.menuitemCopyPropertyDeclaration.hidden = false;
|
||||
this.menuitemCopyPropertyName.hidden = false;
|
||||
} else if (this._clickedNodeInfo.type == overlays.VIEW_NODE_VALUE_TYPE) {
|
||||
this.menuitemCopyPropertyDeclaration.hidden = false;
|
||||
this.menuitemCopyPropertyValue.hidden = false;
|
||||
} else if (this._clickedNodeInfo.type == overlays.VIEW_NODE_SELECTOR_TYPE) {
|
||||
this.menuitemCopySelector.hidden = false;
|
||||
} else if (this._clickedNodeInfo.type == overlays.VIEW_NODE_LOCATION_TYPE) {
|
||||
this.menuitemCopyLocation.hidden = false;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@ -1422,7 +1527,8 @@ CssRuleView.prototype = {
|
||||
enabled: prop.enabled,
|
||||
overridden: prop.overridden,
|
||||
pseudoElement: prop.rule.pseudoElement,
|
||||
sheetHref: prop.rule.domRule.href
|
||||
sheetHref: prop.rule.domRule.href,
|
||||
textProperty: prop
|
||||
};
|
||||
} else if (classes.contains("ruleview-propertyvalue") && prop) {
|
||||
type = overlays.VIEW_NODE_VALUE_TYPE;
|
||||
@ -1432,7 +1538,8 @@ CssRuleView.prototype = {
|
||||
enabled: prop.enabled,
|
||||
overridden: prop.overridden,
|
||||
pseudoElement: prop.rule.pseudoElement,
|
||||
sheetHref: prop.rule.domRule.href
|
||||
sheetHref: prop.rule.domRule.href,
|
||||
textProperty: prop
|
||||
};
|
||||
} else if (classes.contains("theme-link") &&
|
||||
!classes.contains("ruleview-rule-source") && prop) {
|
||||
@ -1444,12 +1551,19 @@ CssRuleView.prototype = {
|
||||
enabled: prop.enabled,
|
||||
overridden: prop.overridden,
|
||||
pseudoElement: prop.rule.pseudoElement,
|
||||
sheetHref: prop.rule.domRule.href
|
||||
sheetHref: prop.rule.domRule.href,
|
||||
textProperty: prop
|
||||
};
|
||||
} else if (classes.contains("ruleview-selector-unmatched") ||
|
||||
classes.contains("ruleview-selector-matched")) {
|
||||
classes.contains("ruleview-selector-matched") ||
|
||||
classes.contains("ruleview-selector")) {
|
||||
type = overlays.VIEW_NODE_SELECTOR_TYPE;
|
||||
value = node.textContent;
|
||||
value = node.offsetParent._ruleEditor.selectorText.textContent;
|
||||
} else if (classes.contains("ruleview-rule-source")) {
|
||||
type = overlays.VIEW_NODE_LOCATION_TYPE;
|
||||
let ruleEditor = node.offsetParent._ruleEditor;
|
||||
let rule = ruleEditor.rule;
|
||||
value = (rule.sheet && rule.sheet.href) ? rule.sheet.href : rule.title;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@ -1624,6 +1738,71 @@ CssRuleView.prototype = {
|
||||
clipboardHelper.copyString(message);
|
||||
}),
|
||||
|
||||
/**
|
||||
* Copy the rule source location of the current clicked node.
|
||||
*/
|
||||
_onCopyLocation: function() {
|
||||
if (!this._clickedNodeInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
clipboardHelper.copyString(this._clickedNodeInfo.value, this.doc);
|
||||
},
|
||||
|
||||
/**
|
||||
* Copy the rule property declaration of the current clicked node.
|
||||
*/
|
||||
_onCopyPropertyDeclaration: function() {
|
||||
if (!this._clickedNodeInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
let textProp = this._clickedNodeInfo.value.textProperty;
|
||||
clipboardHelper.copyString(textProp.stringifyProperty(), this.doc);
|
||||
},
|
||||
|
||||
/**
|
||||
* Copy the rule property name of the current clicked node.
|
||||
*/
|
||||
_onCopyPropertyName: function() {
|
||||
if (!this._clickedNodeInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
clipboardHelper.copyString(this._clickedNodeInfo.value.property, this.doc);
|
||||
},
|
||||
|
||||
/**
|
||||
* Copy the rule property value of the current clicked node.
|
||||
*/
|
||||
_onCopyPropertyValue: function() {
|
||||
if (!this._clickedNodeInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
clipboardHelper.copyString(this._clickedNodeInfo.value.value, this.doc);
|
||||
},
|
||||
|
||||
/**
|
||||
* Copy the rule of the current clicked node.
|
||||
*/
|
||||
_onCopyRule: function() {
|
||||
let ruleEditor = this.doc.popupNode.parentNode.offsetParent._ruleEditor;
|
||||
let rule = ruleEditor.rule;
|
||||
clipboardHelper.copyString(rule.stringifyRule(), this.doc);
|
||||
},
|
||||
|
||||
/**
|
||||
* Copy the rule selector of the current clicked node.
|
||||
*/
|
||||
_onCopySelector: function() {
|
||||
if (!this._clickedNodeInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
clipboardHelper.copyString(this._clickedNodeInfo.value, this.doc);
|
||||
},
|
||||
|
||||
/**
|
||||
* Toggle the original sources pref.
|
||||
*/
|
||||
@ -1831,16 +2010,43 @@ CssRuleView.prototype = {
|
||||
this.menuitemCopyColor = null;
|
||||
|
||||
// Destroy Copy Data URI menuitem.
|
||||
this.menuitemCopyImageDataUrl.removeEventListener("command", this._onCopyImageDataUrl);
|
||||
this.menuitemCopyImageDataUrl.removeEventListener("command",
|
||||
this._onCopyImageDataUrl);
|
||||
this.menuitemCopyImageDataUrl = null;
|
||||
|
||||
this.menuitemCopyLocation.removeEventListener("command",
|
||||
this._onCopyLocation);
|
||||
this.menuitemCopyLocation = null;
|
||||
|
||||
this.menuitemCopyPropertyDeclaration.removeEventListener("command",
|
||||
this._onCopyPropertyDeclaration);
|
||||
this.menuitemCopyPropertyDeclaration = null;
|
||||
|
||||
this.menuitemCopyPropertyName.removeEventListener("command",
|
||||
this._onCopyPropertyName);
|
||||
this.menuitemCopyPropertyName = null;
|
||||
|
||||
this.menuitemCopyPropertyValue.removeEventListener("command",
|
||||
this._onCopyPropertyValue);
|
||||
this.menuitemCopyPropertyValue = null;
|
||||
|
||||
this.menuitemCopyRule.removeEventListener("command",
|
||||
this._onCopyRule);
|
||||
this.menuitemCopyRule = null;
|
||||
|
||||
this.menuitemCopySelector.removeEventListener("command",
|
||||
this._onCopySelector);
|
||||
this.menuitemCopySelector = null;
|
||||
|
||||
this.menuitemSources.removeEventListener("command",
|
||||
this._onToggleOrigSources);
|
||||
this._onToggleOrigSources);
|
||||
this.menuitemSources = null;
|
||||
|
||||
this._clickedNodeInfo = null;
|
||||
|
||||
// Destroy the context menu.
|
||||
this._contextmenu.removeEventListener("popupshowing",
|
||||
this._contextMenuUpdate);
|
||||
this._contextMenuUpdate);
|
||||
this._contextmenu.parentNode.removeChild(this._contextmenu);
|
||||
this._contextmenu = null;
|
||||
}
|
||||
@ -3628,8 +3834,12 @@ 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));
|
||||
|
||||
if (aAttributes.accesskey) {
|
||||
item.setAttribute("accesskey",
|
||||
_strings.GetStringFromName(aAttributes.accesskey));
|
||||
}
|
||||
|
||||
item.addEventListener("command", aAttributes.command);
|
||||
|
||||
if (aAttributes.type) {
|
||||
@ -3641,6 +3851,11 @@ function createMenuItem(aMenu, aAttributes) {
|
||||
return item;
|
||||
}
|
||||
|
||||
function createMenuSeparator(aMenu) {
|
||||
let separator = aMenu.ownerDocument.createElementNS(XUL_NS, "menuseparator");
|
||||
aMenu.appendChild(separator);
|
||||
}
|
||||
|
||||
function setTimeout() {
|
||||
let window = Services.appShell.hiddenDOMWindow;
|
||||
return window.setTimeout.apply(window, arguments);
|
||||
@ -3795,6 +4010,10 @@ XPCOMUtils.defineLazyGetter(this, "clipboardHelper", function() {
|
||||
.getService(Ci.nsIClipboardHelper);
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "osString", function() {
|
||||
return Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "_strings", function() {
|
||||
return Services.strings.createBundle(
|
||||
"chrome://global/locale/devtools/styleinspector.properties");
|
||||
|
@ -37,6 +37,7 @@ const VIEW_NODE_SELECTOR_TYPE = exports.VIEW_NODE_SELECTOR_TYPE = 1;
|
||||
const VIEW_NODE_PROPERTY_TYPE = exports.VIEW_NODE_PROPERTY_TYPE = 2;
|
||||
const VIEW_NODE_VALUE_TYPE = exports.VIEW_NODE_VALUE_TYPE = 3;
|
||||
const VIEW_NODE_IMAGE_URL_TYPE = exports.VIEW_NODE_IMAGE_URL_TYPE = 4;
|
||||
const VIEW_NODE_LOCATION_TYPE = exports.VIEW_NODE_LOCATION_TYPE = 5;
|
||||
|
||||
/**
|
||||
* Manages all highlighters in the style-inspector.
|
||||
|
@ -9,6 +9,8 @@ support-files =
|
||||
doc_content_stylesheet_linked.css
|
||||
doc_content_stylesheet_script.css
|
||||
doc_content_stylesheet_xul.css
|
||||
doc_copystyles.css
|
||||
doc_copystyles.html
|
||||
doc_filter.html
|
||||
doc_frame_script.js
|
||||
doc_keyframeanimation.html
|
||||
@ -76,6 +78,7 @@ skip-if = e10s # Bug 1039528: "inspect element" contextual-menu doesn't work wit
|
||||
[browser_ruleview_context-menu-show-mdn-docs-01.js]
|
||||
[browser_ruleview_context-menu-show-mdn-docs-02.js]
|
||||
[browser_ruleview_context-menu-show-mdn-docs-03.js]
|
||||
[browser_ruleview_copy_styles.js]
|
||||
[browser_ruleview_cubicbezier-appears-on-swatch-click.js]
|
||||
[browser_ruleview_cubicbezier-commit-on-ENTER.js]
|
||||
[browser_ruleview_cubicbezier-revert-on-ESC.js]
|
||||
|
@ -0,0 +1,246 @@
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Tests the behaviour of the copy styles context menu items in the rule
|
||||
* view
|
||||
*/
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "osString", function() {
|
||||
return Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS;
|
||||
});
|
||||
|
||||
let TEST_URI = TEST_URL_ROOT + "doc_copystyles.html";
|
||||
|
||||
add_task(function*() {
|
||||
yield addTab(TEST_URI);
|
||||
let { inspector, view } = yield openRuleView();
|
||||
|
||||
yield selectNode("#testid", inspector);
|
||||
|
||||
let ruleEditor = getRuleViewRuleEditor(view, 1);
|
||||
|
||||
let data = [
|
||||
{
|
||||
desc: "Test Copy Property Name",
|
||||
node: ruleEditor.rule.textProps[0].editor.nameSpan,
|
||||
menuItem: view.menuitemCopyPropertyName,
|
||||
expectedPattern: "color",
|
||||
hidden: {
|
||||
copyLocation: true,
|
||||
copyPropertyDeclaration: false,
|
||||
copyPropertyName: false,
|
||||
copyPropertyValue: true,
|
||||
copySelector: true,
|
||||
copyRule: false
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "Test Copy Property Value",
|
||||
node: ruleEditor.rule.textProps[2].editor.valueSpan,
|
||||
menuItem: view.menuitemCopyPropertyValue,
|
||||
expectedPattern: "12px",
|
||||
hidden: {
|
||||
copyLocation: true,
|
||||
copyPropertyDeclaration: false,
|
||||
copyPropertyName: true,
|
||||
copyPropertyValue: false,
|
||||
copySelector: true,
|
||||
copyRule: false
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "Test Copy Property Declaration",
|
||||
node: ruleEditor.rule.textProps[2].editor.nameSpan,
|
||||
menuItem: view.menuitemCopyPropertyDeclaration,
|
||||
expectedPattern: "font-size: 12px;",
|
||||
hidden: {
|
||||
copyLocation: true,
|
||||
copyPropertyDeclaration: false,
|
||||
copyPropertyName: false,
|
||||
copyPropertyValue: true,
|
||||
copySelector: true,
|
||||
copyRule: false
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "Test Copy Rule",
|
||||
node: ruleEditor.rule.textProps[2].editor.nameSpan,
|
||||
menuItem: view.menuitemCopyRule,
|
||||
expectedPattern: "#testid {[\\r\\n]+" +
|
||||
"\tcolor: #F00;[\\r\\n]+" +
|
||||
"\tbackground-color: #00F;[\\r\\n]+" +
|
||||
"\tfont-size: 12px;[\\r\\n]+" +
|
||||
"}",
|
||||
hidden: {
|
||||
copyLocation: true,
|
||||
copyPropertyDeclaration: false,
|
||||
copyPropertyName: false,
|
||||
copyPropertyValue: true,
|
||||
copySelector: true,
|
||||
copyRule: false
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "Test Copy Selector",
|
||||
node: ruleEditor.selectorText,
|
||||
menuItem: view.menuitemCopySelector,
|
||||
expectedPattern: "html, body, #testid",
|
||||
hidden: {
|
||||
copyLocation: true,
|
||||
copyPropertyDeclaration: true,
|
||||
copyPropertyName: true,
|
||||
copyPropertyValue: true,
|
||||
copySelector: false,
|
||||
copyRule: false
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "Test Copy Location",
|
||||
node: ruleEditor.source,
|
||||
menuItem: view.menuitemCopyLocation,
|
||||
expectedPattern: "http://example.com/browser/browser/devtools/" +
|
||||
"styleinspector/test/doc_copystyles.css",
|
||||
hidden: {
|
||||
copyLocation: false,
|
||||
copyPropertyDeclaration: true,
|
||||
copyPropertyName: true,
|
||||
copyPropertyValue: true,
|
||||
copySelector: true,
|
||||
copyRule: false
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: function*() {
|
||||
yield disableProperty(view);
|
||||
},
|
||||
desc: "Test Copy Rule with Disabled Property",
|
||||
node: ruleEditor.rule.textProps[2].editor.nameSpan,
|
||||
menuItem: view.menuitemCopyRule,
|
||||
expectedPattern: "#testid {[\\r\\n]+" +
|
||||
"\t\/\\* color: #F00; \\*\/[\\r\\n]+" +
|
||||
"\tbackground-color: #00F;[\\r\\n]+" +
|
||||
"\tfont-size: 12px;[\\r\\n]+" +
|
||||
"}",
|
||||
hidden: {
|
||||
copyLocation: true,
|
||||
copyPropertyDeclaration: false,
|
||||
copyPropertyName: false,
|
||||
copyPropertyValue: true,
|
||||
copySelector: true,
|
||||
copyRule: false
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "Test Copy Property Declaration with Disabled Property",
|
||||
node: ruleEditor.rule.textProps[0].editor.nameSpan,
|
||||
menuItem: view.menuitemCopyPropertyDeclaration,
|
||||
expectedPattern: "\/\\* color: #F00; \\*\/",
|
||||
hidden: {
|
||||
copyLocation: true,
|
||||
copyPropertyDeclaration: false,
|
||||
copyPropertyName: false,
|
||||
copyPropertyValue: true,
|
||||
copySelector: true,
|
||||
copyRule: false
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
for (let { setup, desc, node, menuItem, expectedPattern, hidden } of data) {
|
||||
if (setup) {
|
||||
yield setup();
|
||||
}
|
||||
|
||||
info(desc);
|
||||
yield checkCopyStyle(view, node, menuItem, expectedPattern, hidden);
|
||||
}
|
||||
});
|
||||
|
||||
function* checkCopyStyle(view, node, menuItem, expectedPattern, hidden) {
|
||||
let win = view.doc.defaultView;
|
||||
|
||||
let onPopup = once(view._contextmenu, "popupshown");
|
||||
EventUtils.synthesizeMouseAtCenter(node,
|
||||
{button: 2, type: "contextmenu"}, win);
|
||||
yield onPopup;
|
||||
|
||||
is(view.menuitemCopy.hidden, true, "Copy hidden is as expected: true");
|
||||
|
||||
is(view.menuitemCopyLocation.hidden,
|
||||
hidden.copyLocation,
|
||||
"Copy Location hidden attribute is as expected: " +
|
||||
hidden.copyLocation);
|
||||
|
||||
is(view.menuitemCopyPropertyDeclaration.hidden,
|
||||
hidden.copyPropertyDeclaration,
|
||||
"Copy Property Declaration hidden attribute is as expected: " +
|
||||
hidden.copyPropertyDeclaration);
|
||||
|
||||
is(view.menuitemCopyPropertyName.hidden,
|
||||
hidden.copyPropertyName,
|
||||
"Copy Property Name hidden attribute is as expected: " +
|
||||
hidden.copyPropertyName);
|
||||
|
||||
is(view.menuitemCopyPropertyValue.hidden,
|
||||
hidden.copyPropertyValue,
|
||||
"Copy Property Value hidden attribute is as expected: " +
|
||||
hidden.copyPropertyValue);
|
||||
|
||||
is(view.menuitemCopySelector.hidden,
|
||||
hidden.copySelector,
|
||||
"Copy Selector hidden attribute is as expected: " +
|
||||
hidden.copySelector);
|
||||
|
||||
is(view.menuitemCopyRule.hidden,
|
||||
hidden.copyRule,
|
||||
"Copy Rule hidden attribute is as expected: " +
|
||||
hidden.copyRule);
|
||||
|
||||
try {
|
||||
yield waitForClipboard(() => menuItem.click(),
|
||||
() => checkClipboardData(expectedPattern));
|
||||
} catch(e) {
|
||||
failedClipboard(expectedPattern);
|
||||
}
|
||||
|
||||
view._contextmenu.hidePopup();
|
||||
}
|
||||
|
||||
function* disableProperty(view) {
|
||||
let ruleEditor = getRuleViewRuleEditor(view, 1);
|
||||
let propEditor = ruleEditor.rule.textProps[0].editor;
|
||||
|
||||
info("Disabling a property");
|
||||
propEditor.enable.click();
|
||||
yield ruleEditor.rule._applyingModifications;
|
||||
}
|
||||
|
||||
function checkClipboardData(expectedPattern) {
|
||||
let actual = SpecialPowers.getClipboardData("text/unicode");
|
||||
let expectedRegExp = new RegExp(expectedPattern, "g");
|
||||
return expectedRegExp.test(actual);
|
||||
}
|
||||
|
||||
function failedClipboard(expectedPattern) {
|
||||
// Format expected text for comparison
|
||||
let terminator = osString == "WINNT" ? "\r\n" : "\n";
|
||||
expectedPattern = expectedPattern.replace(/\[\\r\\n\][+*]/g, terminator);
|
||||
expectedPattern = expectedPattern.replace(/\\\(/g, "(");
|
||||
expectedPattern = expectedPattern.replace(/\\\)/g, ")");
|
||||
|
||||
let actual = SpecialPowers.getClipboardData("text/unicode");
|
||||
|
||||
// Trim the right hand side of our strings. This is because expectedPattern
|
||||
// accounts for windows sometimes adding a newline to our copied data.
|
||||
expectedPattern = expectedPattern.trimRight();
|
||||
actual = actual.trimRight();
|
||||
|
||||
ok(false, "Clipboard text does not match expected " +
|
||||
"results (escaped for accurate comparison):\n");
|
||||
info("Actual: " + escape(actual));
|
||||
info("Expected: " + escape(expectedPattern));
|
||||
}
|
@ -33,8 +33,7 @@ add_task(function*() {
|
||||
'</div>';
|
||||
content.document.title = "Rule view context menu test";
|
||||
|
||||
info("Opening the computed view");
|
||||
let {toolbox, inspector, view} = yield openRuleView();
|
||||
let {inspector, view} = yield openRuleView();
|
||||
|
||||
info("Selecting the test node");
|
||||
yield selectNode("div", inspector);
|
||||
@ -43,17 +42,18 @@ add_task(function*() {
|
||||
yield checkSelectAll(view);
|
||||
});
|
||||
|
||||
function checkCopySelection(view) {
|
||||
function* checkCopySelection(view) {
|
||||
info("Testing selection copy");
|
||||
|
||||
let contentDoc = view.doc;
|
||||
let win = contentDoc.defaultView;
|
||||
let prop = contentDoc.querySelector(".ruleview-property");
|
||||
let values = contentDoc.querySelectorAll(".ruleview-propertyvaluecontainer");
|
||||
|
||||
let range = contentDoc.createRange();
|
||||
range.setStart(prop, 0);
|
||||
range.setEnd(values[4], 2);
|
||||
let selection = view.doc.defaultView.getSelection().addRange(range);
|
||||
view.doc.defaultView.getSelection().addRange(range);
|
||||
|
||||
info("Checking that _Copy() returns the correct clipboard value");
|
||||
|
||||
@ -65,19 +65,28 @@ function checkCopySelection(view) {
|
||||
"html {[\\r\\n]+" +
|
||||
" color: #000;[\\r\\n]*";
|
||||
|
||||
return waitForClipboard(() => {
|
||||
fireCopyEvent(prop);
|
||||
}, () => {
|
||||
return checkClipboardData(expectedPattern);
|
||||
}).then(() => {}, () => {
|
||||
let onPopup = once(view._contextmenu, "popupshown");
|
||||
EventUtils.synthesizeMouseAtCenter(prop,
|
||||
{button: 2, type: "contextmenu"}, win);
|
||||
yield onPopup;
|
||||
|
||||
ok(!view.menuitemCopy.hidden, "Copy menu item is not hidden as expected");
|
||||
|
||||
try {
|
||||
yield waitForClipboard(() => view.menuitemCopy.click(),
|
||||
() => checkClipboardData(expectedPattern));
|
||||
} catch(e) {
|
||||
failedClipboard(expectedPattern);
|
||||
});
|
||||
}
|
||||
|
||||
view._contextmenu.hidePopup();
|
||||
}
|
||||
|
||||
function checkSelectAll(view) {
|
||||
function* checkSelectAll(view) {
|
||||
info("Testing select-all copy");
|
||||
|
||||
let contentDoc = view.doc;
|
||||
let win = contentDoc.defaultView;
|
||||
let prop = contentDoc.querySelector(".ruleview-property");
|
||||
|
||||
info("Checking that _SelectAll() then copy returns the correct clipboard value");
|
||||
@ -93,13 +102,21 @@ function checkSelectAll(view) {
|
||||
" color: #000;[\\r\\n]+" +
|
||||
"}[\\r\\n]*";
|
||||
|
||||
return waitForClipboard(() => {
|
||||
fireCopyEvent(prop);
|
||||
}, () => {
|
||||
return checkClipboardData(expectedPattern);
|
||||
}).then(() => {}, () => {
|
||||
let onPopup = once(view._contextmenu, "popupshown");
|
||||
EventUtils.synthesizeMouseAtCenter(prop,
|
||||
{button: 2, type: "contextmenu"}, win);
|
||||
yield onPopup;
|
||||
|
||||
ok(!view.menuitemCopy.hidden, "Copy menu item is not hidden as expected");
|
||||
|
||||
try {
|
||||
yield waitForClipboard(() => view.menuitemCopy.click(),
|
||||
() => checkClipboardData(expectedPattern));
|
||||
} catch(e) {
|
||||
failedClipboard(expectedPattern);
|
||||
});
|
||||
}
|
||||
|
||||
view._contextmenu.hidePopup();
|
||||
}
|
||||
|
||||
function checkClipboardData(expectedPattern) {
|
||||
|
9
browser/devtools/styleinspector/test/doc_copystyles.css
Normal file
9
browser/devtools/styleinspector/test/doc_copystyles.css
Normal file
@ -0,0 +1,9 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
html, body, #testid {
|
||||
color: #F00;
|
||||
background-color: #00F;
|
||||
font-size: 12px;
|
||||
}
|
11
browser/devtools/styleinspector/test/doc_copystyles.html
Normal file
11
browser/devtools/styleinspector/test/doc_copystyles.html
Normal file
@ -0,0 +1,11 @@
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<html>
|
||||
<head>
|
||||
<title>Test case for copying stylesheet in rule-view</title>
|
||||
<link rel="stylesheet" type="text/css" href="doc_copystyles.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<div id='testid'>Styled Node</div>
|
||||
</body>
|
||||
</html>
|
@ -112,7 +112,7 @@ styleinspector.copyImageDataUrlError=Failed to copy image Data-URL
|
||||
|
||||
# LOCALIZATION NOTE (ruleView.contextmenu.showOrigSources): Text displayed in the rule view
|
||||
# context menu.
|
||||
ruleView.contextmenu.showOrigSources=Show original sources
|
||||
ruleView.contextmenu.showOrigSources=Show Original Sources
|
||||
|
||||
# LOCALIZATION NOTE (ruleView.contextmenu.showOrigSources.accessKey): Access key for
|
||||
# the rule view context menu "Show original sources" entry.
|
||||
@ -120,7 +120,7 @@ ruleView.contextmenu.showOrigSources.accessKey=O
|
||||
|
||||
# LOCALIZATION NOTE (ruleView.contextmenu.showMdnDocs): Text displayed in the rule view
|
||||
# context menu to display docs from MDN for an item.
|
||||
ruleView.contextmenu.showMdnDocs=Show MDN docs
|
||||
ruleView.contextmenu.showMdnDocs=Show MDN Docs
|
||||
|
||||
# LOCALIZATION NOTE (ruleView.contextmenu.showMdnDocs.accessKey): Access key for
|
||||
# the rule view context menu "Show MDN docs" entry.
|
||||
@ -129,7 +129,7 @@ ruleView.contextmenu.showMdnDocs.accessKey=D
|
||||
# LOCALIZATION NOTE (ruleView.contextmenu.addNewRule): Text displayed in the
|
||||
# rule view context menu for adding a new rule to the element.
|
||||
# This should match addRuleButton.tooltip in styleinspector.dtd
|
||||
ruleView.contextmenu.addNewRule=Add new rule
|
||||
ruleView.contextmenu.addNewRule=Add New Rule
|
||||
|
||||
# LOCALIZATION NOTE (ruleView.contextmenu.addRule.accessKey): Access key for
|
||||
# the rule view context menu "Add rule" entry.
|
||||
@ -137,7 +137,7 @@ ruleView.contextmenu.addNewRule.accessKey=R
|
||||
|
||||
# LOCALIZATION NOTE (computedView.contextmenu.selectAll): Text displayed in the
|
||||
# computed view context menu.
|
||||
computedView.contextmenu.selectAll=Select all
|
||||
computedView.contextmenu.selectAll=Select All
|
||||
|
||||
# LOCALIZATION NOTE (computedView.contextmenu.selectAll.accessKey): Access key for
|
||||
# the computed view context menu "Select all" entry.
|
||||
@ -150,3 +150,27 @@ computedView.contextmenu.copy=Copy
|
||||
# LOCALIZATION NOTE (computedView.contextmenu.copy.accessKey): Access key for
|
||||
# the computed view context menu "Copy" entry.
|
||||
computedView.contextmenu.copy.accessKey=C
|
||||
|
||||
# LOCALIZATION NOTE (ruleView.contextmenu.copyLocation): Text displayed in the
|
||||
# rule view context menu for copying the source location.
|
||||
ruleView.contextmenu.copyLocation=Copy Location
|
||||
|
||||
# LOCALIZATION NOTE (ruleView.contextmenu.copyPropertyDeclaration): Text
|
||||
# displayed in the rule view context menu for copying the property declaration.
|
||||
ruleView.contextmenu.copyPropertyDeclaration=Copy Property Declaration
|
||||
|
||||
# LOCALIZATION NOTE (ruleView.contextmenu.copyPropertyName): Text displayed in
|
||||
# the rule view context menu for copying the property name.
|
||||
ruleView.contextmenu.copyPropertyName=Copy Property Name
|
||||
|
||||
# LOCALIZATION NOTE (ruleView.contextmenu.copyPropertyValue): Text displayed in
|
||||
# the rule view context menu for copying the property value.
|
||||
ruleView.contextmenu.copyPropertyValue=Copy Property Value
|
||||
|
||||
# LOCALIZATION NOTE (ruleView.contextmenu.copyRule): Text displayed in the
|
||||
# rule view context menu for copying the rule.
|
||||
ruleView.contextmenu.copyRule=Copy Rule
|
||||
|
||||
# LOCALIZATION NOTE (ruleView.contextmenu.copySelector): Text displayed in the
|
||||
# rule view context menu for copying the selector.
|
||||
ruleView.contextmenu.copySelector=Copy Selector
|
||||
|
Loading…
Reference in New Issue
Block a user