2020-06-16 14:13:36 +00:00
|
|
|
/**
|
|
|
|
* @external Pointer
|
|
|
|
* @external Slider
|
|
|
|
*/
|
2018-11-16 16:33:52 +00:00
|
|
|
( function () {
|
2016-06-17 13:06:12 +00:00
|
|
|
/**
|
|
|
|
* Module containing presentation logic for the revision pointers
|
|
|
|
*
|
2020-06-16 14:13:36 +00:00
|
|
|
* @class PointerView
|
2016-06-17 13:06:12 +00:00
|
|
|
* @param {Pointer} pointer
|
2016-07-02 20:14:00 +00:00
|
|
|
* @param {string} name
|
2016-06-17 13:06:12 +00:00
|
|
|
* @constructor
|
|
|
|
*/
|
2016-07-02 20:14:00 +00:00
|
|
|
var PointerView = function ( pointer, name ) {
|
2016-05-10 12:42:05 +00:00
|
|
|
this.pointer = pointer;
|
2016-07-02 20:14:00 +00:00
|
|
|
this.name = name;
|
2016-05-03 11:26:42 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
$.extend( PointerView.prototype, {
|
|
|
|
/**
|
|
|
|
* @type {string}
|
|
|
|
*/
|
2016-07-02 20:14:00 +00:00
|
|
|
name: '',
|
2016-05-03 11:26:42 +00:00
|
|
|
|
2016-05-10 12:42:05 +00:00
|
|
|
/**
|
|
|
|
* @type {Pointer}
|
|
|
|
*/
|
2016-06-17 13:06:12 +00:00
|
|
|
pointer: null,
|
2016-05-10 12:42:05 +00:00
|
|
|
|
2016-05-03 11:26:42 +00:00
|
|
|
/**
|
|
|
|
* @type {jQuery}
|
|
|
|
*/
|
|
|
|
$html: null,
|
|
|
|
|
2016-06-17 13:06:12 +00:00
|
|
|
/**
|
|
|
|
* Initializes the DOM element
|
|
|
|
*/
|
2016-05-03 11:26:42 +00:00
|
|
|
initialize: function () {
|
2020-06-16 14:13:36 +00:00
|
|
|
// eslint-disable-next-line mediawiki/class-doc
|
2016-06-03 08:55:17 +00:00
|
|
|
this.$html = $( '<div>' )
|
2016-07-02 20:14:00 +00:00
|
|
|
.addClass( 'mw-revslider-pointer mw-revslider-pointer-cursor ' + this.name );
|
2016-05-03 11:26:42 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return {jQuery}
|
|
|
|
*/
|
|
|
|
render: function () {
|
|
|
|
this.initialize();
|
|
|
|
return this.getElement();
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return {jQuery}
|
|
|
|
*/
|
|
|
|
getElement: function () {
|
|
|
|
return this.$html;
|
|
|
|
},
|
|
|
|
|
2016-06-17 13:06:12 +00:00
|
|
|
/**
|
2017-07-11 08:17:24 +00:00
|
|
|
* Returns whether a pointer is the newer revision pointer based on its CSS class
|
2016-06-17 13:06:12 +00:00
|
|
|
*
|
|
|
|
* @return {boolean}
|
|
|
|
*/
|
2017-07-11 08:17:24 +00:00
|
|
|
isNewerPointer: function () {
|
|
|
|
return this.getElement().hasClass( 'mw-revslider-pointer-newer' );
|
2016-05-26 10:30:12 +00:00
|
|
|
},
|
|
|
|
|
2016-06-17 13:06:12 +00:00
|
|
|
/**
|
2017-07-11 08:17:24 +00:00
|
|
|
* Returns the offset (margin-left) depending on whether its the newer or older pointer
|
2016-06-17 13:06:12 +00:00
|
|
|
*
|
|
|
|
* @return {number}
|
|
|
|
*/
|
2016-05-03 11:26:42 +00:00
|
|
|
getOffset: function () {
|
2017-07-11 08:17:24 +00:00
|
|
|
return this.isNewerPointer() ? 16 : 0;
|
2016-05-10 12:42:05 +00:00
|
|
|
},
|
|
|
|
|
2016-05-21 00:10:08 +00:00
|
|
|
// For correct positioning of the pointer in the RTL mode the left position is flipped in the container.
|
2017-03-31 15:15:03 +00:00
|
|
|
// 30 pixel have to be added to cover the arrow and its margin.
|
2016-05-21 00:10:08 +00:00
|
|
|
getAdjustedLeftPositionWhenRtl: function ( pos ) {
|
2017-03-31 15:15:03 +00:00
|
|
|
return this.getElement().offsetParent().width() - pos - 30;
|
2016-05-21 00:10:08 +00:00
|
|
|
},
|
|
|
|
|
2017-07-11 11:41:16 +00:00
|
|
|
/**
|
|
|
|
* Sets the HTML attribute for the position
|
|
|
|
*
|
|
|
|
* @param {number} pos
|
|
|
|
*/
|
|
|
|
setDataPositionAttribute: function ( pos ) {
|
|
|
|
if ( this.getElement() === null ) {
|
|
|
|
this.initialize();
|
|
|
|
}
|
|
|
|
this.getElement().attr( 'data-pos', pos );
|
|
|
|
},
|
|
|
|
|
2016-06-17 13:06:12 +00:00
|
|
|
/**
|
|
|
|
* Moves the pointer to a position
|
|
|
|
*
|
|
|
|
* @param {number} posInPx
|
2018-05-19 14:21:55 +00:00
|
|
|
* @param {number} revisionWidth
|
2018-05-28 15:11:24 +00:00
|
|
|
* @param {number} [baseDuration] Duration per revisionWidth, is adjusted by log() distance
|
2016-06-17 13:06:12 +00:00
|
|
|
* @return {jQuery}
|
|
|
|
*/
|
2018-05-28 15:11:24 +00:00
|
|
|
animateTo: function ( posInPx, revisionWidth, baseDuration ) {
|
2018-05-19 14:21:55 +00:00
|
|
|
var animatePos = { left: posInPx },
|
|
|
|
currentPos = this.getElement().position(),
|
|
|
|
distance, duration;
|
|
|
|
baseDuration = typeof baseDuration !== 'undefined' ? baseDuration : 100;
|
2016-05-21 00:10:08 +00:00
|
|
|
if ( this.getElement().css( 'direction' ) === 'rtl' ) {
|
|
|
|
animatePos.left = this.getAdjustedLeftPositionWhenRtl( animatePos.left );
|
|
|
|
}
|
2018-05-19 14:21:55 +00:00
|
|
|
distance = Math.abs( animatePos.left - currentPos.left ) / revisionWidth;
|
|
|
|
duration = baseDuration * Math.log( 5 + distance );
|
|
|
|
return this.getElement().animate( animatePos, duration, 'linear' );
|
2016-05-10 12:42:05 +00:00
|
|
|
},
|
|
|
|
|
2016-06-17 13:06:12 +00:00
|
|
|
/**
|
|
|
|
* Slides the pointer to the revision it's pointing at
|
|
|
|
*
|
|
|
|
* @param {Slider} slider
|
2018-05-28 15:11:24 +00:00
|
|
|
* @param {number} [duration]
|
2016-06-17 13:06:12 +00:00
|
|
|
* @return {jQuery}
|
|
|
|
*/
|
2016-05-10 14:01:39 +00:00
|
|
|
slideToPosition: function ( slider, duration ) {
|
2017-03-27 19:04:31 +00:00
|
|
|
var relativePos = this.pointer.getPosition() - slider.getOldestVisibleRevisionIndex();
|
2018-05-28 15:11:24 +00:00
|
|
|
return this.animateTo( ( relativePos - 1 ) * slider.getView().revisionWidth, slider.getView().revisionWidth, duration );
|
2016-05-10 12:42:05 +00:00
|
|
|
},
|
|
|
|
|
2016-06-17 13:06:12 +00:00
|
|
|
/**
|
|
|
|
* Slides the pointer to the side of the slider when it's not in the current range of revisions
|
|
|
|
*
|
|
|
|
* @param {Slider} slider
|
|
|
|
* @param {boolean} posBeforeSlider
|
2018-05-28 15:11:24 +00:00
|
|
|
* @param {number} [duration]
|
2016-06-17 13:06:12 +00:00
|
|
|
* @return {jQuery}
|
|
|
|
*/
|
2016-05-10 14:01:39 +00:00
|
|
|
slideToSide: function ( slider, posBeforeSlider, duration ) {
|
2016-05-10 12:42:05 +00:00
|
|
|
if ( posBeforeSlider ) {
|
2018-05-28 15:11:24 +00:00
|
|
|
return this.animateTo( this.getOffset() - 2 * slider.getView().revisionWidth, slider.getView().revisionWidth, duration );
|
2016-05-10 12:42:05 +00:00
|
|
|
} else {
|
2018-05-28 15:11:24 +00:00
|
|
|
return this.animateTo( slider.getRevisionsPerWindow() * slider.getView().revisionWidth + this.getOffset(), slider.getView().revisionWidth, duration );
|
2016-05-10 12:42:05 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2016-06-17 13:06:12 +00:00
|
|
|
/**
|
|
|
|
* Decides based on its position whether the pointer should be sliding to the side or to its position
|
|
|
|
*
|
|
|
|
* @param {Slider} slider
|
2018-05-28 15:11:24 +00:00
|
|
|
* @param {number} [duration]
|
2016-06-17 13:06:12 +00:00
|
|
|
* @return {jQuery}
|
|
|
|
*/
|
2016-05-10 14:01:39 +00:00
|
|
|
slideToSideOrPosition: function ( slider, duration ) {
|
2017-03-27 19:04:31 +00:00
|
|
|
var firstVisibleRev = slider.getOldestVisibleRevisionIndex(),
|
2016-05-10 12:42:05 +00:00
|
|
|
posBeforeSlider = this.pointer.getPosition() < firstVisibleRev,
|
2016-05-12 15:19:14 +00:00
|
|
|
isVisible = !posBeforeSlider && this.pointer.getPosition() <= firstVisibleRev + slider.getRevisionsPerWindow();
|
2016-05-10 12:42:05 +00:00
|
|
|
if ( isVisible ) {
|
2016-05-20 10:42:01 +00:00
|
|
|
return this.slideToPosition( slider, duration );
|
2016-05-10 12:42:05 +00:00
|
|
|
} else {
|
2016-05-20 10:42:01 +00:00
|
|
|
return this.slideToSide( slider, posBeforeSlider, duration );
|
2016-05-10 12:42:05 +00:00
|
|
|
}
|
2016-05-03 11:26:42 +00:00
|
|
|
}
|
|
|
|
} );
|
|
|
|
|
2020-03-29 20:54:02 +00:00
|
|
|
module.exports = PointerView;
|
2018-11-16 16:33:52 +00:00
|
|
|
}() );
|