chrome-devtools-frontend
Version:
Chrome DevTools UI
146 lines (133 loc) • 5.3 kB
text/typescript
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import '../../ui/legacy/legacy.js';
import * as i18n from '../../core/i18n/i18n.js';
import type * as SDK from '../../core/sdk/sdk.js';
import type * as UI from '../../ui/legacy/legacy.js';
import {html, nothing, render} from '../../ui/lit/lit.js';
import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
import {AccessibilitySubPane} from './AccessibilitySubPane.js';
const UIStrings = {
/**
* @description Name of a tool which allows the developer to view the contents of the page in the
* 'source order' (the order in which the HTML elements show up in the source code). In the
* Accessibility panel.
*/
sourceOrderViewer: 'Source Order Viewer',
/**
* @description Text in Source Order Viewer of the Accessibility panel shown when the selected node has no child elements
*/
noSourceOrderInformation: 'No source order information available',
/**
* @description Text in Source Order Viewer of the Accessibility panel shown when the selected node has many child elements
*/
thereMayBeADelayInDisplaying: 'There may be a delay in displaying source order for elements with many children',
/**
* @description Checkbox label in Source Order Viewer of the Accessibility panel. Source order
* means the order in which the HTML elements show up in the source code.
*/
showSourceOrder: 'Show source order',
} as const;
const str_ = i18n.i18n.registerUIStrings('panels/accessibility/SourceOrderView.ts', UIStrings);
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
const MAX_CHILD_ELEMENTS_THRESHOLD = 300;
interface ViewInput {
childCount: number;
showSourceOrder: boolean|undefined;
onShowSourceOrderChanged: (showSourceOrder: boolean) => void;
}
type View = (input: ViewInput, output: unknown, target: HTMLElement) => void;
const DEFAULT_VIEW: View = (input, _output, target) => {
function onShowSourceOrderChanged(event: Event): void {
const checkbox = event.currentTarget as UI.UIUtils.CheckboxLabel;
input.onShowSourceOrderChanged(checkbox.checked);
event.consume();
}
// clang-format off
render(html`
${input.showSourceOrder === undefined
? html`
<div class="gray-info-message info-message-overflow">
${i18nString(UIStrings.noSourceOrderInformation)}
</div>
`
: html`
${input.childCount >= MAX_CHILD_ELEMENTS_THRESHOLD
? html`
<div class="gray-info-message info-message-overflow"
id="source-order-warning">
${i18nString(UIStrings.thereMayBeADelayInDisplaying)}
</div>
`
: nothing
}
<devtools-checkbox class="source-order-checkbox"
jslog=${VisualLogging.toggle().track({click: true})}
?checked=${input.showSourceOrder}
@change=${onShowSourceOrderChanged}>
${i18nString(UIStrings.showSourceOrder)}
</devtools-checkbox>
`
}
`, target);
// clang-format on
};
export class SourceOrderPane extends AccessibilitySubPane {
#childCount = 0;
#showSourceOrder: boolean|undefined = undefined;
readonly #view: View;
constructor(view: View = DEFAULT_VIEW) {
super({
title: i18nString(UIStrings.sourceOrderViewer),
viewId: 'source-order-viewer',
jslog: `${VisualLogging.section('source-order-viewer')}`,
});
this.#view = view;
}
async setNodeAsync(node: SDK.DOMModel.DOMNode|null): Promise<void> {
if (this.nodeInternal && this.#showSourceOrder) {
this.nodeInternal.domModel().overlayModel().hideSourceOrderInOverlay();
}
super.setNode(node);
this.#childCount = this.nodeInternal?.childNodeCount() ?? 0;
if (!this.nodeInternal || !this.#childCount) {
this.#showSourceOrder = undefined;
} else {
if (!this.nodeInternal.children()) {
await this.nodeInternal.getSubtree(1, false);
}
const children = this.nodeInternal.children() as SDK.DOMModel.DOMNode[];
if (!children.some(child => child.nodeType() === Node.ELEMENT_NODE)) {
this.#showSourceOrder = undefined;
} else if (this.#showSourceOrder === undefined) {
this.#showSourceOrder = false;
}
if (this.#showSourceOrder) {
this.nodeInternal.domModel().overlayModel().highlightSourceOrderInOverlay(this.nodeInternal);
}
}
this.requestUpdate();
}
override async performUpdate(): Promise<void> {
const onShowSourceOrderChanged = (showSourceOrder: boolean): void => {
if (!this.nodeInternal) {
this.#showSourceOrder = undefined;
return;
}
if (showSourceOrder) {
this.nodeInternal.domModel().overlayModel().highlightSourceOrderInOverlay(this.nodeInternal);
} else {
this.nodeInternal.domModel().overlayModel().hideSourceOrderInOverlay();
}
this.#showSourceOrder = showSourceOrder;
};
const input = {
childCount: this.#childCount,
showSourceOrder: this.#showSourceOrder,
onShowSourceOrderChanged,
};
const output = undefined;
this.#view(input, output, this.contentElement);
}
}