mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/RevisionSlider
synced 2024-12-24 04:33:03 +00:00
37dc0b5adb
Also introducing sinon to mock some parts. Bug: T370573 Change-Id: I5a7573bcac9501a7b37a12b86bb0d4f46055f70e
221 lines
6.2 KiB
JavaScript
221 lines
6.2 KiB
JavaScript
/**
|
|
* Module handling diff page reloading and the RevisionSlider browser history
|
|
*
|
|
* @class Diffpage
|
|
* @param {History} [historyObj] defaults to the global History object
|
|
* ] * @constructor
|
|
*/
|
|
function DiffPage( historyObj ) {
|
|
this.lastRequest = null;
|
|
|
|
this.history = historyObj || history;
|
|
}
|
|
|
|
Object.assign( DiffPage.prototype, {
|
|
/**
|
|
* Refreshes the diff view with two given revision IDs
|
|
*
|
|
* @param {number} diff
|
|
* @param {number} oldid
|
|
* @param {SliderView} sliderView
|
|
* @param {number} [retryAttempt=0]
|
|
*/
|
|
refresh: function ( diff, oldid, sliderView, retryAttempt ) {
|
|
const self = this,
|
|
retryLimit = 2,
|
|
data = {
|
|
diff: diff,
|
|
oldid: oldid
|
|
},
|
|
params = this.getExtraDiffPageParams();
|
|
|
|
retryAttempt = retryAttempt || 0;
|
|
|
|
if ( Object.keys( params ).length > 0 ) {
|
|
Object.assign( data, params );
|
|
}
|
|
|
|
if ( this.lastRequest ) {
|
|
this.lastRequest.abort();
|
|
}
|
|
|
|
$( 'table.diff[data-mw="interface"]' ).addClass( 'mw-revslider-diff-loading' );
|
|
|
|
this.lastRequest = $.ajax( {
|
|
url: mw.util.wikiScript( 'index' ),
|
|
data: data,
|
|
tryCount: 0
|
|
} );
|
|
// Don't chain, so lastRequest is a jQuery.jqXHR object
|
|
this.lastRequest.then( ( data2 ) => {
|
|
const $data = $( data2 ),
|
|
$container = $( '.mw-revslider-container' ),
|
|
scrollLeft = $container.find( '.mw-revslider-revisions-container' ).scrollLeft();
|
|
|
|
// Add our current rendered slider into the newly loaded container
|
|
$data.find( '.mw-revslider-container' ).replaceWith( $container );
|
|
const $contentText = $data.find( '#mw-content-text' );
|
|
|
|
// Replace elements on the page with the newly loaded elements, from top to bottom
|
|
$( '#mw-content-text' ).replaceWith( $contentText );
|
|
$( '.printfooter' ).replaceWith( $data.find( '.printfooter' ) );
|
|
|
|
const $catlinks = $data.find( '.catlinks[data-mw="interface"]' );
|
|
mw.hook( 'wikipage.categories' ).fire( $catlinks );
|
|
$( '.catlinks[data-mw="interface"]' ).replaceWith( $catlinks );
|
|
|
|
// Replace navigation menus. See also T211557
|
|
[ '#t-permalink', '#ca-delete', '#ca-edit', '#footer-places-mobileview' ].forEach( ( selector ) => {
|
|
$( selector ).parent().replaceWith( $data.find( selector ).parent() );
|
|
} );
|
|
|
|
// Update wgRevisionId (T161257), and wgDiffOldId/NewId
|
|
mw.config.set( {
|
|
wgRevisionId: diff,
|
|
wgDiffOldId: oldid,
|
|
wgDiffNewId: diff
|
|
} );
|
|
|
|
$( '.mw-revslider-revisions-container' ).scrollLeft( scrollLeft );
|
|
|
|
self.addHandlersToCoreLinks( sliderView );
|
|
|
|
// Re-trigger existing, stable core hooks under the same circumstances as in core
|
|
mw.hook( 'wikipage.content' ).fire( $contentText );
|
|
|
|
const $nodes = $( 'table.diff[data-mw="interface"]' );
|
|
if ( $nodes.length ) {
|
|
mw.hook( 'wikipage.diff' ).fire( $nodes.eq( 0 ) );
|
|
}
|
|
}, function ( xhr ) {
|
|
$( 'table.diff[data-mw="interface"]' ).removeClass( 'mw-revslider-diff-loading' );
|
|
if ( xhr.statusText !== 'abort' ) {
|
|
this.tryCount++;
|
|
mw.track( 'counter.MediaWiki.RevisionSlider.error.refresh' );
|
|
if ( retryAttempt <= retryLimit ) {
|
|
self.refresh( diff, oldid, sliderView, retryAttempt + 1 );
|
|
}
|
|
// TODO notify the user that we failed to update the diff?
|
|
// This could also attempt to reload the page with the correct diff loaded without ajax?
|
|
}
|
|
} );
|
|
},
|
|
|
|
/**
|
|
* Replaces the current state in the history stack
|
|
*
|
|
* @param {number} diff
|
|
* @param {number} oldid
|
|
* @param {SliderView} sliderView
|
|
*/
|
|
replaceState: function ( diff, oldid, sliderView ) {
|
|
this.history.replaceState(
|
|
this.getStateObject( diff, oldid, sliderView ),
|
|
$( document ).find( 'title' ).text(),
|
|
this.getStateUrl( diff, oldid )
|
|
);
|
|
},
|
|
|
|
/**
|
|
* Pushes the current state onto the history stack
|
|
*
|
|
* @param {number} diff
|
|
* @param {number} oldid
|
|
* @param {SliderView} sliderView
|
|
*/
|
|
pushState: function ( diff, oldid, sliderView ) {
|
|
this.history.pushState(
|
|
this.getStateObject( diff, oldid, sliderView ),
|
|
$( document ).find( 'title' ).text(),
|
|
this.getStateUrl( diff, oldid )
|
|
);
|
|
},
|
|
|
|
/**
|
|
* Gets a state object to be used with history.replaceState and history.pushState
|
|
*
|
|
* @private
|
|
* @param {number} diff
|
|
* @param {number} oldid
|
|
* @param {SliderView} sliderView
|
|
* @return {Object}
|
|
*/
|
|
getStateObject: function ( diff, oldid, sliderView ) {
|
|
return {
|
|
diff: diff,
|
|
oldid: oldid,
|
|
pointerOlderPos: sliderView.pointerOlder.getPosition(),
|
|
pointerNewerPos: sliderView.pointerNewer.getPosition(),
|
|
sliderPos: sliderView.slider.getOldestVisibleRevisionIndex()
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Gets a URL to be used with history.replaceState and history.pushState
|
|
*
|
|
* @private
|
|
* @param {number} diff
|
|
* @param {number} oldid
|
|
* @return {string}
|
|
*/
|
|
getStateUrl: function ( diff, oldid ) {
|
|
let url = mw.util.wikiScript( 'index' ) + '?diff=' + diff + '&oldid=' + oldid;
|
|
const params = this.getExtraDiffPageParams();
|
|
for ( const key in params ) {
|
|
url += '&' + key + '=' + params[ key ];
|
|
}
|
|
return url;
|
|
},
|
|
|
|
/**
|
|
* Returns an object containing all possible parameters that should be included in diff URLs
|
|
* when selected revisions change, e.g. uselang
|
|
*
|
|
* @private
|
|
* @return {Object}
|
|
*/
|
|
getExtraDiffPageParams: function () {
|
|
const params = {},
|
|
paramArray = location.search.slice( 1 ).split( '&' ).filter( ( elem ) => elem.indexOf( '=' ) > 0 && elem.match( /^(diff|oldid)=/ ) === null );
|
|
paramArray.forEach( ( elem ) => {
|
|
const pair = elem.split( '=', 2 );
|
|
params[ pair[ 0 ] ] = pair[ 1 ];
|
|
} );
|
|
return params;
|
|
},
|
|
|
|
/**
|
|
* @param {SliderView} sliderView
|
|
*/
|
|
initOnPopState: function ( sliderView ) {
|
|
window.addEventListener( 'popstate', ( event ) => {
|
|
if ( event.state === null ) {
|
|
return;
|
|
}
|
|
mw.track( 'counter.MediaWiki.RevisionSlider.event.historyChange' );
|
|
sliderView.slider.setFirstVisibleRevisionIndex( event.state.sliderPos );
|
|
sliderView.updatePointersAndDiffView(
|
|
event.state.pointerNewerPos,
|
|
event.state.pointerOlderPos,
|
|
false
|
|
);
|
|
} );
|
|
},
|
|
|
|
/**
|
|
* @param {SliderView} sliderView
|
|
*/
|
|
addHandlersToCoreLinks: function ( sliderView ) {
|
|
$( '#differences-nextlink' ).on( 'click', () => {
|
|
sliderView.showNextDiff();
|
|
return false;
|
|
} );
|
|
$( '#differences-prevlink' ).on( 'click', () => {
|
|
sliderView.showPrevDiff();
|
|
return false;
|
|
} );
|
|
}
|
|
} );
|
|
|
|
module.exports = DiffPage;
|