Jdlrobson has uploaded a new change for review.
https://gerrit.wikimedia.org/r/59785
Change subject: Alpha: Generate dynamic sections using templates
......................................................................
Alpha: Generate dynamic sections using templates
TODO: references
Change-Id: I770c84384593ce96e57cb2be6e0c12aed99e5eeb
---
M MobileFrontend.php
M includes/MobileFormatter.php
M javascripts/common/mf-application.js
M javascripts/common/mf-history-jquery.js
M javascripts/modules/mf-toggle-dynamic.js
M javascripts/views/page.js
A templates/page.html
M tests/javascripts/views/test_page.js
8 files changed, 150 insertions(+), 80 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/MobileFrontend
refs/changes/85/59785/1
diff --git a/MobileFrontend.php b/MobileFrontend.php
index e3a83a3..c7aaf00 100644
--- a/MobileFrontend.php
+++ b/MobileFrontend.php
@@ -325,6 +325,7 @@
'localBasePath' => $localBasePath,
'localTemplateBasePath' => $localBasePath . '/templates',
'templates' => array(
+ 'page',
'overlays/talk',
'talkSection',
),
diff --git a/includes/MobileFormatter.php b/includes/MobileFormatter.php
index 8cf3c57..e3ea761 100644
--- a/includes/MobileFormatter.php
+++ b/includes/MobileFormatter.php
@@ -162,8 +162,8 @@
$xpath = new DOMXpath( $doc );
$elements = $xpath->query(
'//*[@class="content_block"]' );
/** @var $element DOMElement */
- foreach ( $elements as $element
) {
-
$element->parentNode->removeChild( $element );
+ foreach ( $elements as $element
) { // empty elements
+ $element->nodeValue =
'';
}
$html = $temp->getText();
}
diff --git a/javascripts/common/mf-application.js
b/javascripts/common/mf-application.js
index bbc6cab..5b6fac3 100644
--- a/javascripts/common/mf-application.js
+++ b/javascripts/common/mf-application.js
@@ -92,12 +92,6 @@
window.scrollTo( 0, 1 );
}
- function triggerPageReadyHook( pageTitle, sectionData, anchorSection ) {
- emit( 'page-loaded', {
- title: pageTitle, data: sectionData, anchorSection:
anchorSection
- } );
- }
-
// TODO: separate main menu navigation code into separate module
function init() {
// FIXME: use wgIsMainPage
@@ -216,7 +210,6 @@
on: on,
prefix: 'mw-mf-',
supportsPositionFixed: supportsPositionFixed,
- triggerPageReadyHook: triggerPageReadyHook,
prettyEncodeTitle: prettyEncodeTitle,
utils: $, // FIXME: deprecate
template: template
diff --git a/javascripts/common/mf-history-jquery.js
b/javascripts/common/mf-history-jquery.js
index 0fbad0f..db70e98 100644
--- a/javascripts/common/mf-history-jquery.js
+++ b/javascripts/common/mf-history-jquery.js
@@ -2,6 +2,7 @@
var
firstRun,
+ Page = M.require( 'page' ),
makeStubPage,
updateQueryStringParameter =
M.history.updateQueryStringParameter,
getArticleUrl = M.history.getArticleUrl,
@@ -79,56 +80,31 @@
} );
}
- // FIXME: use template engine this is not maintainable
function renderPage( pageTitle, resp, constructPage ) {
- var i, secs, s, sectionNum = 0, level, text,
- $content = $( '#content' ),
- $section,
- $tmpContainer = $( '<div>' ),
- sectionData = {},
- anchorSection = {};
- if ( resp && resp.mobileview && resp.mobileview.sections ) {
- secs = resp.mobileview.sections;
- for( i = 0; i < secs.length; i++ ) {
- s = secs[ i ];
- level = s.level;
- text = s.text || '';
- if ( constructPage && i === 0 ) { // do lead
- $( '#content_0' ).html( text );
- }
- if ( level === '2' ) {
- sectionNum = sectionNum + 1;
- sectionData[ sectionNum ] = { html:
text };
- // add self as a parent so that we
unfold it when needed
- anchorSection[ s.anchor ] = sectionNum;
- anchorSection[ 'section_' + sectionNum
] = sectionNum;
- if ( constructPage ) {
- $section = $( '<div
class="section">' ).appendTo( $content );
- // TODO: link these so they are
clickable
- $( '<h2
class="section_heading">' ).attr( 'id', 'section_' + sectionNum ).
- html( s.line
).appendTo( $section );
- }
- } else if ( level ) {
- $tmpContainer.html( text );
- $tmpContainer.prepend( $( '<h' + level
+ '>' ).attr( 'id', s.anchor ).html( s.line ) );
- sectionData[ sectionNum ].html +=
$tmpContainer.html();
- // we need to know the parent of
subsection to unfold the proper section
- anchorSection[ s.anchor ] = sectionNum;
- }
- if( s.hasOwnProperty( 'references' ) ) {
- sectionData[ sectionNum ].references =
true;
- $( '<div class="content_block">'
).attr( 'id', 'content_' + sectionNum ).
- html( sectionData[ sectionNum
].html ).insertAfter( '#section_' + sectionNum );
- }
- }
- updateUILinks( pageTitle );
+ var page, references, $references, options = {
+ title: pageTitle,
+ sections: resp.mobileview.sections
+ };
- if ( resp.mobileview.hasOwnProperty( 'mainpage' ) ) {
- M.emit( 'homepage-loaded' );
- }
- M.triggerPageReadyHook( pageTitle, sectionData,
anchorSection );
- $( '#content_0' ).removeClass( 'loading' ); // reset
loader
+ if ( constructPage ) {
+ options.el = $( '#content' )[0];
}
+
+ page = new Page( options );
+
+ // FIXME: Horrible 4 lines of code to force loading of
references
+ references = page.getReferenceSection();
+ $references = $( '#content_' + references.index );
+ if ( !$references.hasClass( 'loaded' ) ) {
+ $references.addClass( 'loaded' ).html(
references.referenceContent );
+ }
+
+ updateUILinks( pageTitle );
+ $( '#content_0' ).removeClass( 'loading' ); // reset loader
+ if ( resp.mobileview.hasOwnProperty( 'mainpage' ) ) {
+ M.emit( 'homepage-loaded' );
+ }
+ M.emit( 'page-loaded', page );
}
loadLanguages = function( title ) {
@@ -229,8 +205,15 @@
} );
}
+ M.on( 'section-rendered', function( $content ) {
+ // FIXME: this should live in the hidpi module when dynamic
sections is promoted from beta
+ if ( $content.hidpi ) {
+ $content.hidpi();
+ }
+ hijackLinks( $content );
+ } );
+
M.history.makeStubPage = makeStubPage;
- M.history.hijackLinks = hijackLinks;
M.history.loadPage = loadPage;
M.history.navigateToPage = navigateToPage;
diff --git a/javascripts/modules/mf-toggle-dynamic.js
b/javascripts/modules/mf-toggle-dynamic.js
index c61fed5..66de7c9 100644
--- a/javascripts/modules/mf-toggle-dynamic.js
+++ b/javascripts/modules/mf-toggle-dynamic.js
@@ -2,25 +2,18 @@
var T = ( function() {
var
- sectionData = {},
- anchorSection,
+ currentPage,
footerInitialised = false;
function wm_toggle_section( section_id, keepHash ) {
var id = 'section_' + section_id, content_id = 'content_' +
section_id,
- closed, sectionInfo = sectionData[ section_id ],
- $container,
+ closed, section =
currentPage.getSubSections()[section_id-1],
$section = $( '#' + id ), $content = $( '#' +
content_id ),
selector = '#' + content_id + ',#' + id;
- if ( sectionInfo && $content.length === 0 ) {
- $container = $( '<div class="content_block">' ).attr(
'id', content_id ).html( sectionInfo.html ).insertAfter( '#' + id );
- M.emit( 'section-rendered', $container );
- // FIXME: this should live in the hidpi module when
dynamic sections is promoted from beta
- if ( $container.hidpi ) {
- $container.hidpi();
- }
- M.history.hijackLinks( $container );
+ if ( section && !$content.hasClass( 'loaded' ) ) {
+ $content.addClass( 'loaded' ).html( section.content );
+ M.emit( 'section-rendered', $content );
}
$( selector ).toggleClass( 'openSection' );
@@ -33,7 +26,10 @@
}
function wm_reveal_for_hash( hash, keepHash ) {
- wm_toggle_section( anchorSection[ hash.slice( 1 ) ], keepHash );
+ var section = currentPage.getParentSection( hash.slice( 1 ) );
+ if ( section ) {
+ wm_toggle_section( section.index, keepHash );
+ }
}
function checkHash() {
@@ -73,10 +69,8 @@
var pageTitle = mw.config.get( 'wgTitle'),
specialPage = $( '#content_wrapper' ).hasClass(
'mw-mf-special' );
- M.on( 'page-loaded', function( article ) {
- sectionData = article.data || {};
-
- anchorSection = article.anchorSection;
+ M.on( 'page-loaded', function( page ) {
+ currentPage = page;
if ( $( '#content .section_heading' ).length > 1 ) {
enableToggling( $( '#content' ) );
}
diff --git a/javascripts/views/page.js b/javascripts/views/page.js
index e206694..038a428 100644
--- a/javascripts/views/page.js
+++ b/javascripts/views/page.js
@@ -6,31 +6,41 @@
Section = View.extend( {
defaults: {
+ contentClass: '',
+ referenceContent: '',
heading: '',
content: '',
+ index: -1,
id: null
},
initialize: function( options ) {
+ this.index = options.index;
this.heading = options.heading;
this.content = options.content;
+ this.referenceContent = options.referenceContent;
+ this.contentClass = options.contentClass;
this.id = options.id;
}
} );
Page = View.extend( {
+ template: M.template.get( 'page' ),
defaults: {
- heading: '',
+ title: '',
lead: '',
sections: []
},
- initialize: function( options ) {
+ preRender: function( options ) {
var s, i, level, text,
+ data,
$tmpContainer = $( '<div>' ),
html, section,
sectionNum = 0,
secs = options.sections,
sectionData = {};
+ this._anchorSection = {};
+ this.title = options.title;
for ( i = 0; i < secs.length; i++ ) {
s = secs[ i ];
level = s.level;
@@ -41,10 +51,10 @@
}
if ( level === '2' ) {
- sectionNum = sectionNum + 1;
+ sectionNum += 1;
+ this._anchorSection[ 'section_' +
sectionNum ] = sectionNum;
sectionData[ sectionNum ] = { content:
text,
id: s.id, heading: s.line };
-
} else if ( level ) {
$tmpContainer.html( text );
$tmpContainer.prepend(
@@ -58,16 +68,51 @@
sectionData[ sectionNum
].content += html;
}
}
+ if ( s.hasOwnProperty( 'references' ) ) {
+ sectionData[ sectionNum ].references =
true;
+ }
+ this._anchorSection[ s.anchor ] = sectionNum;
}
+
this.sections = [];
this._sectionLookup = {};
for ( s in sectionData ) {
if ( sectionData.hasOwnProperty( s ) ) {
- section = new Section( sectionData[ s ]
);
+ sectionData[ s ].index =
this.sections.length + 1;
+ data = sectionData[ s ];
+ if ( data.references ) {
+ data.referenceContent =
data.content;
+ data.content = '';
+ data.contentClass = 'loaded';
+ }
+ section = new Section( data );
+ if ( data.references ) {
+ this._referenceLookup = section;
+ }
this.sections.push( section );
this._sectionLookup[ section.id ] =
section; // allow easy lookup of section
}
}
+ options = $.extend( options, {
+ sections: this.sections,
+ lead: this.lead
+ } );
+ },
+ /**
+ * Given an anchor finds the Section it belongs to
+ * objects that extend View.
+ *
+ * @param {string}
+ * @return {Section} Section object that it belongs to
+ */
+ getParentSection: function( anchor ) {
+ var parentId = this._anchorSection[ anchor ];
+ if ( parentId ) {
+ return this.getSubSection( parentId );
+ }
+ },
+ getReferenceSection: function() {
+ return this._referenceLookup;
},
getSubSection: function( id ) {
return this._sectionLookup[ id ];
diff --git a/templates/page.html b/templates/page.html
new file mode 100644
index 0000000..3e19930
--- /dev/null
+++ b/templates/page.html
@@ -0,0 +1,11 @@
+<h1 id="section_0">{{title}}</h1>
+<div id="content_0">{{{lead}}}</div>
+{{#sections}}
+<div class="section">
+ <h2 class="section_heading" id="section_{{id}}">{{{heading}}}</h2>
+ <div class="content_block{{contentClass}}" id="content_{{id}}">
+ {{{referenceContent}}}
+ <!-- content expects to be injected -->
+ </div>
+</div>
+{{/sections}}
diff --git a/tests/javascripts/views/test_page.js
b/tests/javascripts/views/test_page.js
index 29b0134..fa03966 100644
--- a/tests/javascripts/views/test_page.js
+++ b/tests/javascripts/views/test_page.js
@@ -2,6 +2,27 @@
var Page = M.require( 'page' ),
nonStandardPage = [{"id":0,"text":""},{"level":"1","line":"Test heading
h1","anchor":"Test_heading_h1","id":1,"text":"<p>another h1?git fetch
ssh:\/\/[email protected]:29418\/mediawiki\/extensions\/MobileFrontend
refs\/changes\/39\/54139\/8 && git checkout FETCH_HEADgit fetch
ssh:\/\/[email protected]:29418\/mediawiki\/extensions\/MobileFrontend
refs\/changes\/39\/54139\/8 && git checkout FETCH_HEAD\ngit fetch
ssh:\/\/[email protected]:29418\/mediawiki\/extensions\/MobileFrontend
refs\/changes\/39\/54139\/8 && git checkout FETCH_HEAD\ngit fetch
ssh:\/\/[email protected]:29418\/mediawiki\/extensions\/MobileFrontend
refs\/changes\/39\/54139\/8 && git checkout FETCH_HEAD\nv\nv\nv\nvgit
fetch
ssh:\/\/[email protected]:29418\/mediawiki\/extensions\/MobileFrontend
refs\/changes\/39\/54139\/8 && git checkout FETCH_HEADgit fetch
ssh:\/\/[email protected]:29418\/mediawiki\/extensions\/MobileFrontend
refs\/changes\/39\/54139\/8 && git checkout FETCH_HEAD\ngit fetch
ssh:\/\/[email protected]:29418\/mediawiki\/extensions\/MobileFrontend
refs\/changes\/39\/54139\/8 && git checkout FETCH_HEADgit fetch
ssh:\/\/[email protected]:29418\/mediawiki\/extensions\/MobileFrontend
refs\/changes\/39\/54139\/8 && git checkout FETCH_HEADgit fetch
ssh:\/\/[email protected]:29418\/mediawiki\/extensions\/MobileFrontend
refs\/changes\/39\/54139\/8 && git checkout FETCH_HEAD\nvgit fetch
ssh:\/\/[email protected]:29418\/mediawiki\/extensions\/MobileFrontend
refs\/changes\/39\/54139\/8 && git checkout FETCH_HEAD\ngit fetch
ssh:\/\/[email protected]:29418\/mediawiki\/extensions\/MobileFrontend
refs\/changes\/39\/54139\/8 && git checkout
FETCH_HEAD\n<\/p>"},{"level":"2","line":"Test heading h2
(1)","anchor":"Test_heading_h2_.281.29","id":2,"text":"<p>1: You have brains in
your head. You have feet in your shoes. You can steer yourself any direction
you choose. You're on your own. And you know what you know. And YOU are the one
who'll decide where to go...\nSed ut perspiciatis unde omnis iste natus error
sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa
quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt
explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut
fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi
nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet,
consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut
labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam,
quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid
ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea
voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem
eum fugiat quo voluptas nulla pariatur?\nSed ut perspiciatis unde omnis iste
natus error sit voluptatem accusantium doloremque laudantium, totam rem
aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae
vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit
aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui
ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum
quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius
modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut
enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit
laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure
reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur,
vel illum qui dolorem eum fugiat quo voluptas nulla
pariatur?\n<\/p>"},{"level":"2","line":"Test heading h2
2)","anchor":"Test_heading_h2_2.29","id":3,"text":"<p>2: You have brains in
your head. You have feet in your shoes. You can steer yourself any direction
you choose. You're on your own. And you know what you know. And YOU are the one
who'll decide where to go...\nSed ut perspiciatis unde omnis iste natus error
sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa
quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt
explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut
fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi
nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet,
consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut
labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam,
quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid
ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea
voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem
eum fugiat quo voluptas nulla pariatur?\n<\/p>"},{"level":"2","line":"Test
heading h2 (3)","anchor":"Test_heading_h2_.283.29","id":4,"text":"<p>3: You
have brains in your head. You have feet in your shoes. You can steer yourself
any direction you choose. You're on your own. And you know what you know. And
YOU are the one who'll decide where to go...\n<\/p>"}],
+ referenceSections = [
+ {
+ "id": 0,
+ "text": "lead section"
+ },
+ {
+ "level": "2",
+ "line": "References",
+ "anchor": "References",
+ "id": 1,
+ "references": '',
+ "text": "1"
+ },
+ {
+ "level": "3",
+ "line": "B",
+ "anchor": "B",
+ "id": 2,
+ "text": "2"
+ }
+ ],
apiSections =
[ {
"id": 0,
@@ -10,12 +31,14 @@
{
"level": "2",
"line": "A",
+ "anchor": "A",
"id": 1,
"text": "<p>a</p>"
},
{
"level": "3",
"line": "B",
+ "anchor": "B",
"id": 2,
"text": "<p>b<\/p>"
},
@@ -28,6 +51,7 @@
{
"level": "4",
"line": "D",
+ "anchor": 'DifferentAnchor',
"id": 4,
"text": "<div>d<\/div>"
},
@@ -48,7 +72,7 @@
strictEqual( sections.length, 2, '2 sub sections found' );
strictEqual( sections[ 0 ].heading, 'A' );
strictEqual( sections[ 0 ].content,
-
'<p>a</p><h3>B</h3><p>b</p><h3>C</h3><p>c</p><h4>D</h4><div>d</div>' );
+ '<p>a</p><h3 id="B">B</h3><p>b</p><h3>C</h3><p>c</p><h4
id="DifferentAnchor">D</h4><div>d</div>' );
strictEqual( sections[ 1 ].heading, 'F' );
strictEqual( sections[ 1 ].content, '<p>f</p>' );
strictEqual( p.getSubSection( 5 ).heading, 'F', 'check correct sub
section with id 5 found' );
@@ -63,6 +87,25 @@
strictEqual( p.getSubSections().length, 3, 'There are 3 h2s inside the
content' );
} );
+
+QUnit.test( 'getParentSection', 5, function() {
+ var p = new Page( { sections: apiSections } );
+ strictEqual( p.getParentSection( 'section_1' ).heading, 'A', 'Check
anchor is saved for actual section' );
+ strictEqual( p.getParentSection( 'A' ).heading, 'A', 'Finds correct
parent section (same section)' );
+ strictEqual( p.getParentSection( 'B' ).heading, 'A', 'Finds correct
parent section' );
+ strictEqual( p.getParentSection( 'DifferentAnchor' ).heading, 'A',
'Finds correct parent section' );
+ strictEqual( typeof p.getParentSection( 'NonExistantSection' ),
'undefined', 'Returns nothing if non-existant' );
+} );
+
+QUnit.test( 'getReferences', 4, function() {
+ var p = new Page( { sections: referenceSections } ),
+ sections = p.getSubSections();
+ strictEqual( sections.length, 1, 'Check references are recorded as a
section' );
+ strictEqual( sections[0].content, '', 'Check content is blank' );
+ strictEqual( sections[0].contentClass, 'loaded', 'Check it is flagged
as being loaded so as not to interfere with toggle-dynamic' );
+ strictEqual( sections[0].referenceContent, '1<h3 id="B">B</h3>2',
'Check references set' );
+} );
+
}( mw.mobileFrontend, jQuery ) );
--
To view, visit https://gerrit.wikimedia.org/r/59785
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I770c84384593ce96e57cb2be6e0c12aed99e5eeb
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