tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 };