From f2e8cd6dbdfc4c2004c5ff5f2d20b6d484589c30 Mon Sep 17 00:00:00 2001 From: Timo Tijhof Date: Wed, 4 Oct 2017 21:30:24 +0100 Subject: [PATCH] mediawiki.notification: Move offset() computation to next frame Crrently on all page views in WMF production, the $.ready handler is inserting the notif $area and subsequently doing a forced style calculation due to getBoundingClientRect() from offset(). Move this to an animation frame instead and re-order the statements so that DOM reads go before DOM writes. Change-Id: I7c6201dc8d4e3227e01b75e853b6e4dc9a734031 --- .../src/mediawiki/mediawiki.notification.js | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/resources/src/mediawiki/mediawiki.notification.js b/resources/src/mediawiki/mediawiki.notification.js index d5289bd9d7..20f8b8d31c 100644 --- a/resources/src/mediawiki/mediawiki.notification.js +++ b/resources/src/mediawiki/mediawiki.notification.js @@ -280,6 +280,7 @@ .toggleClass( 'mw-notification-area-layout', !isFloating ); } + // Write to the DOM: // Prepend the notification area to the content area and save its object. $area = $( '
' ) // Pause auto-hide timers when the mouse is in the notification area. @@ -301,20 +302,29 @@ } ); mw.util.$content.prepend( $area ); - offset = $area.offset(); - $area.css( 'display', 'none' ); - $( window ).on( 'scroll', updateAreaMode ); + // Read from the DOM: + // Must be in the next frame to avoid synchronous layout + // computation from offset()/getBoundingClientRect(). + rAF( function () { + offset = $area.offset(); - // Initial mode - updateAreaMode(); + // Initial mode (reads, and then maybe writes) + updateAreaMode(); - // Handle pre-ready queue. - isPageReady = true; - while ( preReadyNotifQueue.length ) { - notif = preReadyNotifQueue.shift(); - notif.start(); - } + // Once we have the offset for where it would normally render, set the + // initial state of the (currently empty) notification area to be hidden. + $area.css( 'display', 'none' ); + + $( window ).on( 'scroll', updateAreaMode ); + + // Handle pre-ready queue. + isPageReady = true; + while ( preReadyNotifQueue.length ) { + notif = preReadyNotifQueue.shift(); + notif.start(); + } + } ); } /** -- 2.20.1