commit ec3bc4b0086b95df86e947e59402f3821fb90538
parent b0acb7e26ceec793ab86fce1a67be972d8eab09a
Author: Lorenz A <me@lorenzackermann.xyz>
Date: Mon, 15 Dec 2025 17:43:14 +0000
Bug 2004286 - [devtools] Turn devtools/client/inspector/markup/views/element-editor.js into an ES class. r=devtools-reviewers,jdescottes
Differential Revision: https://phabricator.services.mozilla.com/D276118
Diffstat:
1 file changed, 99 insertions(+), 101 deletions(-)
diff --git a/devtools/client/inspector/markup/views/element-editor.js b/devtools/client/inspector/markup/views/element-editor.js
@@ -74,59 +74,59 @@ const DISPLAY_TYPES = {
/**
* Creates an editor for an Element node.
- *
- * @param {MarkupContainer} container
- * The container owning this editor.
- * @param {NodeFront} node
- * The NodeFront being edited.
*/
-function ElementEditor(container, node) {
- this.container = container;
- this.node = node;
- this.markup = this.container.markup;
- this.doc = this.markup.doc;
- this.inspector = this.markup.inspector;
- this.highlighters = this.markup.highlighters;
- this._cssProperties = this.inspector.cssProperties;
-
- this.isOverflowDebuggingEnabled = Services.prefs.getBoolPref(
- "devtools.overflow.debugging.enabled"
- );
-
- // If this is a scrollable element, this specifies whether or not its overflow causing
- // elements are highlighted. Otherwise, it is null if the element is not scrollable.
- this.highlightingOverflowCausingElements = this.node.isScrollable
- ? false
- : null;
-
- this.attrElements = new Map();
- this.animationTimers = {};
-
- this.elt = null;
- this.tag = null;
- this.closeTag = null;
- this.attrList = null;
- this.newAttr = null;
- this.closeElt = null;
-
- this.onCustomBadgeClick = this.onCustomBadgeClick.bind(this);
- this.onDisplayBadgeClick = this.onDisplayBadgeClick.bind(this);
- this.onScrollableBadgeClick = this.onScrollableBadgeClick.bind(this);
- this.onExpandBadgeClick = this.onExpandBadgeClick.bind(this);
- this.onTagEdit = this.onTagEdit.bind(this);
-
- this.buildMarkup();
-
- const isVoidElement = HTML_VOID_ELEMENTS.includes(this.node.displayName);
- if (node.isInHTMLDocument && isVoidElement) {
- this.elt.classList.add("void-element");
- }
+class ElementEditor {
+ /**
+ * @param {MarkupContainer} container
+ * The container owning this editor.
+ * @param {NodeFront} node
+ * The NodeFront being edited.
+ */
+ constructor(container, node) {
+ this.container = container;
+ this.node = node;
+ this.markup = this.container.markup;
+ this.doc = this.markup.doc;
+ this.inspector = this.markup.inspector;
+ this.highlighters = this.markup.highlighters;
+ this._cssProperties = this.inspector.cssProperties;
+
+ this.isOverflowDebuggingEnabled = Services.prefs.getBoolPref(
+ "devtools.overflow.debugging.enabled"
+ );
- this.update();
- this.initialized = true;
-}
+ // If this is a scrollable element, this specifies whether or not its overflow causing
+ // elements are highlighted. Otherwise, it is null if the element is not scrollable.
+ this.highlightingOverflowCausingElements = this.node.isScrollable
+ ? false
+ : null;
+
+ this.attrElements = new Map();
+ this.animationTimers = {};
+
+ this.elt = null;
+ this.tag = null;
+ this.closeTag = null;
+ this.attrList = null;
+ this.newAttr = null;
+ this.closeElt = null;
+
+ this.onCustomBadgeClick = this.onCustomBadgeClick.bind(this);
+ this.onDisplayBadgeClick = this.onDisplayBadgeClick.bind(this);
+ this.onScrollableBadgeClick = this.onScrollableBadgeClick.bind(this);
+ this.onExpandBadgeClick = this.onExpandBadgeClick.bind(this);
+ this.onTagEdit = this.onTagEdit.bind(this);
+
+ this.buildMarkup();
+
+ const isVoidElement = HTML_VOID_ELEMENTS.includes(this.node.displayName);
+ if (node.isInHTMLDocument && isVoidElement) {
+ this.elt.classList.add("void-element");
+ }
-ElementEditor.prototype = {
+ this.update();
+ this.initialized = true;
+ }
buildMarkup() {
this.elt = this.doc.createElement("span");
this.elt.classList.add("editor");
@@ -150,7 +150,7 @@ ElementEditor.prototype = {
cssProperties: this._cssProperties,
});
}
- },
+ }
renderOpenTag() {
const open = this.doc.createElement("span");
@@ -171,12 +171,12 @@ ElementEditor.prototype = {
closingBracket.classList.add("closing-bracket");
closingBracket.textContent = ">";
open.appendChild(closingBracket);
- },
+ }
renderAttributes(containerEl) {
this.attrList = this.doc.createElement("span");
containerEl.appendChild(this.attrList);
- },
+ }
renderNewAttributeEditor(containerEl) {
this.newAttr = this.doc.createElement("span");
@@ -217,14 +217,14 @@ ElementEditor.prototype = {
},
cssProperties: this._cssProperties,
});
- },
+ }
renderEventBadge() {
this.expandBadge = this.doc.createElement("span");
this.expandBadge.classList.add("markup-expand-badge");
this.expandBadge.addEventListener("click", this.onExpandBadgeClick);
this.elt.appendChild(this.expandBadge);
- },
+ }
renderCloseTag() {
const close = this.doc.createElement("span");
@@ -238,17 +238,17 @@ ElementEditor.prototype = {
close.appendChild(this.closeTag);
close.appendChild(this.doc.createTextNode(">"));
- },
+ }
get displayBadge() {
return this._displayBadge;
- },
+ }
set selected(value) {
if (this.textEditor) {
this.textEditor.selected = value;
}
- },
+ }
flashAttribute(attrName) {
if (this.animationTimers[attrName]) {
@@ -264,7 +264,7 @@ ElementEditor.prototype = {
backgroundClass: "theme-bg-contrast",
});
}, this.markup.CONTAINER_FLASHING_DURATION);
- },
+ }
/**
* Returns information about node in the editor.
@@ -292,7 +292,7 @@ ElementEditor.prototype = {
}
return { type, name, value, el: node };
- },
+ }
/**
* Update the state of the editor from the node.
@@ -345,7 +345,7 @@ ElementEditor.prototype = {
this.updateUnavailableChildren();
this.updateOverflowBadge();
this.updateOverflowHighlight();
- },
+ }
updateEventBadge() {
const showEventBadge = this.node.hasEventListeners;
@@ -355,7 +355,7 @@ ElementEditor.prototype = {
} else if (showEventBadge && !this._eventBadge) {
this._createEventBadge();
}
- },
+ }
_createEventBadge() {
this._eventBadge = this.doc.createElement("button");
@@ -372,7 +372,7 @@ ElementEditor.prototype = {
this._displayBadge || this._customBadge
);
this.markup.emit("badge-added-event");
- },
+ }
updateScrollableBadge() {
if (this.node.isScrollable && !this._scrollableBadge) {
@@ -381,7 +381,7 @@ ElementEditor.prototype = {
this._scrollableBadge.remove();
this._scrollableBadge = null;
}
- },
+ }
_createScrollableBadge() {
const isInteractive =
@@ -393,9 +393,7 @@ ElementEditor.prototype = {
this._scrollableBadge = this.doc.createElement(
isInteractive ? "button" : "div"
);
- this._scrollableBadge.className = `inspector-badge scrollable-badge ${
- isInteractive ? "interactive" : ""
- }`;
+ this._scrollableBadge.className = `inspector-badge scrollable-badge ${isInteractive ? "interactive" : ""}`;
this._scrollableBadge.dataset.scrollable = "true";
this._scrollableBadge.textContent = INSPECTOR_L10N.getStr(
"markupView.scrollableBadge.label"
@@ -414,7 +412,7 @@ ElementEditor.prototype = {
this._scrollableBadge.setAttribute("aria-pressed", "false");
}
this.elt.insertBefore(this._scrollableBadge, this._customBadge);
- },
+ }
/**
* Update the markup display badge.
@@ -433,7 +431,7 @@ ElementEditor.prototype = {
this._updateDisplayBadgeContent();
}
- },
+ }
_createDisplayBadge() {
this._displayBadge = this.doc.createElement("button");
@@ -441,7 +439,7 @@ ElementEditor.prototype = {
this._displayBadge.addEventListener("click", this.onDisplayBadgeClick);
// Badges order is [event][display][custom], insert display badge before custom.
this.elt.insertBefore(this._displayBadge, this._customBadge);
- },
+ }
_updateDisplayBadgeContent() {
const displayType = this.node.displayType;
@@ -472,7 +470,7 @@ ElementEditor.prototype = {
this._displayBadge.setAttribute("role", "presentation");
this._displayBadge.removeAttribute("aria-pressed");
}
- },
+ }
updateOverflowBadge() {
if (!this.isOverflowDebuggingEnabled) {
@@ -485,7 +483,7 @@ ElementEditor.prototype = {
this._overflowBadge.remove();
this._overflowBadge = null;
}
- },
+ }
_createOverflowBadge() {
this._overflowBadge = this.doc.createElement("div");
@@ -497,7 +495,7 @@ ElementEditor.prototype = {
"markupView.overflowBadge.tooltip"
);
this.elt.insertBefore(this._overflowBadge, this._customBadge);
- },
+ }
/**
* Update the markup custom element badge.
@@ -510,7 +508,7 @@ ElementEditor.prototype = {
} else if (!this._customBadge && showCustomBadge) {
this._createCustomBadge();
}
- },
+ }
_createCustomBadge() {
this._customBadge = this.doc.createElement("button");
@@ -523,7 +521,7 @@ ElementEditor.prototype = {
this._customBadge.addEventListener("click", this.onCustomBadgeClick);
// Badges order is [event][display][custom], insert custom badge at the end.
this.elt.appendChild(this._customBadge);
- },
+ }
updateContainerBadge() {
const showContainerBadge =
@@ -536,7 +534,7 @@ ElementEditor.prototype = {
} else if (showContainerBadge && !this._containerBadge) {
this._createContainerBadge();
}
- },
+ }
_createContainerBadge() {
this._containerBadge = this.doc.createElement("div");
@@ -549,7 +547,7 @@ ElementEditor.prototype = {
// Ideally badges order should be [event][display][container][custom]
this.elt.insertBefore(this._containerBadge, this._customBadge);
this.markup.emit("badge-added-event");
- },
+ }
updateAnchorBadge() {
const showAnchorBadge = this.node.anchorName?.includes?.("--");
@@ -564,7 +562,7 @@ ElementEditor.prototype = {
if (this._anchorBadge) {
this._anchorBadge.title = `anchor-name: ${this.node.anchorName}`;
}
- },
+ }
_createAnchorBadge() {
this._anchorBadge = this.doc.createElement("div");
@@ -573,7 +571,7 @@ ElementEditor.prototype = {
this._anchorBadge.append(this.doc.createTextNode("anchor"));
this.elt.insertBefore(this._anchorBadge, this._containerBadge);
- },
+ }
/**
* If node causes overflow, toggle its overflow highlight if its scrollable ancestor's
@@ -604,7 +602,7 @@ ElementEditor.prototype = {
}
this.setOverflowHighlight(showOverflowHighlight);
- },
+ }
/**
* Show overflow highlight if showOverflowHighlight is true, otherwise hide it.
@@ -616,7 +614,7 @@ ElementEditor.prototype = {
"overflow-causing-highlighted",
showOverflowHighlight
);
- },
+ }
/**
* Update the inline text editor in case of a single text child node.
@@ -644,11 +642,11 @@ ElementEditor.prototype = {
if (this.textEditor) {
this.textEditor.update();
}
- },
+ }
hasUnavailableChildren() {
return !!this.childrenUnavailableElt;
- },
+ }
/**
* Update a special badge displayed for nodes which have children that can't
@@ -677,11 +675,11 @@ ElementEditor.prototype = {
this.elt.querySelector(".close")
);
}
- },
+ }
_startModifyingAttributes() {
return this.node.startModifyingAttributes();
- },
+ }
/**
* Get the element used for one of the attributes of this element.
@@ -694,7 +692,7 @@ ElementEditor.prototype = {
return this.attrList.querySelector(
".attreditor[data-attr=" + CSS.escape(attrName) + "] .attr-value"
);
- },
+ }
/**
* Remove an attribute from the attrElements object and the DOM.
@@ -708,7 +706,7 @@ ElementEditor.prototype = {
this.attrElements.delete(attrName);
attr.remove();
}
- },
+ }
/**
* Creates and returns the DOM for displaying an attribute with the following DOM
@@ -773,7 +771,7 @@ ElementEditor.prototype = {
this._appendAttributeValue(attribute, val);
return attr;
- },
+ }
/**
* Setup the editable field for the given attribute.
@@ -867,7 +865,7 @@ ElementEditor.prototype = {
},
cssProperties: this._cssProperties,
});
- },
+ }
/**
* Appends the attribute value to the given attribute value <span> element.
@@ -930,7 +928,7 @@ ElementEditor.prototype = {
}
}
}
- },
+ }
/**
* Truncates the given attribute value if it is a base64 data URL or the
@@ -948,7 +946,7 @@ ElementEditor.prototype = {
return this.markup.collapseAttributes
? truncateString(value, this.markup.collapseAttributeLength)
: value;
- },
+ }
/**
* Parse a user-entered attribute string and apply the resulting
@@ -969,7 +967,7 @@ ElementEditor.prototype = {
this._saveAttribute(attr.name, undoMods);
doMods.setAttribute(attr.name, attr.value);
}
- },
+ }
/**
* Saves the current state of the given attribute into an attribute
@@ -983,7 +981,7 @@ ElementEditor.prototype = {
} else {
undoMods.removeAttribute(name);
}
- },
+ }
/**
* Listen to mutations, and when the attribute list is regenerated
@@ -1097,7 +1095,7 @@ ElementEditor.prototype = {
// Start listening for mutations until we find an attributes change
// that modifies this attribute.
this.markup.inspector.once("markupmutation", onMutations);
- },
+ }
/**
* Called when the display badge is clicked. Toggles on the flexbox/grid highlighter for
@@ -1132,7 +1130,7 @@ ElementEditor.prototype = {
await this.highlighters.toggleGridHighlighter(this.node, "markup");
}
- },
+ }
async onCustomBadgeClick() {
const { url, line, column } = this.node.customElementLocation;
@@ -1144,11 +1142,11 @@ ElementEditor.prototype = {
null,
"show_custom_element"
);
- },
+ }
onExpandBadgeClick() {
this.container.expandContainer();
- },
+ }
/**
* Called when the scrollable badge is clicked. Shows the overflow causing elements and
@@ -1181,7 +1179,7 @@ ElementEditor.prototype = {
}
Glean.devtoolsMarkupScrollableBadge.clicked.add(1);
- },
+ }
/**
* Called when the tag name editor has is done editing.
@@ -1234,7 +1232,7 @@ ElementEditor.prototype = {
// Failed to edit the tag name, cancel the reselection.
this.markup.cancelReselectOnRemoved();
}
- },
+ }
destroy() {
if (this._displayBadge) {
@@ -1258,7 +1256,7 @@ ElementEditor.prototype = {
clearTimeout(this.animationTimers[key]);
}
this.animationTimers = null;
- },
-};
+ }
+}
module.exports = ElementEditor;