mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/RevisionSlider
synced 2024-12-01 02:16:18 +00:00
d2b03abe43
We added this more as an experiment because we couldn't reliably figure out what makes later .offset() calls fail. After looking into the actual jQuery source code I realized the only way .offset() can return undefined is when .length is zero. Which means the two checks are redundant and one can be removed. In case an element is not attached to the document an object with { top: 0, left: 0 } is returned. Bug: T342556 Change-Id: I6265fd27b3102a9cfe853a9c0e11063b76cf0b7b
201 lines
5.4 KiB
JavaScript
201 lines
5.4 KiB
JavaScript
/**
|
|
* Module containing presentation logic for the revision pointer lines
|
|
*
|
|
* @class PointerLine
|
|
* @param {Pointer} pointer
|
|
* @param {string} name
|
|
* @constructor
|
|
*/
|
|
function PointerLine( pointer, name ) {
|
|
this.pointer = pointer;
|
|
this.name = name;
|
|
}
|
|
|
|
$.extend( PointerLine.prototype, {
|
|
/**
|
|
* @type {string}
|
|
*/
|
|
name: '',
|
|
|
|
/**
|
|
* @type {Pointer}
|
|
*/
|
|
pointer: null,
|
|
|
|
/**
|
|
* @type {jQuery}
|
|
*/
|
|
$html: null,
|
|
|
|
/**
|
|
* Calculate the relative distance in between the given pointer and column
|
|
*
|
|
* @private
|
|
* @param {jQuery} $sourcePointer
|
|
* @param {jQuery} $targetColumn
|
|
* @return {number} distance between the given elements
|
|
*/
|
|
calculateDistance: function ( $sourcePointer, $targetColumn ) {
|
|
return ( $targetColumn.offset().left + $targetColumn.width() / 2 ) -
|
|
( $sourcePointer.offset().left + ( $sourcePointer.width() ) / 2 );
|
|
},
|
|
|
|
/**
|
|
* Calculate and set line's width and position with the given pointer and column
|
|
*
|
|
* @private
|
|
* @param {jQuery} $sliderView
|
|
* @param {jQuery} $sourcePointer
|
|
* @param {jQuery} $targetColumn
|
|
*/
|
|
setCssProperties: function ( $sliderView, $sourcePointer, $targetColumn ) {
|
|
const distance = this.calculateDistance( $sourcePointer, $targetColumn );
|
|
|
|
const widthToSet = Math.abs( distance );
|
|
let leftToSet = ( $targetColumn.offset().left + $targetColumn.width() / 2 ) -
|
|
$sliderView.offset().left;
|
|
|
|
if ( distance > 0 ) {
|
|
// targetColumn is right relative to sourcePointer
|
|
leftToSet -= widthToSet;
|
|
leftToSet -= 1;
|
|
} else {
|
|
// targetColumn is left relative to sourcePointer
|
|
leftToSet += 1;
|
|
}
|
|
|
|
this.$html.css( {
|
|
width: widthToSet + 'px',
|
|
left: leftToSet + 'px'
|
|
} );
|
|
},
|
|
|
|
/**
|
|
* Check if the target column is located right form the source pointer
|
|
*
|
|
* @private
|
|
* @param {jQuery} $sourcePointer
|
|
* @param {jQuery} $targetColumn
|
|
* @return {boolean}
|
|
*/
|
|
targetColumnIsRightFromPointer: function ( $sourcePointer, $targetColumn ) {
|
|
return this.calculateDistance( $sourcePointer, $targetColumn ) > 0;
|
|
},
|
|
|
|
/**
|
|
* Draws the line between pointer and column by setting borders, position and width of the line box
|
|
*/
|
|
drawLine: function () {
|
|
const isNewer = this.pointer.getView().isNewerPointer();
|
|
const $sliderView = $( '.mw-revslider-revision-slider' );
|
|
const $targetColumn = $( isNewer ? '.diff-ntitle' : '.diff-otitle' );
|
|
|
|
if ( !$sliderView.length || !$targetColumn.length ) {
|
|
return;
|
|
}
|
|
|
|
const $upperLineDiv = this.$html.find( '.mw-revslider-pointer-line-upper' ),
|
|
$lowerLineDiv = this.$html.find( '.mw-revslider-pointer-line-lower' ),
|
|
$underline = this.$html.find( '.mw-revslider-pointer-line-underline' ),
|
|
$sourcePointer = this.pointer.getView().getElement();
|
|
|
|
$lowerLineDiv.add( $upperLineDiv ).add( $underline )
|
|
.toggleClass( 'mw-revslider-lower-color', !isNewer )
|
|
.toggleClass( 'mw-revslider-upper-color', isNewer );
|
|
|
|
this.setCssProperties( $sliderView, $sourcePointer, $targetColumn );
|
|
|
|
const columnWidth = $targetColumn.width();
|
|
$upperLineDiv.addClass( 'mw-revslider-bottom-line' );
|
|
$underline.css( 'width', columnWidth + 'px' );
|
|
|
|
if ( this.targetColumnIsRightFromPointer( $sourcePointer, $targetColumn ) ) {
|
|
$upperLineDiv.addClass( 'mw-revslider-left-line' );
|
|
$lowerLineDiv.addClass( 'mw-revslider-right-line' );
|
|
|
|
$underline.css( {
|
|
'margin-right': -columnWidth / 2 + 'px',
|
|
'margin-left': 0,
|
|
float: 'right'
|
|
} );
|
|
} else {
|
|
$upperLineDiv.addClass( 'mw-revslider-right-line' );
|
|
$lowerLineDiv.addClass( 'mw-revslider-left-line' );
|
|
|
|
$underline.css( {
|
|
'margin-left': -columnWidth / 2 + 'px',
|
|
'margin-right': 0,
|
|
float: 'left'
|
|
} );
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Initializes the DOM element with the line-box for drawing the lines
|
|
*/
|
|
initialize: function () {
|
|
// eslint-disable-next-line mediawiki/class-doc
|
|
this.$html = $( '<div>' )
|
|
.addClass( 'mw-revslider-pointer-line ' + this.name )
|
|
.append(
|
|
// eslint-disable-next-line mediawiki/class-doc
|
|
$( '<div>' ).addClass( 'mw-revslider-pointer-line-upper ' + this.name ),
|
|
// eslint-disable-next-line mediawiki/class-doc
|
|
$( '<div>' ).addClass( 'mw-revslider-pointer-line-lower ' + this.name ),
|
|
// eslint-disable-next-line mediawiki/class-doc
|
|
$( '<div>' ).addClass( 'mw-revslider-pointer-line-underline ' + this.name )
|
|
);
|
|
},
|
|
|
|
/**
|
|
* Adds colored top-borders for the diff columns fitting the line colors between pointers and columns
|
|
*
|
|
* @param {boolean} [show=true]
|
|
* @private
|
|
*/
|
|
addColoredColumnBorders: function ( show ) {
|
|
show = show !== false;
|
|
$( '#mw-diff-otitle1' ).toggleClass( 'mw-revslider-older-diff-column', show );
|
|
$( '#mw-diff-ntitle1' ).toggleClass( 'mw-revslider-newer-diff-column', show );
|
|
},
|
|
|
|
/**
|
|
* Remove colored top-borders for the diff columns fitting the line colors between pointers and columns
|
|
*
|
|
* @private
|
|
*/
|
|
removeColoredColumnBorders: function () {
|
|
this.addColoredColumnBorders( false );
|
|
},
|
|
|
|
/**
|
|
* Sets the hooks to draw the column borders
|
|
*
|
|
* @private
|
|
*/
|
|
setColumnBorderHooks: function () {
|
|
mw.hook( 'wikipage.diff' ).add( this.addColoredColumnBorders );
|
|
mw.hook( 'revslider.expand' ).add( this.addColoredColumnBorders );
|
|
mw.hook( 'revslider.collapse' ).add( this.removeColoredColumnBorders.bind( this ) );
|
|
},
|
|
|
|
/**
|
|
* @return {jQuery}
|
|
*/
|
|
render: function () {
|
|
this.initialize();
|
|
this.setColumnBorderHooks();
|
|
return this.getElement();
|
|
},
|
|
|
|
/**
|
|
* @return {jQuery}
|
|
*/
|
|
getElement: function () {
|
|
return this.$html;
|
|
}
|
|
|
|
} );
|
|
|
|
module.exports = PointerLine;
|