' ).css( { clear: 'both' } ),
$( '
' )
.addClass( 'mw-pointer-container' )
.css( { width: containerWidth + this.revisionWidth - 1 + 'px' } )
.append( this.pointerOne.getView().render(), this.pointerTwo.getView().render() )
);
$slider.find( '.mw-arrow' ).click( function () {
var $arrow = $( this );
if ( $arrow.hasClass( 'mw-arrow-disabled' ) ) {
return;
}
mw.track( 'counter.MediaWiki.RevisionSlider.event.arrowClick' );
self.slide( $arrow.data( 'dir' ) );
} )
.mouseenter( function () {
var $arrow = $( this );
if ( $arrow.hasClass( 'mw-arrow-disabled' ) ) {
return;
}
$arrow.removeClass( 'mw-arrow-enabled' ).addClass( 'mw-arrow-hovered' );
} )
.mouseleave( function () {
var $arrow = $( this );
if ( $arrow.hasClass( 'mw-arrow-disabled' ) ) {
return;
}
$arrow.removeClass( 'mw-arrow-hovered' ).addClass( 'mw-arrow-enabled' );
} )
.mousedown( function ( event ) {
var $arrow = $( this );
if ( $arrow.hasClass( 'mw-arrow-disabled' ) || event.which !== 1 ) {
return;
}
$arrow.addClass( 'mw-arrow-active' );
} )
.mouseup( function ( event ) {
var $arrow = $( this );
if ( $arrow.hasClass( 'mw-arrow-disabled' ) || event.which !== 1 ) {
return;
}
$arrow.removeClass( 'mw-arrow-active' );
} );
$slider.find( '.mw-pointer' ).draggable( {
axis: 'x',
grid: [ this.revisionWidth, null ],
containment: '.mw-pointer-container',
stop: function () {
var $p = $( this ),
pointer = self.whichPointer( $p ),
pos = parseInt( $p.css( 'left' ), 10 ),
relativeIndex = Math.ceil( ( pos + self.revisionWidth / 2 ) / self.revisionWidth ),
revId1, revId2;
mw.track( 'counter.MediaWiki.RevisionSlider.event.pointerMove' );
pointer.setPosition( self.slider.getFirstVisibleRevisionIndex() + relativeIndex );
self.resetPointerStylesBasedOnPosition();
self.resetRevisionStylesBasedOnPointerPosition( $revisions );
revId1 = self.getRevElementAtPosition( $revisions, self.pointerOne.getPosition() ).data( 'revid' );
revId2 = self.getRevElementAtPosition( $revisions, self.pointerTwo.getPosition() ).data( 'revid' );
self.diffPage.refresh( revId1, revId2 );
self.diffPage.pushState( revId1, revId2, self );
},
drag: function ( event, ui ) {
var newestVisibleRevisionLeftPos = containerWidth - self.revisionWidth;
ui.position.left = Math.min( ui.position.left, newestVisibleRevisionLeftPos );
self.resetPointerColorsBasedOnValues(
self.pointerOne.getView().getElement().offset().left,
self.pointerTwo.getView().getElement().offset().left
);
}
} );
$slider.find( '.mw-revision-wrapper' ).click( function ( e ) {
var $revWrap = $( this ),
$clickedRev = $revWrap.find( '.mw-revision' ),
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' ) );
}
self.resetPointerColorsBasedOnValues( self.pointerOne.getPosition(), self.pointerTwo.getPosition() );
self.resetRevisionStylesBasedOnPointerPosition( $revisions );
self.alignPointers();
} );
this.slider.setRevisionsPerWindow( $slider.find( '.mw-revisions-container' ).width() / this.revisionWidth );
this.initializePointers( this.getOldRevElement( $revisions ), this.getNewRevElement( $revisions ) );
this.resetRevisionStylesBasedOnPointerPosition( $revisions );
this.$element = $slider;
$container.html( $slider );
this.slide( Math.floor( ( this.pointerTwo.getPosition() - 1 ) / this.slider.getRevisionsPerWindow() ), 0 );
this.diffPage.pushState( mw.config.values.extRevisionSliderOldRev, mw.config.values.extRevisionSliderNewRev, this );
this.diffPage.initOnPopState( this );
},
getOldRevPointer: function () {
return this.pointerOne.getPosition() <= this.pointerTwo.getPosition() ? this.pointerOne : this.pointerTwo;
},
getNewRevPointer: function () {
return this.pointerOne.getPosition() > this.pointerTwo.getPosition() ? this.pointerOne : this.pointerTwo;
},
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 );
},
getRevElementAtPosition: function ( $revs, pos ) {
return $revs.find( 'div.mw-revision[data-pos="' + pos + '"]' );
},
getOldRevElement: function ( $revs ) {
return $revs.find( 'div.mw-revision[data-revid="' + mw.config.values.extRevisionSliderOldRev + '"]' );
},
getNewRevElement: function ( $revs ) {
return $revs.find( 'div.mw-revision[data-revid="' + mw.config.values.extRevisionSliderNewRev + '"]' );
},
initializePointers: function ( $oldRevElement, $newRevElement ) {
if ( $oldRevElement.length === 0 || $newRevElement.length === 0 ) {
// Note: this is currently caught in init.js
throw 'RS-rev-out-of-range';
}
this.pointerOne.setPosition( $oldRevElement.data( 'pos' ) );
this.pointerTwo.setPosition( $newRevElement.data( 'pos' ) );
this.resetPointerStylesBasedOnPosition();
},
resetPointerColorsBasedOnValues: function ( p1, p2 ) {
if ( p1 > p2 ) {
this.pointerOne.getView().getElement().removeClass( 'mw-oldid-pointer' ).addClass( 'mw-newid-pointer' );
this.pointerTwo.getView().getElement().removeClass( 'mw-newid-pointer' ).addClass( 'mw-oldid-pointer' );
} else {
this.pointerOne.getView().getElement().removeClass( 'mw-newid-pointer' ).addClass( 'mw-oldid-pointer' );
this.pointerTwo.getView().getElement().removeClass( 'mw-oldid-pointer' ).addClass( 'mw-newid-pointer' );
}
},
resetPointerStylesBasedOnPosition: function () {
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' );
},
resetRevisionStylesBasedOnPointerPosition: function ( $revisions ) {
var olderRevPosition = this.getOldRevPointer().getPosition(),
newerRevPosition = this.getNewRevPointer().getPosition(),
positionIndex = olderRevPosition + 1;
$revisions.find( 'div.mw-revision' )
.removeClass( 'mw-revision-intermediate mw-revision-old mw-revision-new' );
this.getRevElementAtPosition( $revisions, olderRevPosition ).addClass( 'mw-revision-old' );
this.getRevElementAtPosition( $revisions, newerRevPosition ).addClass( 'mw-revision-new' );
while ( positionIndex < newerRevPosition ) {
this.getRevElementAtPosition( $revisions, positionIndex ).addClass( 'mw-revision-intermediate' );
positionIndex++;
}
},
calculateRevisionsPerWindow: function () {
return Math.floor( ( $( '#mw-content-text' ).width() - this.containerMargin ) / this.revisionWidth );
},
calculateSliderContainerWidth: function () {
return Math.min( this.slider.getRevisions().getLength(), this.calculateRevisionsPerWindow() ) * this.revisionWidth;
},
slide: function ( direction, duration ) {
var self = this;
this.slider.slide( direction );
self.pointerOne.getView().getElement().draggable( 'disable' );
self.pointerTwo.getView().getElement().draggable( 'disable' );
if ( this.slider.isAtStart() ) {
$( '.mw-arrow-left' ).removeClass( 'mw-arrow-enabled mw-arrow-hovered' ).addClass( 'mw-arrow-disabled' );
} else {
$( '.mw-arrow-left' ).removeClass( 'mw-arrow-disabled' ).addClass( 'mw-arrow-enabled' );
}
if ( this.slider.isAtEnd() ) {
$( '.mw-arrow-right' ).removeClass( 'mw-arrow-enabled mw-arrow-hovered' ).addClass( 'mw-arrow-disabled' );
} else {
$( '.mw-arrow-right' ).removeClass( 'mw-arrow-disabled' ).addClass( 'mw-arrow-enabled' );
}
this.$element.find( '.mw-revisions-container' ).animate(
{ scrollLeft: this.slider.getFirstVisibleRevisionIndex() * this.revisionWidth },
duration,
null,
function () {
self.pointerOne.getView().getElement().draggable( 'enable' );
self.pointerTwo.getView().getElement().draggable( 'enable' );
}
);
this.alignPointers( duration );
},
alignPointers: function ( duration ) {
var self = this;
this.pointerOne.getView()
.slideToSideOrPosition( this.slider, duration )
.promise().done( function () {
self.resetPointerStylesBasedOnPosition();
} );
this.pointerTwo.getView()
.slideToSideOrPosition( this.slider, duration )
.promise().done( function () {
self.resetPointerStylesBasedOnPosition();
} );
},
whichPointer: function ( $e ) {
return $e.attr( 'id' ) === 'mw-revslider-pointer-one' ? this.pointerOne : this.pointerTwo;
}
} );
mw.libs.revisionSlider = mw.libs.revisionSlider || {};
mw.libs.revisionSlider.SliderView = SliderView;
}( mediaWiki, jQuery ) );