mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-08 20:47:44 +00:00
187 lines
5.9 KiB
JavaScript
187 lines
5.9 KiB
JavaScript
#ifdef 0
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
#endif
|
|
|
|
/**
|
|
* This singleton provides functionality to update the current grid to a new
|
|
* set of pinned and blocked sites. It adds, moves and removes sites.
|
|
*/
|
|
let gUpdater = {
|
|
/**
|
|
* Updates the current grid according to its pinned and blocked sites.
|
|
* This removes old, moves existing and creates new sites to fill gaps.
|
|
* @param aCallback The callback to call when finished.
|
|
*/
|
|
updateGrid: function Updater_updateGrid(aCallback) {
|
|
let links = gLinks.getLinks().slice(0, gGrid.cells.length);
|
|
|
|
// Find all sites that remain in the grid.
|
|
let sites = this._findRemainingSites(links);
|
|
|
|
let self = this;
|
|
|
|
// Remove sites that are no longer in the grid.
|
|
this._removeLegacySites(sites, function () {
|
|
// Freeze all site positions so that we can move their DOM nodes around
|
|
// without any visual impact.
|
|
self._freezeSitePositions(sites);
|
|
|
|
// Move the sites' DOM nodes to their new position in the DOM. This will
|
|
// have no visual effect as all the sites have been frozen and will
|
|
// remain in their current position.
|
|
self._moveSiteNodes(sites);
|
|
|
|
// Now it's time to animate the sites actually moving to their new
|
|
// positions.
|
|
self._rearrangeSites(sites, function () {
|
|
// Try to fill empty cells and finish.
|
|
self._fillEmptyCells(links, aCallback);
|
|
|
|
// Update other pages that might be open to keep them synced.
|
|
gAllPages.update(gPage);
|
|
});
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Takes an array of links and tries to correlate them to sites contained in
|
|
* the current grid. If no corresponding site can be found (i.e. the link is
|
|
* new and a site will be created) then just set it to null.
|
|
* @param aLinks The array of links to find sites for.
|
|
* @return Array of sites mapped to the given links (can contain null values).
|
|
*/
|
|
_findRemainingSites: function Updater_findRemainingSites(aLinks) {
|
|
let map = {};
|
|
|
|
// Create a map to easily retrieve the site for a given URL.
|
|
gGrid.sites.forEach(function (aSite) {
|
|
if (aSite)
|
|
map[aSite.url] = aSite;
|
|
});
|
|
|
|
// Map each link to its corresponding site, if any.
|
|
return aLinks.map(function (aLink) {
|
|
return aLink && (aLink.url in map) && map[aLink.url];
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Freezes the given sites' positions.
|
|
* @param aSites The array of sites to freeze.
|
|
*/
|
|
_freezeSitePositions: function Updater_freezeSitePositions(aSites) {
|
|
aSites.forEach(function (aSite) {
|
|
if (aSite)
|
|
gTransformation.freezeSitePosition(aSite);
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Moves the given sites' DOM nodes to their new positions.
|
|
* @param aSites The array of sites to move.
|
|
*/
|
|
_moveSiteNodes: function Updater_moveSiteNodes(aSites) {
|
|
let cells = gGrid.cells;
|
|
|
|
// Truncate the given array of sites to not have more sites than cells.
|
|
// This can happen when the user drags a bookmark (or any other new kind
|
|
// of link) onto the grid.
|
|
let sites = aSites.slice(0, cells.length);
|
|
|
|
sites.forEach(function (aSite, aIndex) {
|
|
let cell = cells[aIndex];
|
|
let cellSite = cell.site;
|
|
|
|
// The site's position didn't change.
|
|
if (!aSite || cellSite != aSite) {
|
|
let cellNode = cell.node;
|
|
|
|
// Empty the cell if necessary.
|
|
if (cellSite)
|
|
cellNode.removeChild(cellSite.node);
|
|
|
|
// Put the new site in place, if any.
|
|
if (aSite)
|
|
cellNode.appendChild(aSite.node);
|
|
}
|
|
}, this);
|
|
},
|
|
|
|
/**
|
|
* Rearranges the given sites and slides them to their new positions.
|
|
* @param aSites The array of sites to re-arrange.
|
|
* @param aCallback The callback to call when finished.
|
|
*/
|
|
_rearrangeSites: function Updater_rearrangeSites(aSites, aCallback) {
|
|
let options = {callback: aCallback, unfreeze: true};
|
|
gTransformation.rearrangeSites(aSites, options);
|
|
},
|
|
|
|
/**
|
|
* Removes all sites from the grid that are not in the given links array or
|
|
* exceed the grid.
|
|
* @param aSites The array of sites remaining in the grid.
|
|
* @param aCallback The callback to call when finished.
|
|
*/
|
|
_removeLegacySites: function Updater_removeLegacySites(aSites, aCallback) {
|
|
let batch = [];
|
|
|
|
// Delete sites that were removed from the grid.
|
|
gGrid.sites.forEach(function (aSite) {
|
|
// The site must be valid and not in the current grid.
|
|
if (!aSite || aSites.indexOf(aSite) != -1)
|
|
return;
|
|
|
|
let deferred = Promise.defer();
|
|
batch.push(deferred.promise);
|
|
|
|
// Fade out the to-be-removed site.
|
|
gTransformation.hideSite(aSite, function () {
|
|
let node = aSite.node;
|
|
|
|
// Remove the site from the DOM.
|
|
node.parentNode.removeChild(node);
|
|
deferred.resolve();
|
|
});
|
|
});
|
|
|
|
let wait = Promise.promised(aCallback);
|
|
wait.apply(null, batch);
|
|
},
|
|
|
|
/**
|
|
* Tries to fill empty cells with new links if available.
|
|
* @param aLinks The array of links.
|
|
* @param aCallback The callback to call when finished.
|
|
*/
|
|
_fillEmptyCells: function Updater_fillEmptyCells(aLinks, aCallback) {
|
|
let {cells, sites} = gGrid;
|
|
let batch = [];
|
|
|
|
// Find empty cells and fill them.
|
|
sites.forEach(function (aSite, aIndex) {
|
|
if (aSite || !aLinks[aIndex])
|
|
return;
|
|
|
|
let deferred = Promise.defer();
|
|
batch.push(deferred.promise);
|
|
|
|
// Create the new site and fade it in.
|
|
let site = gGrid.createSite(aLinks[aIndex], cells[aIndex]);
|
|
|
|
// Set the site's initial opacity to zero.
|
|
site.node.style.opacity = 0;
|
|
|
|
// Flush all style changes for the dynamically inserted site to make
|
|
// the fade-in transition work.
|
|
window.getComputedStyle(site.node).opacity;
|
|
gTransformation.showSite(site, function () deferred.resolve());
|
|
});
|
|
|
|
let wait = Promise.promised(aCallback);
|
|
wait.apply(null, batch);
|
|
}
|
|
};
|