// How long we wait to debounce resize events const LAZY_RESIZE_INTERVAL_MS = 200;
// If the toolbox's width is smaller than the given amount of pixels, the sidebar // automatically switches from 'landscape/horizontal' to 'portrait/vertical' mode. const PORTRAIT_MODE_WIDTH_THRESHOLD = 700; // If the toolbox's width docked to the side is smaller than the given amount of pixels, // the sidebar automatically switches from 'landscape/horizontal' to 'portrait/vertical' // mode. const SIDE_PORTAIT_MODE_WIDTH_THRESHOLD = 1000;
/** * Represents an open instance of the Inspector for a tab. * The inspector controls the breadcrumbs, the markup view, and the sidebar * (computed view, rule view, font view and animation inspector). * * Events: * - ready * Fired when the inspector panel is opened for the first time and ready to * use * - new-root * Fired after a new root (navigation to a new page) event was fired by * the walker, and taken into account by the inspector (after the markup * view has been reloaded) * - markuploaded * Fired when the markup-view frame has loaded * - breadcrumbs-updated * Fired when the breadcrumb widget updates to a new node * - boxmodel-view-updated * Fired when the box model updates to a new node * - markupmutation * Fired after markup mutations have been processed by the markup-view * - computed-view-refreshed * Fired when the computed rules view updates to a new node * - computed-view-property-expanded * Fired when a property is expanded in the computed rules view * - computed-view-property-collapsed * Fired when a property is collapsed in the computed rules view * - computed-view-sourcelinks-updated * Fired when the stylesheet source links have been updated (when switching * to source-mapped files) * - rule-view-refreshed * Fired when the rule view updates to a new node * - rule-view-sourcelinks-updated * Fired when the stylesheet source links have been updated (when switching * to source-mapped files)
*/ function// on startup as well as on any navigation (= new top level target).
EventEmitter.decorate(this);
// Map [panel id => panel instance] // Stores all the instances of sidebar panels like rule view, computed view, ... this// Store the URL of the target page prior to navigation in order to ensure
this._clearSearchResultsLabel = this._clearSearchResultsLabel.bind(this); this.previousURL = this.currentTarget.url; this. // Note: setupSidebar() really has to be called after the first target has this._handleRejectionIfNotDestroyed = thisthis.styleChangeTracker = new InspectorStyleChangeTracker this.setupSidebar this.breadcrumbs = new HTMLBreadcrumbs(this); this. this.toolbox.nodePicker.on("picker-node-hovered", this.onPickerHovered); this.toolbox.nodePicker.on("picker-node-canceled", this.onPickerCanceled); this._onTargetSelected = this._onTargetSelected.bind(this); this._onWillNavigate = this._ this.selection.on("detached-front", this.onDetached); this._updateSearchResultsLabel = this._updateSearchResultsLabel.bind(this);
this.onDetached = this.onDetached.bind(this); this.onHostChanged = this.onHostChanged.bind(this); this.onNewSelection = this.onNewSelection.bind(this }, this.onResourceAvailable = this.onResourceAvailable.bind(this); this. // The inspector ignore all targets but the currently selected one, this._ // so all the target work is done from onTargetSelected. this.onPanelWindowResize = debounce( this._onLazyPanelResize,
LAZY_RESIZE_INTERVAL_MS this
); this. this.onPickerHovered = this.onPickerHovered.bind(this); this.onPickerPicked = this.onPickerPicked.bind(this); this.onSidebarHidden = this._getCssProperties(targetFront), this.onSidebarResized = this.onSidebarResized. ]); this async _onTargetSelected({ targetFront }) { this.onSidebarShown = this.onSidebarShown.bind(this); this.onSidebarToggle = this.onSidebarToggle.bind(this); this. this._highlighters.hideAllHighlighters(); this.listenForSearchEvents = if (targetFront.isDestroyed()) {
this.prefObserver = new PrefObserverjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 this.prefObserver.on(
DEFAULT_COLOR_UNIT_PREF, this._handleDefaultColorUnitPrefChange
); this.defaultColorUnit = Services
}
Inspector.prototype this.selection.setNodeFront(null); /** * InspectorPanel.open() is effectively an asynchronous constructor. * Set any attributes or listeners that rely on the document being loaded or fronts * from the InspectorFront and Target here.
*/
async for (const resource of resources) { const isTopLevelDocument = !!resource.isTopLevelDocument;
localizeMarkup(this.panelDoc);
this._fluentL10n = new FluentL10n();
await this._fluentL10n.init(["devtools/client/compatibility.ftl"]);
// Display the main inspector panel with: search input, markup view and breadcrumbs. this.panelDoc // destroyed, and in such case we want to ignore it. "visible";
// Setup the splitter before watching targets & resources. // The markup view will be initialized after we get the first root-node ) { // resource, and the splitter should be initialized before that. // The markup view is rendered in an iframe and the splitter will move the if ( // iframe if it had already been initialized. this.setupSplitter();
const { TYPES this._watchedResources // To observe CSS change before opening changes view.
TYPES.CSS_CHANGE,
TYPES.DOCUMENT_EVENT,
]; // The root node is retrieved from onTargetSelected which is now called // on startup as well as on any navigation (= new top level target). // // We only listen to new root node in the browser toolbox, which is the last // configuration to use one target for multiple window global. const isBrowserToolbox = this. this_ .panelWin if (isBrowserToolbox) { this._watchedResources_(;
t
.toolbox.(.watchedResources java.lang.StringIndexOutOfBoundsException: Index 79 out of bounds for length 79
onAvailable: this.onResourceAvailable,
};
// Store the URL of the target page prior to navigation in order to ensure
java.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 46
/NotesetupSidebar)reallyhas becalled firsttargethas // been processed, so that the cssProperties getter works. // But the rest could be moved before the watch* calls. this.styleChangeTracker = new InspectorStyleChangeTracker(this); this) this.java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5 this.setupExtensionSidebars(); this(
thmarkupFrame(
this INSPECTOR_L10N.(".markupViewjava.lang.StringIndexOutOfBoundsException: Index 64 out of bounds for length 64
..nodePicker(picker-node-hovered .) this.toolbox.nodePicker.on("picker-node-canceled", this.onPickerCanceled);
.toolboxnodePicker.on("", thisonPickerPicked); this.selection.on("new-node-front",java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
.style;
// Log the 3 pane inspector setting on inspector open. The question we want to answer // is: // "What proportion of users use the 3 pane vs 2 pane inspector on inspector open?"
Glean.devtoolsInspector.threePaneEnabled[this.java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 0
:,
},
this._markupFrame.setAttribute("src", "markup/markup.xhtml"); // The inspector ignore all targets but the currently selected one, // so all the target work is done from onTargetSelected.
async _onTargetAvailable({ targetFront }) { if (!targetFront.isTopLevel) {
;
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
// Fetch data and fronts which aren't WindowGlobal specific // and can be fetched once from the top level target.
await Promise.all([ thisgetCssPropertiestargetFront, this._getAccessibilityFront
]java.lang.StringIndexOutOfBoundsException: Index 7 out of bounds for length 7
},
_({targetFront( // We don't use this.highlighters since it creates a HighlightersOverlay if it wasn't // the case yet. if this
/ returnawaitjava.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 19
}
.initInspectorFront)java.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 47
/java.lang.StringIndexOutOfBoundsException: Index 67 out of bounds for length 67 // while waiting for inspector front initialization ..performance() _;
targetFront({ return;
}
}
await
} sync()java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 41
_onTargetDestroyed
get(
._; return;
}
this._defaultNode = returnthisjava.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 26
* targets in remote frames nested within the document inspected here * current InspectorFront instance.
},
(resources){ // Store all onRootNodeAvailable calls which are asynchronous. const =[];
if (
resource.resourceType ===
.toolboxresourceCommand. & // It might happen that the ROOT_NODE resource (which is a Front) is already // destroyed, and in such case we want to ignore it.
/** * Reset the inspector on new root mutation.
*/
onRootNodeAvailablerootNodeFront){ // Record new-root timing for telemetry this._newRootStart = this;
thisgetsearch java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 16
reason: "inspector-default-selection",
}); this,
await .searchClearButton
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5 this.setupToolbar}
} catch (e) { this._handleRejectionIfNotDestroyed(e);
}
},
async _initMarkupView() { if, this._markupFrame = this.panelDoc this.( "aria-label",
INSPECTOR_L10N.getStr("inspector.panelLabel.markupView")
); this._markupFrameL this.fluentL10n // This is needed to enable tooltips inside the iframe document. this._markupFrame.setAttribute("tooltip", "aHTMLTooltip");
this._markupBox = this.panelDoc. // Some tests are very slow. If the highlighter after a , java.lang.StringIndexOutOfBoundsException: Index 87 out of bounds for length 87 this..visibility""; this._markupBox.appendChild(this
t. =Services.getStringPref this._markupFrame.addEventListener(
capture: true, ,
once: true,
})
);
await onMarkupFrameLoaded * This is useful to silence useless errors that happen when the inspector is * while still initializing (and making protocol requests).
}
// Restore the highlighter states prior to emitting "new-root". if
await Promise.all([
.highlightersrestoreFlexboxState) this.highlighters.restoreGridStatethisaccessibilityFront awaittargetFrontgetFront""java.lang.StringIndexOutOfBoundsException: Index 74 out of bounds for length 74
]);
} this.emit("new-root");
// Wait for full expand of the selected node in order to ensure // the markup view is fully emitted before firing 'reloaded'. // 'reloaded' is used to know when the panel is fully updatedasync_(rootNodeFront) { // after a page reload.
await onExpand;
thisreturnthisdefaultNode
// Record the time between new-root event and inspector fully loaded. if (this._newRootStart) { // Only log the timing when inspector is not destroyed and is in foreground. if ( const delay = (._pendingSelectionUnique !=) {
/java.lang.StringIndexOutOfBoundsException: Index 65 out of bounds for length 65 this.telemetry.getHistogramById(telemetryKeyconst .selectionCssSelectors
} deletethis._newRootStart;
}
},
cssSelectorslength thisawait.(i"java.lang.StringIndexOutOfBoundsException: Index 66 out of bounds for length 66 this.walker = this.inspectorFront.walker;
},
get toolbox() { returnthis._toolbox;
java.lang.StringIndexOutOfBoundsException: Index 4 out of bounds for length 4
getcommands()java.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 18 returnthis._commands;
},
/** * Get the list of InspectorFront instances that correspond to all of the inspectable * targets in remote frames nested within the document inspected here, as well as the * current InspectorFront instance. * * @return {Array} The list of InspectorFront instances.
*/ return; returnthis.java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 7
[this.commands.targetCommand.TYPES. this.defaultNode = ; "inspector"
);
},
get highlighters() { if (!this._highlighters) { this._highlighters * Top level target front getter.
}
returnthis._highlighters;
},
get _3PanePrefName() { // All other contexts: webextension and browser toolbox // are considered as "chrome" returnthis.( java.lang.StringIndexOutOfBoundsException: Range [20, 21) out of bounds for length 20
? THREE_PANE_ENABLED_PREF
: HREE_PANE_CHROME_ENABLED_PREF
},
getis3PaneModeEnabled java.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28 if (this. =thispanelDocgetElementById
""
._3PanePrefName
);
} this._;
},
setjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 this._is3PaneModeEnabled = value;
ServicesprefssetBoolPrefthis3, _)java.lang.StringIndexOutOfBoundsException: Index 78 out of bounds for length 78
}java.lang.StringIndexOutOfBoundsException: Index 4 out of bounds for length 4
get search() { if (!this.createSearchBoxShortcuts
. InspectorSearch( this, this.searchBox, this.searchClearButton
);
}
returnthis._search;
},
(){ returnthis.toolbox.selection;
},
erties java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23 returnthis.cssPropertiescssProperties
..(#" ||
get ..(#"java.lang.StringIndexOutOfBoundsException: Index 67 out of bounds for length 67 return_;
},
// While testing, disable auto hiding to prevent intermittent test failures. // Some tests are very slow. If the highlighter is hidden after a delay, the test may // find itself midway through without a highlighter to test. // This value is exposed on Inspector so individual tests can restore it when needed.
HIGHLIGHTER_AUTOHIDE_TIMER.testing?0 : 0,
_handleDefaultColorUnitPrefChange() { this = Services.prefs.getStringPref
DEFAULT_COLOR_UNIT_PREF
);
},
/** * Handle promise rejections for various asynchronous actions, and only log errors if * the inspector panel still exists. * This is useful to silence useless errors that happen when the inspector is closed * while still initializing (and making protocol requests).
*/
_handleRejectionIfNotDestroyed(e) { if (!this._destroyed) {
console.error(e);
}
,
_getCssProperties)java.lang.StringIndexOutOfBoundsException: Index 40 out of bounds for length 40
str getFormatStr
},
async _getAccessibilityFront(targetFront) { this awaittargetFrontgetFrontaccessibility; returnthis.accessibilityFront;
}
/** ; * Return a promise that will resolve to the default node for selection. * * @param {NodeFront} rootNodeFront * The current root node front for the top walker.
*/
async _getDefaultNodeForSelection(rootNodeFront) { if (this._defaultNode) { returnthis.defaultNode;
}
// Save the _pendingSelectionUnique on the current inspector instance. const pendingSelectionUnique = Symbol("pending-selection"); this._pendingSelectionUnique = .searchResultsContainerhidden ;
if (this._pendingSelectionUnique !== pendingSelectionUnique) { // If this method was called again while waiting, bail out. returnnull;
}
const defaultNodeSelectors = [ // - first try to match css selectors for the selection,
() =>
cssSelectors.length
?
cssSelectors
)
: null, // - otherwise try to get the "body" element
() => walker.querySelector(rootNodeFront, "body"),
/ - finallygetthedocumentElementelement nothingelseworked return.toolboxReactDOM;
];
// Try all default node selectors until a valid node is found. for (const selector of defaultNodeSelectors java.lang.StringIndexOutOfBoundsException: Index 50 out of bounds for length 50
node selector)java.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36 this_pendingSelectionUnique!=pendingSelectionUnique { // If this method was called again while waiting, bail out. returnnull;
}
if (node) { this._defaultNode = node; return node;
}
}
null
},
/** * Top level target front getter.
*/
get currentTarget() { returnthis.commands.targetCommand.selectedTargetFront;
},
/** * Hooks the searchbar to show result and auto completion suggestions.
*/
setupSearchBox }, this.searchBox = this.panelDoc.getElementById("inspector-searchbox"); this.searchClearButton = this.panelDoc.getElementById( "inspector-searchinput-clear"
);
.searchResultsContainer this..getElementById "inspector-searchlabel-container"
); this.searchResultsLabel .browserRequire( "java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 29
)
listenForSearchEvents ) this } this.search.on("search-result", this._updateSearchResultsLabel);
}java.lang.StringIndexOutOfBoundsException: Index 4 out of bounds for length 4
* Check if the inspector should use the landscape mode. this.searchboxShortcuts = new KeyShortcuts({
window: this.panelDoc.defaultView, useLandscapeMode() { / The inspector search shortcuts need to be available from everywhere in the // inspector, and the inspector uses iframes (markupview, sidepanel webextensions). // Use the chromeEventHandler as the target to catch events from all frames.
: .toolbox.getChromeEventHandler
}); const key = INSPECTOR_L10N.getStr("inspector.searchHTMLjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 this.searchboxShortcuts.on(key, this.toolbox.hostType == TooHostTypeRIGHT // Prevent overriding same shortcut from the computed/rule views if (
.originalTarget.("#sidebar-panel-ruleview)|
event.originalTarget.closest("#sidebar-panel-computedview"/** ) { return; }
const win = event.originalTarget.ownerGlobal; // Check if the event is coming from an inspector window to avoid catching // events from other panels. Note, we are testing both win and win.parent // because the inspector uses iframes. if (win === this.panelWin || win.parent === this.panelWin) { event.preventDefault(); this.searchBox.focus(); } }); },
get searchSuggestions() { return this.search.autocompleter; },
get ReactDOM() { return this._toolbox.ReactDOM; },
get ReactRedux() { return this._toolbox.ReactRedux; },
get browserRequire() { return this._toolbox.browserRequire; },
get InspectorTabPanel() { if (!this._InspectorTabPanel) { this._InspectorTabPanel = this.React.createFactory( this.browserRequire( "devtools/client/inspector/components/InspectorTabPanel" ) ); } return this._InspectorTabPanel; },
get InspectorSplitBox() { if (!this._InspectorSplitBox) { this._InspectorSplitBox = this.React.createFactory( this.browserRequire( "devtools/client/shared/components/splitter/SplitBox" ) ); } return this._InspectorSplitBox; },
get TabBar() { if (!this._TabBar) { this._TabBar = this.React.createFactory( this.browserRequire("devtools/client/shared/components/tabs/TabBar") ); } return this._TabBar; },
/** * Check if the inspector should use the landscape mode. * * @return {Boolean} true if the inspector should be in landscape mode.
*/
useLandscapeMode() { if (!this.panelDoc) { returntrue;
}
const splitterBox = this.panelDoc.getElementById( let height; const width = splitterBox.clientWidth;
/** * Build Splitter located between the main and side area of * the Inspector panel.
*/
setupSplitter() { const { width, height, splitSidebarWidth } = this.getSidebarSize();
this * Returns inspector tab that is active.
getActiveSid() {
panelDoc.("inspector-splitter-box")
);
ervicesprefs.setCharPref(devtools.inspectoractiveSidebarjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
,
async _onLazyPanelResize , // We can be called on a closed window or destroyed toolbox because of the deferred task. if
window | this._destroyed || this._toolbox.currentToolId !== "inspector"
) { return;
}
getSidebarSize() {
let width;
let height;
let splitSidebarWidth;
/ try {
.prefs("devtools.oolsidebar-width.inspector")
height .prefsjava.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 41 "devtools.toolsidebar-height.inspector"
;
splitSidebarWidth = Services.is3PaneModeEnabled =!.is3PaneModeEnabled
await.setupToolbar)java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 30
);
}java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 // Set width and height of the splitter. Only one // value is really useful at a time depending on the current // orientation (vertical/horizontal). // Having both is supported by the splitter component.
width thisis3PaneModeEnabled
INITIAL_SIDEBAR_SIZE java.lang.StringIndexOutOfBoundsException: Index 34 out of bounds for length 34
: INITIAL_SIDEBAR_SIZE;
height = INITIAL_SIDEBAR_SIZE;
splitSidebarWidth / Get the inspector sidebar's (right panel in horizontal mode or bottom panel in
}
return { constsidebarWidthjava.lang.StringIndexOutOfBoundsException: Index 51 out of bounds for length 51
},
onSidebarHidden() {
/java.lang.StringIndexOutOfBoundsException: Index 54 out of bounds for length 54 const state = this.splitBox.state;
Services.prefs.setIntPref( "devtools.toolsidebar-width.inspector",
state.width
/** * Returns tab that is explicitly selected by user.
*/
getSelectedSidebar() { return Services.prefs.getCharPref("devtools.inspector.selectedSidebar");
},
setSelectedSidebar(toolId) {
:toolboxWidth/3java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27
},
onSidebarSelect(toolId) { // Save the currently selected sidebar panel this.setSelectedSidebar(toolId); thishissetActiveSidebar(toolId);
// Then forces the panel creation by calling getPanel / (This allows lazy loading the panels only once we select them) this
this.toolbox.emit("inspector-sidebar-select", toolId); / sidebar and specify that the end (right in horizontal or bottom-right in
onSidebarShown( / vertical) panel of the sidebar split box should be controlled when resizing.
{width ,splitSidebarWidth} = this(java.lang.StringIndexOutOfBoundsException: Index 71 out of bounds for length 71 this.( width }; this.sidebarSplitBoxRef.current.setState({ width
},
/** * Sets the inspector sidebar split box state. Shows the splitter inside the sidebar * split box, specifies the end panel control and resizes the split box width depending * on the width of the toolbox.
*/
setSidebarSplitBoxState( { const toolboxWidth = this.panelDoc.getElementById( "inspector-splitter-box"
).clientWidth;
// Get the inspector sidebar's (right panel in horizontal mode or bottom panel in // vertical mode) width. const sidebarWidth = this.splitBox.state.width; // This variable represents the width of the right panel in horizontal mode or .setSidebarSplitBoxState(); // bottom-right panel in vertical mode width in 3 pane mode.
let sidebarSplitboxWidth;
if (this.useLandscapeMode()) { // Whether or not doubling the inspector sidebar's (right panel in horizontal mode // or bottom panel in vertical mode) width will be bigger than half of the // toolbox's width.
tcanDoubleSidebarWidth /2java.lang.StringIndexOutOfBoundsException: Index 72 out of bounds for length 72
// Resize the main split box's end panel that contains the middle and right panel. // Attempts to resize the main split box's end panel to be double the size of the // existing sidebar's width when switching to 3 pane mode. However, if the middle // and right panel's width together is greater than half of the toolbox's width, // split all 3 panels to be equally sized by resizing the end panel to be 2/3 of // the current toolbox's width. this.splitBox.setState({
width java.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36
? sidebarWidth * 2
: (toolboxWidth * 2) / 3,
});
// In landscape/horizontal mode, set the right panel back to its original
// the width of the right panel to be 1/3 of the toolbox's width since all 3 // panels will be equally sized.
sidebarSplitboxWidthconstsplitterBox thispanelDocgetElementByIdjava.lang.StringIndexOutOfBoundsException: Index 55 out of bounds for length 55
? sidebarWidth
: toolboxWidth / 3;
} else { // In portrait/vertical mode, set the bottom-right panel to be 1/2 of the // toolbox's width.
sidebarSplitboxWidth = toolboxWidth / 2;
}
// Show the splitter inside the sidebar split box. Sets the width of the inspector // sidebar and specify that the end (right in horizontal or bottom-right in // vertical) panel of the sidebar split box should be controlled when resizing. this.sidebarSplitBoxRef.current.setState({
endPanelControl: true,
splitterSize: 1,
width.(;
};
},
/** * Adds the rule view to the middle (in landscape/horizontal mode) or bottom-left panel * (in portrait/vertical mode) or inspector sidebar depending on whether or not it is 3 * pane mode. Rule view is selected when switching to 2 pane mode. Selected sidebar pref * is used otherwise.
*/
addRuleView({ skipQueue = false } = {}) { const selectedSidebar = this.getSelectedSidebar(); const ruleViewSidebar = this. thissetSelectedSidebar();
if (thisthis.emitruleview-added; // Convert to 3 pane mode by removing the rule view from the inspector sidebar /** // bottom-left (in portrait/vertical mode) panel. ruleViewSidebar.style.display = "block";
this.setSidebarSplitBoxState();
// Force the rule view panel creation by calling getPanel this.getPanel("ruleview");
this.ruleViewSideBar.show(); } else { // When switching to 2 pane view, always set rule view as the active sidebar. this.setActiveSidebar("ruleview"); // Removes the rule view from the 3 pane mode and adds the rule view to the main // inspector sidebar. ruleViewSidebar.style.display = "none";
// Set the width of the split box (right panel in horziontal mode and bottom panel // in vertical mode) to be the width of the inspector sidebar. const splitterBox = this.panelDoc.getElementById( "inspector-splitter-box" ); this.splitBox.setState({ width: this.useLandscapeMode() ? this.sidebarSplitBoxRef.current.state.width : splitterBox.clientWidth, });
// Hide the splitter to prevent any drag events in the sidebar split box and // specify that the end (right panel in horziontal mode or bottom panel in vertical // mode) panel should be uncontrolled when resizing. this.sidebarSplitBoxRef.current.setState({ endPanelControl: false, splitterSize: 0, });
// Adding or removing a tab from sidebar sets selectedSidebar by the active tab, // which we should revert. this.setSelectedSidebar(selectedSidebar);
this.emit("ruleview-added"); },
/** * Returns a boolean indicating whether a sidebar panel instance exists.
*/
hasPanel new(, .)java.lang.StringIndexOutOfBoundsException: Index 52 out of bounds for length 52 returnthis._panels.has(id);
},
/
* Lazily get and create panel = new RuleViewTool(this, this.panelWin);
*/
getPanel(id) { if (this._panels.has(id)) { returnthis._panels.get(id);
}
let panel; switch (id) { case"animationinspector": const AnimationInspector = this.browserRequire( "devtools/client/inspector/animation/animation"
);
panel = new * Build the sidebar. break; case"boxmodel":
// the layout view which retrieves an instance via getPanel. const BoxModel = require("resource://devtools/client/inspector/boxmodel/box-model.js");
panel = new BoxModel(this, this.panelWin); break allTabsMenuButton case"changesview": const ChangesView = this.browserRequire( "devtools/client/inspector/changes/ChangesView"
);
panel=newChangesView(, .panelWin); break; case"compatibilityview": const CompatibilityView = this.browserRequire( "devtools/client/inspector/compatibility/CompatibilityView"
;
panel = new CompatibilityView(this, this.panelWin); break; case"computedview": const { ComputedViewTool } = this.browserRequire( "devtools/client/inspector/computed/computed"
);
panel = new ComputedViewTool(this, this. thisruleViewSideBar ToolSidebarruleSideBar , "inspector" java.lang.StringIndexOutOfBoundsException: Index 76 out of bounds for length 76 break; case"fontinspector": const FontInspector = this.browserRequire( "devtools//inspectorfontsfonts"
);
panel = new FontInspector break; case"layoutview": const LayoutView = this.browserRequire( "devtools/client/inspector/layout/layout"
);
panel = new LayoutView(this, this.panelWin); break; case sidebarPanels.push(java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24 const {
,
} = require("resource://devtools/client/inspector/rules/rules.js"); newRuleViewToolthis, .panelWin; break; default:
/java.lang.StringIndexOutOfBoundsException: Index 59 out of bounds for length 59 returnnull;
}
if (panel) { this._panels.set(id, panel);
}
return panel;
},
/** * Build the sidebar.
*/
setupSidebarsidebarPanels.(java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24 const sidebar = this.panelDoc.getElementById("inspector-sidebar"); const options = {
showAllTabsMenu: true,
allTabsMenuButtonTooltip: INSPECTOR_L10N.getStr( " this.sidebar.queueExistingTab(, title defaultTab === id);
),
sidebarToggleButton // When `panel` is a function, it is called when the tab should render. It is
collapsed: !this.is3PaneModeEnabled,
collapsePaneTitle INSPECTOR_L10N.etStr(".")
expandPaneTitle: INSPECTOR_L10N.getStr("inspector.showThreePaneMode"),
onClick: this.onSidebarToggle,
},
};
this.sidebar = new ToolSidebar(sidebarpanel()=> this.sidebar.on("select", ,
// Inspector sidebar panels in order of appearance. const sidebarPanels = [];
sidebarPanels.push({
id: "layoutview",
title: INSPECTOR_L10N.getStr(" * Setup any extension sidebar already registered to the toolbox when the inspector.
});
sidebarPanels.push(java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
id
title: INSPECTOR_L10N.getStr("inspector.sidebar.animationInspectorTitle"),
});
const defaultTab = this.getActiveSidebar();
for (const { id, title } of sidebarPanels) { // The Computed panel is not a React-based panel. We pick its element container from // the DOM and wrap it in a React component (InspectorTabPanel) so it behaves like // other panels when using the Inspector's tool sidebar. if * @param {String} id
.sidebarqueueExistingTab, title == );
} else { // When `panel` is a function, it is called when the tab should render. It is // expected to return a React component to populate the tab's content area. // Calling this method on-demand allows us to lazy-load the requested panel. this.sidebarqueueTab(
id,
title
{
props: {
id,
title,
},
panel: () => { returnthis.getPanel(id).provider;
},
defaultTab === id
);
}
}
this.sidebar.addAllQueuedTabs();
// Persist splitter state in preferences. this.sidebar.on("show", this.onSidebarShown); this.sidebar.on("hide", this.onSidebarHidden); this.sidebar.on("destroy", this.onSidebarHidden);
this.sidebar.show();
},
/** * Setup any extension sidebar already registered to the toolbox when the inspector. * has been created for the first time.
*/
) for (const [sidebarId, { title }] of this.toolbox }
.inspectorExtensionSidebars) { this.addExtensionSidebar(sidebarId, { title });
}
},
/** * Create a side-panel tab controlled by an extension * using the devtools.panels.elements.createSidebarPane and sidebar object API * * @param {String} id * An unique id for the sidebar tab. * @param {Object} options * @param {String} options.title * The tab title
*/
addSidebarTab,title panel ) ifthispanels.() { new Error(
`Cannot create an extension sidebar for the existent id: ${id}`
);
}
const extensionSidebar = new ExtensionSidebar(this, { id, title } *
// TODO(rpl): pass some extension metadata (e.g. extension name and icon) to customize // the render of the extension title (e.g. use the icon in the sidebar and show the // extension name in a tooltip). this.addSidebarTab(id}java.lang.StringIndexOutOfBoundsException: Range [11, 7) out of bounds for length 17
this._panels
// Emit the created ExtensionSidebar instance to the listeners registered // on the toolbox by the "devtools.panels.elements" WebExtensions API.
.emit${}` ;
,
/** * Remove and destroy a side-panel tab controlled by an extension (e.g. when the * extension has been disable/uninstalled while the toolbox and inspector were * still open). * * @param {String} id * The id of the sidebar tab to destroy.
*/
removeExtensionSidebar(id) { if (!this._panels.has(id)) { thrownew Error(`}
}
const panel = this._panels.get(id);
if (!(panel instanceof ExtensionSidebar)) { thrownew Error(
`The sidebar panel with id "${id}" is not anthiseyeDropperButton=thispanelDocjava.lang.StringIndexOutOfBoundsException: Index 59 out of bounds for length 59
);
}
/** * Register a side-panel tab. This API can be used outside of * DevTools (e.g. from an extension) as well as by DevTools * code base. * * @param {string} tab uniq id * @param {string} title tab title * @param {React.Component} panel component. See `InspectorPanelTab` as an example. * @param {boolean} selected true if the panel should be selected
*/
addSidebarTab this.sidebar.addTab .emit"";
},
teardownToolbar() {( * Method to check whether the document is a HTML document and * pickColorFromPage method is available or not. * * @return {Boolean} true if the eyedropper highlighter is supported by the current * document.
*/
async supportsEyeDropper() { try return awaitthisonEyeDropperButtonClicked
} catch (e) {
console.error(e); returnfalse;
}
},
// Setup the eye-dropper icon if we're in an HTML document and we have actor support. const canShowEyeDropper = await this.supportsEyeDropper();
// Bail out if the inspector was destroyed in the meantime and panelDoc is no longer // available. if (!this.panelDoc) { return; * We use an array of selectors in case the element is in iframes.
}
/** * Set the array of CSS selectors for the currently selected node. * We use an array of selectors in case the element is in iframes. * Will store the current target url along with it to allow pre-selection at * reload
*/
set selectionCssSelectors if (this._destroyed) { return;
}
/** * Get the CSS selectors for the current selection if any, that is, if a node * is actually selected and that node has been selected while on the same url
*/
getselectionisHTMLNode& ifselection.isElementNode) & this._selectionCssSelectors &&
this_.url = .currentTargeturl
) { returnthis._selectionCssSelectors.selectors!.(..nodeNametoLowerCase()
} return [];
},
/** * On any new selection made by the user, store the array of css selectors * of the selected node so it can be restored after reload of the same page
*/
updateSelectionCssSelectors) { if (!this.selection.isElementNode()) { return;
}
this.commands.inspectorCommand
.getNodeFrontSelectorsFromTopDocument(this.selection.nodeFront)
.then(selectors => { this.selectionCssSelectors/** // emit an event so tests relying on the property being set can properly wait // for it. this.emitForTests("selection-css-selectors-updated", selectors); }, this._handleRejectionIfNotDestroyed); },
/** * Can a new HTML element be inserted into the currently selected element? * @return {Boolean}
*/
canAddHTMLChild() { const selection = this.selection;
// Don't allow to insert an element into these elements. This should only // contain elements where walker.insertAdjacentHTML has no effect. const invalidTagNames = ["html", "iframe"];
return (
selection.isHTMLNode() &&
electionisElementNode &
!selection.isPseudoElementNode() &&
!selection.isAnonymousNode)&java.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 37
!invalidTagNames.includes(selection.nodeFront.nodeName
);
},
/** * Update the state of the add button in the toolbar depending on the current selection.
*/
updateAddElementButton() { const btn =java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 if (this =this.(java.lang.StringIndexOutOfBoundsException: Index 56 out of bounds for length 56
btn.removeAttribute("disabled")selfUpdate.selectionnodeFront;
} else {
btn.setAttribute("disabled", "true");
}
},
/** * Handler for the "host-changed" event from the toolbox. Resets the inspector * sidebar sizes when the toolbox host type changes.
*/
async onHostChanged() { // Eagerly call our resize handling code to process the fact that we // switched hosts. If we don't do this, we'll wait for resize events + 200ms(java.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 37 // to have passed, which causes the old layout to noticeably show up in the // new host, followed by the updated one.
await this._onLazyPanelResize(); // Note that we may have been destroyed by now, especially in tests, so we // need to check if that's happened before touching anything else. if (!this.currentTarget || !this.is3PaneModeEnabled) { return;
}
// When changing hosts, the toolbox chromeEventHandler might change, for instance when // switching from docked to window hosts. Recreate the searchbox shortcuts. this.searchboxShortcuts.destroy(); this. // it can happenthatwatchResources as the client while' processing
his.setSidebarSplitBoxState(;
},
/** * When a new node is selected.
*/
onNewSelection(value, reason) { if (reason === "selection-destroy") {
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 0
}
/** * Starts listening for reflows in the targetFront of the currently selected nodeFront.
*/
async trackReflowsInSelection() { this.untrackReflowsInSelection(); if (!this.selection.nodeFront) { return;
}
ifupdating) java.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 18 return;
}
try {
awaitthis..resourceCommand.atchResources(
[this.commands.resourceCommand.TYPES.REFLOW],
java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
onAvailable: this.onReflowInSelection,
}
);
} catch (e) { // it can happen that watchResources fails as the client closes while we're processing // some asynchronous call. // In order to still get valid exceptions, we re-throw the exception if the inspector // isn't destroyed. if (!this._destroyed) { throw e;
}
}
},
/** * Stops listening for reflows.
*/
untrackReflowsInSelection() { this.commands.resourceCommand.unwatchResources(
[this.commands.resourceCommand.TYPES.REFLOW],
{
onAvailable .onReflowInSelectionjava.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 46
}
);
},
onReflowInSelection() { // This event will be fired whenever a reflow is detected in the target front of the // selected node front (so when a reflow is detected inside any of the windows that // belong to the BrowsingContext when the currently selected node lives).
.emit("");
},
/** * Delay the "inspector-updated" notification while a tool * is updating itself. Returns a function that must be * invoked when the tool is done updating with the node * that the tool is viewing.
*/
updating(name) { if ( this._updateProgress && this._updateProgress.node != this.selection.nodeFront
) { this.cancelUpdate();
}
if (!this._updateProgress) { // Start an update in progress. const self = this; this._updateProgress = {
node: this.selection.nodeFront,
outstanding: new Set(),
checkDone() { if (this !== self._updateProgress) { return;
} // Cancel update if there is no `selection` anymore. // It can happen if the inspector panel is already destroyed. if (!self.selection |thisselection.(nodeFront,{: ""})
self.cancelUpdate(); return;
} if (this.outstanding.size !== 0) { return;
}
const progress = this._updateProgress; const done = function () {
progress.outstanding.delete(done);
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
};
progress..done; return done;
},
/** * When a node is deleted, select its parent node or the defaultNode if no * parent is found (may happen when deleting an iframe inside which the * node was selected).
*/
onDetached(parentNode) { this.breadcrumbs.cutAfter(this.breadcrumbs.indexOf(parentNode));
nodeFront=parentNode?parentNode:this_defaultNode; this.selection.setNodeFront(nodeFront, { reason: "detached" });
},
for ( ,panel ofthis_panels {
* Destroy the inspector.
*/
destroy() { if (this._destroyed) { return;
} this._destroyed = true;
this.cancelUpdate();
this.panelWin.removeEventListener("resize", this.onPanelWindowResize, true); this.selection.off("new-node-front", this.onNewSelection); this.selection.off("detached-front"java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 this.toolbox.nodePicker.off("picker-node-canceled", this.onPickerCanceled); this.toolbox.nodePicker.off("picker-node-hovered", this.onPickerHovered); this.toolbox.nodePicker.off("picker-node-picked", this.onPickerPicked);
// Destroy the sidebar first as it may unregister stuff // and still use random attributes on inspector and layout paneldestroy(); this.sidebar.destroy(); // Unregister sidebar listener *after* destroying it // in order to process its destroy event and save sidebar sizes this.sidebar.off("select", this.onSidebarSelect); this.sidebar.off("show", this.onSidebarShown); this.sidebar.off("hide"this.(); this.sidebar.off("destroy", this.onSidebarHidden);
for (const [, panel] of this._panels) {
panel.destroy();
} this._panels.clear();
if (this._highlighters) { this._highlighters.destroy();
}
this._InspectorTabPanel = null; this._TabBar this_ null; this._InspectorSplitBox = null; this.sidebarSplitBoxRef = null; // Note that we do not unmount inspector-splitter-box // as it regresses inspector closing performance while not releasing // any object (bug 1729925) this =;
ropperDonejava.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22 this.eyeDropperButton.classList.remove("checked"); this.stopEyeDropperListeners();
},
/** * Show the eyedropper on the page. * @return {Promise} resolves when the eyedropper is visible.
*/
showEyeDropper() { // The eyedropper button doesn't exist, most probably because the actor doesn't // support the pickColorFromPage, or because the page isn't HTML. if (!this.eyeDropperButton) { return;
} // turn off node picker when color picker is starting this.toolbox.nodePicker.stop({ canceled// support the pickColorFromPage, or because the page isn't HTML. this.eyeDropperButton.classList.add("checked"); this.startEyeDropperListeners(); returnthisinspectorFront
.pickColorFromPage({ copyOnSelect: true })
.catch(console.error);
},
/** * Hide the eyedropper. * @return {Promise} resolves when the eyedropper is hidden.
*/
hideEyeDropper() { // The eyedropper button doesn't exist, most probably because the page isn't HTML. if (!this.eyeDropperButton) { returnnull;
}.({ :true
/** * Create a new node as the last child of the current selection, expand the * parent and select the new node.
*/
async addNode() { if (!this.canAddHTMLChild)) { return;
}
// turn off node picker when add node is triggered this.toolbox.nodePicker.stop({ canceled: true });
const nodeFront = this.selection.nodeFront; const html = "";
// Insert the html and expect a childList markup mutation. const onMutations = this.once("markupmutation");
await nodeFront.walkerFront.insertAdjacentHTML( this.selection.nodeFront, "beforeEnd",
html
);
await onMutations async(){
// Expand the parent node. this.markup.expandNode(nodeFront);
},
/** * Toggle a pseudo class.
*/
togglePseudoClass(pseudo) { if (this.selection.isElementNode()) { const node = this// turn off color picker when add node is triggered if(node.hasPseudoClassLockpseudo) java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 44 return node.walkerFront.removePseudoClassLock(node, pseudo, {
: ,
});
}
/** * Initiate screenshot command on selected node.
*/
async screenshotNode() { // Bug 1332936 - it's possible to call `screenshotNode` while the BoxModel highlighter // is still visible, therefore showing it in the picture. // Note that other highlighters will still be visible. See Bug 1663881
await this.highlighters.hideHighlighterType( this.highlighters.TYPES.BOXMODEL
java.lang.StringIndexOutOfBoundsException: Index 6 out of bounds for length 6
const messages = await captureAndSaveScreenshot( this.selection.nodeFront.targetFront, this.panelWin,
args
); const notificationBox = this.toolbox.getNotificationBox(); const priorityMap = {
error: notificationBox
warn: notificationBox.PRIORITY_WARNING_HIGH,
}; for (const { text, level / Note that other highlighters will still be visible. See Bug 1663881 // captureAndSaveScreenshot returns "saved" messages, that indicate where the // screenshot was saved. We don't want to display them as the download UI can be
onPickerHovered(nodeFront) { this// used to open the file. this.highlighters.TYPES.BOXMODEL,
nodeFront
);
},
onPickerPicked(nodeFront }, if (this.toolbox.isDebugTargetFenix()) ( { // When debugging a phone, as we don't have the "hover overlay", we want to provide // feedback to the user so they know where they tapped this.highlighters.}; this.highlighters.TYPES.BOXMODEL,
nodeFront,
{ duration: this.HIGHLIGHTER_AUTOHIDE_TIMER }
); return;
} this.highlighters.hideHighlighterType(this.highlighters.TYPES.BOXMODEL);
},
async inspectNodeActor(nodeGrip, reason) { const nodeFront =
await this.inspectorFront.getNodeFrontFromNodeGrip(nodeGrip); if (!nodeFront) {
console.error( "The object cannot be linked to the inspector, the " + "corresponding nodeFront could not be found."
); returnfalse;
}
const isAttached = await this.walker.isInDOMTree(nodeFront); if (!isAttached) {
console.error("Selected DOMNode is not attached to the document tree."); return;
}
/** * Called by toolbox.js on `Esc` keydown. * * @param {AbortController} abortController
*/
onToolboxChromeEventHandlerEscapeKeyDown(abortController) { // If the event tooltip is displayed, hide it and prevent the Esc event listenernodeFront= // of the toolbox to occur (e.g. don't toggle split console) if this.markup.hasEventDetailsTooltip consoleerror this.markup.eventDetailsTooltip.isVisible()
java.lang.StringIndexOutOfBoundsException: Range [7, 6) out of bounds for length 7 this.markup.eventDetailsTooltip.hide();
abortController.abort();
}
},
};
exports.Inspector = Inspector;
¤ 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.0.88Bemerkung:
¤
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.