mediawiki-extensions-Revisi.../modules/ext.RevisionSlider.DiffPage.js
Ed Sanders e9eabd00ef Don't replace all tabs on update
Tabs are hooked up to JS events which will break
if they are replaced, just switch out the oldid
in the edit link as that is all that changes.

Change-Id: Iea073f8d435a511ba91cdc0c7bdb9e8f1ec1d4ac
2016-11-23 13:25:32 +00:00

225 lines
7.2 KiB
JavaScript

( function ( mw, $ ) {
/* global wikEd */
/**
* Module handling diff page reloading and the RevisionSlider browser history
*
* @constructor
*/
var DiffPage = function () {
this.lastRequest = null;
};
$.extend( DiffPage.prototype, {
/**
* Refreshes the diff view with two given revision IDs
*
* @param {number} revId1
* @param {number} revId2
* @param {number} [retryAttempt=0]
*/
refresh: function ( revId1, revId2, retryAttempt ) {
var self = this,
retryLimit = 2,
diff = Math.max( revId1, revId2 ),
oldid = Math.min( revId1, revId2 ),
data = {
diff: diff,
oldid: oldid
},
params = this.getExtraDiffPageParams();
retryAttempt = retryAttempt || 0;
if ( Object.keys( params ).length > 0 ) {
$.extend( 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( function ( data ) {
var $data,
$container = $( '.mw-revslider-container' ),
$contentText = $( '#mw-content-text' ),
$sidePanel = $( '#mw-panel' ),
$catLinks = $( '#catlinks' ),
$printFooter = $( '.printfooter' ),
scrollLeft = $container.find( '.mw-revslider-revisions-container' ).scrollLeft();
// Add our current rendered slider into the newly loaded container
$data = $( data );
$data.find( '.mw-revslider-container' ).replaceWith( $container );
// Replace the elements on the page with the newly loaded elements
$catLinks.replaceWith( $data.find( '#catlinks' ) );
$sidePanel.replaceWith( $data.find( '#mw-panel' ) );
$printFooter.replaceWith( $data.find( '.printfooter' ) );
$contentText.replaceWith( $data.find( '#mw-content-text' ) );
// Update edit link
$( '#ca-edit a, #ca-ve-edit a' ).each( function () {
var uri = new mw.Uri( $( this ).attr( 'href' ) );
uri.query.oldid = diff;
$( this ).attr( 'href', uri.toString() );
} );
$( '.mw-revslider-revisions-container' ).scrollLeft( scrollLeft );
mw.hook( 'wikipage.content' ).fire( $contentText );
mw.hook( 'wikipage.diff' ).fire( $contentText.find( 'table.diff' ) );
// In order to correctly interact with third-party code (extensions and gadgets)
// Revision slider should trigger some general (core) hook that other parties listen too
// Following wikEdDiff.js-specific code is deprecated and will be removed in the future.
// WikEdDiff should be updated to use a hook.
if ( self.wikEdDiffDetected() ) {
mw.log( 'You are running WikEdDiff & your copy of the code may need to be updated to work with the RevisionSlider.' );
mw.log( 'Please see: https://phabricator.wikimedia.org/T143199#2631963' );
mw.log( 'If WikEdDiff is still working while using the RevisonSlider then the code change has already been done.' );
}
}, 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( revId1, revId2, 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?
}
} );
},
wikEdDiffDetected: function () {
return typeof wikEd !== 'undefined' && $( 'meta[name=wikEdDiffSetupFlag]' ).length !== 0;
},
/**
* Replaces the current state in the history stack
*
* @param {number} revId1
* @param {number} revId2
* @param {SliderView} sliderView
*/
replaceState: function ( revId1, revId2, sliderView ) {
// IE8 and IE9 do not have history.pushState()
if ( typeof history.replaceState === 'function' ) {
history.replaceState(
this.getStateObject( revId1, revId2, sliderView ),
$( document ).find( 'title' ).text(),
this.getStateUrl( revId1, revId2 )
);
}
},
/**
* Pushes the current state onto the history stack
*
* @param {number} revId1
* @param {number} revId2
* @param {SliderView} sliderView
*/
pushState: function ( revId1, revId2, sliderView ) {
// IE8 and IE9 do not have history.pushState()
if ( typeof history.pushState === 'function' ) {
history.pushState(
this.getStateObject( revId1, revId2, sliderView ),
$( document ).find( 'title' ).text(),
this.getStateUrl( revId1, revId2 )
);
}
},
/**
* Gets a state object to be used with history.replaceState and history.pushState
*
* @param {number} revId1
* @param {number} revId2
* @param {SliderView} sliderView
* @return {Object}
*/
getStateObject: function ( revId1, revId2, sliderView ) {
return {
revid1: revId1,
revid2: revId2,
pointerOlderPos: sliderView.pointerOlder.getPosition(),
pointerNewerPos: sliderView.pointerNewer.getPosition(),
sliderPos: sliderView.slider.getFirstVisibleRevisionIndex()
};
},
/**
* Gets a URL to be used with history.replaceState and history.pushState
*
* @param {number} revId1
* @param {number} revId2
* @return {string}
*/
getStateUrl: function ( revId1, revId2 ) {
var url = mw.util.wikiScript( 'index' ) + '?diff=' + Math.max( revId1, revId2 ) + '&oldid=' + Math.min( revId1, revId2 ),
params = this.getExtraDiffPageParams();
if ( Object.keys( params ).length > 0 ) {
Object.keys( params ).forEach( function ( key ) {
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
*
* @return {Object}
*/
getExtraDiffPageParams: function () {
var params = {},
paramArray = location.search.substr( 1 ).split( '&' ).filter( function ( elem ) {
return elem.indexOf( '=' ) > 0 && elem.match( /^(diff|oldid)=/ ) === null;
} );
paramArray.forEach( function ( elem ) {
var pair = elem.split( '=', 2 );
params[ pair[ 0 ] ] = pair[ 1 ];
} );
return params;
},
/**
* @param {SliderView} sliderView
*/
initOnPopState: function ( sliderView ) {
var self = this;
window.addEventListener( 'popstate', function ( event ) {
if ( event.state === null ) {
return;
}
mw.track( 'counter.MediaWiki.RevisionSlider.event.historyChange' );
sliderView.pointerOlder.setPosition( event.state.pointerOlderPos );
sliderView.pointerNewer.setPosition( event.state.pointerNewerPos );
sliderView.slider.setFirstVisibleRevisionIndex( event.state.sliderPos );
sliderView.slide( 0 );
sliderView.resetPointerStylesBasedOnPosition();
sliderView.resetRevisionStylesBasedOnPointerPosition(
sliderView.$element.find( 'div.mw-revslider-revisions' )
);
sliderView.updatePointerPositionAttributes();
self.refresh( event.state.revid1, event.state.revid2 );
} );
}
} );
mw.libs.revisionSlider = mw.libs.revisionSlider || {};
mw.libs.revisionSlider.DiffPage = DiffPage;
}( mediaWiki, jQuery ) );