SyncedTabsDeckView.sys.mjs (2607B)
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/. */ 4 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; 15 16 this._window = window; 17 this._doc = window.document; 18 19 this._tabListComponent = tabListComponent; 20 this._deckTemplate = this._doc.getElementById("deck-template"); 21 this.container = this._doc.createElement("div"); 22 }; 23 24 SyncedTabsDeckView.prototype = { 25 render(state) { 26 if (state.isUpdatable) { 27 this.update(state); 28 } else { 29 this.create(state); 30 } 31 }, 32 33 create(state) { 34 let deck = this._doc.importNode( 35 this._deckTemplate.content, 36 true 37 ).firstElementChild; 38 this._clearChilden(); 39 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); 46 47 this._attachListeners(); 48 this.update(state); 49 }, 50 51 destroy() { 52 this._tabListComponent.uninit(); 53 this.container.remove(); 54 }, 55 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 }, 74 75 _clearChilden() { 76 while (this.container.firstChild) { 77 this.container.firstChild.remove(); 78 } 79 }, 80 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 }, 90 };