jquery-ui/ui/widgets/datepicker.js

380 lines
8.4 KiB
JavaScript
Raw Normal View History

/*!
* jQuery UI Datepicker @VERSION
2012-07-04 13:08:08 +00:00
* http://jqueryui.com
2008-06-04 02:34:33 +00:00
*
* Copyright jQuery Foundation and other contributors
2012-08-09 14:13:24 +00:00
* Released under the MIT license.
* http://jquery.org/license
2008-06-04 02:34:33 +00:00
*/
//>>label: Datepicker
//>>group: Widgets
//>>description: Displays a calendar for input-based date selection.
//>>docs: http://api.jqueryui.com/datepicker/
//>>demos: http://jqueryui.com/datepicker/
//>>css.structure: ../../themes/base/core.css
//>>css.structure: ../../themes/base/calendar.css
//>>css.structure: ../../themes/base/datepicker.css
//>>css.theme: ../../themes/base/theme.css
( function( factory ) {
if ( typeof define === "function" && define.amd ) {
// AMD. Register as an anonymous module.
define( [
"jquery",
2015-07-15 13:40:38 +00:00
"globalize",
"globalize/date",
"./calendar",
2015-08-20 13:48:11 +00:00
"../widget",
"../position",
"../version",
"../keycode"
], factory );
} else {
// Browser globals
2015-07-15 13:40:38 +00:00
factory( jQuery, Globalize );
}
}( function( $, Globalize ) {
2008-06-04 02:34:33 +00:00
var widget = $.widget( "ui.datepicker", {
version: "@VERSION",
options: {
appendTo: null,
position: {
my: "left top",
at: "left bottom"
},
show: true,
hide: true,
// callbacks
beforeOpen: null,
close: null,
open: null,
select: null
},
2014-04-23 15:49:03 +00:00
calendarOptions: [ "buttons", "disabled", "dateFormat", "eachDay", "labels",
"locale", "max", "min", "numberOfMonths", "showWeek" ],
_create: function() {
this.suppressExpandOnFocus = false;
if ( $.type( this.options.max ) === "string" ) {
this.options.max = Globalize.parseDate( this.options.max, { raw: "yyyy-MM-dd" } );
}
if ( $.type( this.options.min ) === "string" ) {
this.options.min = Globalize.parseDate( this.options.min, { raw: "yyyy-MM-dd" } );
}
this._createCalendar();
2014-06-05 00:39:46 +00:00
this._on( this._inputEvents );
this._on( this.calendar, this._calendarEvents );
this._on( this.document, this._documentEvents );
},
_getCreateOptions: function() {
var max = this.element.attr( "max" ),
min = this.element.attr( "min" ),
options = {};
if ( max !== undefined ) {
2015-07-28 20:37:47 +00:00
options.max = Globalize.parseDate( max, { raw: "yyyy-MM-dd" } );
}
if ( min !== undefined ) {
2015-07-28 20:37:47 +00:00
options.min = Globalize.parseDate( min, { raw: "yyyy-MM-dd" } );
}
return options;
},
_createCalendar: function() {
var that = this,
globalize = new Globalize( this.options.locale );
this.calendar = $( "<div>" )
.addClass( "ui-front ui-datepicker" )
.appendTo( this._appendTo() );
// Initialize calendar widget
this.calendarInstance = this.calendar
.calendar( $.extend( {}, this.options, {
value: globalize.dateParser( this.options.dateFormat )( this.element.val() ),
select: function( event ) {
that.element.val( that.calendarInstance.value() );
that.close();
event.preventDefault();
that._focusTrigger();
that._trigger( "select", event );
return false;
}
} ) )
.calendar( "instance" );
2014-06-19 22:13:20 +00:00
this.calendarInstance.buttonClickContext = that.element[ 0 ];
this._setHiddenPicker();
this.element.attr( {
"aria-haspopup": true,
"aria-owns": this.calendar.attr( "id" )
} );
2014-06-05 00:39:46 +00:00
},
2014-06-05 00:39:46 +00:00
_inputEvents: {
keydown: function( event ) {
switch ( event.keyCode ) {
case $.ui.keyCode.TAB:
2014-06-05 00:39:46 +00:00
// Waiting for close() will make popup hide too late, which breaks tab key behavior
this.calendar.hide();
this.close( event );
break;
case $.ui.keyCode.ESCAPE:
if ( this.isOpen ) {
2014-06-05 00:39:46 +00:00
this.close( event );
}
2014-06-05 00:39:46 +00:00
break;
case $.ui.keyCode.ENTER:
2014-06-05 00:39:46 +00:00
case $.ui.keyCode.DOWN:
case $.ui.keyCode.UP:
this.open( event );
2014-06-05 00:39:46 +00:00
break;
}
},
keyup: function() {
if ( this.isValid() ) {
this.refresh();
}
},
mousedown: function( event ) {
if ( this.isOpen ) {
this.suppressExpandOnFocus = true;
2014-06-05 00:39:46 +00:00
this.close();
return;
}
this.open( event );
clearTimeout( this.closeTimer );
},
focus: function( event ) {
if ( !this.suppressExpandOnFocus && !this.isOpen ) {
this._delay( function() {
this.open( event );
} );
}
2014-06-05 00:39:46 +00:00
this._delay( function() {
this.suppressExpandOnFocus = false;
2014-06-05 00:39:46 +00:00
}, 100 );
},
blur: function() {
this.suppressExpandOnFocus = false;
2014-06-05 00:39:46 +00:00
}
},
2014-06-05 00:39:46 +00:00
_calendarEvents: {
focusout: function( event ) {
2014-06-05 00:39:46 +00:00
// use a timer to allow click to clear it and letting that
// handle the closing instead of opening again
// also allows tabbing inside the calendar without it closing
this.closeTimer = this._delay( function() {
this.close( event );
}, 150 );
},
focusin: function() {
clearTimeout( this.closeTimer );
},
mouseup: function() {
clearTimeout( this.closeTimer );
},
keydown: function( event ) {
2014-06-05 00:39:46 +00:00
if ( event.keyCode === $.ui.keyCode.ESCAPE && this.calendar.is( ":visible" ) ) {
this.close( event );
this._focusTrigger();
}
if ( event.keyCode === $.ui.keyCode.TAB && this.calendar.is( ":visible" ) ) {
var element = $( event.target );
// Reset focus when leaving widget
if (
( event.shiftKey && element.is( this.calendarInstance.prevButton ) ) ||
( !event.shiftKey && element.is( this.calendarInstance.grid.last() ) )
) {
this.close( event );
this._focusTrigger();
}
}
2014-06-05 00:39:46 +00:00
}
},
2014-06-05 00:39:46 +00:00
_documentEvents: {
mousedown: function( event ) {
if ( !this.isOpen ) {
return;
}
if ( !$( event.target ).closest( this.element.add( this.calendar ) ).length ) {
2014-06-05 00:39:46 +00:00
this.close( event );
2008-06-04 02:34:33 +00:00
}
2014-06-05 00:39:46 +00:00
}
2008-06-04 02:34:33 +00:00
},
2014-04-23 15:49:03 +00:00
_appendTo: function() {
var element = this.options.appendTo;
if ( element ) {
element = element.jquery || element.nodeType ?
$( element ) :
this.document.find( element ).eq( 0 );
}
if ( !element || !element[ 0 ] ) {
element = this.element.closest( ".ui-front, dialog" );
}
if ( !element.length ) {
2014-04-23 15:49:03 +00:00
element = this.document[ 0 ].body;
}
return element;
2008-06-04 02:34:33 +00:00
},
_focusTrigger: function() {
this.suppressExpandOnFocus = true;
this.element.focus();
2008-06-04 02:34:33 +00:00
},
2014-04-23 15:49:03 +00:00
refresh: function() {
this.calendarInstance.option( "value", this._getParsedValue() );
2008-06-04 02:34:33 +00:00
},
2014-04-23 15:49:03 +00:00
open: function( event ) {
if ( this.isOpen ) {
return;
}
if ( this._trigger( "beforeOpen", event ) === false ) {
return;
}
this.calendarInstance.refresh();
this.calendar
.attr( {
"aria-hidden": false,
"aria-expanded": true
} )
.show()
.position( this._buildPosition() )
.hide();
this._show( this.calendar, this.options.show );
this.isOpen = true;
this._trigger( "open", event );
this._delay( function() {
this.calendarInstance.grid.focus();
} );
},
2014-04-23 15:49:03 +00:00
close: function( event ) {
this._setHiddenPicker();
this._hide( this.calendar, this.options.hide );
this.isOpen = false;
this._trigger( "close", event );
2008-06-04 02:34:33 +00:00
},
2014-04-23 15:49:03 +00:00
_setHiddenPicker: function() {
this.calendar.attr( {
"aria-hidden": true,
"aria-expanded": false
} );
2008-06-04 02:34:33 +00:00
},
2014-04-23 15:49:03 +00:00
_buildPosition: function() {
return $.extend( { of: this.element }, this.options.position );
},
2014-04-23 15:49:03 +00:00
value: function( value ) {
if ( arguments.length ) {
this.valueAsDate( this.calendarInstance._parse( value ) );
} else {
return this._getParsedValue() ? this.element.val() : null;
}
},
2014-04-23 15:49:03 +00:00
valueAsDate: function( value ) {
if ( arguments.length ) {
if ( this.calendarInstance._isValid( value ) ) {
this.calendarInstance.valueAsDate( value );
this.element.val( this.calendarInstance._format( value ) );
}
} else {
return this._getParsedValue();
}
},
2014-04-23 15:49:03 +00:00
2014-01-03 14:07:38 +00:00
isValid: function() {
return this.calendarInstance._isValid( this._getParsedValue() );
2014-01-03 14:07:38 +00:00
},
2014-04-23 15:49:03 +00:00
_destroy: function() {
this.calendarInstance.destroy();
this.calendar.remove();
this.element.removeAttr( "aria-haspopup aria-owns" );
},
2014-04-23 15:49:03 +00:00
widget: function() {
return this.calendar;
},
2014-04-23 15:49:03 +00:00
_getParsedValue: function() {
return this.calendarInstance._parse( this.element.val() );
},
_setOption: function( key, value ) {
this._super( key, value );
if ( $.inArray( key, this.calendarOptions ) !== -1 ) {
this.calendarInstance.option( key, value );
}
if ( key === "appendTo" ) {
this.calendar.appendTo( this._appendTo() );
}
if ( key === "locale" || key === "dateFormat" ) {
this.element.val( this.calendarInstance.value() );
}
if ( key === "disabled" ) {
this.element
.prop( "disabled", value )
.toggleClass( "ui-state-disabled", value )
.attr( "aria-disabled", value );
if ( value ) {
this.close();
}
}
if ( key === "position" ) {
this.calendar.position( this._buildPosition() );
}
2008-06-04 02:34:33 +00:00
}
} );
$.each( $.ui.datepicker.prototype.calendarOptions, function( index, option ) {
$.ui.datepicker.prototype.options[ option ] = $.ui.calendar.prototype.options[ option ];
} );
return widget;
} ) );