Jdlrobson has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/239508

Change subject: WIP: Beta: Serve only lead section on page load
......................................................................

WIP: Beta: Serve only lead section on page load

When scrolled after a certain threshold only then do we load
the rest of the content.

Changes:
* Move secondary page actions out of content (it's not content)
* Update to mobileview api to support pulling all but lead
* Icons support urls
* API requests are cached
* Sections can now be rendered via JavaScript

Known problems:
* This breaks full page rendering for non-JS users. This is
deemed okay since this change will give us data around the performance
gains to be had, whilst it is uncertain what those will be. See also
T100778
* References do not work any more.
* Table of contents gets toggling enabled on it twice

Bug: T100258
Change-Id: I154396eb6e6a1caa0d31b86e0196bc7456ce0d12
---
M includes/MobileFrontend.body.php
M includes/Resources.php
M resources/mobile.references/references.js
M resources/mobile.startup/Page.js
M resources/mobile.startup/Section.hogan
M resources/mobile.startup/Section.js
A resources/mobile.startup/heading.hogan
M resources/mobile.toc/TableOfContents.js
M resources/skins.minerva.editor/init.js
M resources/skins.minerva.scripts/init.js
M resources/skins.minerva.scripts/preInit.js
M resources/skins.minerva.tablet.scripts/toc.js
M resources/skins.minerva.toggling/init.js
M tests/qunit/mobile.startup/test_PageApi.js
14 files changed, 129 insertions(+), 20 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/MobileFrontend 
refs/changes/08/239508/1

diff --git a/includes/MobileFrontend.body.php b/includes/MobileFrontend.body.php
index 28dbe0c..e69f18d 100644
--- a/includes/MobileFrontend.body.php
+++ b/includes/MobileFrontend.body.php
@@ -35,6 +35,12 @@
 
                $context = MobileContext::singleton();
 
+               if ( $context->isBetaGroupMember() ) {
+                       // FIXME: use wikipage here?
+                       $chunks = preg_split( '/<h(?=[1-6]\b)/i', $html );
+                       $html = $chunks[0];
+               }
+
                $formatter = MobileFormatter::newFromContext( $context, $html );
 
                Hooks::run( 'MobileFrontendBeforeDOM', array( $context, 
$formatter ) );
diff --git a/includes/Resources.php b/includes/Resources.php
index 43115d6..ee3915f 100644
--- a/includes/Resources.php
+++ b/includes/Resources.php
@@ -420,6 +420,8 @@
                        'button.hogan' => 
'resources/mobile.startup/button.hogan',
                ),
                'messages' => array(
+                       // Sections.js
+                       'edit',
                        // icons.js
                        'mobile-frontend-loading-message',
                        'mobile-frontend-console-recruit',
diff --git a/resources/mobile.references/references.js 
b/resources/mobile.references/references.js
index 1119aa2..38dac0d 100644
--- a/resources/mobile.references/references.js
+++ b/resources/mobile.references/references.js
@@ -1,6 +1,5 @@
 ( function ( M, $ ) {
        var ReferencesDrawer, drawer;
-
        /**
         * Return the matched reference among the children of ol.references
         * @method
diff --git a/resources/mobile.startup/Page.js b/resources/mobile.startup/Page.js
index f943bd3..442705b 100644
--- a/resources/mobile.startup/Page.js
+++ b/resources/mobile.startup/Page.js
@@ -10,6 +10,7 @@
         *
         * @class Page
         * @uses Section
+        * @uses InfiniteScroll
         * @extends View
         */
        Page = View.extend( {
@@ -33,6 +34,8 @@
                 * @cfg {Number} defaults.thumbnail.width of image in pixels.
                 * @cfg {Number} defaults.thumbnail.height of image in pixels.
                 * @cfg {String} defaults.thumbnail.source url for image
+                * @cfg {Api} defaults.api when provided only the lead section 
needs to be provided and all other sections will
+                *  be defer loaded.
                 */
                defaults: {
                        id: 0,
@@ -81,6 +84,54 @@
                                this.thumbnail.isLandscape = thumb.width > 
thumb.height;
                        }
                        this.wikidataDescription = options.wikidataDescription;
+                       if ( options.api ) {
+                               this.api = options.api;
+                               this.lazyLoad();
+                       }
+               },
+
+               /**
+                * Lazy load content beyond the lead section and update the 
Page object
+                */
+               lazyLoad: function () {
+                       var self = this;
+                       this.api.getPage( this.options.title, null, 
'allbutlead', 2592000, mw.config.get( 'wgRevisionId' ) ).done( function ( 
pageOptions ) {
+                               // keep the lead.
+                               pageOptions.sections = 
self.options.sections.slice( 0, 1 ).concat( pageOptions.sections );
+                               self.options = $.extend( self.options, 
pageOptions );
+                               self.compile.call( self );
+                               /**
+                                * @event loaded
+                                */
+                               self.emit( 'loaded' );
+                               mw.loader.using( 'mobile.infiniteScroll' 
).done( $.proxy( self, '_setupScrolling' ) );
+                       } );
+               },
+
+               /**
+                * Setup infinite scrolling on a lazy loaded page.
+                * @private
+                */
+               _setupScrolling: function () {
+                       var InfiniteScroll = M.require( 
'mobile.infiniteScroll/InfiniteScroll' );
+                       this.infiniteScroll = new InfiniteScroll( 1000 );
+                       this.infiniteScroll.setElement( this.$el );
+                       this.infiniteScroll.once( 'load', $.proxy( this, 
'_renderPostLeadSection' ) );
+               },
+
+               /**
+                * Render sections beyond the lead section. Callback for 
infinite scroller.
+                * @private
+                */
+               _renderPostLeadSection: function () {
+                       var self = this;
+                       $.each( this.sections.reverse(), function ( i, section 
) {
+                               section.$el.children().insertAfter( 
self.getLeadSectionElement() );
+                       } );
+                       /**
+                        * @event rendered
+                        */
+                       this.emit( 'rendered' );
                },
 
                /**
@@ -99,7 +150,7 @@
                 * @return {jQuery.Object}
                 */
                getLeadSectionElement: function () {
-                       return this.$( '> div' ).eq( 0 );
+                       return this.$( '.content > div' ).eq( 0 );
                },
 
                /**
@@ -205,6 +256,13 @@
                 * @inheritdoc
                 */
                preRender: function () {
+                       this.compile();
+               },
+
+               /**
+                * Compiles list of sections to Section classes. Adds caching.
+                */
+               compile: function () {
                        var self = this;
                        this.sections = [];
                        this._sectionLookup = {};
diff --git a/resources/mobile.startup/Section.hogan 
b/resources/mobile.startup/Section.hogan
index 0ad5fdb..81d42cf 100644
--- a/resources/mobile.startup/Section.hogan
+++ b/resources/mobile.startup/Section.hogan
@@ -1,2 +1,2 @@
-{{#line}}<h{{level}} id="{{anchor}}">{{{line}}}</h{{level}}>{{/line}}
-{{{text}}}
+{{#line}}<h{{level}}><span class="mw-headline" 
id="{{anchor}}">{{{line}}}</span>{{#editIcon}}{{>icon}}{{/editIcon}}</h{{level}}>{{/line}}
+<div>{{{text}}}</div>
diff --git a/resources/mobile.startup/Section.js 
b/resources/mobile.startup/Section.js
index cba02ab..1c916f7 100644
--- a/resources/mobile.startup/Section.js
+++ b/resources/mobile.startup/Section.js
@@ -2,6 +2,7 @@
 
        var View = M.require( 'mobile.view/View' ),
                Section,
+               Icon = M.require( 'mobile.startup/Icon' ),
                icons = M.require( 'mobile.startup/icons' );
 
        /**
@@ -11,13 +12,18 @@
         */
        Section = View.extend( {
                template: mw.template.get( 'mobile.startup', 'Section.hogan' ),
+               templatePartials: {
+                       icon: Icon.prototype.template
+               },
                /**
                 * @cfg {Object} defaults Default options hash.
                 * @cfg {String} defaults.text Section text.
+                * @cfg {Object} defaults.editIcon options for an edit button.
                 * @cfg {String} defaults.spinner HTML of the spinner icon.
                 */
                defaults: {
                        line: undefined,
+                       editIcon:  undefined,
                        text: '',
                        spinner: icons.spinner().toHtmlString()
                },
@@ -29,6 +35,13 @@
                        this.text = options.text;
                        this.hasReferences = options.hasReferences || false;
                        this.id = options.id || null;
+                       options.editIcon = new Icon( {
+                               href: '#/editor/' + options.id,
+                               name: 'edit-enabled',
+                               title: mw.msg( 'edit' ),
+                               label: mw.msg( 'edit' ),
+                               additionalClassNames: 'edit-page'
+                       } ).options;
                        this.anchor = options.anchor;
                        this.children = [];
                        $.each( options.children || [], function () {
diff --git a/resources/mobile.startup/heading.hogan 
b/resources/mobile.startup/heading.hogan
new file mode 100644
index 0000000..0933979
--- /dev/null
+++ b/resources/mobile.startup/heading.hogan
@@ -0,0 +1 @@
+{{#line}}<h{{level}} 
id="{{anchor}}"><span>{{{line}}}</span>{{#editIcon}}{{>icon}}{{/editIcon}}</h{{level}}>{{/line}}
\ No newline at end of file
diff --git a/resources/mobile.toc/TableOfContents.js 
b/resources/mobile.toc/TableOfContents.js
index c4556ad..87f5dde 100644
--- a/resources/mobile.toc/TableOfContents.js
+++ b/resources/mobile.toc/TableOfContents.js
@@ -1,5 +1,6 @@
 ( function ( M ) {
        var TableOfContents,
+               toggle = M.require( 'mobile.toggle/toggle' ),
                SchemaMobileWebClickTracking = M.require( 
'mobile.loggingSchemas/SchemaMobileWebClickTracking' ),
                uiSchema = new SchemaMobileWebClickTracking( {}, 
'MobileWebUIClickTracking' ),
                View = M.require( 'mobile.view/View' ),
@@ -36,6 +37,10 @@
                        'click h2': 'onTocToggle',
                        'click a': 'onLinkClick'
                },
+               /** @inheritdoc */
+               postRender: function () {
+                       toggle.enable( this.$el, 'toc-' );
+               },
                /**
                 * Log toggling the header
                 */
diff --git a/resources/skins.minerva.editor/init.js 
b/resources/skins.minerva.editor/init.js
index 6e2ca84..ae8b7a3 100644
--- a/resources/skins.minerva.editor/init.js
+++ b/resources/skins.minerva.editor/init.js
@@ -358,11 +358,14 @@
                        // Cta's will be rendered in EditorOverlay, if 
anonymous editing is enabled.
                        if ( mw.config.get( 'wgMFEditorOptions' 
).anonymousEditing ) {
                                init();
+                               currentPage.on( 'rendered', init );
                        } else {
                                initCta();
+                               currentPage.on( 'rendered', initCta );
                        }
                } else {
                        init();
+                       currentPage.on( 'rendered', init );
                }
        }
 
diff --git a/resources/skins.minerva.scripts/init.js 
b/resources/skins.minerva.scripts/init.js
index 0699084..f2ef1ec 100644
--- a/resources/skins.minerva.scripts/init.js
+++ b/resources/skins.minerva.scripts/init.js
@@ -141,6 +141,10 @@
        M.on( 'edit-preview', function ( overlay ) {
                cleanuptemplates.init( overlay.$el );
        } );
+       page.on( 'rendered', function () {
+               references.setup();
+               cleanuptemplates.init( page );
+       } );
 
        // let the interested parties know whether the panel is shown
        mw.track( 'minerva.betaoptin', {
diff --git a/resources/skins.minerva.scripts/preInit.js 
b/resources/skins.minerva.scripts/preInit.js
index 9e6d7db..6df77e8 100644
--- a/resources/skins.minerva.scripts/preInit.js
+++ b/resources/skins.minerva.scripts/preInit.js
@@ -11,6 +11,8 @@
                pageApi = new PageApi(),
                Page = M.require( 'mobile.startup/Page' ),
                mainMenu = M.require( 'mobile.head/mainMenu' ),
+               context = M.require( 'mobile.context/context' ),
+               isLazyLoadEnabled = context.isBetaGroupMember(),
                Skin = M.require( 'mobile.startup/Skin' );
 
        skin = new Skin( {
@@ -47,13 +49,16 @@
         * @ignore
         */
        function loadCurrentPage() {
-               var permissions = mw.config.get( 'wgRestrictionEdit', [] ),
+               var options,
+                       permissions = mw.config.get( 'wgRestrictionEdit', [] ),
                        $content = $( '#content #bodyContent' );
+
                if ( permissions.length === 0 ) {
                        permissions.push( '*' );
                }
-               currentPage = new Page( {
-                       el: $content,
+
+               options = {
+                       el: '#content',
                        title: mw.config.get( 'wgPageName' ).replace( /_/g, ' ' 
),
                        protection: {
                                edit: permissions
@@ -63,7 +68,12 @@
                        sections: pageApi.getSectionsFromHTML( $content ),
                        id: mw.config.get( 'wgArticleId' ),
                        namespaceNumber: mw.config.get( 'wgNamespaceNumber' )
-               } );
+               };
+
+               if ( isLazyLoadEnabled ) {
+                       options.api = pageApi;
+               }
+               currentPage = new Page( options );
                return currentPage;
        }
 
diff --git a/resources/skins.minerva.tablet.scripts/toc.js 
b/resources/skins.minerva.tablet.scripts/toc.js
index b131989..0ab27db 100644
--- a/resources/skins.minerva.tablet.scripts/toc.js
+++ b/resources/skins.minerva.tablet.scripts/toc.js
@@ -1,6 +1,6 @@
 ( function ( M, $ ) {
-       var TableOfContents = M.require( 'mobile.toc/TableOfContents' ),
-               toggle = M.require( 'mobile.toggle/toggle' );
+       var toc, page,
+               TableOfContents = M.require( 'mobile.toc/TableOfContents' );
 
        /**
         * Create TableOfContents if the given Page has sections and is not the 
main page
@@ -10,12 +10,15 @@
         * @ignore
         */
        function init( page ) {
-               var toc,
-                       sections = page.getSections(),
+               var sections = page.getSections(),
                        $toc = $( '#toc' ),
                        // TODO: remove wgTOC when caches with old HTML expire
                        enableToc = mw.config.get( 'wgMFTocEnabled' ) || 
mw.config.get( 'wgTOC' );
 
+               // Remove any existing table of contents
+               if ( toc ) {
+                       toc.remove();
+               }
                if ( enableToc ||
                        // Fallback for old cached HTML, added 26 June, 2014
                        ( enableToc === null && sections.length > 0 && 
!page.isMainPage() ) ) {
@@ -31,13 +34,15 @@
                                // otherwise append it to the lead section
                                toc.appendTo( page.getLeadSectionElement() );
                        }
-                       toggle.enable( toc.$el, 'toc-' );
                }
        }
 
        // add a ToC only for "view" action (user is reading a page)
        if ( mw.config.get( 'wgAction' ) === 'view' ) {
-               init( M.getCurrentPage() );
+               page = M.getCurrentPage();
+               init( page );
+               page.once( 'loaded', function () {
+                       init( page );
+               } );
        }
-
 }( mw.mobileFrontend, jQuery ) );
diff --git a/resources/skins.minerva.toggling/init.js 
b/resources/skins.minerva.toggling/init.js
index 7450994..d98ef1e 100644
--- a/resources/skins.minerva.toggling/init.js
+++ b/resources/skins.minerva.toggling/init.js
@@ -26,4 +26,7 @@
        ) {
                init( $contentContainer, 'content-', page );
        }
+       page.on( 'rendered', function () {
+               init( $contentContainer, 'content-', page );
+       } );
 }( mw.mobileFrontend, jQuery ) );
diff --git a/tests/qunit/mobile.startup/test_PageApi.js 
b/tests/qunit/mobile.startup/test_PageApi.js
index 8a64dca..407a958 100644
--- a/tests/qunit/mobile.startup/test_PageApi.js
+++ b/tests/qunit/mobile.startup/test_PageApi.js
@@ -83,7 +83,7 @@
                                                line: '1',
                                                anchor: '1',
                                                id: 1,
-                                               text: '<p>Text of 1\n</p><h2 
id="1.1"><i>1.1</i></h2>\n<p>Text of 1.1\n</p>\n',
+                                               text: '<p>Text of 1\n</p><h2 
id="1.1"><span><i>1.1</i></span></h2>\n<div><p>Text of 1.1\n</p></div>\n',
                                                children: [
                                                        {
                                                                level: '2',
@@ -100,7 +100,7 @@
                                                line: '2',
                                                anchor: '2',
                                                id: 3,
-                                               text: '<p>Text of 2\n</p><h2 
id="2.1">2.1</h2>\n<p>Text of 2.1\n</p>\n',
+                                               text: '<p>Text of 2\n</p><h2 
id="2.1"><span>2.1</span></h2>\n<div><p>Text of 2.1\n</p></div>\n',
                                                children: [
                                                        {
                                                                level: '2',
@@ -196,7 +196,7 @@
                                                line: 'Aaa section',
                                                anchor: 'Aaa_section',
                                                id: 1,
-                                               text: 'aaa content<h3 
id="Subaaa_section">Subaaa section</h3>\nsubaaa content\n',
+                                               text: 'aaa content<h3 
id="Subaaa_section"><span>Subaaa section</span></h3>\n<div>subaaa 
content</div>\n',
                                                children: [
                                                        {
                                                                level: '3',
@@ -394,7 +394,7 @@
                                line: 'A1',
                                level: '2',
                                anchor: '1.0',
-                               text: '<h3 id="">A2.1</h3>\n\n',
+                               text: '<h3 
id=""><span>A2.1</span></h3>\n<div></div>\n',
                                children: [ {
                                        line: 'A2.1',
                                        level: '3',
@@ -414,7 +414,7 @@
                                line: 'A2',
                                level: '1',
                                anchor: '',
-                               text: '<h2 id="">A2.1</h2>\n\n',
+                               text: '<h2 
id=""><span>A2.1</span></h2>\n<div></div>\n',
                                children: [ {
                                        line: 'A2.1',
                                        level: '2',

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I154396eb6e6a1caa0d31b86e0196bc7456ce0d12
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/MobileFrontend
Gerrit-Branch: master
Gerrit-Owner: Jdlrobson <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to