browser/base/content/newtab/updater.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/browser/base/content/newtab/updater.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,184 @@
     1.4 +#ifdef 0
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     1.7 + * You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +#endif
     1.9 +
    1.10 +/**
    1.11 + * This singleton provides functionality to update the current grid to a new
    1.12 + * set of pinned and blocked sites. It adds, moves and removes sites.
    1.13 + */
    1.14 +let gUpdater = {
    1.15 +  /**
    1.16 +   * Updates the current grid according to its pinned and blocked sites.
    1.17 +   * This removes old, moves existing and creates new sites to fill gaps.
    1.18 +   * @param aCallback The callback to call when finished.
    1.19 +   */
    1.20 +  updateGrid: function Updater_updateGrid(aCallback) {
    1.21 +    let links = gLinks.getLinks().slice(0, gGrid.cells.length);
    1.22 +
    1.23 +    // Find all sites that remain in the grid.
    1.24 +    let sites = this._findRemainingSites(links);
    1.25 +
    1.26 +    let self = this;
    1.27 +
    1.28 +    // Remove sites that are no longer in the grid.
    1.29 +    this._removeLegacySites(sites, function () {
    1.30 +      // Freeze all site positions so that we can move their DOM nodes around
    1.31 +      // without any visual impact.
    1.32 +      self._freezeSitePositions(sites);
    1.33 +
    1.34 +      // Move the sites' DOM nodes to their new position in the DOM. This will
    1.35 +      // have no visual effect as all the sites have been frozen and will
    1.36 +      // remain in their current position.
    1.37 +      self._moveSiteNodes(sites);
    1.38 +
    1.39 +      // Now it's time to animate the sites actually moving to their new
    1.40 +      // positions.
    1.41 +      self._rearrangeSites(sites, function () {
    1.42 +        // Try to fill empty cells and finish.
    1.43 +        self._fillEmptyCells(links, aCallback);
    1.44 +
    1.45 +        // Update other pages that might be open to keep them synced.
    1.46 +        gAllPages.update(gPage);
    1.47 +      });
    1.48 +    });
    1.49 +  },
    1.50 +
    1.51 +  /**
    1.52 +   * Takes an array of links and tries to correlate them to sites contained in
    1.53 +   * the current grid. If no corresponding site can be found (i.e. the link is
    1.54 +   * new and a site will be created) then just set it to null.
    1.55 +   * @param aLinks The array of links to find sites for.
    1.56 +   * @return Array of sites mapped to the given links (can contain null values).
    1.57 +   */
    1.58 +  _findRemainingSites: function Updater_findRemainingSites(aLinks) {
    1.59 +    let map = {};
    1.60 +
    1.61 +    // Create a map to easily retrieve the site for a given URL.
    1.62 +    gGrid.sites.forEach(function (aSite) {
    1.63 +      if (aSite)
    1.64 +        map[aSite.url] = aSite;
    1.65 +    });
    1.66 +
    1.67 +    // Map each link to its corresponding site, if any.
    1.68 +    return aLinks.map(function (aLink) {
    1.69 +      return aLink && (aLink.url in map) && map[aLink.url];
    1.70 +    });
    1.71 +  },
    1.72 +
    1.73 +  /**
    1.74 +   * Freezes the given sites' positions.
    1.75 +   * @param aSites The array of sites to freeze.
    1.76 +   */
    1.77 +  _freezeSitePositions: function Updater_freezeSitePositions(aSites) {
    1.78 +    aSites.forEach(function (aSite) {
    1.79 +      if (aSite)
    1.80 +        gTransformation.freezeSitePosition(aSite);
    1.81 +    });
    1.82 +  },
    1.83 +
    1.84 +  /**
    1.85 +   * Moves the given sites' DOM nodes to their new positions.
    1.86 +   * @param aSites The array of sites to move.
    1.87 +   */
    1.88 +  _moveSiteNodes: function Updater_moveSiteNodes(aSites) {
    1.89 +    let cells = gGrid.cells;
    1.90 +
    1.91 +    // Truncate the given array of sites to not have more sites than cells.
    1.92 +    // This can happen when the user drags a bookmark (or any other new kind
    1.93 +    // of link) onto the grid.
    1.94 +    let sites = aSites.slice(0, cells.length);
    1.95 +
    1.96 +    sites.forEach(function (aSite, aIndex) {
    1.97 +      let cell = cells[aIndex];
    1.98 +      let cellSite = cell.site;
    1.99 +
   1.100 +      // The site's position didn't change.
   1.101 +      if (!aSite || cellSite != aSite) {
   1.102 +        let cellNode = cell.node;
   1.103 +
   1.104 +        // Empty the cell if necessary.
   1.105 +        if (cellSite)
   1.106 +          cellNode.removeChild(cellSite.node);
   1.107 +
   1.108 +        // Put the new site in place, if any.
   1.109 +        if (aSite)
   1.110 +          cellNode.appendChild(aSite.node);
   1.111 +      }
   1.112 +    }, this);
   1.113 +  },
   1.114 +
   1.115 +  /**
   1.116 +   * Rearranges the given sites and slides them to their new positions.
   1.117 +   * @param aSites The array of sites to re-arrange.
   1.118 +   * @param aCallback The callback to call when finished.
   1.119 +   */
   1.120 +  _rearrangeSites: function Updater_rearrangeSites(aSites, aCallback) {
   1.121 +    let options = {callback: aCallback, unfreeze: true};
   1.122 +    gTransformation.rearrangeSites(aSites, options);
   1.123 +  },
   1.124 +
   1.125 +  /**
   1.126 +   * Removes all sites from the grid that are not in the given links array or
   1.127 +   * exceed the grid.
   1.128 +   * @param aSites The array of sites remaining in the grid.
   1.129 +   * @param aCallback The callback to call when finished.
   1.130 +   */
   1.131 +  _removeLegacySites: function Updater_removeLegacySites(aSites, aCallback) {
   1.132 +    let batch = [];
   1.133 +
   1.134 +    // Delete sites that were removed from the grid.
   1.135 +    gGrid.sites.forEach(function (aSite) {
   1.136 +      // The site must be valid and not in the current grid.
   1.137 +      if (!aSite || aSites.indexOf(aSite) != -1)
   1.138 +        return;
   1.139 +
   1.140 +      let deferred = Promise.defer();
   1.141 +      batch.push(deferred.promise);
   1.142 +
   1.143 +      // Fade out the to-be-removed site.
   1.144 +      gTransformation.hideSite(aSite, function () {
   1.145 +        let node = aSite.node;
   1.146 +
   1.147 +        // Remove the site from the DOM.
   1.148 +        node.parentNode.removeChild(node);
   1.149 +        deferred.resolve();
   1.150 +      });
   1.151 +    });
   1.152 +
   1.153 +    Promise.all(batch).then(aCallback);
   1.154 +  },
   1.155 +
   1.156 +  /**
   1.157 +   * Tries to fill empty cells with new links if available.
   1.158 +   * @param aLinks The array of links.
   1.159 +   * @param aCallback The callback to call when finished.
   1.160 +   */
   1.161 +  _fillEmptyCells: function Updater_fillEmptyCells(aLinks, aCallback) {
   1.162 +    let {cells, sites} = gGrid;
   1.163 +    let batch = [];
   1.164 +
   1.165 +    // Find empty cells and fill them.
   1.166 +    sites.forEach(function (aSite, aIndex) {
   1.167 +      if (aSite || !aLinks[aIndex])
   1.168 +        return;
   1.169 +
   1.170 +      let deferred = Promise.defer();
   1.171 +      batch.push(deferred.promise);
   1.172 +
   1.173 +      // Create the new site and fade it in.
   1.174 +      let site = gGrid.createSite(aLinks[aIndex], cells[aIndex]);
   1.175 +
   1.176 +      // Set the site's initial opacity to zero.
   1.177 +      site.node.style.opacity = 0;
   1.178 +
   1.179 +      // Flush all style changes for the dynamically inserted site to make
   1.180 +      // the fade-in transition work.
   1.181 +      window.getComputedStyle(site.node).opacity;
   1.182 +      gTransformation.showSite(site, function () deferred.resolve());
   1.183 +    });
   1.184 +
   1.185 +    Promise.all(batch).then(aCallback);
   1.186 +  }
   1.187 +};

mercurial