browser/base/content/newtab/updater.js

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 #ifdef 0
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     4  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #endif
     7 /**
     8  * This singleton provides functionality to update the current grid to a new
     9  * set of pinned and blocked sites. It adds, moves and removes sites.
    10  */
    11 let gUpdater = {
    12   /**
    13    * Updates the current grid according to its pinned and blocked sites.
    14    * This removes old, moves existing and creates new sites to fill gaps.
    15    * @param aCallback The callback to call when finished.
    16    */
    17   updateGrid: function Updater_updateGrid(aCallback) {
    18     let links = gLinks.getLinks().slice(0, gGrid.cells.length);
    20     // Find all sites that remain in the grid.
    21     let sites = this._findRemainingSites(links);
    23     let self = this;
    25     // Remove sites that are no longer in the grid.
    26     this._removeLegacySites(sites, function () {
    27       // Freeze all site positions so that we can move their DOM nodes around
    28       // without any visual impact.
    29       self._freezeSitePositions(sites);
    31       // Move the sites' DOM nodes to their new position in the DOM. This will
    32       // have no visual effect as all the sites have been frozen and will
    33       // remain in their current position.
    34       self._moveSiteNodes(sites);
    36       // Now it's time to animate the sites actually moving to their new
    37       // positions.
    38       self._rearrangeSites(sites, function () {
    39         // Try to fill empty cells and finish.
    40         self._fillEmptyCells(links, aCallback);
    42         // Update other pages that might be open to keep them synced.
    43         gAllPages.update(gPage);
    44       });
    45     });
    46   },
    48   /**
    49    * Takes an array of links and tries to correlate them to sites contained in
    50    * the current grid. If no corresponding site can be found (i.e. the link is
    51    * new and a site will be created) then just set it to null.
    52    * @param aLinks The array of links to find sites for.
    53    * @return Array of sites mapped to the given links (can contain null values).
    54    */
    55   _findRemainingSites: function Updater_findRemainingSites(aLinks) {
    56     let map = {};
    58     // Create a map to easily retrieve the site for a given URL.
    59     gGrid.sites.forEach(function (aSite) {
    60       if (aSite)
    61         map[aSite.url] = aSite;
    62     });
    64     // Map each link to its corresponding site, if any.
    65     return aLinks.map(function (aLink) {
    66       return aLink && (aLink.url in map) && map[aLink.url];
    67     });
    68   },
    70   /**
    71    * Freezes the given sites' positions.
    72    * @param aSites The array of sites to freeze.
    73    */
    74   _freezeSitePositions: function Updater_freezeSitePositions(aSites) {
    75     aSites.forEach(function (aSite) {
    76       if (aSite)
    77         gTransformation.freezeSitePosition(aSite);
    78     });
    79   },
    81   /**
    82    * Moves the given sites' DOM nodes to their new positions.
    83    * @param aSites The array of sites to move.
    84    */
    85   _moveSiteNodes: function Updater_moveSiteNodes(aSites) {
    86     let cells = gGrid.cells;
    88     // Truncate the given array of sites to not have more sites than cells.
    89     // This can happen when the user drags a bookmark (or any other new kind
    90     // of link) onto the grid.
    91     let sites = aSites.slice(0, cells.length);
    93     sites.forEach(function (aSite, aIndex) {
    94       let cell = cells[aIndex];
    95       let cellSite = cell.site;
    97       // The site's position didn't change.
    98       if (!aSite || cellSite != aSite) {
    99         let cellNode = cell.node;
   101         // Empty the cell if necessary.
   102         if (cellSite)
   103           cellNode.removeChild(cellSite.node);
   105         // Put the new site in place, if any.
   106         if (aSite)
   107           cellNode.appendChild(aSite.node);
   108       }
   109     }, this);
   110   },
   112   /**
   113    * Rearranges the given sites and slides them to their new positions.
   114    * @param aSites The array of sites to re-arrange.
   115    * @param aCallback The callback to call when finished.
   116    */
   117   _rearrangeSites: function Updater_rearrangeSites(aSites, aCallback) {
   118     let options = {callback: aCallback, unfreeze: true};
   119     gTransformation.rearrangeSites(aSites, options);
   120   },
   122   /**
   123    * Removes all sites from the grid that are not in the given links array or
   124    * exceed the grid.
   125    * @param aSites The array of sites remaining in the grid.
   126    * @param aCallback The callback to call when finished.
   127    */
   128   _removeLegacySites: function Updater_removeLegacySites(aSites, aCallback) {
   129     let batch = [];
   131     // Delete sites that were removed from the grid.
   132     gGrid.sites.forEach(function (aSite) {
   133       // The site must be valid and not in the current grid.
   134       if (!aSite || aSites.indexOf(aSite) != -1)
   135         return;
   137       let deferred = Promise.defer();
   138       batch.push(deferred.promise);
   140       // Fade out the to-be-removed site.
   141       gTransformation.hideSite(aSite, function () {
   142         let node = aSite.node;
   144         // Remove the site from the DOM.
   145         node.parentNode.removeChild(node);
   146         deferred.resolve();
   147       });
   148     });
   150     Promise.all(batch).then(aCallback);
   151   },
   153   /**
   154    * Tries to fill empty cells with new links if available.
   155    * @param aLinks The array of links.
   156    * @param aCallback The callback to call when finished.
   157    */
   158   _fillEmptyCells: function Updater_fillEmptyCells(aLinks, aCallback) {
   159     let {cells, sites} = gGrid;
   160     let batch = [];
   162     // Find empty cells and fill them.
   163     sites.forEach(function (aSite, aIndex) {
   164       if (aSite || !aLinks[aIndex])
   165         return;
   167       let deferred = Promise.defer();
   168       batch.push(deferred.promise);
   170       // Create the new site and fade it in.
   171       let site = gGrid.createSite(aLinks[aIndex], cells[aIndex]);
   173       // Set the site's initial opacity to zero.
   174       site.node.style.opacity = 0;
   176       // Flush all style changes for the dynamically inserted site to make
   177       // the fade-in transition work.
   178       window.getComputedStyle(site.node).opacity;
   179       gTransformation.showSite(site, function () deferred.resolve());
   180     });
   182     Promise.all(batch).then(aCallback);
   183   }
   184 };

mercurial