Bug 1393565 - De-duplicate the JS code and CSS that sets the bookmark and pocket library animation. r?gijs
MozReview-Commit-ID: Z1kIdrY2Um
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -73,31 +73,16 @@ var StarUI = {
elt.removeAttribute("disabled");
elt.removeAttribute("wasDisabled");
});
},
// nsIDOMEventListener
handleEvent(aEvent) {
switch (aEvent.type) {
- case "animationend": {
- let animatableBox = document.getElementById("library-animatable-box");
- if (aEvent.animationName.startsWith("library-bookmark-animation")) {
- animatableBox.setAttribute("fade", "true");
- } else if (aEvent.animationName == "library-bookmark-fade") {
- animatableBox.removeEventListener("animationend", this);
- animatableBox.removeAttribute("animate");
- animatableBox.removeAttribute("fade");
- let libraryButton = document.getElementById("library-button");
- // Put the 'fill' back in the normal icon.
- libraryButton.removeAttribute("animate");
- gNavToolbox.removeAttribute("animate");
- }
- break;
- }
case "mousemove":
clearTimeout(this._autoCloseTimer);
// The autoclose timer is not disabled on generic mouseout
// because the user may not have actually interacted with the popup.
break;
case "popuphidden": {
clearTimeout(this._autoCloseTimer);
if (aEvent.originalTarget == this.panel) {
@@ -115,17 +100,16 @@ var StarUI = {
let guidsForRemoval = this._itemGuids;
this._itemGuids = null;
this._itemIdsMap = null;
if (this._batching) {
this.endBatch();
}
- let libraryButton;
if (removeBookmarksOnPopupHidden && guidsForRemoval) {
if (this._isNewBookmark) {
if (!PlacesUIUtils.useAsyncTransactions) {
PlacesUtils.transactionManager.undoTransaction();
break;
}
PlacesTransactions.undo().catch(Cu.reportError);
break;
@@ -139,42 +123,18 @@ var StarUI = {
PlacesUtils.transactionManager.doTransaction(txn);
}
}
break;
}
PlacesTransactions.Remove(guidsForRemoval)
.transact().catch(Cu.reportError);
- } else if (this._isNewBookmark &&
- Services.prefs.getBoolPref("toolkit.cosmeticAnimations.enabled") &&
- (libraryButton = document.getElementById("library-button")) &&
- libraryButton.getAttribute("cui-areatype") != "menu-panel" &&
- libraryButton.getAttribute("overflowedItem") != "true" &&
- libraryButton.closest("#nav-bar")) {
- let animatableBox = document.getElementById("library-animatable-box");
- let navBar = document.getElementById("nav-bar");
- let libraryIcon = document.getAnonymousElementByAttribute(libraryButton, "class", "toolbarbutton-icon");
- let dwu = window.getInterface(Ci.nsIDOMWindowUtils);
- let iconBounds = dwu.getBoundsWithoutFlushing(libraryIcon);
- let libraryBounds = dwu.getBoundsWithoutFlushing(libraryButton);
-
- animatableBox.style.setProperty("--library-button-y", libraryBounds.y + "px");
- animatableBox.style.setProperty("--library-button-height", libraryBounds.height + "px");
- animatableBox.style.setProperty("--library-icon-x", iconBounds.x + "px");
- if (navBar.hasAttribute("brighttext")) {
- animatableBox.setAttribute("brighttext", "true");
- } else {
- animatableBox.removeAttribute("brighttext");
- }
- animatableBox.removeAttribute("fade");
- gNavToolbox.setAttribute("animate", "bookmark");
- libraryButton.setAttribute("animate", "bookmark");
- animatableBox.setAttribute("animate", "bookmark");
- animatableBox.addEventListener("animationend", this);
+ } else if (this._isNewBookmark) {
+ LibraryUI.triggerLibraryAnimation("bookmark");
}
}
break;
}
case "keypress":
clearTimeout(this._autoCloseTimer);
this._autoCloseTimerEnabled = false;
@@ -1540,16 +1500,78 @@ var RecentBookmarksMenuUI = {
onEndUpdateBatch() {},
onItemAdded() {},
onItemChanged() {},
onItemVisited() {},
onItemMoved() {},
}
/**
+ * Handles the Library button in the toolbar.
+ */
+var LibraryUI = {
+ triggerLibraryAnimation(animation) {
+ if (!this.hasOwnProperty("COSMETIC_ANIMATIONS_ENABLED")) {
+ XPCOMUtils.defineLazyPreferenceGetter(this, "COSMETIC_ANIMATIONS_ENABLED",
+ "toolkit.cosmeticAnimations.enabled", true);
+ }
+
+ let libraryButton = document.getElementById("library-button");
+ if (!libraryButton ||
+ libraryButton.getAttribute("cui-areatype") == "menu-panel" ||
+ libraryButton.getAttribute("overflowedItem") == "true" ||
+ !libraryButton.closest("#nav-bar") ||
+ !this.COSMETIC_ANIMATIONS_ENABLED) {
+ return;
+ }
+ let animatableBox = document.getElementById("library-animatable-box");
+ let navBar = document.getElementById("nav-bar");
+ let libraryIcon = document.getAnonymousElementByAttribute(libraryButton, "class", "toolbarbutton-icon");
+ let dwu = window.getInterface(Ci.nsIDOMWindowUtils);
+ let iconBounds = dwu.getBoundsWithoutFlushing(libraryIcon);
+ let libraryBounds = dwu.getBoundsWithoutFlushing(libraryButton);
+
+ animatableBox.style.setProperty("--library-button-y", libraryBounds.y + "px");
+ animatableBox.style.setProperty("--library-button-height", libraryBounds.height + "px");
+ animatableBox.style.setProperty("--library-icon-x", iconBounds.x + "px");
+ if (navBar.hasAttribute("brighttext")) {
+ animatableBox.setAttribute("brighttext", "true");
+ } else {
+ animatableBox.removeAttribute("brighttext");
+ }
+ animatableBox.removeAttribute("fade");
+ gNavToolbox.setAttribute("animate", animation);
+ libraryButton.setAttribute("animate", animation);
+ animatableBox.setAttribute("animate", animation);
+ if (!this._libraryButtonAnimationEndListeners[animation]) {
+ this._libraryButtonAnimationEndListeners[animation] = event => {
+ this._libraryButtonAnimationEndListener(event, animation);
+ }
+ }
+ animatableBox.addEventListener("animationend", this._libraryButtonAnimationEndListeners[animation]);
+ },
+
+ _libraryButtonAnimationEndListeners: {},
+ _libraryButtonAnimationEndListener(aEvent, animation) {
+ let animatableBox = document.getElementById("library-animatable-box");
+ if (aEvent.animationName.startsWith(`library-${animation}-animation`)) {
+ animatableBox.setAttribute("fade", "true");
+ } else if (aEvent.animationName == `library-${animation}-fade`) {
+ animatableBox.removeEventListener("animationend", LibraryUI._libraryButtonAnimationEndListeners[animation]);
+ animatableBox.removeAttribute("animate");
+ animatableBox.removeAttribute("fade");
+ let libraryButton = document.getElementById("library-button");
+ // Put the 'fill' back in the normal icon.
+ libraryButton.removeAttribute("animate");
+ gNavToolbox.removeAttribute("animate");
+ }
+ },
+};
+
+/**
* Handles the bookmarks menu-button in the toolbar.
*/
var BookmarkingUI = {
STAR_ID: "star-button",
BOOKMARK_BUTTON_ID: "bookmarks-menu-button",
BOOKMARK_BUTTON_SHORTCUT: "addBookmarkAsKb",
get button() {
--- a/browser/extensions/pocket/bootstrap.js
+++ b/browser/extensions/pocket/bootstrap.js
@@ -153,17 +153,17 @@ var PocketPageAction = {
PocketPageAction.urlbarNode = urlbarNode;
PocketPageAction.urlbarNode.setAttribute("open", "true");
if (Services.prefs.getBoolPref("toolkit.cosmeticAnimations.enabled")) {
PocketPageAction.urlbarNode.setAttribute("animate", "true");
}
},
onIframeHiding(iframe, panel) {
if (iframe.getAttribute("itemAdded") == "true") {
- PocketPageAction.startLibraryAnimation(iframe.ownerDocument);
+ iframe.ownerGlobal.LibraryUI.triggerLibraryAnimation("pocket");
}
},
onIframeHidden(iframe, panel) {
if (!PocketPageAction.urlbarNode) {
return;
}
PocketPageAction.urlbarNode.removeAttribute("animate");
PocketPageAction.urlbarNode.removeAttribute("open");
@@ -185,64 +185,16 @@ var PocketPageAction = {
if (pocketButtonBox) {
pocketButtonBox.remove();
}
}
this.pageAction.remove();
this.pageAction = null;
},
-
- startLibraryAnimation(doc) {
- let libraryButton = doc.getElementById("library-button");
- if (!Services.prefs.getBoolPref("toolkit.cosmeticAnimations.enabled") ||
- !libraryButton ||
- libraryButton.getAttribute("cui-areatype") == "menu-panel" ||
- libraryButton.getAttribute("overflowedItem") == "true" ||
- !libraryButton.closest("#nav-bar")) {
- return;
- }
-
- let animatableBox = doc.getElementById("library-animatable-box");
- let navBar = doc.getElementById("nav-bar");
- let libraryIcon = doc.getAnonymousElementByAttribute(libraryButton, "class", "toolbarbutton-icon");
- let dwu = doc.defaultView.getInterface(Ci.nsIDOMWindowUtils);
- let iconBounds = dwu.getBoundsWithoutFlushing(libraryIcon);
- let libraryBounds = dwu.getBoundsWithoutFlushing(libraryButton);
-
- animatableBox.style.setProperty("--library-button-y", libraryBounds.y + "px");
- animatableBox.style.setProperty("--library-button-height", libraryBounds.height + "px");
- animatableBox.style.setProperty("--library-icon-x", iconBounds.x + "px");
- if (navBar.hasAttribute("brighttext")) {
- animatableBox.setAttribute("brighttext", "true");
- } else {
- animatableBox.removeAttribute("brighttext");
- }
- animatableBox.removeAttribute("fade");
- doc.defaultView.gNavToolbox.setAttribute("animate", "pocket");
- libraryButton.setAttribute("animate", "pocket");
- animatableBox.setAttribute("animate", "pocket");
- animatableBox.addEventListener("animationend", PocketPageAction.onLibraryButtonAnimationEnd);
- },
-
- onLibraryButtonAnimationEnd(event) {
- let doc = event.target.ownerDocument;
- let libraryButton = doc.getElementById("library-button");
- let animatableBox = doc.getElementById("library-animatable-box");
- if (event.animationName.startsWith("library-pocket-animation")) {
- animatableBox.setAttribute("fade", "true");
- } else if (event.animationName == "library-pocket-fade") {
- animatableBox.removeEventListener("animationend", PocketPageAction.onLibraryButtonAnimationEnd);
- // Put the 'fill' back in the normal icon.
- libraryButton.removeAttribute("animate");
- animatableBox.removeAttribute("animate");
- animatableBox.removeAttribute("fade");
- event.target.ownerGlobal.gNavToolbox.removeAttribute("animate");
- }
- },
};
// PocketContextMenu
// When the context menu is opened check if we need to build and enable pocket UI.
var PocketContextMenu = {
init() {
Services.obs.addObserver(this, "on-build-contextmenu");
},
--- a/browser/extensions/pocket/skin/shared/pocket.css
+++ b/browser/extensions/pocket/skin/shared/pocket.css
@@ -95,20 +95,16 @@
width: 260px;
}
#pocket-button-box[animate="true"]:-moz-locale-dir(rtl) > #pocket-animatable-box > #pocket-animatable-image,
#pocket-button[open="true"][animationsenabled][cui-areatype="toolbar"]:not([overflowedItem="true"]):-moz-locale-dir(rtl) > .toolbarbutton-animatable-box > .toolbarbutton-animatable-image {
animation-name: pocket-animation-rtl;
}
-#library-button[animate="pocket"] > .toolbarbutton-icon {
- fill: transparent;
-}
-
@keyframes library-pocket-animation {
from {
transform: translateX(0);
fill: inherit;
}
25% {
fill: inherit;
}
@@ -146,46 +142,16 @@
from {
fill: #ef4056;
}
to {
fill: inherit;
}
}
-.toolbarbutton-animatable-box[animate="pocket"] {
- position: absolute;
- overflow: hidden;
- /* Position the sprite at the y-position of the library-button, then adjust
- based on the size difference between half of the button height and half
- of the sprite height. */
- top: calc(var(--library-button-y) + var(--library-button-height) / 2 - 27px);
- /* Since .toolbarbutton-icon uses a different width than the animatable box,
- we need to set a margin relative to the difference in widths.
- margin-left is used here even in RTL because the item is positioned using `left` */
- left: calc(var(--library-icon-x) + (16px + 2 * var(--toolbarbutton-inner-padding) - 22px) / 2);
- /* Set the min- and max- width and height of the box equal to that
- of each frame of the SVG sprite. Setting the width and height via
- the `width` and `height` CSS properties causes an assertion for
- `inline-size less than zero: 'aContainingBlockISize >= 0'` (bug 1379332). */
- min-width: 22px;
- max-width: 22px;
- /* Height of each frame within the SVG sprite. The sprite must have equal amount
- of space above and below the icon to allow it to vertically center with the
- sprite's icon on top of the toolbar icon when using position:absolute;. */
- min-height: 54px;
- max-height: 54px;
- z-index: 2;
-}
-
-.toolbarbutton-animatable-box[animate="pocket"] > .toolbarbutton-animatable-image {
- height: var(--toolbarbutton-height); /* Height must be equal to height of toolbarbutton padding-box */
- min-height: 54px; /* Minimum height must be equal to the height of the SVG sprite */
-}
-
.toolbarbutton-animatable-box[animate="pocket"] > .toolbarbutton-animatable-image {
background-image: url("chrome://pocket-shared/skin/library-pocket-animation.svg");
width: 1078px;
animation-name: library-pocket-animation;
animation-duration: 800ms;
animation-timing-function: steps(48);
}
--- a/browser/themes/shared/toolbarbutton-icons.inc.css
+++ b/browser/themes/shared/toolbarbutton-icons.inc.css
@@ -453,21 +453,21 @@ toolbar[brighttext] .toolbarbutton-1 {
from {
fill: var(--toolbarbutton-icon-fill-attention);
}
to {
fill: inherit;
}
}
-#library-button[animate="bookmark"] > .toolbarbutton-icon {
+#library-button[animate] > .toolbarbutton-icon {
fill: transparent;
}
-.toolbarbutton-animatable-box[animate="bookmark"] {
+.toolbarbutton-animatable-box[animate] {
position: absolute;
overflow: hidden;
/* Position the sprite at the y-position of the library-button, then adjust
based on the size difference between half of the button height and half
of the sprite height. */
top: calc(var(--library-button-y) + var(--library-button-height) / 2 - 27px);
/* Set a margin relative to the difference in widths of the .toolbarbutton-icon
and the .toolbar-animatable-box. This is correct even in RTL because the item
@@ -477,19 +477,22 @@ toolbar[brighttext] .toolbarbutton-1 {
of each frame of the SVG sprite (must use min- and max- due to bug 1379332). */
min-width: 22px;
max-width: 22px;
min-height: 54px;
max-height: 54px;
z-index: 2;
}
-.toolbarbutton-animatable-box[animate="bookmark"] > .toolbarbutton-animatable-image {
+.toolbarbutton-animatable-box[animate] > .toolbarbutton-animatable-image {
height: var(--toolbarbutton-height);
min-height: 54px; /* Minimum height must be equal to the height of the SVG sprite */
+}
+
+.toolbarbutton-animatable-box[animate="bookmark"] > .toolbarbutton-animatable-image {
background-image: url("chrome://browser/skin/library-bookmark-animation.svg");
width: 1078px;
animation-name: library-bookmark-animation;
animation-duration: 800ms;
animation-timing-function: steps(48);
-moz-context-properties: fill, stroke;
stroke: var(--toolbarbutton-icon-fill-attention);
}