summaryrefslogtreecommitdiff
path: root/resources/src/mediawiki.page/mediawiki.page.image.pagination.js
diff options
context:
space:
mode:
Diffstat (limited to 'resources/src/mediawiki.page/mediawiki.page.image.pagination.js')
-rw-r--r--resources/src/mediawiki.page/mediawiki.page.image.pagination.js77
1 files changed, 59 insertions, 18 deletions
diff --git a/resources/src/mediawiki.page/mediawiki.page.image.pagination.js b/resources/src/mediawiki.page/mediawiki.page.image.pagination.js
index 622e818d..9ad9c30a 100644
--- a/resources/src/mediawiki.page/mediawiki.page.image.pagination.js
+++ b/resources/src/mediawiki.page/mediawiki.page.image.pagination.js
@@ -2,23 +2,66 @@
* Implement AJAX navigation for multi-page images so the user may browse without a full page reload.
*/
( function ( mw, $ ) {
- var jqXhr, $multipageimage, $spinner;
+ var jqXhr, $multipageimage, $spinner,
+ cache = {},
+ cacheOrder = [];
- /* Fetch the next page and use jQuery to swap the table.multipageimage contents.
+ /* Fetch the next page, caching up to 10 last-loaded pages.
* @param {string} url
- * @param {boolean} [hist=false] Whether this is a load triggered by history navigation (if
- * true, this function won't push a new history state, for the browser did so already).
+ * @return {jQuery.Promise}
*/
- function loadPage( url, hist ) {
- var $tr;
- if ( jqXhr ) {
+ function fetchPageData( url ) {
+ if ( jqXhr && jqXhr.abort ) {
// Prevent race conditions and piling up pending requests
jqXhr.abort();
- jqXhr = undefined;
}
+ jqXhr = undefined;
+
+ // Try the cache
+ if ( cache[url] ) {
+ // Update access freshness
+ cacheOrder.splice( $.inArray( url, cacheOrder ), 1 );
+ cacheOrder.push( url );
+ return $.Deferred().resolve( cache[url] ).promise();
+ }
+
+ // @todo Don't fetch the entire page. Ideally we'd only fetch the content portion or the data
+ // (thumbnail urls) and update the interface manually.
+ jqXhr = $.ajax( url ).then( function ( data ) {
+ return $( data ).find( 'table.multipageimage' ).contents();
+ } );
- // Add a new spinner if one doesn't already exist
- if ( !$spinner ) {
+ // Handle cache updates
+ jqXhr.done( function ( $contents ) {
+ jqXhr = undefined;
+
+ // Cache the newly loaded page
+ cache[url] = $contents;
+ cacheOrder.push( url );
+
+ // Remove the oldest entry if we're over the limit
+ if ( cacheOrder.length > 10 ) {
+ delete cache[ cacheOrder[0] ];
+ cacheOrder = cacheOrder.slice( 1 );
+ }
+ } );
+
+ return jqXhr.promise();
+ }
+
+ /* Fetch the next page and use jQuery to swap the table.multipageimage contents.
+ * @param {string} url
+ * @param {boolean} [hist=false] Whether this is a load triggered by history navigation (if
+ * true, this function won't push a new history state, for the browser did so already).
+ */
+ function switchPage( url, hist ) {
+ var $tr, promise;
+
+ // Start fetching data (might be cached)
+ promise = fetchPageData( url );
+
+ // Add a new spinner if one doesn't already exist and the data is not already ready
+ if ( !$spinner && promise.state() !== 'resolved' ) {
$tr = $multipageimage.find( 'tr' );
$spinner = $.createSpinner( {
size: 'large',
@@ -34,13 +77,11 @@
$multipageimage.empty().append( $spinner );
}
- // @todo Don't fetch the entire page. Ideally we'd only fetch the content portion or the data
- // (thumbnail urls) and update the interface manually.
- jqXhr = $.ajax( url ).done( function ( data ) {
- jqXhr = $spinner = undefined;
+ promise.done( function ( $contents ) {
+ $spinner = undefined;
// Replace table contents
- $multipageimage.empty().append( $( data ).find( 'table.multipageimage' ).contents() );
+ $multipageimage.empty().append( $contents.clone() );
bindPageNavigation( $multipageimage );
@@ -66,12 +107,12 @@
.extend( { title: mw.config.get( 'wgPageName' ), page: page } )
.toString();
- loadPage( uri );
+ switchPage( uri );
e.preventDefault();
} );
$container.find( 'form[name="pageselector"]' ).one( 'change submit', function ( e ) {
- loadPage( this.action + '?' + $( this ).serialize() );
+ switchPage( this.action + '?' + $( this ).serialize() );
e.preventDefault();
} );
}
@@ -93,7 +134,7 @@
$( window ).on( 'popstate', function ( e ) {
var state = e.originalEvent.state;
if ( state && state.tag === 'mw-pagination' ) {
- loadPage( location.href, true );
+ switchPage( location.href, true );
}
} );
}