* @class
* @extends OO.ui.Widget
* @mixins OO.ui.mixin.TabIndexedElement
+ * @mixins OO.ui.mixin.FloatableElement
*
* @constructor
* @param {Object} [config] Configuration options
+ * @cfg {boolean} [lazyInitOnToggle=false] Don't build most of the interface until
+ * `.toggle( true )` is called. Meant to be used when the calendar is not immediately visible.
* @cfg {string} [precision='day'] Date precision to use, 'day' or 'month'
* @cfg {string|null} [date=null] Day or month date (depending on `precision`), in the format
* 'YYYY-MM-DD' or 'YYYY-MM'. When null, the calendar will show today's date, but not select
// Mixin constructors
OO.ui.mixin.TabIndexedElement.call( this, $.extend( {}, config, { $tabIndexed: this.$element } ) );
+ OO.ui.mixin.FloatableElement.call( this, config );
// Properties
+ this.lazyInitOnToggle = !!config.lazyInitOnToggle;
this.precision = config.precision || 'day';
// Currently selected date (day or month)
this.date = null;
this.$bodyOuterWrapper = $( '<div>' ).addClass( 'mw-widget-calendarWidget-body-outer-wrapper' );
this.$bodyWrapper = $( '<div>' ).addClass( 'mw-widget-calendarWidget-body-wrapper' );
this.$body = $( '<div>' ).addClass( 'mw-widget-calendarWidget-body' );
- this.labelButton = new OO.ui.ButtonWidget( {
- tabIndex: -1,
- label: '',
- framed: false,
- classes: [ 'mw-widget-calendarWidget-labelButton' ]
- } );
- this.upButton = new OO.ui.ButtonWidget( {
- tabIndex: -1,
- framed: false,
- icon: 'collapse',
- classes: [ 'mw-widget-calendarWidget-upButton' ]
- } );
- this.prevButton = new OO.ui.ButtonWidget( {
- tabIndex: -1,
- framed: false,
- icon: 'previous',
- classes: [ 'mw-widget-calendarWidget-prevButton' ]
- } );
- this.nextButton = new OO.ui.ButtonWidget( {
- tabIndex: -1,
- framed: false,
- icon: 'next',
- classes: [ 'mw-widget-calendarWidget-nextButton' ]
- } );
// Events
- this.labelButton.connect( this, { click: 'onUpButtonClick' } );
- this.upButton.connect( this, { click: 'onUpButtonClick' } );
- this.prevButton.connect( this, { click: 'onPrevButtonClick' } );
- this.nextButton.connect( this, { click: 'onNextButtonClick' } );
this.$element.on( {
focus: this.onFocus.bind( this ),
mousedown: this.onClick.bind( this ),
this.$element
.addClass( 'mw-widget-calendarWidget' )
.append( this.$header, this.$bodyOuterWrapper.append( this.$bodyWrapper.append( this.$body ) ) );
- this.$header.append(
- this.prevButton.$element,
- this.nextButton.$element,
- this.upButton.$element,
- this.labelButton.$element
- );
+ if ( !this.lazyInitOnToggle ) {
+ this.buildHeaderButtons();
+ }
this.setDate( config.date !== undefined ? config.date : null );
};
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 );
var items, today, selected, currentMonth, currentYear, currentDay, i, needsFade,
$bodyWrapper = this.$bodyWrapper;
+ if ( this.lazyInitOnToggle ) {
+ // We're being called from the constructor and not being shown yet, do nothing
+ return;
+ }
+
if (
this.displayLayer === this.previousDisplayLayer &&
this.date === this.previousDate &&
this.$body.on( 'click', this.onBodyClick.bind( this ) );
};
+ /**
+ * Construct and display buttons to navigate the calendar.
+ *
+ * @private
+ */
+ mw.widgets.CalendarWidget.prototype.buildHeaderButtons = function () {
+ this.labelButton = new OO.ui.ButtonWidget( {
+ tabIndex: -1,
+ label: '',
+ framed: false,
+ classes: [ 'mw-widget-calendarWidget-labelButton' ]
+ } );
+ this.upButton = new OO.ui.ButtonWidget( {
+ tabIndex: -1,
+ framed: false,
+ icon: 'collapse',
+ classes: [ 'mw-widget-calendarWidget-upButton' ]
+ } );
+ this.prevButton = new OO.ui.ButtonWidget( {
+ tabIndex: -1,
+ framed: false,
+ icon: 'previous',
+ classes: [ 'mw-widget-calendarWidget-prevButton' ]
+ } );
+ this.nextButton = new OO.ui.ButtonWidget( {
+ tabIndex: -1,
+ framed: false,
+ icon: 'next',
+ classes: [ 'mw-widget-calendarWidget-nextButton' ]
+ } );
+
+ this.labelButton.connect( this, { click: 'onUpButtonClick' } );
+ this.upButton.connect( this, { click: 'onUpButtonClick' } );
+ this.prevButton.connect( this, { click: 'onPrevButtonClick' } );
+ this.nextButton.connect( this, { click: 'onNextButtonClick' } );
+
+ this.$header.append(
+ this.prevButton.$element,
+ this.nextButton.$element,
+ this.upButton.$element,
+ this.labelButton.$element
+ );
+ };
+
/**
* Handle click events on the "up" button, switching to less precise view.
*
* 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;
}
};
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.CalendarWidget.prototype.toggle = function ( visible ) {
+ if ( this.lazyInitOnToggle && visible ) {
+ this.lazyInitOnToggle = false;
+ this.buildHeaderButtons();
+ this.updateUI();
+ }
+
+ // Parent method
+ mw.widgets.CalendarWidget.parent.prototype.toggle.call( this, visible );
+
+ if ( this.$floatableContainer ) {
+ this.togglePositioning( this.isVisible() );
+ }
+
+ return this;
+ };
+
}( jQuery, mediaWiki ) );