browser/base/content/newtab/transformations.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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 allows to transform the grid by repositioning a site's node
     9  * in the DOM and by showing or hiding the node. It additionally provides
    10  * convenience methods to work with a site's DOM node.
    11  */
    12 let gTransformation = {
    13   /**
    14    * Returns the width of the left and top border of a cell. We need to take it
    15    * into account when measuring and comparing site and cell positions.
    16    */
    17   get _cellBorderWidths() {
    18     let cstyle = window.getComputedStyle(gGrid.cells[0].node, null);
    19     let widths = {
    20       left: parseInt(cstyle.getPropertyValue("border-left-width")),
    21       top: parseInt(cstyle.getPropertyValue("border-top-width"))
    22     };
    24     // Cache this value, overwrite the getter.
    25     Object.defineProperty(this, "_cellBorderWidths",
    26                           {value: widths, enumerable: true});
    28     return widths;
    29   },
    31   /**
    32    * Gets a DOM node's position.
    33    * @param aNode The DOM node.
    34    * @return A Rect instance with the position.
    35    */
    36   getNodePosition: function Transformation_getNodePosition(aNode) {
    37     let {left, top, width, height} = aNode.getBoundingClientRect();
    38     return new Rect(left + scrollX, top + scrollY, width, height);
    39   },
    41   /**
    42    * Fades a given node from zero to full opacity.
    43    * @param aNode The node to fade.
    44    * @param aCallback The callback to call when finished.
    45    */
    46   fadeNodeIn: function Transformation_fadeNodeIn(aNode, aCallback) {
    47     this._setNodeOpacity(aNode, 1, function () {
    48       // Clear the style property.
    49       aNode.style.opacity = "";
    51       if (aCallback)
    52         aCallback();
    53     });
    54   },
    56   /**
    57    * Fades a given node from full to zero opacity.
    58    * @param aNode The node to fade.
    59    * @param aCallback The callback to call when finished.
    60    */
    61   fadeNodeOut: function Transformation_fadeNodeOut(aNode, aCallback) {
    62     this._setNodeOpacity(aNode, 0, aCallback);
    63   },
    65   /**
    66    * Fades a given site from zero to full opacity.
    67    * @param aSite The site to fade.
    68    * @param aCallback The callback to call when finished.
    69    */
    70   showSite: function Transformation_showSite(aSite, aCallback) {
    71     this.fadeNodeIn(aSite.node, aCallback);
    72   },
    74   /**
    75    * Fades a given site from full to zero opacity.
    76    * @param aSite The site to fade.
    77    * @param aCallback The callback to call when finished.
    78    */
    79   hideSite: function Transformation_hideSite(aSite, aCallback) {
    80     this.fadeNodeOut(aSite.node, aCallback);
    81   },
    83   /**
    84    * Allows to set a site's position.
    85    * @param aSite The site to re-position.
    86    * @param aPosition The desired position for the given site.
    87    */
    88   setSitePosition: function Transformation_setSitePosition(aSite, aPosition) {
    89     let style = aSite.node.style;
    90     let {top, left} = aPosition;
    92     style.top = top + "px";
    93     style.left = left + "px";
    94   },
    96   /**
    97    * Freezes a site in its current position by positioning it absolute.
    98    * @param aSite The site to freeze.
    99    */
   100   freezeSitePosition: function Transformation_freezeSitePosition(aSite) {
   101     if (this._isFrozen(aSite))
   102       return;
   104     let style = aSite.node.style;
   105     let comp = getComputedStyle(aSite.node, null);
   106     style.width = comp.getPropertyValue("width")
   107     style.height = comp.getPropertyValue("height");
   109     aSite.node.setAttribute("frozen", "true");
   110     this.setSitePosition(aSite, this.getNodePosition(aSite.node));
   111   },
   113   /**
   114    * Unfreezes a site by removing its absolute positioning.
   115    * @param aSite The site to unfreeze.
   116    */
   117   unfreezeSitePosition: function Transformation_unfreezeSitePosition(aSite) {
   118     if (!this._isFrozen(aSite))
   119       return;
   121     let style = aSite.node.style;
   122     style.left = style.top = style.width = style.height = "";
   123     aSite.node.removeAttribute("frozen");
   124   },
   126   /**
   127    * Slides the given site to the target node's position.
   128    * @param aSite The site to move.
   129    * @param aTarget The slide target.
   130    * @param aOptions Set of options (see below).
   131    *        unfreeze - unfreeze the site after sliding
   132    *        callback - the callback to call when finished
   133    */
   134   slideSiteTo: function Transformation_slideSiteTo(aSite, aTarget, aOptions) {
   135     let currentPosition = this.getNodePosition(aSite.node);
   136     let targetPosition = this.getNodePosition(aTarget.node)
   137     let callback = aOptions && aOptions.callback;
   139     let self = this;
   141     function finish() {
   142       if (aOptions && aOptions.unfreeze)
   143         self.unfreezeSitePosition(aSite);
   145       if (callback)
   146         callback();
   147     }
   149     // We need to take the width of a cell's border into account.
   150     targetPosition.left += this._cellBorderWidths.left;
   151     targetPosition.top += this._cellBorderWidths.top;
   153     // Nothing to do here if the positions already match.
   154     if (currentPosition.left == targetPosition.left &&
   155         currentPosition.top == targetPosition.top) {
   156       finish();
   157     } else {
   158       this.setSitePosition(aSite, targetPosition);
   159       this._whenTransitionEnded(aSite.node, ["left", "top"], finish);
   160     }
   161   },
   163   /**
   164    * Rearranges a given array of sites and moves them to their new positions or
   165    * fades in/out new/removed sites.
   166    * @param aSites An array of sites to rearrange.
   167    * @param aOptions Set of options (see below).
   168    *        unfreeze - unfreeze the site after rearranging
   169    *        callback - the callback to call when finished
   170    */
   171   rearrangeSites: function Transformation_rearrangeSites(aSites, aOptions) {
   172     let batch = [];
   173     let cells = gGrid.cells;
   174     let callback = aOptions && aOptions.callback;
   175     let unfreeze = aOptions && aOptions.unfreeze;
   177     aSites.forEach(function (aSite, aIndex) {
   178       // Do not re-arrange empty cells or the dragged site.
   179       if (!aSite || aSite == gDrag.draggedSite)
   180         return;
   182       let deferred = Promise.defer();
   183       batch.push(deferred.promise);
   184       let cb = deferred.resolve;
   186       if (!cells[aIndex])
   187         // The site disappeared from the grid, hide it.
   188         this.hideSite(aSite, cb);
   189       else if (this._getNodeOpacity(aSite.node) != 1)
   190         // The site disappeared before but is now back, show it.
   191         this.showSite(aSite, cb);
   192       else
   193         // The site's position has changed, move it around.
   194         this._moveSite(aSite, aIndex, {unfreeze: unfreeze, callback: cb});
   195     }, this);
   197     if (callback) {
   198       Promise.all(batch).then(callback);
   199     }
   200   },
   202   /**
   203    * Listens for the 'transitionend' event on a given node and calls the given
   204    * callback.
   205    * @param aNode The node that is transitioned.
   206    * @param aProperties The properties we'll wait to be transitioned.
   207    * @param aCallback The callback to call when finished.
   208    */
   209   _whenTransitionEnded:
   210     function Transformation_whenTransitionEnded(aNode, aProperties, aCallback) {
   212     let props = new Set(aProperties);
   213     aNode.addEventListener("transitionend", function onEnd(e) {
   214       if (props.has(e.propertyName)) {
   215         aNode.removeEventListener("transitionend", onEnd);
   216         aCallback();
   217       }
   218     });
   219   },
   221   /**
   222    * Gets a given node's opacity value.
   223    * @param aNode The node to get the opacity value from.
   224    * @return The node's opacity value.
   225    */
   226   _getNodeOpacity: function Transformation_getNodeOpacity(aNode) {
   227     let cstyle = window.getComputedStyle(aNode, null);
   228     return cstyle.getPropertyValue("opacity");
   229   },
   231   /**
   232    * Sets a given node's opacity.
   233    * @param aNode The node to set the opacity value for.
   234    * @param aOpacity The opacity value to set.
   235    * @param aCallback The callback to call when finished.
   236    */
   237   _setNodeOpacity:
   238     function Transformation_setNodeOpacity(aNode, aOpacity, aCallback) {
   240     if (this._getNodeOpacity(aNode) == aOpacity) {
   241       if (aCallback)
   242         aCallback();
   243     } else {
   244       if (aCallback) {
   245         this._whenTransitionEnded(aNode, ["opacity"], aCallback);
   246       }
   248       aNode.style.opacity = aOpacity;
   249     }
   250   },
   252   /**
   253    * Moves a site to the cell with the given index.
   254    * @param aSite The site to move.
   255    * @param aIndex The target cell's index.
   256    * @param aOptions Options that are directly passed to slideSiteTo().
   257    */
   258   _moveSite: function Transformation_moveSite(aSite, aIndex, aOptions) {
   259     this.freezeSitePosition(aSite);
   260     this.slideSiteTo(aSite, gGrid.cells[aIndex], aOptions);
   261   },
   263   /**
   264    * Checks whether a site is currently frozen.
   265    * @param aSite The site to check.
   266    * @return Whether the given site is frozen.
   267    */
   268   _isFrozen: function Transformation_isFrozen(aSite) {
   269     return aSite.node.hasAttribute("frozen");
   270   }
   271 };

mercurial