diff --git a/devtools/client/inspector/markup/markup.js b/devtools/client/inspector/markup/markup.js index 4918f8a099ad..07b09e1ac493 100644 --- a/devtools/client/inspector/markup/markup.js +++ b/devtools/client/inspector/markup/markup.js @@ -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); diff --git a/devtools/client/inspector/markup/markup.xhtml b/devtools/client/inspector/markup/markup.xhtml index 5196c90c6975..b275f4cf70ed 100644 --- a/devtools/client/inspector/markup/markup.xhtml +++ b/devtools/client/inspector/markup/markup.xhtml @@ -18,87 +18,8 @@ src="chrome://devtools/content/sourceeditor/codemirror/codemirror.bundle.js"> - - - - - diff --git a/devtools/client/inspector/markup/views/element-editor.js b/devtools/client/inspector/markup/views/element-editor.js index 5d1bcd00a9b4..ccd8afbc2e58 100644 --- a/devtools/client/inspector/markup/views/element-editor.js +++ b/devtools/client/inspector/markup/views/element-editor.js @@ -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.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"' diff --git a/devtools/client/inspector/markup/views/markup-container.js b/devtools/client/inspector/markup/views/markup-container.js index a2206788f7dd..d2a449481b4d 100644 --- a/devtools/client/inspector/markup/views/markup-container.js +++ b/devtools/client/inspector/markup/views/markup-container.js @@ -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) { diff --git a/devtools/client/inspector/markup/views/read-only-editor.js b/devtools/client/inspector/markup/views/read-only-editor.js index fb4d904f6858..94c59e905730 100644 --- a/devtools/client/inspector/markup/views/read-only-editor.js +++ b/devtools/client/inspector/markup/views/read-only-editor.js @@ -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; }, /** diff --git a/devtools/client/inspector/markup/views/text-editor.js b/devtools/client/inspector/markup/views/text-editor.js index f3c83ca8788d..d89e95f02a7e 100644 --- a/devtools/client/inspector/markup/views/text-editor.js +++ b/devtools/client/inspector/markup/views/text-editor.js @@ -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(closeComment); + } + }, + get selected() { return this._selected; },