Bug 1143742 - part4: add textarea to valid targets when copying;r=gl
When opening the context menu (and displaying the "copy" menu entry)
or when receiving a copy event, we now check if the current target
is a textarea. (multiline inplace editor relies on textarea)
Modified existing test to check this new use case.
MozReview-Commit-ID: Cgm67JCdN4c
--- a/devtools/client/inspector/rules/rules.js
+++ b/devtools/client/inspector/rules/rules.js
@@ -457,17 +457,18 @@ CssRuleView.prototype = {
*
* @param {DOMNode} target
* DOMNode target of the copy action
*/
copySelection: function(target) {
try {
let text = "";
- if (target && target.nodeName === "input") {
+ let nodeName = target && target.nodeName;
+ if (nodeName === "input" || nodeName == "textarea") {
let start = Math.min(target.selectionStart, target.selectionEnd);
let end = Math.max(target.selectionStart, target.selectionEnd);
let count = end - start;
text = target.value.substr(start, count);
} else {
text = this.styleWindow.getSelection().toString();
// Remove any double newlines.
--- a/devtools/client/inspector/rules/test/browser_rules_select-and-copy-styles.js
+++ b/devtools/client/inspector/rules/test/browser_rules_select-and-copy-styles.js
@@ -39,16 +39,17 @@ const TEST_URI = `
`;
add_task(function*() {
yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
let {inspector, view} = yield openRuleView();
yield selectNode("div", inspector);
yield checkCopySelection(view);
yield checkSelectAll(view);
+ yield checkCopyEditorValue(view);
});
function* checkCopySelection(view) {
info("Testing selection copy");
let contentDoc = view.styleDocument;
let win = view.styleWindow;
let prop = contentDoc.querySelector(".ruleview-property");
@@ -70,17 +71,17 @@ function* checkCopySelection(view) {
" color: #000000;[\\r\\n]*";
let onPopup = once(view._contextmenu._menupopup, "popupshown");
EventUtils.synthesizeMouseAtCenter(prop,
{button: 2, type: "contextmenu"}, win);
yield onPopup;
ok(!view._contextmenu.menuitemCopy.hidden,
- "Copy menu item is not hidden as expected");
+ "Copy menu item is displayed as expected");
try {
yield waitForClipboard(() => view._contextmenu.menuitemCopy.click(),
() => checkClipboardData(expectedPattern));
} catch (e) {
failedClipboard(expectedPattern);
}
@@ -108,28 +109,66 @@ function* checkSelectAll(view) {
"}[\\r\\n]*";
let onPopup = once(view._contextmenu._menupopup, "popupshown");
EventUtils.synthesizeMouseAtCenter(prop,
{button: 2, type: "contextmenu"}, win);
yield onPopup;
ok(!view._contextmenu.menuitemCopy.hidden,
- "Copy menu item is not hidden as expected");
+ "Copy menu item is displayed as expected");
try {
yield waitForClipboard(() => view._contextmenu.menuitemCopy.click(),
() => checkClipboardData(expectedPattern));
} catch (e) {
failedClipboard(expectedPattern);
}
view._contextmenu._menupopup.hidePopup();
}
+function* checkCopyEditorValue(view) {
+ info("Testing CSS property editor value copy");
+
+ let win = view.styleWindow;
+ let ruleEditor = getRuleViewRuleEditor(view, 0);
+ let propEditor = ruleEditor.rule.textProps[0].editor;
+
+ let editor = yield focusEditableField(view, propEditor.valueSpan);
+
+ info("Checking that copying a css property value editor returns the correct" +
+ " clipboard value");
+
+ let expectedPattern = "10em";
+
+ let onPopup = once(view._contextmenu._menupopup, "popupshown");
+ EventUtils.synthesizeMouseAtCenter(editor.input,
+ {button: 2, type: "contextmenu"}, win);
+ yield onPopup;
+
+ ok(!view._contextmenu.menuitemCopy.hidden,
+ "Copy menu item is displayed as expected");
+
+ try {
+ yield waitForClipboard(() => view._contextmenu.menuitemCopy.click(),
+ () => checkClipboardData(expectedPattern));
+ } catch (e) {
+ failedClipboard(expectedPattern);
+ }
+
+ view._contextmenu._menupopup.hidePopup();
+
+ // The value field is still focused. Blur it now and wait for the
+ // ruleview-changed event to avoid pending requests.
+ let onRuleViewChanged = view.once("ruleview-changed");
+ EventUtils.synthesizeKey("VK_ESCAPE", {});
+ yield onRuleViewChanged;
+}
+
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
--- a/devtools/client/inspector/shared/style-inspector-menu.js
+++ b/devtools/client/inspector/shared/style-inspector-menu.js
@@ -271,18 +271,17 @@ StyleInspectorMenu.prototype = {
}
},
_hasTextSelected: function() {
let hasTextSelected;
let selection = this.styleWindow.getSelection();
let node = this._getClickedNode();
- if (node.nodeName == "input") {
- // input type="text"
+ if (node.nodeName == "input" || node.nodeName == "textarea") {
let { selectionStart, selectionEnd } = node;
hasTextSelected = isFinite(selectionStart) && isFinite(selectionEnd)
&& selectionStart !== selectionEnd;
} else {
hasTextSelected = selection.toString() && !selection.isCollapsed;
}
return hasTextSelected;