jenkins-bot has submitted this change and it was merged.

Change subject: Don't pull in initialisation code.
......................................................................


Don't pull in initialisation code.

In Special:JavaScriptTest/qunit/plain there is no page to construct
Thus a lot of the code in mobile.startup init.js was causing side
effects and it really shouldn't be pulled into the test suite.

Separating our initialisation scripts from our classes allows us to use
them in places over than Minerva and test them better in isolation without
incurring side effects.

Changes:
* EditorOverlayBase and classes that inherit from it
 must be passed an instance of PageApi
* TalkSectionAddOverlay, TalkOverlay,
TalkSectionOverlay now must be passed an instance of PageApi
* Skins can now be initialized without passing tabletModules as an
option
* Rename of mobile.head to more meaningful skins.minerva.scripts.top
* Rename all ResourceLoader modules which have initialisation code in them to
have a skins.minerva prefix.
* Make it clear that any module defined with a mobile prefix should not have any
side effects
* Leave module names that impact anonymous users intact until cache clears (note
mobile.talk and mobile.newusers only impact logged in users so are cache exempt)
* Update test for toast code now that it's not passing simply due to 
side-effects of
pulling in styles that should not be pulled in

Dependency: I1e19e6df6f36ec6d59630d651ca7f1e74cb16d30
Dependency: Iaef2e7a0706b0ec6c470ab43692c48b96a74b403
Bug: T103991
Bug: T101795
Change-Id: If37a623f1571645a040c10fc7c5304c7ee0fd332
---
M includes/Resources.php
M includes/skins/SkinMinerva.php
M includes/skins/SkinMinervaBeta.php
M resources/mobile.editor.common/EditorOverlayBase.js
R resources/mobile.issues/cleanuptemplates.js
R resources/mobile.references/references.js
M resources/mobile.startup/Skin.js
M resources/mobile.talk.overlays/TalkOverlay.js
M resources/mobile.talk.overlays/TalkSectionAddOverlay.js
M resources/mobile.talk.overlays/TalkSectionOverlay.js
R resources/mobile.toggle/toggle.js
R resources/mobile.toggle/toggle.less
A resources/skins.minerva.alpha.scripts/quickLookup.js
R resources/skins.minerva.beta.scripts/fontchanger.js
R resources/skins.minerva.categories/init.js
R resources/skins.minerva.editor/init.js
R resources/skins.minerva.newusers/init.js
R resources/skins.minerva.notifications/init.js
R resources/skins.minerva.scripts.top/init.js
M resources/skins.minerva.scripts/init.js
R resources/skins.minerva.scripts/mobileRedirect.js
R resources/skins.minerva.scripts/preInit.js
R resources/skins.minerva.scripts/search.js
R resources/skins.minerva.tablet.scripts/toc.js
R resources/skins.minerva.talk/init.js
R resources/skins.minerva.talk/talk.less
A resources/skins.minerva.toggling/init.js
R resources/skins.minerva.watchstar/init.js
M tests/browser/features/step_definitions/notification_steps.rb
R tests/qunit/mobile.issues/test_cleanuptemplates.js
R tests/qunit/mobile.references/test_references.js
M tests/qunit/mobile.talk.overlays/test_TalkOverlay.js
M tests/qunit/mobile.talk.overlays/test_TalkSectionOverlay.js
R tests/qunit/mobile.toggle/test_toggle.js
M tests/qunit/mobile.watchstar/test_Watchstar.js
35 files changed, 437 insertions(+), 264 deletions(-)

Approvals:
  Bmansurov: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/includes/Resources.php b/includes/Resources.php
index b2ee74b..5c4d095 100644
--- a/includes/Resources.php
+++ b/includes/Resources.php
@@ -217,6 +217,12 @@
        ),
 );
 
+/*
+Any modules defined here should come without side effects.
+A module prefixed with 'mobile.' should be reusable in any context e.g.
+any skin. If you are writing an initialisation script please define it with
+the skin.minerva. prefix along with all the others below.
+*/
 $wgResourceModules = array_merge( $wgResourceModules, array(
        'mobile.modules' => $wgMFResourceFileModuleBoilerplate + array(
                'scripts' => array(
@@ -249,17 +255,6 @@
                        'resources/mobile.context/context.js',
                ),
        ),
-       'mobile.browse' => $wgMFResourceFileModuleBoilerplate + array(
-               'dependencies' => array(
-                       'mobile.loggingSchemas'
-               ),
-               'scripts' => array(
-                       'resources/mobile.browse/init.js',
-               ),
-               'styles' => array(
-                       'resources/mobile.browse/tags.less',
-               )
-       ),
        'mobile.browser' => $wgMFResourceFileModuleBoilerplate + array(
                'dependencies' => array(
                        'mobile.view',
@@ -271,6 +266,7 @@
        'mobile.mainMenu' => $wgMFResourceFileModuleBoilerplate + array(
                'dependencies' => array(
                        'mobile.view',
+                       'mobile.browser',
                ),
                'position' => 'bottom',
                'styles' => array(
@@ -373,6 +369,7 @@
                'dependencies' => array(
                        'mobile.infiniteScroll',
                        'mobile.pagelist.scripts',
+                       'mobile.modifiedBar',
                ),
                'scripts' => array(
                        'resources/mobile.watchlist/WatchListApi.js',
@@ -388,7 +385,6 @@
                ),
                'scripts' => array(
                        'resources/mobile.toc/TableOfContents.js',
-                       'resources/mobile.toc/init.js',
                ),
                'styles' => array(
                        'resources/mobile.toc/toc.less',
@@ -413,7 +409,6 @@
 
        'mobile.settings' => $wgMFResourceFileModuleBoilerplate + array(
                'dependencies' => array(
-                       'mobile.head',
                        'jquery.cookie',
                        'mediawiki.storage',
                ),
@@ -425,7 +420,9 @@
        // FIXME: Split this module into different features.
        'mobile.startup' => $wgMFResourceFileModuleBoilerplate + array(
                'dependencies' => array(
-                       'mobile.head',
+                       'mobile.context',
+                       'mobile.browser',
+                       'mobile.oo',
                        'mobile.user',
                        'mediawiki.api',
                        'mobile.settings',
@@ -467,7 +464,6 @@
                        'resources/mobile.startup/Skin.js',
                        'resources/mobile.startup/Schema.js',
                        'resources/mobile.startup/util.js',
-                       'resources/mobile.startup/init.js',
                ),
                'position' => 'bottom',
        ),
@@ -486,43 +482,29 @@
                        'mediawiki.user',
                        'mediawiki.storage',
                        // Ensure M.define exists
-                       'mobile.head',
+                       'mobile.modules',
                ),
                'scripts' => array(
                        'resources/mobile.user/user.js',
                ),
        ),
 
-       'mobile.editor' => $wgMFResourceParsedMessageModuleBoilerplate + array(
+       // FIXME: Remove when cache clears
+       'mobile.editor' => $wgMFResourceFileModuleBoilerplate + array(
                'dependencies' => array(
-                       'mobile.startup',
-                       'mobile.drawers',
-                       'mediawiki.ui.input',
-                       'mobile.settings',
-                       'mobile.toast',
-                       // Let's ensure toggle styles have loaded before adding 
edit section links
-                       'mobile.toggling',
-                       // Route needs moduleLoader
-                       'mobile.overlays',
-                       'mediawiki.jqueryMsg',
+                       'skins.minerva.editor',
                ),
-               'messages' => array(
-                       // editor.js
-                       'mobile-frontend-editor-disabled',
-                       'mobile-frontend-editor-unavailable',
-                       'mobile-frontend-editor-uploadenable',
-                       'mobile-frontend-editor-blocked-info-loggedin' => 
array( 'parse' ),
-                       'mobile-frontend-editor-cta',
-                       'mobile-frontend-editor-anon',
-                       'mobile-frontend-editor-undo-unsupported',
-                       // edit link
-                       'mobile-frontend-editor-edit',
-                       'mobile-frontend-editor-redlink-create',
-                       'mobile-frontend-editor-redlink-leave',
-                       'mobile-frontend-editor-redlink-explain' => array( 
'parse' ),
+       ),
+       // FIXME: Remove when cache clears
+       'mobile.browse' => $wgMFResourceFileModuleBoilerplate + array(
+               'dependencies' => array(
+                       'skins.minerva.browse',
                ),
-               'scripts' => array(
-                       'resources/mobile.editor/init.js',
+       ),
+       // FIXME: Remove when cache clears
+       'mobile.toggling' => $wgMFResourceFileModuleBoilerplate + array(
+               'dependencies' => array(
+                       'skins.minerva.toggling',
                ),
        ),
 
@@ -688,26 +670,6 @@
                )
        ),
 
-       'mobile.talk' => $wgMFResourceFileModuleBoilerplate + array(
-               'dependencies' => array(
-                       'mobile.overlays',
-               ),
-               'styles' => array(
-                       'resources/mobile.talk/talk.less',
-               ),
-               'scripts' => array(
-                       'resources/mobile.talk/init.js',
-               ),
-               'messages' => array(
-                       'mobile-frontend-talk-overlay-header',
-                       'mobile-frontend-talk-add-overlay-submit',
-                       'mobile-frontend-editor-licensing',
-                       'mobile-frontend-editor-licensing-with-terms',
-                       // FIXME: Remove after cache is cleared
-                       'talk',
-               ),
-       ),
-
        'mobile.search' => $wgMFResourceParsedMessageModuleBoilerplate + array(
                'dependencies' => array(
                        'mobile.pagelist.scripts',
@@ -720,7 +682,6 @@
                'scripts' => array(
                        'resources/mobile.search/SearchOverlay.js',
                        'resources/mobile.search/MobileWebSearchLogger.js',
-                       'resources/mobile.search/init.js',
                ),
                'templates' => array(
                        'SearchOverlay.hogan' => 
'resources/mobile.search/SearchOverlay.hogan',
@@ -769,7 +730,6 @@
 
        'mobile.talk.overlays' => $wgMFResourceFileModuleBoilerplate + array(
                'dependencies' => array(
-                       'mobile.talk',
                        'mediawiki.ui.anchor',
                        'mobile.editor.common',
                ),
@@ -876,16 +836,6 @@
                ),
        ),
 
-       'mobile.categories' => $wgMFResourceFileModuleBoilerplate + array(
-               'dependencies' => array(
-                       'mobile.overlays',
-                       'mobile.loggingSchemas',
-               ),
-               'scripts' => array(
-                       'resources/mobile.categories/init.js',
-               ),
-       ),
-
        'mobile.categories.overlays' => $wgMFResourceFileModuleBoilerplate + 
array(
                'dependencies' => array(
                        'mediawiki.Title',
@@ -988,22 +938,6 @@
                ),
        ),
 
-       // This module remembers that desktop site is your preference for 
viewing on a mobile phone
-       'mobile.redirect' => $wgMFResourceFileModuleBoilerplate + array(
-               'dependencies' => array(
-                       'mobile.startup',
-                       'mobile.toast',
-                       'mobile.settings',
-               ),
-               'scripts' => array(
-                       'resources/mobile.redirect/init.js',
-               ),
-               'messages' => array(
-                       // mf-stop-mobile-redirect.js
-                       'mobile-frontend-cookies-required',
-               ),
-       ),
-
        'mobile.references' => $wgMFResourceFileModuleBoilerplate + array(
                'dependencies' => array(
                        'mobile.drawers',
@@ -1020,20 +954,21 @@
                ),
                'scripts' => array(
                        'resources/mobile.references/ReferencesDrawer.js',
-                       'resources/mobile.references/init.js',
+                       'resources/mobile.references/references.js',
                ),
        ),
 
-       'mobile.toggling' => $wgMFResourceFileModuleBoilerplate + array(
+       'mobile.toggle' => $wgMFResourceFileModuleBoilerplate + array(
                'dependencies' => array(
-                       'mobile.startup',
                        'mobile.settings',
+                       // uses util.js
+                       'mobile.startup',
                ),
                'styles' => array(
-                       'resources/mobile.toggling/toggle.less',
+                       'resources/mobile.toggle/toggle.less',
                ),
                'scripts' => array(
-                       'resources/mobile.toggling/init.js',
+                       'resources/mobile.toggle/toggle.js',
                ),
        ),
 
@@ -1053,23 +988,6 @@
                ),
                'templates' => array(
                        'PointerOverlay.hogan' => 
'resources/mobile.contentOverlays/PointerOverlay.hogan',
-               ),
-       ),
-
-       'mobile.newusers' => $wgMFResourceFileModuleBoilerplate + array(
-               'dependencies' => array(
-                       'mobile.editor',
-                       'mobile.contentOverlays',
-                       'mobile.loggingSchemas',
-               ),
-               'scripts' => array(
-                       'resources/mobile.newusers/init.js',
-               ),
-               'messages' => array(
-                       // newbieEditor.js
-                       'mobile-frontend-editor-tutorial-summary',
-                       'mobile-frontend-editor-tutorial-confirm',
-                       'mobile-frontend-editor-tutorial-cancel',
                ),
        ),
 
@@ -1099,21 +1017,10 @@
                ),
        ),
 
-       'mobile.watchstar.init' => $wgMFResourceFileModuleBoilerplate + array(
+       // FIXME: Remove when cache clears.
+       'mobile.watchstar.init' => array(
                'dependencies' => array(
-                       'mobile.watchstar',
-               ),
-               'scripts' => array(
-                       'resources/mobile.watchstar.init/init.js',
-               ),
-               'messages' => array(
-                       'watchthispage',
-                       'unwatchthispage',
-                       // mf-watchstar.js
-                       'mobile-frontend-watchlist-add',
-                       'mobile-frontend-watchlist-removed',
-                       'mobile-frontend-watchlist-cta',
-                       'mobile-frontend-watchlist-please-wait',
+                       'skins.minerva.watchstar',
                ),
        ),
 
@@ -1163,7 +1070,7 @@
                ),
                'scripts' => array(
                        'resources/mobile.issues/CleanupOverlay.js',
-                       'resources/mobile.issues/init.js',
+                       'resources/mobile.issues/cleanuptemplates.js',
                ),
                'messages' => array(
                        // issues.js
@@ -1284,17 +1191,6 @@
                'position' => 'top',
        ),
 
-       'mobile.fontchanger.init' => $wgMFResourceFileModuleBoilerplate + array(
-               'dependencies' => array(
-                       'mobile.startup',
-                       'mobile.settings',
-               ),
-               'scripts' => array(
-                       'resources/mobile.fontchanger.init/init.js',
-               ),
-               'position' => 'top',
-       ),
-
        'mobile.fontchanger' => $wgMFResourceFileModuleBoilerplate + array(
                'dependencies' => array(
                        'mobile.startup',
@@ -1354,14 +1250,15 @@
  * Extension:Echo related modules
  */
 $wgMobileEchoModules = array(
-       'mobile.notifications' => $wgMFResourceFileModuleBoilerplate + array(
+       'skins.minerva.notifications' => $wgMFResourceFileModuleBoilerplate + 
array(
                'dependencies' => array(
                        'mobile.overlays',
+                       'skins.minerva.scripts',
                        'mediawiki.ui.anchor',
                        'mobile.loggingSchemas',
                ),
                'scripts' => array(
-                       'resources/mobile.notifications/init.js',
+                       'resources/skins.minerva.notifications/init.js',
                ),
        ),
 
@@ -1648,9 +1545,14 @@
 // These modules are the gateways to all other modules and will ensure the 
other modules get loaded
 // on the page.
 $wgMinervaBootstrapModules = array(
-       // Important: This module is loaded on both mobile and desktop skin
-       // This JavaScript is loaded at the top of the page so be cautious what 
you put in it.
+       //FIXME: Remove when cache has cleared. Use skins.minerva.head instead
        'mobile.head' => $wgMFResourceFileModuleBoilerplate + array(
+               'dependencies' => array(
+                       'skins.minerva.scripts.top',
+               ),
+       ),
+
+       'skins.minerva.scripts.top' => $wgMFResourceFileModuleBoilerplate + 
array(
                'dependencies' => array(
                        'mobile.modifiedBar',
                        'mobile.mainMenu',
@@ -1664,7 +1566,7 @@
                        'mobile.context',
                ),
                'scripts' => array(
-                       'resources/mobile.head/init.js',
+                       'resources/skins.minerva.scripts.top/init.js',
                ),
                'messages' => array(
                        // lastEdited.js
@@ -1682,37 +1584,169 @@
        // By mode. This should only ever be loaded in Minerva skin.
        'skins.minerva.scripts' => $wgMFResourceFileModuleBoilerplate + array(
                'dependencies' => array(
+                       'skins.minerva.scripts.top',
                        'mobile.startup',
+                       'mobile.mainMenu',
                        'mobile.loggingSchemas',
                        'skins.minerva.icons.images.js',
-                       // Feature modules that should be loaded in stable.
-                       // These modules should only setup routes/events or
-                       // load code under certain conditions.
                        'mobile.issues',
                        'mobile.search',
                        'mobile.references',
-                       'mobile.redirect',
                        'mobile.betaoptin',
+                       'mobile.toast',
+                       'mobile.settings',
                ),
                'scripts' => array(
+                       // FIXME: Merge preInit and init files.
+                       'resources/skins.minerva.scripts/preInit.js',
                        'resources/skins.minerva.scripts/init.js',
                        'resources/skins.minerva.scripts/initLogging.js',
+                       'resources/skins.minerva.scripts/mobileRedirect.js',
+                       'resources/skins.minerva.scripts/search.js',
+               ),
+               'messages' => array(
+                       // mf-stop-mobile-redirect.js
+                       'mobile-frontend-cookies-required',
                ),
        ),
+
+       'skins.minerva.browse' => $wgMFResourceFileModuleBoilerplate + array(
+               'dependencies' => array(
+                       'mobile.loggingSchemas'
+               ),
+               'scripts' => array(
+                       'resources/mobile.browse/init.js',
+               ),
+               'styles' => array(
+                       'resources/mobile.browse/tags.less',
+               )
+       ),
+
+       'skins.minerva.newusers' => $wgMFResourceFileModuleBoilerplate + array(
+               'dependencies' => array(
+                       'mobile.editor',
+                       'mobile.contentOverlays',
+                       'mobile.loggingSchemas',
+               ),
+               'scripts' => array(
+                       'resources/skins.minerva.newusers/init.js',
+               ),
+               'messages' => array(
+                       // newbieEditor.js
+                       'mobile-frontend-editor-tutorial-summary',
+                       'mobile-frontend-editor-tutorial-confirm',
+                       'mobile-frontend-editor-tutorial-cancel',
+               ),
+       ),
+
+       'skins.minerva.editor' => $wgMFResourceParsedMessageModuleBoilerplate + 
array(
+               'dependencies' => array(
+                       'skins.minerva.scripts',
+                       'mobile.drawers',
+                       'mediawiki.ui.input',
+                       'mobile.settings',
+                       'mobile.toast',
+                       // Let's ensure toggle styles have loaded before adding 
edit section links
+                       'skins.minerva.toggling',
+                       // Route needs moduleLoader
+                       'mobile.overlays',
+                       'mediawiki.jqueryMsg',
+               ),
+               'messages' => array(
+                       // editor.js
+                       'mobile-frontend-editor-disabled',
+                       'mobile-frontend-editor-unavailable',
+                       'mobile-frontend-editor-uploadenable',
+                       'mobile-frontend-editor-blocked-info-loggedin' => 
array( 'parse' ),
+                       'mobile-frontend-editor-cta',
+                       'mobile-frontend-editor-anon',
+                       'mobile-frontend-editor-undo-unsupported',
+                       // edit link
+                       'mobile-frontend-editor-edit',
+                       'mobile-frontend-editor-redlink-create',
+                       'mobile-frontend-editor-redlink-leave',
+                       'mobile-frontend-editor-redlink-explain' => array( 
'parse' ),
+               ),
+               'scripts' => array(
+                       'resources/skins.minerva.editor/init.js',
+               ),
+       ),
+
+       'skins.minerva.categories' => $wgMFResourceFileModuleBoilerplate + 
array(
+               'dependencies' => array(
+                       'mobile.overlays',
+                       'mobile.loggingSchemas',
+               ),
+               'scripts' => array(
+                       'resources/skins.minerva.categories/init.js',
+               ),
+       ),
+
+       'skins.minerva.talk' => $wgMFResourceFileModuleBoilerplate + array(
+               'dependencies' => array(
+                       'skins.minerva.scripts',
+                       'mobile.overlays',
+               ),
+               'styles' => array(
+                       'resources/skins.minerva.talk/talk.less',
+               ),
+               'scripts' => array(
+                       'resources/skins.minerva.talk/init.js',
+               ),
+               'messages' => array(
+                       'mobile-frontend-talk-overlay-header',
+                       'mobile-frontend-talk-add-overlay-submit',
+                       'mobile-frontend-editor-licensing',
+                       'mobile-frontend-editor-licensing-with-terms',
+                       // FIXME: Remove after cache is cleared
+                       'talk',
+               ),
+       ),
+
+       'skins.minerva.toggling' => $wgMFResourceParsedMessageModuleBoilerplate 
+ array(
+               'dependencies' => array(
+                       'mobile.toggle',
+                       'skins.minerva.scripts',
+               ),
+               'scripts' => array(
+                       'resources/skins.minerva.toggling/init.js',
+               ),
+       ),
+
+       'skins.minerva.watchstar' => $wgMFResourceFileModuleBoilerplate + array(
+               'dependencies' => array(
+                       'mobile.watchstar',
+                       'skins.minerva.scripts',
+               ),
+               'scripts' => array(
+                       'resources/skins.minerva.watchstar/init.js',
+               ),
+               'messages' => array(
+                       'watchthispage',
+                       'unwatchthispage',
+                       // mf-watchstar.js
+                       'mobile-frontend-watchlist-add',
+                       'mobile-frontend-watchlist-removed',
+                       'mobile-frontend-watchlist-cta',
+                       'mobile-frontend-watchlist-please-wait',
+               ),
+       ),
+
        // By mode. This should only ever be loaded in Minerva skin.
        'skins.minerva.beta.scripts' => $wgMFResourceFileModuleBoilerplate + 
array(
                'dependencies' => array(
                        'skins.minerva.scripts',
+                       'mobile.settings',
                        // Feature modules that should be loaded in beta should 
be listed below here.
                        // These modules should only setup routes/events or
                        // load code under certain conditions.
                        'mobile.bannerImage',
                        'mobile.search.beta',
-                       'mobile.fontchanger.init',
                ),
                'scripts' => array(
                        'resources/skins.minerva.beta.scripts/bannerImage.js',
                        
'resources/skins.minerva.beta.scripts/commonsCategory.js',
+                       'resources/skins.minerva.beta.scripts/fontchanger.js',
                ),
                'messages' => array(
                        'mobile-frontend-commons-category-view',
@@ -1725,11 +1759,20 @@
                ),
                'scripts' => array(),
        ),
-       'tablet.scripts' => $wgMFResourceFileModuleBoilerplate + array(
+       'skins.minerva.tablet.scripts' => $wgMFResourceFileModuleBoilerplate + 
array(
                'dependencies' => array(
                        // Feature modules that should be loaded on tablets 
should be listed below here.
                        'mobile.toc',
                ),
+               'scripts' => array(
+                       'resources/skins.minerva.tablet.scripts/toc.js',
+               ),
+       ),
+       // Remove when cache clears
+       'tablet.scripts' => array(
+               'dependencies' => array(
+                       'skins.minerva.tablet.scripts',
+               ),
        ),
 );
 
diff --git a/includes/skins/SkinMinerva.php b/includes/skins/SkinMinerva.php
index 97d9230..dc3ca0e 100644
--- a/includes/skins/SkinMinerva.php
+++ b/includes/skins/SkinMinerva.php
@@ -1015,12 +1015,12 @@
 
                if ( $user->isLoggedIn() ) {
                        if ( $this->useEcho() ) {
-                               $modules[] = 'mobile.notifications';
+                               $modules[] = 'skins.minerva.notifications';
                        }
 
                        if ( $this->isCurrentPageEditable() ) {
                                if ( $action === 'signup-edit' || $campaign === 
'leftNavSignup' ) {
-                                       $modules[] = 'mobile.newusers';
+                                       $modules[] = 'skins.minerva.newusers';
                                }
                        }
                }
@@ -1030,7 +1030,7 @@
                        ( $this->isTalkAllowed() || $title->isTalkPage() ) &&
                        $this->isWikiTextTalkPage()
                ) {
-                       $modules[] = 'mobile.talk';
+                       $modules[] = 'skins.minerva.talk';
                }
 
                return $modules;
@@ -1048,7 +1048,7 @@
                $modules['legacy'] = array();
 
                // Add minerva specific modules
-               $modules['head'] = 'mobile.head';
+               $modules['head'] = 'skins.minerva.scripts.top';
                // Define all the modules that should load on the mobile site 
and their dependencies.
                // Do not add mobules here.
                $modules['stable'] = 'skins.minerva.scripts';
@@ -1057,23 +1057,22 @@
                $modules['watch'] = array();
                if ( $this->isAllowedPageAction( 'watch' ) ) {
                        // Explicitly add the mobile watchstar code.
-                       $modules['watch'] = array( 'mobile.watchstar.init' );
+                       $modules['watch'] = array( 'skins.minerva.watchstar' );
                }
 
                if ( $this->isAllowedPageAction( 'edit' ) ) {
-                       $modules['editor'] = array( 'mobile.editor' );
+                       $modules['editor'] = array( 'skins.minerva.editor' );
                }
 
                // add the browse module if the page has a tag assigned to it
                if ( $this->getBrowseTags( $this->getTitle() ) ) {
-                       $modules['browse'] = array( 'mobile.browse' );
+                       $modules['browse'] = array( 'skins.minerva.browse' );
                }
 
                $modules['context'] = $this->getContextSpecificModules();
 
                if ( $this->isMobileMode ) {
-                       $modules['toggling'] = array( 'mobile.toggling' );
-                       $modules['eventlogging'] = array( 
'mobile.loggingSchemas' );
+                       $modules['toggling'] = array( 'skins.minerva.toggling' 
);
                }
                $modules['site'] = 'mobile.site';
 
diff --git a/includes/skins/SkinMinervaBeta.php 
b/includes/skins/SkinMinervaBeta.php
index befdbb9..3e3ce77 100644
--- a/includes/skins/SkinMinervaBeta.php
+++ b/includes/skins/SkinMinervaBeta.php
@@ -66,7 +66,7 @@
        public function getContextSpecificModules() {
                $modules = parent::getContextSpecificModules();
                if ( $this->getCategoryLinks( false ) ) {
-                       $modules[] = 'mobile.categories';
+                       $modules[] = 'skins.minerva.categories';
                }
 
                return $modules;
diff --git a/resources/mobile.editor.common/EditorOverlayBase.js 
b/resources/mobile.editor.common/EditorOverlayBase.js
index 850a570..33dea14 100644
--- a/resources/mobile.editor.common/EditorOverlayBase.js
+++ b/resources/mobile.editor.common/EditorOverlayBase.js
@@ -5,7 +5,6 @@
                Icon = M.require( 'Icon' ),
                toast = M.require( 'toast' ),
                user = M.require( 'user' ),
-               pageApi = M.require( 'pageApi' ),
                EditorOverlayBase;
 
        /**
@@ -43,6 +42,7 @@
                /**
                 * @inheritdoc
                 * @cfg {Object} defaults Default options hash.
+                * @cfg {PageApi} defaults.pageApi an api module to retrieve 
pages.
                 * @cfg {Boolean} defaults.hasToolbar Whether the editor has a 
toolbar or not. When
                 *  disabled a header will be show instead.
                 * @cfg {String} defaults.continueMsg Caption for the next 
button on edit form which takes
@@ -67,6 +67,7 @@
                 * released to inform the user.
                 */
                defaults: $.extend( {}, Overlay.prototype.defaults, {
+                       pageApi: undefined,
                        hasToolbar: false,
                        continueMsg: mw.msg( 'mobile-frontend-editor-continue' 
),
                        cancelMsg: mw.msg( 'mobile-frontend-editor-cancel' ),
@@ -145,7 +146,7 @@
                                self = this;
 
                        // FIXME: use generic method for following 3 lines
-                       pageApi.invalidatePage( title );
+                       this.options.pageApi.invalidatePage( title );
 
                        if ( this.isNewPage ) {
                                msg = 'mobile-frontend-editor-success-new-page';
diff --git a/resources/mobile.issues/init.js 
b/resources/mobile.issues/cleanuptemplates.js
similarity index 94%
rename from resources/mobile.issues/init.js
rename to resources/mobile.issues/cleanuptemplates.js
index 3e53ad1..58d0cde 100644
--- a/resources/mobile.issues/init.js
+++ b/resources/mobile.issues/cleanuptemplates.js
@@ -114,14 +114,8 @@
                        }
                }
 
-               // Setup the issues banner on the page
-               initPageIssues();
-               // Show it in edit preview.
-               M.on( 'edit-preview', function ( overlay ) {
-                       initPageIssues( overlay.$el );
-               } );
-
                return {
+                       init: initPageIssues,
                        createBanner: createBanner,
                        _extractMessage: extractMessage
                };
diff --git a/resources/mobile.references/init.js 
b/resources/mobile.references/references.js
similarity index 97%
rename from resources/mobile.references/init.js
rename to resources/mobile.references/references.js
index a800fcc..7354e8c 100644
--- a/resources/mobile.references/init.js
+++ b/resources/mobile.references/references.js
@@ -62,10 +62,6 @@
 
        }
 
-       $( function () {
-               setup();
-       } );
-
        M.define( 'references', {
                setup: setup
        } );
diff --git a/resources/mobile.startup/Skin.js b/resources/mobile.startup/Skin.js
index 24ae215..a352a2c 100644
--- a/resources/mobile.startup/Skin.js
+++ b/resources/mobile.startup/Skin.js
@@ -102,9 +102,10 @@
 
                        this.page = options.page;
                        this.name = options.name;
-                       this.tabletModules = options.tabletModules;
                        this.mainMenu = options.mainMenu;
                        View.prototype.initialize.apply( this, arguments );
+                       // Must be run after merging with defaults as must be 
defined.
+                       this.tabletModules = options.tabletModules;
 
                        /**
                         * Tests current window size and if suitable loads 
styles and scripts specific for larger devices
diff --git a/resources/mobile.talk.overlays/TalkOverlay.js 
b/resources/mobile.talk.overlays/TalkOverlay.js
index e80d28d..c0a48a4 100644
--- a/resources/mobile.talk.overlays/TalkOverlay.js
+++ b/resources/mobile.talk.overlays/TalkOverlay.js
@@ -3,7 +3,6 @@
                Overlay = M.require( 'Overlay' ),
                Page = M.require( 'Page' ),
                Anchor = M.require( 'Anchor' ),
-               pageApi = M.require( 'pageApi' ),
                user = M.require( 'user' ),
                /**
                 * Overlay for talk page
@@ -20,6 +19,7 @@
                        /**
                         * @inheritdoc
                         * @cfg {Object} defaults Default options hash.
+                        * @cfg {PageApi} defaults.pageApi an api module to 
retrieve pages.
                         * @cfg {Array} defaults.headings A list of {Section} 
objects to render heading links
                         * for. If not set ajax request will be performed.
                         * @cfg {String} defaults.heading Heading for talk 
overlay.
@@ -95,7 +95,7 @@
                                this.$( '.topic-title-list' ).empty();
 
                                // FIXME: use Page's mechanisms for retrieving 
page data instead
-                               pageApi.getPage( options.title ).fail( function 
( resp ) {
+                               this.options.pageApi.getPage( options.title 
).fail( function ( resp ) {
                                        // If the API returns the error code 
'missingtitle', that means the
                                        // talk page doesn't exist yet.
                                        if ( resp === 'missingtitle' ) {
diff --git a/resources/mobile.talk.overlays/TalkSectionAddOverlay.js 
b/resources/mobile.talk.overlays/TalkSectionAddOverlay.js
index 6cec9aa..20465fa 100644
--- a/resources/mobile.talk.overlays/TalkSectionAddOverlay.js
+++ b/resources/mobile.talk.overlays/TalkSectionAddOverlay.js
@@ -2,7 +2,6 @@
        var
                Overlay = M.require( 'Overlay' ),
                api = M.require( 'api' ),
-               pageApi = M.require( 'pageApi' ),
                toast = M.require( 'toast' ),
                Icon = M.require( 'Icon' ),
                TalkSectionAddOverlay;
@@ -18,6 +17,7 @@
                /**
                 * @inheritdoc
                 * @cfg {Object} defaults Default options hash.
+                * @cfg {PageApi} defaults.pageApi an api module to retrieve 
pages.
                 * @cfg {String} defaults.cancelMsg Caption for cancel button 
on edit form.
                 * @cfg {String} defaults.topicTitlePlaceHolder Placeholder 
text to prompt user to add
                 * a talk page topic subject.
@@ -101,7 +101,7 @@
                                if ( status === 'ok' ) {
                                        // Check if the user was previously on 
the talk overlay
                                        if ( self.title !== mw.config.get( 
'wgPageName' ) ) {
-                                               pageApi.invalidatePage( 
self.title );
+                                               
self.options.pageApi.invalidatePage( self.title );
                                                toast.show( mw.msg( 
'mobile-frontend-talk-topic-feedback' ), 'toast' );
                                                M.emit( 'talk-discussion-added' 
);
                                                window.history.back();
diff --git a/resources/mobile.talk.overlays/TalkSectionOverlay.js 
b/resources/mobile.talk.overlays/TalkSectionOverlay.js
index 9fc364e..ae4a16c 100644
--- a/resources/mobile.talk.overlays/TalkSectionOverlay.js
+++ b/resources/mobile.talk.overlays/TalkSectionOverlay.js
@@ -6,7 +6,6 @@
                user = M.require( 'user' ),
                Page = M.require( 'Page' ),
                Button = M.require( 'Button' ),
-               pageApi = M.require( 'pageApi' ),
                TalkSectionOverlay;
 
        /**
@@ -26,6 +25,7 @@
                /**
                 * @inheritdoc
                 * @cfg {Object} defaults Default options hash.
+                * @cfg {PageApi} defaults.pageApi an api module to retrieve 
pages.
                 * @cfg {String} defaults.title Title.
                 * @cfg {Section} defaults.section that is currently being 
viewed in overlay.
                 * @cfg {String} defaults.reply Reply heading.
@@ -33,6 +33,7 @@
                 * automatically signed.
                 */
                defaults: $.extend( {}, Overlay.prototype.defaults, {
+                       pageApi: undefined,
                        saveButton: new Button( {
                                block: true,
                                additionalClassNames: 'save-button',
@@ -83,7 +84,7 @@
                renderFromApi: function ( options ) {
                        var self = this;
 
-                       pageApi.getPage( options.title ).done( function ( 
pageData ) {
+                       this.options.pageApi.getPage( options.title ).done( 
function ( pageData ) {
                                var page = new Page( pageData );
                                options.section = page.getSection( options.id );
                                self.render( options );
@@ -117,7 +118,7 @@
                                } ).done( function () {
                                        popup.show( mw.msg( 
'mobile-frontend-talk-reply-success' ), 'toast' );
                                        // invalidate the cache
-                                       pageApi.invalidatePage( 
self.options.title );
+                                       self.options.pageApi.invalidatePage( 
self.options.title );
 
                                        self.renderFromApi( self.options );
                                } ).fail( function ( data, response ) {
diff --git a/resources/mobile.toggling/init.js 
b/resources/mobile.toggle/toggle.js
similarity index 80%
rename from resources/mobile.toggling/init.js
rename to resources/mobile.toggle/toggle.js
index bcecb12..9aba91b 100644
--- a/resources/mobile.toggling/init.js
+++ b/resources/mobile.toggle/toggle.js
@@ -1,9 +1,5 @@
 ( function ( M, $ ) {
-       var page = M.getCurrentPage(),
-               currentPageTitle =  page.title,
-               // FIXME: Clean up when cache clears.
-               $contentContainer = $( '#content #bodyContent, #content_wrapper 
#content' ),
-               context = M.require( 'context' ),
+       var context = M.require( 'context' ),
                settings = M.require( 'settings' ),
                browser = M.require( 'browser' ),
                escapeHash = M.require( 'util' ).escapeHash,
@@ -22,14 +18,15 @@
         * existing page.
         *
         * @method
+        * @param {Page} page
         * @returns {Object} representing open sections
         * @ignore
         */
-       function getExpandedSections() {
+       function getExpandedSections( page ) {
                var expandedSections = $.parseJSON(
                        settings.get( 'expandedSections', false ) || '{}'
                );
-               expandedSections[currentPageTitle] = 
expandedSections[currentPageTitle] || {};
+               expandedSections[page.title] = expandedSections[page.title] || 
{};
                return expandedSections;
        }
 
@@ -49,18 +46,19 @@
         * If the heading is collapsed, remove it from localStorage.
         *
         * @param {jQuery.Object} $heading - A heading belonging to a section
+        * @param {Page} page
         * @ignore
         */
-       function storeSectionToggleState( $heading ) {
+       function storeSectionToggleState( $heading, page ) {
                var headline = $heading.find( 'span' ).attr( 'id' ),
                        isSectionOpen = $heading.hasClass( 'open-block' ),
-                       expandedSections = getExpandedSections();
+                       expandedSections = getExpandedSections( page );
 
                if ( headline ) {
                        if ( isSectionOpen ) {
-                               expandedSections[currentPageTitle][headline] = 
( new Date() ).getTime();
+                               expandedSections[page.title][headline] = ( new 
Date() ).getTime();
                        } else {
-                               delete 
expandedSections[currentPageTitle][headline];
+                               delete expandedSections[page.title][headline];
                        }
 
                        saveExpandedSections( expandedSections );
@@ -70,11 +68,12 @@
        /**
         * Expand sections that were previously expanded before leaving this 
page.
         * @param {jQuery.Object} $container
+        * @param {Page} page
         * @ignore
         */
-       function expandStoredSections( $container ) {
+       function expandStoredSections( $container, page ) {
                var $sectionHeading, $headline,
-                       expandedSections = getExpandedSections(),
+                       expandedSections = getExpandedSections( page ),
                        $headlines = $container.find( '.section-heading span' );
 
                $headlines.each( function () {
@@ -82,10 +81,10 @@
                        $sectionHeading = $headline.parents( '.section-heading' 
);
                        // toggle only if the section is not already expanded
                        if (
-                               
expandedSections[currentPageTitle][$headline.attr( 'id' )] &&
+                               expandedSections[page.title][$headline.attr( 
'id' )] &&
                                !$sectionHeading.hasClass( 'open-block' )
                        ) {
-                               toggle( $sectionHeading );
+                               toggle( $sectionHeading, page );
                        }
                } );
        }
@@ -93,11 +92,12 @@
        /**
         * Clean obsolete (saved more than a day ago) expanded sections from
         * localStorage.
+        * @param {Page} page
         * @ignore
         */
-       function cleanObsoleteStoredSections() {
+       function cleanObsoleteStoredSections( page ) {
                var now = ( new Date() ).getTime(),
-                       expandedSections = getExpandedSections(),
+                       expandedSections = getExpandedSections( page ),
                        // the number of days between now and the time a 
setting was saved
                        daysDifference;
                $.each( expandedSections, function ( page, sections ) {
@@ -120,6 +120,7 @@
         */
        function toggle( $heading ) {
                var isCollapsed = $heading.is( '.open-block' ),
+                       page = $heading.data( 'page' ),
                        options, indicator;
 
                $heading.toggleClass( 'open-block' );
@@ -137,7 +138,7 @@
                        } );
 
                if ( !browser.isWideScreen() ) {
-                       storeSectionToggleState( $heading );
+                       storeSectionToggleState( $heading, page );
                }
        }
 
@@ -195,11 +196,10 @@
         * @param {String} prefix a prefix to use for the id.
         * @ignore
         */
-       function enable( $container, prefix ) {
+       function enable( $container, prefix, page ) {
                var tagName, expandSections, indicator,
                        $firstHeading,
                        collapseSectionsByDefault = mw.config.get( 
'wgMFCollapseSectionsByDefault' );
-               $container = $container || $contentContainer;
 
                // Also allow .section-heading if some extensions like Wikibase
                // want to toggle other headlines than direct descendants of 
$container.
@@ -221,6 +221,7 @@
                        if ( $heading.next().is( 'div' ) ) {
                                $heading
                                        .addClass( 'collapsible-heading ' )
+                                       .data( 'page', page )
                                        .attr( {
                                                tabindex: 0,
                                                'aria-haspopup': 'true',
@@ -287,7 +288,7 @@
                checkInternalRedirectAndHash();
                checkHash();
                // Restricted to links created by editors and thus outside our 
control
-               $contentContainer.find( 'a' ).on( 'click', function () {
+               $container.find( 'a' ).on( 'click', function () {
                        // the link might be an internal link with a hash.
                        // if it is check if we need to reveal any sections.
                        if ( $( this ).attr( 'href' ) !== undefined &&
@@ -298,47 +299,15 @@
                } );
 
                if ( !browser.isWideScreen() ) {
-                       expandStoredSections( $container );
-                       cleanObsoleteStoredSections();
+                       expandStoredSections( $container, page );
+                       cleanObsoleteStoredSections( page );
                }
-       }
-
-       /**
-        * Initialises toggling code.
-        *
-        * @method
-        * @param {jQuery.Object} $container to enable toggling on
-        * @param {String} prefix a prefix to use for the id.
-        * @ignore
-        */
-       function init( $container, prefix ) {
-               // distinguish headings in content from other headings
-               $container.find( '> h1,> h2,> h3,> h4,> h5,> h6' ).addClass( 
'section-heading' );
-               enable( $container, prefix );
-
-               // FIXME: remove when cache clears
-               $( function () {
-                       $container.find( '.open-block > a.edit-page, .in-block 
> a.edit-page' ).each( function ( i, el ) {
-                               $( el ).wrap( '<span></span>' );
-                       } );
-               } );
-       }
-
-       // avoid this running on Watchlist
-       if (
-               !page.inNamespace( 'special' ) &&
-               !mw.config.get( 'wgIsMainPage' ) &&
-               mw.config.get( 'wgAction' ) === 'view'
-       ) {
-               init( $contentContainer, 'content-' );
        }
 
        M.define( 'toggle', {
                reveal: reveal,
                toggle: toggle,
                enable: enable,
-               // for tests
-               _currentPageTitle: currentPageTitle,
                _getExpandedSections: getExpandedSections,
                _expandStoredSections: expandStoredSections,
                _cleanObsoleteStoredSections: cleanObsoleteStoredSections
diff --git a/resources/mobile.toggling/toggle.less 
b/resources/mobile.toggle/toggle.less
similarity index 100%
rename from resources/mobile.toggling/toggle.less
rename to resources/mobile.toggle/toggle.less
diff --git a/resources/skins.minerva.alpha.scripts/quickLookup.js 
b/resources/skins.minerva.alpha.scripts/quickLookup.js
new file mode 100644
index 0000000..74007c6
--- /dev/null
+++ b/resources/skins.minerva.alpha.scripts/quickLookup.js
@@ -0,0 +1,114 @@
+( function ( M, $ ) {
+       var api = M.require( 'api' ),
+               toast = M.require( 'toast' ),
+               Swipe = M.require( 'Swipe' ),
+               swipe,
+               QuickLookupDrawer = M.require( 
'modules/quickLookup/QuickLookupDrawer' ),
+               hostname = window.location.hostname,
+               cache = {},
+               drawer;
+
+       M.require( 'context' ).assertMode( [ 'alpha' ] );
+       /**
+        * Search API for a brief intro about a page.
+        * @ignore
+        * @param {String} title title of the page
+        */
+       function lookup( title ) {
+               var deferred = $.Deferred(),
+                       promise = deferred.promise();
+
+               if ( cache.hasOwnProperty( title ) ) {
+                       if ( cache[title] ) {
+                               deferred.resolve( cache[title] );
+                       } else {
+                               deferred.reject();
+                       }
+               } else {
+                       api.get( {
+                               prop: 'extracts',
+                               exsentences: 5,
+                               titles: title,
+                               exintro: '',
+                               continue: '',
+                               explaintext: ''
+                       } ).then( function ( data ) {
+                               var pages = OO.getProp( data, 'query', 'pages' 
),
+                                       pageID,
+                                       extract;
+
+                               cache[title] = null;  // just to mark that we 
searched the API
+                               if ( pages ) {
+                                       for ( pageID in pages ) {
+                                               if ( pages.hasOwnProperty( 
pageID ) ) {
+                                                       extract = OO.getProp( 
pages, pageID, 'extract' );
+                                                       if ( extract ) {
+                                                               cache[title] = {
+                                                                       title: 
title,
+                                                                       text: 
extract,
+                                                                       id: 
pageID
+                                                               };
+                                                               
deferred.resolve( cache[title] );
+                                                               break;
+                                                       }
+                                               }
+                                       }
+                               }
+                               if ( cache[title] === null ) {
+                                       deferred.reject();
+                               }
+                       } ).fail( deferred.reject );
+               }
+
+               return promise;
+       }
+
+       /**
+        * Show a QuickLookupDrawer with information about {link}
+        * Link must have the same hostname as the site, i.e. it must be an 
internal link.
+        * Show a toast before searching and a drawer with page info after the 
search is successful.
+        * @ignore
+        * @param {jQuery.Event} ev Event object of the swipe gesture
+        */
+       function showDrawer( ev ) {
+               var link = ev.currentTarget,
+                       linkTitle = link.title,
+                       linkHostname = link.hostname;
+
+               toast.hide();
+               if ( drawer ) {
+                       drawer.hide();
+               }
+
+               if ( linkHostname === hostname && linkTitle ) {
+                       toast.show( mw.msg( 
'mobile-frontend-quick-lookup-looking', linkTitle ), 'toast quick-lookup' );
+                       lookup( linkTitle ).done( function ( page ) {
+                               toast.hide();
+                               drawer = new QuickLookupDrawer( page );
+                               drawer.show();
+                       } ).fail( function () {
+                               toast.show(
+                                       mw.msg( 
'mobile-frontend-quick-lookup-no-results', linkTitle ),
+                                       'toast quick-lookup'
+                               );
+                       } );
+               } else {
+                       // @todo Remove the sitename parameter late 2015 as it 
only exists for B/C.
+                       toast.show(
+                               mw.msg( 
'mobile-frontend-quick-lookup-not-internal', mw.config.get( 'wgSiteName' ) ),
+                               'toast quick-lookup'
+                       );
+               }
+       }
+
+       $( function () {
+               // initialize swipe module
+               swipe = new Swipe();
+               // listen on our wanted swipe directions
+               swipe
+                       .on( 'swipe-right', $.proxy( showDrawer ) )
+                       .on( 'swipe-left', $.proxy( showDrawer ) );
+               // listen on all links
+               swipe.setElement( $( 'a' ) );
+       } );
+}( mw.mobileFrontend, jQuery ) );
diff --git a/resources/mobile.fontchanger.init/init.js 
b/resources/skins.minerva.beta.scripts/fontchanger.js
similarity index 100%
rename from resources/mobile.fontchanger.init/init.js
rename to resources/skins.minerva.beta.scripts/fontchanger.js
diff --git a/resources/mobile.categories/init.js 
b/resources/skins.minerva.categories/init.js
similarity index 100%
rename from resources/mobile.categories/init.js
rename to resources/skins.minerva.categories/init.js
diff --git a/resources/mobile.editor/init.js 
b/resources/skins.minerva.editor/init.js
similarity index 99%
rename from resources/mobile.editor/init.js
rename to resources/skins.minerva.editor/init.js
index 403d10c..b068434 100644
--- a/resources/mobile.editor/init.js
+++ b/resources/skins.minerva.editor/init.js
@@ -17,6 +17,7 @@
                        name: 'edit-enabled'
                } ),
                currentPage = M.getCurrentPage(),
+               pageApi = M.require( 'pageApi' ),
                enabledClass = enabledEditIcon.getGlyphClassName(),
                disabledClass = disabledEditIcon.getGlyphClassName(),
                context = M.require( 'context' ),
@@ -130,6 +131,7 @@
                                result = $.Deferred(),
                                preferredEditor = getPreferredEditor(),
                                editorOptions = {
+                                       pageApi: pageApi,
                                        licenseMsg: skin.getLicenseMsg(),
                                        title: page.title,
                                        isAnon: user.isAnon(),
diff --git a/resources/mobile.newusers/init.js 
b/resources/skins.minerva.newusers/init.js
similarity index 100%
rename from resources/mobile.newusers/init.js
rename to resources/skins.minerva.newusers/init.js
diff --git a/resources/mobile.notifications/init.js 
b/resources/skins.minerva.notifications/init.js
similarity index 100%
rename from resources/mobile.notifications/init.js
rename to resources/skins.minerva.notifications/init.js
diff --git a/resources/mobile.head/init.js 
b/resources/skins.minerva.scripts.top/init.js
similarity index 100%
rename from resources/mobile.head/init.js
rename to resources/skins.minerva.scripts.top/init.js
diff --git a/resources/skins.minerva.scripts/init.js 
b/resources/skins.minerva.scripts/init.js
index 847c5b8..b5c97d4 100644
--- a/resources/skins.minerva.scripts/init.js
+++ b/resources/skins.minerva.scripts/init.js
@@ -6,6 +6,8 @@
                loader = M.require( 'loader' ),
                router = M.require( 'router' ),
                context = M.require( 'context' ),
+               references = M.require( 'references' ),
+               cleanuptemplates = M.require( 'cleanuptemplates' ),
                useNewMediaViewer = context.isBetaGroupMember(),
                overlayManager = M.require( 'overlayManager' ),
                page = M.getCurrentPage(),
@@ -103,8 +105,11 @@
        M.on( 'photo-loaded', initMediaViewer );
 
        // Setup
-       $( initButton );
-       initMediaViewer();
+       $( function () {
+               initButton();
+               initMediaViewer();
+               references.setup();
+       } );
 
        // local storage is supported in this case, when ~ means it was 
dismissed
        if ( token !== false && token !== '~' && !page.isMainPage() && 
!page.inNamespace( 'special' ) ) {
@@ -130,6 +135,13 @@
                }
        }
 
+       // Setup the issues banner on the page
+       cleanuptemplates.init();
+       // Show it in edit preview.
+       M.on( 'edit-preview', function ( overlay ) {
+               cleanuptemplates.init( overlay.$el );
+       } );
+
        // let the interested parties know whether the panel is shown
        mw.track( 'minerva.betaoptin', {
                isPanelShown: betaOptinPanel !== undefined
diff --git a/resources/mobile.redirect/init.js 
b/resources/skins.minerva.scripts/mobileRedirect.js
similarity index 100%
rename from resources/mobile.redirect/init.js
rename to resources/skins.minerva.scripts/mobileRedirect.js
diff --git a/resources/mobile.startup/init.js 
b/resources/skins.minerva.scripts/preInit.js
similarity index 96%
rename from resources/mobile.startup/init.js
rename to resources/skins.minerva.scripts/preInit.js
index 7eaa259..cee8e76 100644
--- a/resources/mobile.startup/init.js
+++ b/resources/skins.minerva.scripts/preInit.js
@@ -17,7 +17,7 @@
 
        skin = new Skin( {
                el: 'body',
-               tabletModules: mw.config.get( 'skin' ) === 'minerva' ? [ 
'tablet.scripts' ] : [],
+               tabletModules: mw.config.get( 'skin' ) === 'minerva' ? [ 
'skins.minerva.tablet.scripts' ] : [],
                page: getCurrentPage(),
                mainMenu: mainMenu
        } );
diff --git a/resources/mobile.search/init.js 
b/resources/skins.minerva.scripts/search.js
similarity index 100%
rename from resources/mobile.search/init.js
rename to resources/skins.minerva.scripts/search.js
diff --git a/resources/mobile.toc/init.js 
b/resources/skins.minerva.tablet.scripts/toc.js
similarity index 100%
rename from resources/mobile.toc/init.js
rename to resources/skins.minerva.tablet.scripts/toc.js
diff --git a/resources/mobile.talk/init.js 
b/resources/skins.minerva.talk/init.js
similarity index 97%
rename from resources/mobile.talk/init.js
rename to resources/skins.minerva.talk/init.js
index 46fd661..3934623 100644
--- a/resources/mobile.talk/init.js
+++ b/resources/skins.minerva.talk/init.js
@@ -1,5 +1,6 @@
 ( function ( M, $ ) {
        var loader = M.require( 'loader' ),
+               pageApi = M.require( 'pageApi' ),
                LoadingOverlay = M.require( 'LoadingOverlay' ),
                user = M.require( 'user' ),
                Button = M.require( 'Button' ),
@@ -12,6 +13,7 @@
        overlayManager.add( /^\/talk\/?(.*)$/, function ( id ) {
                var result = $.Deferred(),
                        talkOptions = {
+                               pageApi: pageApi,
                                title: title,
                                licenseMsg: skin.getLicenseMsg()
                        };
diff --git a/resources/mobile.talk/talk.less 
b/resources/skins.minerva.talk/talk.less
similarity index 100%
rename from resources/mobile.talk/talk.less
rename to resources/skins.minerva.talk/talk.less
diff --git a/resources/skins.minerva.toggling/init.js 
b/resources/skins.minerva.toggling/init.js
new file mode 100644
index 0000000..97ee383
--- /dev/null
+++ b/resources/skins.minerva.toggling/init.js
@@ -0,0 +1,29 @@
+( function ( M, $ ) {
+       var page = M.getCurrentPage(),
+               // FIXME: Clean up when cache clears.
+               $contentContainer = $( '#content #bodyContent, #content_wrapper 
#content' ),
+               toggle = M.require( 'toggle' );
+
+       /**
+        * Initialises toggling code.
+        *
+        * @method
+        * @param {jQuery.Object} $container to enable toggling on
+        * @param {String} prefix a prefix to use for the id.
+        * @ignore
+        */
+       function init( $container, prefix ) {
+               // distinguish headings in content from other headings
+               $container.find( '> h1,> h2,> h3,> h4,> h5,> h6' ).addClass( 
'section-heading' );
+               toggle.enable( $container, prefix );
+       }
+
+       // avoid this running on Watchlist
+       if (
+               !page.inNamespace( 'special' ) &&
+               !mw.config.get( 'wgIsMainPage' ) &&
+               mw.config.get( 'wgAction' ) === 'view'
+       ) {
+               init( $contentContainer, 'content-' );
+       }
+}( mw.mobileFrontend, jQuery ) );
diff --git a/resources/mobile.watchstar.init/init.js 
b/resources/skins.minerva.watchstar/init.js
similarity index 100%
rename from resources/mobile.watchstar.init/init.js
rename to resources/skins.minerva.watchstar/init.js
diff --git a/tests/browser/features/step_definitions/notification_steps.rb 
b/tests/browser/features/step_definitions/notification_steps.rb
index e2e5e35..d73cec0 100644
--- a/tests/browser/features/step_definitions/notification_steps.rb
+++ b/tests/browser/features/step_definitions/notification_steps.rb
@@ -5,7 +5,7 @@
       # TODO: If this approach works well, we should implement general
       # `wait_for_resource` and `resource_ready?` helper methods in
       # mw-selenium, and document this pattern on mw.org
-      browser.execute_script("return 
mw.loader.getState('mobile.notifications') === 'ready'")
+      browser.execute_script("return 
mw.loader.getState('skins.minerva.notifications') === 'ready'")
     end
 
     page.notifications_button_element.when_present.click
diff --git a/tests/qunit/mobile.issues/test_init.js 
b/tests/qunit/mobile.issues/test_cleanuptemplates.js
similarity index 100%
rename from tests/qunit/mobile.issues/test_init.js
rename to tests/qunit/mobile.issues/test_cleanuptemplates.js
diff --git a/tests/qunit/mobile.references/test_init.js 
b/tests/qunit/mobile.references/test_references.js
similarity index 100%
rename from tests/qunit/mobile.references/test_init.js
rename to tests/qunit/mobile.references/test_references.js
diff --git a/tests/qunit/mobile.talk.overlays/test_TalkOverlay.js 
b/tests/qunit/mobile.talk.overlays/test_TalkOverlay.js
index 10ea097..cdb3df4 100644
--- a/tests/qunit/mobile.talk.overlays/test_TalkOverlay.js
+++ b/tests/qunit/mobile.talk.overlays/test_TalkOverlay.js
@@ -1,6 +1,7 @@
 ( function ( M, $ ) {
 
-       var pageApi = M.require( 'pageApi' ),
+       var PageApi = M.require( 'PageApi' ),
+               pageApi = new PageApi(),
                TalkOverlay = M.require( 'modules/talk/TalkOverlay' );
 
        QUnit.module( 'MobileFrontend TalkOverlay', {
@@ -30,6 +31,7 @@
 
        QUnit.test( '#TalkOverlay (new page; anonymous)', 4, function ( assert 
) {
                var options = {
+                               pageApi: pageApi,
                                title: 'Talk:No exist'
                        },
                        overlay = new TalkOverlay( options ),
@@ -52,6 +54,7 @@
 
                mw.config.set( 'wgUserName', 'FlorianSW' );
                overlay = new TalkOverlay( {
+                       pageApi: pageApi,
                        title: 'Talk:No exist'
                } );
 
@@ -63,6 +66,7 @@
 
        QUnit.test( '#TalkOverlay (existing page lists section headings)', 4, 
function ( assert ) {
                var overlay = new TalkOverlay( {
+                       pageApi: pageApi,
                        title: 'Talk:Topic'
                } );
 
diff --git a/tests/qunit/mobile.talk.overlays/test_TalkSectionOverlay.js 
b/tests/qunit/mobile.talk.overlays/test_TalkSectionOverlay.js
index dd55b08..2c7c6d3 100644
--- a/tests/qunit/mobile.talk.overlays/test_TalkSectionOverlay.js
+++ b/tests/qunit/mobile.talk.overlays/test_TalkSectionOverlay.js
@@ -2,6 +2,8 @@
 
        var TalkSectionOverlay = M.require( 'modules/talk/TalkSectionOverlay' ),
                api = M.require( 'api' ),
+               PageApi = M.require( 'PageApi' ),
+               pageApi = new PageApi(),
                user = M.require( 'user' ),
                renderFromApiSpy;
 
@@ -48,6 +50,7 @@
        QUnit.test( 'Check api request on save', 1, function ( assert ) {
                var spy = this.sandbox.stub( api, 'postWithToken' ).returns( 
$.Deferred().resolve() ),
                overlay = new TalkSectionOverlay( {
+                       pageApi: pageApi,
                        title: 'Talk:Test',
                        id: 1,
                        section: 'Test'
diff --git a/tests/qunit/mobile.toggling/test_init.js 
b/tests/qunit/mobile.toggle/test_toggle.js
similarity index 90%
rename from tests/qunit/mobile.toggling/test_init.js
rename to tests/qunit/mobile.toggle/test_toggle.js
index 4a12ad7..8077eeb 100644
--- a/tests/qunit/mobile.toggling/test_init.js
+++ b/tests/qunit/mobile.toggle/test_toggle.js
@@ -3,6 +3,7 @@
        var sectionHtml = mw.template.get( 'tests.mobile.templates', 
'section.hogan' ).render(),
                settings = M.require( 'settings' ),
                browser = M.require( 'browser' ),
+               page = { title: 'Toggle test' },
                toggle = M.require( 'toggle' );
 
        /**
@@ -16,7 +17,7 @@
                        this.$container = $( '<div>' ).html( sectionHtml );
                        this.$section0 = this.$container.find( 'h2' ).eq( 0 );
                        this.sandbox.stub( browser, 'isWideScreen' ).returns( 
false );
-                       toggle.enable( this.$container );
+                       toggle.enable( this.$container, '', page );
                        toggle.toggle( this.$section0 );
                },
                teardown: function () {
@@ -99,7 +100,7 @@
                setup: function () {
                        this.$container = $( '<div>' ).html( sectionHtml );
                        this.sandbox.stub( browser, 'isWideScreen' ).returns( 
true );
-                       toggle.enable( this.$container );
+                       toggle.enable( this.$container, '', page );
                },
                teardown: function () {
                        window.location.hash = '#';
@@ -123,7 +124,7 @@
                        this.sandbox.stub( mw.config, 'get' ).withArgs( 
'wgMFCollapseSectionsByDefault' ).returns( false );
                        settings.save( 'expandSections', 'true', true );
                        this.$container = $( '<div>' ).html( sectionHtml );
-                       toggle.enable( this.$container );
+                       toggle.enable( this.$container, '', page );
                },
                teardown: function () {
                        window.location.hash = '#';
@@ -147,7 +148,7 @@
                        this.sandbox.stub( mw.config, 'get' ).withArgs( 
'wgMFCollapseSectionsByDefault' ).returns( true );
                        this.$container = $( '<div>' ).html( sectionHtml );
                        this.sandbox.stub( browser, 'isWideScreen' ).returns( 
false );
-                       toggle.enable( this.$container );
+                       toggle.enable( this.$container, '', page );
                },
                teardown: function () {
                        window.location.hash = '#';
@@ -189,11 +190,11 @@
                        this.sandbox.stub( mw.config, 'get' ).withArgs( 
'wgMFCollapseSectionsByDefault' ).returns( true );
                        this.sandbox.stub( browser, 'isWideScreen' ).returns( 
false );
                        this.$container = $( '<div>' ).html( sectionHtml );
-                       toggle.enable( this.$container );
+                       toggle.enable( this.$container, '', page );
                        this.$section = this.$container.find( 'h2' );
                        this.headline = this.$section.find( 'span' ).attr( 'id' 
);
-                       this.pageTitle = toggle._currentPageTitle;
-                       this.expandedSections = toggle._getExpandedSections( 
this.pageTitle );
+                       this.pageTitle = page.title;
+                       this.expandedSections = toggle._getExpandedSections( 
page );
                },
                teardown: function () {
                        window.location.hash = '#';
@@ -209,14 +210,14 @@
                );
 
                toggle.toggle( this.$section );
-               this.expandedSections = toggle._getExpandedSections( 
this.pageTitle );
+               this.expandedSections = toggle._getExpandedSections( page );
                assert.strictEqual( typeof this.expandedSections[ 
this.pageTitle ][ this.headline ],
                        'number',
                        'the just toggled section state has been saved'
                );
 
                toggle.toggle( this.$section );
-               this.expandedSections = toggle._getExpandedSections( 
this.pageTitle );
+               this.expandedSections = toggle._getExpandedSections( page );
                assert.strictEqual( this.expandedSections[ this.pageTitle ][ 
this.headline ],
                        undefined,
                        'the just toggled section state has been removed'
@@ -228,14 +229,14 @@
                settings.save( 'expandedSections',
                        JSON.stringify( this.expandedSections )
                );
-               this.expandedSections = toggle._getExpandedSections( 
this.pageTitle );
+               this.expandedSections = toggle._getExpandedSections( page );
                assert.strictEqual( typeof this.expandedSections[ 
this.pageTitle ][ this.headline ],
                        'number',
                        'manually created section state has been saved 
correctly'
                );
 
-               toggle._cleanObsoleteStoredSections();
-               this.expandedSections = toggle._getExpandedSections( 
this.pageTitle );
+               toggle._cleanObsoleteStoredSections( page );
+               this.expandedSections = toggle._getExpandedSections( page );
                assert.strictEqual( this.expandedSections[ this.pageTitle ][ 
this.headline ],
                        undefined,
                        'section, whose store time is manually changed to an 
older date,' +
@@ -244,7 +245,7 @@
        } );
 
        QUnit.test( 'Expanding already expanded section does not toggle it.', 
5, function ( assert ) {
-               this.expandedSections = toggle._getExpandedSections( 
this.pageTitle );
+               this.expandedSections = toggle._getExpandedSections( page );
                assert.strictEqual( $.isEmptyObject( this.expandedSections[ 
this.pageTitle ] ),
                        true,
                        'no expanded sections are stored in localStorage yet'
@@ -265,13 +266,13 @@
                        'revealed section has open-block class'
                );
 
-               this.expandedSections = toggle._getExpandedSections( 
this.pageTitle );
+               this.expandedSections = toggle._getExpandedSections( page );
                assert.strictEqual( typeof this.expandedSections[ 
this.pageTitle ][ this.headline ],
                        'number',
                        'manually revealed section state has been correctly 
saved in localStorage'
                );
 
-               toggle._expandStoredSections( this.$container );
+               toggle._expandStoredSections( this.$container, page );
 
                assert.strictEqual(
                        this.$section.hasClass( 'open-block' ),
@@ -289,8 +290,8 @@
                        this.$container.find( 'h2' ).addClass( 
'section-heading' );
                        this.$section = this.$container.find( 'h2' ).eq( 0 );
                        this.headline = 'First_Section';
-                       this.pageTitle = toggle._currentPageTitle;
-                       this.expandedSections = toggle._getExpandedSections( 
this.pageTitle );
+                       this.pageTitle = page.title;
+                       this.expandedSections = toggle._getExpandedSections( 
page );
                },
                teardown: function () {
                        window.location.hash = '#';
@@ -310,15 +311,15 @@
                // save a toggle state manually
                this.expandedSections[ this.pageTitle ][ this.headline ] = ( 
new Date() ).getTime();
                settings.save( 'expandedSections', JSON.stringify( 
this.expandedSections ), false );
-               this.expandedSections = toggle._getExpandedSections( 
this.pageTitle );
+               this.expandedSections = toggle._getExpandedSections( page );
                assert.strictEqual( typeof this.expandedSections[ 
this.pageTitle ][ this.headline ],
                        'number',
                        'manually created section state has been saved 
correctly'
                );
 
-               toggle.enable( this.$container );
+               toggle.enable( this.$container, '', page );
 
-               this.expandedSections = toggle._getExpandedSections( 
this.pageTitle );
+               this.expandedSections = toggle._getExpandedSections( page );
                assert.strictEqual( typeof this.expandedSections[ 
this.pageTitle ][ this.headline ],
                        'number',
                        'manually created section state is still active after 
toggle.init()'
diff --git a/tests/qunit/mobile.watchstar/test_Watchstar.js 
b/tests/qunit/mobile.watchstar/test_Watchstar.js
index c4c2389..a2fe4e8 100644
--- a/tests/qunit/mobile.watchstar/test_Watchstar.js
+++ b/tests/qunit/mobile.watchstar/test_Watchstar.js
@@ -30,7 +30,8 @@
                } );
                $el.trigger( 'click' );
 
-               // Note due to the fact isVisible uses a timeout we cannot 
easily test this
+               // position-fixed class may not have loaded and without it the 
toast is not visible so use
+               // a spy rather than directly testing toast element visibility
                assert.ok( this.spy.called, 'We checked if the drawer was 
visible before displaying it' );
        } );
 
@@ -42,6 +43,7 @@
 
                        // FIXME: Should Schema.log be stubbed by default?
                        this.stub( SchemaMobileWebWatching.prototype, 'log' 
).returns( null );
+                       this.toastSpy = this.sandbox.spy( toast, 'show' );
                },
                teardown: function () {
                        // Hide any existing toasts
@@ -66,7 +68,7 @@
                } ), 'The watch happened' );
                assert.strictEqual( $el.hasClass( watchIcon.getGlyphClassName() 
),
                        true, 'After successful watch has watched class' );
-               assert.strictEqual( $( '.toast' ).is( ':visible' ), true, 'A 
toast is shown' );
+               assert.ok( this.toastSpy.calledOnce, 'A toast is shown' );
        } );
 
        QUnit.test( 'Logged in user unwatches article', 2, function ( assert ) {
@@ -85,7 +87,7 @@
                        unwatch: true,
                        pageids: 42
                } ), 'The watch happened' );
-               assert.strictEqual( $( '.toast' ).is( ':visible' ), true, 'A 
toast is shown' );
+               assert.ok( this.toastSpy.calledOnce, 'A toast is shown' );
        } );
 
 }( jQuery, mw.mobileFrontend ) );

-- 
To view, visit https://gerrit.wikimedia.org/r/229449
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: If37a623f1571645a040c10fc7c5304c7ee0fd332
Gerrit-PatchSet: 32
Gerrit-Project: mediawiki/extensions/MobileFrontend
Gerrit-Branch: master
Gerrit-Owner: Jdlrobson <jrob...@wikimedia.org>
Gerrit-Reviewer: Bmansurov <bmansu...@wikimedia.org>
Gerrit-Reviewer: Florianschmidtwelzow <florian.schmidt.stargatewis...@gmail.com>
Gerrit-Reviewer: Jdlrobson <jrob...@wikimedia.org>
Gerrit-Reviewer: Phuedx <g...@samsmith.io>
Gerrit-Reviewer: Robmoen <rm...@wikimedia.org>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to