summaryrefslogtreecommitdiffstats
path: root/browser/components/syncedtabs/SyncedTabsDeckView.sys.mjs
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/syncedtabs/SyncedTabsDeckView.sys.mjs')
-rw-r--r--browser/components/syncedtabs/SyncedTabsDeckView.sys.mjs90
1 files changed, 90 insertions, 0 deletions
diff --git a/browser/components/syncedtabs/SyncedTabsDeckView.sys.mjs b/browser/components/syncedtabs/SyncedTabsDeckView.sys.mjs
new file mode 100644
index 0000000000..aacae71fa5
--- /dev/null
+++ b/browser/components/syncedtabs/SyncedTabsDeckView.sys.mjs
@@ -0,0 +1,90 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * SyncedTabsDeckView
+ *
+ * Instances of SyncedTabsDeckView render DOM nodes from a given state.
+ * No state is kept internaly and the DOM will completely
+ * rerender unless the state flags `isUpdatable`, which helps
+ * make small changes without the overhead of a full rerender.
+ */
+export const SyncedTabsDeckView = function (window, tabListComponent, props) {
+ this.props = props;
+
+ this._window = window;
+ this._doc = window.document;
+
+ this._tabListComponent = tabListComponent;
+ this._deckTemplate = this._doc.getElementById("deck-template");
+ this.container = this._doc.createElement("div");
+};
+
+SyncedTabsDeckView.prototype = {
+ render(state) {
+ if (state.isUpdatable) {
+ this.update(state);
+ } else {
+ this.create(state);
+ }
+ },
+
+ create(state) {
+ let deck = this._doc.importNode(
+ this._deckTemplate.content,
+ true
+ ).firstElementChild;
+ this._clearChilden();
+
+ let tabListWrapper = this._doc.createElement("div");
+ tabListWrapper.className = "tabs-container sync-state";
+ this._tabListComponent.init();
+ tabListWrapper.appendChild(this._tabListComponent.container);
+ deck.appendChild(tabListWrapper);
+ this.container.appendChild(deck);
+
+ this._attachListeners();
+ this.update(state);
+ },
+
+ destroy() {
+ this._tabListComponent.uninit();
+ this.container.remove();
+ },
+
+ update(state) {
+ // Note that we may also want to update elements that are outside of the
+ // deck, so use the document to find the class names rather than our
+ // container.
+ for (let panel of state.panels) {
+ if (panel.selected) {
+ Array.prototype.map.call(
+ this._doc.getElementsByClassName(panel.id),
+ item => item.classList.add("selected")
+ );
+ } else {
+ Array.prototype.map.call(
+ this._doc.getElementsByClassName(panel.id),
+ item => item.classList.remove("selected")
+ );
+ }
+ }
+ },
+
+ _clearChilden() {
+ while (this.container.firstChild) {
+ this.container.firstChild.remove();
+ }
+ },
+
+ _attachListeners() {
+ let syncPrefLinks = this.container.querySelectorAll(".sync-prefs");
+ for (let link of syncPrefLinks) {
+ link.addEventListener("click", this.props.onSyncPrefClick);
+ }
+ this.container
+ .querySelector(".connect-device")
+ .addEventListener("click", this.props.onConnectDeviceClick);
+ },
+};