' )
.addClass( 'mw-revslider-revision' )
.attr( 'data-revid', revs[ i ].getId() )
.attr( 'data-pos', positionOffset + i + 1 )
.css( {
height: relativeChangeSize + 'px',
width: this.revisionWidth + 'px',
top: diffSize > 0 ? '-' + relativeChangeSize + 'px' : 0
} )
.addClass( diffSize > 0 ? 'mw-revslider-revision-up' : 'mw-revslider-revision-down' )
.append( $( '
' ).addClass( 'mw-revslider-revision-border-box' ) )
)
.mouseenter( showTooltip )
.mouseleave( hideTooltip )
);
}
this.keepTooltipsOnHover();
this.closeTooltipsOnClick();
return $html;
},
/**
* @param {jQuery} $renderedList
*/
adjustRevisionSizes: function ( $renderedList ) {
var revs = this.revisionList.getRevisions(),
maxChangeSizeLogged = Math.log( this.revisionList.getBiggestChangeSize() ),
i, diffSize, relativeChangeSize;
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;
$renderedList.find( '.mw-revslider-revision[data-pos="' + ( i + 1 ) + '"]' ).css( {
height: relativeChangeSize + 'px',
top: diffSize > 0 ? '-' + relativeChangeSize + 'px' : 0
} );
}
},
/**
* Hides the current tooltip immediately
*/
hideCurrentTooltip: function () {
var $highlightedRevisionWrapper = $( '.mw-revslider-revision-wrapper-hovered' ),
$currentTooltip = $( '.mw-revslider-revision-tooltip' );
if ( this.tooltipTimeout !== -1 ) {
window.clearTimeout( this.tooltipTimeout );
}
if ( $highlightedRevisionWrapper.length !== 0 ) {
$highlightedRevisionWrapper.removeClass( 'mw-revslider-revision-wrapper-hovered' );
}
if ( $currentTooltip.length !== 0 ) {
$currentTooltip.remove();
}
},
/**
* Hides the tooltip after 500ms
*
* @param {jQuery} $rev
*/
hideTooltip: function ( $rev ) {
var $currentTooltip = $( '.mw-revslider-revision-tooltip' );
this.tooltipTimeout = window.setTimeout( function () {
if ( $rev.length !== 0 ) {
$rev.removeClass( 'mw-revslider-revision-wrapper-hovered' );
}
if ( $currentTooltip.length !== 0 ) {
$currentTooltip.remove();
}
}, 500 );
},
/**
* Hides the previous tooltip and shows the new one
*
* @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;
}
this.hideCurrentTooltip();
tooltip = this.makeTooltip( revision );
tooltip.$element.css( {
left: $rev.offset().left + this.revisionWidth / 2 + 'px',
top: $rev.offset().top + $rev.outerHeight() + 'px'
} ).addClass( 'mw-revslider-revision-tooltip-' + pos );
$( 'body' ).append( tooltip.$element );
tooltip.toggle( true );
$rev.addClass( 'mw-revslider-revision-wrapper-hovered' );
},
/**
* @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;
},
/**
* Sets event handlers on tooltips so they do not disappear when hovering over them
*/
keepTooltipsOnHover: function () {
var self = this;
$( document )
.on( 'mouseenter', '.mw-revslider-revision-tooltip', function () {
window.clearTimeout( self.tooltipTimeout );
} )
.on( 'mouseleave', '.mw-revslider-revision-tooltip', function () {
self.hideTooltip( $( '.mw-revslider-revision-wrapper-hovered' ) );
} );
},
/**
* Sets an event handler to close tooltips when clicking somewhere outside
*/
closeTooltipsOnClick: function () {
var self = this;
$( document )
.on( 'click', function ( event ) {
if ( $( event.target ).closest( '.mw-revslider-revision-tooltip' ).length === 0 &&
$( event.target ).closest( '.mw-revslider-revisions-container' ).length === 0 ) {
self.hideCurrentTooltip();
}
} );
},
/**
* Generates the HTML for a tooltip that appears on hover above each revision on the slider
*
* @param {Revision} rev
* @return {OO.ui.PopupWidget}
*/
makeTooltip: function ( rev ) {
var $tooltip = $( '
' )
.append(
$( '
' ).append(
$( '' ).text( mw.msg( 'revisionslider-label-date' ) + mw.msg( 'colon-separator' ) ),
rev.getFormattedDate()
),
this.makeUserLine( rev.getUser(), rev.getUserGender() ),
this.makeCommentLine( rev ),
this.makePageSizeLine( rev.getSize() ),
this.makeChangeSizeLine( rev.getRelativeSize() ),
rev.isMinor() ? $( '' ).text( mw.message( 'revisionslider-minoredit' ).text() ) : ''
);
return new OO.ui.PopupWidget( {
$content: $tooltip,
padded: true,
classes: [ 'mw-revslider-tooltip', 'mw-revslider-revision-tooltip' ]
} );
},
/**
* Generates a link to user page or to contributions page for IP addresses
*
* @param {string} user
* @return {string}
*/
getUserPage: function ( user ) {
return ( mw.util.isIPAddress( user, false ) ? 'Special:Contributions/' : 'User:' ) + this.stripInvalidCharacters( user );
},
/**
* Generates the HTML for the user label
*
* @param {string} userString
* @param {string} userGender
* @return {string|jQuery}
*/
makeUserLine: function ( userString, userGender ) {
if ( !userString ) {
return '';
}
if ( !userGender ) {
userGender = 'unknown';
}
return $( '
' ).append(
$( '' ).text( mw.msg( 'revisionslider-label-username', userGender ) + mw.msg( 'colon-separator' ) ),
$( '' ).append(
$( '' ).addClass( 'mw-userlink' ).attr( 'href', mw.util.getUrl( this.getUserPage( userString ) ) ).text( this.stripInvalidCharacters( userString ) )
)
);
},
/**
* @param {string} s
* @return {string}
*/
stripInvalidCharacters: function ( s ) {
return s.replace( /[<>&]/g, '' );
},
/**
* Generates the HTML for the comment label
*
* @param {Revision} rev
* @return {string|jQuery}
*/
makeCommentLine: function ( rev ) {
if ( rev.hasEmptyComment() ) {
return '';
}
return $( '' ).append(
$( '' ).text( mw.msg( 'revisionslider-label-comment' ) + mw.msg( 'colon-separator' ) ),
$( '' ).append(
$( '' ).append(
rev.getParsedComment()
)
)
);
},
/**
* Generates the HTML for the page size label
*
* @param {number} size
* @return {jQuery}
*/
makePageSizeLine: function ( size ) {
return $( '' ).append(
$( '' ).text( mw.msg( 'revisionslider-label-page-size' ) + mw.msg( 'colon-separator' ) ),
mw.msg( 'revisionslider-page-size', mw.language.convertNumber( size ), size )
);
},
/**
* Generates the HTML for the change size label
*
* @param {number} relativeSize
* @return {jQuery}
*/
makeChangeSizeLine: function ( relativeSize ) {
var changeSizeClass = 'mw-revslider-change-none',
leadingSign = '',
$changeNumber;
if ( relativeSize > 0 ) {
changeSizeClass = 'mw-revslider-change-positive';
leadingSign = '+';
} else if ( relativeSize < 0 ) {
changeSizeClass = 'mw-revslider-change-negative';
}
$changeNumber = $( '' )
.addClass( changeSizeClass )
.attr( {
dir: 'ltr' // Make sure that minus/plus is on the left
} )
.text( leadingSign + mw.language.convertNumber( relativeSize ) );
return $( '' ).append(
$( '' ).text( mw.msg( 'revisionslider-label-change-size' ) + mw.msg( 'colon-separator' ) ),
mw.message( 'revisionslider-change-size', $changeNumber, relativeSize, Math.abs( relativeSize ) ).parse()
);
}
} );
mw.libs.revisionSlider = mw.libs.revisionSlider || {};
mw.libs.revisionSlider.RevisionListView = RevisionListView;
}( mediaWiki, jQuery ) );