/* This Source Code Form is subject to the terms of the Mozilla Public * 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/. */
/** * Set of actors the expose the CSS layout information to the devtools protocol clients. * * The |Layout| actor is the main entry point. It is used to get various CSS * layout-related information from the document. * * The |Flexbox| actor provides the container node information to inspect the flexbox * container. It is also used to return an array of |FlexItem| actors which provide the * flex item information. * * The |Grid| actor provides the grid fragment information to inspect the grid container.
*/
class FlexboxActor extends Actor { /** * @param {LayoutActor} layoutActor * The LayoutActor instance. * @param {DOMNode} containerEl * The flex container element.
*/
constructor(layoutActor, containerEl) { super(layoutActor.conn, flexboxSpec);
const form = {
actor: this.actorID, // The computed style properties of the flex container.
properties: { "align-content": styles.alignContent, "align-items": styles.alignItems, "flex-direction": styles.flexDirection, "flex-wrap": styles.flexWrap, "justify-content": styles.justifyContent,
},
};
// If the WalkerActor already knows the container element, then also return its // ActorID so we avoid the client from doing another round trip to get it in many // cases. if (this.walker.hasNode(this.containerEl)) {
form.containerNodeActorID = this.walker.getNode(this.containerEl).actorID;
}
return form;
}
/** * Returns an array of FlexItemActor objects for all the flex item elements contained * in the flex container element. * * @return {Array} * An array of FlexItemActor objects.
*/
getFlexItems() { if (isNodeDead(this.containerEl)) { return [];
}
const flex = this.containerEl.getAsFlexContainer(); if (!flex) { return [];
}
if (isElementNode) { for (const name in properties) { const values = []; const cssRules = getMatchingCSSRules(this.element);
for (const rule of cssRules) { // For each rule, go through *all* properties, because there may be several of // them in the same rule and some with !important flags (which would be more // important even if placed before another property with the same name) const declarations = parseDeclarations(
isCssPropertyKnown,
rule.style.cssText
);
for (const declaration of declarations) { if (declaration.name === name && declaration.value !== "auto") {
values.push({
value: declaration.value,
priority: declaration.priority,
});
}
}
}
// Then go through the element style because it's usually more important, but // might not be if there is a prior !important property if ( this.element.style && this.element.style[name] && this.element.style[name] !== "auto"
) {
values.push({
value: this.element.style.getPropertyValue(name),
priority: this.element.style.getPropertyPriority(name),
});
}
// Now that we have a list of all the property's rule values, go through all the // values and show the property value with the highest priority. Therefore, show // the last !important value. Otherwise, show the last value stored.
let rulePropertyValue = "";
for (const { priority, value } of values) { if (priority === "important") {
rulePropertyValue = `${value} !important`;
}
}
}
properties[name] = rulePropertyValue;
}
}
// Also find some computed sizing properties that will be useful for this item. const { flexGrow, flexShrink } = isElementNode
? CssLogic.getComputedStyle(this.element)
: { flexGrow: null, flexShrink: null }; const computedStyle = { flexGrow, flexShrink };
const form = {
actor: this.actorID, // The flex item sizing data.
flexItemSizing: this.flexItemSizing, // The authored style properties of the flex item.
properties, // The computed style properties of the flex item.
computedStyle,
};
// If the WalkerActor already knows the flex item element, then also return its // ActorID so we avoid the client from doing another round trip to get it in many // cases. if (this.walker.hasNode(this.element)) {
form.nodeActorID = this.walker.getNode(this.element).actorID;
}
return form;
}
}
/** * The GridActor provides information about a given grid's fragment data.
*/ class GridActor extends Actor { /** * @param {LayoutActor} layoutActor * The LayoutActor instance. * @param {DOMNode} containerEl * The grid container element.
*/
constructor(layoutActor, containerEl) { super(layoutActor.conn, gridSpec);
form() { // Seralize the grid fragment data into JSON so protocol.js knows how to write // and read the data. const gridFragments = this.containerEl.getGridFragments(); this.gridFragments = getStringifiableFragments(gridFragments);
// Record writing mode and text direction for use by the grid outline. const { direction, gridTemplateColumns, gridTemplateRows, writingMode } =
CssLogic.getComputedStyle(this.containerEl);
// If the WalkerActor already knows the container element, then also return its // ActorID so we avoid the client from doing another round trip to get it in many // cases. if (this.walker.hasNode(this.containerEl)) {
form.containerNodeActorID = this.walker.getNode(this.containerEl).actorID;
}
/** * The CSS layout actor provides layout information for the given document.
*/ class LayoutActor extends Actor {
constructor(conn, targetActor, walker) { super(conn, layoutSpec);
/** * Helper function for getAsFlexItem, getCurrentGrid and getCurrentFlexbox. Returns the * grid or flex container (whichever is requested) found by iterating on the given * selected node. The current node can be a grid/flex container or grid/flex item. * If it is a grid/flex item, returns the parent grid/flex container. Otherwise, returns * null if the current or parent node is not a grid/flex container. * * @param {Node|NodeActor} node * The node to start iterating at. * @param {String} type * Can be "grid" or "flex", the display type we are searching for. * @param {Boolean} onlyLookAtContainer * If true, only look at given node's container and iterate from there. * @return {GridActor|FlexboxActor|null} * The GridActor or FlexboxActor of the grid/flex container of the given node. * Otherwise, returns null.
*/
getCurrentDisplay(node, type, onlyLookAtContainer) { if (isNodeDead(node)) { returnnull;
}
// Given node can either be a Node or a NodeActor. if (node.rawNode) {
node = node.rawNode;
}
const flexType = type === "flex"; const gridType = type === "grid"; const displayType = this.walker.getNode(node).displayType;
// If the node is an element, check first if it is itself a flex or a grid. if (node.nodeType === node.ELEMENT_NODE) { if (!displayType) { returnnull;
}
if (flexType && displayType.includes("flex")) { if (!onlyLookAtContainer) { returnnew FlexboxActor(this, node);
}
// Otherwise, check if this is a flex/grid item or the parent node is a flex/grid // container. // Note that text nodes that are children of flex/grid containers are wrapped in // anonymous containers, so even if their displayType getter returns null we still // want to walk up the chain to find their container. const parentFlexElement = node.parentFlexElement; if (parentFlexElement && flexType) { returnnew FlexboxActor(this, parentFlexElement);
} const container = findGridParentContainerForNode(node); if (container && gridType) { returnnew GridActor(this, container);
}
returnnull;
}
/** * Returns the grid container for a given selected node. * The node itself can be a container, but if not, walk up the DOM to find its * container. * Returns null if no container can be found. * * @param {Node|NodeActor} node * The node to start iterating at. * @return {GridActor|null} * The GridActor of the grid container of the given node. Otherwise, returns * null.
*/
getCurrentGrid(node) { returnthis.getCurrentDisplay(node, "grid");
}
/** * Returns the flex container for a given selected node. * The node itself can be a container, but if not, walk up the DOM to find its * container. * Returns null if no container can be found. * * @param {Node|NodeActor} node * The node to start iterating at. * @param {Boolean|null} onlyLookAtParents * If true, skip the passed node and only start looking at its parent and up. * @return {FlexboxActor|null} * The FlexboxActor of the flex container of the given node. Otherwise, returns * null.
*/
getCurrentFlexbox(node, onlyLookAtParents) { returnthis.getCurrentDisplay(node, "flex", onlyLookAtParents);
}
/** * Returns an array of GridActor objects for all the grid elements contained in the * given root node. * * @param {Node|NodeActor} node * The root node for grid elements * @return {Array} An array of GridActor objects.
*/
getGrids(node) { if (isNodeDead(node)) { return [];
}
// Root node can either be a Node or a NodeActor. if (node.rawNode) {
node = node.rawNode;
}
// Root node can be a #document object, which does not support getElementsWithGrid. if (node.nodeType === nodeConstants.DOCUMENT_NODE) {
node = node.documentElement;
}
if (!node) { return [];
}
const gridElements = node.getElementsWithGrid();
let gridActors = gridElements.map(n => new GridActor(this, n));
if (this.targetActor.ignoreSubFrames) { return gridActors;
}
const frames = node.querySelectorAll("iframe, frame"); for (const frame of frames) {
gridActors = gridActors.concat(this.getGrids(frame.contentDocument));
}
return gridActors;
}
}
function isNodeDead(node) { return !node || (node.rawNode && Cu.isDeadWrapper(node.rawNode));
}
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.