Bug 1225063 - add option (devtools.markup.collapseAttributes) to enable/disable attribute collapsing from settings panel;r=bgrins
--- a/devtools/client/framework/toolbox-options.xul
+++ b/devtools/client/framework/toolbox-options.xul
@@ -42,16 +42,19 @@
tooltiptext="&options.enablePersistentLogs.tooltip;"
data-pref="devtools.webconsole.persistlog"/>
</vbox>
<label>&options.context.inspector;</label>
<vbox id="inspector-options" class="options-groupbox">
<checkbox label="&options.showUserAgentStyles.label;"
tooltiptext="&options.showUserAgentStyles.tooltip;"
data-pref="devtools.inspector.showUserAgentStyles"/>
+ <checkbox label="&options.collapseAttrs.label;"
+ tooltiptext="&options.collapseAttrs.tooltip;"
+ data-pref="devtools.markup.collapseAttributes"/>
<description>
<label control="defaultColorUnitMenuList"
accesskey="&options.defaultColorUnit.accesskey;"
>&options.defaultColorUnit.label;</label>
<hbox>
<menulist id="defaultColorUnitMenuList"
data-pref="devtools.defaultColorUnit">
<menupopup>
--- a/devtools/client/inspector/markup/markup.js
+++ b/devtools/client/inspector/markup/markup.js
@@ -15,16 +15,18 @@ const DEFAULT_MAX_CHILDREN = 100;
const COLLAPSE_DATA_URL_REGEX = /^data.+base64/;
const COLLAPSE_DATA_URL_LENGTH = 60;
const NEW_SELECTION_HIGHLIGHTER_TIMER = 1000;
const DRAG_DROP_AUTOSCROLL_EDGE_DISTANCE = 50;
const DRAG_DROP_MIN_AUTOSCROLL_SPEED = 5;
const DRAG_DROP_MAX_AUTOSCROLL_SPEED = 15;
const DRAG_DROP_MIN_INITIAL_DISTANCE = 10;
const AUTOCOMPLETE_POPUP_PANEL_ID = "markupview_autoCompletePopup";
+const ATTR_COLLAPSE_ENABLED_PREF = "devtools.markup.collapseAttributes";
+const ATTR_COLLAPSE_LENGTH_PREF = "devtools.markup.collapseAttributeLength";
const {UndoStack} = require("devtools/client/shared/undo");
const {editableField, InplaceEditor} =
require("devtools/client/shared/inplace-editor");
const {HTMLEditor} = require("devtools/client/inspector/markup/html-editor");
const promise = require("promise");
const {Tooltip} = require("devtools/client/shared/widgets/Tooltip");
const EventEmitter = require("devtools/shared/event-emitter");
@@ -32,16 +34,17 @@ const Heritage = require("sdk/core/herit
const {setTimeout, clearTimeout, setInterval, clearInterval} =
require("sdk/timers");
const {parseAttribute} =
require("devtools/client/shared/node-attribute-parser");
const ELLIPSIS = Services.prefs.getComplexValue("intl.ellipsis",
Ci.nsIPrefLocalizedString).data;
const {Task} = require("resource://gre/modules/Task.jsm");
const {scrollIntoViewIfNeeded} = require("devtools/shared/layout/utils");
+const {PrefObserver} = require("devtools/client/styleeditor/utils");
Cu.import("resource://devtools/shared/gcli/Templater.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
loader.lazyRequireGetter(this, "CSS", "CSS");
loader.lazyGetter(this, "DOMParser", () => {
return Cc["@mozilla.org/xmlextras/domparser;1"]
@@ -82,18 +85,20 @@ function MarkupView(inspector, frame, co
this.htmlEditor = new HTMLEditor(this.doc);
try {
this.maxChildren = Services.prefs.getIntPref("devtools.markup.pagesize");
} catch (ex) {
this.maxChildren = DEFAULT_MAX_CHILDREN;
}
+ this.collapseAttributes =
+ Services.prefs.getBoolPref(ATTR_COLLAPSE_ENABLED_PREF);
this.collapseAttributeLength =
- Services.prefs.getIntPref("devtools.markup.collapseAttributeLength");
+ Services.prefs.getIntPref(ATTR_COLLAPSE_LENGTH_PREF);
// Creating the popup to be used to show CSS suggestions.
let options = {
autoSelect: true,
theme: "auto",
// panelId option prevents the markupView autocomplete popup from
// sharing XUL elements with other views, such as ruleView (see Bug 1191093)
panelId: AUTOCOMPLETE_POPUP_PANEL_ID
@@ -113,16 +118,18 @@ function MarkupView(inspector, frame, co
this._onMouseUp = this._onMouseUp.bind(this);
this._onNewSelection = this._onNewSelection.bind(this);
this._onKeyDown = this._onKeyDown.bind(this);
this._onCopy = this._onCopy.bind(this);
this._onFocus = this._onFocus.bind(this);
this._onMouseMove = this._onMouseMove.bind(this);
this._onMouseLeave = this._onMouseLeave.bind(this);
this._onToolboxPickerHover = this._onToolboxPickerHover.bind(this);
+ this._onCollapseAttributesPrefChange =
+ this._onCollapseAttributesPrefChange.bind(this);
// Listening to various events.
this._elt.addEventListener("click", this._onMouseClick, false);
this._elt.addEventListener("mousemove", this._onMouseMove, false);
this._elt.addEventListener("mouseleave", this._onMouseLeave, false);
this.doc.body.addEventListener("mouseup", this._onMouseUp);
this.win.addEventListener("keydown", this._onKeyDown, false);
this.win.addEventListener("copy", this._onCopy);
@@ -130,16 +137,22 @@ function MarkupView(inspector, frame, co
this.walker.on("mutations", this._mutationObserver);
this.walker.on("display-change", this._onDisplayChange);
this._inspector.selection.on("new-node-front", this._onNewSelection);
this._inspector.toolbox.on("picker-node-hovered", this._onToolboxPickerHover);
this._onNewSelection();
this._initTooltips();
+ this._prefObserver = new PrefObserver("devtools.markup");
+ this._prefObserver.on(ATTR_COLLAPSE_ENABLED_PREF,
+ this._onCollapseAttributesPrefChange);
+ this._prefObserver.on(ATTR_COLLAPSE_LENGTH_PREF,
+ this._onCollapseAttributesPrefChange);
+
EventEmitter.decorate(this);
}
MarkupView.prototype = {
/**
* How long does a node flash when it mutates (in ms).
*/
CONTAINER_FLASHING_DURATION: 500,
@@ -262,16 +275,24 @@ MarkupView.prototype = {
_onMouseUp: function() {
this.indicateDropTarget(null);
this.indicateDragTarget(null);
if (this._autoScrollInterval) {
clearInterval(this._autoScrollInterval);
}
},
+ _onCollapseAttributesPrefChange: function() {
+ this.collapseAttributes =
+ Services.prefs.getBoolPref(ATTR_COLLAPSE_ENABLED_PREF);
+ this.collapseAttributeLength =
+ Services.prefs.getIntPref(ATTR_COLLAPSE_LENGTH_PREF);
+ this.update();
+ },
+
cancelDragging: function() {
if (!this.isDragging) {
return;
}
for (let [, container] of this._containers) {
if (container.isDragging) {
container.cancelDragging();
@@ -1587,16 +1608,22 @@ MarkupView.prototype = {
this.win.removeEventListener("copy", this._onCopy);
this._frame.removeEventListener("focus", this._onFocus, false);
this.walker.off("mutations", this._mutationObserver);
this.walker.off("display-change", this._onDisplayChange);
this._inspector.selection.off("new-node-front", this._onNewSelection);
this._inspector.toolbox.off("picker-node-hovered",
this._onToolboxPickerHover);
+ this._prefObserver.off(ATTR_COLLAPSE_ENABLED_PREF,
+ this._onCollapseAttributesPrefChange);
+ this._prefObserver.off(ATTR_COLLAPSE_LENGTH_PREF,
+ this._onCollapseAttributesPrefChange);
+ this._prefObserver.destroy();
+
this._elt = null;
for (let [, container] of this._containers) {
container.destroy();
}
this._containers = null;
this.tooltip.destroy();
@@ -2682,17 +2709,17 @@ ElementEditor.prototype = {
}
}
// Only loop through the current attributes on the node. Missing
// attributes have already been removed at this point.
for (let attr of nodeAttributes) {
let el = this.attrElements.get(attr.name);
let valueChanged = el &&
- el.querySelector(".attr-value").textContent !== attr.value;
+ el.dataset.value !== attr.value;
let isEditing = el && el.querySelector(".editable").inplaceEditor;
let canSimplyShowEditor = el && (!valueChanged || isEditing);
if (canSimplyShowEditor) {
// Element already exists and doesn't need to be recreated.
// Just show it (it's hidden by default due to the template).
el.style.removeProperty("display");
} else {
@@ -2868,19 +2895,19 @@ ElementEditor.prototype = {
this.node.tagName, attributes, attribute.name);
// Create links in the attribute value, and collapse long attributes if
// needed.
let collapse = value => {
if (value && value.match(COLLAPSE_DATA_URL_REGEX)) {
return truncateString(value, COLLAPSE_DATA_URL_LENGTH);
}
- return this.markup.collapseAttributeLength < 0
- ? value :
- truncateString(value, this.markup.collapseAttributeLength);
+ return this.markup.collapseAttributes
+ ? truncateString(value, this.markup.collapseAttributeLength)
+ : value;
};
val.innerHTML = "";
for (let token of parsedLinksData) {
if (token.type === "string") {
val.appendChild(this.doc.createTextNode(collapse(token.value)));
} else {
let link = this.doc.createElement("span");
--- a/devtools/client/inspector/markup/markup.xhtml
+++ b/devtools/client/inspector/markup/markup.xhtml
@@ -69,16 +69,17 @@
-->><!--
--></span><!--
--><div save="${eventNode}" class="markupview-events" data-event="true">ev</div><!--
--></span>
<span id="template-attribute"
save="${attr}"
data-attr="${attrName}"
+ data-value="${attrValue}"
class="attreditor"
style="display:none"> <!--
--><span class="editable" save="${inner}" tabindex="0"><!--
--><span save="${name}" class="attr-name theme-fg-color2"></span><!--
-->="<!--
--><span save="${val}" class="attr-value theme-fg-color6"></span><!--
-->"<!--
--></span><!--
--- a/devtools/client/inspector/markup/test/browser_markup_tag_edit_07.js
+++ b/devtools/client/inspector/markup/test/browser_markup_tag_edit_07.js
@@ -68,35 +68,58 @@ var TEST_DATA = [{
"src": DATA_URL_ATTRIBUTE
},
validate: (element, container, inspector) => {
let editor = container.editor;
let visibleAttrText = editor.attrElements.get("src").querySelector(".attr-value").textContent;
is (visibleAttrText, DATA_URL_ATTRIBUTE_COLLAPSED);
}
}, {
- desc: "Try to add long attribute with collapseAttributeLength == -1" +
+ desc: "Try to add long attribute with collapseAttributes == false" +
"to make sure it isn't collapsed in attribute editor.",
text: 'data-long="' + LONG_ATTRIBUTE + '"',
expectedAttributes: {
"data-long": LONG_ATTRIBUTE
},
setUp: function(inspector) {
- inspector.markup.collapseAttributeLength = -1;
+ Services.prefs.setBoolPref("devtools.markup.collapseAttributes", false);
},
validate: (element, container, inspector) => {
let editor = container.editor;
let visibleAttrText = editor.attrElements
.get("data-long")
.querySelector(".attr-value")
.textContent;
is(visibleAttrText, LONG_ATTRIBUTE);
},
tearDown: function(inspector) {
- inspector.markup.collapseAttributeLength = 120;
+ Services.prefs.clearUserPref("devtools.markup.collapseAttributes");
+ }
+}, {
+ desc: "Try to collapse attributes with collapseAttributeLength == 5",
+ text: 'data-long="' + LONG_ATTRIBUTE + '"',
+ expectedAttributes: {
+ "data-long": LONG_ATTRIBUTE
+ },
+ setUp: function(inspector) {
+ Services.prefs.setIntPref("devtools.markup.collapseAttributeLength", 2);
+ },
+ validate: (element, container, inspector) => {
+ let firstChar = LONG_ATTRIBUTE[0];
+ let lastChar = LONG_ATTRIBUTE[LONG_ATTRIBUTE.length - 1];
+ let collapsed = firstChar + "\u2026" + lastChar;
+ let editor = container.editor;
+ let visibleAttrText = editor.attrElements
+ .get("data-long")
+ .querySelector(".attr-value")
+ .textContent;
+ is(visibleAttrText, collapsed);
+ },
+ tearDown: function(inspector) {
+ Services.prefs.clearUserPref("devtools.markup.collapseAttributeLength");
}
}];
add_task(function*() {
let {inspector, testActor} = yield openInspectorForURL(TEST_URL);
yield runAddAttributesTests(TEST_DATA, "div", inspector, testActor);
});
--- a/devtools/client/locales/en-US/toolbox.dtd
+++ b/devtools/client/locales/en-US/toolbox.dtd
@@ -54,16 +54,22 @@ values from browser.dtd. -->
<!ENTITY options.context.inspector "Inspector">
<!-- LOCALIZATION NOTE (options.showUserAgentStyles.label): This is the label
- for the checkbox option to show user agent styles in the Inspector
- panel. -->
<!ENTITY options.showUserAgentStyles.label "Show Browser Styles">
<!ENTITY options.showUserAgentStyles.tooltip "Turning this on will show default styles that are loaded by the browser.">
+<!-- LOCALIZATION NOTE (options.collapseAttrs.label): This is the label
+ - for the checkbox option to enable collapse attributes in the Inspector
+ - panel. -->
+<!ENTITY options.collapseAttrs.label "Truncate DOM attributes">
+<!ENTITY options.collapseAttrs.tooltip "Truncate long attributes in the inspector">
+
<!-- LOCALIZATION NOTE (options.defaultColorUnit.label): This is the label for a
- dropdown list that controls the default color unit used in the inspector.
- This label is visible in the options panel. -->
<!ENTITY options.defaultColorUnit.label "Default color unit">
<!-- LOCALIZATION NOTE (options.defaultColorUnit.accesskey): This is the access
- key for a dropdown list that controls the default color unit used in the
- inspector. This is visible in the options panel. -->
--- a/devtools/client/preferences/devtools.js
+++ b/devtools/client/preferences/devtools.js
@@ -61,18 +61,20 @@ pref("devtools.inspector.show_pseudo_ele
pref("devtools.inspector.imagePreviewTooltipSize", 300);
// Enable user agent style inspection in rule-view
pref("devtools.inspector.showUserAgentStyles", false);
// Show all native anonymous content (like controls in <video> tags)
pref("devtools.inspector.showAllAnonymousContent", false);
// Enable the MDN docs tooltip
pref("devtools.inspector.mdnDocsTooltip.enabled", true);
-// Collapse attributes that are too long.
-// Use -1 to not collapse attributes at all.
+// Enable to collapse attributes that are too long.
+pref("devtools.markup.collapseAttributes", true);
+
+// Length to collapse attributes
pref("devtools.markup.collapseAttributeLength", 120);
// DevTools default color unit
pref("devtools.defaultColorUnit", "authored");
// Enable the Responsive UI tool
pref("devtools.responsiveUI.no-reload-notification", false);