Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge pull request #262 from yuvipanda/dynamic-sections

Dynamic sections
  • Loading branch information...
commit fe6a4af7807e32f81cc645204153195dc86733e6 2 parents 34d90f9 + 963d8b0
@brion brion authored
View
38 assets/www/android/platform.js
@@ -235,9 +235,43 @@ savedPages.doSave = function(options) {
chrome.hideSpinner();
d.reject();
}
+
+ var populateSectionDeferreds = [];
$.each(app.curPage.sections, function(i, section) {
- chrome.populateSection(section.id);
+ populateSectionDeferreds.push( chrome.populateSection( section.id ) );
+ });
+ $.when.apply( $, populateSectionDeferreds ).done( function() {
+ window.plugins.urlCache.getCachedPathForURI( page.getAPIUrl(), gotPath, gotError );
});
- window.plugins.urlCache.getCachedPathForURI(page.getAPIUrl(), gotPath, gotError);
+ return d;
+}
+
+app.loadCachedPage = function( url, title, lang ) {
+ chrome.showSpinner();
+ var d = $.Deferred();
+ var replaceRes = function() {
+ // images
+ $( '#main img' ).each( function() {
+ var em = $( this );
+ var gotLinkPath = function( linkPath ) {
+ em.attr( 'src', 'file://' + linkPath.file );
+ }
+ var target = this.src.replace( 'file:', window.PROTOCOL + ':' );
+ window.plugins.urlCache.getCachedPathForURI( target, gotLinkPath, gotError );
+ });
+ };
+ var gotPath = function( cachedPage ) {
+ $.get( 'file://' + cachedPage.file ).then( function( data ) {
+ var page = new Page( title, JSON.parse( data ), lang, true );
+ replaceRes();
+ app.setCurrentPage( page );
+ d.resolve();
+ });
+ }
+ var gotError = function( error ) {
+ console.log( 'Error: ' + error );
+ chrome.hideSpinner();
+ }
+ window.plugins.urlCache.getCachedPathForURI( url, gotPath, gotError );
return d;
}
View
29 assets/www/ios/platform.js
@@ -24,7 +24,7 @@ function getAboutVersionString() {
app.loadCachedPage = function (url) {
return urlCache.getCachedData(url).then(function(data) {
var pageData = JSON.parse(data);
- var page = new Page(pageData.title, pageData.lead, pageData.sections, pageData.lang);
+ var page = Page.deserializeFrom( pageData );
app.setCurrentPage(page);
}).fail(function(error) {
console.log('Error: ' + error);
@@ -35,20 +35,25 @@ app.loadCachedPage = function (url) {
savedPages.doSave = function(options) {
var d = $.Deferred();
var url = app.curPage.getAPIUrl();
- var data = JSON.stringify(app.curPage);
+ var data = app.curPage.serialize();
chrome.showSpinner();
+
+ var populateSectionDeferreds = [];
$.each(app.curPage.sections, function(i, section) {
- chrome.populateSection(section.id);
+ populateSectionDeferreds.push( chrome.populateSection( section.id ) );
});
- urlCache.saveCompleteHtml(url, data, $("#main")).done(function() {
- if(!options.silent) {
- chrome.showNotification(mw.message('page-saved', app.curPage.title).plain());
- }
- app.track('mobile.app.wikipedia.save-page');
- chrome.hideSpinner();
- d.resolve();
- }).fail(function() {
- d.reject()
+
+ $.when.apply( $, populateSectionDeferreds ).done( function() {
+ urlCache.saveCompleteHtml( url, data, $( "#main" ) ).done( function() {
+ if( !options.silent ) {
+ chrome.showNotification( mw.message( 'page-saved', app.curPage.title ).plain() );
+ }
+ app.track( 'mobile.app.wikipedia.save-page' );
+ chrome.hideSpinner();
+ d.resolve();
+ }).fail( function() {
+ d.reject()
+ });
});
return d;
}
View
50 assets/www/js/app.js
@@ -23,7 +23,7 @@ window.app = function() {
app.getWikiMetadata().done(function(wikis) {
var mainPage = wikis[lang].mainPage;
- app.navigateTo(mainPage, lang).done(function(data) {
+ app.navigateTo( mainPage, lang, { isCompletePage: true } ).done( function( data ) {
d.resolve(data);
}).fail(function(err) {
d.reject(err);
@@ -32,36 +32,8 @@ window.app = function() {
return d;
}
- function loadCachedPage (url, title, lang) {
- chrome.showSpinner();
- var d = $.Deferred();
- var replaceRes = function() {
-
- // images
- $('#main img').each(function() {
- var em = $(this);
- var gotLinkPath = function(linkPath) {
- em.attr('src', 'file://' + linkPath.file);
- }
- var target = this.src.replace('file:', window.PROTOCOL + ':');
- window.plugins.urlCache.getCachedPathForURI(target, gotLinkPath, gotError);
- });
- };
- var gotPath = function(cachedPage) {
-
- $.get('file://' + cachedPage.file).then(function(data) {
- var page = Page.fromRawJSON(title, JSON.parse(data), lang);
- replaceRes();
- setCurrentPage(page);
- d.resolve();
- });
- }
- var gotError = function(error) {
- console.log('Error: ' + error);
- chrome.hideSpinner();
- }
- window.plugins.urlCache.getCachedPathForURI(url, gotPath, gotError);
- return d;
+ function loadCachedPage( url, title, lang ) {
+ // Overriden by platform specific implementations;
}
function setCurrentPage(page) {
@@ -93,15 +65,20 @@ window.app = function() {
app.curPage = null;
}
- function loadPage(title, language) {
+ function loadPage( title, language, isCompletePage ) {
var d = $.Deferred();
function doRequest() {
- var req = Page.requestFromTitle(title, language).done(function(page) {
+ var req = Page.requestFromTitle( title, language, isCompletePage ).done( function( page ) {
if(page === null) {
setErrorPage(404);
}
setCurrentPage(page);
+ if( !page.isCompletePage ) {
+ page.requestCompletePage().done( function() {
+ console.log("Full page retreived!");
+ });
+ }
d.resolve(page);
}).fail(function(xhr, textStatus, errorThrown) {
if(textStatus === "abort") {
@@ -169,7 +146,7 @@ window.app = function() {
function navigateTo(title, lang, options) {
var d = $.Deferred();
- var options = $.extend({cache: false, updateHistory: true}, options || {});
+ var options = $.extend( {cache: false, updateHistory: true, isCompletePage: false}, options || {} );
var url = app.urlForTitle(title, lang);
if(title === "") {
@@ -190,9 +167,8 @@ window.app = function() {
if(title === "") {
title = "Main_Page"; // FIXME
}
- d = app.loadPage(title, lang);
- d.done(function() {
- console.log("Navigating to " + title);
+ d = app.loadPage( title, lang, options.isCompletePage );
+ d.done(function(page) {
if(options.hideCurrent) {
$("#content").show();
// see http://forrst.com/posts/iOS_scrolling_issue_solved-rgX
View
23 assets/www/js/chrome.js
@@ -52,22 +52,29 @@ window.chrome = function() {
}
function populateSection(sectionID) {
+ var d = $.Deferred();
var selector = "#content_" + sectionID;
var $contentBlock = $(selector);
if(!$contentBlock.data('populated')) {
- var sectionHtml = app.curPage.getSectionHtml(sectionID);
- $contentBlock.append($(sectionHtml)).data('populated', true);
- chrome.initContentLinkHandlers(selector);
- mw.mobileFrontend.references.init($contentBlock[0], false, {animation: 'none', onClickReference: onClickReference});
- }
+ app.curPage.requestSectionHtml( sectionID ).done( function( sectionHtml ) {
+ $contentBlock.append( $( sectionHtml ) ).data( 'populated', true );
+ chrome.initContentLinkHandlers( selector );
+ mw.mobileFrontend.references.init( $contentBlock[0], false, { animation: 'none', onClickReference: onClickReference } );
+ d.resolve();
+ });
+ } else {
+ d.resolve();
+ }
+ return d;
}
function handleSectionExpansion() {
$(".section_heading").click(function() {
var sectionID = $(this).data('section-id');
- chrome.populateSection(sectionID);
- mw.mobileFrontend.toggle.wm_toggle_section(sectionID);
- chrome.setupScrolling("#content");
+ chrome.populateSection(sectionID).done(function() {
+ mw.mobileFrontend.toggle.wm_toggle_section( sectionID );
+ chrome.setupScrolling( "#content" );
+ });
});
}
View
178 assets/www/js/page.js
@@ -1,75 +1,135 @@
(function() {
- window.Page = function(title, lead, sections, lang) {
- this.title = title;
- this.lead = lead;
- this.sections = sections;
- this.lang = lang;
- };
-
- Page.fromRawJSON = function(title, rawJSON, lang) {
+ window.Page = function( title, rawJSON, lang, isCompletePage ) {
var lead = {};
var sections = [];
var lastCollapsibleSection = {subSections: []};
- if(typeof rawJSON.mobileview.redirected !== "undefined") {
- // If we're redirected, use the final page name
- title = rawJSON.mobileview.redirected;
- }
-
- if(typeof rawJSON.mobileview.error !== "undefined") {
- // Only two types of errors possible when the mobileview api returns
- // One is a 404 (missingtitle), other is an invalid title (usually empty title)
- // We're redirecting empty title to main page in app.navigateTo
- if(rawJSON.mobileview.error.code === "missingtitle") {
- return null;
+ if( typeof rawJSON.mobileview !== 'undefined' ) {
+ if( typeof rawJSON.mobileview.redirected !== "undefined" ) {
+ // If we're redirected, use the final page name
+ title = rawJSON.mobileview.redirected;
}
- }
- $.each(rawJSON.mobileview.sections, function(index, section) {
- if(section.id === 0) {
- // Lead Section
- // We should also make sure that if there is a lead followed by
- // h3, h4, etc they all fold into the lead
- // Not sure why a page would do this though
- section.subSections = [];
- lead = section;
- lastCollapsibleSection = section;
- return;
- }
- if(typeof section.references !== "undefined") {
- section.references = true;
- }
- // Only consider leve 2 sections as 'sections'
- // Group *all* subsections under them, no matter which level they are at
- if(section.level == 2) {
- section.subSections = [];
- lastCollapsibleSection = section;
- sections.push(section);
- } else {
- lastCollapsibleSection.subSections.push(section);
+ if( typeof rawJSON.mobileview.error !== "undefined" ) {
+ // Only two types of errors possible when the mobileview api returns
+ // One is a 404 (missingtitle), other is an invalid title (usually empty title)
+ // We're redirecting empty title to main page in app.navigateTo
+ if( rawJSON.mobileview.error.code === "missingtitle" ) {
+ return null;
+ }
}
- });
- return new Page(title, lead, sections, lang);
+ $.each( rawJSON.mobileview.sections, function( index, section ) {
+ if( section.id === 0 ) {
+ // Lead Section
+ // We should also make sure that if there is a lead followed by
+ // h3, h4, etc they all fold into the lead
+ // Not sure why a page would do this though
+ section.subSections = [];
+ lead = section;
+ lastCollapsibleSection = section;
+ return;
+ }
+ if( typeof section.references !== "undefined" ) {
+ section.references = true;
+ }
+ // Only consider leve 2 sections as 'sections'
+ // Group *all* subsections under them, no matter which level they are at
+ if( section.level == 2 ) {
+ section.subSections = [];
+ lastCollapsibleSection = section;
+ sections.push( section );
+ } else {
+ lastCollapsibleSection.subSections.push( section );
+ }
+ });
+ }
+
+ this.title = title;
+ this.lead = lead;
+ this.sections = sections;
+ this.lang = lang;
+ this.isCompletePage = isCompletePage;
};
- Page.requestFromTitle = function(title, lang) {
+ Page.deserializeFrom = function( data ) {
+ var page = new Page( data.title, {}, data.lang, true);
+ page.lead = data.lead;
+ page.sections = data.sections;
+ return page;
+ }
+
+ Page.requestFromTitle = function(title, lang, isCompletePage) {
+ var sections;
+ if( !isCompletePage ) {
+ sections = "0|references";
+ } else {
+ sections = "all";
+ }
// Make sure changes to this are also propogated to getAPIUrl
return app.makeAPIRequest({
action: 'mobileview',
page: title,
redirects: 'yes',
prop: 'sections|text',
- sections: 'all',
+ sections: sections,
sectionprop: 'level|line',
noheadings: 'yes'
}, lang, {
dataFilter: function(data) {
- return Page.fromRawJSON(title, JSON.parse(data), lang);
+ return new Page( title, JSON.parse( data ), lang, isCompletePage );
}
});
};
+ Page.prototype.requestCompletePage = function() {
+ if( this.completePageReq ) {
+ // Only one request should be sent
+ return this.completePageReq;
+ }
+
+ var sectionsList = [];
+ var that = this;
+
+ $.each( this.sections, function( index, section ) {
+ sectionsList.push( section.id );
+ var subSectionIDs = section.subSections.map( function( subSection ) {
+ return subSection.id;
+ });
+ sectionsList.push.apply( sectionsList, subSectionIDs );
+ });
+
+ this.completePageReq = app.makeAPIRequest({
+ action: 'mobileview',
+ page: this.title,
+ redirects: 'yes',
+ prop: 'sections|text',
+ sections: sectionsList.join( '|' ),
+ sectionprop: 'level|line',
+ noheadings: 'yes'
+ }, this.lang, {
+ dataFilter: function(text) {
+ var data = JSON.parse( text );
+ var newPage = new Page( that.title, data, that.lang, true );
+ $.each( newPage.sections, function( index, section ) {
+ if( section.id !== 0 || typeof section.references !== 'undefined' ) {
+ // FIXME: *Rare* race condition when a new section is added
+ // bwetween the first request and second request. Will cause the new
+ // section to not show up (if added at the bottom) or replace other
+ // sections' content (if in the middle). Not a big enough concern for
+ // now, but needs a fix eventually.
+ that.sections[ index ] = section;
+ }
+ });
+ that.isCompletePage = true;
+ return that;
+ }
+ }).always( function() {
+ that.completePageReq = null;;
+ });
+ return this.completePageReq;
+ }
+
Page.prototype.requestLangLinks = function() {
if(this.langLinks) {
var d = $.Deferred();
@@ -94,16 +154,30 @@
});
};
- Page.prototype.getSectionHtml = function(id) {
- var sectionTemplate = templates.getTemplate('section-template');
+
+ Page.prototype.getSection = function( id ) {
var foundSection = null;
- $.each(this.sections, function(i, section) {
- if(section.id == id) {
+ $.each( this.sections, function( i, section ) {
+ if( section.id == id ) {
foundSection = section;
return;
}
});
- return sectionTemplate.render(foundSection);
+ return foundSection;
+ }
+
+ Page.prototype.requestSectionHtml = function( id ) {
+ var d = $.Deferred();
+ var sectionTemplate = templates.getTemplate( 'section-template' );
+ console.log( 'fullpage is ' + this.isCompletePage );
+ if( this.isCompletePage ) {
+ d.resolve( sectionTemplate.render( this.getSection( id ) ) );
+ } else {
+ this.requestCompletePage().done( function( page ) {
+ d.resolve( sectionTemplate.render( page.getSection( id ) ) );
+ });
+ }
+ return d;
};
Page.prototype.toHtml = function() {
Please sign in to comment.
Something went wrong with that request. Please try again.