зеркало из https://github.com/mozilla/gecko-dev.git
Bug 740615 - Move rule view copy code into CssRuleView.jsm. r=paul
This commit is contained in:
Родитель
41a9d47cb4
Коммит
0593335323
|
@ -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() {
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
@ -762,7 +806,7 @@ CssRuleView.prototype = {
|
|||
this._clearRules();
|
||||
this._elementStyle.populate();
|
||||
this._createEditors();
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* Clear the rules.
|
||||
|
@ -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)
|
||||
|
|
Загрузка…
Ссылка в новой задаче