* @class
* @extends OO.ui.Widget
* @mixins OO.ui.mixin.TabIndexedElement
+ * @mixins OO.ui.mixin.FloatableElement
*
* @constructor
* @param {Object} [config] Configuration options
// Mixin constructors
OO.ui.mixin.TabIndexedElement.call( this, $.extend( {}, config, { $tabIndexed: this.$element } ) );
+ OO.ui.mixin.FloatableElement.call( this, config );
// Properties
this.precision = config.precision || 'day';
OO.inheritClass( mw.widgets.CalendarWidget, OO.ui.Widget );
OO.mixinClass( mw.widgets.CalendarWidget, OO.ui.mixin.TabIndexedElement );
+ OO.mixinClass( mw.widgets.CalendarWidget, OO.ui.mixin.FloatableElement );
/* Events */
* internally and for dates accepted by #setDate and returned by #getDate.
*
* @private
- * @returns {string} Format
+ * @return {string} Format
*/
mw.widgets.CalendarWidget.prototype.getDateFormat = function () {
return {
* Get the date precision this calendar uses, 'day' or 'month'.
*
* @private
- * @returns {string} Precision, 'day' or 'month'
+ * @return {string} Precision, 'day' or 'month'
*/
mw.widgets.CalendarWidget.prototype.getPrecision = function () {
return this.precision;
* Get list of possible display layers.
*
* @private
- * @returns {string[]} Layers
+ * @return {string[]} Layers
*/
mw.widgets.CalendarWidget.prototype.getDisplayLayers = function () {
return [ 'month', 'year', 'duodecade' ].slice( this.precision === 'month' ? 1 : 0 );
* Update the calendar.
*
* @private
- * @param {string|null} [fade=null] Direction in which to fade out current calendar contents, 'previous',
- * 'next' or 'up'
- * @returns {string} Format
+ * @param {string|null} [fade=null] Direction in which to fade out current calendar contents,
+ * 'previous', 'next', 'up' or 'down'; or 'auto', which has the same result as 'previous' or
+ * 'next' depending on whether the current date is later or earlier than the previous.
*/
mw.widgets.CalendarWidget.prototype.updateUI = function ( fade ) {
var items, today, selected, currentMonth, currentYear, currentDay, i, needsFade,
return;
}
+ if ( fade === 'auto' ) {
+ if ( !this.previousMoment ) {
+ fade = null;
+ } else if ( this.previousMoment.isBefore( this.moment, this.precision === 'month' ? 'month' : 'day' ) ) {
+ fade = 'next';
+ } else if ( this.previousMoment.isAfter( this.moment, this.precision === 'month' ? 'month' : 'day' ) ) {
+ fade = 'previous';
+ } else {
+ fade = null;
+ }
+ }
+
items = [];
if ( this.$oldBody ) {
this.$oldBody.remove();
*/
mw.widgets.CalendarWidget.prototype.onBodyClick = function ( e ) {
var
- previousMoment = moment( this.moment ),
$target = $( e.target ),
layers = this.getDisplayLayers(),
currentLayer = layers.indexOf( this.displayLayer );
}
if ( currentLayer === 0 ) {
this.setDateFromMoment();
- this.updateUI(
- this.precision === 'day' && this.moment.isBefore( previousMoment, 'month' ) ? 'previous' :
- this.precision === 'day' && this.moment.isAfter( previousMoment, 'month' ) ? 'next' : null
- );
+ this.updateUI( 'auto' );
} else {
// One layer down
this.displayLayer = layers[ currentLayer - 1 ];
* Reset the user interface of this widget to reflect selected date.
*/
mw.widgets.CalendarWidget.prototype.resetUI = function () {
- this.moment = moment( this.getDate(), this.getDateFormat() );
+ this.moment = this.getDate() !== null ? moment( this.getDate(), this.getDateFormat() ) : moment();
this.displayLayer = this.getDisplayLayers()[ 0 ];
this.updateUI();
};
* Get current date, in the format 'YYYY-MM-DD' or 'YYYY-MM', depending on precision. Digits will
* not be localised.
*
- * @returns {string|null} Date string
+ * @return {string|null} Date string
*/
mw.widgets.CalendarWidget.prototype.getDate = function () {
return this.date;
/*jshint +W024*/
nextDirectionKey = dir === 'ltr' ? OO.ui.Keys.RIGHT : OO.ui.Keys.LEFT,
prevDirectionKey = dir === 'ltr' ? OO.ui.Keys.LEFT : OO.ui.Keys.RIGHT,
- updateInDirection = null;
+ changed = true;
if ( !this.isDisabled() ) {
switch ( e.which ) {
case prevDirectionKey:
this.moment.subtract( 1, this.precision === 'month' ? 'month' : 'day' );
- updateInDirection = 'previous';
break;
case nextDirectionKey:
this.moment.add( 1, this.precision === 'month' ? 'month' : 'day' );
- updateInDirection = 'next';
break;
case OO.ui.Keys.UP:
this.moment.subtract( 1, this.precision === 'month' ? 'month' : 'week' );
- updateInDirection = 'previous';
break;
case OO.ui.Keys.DOWN:
this.moment.add( 1, this.precision === 'month' ? 'month' : 'week' );
- updateInDirection = 'next';
break;
case OO.ui.Keys.PAGEUP:
this.moment.subtract( 1, this.precision === 'month' ? 'year' : 'month' );
- updateInDirection = 'previous';
break;
case OO.ui.Keys.PAGEDOWN:
this.moment.add( 1, this.precision === 'month' ? 'year' : 'month' );
- updateInDirection = 'next';
+ break;
+ default:
+ changed = false;
break;
}
- if ( updateInDirection ) {
+ if ( changed ) {
this.displayLayer = this.getDisplayLayers()[ 0 ];
this.setDateFromMoment();
- this.updateUI( updateInDirection );
+ this.updateUI( 'auto' );
return false;
}
}
};
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.CalendarWidget.prototype.toggle = function ( visible ) {
+ // Parent method
+ mw.widgets.CalendarWidget.parent.prototype.toggle.call( this, visible );
+
+ if ( this.$floatableContainer ) {
+ this.togglePositioning( this.isVisible() );
+ }
+
+ return this;
+ };
+
}( jQuery, mediaWiki ) );