2016-05-10 12:42:05 +00:00
|
|
|
( function ( mw, $ ) {
|
2016-06-17 13:06:12 +00:00
|
|
|
/**
|
|
|
|
* Module handling the view logic of the RevisionSlider slider
|
|
|
|
*
|
|
|
|
* @param {Slider} slider
|
|
|
|
* @constructor
|
|
|
|
*/
|
2016-05-10 12:42:05 +00:00
|
|
|
var SliderView = function ( slider ) {
|
|
|
|
this.slider = slider;
|
2016-05-20 10:42:01 +00:00
|
|
|
this.diffPage = new mw.libs.revisionSlider.DiffPage( this.slider.getRevisions() );
|
2016-05-10 12:42:05 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
$.extend( SliderView.prototype, {
|
|
|
|
revisionWidth: 16,
|
|
|
|
|
2016-05-18 13:09:22 +00:00
|
|
|
containerMargin: 120,
|
2016-05-10 12:42:05 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @type {jQuery}
|
|
|
|
*/
|
|
|
|
$element: null,
|
|
|
|
|
2016-05-20 10:42:01 +00:00
|
|
|
/**
|
|
|
|
* @type {DiffPage}
|
|
|
|
*/
|
|
|
|
diffPage: null,
|
|
|
|
|
2016-05-10 12:42:05 +00:00
|
|
|
/**
|
|
|
|
* @type {Slider}
|
|
|
|
*/
|
|
|
|
slider: null,
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @type {Pointer}
|
|
|
|
*/
|
2016-05-21 00:10:08 +00:00
|
|
|
pointerOlder: null,
|
2016-05-10 12:42:05 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @type {Pointer}
|
|
|
|
*/
|
2016-05-21 00:10:08 +00:00
|
|
|
pointerNewer: null,
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @type {string}
|
|
|
|
*
|
|
|
|
* Value of scrollLeft property when in RTL mode varies between browser. This identifies
|
|
|
|
* an implementation used by user's browser:
|
|
|
|
* - 'default': 0 is the left-most position, values increase when scrolling right (same as scrolling from left to right in LTR mode)
|
|
|
|
* - 'negative': 0 is right-most position, values decrease when scrolling left (ie. all values except 0 are negative)
|
|
|
|
* - 'reverse': 0 is right-most position, values incrase when scrolling left
|
|
|
|
*/
|
|
|
|
rtlScrollLeftType: 'default',
|
2016-05-10 12:42:05 +00:00
|
|
|
|
|
|
|
render: function ( $container ) {
|
|
|
|
var containerWidth = this.calculateSliderContainerWidth(),
|
2016-05-21 00:10:08 +00:00
|
|
|
pointerContainerPosition = 55,
|
|
|
|
pointerContainerWidth = containerWidth + this.revisionWidth - 1,
|
|
|
|
pointerContainerStyle,
|
2016-05-12 11:34:16 +00:00
|
|
|
$revisions = this.slider.getRevisions().getView().render( this.revisionWidth ),
|
2016-05-21 00:10:08 +00:00
|
|
|
$slider = $( '<div>' )
|
|
|
|
.addClass( 'mw-revision-slider' )
|
|
|
|
.css( { direction: $container.css( 'direction' ) } ),
|
2016-05-10 12:42:05 +00:00
|
|
|
self = this;
|
|
|
|
|
2016-05-21 00:10:08 +00:00
|
|
|
if ( $slider.css( 'direction' ) === 'rtl' ) {
|
|
|
|
this.rtlScrollLeftType = this.determineRtlScrollType();
|
|
|
|
}
|
2016-05-10 12:42:05 +00:00
|
|
|
|
2016-05-21 00:10:08 +00:00
|
|
|
this.pointerOlder = new mw.libs.revisionSlider.Pointer( 'mw-revslider-pointer-older' );
|
|
|
|
this.pointerNewer = new mw.libs.revisionSlider.Pointer( 'mw-revslider-pointer-newer' );
|
|
|
|
|
|
|
|
pointerContainerStyle = { left: pointerContainerPosition + 'px', width: pointerContainerWidth + 'px' };
|
|
|
|
if ( $slider.css( 'direction' ) === 'rtl' ) {
|
|
|
|
// Due to properly limit dragging a pointer on the right side of the screen,
|
|
|
|
// there must some extra space added to the right of the revision bar container
|
|
|
|
// For this reason right position of the pointer container in the RTL mode is
|
|
|
|
// a bit moved off right compared to its left position in the LTR mode
|
|
|
|
pointerContainerPosition = pointerContainerPosition - this.revisionWidth + 1;
|
|
|
|
pointerContainerStyle = { right: pointerContainerPosition + 'px', width: pointerContainerWidth + 'px' };
|
|
|
|
}
|
2016-05-10 12:42:05 +00:00
|
|
|
$slider.css( {
|
|
|
|
width: ( containerWidth + this.containerMargin ) + 'px'
|
|
|
|
} )
|
2016-05-26 09:38:56 +00:00
|
|
|
.append(
|
2016-05-30 10:06:44 +00:00
|
|
|
$( '<a> ' )
|
2016-05-21 00:10:08 +00:00
|
|
|
.addClass( 'mw-arrow mw-arrow-backwards' )
|
2016-05-30 10:06:44 +00:00
|
|
|
.attr( 'data-dir', '-1' )
|
|
|
|
.tipsy( {
|
|
|
|
title: function () {
|
|
|
|
if ( $( this ).hasClass( 'mw-arrow-disabled' ) ) {
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
return mw.message( 'revisionslider-arrow-tooltip-older' ).text();
|
2016-05-27 14:14:16 +00:00
|
|
|
}
|
2016-05-30 10:06:44 +00:00
|
|
|
} ),
|
|
|
|
$( '<div>' )
|
|
|
|
.addClass( 'mw-revisions-container' )
|
|
|
|
.css( {
|
|
|
|
width: containerWidth + 'px'
|
|
|
|
} )
|
|
|
|
.append( $revisions ),
|
|
|
|
$( '<a> ' )
|
2016-05-21 00:10:08 +00:00
|
|
|
.addClass( 'mw-arrow mw-arrow-forwards' )
|
2016-05-30 10:06:44 +00:00
|
|
|
.attr( 'data-dir', '1' )
|
|
|
|
.tipsy( {
|
|
|
|
gravity: function () {
|
2016-05-21 00:10:08 +00:00
|
|
|
if ( $slider.css( 'direction' ) === 'ltr' ) {
|
|
|
|
return Math.abs( window.innerWidth - this.getBoundingClientRect().right ) > 90 ? 'n' : 'ne';
|
|
|
|
} else {
|
|
|
|
return this.getBoundingClientRect().left > 90 ? 'n' : 'nw';
|
|
|
|
}
|
2016-05-30 10:06:44 +00:00
|
|
|
},
|
|
|
|
title: function () {
|
|
|
|
if ( $( this ).hasClass( 'mw-arrow-disabled' ) ) {
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
return mw.message( 'revisionslider-arrow-tooltip-newer' ).text();
|
2016-05-27 14:14:16 +00:00
|
|
|
}
|
2016-05-30 10:06:44 +00:00
|
|
|
} ),
|
|
|
|
$( '<div>' ).css( { clear: 'both' } ),
|
|
|
|
$( '<div>' )
|
|
|
|
.addClass( 'mw-pointer-container' )
|
2016-05-21 00:10:08 +00:00
|
|
|
.css( pointerContainerStyle )
|
|
|
|
.append( this.pointerOlder.getView().render(), this.pointerNewer.getView().render() )
|
2016-05-12 11:34:16 +00:00
|
|
|
);
|
2016-05-10 12:42:05 +00:00
|
|
|
|
2016-05-21 00:10:08 +00:00
|
|
|
if ( $slider.css( 'direction' ) === 'ltr' ) {
|
|
|
|
$slider.find( '.mw-arrow-backwards' ).addClass( 'mw-arrow-left' );
|
|
|
|
$slider.find( '.mw-arrow-forwards' ).addClass( 'mw-arrow-right' );
|
|
|
|
} else {
|
|
|
|
$slider.find( '.mw-arrow-backwards' ).addClass( 'mw-arrow-right' );
|
|
|
|
$slider.find( '.mw-arrow-forwards' ).addClass( 'mw-arrow-left' );
|
|
|
|
}
|
|
|
|
|
2016-05-30 10:06:44 +00:00
|
|
|
$slider.find( '.mw-arrow' ).click( function () {
|
2016-05-27 14:14:16 +00:00
|
|
|
var $arrow = $( this );
|
2016-05-30 10:06:44 +00:00
|
|
|
if ( $arrow.hasClass( 'mw-arrow-disabled' ) ) {
|
2016-05-27 14:14:16 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
mw.track( 'counter.MediaWiki.RevisionSlider.event.arrowClick' );
|
|
|
|
self.slide( $arrow.data( 'dir' ) );
|
|
|
|
} )
|
|
|
|
.mouseenter( function () {
|
|
|
|
var $arrow = $( this );
|
2016-05-30 10:06:44 +00:00
|
|
|
if ( $arrow.hasClass( 'mw-arrow-disabled' ) ) {
|
2016-05-27 14:14:16 +00:00
|
|
|
return;
|
|
|
|
}
|
2016-05-30 10:06:44 +00:00
|
|
|
$arrow.removeClass( 'mw-arrow-enabled' ).addClass( 'mw-arrow-hovered' );
|
2016-05-27 14:14:16 +00:00
|
|
|
} )
|
|
|
|
.mouseleave( function () {
|
|
|
|
var $arrow = $( this );
|
2016-05-30 10:06:44 +00:00
|
|
|
if ( $arrow.hasClass( 'mw-arrow-disabled' ) ) {
|
2016-05-27 14:14:16 +00:00
|
|
|
return;
|
|
|
|
}
|
2016-05-30 10:06:44 +00:00
|
|
|
$arrow.removeClass( 'mw-arrow-hovered' ).addClass( 'mw-arrow-enabled' );
|
2016-05-27 14:14:16 +00:00
|
|
|
} )
|
|
|
|
.mousedown( function ( event ) {
|
|
|
|
var $arrow = $( this );
|
2016-05-30 10:06:44 +00:00
|
|
|
if ( $arrow.hasClass( 'mw-arrow-disabled' ) || event.which !== 1 ) {
|
2016-05-27 14:14:16 +00:00
|
|
|
return;
|
|
|
|
}
|
2016-05-30 10:06:44 +00:00
|
|
|
$arrow.addClass( 'mw-arrow-active' );
|
2016-05-27 14:14:16 +00:00
|
|
|
} )
|
|
|
|
.mouseup( function ( event ) {
|
|
|
|
var $arrow = $( this );
|
2016-05-30 10:06:44 +00:00
|
|
|
if ( $arrow.hasClass( 'mw-arrow-disabled' ) || event.which !== 1 ) {
|
2016-05-27 14:14:16 +00:00
|
|
|
return;
|
|
|
|
}
|
2016-05-30 10:06:44 +00:00
|
|
|
$arrow.removeClass( 'mw-arrow-active' );
|
2016-05-27 14:14:16 +00:00
|
|
|
} );
|
2016-05-10 12:42:05 +00:00
|
|
|
|
2016-05-30 10:06:44 +00:00
|
|
|
$slider.find( '.mw-pointer' ).draggable( {
|
2016-05-10 12:42:05 +00:00
|
|
|
axis: 'x',
|
2016-05-26 09:50:51 +00:00
|
|
|
grid: [ this.revisionWidth, null ],
|
2016-05-30 10:06:44 +00:00
|
|
|
containment: '.mw-pointer-container',
|
2016-06-03 08:55:17 +00:00
|
|
|
start: function () {
|
|
|
|
$( '.mw-revision-wrapper' ).addClass( 'mw-pointer-cursor' );
|
|
|
|
},
|
2016-05-10 12:42:05 +00:00
|
|
|
stop: function () {
|
|
|
|
var $p = $( this ),
|
|
|
|
pointer = self.whichPointer( $p ),
|
2016-05-11 10:01:44 +00:00
|
|
|
pos = parseInt( $p.css( 'left' ), 10 ),
|
2016-05-21 00:10:08 +00:00
|
|
|
adjustedPos = $p.offsetParent().css( 'direction' ) === 'rtl' ? pointer.getView().getAdjustedLeftPositionWhenRtl( pos ) : pos,
|
|
|
|
relativeIndex = Math.ceil( ( adjustedPos + self.revisionWidth / 2 ) / self.revisionWidth ),
|
2016-05-11 10:01:44 +00:00
|
|
|
revId1, revId2;
|
2016-05-11 09:04:13 +00:00
|
|
|
mw.track( 'counter.MediaWiki.RevisionSlider.event.pointerMove' );
|
2016-05-12 13:52:54 +00:00
|
|
|
pointer.setPosition( self.slider.getFirstVisibleRevisionIndex() + relativeIndex );
|
2016-05-17 12:29:08 +00:00
|
|
|
self.resetPointerStylesBasedOnPosition();
|
2016-05-19 16:39:58 +00:00
|
|
|
self.resetRevisionStylesBasedOnPointerPosition( $revisions );
|
2016-05-11 10:01:44 +00:00
|
|
|
|
2016-05-21 00:10:08 +00:00
|
|
|
revId1 = self.getRevElementAtPosition( $revisions, self.pointerOlder.getPosition() ).data( 'revid' );
|
|
|
|
revId2 = self.getRevElementAtPosition( $revisions, self.pointerNewer.getPosition() ).data( 'revid' );
|
2016-05-11 10:01:44 +00:00
|
|
|
|
2016-05-20 10:42:01 +00:00
|
|
|
self.diffPage.refresh( revId1, revId2 );
|
|
|
|
self.diffPage.pushState( revId1, revId2, self );
|
2016-06-03 08:55:17 +00:00
|
|
|
|
|
|
|
$( '.mw-revision-wrapper' ).removeClass( 'mw-pointer-cursor' );
|
2016-05-13 09:43:01 +00:00
|
|
|
},
|
2016-05-26 09:50:51 +00:00
|
|
|
drag: function ( event, ui ) {
|
|
|
|
var newestVisibleRevisionLeftPos = containerWidth - self.revisionWidth;
|
|
|
|
ui.position.left = Math.min( ui.position.left, newestVisibleRevisionLeftPos );
|
2016-05-21 00:10:08 +00:00
|
|
|
if ( $( this ).css( 'direction' ) === 'ltr' ) {
|
|
|
|
self.resetPointerColorsBasedOnValues(
|
|
|
|
self.pointerOlder.getView().getElement().offset().left,
|
|
|
|
self.pointerNewer.getView().getElement().offset().left
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
self.resetPointerColorsBasedOnValues(
|
|
|
|
self.pointerNewer.getView().getElement().offset().left,
|
|
|
|
self.pointerOlder.getView().getElement().offset().left
|
|
|
|
);
|
|
|
|
}
|
2016-05-20 10:42:01 +00:00
|
|
|
}
|
|
|
|
} );
|
|
|
|
|
2016-05-30 10:06:44 +00:00
|
|
|
$slider.find( '.mw-revision-wrapper' ).click( function ( e ) {
|
2016-05-20 10:42:01 +00:00
|
|
|
var $revWrap = $( this ),
|
2016-05-30 10:06:44 +00:00
|
|
|
$clickedRev = $revWrap.find( '.mw-revision' ),
|
2016-05-20 10:42:01 +00:00
|
|
|
hasClickedTop = e.pageY - $revWrap.offset().top < $revWrap.height() / 2,
|
|
|
|
pOld = self.getOldRevPointer(),
|
|
|
|
pNew = self.getNewRevPointer();
|
|
|
|
|
|
|
|
if ( hasClickedTop ) {
|
|
|
|
self.refreshRevisions(
|
|
|
|
self.getRevElementAtPosition( $revisions, pOld.getPosition() ).data( 'revid' ),
|
|
|
|
$clickedRev.data( 'revid' )
|
|
|
|
);
|
|
|
|
pNew.setPosition( $clickedRev.data( 'pos' ) );
|
|
|
|
} else {
|
|
|
|
self.refreshRevisions(
|
|
|
|
$clickedRev.data( 'revid' ),
|
|
|
|
self.getRevElementAtPosition( $revisions, pNew.getPosition() ).data( 'revid' )
|
|
|
|
);
|
|
|
|
pOld.setPosition( $clickedRev.data( 'pos' ) );
|
2016-05-10 12:42:05 +00:00
|
|
|
}
|
2016-05-20 10:42:01 +00:00
|
|
|
|
2016-05-21 00:10:08 +00:00
|
|
|
self.resetPointerColorsBasedOnValues( self.pointerOlder.getPosition(), self.pointerNewer.getPosition() );
|
2016-05-20 10:42:01 +00:00
|
|
|
self.resetRevisionStylesBasedOnPointerPosition( $revisions );
|
|
|
|
self.alignPointers();
|
2016-05-10 12:42:05 +00:00
|
|
|
} );
|
|
|
|
|
2016-05-30 10:06:44 +00:00
|
|
|
this.slider.setRevisionsPerWindow( $slider.find( '.mw-revisions-container' ).width() / this.revisionWidth );
|
2016-05-10 14:01:39 +00:00
|
|
|
|
2016-05-20 10:42:01 +00:00
|
|
|
this.initializePointers( this.getOldRevElement( $revisions ), this.getNewRevElement( $revisions ) );
|
2016-05-19 16:39:58 +00:00
|
|
|
this.resetRevisionStylesBasedOnPointerPosition( $revisions );
|
2016-05-12 11:29:45 +00:00
|
|
|
|
|
|
|
this.$element = $slider;
|
|
|
|
$container.html( $slider );
|
|
|
|
|
2016-05-21 00:10:08 +00:00
|
|
|
this.slide( Math.floor( ( this.pointerNewer.getPosition() - 1 ) / this.slider.getRevisionsPerWindow() ), 0 );
|
2016-05-20 10:42:01 +00:00
|
|
|
this.diffPage.pushState( mw.config.values.extRevisionSliderOldRev, mw.config.values.extRevisionSliderNewRev, this );
|
|
|
|
this.diffPage.initOnPopState( this );
|
|
|
|
},
|
|
|
|
|
2016-06-17 13:06:12 +00:00
|
|
|
/**
|
|
|
|
* Returns the pointer that points to the older revision
|
|
|
|
*
|
|
|
|
* @return {Pointer}
|
|
|
|
*/
|
2016-05-20 10:42:01 +00:00
|
|
|
getOldRevPointer: function () {
|
2016-05-21 00:10:08 +00:00
|
|
|
return this.pointerOlder.getPosition() <= this.pointerNewer.getPosition() ? this.pointerOlder : this.pointerNewer;
|
2016-05-20 10:42:01 +00:00
|
|
|
},
|
|
|
|
|
2016-06-17 13:06:12 +00:00
|
|
|
/**
|
|
|
|
* Returns the pointer that points to the newer revision
|
|
|
|
*
|
|
|
|
* @return {Pointer}
|
|
|
|
*/
|
2016-05-20 10:42:01 +00:00
|
|
|
getNewRevPointer: function () {
|
2016-05-21 00:10:08 +00:00
|
|
|
return this.pointerOlder.getPosition() > this.pointerNewer.getPosition() ? this.pointerOlder : this.pointerNewer;
|
2016-05-20 10:42:01 +00:00
|
|
|
},
|
|
|
|
|
2016-06-17 13:06:12 +00:00
|
|
|
/**
|
|
|
|
* Refreshes the diff page to show the diff for the specified revisions
|
|
|
|
*
|
|
|
|
* @param {number} revId1
|
|
|
|
* @param {number} revId2
|
|
|
|
*/
|
2016-05-20 10:42:01 +00:00
|
|
|
refreshRevisions: function ( revId1, revId2 ) {
|
|
|
|
var oldRev = Math.min( revId1, revId2 ),
|
|
|
|
newRev = Math.max( revId1, revId2 );
|
|
|
|
this.diffPage.refresh( oldRev, newRev );
|
|
|
|
this.diffPage.pushState( oldRev, newRev, this );
|
|
|
|
},
|
|
|
|
|
2016-06-17 13:06:12 +00:00
|
|
|
/**
|
|
|
|
* @param {jQuery} $revs
|
|
|
|
* @param {number} pos
|
|
|
|
* @return {jQuery}
|
|
|
|
*/
|
2016-05-20 10:42:01 +00:00
|
|
|
getRevElementAtPosition: function ( $revs, pos ) {
|
2016-05-30 10:06:44 +00:00
|
|
|
return $revs.find( 'div.mw-revision[data-pos="' + pos + '"]' );
|
2016-05-20 10:42:01 +00:00
|
|
|
},
|
|
|
|
|
2016-06-17 13:06:12 +00:00
|
|
|
/**
|
|
|
|
* Gets the jQuery element of the older selected revision
|
|
|
|
*
|
|
|
|
* @param {jQuery} $revs
|
|
|
|
* @return {jQuery}
|
|
|
|
*/
|
2016-05-20 10:42:01 +00:00
|
|
|
getOldRevElement: function ( $revs ) {
|
2016-05-30 10:06:44 +00:00
|
|
|
return $revs.find( 'div.mw-revision[data-revid="' + mw.config.values.extRevisionSliderOldRev + '"]' );
|
2016-05-20 10:42:01 +00:00
|
|
|
},
|
|
|
|
|
2016-06-17 13:06:12 +00:00
|
|
|
/**
|
|
|
|
* Gets the jQuery element of the newer selected revision
|
|
|
|
*
|
|
|
|
* @param {jQuery} $revs
|
|
|
|
* @return {jQuery}
|
|
|
|
*/
|
2016-05-20 10:42:01 +00:00
|
|
|
getNewRevElement: function ( $revs ) {
|
2016-05-30 10:06:44 +00:00
|
|
|
return $revs.find( 'div.mw-revision[data-revid="' + mw.config.values.extRevisionSliderNewRev + '"]' );
|
2016-05-10 12:42:05 +00:00
|
|
|
},
|
|
|
|
|
2016-06-17 13:06:12 +00:00
|
|
|
/**
|
|
|
|
* Initializes the Pointer objects based on the selected revisions
|
|
|
|
*
|
|
|
|
* @param {jQuery} $oldRevElement
|
|
|
|
* @param {jQuery} $newRevElement
|
|
|
|
*/
|
2016-05-20 10:42:01 +00:00
|
|
|
initializePointers: function ( $oldRevElement, $newRevElement ) {
|
|
|
|
if ( $oldRevElement.length === 0 || $newRevElement.length === 0 ) {
|
2016-05-12 11:29:45 +00:00
|
|
|
// Note: this is currently caught in init.js
|
|
|
|
throw 'RS-rev-out-of-range';
|
|
|
|
}
|
2016-05-21 00:10:08 +00:00
|
|
|
this.pointerOlder.setPosition( $oldRevElement.data( 'pos' ) );
|
|
|
|
this.pointerNewer.setPosition( $newRevElement.data( 'pos' ) );
|
2016-05-17 12:29:08 +00:00
|
|
|
this.resetPointerStylesBasedOnPosition();
|
2016-05-13 10:29:05 +00:00
|
|
|
},
|
|
|
|
|
2016-06-17 13:06:12 +00:00
|
|
|
/**
|
|
|
|
* Adjusts the colors of the pointers without changing the upper/lower property based on values `p1` and `p2`.
|
|
|
|
* Used e.g. when pointers get dragged past one another.
|
|
|
|
*
|
|
|
|
* @param {number} p1
|
|
|
|
* @param {number} p2
|
|
|
|
*/
|
2016-05-20 10:42:01 +00:00
|
|
|
resetPointerColorsBasedOnValues: function ( p1, p2 ) {
|
|
|
|
if ( p1 > p2 ) {
|
2016-05-21 00:10:08 +00:00
|
|
|
this.pointerOlder.getView().getElement().removeClass( 'mw-oldid-pointer' ).addClass( 'mw-newid-pointer' );
|
|
|
|
this.pointerNewer.getView().getElement().removeClass( 'mw-newid-pointer' ).addClass( 'mw-oldid-pointer' );
|
2016-05-13 10:29:05 +00:00
|
|
|
} else {
|
2016-05-21 00:10:08 +00:00
|
|
|
this.pointerOlder.getView().getElement().removeClass( 'mw-newid-pointer' ).addClass( 'mw-oldid-pointer' );
|
|
|
|
this.pointerNewer.getView().getElement().removeClass( 'mw-oldid-pointer' ).addClass( 'mw-newid-pointer' );
|
2016-05-13 10:29:05 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2016-06-17 13:06:12 +00:00
|
|
|
/**
|
|
|
|
* Resets the pointer styles (upper/lower, blue/yellow) based on their position.
|
|
|
|
*/
|
2016-05-17 12:29:08 +00:00
|
|
|
resetPointerStylesBasedOnPosition: function () {
|
2016-05-30 10:06:44 +00:00
|
|
|
this.getNewRevPointer().getView().getElement().removeClass( 'mw-oldid-pointer' ).addClass( 'mw-newid-pointer' )
|
|
|
|
.removeClass( 'mw-lower-pointer' ).addClass( 'mw-upper-pointer' );
|
|
|
|
this.getOldRevPointer().getView().getElement().removeClass( 'mw-newid-pointer' ).addClass( 'mw-oldid-pointer' )
|
|
|
|
.removeClass( 'mw-upper-pointer' ).addClass( 'mw-lower-pointer' );
|
2016-05-10 12:42:05 +00:00
|
|
|
},
|
|
|
|
|
2016-06-17 13:06:12 +00:00
|
|
|
/**
|
|
|
|
* Highlights revisions between the pointers
|
|
|
|
*
|
|
|
|
* @param {jQuery} $revisions
|
|
|
|
*/
|
2016-05-19 16:39:58 +00:00
|
|
|
resetRevisionStylesBasedOnPointerPosition: function ( $revisions ) {
|
2016-05-20 10:42:01 +00:00
|
|
|
var olderRevPosition = this.getOldRevPointer().getPosition(),
|
|
|
|
newerRevPosition = this.getNewRevPointer().getPosition(),
|
2016-05-19 16:39:58 +00:00
|
|
|
positionIndex = olderRevPosition + 1;
|
2016-05-20 10:42:01 +00:00
|
|
|
|
2016-05-30 10:06:44 +00:00
|
|
|
$revisions.find( 'div.mw-revision' )
|
|
|
|
.removeClass( 'mw-revision-intermediate mw-revision-old mw-revision-new' );
|
2016-05-20 10:42:01 +00:00
|
|
|
|
2016-05-30 10:06:44 +00:00
|
|
|
this.getRevElementAtPosition( $revisions, olderRevPosition ).addClass( 'mw-revision-old' );
|
|
|
|
this.getRevElementAtPosition( $revisions, newerRevPosition ).addClass( 'mw-revision-new' );
|
2016-05-19 16:39:58 +00:00
|
|
|
while ( positionIndex < newerRevPosition ) {
|
2016-05-30 10:06:44 +00:00
|
|
|
this.getRevElementAtPosition( $revisions, positionIndex ).addClass( 'mw-revision-intermediate' );
|
2016-05-19 16:39:58 +00:00
|
|
|
positionIndex++;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2016-06-17 13:06:12 +00:00
|
|
|
/**
|
|
|
|
* Determines how many revisions fit onto the screen at once depending on the browser window width
|
|
|
|
*
|
|
|
|
* @return {number}
|
|
|
|
*/
|
2016-05-10 12:42:05 +00:00
|
|
|
calculateRevisionsPerWindow: function () {
|
|
|
|
return Math.floor( ( $( '#mw-content-text' ).width() - this.containerMargin ) / this.revisionWidth );
|
|
|
|
},
|
|
|
|
|
2016-06-17 13:06:12 +00:00
|
|
|
/**
|
|
|
|
* @return {number}
|
|
|
|
*/
|
2016-05-10 12:42:05 +00:00
|
|
|
calculateSliderContainerWidth: function () {
|
|
|
|
return Math.min( this.slider.getRevisions().getLength(), this.calculateRevisionsPerWindow() ) * this.revisionWidth;
|
|
|
|
},
|
|
|
|
|
2016-05-10 19:33:40 +00:00
|
|
|
slide: function ( direction, duration ) {
|
2016-05-21 00:10:08 +00:00
|
|
|
var animateObj,
|
|
|
|
$animatedElement = this.$element.find( '.mw-revisions-container' ),
|
|
|
|
self = this;
|
2016-05-10 20:04:21 +00:00
|
|
|
|
2016-05-10 12:42:05 +00:00
|
|
|
this.slider.slide( direction );
|
2016-05-21 00:10:08 +00:00
|
|
|
this.pointerOlder.getView().getElement().draggable( 'disable' );
|
|
|
|
this.pointerNewer.getView().getElement().draggable( 'disable' );
|
2016-05-10 20:04:21 +00:00
|
|
|
|
2016-05-10 20:47:37 +00:00
|
|
|
if ( this.slider.isAtStart() ) {
|
2016-05-21 00:10:08 +00:00
|
|
|
$( '.mw-arrow-backwards' ).removeClass( 'mw-arrow-enabled mw-arrow-hovered' ).addClass( 'mw-arrow-disabled' );
|
2016-05-10 20:47:37 +00:00
|
|
|
} else {
|
2016-05-21 00:10:08 +00:00
|
|
|
$( '.mw-arrow-backwards' ).removeClass( 'mw-arrow-disabled' ).addClass( 'mw-arrow-enabled' );
|
2016-05-10 20:47:37 +00:00
|
|
|
}
|
|
|
|
if ( this.slider.isAtEnd() ) {
|
2016-05-21 00:10:08 +00:00
|
|
|
$( '.mw-arrow-forwards' ).removeClass( 'mw-arrow-enabled mw-arrow-hovered' ).addClass( 'mw-arrow-disabled' );
|
2016-05-10 20:47:37 +00:00
|
|
|
} else {
|
2016-05-21 00:10:08 +00:00
|
|
|
$( '.mw-arrow-forwards' ).removeClass( 'mw-arrow-disabled' ).addClass( 'mw-arrow-enabled' );
|
2016-05-10 20:47:37 +00:00
|
|
|
}
|
|
|
|
|
2016-05-21 00:10:08 +00:00
|
|
|
animateObj = { scrollLeft: this.slider.getFirstVisibleRevisionIndex() * this.revisionWidth };
|
|
|
|
if ( this.$element.css( 'direction' ) === 'rtl' ) {
|
|
|
|
animateObj.scrollLeft = this.getRtlScrollLeft( $animatedElement, animateObj.scrollLeft );
|
|
|
|
}
|
|
|
|
|
|
|
|
$animatedElement.animate(
|
|
|
|
animateObj,
|
2016-05-10 20:04:21 +00:00
|
|
|
duration,
|
|
|
|
null,
|
|
|
|
function () {
|
2016-05-21 00:10:08 +00:00
|
|
|
self.pointerOlder.getView().getElement().draggable( 'enable' );
|
|
|
|
self.pointerNewer.getView().getElement().draggable( 'enable' );
|
2016-05-10 20:04:21 +00:00
|
|
|
}
|
|
|
|
);
|
2016-05-10 12:42:05 +00:00
|
|
|
|
2016-05-20 10:42:01 +00:00
|
|
|
this.alignPointers( duration );
|
|
|
|
},
|
|
|
|
|
2016-06-17 13:06:12 +00:00
|
|
|
/**
|
|
|
|
* Based on jQuery RTL Scroll Type Detector plugin by othree: https://github.com/othree/jquery.rtl-scroll-type
|
|
|
|
*
|
|
|
|
* @return {string} - 'default', 'negative' or 'reverse'
|
|
|
|
*/
|
2016-05-21 00:10:08 +00:00
|
|
|
determineRtlScrollType: function () {
|
|
|
|
var $dummy = $( '<div>' )
|
|
|
|
.css( {
|
|
|
|
dir: 'rtl',
|
|
|
|
width: '1px',
|
|
|
|
height: '1px',
|
|
|
|
position: 'absolute',
|
|
|
|
top: '-1000px',
|
|
|
|
overflow: 'scroll'
|
|
|
|
} )
|
|
|
|
.text( 'A' )
|
|
|
|
.appendTo( 'body' )[ 0 ];
|
|
|
|
if ( $dummy.scrollLeft > 0 ) {
|
|
|
|
return 'default';
|
|
|
|
} else {
|
|
|
|
$dummy.scrollLeft = 1;
|
|
|
|
if ( $dummy.scrollLeft === 0 ) {
|
|
|
|
return 'negative';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 'reverse';
|
|
|
|
},
|
|
|
|
|
2016-06-17 13:06:12 +00:00
|
|
|
/**
|
|
|
|
* @param {jQuery} $element
|
|
|
|
* @param {number} scrollLeft
|
|
|
|
* @return {number}
|
|
|
|
*/
|
2016-05-21 00:10:08 +00:00
|
|
|
getRtlScrollLeft: function ( $element, scrollLeft ) {
|
|
|
|
if ( this.rtlScrollLeftType === 'reverse' ) {
|
|
|
|
return scrollLeft;
|
|
|
|
}
|
|
|
|
if ( this.rtlScrollLeftType === 'negative' ) {
|
|
|
|
return -scrollLeft;
|
|
|
|
}
|
|
|
|
return $element.prop( 'scrollWidth' ) - $element.width() - scrollLeft;
|
|
|
|
},
|
|
|
|
|
2016-05-20 10:42:01 +00:00
|
|
|
alignPointers: function ( duration ) {
|
|
|
|
var self = this;
|
|
|
|
|
2016-05-21 00:10:08 +00:00
|
|
|
this.pointerOlder.getView()
|
2016-05-20 10:42:01 +00:00
|
|
|
.slideToSideOrPosition( this.slider, duration )
|
|
|
|
.promise().done( function () {
|
|
|
|
self.resetPointerStylesBasedOnPosition();
|
|
|
|
} );
|
2016-05-21 00:10:08 +00:00
|
|
|
this.pointerNewer.getView()
|
2016-05-20 10:42:01 +00:00
|
|
|
.slideToSideOrPosition( this.slider, duration )
|
|
|
|
.promise().done( function () {
|
|
|
|
self.resetPointerStylesBasedOnPosition();
|
|
|
|
} );
|
2016-05-10 12:42:05 +00:00
|
|
|
},
|
|
|
|
|
2016-06-17 13:06:12 +00:00
|
|
|
/**
|
|
|
|
* Returns the Pointer object that belongs to the passed element
|
|
|
|
*
|
|
|
|
* @param {jQuery} $e
|
|
|
|
* @return {Pointer}
|
|
|
|
*/
|
2016-05-10 12:42:05 +00:00
|
|
|
whichPointer: function ( $e ) {
|
2016-05-21 00:10:08 +00:00
|
|
|
return $e.attr( 'id' ) === 'mw-revslider-pointer-older' ? this.pointerOlder : this.pointerNewer;
|
2016-05-10 12:42:05 +00:00
|
|
|
}
|
|
|
|
} );
|
|
|
|
|
|
|
|
mw.libs.revisionSlider = mw.libs.revisionSlider || {};
|
|
|
|
mw.libs.revisionSlider.SliderView = SliderView;
|
|
|
|
}( mediaWiki, jQuery ) );
|