| // Copyright 2016 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import '../cr_icon_button/cr_icon_button.m.js'; |
| import '../cr_icons_css.m.js'; |
| import '../icons.m.js'; |
| import '../shared_style_css.m.js'; |
| import '../shared_vars_css.m.js'; |
| import '//resources/polymer/v3_0/paper-spinner/paper-spinner-lite.js'; |
| |
| import {DomIf, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; |
| |
| import {CrSearchFieldMixin} from '../cr_search_field/cr_search_field_mixin.js'; |
| |
| import {getTemplate} from './cr_toolbar_search_field.html.js'; |
| |
| export interface CrToolbarSearchFieldElement { |
| $: { |
| searchInput: HTMLInputElement, |
| spinnerTemplate: DomIf, |
| }; |
| } |
| |
| const CrToolbarSearchFieldElementBase = CrSearchFieldMixin(PolymerElement); |
| |
| |
| export class CrToolbarSearchFieldElement extends |
| CrToolbarSearchFieldElementBase { |
| static get is() { |
| return 'cr-toolbar-search-field'; |
| } |
| |
| static get template() { |
| return getTemplate(); |
| } |
| |
| static get properties() { |
| return { |
| narrow: { |
| type: Boolean, |
| reflectToAttribute: true, |
| }, |
| |
| showingSearch: { |
| type: Boolean, |
| value: false, |
| notify: true, |
| observer: 'showingSearchChanged_', |
| reflectToAttribute: true, |
| }, |
| |
| autofocus: { |
| type: Boolean, |
| value: false, |
| reflectToAttribute: true, |
| }, |
| |
| // When true, show a loading spinner to indicate that the backend is |
| // processing the search. Will only show if the search field is open. |
| spinnerActive: {type: Boolean, reflectToAttribute: true}, |
| |
| isSpinnerShown_: { |
| type: Boolean, |
| computed: 'computeIsSpinnerShown_(spinnerActive, showingSearch)', |
| }, |
| |
| searchFocused_: {type: Boolean, value: false}, |
| }; |
| } |
| |
| narrow: boolean; |
| showingSearch: boolean; |
| override autofocus: boolean; |
| spinnerActive: boolean; |
| private isSpinnerShown_: boolean; |
| private searchFocused_: boolean; |
| |
| override ready() { |
| super.ready(); |
| |
| this.addEventListener('click', e => this.showSearch_(e)); |
| } |
| |
| override getSearchInput(): HTMLInputElement { |
| return this.$.searchInput; |
| } |
| |
| isSearchFocused(): boolean { |
| return this.searchFocused_; |
| } |
| |
| showAndFocus() { |
| this.showingSearch = true; |
| this.focus_(); |
| } |
| |
| override onSearchTermInput() { |
| super.onSearchTermInput(); |
| this.showingSearch = this.hasSearchText || this.isSearchFocused(); |
| } |
| |
| private onSearchIconClicked_() { |
| this.dispatchEvent(new CustomEvent( |
| 'search-icon-clicked', {bubbles: true, composed: true})); |
| } |
| |
| private focus_() { |
| this.getSearchInput().focus(); |
| } |
| |
| private computeIconTabIndex_(narrow: boolean): number { |
| return narrow && !this.hasSearchText ? 0 : -1; |
| } |
| |
| private computeIconAriaHidden_(narrow: boolean): string { |
| return Boolean(!narrow || this.hasSearchText).toString(); |
| } |
| |
| private computeIsSpinnerShown_(): boolean { |
| const showSpinner = this.spinnerActive && this.showingSearch; |
| if (showSpinner) { |
| this.$.spinnerTemplate.if = true; |
| } |
| return showSpinner; |
| } |
| |
| private onInputFocus_() { |
| this.searchFocused_ = true; |
| } |
| |
| private onInputBlur_() { |
| this.searchFocused_ = false; |
| if (!this.hasSearchText) { |
| this.showingSearch = false; |
| } |
| } |
| |
| private onSearchTermKeydown_(e: KeyboardEvent) { |
| if (e.key === 'Escape') { |
| this.showingSearch = false; |
| } |
| } |
| |
| private showSearch_(e: Event) { |
| if (e.target !== this.shadowRoot!.querySelector('#clearSearch')) { |
| this.showingSearch = true; |
| } |
| } |
| |
| private clearSearch_() { |
| this.setValue(''); |
| this.focus_(); |
| this.spinnerActive = false; |
| } |
| |
| private showingSearchChanged_(_current: boolean, previous?: boolean) { |
| // Prevent unnecessary 'search-changed' event from firing on startup. |
| if (previous === undefined) { |
| return; |
| } |
| |
| if (this.showingSearch) { |
| this.focus_(); |
| return; |
| } |
| |
| this.setValue(''); |
| this.getSearchInput().blur(); |
| } |
| } |
| |
| declare global { |
| interface HTMLElementTagNameMap { |
| 'cr-toolbar-search-field': CrToolbarSearchFieldElement; |
| } |
| } |
| |
| customElements.define( |
| CrToolbarSearchFieldElement.is, CrToolbarSearchFieldElement); |