| // Copyright 2018 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'chrome://resources/cr_elements/cr_button/cr_button.js'; |
| import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; |
| import 'chrome://resources/cr_elements/cr_hidden_style.css.js'; |
| import './advanced_settings_item.js'; |
| import './print_preview_search_box.js'; |
| import './print_preview_shared.css.js'; |
| import './print_preview_vars.css.js'; |
| import '/strings.m.js'; |
| |
| import type {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; |
| import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js'; |
| import {removeHighlights} from 'chrome://resources/js/search_highlight_utils.js'; |
| import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; |
| |
| import type {Destination} from '../data/destination.js'; |
| import {MetricsContext, PrintSettingsUiBucket} from '../metrics.js'; |
| |
| import {getTemplate} from './advanced_settings_dialog.html.js'; |
| import type {PrintPreviewSearchBoxElement} from './print_preview_search_box.js'; |
| import {SettingsMixin} from './settings_mixin.js'; |
| |
| export interface PrintPreviewAdvancedSettingsDialogElement { |
| $: { |
| dialog: CrDialogElement, |
| searchBox: PrintPreviewSearchBoxElement, |
| }; |
| } |
| |
| const PrintPreviewAdvancedSettingsDialogElementBase = |
| I18nMixin(SettingsMixin(PolymerElement)); |
| |
| export class PrintPreviewAdvancedSettingsDialogElement extends |
| PrintPreviewAdvancedSettingsDialogElementBase { |
| static get is() { |
| return 'print-preview-advanced-settings-dialog'; |
| } |
| |
| static get template() { |
| return getTemplate(); |
| } |
| |
| static get properties() { |
| return { |
| destination: Object, |
| |
| searchQuery_: { |
| type: Object, |
| value: null, |
| }, |
| |
| hasMatching_: { |
| type: Boolean, |
| notify: true, |
| computed: 'computeHasMatching_(searchQuery_)', |
| }, |
| }; |
| } |
| |
| destination: Destination; |
| private searchQuery_: RegExp|null; |
| private hasMatching_: boolean; |
| private highlights_: HTMLElement[] = []; |
| private bubbles_: Map<HTMLElement, number> = new Map(); |
| private metrics_: MetricsContext = MetricsContext.printSettingsUi(); |
| |
| override ready() { |
| super.ready(); |
| |
| this.addEventListener('keydown', e => this.onKeydown_(e as KeyboardEvent)); |
| } |
| |
| override connectedCallback() { |
| super.connectedCallback(); |
| |
| this.metrics_.record(PrintSettingsUiBucket.ADVANCED_SETTINGS_DIALOG_SHOWN); |
| this.$.dialog.showModal(); |
| } |
| |
| private onKeydown_(e: KeyboardEvent) { |
| e.stopPropagation(); |
| const searchInput = this.$.searchBox.getSearchInput(); |
| const eventInSearchBox = e.composedPath().includes(searchInput); |
| if (e.key === 'Escape' && |
| (!eventInSearchBox || !searchInput.value.trim())) { |
| this.$.dialog.cancel(); |
| e.preventDefault(); |
| return; |
| } |
| |
| if (e.key === 'Enter' && !eventInSearchBox) { |
| const activeElementTag = (e.composedPath()[0] as HTMLElement).tagName; |
| if (['CR-BUTTON', 'SELECT'].includes(activeElementTag)) { |
| return; |
| } |
| this.onApplyButtonClick_(); |
| e.preventDefault(); |
| return; |
| } |
| } |
| |
| /** |
| * @return Whether there is more than one vendor item to display. |
| */ |
| private hasMultipleItems_(): boolean { |
| return this.destination.capabilities!.printer.vendor_capability!.length > 1; |
| } |
| |
| /** |
| * @return Whether there is a setting matching the query. |
| */ |
| private computeHasMatching_(): boolean { |
| if (!this.shadowRoot) { |
| return true; |
| } |
| |
| removeHighlights(this.highlights_); |
| this.bubbles_.forEach((_number, bubble) => bubble.remove()); |
| this.highlights_ = []; |
| this.bubbles_.clear(); |
| |
| const listItems = this.shadowRoot!.querySelectorAll( |
| 'print-preview-advanced-settings-item'); |
| let hasMatch = false; |
| listItems.forEach(item => { |
| const matches = item.hasMatch(this.searchQuery_); |
| item.hidden = !matches; |
| hasMatch = hasMatch || matches; |
| this.highlights_.push( |
| ...item.updateHighlighting(this.searchQuery_, this.bubbles_)); |
| }); |
| return hasMatch; |
| } |
| |
| /** |
| * @return Whether the no matching settings hint should be shown. |
| */ |
| private shouldShowHint_(): boolean { |
| return !!this.searchQuery_ && !this.hasMatching_; |
| } |
| |
| private onCloseOrCancel_() { |
| if (this.searchQuery_) { |
| this.$.searchBox.setValue(''); |
| } |
| if (this.$.dialog.getNative().returnValue === 'success') { |
| this.metrics_.record( |
| PrintSettingsUiBucket.ADVANCED_SETTINGS_DIALOG_CANCELED); |
| } |
| } |
| |
| private onCancelButtonClick_() { |
| this.$.dialog.cancel(); |
| } |
| |
| private onApplyButtonClick_() { |
| const settingsValues: {[settingName: string]: any} = {}; |
| const itemList = this.shadowRoot!.querySelectorAll( |
| 'print-preview-advanced-settings-item'); |
| itemList.forEach(item => { |
| settingsValues[item.capability.id] = item.getCurrentValue(); |
| }); |
| this.setSetting('vendorItems', settingsValues); |
| this.$.dialog.close(); |
| } |
| |
| close() { |
| this.$.dialog.close(); |
| } |
| |
| private isSearching_(): string { |
| return this.searchQuery_ ? 'searching' : ''; |
| } |
| } |
| |
| declare global { |
| interface HTMLElementTagNameMap { |
| 'print-preview-advanced-settings-dialog': |
| PrintPreviewAdvancedSettingsDialogElement; |
| } |
| } |
| |
| customElements.define( |
| PrintPreviewAdvancedSettingsDialogElement.is, |
| PrintPreviewAdvancedSettingsDialogElement); |