User:JDrewniak (WMF)/notes/Close thyself - Managing MF Overlays
Who show/hides what? When? There are overlays, and there is OverlayManager, and there are also Drawers. Sometimes Overlays show/hide themselves, sometimes OverlayManager hides them. Drawers manage themselves.
Overlay
editOverlays manage their own DOM structure, (i.e. everything inside the overlay, Overlay.$el
). They also manage their own DOM events and a few window events as well.
DOM managed by Overlay
editthis
refers to the Overlay.
this.$el
.addClass( ‘overlay-ios’ );
.$( ‘.overlay-header h2 span’ ).addClass( ‘truncated-text’ );
.addClass( ‘visible’ );
.detach();
this.$spinner
.addClass( ‘hidden’ );
.removeClass( ‘hidden’ );
this.$overlayContent
.height
window
.scrollTo
$html
.addClass( overlay-enabled’ );
.removeClass( ‘overlay-enabled’ );
.find( ‘#mw-mf-page-center’ )
The bits that touch the actual document DOM are .detach()
and window.scrollTo
. These are executed in the Overlay show/hide methods.
OverlayManager
editManages overlays based on routing and keeps track of open overlays.
DOM managed by OverlayManager
editBefore this patch, OverlayManager did not manage any DOM directly, instead, it called Overlay.show/hide based on routing events.
Now OverlayManager accepts an appendToSelector
and attaches the Overlay to the DOM in the _show
method, but does not detach the overlay in the _hideOverlay
method.
This means that currently Overlays cannot attach themselves to the DOM. This breaks loadingOverlays in rlModuleLoader, which calls Overlay.show().
In both before/after that patch, the following code produces a “ghost overlay” . In console:
var om = mw.mobileFrontend.require( 'mobile.startup' ).OverlayManager.getSingleton();
var O = mw.mobileFrontend.require( 'mobile.startup/Overlay' )
var o = new O({ heading: 'why' })
var o2 = new O({ heading: 'hello' })
// On master
om.show( o ); om.show( o2 ); om.hide( o2 );
// In production (still)
om._showOverlay( o ); om._showOverlay( o2 ); om._hideOverlay( o2 );
// Expected: o shown in all its glory. actual: body hidden
This is because when one overlay calls hide, it removes the overlay-enabled
class from the HTML element, regardless of other open overlays.
Given this problem
- Should OverlayManager append the
overlay-enabled
class to the HTML element, instead of having Overlay do it? - Should OverlayManager detach the Overlay from the DOM as well?
- Should Drawers have their own manager? Which does the same thing as OverlayManager just without routing?
- Can OverlayManager be refactored for both cases?
Open questions:
“When does an overlay not use a route?“
-> in rlModuleLoader, loadingOverlay.show/hide is called manually. Anything that calls loader.loadModule
and returns a loadingOverlay, calls Overlay.hide()
on that overlay before showing the new overlay.
- Categories overlay
- VE overlay
- Language overlay
- Nearby
All these modules call Overlay.hide()
. For this reason, moving the DOM ‘detach’ behaviour to the OverlayManager would require refactoring these modules to use the overlayManager. In these instances however, the overlays are all shown through the OverlayManager.