blob: 0b16488f0ca6db1deb1565dcb155abc27ede32aa [file] [log] [blame]
John Lee912fb9c02019-08-02 01:28:211// Copyright 2019 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
John Lee2bafb2f2019-08-21 19:20:035import {getFavicon, getFaviconForPageURL} from 'chrome://resources/js/icon.m.js';
6
John Lee912fb9c02019-08-02 01:28:217import {CustomElement} from './custom_element.js';
John Lee7d416b782019-08-12 22:32:138import {TabsApiProxy} from './tabs_api_proxy.js';
John Lee912fb9c02019-08-02 01:28:219
John Leea97ceab6f2019-09-04 22:26:4610export const DEFAULT_ANIMATION_DURATION = 125;
11
John Lee3f8dae92019-08-09 22:37:0912export class TabElement extends CustomElement {
John Lee912fb9c02019-08-02 01:28:2113 static get template() {
14 return `{__html_template__}`;
15 }
16
John Lee3f8dae92019-08-09 22:37:0917 constructor() {
18 super();
19
John Lee7d416b782019-08-12 22:32:1320 /** @private {!HTMLElement} */
21 this.closeButtonEl_ =
22 /** @type {!HTMLElement} */ (this.shadowRoot.querySelector('#close'));
23
John Lee2bafb2f2019-08-21 19:20:0324 /** @private {!HTMLElement} */
25 this.faviconEl_ =
26 /** @type {!HTMLElement} */ (this.shadowRoot.querySelector('#favicon'));
27
Collin Bakere21f723d2019-09-05 20:05:4128 /** @private {!HTMLElement} */
29 this.thumbnailContainer_ =
30 /** @type {!HTMLElement} */ (
31 this.shadowRoot.querySelector('#thumbnail'));
32
33 /** @private {!Image} */
34 this.thumbnail_ =
35 /** @type {!Image} */ (this.shadowRoot.querySelector('#thumbnailImg'));
36
John Lee3f8dae92019-08-09 22:37:0937 /** @private {!Tab} */
38 this.tab_;
39
John Lee7d416b782019-08-12 22:32:1340 /** @private {!TabsApiProxy} */
41 this.tabsApi_ = TabsApiProxy.getInstance();
42
John Lee3f8dae92019-08-09 22:37:0943 /** @private {!HTMLElement} */
44 this.titleTextEl_ = /** @type {!HTMLElement} */ (
45 this.shadowRoot.querySelector('#titleText'));
John Lee3f8dae92019-08-09 22:37:0946
John Lee8e253602019-08-14 22:22:5147 this.addEventListener('click', this.onClick_.bind(this));
John Lee7d416b782019-08-12 22:32:1348 this.closeButtonEl_.addEventListener('click', this.onClose_.bind(this));
John Lee912fb9c02019-08-02 01:28:2149 }
John Lee3f8dae92019-08-09 22:37:0950
51 /** @return {!Tab} */
52 get tab() {
53 return this.tab_;
54 }
55
56 /** @param {!Tab} tab */
57 set tab(tab) {
John Lee8e253602019-08-14 22:22:5158 this.toggleAttribute('active', tab.active);
John Leed7611b22019-08-26 21:26:0359 this.toggleAttribute('pinned', tab.pinned);
John Lee8e253602019-08-14 22:22:5160
John Lee3f8dae92019-08-09 22:37:0961 if (!this.tab_ || this.tab_.title !== tab.title) {
62 this.titleTextEl_.textContent = tab.title;
63 }
64
John Lee2bafb2f2019-08-21 19:20:0365 if (tab.favIconUrl &&
66 (!this.tab_ || this.tab_.favIconUrl !== tab.favIconUrl)) {
67 this.faviconEl_.style.backgroundImage = getFavicon(tab.favIconUrl);
68 } else if (!this.tab_ || this.tab_.url !== tab.url) {
69 this.faviconEl_.style.backgroundImage =
70 getFaviconForPageURL(tab.url, false);
71 }
72
John Lee3f8dae92019-08-09 22:37:0973 // Expose the ID to an attribute to allow easy querySelector use
74 this.setAttribute('data-tab-id', tab.id);
75
Collin Bakere21f723d2019-09-05 20:05:4176 if (!this.tab_ || this.tab_.id !== tab.id) {
77 // Request thumbnail updates
78 chrome.send('addTrackedTab', [tab.id]);
79 }
80
John Lee3f8dae92019-08-09 22:37:0981 this.tab_ = Object.freeze(tab);
82 }
John Lee7d416b782019-08-12 22:32:1383
Collin Bakere21f723d2019-09-05 20:05:4184 /**
85 * @param {string} imgData
86 */
87 updateThumbnail(imgData) {
88 this.thumbnail_.src = imgData;
89 }
90
John Lee7d416b782019-08-12 22:32:1391 /** @private */
John Lee8e253602019-08-14 22:22:5192 onClick_() {
John Lee7d416b782019-08-12 22:32:1393 if (!this.tab_) {
94 return;
95 }
96
John Lee8e253602019-08-14 22:22:5197 this.tabsApi_.activateTab(this.tab_.id);
98 }
99
100 /**
101 * @param {!Event} event
102 * @private
103 */
104 onClose_(event) {
105 if (!this.tab_) {
106 return;
107 }
108
109 event.stopPropagation();
John Lee7d416b782019-08-12 22:32:13110 this.tabsApi_.closeTab(this.tab_.id);
111 }
John Leea97ceab6f2019-09-04 22:26:46112
113 /**
114 * @return {!Promise}
115 */
116 slideIn() {
117 return new Promise(resolve => {
118 const animation = this.animate(
119 [
120 {maxWidth: 0, opacity: 0},
121 {maxWidth: '280px', opacity: 1},
122 ],
123 {
124 duration: DEFAULT_ANIMATION_DURATION,
125 fill: 'forwards',
126 });
127 animation.onfinish = resolve;
128 });
129 }
130
131 /**
132 * @return {!Promise}
133 */
134 slideOut() {
135 return new Promise(resolve => {
136 const animation = this.animate(
137 [
138 {maxWidth: '280px', opacity: 1},
139 {maxWidth: 0, opacity: 0},
140 ],
141 {
142 duration: DEFAULT_ANIMATION_DURATION,
143 fill: 'forwards',
144 });
145 animation.onfinish = () => {
146 this.remove();
147 resolve();
148 };
149 });
150 }
John Lee912fb9c02019-08-02 01:28:21151}
152
John Lee3f8dae92019-08-09 22:37:09153customElements.define('tabstrip-tab', TabElement);