mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/RevisionSlider
synced 2024-11-30 18:14:32 +00:00
Use OOjs Popup Widgets instead of tipsy
Bug: T141983 Change-Id: I4b4ea427f82b15625537d859623461eceb1eb52b
This commit is contained in:
parent
0af4fe35d5
commit
77095bfa65
|
@ -109,7 +109,6 @@ class RevisionSliderHooks {
|
|||
'ext.RevisionSlider.HelpDialog',
|
||||
'jquery.ui.draggable',
|
||||
'jquery.ui.tooltip',
|
||||
'jquery.tipsy',
|
||||
'oojs-ui'
|
||||
],
|
||||
'localBasePath' => __DIR__,
|
||||
|
|
|
@ -133,7 +133,7 @@
|
|||
"revisionslider-minoredit"
|
||||
],
|
||||
"dependencies": [
|
||||
"jquery.tipsy"
|
||||
"oojs-ui"
|
||||
]
|
||||
},
|
||||
"ext.RevisionSlider.arrows.left": {
|
||||
|
|
|
@ -13,15 +13,25 @@
|
|||
*/
|
||||
revisionList: null,
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
revisionWidth: 16,
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
tooltipTimeout: -1,
|
||||
|
||||
/**
|
||||
* @type {OO.ui.PopupWidget}
|
||||
*/
|
||||
currentTooltip: null,
|
||||
|
||||
/**
|
||||
* @type {jQuery}
|
||||
*/
|
||||
currentTooltip: null,
|
||||
$highlightedRevisionWrapper: null,
|
||||
|
||||
/**
|
||||
* @param {number} revisionTickWidth
|
||||
|
@ -33,60 +43,32 @@
|
|||
revs = this.revisionList.getRevisions(),
|
||||
maxChangeSizeLogged = Math.log( this.revisionList.getBiggestChangeSize() ),
|
||||
self = this,
|
||||
i, diffSize, tooltip, relativeChangeSize,
|
||||
i, diffSize, relativeChangeSize,
|
||||
showTooltip = function () {
|
||||
self.showTooltip( $( this ) );
|
||||
$( this ).tipsy( 'show' );
|
||||
},
|
||||
hideTooltip = function () {
|
||||
self.hideTooltip( $( this ) );
|
||||
},
|
||||
tooltipGravity = function () {
|
||||
// Returns a function setting a gravity of the tooltip so that it will be entirely visible
|
||||
// Based on tipsy's own $.fn.tipsy.autoBounds, with considering the width of the
|
||||
// inner contents of the tooltip, and assuming the gravity always starts with 'n'
|
||||
return function () {
|
||||
var dir = 'n',
|
||||
$this = $( this ),
|
||||
$tip = $this.tipsy( true ).$tip,
|
||||
boundLeft = $( document ).scrollLeft() + $tip.outerWidth();
|
||||
|
||||
if ( $this.offset().left < boundLeft ) {
|
||||
dir += 'w';
|
||||
}
|
||||
if ( $( window ).width() + $( document ).scrollLeft() - $this.offset().left < 0 ) {
|
||||
dir += 'e';
|
||||
}
|
||||
|
||||
return dir;
|
||||
};
|
||||
};
|
||||
|
||||
positionOffset = positionOffset || 0;
|
||||
this.revisionWidth = revisionTickWidth;
|
||||
|
||||
for ( i = 0; i < revs.length; i++ ) {
|
||||
diffSize = revs[ i ].getRelativeSize();
|
||||
relativeChangeSize = diffSize !== 0 ? Math.ceil( 65.0 * Math.log( Math.abs( diffSize ) ) / maxChangeSizeLogged ) + 5 : 0;
|
||||
tooltip = this.makeTooltip( revs[ i ] );
|
||||
|
||||
$html
|
||||
.append( $( '<div>' )
|
||||
.addClass( 'mw-revslider-revision-wrapper' )
|
||||
.attr( 'title', tooltip )
|
||||
.width( revisionTickWidth )
|
||||
.tipsy( {
|
||||
gravity: tooltipGravity(),
|
||||
html: true,
|
||||
trigger: 'manual',
|
||||
className: 'mw-revslider-revision-tooltip mw-revslider-revision-tooltip-' + ( i + 1 )
|
||||
} )
|
||||
.width( this.revisionWidth )
|
||||
.append( $( '<div>' )
|
||||
.addClass( 'mw-revslider-revision' )
|
||||
.attr( 'data-revid', revs[ i ].getId() )
|
||||
.attr( 'data-pos', positionOffset + i + 1 )
|
||||
.css( {
|
||||
height: relativeChangeSize + 'px',
|
||||
width: revisionTickWidth + 'px',
|
||||
width: this.revisionWidth + 'px',
|
||||
top: diffSize > 0 ? '-' + relativeChangeSize + 'px' : 0
|
||||
} )
|
||||
.addClass( diffSize > 0 ? 'mw-revslider-revision-up' : 'mw-revslider-revision-down' )
|
||||
|
@ -123,10 +105,11 @@
|
|||
* Hides the current tooltip immediately
|
||||
*/
|
||||
hideCurrentTooltip: function () {
|
||||
if ( this.tooltipTimeout !== -1 ) {
|
||||
if ( this.tooltipTimeout !== -1 && this.$highlightedRevisionWrapper !== null ) {
|
||||
window.clearTimeout( this.tooltipTimeout );
|
||||
this.currentTooltip.tipsy( 'hide' );
|
||||
this.currentTooltip.removeClass( 'mw-revslider-revision-wrapper-hovered' );
|
||||
this.$highlightedRevisionWrapper.removeClass( 'mw-revslider-revision-wrapper-hovered' );
|
||||
this.currentTooltip.toggle( false );
|
||||
this.currentTooltip.$element.remove();
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -136,9 +119,15 @@
|
|||
* @param {jQuery} $rev
|
||||
*/
|
||||
hideTooltip: function ( $rev ) {
|
||||
var self = this;
|
||||
this.tooltipTimeout = window.setTimeout( function () {
|
||||
$rev.tipsy( 'hide' );
|
||||
$rev.removeClass( 'mw-revslider-revision-wrapper-hovered' );
|
||||
if ( $rev !== null ) {
|
||||
$rev.removeClass( 'mw-revslider-revision-wrapper-hovered' );
|
||||
}
|
||||
if ( self.currentTooltip !== null && self.currentTooltip.isVisible() ) {
|
||||
self.currentTooltip.toggle( false );
|
||||
self.currentTooltip.$element.remove();
|
||||
}
|
||||
}, 500 );
|
||||
},
|
||||
|
||||
|
@ -148,10 +137,40 @@
|
|||
* @param {jQuery} $rev
|
||||
*/
|
||||
showTooltip: function ( $rev ) {
|
||||
var pos = parseInt( $rev.find( '.mw-revslider-revision' ).attr( 'data-pos' ), 10 ),
|
||||
revId = parseInt( $rev.find( '.mw-revslider-revision' ).attr( 'data-revid' ), 10 ),
|
||||
revision = this.getRevisionWithId( revId ),
|
||||
tooltip;
|
||||
if ( revision === null ) {
|
||||
return;
|
||||
}
|
||||
tooltip = this.makeTooltip( revision );
|
||||
tooltip.$element.css( {
|
||||
left: $rev.offset().left + this.revisionWidth / 2 + 'px',
|
||||
top: $rev.offset().top + $rev.outerHeight() + 'px'
|
||||
} );
|
||||
tooltip.$element.attr( 'id', 'mw-revslider-revision-tooltip-' + pos );
|
||||
$( 'body' ).append( tooltip.$element );
|
||||
tooltip.toggle( true );
|
||||
|
||||
this.hideCurrentTooltip();
|
||||
$rev.tipsy( 'show' );
|
||||
$rev.addClass( 'mw-revslider-revision-wrapper-hovered' );
|
||||
this.currentTooltip = $rev;
|
||||
this.$highlightedRevisionWrapper = $rev;
|
||||
this.currentTooltip = tooltip;
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {number} revId
|
||||
* @return {Revision|null}
|
||||
*/
|
||||
getRevisionWithId: function ( revId ) {
|
||||
var matchedRevision = null;
|
||||
this.revisionList.revisions.forEach( function ( revision ) {
|
||||
if ( revision.getId() === revId ) {
|
||||
matchedRevision = revision;
|
||||
}
|
||||
} );
|
||||
return matchedRevision;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -165,7 +184,7 @@
|
|||
window.clearTimeout( self.tooltipTimeout );
|
||||
} )
|
||||
.on( 'mouseout', '.mw-revslider-revision-tooltip', function () {
|
||||
self.hideTooltip( self.currentTooltip );
|
||||
self.hideTooltip( self.$highlightedRevisionWrapper );
|
||||
} );
|
||||
},
|
||||
|
||||
|
@ -173,7 +192,7 @@
|
|||
* Generates the HTML for a tooltip that appears on hover above each revision on the slider
|
||||
*
|
||||
* @param {Revision} rev
|
||||
* @return {string}
|
||||
* @return {OO.ui.PopupWidget}
|
||||
*/
|
||||
makeTooltip: function ( rev ) {
|
||||
var $tooltip = $( '<div>' )
|
||||
|
@ -188,7 +207,11 @@
|
|||
this.makeChangeSizeLine( rev.getRelativeSize() ),
|
||||
rev.isMinor() ? $( '<p>' ).text( mw.message( 'revisionslider-minoredit' ).text() ) : ''
|
||||
);
|
||||
return $tooltip.html();
|
||||
return new OO.ui.PopupWidget( {
|
||||
$content: $tooltip,
|
||||
padded: true,
|
||||
classes: [ 'mw-revslider-tooltip', 'mw-revslider-revision-tooltip' ]
|
||||
} );
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -71,6 +71,9 @@
|
|||
.addClass( 'mw-revslider-revision-slider' )
|
||||
.css( { direction: $container.css( 'direction' ) } ),
|
||||
helpButton,
|
||||
helpPopup,
|
||||
backwardArrowPopup,
|
||||
forwardArrowPopup,
|
||||
self = this;
|
||||
|
||||
if ( $slider.css( 'direction' ) === 'rtl' ) {
|
||||
|
@ -80,6 +83,13 @@
|
|||
this.pointerOlder = new mw.libs.revisionSlider.Pointer( 'mw-revslider-pointer-older' );
|
||||
this.pointerNewer = new mw.libs.revisionSlider.Pointer( 'mw-revslider-pointer-newer' );
|
||||
|
||||
helpPopup = new OO.ui.PopupWidget( {
|
||||
$content: $( '<p>' ).text( mw.msg( 'revisionslider-show-help-tooltip' ) ),
|
||||
padded: true,
|
||||
width: 200,
|
||||
classes: [ 'mw-revslider-tooltip', 'mw-revslider-help-tooltip' ]
|
||||
} );
|
||||
|
||||
helpButton = new OO.ui.ButtonWidget( {
|
||||
icon: 'help',
|
||||
framed: false,
|
||||
|
@ -89,13 +99,22 @@
|
|||
.click( function () {
|
||||
mw.libs.revisionSlider.HelpDialog.show();
|
||||
} )
|
||||
.tipsy( {
|
||||
gravity: $( 'body' ).hasClass( 'ltr' ) ? 'se' : 'sw',
|
||||
offset: 15,
|
||||
title: function () {
|
||||
return mw.msg( 'revisionslider-show-help-tooltip' );
|
||||
}
|
||||
} );
|
||||
.mouseover( { popup: helpPopup }, this.showPopup )
|
||||
.mouseout( function () { helpPopup.toggle( false ); } );
|
||||
|
||||
backwardArrowPopup = new OO.ui.PopupWidget( {
|
||||
$content: $( '<p>' ).text( mw.msg( 'revisionslider-arrow-tooltip-older' ) ),
|
||||
padded: true,
|
||||
width: 200,
|
||||
classes: [ 'mw-revslider-tooltip', 'mw-revslider-arrow-tooltip' ]
|
||||
} );
|
||||
forwardArrowPopup = new OO.ui.PopupWidget( {
|
||||
$content: $( '<p>' ).text( mw.msg( 'revisionslider-arrow-tooltip-newer' ) ),
|
||||
padded: true,
|
||||
width: 200,
|
||||
classes: [ 'mw-revslider-tooltip', 'mw-revslider-arrow-tooltip' ]
|
||||
} );
|
||||
$( 'body' ).append( backwardArrowPopup.$element, forwardArrowPopup.$element, helpPopup.$element );
|
||||
|
||||
pointerContainerStyle = { left: pointerContainerPosition + 'px', width: pointerContainerWidth + 'px' };
|
||||
if ( $slider.css( 'direction' ) === 'rtl' ) {
|
||||
|
@ -113,14 +132,8 @@
|
|||
$( '<a> ' )
|
||||
.addClass( 'mw-revslider-arrow mw-revslider-arrow-backwards' )
|
||||
.attr( 'data-dir', '-1' )
|
||||
.tipsy( {
|
||||
title: function () {
|
||||
if ( $( this ).hasClass( 'mw-revslider-arrow-disabled' ) ) {
|
||||
return '';
|
||||
}
|
||||
return mw.message( 'revisionslider-arrow-tooltip-older' ).text();
|
||||
}
|
||||
} ),
|
||||
.mouseover( { popup: backwardArrowPopup }, this.showPopup )
|
||||
.mouseout( { popup: backwardArrowPopup }, this.hidePopup ),
|
||||
$( '<div>' )
|
||||
.addClass( 'mw-revslider-revisions-container' )
|
||||
.css( {
|
||||
|
@ -130,21 +143,8 @@
|
|||
$( '<a> ' )
|
||||
.addClass( 'mw-revslider-arrow mw-revslider-arrow-forwards' )
|
||||
.attr( 'data-dir', '1' )
|
||||
.tipsy( {
|
||||
gravity: function () {
|
||||
if ( $slider.css( 'direction' ) === 'ltr' ) {
|
||||
return Math.abs( window.innerWidth - this.getBoundingClientRect().right ) > 90 ? 'n' : 'ne';
|
||||
} else {
|
||||
return this.getBoundingClientRect().left > 90 ? 'n' : 'nw';
|
||||
}
|
||||
},
|
||||
title: function () {
|
||||
if ( $( this ).hasClass( 'mw-revslider-arrow-disabled' ) ) {
|
||||
return '';
|
||||
}
|
||||
return mw.message( 'revisionslider-arrow-tooltip-newer' ).text();
|
||||
}
|
||||
} ),
|
||||
.mouseover( { popup: forwardArrowPopup }, this.showPopup )
|
||||
.mouseout( { popup: forwardArrowPopup }, this.hidePopup ),
|
||||
helpButton.$element,
|
||||
$( '<div>' ).css( { clear: 'both' } ),
|
||||
$( '<div>' )
|
||||
|
@ -256,6 +256,23 @@
|
|||
this.diffPage.initOnPopState( this );
|
||||
},
|
||||
|
||||
showPopup: function ( e ) {
|
||||
var popup = e.data.popup;
|
||||
if ( $( this ).hasClass( 'mw-revslider-arrow-disabled' ) ) {
|
||||
return;
|
||||
}
|
||||
popup.$element.css( {
|
||||
left: $( this ).offset().left + $( this ).outerWidth() / 2 + 'px',
|
||||
top: $( this ).offset().top + $( this ).outerHeight() + 'px'
|
||||
} );
|
||||
popup.toggle( true );
|
||||
},
|
||||
|
||||
hidePopup: function ( e ) {
|
||||
var popup = e.data.popup;
|
||||
popup.toggle( false );
|
||||
},
|
||||
|
||||
revisionWrapperClickHandler: function ( e ) {
|
||||
var $revWrap = $( this ),
|
||||
view = e.data.view,
|
||||
|
|
|
@ -85,8 +85,8 @@
|
|||
border-left: solid 1px #fff;
|
||||
}
|
||||
|
||||
.mw-revslider-revision-tooltip .tipsy-inner {
|
||||
max-width: none;
|
||||
.mw-revslider-tooltip {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
.mw-revslider-revision-tooltip .mw-revslider-change-positive {
|
||||
|
@ -101,6 +101,11 @@
|
|||
color: #aaa;
|
||||
}
|
||||
|
||||
.mw-revslider-arrow-tooltip,
|
||||
.mw-revslider-help-tooltip {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.mw-revslider-revisions {
|
||||
height: 140px;
|
||||
white-space: nowrap;
|
||||
|
|
|
@ -26,7 +26,7 @@ class DiffPage
|
|||
end
|
||||
|
||||
def revisionslider_tooltip(index = 1)
|
||||
element('div', css: '.mw-revslider-revision-tooltip-' + index.to_s)
|
||||
element('div', id: 'mw-revslider-revision-tooltip-' + index.to_s)
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
assert.ok( $( $revisionDivs[ 2 ] ).hasClass( 'mw-revslider-revision-down' ) );
|
||||
} );
|
||||
|
||||
QUnit.test( 'tool tip is composed correctly', function ( assert ) {
|
||||
QUnit.test( 'tooltip is composed correctly', function ( assert ) {
|
||||
var revisionListView = new RevisionListView(),
|
||||
revision = new Revision( {
|
||||
revid: 1,
|
||||
|
@ -37,21 +37,23 @@
|
|||
user: 'User1',
|
||||
minor: true
|
||||
} ),
|
||||
$tooltipHtml;
|
||||
tooltip,
|
||||
tooltipHtml;
|
||||
|
||||
revision.setRelativeSize( 210 );
|
||||
|
||||
mw.libs.revisionSlider.userOffset = 0;
|
||||
|
||||
$tooltipHtml = revisionListView.makeTooltip( revision );
|
||||
tooltip = revisionListView.makeTooltip( revision );
|
||||
tooltipHtml = tooltip.$element.html();
|
||||
|
||||
assert.ok( $tooltipHtml.match( /User1/ ), 'Test the user.' );
|
||||
assert.ok( $tooltipHtml.match( /Hello/ ), 'Test the comment.' );
|
||||
assert.ok( $tooltipHtml.match( /230/ ), 'Test the page size.' );
|
||||
assert.ok( $tooltipHtml.match( /\+210/ ), 'Test the change size.' );
|
||||
assert.ok( tooltipHtml.match( /User1/ ), 'Test the user.' );
|
||||
assert.ok( tooltipHtml.match( /Hello/ ), 'Test the comment.' );
|
||||
assert.ok( tooltipHtml.match( /230/ ), 'Test the page size.' );
|
||||
assert.ok( tooltipHtml.match( /\+210/ ), 'Test the change size.' );
|
||||
} );
|
||||
|
||||
QUnit.revisionSlider.testOrSkip( 'tool tip is composed correctly with en lang', function ( assert ) {
|
||||
QUnit.revisionSlider.testOrSkip( 'tooltip is composed correctly with en lang', function ( assert ) {
|
||||
var revisionListView = new RevisionListView(),
|
||||
revision = new Revision( {
|
||||
revid: 1,
|
||||
|
@ -62,20 +64,22 @@
|
|||
user: 'User1',
|
||||
minor: true
|
||||
} ),
|
||||
$tooltipHtml;
|
||||
tooltip,
|
||||
tooltipHtml;
|
||||
|
||||
revision.setRelativeSize( 2100 );
|
||||
|
||||
mw.libs.revisionSlider.userOffset = 0;
|
||||
|
||||
$tooltipHtml = revisionListView.makeTooltip( revision );
|
||||
tooltip = revisionListView.makeTooltip( revision );
|
||||
tooltipHtml = tooltip.$element.html();
|
||||
|
||||
assert.ok( $tooltipHtml.match( /User1/ ), 'Test the user.' );
|
||||
assert.ok( $tooltipHtml.match( /Hello/ ), 'Test the comment.' );
|
||||
assert.ok( $tooltipHtml.match( /2,300/ ), 'Test the page size.' );
|
||||
assert.ok( $tooltipHtml.match( /\+2,100/ ), 'Test the change size.' );
|
||||
assert.ok( $tooltipHtml.match( /10:27, 26 Apr 2016/ ), 'Test the date.' );
|
||||
assert.ok( $tooltipHtml.match( /minor/ ), 'Test minor.' );
|
||||
assert.ok( tooltipHtml.match( /User1/ ), 'Test the user.' );
|
||||
assert.ok( tooltipHtml.match( /Hello/ ), 'Test the comment.' );
|
||||
assert.ok( tooltipHtml.match( /2,300/ ), 'Test the page size.' );
|
||||
assert.ok( tooltipHtml.match( /\+2,100/ ), 'Test the change size.' );
|
||||
assert.ok( tooltipHtml.match( /10:27, 26 Apr 2016/ ), 'Test the date.' );
|
||||
assert.ok( tooltipHtml.match( /minor/ ), 'Test minor.' );
|
||||
}, mw.config.get( 'wgUserLanguage' ) !== 'en' );
|
||||
|
||||
QUnit.test( 'empty user leads to no user line', function ( assert ) {
|
||||
|
|
Loading…
Reference in a new issue