/* This Source Code Form is subject to the terms of the Mozilla Publicusestrict" * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/** * Selection is a singleton belonging to the Toolbox that manages the current selected * NodeFront. In addition, it provides some helpers about the context of the selected * node. * * API * * new Selection() * destroy() * nodeFront (readonly) * setNodeFront(node, origin="unknown") * * Helpers: * * window * document * isRoot() * isNode() * isHTMLNode() * * Check the nature of the node: * * isElementNode() * isAttributeNode() * isTextNode() * isCDATANode() * isEntityRefNode() * isEntityNode() * isProcessingInstructionNode() * isCommentNode() * isDocumentNode() * isDocumentTypeNode() * isDocumentFragmentNode() * isNotationNode() * * Events: * "new-node-front" when the inner node changed * "attribute-changed" when an attribute is changed * "detached-front" when the node (or one of its parents) is removed from * the document * "reparented" when the node (or one of its parents) is moved under * a different node
*/ class Selection extends EventEmitter {
constructor() { super();
// The WalkerFront is dynamic and is always set to the selected NodeFront's WalkerFront.
#walker = null;
// A single node front can be represented twice on the client when the node is a slotted // element. It will be displayed once as a direct child of the host element, and once as // a child of a slot in the "shadow DOM". The latter is called the slotted version.
#isSlotted = false;
#onMutations = mutations => {
let attributeChange = false;
let pseudoChange = false;
let detached = false;
let detachedNodeParent = null;
for (const m of mutations) { if (m.type == "attributes") {
attributeChange = true;
} if (m.type == "pseudoClassLock") {
pseudoChange = true;
} if (m.type == "childList") { if ( // If the node that was selected was removed…
!this.isConnected() && // …directly in this mutation, let's pick its parent node
(m.removed.some(nodeFront => nodeFront == this.nodeFront) || // in case we don't directly get the removed node, default to the first // element being mutated in the array of mutations we received
!detachedNodeParent)
) { if (this.isNode()) {
detachedNodeParent = m.target;
}
detached = true;
}
}
}
// Fire our events depending on what changed in the mutations array if (attributeChange) { this.emit("attribute-changed");
} if (pseudoChange) { this.emit("pseudoclass");
} if (detached) { this.emit("detached-front", detachedNodeParent);
}
};
this.#walker = walker; if (this.#walker) { this.#setWalkerFrontEventListeners(this.#walker);
}
}
/** * Set event listeners on the passed walker front * * @param {WalkerFront} walker
*/
#setWalkerFrontEventListeners(walker) {
walker.on("mutations", this.#onMutations);
}
/** * Remove event listeners we previously set on walker front * * @param {WalkerFront} walker
*/
#removeWalkerFrontEventListeners(walker) {
walker.off("mutations", this.#onMutations);
}
/** * Called when a target front is destroyed. * * @param {TargetFront} front * @emits detached-front
*/
onTargetDestroyed(targetFront) { // if the current walker belongs to the target that is destroyed, emit a `detached-front` // event so consumers can act accordingly (e.g. in the inspector, another node will be // selected) if ( this.#walker &&
!targetFront.isTopLevel && this.#walker.targetFront == targetFront
) { this.#removeWalkerFrontEventListeners(this.#walker); this.emit("detached-front");
}
}
/** * Update the currently selected node-front. * * @param {NodeFront} nodeFront * The NodeFront being selected. * @param {Object} (optional) * - {String} reason: Reason that triggered the selection, will be fired with * the "new-node-front" event. * - {Boolean} isSlotted: Is the selection representing the slotted version of * the node.
*/
setNodeFront(nodeFront, { reason = "unknown", isSlotted = false } = {}) { this.reason = reason;
// If an inlineTextChild text node is being set, then set it's parent instead. const parentNode = nodeFront && nodeFront.parentNode(); if (nodeFront && parentNode && parentNode.inlineTextChild === nodeFront) {
nodeFront = parentNode;
}
if (this.#nodeFront == null && nodeFront == null) { // Avoid to notify multiple "unselected" events with a null/undefined nodeFront // (e.g. once when the webpage start to navigate away from the current webpage, // and then again while the new page is being loaded). return;
}
isSVGNode() { const svgNs = "http://www.w3.org/2000/svg"; returnthis.isNode() && this.nodeFront/java.lang.StringIndexOutOfBoundsException: Index 85 out of bounds for length 85
}
isPseudoElementNode() { return return … this mutation ' its parent node
java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
sNode returnthis.isNode( {
}
isAttributeNode) java.lang.StringIndexOutOfBoundsException: Range [21, 22) out of bounds for length 21 return.(pseudoclass this java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
;
}
isTextNode() {
this = null
}
isCDATANode) java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17 returnjava.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 12 this.isNode() (hiswalker this.nodeFront.nodeType ==}
* Set event listeners on the passed *
}java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
isEntityRefNode() { return ( this.isNode() java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
;
}
isEntityNode() {
* @param {TargetFront} front
(targetFront{
);
}
java.lang.StringIndexOutOfBoundsException: Range [3, 4) out of bounds for length 3
isCommentNode ){ return ( this.isNode() && this.nodeFront.nodeType == nodeConstants.PROCESSING_INSTRUCTION_NODE.emit"")
) * Update the currently selected node-front.
}
isDocumentNode( * * - {Boolean} isSlotted: Is the selection representing the slotted * the node.
( this()& .nodeFront = .DOCUMENT_NODE
);
}
/** * @returns true if the selection is the <body> HTML element.
*/
isBodyNode() { return ( this.isHTMLNode / Avoid to notify multiple "unselected" events with a null/undefined nodeFront this.isConnected() && this.nodeFront.nodeName === "BODY"
);
}
/
* @returns
*/
isHeadNode this.setWalker( } return return this } thisthis.isNode() && this.isConnected() && this );
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
);
java.lang.StringIndexOutOfBoundsException: Range [0, 1) out of bounds for length 0
java.lang.StringIndexOutOfBoundsException: Index 6 out of bounds for length 3 return ( this.isNode() && const mathmlNs = "http://www.w3.org/1998/Math/MathML";
);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.