jenkins-bot has submitted this change and it was merged.
Change subject: Fixes to animations (transitions) and notifications
......................................................................
Fixes to animations (transitions) and notifications
Make those animations buttery smooth, glitchless and awesome.
* Put all notifications into a separate #notifications div (helps
sandbox those transformed elements better, seems to fix blurry text
for good).
* Create a more universal transition LESS mixin (accepts arbitrary
number of transitions just like transition CSS property).
* Animate only the required properties for notifications (not all
properties).
* Provide a reliable fallback for browsers that don't support
position: fixed (that works both with and without animations).
* Stop treating Firefox and MSIE 10 (Windows Phone 8) as if they didn't
support position: fixed.
Bug: 50621
Change-Id: I9aa603fae53c36184421c520e911f6e4b9ba5300
---
M javascripts/common/Drawer.js
M javascripts/common/mf-application.js
M javascripts/common/mf-notification.js
M less/common/mainmenu.less
M less/common/mf-common.less
M less/common/notifications.less
M less/mf-mixins.less
M less/modules/mf-watchstar.less
M less/specials/mobilediff.less
M less/specials/uploads.less
M stylesheets/common/mf-common.css
M stylesheets/common/notifications.css
M stylesheets/common/ui.css
M stylesheets/modules/mf-watchstar.css
M stylesheets/specials/mobilediff.css
M stylesheets/specials/uploads.css
16 files changed, 137 insertions(+), 103 deletions(-)
Approvals:
Jdlrobson: Looks good to me, approved
jenkins-bot: Verified
diff --git a/javascripts/common/Drawer.js b/javascripts/common/Drawer.js
index caa7d6f..fc3370f 100644
--- a/javascripts/common/Drawer.js
+++ b/javascripts/common/Drawer.js
@@ -13,7 +13,7 @@
ev.preventDefault();
self.hide();
} );
- this.appendTo( '#mw-mf-page-center' );
+ this.appendTo( '#notifications' );
},
show: function() {
@@ -22,13 +22,16 @@
this.$el.addClass( 'visible' );
// ignore a possible click that called show()
setTimeout( function() {
- $( window ).one( 'scroll click',
$.proxy( self, 'hide' ) );
+ $( window ).one( 'scroll.drawer
click.drawer', $.proxy( self, 'hide' ) );
}, 0 );
}
},
hide: function() {
this.$el.removeClass( 'visible' );
+ // .one() registers one callback for scroll and click
independently
+ // if one fired, get rid of the other one
+ $( window ).off( '.drawer' );
},
isVisible: function() {
diff --git a/javascripts/common/mf-application.js
b/javascripts/common/mf-application.js
index 324f178..811111f 100644
--- a/javascripts/common/mf-application.js
+++ b/javascripts/common/mf-application.js
@@ -6,7 +6,7 @@
// FIXME: when mobileFrontend is an object with a constructor,
// just inherit from EventEmitter instead
eventEmitter = new EventEmitter(),
- $viewport, viewport,
+ $viewportMeta, viewport,
template,
templates = {};
@@ -59,21 +59,24 @@
}
};
- // TODO: only apply to places that need it
// http://www.quirksmode.org/blog/archives/2010/12/the_fifth_posit.html
// https://github.com/Modernizr/Modernizr/issues/167
+ // http://mobilehtml5.org/
function supportsPositionFixed() {
- // TODO: don't use device detection
- var agent = navigator.userAgent,
- support = false,
- supportedAgents = [
- // match anything over Webkit 534
+ var support = false;
+ [
+ // Webkit 534+
+ // FIXME: this will fail if Webkit goes past 599 and
for Blink
+ // (http://www.chromium.org/blink)
/AppleWebKit\/(53[4-9]|5[4-9]\d?|[6-9])\d?\d?/,
// Android 3+
- /Android [3-9]/
- ];
- supportedAgents.forEach( function( item ) {
- if( agent.match( item ) ) {
+ /Android [3-9]/,
+ // any Firefox
+ /Firefox/,
+ // MSIE 10+
+ /MSIE 1\d/
+ ].forEach( function( item ) {
+ if ( item.test( navigator.userAgent ) ) {
support = true;
}
} );
@@ -85,18 +88,20 @@
}
function lockViewport() {
- $viewport.attr( 'content', 'minimum-scale=1.0,
maximum-scale=1.0' );
+ $viewportMeta.attr( 'content', 'minimum-scale=1.0,
maximum-scale=1.0' );
}
function unlockViewport() {
- $viewport.attr( 'content', viewport );
+ $viewportMeta.attr( 'content', viewport );
}
// TODO: separate main menu navigation code into separate module
function init() {
var
mode, $body = $( 'body' ),
- $doc = $( 'html' );
+ $doc = $( 'html' ),
+ $viewport = $( '#mw-mf-viewport' ),
+ $pageCenter = $( '#mw-mf-page-center' );
if ( $body.hasClass( 'alpha' ) ) {
mode = 'alpha';
@@ -106,12 +111,33 @@
mw.config.set( 'wgMFMode', mode );
$doc.removeClass( 'page-loading' ); // FIXME: Kill with fire.
This is here for historic reasons in case old HTML is cached
- if( supportsPositionFixed() ) {
- $doc.addClass( 'supportsPositionFixed' );
+
+ $( '<div id="notifications">' ).appendTo( $viewport );
+
+ if ( !supportsPositionFixed() ) {
+ $doc.addClass( 'no-position-fixed' );
+
+ $( window ).on( 'scroll', function() {
+ var scrollTop = $( window ).scrollTop(),
+ scrollBottom = scrollTop + $( window
).height();
+
+ if ( scrollTop === 0 ) {
+ // special case when we're at the
beginning of the page and many
+ // browsers (e.g. Android 2.x) return
wrong window height because
+ // of the URL bar
+ $viewport.height( '100%' );
+ } else if ( scrollBottom < $pageCenter.height()
) {
+ // keep expanding the viewport until
it's as big as main content
+ // (prevents possible infinite scroll
in some browsers, can be tested
+ // on desktop Chrome forcing
supportsPositionFixed() to return false)
+ // #notification has bottom: 0 and
sticks to the end of the viewport
+ $viewport.height( scrollBottom );
+ }
+ } );
}
- $viewport = $( 'meta[name="viewport"]' );
- viewport = $viewport.attr( 'content' );
+ $viewportMeta = $( 'meta[name="viewport"]' );
+ viewport = $viewportMeta.attr( 'content' );
// FIXME: If minimum-scale and maximum-scale are not set
locking viewport will prevent a reset
if ( viewport && viewport.indexOf( 'minimum-scale' ) === -1 ) {
viewport += ', minimum-scale=0.25, maximum-scale=1.6';
@@ -123,7 +149,7 @@
// see http://adactio.com/journal/4470/ (fixed in ios 6)
var
ua = navigator.userAgent;
- if( $viewport[0] && ua.match( /iPhone|iPad/i ) &&
ua.match( /OS [4-5]_0/ ) ) {
+ if( $viewportMeta[0] && ua.match( /iPhone|iPad/i ) &&
ua.match( /OS [4-5]_0/ ) ) {
lockViewport();
document.addEventListener( 'gesturestart',
function() {
lockViewport();
diff --git a/javascripts/common/mf-notification.js
b/javascripts/common/mf-notification.js
index 81542e9..bd0f91d 100644
--- a/javascripts/common/mf-notification.js
+++ b/javascripts/common/mf-notification.js
@@ -4,18 +4,6 @@
canCancel = true,
inBeta = mw.config.get( 'wgMFMode' ) === 'beta';
- if ( !M.supportsPositionFixed() ) {
- calculatePosition = function() {
- var h = $( '#mf-notification' ).outerHeight();
- $( '#mf-notification' ).css( {
- top: ( window.innerHeight +
window.pageYOffset ) - h,
- bottom: 'auto',
- position: 'absolute'
- } );
- };
- $( document ).scroll( calculatePosition );
- }
-
function isVisible() {
return $( '#mf-notification' ).is( ':visible' );
}
@@ -54,7 +42,7 @@
function init( firstRun ) {
// FIXME: turn into view with template
var el = $( '<div id="mf-notification"
class="position-fixed"><div></div></div>' ).
- appendTo( '#mw-mf-page-center' )[ 0 ];
+ appendTo( '#notifications' )[ 0 ];
if ( inBeta ) {
notifyAuthenticatedUser();
diff --git a/less/common/mainmenu.less b/less/common/mainmenu.less
index cf05779..9f831f3 100644
--- a/less/common/mainmenu.less
+++ b/less/common/mainmenu.less
@@ -4,7 +4,7 @@
#mw-mf-viewport {
position: relative;
- min-height: 100%;
+ height: 100%;
}
#mw-mf-page-center {
@@ -118,6 +118,7 @@
margin-left: -@menuBorder;
// disable horizontal scrolling
overflow: hidden;
+ height: auto !important;
}
#mw-mf-page-center {
diff --git a/less/common/mf-common.less b/less/common/mf-common.less
index 5b42819..3f89dc7 100644
--- a/less/common/mf-common.less
+++ b/less/common/mf-common.less
@@ -273,12 +273,20 @@
display: block;
}
-.supportsPositionFixed {
+.position-fixed {
+ position: fixed;
+ // workaround for:
+ // http://code.google.com/p/chromium/issues/detail?id=20574
+ // (otherwise hidden drawer causes .buttonBar to render incorrectly)
+ .transform( translate3d(0,0,0) );
+}
+
+.no-position-fixed {
+ #notifications {
+ bottom: 0;
+ }
+
.position-fixed {
- position: fixed;
- // workaround for:
- // http://code.google.com/p/chromium/issues/detail?id=20574
- // (otherwise hidden drawer causes .buttonBar to render
incorrectly)
- .transform( translate3d(0,0,0) );
+ position: absolute;
}
}
diff --git a/less/common/notifications.less b/less/common/notifications.less
index 9ef0039..252da5a 100644
--- a/less/common/notifications.less
+++ b/less/common/notifications.less
@@ -1,23 +1,31 @@
@import "../mf-mixins.less";
@toastNotificationColor: #373737;
+#notifications {
+ // it's only a container, should not get in the way
+ height: 0;
+ // needed for Android 4.x
+ position: absolute;
+ z-index: 5;
+ // needed for MSIE 9 (Windows Phone 7)
+ width: 100%;
+}
+
/* Notifications */
#mf-notification,
.drawer {
- /* -2px to avoid a weird glitch in some browsers where the popup moves
- * slightly when scrolling */
- bottom: -2px;
+ bottom: 0;
width: 100%;
background-color: @searchBoxColorTo;
.boxshadow( 0, -1px, 8px, 0, rgba(0, 0, 0, 0.35) );
word-wrap: break-word;
- z-index: -1;
+ // needs to be higher than for overlays to show on top of overlays
+ z-index: 5;
+ // don't use visibility: hidden in old browsers that don't support
animations
display: none;
&.visible {
- // needs to be higher than for overlays to show on top of
overlays
- z-index: 5;
- display: block
+ display: block;
}
}
@@ -25,19 +33,23 @@
.animations .alpha {
#mf-notification,
.drawer {
+ @duration: .25s;
display: block;
+ visibility: hidden;
/* we can't determine the actual size of the drawer in CSS, so
this is
* an estimate; it doesn't have to be exact because it's used
only for
* the sliding animation, not for hiding the drawer */
- bottom: -11em;
+ .transform( translate3d(0, 100px, 0) );
opacity: 0;
- .transition( all, .2s );
+ // delay visibility transition to make other transitions visible
+ // http://fvsch.com/code/transition-fade/test5.html/
+ .transition( transform @duration, opacity @duration, visibility
0 @duration );
&.visible {
+ .transition( transform @duration, opacity @duration );
+ visibility: visible;
opacity: 1;
- /* -0.2em to avoid a weird glitch in some browsers
where the popup moves
- * slightly when scrolling */
- .transform( translate3d(0, -10.8em, 0) );
+ .transform( translate3d(0, 0, 0) );
}
}
}
@@ -125,7 +137,7 @@
}
a:visited, a {
- color: #3354C0;
+ color: #3354C0;
}
p {
diff --git a/less/mf-mixins.less b/less/mf-mixins.less
index 72b90c2..e496a8f 100644
--- a/less/mf-mixins.less
+++ b/less/mf-mixins.less
@@ -89,16 +89,14 @@
transform: @transform;
}
-.transition( @property: all, @duration: .2s, @timingFunction: ease ) {
+// http://www.toekneestuck.com/blog/2012/05/15/less-css-arguments-variable/
+.transition( @dummy, @dummier: X, ... ) {
// avoid Webkit bugs
-webkit-backface-visibility: hidden;
- -webkit-transition-property: ~`"@{property}" === "transform" ?
"-webkit-@{property}" : "@{property}"`;
- transition-property: @property;
- -webkit-transition-duration: @duration;
- transition-duration: @duration;
- -webkit-transition-timing-function: @timingFunction;
- transition-timing-function: @timingFunction;
+ @args: ~`"@{arguments}".replace(/^\[|(, X)?\]$/g, '')`;
+ -webkit-transition: ~`"@{args}".replace('transform',
'-webkit-transform')`;
+ transition: @args;
}
.animation( @name, @duration, @function: ease-in-out, @iterationCount:
infinite, @direction: alternate ) {
diff --git a/less/modules/mf-watchstar.less b/less/modules/mf-watchstar.less
index a499b07..0846d6c 100644
--- a/less/modules/mf-watchstar.less
+++ b/less/modules/mf-watchstar.less
@@ -11,7 +11,7 @@
.animations .beta,
.animations .alpha {
.watch-this-article {
- .transition( transform, .5s );
+ .transition( transform .5s );
&.watched {
.transform( rotate(72deg) );
diff --git a/less/specials/mobilediff.less b/less/specials/mobilediff.less
index c349d70..1764bad 100644
--- a/less/specials/mobilediff.less
+++ b/less/specials/mobilediff.less
@@ -172,12 +172,10 @@
}
}
-.supportsPositionFixed {
- #mw-mf-diffview {
- #mw-mf-userinfo {
- bottom: 0;
- left: 0;
- right: 0;
- }
+#mw-mf-diffview {
+ #mw-mf-userinfo {
+ bottom: 0;
+ left: 0;
+ right: 0;
}
}
diff --git a/less/specials/uploads.less b/less/specials/uploads.less
index e709ca5..413a760 100644
--- a/less/specials/uploads.less
+++ b/less/specials/uploads.less
@@ -138,7 +138,7 @@
.slideable {
.slider {
left: 0;
- .transition( @duration: .5s );
+ .transition( .5s );
&.slider-left {
.transform( translate3d(-100%, 0, 0) )
diff --git a/stylesheets/common/mf-common.css b/stylesheets/common/mf-common.css
index 16ad285..f519d05 100644
--- a/stylesheets/common/mf-common.css
+++ b/stylesheets/common/mf-common.css
@@ -226,8 +226,14 @@
.client-js .jsonly {
display: block;
}
-.supportsPositionFixed .position-fixed {
+.position-fixed {
position: fixed;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
+.no-position-fixed #notifications {
+ bottom: 0;
+}
+.no-position-fixed .position-fixed {
+ position: absolute;
+}
diff --git a/stylesheets/common/notifications.css
b/stylesheets/common/notifications.css
index 8b0492b..358858f 100644
--- a/stylesheets/common/notifications.css
+++ b/stylesheets/common/notifications.css
@@ -1,20 +1,22 @@
+#notifications {
+ height: 0;
+ position: absolute;
+ z-index: 5;
+ width: 100%;
+}
/* Notifications */
#mf-notification,
.drawer {
- /* -2px to avoid a weird glitch in some browsers where the popup moves
- * slightly when scrolling */
-
- bottom: -2px;
+ bottom: 0;
width: 100%;
background-color: #f3f3f3;
box-shadow: 0 -1px 8px 0 rgba(0, 0, 0, 0.35);
word-wrap: break-word;
- z-index: -1;
+ z-index: 5;
display: none;
}
#mf-notification.visible,
.drawer.visible {
- z-index: 5;
display: block;
}
.animations .beta #mf-notification,
@@ -22,30 +24,29 @@
.animations .beta .drawer,
.animations .alpha .drawer {
display: block;
+ visibility: hidden;
/* we can't determine the actual size of the drawer in CSS, so this is
* an estimate; it doesn't have to be exact because it's used
only for
* the sliding animation, not for hiding the drawer */
- bottom: -11em;
+ -webkit-transform: translate3d(0, 100px, 0);
+ transform: translate3d(0, 100px, 0);
opacity: 0;
-webkit-backface-visibility: hidden;
- -webkit-transition-property: all;
- transition-property: all;
- -webkit-transition-duration: 0.2s;
- transition-duration: 0.2s;
- -webkit-transition-timing-function: ease;
- transition-timing-function: ease;
+ -webkit-transition: -webkit-transform 0.25s, opacity 0.25s, visibility 0
0.25s;
+ transition: transform 0.25s, opacity 0.25s, visibility 0 0.25s;
}
.animations .beta #mf-notification.visible,
.animations .alpha #mf-notification.visible,
.animations .beta .drawer.visible,
.animations .alpha .drawer.visible {
+ -webkit-backface-visibility: hidden;
+ -webkit-transition: -webkit-transform 0.25s, opacity 0.25s;
+ transition: transform 0.25s, opacity 0.25s;
+ visibility: visible;
opacity: 1;
- /* -0.2em to avoid a weird glitch in some browsers where the popup moves
- * slightly when scrolling */
-
- -webkit-transform: translate3d(0, -10.8em, 0);
- transform: translate3d(0, -10.8em, 0);
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
}
#mf-notification {
font-size: 0.9em;
diff --git a/stylesheets/common/ui.css b/stylesheets/common/ui.css
index 54c3cf1..2df0653 100644
--- a/stylesheets/common/ui.css
+++ b/stylesheets/common/ui.css
@@ -198,7 +198,7 @@
/* Left menu */
#mw-mf-viewport {
position: relative;
- min-height: 100%;
+ height: 100%;
}
#mw-mf-page-center {
width: 100%;
@@ -305,6 +305,7 @@
body.navigation-enabled #mw-mf-viewport {
margin-left: -12px;
overflow: hidden;
+ height: auto !important;
}
body.navigation-enabled #mw-mf-page-center {
position: absolute;
diff --git a/stylesheets/modules/mf-watchstar.css
b/stylesheets/modules/mf-watchstar.css
index 4632992..18dde1f 100644
--- a/stylesheets/modules/mf-watchstar.css
+++ b/stylesheets/modules/mf-watchstar.css
@@ -5,12 +5,8 @@
.animations .beta .watch-this-article,
.animations .alpha .watch-this-article {
-webkit-backface-visibility: hidden;
- -webkit-transition-property: -webkit-transform;
- transition-property: transform;
- -webkit-transition-duration: 0.5s;
- transition-duration: 0.5s;
- -webkit-transition-timing-function: ease;
- transition-timing-function: ease;
+ -webkit-transition: -webkit-transform 0.5s;
+ transition: transform 0.5s;
}
.animations .beta .watch-this-article.watched,
.animations .alpha .watch-this-article.watched {
diff --git a/stylesheets/specials/mobilediff.css
b/stylesheets/specials/mobilediff.css
index 24c1a93..e722b0a 100644
--- a/stylesheets/specials/mobilediff.css
+++ b/stylesheets/specials/mobilediff.css
@@ -156,7 +156,7 @@
font-size: 0.9em;
margin-top: 8px;
}
-.supportsPositionFixed #mw-mf-diffview #mw-mf-userinfo {
+#mw-mf-diffview #mw-mf-userinfo {
bottom: 0;
left: 0;
right: 0;
diff --git a/stylesheets/specials/uploads.css b/stylesheets/specials/uploads.css
index 955668b..9525699 100644
--- a/stylesheets/specials/uploads.css
+++ b/stylesheets/specials/uploads.css
@@ -128,12 +128,8 @@
.animations .alpha .slideable .slider {
left: 0;
-webkit-backface-visibility: hidden;
- -webkit-transition-property: all;
- transition-property: all;
- -webkit-transition-duration: 0.5s;
- transition-duration: 0.5s;
- -webkit-transition-timing-function: ease;
- transition-timing-function: ease;
+ -webkit-transition: 0.5s;
+ transition: 0.5s;
}
.animations .beta .slideable .slider.slider-left,
.animations .alpha .slideable .slider.slider-left {
--
To view, visit https://gerrit.wikimedia.org/r/71855
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I9aa603fae53c36184421c520e911f6e4b9ba5300
Gerrit-PatchSet: 4
Gerrit-Project: mediawiki/extensions/MobileFrontend
Gerrit-Branch: master
Gerrit-Owner: JGonera <[email protected]>
Gerrit-Reviewer: Jdlrobson <[email protected]>
Gerrit-Reviewer: jenkins-bot
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits