diff options
Diffstat (limited to 'browser/components/syncedtabs/SyncedTabsDeckView.js')
-rw-r--r-- | browser/components/syncedtabs/SyncedTabsDeckView.js | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/browser/components/syncedtabs/SyncedTabsDeckView.js b/browser/components/syncedtabs/SyncedTabsDeckView.js new file mode 100644 index 0000000000..ecbbbed8fb --- /dev/null +++ b/browser/components/syncedtabs/SyncedTabsDeckView.js @@ -0,0 +1,96 @@ +/* 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/. */ + +"use strict"; + +let log = ChromeUtils.importESModule( + "resource://gre/modules/Log.sys.mjs" +).Log.repository.getLogger("Sync.RemoteTabs"); + +var EXPORTED_SYMBOLS = ["SyncedTabsDeckView"]; + +/** + * 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. + */ +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); + }, +}; |