tor-browser

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

style-change-tracker.js (3177B)


      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 "use strict";
      6 
      7 const EventEmitter = require("resource://devtools/shared/event-emitter.js");
      8 const WalkerEventListener = require("resource://devtools/client/inspector/shared/walker-event-listener.js");
      9 
     10 /**
     11 * The InspectorStyleChangeTracker simply emits an event when it detects any changes in
     12 * the page that may cause the current inspector selection to have different style applied
     13 * to it.
     14 * It currently tracks:
     15 * - markup mutations, because they may cause different CSS rules to apply to the current
     16 *   node.
     17 * - window resize, because they may cause media query changes and therefore also
     18 *   different CSS rules to apply to the current node.
     19 */
     20 class InspectorStyleChangeTracker {
     21  constructor(inspector) {
     22    this.selection = inspector.selection;
     23 
     24    this.onMutations = this.onMutations.bind(this);
     25    this.onResized = this.onResized.bind(this);
     26 
     27    this.walkerEventListener = new WalkerEventListener(inspector, {
     28      mutations: this.onMutations,
     29      resize: this.onResized,
     30    });
     31 
     32    EventEmitter.decorate(this);
     33  }
     34 
     35  destroy() {
     36    this.walkerEventListener.destroy();
     37    this.walkerEventListener = null;
     38    this.selection = null;
     39  }
     40 
     41  /**
     42   * When markup mutations occur, if an attribute of the selected node, one of its
     43   * ancestors or siblings changes, we need to consider this as potentially causing a
     44   * style change for the current node.
     45   */
     46  onMutations(mutations) {
     47    const canMutationImpactCurrentStyles = ({
     48      type,
     49      target: mutationTarget,
     50    }) => {
     51      // Only attributes mutations are interesting here.
     52      if (type !== "attributes") {
     53        return false;
     54      }
     55 
     56      // Is the mutation on the current selected node?
     57      const currentNode = this.selection.nodeFront;
     58      if (mutationTarget === currentNode) {
     59        return true;
     60      }
     61 
     62      // Is the mutation on one of the current selected node's siblings?
     63      // We can't know the order of nodes on the client-side without calling
     64      // walker.children, so don't attempt to check the previous or next element siblings.
     65      // It's good enough to know that one sibling changed.
     66      let parent = currentNode.parentNode();
     67      const siblings = parent.treeChildren();
     68      if (siblings.includes(mutationTarget)) {
     69        return true;
     70      }
     71 
     72      // Is the mutation on one of the current selected node's parents?
     73      while (parent) {
     74        if (mutationTarget === parent) {
     75          return true;
     76        }
     77        parent = parent.parentNode();
     78      }
     79 
     80      return false;
     81    };
     82 
     83    for (const mutation of mutations) {
     84      if (canMutationImpactCurrentStyles(mutation)) {
     85        this.emit("style-changed");
     86        break;
     87      }
     88    }
     89  }
     90 
     91  /**
     92   * When the window gets resized, this may cause media-queries to match, and we therefore
     93   * need to consider this as a style change for the current node.
     94   */
     95  onResized() {
     96    this.emit("style-changed");
     97  }
     98 }
     99 
    100 module.exports = InspectorStyleChangeTracker;