зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1355064 - Build the markup-view DOM manually rather than with templater; r=jdescottes
MozReview-Commit-ID: LbULOa7UGq2 --HG-- extra : rebase_source : 6ccac31433e1cc7ad155cf1fbbd8a3c61d6b785b
This commit is contained in:
Родитель
f7f53449d6
Коммит
9015908958
|
@ -13,7 +13,6 @@ const nodeFilterConstants = require("devtools/shared/dom-node-filter-constants")
|
|||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
const {LocalizationHelper} = require("devtools/shared/l10n");
|
||||
const {PluralForm} = require("devtools/shared/plural-form");
|
||||
const {template} = require("devtools/shared/gcli/templater");
|
||||
const AutocompletePopup = require("devtools/client/shared/autocomplete-popup");
|
||||
const KeyShortcuts = require("devtools/client/shared/key-shortcuts");
|
||||
const {scrollIntoViewIfNeeded} = require("devtools/client/shared/scroll");
|
||||
|
@ -465,13 +464,6 @@ MarkupView.prototype = {
|
|||
return promise.all([onShown, this._briefBoxModelPromise.promise]);
|
||||
},
|
||||
|
||||
template: function (name, dest, options = {stack: "markup.xhtml"}) {
|
||||
let node = this.doc.getElementById("template-" + name).cloneNode(true);
|
||||
node.removeAttribute("id");
|
||||
template(node, dest, options);
|
||||
return node;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the MarkupContainer object for a given node, or undefined if
|
||||
* none exists.
|
||||
|
@ -1668,28 +1660,13 @@ MarkupView.prototype = {
|
|||
container.children.firstChild.remove();
|
||||
}
|
||||
|
||||
if (!(children.hasFirst && children.hasLast)) {
|
||||
let nodesCount = container.node.numChildren;
|
||||
let showAllString = PluralForm.get(nodesCount,
|
||||
INSPECTOR_L10N.getStr("markupView.more.showAll2"));
|
||||
let data = {
|
||||
showing: INSPECTOR_L10N.getStr("markupView.more.showing"),
|
||||
showAll: showAllString.replace("#1", nodesCount),
|
||||
allButtonClick: () => {
|
||||
container.maxChildren = -1;
|
||||
container.childrenDirty = true;
|
||||
this._updateChildren(container);
|
||||
}
|
||||
};
|
||||
|
||||
if (!children.hasFirst) {
|
||||
let span = this.template("more-nodes", data);
|
||||
fragment.insertBefore(span, fragment.firstChild);
|
||||
}
|
||||
if (!children.hasLast) {
|
||||
let span = this.template("more-nodes", data);
|
||||
fragment.appendChild(span);
|
||||
}
|
||||
if (!children.hasFirst) {
|
||||
let topItem = this.buildMoreNodesButtonMarkup(container);
|
||||
fragment.insertBefore(topItem, fragment.firstChild);
|
||||
}
|
||||
if (!children.hasLast) {
|
||||
let bottomItem = this.buildMoreNodesButtonMarkup(container);
|
||||
fragment.appendChild(bottomItem);
|
||||
}
|
||||
|
||||
container.children.appendChild(fragment);
|
||||
|
@ -1699,6 +1676,30 @@ MarkupView.prototype = {
|
|||
return updatePromise;
|
||||
},
|
||||
|
||||
buildMoreNodesButtonMarkup: function (container) {
|
||||
let elt = this.doc.createElement("li");
|
||||
elt.classList.add("more-nodes", "devtools-class-comment");
|
||||
|
||||
let label = this.doc.createElement("span");
|
||||
label.textContent = INSPECTOR_L10N.getStr("markupView.more.showing");
|
||||
elt.appendChild(label);
|
||||
|
||||
let button = this.doc.createElement("button");
|
||||
button.setAttribute("href", "#");
|
||||
let showAllString = PluralForm.get(container.node.numChildren,
|
||||
INSPECTOR_L10N.getStr("markupView.more.showAll2"));
|
||||
button.textContent = showAllString.replace("#1", container.node.numChildren);
|
||||
elt.appendChild(button);
|
||||
|
||||
button.addEventListener("click", () => {
|
||||
container.maxChildren = -1;
|
||||
container.childrenDirty = true;
|
||||
this._updateChildren(container);
|
||||
});
|
||||
|
||||
return elt;
|
||||
},
|
||||
|
||||
_waitForChildren: function () {
|
||||
if (!this._queuedChildUpdates) {
|
||||
return promise.resolve(undefined);
|
||||
|
|
|
@ -18,87 +18,8 @@
|
|||
src="chrome://devtools/content/sourceeditor/codemirror/codemirror.bundle.js"></script>
|
||||
</head>
|
||||
<body class="theme-body devtools-monospace" role="application">
|
||||
|
||||
<!-- NOTE THAT WE MAKE EXTENSIVE USE OF HTML COMMENTS IN THIS FILE IN ORDER -->
|
||||
<!-- TO MAKE SPANS READABLE WHILST AVOIDING SIGNIFICANT WHITESPACE -->
|
||||
|
||||
<div id="root-wrapper" role="presentation">
|
||||
<div id="root" role="presentation"></div>
|
||||
</div>
|
||||
<div id="templates" style="display:none">
|
||||
|
||||
<ul class="children">
|
||||
<li id="template-elementcontainer" save="${elt}" class="child collapsed" role="presentation">
|
||||
<div save="${tagLine}" id="${id}" class="tag-line" role="treeitem" aria-level="${level}" aria-grabbed="${isDragging}"><!--
|
||||
--><span save="${tagState}" class="tag-state" role="presentation"></span><!--
|
||||
--><span save="${expander}" class="theme-twisty expander" role="presentation"></span><!--
|
||||
--></div>
|
||||
<ul save="${children}" class="children" role="group"></ul>
|
||||
</li>
|
||||
|
||||
<li id="template-textcontainer" save="${elt}" class="child collapsed" role="presentation">
|
||||
<div save="${tagLine}" id="${id}" class="tag-line" role="treeitem" aria-level="${level}" aria-grabbed="${isDragging}"><span save="${tagState}" class="tag-state" role="presentation"></span></div>
|
||||
<ul save="${children}" class="children" role="group"></ul>
|
||||
</li>
|
||||
|
||||
<li id="template-readonlycontainer" save="${elt}" class="child collapsed" role="presentation">
|
||||
<div save="${tagLine}" id="${id}" class="tag-line" role="treeitem" aria-level="${level}" aria-grabbed="${isDragging}"><!--
|
||||
--><span save="${tagState}" class="tag-state" role="presentation"></span><!--
|
||||
--><span save="${expander}" class="theme-twisty expander" role="presentation"></span><!--
|
||||
--></div>
|
||||
<ul save="${children}" class="children" role="group"></ul>
|
||||
</li>
|
||||
|
||||
<li id="template-more-nodes"
|
||||
class="more-nodes devtools-class-comment"
|
||||
save="${elt}"><!--
|
||||
--><span>${showing}</span> <!--
|
||||
--><button href="#" onclick="${allButtonClick}">${showAll}</button>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<span id="template-generic" save="${elt}" class="editor"><span save="${tag}" class="tag"></span></span>
|
||||
|
||||
<span id="template-element" save="${elt}" class="editor"><!--
|
||||
--><span class="open"><<!--
|
||||
--><span save="${tag}" class="tag theme-fg-color3" tabindex="-1"></span><!--
|
||||
--><span save="${attrList}"></span><!--
|
||||
--><span save="${newAttr}" class="newattr" tabindex="-1"></span><!--
|
||||
--><span class="closing-bracket">></span><!--
|
||||
--></span><!--
|
||||
--><span class="close"></<!--
|
||||
--><span save="${closeTag}" class="tag theme-fg-color3"></span><!--
|
||||
-->><!--
|
||||
--></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="${tabindex}"><!--
|
||||
--><span save="${name}" class="attr-name theme-fg-color2"></span><!--
|
||||
-->="<!--
|
||||
--><span save="${val}" class="attr-value theme-fg-color6"></span><!--
|
||||
-->"<!--
|
||||
--></span><!--
|
||||
--></span>
|
||||
|
||||
<span id="template-text" save="${elt}" class="editor text"><!--
|
||||
--><pre save="${value}" style="display:inline-block; white-space: normal;" tabindex="-1"></pre><!--
|
||||
--></span>
|
||||
|
||||
<span id="template-comment"
|
||||
save="${elt}"
|
||||
class="editor comment theme-comment"><!--
|
||||
--><span><!--</span><!--
|
||||
--><pre save="${value}" style="display:inline-block; white-space: normal;" tabindex="-1"></pre><!--
|
||||
--><span>--></span><!--
|
||||
--></span>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -41,14 +41,12 @@ function ElementEditor(container, node) {
|
|||
this.container = container;
|
||||
this.node = node;
|
||||
this.markup = this.container.markup;
|
||||
this.template = this.markup.template.bind(this.markup);
|
||||
this.doc = this.markup.doc;
|
||||
this._cssProperties = getCssProperties(this.markup.toolbox);
|
||||
|
||||
this.attrElements = new Map();
|
||||
this.animationTimers = {};
|
||||
|
||||
// The templates will fill the following properties
|
||||
this.elt = null;
|
||||
this.tag = null;
|
||||
this.closeTag = null;
|
||||
|
@ -57,7 +55,7 @@ function ElementEditor(container, node) {
|
|||
this.closeElt = null;
|
||||
|
||||
// Create the main editor
|
||||
this.template("element", this);
|
||||
this.buildMarkup();
|
||||
|
||||
// Make the tag name editable (unless this is a remote node or
|
||||
// a document element)
|
||||
|
@ -117,6 +115,51 @@ function ElementEditor(container, node) {
|
|||
}
|
||||
|
||||
ElementEditor.prototype = {
|
||||
buildMarkup: function () {
|
||||
this.elt = this.doc.createElement("span");
|
||||
this.elt.classList.add("editor");
|
||||
|
||||
let open = this.doc.createElement("span");
|
||||
open.classList.add("open");
|
||||
open.appendChild(this.doc.createTextNode("<"));
|
||||
this.elt.appendChild(open);
|
||||
|
||||
this.tag = this.doc.createElement("span");
|
||||
this.tag.classList.add("tag", "theme-fg-color3");
|
||||
this.tag.setAttribute("tabindex", "-1");
|
||||
open.appendChild(this.tag);
|
||||
|
||||
this.attrList = this.doc.createElement("span");
|
||||
open.appendChild(this.attrList);
|
||||
|
||||
this.newAttr = this.doc.createElement("span");
|
||||
this.newAttr.classList.add("newattr");
|
||||
this.newAttr.setAttribute("tabindex", "-1");
|
||||
open.appendChild(this.newAttr);
|
||||
|
||||
let closingBracket = this.doc.createElement("span");
|
||||
closingBracket.classList.add("closing-bracket");
|
||||
closingBracket.textContent = ">";
|
||||
open.appendChild(closingBracket);
|
||||
|
||||
let close = this.doc.createElement("span");
|
||||
close.classList.add("close");
|
||||
close.appendChild(this.doc.createTextNode("</"));
|
||||
this.elt.appendChild(close);
|
||||
|
||||
this.closeTag = this.doc.createElement("span");
|
||||
this.closeTag.classList.add("tag", "theme-fg-color3");
|
||||
close.appendChild(this.closeTag);
|
||||
|
||||
close.appendChild(this.doc.createTextNode(">"));
|
||||
|
||||
this.eventNode = this.doc.createElement("div");
|
||||
this.eventNode.classList.add("markupview-events");
|
||||
this.eventNode.dataset.event = "true";
|
||||
this.eventNode.textContent = "ev";
|
||||
this.elt.appendChild(this.eventNode);
|
||||
},
|
||||
|
||||
set selected(value) {
|
||||
if (this.textEditor) {
|
||||
this.textEditor.selected = value;
|
||||
|
@ -188,7 +231,7 @@ ElementEditor.prototype = {
|
|||
|
||||
if (canSimplyShowEditor) {
|
||||
// Element already exists and doesn't need to be recreated.
|
||||
// Just show it (it's hidden by default due to the template).
|
||||
// Just show it (it's hidden by default).
|
||||
el.style.removeProperty("display");
|
||||
} else {
|
||||
// Create a new editor, because the value of an existing attribute
|
||||
|
@ -268,14 +311,32 @@ ElementEditor.prototype = {
|
|||
},
|
||||
|
||||
_createAttribute: function (attribute, before = null) {
|
||||
// Create the template editor, which will save some variables here.
|
||||
let data = {
|
||||
attrName: attribute.name,
|
||||
attrValue: attribute.value,
|
||||
tabindex: this.container.canFocus ? "0" : "-1",
|
||||
};
|
||||
this.template("attribute", data);
|
||||
let {attr, inner, name, val} = data;
|
||||
let attr = this.doc.createElement("span");
|
||||
attr.dataset.attr = attribute.name;
|
||||
attr.dataset.value = attribute.value;
|
||||
attr.classList.add("attreditor");
|
||||
attr.style.display = "none";
|
||||
|
||||
attr.appendChild(this.doc.createTextNode(" "));
|
||||
|
||||
let inner = this.doc.createElement("span");
|
||||
inner.classList.add("editable");
|
||||
inner.setAttribute("tabindex", this.container.canFocus ? "0" : "-1");
|
||||
attr.appendChild(inner);
|
||||
|
||||
let name = this.doc.createElement("span");
|
||||
name.classList.add("attr-name");
|
||||
name.classList.add("theme-fg-color2");
|
||||
inner.appendChild(name);
|
||||
|
||||
inner.appendChild(this.doc.createTextNode('="'));
|
||||
|
||||
let val = this.doc.createElement("span");
|
||||
val.classList.add("attr-value");
|
||||
val.classList.add("theme-fg-color6");
|
||||
inner.appendChild(val);
|
||||
|
||||
inner.appendChild(this.doc.createTextNode('"'));
|
||||
|
||||
// Double quotes need to be handled specially to prevent DOMParser failing.
|
||||
// name="v"a"l"u"e" when editing -> name='v"a"l"u"e"'
|
||||
|
|
|
@ -39,10 +39,11 @@ MarkupContainer.prototype = {
|
|||
* The markup view that owns this container.
|
||||
* @param {NodeFront} node
|
||||
* The node to display.
|
||||
* @param {String} templateID
|
||||
* Which template to render for this container
|
||||
* @param {String} type
|
||||
* The type of container to build. This can be either 'textcontainer',
|
||||
* 'readonlycontainer' or 'elementcontainer'.
|
||||
*/
|
||||
initialize: function (markupView, node, templateID) {
|
||||
initialize: function (markupView, node, type) {
|
||||
this.markup = markupView;
|
||||
this.node = node;
|
||||
this.undo = this.markup.undo;
|
||||
|
@ -50,13 +51,8 @@ MarkupContainer.prototype = {
|
|||
this.id = "treeitem-" + markupContainerID++;
|
||||
this.htmlElt = this.win.document.documentElement;
|
||||
|
||||
// The template will fill the following properties
|
||||
this.elt = null;
|
||||
this.expander = null;
|
||||
this.tagState = null;
|
||||
this.tagLine = null;
|
||||
this.children = null;
|
||||
this.markup.template(templateID, this);
|
||||
this.buildMarkup(type);
|
||||
|
||||
this.elt.container = this;
|
||||
|
||||
this._onMouseDown = this._onMouseDown.bind(this);
|
||||
|
@ -78,6 +74,37 @@ MarkupContainer.prototype = {
|
|||
this.updateIsDisplayed();
|
||||
},
|
||||
|
||||
buildMarkup: function (type) {
|
||||
this.elt = this.win.document.createElement("li");
|
||||
this.elt.classList.add("child", "collapsed");
|
||||
this.elt.setAttribute("role", "presentation");
|
||||
|
||||
this.tagLine = this.win.document.createElement("div");
|
||||
this.tagLine.setAttribute("id", this.id);
|
||||
this.tagLine.classList.add("tag-line");
|
||||
this.tagLine.setAttribute("role", "treeitem");
|
||||
this.tagLine.setAttribute("aria-level", this.level);
|
||||
this.tagLine.setAttribute("aria-grabbed", this.isDragging);
|
||||
this.elt.appendChild(this.tagLine);
|
||||
|
||||
this.tagState = this.win.document.createElement("span");
|
||||
this.tagState.classList.add("tag-state");
|
||||
this.tagState.setAttribute("role", "presentation");
|
||||
this.tagLine.appendChild(this.tagState);
|
||||
|
||||
if (type !== "textcontainer") {
|
||||
this.expander = this.win.document.createElement("span");
|
||||
this.expander.classList.add("theme-twisty", "expander");
|
||||
this.expander.setAttribute("role", "presentation");
|
||||
this.tagLine.appendChild(this.expander);
|
||||
}
|
||||
|
||||
this.children = this.win.document.createElement("ul");
|
||||
this.children.classList.add("children");
|
||||
this.children.setAttribute("role", "group");
|
||||
this.elt.appendChild(this.children);
|
||||
},
|
||||
|
||||
toString: function () {
|
||||
return "[MarkupContainer for " + this.node + "]";
|
||||
},
|
||||
|
@ -237,7 +264,7 @@ MarkupContainer.prototype = {
|
|||
* Set an appropriate DOM tree depth level for a node and its subtree.
|
||||
*/
|
||||
updateLevel: function () {
|
||||
// ARIA level should already be set when container template is rendered.
|
||||
// ARIA level should already be set when the container markup is created.
|
||||
let currentLevel = this.tagLine.getAttribute("aria-level");
|
||||
let newLevel = this.level;
|
||||
if (currentLevel === newLevel) {
|
||||
|
|
|
@ -12,9 +12,7 @@ const nodeConstants = require("devtools/shared/dom-node-constants");
|
|||
function ReadOnlyEditor(container, node) {
|
||||
this.container = container;
|
||||
this.markup = this.container.markup;
|
||||
this.template = this.markup.template.bind(this.markup);
|
||||
this.elt = null;
|
||||
this.template("generic", this);
|
||||
this.buildMarkup();
|
||||
|
||||
if (node.isPseudoElement) {
|
||||
this.tag.classList.add("theme-fg-color5");
|
||||
|
@ -28,8 +26,26 @@ function ReadOnlyEditor(container, node) {
|
|||
}
|
||||
|
||||
ReadOnlyEditor.prototype = {
|
||||
buildMarkup: function () {
|
||||
let doc = this.markup.doc;
|
||||
|
||||
this.elt = doc.createElement("span");
|
||||
this.elt.classList.add("editor");
|
||||
|
||||
this.tag = doc.createElement("span");
|
||||
this.tag.classList.add("tag");
|
||||
this.elt.appendChild(this.tag);
|
||||
},
|
||||
|
||||
destroy: function () {
|
||||
// We might be already destroyed.
|
||||
if (!this.elt) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.elt.remove();
|
||||
this.elt = null;
|
||||
this.tag = null;
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -20,17 +20,16 @@ const INSPECTOR_L10N =
|
|||
* The container owning this editor.
|
||||
* @param {DOMNode} node
|
||||
* The node being edited.
|
||||
* @param {String} templateId
|
||||
* The template id to use to build the editor.
|
||||
* @param {String} type
|
||||
* The type of editor to build. This can be either 'text' or 'comment'.
|
||||
*/
|
||||
function TextEditor(container, node, templateId) {
|
||||
function TextEditor(container, node, type) {
|
||||
this.container = container;
|
||||
this.markup = this.container.markup;
|
||||
this.node = node;
|
||||
this.template = this.markup.template.bind(templateId);
|
||||
this._selected = false;
|
||||
|
||||
this.markup.template(templateId, this);
|
||||
this.buildMarkup(type);
|
||||
|
||||
editableField({
|
||||
element: this.value,
|
||||
|
@ -63,6 +62,32 @@ function TextEditor(container, node, templateId) {
|
|||
}
|
||||
|
||||
TextEditor.prototype = {
|
||||
buildMarkup: function (type) {
|
||||
let doc = this.markup.doc;
|
||||
|
||||
this.elt = doc.createElement("span");
|
||||
this.elt.classList.add("editor", type);
|
||||
|
||||
if (type === "comment") {
|
||||
this.elt.classList.add("theme-comment");
|
||||
|
||||
let openComment = doc.createElement("span");
|
||||
openComment.textContent = "<!--";
|
||||
this.elt.appendChild(openComment);
|
||||
}
|
||||
|
||||
this.value = doc.createElement("pre");
|
||||
this.value.setAttribute("style", "display:inline-block;white-space: normal;");
|
||||
this.value.setAttribute("tabindex", "-1");
|
||||
this.elt.appendChild(this.value);
|
||||
|
||||
if (type === "comment") {
|
||||
let closeComment = doc.createElement("span");
|
||||
closeComment.textContent = "-->";
|
||||
this.elt.appendChild(closeComment);
|
||||
}
|
||||
},
|
||||
|
||||
get selected() {
|
||||
return this._selected;
|
||||
},
|
||||
|
|
Загрузка…
Ссылка в новой задаче