blob: bdb93fdfade25edacd26be789c4e405072607289 [file] [log] [blame]
// Copyright 2020 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 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
import 'chrome://resources/cr_elements/cr_icons_css.m.js';
import 'chrome://resources/cr_elements/mwb_shared_icons.js';
import 'chrome://resources/cr_elements/mwb_shared_vars.js';
import 'chrome://resources/cr_elements/shared_vars_css.m.js';
import './strings.m.js';
import {MouseHoverableMixin, MouseHoverableMixinInterface} from 'chrome://resources/cr_elements/mouse_hoverable_mixin.js';
import {getFaviconForPageURL} from 'chrome://resources/js/icon.m.js';
import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
import {highlight} from 'chrome://resources/js/search_highlight_utils.js';
import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {ariaLabel, TabData, TabItemType} from './tab_data.js';
import {Tab} from './tab_search.mojom-webui.js';
/**
* @constructor
* @extends PolymerElement
* @implements {MouseHoverableMixinInterface}
* @appliesMixin MouseHoverableMixin
*/
const TabSearchItemBase = MouseHoverableMixin(PolymerElement);
/** @polymer */
export class TabSearchItem extends TabSearchItemBase {
static get is() {
return 'tab-search-item';
}
static get template() {
return html`{__html_template__}`;
}
static get properties() {
return {
/** @type {!TabData} */
data: {
type: Object,
observer: 'dataChanged_',
},
/** @private {boolean} */
buttonRipples_: {
type: Boolean,
value: () => loadTimeData.getBoolean('useRipples'),
},
/** @type {number} */
index: Number,
};
}
/**
* @param {!TabItemType} type
* @return {boolean} Whether a close action can be performed on the item.
*/
isCloseable_(type) {
return type === TabItemType.OPEN;
}
/**
* @param {!Event} e
* @private
*/
onItemClose_(e) {
this.dispatchEvent(new CustomEvent('close'));
e.stopPropagation();
}
/**
* @param {!Tab} tab
* @return {string}
* @private
*/
faviconUrl_(tab) {
return tab.faviconUrl ?
`url("${tab.faviconUrl}")` :
getFaviconForPageURL(
tab.isDefaultFavicon ? 'chrome://newtab' : tab.url, false);
}
/**
* @private
*/
dataChanged_() {
this.highlightText_(
/** @type {!HTMLElement} */ (this.$.primaryText), this.data.tab.title,
this.data.titleHighlightRanges);
this.highlightText_(
/** @type {!HTMLElement} */ (this.$.secondaryText), this.data.hostname,
this.data.hostnameHighlightRanges);
// Show chrome:// if it's a chrome internal url
let secondaryLabel = this.data.hostname;
let protocol = '';
try {
protocol = new URL(this.data.tab.url).protocol;
} catch (e) {
// TODO(crbug.com/1186409): Remove this after we root cause the issue
console.error(
`Error parsing URL on Tab Search: url=${this.data.tab.url}`);
}
if (protocol === 'chrome:') {
/** @type {!HTMLElement} */ (this.$.secondaryText)
.prepend(document.createTextNode('chrome://'));
secondaryLabel = `chrome://${secondaryLabel}`;
}
}
/**
*
* @param {!HTMLElement} container
* @param {string} text
* @param {!Array<!{start:number, length:number}>|undefined} ranges
*/
highlightText_(container, text, ranges) {
container.textContent = '';
const node = document.createTextNode(text);
container.appendChild(node);
if (ranges) {
const result = highlight(node, ranges, true);
// Delete default highlight style.
result.querySelectorAll('.search-highlight-hit').forEach(e => {
e.style = '';
});
}
}
/**
* @param {!TabData} tabData
* @return {string}
* @private
*/
ariaLabelForText_(tabData) {
return ariaLabel(tabData);
}
/**
* @param {string} title
* @return {string}
* @private
*/
ariaLabelForButton_(title) {
return `${loadTimeData.getString('closeTab')} ${title}`;
}
}
customElements.define(TabSearchItem.is, TabSearchItem);