Backed out changeset aa5fc411278d (bug 1876522) for causing failures on browser_tab_t...
[gecko.git] / browser / components / syncedtabs / SyncedTabsDeckView.sys.mjs
blobaacae71fa57faf757fc031677aa475ebe056f245
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 /**
6  * SyncedTabsDeckView
7  *
8  * Instances of SyncedTabsDeckView render DOM nodes from a given state.
9  * No state is kept internaly and the DOM will completely
10  * rerender unless the state flags `isUpdatable`, which helps
11  * make small changes without the overhead of a full rerender.
12  */
13 export const SyncedTabsDeckView = function (window, tabListComponent, props) {
14   this.props = props;
16   this._window = window;
17   this._doc = window.document;
19   this._tabListComponent = tabListComponent;
20   this._deckTemplate = this._doc.getElementById("deck-template");
21   this.container = this._doc.createElement("div");
24 SyncedTabsDeckView.prototype = {
25   render(state) {
26     if (state.isUpdatable) {
27       this.update(state);
28     } else {
29       this.create(state);
30     }
31   },
33   create(state) {
34     let deck = this._doc.importNode(
35       this._deckTemplate.content,
36       true
37     ).firstElementChild;
38     this._clearChilden();
40     let tabListWrapper = this._doc.createElement("div");
41     tabListWrapper.className = "tabs-container sync-state";
42     this._tabListComponent.init();
43     tabListWrapper.appendChild(this._tabListComponent.container);
44     deck.appendChild(tabListWrapper);
45     this.container.appendChild(deck);
47     this._attachListeners();
48     this.update(state);
49   },
51   destroy() {
52     this._tabListComponent.uninit();
53     this.container.remove();
54   },
56   update(state) {
57     // Note that we may also want to update elements that are outside of the
58     // deck, so use the document to find the class names rather than our
59     // container.
60     for (let panel of state.panels) {
61       if (panel.selected) {
62         Array.prototype.map.call(
63           this._doc.getElementsByClassName(panel.id),
64           item => item.classList.add("selected")
65         );
66       } else {
67         Array.prototype.map.call(
68           this._doc.getElementsByClassName(panel.id),
69           item => item.classList.remove("selected")
70         );
71       }
72     }
73   },
75   _clearChilden() {
76     while (this.container.firstChild) {
77       this.container.firstChild.remove();
78     }
79   },
81   _attachListeners() {
82     let syncPrefLinks = this.container.querySelectorAll(".sync-prefs");
83     for (let link of syncPrefLinks) {
84       link.addEventListener("click", this.props.onSyncPrefClick);
85     }
86     this.container
87       .querySelector(".connect-device")
88       .addEventListener("click", this.props.onConnectDeviceClick);
89   },