Introduce alternate SliderView

Adding a new class for an alternative slider view with
one slider for each pointer. The new class will be used
when the extension is installed as a beta feature.

Each pointer has now its own pointer container visualized
with a thin line. Pointers can not change places anymore
and methods doing so where overwritten in the patch.

Selected revisions are not colored atm to better distinguish
between pointers and bars. Poiner lines are now shown above
the bars. ( as from feedback in the last PM session )

Some issues with the design might remain. But since we plan
the deployment anyway next week this could be merged if reviewed. 

Bug: T160410
Change-Id: If00c31e30f8a01f3525b191c70605b9c9381671d
This commit is contained in:
WMDE-Fisch 2017-03-23 14:53:13 +01:00
parent 040dd9c945
commit c52c657516
7 changed files with 315 additions and 4 deletions

View file

@ -147,6 +147,17 @@
"revisionslider-arrow-tooltip-older"
]
},
"ext.RevisionSlider.SliderViewTwo": {
"scripts": [
"modules/ext.RevisionSlider.SliderViewTwo.js"
],
"styles": [
"modules/ext.RevisionSliderViewTwo.css"
],
"dependencies": [
"ext.RevisionSlider.SliderView"
]
},
"ext.RevisionSlider.DiffPage": {
"scripts": [
"modules/ext.RevisionSlider.DiffPage.js"

View file

@ -7,7 +7,11 @@
*/
var Slider = function ( revisions ) {
this.revisions = revisions;
if ( mw.config.get( 'extRevisionSliderBeta' ) ) {
this.view = new mw.libs.revisionSlider.SliderViewTwo( this );
} else {
this.view = new mw.libs.revisionSlider.SliderView( this );
}
};
$.extend( Slider.prototype, {

View file

@ -190,7 +190,7 @@
}
} );
$pointers.draggable( this.buildDraggableOptions( escapePressed, $revisions ) );
$pointers.draggable( this.buildDraggableOptions( escapePressed, $revisions, '.mw-revslider-pointer-container' ) );
},
/**
@ -198,16 +198,17 @@
*
* @param {boolean} escapePressed
* @param {jQuery} $revisions
* @param {string} containmentClass
* @return {Object}
*/
buildDraggableOptions: function( escapePressed, $revisions ) {
buildDraggableOptions: function( escapePressed, $revisions, containmentClass ) {
var lastValidLeftPos,
self = this;
return {
axis: 'x',
grid: [ this.revisionWidth, null ],
containment: '.mw-revslider-pointer-container',
containment: containmentClass,
start: function() {
self.setPointerDragCursor();
self.fadeOutPointerLines();

View file

@ -0,0 +1,211 @@
( function ( mw, $ ) {
/**
* Module handling the view logic of the RevisionSlider slider with two slides
*
* @param {Slider} slider
* @constructor
*/
var SliderViewTwo = function ( slider ) {
this.slider = slider;
this.diffPage = new mw.libs.revisionSlider.DiffPage( this.slider.getRevisions() );
};
OO.inheritClass( SliderViewTwo, mw.libs.revisionSlider.SliderView );
$.extend( SliderViewTwo.prototype, {
/**
* Renders the pointer container and adds the pointers to it
*
* @param {number} containerWidth
* @return {jQuery} the pointer container
*/
renderPointerContainer: function( containerWidth ) {
var pointerContainerPosition = 53,
pointerContainerWidth = containerWidth + this.revisionWidth - 1,
pointerContainerStyle;
pointerContainerStyle = { left: pointerContainerPosition + 'px', width: pointerContainerWidth + 'px' };
if ( this.dir === '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' };
}
return $( '<div>' )
.addClass( 'mw-revslider-pointer-container' )
.css( pointerContainerStyle )
.append( this.renderPointerContainers() );
},
renderPointerContainers: function() {
var self = this;
return [
$( '<div>' )
.addClass( 'mw-revslider-pointer-container-newer' )
.click( function( event ) {
self.sliderLineClickHandler( event, $( this ) );
} )
.append(
$( '<div>' ).addClass( 'mw-revslider-slider-line' ),
this.pointerNewer.getView().render()
),
$( '<div>' )
.addClass( 'mw-revslider-pointer-container-older' )
.click( function( event ) {
self.sliderLineClickHandler( event, $( this ) );
} )
.append(
$( '<div>' ).addClass( 'mw-revslider-slider-line' ),
this.pointerOlder.getView().render()
)
];
},
/**
* Initializes the pointer dragging logic
*
* @param {jQuery} $revisions
*/
initPointers: function( $revisions ) {
var $pointers,
$pointerOlder = this.pointerOlder.getView().getElement(),
$pointerNewer = this.pointerNewer.getView().getElement(),
escapePressed = false;
$pointers = this.$element.find( '.mw-revslider-pointer' );
$( 'body' ).keydown( function( e ) {
if ( e.which === 27 ) {
escapePressed = true;
$pointers.trigger( 'mouseup' );
}
} );
$pointerOlder.draggable( this.buildDraggableOptions(
escapePressed, $revisions,
'.mw-revslider-pointer-container-older'
) );
$pointerNewer.draggable( this.buildDraggableOptions(
escapePressed, $revisions,
'.mw-revslider-pointer-container-newer'
) );
SliderViewTwo.super.prototype.resetPointerStylesBasedOnPosition.call( this );
},
sliderLineClickHandler: function( event, $line ) {
var $revisions = this.$element.find( '.mw-revslider-revisions' ),
$clickedRev = this.getRevisionNearestToClick( event ),
pointerMoved, pointerOther, newPosition;
newPosition = parseInt( $clickedRev.attr( 'data-pos' ) );
if ( $line.hasClass( 'mw-revslider-pointer-container-newer' ) ) {
pointerMoved = this.pointerNewer;
pointerOther = this.pointerOlder;
} else {
pointerMoved = this.pointerOlder;
pointerOther = this.pointerNewer;
}
if ( newPosition === pointerOther.getPosition() ) {
return;
}
pointerMoved.setPosition( newPosition );
this.updatePointerPositionAttributes();
this.refreshRevisions(
this.getRevElementAtPosition( $revisions, pointerOther.getPosition() ).attr( 'data-revid' ),
$clickedRev.attr( 'data-revid' )
);
this.resetRevisionStylesBasedOnPointerPosition( $revisions );
this.alignPointers();
},
getRevisionNearestToClick: function( clickEvent ) {
var $revisionArr = $( '.mw-revslider-revision' ),
$current, rtlOffset, i = 0, count;
rtlOffset = this.dir === 'rtl' ? this.revisionWidth : 0;
for ( count = $revisionArr.length; i < count; i++ ) {
$current = $( $revisionArr[ i ] );
if ( Math.abs( $current.offset().left + rtlOffset - clickEvent.pageX ) < this.revisionWidth ) {
break;
}
}
return $current;
},
resetPointerStylesBasedOnPosition: function() {
this.updateOlderSliderLineCSS();
this.updateNewerSliderLineCSS();
},
resetPointerColorsBasedOnValues: function() {
},
updateOlderSliderLineCSS: function() {
var widthToSet = ( this.getOlderDistanceToOldest() + this.getDistanceBetweenPointers() ) *
this.revisionWidth,
marginToSet = -this.revisionWidth / 2;
widthToSet = Math.min( widthToSet, this.calculateSliderContainerWidth() + this.revisionWidth );
this.setSliderLineCSS(
$( '.mw-revslider-pointer-container-older' ), widthToSet, marginToSet
);
},
updateNewerSliderLineCSS: function() {
var widthToSet = ( this.getNewerDistanceToNewest() + this.getDistanceBetweenPointers() + 2 ) *
this.revisionWidth,
marginToSet = ( this.getOlderDistanceToOldest() * this.revisionWidth ) -
this.revisionWidth / 2;
widthToSet = Math.min( widthToSet, this.calculateSliderContainerWidth() + this.revisionWidth );
marginToSet = Math.max( marginToSet, -0.5 * this.revisionWidth );
this.setSliderLineCSS(
$( '.mw-revslider-pointer-container-newer' ), widthToSet, marginToSet
);
},
setSliderLineCSS: function( $lineContainer, widthToSet, marginToSet ) {
if ( this.dir === 'ltr' ) {
$lineContainer.css( {
width: widthToSet,
'margin-left': marginToSet
} );
} else {
$lineContainer.css( {
width: widthToSet,
'margin-right': marginToSet + this.revisionWidth
} );
}
},
getOlderDistanceToOldest: function() {
return this.pointerOlder.getPosition() - this.slider.getOldestVisibleRevisionIndex();
},
getNewerDistanceToNewest: function() {
return this.slider.getNewestVisibleRevisionIndex() - this.pointerNewer.getPosition();
},
getDistanceBetweenPointers: function() {
return this.pointerNewer.getPosition() - this.pointerOlder.getPosition();
},
revisionWrapperClickHandler: function() {
}
} );
mw.libs.revisionSlider = mw.libs.revisionSlider || {};
mw.libs.revisionSlider.SliderViewTwo = SliderViewTwo;
}( mediaWiki, jQuery ) );

View file

@ -118,6 +118,9 @@
}
} );
if ( mw.config.get( 'extRevisionSliderBeta' ) ) {
mw.loader.load( 'ext.RevisionSlider.SliderViewTwo' );
}
expand();
initialize();

View file

@ -0,0 +1,80 @@
.mw-revslider-revision-wrapper {
cursor: auto;
}
.mw-revslider-pointer-container {
top: 52px;
z-index: 10;
height: 26px;
margin: 0;
}
.mw-revslider-pointer-container-newer,
.mw-revslider-pointer-container-older {
cursor: pointer;
height: 12px;
}
.mw-revslider-revision-old,
.mw-revslider-revision-new {
background-color: #bcbcbc;
border-color: #989898;
}
.mw-revslider-revision-old:hover,
.mw-revslider-revision-wrapper-hovered .mw-revslider-revision-old,
.mw-revslider-revision-new:hover,
.mw-revslider-revision-wrapper-hovered .mw-revslider-revision-new {
background-color: #a6a6a6;
border-color: #828282;
}
.mw-revslider-pointer-container-newer {
margin-top: 7px;
}
.mw-revslider-slider-line {
margin: 0 10px;
}
.mw-revslider-pointer-container-newer .mw-revslider-slider-line {
height: 8px;
border-bottom: 2px solid rgba( 30, 109, 184, 0.5 ); /* #1e6db8 */
}
.mw-revslider-pointer-container-older .mw-revslider-slider-line {
height: 2px;
border-bottom: 2px solid rgba( 255, 204, 51, 0.5 ); /* #fc3 */
}
.mw-revslider-pointer-upper.mw-revslider-pointer-newid {
top: 8px;
border: 1px solid #66b2ff;
background: -webkit-linear-gradient( bottom, rgba( 47, 147, 247, 1 ), rgba( 3, 81, 159, 1 ) );
background: -moz-linear-gradient( bottom, rgba( 47, 147, 247, 1 ), rgba( 3, 81, 159, 1 ) );
background: -ms-linear-gradient( bottom, rgba( 47, 147, 247, 1 ), rgba( 3, 81, 159, 1 ) );
background: -o-linear-gradient( bottom, rgba( 47, 147, 247, 1 ), rgba( 3, 81, 159, 1 ) );
background: linear-gradient( to bottom, rgba( 47, 147, 247, 1 ), rgba( 3, 81, 159, 1 ) );
}
.mw-revslider-pointer-lower.mw-revslider-pointer-oldid {
top: 14px;
border: 1px solid #ffc561;
background: -webkit-linear-gradient( bottom, rgba( 253, 224, 114, 1 ), rgba( 230, 173, 29, 1 ) );
background: -moz-linear-gradient( bottom, rgba( 253, 224, 114, 1 ), rgba( 230, 173, 29, 1 ) );
background: -ms-linear-gradient( bottom, rgba( 253, 224, 114, 1 ), rgba( 230, 173, 29, 1 ) );
background: -o-linear-gradient( bottom, rgba( 253, 224, 114, 1 ), rgba( 230, 173, 29, 1 ) );
background: linear-gradient( to bottom, rgba( 253, 224, 114, 1 ), rgba( 230, 173, 29, 1 ) );
}
.mw-revslider-pointer {
padding: 0;
width: 14px;
height: 14px;
border-radius: 50%;
}
.mw-revslider-pointer-line {
z-index: 5;
/* @noflip */
margin-left: 1px;
}

View file

@ -68,6 +68,7 @@ class RevisionSliderHooks {
$out->addJsConfigVars( 'extRevisionSliderOldRev', $oldRev->getId() );
$out->addJsConfigVars( 'extRevisionSliderNewRev', $newRev->getId() );
$out->addJsConfigVars( 'extRevisionSliderTimeOffset', intval( $timeOffset ) );
$out->addJsConfigVars( 'extRevisionSliderBeta', $config->get( 'RevisionSliderBetaFeature' ) );
$out->enableOOUI();
// FIXME: this really not nice to inject those elements to ButtonWidget like that