diff --git a/Gruntfile.js b/Gruntfile.js
index 6a711962b82..6e9c8967ac4 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -28,6 +28,7 @@ var
"core",
"accordion",
"autocomplete",
+ "calendar",
"button",
"datepicker",
"dialog",
diff --git a/build/tasks/testswarm.js b/build/tasks/testswarm.js
index a147b8f573c..0d500ef09dd 100644
--- a/build/tasks/testswarm.js
+++ b/build/tasks/testswarm.js
@@ -14,6 +14,7 @@ var versions = {
"Accordion": "accordion/accordion.html",
"Autocomplete": "autocomplete/autocomplete.html",
"Button": "button/button.html",
+ "Calendar": "calendar/calendar.html",
"Core": "core/core.html",
"Core_deprecated": "core/core_deprecated.html",
"Datepicker": "datepicker/datepicker.html",
diff --git a/demos/datepicker/buttonbar.html b/demos/calendar/buttonbar.html
similarity index 57%
rename from demos/datepicker/buttonbar.html
rename to demos/calendar/buttonbar.html
index 040ec1112ec..7a2098b3f6d 100644
--- a/demos/datepicker/buttonbar.html
+++ b/demos/calendar/buttonbar.html
@@ -2,24 +2,33 @@
- jQuery UI Datepicker - Display button bar
+ jQuery UI Calendar - Display button bar
+
+
+
-
+
+
+
-Date:
+
Display a button for selecting Today's date and a Done button for closing the calendar with the boolean showButtonPanel
option. Each button is enabled by default when the bar is displayed, but can be turned off with additional options. Button text is customizable.
diff --git a/demos/calendar/date-formats.html b/demos/calendar/date-formats.html
new file mode 100644
index 00000000000..e3f4e045762
--- /dev/null
+++ b/demos/calendar/date-formats.html
@@ -0,0 +1,52 @@
+
+
+
+
+
jQuery UI Calendar - Format date
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Format options:
+
+ Short - M/d/yy in "en" locale
+ Long - MMMM d, y in "en" locale
+ ISO 8601 - yyyy-MM-dd
+
+
+
+
+
Display date feedback in a variety of ways. Choose a date format from the dropdown, then click on the input and select a date to see it in that format.
+
+
+
diff --git a/demos/calendar/default.html b/demos/calendar/default.html
new file mode 100644
index 00000000000..8c77174b435
--- /dev/null
+++ b/demos/calendar/default.html
@@ -0,0 +1,31 @@
+
+
+
+
+
jQuery UI Calendar - Default functionality
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
The calendar is tied to a standard form input field. Focus on the input (click, or use the tab key) to open an interactive calendar in a small overlay. Choose a date, click elsewhere on the page (blur the input), or hit the Esc key to close. If a date is chosen, feedback is shown as the input's value.
+
+
+
diff --git a/demos/datepicker/dropdown-month-year.html b/demos/calendar/dropdown-month-year.html
similarity index 61%
rename from demos/datepicker/dropdown-month-year.html
rename to demos/calendar/dropdown-month-year.html
index 8668018d96e..050a89157ff 100644
--- a/demos/datepicker/dropdown-month-year.html
+++ b/demos/calendar/dropdown-month-year.html
@@ -2,16 +2,21 @@
-
jQuery UI Datepicker - Display month & year menus
+
jQuery UI Calendar - Display month & year menus
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ German (Deutsch)
+ English
+
+
+
+
Localize the calendar calendar language and format (English / Western formatting is the default). The calendar includes built-in support for languages that read right-to-left, such as Arabic and Hebrew.
+
+
+
diff --git a/demos/calendar/min-max.html b/demos/calendar/min-max.html
new file mode 100644
index 00000000000..5b9b5fd825f
--- /dev/null
+++ b/demos/calendar/min-max.html
@@ -0,0 +1,38 @@
+
+
+
+
+
jQuery UI Calendar - Restrict date range
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Restrict the range of selectable dates with the min
and max
options. Set the beginning and end dates as actual dates (new Date(2009, 1 - 1, 26)).
+
+
+
diff --git a/demos/datepicker/multiple-calendars.html b/demos/calendar/multiple-months.html
similarity index 52%
rename from demos/datepicker/multiple-calendars.html
rename to demos/calendar/multiple-months.html
index 716b6c68ef6..f67609d143e 100644
--- a/demos/datepicker/multiple-calendars.html
+++ b/demos/calendar/multiple-months.html
@@ -2,16 +2,21 @@
-
jQuery UI Datepicker - Display multiple months
+
jQuery UI Calendar - Display multiple months
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
The calendar can show dates that come from other than the main month
+ being displayed. These other dates can also be made selectable.
+
+
+
diff --git a/demos/calendar/show-week.html b/demos/calendar/show-week.html
new file mode 100644
index 00000000000..08687aa0dea
--- /dev/null
+++ b/demos/calendar/show-week.html
@@ -0,0 +1,35 @@
+
+
+
+
+
jQuery UI Calendar - Show week of the year
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
The calendar can show the week of the year. The calculation follows
+ Unicode CLDR specification .
+ This means that some days from one year may be placed into weeks 'belonging' to another year.
+
+
+
diff --git a/demos/datepicker/alt-field.html b/demos/datepicker/alt-field.html
index 7e3b50a6de9..9518e48a73c 100644
--- a/demos/datepicker/alt-field.html
+++ b/demos/datepicker/alt-field.html
@@ -5,15 +5,23 @@
jQuery UI Datepicker - Populate alternate field
+
+
+
+
+
+
diff --git a/demos/datepicker/animation.html b/demos/datepicker/animation.html
index 990fd6262e3..02c01c21f6a 100644
--- a/demos/datepicker/animation.html
+++ b/demos/datepicker/animation.html
@@ -5,8 +5,15 @@
jQuery UI Datepicker - Animations
+
+
+
+
+
+
+
@@ -14,13 +21,16 @@
-
@@ -31,16 +41,15 @@
Animations:
- Show (default)
- Slide down
- Fade in
+ Fade in/out (default)
+ Slide down/up
Blind (UI Effect)
Bounce (UI Effect)
Clip (UI Effect)
Drop (UI Effect)
Fold (UI Effect)
Slide (UI Effect)
- None
+ None
diff --git a/demos/datepicker/date-formats.html b/demos/datepicker/date-formats.html
index 39be9aa1522..d8ff62d1c28 100644
--- a/demos/datepicker/date-formats.html
+++ b/demos/datepicker/date-formats.html
@@ -5,15 +5,31 @@
jQuery UI Datepicker - Format date
+
+
+
+
+
+
@@ -24,12 +40,9 @@
Format options:
- Default - mm/dd/yy
- ISO 8601 - yy-mm-dd
- Short - d M, y
- Medium - d MM, y
- Full - DD, d MM, yy
- With text - 'day' d 'of' MM 'in the year' yy
+ Short - M/d/yy in "en" locale
+ Long - MMMM d, y in "en" locale
+ ISO 8601 - yyyy-MM-dd
diff --git a/demos/datepicker/date-range.html b/demos/datepicker/date-range.html
deleted file mode 100644
index 34c64a9b2e0..00000000000
--- a/demos/datepicker/date-range.html
+++ /dev/null
@@ -1,44 +0,0 @@
-
-
-
-
-
jQuery UI Datepicker - Select a Date Range
-
-
-
-
-
-
-
-
-
-
-
From
-
-
to
-
-
-
-
Select the date range to search for.
-
-
-
diff --git a/demos/datepicker/datepicker-ar.js b/demos/datepicker/datepicker-ar.js
deleted file mode 100644
index fc6d2a883c0..00000000000
--- a/demos/datepicker/datepicker-ar.js
+++ /dev/null
@@ -1,36 +0,0 @@
-/* Arabic Translation for jQuery UI date picker plugin. */
-/* Khaled Alhourani -- me@khaledalhourani.com */
-/* NOTE: monthNames are the original months names and they are the Arabic names, not the new months name فبراير - يناير and there isn't any Arabic roots for these months */
-(function( factory ) {
- if ( typeof define === "function" && define.amd ) {
-
- // AMD. Register as an anonymous module.
- define([ "../jquery.ui.datepicker" ], factory );
- } else {
-
- // Browser globals
- factory( jQuery.datepicker );
- }
-}(function( datepicker ) {
- datepicker.regional['ar'] = {
- closeText: 'إغلاق',
- prevText: '<السابق',
- nextText: 'التالي>',
- currentText: 'اليوم',
- monthNames: ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'مايو', 'حزيران',
- 'تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'],
- monthNamesShort: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
- dayNames: ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
- dayNamesShort: ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
- dayNamesMin: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
- weekHeader: 'أسبوع',
- dateFormat: 'dd/mm/yy',
- firstDay: 6,
- isRTL: true,
- showMonthAfterYear: false,
- yearSuffix: ''};
- datepicker.setDefaults(datepicker.regional['ar']);
-
- return datepicker.regional['ar'];
-
-}));
diff --git a/demos/datepicker/datepicker-fr.js b/demos/datepicker/datepicker-fr.js
deleted file mode 100644
index 33fa80d48f3..00000000000
--- a/demos/datepicker/datepicker-fr.js
+++ /dev/null
@@ -1,38 +0,0 @@
-/* French initialisation for the jQuery UI date picker plugin. */
-/* Written by Keith Wood (kbwood{at}iinet.com.au),
- Stéphane Nahmani (sholby@sholby.net),
- Stéphane Raimbault
*/
-(function( factory ) {
- if ( typeof define === "function" && define.amd ) {
-
- // AMD. Register as an anonymous module.
- define([ "../jquery.ui.datepicker" ], factory );
- } else {
-
- // Browser globals
- factory( jQuery.datepicker );
- }
-}(function( datepicker ) {
- datepicker.regional['fr'] = {
- closeText: 'Fermer',
- prevText: 'Précédent',
- nextText: 'Suivant',
- currentText: 'Aujourd\'hui',
- monthNames: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin',
- 'juillet', 'août', 'septembre', 'octobre', 'novembre', 'décembre'],
- monthNamesShort: ['janv.', 'févr.', 'mars', 'avril', 'mai', 'juin',
- 'juil.', 'août', 'sept.', 'oct.', 'nov.', 'déc.'],
- dayNames: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi'],
- dayNamesShort: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
- dayNamesMin: ['D','L','M','M','J','V','S'],
- weekHeader: 'Sem.',
- dateFormat: 'dd/mm/yy',
- firstDay: 1,
- isRTL: false,
- showMonthAfterYear: false,
- yearSuffix: ''};
- datepicker.setDefaults(datepicker.regional['fr']);
-
- return datepicker.regional['fr'];
-
-}));
diff --git a/demos/datepicker/datepicker-he.js b/demos/datepicker/datepicker-he.js
deleted file mode 100644
index bf58038f586..00000000000
--- a/demos/datepicker/datepicker-he.js
+++ /dev/null
@@ -1,36 +0,0 @@
-/* Hebrew initialisation for the UI Datepicker extension. */
-/* Written by Amir Hardon (ahardon at gmail dot com). */
-(function( factory ) {
- if ( typeof define === "function" && define.amd ) {
-
- // AMD. Register as an anonymous module.
- define([ "../jquery.ui.datepicker" ], factory );
- } else {
-
- // Browser globals
- factory( jQuery.datepicker );
- }
-}(function( datepicker ) {
- datepicker.regional['he'] = {
- closeText: 'סגור',
- prevText: '<הקודם',
- nextText: 'הבא>',
- currentText: 'היום',
- monthNames: ['ינואר','פברואר','מרץ','אפריל','מאי','יוני',
- 'יולי','אוגוסט','ספטמבר','אוקטובר','נובמבר','דצמבר'],
- monthNamesShort: ['ינו','פבר','מרץ','אפר','מאי','יוני',
- 'יולי','אוג','ספט','אוק','נוב','דצמ'],
- dayNames: ['ראשון','שני','שלישי','רביעי','חמישי','שישי','שבת'],
- dayNamesShort: ['א\'','ב\'','ג\'','ד\'','ה\'','ו\'','שבת'],
- dayNamesMin: ['א\'','ב\'','ג\'','ד\'','ה\'','ו\'','שבת'],
- weekHeader: 'Wk',
- dateFormat: 'dd/mm/yy',
- firstDay: 0,
- isRTL: true,
- showMonthAfterYear: false,
- yearSuffix: ''};
- datepicker.setDefaults(datepicker.regional['he']);
-
- return datepicker.regional['he'];
-
-}));
diff --git a/demos/datepicker/datepicker-zh-TW.js b/demos/datepicker/datepicker-zh-TW.js
deleted file mode 100644
index ebfd73ac5ab..00000000000
--- a/demos/datepicker/datepicker-zh-TW.js
+++ /dev/null
@@ -1,36 +0,0 @@
-/* Chinese initialisation for the jQuery UI date picker plugin. */
-/* Written by Ressol (ressol@gmail.com). */
-(function( factory ) {
- if ( typeof define === "function" && define.amd ) {
-
- // AMD. Register as an anonymous module.
- define([ "../jquery.ui.datepicker" ], factory );
- } else {
-
- // Browser globals
- factory( jQuery.datepicker );
- }
-}(function( datepicker ) {
- datepicker.regional['zh-TW'] = {
- closeText: '關閉',
- prevText: '<上月',
- nextText: '下月>',
- currentText: '今天',
- monthNames: ['一月','二月','三月','四月','五月','六月',
- '七月','八月','九月','十月','十一月','十二月'],
- monthNamesShort: ['一月','二月','三月','四月','五月','六月',
- '七月','八月','九月','十月','十一月','十二月'],
- dayNames: ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'],
- dayNamesShort: ['周日','周一','周二','周三','周四','周五','周六'],
- dayNamesMin: ['日','一','二','三','四','五','六'],
- weekHeader: '周',
- dateFormat: 'yy/mm/dd',
- firstDay: 1,
- isRTL: false,
- showMonthAfterYear: true,
- yearSuffix: '年'};
- datepicker.setDefaults(datepicker.regional['zh-TW']);
-
- return datepicker.regional['zh-TW'];
-
-}));
diff --git a/demos/datepicker/default.html b/demos/datepicker/default.html
index a11d5def7a9..08e93846f23 100644
--- a/demos/datepicker/default.html
+++ b/demos/datepicker/default.html
@@ -5,9 +5,15 @@
jQuery UI Datepicker - Default functionality
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/datepicker/index.html b/demos/datepicker/index.html
index d9c8dfc10da..5587564831f 100644
--- a/demos/datepicker/index.html
+++ b/demos/datepicker/index.html
@@ -9,19 +9,11 @@
diff --git a/demos/datepicker/inline.html b/demos/datepicker/inline.html
deleted file mode 100644
index 5d120457b77..00000000000
--- a/demos/datepicker/inline.html
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
- jQuery UI Datepicker - Display inline
-
-
-
-
-
-
-
-
-
-
-Date:
-
-
-
Display the datepicker embedded in the page instead of in an overlay. Simply call .datepicker() on a div instead of an input.
-
-
-
diff --git a/demos/datepicker/localization.html b/demos/datepicker/localization.html
index 2761dd31baf..34c35bff547 100644
--- a/demos/datepicker/localization.html
+++ b/demos/datepicker/localization.html
@@ -5,20 +5,24 @@
jQuery UI Datepicker - Localize calendar
+
+
+
+
+
-
-
-
-
+
@@ -27,11 +31,8 @@
Date:
- Arabic ((العربية
- Chinese Traditional (繁體中文)
- English
- French (Français)
- Hebrew ((עברית
+ German (Deutsch)
+ English
diff --git a/demos/datepicker/min-max.html b/demos/datepicker/min-max.html
deleted file mode 100644
index 4052c17852b..00000000000
--- a/demos/datepicker/min-max.html
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
jQuery UI Datepicker - Restrict date range
-
-
-
-
-
-
-
-
-
-
-
Date:
-
-
-
Restrict the range of selectable dates with the minDate
and maxDate
options. Set the beginning and end dates as actual dates (new Date(2009, 1 - 1, 26)), as a numeric offset from today (-20), or as a string of periods and units ('+1M +10D'). For the last, use 'D' for days, 'W' for weeks, 'M' for months, or 'Y' for years.
-
-
-
diff --git a/demos/datepicker/other-months.html b/demos/datepicker/other-months.html
deleted file mode 100644
index 71a06c5d2b9..00000000000
--- a/demos/datepicker/other-months.html
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
-
jQuery UI Datepicker - Dates in other months
-
-
-
-
-
-
-
-
-
-
-
Date:
-
-
-
The datepicker can show dates that come from other than the main month
- being displayed. These other dates can also be made selectable.
-
-
-
diff --git a/demos/datepicker/show-week.html b/demos/datepicker/show-week.html
deleted file mode 100644
index 362645a7ede..00000000000
--- a/demos/datepicker/show-week.html
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
-
-
jQuery UI Datepicker - Show week of the year
-
-
-
-
-
-
-
-
-
-
-
Date:
-
-
-
The datepicker can show the week of the year. The default calculation follows
- the ISO 8601 definition: the week starts on Monday, the first week of the year
- contains the first Thursday of the year. This means that some days from one
- year may be placed into weeks 'belonging' to another year.
-
-
-
diff --git a/demos/index.html b/demos/index.html
index f37874a4481..c4a0fdf9501 100644
--- a/demos/index.html
+++ b/demos/index.html
@@ -11,6 +11,7 @@
accordion
autocomplete
button
+
calendar
datepicker
dialog
draggable
diff --git a/external/date.js b/external/date.js
new file mode 100644
index 00000000000..edc47c161f6
--- /dev/null
+++ b/external/date.js
@@ -0,0 +1,211 @@
+/*
+ * Calendar math built on jquery-global
+ *
+ * Based on Marc Grabanski's jQuery Date Plugin
+ * http://marcgrabanski.com/articles/jquery-date-plugin
+ */
+(function( $, undefined ) {
+
+var weekdays = [ "sun", "mon", "tue", "wed", "thu", "fri", "sat" ],
+ weekdaysRev = {
+ "sun": 0,
+ "mon": 1,
+ "tue": 2,
+ "wed": 3,
+ "thu": 4,
+ "fri": 5,
+ "sat": 6
+ };
+
+Globalize.locale( "en" );
+
+$.date = function( date, globalFormat ) {
+ if ( !( this instanceof $.date ) ) {
+ return new $.date( date, globalFormat );
+ }
+ if ( typeof date === "string" && date.length ) {
+ this.dateObject = Globalize.parseDate( date, globalFormat );
+ }
+ if ( date instanceof Date ) {
+ this.dateObject = date;
+ }
+
+ this.dateObject = this.dateObject || new Date();
+ this.globalFormat = globalFormat;
+ this.selected = null;
+};
+
+$.date.prototype = {
+ setFormat: function( format ) {
+ if ( format ) {
+ this.globalFormat = format;
+ }
+ return this;
+ },
+ //TODO: same as the underlying Date object's terminology, but still misleading.
+ //TODO: We can use .setTime() instead of new Date and rename to setTimestamp.
+ setTime: function( time ) {
+ this.dateObject = new Date( time );
+ return this;
+ },
+ setDay: function( day ) {
+ var date = this.dateObject;
+ this.dateObject = new Date( date.getFullYear(), date.getMonth(), day, date.getHours(),
+ date.getMinutes(), date.getSeconds() );
+ return this;
+ },
+ setMonth: function( month ) {
+ // Overflow example: Month is October 31 (yeah Halloween) and month is changed to April with 30 days,
+ // the new date will me May 1. We will honor the month the user wants to set and if and overflow
+ // occurs, set to last day of month.
+ var date = this.dateObject,
+ days = date.getDay(), year = date.getFullYear();
+ if ( days > this.daysInMonth( year, month ) ) {
+
+ // Overflow
+ days = this.daysInMonth( year, month );
+ }
+ this.dateObject = new Date( year, month, days, date.getHours(),
+ date.getMinutes(), date.getSeconds() );
+ return this;
+ },
+ setYear: function( year ) {
+ var date = this.dateObject,
+ day = date.getDate(),
+ month = date.getMonth();
+
+ // Check if Leap, and February and day is 29th
+ if ( this.isLeapYear( year ) && month == 1 && day == 29 ) {
+
+ // set day to last day of February
+ day = this.daysInMonth( year, month );
+ }
+ this.dateObject = new Date( year, month, day, date.getHours(),
+ date.getMinutes(), date.getSeconds() );
+ return this;
+ },
+ setFullDate: function( year, month, day ) {
+ this.dateObject = new Date( year, month, day );
+ return this;
+ },
+ adjust: function( period, offset ) {
+ var date = this.dateObject,
+ day = period == "D" ? date.getDate() + offset : date.getDate(),
+ month = period == "M" ? date.getMonth() + offset : date.getMonth(),
+ year = period == "Y" ? date.getFullYear() + offset : date.getFullYear();
+
+ // If not day, update the day to the new month and year
+ if ( period != "D" ) {
+ day = Math.max( 1, Math.min( day, this.daysInMonth( year, month ) ) );
+ }
+ this.dateObject = new Date( year, month, day, date.getHours(),
+ date.getMinutes(), date.getSeconds() );
+ return this;
+ },
+ daysInMonth: function( year, month ) {
+ var date = this.dateObject;
+ year = year || date.getFullYear();
+ month = month || date.getMonth();
+ return 32 - new Date( year, month, 32 ).getDate();
+ },
+ monthName: function() {
+ return Globalize.format( this.dateObject, { pattern: "MMMM" } );
+ },
+ day: function() {
+ return this.dateObject.getDate();
+ },
+ month: function() {
+ return this.dateObject.getMonth();
+ },
+ year: function() {
+ return this.dateObject.getFullYear();
+ },
+ isLeapYear: function( year ) {
+ year = year || this.dateObject.getFullYear();
+ return new Date( year, 1, 29 ).getMonth() == 1;
+ },
+ weekdays: function() {
+ var result = [];
+ for ( var dow = 0; dow < 7; dow++ ) {
+ var day = ( dow + weekdaysRev[ Globalize.locale().supplemental.weekData.firstDay() ] ) % 7;
+ result.push({
+ shortname: Globalize.locale().main([ "dates/calendars/gregorian/days/format/short", weekdays[ day ] ]),
+ fullname: Globalize.locale().main([ "dates/calendars/gregorian/days/format/wide", weekdays[ day ] ])
+ });
+ }
+ return result;
+ },
+ days: function() {
+ var result = [],
+ today = $.date(),
+ date = this.dateObject,
+ firstDayOfMonth = new Date( this.year(), date.getMonth(), 1 ).getDay(),
+ leadDays = ( firstDayOfMonth - weekdaysRev[ Globalize.locale().supplemental.weekData.firstDay() ] + 7 ) % 7,
+ rows = Math.ceil( ( leadDays + this.daysInMonth() ) / 7 ),
+ printDate = new Date( this.year(), date.getMonth(), 1 - leadDays );
+ for ( var row = 0; row < rows; row++ ) {
+ var week = result[ result.length ] = {
+ number: Globalize.format( printDate, { pattern: "w" } ),
+ days: []
+ };
+ for ( var dayx = 0; dayx < 7; dayx++ ) {
+ var day = week.days[ week.days.length ] = {
+ lead: printDate.getMonth() != date.getMonth(),
+ date: printDate.getDate(),
+ timestamp: printDate.getTime(),
+ current: this.selected && this.selected.equal( printDate ),
+ today: today.equal( printDate )
+ };
+ day.render = day.selectable = !day.lead;
+ if ( this.eachDay ) {
+ this.eachDay( day );
+ }
+ // TODO use adjust("D", 1)?
+ printDate.setDate( printDate.getDate() + 1 );
+ }
+ }
+ return result;
+ },
+ // specialized for multi-month template, could be used in general
+ months: function( add ) {
+ var clone,
+ result = [ this ];
+
+ for ( var i = 0; i < add; i++ ) {
+ clone = this.clone();
+ clone.adjust( "M", i + 1 );
+ result.push( clone );
+ }
+ result[ 0 ].first = true;
+ result[ result.length - 1 ].last = true;
+ return result;
+ },
+ select: function() {
+ this.selected = this.clone();
+ return this;
+ },
+ selectedDate: function() {
+ return this.selected.date();
+ },
+ clone: function() {
+ var date = this.dateObject;
+ return new $.date( new Date( date.getFullYear(), date.getMonth(),
+ date.getDate(), date.getHours(),
+ date.getMinutes(), date.getSeconds()), this.globalFormat );
+ },
+ // TODO compare year, month, day each for better performance
+ equal: function( other ) {
+ function format( date ) {
+ return Globalize.format( date, { pattern: "yyyyMMdd" } );
+ }
+ return format( this.dateObject ) === format( other );
+ },
+ date: function() {
+ return this.dateObject;
+ },
+ format: function( format ) {
+ return Globalize.format( this.dateObject, format || this.globalFormat );
+ }
+};
+
+}( jQuery ));
diff --git a/external/globalize/globalize.culture.de-DE.js b/external/globalize/globalize.culture.de-DE.js
deleted file mode 100644
index 5466bd75e3b..00000000000
--- a/external/globalize/globalize.culture.de-DE.js
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Globalize Culture de-DE
- *
- * http://github.com/jquery/globalize
- *
- * Copyright Software Freedom Conservancy, Inc.
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * This file was generated by the Globalize Culture Generator
- * Translation: bugs found in this file need to be fixed in the generator
- */
-
-(function( window, undefined ) {
-
-var Globalize;
-
-if ( typeof require !== "undefined"
- && typeof exports !== "undefined"
- && typeof module !== "undefined" ) {
- // Assume CommonJS
- Globalize = require( "globalize" );
-} else {
- // Global variable
- Globalize = window.Globalize;
-}
-
-Globalize.addCultureInfo( "de-DE", "default", {
- name: "de-DE",
- englishName: "German (Germany)",
- nativeName: "Deutsch (Deutschland)",
- language: "de",
- numberFormat: {
- ",": ".",
- ".": ",",
- NaN: "n. def.",
- negativeInfinity: "-unendlich",
- positiveInfinity: "+unendlich",
- percent: {
- pattern: ["-n%","n%"],
- ",": ".",
- ".": ","
- },
- currency: {
- pattern: ["-n $","n $"],
- ",": ".",
- ".": ",",
- symbol: "€"
- }
- },
- calendars: {
- standard: {
- "/": ".",
- firstDay: 1,
- days: {
- names: ["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],
- namesAbbr: ["So","Mo","Di","Mi","Do","Fr","Sa"],
- namesShort: ["So","Mo","Di","Mi","Do","Fr","Sa"]
- },
- months: {
- names: ["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember",""],
- namesAbbr: ["Jan","Feb","Mrz","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez",""]
- },
- AM: null,
- PM: null,
- eras: [{"name":"n. Chr.","start":null,"offset":0}],
- patterns: {
- d: "dd.MM.yyyy",
- D: "dddd, d. MMMM yyyy",
- t: "HH:mm",
- T: "HH:mm:ss",
- f: "dddd, d. MMMM yyyy HH:mm",
- F: "dddd, d. MMMM yyyy HH:mm:ss",
- M: "dd MMMM",
- Y: "MMMM yyyy"
- }
- }
- }
-});
-
-}( this ));
diff --git a/external/globalize/globalize.culture.ja-JP.js b/external/globalize/globalize.culture.ja-JP.js
deleted file mode 100644
index a9469d709f4..00000000000
--- a/external/globalize/globalize.culture.ja-JP.js
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Globalize Culture ja-JP
- *
- * http://github.com/jquery/globalize
- *
- * Copyright Software Freedom Conservancy, Inc.
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * This file was generated by the Globalize Culture Generator
- * Translation: bugs found in this file need to be fixed in the generator
- */
-
-(function( window, undefined ) {
-
-var Globalize;
-
-if ( typeof require !== "undefined"
- && typeof exports !== "undefined"
- && typeof module !== "undefined" ) {
- // Assume CommonJS
- Globalize = require( "globalize" );
-} else {
- // Global variable
- Globalize = window.Globalize;
-}
-
-Globalize.addCultureInfo( "ja-JP", "default", {
- name: "ja-JP",
- englishName: "Japanese (Japan)",
- nativeName: "日本語 (日本)",
- language: "ja",
- numberFormat: {
- NaN: "NaN (非数値)",
- negativeInfinity: "-∞",
- positiveInfinity: "+∞",
- percent: {
- pattern: ["-n%","n%"]
- },
- currency: {
- pattern: ["-$n","$n"],
- decimals: 0,
- symbol: "¥"
- }
- },
- calendars: {
- standard: {
- days: {
- names: ["日曜日","月曜日","火曜日","水曜日","木曜日","金曜日","土曜日"],
- namesAbbr: ["日","月","火","水","木","金","土"],
- namesShort: ["日","月","火","水","木","金","土"]
- },
- months: {
- names: ["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月",""],
- namesAbbr: ["1","2","3","4","5","6","7","8","9","10","11","12",""]
- },
- AM: ["午前","午前","午前"],
- PM: ["午後","午後","午後"],
- eras: [{"name":"西暦","start":null,"offset":0}],
- patterns: {
- d: "yyyy/MM/dd",
- D: "yyyy'年'M'月'd'日'",
- t: "H:mm",
- T: "H:mm:ss",
- f: "yyyy'年'M'月'd'日' H:mm",
- F: "yyyy'年'M'月'd'日' H:mm:ss",
- M: "M'月'd'日'",
- Y: "yyyy'年'M'月'"
- }
- },
- Japanese: {
- name: "Japanese",
- days: {
- names: ["日曜日","月曜日","火曜日","水曜日","木曜日","金曜日","土曜日"],
- namesAbbr: ["日","月","火","水","木","金","土"],
- namesShort: ["日","月","火","水","木","金","土"]
- },
- months: {
- names: ["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月",""],
- namesAbbr: ["1","2","3","4","5","6","7","8","9","10","11","12",""]
- },
- AM: ["午前","午前","午前"],
- PM: ["午後","午後","午後"],
- eras: [{"name":"平成","start":null,"offset":1867},{"name":"昭和","start":-1812153600000,"offset":1911},{"name":"大正","start":-1357603200000,"offset":1925},{"name":"明治","start":60022080000,"offset":1988}],
- twoDigitYearMax: 99,
- patterns: {
- d: "gg y/M/d",
- D: "gg y'年'M'月'd'日'",
- t: "H:mm",
- T: "H:mm:ss",
- f: "gg y'年'M'月'd'日' H:mm",
- F: "gg y'年'M'月'd'日' H:mm:ss",
- M: "M'月'd'日'",
- Y: "gg y'年'M'月'"
- }
- }
- }
-});
-
-}( this ));
diff --git a/external/globalize/globalize.js b/external/globalize/globalize.js
index a38a32625d3..1086d339db9 100644
--- a/external/globalize/globalize.js
+++ b/external/globalize/globalize.js
@@ -1,1585 +1,1788 @@
/*!
- * Globalize
+ * Globalize v1.0.0pre
*
* http://github.com/jquery/globalize
*
- * Copyright Software Freedom Conservancy, Inc.
- * Dual licensed under the MIT or GPL Version 2 licenses.
+ * Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors
+ * Released under the MIT license
* http://jquery.org/license
+ *
+ * Date: 2013-12-01T12:08Z
*/
-
-(function( window, undefined ) {
-
-var Globalize,
- // private variables
- regexHex,
- regexInfinity,
- regexParseFloat,
- regexTrim,
- // private JavaScript utility functions
- arrayIndexOf,
- endsWith,
- extend,
- isArray,
- isFunction,
- isObject,
- startsWith,
- trim,
- truncate,
- zeroPad,
- // private Globalization utility functions
- appendPreOrPostMatch,
- expandFormat,
- formatDate,
- formatNumber,
- getTokenRegExp,
- getEra,
- getEraYear,
- parseExact,
- parseNegativePattern;
-
-// Global variable (Globalize) or CommonJS module (globalize)
-Globalize = function( cultureSelector ) {
- return new Globalize.prototype.init( cultureSelector );
-};
-
-if ( typeof require !== "undefined" &&
- typeof exports !== "undefined" &&
- typeof module !== "undefined" ) {
- // Assume CommonJS
- module.exports = Globalize;
-} else {
- // Export as global variable
- window.Globalize = Globalize;
-}
-
-Globalize.cultures = {};
-
-Globalize.prototype = {
- constructor: Globalize,
- init: function( cultureSelector ) {
- this.cultures = Globalize.cultures;
- this.cultureSelector = cultureSelector;
-
- return this;
+(function( root, factory ) {
+
+ if ( typeof define === "function" && define.amd ) {
+ // AMD.
+ define( factory );
+ } else if ( typeof module === "object" && typeof module.exports === "object" ) {
+ // Node. CommonJS.
+ module.exports = factory();
+ } else {
+ // Global
+ root.Globalize = factory();
}
-};
-Globalize.prototype.init.prototype = Globalize.prototype;
-
-// 1. When defining a culture, all fields are required except the ones stated as optional.
-// 2. Each culture should have a ".calendars" object with at least one calendar named "standard"
-// which serves as the default calendar in use by that culture.
-// 3. Each culture should have a ".calendar" object which is the current calendar being used,
-// it may be dynamically changed at any time to one of the calendars in ".calendars".
-Globalize.cultures[ "default" ] = {
- // A unique name for the culture in the form
-
- name: "en",
- // the name of the culture in the english language
- englishName: "English",
- // the name of the culture in its own language
- nativeName: "English",
- // whether the culture uses right-to-left text
- isRTL: false,
- // "language" is used for so-called "specific" cultures.
- // For example, the culture "es-CL" means "Spanish, in Chili".
- // It represents the Spanish-speaking culture as it is in Chili,
- // which might have different formatting rules or even translations
- // than Spanish in Spain. A "neutral" culture is one that is not
- // specific to a region. For example, the culture "es" is the generic
- // Spanish culture, which may be a more generalized version of the language
- // that may or may not be what a specific culture expects.
- // For a specific culture like "es-CL", the "language" field refers to the
- // neutral, generic culture information for the language it is using.
- // This is not always a simple matter of the string before the dash.
- // For example, the "zh-Hans" culture is netural (Simplified Chinese).
- // And the "zh-SG" culture is Simplified Chinese in Singapore, whose lanugage
- // field is "zh-CHS", not "zh".
- // This field should be used to navigate from a specific culture to it's
- // more general, neutral culture. If a culture is already as general as it
- // can get, the language may refer to itself.
- language: "en",
- // numberFormat defines general number formatting rules, like the digits in
- // each grouping, the group separator, and how negative numbers are displayed.
- numberFormat: {
- // [negativePattern]
- // Note, numberFormat.pattern has no "positivePattern" unlike percent and currency,
- // but is still defined as an array for consistency with them.
- // negativePattern: one of "(n)|-n|- n|n-|n -"
- pattern: [ "-n" ],
- // number of decimal places normally shown
- decimals: 2,
- // string that separates number groups, as in 1,000,000
- ",": ",",
- // string that separates a number from the fractional portion, as in 1.99
- ".": ".",
- // array of numbers indicating the size of each number group.
- // TODO: more detailed description and example
- groupSizes: [ 3 ],
- // symbol used for positive numbers
- "+": "+",
- // symbol used for negative numbers
- "-": "-",
- // symbol used for NaN (Not-A-Number)
- "NaN": "NaN",
- // symbol used for Negative Infinity
- negativeInfinity: "-Infinity",
- // symbol used for Positive Infinity
- positiveInfinity: "Infinity",
- percent: {
- // [negativePattern, positivePattern]
- // negativePattern: one of "-n %|-n%|-%n|%-n|%n-|n-%|n%-|-% n|n %-|% n-|% -n|n- %"
- // positivePattern: one of "n %|n%|%n|% n"
- pattern: [ "-n %", "n %" ],
- // number of decimal places normally shown
- decimals: 2,
- // array of numbers indicating the size of each number group.
- // TODO: more detailed description and example
- groupSizes: [ 3 ],
- // string that separates number groups, as in 1,000,000
- ",": ",",
- // string that separates a number from the fractional portion, as in 1.99
- ".": ".",
- // symbol used to represent a percentage
- symbol: "%"
- },
- currency: {
- // [negativePattern, positivePattern]
- // negativePattern: one of "($n)|-$n|$-n|$n-|(n$)|-n$|n-$|n$-|-n $|-$ n|n $-|$ n-|$ -n|n- $|($ n)|(n $)"
- // positivePattern: one of "$n|n$|$ n|n $"
- pattern: [ "($n)", "$n" ],
- // number of decimal places normally shown
- decimals: 2,
- // array of numbers indicating the size of each number group.
- // TODO: more detailed description and example
- groupSizes: [ 3 ],
- // string that separates number groups, as in 1,000,000
- ",": ",",
- // string that separates a number from the fractional portion, as in 1.99
- ".": ".",
- // symbol used to represent currency
- symbol: "$"
- }
- },
- // calendars defines all the possible calendars used by this culture.
- // There should be at least one defined with name "standard", and is the default
- // calendar used by the culture.
- // A calendar contains information about how dates are formatted, information about
- // the calendar's eras, a standard set of the date formats,
- // translations for day and month names, and if the calendar is not based on the Gregorian
- // calendar, conversion functions to and from the Gregorian calendar.
- calendars: {
- standard: {
- // name that identifies the type of calendar this is
- name: "Gregorian_USEnglish",
- // separator of parts of a date (e.g. "/" in 11/05/1955)
- "/": "/",
- // separator of parts of a time (e.g. ":" in 05:44 PM)
- ":": ":",
- // the first day of the week (0 = Sunday, 1 = Monday, etc)
- firstDay: 0,
- days: {
- // full day names
- names: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ],
- // abbreviated day names
- namesAbbr: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ],
- // shortest day names
- namesShort: [ "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" ]
- },
- months: {
- // full month names (13 months for lunar calendards -- 13th month should be "" if not lunar)
- names: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", "" ],
- // abbreviated month names
- namesAbbr: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "" ]
- },
- // AM and PM designators in one of these forms:
- // The usual view, and the upper and lower case versions
- // [ standard, lowercase, uppercase ]
- // The culture does not use AM or PM (likely all standard date formats use 24 hour time)
- // null
- AM: [ "AM", "am", "AM" ],
- PM: [ "PM", "pm", "PM" ],
- eras: [
- // eras in reverse chronological order.
- // name: the name of the era in this culture (e.g. A.D., C.E.)
- // start: when the era starts in ticks (gregorian, gmt), null if it is the earliest supported era.
- // offset: offset in years from gregorian calendar
- {
- "name": "A.D.",
- "start": null,
- "offset": 0
- }
- ],
- // when a two digit year is given, it will never be parsed as a four digit
- // year greater than this year (in the appropriate era for the culture)
- // Set it as a full year (e.g. 2029) or use an offset format starting from
- // the current year: "+19" would correspond to 2029 if the current year 2010.
- twoDigitYearMax: 2029,
- // set of predefined date and time patterns used by the culture
- // these represent the format someone in this culture would expect
- // to see given the portions of the date that are shown.
- patterns: {
- // short date pattern
- d: "M/d/yyyy",
- // long date pattern
- D: "dddd, MMMM dd, yyyy",
- // short time pattern
- t: "h:mm tt",
- // long time pattern
- T: "h:mm:ss tt",
- // long date, short time pattern
- f: "dddd, MMMM dd, yyyy h:mm tt",
- // long date, long time pattern
- F: "dddd, MMMM dd, yyyy h:mm:ss tt",
- // month/day pattern
- M: "MMMM dd",
- // month/year pattern
- Y: "yyyy MMMM",
- // S is a sortable format that does not vary by culture
- S: "yyyy\u0027-\u0027MM\u0027-\u0027dd\u0027T\u0027HH\u0027:\u0027mm\u0027:\u0027ss"
- }
- // optional fields for each calendar:
- /*
- monthsGenitive:
- Same as months but used when the day preceeds the month.
- Omit if the culture has no genitive distinction in month names.
- For an explaination of genitive months, see http://blogs.msdn.com/michkap/archive/2004/12/25/332259.aspx
- convert:
- Allows for the support of non-gregorian based calendars. This convert object is used to
- to convert a date to and from a gregorian calendar date to handle parsing and formatting.
- The two functions:
- fromGregorian( date )
- Given the date as a parameter, return an array with parts [ year, month, day ]
- corresponding to the non-gregorian based year, month, and day for the calendar.
- toGregorian( year, month, day )
- Given the non-gregorian year, month, and day, return a new Date() object
- set to the corresponding date in the gregorian calendar.
- */
- }
- },
- // For localized strings
- messages: {}
-};
-Globalize.cultures[ "default" ].calendar = Globalize.cultures[ "default" ].calendars.standard;
+}( this, function() {
-Globalize.cultures.en = Globalize.cultures[ "default" ];
+/**
+ * CLDR JavaScript Library v0.2.4-pre
+ * http://jquery.com/
+ *
+ * Copyright 2013 Rafael Xavier de Souza
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2013-11-30T11:30Z
+ */
+/*!
+ * CLDR JavaScript Library v0.2.4-pre 2013-11-30T11:30Z MIT license © Rafael Xavier
+ * http://git.io/h4lmVg
+ */
+ var Cldr = (function() {
-Globalize.cultureSelector = "en";
-//
-// private variables
-//
-regexHex = /^0x[a-f0-9]+$/i;
-regexInfinity = /^[+\-]?infinity$/i;
-regexParseFloat = /^[+\-]?\d*\.?\d*(e[+\-]?\d+)?$/;
-regexTrim = /^\s+|\s+$/g;
+ var alwaysArray = function( stringOrArray ) {
+ return typeof stringOrArray === "string" ? [ stringOrArray ] : stringOrArray;
+ };
-//
-// private JavaScript utility functions
-//
-arrayIndexOf = function( array, item ) {
- if ( array.indexOf ) {
- return array.indexOf( item );
- }
- for ( var i = 0, length = array.length; i < length; i++ ) {
- if ( array[i] === item ) {
- return i;
- }
- }
- return -1;
-};
-
-endsWith = function( value, pattern ) {
- return value.substr( value.length - pattern.length ) === pattern;
-};
-
-extend = function() {
- var options, name, src, copy, copyIsArray, clone,
- target = arguments[0] || {},
- i = 1,
- length = arguments.length,
- deep = false;
-
- // Handle a deep copy situation
- if ( typeof target === "boolean" ) {
- deep = target;
- target = arguments[1] || {};
- // skip the boolean and the target
- i = 2;
- }
- // Handle case when target is a string or something (possible in deep copy)
- if ( typeof target !== "object" && !isFunction(target) ) {
- target = {};
- }
- for ( ; i < length; i++ ) {
- // Only deal with non-null/undefined values
- if ( (options = arguments[ i ]) != null ) {
- // Extend the base object
- for ( name in options ) {
- src = target[ name ];
- copy = options[ name ];
-
- // Prevent never-ending loop
- if ( target === copy ) {
- continue;
- }
+ var common = function( Cldr ) {
- // Recurse if we're merging plain objects or arrays
- if ( deep && copy && ( isObject(copy) || (copyIsArray = isArray(copy)) ) ) {
- if ( copyIsArray ) {
- copyIsArray = false;
- clone = src && isArray(src) ? src : [];
+ Cldr.prototype.main = function( path ) {
+ path = alwaysArray( path );
+ return this.get( [ "main/{languageId}" ].concat( path ) );
+ };
- } else {
- clone = src && isObject(src) ? src : {};
- }
+ };
- // Never move original objects, clone them
- target[ name ] = extend( deep, clone, copy );
- // Don't bring in undefined values
- } else if ( copy !== undefined ) {
- target[ name ] = copy;
- }
- }
- }
- }
- // Return the modified object
- return target;
-};
-isArray = Array.isArray || function( obj ) {
- return Object.prototype.toString.call( obj ) === "[object Array]";
-};
+ var arrayIsArray = Array.isArray || function( obj ) {
+ return Object.prototype.toString.call( obj ) === "[object Array]";
+ };
-isFunction = function( obj ) {
- return Object.prototype.toString.call( obj ) === "[object Function]";
-};
-isObject = function( obj ) {
- return Object.prototype.toString.call( obj ) === "[object Object]";
-};
-startsWith = function( value, pattern ) {
- return value.indexOf( pattern ) === 0;
-};
-trim = function( value ) {
- return ( value + "" ).replace( regexTrim, "" );
-};
+ var pathNormalize = function( path, attributes ) {
+ if ( arrayIsArray( path ) ) {
+ path = path.join( "/" );
+ }
+ if ( typeof path !== "string" ) {
+ throw new Error( "invalid path \"" + path + "\"" );
+ }
+ // 1: Ignore leading slash `/`
+ // 2: Ignore leading `cldr/`
+ path = path
+ .replace( /^\// , "" ) /* 1 */
+ .replace( /^cldr\// , "" ); /* 2 */
-truncate = function( value ) {
- if ( isNaN( value ) ) {
- return NaN;
- }
- return Math[ value < 0 ? "ceil" : "floor" ]( value );
-};
+ // Replace {attribute}'s
+ path = path.replace( /{[a-zA-Z]+}/g, function( name ) {
+ name = name.replace( /^{([^}]*)}$/, "$1" );
+ return attributes[ name ];
+ });
-zeroPad = function( str, count, left ) {
- var l;
- for ( l = str.length; l < count; l += 1 ) {
- str = ( left ? ("0" + str) : (str + "0") );
- }
- return str;
-};
-
-//
-// private Globalization utility functions
-//
-
-appendPreOrPostMatch = function( preMatch, strings ) {
- // appends pre- and post- token match strings while removing escaped characters.
- // Returns a single quote count which is used to determine if the token occurs
- // in a string literal.
- var quoteCount = 0,
- escaped = false;
- for ( var i = 0, il = preMatch.length; i < il; i++ ) {
- var c = preMatch.charAt( i );
- switch ( c ) {
- case "\'":
- if ( escaped ) {
- strings.push( "\'" );
- }
- else {
- quoteCount++;
- }
- escaped = false;
- break;
- case "\\":
- if ( escaped ) {
- strings.push( "\\" );
- }
- escaped = !escaped;
- break;
- default:
- strings.push( c );
- escaped = false;
- break;
- }
- }
- return quoteCount;
-};
-
-expandFormat = function( cal, format ) {
- // expands unspecified or single character date formats into the full pattern.
- format = format || "F";
- var pattern,
- patterns = cal.patterns,
- len = format.length;
- if ( len === 1 ) {
- pattern = patterns[ format ];
- if ( !pattern ) {
- throw "Invalid date format string \'" + format + "\'.";
+ return path.split( "/" );
+ };
+
+
+
+
+ var arraySome = function( array, callback ) {
+ var i, length;
+ if ( array.some ) {
+ return array.some( callback );
}
- format = pattern;
- }
- else if ( len === 2 && format.charAt(0) === "%" ) {
- // %X escape format -- intended as a custom format string that is only one character, not a built-in format.
- format = format.charAt( 1 );
- }
- return format;
-};
-
-formatDate = function( value, format, culture ) {
- var cal = culture.calendar,
- convert = cal.convert,
- ret;
-
- if ( !format || !format.length || format === "i" ) {
- if ( culture && culture.name.length ) {
- if ( convert ) {
- // non-gregorian calendar, so we cannot use built-in toLocaleString()
- ret = formatDate( value, cal.patterns.F, culture );
- }
- else {
- var eraDate = new Date( value.getTime() ),
- era = getEra( value, cal.eras );
- eraDate.setFullYear( getEraYear(value, cal, era) );
- ret = eraDate.toLocaleString();
+ for ( i = 0, length = array.length; i < length; i++ ) {
+ if ( callback( array[ i ], i, array ) ) {
+ return true;
}
}
- else {
- ret = value.toString();
- }
- return ret;
- }
+ return false;
+ };
- var eras = cal.eras,
- sortable = format === "s";
- format = expandFormat( cal, format );
-
- // Start with an empty string
- ret = [];
- var hour,
- zeros = [ "0", "00", "000" ],
- foundDay,
- checkedDay,
- dayPartRegExp = /([^d]|^)(d|dd)([^d]|$)/g,
- quoteCount = 0,
- tokenRegExp = getTokenRegExp(),
- converted;
-
- function padZeros( num, c ) {
- var r, s = num + "";
- if ( c > 1 && s.length < c ) {
- r = ( zeros[c - 2] + s);
- return r.substr( r.length - c, c );
- }
- else {
- r = s;
- }
- return r;
- }
- function hasDay() {
- if ( foundDay || checkedDay ) {
- return foundDay;
- }
- foundDay = dayPartRegExp.test( format );
- checkedDay = true;
- return foundDay;
- }
- function getPart( date, part ) {
- if ( converted ) {
- return converted[ part ];
- }
- switch ( part ) {
- case 0:
- return date.getFullYear();
- case 1:
- return date.getMonth();
- case 2:
- return date.getDate();
- default:
- throw "Invalid part value " + part;
+
+ // Return the maximized language id as defined in
+ // http://www.unicode.org/reports/tr35/#Likely_Subtags
+ // 1. Canonicalize.
+ // 1.1 Make sure the input locale is in canonical form: uses the right separator, and has the right casing.
+ // TODO Right casing? What df? It seems languages are lowercase, scripts are Capitalized, territory is uppercase. I am leaving this as an exercise to the user.
+
+ // 1.2 Replace any deprecated subtags with their canonical values using the data in supplemental metadata. Use the first value in the replacement list, if it exists. Language tag replacements may have multiple parts, such as "sh" ➞ "sr_Latn" or mo" ➞ "ro_MD". In such a case, the original script and/or region are retained if there is one. Thus "sh_Arab_AQ" ➞ "sr_Arab_AQ", not "sr_Latn_AQ".
+ // TODO What data?
+
+ // 1.3 If the tag is grandfathered (see in the supplemental data), then return it.
+ // TODO grandfathered?
+
+ // 1.4 Remove the script code 'Zzzz' and the region code 'ZZ' if they occur.
+ // 1.5 Get the components of the cleaned-up source tag (languages, scripts, and regions), plus any variants and extensions.
+ // 2. Lookup. Lookup each of the following in order, and stop on the first match:
+ // 2.1 languages_scripts_regions
+ // 2.2 languages_regions
+ // 2.3 languages_scripts
+ // 2.4 languages
+ // 2.5 und_scripts
+ // 3. Return
+ // 3.1 If there is no match, either return an error value, or the match for "und" (in APIs where a valid language tag is required).
+ // 3.2 Otherwise there is a match = languagem_scriptm_regionm
+ // 3.3 Let xr = xs if xs is not empty, and xm otherwise.
+ // 3.4 Return the language tag composed of languager _ scriptr _ regionr + variants + extensions .
+
+ //
+ // @subtags [Array] normalized language id subtags tuple (see init.js).
+ var likelySubtags = function( cldr, subtags, options ) {
+ var match, matchFound,
+ language = subtags[ 0 ],
+ script = subtags[ 1 ],
+ territory = subtags[ 2 ];
+ options = options || {};
+
+ // Skip if (language, script, territory) is not empty [3.3]
+ if ( language !== "und" && script !== "Zzzz" && territory !== "ZZ" ) {
+ return [ language, script, territory ];
+ }
+
+ // Skip if no supplemental likelySubtags data is present
+ if ( typeof cldr.get( "supplemental/likelySubtags" ) === "undefined" ) {
+ return;
+ }
+
+ // [2]
+ matchFound = arraySome([
+ [ language, script, territory ],
+ [ language, territory ],
+ [ language, script ],
+ [ language ],
+ [ "und", script ]
+ ], function( test ) {
+ return match = !(/\b(Zzzz|ZZ)\b/).test( test.join( "_" ) ) /* [1.4] */ && cldr.get( [ "supplemental/likelySubtags", test.join( "_" ) ] );
+ });
+
+ // [3]
+ if ( matchFound ) {
+ // [3.2 .. 3.4]
+ match = match.split( "_" );
+ return [
+ language !== "und" ? language : match[ 0 ],
+ script !== "Zzzz" ? script : match[ 1 ],
+ territory !== "ZZ" ? territory : match[ 2 ]
+ ];
+ } else if ( options.force ) {
+ // [3.1.2]
+ return cldr.get( "supplemental/likelySubtags/und" ).split( "_" );
+ } else {
+ // [3.1.1]
+ return;
}
- }
+ };
+
- if ( !sortable && convert ) {
- converted = convert.fromGregorian( value );
- }
- for ( ; ; ) {
- // Save the current index
- var index = tokenRegExp.lastIndex,
- // Look for the next pattern
- ar = tokenRegExp.exec( format );
+ // Given a locale, remove any fields that Add Likely Subtags would add.
+ // http://www.unicode.org/reports/tr35/#Likely_Subtags
+ // 1. First get max = AddLikelySubtags(inputLocale). If an error is signaled, return it.
+ // 2. Remove the variants from max.
+ // 3. Then for trial in {language, language _ region, language _ script}. If AddLikelySubtags(trial) = max, then return trial + variants.
+ // 4. If you do not get a match, return max + variants.
+ //
+ // @maxLanguageId [Array] maxLanguageId tuple (see init.js).
+ var removeLikelySubtags = function( cldr, maxLanguageId ) {
+ var match, matchFound,
+ language = maxLanguageId[ 0 ],
+ script = maxLanguageId[ 1 ],
+ territory = maxLanguageId[ 2 ];
+
+ // [3]
+ matchFound = arraySome([
+ [ [ language, "Zzzz", "ZZ" ], [ language ] ],
+ [ [ language, "Zzzz", territory ], [ language, territory ] ],
+ [ [ language, script, "ZZ" ], [ language, script ] ]
+ ], function( test ) {
+ var result = likelySubtags( cldr, test[ 0 ] );
+ match = test[ 1 ];
+ return result && result[ 0 ] === maxLanguageId[ 0 ] &&
+ result[ 1 ] === maxLanguageId[ 1 ] &&
+ result[ 2 ] === maxLanguageId[ 2 ];
+ });
+
+ // [4]
+ return matchFound ? match : maxLanguageId;
+ };
- // Append the text before the pattern (or the end of the string if not found)
- var preMatch = format.slice( index, ar ? ar.index : format.length );
- quoteCount += appendPreOrPostMatch( preMatch, ret );
- if ( !ar ) {
- break;
- }
- // do not replace any matches that occur inside a string literal.
- if ( quoteCount % 2 ) {
- ret.push( ar[0] );
- continue;
+
+ var supplemental = function( cldr ) {
+
+ var prepend, supplemental;
+
+ prepend = function( prepend ) {
+ return function( path ) {
+ path = alwaysArray( path );
+ return cldr.get( [ prepend ].concat( path ) );
+ };
+ };
+
+ supplemental = prepend( "supplemental" );
+
+ // Week Data
+ // http://www.unicode.org/reports/tr35/tr35-dates.html#Week_Data
+ supplemental.weekData = prepend( "supplemental/weekData" );
+
+ supplemental.weekData.firstDay = function() {
+ return cldr.get( "supplemental/weekData/firstDay/{territory}" ) ||
+ cldr.get( "supplemental/weekData/firstDay/001" );
+ };
+
+ supplemental.weekData.minDays = function() {
+ var minDays = cldr.get( "supplemental/weekData/minDays/{territory}" ) ||
+ cldr.get( "supplemental/weekData/minDays/001" );
+ return parseInt( minDays, 10 );
+ };
+
+ // Time Data
+ // http://www.unicode.org/reports/tr35/tr35-dates.html#Time_Data
+ supplemental.timeData = prepend( "supplemental/timeData" );
+
+ supplemental.timeData.allowed = function() {
+ return cldr.get( "supplemental/timeData/{territory}/_allowed" ) ||
+ cldr.get( "supplemental/timeData/001/_allowed" );
+ };
+
+ supplemental.timeData.preferred = function() {
+ return cldr.get( "supplemental/timeData/{territory}/_preferred" ) ||
+ cldr.get( "supplemental/timeData/001/_preferred" );
+ };
+
+ return supplemental;
+
+ };
+
+
+
+
+ var init = function( locale ) {
+ var language, languageId, maxLanguageId, script, territory, unicodeLanguageId, variant;
+
+ if ( typeof locale !== "string" ) {
+ throw new Error( "invalid locale type: \"" + JSON.stringify( locale ) + "\"" );
}
- var current = ar[ 0 ],
- clength = current.length;
+ // Normalize locale code.
+ // Get (or deduce) the "triple subtags": language, territory (also aliased as region), and script subtags.
+ // Get the variant subtags (calendar, collation, currency, etc).
+ // refs:
+ // - http://www.unicode.org/reports/tr35/#Field_Definitions
+ // - http://www.unicode.org/reports/tr35/#Language_and_Locale_IDs
+ // - http://www.unicode.org/reports/tr35/#Unicode_locale_identifier
- switch ( current ) {
- case "ddd":
- //Day of the week, as a three-letter abbreviation
- case "dddd":
- // Day of the week, using the full name
- var names = ( clength === 3 ) ? cal.days.namesAbbr : cal.days.names;
- ret.push( names[value.getDay()] );
- break;
- case "d":
- // Day of month, without leading zero for single-digit days
- case "dd":
- // Day of month, with leading zero for single-digit days
- foundDay = true;
- ret.push(
- padZeros( getPart(value, 2), clength )
- );
- break;
- case "MMM":
- // Month, as a three-letter abbreviation
- case "MMMM":
- // Month, using the full name
- var part = getPart( value, 1 );
- ret.push(
- ( cal.monthsGenitive && hasDay() ) ?
- ( cal.monthsGenitive[ clength === 3 ? "namesAbbr" : "names" ][ part ] ) :
- ( cal.months[ clength === 3 ? "namesAbbr" : "names" ][ part ] )
- );
- break;
- case "M":
- // Month, as digits, with no leading zero for single-digit months
- case "MM":
- // Month, as digits, with leading zero for single-digit months
- ret.push(
- padZeros( getPart(value, 1) + 1, clength )
- );
- break;
- case "y":
- // Year, as two digits, but with no leading zero for years less than 10
- case "yy":
- // Year, as two digits, with leading zero for years less than 10
- case "yyyy":
- // Year represented by four full digits
- part = converted ? converted[ 0 ] : getEraYear( value, cal, getEra(value, eras), sortable );
- if ( clength < 4 ) {
- part = part % 100;
- }
- ret.push(
- padZeros( part, clength )
- );
- break;
- case "h":
- // Hours with no leading zero for single-digit hours, using 12-hour clock
- case "hh":
- // Hours with leading zero for single-digit hours, using 12-hour clock
- hour = value.getHours() % 12;
- if ( hour === 0 ) hour = 12;
- ret.push(
- padZeros( hour, clength )
- );
- break;
- case "H":
- // Hours with no leading zero for single-digit hours, using 24-hour clock
- case "HH":
- // Hours with leading zero for single-digit hours, using 24-hour clock
- ret.push(
- padZeros( value.getHours(), clength )
- );
- break;
- case "m":
- // Minutes with no leading zero for single-digit minutes
- case "mm":
- // Minutes with leading zero for single-digit minutes
- ret.push(
- padZeros( value.getMinutes(), clength )
- );
- break;
- case "s":
- // Seconds with no leading zero for single-digit seconds
- case "ss":
- // Seconds with leading zero for single-digit seconds
- ret.push(
- padZeros( value.getSeconds(), clength )
- );
- break;
- case "t":
- // One character am/pm indicator ("a" or "p")
- case "tt":
- // Multicharacter am/pm indicator
- part = value.getHours() < 12 ? ( cal.AM ? cal.AM[0] : " " ) : ( cal.PM ? cal.PM[0] : " " );
- ret.push( clength === 1 ? part.charAt(0) : part );
+ locale = locale.replace( /-/, "_" );
+
+ // TODO normalize unicode locale extensions. Currently, skipped.
+ // unicodeLocaleExtensions = locale.split( "_u_" )[ 1 ];
+ locale = locale.split( "_u_" )[ 0 ];
+
+ // TODO normalize transformed extensions. Currently, skipped.
+ // transformedExtensions = locale.split( "_t_" )[ 1 ];
+ locale = locale.split( "_t_" )[ 0 ];
+
+ unicodeLanguageId = locale;
+
+ // unicodeLanguageId = ...
+ switch ( true ) {
+
+ // language_script_territory..
+ case /^[a-z]{2}_[A-Z][a-z]{3}_[A-Z0-9]{2}(\b|_)/.test( unicodeLanguageId ):
+ language = unicodeLanguageId.split( "_" )[ 0 ];
+ script = unicodeLanguageId.split( "_" )[ 1 ];
+ territory = unicodeLanguageId.split( "_" )[ 2 ];
+ variant = unicodeLanguageId.split( "_" )[ 3 ];
break;
- case "f":
- // Deciseconds
- case "ff":
- // Centiseconds
- case "fff":
- // Milliseconds
- ret.push(
- padZeros( value.getMilliseconds(), 3 ).substr( 0, clength )
- );
+
+ // language_script..
+ case /^[a-z]{2}_[A-Z][a-z]{3}(\b|_)/.test( unicodeLanguageId ):
+ language = unicodeLanguageId.split( "_" )[ 0 ];
+ script = unicodeLanguageId.split( "_" )[ 1 ];
+ territory = "ZZ";
+ variant = unicodeLanguageId.split( "_" )[ 2 ];
break;
- case "z":
- // Time zone offset, no leading zero
- case "zz":
- // Time zone offset with leading zero
- hour = value.getTimezoneOffset() / 60;
- ret.push(
- ( hour <= 0 ? "+" : "-" ) + padZeros( Math.floor(Math.abs(hour)), clength )
- );
+
+ // language_territory..
+ case /^[a-z]{2}_[A-Z0-9]{2}(\b|_)/.test( unicodeLanguageId ):
+ language = unicodeLanguageId.split( "_" )[ 0 ];
+ script = "Zzzz";
+ territory = unicodeLanguageId.split( "_" )[ 1 ];
+ variant = unicodeLanguageId.split( "_" )[ 2 ];
break;
- case "zzz":
- // Time zone offset with leading zero
- hour = value.getTimezoneOffset() / 60;
- ret.push(
- ( hour <= 0 ? "+" : "-" ) + padZeros( Math.floor(Math.abs(hour)), 2 ) +
- // Hard coded ":" separator, rather than using cal.TimeSeparator
- // Repeated here for consistency, plus ":" was already assumed in date parsing.
- ":" + padZeros( Math.abs(value.getTimezoneOffset() % 60), 2 )
- );
+
+ // language.., or root
+ case /^([a-z]{2}|root)(\b|_)/.test( unicodeLanguageId ):
+ language = unicodeLanguageId.split( "_" )[ 0 ];
+ script = "Zzzz";
+ territory = "ZZ";
+ variant = unicodeLanguageId.split( "_" )[ 1 ];
break;
- case "g":
- case "gg":
- if ( cal.eras ) {
- ret.push(
- cal.eras[ getEra(value, eras) ].name
- );
- }
+
+ default:
+ language = "und";
break;
- case "/":
- ret.push( cal["/"] );
- break;
- default:
- throw "Invalid date format pattern \'" + current + "\'.";
- }
- }
- return ret.join( "" );
-};
-
-// formatNumber
-(function() {
- var expandNumber;
-
- expandNumber = function( number, precision, formatInfo ) {
- var groupSizes = formatInfo.groupSizes,
- curSize = groupSizes[ 0 ],
- curGroupIndex = 1,
- factor = Math.pow( 10, precision ),
- rounded = Math.round( number * factor ) / factor;
-
- if ( !isFinite(rounded) ) {
- rounded = number;
}
- number = rounded;
-
- var numberString = number+"",
- right = "",
- split = numberString.split( /e/i ),
- exponent = split.length > 1 ? parseInt( split[1], 10 ) : 0;
- numberString = split[ 0 ];
- split = numberString.split( "." );
- numberString = split[ 0 ];
- right = split.length > 1 ? split[ 1 ] : "";
-
- if ( exponent > 0 ) {
- right = zeroPad( right, exponent, false );
- numberString += right.slice( 0, exponent );
- right = right.substr( exponent );
+
+ // When a locale id does not specify a language, or territory (region), or script, they are obtained by Likely Subtags.
+ maxLanguageId = likelySubtags( this, [ language, script, territory ], { force: true } ) || unicodeLanguageId.split( "_" );
+ language = maxLanguageId[ 0 ];
+ script = maxLanguageId[ 1 ];
+ territory = maxLanguageId[ 2 ];
+
+ // TODO json content distributed on zip file use languageId with `-` on main.. Why `-` vs. `_` ?
+ languageId = removeLikelySubtags( this, maxLanguageId ).join( "_" );
+
+ // Set attributes
+ this.attributes = {
+
+ // Unicode Language Id
+ languageId: languageId,
+ maxLanguageId: maxLanguageId.join( "_" ),
+
+ // Unicode Language Id Subtabs
+ language: language,
+ script: script,
+ territory: territory,
+ region: territory, /* alias */
+ variant: variant
+ };
+
+ this.locale = variant ? [ languageId, variant ].join( "_" ) : languageId;
+
+ // Inlcude supplemental helper
+ this.supplemental = supplemental( this );
+ };
+
+
+
+
+ // @path: normalized path
+ var resourceGet = function( data, path ) {
+ var i,
+ node = data,
+ length = path.length;
+
+ for ( i = 0; i < length - 1; i++ ) {
+ node = node[ path[ i ] ];
+ if ( !node ) {
+ return undefined;
+ }
}
- else if ( exponent < 0 ) {
- exponent = -exponent;
- numberString = zeroPad( numberString, exponent + 1, true );
- right = numberString.slice( -exponent, numberString.length ) + right;
- numberString = numberString.slice( 0, -exponent );
+ return node[ path[ i ] ];
+ };
+
+
+
+
+ var bundleParentLookup = function( Cldr, locale ) {
+ var parent;
+
+ if ( locale === "root" ) {
+ return;
}
- if ( precision > 0 ) {
- right = formatInfo[ "." ] +
- ( (right.length > precision) ? right.slice(0, precision) : zeroPad(right, precision) );
+ // First, try to find parent on supplemental data.
+ parent = resourceGet( Cldr._resolved, pathNormalize( [ "supplemental/parentLocales/parentLocale", locale ] ) );
+ if ( parent ) {
+ return parent;
}
- else {
- right = "";
+
+ // Or truncate locale.
+ parent = locale.substr( 0, locale.lastIndexOf( "_" ) );
+ if ( !parent ) {
+ return "root";
}
- var stringIndex = numberString.length - 1,
- sep = formatInfo[ "," ],
- ret = "";
+ return parent;
+ };
+
- while ( stringIndex >= 0 ) {
- if ( curSize === 0 || curSize > stringIndex ) {
- return numberString.slice( 0, stringIndex + 1 ) + ( ret.length ? (sep + ret + right) : right );
- }
- ret = numberString.slice( stringIndex - curSize + 1, stringIndex + 1 ) + ( ret.length ? (sep + ret) : "" );
- stringIndex -= curSize;
- if ( curGroupIndex < groupSizes.length ) {
- curSize = groupSizes[ curGroupIndex ];
- curGroupIndex++;
+ // @path: normalized path
+ var resourceSet = function( data, path, value ) {
+ var i,
+ node = data,
+ length = path.length;
+
+ for ( i = 0; i < length - 1; i++ ) {
+ if ( !node[ path[ i ] ] ) {
+ node[ path[ i ] ] = {};
}
+ node = node[ path[ i ] ];
}
-
- return numberString.slice( 0, stringIndex + 1 ) + sep + ret + right;
+ node[ path[ i ] ] = value;
};
- formatNumber = function( value, format, culture ) {
- if ( !isFinite(value) ) {
- if ( value === Infinity ) {
- return culture.numberFormat.positiveInfinity;
- }
- if ( value === -Infinity ) {
- return culture.numberFormat.negativeInfinity;
- }
- return culture.numberFormat.NaN;
+
+
+
+ var arrayForEach = function( array, callback ) {
+ var i, length;
+ if ( array.forEach ) {
+ return array.forEach( callback );
}
- if ( !format || format === "i" ) {
- return culture.name.length ? value.toLocaleString() : value.toString();
+ for ( i = 0, length = array.length; i < length; i++ ) {
+ callback( array[ i ], i, array );
}
- format = format || "D";
-
- var nf = culture.numberFormat,
- number = Math.abs( value ),
- precision = -1,
- pattern;
- if ( format.length > 1 ) precision = parseInt( format.slice(1), 10 );
-
- var current = format.charAt( 0 ).toUpperCase(),
- formatInfo;
-
- switch ( current ) {
- case "D":
- pattern = "n";
- number = truncate( number );
- if ( precision !== -1 ) {
- number = zeroPad( "" + number, precision, true );
+ };
+
+
+ var jsonMerge = (function() {
+
+ // Returns new deeply merged JSON.
+ //
+ // Eg.
+ // merge( { a: { b: 1, c: 2 } }, { a: { b: 3, d: 4 } } )
+ // -> { a: { b: 3, c: 2, d: 4 } }
+ //
+ // @arguments JSON's
+ //
+ var merge = function() {
+ var destination = {},
+ sources = [].slice.call( arguments, 0 );
+ arrayForEach( sources, function( source ) {
+ var prop;
+ for ( prop in source ) {
+ if ( prop in destination && arrayIsArray( destination[ prop ] ) ) {
+
+ // Concat Arrays
+ destination[ prop ] = destination[ prop ].concat( source[ prop ] );
+
+ } else if ( prop in destination && typeof destination[ prop ] === "object" ) {
+
+ // Merge Objects
+ destination[ prop ] = merge( destination[ prop ], source[ prop ] );
+
+ } else {
+
+ // Set new values
+ destination[ prop ] = source[ prop ];
+
}
- if ( value < 0 ) number = "-" + number;
- break;
- case "N":
- formatInfo = nf;
- /* falls through */
- case "C":
- formatInfo = formatInfo || nf.currency;
- /* falls through */
- case "P":
- formatInfo = formatInfo || nf.percent;
- pattern = value < 0 ? formatInfo.pattern[ 0 ] : ( formatInfo.pattern[1] || "n" );
- if ( precision === -1 ) precision = formatInfo.decimals;
- number = expandNumber( number * (current === "P" ? 100 : 1), precision, formatInfo );
- break;
- default:
- throw "Bad number format specifier: " + current;
+ }
+ });
+ return destination;
+ };
+
+ return merge;
+
+}());
+ var itemLookup = (function() {
+
+ var lookup;
+
+ lookup = function( Cldr, locale, path, attributes, childLocale ) {
+ var normalizedPath, parent, value;
+
+ // 1: Finish recursion
+ // 2: Avoid infinite loop
+ if ( typeof locale === "undefined" /* 1 */ || locale === childLocale /* 2 */ ) {
+ return;
}
- var patternParts = /n|\$|-|%/g,
- ret = "";
- for ( ; ; ) {
- var index = patternParts.lastIndex,
- ar = patternParts.exec( pattern );
+ // Resolve path
+ normalizedPath = pathNormalize( path, attributes );
- ret += pattern.slice( index, ar ? ar.index : pattern.length );
+ // Check resolved (cached) data first
+ value = resourceGet( Cldr._resolved, normalizedPath );
+ if ( value ) {
+ return value;
+ }
- if ( !ar ) {
- break;
- }
+ // Check raw data
+ value = resourceGet( Cldr._raw, normalizedPath );
- switch ( ar[0] ) {
- case "n":
- ret += number;
- break;
- case "$":
- ret += nf.currency.symbol;
- break;
- case "-":
- // don't make 0 negative
- if ( /[1-9]/.test(number) ) {
- ret += nf[ "-" ];
- }
- break;
- case "%":
- ret += nf.percent.symbol;
- break;
- }
+ if ( !value ) {
+ // Or, lookup at parent locale
+ parent = bundleParentLookup( Cldr, locale );
+ value = lookup( Cldr, parent, path, jsonMerge( attributes, { languageId: parent }), locale );
}
- return ret;
+ // Set resolved (cached)
+ resourceSet( Cldr._resolved, normalizedPath, value );
+
+ return value;
};
+ return lookup;
+
}());
-getTokenRegExp = function() {
- // regular expression for matching date and time tokens in format strings.
- return (/\/|dddd|ddd|dd|d|MMMM|MMM|MM|M|yyyy|yy|y|hh|h|HH|H|mm|m|ss|s|tt|t|fff|ff|f|zzz|zz|z|gg|g/g);
-};
-
-getEra = function( date, eras ) {
- if ( !eras ) return 0;
- var start, ticks = date.getTime();
- for ( var i = 0, l = eras.length; i < l; i++ ) {
- start = eras[ i ].start;
- if ( start === null || ticks >= start ) {
- return i;
- }
- }
- return 0;
-};
-
-getEraYear = function( date, cal, era, sortable ) {
- var year = date.getFullYear();
- if ( !sortable && cal.eras ) {
- // convert normal gregorian year to era-shifted gregorian
- // year by subtracting the era offset
- year -= cal.eras[ era ].offset;
- }
- return year;
-};
-
-// parseExact
-(function() {
- var expandYear,
- getDayIndex,
- getMonthIndex,
- getParseRegExp,
- outOfRange,
- toUpper,
- toUpperArray;
-
- expandYear = function( cal, year ) {
- // expands 2-digit year into 4 digits.
- if ( year < 100 ) {
- var now = new Date(),
- era = getEra( now ),
- curr = getEraYear( now, cal, era ),
- twoDigitYearMax = cal.twoDigitYearMax;
- twoDigitYearMax = typeof twoDigitYearMax === "string" ? new Date().getFullYear() % 100 + parseInt( twoDigitYearMax, 10 ) : twoDigitYearMax;
- year += curr - ( curr % 100 );
- if ( year > twoDigitYearMax ) {
- year -= 100;
- }
- }
- return year;
+
+ var itemGetResolved = function( Cldr, path, attributes ) {
+ // Resolve path
+ var normalizedPath = pathNormalize( path, attributes );
+
+ return resourceGet( Cldr._resolved, normalizedPath );
};
- getDayIndex = function ( cal, value, abbr ) {
- var ret,
- days = cal.days,
- upperDays = cal._upperDays;
- if ( !upperDays ) {
- cal._upperDays = upperDays = [
- toUpperArray( days.names ),
- toUpperArray( days.namesAbbr ),
- toUpperArray( days.namesShort )
- ];
- }
- value = toUpper( value );
- if ( abbr ) {
- ret = arrayIndexOf( upperDays[1], value );
- if ( ret === -1 ) {
- ret = arrayIndexOf( upperDays[2], value );
- }
- }
- else {
- ret = arrayIndexOf( upperDays[0], value );
+
+
+
+ var Cldr = function() {
+ init.apply( this, arguments );
+ };
+
+ Cldr._resolved = {};
+ Cldr._raw = {};
+
+ // Load resolved or unresolved cldr data
+ // @json [JSON]
+ Cldr.load = function( json ) {
+ if ( typeof json !== "object" ) {
+ throw new Error( "invalid json" );
}
- return ret;
+ Cldr._raw = jsonMerge( Cldr._raw, json );
};
- getMonthIndex = function( cal, value, abbr ) {
- var months = cal.months,
- monthsGen = cal.monthsGenitive || cal.months,
- upperMonths = cal._upperMonths,
- upperMonthsGen = cal._upperMonthsGen;
- if ( !upperMonths ) {
- cal._upperMonths = upperMonths = [
- toUpperArray( months.names ),
- toUpperArray( months.namesAbbr )
- ];
- cal._upperMonthsGen = upperMonthsGen = [
- toUpperArray( monthsGen.names ),
- toUpperArray( monthsGen.namesAbbr )
- ];
+ Cldr.prototype.get = function( path ) {
+ // Simplify locale using languageId (there are no other resource bundles)
+ // 1: during init(), get is called, but languageId is not defined. Use "" as a workaround in this very specific scenario.
+ var locale = this.attributes && this.attributes.languageId || "" /* 1 */;
+
+ return itemGetResolved( Cldr, path, this.attributes ) ||
+ itemLookup( Cldr, locale, path, this.attributes );
+ };
+
+ common( Cldr );
+
+ return Cldr;
+
+
+
+}());
+
+
+ var arrayMap = function( array, callback ) {
+ var clone, i, length;
+ if ( array.map ) {
+ return array.map( callback );
}
- value = toUpper( value );
- var i = arrayIndexOf( abbr ? upperMonths[1] : upperMonths[0], value );
- if ( i < 0 ) {
- i = arrayIndexOf( abbr ? upperMonthsGen[1] : upperMonthsGen[0], value );
+ for ( clone = [], i = 0, length = array.length; i < length; i++ ) {
+ clone[ i ] = callback( array[ i ], i, array );
}
- return i;
+ return clone;
};
- getParseRegExp = function( cal, format ) {
- // converts a format string into a regular expression with groups that
- // can be used to extract date fields from a date string.
- // check for a cached parse regex.
- var re = cal._parseRegExp;
- if ( !re ) {
- cal._parseRegExp = re = {};
- }
- else {
- var reFormat = re[ format ];
- if ( reFormat ) {
- return reFormat;
- }
+
+
+
+ var objectValues = function( object ) {
+ var i,
+ result = [];
+
+ for ( i in object ) {
+ result.push( object[ i ] );
}
- // expand single digit formats, then escape regular expression characters.
- var expFormat = expandFormat( cal, format ).replace( /([\^\$\.\*\+\?\|\[\]\(\)\{\}])/g, "\\\\$1" ),
- regexp = [ "^" ],
- groups = [],
- index = 0,
- quoteCount = 0,
- tokenRegExp = getTokenRegExp(),
- match;
-
- // iterate through each date token found.
- while ( (match = tokenRegExp.exec(expFormat)) !== null ) {
- var preMatch = expFormat.slice( index, match.index );
- index = tokenRegExp.lastIndex;
-
- // don't replace any matches that occur inside a string literal.
- quoteCount += appendPreOrPostMatch( preMatch, regexp );
- if ( quoteCount % 2 ) {
- regexp.push( match[0] );
- continue;
+ return result;
+ };
+
+
+
+
+ /**
+ * allPreset()
+ *
+ * @cldr [Cldr instance].
+ *
+ * Return an Array with all (skeleton, date, time, datetime) presets.
+ */
+ var datetimeAllPresets = function( cldr ) {
+ var result = [];
+
+ // Skeleton
+ result = objectValues( cldr.main( "dates/calendars/gregorian/dateTimeFormats/availableFormats" ) );
+
+ // Time
+ result = result.concat( objectValues( cldr.main( "dates/calendars/gregorian/timeFormats" ) ) );
+
+ // Date
+ result = result.concat( objectValues( cldr.main( "dates/calendars/gregorian/dateFormats" ) ) );
+
+ // Datetime
+ result = result.concat( arrayMap( objectValues( cldr.main( "dates/calendars/gregorian/dateTimeFormats" ) ), function( datetimeFormat, key ) {
+ if ( typeof datetimeFormat !== "string" ) {
+ return datetimeFormat;
}
+ return datetimeFormat
+ .replace( /\{0\}/, cldr.main([
+ "dates/calendars/gregorian/timeFormats",
+ key
+ ]))
+ .replace( /\{1\}/, cldr.main([
+ "dates/calendars/gregorian/dateFormats",
+ key
+ ]));
+ }));
+
+ return arrayMap( result, function( pattern ) {
+ return { pattern: pattern };
+ });
+ };
- // add a regex group for the token.
- var m = match[ 0 ],
- len = m.length,
- add;
- switch ( m ) {
- case "dddd": case "ddd":
- case "MMMM": case "MMM":
- case "gg": case "g":
- add = "(\\D+)";
- break;
- case "tt": case "t":
- add = "(\\D*)";
- break;
- case "yyyy":
- case "fff":
- case "ff":
- case "f":
- add = "(\\d{" + len + "})";
- break;
- case "dd": case "d":
- case "MM": case "M":
- case "yy": case "y":
- case "HH": case "H":
- case "hh": case "h":
- case "mm": case "m":
- case "ss": case "s":
- add = "(\\d\\d?)";
+
+
+
+ /**
+ * expandPattern( pattern, cldr )
+ *
+ * @pattern [String or Object] if String, it's considered a skeleton. Object accepts:
+ * - skeleton: [String] lookup availableFormat;
+ * - date: [String] ( "full" | "long" | "medium" | "short" );
+ * - time: [String] ( "full" | "long" | "medium" | "short" );
+ * - datetime: [String] ( "full" | "long" | "medium" | "short" );
+ * - pattern: [String] For more info see datetime/format.js.
+ *
+ * @cldr [Cldr instance].
+ *
+ * Return the corresponding pattern.
+ * Eg for "en":
+ * - "GyMMMd" returns "MMM d, y G";
+ * - { skeleton: "GyMMMd" } returns "MMM d, y G";
+ * - { date: "full" } returns "EEEE, MMMM d, y";
+ * - { time: "full" } returns "h:mm:ss a zzzz";
+ * - { datetime: "full" } returns "EEEE, MMMM d, y 'at' h:mm:ss a zzzz";
+ * - { pattern: "dd/mm" } returns "dd/mm";
+ */
+ var datetimeExpandPattern = function( pattern, cldr ) {
+ var result;
+
+ if ( typeof pattern === "string" ) {
+ pattern = { skeleton: pattern };
+ }
+
+ if ( typeof pattern === "object" ) {
+
+ switch ( true ) {
+ case "skeleton" in pattern:
+ result = cldr.main([
+ "dates/calendars/gregorian/dateTimeFormats/availableFormats",
+ pattern.skeleton
+ ]);
break;
- case "zzz":
- add = "([+-]?\\d\\d?:\\d{2})";
+
+ case "date" in pattern:
+ case "time" in pattern:
+ result = cldr.main([
+ "dates/calendars/gregorian",
+ "date" in pattern ? "dateFormats" : "timeFormats",
+ ( pattern.date || pattern.time )
+ ]);
break;
- case "zz": case "z":
- add = "([+-]?\\d\\d?)";
+
+ case "datetime" in pattern:
+ result = cldr.main([
+ "dates/calendars/gregorian/dateTimeFormats",
+ pattern.datetime
+ ]);
+ if ( result ) {
+ result = result
+ .replace( /\{0\}/, cldr.main([
+ "dates/calendars/gregorian/timeFormats",
+ pattern.datetime
+ ]))
+ .replace( /\{1\}/, cldr.main([
+ "dates/calendars/gregorian/dateFormats",
+ pattern.datetime
+ ]));
+ }
break;
- case "/":
- add = "(\\/)";
+
+ case "pattern" in pattern:
+ result = pattern.pattern;
break;
+
default:
- throw "Invalid date format pattern \'" + m + "\'.";
+ throw new Error( "Invalid pattern" );
}
- if ( add ) {
- regexp.push( add );
- }
- groups.push( match[0] );
+
+ } else {
+ throw new Error( "Invalid pattern" );
}
- appendPreOrPostMatch( expFormat.slice(index), regexp );
- regexp.push( "$" );
- // allow whitespace to differ when matching formats.
- var regexpStr = regexp.join( "" ).replace( /\s+/g, "\\s+" ),
- parseRegExp = { "regExp": regexpStr, "groups": groups };
+ if ( !result ) {
+ throw new Error( "Pattern not found" );
+ }
- // cache the regex for this format.
- return re[ format ] = parseRegExp;
+ return result;
};
- outOfRange = function( value, low, high ) {
- return value < low || value > high;
+
+
+ var datetimeWeekDays = [ "sun", "mon", "tue", "wed", "thu", "fri", "sat" ];
+
+
+
+ var arrayIndexOf = function( array, item ) {
+ if ( array.indexOf ) {
+ return array.indexOf( item );
+ }
+ for ( var i = 0, length = array.length; i < length; i++ ) {
+ if ( array[i] === item ) {
+ return i;
+ }
+ }
+ return -1;
};
- toUpper = function( value ) {
- // "he-IL" has non-breaking space in weekday names.
- return value.split( "\u00A0" ).join( " " ).toUpperCase();
+
+
+
+ /**
+ * firstDayOfWeek
+ */
+ var datetimeFirstDayOfWeek = function( cldr ) {
+ return arrayIndexOf( datetimeWeekDays, cldr.supplemental.weekData.firstDay() );
};
- toUpperArray = function( arr ) {
- var results = [];
- for ( var i = 0, l = arr.length; i < l; i++ ) {
- results[ i ] = toUpper( arr[i] );
- }
- return results;
+
+
+
+ /**
+ * dayOfWeek
+ *
+ * Return the day of the week normalized by the territory's firstDay [0-6].
+ * Eg for "mon":
+ * - return 0 if territory is GB, or BR, or DE, or FR (week starts on "mon");
+ * - return 1 if territory is US (week starts on "sun");
+ * - return 2 if territory is EG (week starts on "sat");
+ */
+ var datetimeDayOfWeek = function( date, cldr ) {
+ return ( date.getDay() - datetimeFirstDayOfWeek( cldr ) + 7 ) % 7;
};
- parseExact = function( value, format, culture ) {
- // try to parse the date string by matching against the format string
- // while using the specified culture for date field names.
- value = trim( value );
- var cal = culture.calendar,
- // convert date formats into regular expressions with groupings.
- // use the regexp to determine the input format and extract the date fields.
- parseInfo = getParseRegExp( cal, format ),
- match = new RegExp( parseInfo.regExp ).exec( value );
- if ( match === null ) {
- return null;
- }
- // found a date format that matches the input.
- var groups = parseInfo.groups,
- era = null, year = null, month = null, date = null, weekDay = null,
- hour = 0, hourOffset, min = 0, sec = 0, msec = 0, tzMinOffset = null,
- pmHour = false;
- // iterate the format groups to extract and set the date fields.
- for ( var j = 0, jl = groups.length; j < jl; j++ ) {
- var matchGroup = match[ j + 1 ];
- if ( matchGroup ) {
- var current = groups[ j ],
- clength = current.length,
- matchInt = parseInt( matchGroup, 10 );
- switch ( current ) {
- case "dd": case "d":
- // Day of month.
- date = matchInt;
- // check that date is generally in valid range, also checking overflow below.
- if ( outOfRange(date, 1, 31) ) return null;
- break;
- case "MMM": case "MMMM":
- month = getMonthIndex( cal, matchGroup, clength === 3 );
- if ( outOfRange(month, 0, 11) ) return null;
- break;
- case "M": case "MM":
- // Month.
- month = matchInt - 1;
- if ( outOfRange(month, 0, 11) ) return null;
- break;
- case "y": case "yy":
- case "yyyy":
- year = clength < 4 ? expandYear( cal, matchInt ) : matchInt;
- if ( outOfRange(year, 0, 9999) ) return null;
- break;
- case "h": case "hh":
- // Hours (12-hour clock).
- hour = matchInt;
- if ( hour === 12 ) hour = 0;
- if ( outOfRange(hour, 0, 11) ) return null;
- break;
- case "H": case "HH":
- // Hours (24-hour clock).
- hour = matchInt;
- if ( outOfRange(hour, 0, 23) ) return null;
- break;
- case "m": case "mm":
- // Minutes.
- min = matchInt;
- if ( outOfRange(min, 0, 59) ) return null;
- break;
- case "s": case "ss":
- // Seconds.
- sec = matchInt;
- if ( outOfRange(sec, 0, 59) ) return null;
- break;
- case "tt": case "t":
- // AM/PM designator.
- // see if it is standard, upper, or lower case PM. If not, ensure it is at least one of
- // the AM tokens. If not, fail the parse for this format.
- pmHour = cal.PM && ( matchGroup === cal.PM[0] || matchGroup === cal.PM[1] || matchGroup === cal.PM[2] );
- if (
- !pmHour && (
- !cal.AM || ( matchGroup !== cal.AM[0] && matchGroup !== cal.AM[1] && matchGroup !== cal.AM[2] )
- )
- ) return null;
- break;
- case "f":
- // Deciseconds.
- case "ff":
- // Centiseconds.
- case "fff":
- // Milliseconds.
- msec = matchInt * Math.pow( 10, 3 - clength );
- if ( outOfRange(msec, 0, 999) ) return null;
- break;
- case "ddd":
- // Day of week.
- case "dddd":
- // Day of week.
- weekDay = getDayIndex( cal, matchGroup, clength === 3 );
- if ( outOfRange(weekDay, 0, 6) ) return null;
- break;
- case "zzz":
- // Time zone offset in +/- hours:min.
- var offsets = matchGroup.split( /:/ );
- if ( offsets.length !== 2 ) return null;
- hourOffset = parseInt( offsets[0], 10 );
- if ( outOfRange(hourOffset, -12, 13) ) return null;
- var minOffset = parseInt( offsets[1], 10 );
- if ( outOfRange(minOffset, 0, 59) ) return null;
- tzMinOffset = ( hourOffset * 60 ) + ( startsWith(matchGroup, "-") ? -minOffset : minOffset );
- break;
- case "z": case "zz":
- // Time zone offset in +/- hours.
- hourOffset = matchInt;
- if ( outOfRange(hourOffset, -12, 13) ) return null;
- tzMinOffset = hourOffset * 60;
- break;
- case "g": case "gg":
- var eraName = matchGroup;
- if ( !eraName || !cal.eras ) return null;
- eraName = trim( eraName.toLowerCase() );
- for ( var i = 0, l = cal.eras.length; i < l; i++ ) {
- if ( eraName === cal.eras[i].name.toLowerCase() ) {
- era = i;
- break;
- }
- }
- // could not find an era with that name
- if ( era === null ) return null;
- break;
- }
- }
- }
- var result = new Date(), defaultYear, convert = cal.convert;
- defaultYear = convert ? convert.fromGregorian( result )[ 0 ] : result.getFullYear();
- if ( year === null ) {
- year = defaultYear;
- }
- else if ( cal.eras ) {
- // year must be shifted to normal gregorian year
- // but not if year was not specified, its already normal gregorian
- // per the main if clause above.
- year += cal.eras[( era || 0 )].offset;
- }
- // set default day and month to 1 and January, so if unspecified, these are the defaults
- // instead of the current day/month.
- if ( month === null ) {
- month = 0;
- }
- if ( date === null ) {
- date = 1;
- }
- // now have year, month, and date, but in the culture's calendar.
- // convert to gregorian if necessary
- if ( convert ) {
- result = convert.toGregorian( year, month, date );
- // conversion failed, must be an invalid match
- if ( result === null ) return null;
- }
- else {
- // have to set year, month and date together to avoid overflow based on current date.
- result.setFullYear( year, month, date );
- // check to see if date overflowed for specified month (only checked 1-31 above).
- if ( result.getDate() !== date ) return null;
- // invalid day of week.
- if ( weekDay !== null && result.getDay() !== weekDay ) {
- return null;
- }
+
+
+
+ /**
+ * distanceInDays( from, to )
+ *
+ * Return the distance in days between from and to Dates.
+ */
+ var datetimeDistanceInDays = function( from, to ) {
+ var inDays = 864e5;
+ return ( to.getTime() - from.getTime() ) / inDays;
+ };
+
+
+
+
+ /**
+ * startOf
+ *
+ * Return the
+ */
+ var datetimeStartOf = function( date, unit ) {
+ date = new Date( date.getTime() );
+ switch( unit ) {
+ case "year":
+ date.setMonth( 0 );
+ /* falls through */
+ case "month":
+ date.setDate( 1 );
+ /* falls through */
+ case "day":
+ date.setHours( 0 );
+ /* falls through */
+ case "hour":
+ date.setMinutes( 0 );
+ /* falls through */
+ case "minute":
+ date.setSeconds( 0 );
+ /* falls through */
+ case "second":
+ date.setMilliseconds( 0 );
}
- // if pm designator token was found make sure the hours fit the 24-hour clock.
- if ( pmHour && hour < 12 ) {
- hour += 12;
+ return date;
+ };
+
+
+
+
+ /**
+ * dayOfYear
+ *
+ * Return the distance in days of the date to the begin of the year [0-d].
+ */
+ var datetimeDayOfYear = function( date ) {
+ return Math.floor( datetimeDistanceInDays( datetimeStartOf( date, "year" ), date ) );
+ };
+
+
+
+
+ /**
+ * millisecondsInDay
+ */
+ var datetimeMillisecondsInDay = function( date ) {
+ // TODO Handle daylight savings discontinuities
+ return date - datetimeStartOf( date, "day" );
+ };
+
+
+
+ var datetimePatternRe = (/([a-z])\1*|'[^']+'|''|./ig);
+
+
+
+ var stringPad = function( str, count, right ) {
+ var length;
+ if ( typeof str !== "string" ) {
+ str = String( str );
}
- result.setHours( hour, min, sec, msec );
- if ( tzMinOffset !== null ) {
- // adjust timezone to utc before applying local offset.
- var adjustedMin = result.getMinutes() - ( tzMinOffset + result.getTimezoneOffset() );
- // Safari limits hours and minutes to the range of -127 to 127. We need to use setHours
- // to ensure both these fields will not exceed this range. adjustedMin will range
- // somewhere between -1440 and 1500, so we only need to split this into hours.
- result.setHours( result.getHours() + parseInt(adjustedMin / 60, 10), adjustedMin % 60 );
+ for ( length = str.length; length < count; length += 1 ) {
+ str = ( right ? ( str + "0" ) : ( "0" + str ) );
}
- return result;
+ return str;
};
-}());
-parseNegativePattern = function( value, nf, negativePattern ) {
- var neg = nf[ "-" ],
- pos = nf[ "+" ],
- ret;
- switch ( negativePattern ) {
- case "n -":
- neg = " " + neg;
- pos = " " + pos;
- /* falls through */
- case "n-":
- if ( endsWith(value, neg) ) {
- ret = [ "-", value.substr(0, value.length - neg.length) ];
- }
- else if ( endsWith(value, pos) ) {
- ret = [ "+", value.substr(0, value.length - pos.length) ];
- }
- break;
- case "- n":
- neg += " ";
- pos += " ";
- /* falls through */
- case "-n":
- if ( startsWith(value, neg) ) {
- ret = [ "-", value.substr(neg.length) ];
- }
- else if ( startsWith(value, pos) ) {
- ret = [ "+", value.substr(pos.length) ];
- }
- break;
- case "(n)":
- if ( startsWith(value, "(") && endsWith(value, ")") ) {
- ret = [ "-", value.substr(1, value.length - 2) ];
- }
- break;
- }
- return ret || [ "", value ];
-};
-
-//
-// public instance functions
-//
-
-Globalize.prototype.findClosestCulture = function( cultureSelector ) {
- return Globalize.findClosestCulture.call( this, cultureSelector );
-};
-
-Globalize.prototype.format = function( value, format, cultureSelector ) {
- return Globalize.format.call( this, value, format, cultureSelector );
-};
-
-Globalize.prototype.localize = function( key, cultureSelector ) {
- return Globalize.localize.call( this, key, cultureSelector );
-};
-
-Globalize.prototype.parseInt = function( value, radix, cultureSelector ) {
- return Globalize.parseInt.call( this, value, radix, cultureSelector );
-};
-
-Globalize.prototype.parseFloat = function( value, radix, cultureSelector ) {
- return Globalize.parseFloat.call( this, value, radix, cultureSelector );
-};
-
-Globalize.prototype.culture = function( cultureSelector ) {
- return Globalize.culture.call( this, cultureSelector );
-};
-
-//
-// public singleton functions
-//
-
-Globalize.addCultureInfo = function( cultureName, baseCultureName, info ) {
-
- var base = {},
- isNew = false;
-
- if ( typeof cultureName !== "string" ) {
- // cultureName argument is optional string. If not specified, assume info is first
- // and only argument. Specified info deep-extends current culture.
- info = cultureName;
- cultureName = this.culture().name;
- base = this.cultures[ cultureName ];
- } else if ( typeof baseCultureName !== "string" ) {
- // baseCultureName argument is optional string. If not specified, assume info is second
- // argument. Specified info deep-extends specified culture.
- // If specified culture does not exist, create by deep-extending default
- info = baseCultureName;
- isNew = ( this.cultures[ cultureName ] == null );
- base = this.cultures[ cultureName ] || this.cultures[ "default" ];
- } else {
- // cultureName and baseCultureName specified. Assume a new culture is being created
- // by deep-extending an specified base culture
- isNew = true;
- base = this.cultures[ baseCultureName ];
- }
- this.cultures[ cultureName ] = extend(true, {},
- base,
- info
- );
- // Make the standard calendar the current culture if it's a new culture
- if ( isNew ) {
- this.cultures[ cultureName ].calendar = this.cultures[ cultureName ].calendars.standard;
- }
-};
-Globalize.findClosestCulture = function( name ) {
- var match;
- if ( !name ) {
- return this.findClosestCulture( this.cultureSelector ) || this.cultures[ "default" ];
- }
- if ( typeof name === "string" ) {
- name = name.split( "," );
- }
- if ( isArray(name) ) {
- var lang,
- cultures = this.cultures,
- list = name,
- i, l = list.length,
- prioritized = [];
- for ( i = 0; i < l; i++ ) {
- name = trim( list[i] );
- var pri, parts = name.split( ";" );
- lang = trim( parts[0] );
- if ( parts.length === 1 ) {
- pri = 1;
+
+ /**
+ * format( date, pattern, cldr )
+ *
+ * @date [Date instance].
+ *
+ * @pattern [String] raw pattern.
+ * ref: http://www.unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns
+ *
+ * @cldr [Cldr instance].
+ *
+ * TODO Support other calendar types.
+ *
+ * Disclosure: this function borrows excerpts of dojo/date/locale.
+ */
+ var datetimeFormat = function( date, pattern, cldr ) {
+ var widths = [ "abbreviated", "wide", "narrow" ];
+ return pattern.replace( datetimePatternRe, function( current ) {
+ var pad, ret,
+ chr = current.charAt( 0 ),
+ length = current.length;
+
+ if ( chr === "j" ) {
+ // Locale preferred hHKk.
+ // http://www.unicode.org/reports/tr35/tr35-dates.html#Time_Data
+ chr = cldr.supplemental.timeData.preferred();
}
- else {
- name = trim( parts[1] );
- if ( name.indexOf("q=") === 0 ) {
- name = name.substr( 2 );
- pri = parseFloat( name );
- pri = isNaN( pri ) ? 0 : pri;
- }
- else {
- pri = 1;
- }
+
+ switch ( chr ) {
+
+ // Era
+ case "G":
+ ret = cldr.main([
+ "dates/calendars/gregorian/eras",
+ length <= 3 ? "eraAbbr" : ( length === 4 ? "eraNames" : "eraNarrow" ),
+ date.getFullYear() < 0 ? 0 : 1
+ ]);
+ break;
+
+ // Year
+ case "y":
+ // Plain year.
+ // The length specifies the padding, but for two letters it also specifies the maximum length.
+ ret = String( date.getFullYear() );
+ pad = true;
+ if ( length === 2 ) {
+ ret = ret.substr( ret.length - 2 );
+ }
+ break;
+
+ case "Y":
+ // Year in "Week of Year"
+ // The length specifies the padding, but for two letters it also specifies the maximum length.
+ // yearInWeekofYear = date + DaysInAWeek - (dayOfWeek - firstDay) - minDays
+ ret = new Date( date.getTime() );
+ ret.setDate( ret.getDate() + 7 - ( datetimeDayOfWeek( date, cldr ) - datetimeFirstDayOfWeek( cldr ) ) - cldr.supplemental.weekData.minDays() );
+ ret = String( ret.getFullYear() );
+ pad = true;
+ if ( length === 2 ) {
+ ret = ret.substr( ret.length - 2 );
+ }
+ break;
+
+ case "u": // Extended year. Need to be implemented.
+ case "U": // Cyclic year name. Need to be implemented.
+ throw new Error( "Not implemented" );
+
+ // Quarter
+ case "Q":
+ case "q":
+ ret = Math.ceil( ( date.getMonth() + 1 ) / 3 );
+ if ( length <= 2 ) {
+ pad = true;
+ } else {
+ // http://unicode.org/cldr/trac/ticket/6788
+ ret = cldr.main([
+ "dates/calendars/gregorian/quarters",
+ chr === "Q" ? "format" : "stand-alone",
+ widths[ length - 3 ],
+ ret
+ ]);
+ }
+ break;
+
+ // Month
+ case "M":
+ case "L":
+ ret = date.getMonth() + 1;
+ if ( length <= 2 ) {
+ pad = true;
+ } else {
+ ret = cldr.main([
+ "dates/calendars/gregorian/months",
+ chr === "M" ? "format" : "stand-alone",
+ widths[ length - 3 ],
+ ret
+ ]);
+ }
+ break;
+
+ // Week
+ case "w":
+ // Week of Year.
+ // woy = ceil( ( doy + dow of 1/1 ) / 7 ) - minDaysStuff ? 1 : 0.
+ // TODO should pad on ww? Not documented, but I guess so.
+ ret = datetimeDayOfWeek( datetimeStartOf( date, "year" ), cldr );
+ ret = Math.ceil( ( datetimeDayOfYear( date ) + ret ) / 7 ) - ( 7 - ret >= cldr.supplemental.weekData.minDays() ? 0 : 1 );
+ pad = true;
+ break;
+
+ case "W":
+ // Week of Month.
+ // wom = ceil( ( dom + dow of `1/month` ) / 7 ) - minDaysStuff ? 1 : 0.
+ ret = datetimeDayOfWeek( datetimeStartOf( date, "month" ), cldr );
+ ret = Math.ceil( ( date.getDate() + ret ) / 7 ) - ( 7 - ret >= cldr.supplemental.weekData.minDays() ? 0 : 1 );
+ break;
+
+ // Day
+ case "d":
+ ret = date.getDate();
+ pad = true;
+ break;
+
+ case "D":
+ ret = datetimeDayOfYear( date ) + 1;
+ pad = true;
+ break;
+
+ case "F":
+ // Day of Week in month. eg. 2nd Wed in July.
+ ret = Math.floor( date.getDate() / 7 ) + 1;
+ break;
+
+ case "g+":
+ // Modified Julian day. Need to be implemented.
+ throw new Error( "Not implemented" );
+
+ // Week day
+ case "e":
+ case "c":
+ if ( length <= 2 ) {
+ // Range is [1-7] (deduced by example provided on documentation)
+ // TODO Should pad with zeros (not specified in the docs)?
+ ret = datetimeDayOfWeek( date, cldr ) + 1;
+ pad = true;
+ break;
+ }
+
+ /* falls through */
+ case "E":
+ ret = datetimeWeekDays[ date.getDay() ];
+ if ( length === 6 ) {
+ // If short day names are not explicitly specified, abbreviated day names are used instead.
+ // http://www.unicode.org/reports/tr35/tr35-dates.html#months_days_quarters_eras
+ // http://unicode.org/cldr/trac/ticket/6790
+ ret = cldr.main([
+ "dates/calendars/gregorian/days",
+ [ chr === "c" ? "stand-alone" : "format" ],
+ "short",
+ ret
+ ]) || cldr.main([
+ "dates/calendars/gregorian/days",
+ [ chr === "c" ? "stand-alone" : "format" ],
+ "abbreviated",
+ ret
+ ]);
+ } else {
+ ret = cldr.main([
+ "dates/calendars/gregorian/days",
+ [ chr === "c" ? "stand-alone" : "format" ],
+ widths[ length < 3 ? 0 : length - 3 ],
+ ret
+ ]);
+ }
+ break;
+
+ // Period (AM or PM)
+ case "a":
+ ret = cldr.main([
+ "dates/calendars/gregorian/dayPeriods/format/wide",
+ date.getHours() < 12 ? "am" : "pm"
+ ]);
+ break;
+
+ // Hour
+ case "h": // 1-12
+ ret = ( date.getHours() % 12 ) || 12;
+ pad = true;
+ break;
+
+ case "H": // 0-23
+ ret = date.getHours();
+ pad = true;
+ break;
+
+ case "K": // 0-11
+ ret = date.getHours() % 12;
+ pad = true;
+ break;
+
+ case "k": // 1-24
+ ret = date.getHours() || 24;
+ pad = true;
+ break;
+
+ // Minute
+ case "m":
+ ret = date.getMinutes();
+ pad = true;
+ break;
+
+ // Second
+ case "s":
+ ret = date.getSeconds();
+ pad = true;
+ break;
+
+ case "S":
+ ret = Math.round( date.getMilliseconds() * Math.pow( 10, length - 3 ) );
+ pad = true;
+ break;
+
+ case "A":
+ ret = Math.round( datetimeMillisecondsInDay( date ) * Math.pow( 10, length - 3 ) );
+ pad = true;
+ break;
+
+ // Zone
+ // see http://www.unicode.org/reports/tr35/tr35-dates.html#Using_Time_Zone_Names ?
+ // Need to be implemented.
+ case "z":
+ case "Z":
+ case "O":
+ case "v":
+ case "V":
+ case "X":
+ case "x":
+ throw new Error( "Not implemented" );
+
+ // Anything else is considered a literal, including [ ,:/.'@#], chinese, japonese, and arabic characters.
+ default:
+ return current;
}
- prioritized.push({ lang: lang, pri: pri });
- }
- prioritized.sort(function( a, b ) {
- if ( a.pri < b.pri ) {
- return 1;
- } else if ( a.pri > b.pri ) {
- return -1;
+ if ( pad ) {
+ ret = stringPad( ret, length );
}
- return 0;
+ return ret;
});
- // exact match
- for ( i = 0; i < l; i++ ) {
- lang = prioritized[ i ].lang;
- match = cultures[ lang ];
- if ( match ) {
- return match;
+ };
+
+
+
+
+ var arrayEvery = function( array, callback ) {
+ var i, length;
+ if ( array.every ) {
+ return array.every( callback );
+ }
+ for ( i = 0, length = array.length; i < length; i++ ) {
+ if ( !callback( array[ i ], i, array ) ) {
+ return false;
}
}
+ return true;
+ };
- // neutral language match
- for ( i = 0; i < l; i++ ) {
- lang = prioritized[ i ].lang;
- do {
- var index = lang.lastIndexOf( "-" );
- if ( index === -1 ) {
- break;
+
+
+
+ /**
+ * tokenizer( value, pattern )
+ *
+ * Returns an Array of tokens, eg. value "5 o'clock PM", pattern "h 'o''clock' a":
+ * [{
+ * type: "h",
+ * lexeme: "5"
+ * }, {
+ * type: "literal",
+ * lexeme: " "
+ * }, {
+ * type: "literal",
+ * lexeme: "o'clock"
+ * }, {
+ * type: "literal",
+ * lexeme: " "
+ * }, {
+ * type: "a",
+ * lexeme: "PM",
+ * value: "pm"
+ * }]
+ *
+ * OBS: lexeme's are always String and may return invalid ranges depending of the token type. Eg. "99" for month number.
+ *
+ * Return an empty Array when not successfully parsed.
+ */
+ var datetimeTokenizer = function( value, pattern, cldr ) {
+ var valid,
+ tokens = [],
+ widths = [ "abbreviated", "wide", "narrow" ];
+
+ valid = arrayEvery( pattern.match( datetimePatternRe ), function( current ) {
+ var chr, length, tokenRe,
+ token = {};
+
+ function oneDigitIfLengthOne() {
+ if ( length === 1 ) {
+ return tokenRe = /\d/;
}
- // strip off the last part. e.g. en-US => en
- lang = lang.substr( 0, index );
- match = cultures[ lang ];
- if ( match ) {
- return match;
+ }
+
+ function oneOrTwoDigitsIfLengthOne() {
+ if ( length === 1 ) {
+ return tokenRe = /\d\d?/;
}
}
- while ( 1 );
- }
- // last resort: match first culture using that language
- for ( i = 0; i < l; i++ ) {
- lang = prioritized[ i ].lang;
- for ( var cultureKey in cultures ) {
- var culture = cultures[ cultureKey ];
- if ( culture.language === lang ) {
- return culture;
+ function twoDigitsIfLengthTwo() {
+ if ( length === 2 ) {
+ return tokenRe = /\d\d/;
}
}
- }
- }
- else if ( typeof name === "object" ) {
- return name;
- }
- return match || null;
-};
-Globalize.format = function( value, format, cultureSelector ) {
- var culture = this.findClosestCulture( cultureSelector );
- if ( value instanceof Date ) {
- value = formatDate( value, format, culture );
- }
- else if ( typeof value === "number" ) {
- value = formatNumber( value, format, culture );
- }
- return value;
-};
+ // Brute-force test every locale entry in an attempt to match the given value.
+ // Return the first found one (and set token accordingly), or null.
+ function lookup( path ) {
+ var i, re,
+ data = cldr.main( path );
+ for ( i in data ) {
+ re = new RegExp( "^" + data[ i ] );
+ if ( re.test( value ) ) {
+ token.value = i;
+ return tokenRe = new RegExp( data[ i ] );
+ }
+ }
+ return null;
+ }
-Globalize.localize = function( key, cultureSelector ) {
- return this.findClosestCulture( cultureSelector ).messages[ key ] ||
- this.cultures[ "default" ].messages[ key ];
-};
+ token.type = current;
+ chr = current.charAt( 0 ),
+ length = current.length;
-Globalize.parseDate = function( value, formats, culture ) {
- culture = this.findClosestCulture( culture );
+ switch ( chr ) {
- var date, prop, patterns;
- if ( formats ) {
- if ( typeof formats === "string" ) {
- formats = [ formats ];
- }
- if ( formats.length ) {
- for ( var i = 0, l = formats.length; i < l; i++ ) {
- var format = formats[ i ];
- if ( format ) {
- date = parseExact( value, format, culture );
- if ( date ) {
+ // Era
+ case "G":
+ lookup([
+ "dates/calendars/gregorian/eras",
+ length <= 3 ? "eraAbbr" : ( length === 4 ? "eraNames" : "eraNarrow" )
+ ]);
+ break;
+
+ // Year
+ case "y":
+ case "Y":
+ // number l=1:+, l=2:{2}, l=3:{3,}, l=4:{4,}, ...
+ if ( length === 1 ) {
+ tokenRe = /\d+/;
+ } else if ( length === 2 ) {
+ tokenRe = /\d\d/;
+ } else {
+ tokenRe = new RegExp( "\\d{" + length + ",}" );
+ }
+ break;
+
+ case "u": // Extended year. Need to be implemented.
+ case "U": // Cyclic year name. Need to be implemented.
+ throw new Error( "Not implemented" );
+
+ // Quarter
+ case "Q":
+ case "q":
+ // number l=1:{1}, l=2:{2}.
+ // lookup l=3...
+ oneDigitIfLengthOne() || twoDigitsIfLengthTwo() || lookup([
+ "dates/calendars/gregorian/quarters",
+ chr === "Q" ? "format" : "stand-alone",
+ widths[ length - 3 ]
+ ]);
+ break;
+
+ // Month
+ case "M":
+ case "L":
+ // number l=1:{1,2}, l=2:{2}.
+ // lookup l=3...
+ oneOrTwoDigitsIfLengthOne() || twoDigitsIfLengthTwo() || lookup([
+ "dates/calendars/gregorian/months",
+ chr === "M" ? "format" : "stand-alone",
+ widths[ length - 3 ]
+ ]);
+ break;
+
+ // Day (see d below)
+ case "D":
+ // number {l,3}.
+ if ( length <= 3 ) {
+ tokenRe = new RegExp( "\\d{" + length + ",3}" );
+ }
+ break;
+
+ case "W":
+ case "F":
+ // number l=1:{1}.
+ oneDigitIfLengthOne();
+ break;
+
+ case "g+":
+ // Modified Julian day. Need to be implemented.
+ throw new Error( "Not implemented" );
+
+ // Week day
+ case "e":
+ case "c":
+ // number l=1:{1}, l=2:{2}.
+ // lookup for length >=3.
+ if( length <= 2 ) {
+ oneDigitIfLengthOne() || twoDigitsIfLengthTwo();
break;
}
- }
- }
- }
- } else {
- patterns = culture.calendar.patterns;
- for ( prop in patterns ) {
- date = parseExact( value, patterns[prop], culture );
- if ( date ) {
- break;
+
+ /* falls through */
+ case "E":
+ if ( length === 6 ) {
+ // Note: if short day names are not explicitly specified, abbreviated day names are used instead http://www.unicode.org/reports/tr35/tr35-dates.html#months_days_quarters_eras
+ lookup([
+ "dates/calendars/gregorian/days",
+ [ chr === "c" ? "stand-alone" : "format" ],
+ "short"
+ ]) || lookup([
+ "dates/calendars/gregorian/days",
+ [ chr === "c" ? "stand-alone" : "format" ],
+ "abbreviated"
+ ]);
+ } else {
+ lookup([
+ "dates/calendars/gregorian/days",
+ [ chr === "c" ? "stand-alone" : "format" ],
+ widths[ length < 3 ? 0 : length - 3 ]
+ ]);
+ }
+ break;
+
+ // Period (AM or PM)
+ case "a":
+ lookup([
+ "dates/calendars/gregorian/dayPeriods/format/wide"
+ ]);
+ break;
+
+ // Week, Day, Hour, Minute, or Second
+ case "w":
+ case "d":
+ case "h":
+ case "H":
+ case "K":
+ case "k":
+ case "j":
+ case "m":
+ case "s":
+ // number l1:{1,2}, l2:{2}.
+ oneOrTwoDigitsIfLengthOne() || twoDigitsIfLengthTwo();
+ break;
+
+ case "S":
+ // number {l}.
+ tokenRe = new RegExp( "\\d{" + length + "}" );
+ break;
+
+ case "A":
+ // number {l+5}.
+ tokenRe = new RegExp( "\\d{" + ( length + 5 ) + "}" );
+ break;
+
+ // Zone
+ // see http://www.unicode.org/reports/tr35/tr35-dates.html#Using_Time_Zone_Names ?
+ // Need to be implemented.
+ case "z":
+ case "Z":
+ case "O":
+ case "v":
+ case "V":
+ case "X":
+ case "x":
+ throw new Error( "Not implemented" );
+
+ case "'":
+ token.type = "literal";
+ if ( current.charAt( 1 ) === "'" ) {
+ tokenRe = /'/;
+ } else {
+ tokenRe = /'[^']+'/;
+ }
+ break;
+
+ default:
+ token.type = "literal";
+ tokenRe = /./;
}
- }
- }
- return date || null;
-};
+ if ( !tokenRe ) {
+ return false;
+ }
-Globalize.parseInt = function( value, radix, cultureSelector ) {
- return truncate( Globalize.parseFloat(value, radix, cultureSelector) );
-};
+ // Get lexeme and consume it.
+ value = value.replace( new RegExp( "^" + tokenRe.source ), function( lexeme ) {
+ token.lexeme = lexeme;
+ return "";
+ });
-Globalize.parseFloat = function( value, radix, cultureSelector ) {
- // radix argument is optional
- if ( typeof radix !== "number" ) {
- cultureSelector = radix;
- radix = 10;
- }
+ if ( !token.lexeme ) {
+ return false;
+ }
- var culture = this.findClosestCulture( cultureSelector );
- var ret = NaN,
- nf = culture.numberFormat;
+ tokens.push( token );
+ return true;
+ });
- if ( value.indexOf(culture.numberFormat.currency.symbol) > -1 ) {
- // remove currency symbol
- value = value.replace( culture.numberFormat.currency.symbol, "" );
- // replace decimal seperator
- value = value.replace( culture.numberFormat.currency["."], culture.numberFormat["."] );
- }
+ return valid ? tokens : [];
+ };
- //Remove percentage character from number string before parsing
- if ( value.indexOf(culture.numberFormat.percent.symbol) > -1){
- value = value.replace( culture.numberFormat.percent.symbol, "" );
- }
- // remove spaces: leading, trailing and between - and number. Used for negative currency pt-BR
- value = value.replace( / /g, "" );
+ var datetimeParse = (function() {
- // allow infinity or hexidecimal
- if ( regexInfinity.test(value) ) {
- ret = parseFloat( value );
- }
- else if ( !radix && regexHex.test(value) ) {
- ret = parseInt( value, 16 );
+ function outOfRange( value, low, high ) {
+ return value < low || value > high;
}
- else {
-
- // determine sign and number
- var signInfo = parseNegativePattern( value, nf, nf.pattern[0] ),
- sign = signInfo[ 0 ],
- num = signInfo[ 1 ];
-
- // #44 - try parsing as "(n)"
- if ( sign === "" && nf.pattern[0] !== "(n)" ) {
- signInfo = parseNegativePattern( value, nf, "(n)" );
- sign = signInfo[ 0 ];
- num = signInfo[ 1 ];
- }
- // try parsing as "-n"
- if ( sign === "" && nf.pattern[0] !== "-n" ) {
- signInfo = parseNegativePattern( value, nf, "-n" );
- sign = signInfo[ 0 ];
- num = signInfo[ 1 ];
+ /**
+ * parse
+ *
+ * ref: http://www.unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns
+ */
+ return function( value, pattern, cldr ) {
+ var amPm, era, hour24, valid,
+ YEAR = 0,
+ MONTH = 1,
+ DAY = 2,
+ HOUR = 3,
+ MINUTE = 4,
+ SECOND = 5,
+ MILLISECONDS = 6,
+ date = new Date(),
+ tokens = datetimeTokenizer( value, pattern, cldr ),
+ truncateAt = [],
+ units = [ "year", "month", "day", "hour", "minute", "second", "milliseconds" ];
+
+ if ( !tokens.length ) {
+ return null;
}
- sign = sign || "+";
+ valid = arrayEvery( tokens, function( token ) {
+ var century, chr, value, length;
- // determine exponent and number
- var exponent,
- intAndFraction,
- exponentPos = num.indexOf( "e" );
- if ( exponentPos < 0 ) exponentPos = num.indexOf( "E" );
- if ( exponentPos < 0 ) {
- intAndFraction = num;
- exponent = null;
- }
- else {
- intAndFraction = num.substr( 0, exponentPos );
- exponent = num.substr( exponentPos + 1 );
- }
- // determine decimal position
- var integer,
- fraction,
- decSep = nf[ "." ],
- decimalPos = intAndFraction.indexOf( decSep );
- if ( decimalPos < 0 ) {
- integer = intAndFraction;
- fraction = null;
- }
- else {
- integer = intAndFraction.substr( 0, decimalPos );
- fraction = intAndFraction.substr( decimalPos + decSep.length );
+ if ( token.type === "literal" ) {
+ // continue
+ return true;
+ }
+
+ chr = token.type.charAt( 0 );
+ length = token.type.length;
+
+ if ( chr === "j" ) {
+ // Locale preferred hHKk.
+ // http://www.unicode.org/reports/tr35/tr35-dates.html#Time_Data
+ chr = cldr.supplemental.timeData.preferred();
+ }
+
+ switch ( chr ) {
+
+ // Era
+ case "G":
+ truncateAt.push( YEAR );
+ era = +token.value;
+ break;
+
+ // Year
+ case "y":
+ value = +token.lexeme;
+ if ( length === 2 ) {
+ if ( outOfRange( value, 0, 99 ) ) {
+ return false;
+ }
+ // mimic dojo/date/locale: choose century to apply, according to a sliding window of 80 years before and 20 years after present year.
+ century = Math.floor( date.getFullYear() / 100 ) * 100;
+ value += century;
+ if ( value > date.getFullYear() + 20 ) {
+ value -= 100;
+ }
+ }
+ date.setFullYear( value );
+ truncateAt.push( YEAR );
+ break;
+
+ case "Y": // Year in "Week of Year"
+ case "u": // Extended year. Need to be implemented.
+ case "U": // Cyclic year name. Need to be implemented.
+ throw new Error( "Not implemented" );
+
+ // Quarter (skip)
+ case "Q":
+ case "q":
+ break;
+
+ // Month
+ case "M":
+ case "L":
+ if ( length <= 2 ) {
+ value = +token.lexeme;
+ } else {
+ value = +token.value;
+ }
+ if( outOfRange( value, 1, 12 ) ) {
+ return false;
+ }
+ date.setMonth( value - 1 );
+ truncateAt.push( MONTH );
+ break;
+
+ // Week (skip)
+ case "w": // Week of Year.
+ case "W": // Week of Month.
+ break;
+
+ // Day
+ case "d":
+ value = +token.lexeme;
+ if( outOfRange( value, 1, 31 ) ) {
+ return false;
+ }
+ date.setDate( value );
+ truncateAt.push( DAY );
+ break;
+
+ case "D":
+ value = +token.lexeme;
+ if( outOfRange( value, 1, 366 ) ) {
+ return false;
+ }
+ date.setMonth(0);
+ date.setDate( value );
+ truncateAt.push( DAY );
+ break;
+
+ case "F":
+ // Day of Week in month. eg. 2nd Wed in July.
+ // Skip
+ break;
+
+ case "g+":
+ // Modified Julian day. Need to be implemented.
+ throw new Error( "Not implemented" );
+
+ // Week day
+ case "e":
+ case "c":
+ case "E":
+ // Skip.
+ // value = arrayIndexOf( datetimeWeekDays, token.value );
+ break;
+
+ // Period (AM or PM)
+ case "a":
+ amPm = token.value;
+ break;
+
+ // Hour
+ case "K": // 0-11
+ value = +token.lexeme + 1;
+
+ /* falls through */
+ case "h": // 1-12
+ value = value || +token.lexeme;
+ if( outOfRange( value, 1, 12 ) ) {
+ return false;
+ }
+ date.setHours( value );
+ truncateAt.push( HOUR );
+ break;
+
+ case "H": // 0-23
+ value = +token.lexeme + 1;
+
+ /* falls through */
+ case "k": // 1-24
+ hour24 = true;
+ value = value || +token.lexeme;
+ if( outOfRange( value, 1, 24 ) ) {
+ return false;
+ }
+ date.setHours( value );
+ truncateAt.push( HOUR );
+ break;
+
+ // Minute
+ case "m":
+ value = +token.lexeme;
+ if( outOfRange( value, 0, 59 ) ) {
+ return false;
+ }
+ date.setMinutes( value );
+ truncateAt.push( MINUTE );
+ break;
+
+ // Second
+ case "s":
+ value = +token.lexeme;
+ if( outOfRange( value, 0, 59 ) ) {
+ return false;
+ }
+ date.setSeconds( value );
+ truncateAt.push( SECOND );
+ break;
+
+ case "A":
+ date.setHours( 0 );
+ date.setMinutes( 0 );
+ date.setSeconds( 0 );
+
+ /* falls through */
+ case "S":
+ value = Math.round( +token.lexeme * Math.pow( 10, 3 - length ) );
+ date.setMilliseconds( value );
+ truncateAt.push( MILLISECONDS );
+ break;
+
+ // Zone
+ // see http://www.unicode.org/reports/tr35/tr35-dates.html#Using_Time_Zone_Names ?
+ // Need to be implemented.
+ case "z":
+ case "Z":
+ case "O":
+ case "v":
+ case "V":
+ case "X":
+ case "x":
+ throw new Error( "Not implemented" );
+ }
+
+ return true;
+ });
+
+ if ( !valid || amPm && hour24 ) {
+ return null;
}
- // handle groups (e.g. 1,000,000)
- var groupSep = nf[ "," ];
- integer = integer.split( groupSep ).join( "" );
- var altGroupSep = groupSep.replace( /\u00A0/g, " " );
- if ( groupSep !== altGroupSep ) {
- integer = integer.split( altGroupSep ).join( "" );
+
+ if ( era === 0 ) {
+ // 1 BC = year 0
+ date.setFullYear( date.getFullYear() * -1 + 1 );
}
- // build a natively parsable number string
- var p = sign + integer;
- if ( fraction !== null ) {
- p += "." + fraction;
+
+ if ( amPm === "pm" && date.getHours() !== 12 ) {
+ date.setHours( date.getHours() + 12 );
}
- if ( exponent !== null ) {
- // exponent itself may have a number patternd
- var expSignInfo = parseNegativePattern( exponent, nf, "-n" );
- p += "e" + ( expSignInfo[0] || "+" ) + expSignInfo[ 1 ];
+
+ // Truncate date at the most precise unit defined. Eg.
+ // If value is "12/31", and pattern is "MM/dd":
+ // => new Date( , 12, 31, 0, 0, 0, 0 );
+ truncateAt = Math.max.apply( null, truncateAt );
+ date = datetimeStartOf( date, units[ truncateAt ] );
+
+ return date;
+ };
+
+}());
+
+
+ var arrayIsArray = Array.isArray || function( obj ) {
+ return Object.prototype.toString.call( obj ) === "[object Array]";
+ };
+
+
+
+
+ var alwaysArray = function( stringOrArray ) {
+ return arrayIsArray( stringOrArray ) ? stringOrArray : [ stringOrArray ];
+ };
+
+
+
+
+ var arraySome = function( array, callback ) {
+ var i, length;
+ if ( array.some ) {
+ return array.some( callback );
}
- if ( regexParseFloat.test(p) ) {
- ret = parseFloat( p );
+ for ( i = 0, length = array.length; i < length; i++ ) {
+ if ( callback( array[ i ], i, array ) ) {
+ return true;
+ }
}
- }
- return ret;
-};
+ return false;
+ };
+
-Globalize.culture = function( cultureSelector ) {
- // setter
- if ( typeof cultureSelector !== "undefined" ) {
- this.cultureSelector = cultureSelector;
+
+
+ var defaultLocale;
+
+ function getLocale( locale ) {
+ return locale ? new Cldr( locale ) : defaultLocale;
}
- // getter
- return this.findClosestCulture( cultureSelector ) || this.cultures[ "default" ];
-};
-}( this ));
\ No newline at end of file
+ var Globalize = {};
+
+ /**
+ * Globalize.load( json )
+ *
+ * @json [JSON]
+ *
+ * Load resolved or unresolved cldr data.
+ * Somewhat equivalent to previous Globalize.addCultureInfo(...).
+ */
+ Globalize.load = function( json ) {
+ Cldr.load( json );
+ };
+
+ /**
+ * Globalize.loadTranslations( locale, json )
+ *
+ * @locale [String]
+ *
+ * @json [JSON]
+ *
+ * Load translation data per locale.
+ */
+ Globalize.loadTranslations = function( locale, json ) {
+ var customData = {
+ "globalize-translation": {}
+ };
+ locale = new Cldr( locale );
+ customData[ "globalize-translation" ][ locale.attributes.languageId ] = json;
+ Cldr.load( customData );
+ };
+
+ /**
+ * Globalize.locale( locale )
+ *
+ * @locale [String]
+ *
+ * Set default locale.
+ * Somewhat equivalent to previous culture( selector ).
+ */
+ Globalize.locale = function( locale ) {
+ if ( arguments.length ) {
+ defaultLocale = new Cldr( locale );
+ }
+ return defaultLocale;
+ };
+
+ /**
+ * Globalize.format( value, pattern, locale )
+ *
+ * @value [Date or Number]
+ *
+ * @pattern [String or Object] see datetime/expand_pattern for more info.
+ *
+ * @locale [String]
+ *
+ * Formats a date or number according to the given pattern string and the given locale (or the default locale if not specified).
+ */
+ Globalize.format = function( value, pattern, locale ) {
+ locale = getLocale( locale );
+
+ if ( value instanceof Date ) {
+
+ if ( !pattern ) {
+ throw new Error( "Missing pattern" );
+ }
+ pattern = datetimeExpandPattern( pattern, locale );
+
+ value = datetimeFormat( value, pattern, locale );
+
+ } else if ( typeof value === "number" ) {
+ // TODO value = numberFormat( value, pattern, locale );
+ throw new Error( "Number Format not implemented yet" );
+ }
+
+ return value;
+ };
+
+ /**
+ * Globalize.parseDate( value, patterns, locale )
+ *
+ * @value [Date]
+ *
+ * @patterns [Array] Optional. See datetime/expand_pattern for more info about each pattern. Defaults to the list of all presets defined in the locale (see datetime/all_presets for more info).
+ *
+ * @locale [String]
+ *
+ * Return a Date instance or null.
+ */
+ Globalize.parseDate = function( value, patterns, locale ) {
+ var date;
+ locale = getLocale( locale );
+
+ if ( typeof value !== "string" ) {
+ throw new Error( "invalid value (" + value + "), string expected" );
+ }
+
+ if ( !patterns ) {
+ patterns = datetimeAllPresets( locale );
+ } else {
+ patterns = alwaysArray( patterns );
+ }
+
+ arraySome( patterns, function( pattern ) {
+ pattern = datetimeExpandPattern( pattern, locale );
+ date = datetimeParse( value, pattern, locale );
+ return !!date;
+ });
+
+ return date || null;
+ };
+
+ /**
+ * Globalize.translate( path, locale )
+ *
+ * @path [String or Array]
+ *
+ * @locale [String]
+ *
+ * Translate item given its path.
+ */
+ Globalize.translate = function( path , locale ) {
+ locale = getLocale( locale );
+ path = alwaysArray( path );
+ return locale.get( [ "globalize-translation/{languageId}" ].concat( path ) );
+ };
+
+ return Globalize;
+
+
+
+}));
diff --git a/external/localization.js b/external/localization.js
new file mode 100644
index 00000000000..4fd436aca00
--- /dev/null
+++ b/external/localization.js
@@ -0,0 +1,3119 @@
+/**
+ * CLDR locale data
+ */
+Globalize.load({
+ "main": {
+ "en": {
+ "identity": {
+ "version": {
+ "_cldrVersion": "24",
+ "_number": "$Revision: 9287 $"
+ },
+ "generation": {
+ "_date": "$Date: 2013-08-28 21:32:04 -0500 (Wed, 28 Aug 2013) $"
+ },
+ "language": "en"
+ },
+ "dates": {
+ "calendars": {
+ "gregorian": {
+ "months": {
+ "format": {
+ "abbreviated": {
+ "1": "Jan",
+ "2": "Feb",
+ "3": "Mar",
+ "4": "Apr",
+ "5": "May",
+ "6": "Jun",
+ "7": "Jul",
+ "8": "Aug",
+ "9": "Sep",
+ "10": "Oct",
+ "11": "Nov",
+ "12": "Dec"
+ },
+ "narrow": {
+ "1": "J",
+ "2": "F",
+ "3": "M",
+ "4": "A",
+ "5": "M",
+ "6": "J",
+ "7": "J",
+ "8": "A",
+ "9": "S",
+ "10": "O",
+ "11": "N",
+ "12": "D"
+ },
+ "wide": {
+ "1": "January",
+ "2": "February",
+ "3": "March",
+ "4": "April",
+ "5": "May",
+ "6": "June",
+ "7": "July",
+ "8": "August",
+ "9": "September",
+ "10": "October",
+ "11": "November",
+ "12": "December"
+ }
+ },
+ "stand-alone": {
+ "abbreviated": {
+ "1": "Jan",
+ "2": "Feb",
+ "3": "Mar",
+ "4": "Apr",
+ "5": "May",
+ "6": "Jun",
+ "7": "Jul",
+ "8": "Aug",
+ "9": "Sep",
+ "10": "Oct",
+ "11": "Nov",
+ "12": "Dec"
+ },
+ "narrow": {
+ "1": "J",
+ "2": "F",
+ "3": "M",
+ "4": "A",
+ "5": "M",
+ "6": "J",
+ "7": "J",
+ "8": "A",
+ "9": "S",
+ "10": "O",
+ "11": "N",
+ "12": "D"
+ },
+ "wide": {
+ "1": "January",
+ "2": "February",
+ "3": "March",
+ "4": "April",
+ "5": "May",
+ "6": "June",
+ "7": "July",
+ "8": "August",
+ "9": "September",
+ "10": "October",
+ "11": "November",
+ "12": "December"
+ }
+ }
+ },
+ "days": {
+ "format": {
+ "abbreviated": {
+ "sun": "Sun",
+ "mon": "Mon",
+ "tue": "Tue",
+ "wed": "Wed",
+ "thu": "Thu",
+ "fri": "Fri",
+ "sat": "Sat"
+ },
+ "narrow": {
+ "sun": "S",
+ "mon": "M",
+ "tue": "T",
+ "wed": "W",
+ "thu": "T",
+ "fri": "F",
+ "sat": "S"
+ },
+ "short": {
+ "sun": "Su",
+ "mon": "Mo",
+ "tue": "Tu",
+ "wed": "We",
+ "thu": "Th",
+ "fri": "Fr",
+ "sat": "Sa"
+ },
+ "wide": {
+ "sun": "Sunday",
+ "mon": "Monday",
+ "tue": "Tuesday",
+ "wed": "Wednesday",
+ "thu": "Thursday",
+ "fri": "Friday",
+ "sat": "Saturday"
+ }
+ },
+ "stand-alone": {
+ "abbreviated": {
+ "sun": "Sun",
+ "mon": "Mon",
+ "tue": "Tue",
+ "wed": "Wed",
+ "thu": "Thu",
+ "fri": "Fri",
+ "sat": "Sat"
+ },
+ "narrow": {
+ "sun": "S",
+ "mon": "M",
+ "tue": "T",
+ "wed": "W",
+ "thu": "T",
+ "fri": "F",
+ "sat": "S"
+ },
+ "short": {
+ "sun": "Su",
+ "mon": "Mo",
+ "tue": "Tu",
+ "wed": "We",
+ "thu": "Th",
+ "fri": "Fr",
+ "sat": "Sa"
+ },
+ "wide": {
+ "sun": "Sunday",
+ "mon": "Monday",
+ "tue": "Tuesday",
+ "wed": "Wednesday",
+ "thu": "Thursday",
+ "fri": "Friday",
+ "sat": "Saturday"
+ }
+ }
+ },
+ "quarters": {
+ "format": {
+ "abbreviated": {
+ "1": "Q1",
+ "2": "Q2",
+ "3": "Q3",
+ "4": "Q4"
+ },
+ "narrow": {
+ "1": "1",
+ "2": "2",
+ "3": "3",
+ "4": "4"
+ },
+ "wide": {
+ "1": "1st quarter",
+ "2": "2nd quarter",
+ "3": "3rd quarter",
+ "4": "4th quarter"
+ }
+ },
+ "stand-alone": {
+ "abbreviated": {
+ "1": "Q1",
+ "2": "Q2",
+ "3": "Q3",
+ "4": "Q4"
+ },
+ "narrow": {
+ "1": "1",
+ "2": "2",
+ "3": "3",
+ "4": "4"
+ },
+ "wide": {
+ "1": "1st quarter",
+ "2": "2nd quarter",
+ "3": "3rd quarter",
+ "4": "4th quarter"
+ }
+ }
+ },
+ "dayPeriods": {
+ "format": {
+ "abbreviated": {
+ "am": "AM",
+ "am-alt-variant": "a.m.",
+ "noon": "noon",
+ "pm": "PM",
+ "pm-alt-variant": "p.m."
+ },
+ "narrow": {
+ "am": "a",
+ "am-alt-variant": "a.m.",
+ "noon": "n",
+ "pm": "p",
+ "pm-alt-variant": "p.m."
+ },
+ "wide": {
+ "am": "AM",
+ "am-alt-variant": "a.m.",
+ "noon": "noon",
+ "pm": "PM",
+ "pm-alt-variant": "p.m."
+ }
+ },
+ "stand-alone": {
+ "abbreviated": {
+ "am": "AM",
+ "am-alt-variant": "a.m.",
+ "noon": "noon",
+ "pm": "PM",
+ "pm-alt-variant": "p.m."
+ },
+ "narrow": {
+ "am": "a",
+ "am-alt-variant": "a.m.",
+ "noon": "n",
+ "pm": "p",
+ "pm-alt-variant": "p.m."
+ },
+ "wide": {
+ "am": "AM",
+ "am-alt-variant": "a.m.",
+ "noon": "noon",
+ "pm": "PM",
+ "pm-alt-variant": "p.m."
+ }
+ }
+ },
+ "eras": {
+ "eraNames": {
+ "0": "Before Christ",
+ "0-alt-variant": "Before Common Era",
+ "1": "Anno Domini",
+ "1-alt-variant": "Common Era"
+ },
+ "eraAbbr": {
+ "0": "BC",
+ "0-alt-variant": "BCE",
+ "1": "AD",
+ "1-alt-variant": "CE"
+ },
+ "eraNarrow": {
+ "0": "B",
+ "0-alt-variant": "BCE",
+ "1": "A",
+ "1-alt-variant": "CE"
+ }
+ },
+ "dateFormats": {
+ "full": "EEEE, MMMM d, y",
+ "long": "MMMM d, y",
+ "medium": "MMM d, y",
+ "short": "M/d/yy"
+ },
+ "timeFormats": {
+ "full": "h:mm:ss a zzzz",
+ "long": "h:mm:ss a z",
+ "medium": "h:mm:ss a",
+ "short": "h:mm a"
+ },
+ "dateTimeFormats": {
+ "full": "{1} 'at' {0}",
+ "long": "{1} 'at' {0}",
+ "medium": "{1}, {0}",
+ "short": "{1}, {0}",
+ "availableFormats": {
+ "d": "d",
+ "Ed": "d E",
+ "Ehm": "E h:mm a",
+ "EHm": "E HH:mm",
+ "Ehms": "E h:mm:ss a",
+ "EHms": "E HH:mm:ss",
+ "Gy": "y G",
+ "GyMMM": "MMM y G",
+ "GyMMMd": "MMM d, y G",
+ "GyMMMEd": "E, MMM d, y G",
+ "h": "h a",
+ "H": "HH",
+ "hm": "h:mm a",
+ "Hm": "HH:mm",
+ "hms": "h:mm:ss a",
+ "Hms": "HH:mm:ss",
+ "M": "L",
+ "Md": "M/d",
+ "MEd": "E, M/d",
+ "MMM": "LLL",
+ "MMMd": "MMM d",
+ "MMMEd": "E, MMM d",
+ "ms": "mm:ss",
+ "y": "y",
+ "yM": "M/y",
+ "yMd": "M/d/y",
+ "yMEd": "E, M/d/y",
+ "yMMM": "MMM y",
+ "yMMMd": "MMM d, y",
+ "yMMMEd": "E, MMM d, y",
+ "yQQQ": "QQQ y",
+ "yQQQQ": "QQQQ y"
+ },
+ "appendItems": {
+ "Day": "{0} ({2}: {1})",
+ "Day-Of-Week": "{0} {1}",
+ "Era": "{0} {1}",
+ "Hour": "{0} ({2}: {1})",
+ "Minute": "{0} ({2}: {1})",
+ "Month": "{0} ({2}: {1})",
+ "Quarter": "{0} ({2}: {1})",
+ "Second": "{0} ({2}: {1})",
+ "Timezone": "{0} {1}",
+ "Week": "{0} ({2}: {1})",
+ "Year": "{0} {1}"
+ },
+ "intervalFormats": {
+ "intervalFormatFallback": "{0} – {1}",
+ "d": {
+ "d": "d – d"
+ },
+ "h": {
+ "a": "h a – h a",
+ "h": "h – h a"
+ },
+ "H": {
+ "H": "HH – HH"
+ },
+ "hm": {
+ "a": "h:mm a – h:mm a",
+ "h": "h:mm – h:mm a",
+ "m": "h:mm – h:mm a"
+ },
+ "Hm": {
+ "H": "HH:mm – HH:mm",
+ "m": "HH:mm – HH:mm"
+ },
+ "hmv": {
+ "a": "h:mm a – h:mm a v",
+ "h": "h:mm – h:mm a v",
+ "m": "h:mm – h:mm a v"
+ },
+ "Hmv": {
+ "H": "HH:mm – HH:mm v",
+ "m": "HH:mm – HH:mm v"
+ },
+ "hv": {
+ "a": "h a – h a v",
+ "h": "h – h a v"
+ },
+ "Hv": {
+ "H": "HH – HH v"
+ },
+ "M": {
+ "M": "M – M"
+ },
+ "Md": {
+ "d": "M/d – M/d",
+ "M": "M/d – M/d"
+ },
+ "MEd": {
+ "d": "E, M/d – E, M/d",
+ "M": "E, M/d – E, M/d"
+ },
+ "MMM": {
+ "M": "MMM – MMM"
+ },
+ "MMMd": {
+ "d": "MMM d – d",
+ "M": "MMM d – MMM d"
+ },
+ "MMMEd": {
+ "d": "E, MMM d – E, MMM d",
+ "M": "E, MMM d – E, MMM d"
+ },
+ "y": {
+ "y": "y – y"
+ },
+ "yM": {
+ "M": "M/y – M/y",
+ "y": "M/y – M/y"
+ },
+ "yMd": {
+ "d": "M/d/y – M/d/y",
+ "M": "M/d/y – M/d/y",
+ "y": "M/d/y – M/d/y"
+ },
+ "yMEd": {
+ "d": "E, M/d/y – E, M/d/y",
+ "M": "E, M/d/y – E, M/d/y",
+ "y": "E, M/d/y – E, M/d/y"
+ },
+ "yMMM": {
+ "M": "MMM – MMM y",
+ "y": "MMM y – MMM y"
+ },
+ "yMMMd": {
+ "d": "MMM d – d, y",
+ "M": "MMM d – MMM d, y",
+ "y": "MMM d, y – MMM d, y"
+ },
+ "yMMMEd": {
+ "d": "E, MMM d – E, MMM d, y",
+ "M": "E, MMM d – E, MMM d, y",
+ "y": "E, MMM d, y – E, MMM d, y"
+ },
+ "yMMMM": {
+ "M": "MMMM – MMMM y",
+ "y": "MMMM y – MMMM y"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+});
+
+Globalize.load({
+ "main": {
+ "de": {
+ "identity": {
+ "version": {
+ "_cldrVersion": "24",
+ "_number": "$Revision: 9287 $"
+ },
+ "generation": {
+ "_date": "$Date: 2013-08-28 21:32:04 -0500 (Wed, 28 Aug 2013) $"
+ },
+ "language": "de"
+ },
+ "dates": {
+ "calendars": {
+ "gregorian": {
+ "months": {
+ "format": {
+ "abbreviated": {
+ "1": "Jan.",
+ "2": "Feb.",
+ "3": "März",
+ "4": "Apr.",
+ "5": "Mai",
+ "6": "Juni",
+ "7": "Juli",
+ "8": "Aug.",
+ "9": "Sep.",
+ "10": "Okt.",
+ "11": "Nov.",
+ "12": "Dez."
+ },
+ "narrow": {
+ "1": "J",
+ "2": "F",
+ "3": "M",
+ "4": "A",
+ "5": "M",
+ "6": "J",
+ "7": "J",
+ "8": "A",
+ "9": "S",
+ "10": "O",
+ "11": "N",
+ "12": "D"
+ },
+ "wide": {
+ "1": "Januar",
+ "2": "Februar",
+ "3": "März",
+ "4": "April",
+ "5": "Mai",
+ "6": "Juni",
+ "7": "Juli",
+ "8": "August",
+ "9": "September",
+ "10": "Oktober",
+ "11": "November",
+ "12": "Dezember"
+ }
+ },
+ "stand-alone": {
+ "abbreviated": {
+ "1": "Jan",
+ "2": "Feb",
+ "3": "Mär",
+ "4": "Apr",
+ "5": "Mai",
+ "6": "Jun",
+ "7": "Jul",
+ "8": "Aug",
+ "9": "Sep",
+ "10": "Okt",
+ "11": "Nov",
+ "12": "Dez"
+ },
+ "narrow": {
+ "1": "J",
+ "2": "F",
+ "3": "M",
+ "4": "A",
+ "5": "M",
+ "6": "J",
+ "7": "J",
+ "8": "A",
+ "9": "S",
+ "10": "O",
+ "11": "N",
+ "12": "D"
+ },
+ "wide": {
+ "1": "Januar",
+ "2": "Februar",
+ "3": "März",
+ "4": "April",
+ "5": "Mai",
+ "6": "Juni",
+ "7": "Juli",
+ "8": "August",
+ "9": "September",
+ "10": "Oktober",
+ "11": "November",
+ "12": "Dezember"
+ }
+ }
+ },
+ "days": {
+ "format": {
+ "abbreviated": {
+ "sun": "So.",
+ "mon": "Mo.",
+ "tue": "Di.",
+ "wed": "Mi.",
+ "thu": "Do.",
+ "fri": "Fr.",
+ "sat": "Sa."
+ },
+ "narrow": {
+ "sun": "S",
+ "mon": "M",
+ "tue": "D",
+ "wed": "M",
+ "thu": "D",
+ "fri": "F",
+ "sat": "S"
+ },
+ "short": {
+ "sun": "So.",
+ "mon": "Mo.",
+ "tue": "Di.",
+ "wed": "Mi.",
+ "thu": "Do.",
+ "fri": "Fr.",
+ "sat": "Sa."
+ },
+ "wide": {
+ "sun": "Sonntag",
+ "mon": "Montag",
+ "tue": "Dienstag",
+ "wed": "Mittwoch",
+ "thu": "Donnerstag",
+ "fri": "Freitag",
+ "sat": "Samstag"
+ }
+ },
+ "stand-alone": {
+ "abbreviated": {
+ "sun": "So",
+ "mon": "Mo",
+ "tue": "Di",
+ "wed": "Mi",
+ "thu": "Do",
+ "fri": "Fr",
+ "sat": "Sa"
+ },
+ "narrow": {
+ "sun": "S",
+ "mon": "M",
+ "tue": "D",
+ "wed": "M",
+ "thu": "D",
+ "fri": "F",
+ "sat": "S"
+ },
+ "short": {
+ "sun": "So.",
+ "mon": "Mo.",
+ "tue": "Di.",
+ "wed": "Mi.",
+ "thu": "Do.",
+ "fri": "Fr.",
+ "sat": "Sa."
+ },
+ "wide": {
+ "sun": "Sonntag",
+ "mon": "Montag",
+ "tue": "Dienstag",
+ "wed": "Mittwoch",
+ "thu": "Donnerstag",
+ "fri": "Freitag",
+ "sat": "Samstag"
+ }
+ }
+ },
+ "quarters": {
+ "format": {
+ "abbreviated": {
+ "1": "Q1",
+ "2": "Q2",
+ "3": "Q3",
+ "4": "Q4"
+ },
+ "narrow": {
+ "1": "1",
+ "2": "2",
+ "3": "3",
+ "4": "4"
+ },
+ "wide": {
+ "1": "1. Quartal",
+ "2": "2. Quartal",
+ "3": "3. Quartal",
+ "4": "4. Quartal"
+ }
+ },
+ "stand-alone": {
+ "abbreviated": {
+ "1": "Q1",
+ "2": "Q2",
+ "3": "Q3",
+ "4": "Q4"
+ },
+ "narrow": {
+ "1": "1",
+ "2": "2",
+ "3": "3",
+ "4": "4"
+ },
+ "wide": {
+ "1": "1. Quartal",
+ "2": "2. Quartal",
+ "3": "3. Quartal",
+ "4": "4. Quartal"
+ }
+ }
+ },
+ "dayPeriods": {
+ "format": {
+ "abbreviated": {
+ "afternoon": "nachmittags",
+ "am": "vorm.",
+ "earlyMorning": "morgens",
+ "evening": "abends",
+ "morning": "vormittags",
+ "night": "nachts",
+ "noon": "Mittag",
+ "pm": "nachm."
+ },
+ "narrow": {
+ "afternoon": "nachmittags",
+ "am": "vorm.",
+ "earlyMorning": "morgens",
+ "evening": "abends",
+ "morning": "vormittags",
+ "night": "nachts",
+ "noon": "Mittag",
+ "pm": "nachm."
+ },
+ "wide": {
+ "afternoon": "nachmittags",
+ "am": "vorm.",
+ "earlyMorning": "morgens",
+ "evening": "abends",
+ "morning": "vormittags",
+ "night": "nachts",
+ "noon": "Mittag",
+ "pm": "nachm."
+ }
+ },
+ "stand-alone": {
+ "abbreviated": {
+ "afternoon": "nachmittags",
+ "am": "vorm.",
+ "earlyMorning": "morgens",
+ "evening": "abends",
+ "morning": "vormittags",
+ "night": "nachts",
+ "noon": "Mittag",
+ "pm": "nachm."
+ },
+ "narrow": {
+ "afternoon": "nachmittags",
+ "am": "vorm.",
+ "earlyMorning": "morgens",
+ "evening": "abends",
+ "morning": "vormittags",
+ "night": "nachts",
+ "noon": "Mittag",
+ "pm": "nachm."
+ },
+ "wide": {
+ "afternoon": "Nachmittag",
+ "am": "vorm.",
+ "earlyMorning": "Morgen",
+ "evening": "Abend",
+ "morning": "Vormittag",
+ "night": "Nacht",
+ "noon": "Mittag",
+ "pm": "nachm."
+ }
+ }
+ },
+ "eras": {
+ "eraNames": {
+ "0": "v. Chr.",
+ "0-alt-variant": "vor der gewöhnlichen Zeitrechnung",
+ "1": "n. Chr.",
+ "1-alt-variant": "der gewöhnlichen Zeitrechnung"
+ },
+ "eraAbbr": {
+ "0": "v. Chr.",
+ "0-alt-variant": "v. u. Z.",
+ "1": "n. Chr.",
+ "1-alt-variant": "u. Z."
+ },
+ "eraNarrow": {
+ "0": "v. Chr.",
+ "0-alt-variant": "vdZ",
+ "1": "n. Chr.",
+ "1-alt-variant": "dZ"
+ }
+ },
+ "dateFormats": {
+ "full": "EEEE, d. MMMM y",
+ "long": "d. MMMM y",
+ "medium": "dd.MM.y",
+ "short": "dd.MM.yy"
+ },
+ "timeFormats": {
+ "full": "HH:mm:ss zzzz",
+ "long": "HH:mm:ss z",
+ "medium": "HH:mm:ss",
+ "short": "HH:mm"
+ },
+ "dateTimeFormats": {
+ "full": "{1} {0}",
+ "long": "{1} {0}",
+ "medium": "{1} {0}",
+ "short": "{1} {0}",
+ "availableFormats": {
+ "d": "d",
+ "Ed": "E, d.",
+ "Ehm": "E h:mm a",
+ "EHm": "E, HH:mm",
+ "Ehms": "E, h:mm:ss a",
+ "EHms": "E, HH:mm:ss",
+ "Gy": "y G",
+ "GyMMM": "MMM y G",
+ "GyMMMd": "d. MMM y G",
+ "GyMMMEd": "E, d. MMM y G",
+ "h": "h a",
+ "H": "HH 'Uhr'",
+ "hm": "h:mm a",
+ "Hm": "HH:mm",
+ "hms": "h:mm:ss a",
+ "Hms": "HH:mm:ss",
+ "M": "L",
+ "Md": "d.M.",
+ "MEd": "E, d.M.",
+ "MMd": "d.MM.",
+ "MMdd": "dd.MM.",
+ "MMM": "LLL",
+ "MMMd": "d. MMM",
+ "MMMEd": "E, d. MMM",
+ "MMMMdd": "dd. MMMM",
+ "MMMMEd": "E, d. MMMM",
+ "ms": "mm:ss",
+ "y": "y",
+ "yM": "M.y",
+ "yMd": "d.M.y",
+ "yMEd": "E, d.M.y",
+ "yMM": "MM.y",
+ "yMMdd": "dd.MM.y",
+ "yMMM": "MMM y",
+ "yMMMd": "d. MMM y",
+ "yMMMEd": "E, d. MMM y",
+ "yMMMM": "MMMM y",
+ "yQQQ": "QQQ y",
+ "yQQQQ": "QQQQ y"
+ },
+ "appendItems": {
+ "Day": "{0} ({2}: {1})",
+ "Day-Of-Week": "{0} {1}",
+ "Era": "{1} {0}",
+ "Hour": "{0} ({2}: {1})",
+ "Minute": "{0} ({2}: {1})",
+ "Month": "{0} ({2}: {1})",
+ "Quarter": "{0} ({2}: {1})",
+ "Second": "{0} ({2}: {1})",
+ "Timezone": "{0} {1}",
+ "Week": "{0} ({2}: {1})",
+ "Year": "{1} {0}"
+ },
+ "intervalFormats": {
+ "intervalFormatFallback": "{0} - {1}",
+ "d": {
+ "d": "d.-d."
+ },
+ "h": {
+ "a": "h a - h a",
+ "h": "h-h a"
+ },
+ "H": {
+ "H": "HH-HH 'Uhr'"
+ },
+ "hm": {
+ "a": "h:mm a - h:mm a",
+ "h": "h:mm-h:mm a",
+ "m": "h:mm-h:mm a"
+ },
+ "Hm": {
+ "H": "HH:mm-HH:mm",
+ "m": "HH:mm-HH:mm"
+ },
+ "hmv": {
+ "a": "h:mm a - h:mm a v",
+ "h": "h:mm-h:mm a v",
+ "m": "h:mm-h:mm a v"
+ },
+ "Hmv": {
+ "H": "HH:mm-HH:mm v",
+ "m": "HH:mm-HH:mm v"
+ },
+ "hv": {
+ "a": "h a - h a v",
+ "h": "h-h a v"
+ },
+ "Hv": {
+ "H": "HH-HH 'Uhr' v"
+ },
+ "M": {
+ "M": "M.-M."
+ },
+ "Md": {
+ "d": "dd.MM. - dd.MM.",
+ "M": "dd.MM. - dd.MM."
+ },
+ "MEd": {
+ "d": "E, dd.MM. - E, dd.MM.",
+ "M": "E, dd.MM. - E, dd.MM."
+ },
+ "MMM": {
+ "M": "MMM-MMM"
+ },
+ "MMMd": {
+ "d": "d.-d. MMM",
+ "M": "d. MMM - d. MMM"
+ },
+ "MMMEd": {
+ "d": "E, d. - E, d. MMM",
+ "M": "E, d. MMM - E, d. MMM"
+ },
+ "MMMM": {
+ "M": "LLLL-LLLL"
+ },
+ "y": {
+ "y": "y-y"
+ },
+ "yM": {
+ "M": "MM.y - MM.y",
+ "y": "MM.y - MM.y"
+ },
+ "yMd": {
+ "d": "dd.MM.y - dd.MM.y",
+ "M": "dd.MM.y - dd.MM.y",
+ "y": "dd.MM.y - dd.MM.y"
+ },
+ "yMEd": {
+ "d": "E, dd.MM.y - E, dd.MM.y",
+ "M": "E, dd.MM.y - E, dd.MM.y",
+ "y": "E, dd.MM.y - E, dd.MM.y"
+ },
+ "yMMM": {
+ "M": "MMM-MMM y",
+ "y": "MMM y - MMM y"
+ },
+ "yMMMd": {
+ "d": "d.-d. MMM y",
+ "M": "d. MMM - d. MMM y",
+ "y": "d. MMM y - d. MMM y"
+ },
+ "yMMMEd": {
+ "d": "E, d. - E, d. MMM y",
+ "M": "E, d. MMM - E, d. MMM y",
+ "y": "E, d. MMM y - E, d. MMM y"
+ },
+ "yMMMM": {
+ "M": "MMMM-MMMM y",
+ "y": "MMMM y - MMMM y"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+});
+
+/**
+ * CLDR supplemental data
+ */
+
+// likelySubtags
+Globalize.load({
+ "supplemental": {
+ "version": {
+ "_cldrVersion": "24",
+ "_number": "$Revision: 9305 $"
+ },
+ "generation": {
+ "_date": "$Date: 2013-09-04 09:50:17 -0500 (Wed, 04 Sep 2013) $"
+ },
+ "likelySubtags": {
+ "aa": "aa_Latn_ET",
+ "ab": "ab_Cyrl_GE",
+ "ace": "ace_Latn_ID",
+ "ady": "ady_Cyrl_RU",
+ "af": "af_Latn_ZA",
+ "agq": "agq_Latn_CM",
+ "ak": "ak_Latn_GH",
+ "alt": "alt_Cyrl_RU",
+ "am": "am_Ethi_ET",
+ "amo": "amo_Latn_NG",
+ "ar": "ar_Arab_EG",
+ "as": "as_Beng_IN",
+ "asa": "asa_Latn_TZ",
+ "ast": "ast_Latn_ES",
+ "av": "av_Cyrl_RU",
+ "awa": "awa_Deva_IN",
+ "ay": "ay_Latn_BO",
+ "az": "az_Latn_AZ",
+ "az_Arab": "az_Arab_IR",
+ "az_IR": "az_Arab_IR",
+ "az_RU": "az_Cyrl_RU",
+ "ba": "ba_Cyrl_RU",
+ "bal": "bal_Arab_PK",
+ "ban": "ban_Latn_ID",
+ "bas": "bas_Latn_CM",
+ "bax": "bax_Bamu_CM",
+ "bbc": "bbc_Latn_ID",
+ "be": "be_Cyrl_BY",
+ "bem": "bem_Latn_ZM",
+ "bez": "bez_Latn_TZ",
+ "bfq": "bfq_Taml_IN",
+ "bft": "bft_Arab_PK",
+ "bfy": "bfy_Deva_IN",
+ "bg": "bg_Cyrl_BG",
+ "bhb": "bhb_Deva_IN",
+ "bho": "bho_Deva_IN",
+ "bi": "bi_Latn_VU",
+ "bik": "bik_Latn_PH",
+ "bin": "bin_Latn_NG",
+ "bjj": "bjj_Deva_IN",
+ "bku": "bku_Latn_PH",
+ "bm": "bm_Latn_ML",
+ "bn": "bn_Beng_BD",
+ "bo": "bo_Tibt_CN",
+ "bqv": "bqv_Latn_CI",
+ "br": "br_Latn_FR",
+ "bra": "bra_Deva_IN",
+ "brx": "brx_Deva_IN",
+ "bs": "bs_Latn_BA",
+ "bss": "bss_Latn_CM",
+ "btv": "btv_Deva_PK",
+ "bua": "bua_Cyrl_RU",
+ "buc": "buc_Latn_YT",
+ "bug": "bug_Latn_ID",
+ "bya": "bya_Latn_ID",
+ "byn": "byn_Ethi_ER",
+ "ca": "ca_Latn_ES",
+ "cch": "cch_Latn_NG",
+ "ccp": "ccp_Beng_IN",
+ "ce": "ce_Cyrl_RU",
+ "ceb": "ceb_Latn_PH",
+ "cgg": "cgg_Latn_UG",
+ "ch": "ch_Latn_GU",
+ "chk": "chk_Latn_FM",
+ "chm": "chm_Cyrl_RU",
+ "chp": "chp_Latn_CA",
+ "chr": "chr_Cher_US",
+ "cja": "cja_Arab_KH",
+ "cjm": "cjm_Cham_VN",
+ "ckb": "ckb_Arab_IQ",
+ "co": "co_Latn_FR",
+ "cr": "cr_Cans_CA",
+ "crk": "crk_Cans_CA",
+ "cs": "cs_Latn_CZ",
+ "csb": "csb_Latn_PL",
+ "cv": "cv_Cyrl_RU",
+ "cy": "cy_Latn_GB",
+ "da": "da_Latn_DK",
+ "dar": "dar_Cyrl_RU",
+ "dav": "dav_Latn_KE",
+ "de": "de_Latn_DE",
+ "den": "den_Latn_CA",
+ "dgr": "dgr_Latn_CA",
+ "dje": "dje_Latn_NE",
+ "doi": "doi_Arab_IN",
+ "dsb": "dsb_Latn_DE",
+ "dua": "dua_Latn_CM",
+ "dv": "dv_Thaa_MV",
+ "dyo": "dyo_Latn_SN",
+ "dyu": "dyu_Latn_BF",
+ "dz": "dz_Tibt_BT",
+ "ebu": "ebu_Latn_KE",
+ "ee": "ee_Latn_GH",
+ "efi": "efi_Latn_NG",
+ "el": "el_Grek_GR",
+ "en": "en_Latn_US",
+ "eo": "eo_Latn_001",
+ "es": "es_Latn_ES",
+ "et": "et_Latn_EE",
+ "eu": "eu_Latn_ES",
+ "ewo": "ewo_Latn_CM",
+ "fa": "fa_Arab_IR",
+ "fan": "fan_Latn_GQ",
+ "ff": "ff_Latn_SN",
+ "fi": "fi_Latn_FI",
+ "fil": "fil_Latn_PH",
+ "fj": "fj_Latn_FJ",
+ "fo": "fo_Latn_FO",
+ "fon": "fon_Latn_BJ",
+ "fr": "fr_Latn_FR",
+ "fur": "fur_Latn_IT",
+ "fy": "fy_Latn_NL",
+ "ga": "ga_Latn_IE",
+ "gaa": "gaa_Latn_GH",
+ "gag": "gag_Latn_MD",
+ "gbm": "gbm_Deva_IN",
+ "gcr": "gcr_Latn_GF",
+ "gd": "gd_Latn_GB",
+ "gez": "gez_Ethi_ET",
+ "gil": "gil_Latn_KI",
+ "gl": "gl_Latn_ES",
+ "gn": "gn_Latn_PY",
+ "gon": "gon_Telu_IN",
+ "gor": "gor_Latn_ID",
+ "grt": "grt_Beng_IN",
+ "gsw": "gsw_Latn_CH",
+ "gu": "gu_Gujr_IN",
+ "guz": "guz_Latn_KE",
+ "gv": "gv_Latn_IM",
+ "gwi": "gwi_Latn_CA",
+ "ha": "ha_Latn_NG",
+ "ha_CM": "ha_Arab_CM",
+ "ha_SD": "ha_Arab_SD",
+ "haw": "haw_Latn_US",
+ "he": "he_Hebr_IL",
+ "hi": "hi_Deva_IN",
+ "hil": "hil_Latn_PH",
+ "hne": "hne_Deva_IN",
+ "hnn": "hnn_Latn_PH",
+ "ho": "ho_Latn_PG",
+ "hoc": "hoc_Deva_IN",
+ "hoj": "hoj_Deva_IN",
+ "hr": "hr_Latn_HR",
+ "ht": "ht_Latn_HT",
+ "hu": "hu_Latn_HU",
+ "hy": "hy_Armn_AM",
+ "ia": "ia_Latn_FR",
+ "ibb": "ibb_Latn_NG",
+ "id": "id_Latn_ID",
+ "ig": "ig_Latn_NG",
+ "ii": "ii_Yiii_CN",
+ "ik": "ik_Latn_US",
+ "ilo": "ilo_Latn_PH",
+ "in": "in_Latn_ID",
+ "inh": "inh_Cyrl_RU",
+ "is": "is_Latn_IS",
+ "it": "it_Latn_IT",
+ "iu": "iu_Cans_CA",
+ "iw": "iw_Hebr_IL",
+ "ja": "ja_Jpan_JP",
+ "jgo": "jgo_Latn_CM",
+ "ji": "ji_Hebr_UA",
+ "jmc": "jmc_Latn_TZ",
+ "jv": "jv_Latn_ID",
+ "jw": "jw_Latn_ID",
+ "ka": "ka_Geor_GE",
+ "kaa": "kaa_Cyrl_UZ",
+ "kab": "kab_Latn_DZ",
+ "kaj": "kaj_Latn_NG",
+ "kam": "kam_Latn_KE",
+ "kbd": "kbd_Cyrl_RU",
+ "kcg": "kcg_Latn_NG",
+ "kde": "kde_Latn_TZ",
+ "kdt": "kdt_Thai_TH",
+ "kea": "kea_Latn_CV",
+ "ken": "ken_Latn_CM",
+ "kfo": "kfo_Latn_CI",
+ "kfr": "kfr_Deva_IN",
+ "kg": "kg_Latn_CD",
+ "kha": "kha_Latn_IN",
+ "khb": "khb_Talu_CN",
+ "khq": "khq_Latn_ML",
+ "kht": "kht_Mymr_IN",
+ "ki": "ki_Latn_KE",
+ "kj": "kj_Latn_NA",
+ "kk": "kk_Cyrl_KZ",
+ "kk_AF": "kk_Arab_AF",
+ "kk_Arab": "kk_Arab_CN",
+ "kk_CN": "kk_Arab_CN",
+ "kk_IR": "kk_Arab_IR",
+ "kk_MN": "kk_Arab_MN",
+ "kkj": "kkj_Latn_CM",
+ "kl": "kl_Latn_GL",
+ "kln": "kln_Latn_KE",
+ "km": "km_Khmr_KH",
+ "kmb": "kmb_Latn_AO",
+ "kn": "kn_Knda_IN",
+ "ko": "ko_Kore_KR",
+ "koi": "koi_Cyrl_RU",
+ "kok": "kok_Deva_IN",
+ "kos": "kos_Latn_FM",
+ "kpe": "kpe_Latn_LR",
+ "krc": "krc_Cyrl_RU",
+ "kri": "kri_Latn_SL",
+ "krl": "krl_Latn_RU",
+ "kru": "kru_Deva_IN",
+ "ks": "ks_Arab_IN",
+ "ksb": "ksb_Latn_TZ",
+ "ksf": "ksf_Latn_CM",
+ "ksh": "ksh_Latn_DE",
+ "ku": "ku_Latn_TR",
+ "ku_Arab": "ku_Arab_IQ",
+ "ku_LB": "ku_Arab_LB",
+ "kum": "kum_Cyrl_RU",
+ "kv": "kv_Cyrl_RU",
+ "kw": "kw_Latn_GB",
+ "ky": "ky_Cyrl_KG",
+ "ky_Arab": "ky_Arab_CN",
+ "ky_CN": "ky_Arab_CN",
+ "ky_Latn": "ky_Latn_TR",
+ "ky_TR": "ky_Latn_TR",
+ "la": "la_Latn_VA",
+ "lag": "lag_Latn_TZ",
+ "lah": "lah_Arab_PK",
+ "lb": "lb_Latn_LU",
+ "lbe": "lbe_Cyrl_RU",
+ "lcp": "lcp_Thai_CN",
+ "lep": "lep_Lepc_IN",
+ "lez": "lez_Cyrl_RU",
+ "lg": "lg_Latn_UG",
+ "li": "li_Latn_NL",
+ "lif": "lif_Deva_NP",
+ "lis": "lis_Lisu_CN",
+ "lki": "lki_Arab_IR",
+ "lkt": "lkt_Latn_US",
+ "lmn": "lmn_Telu_IN",
+ "ln": "ln_Latn_CD",
+ "lo": "lo_Laoo_LA",
+ "lol": "lol_Latn_CD",
+ "lt": "lt_Latn_LT",
+ "lu": "lu_Latn_CD",
+ "lua": "lua_Latn_CD",
+ "luo": "luo_Latn_KE",
+ "luy": "luy_Latn_KE",
+ "lv": "lv_Latn_LV",
+ "lwl": "lwl_Thai_TH",
+ "mad": "mad_Latn_ID",
+ "mag": "mag_Deva_IN",
+ "mai": "mai_Deva_IN",
+ "mak": "mak_Latn_ID",
+ "man": "man_Latn_GM",
+ "man_GN": "man_Nkoo_GN",
+ "man_Nkoo": "man_Nkoo_GN",
+ "mas": "mas_Latn_KE",
+ "mdf": "mdf_Cyrl_RU",
+ "mdh": "mdh_Latn_PH",
+ "mdr": "mdr_Latn_ID",
+ "men": "men_Latn_SL",
+ "mer": "mer_Latn_KE",
+ "mfe": "mfe_Latn_MU",
+ "mg": "mg_Latn_MG",
+ "mgh": "mgh_Latn_MZ",
+ "mgo": "mgo_Latn_CM",
+ "mh": "mh_Latn_MH",
+ "mi": "mi_Latn_NZ",
+ "min": "min_Latn_ID",
+ "mk": "mk_Cyrl_MK",
+ "ml": "ml_Mlym_IN",
+ "mn": "mn_Cyrl_MN",
+ "mn_CN": "mn_Mong_CN",
+ "mn_Mong": "mn_Mong_CN",
+ "mni": "mni_Beng_IN",
+ "mnw": "mnw_Mymr_MM",
+ "mo": "mo_Latn_RO",
+ "mos": "mos_Latn_BF",
+ "mr": "mr_Deva_IN",
+ "ms": "ms_Latn_MY",
+ "ms_CC": "ms_Arab_CC",
+ "ms_ID": "ms_Arab_ID",
+ "mt": "mt_Latn_MT",
+ "mua": "mua_Latn_CM",
+ "mwr": "mwr_Deva_IN",
+ "my": "my_Mymr_MM",
+ "myv": "myv_Cyrl_RU",
+ "na": "na_Latn_NR",
+ "nap": "nap_Latn_IT",
+ "naq": "naq_Latn_NA",
+ "nb": "nb_Latn_NO",
+ "nd": "nd_Latn_ZW",
+ "nds": "nds_Latn_DE",
+ "ne": "ne_Deva_NP",
+ "new": "new_Deva_NP",
+ "ng": "ng_Latn_NA",
+ "niu": "niu_Latn_NU",
+ "nl": "nl_Latn_NL",
+ "nmg": "nmg_Latn_CM",
+ "nn": "nn_Latn_NO",
+ "nnh": "nnh_Latn_CM",
+ "no": "no_Latn_NO",
+ "nod": "nod_Lana_TH",
+ "nr": "nr_Latn_ZA",
+ "nso": "nso_Latn_ZA",
+ "nus": "nus_Latn_SD",
+ "nv": "nv_Latn_US",
+ "ny": "ny_Latn_MW",
+ "nym": "nym_Latn_TZ",
+ "nyn": "nyn_Latn_UG",
+ "oc": "oc_Latn_FR",
+ "om": "om_Latn_ET",
+ "or": "or_Orya_IN",
+ "os": "os_Cyrl_GE",
+ "pa": "pa_Guru_IN",
+ "pa_Arab": "pa_Arab_PK",
+ "pa_PK": "pa_Arab_PK",
+ "pag": "pag_Latn_PH",
+ "pam": "pam_Latn_PH",
+ "pap": "pap_Latn_AW",
+ "pau": "pau_Latn_PW",
+ "pl": "pl_Latn_PL",
+ "pon": "pon_Latn_FM",
+ "prd": "prd_Arab_IR",
+ "ps": "ps_Arab_AF",
+ "pt": "pt_Latn_BR",
+ "qu": "qu_Latn_PE",
+ "raj": "raj_Latn_IN",
+ "rcf": "rcf_Latn_RE",
+ "rej": "rej_Latn_ID",
+ "rjs": "rjs_Deva_NP",
+ "rkt": "rkt_Beng_BD",
+ "rm": "rm_Latn_CH",
+ "rn": "rn_Latn_BI",
+ "ro": "ro_Latn_RO",
+ "rof": "rof_Latn_TZ",
+ "ru": "ru_Cyrl_RU",
+ "rw": "rw_Latn_RW",
+ "rwk": "rwk_Latn_TZ",
+ "sa": "sa_Deva_IN",
+ "saf": "saf_Latn_GH",
+ "sah": "sah_Cyrl_RU",
+ "saq": "saq_Latn_KE",
+ "sas": "sas_Latn_ID",
+ "sat": "sat_Latn_IN",
+ "saz": "saz_Saur_IN",
+ "sbp": "sbp_Latn_TZ",
+ "scn": "scn_Latn_IT",
+ "sco": "sco_Latn_GB",
+ "sd": "sd_Arab_PK",
+ "sd_Deva": "sd_Deva_IN",
+ "sdh": "sdh_Arab_IR",
+ "se": "se_Latn_NO",
+ "seh": "seh_Latn_MZ",
+ "ses": "ses_Latn_ML",
+ "sg": "sg_Latn_CF",
+ "shi": "shi_Tfng_MA",
+ "shn": "shn_Mymr_MM",
+ "si": "si_Sinh_LK",
+ "sid": "sid_Latn_ET",
+ "sk": "sk_Latn_SK",
+ "sl": "sl_Latn_SI",
+ "sm": "sm_Latn_WS",
+ "sma": "sma_Latn_SE",
+ "smj": "smj_Latn_SE",
+ "smn": "smn_Latn_FI",
+ "sms": "sms_Latn_FI",
+ "sn": "sn_Latn_ZW",
+ "snk": "snk_Latn_ML",
+ "so": "so_Latn_SO",
+ "sq": "sq_Latn_AL",
+ "sr": "sr_Cyrl_RS",
+ "sr_ME": "sr_Latn_ME",
+ "sr_RO": "sr_Latn_RO",
+ "sr_RU": "sr_Latn_RU",
+ "sr_TR": "sr_Latn_TR",
+ "srn": "srn_Latn_SR",
+ "srr": "srr_Latn_SN",
+ "ss": "ss_Latn_ZA",
+ "ssy": "ssy_Latn_ER",
+ "st": "st_Latn_ZA",
+ "su": "su_Latn_ID",
+ "suk": "suk_Latn_TZ",
+ "sus": "sus_Latn_GN",
+ "sv": "sv_Latn_SE",
+ "sw": "sw_Latn_TZ",
+ "swb": "swb_Arab_YT",
+ "swc": "swc_Latn_CD",
+ "syl": "syl_Beng_BD",
+ "syr": "syr_Syrc_IQ",
+ "ta": "ta_Taml_IN",
+ "tbw": "tbw_Latn_PH",
+ "tcy": "tcy_Knda_IN",
+ "tdd": "tdd_Tale_CN",
+ "te": "te_Telu_IN",
+ "tem": "tem_Latn_SL",
+ "teo": "teo_Latn_UG",
+ "tet": "tet_Latn_TL",
+ "tg": "tg_Cyrl_TJ",
+ "tg_Arab": "tg_Arab_PK",
+ "tg_PK": "tg_Arab_PK",
+ "th": "th_Thai_TH",
+ "ti": "ti_Ethi_ET",
+ "tig": "tig_Ethi_ER",
+ "tiv": "tiv_Latn_NG",
+ "tk": "tk_Latn_TM",
+ "tkl": "tkl_Latn_TK",
+ "tl": "tl_Latn_PH",
+ "tmh": "tmh_Latn_NE",
+ "tn": "tn_Latn_ZA",
+ "to": "to_Latn_TO",
+ "tpi": "tpi_Latn_PG",
+ "tr": "tr_Latn_TR",
+ "trv": "trv_Latn_TW",
+ "ts": "ts_Latn_ZA",
+ "tsg": "tsg_Latn_PH",
+ "tt": "tt_Cyrl_RU",
+ "tts": "tts_Thai_TH",
+ "tum": "tum_Latn_MW",
+ "tvl": "tvl_Latn_TV",
+ "twq": "twq_Latn_NE",
+ "ty": "ty_Latn_PF",
+ "tyv": "tyv_Cyrl_RU",
+ "tzm": "tzm_Latn_MA",
+ "udm": "udm_Cyrl_RU",
+ "ug": "ug_Arab_CN",
+ "ug_Cyrl": "ug_Cyrl_KZ",
+ "ug_KZ": "ug_Cyrl_KZ",
+ "ug_MN": "ug_Cyrl_MN",
+ "uk": "uk_Cyrl_UA",
+ "uli": "uli_Latn_FM",
+ "umb": "umb_Latn_AO",
+ "und": "en_Latn_US",
+ "und_AD": "ca_Latn_AD",
+ "und_AE": "ar_Arab_AE",
+ "und_AF": "fa_Arab_AF",
+ "und_AL": "sq_Latn_AL",
+ "und_AM": "hy_Armn_AM",
+ "und_AO": "pt_Latn_AO",
+ "und_AQ": "und_Latn_AQ",
+ "und_AR": "es_Latn_AR",
+ "und_Arab": "ar_Arab_EG",
+ "und_Arab_CC": "ms_Arab_CC",
+ "und_Arab_CN": "ug_Arab_CN",
+ "und_Arab_GB": "ks_Arab_GB",
+ "und_Arab_ID": "ms_Arab_ID",
+ "und_Arab_IN": "ur_Arab_IN",
+ "und_Arab_KH": "cja_Arab_KH",
+ "und_Arab_MN": "kk_Arab_MN",
+ "und_Arab_MU": "ur_Arab_MU",
+ "und_Arab_NG": "ha_Arab_NG",
+ "und_Arab_PK": "ur_Arab_PK",
+ "und_Arab_TJ": "fa_Arab_TJ",
+ "und_Arab_TR": "zza_Arab_TR",
+ "und_Arab_YT": "swb_Arab_YT",
+ "und_Armi": "arc_Armi_IR",
+ "und_Armn": "hy_Armn_AM",
+ "und_AS": "sm_Latn_AS",
+ "und_AT": "de_Latn_AT",
+ "und_Avst": "ae_Avst_IR",
+ "und_AW": "nl_Latn_AW",
+ "und_AX": "sv_Latn_AX",
+ "und_AZ": "az_Latn_AZ",
+ "und_BA": "bs_Latn_BA",
+ "und_Bali": "ban_Bali_ID",
+ "und_Bamu": "bax_Bamu_CM",
+ "und_Batk": "bbc_Batk_ID",
+ "und_BD": "bn_Beng_BD",
+ "und_BE": "nl_Latn_BE",
+ "und_Beng": "bn_Beng_BD",
+ "und_BF": "fr_Latn_BF",
+ "und_BG": "bg_Cyrl_BG",
+ "und_BH": "ar_Arab_BH",
+ "und_BI": "rn_Latn_BI",
+ "und_BJ": "fr_Latn_BJ",
+ "und_BL": "fr_Latn_BL",
+ "und_BN": "ms_Latn_BN",
+ "und_BO": "es_Latn_BO",
+ "und_Bopo": "zh_Bopo_TW",
+ "und_BQ": "pap_Latn_BQ",
+ "und_BR": "pt_Latn_BR",
+ "und_Brah": "pra_Brah_IN",
+ "und_Brai": "und_Brai_FR",
+ "und_BT": "dz_Tibt_BT",
+ "und_Bugi": "bug_Bugi_ID",
+ "und_Buhd": "bku_Buhd_PH",
+ "und_BV": "und_Latn_BV",
+ "und_BY": "be_Cyrl_BY",
+ "und_Cakm": "ccp_Cakm_BD",
+ "und_Cans": "cr_Cans_CA",
+ "und_Cari": "xcr_Cari_TR",
+ "und_CD": "sw_Latn_CD",
+ "und_CF": "fr_Latn_CF",
+ "und_CG": "fr_Latn_CG",
+ "und_CH": "de_Latn_CH",
+ "und_Cham": "cjm_Cham_VN",
+ "und_Cher": "chr_Cher_US",
+ "und_CI": "fr_Latn_CI",
+ "und_CL": "es_Latn_CL",
+ "und_CM": "fr_Latn_CM",
+ "und_CN": "zh_Hans_CN",
+ "und_CO": "es_Latn_CO",
+ "und_Copt": "cop_Copt_EG",
+ "und_CP": "und_Latn_CP",
+ "und_Cprt": "grc_Cprt_CY",
+ "und_CR": "es_Latn_CR",
+ "und_CU": "es_Latn_CU",
+ "und_CV": "pt_Latn_CV",
+ "und_CW": "pap_Latn_CW",
+ "und_CY": "el_Grek_CY",
+ "und_Cyrl": "ru_Cyrl_RU",
+ "und_Cyrl_AL": "mk_Cyrl_AL",
+ "und_Cyrl_BA": "sr_Cyrl_BA",
+ "und_Cyrl_GE": "ab_Cyrl_GE",
+ "und_Cyrl_GR": "mk_Cyrl_GR",
+ "und_Cyrl_MD": "uk_Cyrl_MD",
+ "und_Cyrl_PL": "be_Cyrl_PL",
+ "und_Cyrl_RO": "bg_Cyrl_RO",
+ "und_Cyrl_SK": "uk_Cyrl_SK",
+ "und_Cyrl_TR": "kbd_Cyrl_TR",
+ "und_Cyrl_XK": "sr_Cyrl_XK",
+ "und_CZ": "cs_Latn_CZ",
+ "und_DE": "de_Latn_DE",
+ "und_Deva": "hi_Deva_IN",
+ "und_Deva_BT": "ne_Deva_BT",
+ "und_Deva_MU": "bho_Deva_MU",
+ "und_Deva_PK": "btv_Deva_PK",
+ "und_DJ": "aa_Latn_DJ",
+ "und_DK": "da_Latn_DK",
+ "und_DO": "es_Latn_DO",
+ "und_DZ": "ar_Arab_DZ",
+ "und_EA": "es_Latn_EA",
+ "und_EC": "es_Latn_EC",
+ "und_EE": "et_Latn_EE",
+ "und_EG": "ar_Arab_EG",
+ "und_Egyp": "egy_Egyp_EG",
+ "und_EH": "ar_Arab_EH",
+ "und_ER": "ti_Ethi_ER",
+ "und_ES": "es_Latn_ES",
+ "und_ET": "am_Ethi_ET",
+ "und_Ethi": "am_Ethi_ET",
+ "und_FI": "fi_Latn_FI",
+ "und_FM": "chk_Latn_FM",
+ "und_FO": "fo_Latn_FO",
+ "und_FR": "fr_Latn_FR",
+ "und_GA": "fr_Latn_GA",
+ "und_GE": "ka_Geor_GE",
+ "und_Geor": "ka_Geor_GE",
+ "und_GF": "fr_Latn_GF",
+ "und_GH": "ak_Latn_GH",
+ "und_GL": "kl_Latn_GL",
+ "und_Glag": "cu_Glag_BG",
+ "und_GN": "fr_Latn_GN",
+ "und_Goth": "got_Goth_UA",
+ "und_GP": "fr_Latn_GP",
+ "und_GQ": "es_Latn_GQ",
+ "und_GR": "el_Grek_GR",
+ "und_Grek": "el_Grek_GR",
+ "und_GS": "und_Latn_GS",
+ "und_GT": "es_Latn_GT",
+ "und_Gujr": "gu_Gujr_IN",
+ "und_Guru": "pa_Guru_IN",
+ "und_GW": "pt_Latn_GW",
+ "und_Hang": "ko_Hang_KR",
+ "und_Hani": "zh_Hani_CN",
+ "und_Hano": "hnn_Hano_PH",
+ "und_Hans": "zh_Hans_CN",
+ "und_Hant": "zh_Hant_TW",
+ "und_Hebr": "he_Hebr_IL",
+ "und_Hebr_CA": "yi_Hebr_CA",
+ "und_Hebr_GB": "yi_Hebr_GB",
+ "und_Hebr_SE": "yi_Hebr_SE",
+ "und_Hebr_UA": "yi_Hebr_UA",
+ "und_Hebr_US": "yi_Hebr_US",
+ "und_Hira": "ja_Hira_JP",
+ "und_HK": "zh_Hant_HK",
+ "und_HM": "und_Latn_HM",
+ "und_HN": "es_Latn_HN",
+ "und_HR": "hr_Latn_HR",
+ "und_HT": "ht_Latn_HT",
+ "und_HU": "hu_Latn_HU",
+ "und_IC": "es_Latn_IC",
+ "und_ID": "id_Latn_ID",
+ "und_IL": "he_Hebr_IL",
+ "und_IN": "hi_Deva_IN",
+ "und_IQ": "ar_Arab_IQ",
+ "und_IR": "fa_Arab_IR",
+ "und_IS": "is_Latn_IS",
+ "und_IT": "it_Latn_IT",
+ "und_Ital": "ett_Ital_IT",
+ "und_Java": "jv_Java_ID",
+ "und_JO": "ar_Arab_JO",
+ "und_JP": "ja_Jpan_JP",
+ "und_Jpan": "ja_Jpan_JP",
+ "und_Kali": "eky_Kali_MM",
+ "und_Kana": "ja_Kana_JP",
+ "und_KG": "ky_Cyrl_KG",
+ "und_KH": "km_Khmr_KH",
+ "und_Khar": "pra_Khar_PK",
+ "und_Khmr": "km_Khmr_KH",
+ "und_KM": "ar_Arab_KM",
+ "und_Knda": "kn_Knda_IN",
+ "und_Kore": "ko_Kore_KR",
+ "und_KP": "ko_Kore_KP",
+ "und_KR": "ko_Kore_KR",
+ "und_Kthi": "bh_Kthi_IN",
+ "und_KW": "ar_Arab_KW",
+ "und_KZ": "ru_Cyrl_KZ",
+ "und_LA": "lo_Laoo_LA",
+ "und_Lana": "nod_Lana_TH",
+ "und_Laoo": "lo_Laoo_LA",
+ "und_Latn_AF": "tk_Latn_AF",
+ "und_Latn_AM": "az_Latn_AM",
+ "und_Latn_BG": "tr_Latn_BG",
+ "und_Latn_CN": "za_Latn_CN",
+ "und_Latn_CY": "tr_Latn_CY",
+ "und_Latn_DZ": "fr_Latn_DZ",
+ "und_Latn_ET": "en_Latn_ET",
+ "und_Latn_GE": "ku_Latn_GE",
+ "und_Latn_GR": "tr_Latn_GR",
+ "und_Latn_IL": "ro_Latn_IL",
+ "und_Latn_IR": "tk_Latn_IR",
+ "und_Latn_KM": "fr_Latn_KM",
+ "und_Latn_KZ": "de_Latn_KZ",
+ "und_Latn_LB": "fr_Latn_LB",
+ "und_Latn_MA": "fr_Latn_MA",
+ "und_Latn_MK": "sq_Latn_MK",
+ "und_Latn_MO": "pt_Latn_MO",
+ "und_Latn_MR": "fr_Latn_MR",
+ "und_Latn_RU": "krl_Latn_RU",
+ "und_Latn_SY": "fr_Latn_SY",
+ "und_Latn_TN": "fr_Latn_TN",
+ "und_Latn_TW": "trv_Latn_TW",
+ "und_Latn_UA": "pl_Latn_UA",
+ "und_LB": "ar_Arab_LB",
+ "und_Lepc": "lep_Lepc_IN",
+ "und_LI": "de_Latn_LI",
+ "und_Limb": "lif_Limb_IN",
+ "und_Linb": "grc_Linb_GR",
+ "und_Lisu": "lis_Lisu_CN",
+ "und_LK": "si_Sinh_LK",
+ "und_LS": "st_Latn_LS",
+ "und_LT": "lt_Latn_LT",
+ "und_LU": "fr_Latn_LU",
+ "und_LV": "lv_Latn_LV",
+ "und_LY": "ar_Arab_LY",
+ "und_Lyci": "xlc_Lyci_TR",
+ "und_Lydi": "xld_Lydi_TR",
+ "und_MA": "ar_Arab_MA",
+ "und_Mand": "myz_Mand_IR",
+ "und_MC": "fr_Latn_MC",
+ "und_MD": "ro_Latn_MD",
+ "und_ME": "sr_Latn_ME",
+ "und_Merc": "xmr_Merc_SD",
+ "und_Mero": "xmr_Mero_SD",
+ "und_MF": "fr_Latn_MF",
+ "und_MG": "mg_Latn_MG",
+ "und_MK": "mk_Cyrl_MK",
+ "und_ML": "bm_Latn_ML",
+ "und_Mlym": "ml_Mlym_IN",
+ "und_MM": "my_Mymr_MM",
+ "und_MN": "mn_Cyrl_MN",
+ "und_MO": "zh_Hant_MO",
+ "und_Mong": "mn_Mong_CN",
+ "und_MQ": "fr_Latn_MQ",
+ "und_MR": "ar_Arab_MR",
+ "und_MT": "mt_Latn_MT",
+ "und_Mtei": "mni_Mtei_IN",
+ "und_MU": "mfe_Latn_MU",
+ "und_MV": "dv_Thaa_MV",
+ "und_MX": "es_Latn_MX",
+ "und_MY": "ms_Latn_MY",
+ "und_Mymr": "my_Mymr_MM",
+ "und_Mymr_IN": "kht_Mymr_IN",
+ "und_Mymr_TH": "mnw_Mymr_TH",
+ "und_MZ": "pt_Latn_MZ",
+ "und_NA": "af_Latn_NA",
+ "und_NC": "fr_Latn_NC",
+ "und_NE": "ha_Latn_NE",
+ "und_NI": "es_Latn_NI",
+ "und_Nkoo": "man_Nkoo_GN",
+ "und_NL": "nl_Latn_NL",
+ "und_NO": "nb_Latn_NO",
+ "und_NP": "ne_Deva_NP",
+ "und_Ogam": "sga_Ogam_IE",
+ "und_Olck": "sat_Olck_IN",
+ "und_OM": "ar_Arab_OM",
+ "und_Orkh": "otk_Orkh_MN",
+ "und_Orya": "or_Orya_IN",
+ "und_Osma": "so_Osma_SO",
+ "und_PA": "es_Latn_PA",
+ "und_PE": "es_Latn_PE",
+ "und_PF": "fr_Latn_PF",
+ "und_PG": "tpi_Latn_PG",
+ "und_PH": "fil_Latn_PH",
+ "und_Phag": "lzh_Phag_CN",
+ "und_Phli": "pal_Phli_IR",
+ "und_Phnx": "phn_Phnx_LB",
+ "und_PK": "ur_Arab_PK",
+ "und_PL": "pl_Latn_PL",
+ "und_Plrd": "hmd_Plrd_CN",
+ "und_PM": "fr_Latn_PM",
+ "und_PR": "es_Latn_PR",
+ "und_Prti": "xpr_Prti_IR",
+ "und_PS": "ar_Arab_PS",
+ "und_PT": "pt_Latn_PT",
+ "und_PW": "pau_Latn_PW",
+ "und_PY": "gn_Latn_PY",
+ "und_QA": "ar_Arab_QA",
+ "und_RE": "fr_Latn_RE",
+ "und_Rjng": "rej_Rjng_ID",
+ "und_RO": "ro_Latn_RO",
+ "und_RS": "sr_Cyrl_RS",
+ "und_RU": "ru_Cyrl_RU",
+ "und_Runr": "non_Runr_SE",
+ "und_RW": "rw_Latn_RW",
+ "und_SA": "ar_Arab_SA",
+ "und_Samr": "smp_Samr_IL",
+ "und_Sarb": "xsa_Sarb_YE",
+ "und_Saur": "saz_Saur_IN",
+ "und_SC": "fr_Latn_SC",
+ "und_SD": "ar_Arab_SD",
+ "und_SE": "sv_Latn_SE",
+ "und_Shaw": "en_Shaw_GB",
+ "und_Shrd": "sa_Shrd_IN",
+ "und_SI": "sl_Latn_SI",
+ "und_Sinh": "si_Sinh_LK",
+ "und_SJ": "nb_Latn_SJ",
+ "und_SK": "sk_Latn_SK",
+ "und_SM": "it_Latn_SM",
+ "und_SN": "fr_Latn_SN",
+ "und_SO": "so_Latn_SO",
+ "und_Sora": "srb_Sora_IN",
+ "und_SR": "nl_Latn_SR",
+ "und_ST": "pt_Latn_ST",
+ "und_Sund": "su_Sund_ID",
+ "und_SV": "es_Latn_SV",
+ "und_SY": "ar_Arab_SY",
+ "und_Sylo": "syl_Sylo_BD",
+ "und_Syrc": "syr_Syrc_IQ",
+ "und_Tagb": "tbw_Tagb_PH",
+ "und_Takr": "doi_Takr_IN",
+ "und_Tale": "tdd_Tale_CN",
+ "und_Talu": "khb_Talu_CN",
+ "und_Taml": "ta_Taml_IN",
+ "und_Tavt": "blt_Tavt_VN",
+ "und_TD": "fr_Latn_TD",
+ "und_Telu": "te_Telu_IN",
+ "und_TF": "fr_Latn_TF",
+ "und_Tfng": "zgh_Tfng_MA",
+ "und_TG": "fr_Latn_TG",
+ "und_Tglg": "fil_Tglg_PH",
+ "und_TH": "th_Thai_TH",
+ "und_Thaa": "dv_Thaa_MV",
+ "und_Thai": "th_Thai_TH",
+ "und_Thai_CN": "lcp_Thai_CN",
+ "und_Thai_KH": "kdt_Thai_KH",
+ "und_Thai_LA": "kdt_Thai_LA",
+ "und_Tibt": "bo_Tibt_CN",
+ "und_TJ": "tg_Cyrl_TJ",
+ "und_TK": "tkl_Latn_TK",
+ "und_TL": "pt_Latn_TL",
+ "und_TM": "tk_Latn_TM",
+ "und_TN": "ar_Arab_TN",
+ "und_TO": "to_Latn_TO",
+ "und_TR": "tr_Latn_TR",
+ "und_TV": "tvl_Latn_TV",
+ "und_TW": "zh_Hant_TW",
+ "und_TZ": "sw_Latn_TZ",
+ "und_UA": "uk_Cyrl_UA",
+ "und_UG": "sw_Latn_UG",
+ "und_Ugar": "uga_Ugar_SY",
+ "und_UY": "es_Latn_UY",
+ "und_UZ": "uz_Latn_UZ",
+ "und_VA": "la_Latn_VA",
+ "und_Vaii": "vai_Vaii_LR",
+ "und_VE": "es_Latn_VE",
+ "und_VN": "vi_Latn_VN",
+ "und_VU": "bi_Latn_VU",
+ "und_WF": "fr_Latn_WF",
+ "und_WS": "sm_Latn_WS",
+ "und_XK": "sq_Latn_XK",
+ "und_Xpeo": "peo_Xpeo_IR",
+ "und_Xsux": "akk_Xsux_IQ",
+ "und_YE": "ar_Arab_YE",
+ "und_Yiii": "ii_Yiii_CN",
+ "und_YT": "fr_Latn_YT",
+ "unr": "unr_Beng_IN",
+ "unr_Deva": "unr_Deva_NP",
+ "unr_NP": "unr_Deva_NP",
+ "unx": "unx_Beng_IN",
+ "ur": "ur_Arab_PK",
+ "uz": "uz_Latn_UZ",
+ "uz_AF": "uz_Arab_AF",
+ "uz_Arab": "uz_Arab_AF",
+ "uz_CN": "uz_Cyrl_CN",
+ "vai": "vai_Vaii_LR",
+ "ve": "ve_Latn_ZA",
+ "vi": "vi_Latn_VN",
+ "vo": "vo_Latn_001",
+ "vun": "vun_Latn_TZ",
+ "wa": "wa_Latn_BE",
+ "wae": "wae_Latn_CH",
+ "wal": "wal_Ethi_ET",
+ "war": "war_Latn_PH",
+ "wo": "wo_Latn_SN",
+ "xh": "xh_Latn_ZA",
+ "xog": "xog_Latn_UG",
+ "xsr": "xsr_Deva_NP",
+ "yao": "yao_Latn_MZ",
+ "yap": "yap_Latn_FM",
+ "yav": "yav_Latn_CM",
+ "yi": "yi_Hebr_UA",
+ "yo": "yo_Latn_NG",
+ "za": "za_Latn_CN",
+ "zgh": "zgh_Tfng_MA",
+ "zh": "zh_Hans_CN",
+ "zh_AU": "zh_Hant_AU",
+ "zh_BN": "zh_Hant_BN",
+ "zh_GB": "zh_Hant_GB",
+ "zh_GF": "zh_Hant_GF",
+ "zh_Hant": "zh_Hant_TW",
+ "zh_HK": "zh_Hant_HK",
+ "zh_ID": "zh_Hant_ID",
+ "zh_MO": "zh_Hant_MO",
+ "zh_MY": "zh_Hant_MY",
+ "zh_PA": "zh_Hant_PA",
+ "zh_PF": "zh_Hant_PF",
+ "zh_PH": "zh_Hant_PH",
+ "zh_SR": "zh_Hant_SR",
+ "zh_TH": "zh_Hant_TH",
+ "zh_TW": "zh_Hant_TW",
+ "zh_US": "zh_Hant_US",
+ "zh_VN": "zh_Hant_VN",
+ "zu": "zu_Latn_ZA",
+ "zza": "zza_Arab_TR"
+ }
+ }
+});
+
+// weekData
+Globalize.load({
+ "supplemental": {
+ "version": {
+ "_cldrVersion": "24",
+ "_number": "$Revision: 9270 $"
+ },
+ "generation": {
+ "_date": "$Date: 2013-08-25 16:44:03 -0500 (Sun, 25 Aug 2013) $"
+ },
+ "weekData": {
+ "minDays": {
+ "001": "1",
+ "AD": "4",
+ "AN": "4",
+ "AT": "4",
+ "AX": "4",
+ "BE": "4",
+ "BG": "4",
+ "CH": "4",
+ "CZ": "4",
+ "DE": "4",
+ "DK": "4",
+ "EE": "4",
+ "ES": "4",
+ "FI": "4",
+ "FJ": "4",
+ "FO": "4",
+ "FR": "4",
+ "GB": "4",
+ "GF": "4",
+ "GG": "4",
+ "GI": "4",
+ "GP": "4",
+ "GR": "4",
+ "GU": "1",
+ "HU": "4",
+ "IE": "4",
+ "IM": "4",
+ "IS": "4",
+ "IT": "4",
+ "JE": "4",
+ "LI": "4",
+ "LT": "4",
+ "LU": "4",
+ "MC": "4",
+ "MQ": "4",
+ "NL": "4",
+ "NO": "4",
+ "PL": "4",
+ "PT": "4",
+ "RE": "4",
+ "SE": "4",
+ "SJ": "4",
+ "SK": "4",
+ "SM": "4",
+ "UM": "1",
+ "US": "1",
+ "VA": "4",
+ "VI": "1"
+ },
+ "firstDay": {
+ "001": "mon",
+ "AD": "mon",
+ "AE": "sat",
+ "AF": "sat",
+ "AG": "sun",
+ "AI": "mon",
+ "AL": "mon",
+ "AM": "mon",
+ "AN": "mon",
+ "AR": "sun",
+ "AS": "sun",
+ "AT": "mon",
+ "AU": "sun",
+ "AX": "mon",
+ "AZ": "mon",
+ "BA": "mon",
+ "BD": "fri",
+ "BE": "mon",
+ "BG": "mon",
+ "BH": "sat",
+ "BM": "mon",
+ "BN": "mon",
+ "BR": "sun",
+ "BS": "sun",
+ "BT": "sun",
+ "BW": "sun",
+ "BY": "sun",
+ "BZ": "sun",
+ "CA": "sun",
+ "CH": "mon",
+ "CL": "mon",
+ "CM": "mon",
+ "CN": "sun",
+ "CO": "sun",
+ "CR": "mon",
+ "CY": "mon",
+ "CZ": "mon",
+ "DE": "mon",
+ "DJ": "sat",
+ "DK": "mon",
+ "DM": "sun",
+ "DO": "sun",
+ "DZ": "sat",
+ "EC": "mon",
+ "EE": "mon",
+ "EG": "sat",
+ "ES": "mon",
+ "ET": "sun",
+ "FI": "mon",
+ "FJ": "mon",
+ "FO": "mon",
+ "FR": "mon",
+ "GB": "mon",
+ "GE": "mon",
+ "GF": "mon",
+ "GP": "mon",
+ "GR": "mon",
+ "GT": "sun",
+ "GU": "sun",
+ "HK": "sun",
+ "HN": "sun",
+ "HR": "mon",
+ "HU": "mon",
+ "ID": "sun",
+ "IE": "sun",
+ "IL": "sun",
+ "IN": "sun",
+ "IQ": "sat",
+ "IR": "sat",
+ "IS": "mon",
+ "IT": "mon",
+ "JM": "sun",
+ "JO": "sat",
+ "JP": "sun",
+ "KE": "sun",
+ "KG": "mon",
+ "KH": "sun",
+ "KR": "sun",
+ "KW": "sat",
+ "KZ": "mon",
+ "LA": "sun",
+ "LB": "mon",
+ "LI": "mon",
+ "LK": "mon",
+ "LT": "mon",
+ "LU": "mon",
+ "LV": "mon",
+ "LY": "sat",
+ "MA": "sat",
+ "MC": "mon",
+ "MD": "mon",
+ "ME": "mon",
+ "MH": "sun",
+ "MK": "mon",
+ "MM": "sun",
+ "MN": "mon",
+ "MO": "sun",
+ "MQ": "mon",
+ "MT": "sun",
+ "MV": "fri",
+ "MX": "sun",
+ "MY": "mon",
+ "MZ": "sun",
+ "NI": "sun",
+ "NL": "mon",
+ "NO": "mon",
+ "NP": "sun",
+ "NZ": "sun",
+ "OM": "sat",
+ "PA": "sun",
+ "PE": "sun",
+ "PH": "sun",
+ "PK": "sun",
+ "PL": "mon",
+ "PR": "sun",
+ "PT": "mon",
+ "PY": "sun",
+ "QA": "sat",
+ "RE": "mon",
+ "RO": "mon",
+ "RS": "mon",
+ "RU": "mon",
+ "SA": "sun",
+ "SD": "sat",
+ "SE": "mon",
+ "SG": "sun",
+ "SI": "mon",
+ "SK": "mon",
+ "SM": "mon",
+ "SV": "sun",
+ "SY": "sat",
+ "TH": "sun",
+ "TJ": "mon",
+ "TM": "mon",
+ "TN": "sun",
+ "TR": "mon",
+ "TT": "sun",
+ "TW": "sun",
+ "UA": "mon",
+ "UM": "sun",
+ "US": "sun",
+ "UY": "mon",
+ "UZ": "mon",
+ "VA": "mon",
+ "VE": "sun",
+ "VI": "sun",
+ "VN": "mon",
+ "WS": "sun",
+ "XK": "mon",
+ "YE": "sun",
+ "ZA": "sun",
+ "ZW": "sun"
+ },
+ "firstDay-alt-variant": {
+ "GB": "sun"
+ },
+ "weekendStart": {
+ "001": "sat",
+ "AE": "fri",
+ "AF": "thu",
+ "BH": "fri",
+ "DZ": "thu",
+ "EG": "fri",
+ "IL": "fri",
+ "IN": "sun",
+ "IQ": "fri",
+ "IR": "thu",
+ "JO": "fri",
+ "KW": "fri",
+ "LY": "fri",
+ "MA": "fri",
+ "OM": "thu",
+ "QA": "fri",
+ "SA": "fri",
+ "SD": "fri",
+ "SY": "fri",
+ "TN": "fri",
+ "YE": "fri"
+ },
+ "weekendEnd": {
+ "001": "sun",
+ "AE": "sat",
+ "AF": "fri",
+ "BH": "sat",
+ "DZ": "fri",
+ "EG": "sat",
+ "IL": "sat",
+ "IQ": "sat",
+ "IR": "fri",
+ "JO": "sat",
+ "KW": "sat",
+ "LY": "sat",
+ "MA": "sat",
+ "OM": "fri",
+ "QA": "sat",
+ "SA": "sat",
+ "SD": "sat",
+ "SY": "sat",
+ "TN": "sat",
+ "YE": "sat"
+ }
+ }
+ }
+});
+
+// timeData
+Globalize.load({
+ "supplemental": {
+ "version": {
+ "_cldrVersion": "24",
+ "_number": "$Revision: 9270 $"
+ },
+ "generation": {
+ "_date": "$Date: 2013-08-25 16:44:03 -0500 (Sun, 25 Aug 2013) $"
+ },
+ "timeData": {
+ "001": {
+ "_allowed": "H h",
+ "_preferred": "H"
+ },
+ "AD": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "AE": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "AG": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "AL": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "AM": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "AO": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "AS": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "AT": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "AU": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "AW": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "AX": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "BB": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "BD": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "BE": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "BF": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "BH": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "BJ": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "BL": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "BM": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "BN": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "BR": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "BS": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "BT": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "BW": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "CA": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "CD": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "CI": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "CN": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "CO": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "CP": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "CV": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "CY": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "CZ": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "DE": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "DJ": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "DK": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "DM": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "DZ": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "EE": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "EG": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "EH": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "ER": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "ET": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "FI": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "FJ": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "FM": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "FR": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "GA": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "GD": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "GF": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "GH": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "GL": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "GM": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "GN": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "GP": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "GR": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "GU": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "GW": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "GY": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "HK": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "HR": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "IL": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "IN": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "IQ": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "IS": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "IT": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "JM": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "JO": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "JP": {
+ "_allowed": "H K h",
+ "_preferred": "H"
+ },
+ "KH": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "KI": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "KN": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "KP": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "KR": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "KW": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "KY": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "LB": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "LC": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "LR": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "LS": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "LY": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "MA": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "MC": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "MD": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "MF": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "MH": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "ML": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "MO": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "MP": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "MQ": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "MR": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "MW": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "MY": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "MZ": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "NA": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "NC": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "NE": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "NG": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "NL": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "NZ": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "OM": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "PG": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "PK": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "PM": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "PR": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "PS": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "PT": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "PW": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "QA": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "RE": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "RO": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "RU": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "SA": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "SB": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "SD": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "SE": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "SG": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "SI": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "SJ": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "SK": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "SL": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "SM": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "SO": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "SR": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "SS": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "ST": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "SY": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "SZ": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "TC": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "TD": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "TG": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "TN": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "TR": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "TT": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "TW": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "UM": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "US": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "VC": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "VG": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "VI": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "VU": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "WF": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "WS": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "YE": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "YT": {
+ "_allowed": "H",
+ "_preferred": "H"
+ },
+ "ZA": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "ZM": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ },
+ "ZW": {
+ "_allowed": "H h",
+ "_preferred": "h"
+ }
+ }
+ }
+});
+
+/**
+ * jQuery UI translation data
+ */
+var regions = {
+ "en": {
+ "closeText": "Done",
+ "prevText": "Prev",
+ "nextText": "Next",
+ "currentText": "Today",
+ "weekHeader": "Wk",
+ "dateFormat": "d",
+ "datePickerRole": "date picker"
+ },
+ "af": {
+ "closeText": "Selekteer",
+ "prevText": "Vorige",
+ "nextText": "Volgende",
+ "currentText": "Vandag",
+ "weekHeader": "Wk",
+ "dateFormat": "d"
+ },
+ "zh-TW": {
+ "closeText": "\u95dc\u9589",
+ "prevText": "<\u4e0a\u6708",
+ "nextText": "\u4e0b\u6708>",
+ "currentText": "\u4eca\u5929",
+ "weekHeader": "\u5468",
+ "dateFormat": "d"
+ },
+ "ar": {
+ "closeText": "\u0625\u063a\u0644\u0627\u0642",
+ "prevText": "<\u0627\u0644\u0633\u0627\u0628\u0642",
+ "nextText": "\u0627\u0644\u062a\u0627\u0644\u064a>",
+ "currentText": "\u0627\u0644\u064a\u0648\u0645",
+ "weekHeader": "\u0623\u0633\u0628\u0648\u0639",
+ "dateFormat": "d"
+ },
+ "az": {
+ "closeText": "Ba\u011fla",
+ "prevText": "<Geri",
+ "nextText": "\u0130r\u0259li>",
+ "currentText": "Bug\u00fcn",
+ "weekHeader": "Hf",
+ "dateFormat": "d"
+ },
+ "bg": {
+ "closeText": "\u0437\u0430\u0442\u0432\u043e\u0440\u0438",
+ "prevText": "<\u043d\u0430\u0437\u0430\u0434",
+ "nextText": "\u043d\u0430\u043f\u0440\u0435\u0434>",
+ "currentText": "\u0434\u043d\u0435\u0441",
+ "weekHeader": "Wk",
+ "dateFormat": "d"
+ },
+ "bs": {
+ "closeText": "Zatvori",
+ "prevText": "<",
+ "nextText": ">",
+ "currentText": "Danas",
+ "weekHeader": "Wk",
+ "dateFormat": "d"
+ },
+ "ca": {
+ "closeText": "Tancar",
+ "prevText": "<Ant",
+ "nextText": "Seg>",
+ "currentText": "Avui",
+ "weekHeader": "Sm",
+ "dateFormat": "d"
+ },
+ "cs": {
+ "closeText": "Zav\u0159\u00edt",
+ "prevText": "<D\u0159\u00edve",
+ "nextText": "Pozd\u011bji>",
+ "currentText": "Nyn\u00ed",
+ "weekHeader": "T\u00fdd",
+ "dateFormat": "d"
+ },
+ "da": {
+ "closeText": "Luk",
+ "prevText": "<Forrige",
+ "nextText": "N\u00e6ste>",
+ "currentText": "Idag",
+ "weekHeader": "Uge",
+ "dateFormat": "d"
+ },
+ "de": {
+ "closeText": "Schlie\u00dfen",
+ "prevText": "<Zur\u00fcck",
+ "nextText": "Vor>",
+ "currentText": "Heute",
+ "weekHeader": "Wo",
+ "dateFormat": "d"
+ },
+ "el": {
+ "closeText": "\u039a\u03bb\u03b5\u03af\u03c3\u03b9\u03bc\u03bf",
+ "prevText": "\u03a0\u03c1\u03bf\u03b7\u03b3\u03bf\u03cd\u03bc\u03b5\u03bd\u03bf\u03c2",
+ "nextText": "\u0395\u03c0\u03cc\u03bc\u03b5\u03bd\u03bf\u03c2",
+ "currentText": "\u03a4\u03c1\u03ad\u03c7\u03c9\u03bd \u039c\u03ae\u03bd\u03b1\u03c2",
+ "weekHeader": "\u0395\u03b2\u03b4",
+ "dateFormat": "d"
+ },
+ "en-GB": {
+ "closeText": "Done",
+ "prevText": "Prev",
+ "nextText": "Next",
+ "currentText": "Today",
+ "weekHeader": "Wk",
+ "dateFormat": "d"
+ },
+ "eo": {
+ "closeText": "Fermi",
+ "prevText": "<Anta",
+ "nextText": "Sekv>",
+ "currentText": "Nuna",
+ "weekHeader": "Sb",
+ "dateFormat": "dd/MM/yyyy"
+ },
+ "es": {
+ "closeText": "Cerrar",
+ "prevText": "<Ant",
+ "nextText": "Sig>",
+ "currentText": "Hoy",
+ "weekHeader": "Sm",
+ "dateFormat": "d"
+ },
+ "et": {
+ "closeText": "Sulge",
+ "prevText": "Eelnev",
+ "nextText": "J\u00e4rgnev",
+ "currentText": "T\u00e4na",
+ "weekHeader": "Sm",
+ "dateFormat": "d"
+ },
+ "eu": {
+ "closeText": "Egina",
+ "prevText": "<Aur",
+ "nextText": "Hur>",
+ "currentText": "Gaur",
+ "weekHeader": "Wk",
+ "dateFormat": "d"
+ },
+ "fa": {
+ "closeText": "\u0628\u0633\u062a\u0646",
+ "prevText": "<\u0642\u0628\u0644\u064a",
+ "nextText": "\u0628\u0639\u062f\u064a>",
+ "currentText": "\u0627\u0645\u0631\u0648\u0632",
+ "weekHeader": "\u0647\u0641",
+ "dateFormat": "d"
+ },
+ "fi": {
+ "closeText": "Sulje",
+ "prevText": "«Edellinen",
+ "nextText": "Seuraava»",
+ "currentText": "Tänään",
+ "weekHeader": "Vk",
+ "dateFormat": "d"
+ },
+ "fo": {
+ "closeText": "Lat aftur",
+ "prevText": "<Fyrra",
+ "nextText": "N\u00e6sta>",
+ "currentText": "\u00cd dag",
+ "weekHeader": "Vk",
+ "dateFormat": "d"
+ },
+ "fr-CH": {
+ "closeText": "Fermer",
+ "prevText": "<Pr\u00e9c",
+ "nextText": "Suiv>",
+ "currentText": "Courant",
+ "weekHeader": "Sm",
+ "dateFormat": "d"
+ },
+ "fr": {
+ "closeText": "Fermer",
+ "prevText": "<Pr\u00e9c",
+ "nextText": "Suiv>",
+ "currentText": "Courant",
+ "weekHeader": "Sm",
+ "dateFormat": "d"
+ },
+ "he": {
+ "closeText": "\u05e1\u05d2\u05d5\u05e8",
+ "prevText": "<\u05d4\u05e7\u05d5\u05d3\u05dd",
+ "nextText": "\u05d4\u05d1\u05d0>",
+ "currentText": "\u05d4\u05d9\u05d5\u05dd",
+ "weekHeader": "Wk",
+ "dateFormat": "d"
+ },
+ "hr": {
+ "closeText": "Zatvori",
+ "prevText": "<",
+ "nextText": ">",
+ "currentText": "Danas",
+ "weekHeader": "Tje",
+ "dateFormat": "d"
+ },
+ "hu": {
+ "closeText": "bez\u00c3\u00a1r\u00c3\u00a1s",
+ "prevText": "« vissza",
+ "nextText": "el\u00c5\u2018re »",
+ "currentText": "ma",
+ "weekHeader": "H\u00c3\u00a9",
+ "dateFormat": "d"
+ },
+ "hy": {
+ "closeText": "\u00d5\u201c\u00d5\u00a1\u00d5\u00af\u00d5\u00a5\u00d5\u00ac",
+ "prevText": "<\u00d5\u2020\u00d5\u00a1\u00d5\u00ad.",
+ "nextText": "\u00d5\u20ac\u00d5\u00a1\u00d5\u00bb.>",
+ "currentText": "\u00d4\u00b1\u00d5\u00b5\u00d5\u00bd\u00d6\u2026\u00d6\u20ac",
+ "weekHeader": "\u00d5\u2021\u00d4\u00b2\u00d5\u008f",
+ "dateFormat": "d"
+ },
+ "id": {
+ "closeText": "Tutup",
+ "prevText": "<mundur",
+ "nextText": "maju>",
+ "currentText": "hari ini",
+ "weekHeader": "Mg",
+ "dateFormat": "d"
+ },
+ "is": {
+ "closeText": "Loka",
+ "prevText": "< Fyrri",
+ "nextText": "Næsti >",
+ "currentText": "Í dag",
+ "weekHeader": "Vika",
+ "dateFormat": "d"
+ },
+ "it": {
+ "closeText": "Chiudi",
+ "prevText": "<Prec",
+ "nextText": "Succ>",
+ "currentText": "Oggi",
+ "weekHeader": "Sm",
+ "dateFormat": "d"
+ },
+ "ja": {
+ "closeText": "\u9589\u3058\u308b",
+ "prevText": "<\u524d",
+ "nextText": "\u6b21>",
+ "currentText": "\u4eca\u65e5",
+ "weekHeader": "\u9031",
+ "dateFormat": "d"
+ },
+ "ko": {
+ "closeText": "\u00eb\u2039\u00ab\u00ea\u00b8\u00b0",
+ "prevText": "\u00ec\u009d\u00b4\u00ec\u00a0\u201e\u00eb\u2039\u00ac",
+ "nextText": "\u00eb\u2039\u00a4\u00ec\u009d\u0152\u00eb\u2039\u00ac",
+ "currentText": "\u00ec\u02dc\u00a4\u00eb\u0160\u02dc",
+ "weekHeader": "Wk",
+ "dateFormat": "d"
+ },
+ "lt": {
+ "closeText": "U\u00c5\u00bedaryti",
+ "prevText": "<Atgal",
+ "nextText": "Pirmyn>",
+ "currentText": "\u00c5\u00a0iandien",
+ "weekHeader": "Wk",
+ "dateFormat": "d"
+ },
+ "lv": {
+ "closeText": "Aizv\u00c4\u201crt",
+ "prevText": "Iepr",
+ "nextText": "N\u00c4\u0081ka",
+ "currentText": "\u00c5\u00a0odien",
+ "weekHeader": "Nav",
+ "dateFormat": "d"
+ },
+ "ms": {
+ "closeText": "Tutup",
+ "prevText": "<Sebelum",
+ "nextText": "Selepas>",
+ "currentText": "hari ini",
+ "weekHeader": "Mg",
+ "dateFormat": "d"
+ },
+ "nl": {
+ "closeText": "Sluiten",
+ "prevText": "\u2190",
+ "nextText": "\u2192",
+ "currentText": "Vandaag",
+ "weekHeader": "Wk",
+ "dateFormat": "d"
+ },
+ "no": {
+ "closeText": "Lukk",
+ "prevText": "«Forrige",
+ "nextText": "Neste»",
+ "currentText": "I dag",
+ "weekHeader": "Uke",
+ "dateFormat": "d"
+ },
+ "pl": {
+ "closeText": "Zamknij",
+ "prevText": "<Poprzedni",
+ "nextText": "Nast\u00c4\u2122pny>",
+ "currentText": "Dzi\u00c5\u203a",
+ "weekHeader": "Tydz",
+ "dateFormat": "d"
+ },
+ "pt-BR": {
+ "closeText": "Fechar",
+ "prevText": "<Anterior",
+ "nextText": "Próximo>",
+ "currentText": "Hoje",
+ "weekHeader": "Sm",
+ "dateFormat": "d"
+ },
+ "ro": {
+ "closeText": "\u00cenchide",
+ "prevText": "« Luna precedent\u0103",
+ "nextText": "Luna urm\u0103toare »",
+ "currentText": "Azi",
+ "weekHeader": "S\u0103pt",
+ "dateFormat": "d"
+ },
+ "ru": {
+ "closeText": "\u00d0\u2014\u00d0\u00b0\u00d0\u00ba\u00d1\u20ac\u00d1\u2039\u00d1\u201a\u00d1\u0152",
+ "prevText": "<\u00d0\u0178\u00d1\u20ac\u00d0\u00b5\u00d0\u00b4",
+ "nextText": "\u00d0\u00a1\u00d0\u00bb\u00d0\u00b5\u00d0\u00b4>",
+ "currentText": "\u00d0\u00a1\u00d0\u00b5\u00d0\u00b3\u00d0\u00be\u00d0\u00b4\u00d0\u00bd\u00d1\u008f",
+ "weekHeader": "\u00d0\u009d\u00d0\u00b5",
+ "dateFormat": "d"
+ },
+ "sk": {
+ "closeText": "Zavrie\u00c5\u00a5",
+ "prevText": "<Predch\u00c3\u00a1dzaj\u00c3\u00baci",
+ "nextText": "Nasleduj\u00c3\u00baci>",
+ "currentText": "Dnes",
+ "weekHeader": "Ty",
+ "dateFormat": "d"
+ },
+ "sl": {
+ "closeText": "Zapri",
+ "prevText": "<Prejšnji",
+ "nextText": "Naslednji>",
+ "currentText": "Trenutni",
+ "weekHeader": "Teden",
+ "dateFormat": "d"
+ },
+ "sq": {
+ "closeText": "mbylle",
+ "prevText": "<mbrapa",
+ "nextText": "P\u00ebrpara>",
+ "currentText": "sot",
+ "weekHeader": "Ja",
+ "dateFormat": "d"
+ },
+ "sr-SR": {
+ "closeText": "Zatvori",
+ "prevText": "<",
+ "nextText": ">",
+ "currentText": "Danas",
+ "weekHeader": "Sed",
+ "dateFormat": "dd/MM/yyyy"
+ },
+ "sr": {
+ "closeText": "\u0417\u0430\u0442\u0432\u043e\u0440\u0438",
+ "prevText": "<",
+ "nextText": ">",
+ "currentText": "\u0414\u0430\u043d\u0430\u0441",
+ "weekHeader": "\u0421\u0435\u0434",
+ "dateFormat": "d"
+ },
+ "sv": {
+ "closeText": "St\u00e4ng",
+ "prevText": "«F\u00f6rra",
+ "nextText": "N\u00e4sta»",
+ "currentText": "Idag",
+ "weekHeader": "Ve",
+ "dateFormat": "d"
+ },
+ "ta": {
+ "closeText": "\u0bae\u0bc2\u0b9f\u0bc1",
+ "prevText": "\u0bae\u0bc1\u0ba9\u0bcd\u0ba9\u0bc8\u0baf\u0ba4\u0bc1",
+ "nextText": "\u0b85\u0b9f\u0bc1\u0ba4\u0bcd\u0ba4\u0ba4\u0bc1",
+ "currentText": "\u0b87\u0ba9\u0bcd\u0bb1\u0bc1",
+ "weekHeader": "\u041d\u0435",
+ "dateFormat": "d"
+ },
+ "th": {
+ "closeText": "\u0e1b\u0e34\u0e14",
+ "prevText": "« \u0e22\u0e49\u0e2d\u0e19",
+ "nextText": "\u0e16\u0e31\u0e14\u0e44\u0e1b »",
+ "currentText": "\u0e27\u0e31\u0e19\u0e19\u0e35\u0e49",
+ "weekHeader": "Wk",
+ "dateFormat": "d"
+ },
+ "tr": {
+ "closeText": "kapat",
+ "prevText": "<geri",
+ "nextText": "ileri>",
+ "currentText": "bug\u00c3\u00bcn",
+ "weekHeader": "Hf",
+ "dateFormat": "d"
+ },
+ "uk": {
+ "closeText": "\u00d0\u2014\u00d0\u00b0\u00d0\u00ba\u00d1\u20ac\u00d0\u00b8\u00d1\u201a\u00d0\u00b8",
+ "prevText": "<",
+ "nextText": ">",
+ "currentText": "\u00d0\u00a1\u00d1\u0152\u00d0\u00be\u00d0\u00b3\u00d0\u00be\u00d0\u00b4\u00d0\u00bd\u00d1\u2013",
+ "weekHeader": "\u00d0\u009d\u00d0\u00b5",
+ "dateFormat": "d"
+ },
+ "vi": {
+ "closeText": "\u0110\u00f3ng",
+ "prevText": "<Tr\u01b0\u1edbc",
+ "nextText": "Ti\u1ebfp>",
+ "currentText": "H\u00f4m nay",
+ "weekHeader": "Tu",
+ "dateFormat": "d"
+ },
+ "zh-CN": {
+ "closeText": "\u00e5\u2026\u00b3\u00e9\u2014\u00ad",
+ "prevText": "<\u00e4\u00b8\u0160\u00e6\u0153\u02c6",
+ "nextText": "\u00e4\u00b8\u2039\u00e6\u0153\u02c6>",
+ "currentText": "\u00e4\u00bb\u0160\u00e5\u00a4\u00a9",
+ "weekHeader": "\u00e5\u2018\u00a8",
+ "dateFormat": "d"
+ },
+ "zh-HK": {
+ "closeText": "\u00e9\u2014\u0153\u00e9\u2013\u2030",
+ "prevText": "<\u00e4\u00b8\u0160\u00e6\u0153\u02c6",
+ "nextText": "\u00e4\u00b8\u2039\u00e6\u0153\u02c6>",
+ "currentText": "\u00e4\u00bb\u0160\u00e5\u00a4\u00a9",
+ "weekHeader": "\u00e5\u2018\u00a8",
+ "dateFormat": "d"
+ }
+};
+
+$.each( regions, function( name, value ) {
+ Globalize.loadTranslations( name, {
+ datepicker : value
+ });
+});
diff --git a/package.json b/package.json
index bb4313c74fe..e48af81fbbd 100644
--- a/package.json
+++ b/package.json
@@ -61,7 +61,7 @@
},
"dependencies": {},
"devDependencies": {
- "commitplease": "1.6.0",
+ "commitplease": "1.10.1",
"grunt": "0.4.2",
"grunt-bowercopy": "1.1.0",
"grunt-compare-size": "0.4.0",
diff --git a/tests/unit/all.html b/tests/unit/all.html
index f8a4636d051..85e21077412 100644
--- a/tests/unit/all.html
+++ b/tests/unit/all.html
@@ -21,6 +21,7 @@
"button/button.html",
"core/core.html",
"core/core_deprecated.html",
+ "calendar/calendar.html",
"datepicker/datepicker.html",
"dialog/dialog.html",
"draggable/draggable.html",
diff --git a/tests/unit/calendar/all.html b/tests/unit/calendar/all.html
new file mode 100644
index 00000000000..ea5662fe8d8
--- /dev/null
+++ b/tests/unit/calendar/all.html
@@ -0,0 +1,26 @@
+
+
+
+
+ jQuery UI Calendar Test Suite
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/unit/calendar/calendar.html b/tests/unit/calendar/calendar.html
new file mode 100644
index 00000000000..ed536414fbc
--- /dev/null
+++ b/tests/unit/calendar/calendar.html
@@ -0,0 +1,46 @@
+
+
+
+
+ jQuery UI Calendar Test Suite
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/unit/calendar/calendar_common.js b/tests/unit/calendar/calendar_common.js
new file mode 100644
index 00000000000..a669fdfc2c1
--- /dev/null
+++ b/tests/unit/calendar/calendar_common.js
@@ -0,0 +1,17 @@
+TestHelpers.commonWidgetTests( "calendar", {
+ defaults: {
+ buttons: [],
+ dateFormat: { date: "short" },
+ disabled: false,
+ eachDay: $.noop,
+ max: null,
+ min: null,
+ numberOfMonths: 1,
+ showWeek: false,
+ value: null,
+
+ // callbacks
+ create: null,
+ select: null
+ }
+});
diff --git a/tests/unit/calendar/calendar_core.js b/tests/unit/calendar/calendar_core.js
new file mode 100644
index 00000000000..49278345753
--- /dev/null
+++ b/tests/unit/calendar/calendar_core.js
@@ -0,0 +1,391 @@
+(function( $ ) {
+
+module( "calendar: core" );
+
+TestHelpers.testJshint( "calendar" );
+
+test( "baseStructure", function() {
+ expect( 26 );
+
+ var header, title, table, thead, week, child, buttonpane,
+ element = $( "#calendar" ).calendar(),
+ dp = element.calendar( "widget" );
+
+ function step1() {
+ ok( !dp.is( ".ui-calendar-rtl" ), "Structure - not right-to-left" );
+ ok( !dp.is( ".ui-calendar-multi" ), "Structure - not multi-month" );
+ equal( dp.children().length, 2, "Structure - child count (header, calendar)" );
+
+ header = dp.children( ":first" );
+ ok( header.is( "div.ui-calendar-header" ), "Structure - header division" );
+ equal( header.children().length, 3, "Structure - header child count" );
+ ok( header.children( ":first" ).is( ".ui-calendar-prev" ) && header.children( ":first" ).html() !== "", "Structure - prev link" );
+ ok( header.children( ":eq(1)" ).is( ".ui-calendar-next" ) && header.children( ":eq(1)" ).html() !== "", "Structure - next link" );
+
+ title = header.children( ":last" ).children( ":first" );
+ ok( title.is( "div.ui-calendar-title" ) && title.html() !== "", "Structure - title division" );
+ equal( title.children().length, 2, "Structure - title child count" );
+ ok( title.children( ":first" ).is( "span.ui-calendar-month" ) && title.children( ":first" ).text() !== "", "Structure - month text" );
+ ok( title.children( ":last" ).is( "span.ui-calendar-year" ) && title.children( ":last" ).text() !== "", "Structure - year text" );
+
+ table = dp.children( ":eq(1)" );
+ ok( table.is( "table.ui-calendar-calendar" ), "Structure - month table" );
+ ok( table.children( ":first" ).is( "thead" ), "Structure - month table thead" );
+
+ thead = table.children( ":first" ).children( ":first" );
+ ok( thead.is( "tr" ), "Structure - month table title row" );
+ equal( thead.find( "th" ).length, 7, "Structure - month table title cells" );
+ ok( table.children( ":eq(1)" ).is( "tbody" ), "Structure - month table body" );
+ ok( table.children( ":eq(1)" ).children( "tr" ).length >= 4, "Structure - month table week count" );
+
+ week = table.children( ":eq(1)" ).children( ":first" );
+ ok( week.is( "tr" ), "Structure - month table week row" );
+ equal( week.children().length, 7, "Structure - week child count" );
+
+ step2();
+ }
+
+ function step2() {
+ element.calendar( "option", "buttons", {
+ "test": function() {},
+ "test button": function() {}
+ });
+
+ equal( dp.children().length, 3, "Structure buttons - child count (header, calendar, buttonpane)" );
+
+ buttonpane = dp.children( ".ui-calendar-buttonpane" );
+ equal( buttonpane.children( "div.ui-calendar-buttonset" ).length, 1, "Structure buttons - buttonset" );
+ equal( buttonpane.find( "button.ui-button:first" ).text(), "test", "Structure buttons - buttonset" );
+ equal( buttonpane.find( "button.ui-button:eq(1)" ).text(), "test button", "Structure buttons - buttonset" );
+
+ element.calendar( "destroy" );
+ step3();
+ }
+
+ function step3() {
+ // Multi-month 2
+ element = $( "#calendar" ).calendar( { numberOfMonths: 2 } );
+ dp = element.calendar( "widget" );
+
+ ok( dp.is( ".ui-calendar-multi" ), "Structure multi [2] - multi-month" );
+ equal( dp.children().length, 3, "Structure multi [2] - child count" );
+
+ child = dp.children( ":eq(2)" );
+ ok( child.is( "div.ui-calendar-row-break" ), "Structure multi [2] - row break" );
+
+ element.calendar( "destroy" );
+ }
+
+ step1();
+});
+
+test( "Localization", function() {
+ expect( 10 );
+
+ var defaultLocale = Globalize.locale(),
+ element = $( "#calendar" ),
+ date = new Date( 2014, 0, 1 ),
+ initCalendar = function() {
+ element
+ .calendar()
+ .calendar( "valueAsDate", date );
+ },
+ testLocalization = function( message ) {
+ equal( element.find( ".ui-calendar-month" ).text(), "Januar", message + "titlebar year" );
+ equal( element.find( "thead th:first" ).text(), "Mo.", message + "teader first day" );
+ equal( element.find( "thead th:last" ).text(), "So.", message + "header last day" );
+ equal( element.find( ".ui-calendar-prev" ).text(), "", message + "header next" );
+ };
+
+ Globalize.locale( "de-DE" );
+ initCalendar();
+ testLocalization( "Init: " );
+ element.calendar( "destroy" );
+
+ Globalize.locale( defaultLocale.locale );
+ initCalendar();
+ Globalize.locale( "de-DE" );
+ element.calendar( "refresh" );
+ testLocalization( "After init: " );
+
+ Globalize.locale( defaultLocale.locale );
+});
+
+asyncTest( "keyboard handling", function() {
+ expect( 10 );
+
+ var element = $( "#calendar" );
+
+ function step1() {
+ element.calendar({ value: new Date( 2014, 1 - 1, 1 ) });
+
+ TestHelpers.calendar.focusGrid( element ).simulate( "keydown", { keyCode: $.ui.keyCode.LEFT } );
+ setTimeout(function() {
+ $( ":focus" ).simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } );
+ TestHelpers.calendar.equalsDate(
+ element.calendar( "valueAsDate" ),
+ new Date( 2013, 12 - 1, 31 ),
+ "Keystroke left to switch to previous day"
+ );
+ element.calendar( "destroy" );
+ step2();
+ }, 50 );
+ }
+
+ function step2() {
+ element.calendar({ value: new Date( 2014, 1 - 1, 1 ) });
+
+ TestHelpers.calendar.focusGrid( element )
+ .simulate( "keydown", { keyCode: $.ui.keyCode.RIGHT } )
+ .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } );
+
+ TestHelpers.calendar.equalsDate(
+ element.calendar( "valueAsDate" ),
+ new Date( 2014, 1 - 1, 2 ),
+ "Keystroke right to switch to next day"
+ );
+ step3();
+ }
+
+ function step3() {
+ element.calendar({ value: new Date( 2014, 1 - 1, 1 ) });
+
+ TestHelpers.calendar.focusGrid( element ).simulate( "keydown", { keyCode: $.ui.keyCode.UP } );
+ setTimeout(function() {
+ $( ":focus" ).simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } );
+ TestHelpers.calendar.equalsDate(
+ element.calendar( "valueAsDate" ),
+ new Date( 2013, 12 - 1, 25 ),
+ "Keystroke up to move to the previous week"
+ );
+ element.calendar( "destroy" );
+ step4();
+ }, 50 );
+ }
+
+ function step4() {
+ element.calendar({ value: new Date( 2014, 1 - 1, 1 ) });
+
+ TestHelpers.calendar.focusGrid( element ).simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } );
+ setTimeout(function() {
+ $( ":focus" ).simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } );
+ TestHelpers.calendar.equalsDate(
+ element.calendar( "valueAsDate" ),
+ new Date( 2014, 1 - 1, 8 ),
+ "Keystroke down to move to the next week"
+ );
+ element.calendar( "destroy" );
+ step5();
+ }, 50 );
+ }
+
+ function step5() {
+ element.calendar({ value: new Date( 2014, 1 - 1, 1 ) });
+
+ TestHelpers.calendar.focusGrid( element ).simulate( "keydown", { keyCode: $.ui.keyCode.PAGE_UP } );
+ setTimeout(function() {
+ $( ":focus" ).simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } );
+ TestHelpers.calendar.equalsDate(
+ element.calendar( "valueAsDate" ),
+ new Date( 2013, 12 - 1, 1 ),
+ "Keystroke Page Up moves date to previous month"
+ );
+ element.calendar( "destroy" );
+ step6();
+ }, 50 );
+ }
+
+ function step6() {
+ element.calendar({ value: new Date( 2014, 1 - 1, 1 ) });
+
+ TestHelpers.calendar.focusGrid( element )
+ .simulate( "keydown", { keyCode: $.ui.keyCode.PAGE_UP, altKey: true } );
+ setTimeout(function() {
+ $( ":focus" ).simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } );
+ TestHelpers.calendar.equalsDate(
+ element.calendar( "valueAsDate" ),
+ new Date( 2013, 1 - 1, 1 ),
+ "Keystroke Page Up + Ctrl moves date to previous year"
+ );
+ element.calendar( "destroy" );
+ step7();
+ }, 50 );
+ }
+
+ function step7() {
+ element.calendar({ value: new Date( 2014, 1 - 1, 1 ) });
+
+ TestHelpers.calendar.focusGrid( element ).simulate( "keydown", { keyCode: $.ui.keyCode.PAGE_DOWN } );
+ setTimeout(function() {
+ $( ":focus" ).simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } );
+ TestHelpers.calendar.equalsDate(
+ element.calendar( "valueAsDate" ),
+ new Date( 2014, 2 - 1, 1 ),
+ "Keystroke Page Down moves date to next month"
+ );
+ element.calendar( "destroy" );
+ step8();
+ }, 50 );
+ }
+
+ function step8() {
+ element.calendar({ value: new Date( 2014, 1 - 1, 1 ) });
+
+ TestHelpers.calendar.focusGrid( element )
+ .simulate( "keydown", { keyCode: $.ui.keyCode.PAGE_DOWN, altKey: true } );
+ setTimeout(function() {
+ $( ":focus" ).simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } );
+ TestHelpers.calendar.equalsDate(
+ element.calendar( "valueAsDate" ),
+ new Date( 2015, 1 - 1, 1 ),
+ "Keystroke Page Down + Ctrl moves date to next year"
+ );
+ element.calendar( "destroy" );
+ step9();
+ }, 50 );
+ }
+
+ // Check for moving to short months
+ function step9() {
+ element.calendar({ value: new Date( 2014, 3 - 1, 31 ) });
+
+ TestHelpers.calendar.focusGrid( element ).simulate( "keydown", { keyCode: $.ui.keyCode.PAGE_UP } );
+ setTimeout(function() {
+ $( ":focus" ).simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } );
+ TestHelpers.calendar.equalsDate(
+ element.calendar( "valueAsDate" ),
+ new Date( 2014, 2 - 1, 28 ),
+ "Keystroke Page Up and short months"
+ );
+ element.calendar( "destroy" );
+ step10();
+ }, 50 );
+ }
+
+ function step10() {
+ element.calendar({ value: new Date( 2016, 1 - 1, 30 ) });
+
+ TestHelpers.calendar.focusGrid( element ).simulate( "keydown", { keyCode: $.ui.keyCode.PAGE_DOWN } );
+ setTimeout(function() {
+ $( ":focus" ).simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } );
+ TestHelpers.calendar.equalsDate(
+ element.calendar( "valueAsDate" ),
+ new Date( 2016, 2 - 1, 29 ),
+ "Keystroke Page Down and leap years"
+ );
+ element.calendar( "destroy" );
+ start();
+ }, 50 );
+ }
+
+ step1();
+});
+
+/*
+ // TODO: Re-add tests if we implement a stepMonths option
+ input.calendar( "option", { stepMonths: 2, gotoCurrent: false } )
+ .calendar( "close" ).val( "02/04/2008" ).calendar( "open" )
+ .late( "keydown", { keyCode: $.ui.keyCode.PAGE_UP } )
+ .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } );
+ TestHelpers.datepicker.equalsDate( input.calendar( "valueAsDate" ), new Date( 2007, 12 - 1, 4 ),
+ "Keystroke pgup step 2" );
+
+ input.val( "02/04/2008" ).calendar( "open" )
+ .simulate( "keydown", { keyCode: $.ui.keyCode.PAGE_DOWN } )
+ .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } );
+ TestHelpers.datepicker.equalsDate( input.calendar( "valueAsDate" ), new Date( 2008, 4 - 1, 4 ),
+ "Keystroke pgdn step 2" );
+ */
+
+// TODO: implement
+test( "ARIA", function() {
+ expect( 0 );
+});
+
+asyncTest( "mouse", function() {
+ expect( 6 );
+
+ var element = $( "#calendar" ).calendar(),
+ date = new Date();
+
+ function step1() {
+ $( "tbody a:contains(10)", element ).simulate( "mousedown", {} );
+ date.setDate( 10 );
+ TestHelpers.calendar.equalsDate(
+ element.calendar( "valueAsDate" ),
+ date,
+ "Mouse click"
+ );
+
+ element.calendar( "option", "value", new Date( 2008, 2 - 1, 4) );
+ $( ".ui-calendar-calendar tbody a:contains(12)", element ).simulate( "mousedown" );
+ TestHelpers.calendar.equalsDate(
+ element.calendar( "valueAsDate" ),
+ new Date( 2008, 2 - 1, 12 ),
+ "Mouse click - preset"
+ );
+
+ // Previous/next
+ element.calendar( "option", "value", new Date( 2008, 2 - 1, 4) );
+ $( ".ui-calendar-prev", element ).simulate( "click" );
+ $( ".ui-calendar-calendar tbody a:contains(16)", element ).simulate( "mousedown" );
+ TestHelpers.calendar.equalsDate(
+ element.calendar( "valueAsDate" ),
+ new Date( 2008, 1 - 1, 16 ),
+ "Mouse click - previous"
+ );
+
+ element.calendar( "option", "value", new Date( 2008, 2 - 1, 4) );
+ $( ".ui-calendar-next", element ).simulate( "click" );
+ $( ".ui-calendar-calendar tbody a:contains(18)", element ).simulate( "mousedown" );
+ TestHelpers.calendar.equalsDate(
+ element.calendar( "valueAsDate" ),
+ new Date( 2008, 3 - 1, 18 ),
+ "Mouse click - next"
+ );
+
+ step2();
+ }
+
+ // Previous/next with minimum/maximum
+ function step2() {
+ element.calendar( "destroy" );
+ element.calendar({
+ value: new Date( 2008, 3 - 1, 4),
+ min: new Date( 2008, 2 - 1, 2 ),
+ max: new Date( 2008, 2 - 1, 26 )
+ });
+
+ $( ".ui-calendar-prev", element ).simulate( "click" );
+ $( "tbody a:contains(16)", element ).simulate( "mousedown" );
+ TestHelpers.calendar.equalsDate(
+ element.calendar( "valueAsDate" ),
+ new Date( 2008, 2 - 1, 16 ),
+ "Mouse click - previous + min/max"
+ );
+ step3();
+ }
+
+ function step3() {
+ element.calendar( "destroy" );
+ element.calendar({
+ value: new Date( 2008, 1 - 1, 4),
+ min: new Date( 2008, 2 - 1, 2 ),
+ max: new Date( 2008, 2 - 1, 26 )
+ });
+
+ $( ".ui-calendar-next", element ).simulate( "click" );
+ $( "tbody a:contains(18)", element ).simulate( "mousedown" );
+ TestHelpers.calendar.equalsDate(
+ element.calendar( "valueAsDate" ),
+ new Date( 2008, 2 - 1, 18 ),
+ "Mouse click - next + min/max"
+ );
+ start();
+ }
+
+ step1();
+});
+
+})( jQuery );
diff --git a/tests/unit/calendar/calendar_events.js b/tests/unit/calendar/calendar_events.js
new file mode 100644
index 00000000000..2d03801fadb
--- /dev/null
+++ b/tests/unit/calendar/calendar_events.js
@@ -0,0 +1,150 @@
+// The implement of events is completely changing therefore these tests are no longer directly
+// relevant. Leaving them around commented out so we can ensure the functionality is replicated.
+// For example:
+// TODO: In the old implementation the Enter key select's today's date when the has
+// focus and is empty. Do we want to replicate this behavior in the rewrite?
+/*
+
+(function( $ ) {
+
+module( "calendar: events" );
+
+test( "beforeOpen", function() {
+ expect( 0 );
+});
+
+test( "close", function() {
+ expect( 0 );
+});
+
+test( "open", function() {
+ expect( 0 );
+});
+
+test( "select", function() {
+ expect( 0 );
+});
+
+var selectedThis = null,
+selectedDate = null,
+selectedInst = null;
+
+function callback(date, inst) {
+ selectedThis = this;
+ selectedDate = date;
+ selectedInst = inst;
+}
+
+function callback2(year, month, inst) {
+ selectedThis = this;
+ selectedDate = year + "/" + month;
+ selectedInst = inst;
+}
+
+test( "events", function() {
+ expect( 26 );
+ var dateStr, newMonthYear, inp2,
+ inp = TestHelpers.calendar.init( "#inp", {onSelect: callback}),
+ date = new Date();
+ // onSelect
+ inp.val( "" ).calendar( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ equal(selectedThis, inp[0], "Callback selected this" );
+ equal(selectedInst, $.data(inp[0], TestHelpers.calendar.PROP_NAME), "Callback selected inst" );
+ equal(selectedDate, $.calendar.formatDate( "mm/dd/yy", date),
+ "Callback selected date" );
+ inp.val( "" ).calendar( "show" ).
+ simulate( "keydown", {ctrlKey: true, keyCode: $.ui.keyCode.DOWN}).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ date.setDate(date.getDate() + 7);
+ equal(selectedDate, $.calendar.formatDate( "mm/dd/yy", date),
+ "Callback selected date - ctrl+down" );
+ inp.val( "" ).calendar( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ESCAPE});
+ equal(selectedDate, $.calendar.formatDate( "mm/dd/yy", date),
+ "Callback selected date - esc" );
+ dateStr = "02/04/2008";
+ inp.val(dateStr).calendar( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ equal(dateStr, selectedDate,
+ "onSelect is called after enter keydown" );
+ // onChangeMonthYear
+ inp.calendar( "option", {onChangeMonthYear: callback2, onSelect: null}).
+ val( "" ).calendar( "show" );
+ newMonthYear = function(date) {
+ return date.getFullYear() + "/" + (date.getMonth() + 1);
+ };
+ date = new Date();
+ date.setDate(1);
+ inp.simulate( "keydown", {keyCode: $.ui.keyCode.PAGE_UP});
+ date.setMonth(date.getMonth() - 1);
+ equal(selectedThis, inp[0], "Callback change month/year this" );
+ equal(selectedInst, $.data(inp[0], TestHelpers.calendar.PROP_NAME), "Callback change month/year inst" );
+ equal(selectedDate, newMonthYear(date),
+ "Callback change month/year date - pgup" );
+ inp.simulate( "keydown", {keyCode: $.ui.keyCode.PAGE_DOWN});
+ date.setMonth(date.getMonth() + 1);
+ equal(selectedDate, newMonthYear(date),
+ "Callback change month/year date - pgdn" );
+ inp.simulate( "keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP});
+ date.setFullYear(date.getFullYear() - 1);
+ equal(selectedDate, newMonthYear(date),
+ "Callback change month/year date - ctrl+pgup" );
+ inp.simulate( "keydown", {ctrlKey: true, keyCode: $.ui.keyCode.HOME});
+ date.setFullYear(date.getFullYear() + 1);
+ equal(selectedDate, newMonthYear(date),
+ "Callback change month/year date - ctrl+home" );
+ inp.simulate( "keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN});
+ date.setFullYear(date.getFullYear() + 1);
+ equal(selectedDate, newMonthYear(date),
+ "Callback change month/year date - ctrl+pgdn" );
+ inp.calendar( "setDate", new Date(2007, 1 - 1, 26));
+ equal(selectedDate, "2007/1", "Callback change month/year date - setDate" );
+ selectedDate = null;
+ inp.calendar( "setDate", new Date(2007, 1 - 1, 12));
+ ok(selectedDate == null, "Callback change month/year date - setDate no change" );
+ // onChangeMonthYear step by 2
+ inp.calendar( "option", {stepMonths: 2}).
+ calendar( "hide" ).val( "" ).calendar( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.PAGE_UP});
+ date.setMonth(date.getMonth() - 14);
+ equal(selectedDate, newMonthYear(date),
+ "Callback change month/year by 2 date - pgup" );
+ inp.simulate( "keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP});
+ date.setMonth(date.getMonth() - 12);
+ equal(selectedDate, newMonthYear(date),
+ "Callback change month/year by 2 date - ctrl+pgup" );
+ inp.simulate( "keydown", {keyCode: $.ui.keyCode.PAGE_DOWN});
+ date.setMonth(date.getMonth() + 2);
+ equal(selectedDate, newMonthYear(date),
+ "Callback change month/year by 2 date - pgdn" );
+ inp.simulate( "keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN});
+ date.setMonth(date.getMonth() + 12);
+ equal(selectedDate, newMonthYear(date),
+ "Callback change month/year by 2 date - ctrl+pgdn" );
+ // onClose
+ inp.calendar( "option", {onClose: callback, onChangeMonthYear: null, stepMonths: 1}).
+ val( "" ).calendar( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ESCAPE});
+ equal(selectedThis, inp[0], "Callback close this" );
+ equal(selectedInst, $.data(inp[0], TestHelpers.calendar.PROP_NAME), "Callback close inst" );
+ equal(selectedDate, "", "Callback close date - esc" );
+ inp.val( "" ).calendar( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ equal(selectedDate, $.calendar.formatDate( "mm/dd/yy", new Date()),
+ "Callback close date - enter" );
+ inp.val( "02/04/2008" ).calendar( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ESCAPE});
+ equal(selectedDate, "02/04/2008", "Callback close date - preset" );
+ inp.val( "02/04/2008" ).calendar( "show" ).
+ simulate( "keydown", {ctrlKey: true, keyCode: $.ui.keyCode.END});
+ equal(selectedDate, "", "Callback close date - ctrl+end" );
+
+ inp2 = TestHelpers.calendar.init( "#inp2" );
+ inp2.calendar().calendar( "option", {onClose: callback}).calendar( "show" );
+ inp.calendar( "show" );
+ equal(selectedThis, inp2[0], "Callback close this" );
+});
+
+})( jQuery );
+ */
diff --git a/tests/unit/calendar/calendar_methods.js b/tests/unit/calendar/calendar_methods.js
new file mode 100644
index 00000000000..59078e398cb
--- /dev/null
+++ b/tests/unit/calendar/calendar_methods.js
@@ -0,0 +1,109 @@
+(function( $ ) {
+
+module( "calendar: methods" );
+
+test( "destroy", function() {
+ expect( 4 );
+
+ var element = $( "#calendar" ).calendar();
+
+ ok( element.calendar( "instance" ), "instance created" );
+ element.calendar( "destroy" );
+ ok( !element.calendar( "instance" ), "instance removed" );
+ ok( !element.attr( "role" ), "role attribute removed" );
+ ok( !element.attr( "aria-labelledby" ), "aria-labelledby attribute removed" );
+});
+
+test( "enable / disable", function() {
+ expect( 6 );
+
+ var element = $( "#calendar" ).calendar();
+
+ ok( !element.calendar( "option", "disabled" ), "initially enabled" );
+ ok( !element.hasClass( "ui-calendar-disabled" ), "does not have disabled class name" );
+
+ element.calendar( "disable" );
+ ok( element.calendar( "option", "disabled" ), "disabled option is set" );
+ ok( element.hasClass( "ui-calendar-disabled" ), "calendar has disabled class name" );
+
+ element.calendar( "enable" );
+ ok( !element.calendar( "option", "disabled" ), "enabled after enable() call" );
+ ok( !element.hasClass( "ui-calendar-disabled" ), "no longer has disabled class name" );
+});
+
+test( "widget", function() {
+ expect( 1 );
+
+ var element = $( "#calendar" ).calendar(),
+ widget = element.calendar( "widget" );
+
+ deepEqual( widget[ 0 ], element[ 0 ] );
+});
+
+test( "value", function() {
+ expect( 3 );
+ var element = $( "#calendar" ).calendar();
+
+ element.calendar( "value", "1/1/14" );
+ ok( element.find( "a[data-timestamp]:first" ).hasClass( "ui-state-active" ), "first day marked as selected" );
+ equal( element.calendar( "value" ), "1/1/14", "getter" );
+
+ element.calendar( "value", "abc" );
+ equal( element.calendar( "value" ), "1/1/14", "Setting invalid values should be ignored." );
+});
+
+test( "valueAsDate", function() {
+ expect( 12 );
+
+ var minDate, maxDate, dateAndTimeToSet, dateAndTimeClone,
+ element = $( "#calendar" ).calendar(),
+ date1 = new Date(2008, 6 - 1, 4),
+ date2 = new Date();
+
+ element.calendar( "valueAsDate", new Date( 2014, 0, 1 ) );
+ ok( element.find( "a[data-timestamp]:first" ).hasClass( "ui-state-active" ), "First day marked as selected" );
+ TestHelpers.calendar.equalsDate( element.calendar( "valueAsDate" ), new Date( 2014, 0, 1 ), "Getter" );
+
+ element.calendar( "destroy" );
+
+ element.calendar();
+ TestHelpers.calendar.equalsDate( element.calendar( "valueAsDate" ), new Date(), "Set date - default" );
+
+ element.calendar( "valueAsDate", date1 );
+ TestHelpers.calendar.equalsDate(element.calendar( "valueAsDate" ), date1, "Set date - 2008-06-04" );
+
+ element.calendar( "valueAsDate", date1, date2);
+ TestHelpers.calendar.equalsDate(element.calendar( "valueAsDate" ), date1, "Set date - two dates" );
+
+ // With minimum/maximum
+ element = $( "#calendar" ).calendar();
+ date1 = new Date( 2008, 1 - 1, 4 );
+ date2 = new Date( 2008, 6 - 1, 4 );
+ minDate = new Date( 2008, 2 - 1, 29 );
+ maxDate = new Date( 2008, 3 - 1, 28 );
+
+ element.calendar( "option", { min: minDate } ).calendar( "valueAsDate", date2 );
+ TestHelpers.calendar.equalsDate( element.calendar( "valueAsDate" ), date2, "Set date min/max - value > min" );
+
+ element.calendar( "valueAsDate", date1 );
+ TestHelpers.calendar.equalsDate( element.calendar( "valueAsDate" ), date2, "Set date min/max - value < min" );
+
+ element.calendar( "option", { max: maxDate, min: null } ).calendar( "valueAsDate", date1 );
+ TestHelpers.calendar.equalsDate( element.calendar( "valueAsDate" ), date1, "Set date min/max - value < max" );
+
+ element.calendar( "valueAsDate", date2 );
+ TestHelpers.calendar.equalsDate( element.calendar( "valueAsDate" ), date1, "Set date min/max - value > max" );
+
+ element.calendar( "option", { min: minDate } ).calendar( "valueAsDate", date1 );
+ TestHelpers.calendar.equalsDate( element.calendar( "valueAsDate" ), date1, "Set date min/max - value < min" );
+
+ element.calendar( "valueAsDate", date2 );
+ TestHelpers.calendar.equalsDate( element.calendar( "valueAsDate" ), date1, "Set date min/max - value > max" );
+
+ dateAndTimeToSet = new Date( 2008, 3 - 1, 28, 1, 11, 0 );
+ dateAndTimeClone = new Date( 2008, 3 - 1, 28, 1, 11, 0 );
+ element.calendar( "valueAsDate", dateAndTimeToSet );
+ equal( dateAndTimeToSet.getTime(), dateAndTimeClone.getTime(), "Date object passed should not be changed by valueAsDate" );
+});
+
+})( jQuery );
diff --git a/tests/unit/calendar/calendar_options.js b/tests/unit/calendar/calendar_options.js
new file mode 100644
index 00000000000..d45181e91cd
--- /dev/null
+++ b/tests/unit/calendar/calendar_options.js
@@ -0,0 +1,1273 @@
+(function( $ ) {
+
+module( "calendar: options" );
+
+test( "appendTo", function() {
+ expect( 6 );
+ var container,
+ detached = $( "" ),
+ input = $( "#calendar" );
+
+ input.calendar();
+ container = input.calendar( "widget" ).parent()[ 0 ];
+ equal( container, document.body, "defaults to body" );
+ input.calendar( "destroy" );
+
+ input.calendar({ appendTo: "#qunit-fixture" });
+ container = input.calendar( "widget" ).parent()[ 0 ];
+ equal( container, $( "#qunit-fixture" )[ 0 ], "child of specified element" );
+ input.calendar( "destroy" );
+
+ input.calendar({ appendTo: "#does-not-exist" });
+ container = input.calendar( "widget" ).parent()[ 0 ];
+ equal( container, document.body, "set to body if element does not exist" );
+ input.calendar( "destroy" );
+
+ input.calendar()
+ .calendar( "option", "appendTo", "#qunit-fixture" );
+ container = input.calendar( "widget" ).parent()[ 0 ];
+ equal( container, $( "#qunit-fixture" )[ 0 ], "modified after init" );
+ input.calendar( "destroy" );
+
+ input.calendar({ appendTo: detached });
+ container = input.calendar( "widget" ).parent()[ 0 ];
+ equal( container, detached[ 0 ], "detached jQuery object" );
+ input.calendar( "destroy" );
+
+ input.calendar({ appendTo: detached[ 0 ] });
+ container = input.calendar( "widget" ).parent()[ 0 ];
+ equal( container, detached[ 0 ], "detached DOM element" );
+ input.calendar( "destroy" );
+});
+
+test( "dateFormat", function() {
+ expect( 2 );
+ var input = $( "#calendar" ).val( "1/1/14" ).calendar(),
+ picker = input.calendar( "widget" ),
+ firstDayLink = picker.find( "td[id]:first a" );
+
+ input.calendar( "open" );
+ firstDayLink.trigger( "mousedown" );
+ equal( input.val(), "1/1/14", "default formatting" );
+
+ input.calendar( "option", "dateFormat", { date: "full" } );
+ equal( input.val(), "Wednesday, January 1, 2014", "updated formatting" );
+
+ input.calendar( "destroy" );
+});
+
+test( "eachDay", function() {
+ expect( 5 );
+ var timestamp,
+ input = $( "#calendar" ).calendar(),
+ picker = input.calendar( "widget" ),
+ firstCell = picker.find( "td[id]:first" );
+
+ equal( firstCell.find( "a" ).length, 1, "days are selectable by default" );
+ timestamp = parseInt( firstCell.find( "a" ).attr( "data-timestamp" ), 10 );
+ equal( new Date( timestamp ).getDate(), 1, "first available day is the 1st by default" );
+
+ // Do not render the 1st of the month
+ input.calendar( "option", "eachDay", function( day ) {
+ if ( day.date === 1 ) {
+ day.render = false;
+ }
+ });
+ firstCell = picker.find( "td[id]:first" );
+ timestamp = parseInt( firstCell.find( "a" ).attr( "data-timestamp" ), 10 );
+ equal( new Date( timestamp ).getDate(), 2, "first available day is the 2nd" );
+
+ // Display the 1st of the month but make it not selectable.
+ input.calendar( "option", "eachDay", function( day ) {
+ if ( day.date === 1 ) {
+ day.selectable = false;
+ }
+ });
+ firstCell = picker.find( "td[id]:first" );
+ equal( firstCell.find( "a" ).length, 0, "the 1st is not selectable" );
+
+ input.calendar( "option", "eachDay", function( day ) {
+ if ( day.date === 1 ) {
+ day.extraClasses = "ui-custom";
+ }
+ });
+ ok( picker.find( "td[id]:first a" ).hasClass( "ui-custom" ), "extraClasses applied" );
+
+ input.calendar( "destroy" );
+});
+
+test( "numberOfMonths", function() {
+ expect( 0 );
+});
+
+asyncTest( "position", function() {
+ expect( 3 );
+ var input = $( "
" ).calendar().appendTo( "body" ).css({
+ position: "absolute",
+ top: 0,
+ left: 0
+ }),
+ container = input.calendar( "widget" );
+
+ input.calendar( "open" );
+ setTimeout(function() {
+ closeEnough( input.offset().left, container.offset().left, 1, "left sides line up by default" );
+ closeEnough( container.offset().top, input.offset().top + input.outerHeight(), 1,
+ "calendar directly under input by default" );
+
+ // Change the position option using option()
+ input.calendar( "option", "position", {
+ my: "left top",
+ at: "right bottom"
+ });
+ closeEnough( container.offset().left, input.offset().left + input.outerWidth(), 1,
+ "calendar on right hand side of input after position change" );
+
+ input.remove();
+ start();
+ });
+});
+
+test( "showWeek", function() {
+ expect( 7 );
+ var input = $( "#calendar" ).calendar(),
+ container = input.calendar( "widget" );
+
+ equal( container.find( "thead th" ).length, 7, "just 7 days, no column cell" );
+ equal( container.find( ".ui-calendar-week-col" ).length, 0,
+ "no week column cells present" );
+ input.calendar( "destroy" );
+
+ input = $( "#calendar" ).calendar({ showWeek: true });
+ container = input.calendar( "widget" );
+ equal( container.find( "thead th" ).length, 8, "7 days + a column cell" );
+ ok( container.find( "thead th:first" ).is( ".ui-calendar-week-col" ),
+ "first cell should have ui-calendar-week-col class name" );
+ equal( container.find( ".ui-calendar-week-col" ).length,
+ container.find( "tr" ).length, "one week cell for each week" );
+ input.calendar( "destroy" );
+
+ input = $( "#calendar" ).calendar();
+ container = input.calendar( "widget" );
+ equal( container.find( "thead th" ).length, 7, "no week column" );
+ input.calendar( "option", "showWeek", true );
+ equal( container.find( "thead th" ).length, 8, "supports changing option after init" );
+});
+
+/*
+test( "setDefaults", function() {
+ expect( 3 );
+ TestHelpers.calendar.init( "#inp" );
+ equal($.calendar._defaults.showOn, "focus", "Initial showOn" );
+ $.calendar.setDefaults({showOn: "button"});
+ equal($.calendar._defaults.showOn, "button", "Change default showOn" );
+ $.calendar.setDefaults({showOn: "focus"});
+ equal($.calendar._defaults.showOn, "focus", "Restore showOn" );
+});
+
+test( "option", function() {
+ expect( 17 );
+ var inp = TestHelpers.calendar.init( "#inp" ),
+ inst = $.data(inp[0], TestHelpers.calendar.PROP_NAME);
+ // Set option
+ equal(inst.settings.showOn, null, "Initial setting showOn" );
+ equal($.calendar._get(inst, "showOn" ), "focus", "Initial instance showOn" );
+ equal($.calendar._defaults.showOn, "focus", "Initial default showOn" );
+ inp.calendar( "option", "showOn", "button" );
+ equal(inst.settings.showOn, "button", "Change setting showOn" );
+ equal($.calendar._get(inst, "showOn" ), "button", "Change instance showOn" );
+ equal($.calendar._defaults.showOn, "focus", "Retain default showOn" );
+ inp.calendar( "option", {showOn: "both"});
+ equal(inst.settings.showOn, "both", "Change setting showOn" );
+ equal($.calendar._get(inst, "showOn" ), "both", "Change instance showOn" );
+ equal($.calendar._defaults.showOn, "focus", "Retain default showOn" );
+ inp.calendar( "option", "showOn", undefined);
+ equal(inst.settings.showOn, null, "Clear setting showOn" );
+ equal($.calendar._get(inst, "showOn" ), "focus", "Restore instance showOn" );
+ equal($.calendar._defaults.showOn, "focus", "Retain default showOn" );
+ // Get option
+ inp = TestHelpers.calendar.init( "#inp" );
+ equal(inp.calendar( "option", "showOn" ), "focus", "Initial setting showOn" );
+ inp.calendar( "option", "showOn", "button" );
+ equal(inp.calendar( "option", "showOn" ), "button", "Change instance showOn" );
+ inp.calendar( "option", "showOn", undefined);
+ equal(inp.calendar( "option", "showOn" ), "focus", "Reset instance showOn" );
+ deepEqual(inp.calendar( "option", "all" ), {showAnim: ""}, "Get instance settings" );
+ deepEqual(inp.calendar( "option", "defaults" ), $.calendar._defaults,
+ "Get default settings" );
+});
+
+test( "disabled", function() {
+ expect(8);
+ var inp = TestHelpers.calendar.init( "#inp" );
+ ok(!inp.calendar( "isDisabled" ), "Initially marked as enabled" );
+ ok(!inp[0].disabled, "Field initially enabled" );
+ inp.calendar( "option", "disabled", true);
+ ok(inp.calendar( "isDisabled" ), "Marked as disabled" );
+ ok(inp[0].disabled, "Field now disabled" );
+ inp.calendar( "option", "disabled", false);
+ ok(!inp.calendar( "isDisabled" ), "Marked as enabled" );
+ ok(!inp[0].disabled, "Field now enabled" );
+ inp.calendar( "destroy" );
+
+ inp = TestHelpers.calendar.init( "#inp", { disabled: true });
+ ok(inp.calendar( "isDisabled" ), "Initially marked as disabled" );
+ ok(inp[0].disabled, "Field initially disabled" );
+});
+
+test( "change", function() {
+ expect( 12 );
+ var inp = TestHelpers.calendar.init( "#inp" ),
+ inst = $.data(inp[0], TestHelpers.calendar.PROP_NAME);
+ equal(inst.settings.showOn, null, "Initial setting showOn" );
+ equal($.calendar._get(inst, "showOn" ), "focus", "Initial instance showOn" );
+ equal($.calendar._defaults.showOn, "focus", "Initial default showOn" );
+ inp.calendar( "change", "showOn", "button" );
+ equal(inst.settings.showOn, "button", "Change setting showOn" );
+ equal($.calendar._get(inst, "showOn" ), "button", "Change instance showOn" );
+ equal($.calendar._defaults.showOn, "focus", "Retain default showOn" );
+ inp.calendar( "change", {showOn: "both"});
+ equal(inst.settings.showOn, "both", "Change setting showOn" );
+ equal($.calendar._get(inst, "showOn" ), "both", "Change instance showOn" );
+ equal($.calendar._defaults.showOn, "focus", "Retain default showOn" );
+ inp.calendar( "change", "showOn", undefined);
+ equal(inst.settings.showOn, null, "Clear setting showOn" );
+ equal($.calendar._get(inst, "showOn" ), "focus", "Restore instance showOn" );
+ equal($.calendar._defaults.showOn, "focus", "Retain default showOn" );
+});
+
+(function() {
+ var url = window.location.search;
+ url = decodeURIComponent( url.slice( url.indexOf( "swarmURL=" ) + 9 ) );
+
+ // TODO: This test occassionally fails in IE in TestSwarm
+ if ( $.ui.ie && url && url.indexOf( "http" ) === 0 ) {
+ return;
+ }
+
+ asyncTest( "invocation", function() {
+ var button, image,
+ isOldIE = $.ui.ie && ( !document.documentMode || document.documentMode < 9 ),
+ body = $( "body" );
+
+ expect( isOldIE ? 25 : 29 );
+
+ function step0() {
+ var inp = TestHelpers.calendar.initNewInput(),
+ dp = $( "#ui-calendar-div" );
+
+ button = inp.siblings( "button" );
+ ok( button.length === 0, "Focus - button absent" );
+ image = inp.siblings( "img" );
+ ok( image.length === 0, "Focus - image absent" );
+
+ TestHelpers.calendar.onFocus( inp, function() {
+ ok( dp.is( ":visible" ), "Focus - rendered on focus" );
+ inp.simulate( "keydown", { keyCode: $.ui.keyCode.ESCAPE } );
+ ok( !dp.is( ":visible" ), "Focus - hidden on exit" );
+ step1();
+ });
+ }
+
+ function step1() {
+
+ var inp = TestHelpers.calendar.initNewInput(),
+ dp = $( "#ui-calendar-div" );
+
+ TestHelpers.calendar.onFocus( inp, function() {
+ ok( dp.is( ":visible" ), "Focus - rendered on focus" );
+ body.simulate( "mousedown", {} );
+ ok( !dp.is( ":visible" ), "Focus - hidden on external click" );
+ inp.calendar( "hide" ).calendar( "destroy" );
+
+ step2();
+ });
+ }
+
+ function step2() {
+ var inp = TestHelpers.calendar.initNewInput({
+ showOn: "button",
+ buttonText: "Popup"
+ }),
+ dp = $( "#ui-calendar-div" );
+
+ ok( !dp.is( ":visible" ), "Button - initially hidden" );
+ button = inp.siblings( "button" );
+ image = inp.siblings( "img" );
+ ok( button.length === 1, "Button - button present" );
+ ok( image.length === 0, "Button - image absent" );
+ equal( button.text(), "Popup", "Button - button text" );
+
+ TestHelpers.calendar.onFocus( inp, function() {
+ ok( !dp.is( ":visible" ), "Button - not rendered on focus" );
+ button.click();
+ ok( dp.is( ":visible" ), "Button - rendered on button click" );
+ button.click();
+ ok( !dp.is( ":visible" ), "Button - hidden on second button click" );
+ inp.calendar( "hide" ).calendar( "destroy" );
+
+ step3();
+ });
+ }
+
+ function step3() {
+ var inp = TestHelpers.calendar.initNewInput({
+ showOn: "button",
+ buttonImageOnly: true,
+ buttonImage: "images/calendar.gif",
+ buttonText: "Cal"
+ }),
+ dp = $( "#ui-calendar-div" );
+
+ ok( !dp.is( ":visible" ), "Image button - initially hidden" );
+ button = inp.siblings( "button" );
+ ok( button.length === 0, "Image button - button absent" );
+ image = inp.siblings( "img" );
+ ok( image.length === 1, "Image button - image present" );
+ ok( /images\/calendar\.gif$/.test( image.attr( "src" ) ), "Image button - image source" );
+ equal( image.attr( "title" ), "Cal", "Image button - image text" );
+
+ TestHelpers.calendar.onFocus( inp, function() {
+ ok( !dp.is( ":visible" ), "Image button - not rendered on focus" );
+ image.click();
+ ok( dp.is( ":visible" ), "Image button - rendered on image click" );
+ image.click();
+ ok( !dp.is( ":visible" ), "Image button - hidden on second image click" );
+ inp.calendar( "hide" ).calendar( "destroy" );
+
+ step4();
+ });
+ }
+
+ function step4() {
+ var inp = TestHelpers.calendar.initNewInput({
+ showOn: "both",
+ buttonImage: "images/calendar.gif"
+ }),
+ dp = $( "#ui-calendar-div" );
+
+ ok( !dp.is( ":visible" ), "Both - initially hidden" );
+ button = inp.siblings( "button" );
+ ok( button.length === 1, "Both - button present" );
+ image = inp.siblings( "img" );
+ ok( image.length === 0, "Both - image absent" );
+ image = button.children( "img" );
+ ok( image.length === 1, "Both - button image present" );
+
+ // TODO: This test occasionally fails to focus in IE8 in BrowserStack
+ if ( !isOldIE ) {
+ TestHelpers.calendar.onFocus( inp, function() {
+ ok( dp.is( ":visible" ), "Both - rendered on focus" );
+ body.simulate( "mousedown", {} );
+ ok( !dp.is( ":visible" ), "Both - hidden on external click" );
+ button.click();
+ ok( dp.is( ":visible" ), "Both - rendered on button click" );
+ button.click();
+ ok( !dp.is( ":visible" ), "Both - hidden on second button click" );
+ inp.calendar( "hide" ).calendar( "destroy" );
+
+ start();
+ });
+ } else {
+ start();
+ }
+ }
+
+ step0();
+ });
+})();
+
+test( "otherMonths", function() {
+ expect( 8 );
+ var inp = TestHelpers.calendar.init( "#inp" ),
+ pop = $( "#ui-calendar-div" );
+ inp.val( "06/01/2009" ).calendar( "show" );
+ equal(pop.find( "tbody" ).text(),
+ // support: IE <9, jQuery <1.8
+ // In IE7/8 with jQuery <1.8, encoded spaces behave in strange ways
+ $( "
\u00a0123456789101112131415161718192021222324252627282930\u00a0\u00a0\u00a0\u00a0 " ).text(),
+ "Other months - none" );
+ ok(pop.find( "td:last *" ).length === 0, "Other months - no content" );
+ inp.calendar( "hide" ).calendar( "option", "showOtherMonths", true).calendar( "show" );
+ equal(pop.find( "tbody" ).text(), "311234567891011121314151617181920212223242526272829301234",
+ "Other months - show" );
+ ok(pop.find( "td:last span" ).length === 1, "Other months - span content" );
+ inp.calendar( "hide" ).calendar( "option", "selectOtherMonths", true).calendar( "show" );
+ equal(pop.find( "tbody" ).text(), "311234567891011121314151617181920212223242526272829301234",
+ "Other months - select" );
+ ok(pop.find( "td:last a" ).length === 1, "Other months - link content" );
+ inp.calendar( "hide" ).calendar( "option", "showOtherMonths", false).calendar( "show" );
+ equal(pop.find( "tbody" ).text(),
+ // support: IE <9, jQuery <1.8
+ // In IE7/8 with jQuery <1.8, encoded spaces behave in strange ways
+ $( "
\u00a0123456789101112131415161718192021222324252627282930\u00a0\u00a0\u00a0\u00a0 " ).text(),
+ "Other months - none" );
+ ok(pop.find( "td:last *" ).length === 0, "Other months - no content" );
+});
+
+test( "defaultDate", function() {
+ expect( 16 );
+ var inp = TestHelpers.calendar.init( "#inp" ),
+ date = new Date();
+ inp.val( "" ).calendar( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), date, "Default date null" );
+
+ // Numeric values
+ inp.calendar( "option", {defaultDate: -2}).
+ calendar( "hide" ).val( "" ).calendar( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ date.setDate(date.getDate() - 2);
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), date, "Default date -2" );
+
+ date = new Date();
+ inp.calendar( "option", {defaultDate: 3}).
+ calendar( "hide" ).val( "" ).calendar( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ date.setDate(date.getDate() + 3);
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), date, "Default date 3" );
+
+ date = new Date();
+ inp.calendar( "option", {defaultDate: 1 / "a"}).
+ calendar( "hide" ).val( "" ).calendar( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), date, "Default date NaN" );
+
+ // String offset values
+ inp.calendar( "option", {defaultDate: "-1d"}).
+ calendar( "hide" ).val( "" ).calendar( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ date.setDate(date.getDate() - 1);
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), date, "Default date -1d" );
+ inp.calendar( "option", {defaultDate: "+3D"}).
+ calendar( "hide" ).val( "" ).calendar( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ date.setDate(date.getDate() + 4);
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), date, "Default date +3D" );
+ inp.calendar( "option", {defaultDate: " -2 w "}).
+ calendar( "hide" ).val( "" ).calendar( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ date = new Date();
+ date.setDate(date.getDate() - 14);
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), date, "Default date -2 w" );
+ inp.calendar( "option", {defaultDate: "+1 W"}).
+ calendar( "hide" ).val( "" ).calendar( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ date.setDate(date.getDate() + 21);
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), date, "Default date +1 W" );
+ inp.calendar( "option", {defaultDate: " -1 m "}).
+ calendar( "hide" ).val( "" ).calendar( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ date = TestHelpers.calendar.addMonths(new Date(), -1);
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), date, "Default date -1 m" );
+ inp.calendar( "option", {defaultDate: "+2M"}).
+ calendar( "hide" ).val( "" ).calendar( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ date = TestHelpers.calendar.addMonths(new Date(), 2);
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), date, "Default date +2M" );
+ inp.calendar( "option", {defaultDate: "-2y"}).
+ calendar( "hide" ).val( "" ).calendar( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ date = new Date();
+ date.setFullYear(date.getFullYear() - 2);
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), date, "Default date -2y" );
+ inp.calendar( "option", {defaultDate: "+1 Y "}).
+ calendar( "hide" ).val( "" ).calendar( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ date.setFullYear(date.getFullYear() + 3);
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), date, "Default date +1 Y" );
+ inp.calendar( "option", {defaultDate: "+1M +10d"}).
+ calendar( "hide" ).val( "" ).calendar( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ date = TestHelpers.calendar.addMonths(new Date(), 1);
+ date.setDate(date.getDate() + 10);
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), date, "Default date +1M +10d" );
+ // String date values
+ inp.calendar( "option", {defaultDate: "07/04/2007"}).
+ calendar( "hide" ).val( "" ).calendar( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ date = new Date(2007, 7 - 1, 4);
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), date, "Default date 07/04/2007" );
+ inp.calendar( "option", {dateFormat: "yy-mm-dd", defaultDate: "2007-04-02"}).
+ calendar( "hide" ).val( "" ).calendar( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ date = new Date(2007, 4 - 1, 2);
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), date, "Default date 2007-04-02" );
+ // Date value
+ date = new Date(2007, 1 - 1, 26);
+ inp.calendar( "option", {dateFormat: "mm/dd/yy", defaultDate: date}).
+ calendar( "hide" ).val( "" ).calendar( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), date, "Default date 01/26/2007" );
+});
+
+test( "miscellaneous", function() {
+ expect( 19 );
+ var curYear, longNames, shortNames, date,
+ dp = $( "#ui-calendar-div" ),
+ inp = TestHelpers.calendar.init( "#inp" );
+ // Year range
+ function genRange(start, offset) {
+ var i = start,
+ range = "";
+ for (; i < start + offset; i++) {
+ range += i;
+ }
+ return range;
+ }
+ curYear = new Date().getFullYear();
+ inp.val( "02/04/2008" ).calendar( "show" );
+ equal(dp.find( ".ui-calendar-year" ).text(), "2008", "Year range - read-only default" );
+ inp.calendar( "hide" ).calendar( "option", {changeYear: true}).calendar( "show" );
+ equal(dp.find( ".ui-calendar-year" ).text(), genRange(2008 - 10, 21), "Year range - changeable default" );
+ inp.calendar( "hide" ).calendar( "option", {yearRange: "c-6:c+2", changeYear: true}).calendar( "show" );
+ equal(dp.find( ".ui-calendar-year" ).text(), genRange(2008 - 6, 9), "Year range - c-6:c+2" );
+ inp.calendar( "hide" ).calendar( "option", {yearRange: "2000:2010", changeYear: true}).calendar( "show" );
+ equal(dp.find( ".ui-calendar-year" ).text(), genRange(2000, 11), "Year range - 2000:2010" );
+ inp.calendar( "hide" ).calendar( "option", {yearRange: "-5:+3", changeYear: true}).calendar( "show" );
+ equal(dp.find( ".ui-calendar-year" ).text(), genRange(curYear - 5, 9), "Year range - -5:+3" );
+ inp.calendar( "hide" ).calendar( "option", {yearRange: "2000:-5", changeYear: true}).calendar( "show" );
+ equal(dp.find( ".ui-calendar-year" ).text(), genRange(2000, curYear - 2004), "Year range - 2000:-5" );
+ inp.calendar( "hide" ).calendar( "option", {yearRange: "", changeYear: true}).calendar( "show" );
+ equal(dp.find( ".ui-calendar-year" ).text(), genRange(curYear, 1), "Year range - -6:+2" );
+
+ // Navigation as date format
+ inp.calendar( "option", {showButtonPanel: true});
+ equal(dp.find( ".ui-calendar-prev" ).text(), "Prev", "Navigation prev - default" );
+ equal(dp.find( ".ui-calendar-current" ).text(), "Today", "Navigation current - default" );
+ equal(dp.find( ".ui-calendar-next" ).text(), "Next", "Navigation next - default" );
+ inp.calendar( "hide" ).calendar( "option", {navigationAsDateFormat: true, prevText: "< M", currentText: "MM", nextText: "M >"}).
+ val( "02/04/2008" ).calendar( "show" );
+ longNames = $.calendar.regional[""].monthNames;
+ shortNames = $.calendar.regional[""].monthNamesShort;
+ date = new Date();
+ equal(dp.find( ".ui-calendar-prev" ).text(), "< " + shortNames[0], "Navigation prev - as date format" );
+ equal(dp.find( ".ui-calendar-current" ).text(),
+ longNames[date.getMonth()], "Navigation current - as date format" );
+ equal(dp.find( ".ui-calendar-next" ).text(),
+ shortNames[2] + " >", "Navigation next - as date format" );
+ inp.simulate( "keydown", {keyCode: $.ui.keyCode.PAGE_DOWN});
+ equal(dp.find( ".ui-calendar-prev" ).text(),
+ "< " + shortNames[1], "Navigation prev - as date format + pgdn" );
+ equal(dp.find( ".ui-calendar-current" ).text(),
+ longNames[date.getMonth()], "Navigation current - as date format + pgdn" );
+ equal(dp.find( ".ui-calendar-next" ).text(),
+ shortNames[3] + " >", "Navigation next - as date format + pgdn" );
+ inp.calendar( "hide" ).calendar( "option", {gotoCurrent: true}).
+ val( "02/04/2008" ).calendar( "show" );
+ equal(dp.find( ".ui-calendar-prev" ).text(),
+ "< " + shortNames[0], "Navigation prev - as date format + goto current" );
+ equal(dp.find( ".ui-calendar-current" ).text(),
+ longNames[1], "Navigation current - as date format + goto current" );
+ equal(dp.find( ".ui-calendar-next" ).text(),
+ shortNames[2] + " >", "Navigation next - as date format + goto current" );
+});
+
+test( "minMax", function() {
+ expect( 23 );
+ var date,
+ inp = TestHelpers.calendar.init( "#inp" ),
+ dp = $( "#ui-calendar-div" ),
+ lastYear = new Date(2007, 6 - 1, 4),
+ nextYear = new Date(2009, 6 - 1, 4),
+ minDate = new Date(2008, 2 - 1, 29),
+ maxDate = new Date(2008, 12 - 1, 7);
+ inp.val( "06/04/2008" ).calendar( "show" );
+ inp.simulate( "keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP}).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), lastYear,
+ "Min/max - null, null - ctrl+pgup" );
+ inp.val( "06/04/2008" ).calendar( "show" );
+ inp.simulate( "keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN}).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), nextYear,
+ "Min/max - null, null - ctrl+pgdn" );
+ inp.calendar( "option", {minDate: minDate}).
+ calendar( "hide" ).val( "06/04/2008" ).calendar( "show" );
+ inp.simulate( "keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP}).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), minDate,
+ "Min/max - 02/29/2008, null - ctrl+pgup" );
+ inp.val( "06/04/2008" ).calendar( "show" );
+ inp.simulate( "keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN}).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), nextYear,
+ "Min/max - 02/29/2008, null - ctrl+pgdn" );
+ inp.calendar( "option", {maxDate: maxDate}).
+ calendar( "hide" ).val( "06/04/2008" ).calendar( "show" );
+ inp.simulate( "keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP}).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), minDate,
+ "Min/max - 02/29/2008, 12/07/2008 - ctrl+pgup" );
+ inp.val( "06/04/2008" ).calendar( "show" );
+ inp.simulate( "keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN}).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), maxDate,
+ "Min/max - 02/29/2008, 12/07/2008 - ctrl+pgdn" );
+ inp.calendar( "option", {minDate: null}).
+ calendar( "hide" ).val( "06/04/2008" ).calendar( "show" );
+ inp.simulate( "keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP}).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), lastYear,
+ "Min/max - null, 12/07/2008 - ctrl+pgup" );
+ inp.val( "06/04/2008" ).calendar( "show" );
+ inp.simulate( "keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN}).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), maxDate,
+ "Min/max - null, 12/07/2008 - ctrl+pgdn" );
+ // Relative dates
+ date = new Date();
+ date.setDate(date.getDate() - 7);
+ inp.calendar( "option", {minDate: "-1w", maxDate: "+1 M +10 D "}).
+ calendar( "hide" ).val( "" ).calendar( "show" );
+ inp.simulate( "keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP}).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), date,
+ "Min/max - -1w, +1 M +10 D - ctrl+pgup" );
+ date = TestHelpers.calendar.addMonths(new Date(), 1);
+ date.setDate(date.getDate() + 10);
+ inp.val( "" ).calendar( "show" );
+ inp.simulate( "keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN}).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), date,
+ "Min/max - -1w, +1 M +10 D - ctrl+pgdn" );
+ // With existing date
+ inp = TestHelpers.calendar.init( "#inp" );
+ inp.val( "06/04/2008" ).calendar( "option", {minDate: minDate});
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), new Date(2008, 6 - 1, 4), "Min/max - setDate > min" );
+ inp.calendar( "option", {minDate: null}).val( "01/04/2008" ).calendar( "option", {minDate: minDate});
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), minDate, "Min/max - setDate < min" );
+ inp.calendar( "option", {minDate: null}).val( "06/04/2008" ).calendar( "option", {maxDate: maxDate});
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), new Date(2008, 6 - 1, 4), "Min/max - setDate < max" );
+ inp.calendar( "option", {maxDate: null}).val( "01/04/2009" ).calendar( "option", {maxDate: maxDate});
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), maxDate, "Min/max - setDate > max" );
+ inp.calendar( "option", {maxDate: null}).val( "01/04/2008" ).calendar( "option", {minDate: minDate, maxDate: maxDate});
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), minDate, "Min/max - setDate < min" );
+ inp.calendar( "option", {maxDate: null}).val( "06/04/2008" ).calendar( "option", {minDate: minDate, maxDate: maxDate});
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), new Date(2008, 6 - 1, 4), "Min/max - setDate > min, < max" );
+ inp.calendar( "option", {maxDate: null}).val( "01/04/2009" ).calendar( "option", {minDate: minDate, maxDate: maxDate});
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), maxDate, "Min/max - setDate > max" );
+
+ inp.calendar( "option", {yearRange: "-0:+1"}).val( "01/01/" + new Date().getFullYear());
+ ok(dp.find( ".ui-calendar-prev" ).hasClass( "ui-state-disabled" ), "Year Range Test - previous button disabled at 1/1/minYear" );
+ inp.calendar( "setDate", "12/30/" + new Date().getFullYear());
+ ok(dp.find( ".ui-calendar-next" ).hasClass( "ui-state-disabled" ), "Year Range Test - next button disabled at 12/30/maxYear" );
+
+ inp.calendar( "option", {
+ minDate: new Date(1900, 0, 1),
+ maxDate: "-6Y",
+ yearRange: "1900:-6"
+ }).val( "" );
+ ok(dp.find( ".ui-calendar-next" ).hasClass( "ui-state-disabled" ), "Year Range Test - next button disabled" );
+ ok(!dp.find( ".ui-calendar-prev" ).hasClass( "ui-state-disabled" ), "Year Range Test - prev button enabled" );
+
+ inp.calendar( "option", {
+ minDate: new Date(1900, 0, 1),
+ maxDate: "1/25/2007",
+ yearRange: "1900:2007"
+ }).val( "" );
+ ok(dp.find( ".ui-calendar-next" ).hasClass( "ui-state-disabled" ), "Year Range Test - next button disabled" );
+ ok(!dp.find( ".ui-calendar-prev" ).hasClass( "ui-state-disabled" ), "Year Range Test - prev button enabled" );
+});
+
+test( "setDate", function() {
+ expect( 24 );
+ var inl, alt, minDate, maxDate, dateAndTimeToSet, dateAndTimeClone,
+ inp = TestHelpers.calendar.init( "#inp" ),
+ date1 = new Date(2008, 6 - 1, 4),
+ date2 = new Date();
+ ok(inp.calendar( "getDate" ) == null, "Set date - default" );
+ inp.calendar( "setDate", date1);
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), date1, "Set date - 2008-06-04" );
+ date1 = new Date();
+ date1.setDate(date1.getDate() + 7);
+ inp.calendar( "setDate", +7);
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), date1, "Set date - +7" );
+ date2.setFullYear(date2.getFullYear() + 2);
+ inp.calendar( "setDate", "+2y" );
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), date2, "Set date - +2y" );
+ inp.calendar( "setDate", date1, date2);
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), date1, "Set date - two dates" );
+ inp.calendar( "setDate" );
+ ok(inp.calendar( "getDate" ) == null, "Set date - null" );
+ // Relative to current date
+ date1 = new Date();
+ date1.setDate(date1.getDate() + 7);
+ inp.calendar( "setDate", "c +7" );
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), date1, "Set date - c +7" );
+ date1.setDate(date1.getDate() + 7);
+ inp.calendar( "setDate", "c+7" );
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), date1, "Set date - c+7" );
+ date1.setDate(date1.getDate() - 21);
+ inp.calendar( "setDate", "c -3 w" );
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), date1, "Set date - c -3 w" );
+ // Inline
+ inl = TestHelpers.calendar.init( "#inl" );
+ date1 = new Date(2008, 6 - 1, 4);
+ date2 = new Date();
+ TestHelpers.calendar.equalsDate(inl.calendar( "getDate" ), date2, "Set date inline - default" );
+ inl.calendar( "setDate", date1);
+ TestHelpers.calendar.equalsDate(inl.calendar( "getDate" ), date1, "Set date inline - 2008-06-04" );
+ date1 = new Date();
+ date1.setDate(date1.getDate() + 7);
+ inl.calendar( "setDate", +7);
+ TestHelpers.calendar.equalsDate(inl.calendar( "getDate" ), date1, "Set date inline - +7" );
+ date2.setFullYear(date2.getFullYear() + 2);
+ inl.calendar( "setDate", "+2y" );
+ TestHelpers.calendar.equalsDate(inl.calendar( "getDate" ), date2, "Set date inline - +2y" );
+ inl.calendar( "setDate", date1, date2);
+ TestHelpers.calendar.equalsDate(inl.calendar( "getDate" ), date1, "Set date inline - two dates" );
+ inl.calendar( "setDate" );
+ ok(inl.calendar( "getDate" ) == null, "Set date inline - null" );
+ // Alternate field
+ alt = $( "#alt" );
+ inp.calendar( "option", {altField: "#alt", altFormat: "yy-mm-dd"});
+ date1 = new Date(2008, 6 - 1, 4);
+ inp.calendar( "setDate", date1);
+ equal(inp.val(), "06/04/2008", "Set date alternate - 06/04/2008" );
+ equal(alt.val(), "2008-06-04", "Set date alternate - 2008-06-04" );
+ // With minimum/maximum
+ inp = TestHelpers.calendar.init( "#inp" );
+ date1 = new Date(2008, 1 - 1, 4);
+ date2 = new Date(2008, 6 - 1, 4);
+ minDate = new Date(2008, 2 - 1, 29);
+ maxDate = new Date(2008, 3 - 1, 28);
+ inp.val( "" ).calendar( "option", {minDate: minDate}).calendar( "setDate", date2);
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), date2, "Set date min/max - setDate > min" );
+ inp.calendar( "setDate", date1);
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), minDate, "Set date min/max - setDate < min" );
+ inp.val( "" ).calendar( "option", {maxDate: maxDate, minDate: null}).calendar( "setDate", date1);
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), date1, "Set date min/max - setDate < max" );
+ inp.calendar( "setDate", date2);
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), maxDate, "Set date min/max - setDate > max" );
+ inp.val( "" ).calendar( "option", {minDate: minDate}).calendar( "setDate", date1);
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), minDate, "Set date min/max - setDate < min" );
+ inp.calendar( "setDate", date2);
+ TestHelpers.calendar.equalsDate(inp.calendar( "getDate" ), maxDate, "Set date min/max - setDate > max" );
+ dateAndTimeToSet = new Date(2008, 3 - 1, 28, 1, 11, 0);
+ dateAndTimeClone = new Date(2008, 3 - 1, 28, 1, 11, 0);
+ inp.calendar( "setDate", dateAndTimeToSet);
+ equal(dateAndTimeToSet.getTime(), dateAndTimeClone.getTime(), "Date object passed should not be changed by setDate" );
+});
+
+test( "altField", function() {
+ expect( 10 );
+ var inp = TestHelpers.calendar.init( "#inp" ),
+ alt = $( "#alt" );
+ // No alternate field set
+ alt.val( "" );
+ inp.val( "06/04/2008" ).calendar( "show" );
+ inp.simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ equal(inp.val(), "06/04/2008", "Alt field - dp - enter" );
+ equal(alt.val(), "", "Alt field - alt not set" );
+ // Alternate field set
+ alt.val( "" );
+ inp.calendar( "option", {altField: "#alt", altFormat: "yy-mm-dd"}).
+ val( "06/04/2008" ).calendar( "show" );
+ inp.simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ equal(inp.val(), "06/04/2008", "Alt field - dp - enter" );
+ equal(alt.val(), "2008-06-04", "Alt field - alt - enter" );
+ // Move from initial date
+ alt.val( "" );
+ inp.val( "06/04/2008" ).calendar( "show" );
+ inp.simulate( "keydown", {keyCode: $.ui.keyCode.PAGE_DOWN}).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ equal(inp.val(), "07/04/2008", "Alt field - dp - pgdn" );
+ equal(alt.val(), "2008-07-04", "Alt field - alt - pgdn" );
+ // Alternate field set - closed
+ alt.val( "" );
+ inp.val( "06/04/2008" ).calendar( "show" );
+ inp.simulate( "keydown", {keyCode: $.ui.keyCode.PAGE_DOWN}).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ESCAPE});
+ equal(inp.val(), "06/04/2008", "Alt field - dp - pgdn/esc" );
+ equal(alt.val(), "", "Alt field - alt - pgdn/esc" );
+ // Clear date and alternate
+ alt.val( "" );
+ inp.val( "06/04/2008" ).calendar( "show" );
+ inp.simulate( "keydown", {ctrlKey: true, keyCode: $.ui.keyCode.END});
+ equal(inp.val(), "", "Alt field - dp - ctrl+end" );
+ equal(alt.val(), "", "Alt field - alt - ctrl+end" );
+});
+
+test( "autoSize", function() {
+ expect( 15 );
+ var inp = TestHelpers.calendar.init( "#inp" );
+ equal(inp.prop( "size" ), 20, "Auto size - default" );
+ inp.calendar( "option", "autoSize", true);
+ equal(inp.prop( "size" ), 10, "Auto size - mm/dd/yy" );
+ inp.calendar( "option", "dateFormat", "m/d/yy" );
+ equal(inp.prop( "size" ), 10, "Auto size - m/d/yy" );
+ inp.calendar( "option", "dateFormat", "D M d yy" );
+ equal(inp.prop( "size" ), 15, "Auto size - D M d yy" );
+ inp.calendar( "option", "dateFormat", "DD, MM dd, yy" );
+ equal(inp.prop( "size" ), 29, "Auto size - DD, MM dd, yy" );
+
+ // French
+ inp.calendar( "option", $.extend({autoSize: false}, $.calendar.regional.fr));
+ equal(inp.prop( "size" ), 29, "Auto size - fr - default" );
+ inp.calendar( "option", "autoSize", true);
+ equal(inp.prop( "size" ), 10, "Auto size - fr - dd/mm/yy" );
+ inp.calendar( "option", "dateFormat", "m/d/yy" );
+ equal(inp.prop( "size" ), 10, "Auto size - fr - m/d/yy" );
+ inp.calendar( "option", "dateFormat", "D M d yy" );
+ equal(inp.prop( "size" ), 18, "Auto size - fr - D M d yy" );
+ inp.calendar( "option", "dateFormat", "DD, MM dd, yy" );
+ equal(inp.prop( "size" ), 28, "Auto size - fr - DD, MM dd, yy" );
+
+ // Hebrew
+ inp.calendar( "option", $.extend({autoSize: false}, $.calendar.regional.he));
+ equal(inp.prop( "size" ), 28, "Auto size - he - default" );
+ inp.calendar( "option", "autoSize", true);
+ equal(inp.prop( "size" ), 10, "Auto size - he - dd/mm/yy" );
+ inp.calendar( "option", "dateFormat", "m/d/yy" );
+ equal(inp.prop( "size" ), 10, "Auto size - he - m/d/yy" );
+ inp.calendar( "option", "dateFormat", "D M d yy" );
+ equal(inp.prop( "size" ), 16, "Auto size - he - D M d yy" );
+ inp.calendar( "option", "dateFormat", "DD, MM dd, yy" );
+ equal(inp.prop( "size" ), 23, "Auto size - he - DD, MM dd, yy" );
+});
+
+test( "daylightSaving", function() {
+ expect( 25 );
+ var inp = TestHelpers.calendar.init( "#inp" ),
+ dp = $( "#ui-calendar-div" );
+ ok(true, "Daylight saving - " + new Date());
+ // Australia, Sydney - AM change, southern hemisphere
+ inp.val( "04/01/2008" ).calendar( "show" );
+ $( ".ui-calendar-calendar td:eq(6) a", dp).simulate( "click" );
+ equal(inp.val(), "04/05/2008", "Daylight saving - Australia 04/05/2008" );
+ inp.val( "04/01/2008" ).calendar( "show" );
+ $( ".ui-calendar-calendar td:eq(7) a", dp).simulate( "click" );
+ equal(inp.val(), "04/06/2008", "Daylight saving - Australia 04/06/2008" );
+ inp.val( "04/01/2008" ).calendar( "show" );
+ $( ".ui-calendar-calendar td:eq(8) a", dp).simulate( "click" );
+ equal(inp.val(), "04/07/2008", "Daylight saving - Australia 04/07/2008" );
+ inp.val( "10/01/2008" ).calendar( "show" );
+ $( ".ui-calendar-calendar td:eq(6) a", dp).simulate( "click" );
+ equal(inp.val(), "10/04/2008", "Daylight saving - Australia 10/04/2008" );
+ inp.val( "10/01/2008" ).calendar( "show" );
+ $( ".ui-calendar-calendar td:eq(7) a", dp).simulate( "click" );
+ equal(inp.val(), "10/05/2008", "Daylight saving - Australia 10/05/2008" );
+ inp.val( "10/01/2008" ).calendar( "show" );
+ $( ".ui-calendar-calendar td:eq(8) a", dp).simulate( "click" );
+ equal(inp.val(), "10/06/2008", "Daylight saving - Australia 10/06/2008" );
+ // Brasil, Brasilia - midnight change, southern hemisphere
+ inp.val( "02/01/2008" ).calendar( "show" );
+ $( ".ui-calendar-calendar td:eq(20) a", dp).simulate( "click" );
+ equal(inp.val(), "02/16/2008", "Daylight saving - Brasil 02/16/2008" );
+ inp.val( "02/01/2008" ).calendar( "show" );
+ $( ".ui-calendar-calendar td:eq(21) a", dp).simulate( "click" );
+ equal(inp.val(), "02/17/2008", "Daylight saving - Brasil 02/17/2008" );
+ inp.val( "02/01/2008" ).calendar( "show" );
+ $( ".ui-calendar-calendar td:eq(22) a", dp).simulate( "click" );
+ equal(inp.val(), "02/18/2008", "Daylight saving - Brasil 02/18/2008" );
+ inp.val( "10/01/2008" ).calendar( "show" );
+ $( ".ui-calendar-calendar td:eq(13) a", dp).simulate( "click" );
+ equal(inp.val(), "10/11/2008", "Daylight saving - Brasil 10/11/2008" );
+ inp.val( "10/01/2008" ).calendar( "show" );
+ $( ".ui-calendar-calendar td:eq(14) a", dp).simulate( "click" );
+ equal(inp.val(), "10/12/2008", "Daylight saving - Brasil 10/12/2008" );
+ inp.val( "10/01/2008" ).calendar( "show" );
+ $( ".ui-calendar-calendar td:eq(15) a", dp).simulate( "click" );
+ equal(inp.val(), "10/13/2008", "Daylight saving - Brasil 10/13/2008" );
+ // Lebanon, Beirut - midnight change, northern hemisphere
+ inp.val( "03/01/2008" ).calendar( "show" );
+ $( ".ui-calendar-calendar td:eq(34) a", dp).simulate( "click" );
+ equal(inp.val(), "03/29/2008", "Daylight saving - Lebanon 03/29/2008" );
+ inp.val( "03/01/2008" ).calendar( "show" );
+ $( ".ui-calendar-calendar td:eq(35) a", dp).simulate( "click" );
+ equal(inp.val(), "03/30/2008", "Daylight saving - Lebanon 03/30/2008" );
+ inp.val( "03/01/2008" ).calendar( "show" );
+ $( ".ui-calendar-calendar td:eq(36) a", dp).simulate( "click" );
+ equal(inp.val(), "03/31/2008", "Daylight saving - Lebanon 03/31/2008" );
+ inp.val( "10/01/2008" ).calendar( "show" );
+ $( ".ui-calendar-calendar td:eq(27) a", dp).simulate( "click" );
+ equal(inp.val(), "10/25/2008", "Daylight saving - Lebanon 10/25/2008" );
+ inp.val( "10/01/2008" ).calendar( "show" );
+ $( ".ui-calendar-calendar td:eq(28) a", dp).simulate( "click" );
+ equal(inp.val(), "10/26/2008", "Daylight saving - Lebanon 10/26/2008" );
+ inp.val( "10/01/2008" ).calendar( "show" );
+ $( ".ui-calendar-calendar td:eq(29) a", dp).simulate( "click" );
+ equal(inp.val(), "10/27/2008", "Daylight saving - Lebanon 10/27/2008" );
+ // US, Eastern - AM change, northern hemisphere
+ inp.val( "03/01/2008" ).calendar( "show" );
+ $( ".ui-calendar-calendar td:eq(13) a", dp).simulate( "click" );
+ equal(inp.val(), "03/08/2008", "Daylight saving - US 03/08/2008" );
+ inp.val( "03/01/2008" ).calendar( "show" );
+ $( ".ui-calendar-calendar td:eq(14) a", dp).simulate( "click" );
+ equal(inp.val(), "03/09/2008", "Daylight saving - US 03/09/2008" );
+ inp.val( "03/01/2008" ).calendar( "show" );
+ $( ".ui-calendar-calendar td:eq(15) a", dp).simulate( "click" );
+ equal(inp.val(), "03/10/2008", "Daylight saving - US 03/10/2008" );
+ inp.val( "11/01/2008" ).calendar( "show" );
+ $( ".ui-calendar-calendar td:eq(6) a", dp).simulate( "click" );
+ equal(inp.val(), "11/01/2008", "Daylight saving - US 11/01/2008" );
+ inp.val( "11/01/2008" ).calendar( "show" );
+ $( ".ui-calendar-calendar td:eq(7) a", dp).simulate( "click" );
+ equal(inp.val(), "11/02/2008", "Daylight saving - US 11/02/2008" );
+ inp.val( "11/01/2008" ).calendar( "show" );
+ $( ".ui-calendar-calendar td:eq(8) a", dp).simulate( "click" );
+ equal(inp.val(), "11/03/2008", "Daylight saving - US 11/03/2008" );
+});
+
+var beforeShowThis = null,
+ beforeShowInput = null,
+ beforeShowInst = null,
+ beforeShowDayThis = null,
+ beforeShowDayOK = true;
+
+
+function beforeAll(input, inst) {
+ beforeShowThis = this;
+ beforeShowInput = input;
+ beforeShowInst = inst;
+ return {currentText: "Current"};
+}
+
+function beforeDay(date) {
+ beforeShowDayThis = this;
+ beforeShowDayOK &= (date > new Date(2008, 1 - 1, 26) &&
+ date < new Date(2008, 3 - 1, 6));
+ return [(date.getDate() % 2 === 0), (date.getDate() % 10 === 0 ? "day10" : "" ),
+ (date.getDate() % 3 === 0 ? "Divisble by 3" : "" )];
+}
+
+test( "callbacks", function() {
+ expect( 13 );
+ // Before show
+ var dp, day20, day21,
+ inp = TestHelpers.calendar.init( "#inp", {beforeShow: beforeAll}),
+ inst = $.data(inp[0], "calendar" );
+ equal($.calendar._get(inst, "currentText" ), "Today", "Before show - initial" );
+ inp.val( "02/04/2008" ).calendar( "show" );
+ equal($.calendar._get(inst, "currentText" ), "Current", "Before show - changed" );
+ ok(beforeShowThis.id === inp[0].id, "Before show - this OK" );
+ ok(beforeShowInput.id === inp[0].id, "Before show - input OK" );
+ deepEqual(beforeShowInst, inst, "Before show - inst OK" );
+ inp.calendar( "hide" ).calendar( "destroy" );
+ // Before show day
+ inp = TestHelpers.calendar.init( "#inp", {beforeShowDay: beforeDay});
+ dp = $( "#ui-calendar-div" );
+ inp.val( "02/04/2008" ).calendar( "show" );
+ ok(beforeShowDayThis.id === inp[0].id, "Before show day - this OK" );
+ ok(beforeShowDayOK, "Before show day - dates OK" );
+ day20 = dp.find( ".ui-calendar-calendar td:contains('20')" );
+ day21 = dp.find( ".ui-calendar-calendar td:contains('21')" );
+ ok(!day20.is( ".ui-calendar-unselectable" ), "Before show day - unselectable 20" );
+ ok(day21.is( ".ui-calendar-unselectable" ), "Before show day - unselectable 21" );
+ ok(day20.is( ".day10" ), "Before show day - CSS 20" );
+ ok(!day21.is( ".day10" ), "Before show day - CSS 21" );
+ ok(!day20.attr( "title" ), "Before show day - title 20" );
+ ok(day21.attr( "title" ) === "Divisble by 3", "Before show day - title 21" );
+ inp.calendar( "hide" ).calendar( "destroy" );
+});
+
+test( "beforeShowDay - tooltips with quotes", function() {
+ expect( 1 );
+ var inp, dp;
+ inp = TestHelpers.calendar.init( "#inp", {
+ beforeShowDay: function() {
+ return [ true, "", "'" ];
+ }
+ });
+ dp = $( "#ui-calendar-div" );
+
+ inp.calendar( "show" );
+ equal( dp.find( ".ui-calendar-calendar td:contains('9')" ).attr( "title" ), "'" );
+ inp.calendar( "hide" ).calendar( "destroy" );
+});
+
+test( "localisation", function() {
+ expect( 24 );
+ var dp, month, day, date,
+ inp = TestHelpers.calendar.init( "#inp", $.calendar.regional.fr);
+ inp.calendar( "option", {dateFormat: "DD, d MM yy", showButtonPanel:true, changeMonth:true, changeYear:true}).val( "" ).calendar( "show" );
+ dp = $( "#ui-calendar-div" );
+ equal($( ".ui-calendar-close", dp).text(), "Fermer", "Localisation - close" );
+ $( ".ui-calendar-close", dp).simulate( "mouseover" );
+ equal($( ".ui-calendar-prev", dp).text(), "Précédent", "Localisation - previous" );
+ equal($( ".ui-calendar-current", dp).text(), "Aujourd'hui", "Localisation - current" );
+ equal($( ".ui-calendar-next", dp).text(), "Suivant", "Localisation - next" );
+ month = 0;
+ $( ".ui-calendar-month option", dp).each(function() {
+ equal($(this).text(), $.calendar.regional.fr.monthNamesShort[month],
+ "Localisation - month " + month);
+ month++;
+ });
+ day = 1;
+ $( ".ui-calendar-calendar th", dp).each(function() {
+ equal($(this).text(), $.calendar.regional.fr.dayNamesMin[day],
+ "Localisation - day " + day);
+ day = (day + 1) % 7;
+ });
+ inp.simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ date = new Date();
+ equal(inp.val(), $.calendar.regional.fr.dayNames[date.getDay()] + ", " +
+ date.getDate() + " " + $.calendar.regional.fr.monthNames[date.getMonth()] +
+ " " + date.getFullYear(), "Localisation - formatting" );
+});
+
+test( "noWeekends", function() {
+ expect( 31 );
+ var i, date;
+ for (i = 1; i <= 31; i++) {
+ date = new Date(2001, 1 - 1, i);
+ deepEqual($.calendar.noWeekends(date), [(i + 1) % 7 >= 2, ""],
+ "No weekends " + date);
+ }
+});
+
+test( "iso8601Week", function() {
+ expect( 12 );
+ var date = new Date(2000, 12 - 1, 31);
+ equal($.calendar.iso8601Week(date), 52, "ISO 8601 week " + date);
+ date = new Date(2001, 1 - 1, 1);
+ equal($.calendar.iso8601Week(date), 1, "ISO 8601 week " + date);
+ date = new Date(2001, 1 - 1, 7);
+ equal($.calendar.iso8601Week(date), 1, "ISO 8601 week " + date);
+ date = new Date(2001, 1 - 1, 8);
+ equal($.calendar.iso8601Week(date), 2, "ISO 8601 week " + date);
+ date = new Date(2003, 12 - 1, 28);
+ equal($.calendar.iso8601Week(date), 52, "ISO 8601 week " + date);
+ date = new Date(2003, 12 - 1, 29);
+ equal($.calendar.iso8601Week(date), 1, "ISO 8601 week " + date);
+ date = new Date(2004, 1 - 1, 4);
+ equal($.calendar.iso8601Week(date), 1, "ISO 8601 week " + date);
+ date = new Date(2004, 1 - 1, 5);
+ equal($.calendar.iso8601Week(date), 2, "ISO 8601 week " + date);
+ date = new Date(2009, 12 - 1, 28);
+ equal($.calendar.iso8601Week(date), 53, "ISO 8601 week " + date);
+ date = new Date(2010, 1 - 1, 3);
+ equal($.calendar.iso8601Week(date), 53, "ISO 8601 week " + date);
+ date = new Date(2010, 1 - 1, 4);
+ equal($.calendar.iso8601Week(date), 1, "ISO 8601 week " + date);
+ date = new Date(2010, 1 - 1, 10);
+ equal($.calendar.iso8601Week(date), 1, "ISO 8601 week " + date);
+});
+
+test( "parseDate", function() {
+ expect( 26 );
+ TestHelpers.calendar.init( "#inp" );
+ var currentYear, gmtDate, fr, settings, zh;
+ ok($.calendar.parseDate( "d m y", "" ) == null, "Parse date empty" );
+ TestHelpers.calendar.equalsDate($.calendar.parseDate( "d m y", "3 2 01" ),
+ new Date(2001, 2 - 1, 3), "Parse date d m y" );
+ TestHelpers.calendar.equalsDate($.calendar.parseDate( "dd mm yy", "03 02 2001" ),
+ new Date(2001, 2 - 1, 3), "Parse date dd mm yy" );
+ TestHelpers.calendar.equalsDate($.calendar.parseDate( "d m y", "13 12 01" ),
+ new Date(2001, 12 - 1, 13), "Parse date d m y" );
+ TestHelpers.calendar.equalsDate($.calendar.parseDate( "dd mm yy", "13 12 2001" ),
+ new Date(2001, 12 - 1, 13), "Parse date dd mm yy" );
+ TestHelpers.calendar.equalsDate($.calendar.parseDate( "y-o", "01-34" ),
+ new Date(2001, 2 - 1, 3), "Parse date y-o" );
+ TestHelpers.calendar.equalsDate($.calendar.parseDate( "yy-oo", "2001-347" ),
+ new Date(2001, 12 - 1, 13), "Parse date yy-oo" );
+ TestHelpers.calendar.equalsDate($.calendar.parseDate( "oo yy", "348 2004" ),
+ new Date(2004, 12 - 1, 13), "Parse date oo yy" );
+ TestHelpers.calendar.equalsDate($.calendar.parseDate( "D d M y", "Sat 3 Feb 01" ),
+ new Date(2001, 2 - 1, 3), "Parse date D d M y" );
+ TestHelpers.calendar.equalsDate($.calendar.parseDate( "d MM DD yy", "3 February Saturday 2001" ),
+ new Date(2001, 2 - 1, 3), "Parse date dd MM DD yy" );
+ TestHelpers.calendar.equalsDate($.calendar.parseDate( "DD, MM d, yy", "Saturday, February 3, 2001" ),
+ new Date(2001, 2 - 1, 3), "Parse date DD, MM d, yy" );
+ TestHelpers.calendar.equalsDate($.calendar.parseDate( "'day' d 'of' MM (''DD''), yy",
+ "day 3 of February ('Saturday'), 2001" ), new Date(2001, 2 - 1, 3),
+ "Parse date 'day' d 'of' MM (''DD''), yy" );
+ currentYear = new Date().getFullYear();
+ TestHelpers.calendar.equalsDate($.calendar.parseDate( "y-m-d", (currentYear - 2000) + "-02-03" ),
+ new Date(currentYear, 2 - 1, 3), "Parse date y-m-d - default cutuff" );
+ TestHelpers.calendar.equalsDate($.calendar.parseDate( "y-m-d", (currentYear - 2000 + 10) + "-02-03" ),
+ new Date(currentYear+10, 2 - 1, 3), "Parse date y-m-d - default cutuff" );
+ TestHelpers.calendar.equalsDate($.calendar.parseDate( "y-m-d", (currentYear - 2000 + 11) + "-02-03" ),
+ new Date(currentYear-89, 2 - 1, 3), "Parse date y-m-d - default cutuff" );
+ TestHelpers.calendar.equalsDate($.calendar.parseDate( "y-m-d", "80-02-03", {shortYearCutoff: 80}),
+ new Date(2080, 2 - 1, 3), "Parse date y-m-d - cutoff 80" );
+ TestHelpers.calendar.equalsDate($.calendar.parseDate( "y-m-d", "81-02-03", {shortYearCutoff: 80}),
+ new Date(1981, 2 - 1, 3), "Parse date y-m-d - cutoff 80" );
+ TestHelpers.calendar.equalsDate($.calendar.parseDate( "y-m-d", (currentYear - 2000 + 60) + "-02-03", {shortYearCutoff: "+60"}),
+ new Date(currentYear + 60, 2 - 1, 3), "Parse date y-m-d - cutoff +60" );
+ TestHelpers.calendar.equalsDate($.calendar.parseDate( "y-m-d", (currentYear - 2000 + 61) + "-02-03", {shortYearCutoff: "+60"}),
+ new Date(currentYear - 39, 2 - 1, 3), "Parse date y-m-d - cutoff +60" );
+ gmtDate = new Date(2001, 2 - 1, 3);
+ gmtDate.setMinutes(gmtDate.getMinutes() - gmtDate.getTimezoneOffset());
+ TestHelpers.calendar.equalsDate($.calendar.parseDate( "@", "981158400000" ), gmtDate, "Parse date @" );
+ TestHelpers.calendar.equalsDate($.calendar.parseDate( "!", "631167552000000000" ), gmtDate, "Parse date !" );
+
+ fr = $.calendar.regional.fr;
+ settings = {dayNamesShort: fr.dayNamesShort, dayNames: fr.dayNames,
+ monthNamesShort: fr.monthNamesShort, monthNames: fr.monthNames};
+ TestHelpers.calendar.equalsDate($.calendar.parseDate( "D d M y", "Lun. 9 Avril 01", settings),
+ new Date(2001, 4 - 1, 9), "Parse date D M y with settings" );
+ TestHelpers.calendar.equalsDate($.calendar.parseDate( "d MM DD yy", "9 Avril Lundi 2001", settings),
+ new Date(2001, 4 - 1, 9), "Parse date d MM DD yy with settings" );
+ TestHelpers.calendar.equalsDate($.calendar.parseDate( "DD, MM d, yy", "Lundi, Avril 9, 2001", settings),
+ new Date(2001, 4 - 1, 9), "Parse date DD, MM d, yy with settings" );
+ TestHelpers.calendar.equalsDate($.calendar.parseDate( "'jour' d 'de' MM (''DD''), yy", "jour 9 de Avril ('Lundi'), 2001", settings),
+ new Date(2001, 4 - 1, 9), "Parse date 'jour' d 'de' MM (''DD''), yy with settings" );
+
+ zh = $.calendar.regional["zh-CN"];
+ TestHelpers.calendar.equalsDate($.calendar.parseDate( "yy M d", "2011 十一月 22", zh),
+ new Date(2011, 11 - 1, 22), "Parse date yy M d with zh-CN" );
+});
+
+test( "parseDateErrors", function() {
+ expect( 17 );
+ TestHelpers.calendar.init( "#inp" );
+ var fr, settings;
+ function expectError(expr, value, error) {
+ try {
+ expr();
+ ok(false, "Parsed error " + value);
+ }
+ catch (e) {
+ equal(e, error, "Parsed error " + value);
+ }
+ }
+ expectError(function() { $.calendar.parseDate(null, "Sat 2 01" ); },
+ "Sat 2 01", "Invalid arguments" );
+ expectError(function() { $.calendar.parseDate( "d m y", null); },
+ "null", "Invalid arguments" );
+ expectError(function() { $.calendar.parseDate( "d m y", "Sat 2 01" ); },
+ "Sat 2 01 - d m y", "Missing number at position 0" );
+ expectError(function() { $.calendar.parseDate( "dd mm yy", "Sat 2 01" ); },
+ "Sat 2 01 - dd mm yy", "Missing number at position 0" );
+ expectError(function() { $.calendar.parseDate( "d m y", "3 Feb 01" ); },
+ "3 Feb 01 - d m y", "Missing number at position 2" );
+ expectError(function() { $.calendar.parseDate( "dd mm yy", "3 Feb 01" ); },
+ "3 Feb 01 - dd mm yy", "Missing number at position 2" );
+ expectError(function() { $.calendar.parseDate( "d m y", "3 2 AD01" ); },
+ "3 2 AD01 - d m y", "Missing number at position 4" );
+ expectError(function() { $.calendar.parseDate( "d m yy", "3 2 AD01" ); },
+ "3 2 AD01 - dd mm yy", "Missing number at position 4" );
+ expectError(function() { $.calendar.parseDate( "y-o", "01-D01" ); },
+ "2001-D01 - y-o", "Missing number at position 3" );
+ expectError(function() { $.calendar.parseDate( "yy-oo", "2001-D01" ); },
+ "2001-D01 - yy-oo", "Missing number at position 5" );
+ expectError(function() { $.calendar.parseDate( "D d M y", "D7 3 Feb 01" ); },
+ "D7 3 Feb 01 - D d M y", "Unknown name at position 0" );
+ expectError(function() { $.calendar.parseDate( "D d M y", "Sat 3 M2 01" ); },
+ "Sat 3 M2 01 - D d M y", "Unknown name at position 6" );
+ expectError(function() { $.calendar.parseDate( "DD, MM d, yy", "Saturday- Feb 3, 2001" ); },
+ "Saturday- Feb 3, 2001 - DD, MM d, yy", "Unexpected literal at position 8" );
+ expectError(function() { $.calendar.parseDate( "'day' d 'of' MM (''DD''), yy",
+ "day 3 of February (\"Saturday\" ), 2001" ); },
+ "day 3 of Mon2 ('Day7'), 2001", "Unexpected literal at position 19" );
+ expectError(function() { $.calendar.parseDate( "d m y", "29 2 01" ); },
+ "29 2 01 - d m y", "Invalid date" );
+ fr = $.calendar.regional.fr;
+ settings = {dayNamesShort: fr.dayNamesShort, dayNames: fr.dayNames,
+ monthNamesShort: fr.monthNamesShort, monthNames: fr.monthNames};
+ expectError(function() { $.calendar.parseDate( "D d M y", "Mon 9 Avr 01", settings); },
+ "Mon 9 Avr 01 - D d M y", "Unknown name at position 0" );
+ expectError(function() { $.calendar.parseDate( "D d M y", "Lun. 9 Apr 01", settings); },
+ "Lun. 9 Apr 01 - D d M y", "Unknown name at position 7" );
+});
+
+test( "Ticket #7244: date parser does not fail when too many numbers are passed into the date function", function() {
+ expect( 4 );
+ var date;
+ try{
+ date = $.calendar.parseDate( "dd/mm/yy", "18/04/19881" );
+ ok(false, "Did not properly detect an invalid date" );
+ }catch(e){
+ ok( "invalid date detected" );
+ }
+
+ try {
+ date = $.calendar.parseDate( "dd/mm/yy", "18/04/1988 @ 2:43 pm" );
+ equal(date.getDate(), 18);
+ equal(date.getMonth(), 3);
+ equal(date.getFullYear(), 1988);
+ } catch(e) {
+ ok(false, "Did not properly parse date with extra text separated by whitespace" );
+ }
+});
+
+test( "formatDate", function() {
+ expect( 16 );
+ TestHelpers.calendar.init( "#inp" );
+ var gmtDate, fr, settings;
+ equal($.calendar.formatDate( "d m y", new Date(2001, 2 - 1, 3)),
+ "3 2 01", "Format date d m y" );
+ equal($.calendar.formatDate( "dd mm yy", new Date(2001, 2 - 1, 3)),
+ "03 02 2001", "Format date dd mm yy" );
+ equal($.calendar.formatDate( "d m y", new Date(2001, 12 - 1, 13)),
+ "13 12 01", "Format date d m y" );
+ equal($.calendar.formatDate( "dd mm yy", new Date(2001, 12 - 1, 13)),
+ "13 12 2001", "Format date dd mm yy" );
+ equal($.calendar.formatDate( "yy-o", new Date(2001, 2 - 1, 3)),
+ "2001-34", "Format date yy-o" );
+ equal($.calendar.formatDate( "yy-oo", new Date(2001, 2 - 1, 3)),
+ "2001-034", "Format date yy-oo" );
+ equal($.calendar.formatDate( "D M y", new Date(2001, 2 - 1, 3)),
+ "Sat Feb 01", "Format date D M y" );
+ equal($.calendar.formatDate( "DD MM yy", new Date(2001, 2 - 1, 3)),
+ "Saturday February 2001", "Format date DD MM yy" );
+ equal($.calendar.formatDate( "DD, MM d, yy", new Date(2001, 2 - 1, 3)),
+ "Saturday, February 3, 2001", "Format date DD, MM d, yy" );
+ equal($.calendar.formatDate( "'day' d 'of' MM (''DD''), yy",
+ new Date(2001, 2 - 1, 3)), "day 3 of February ('Saturday'), 2001",
+ "Format date 'day' d 'of' MM ('DD'), yy" );
+ gmtDate = new Date(2001, 2 - 1, 3);
+ gmtDate.setMinutes( gmtDate.getMinutes() - gmtDate.getTimezoneOffset() );
+ equal($.calendar.formatDate( "@", gmtDate), "981158400000", "Format date @" );
+ equal($.calendar.formatDate( "!", gmtDate), "631167552000000000", "Format date !" );
+ fr = $.calendar.regional.fr;
+ settings = {dayNamesShort: fr.dayNamesShort, dayNames: fr.dayNames,
+ monthNamesShort: fr.monthNamesShort, monthNames: fr.monthNames};
+ equal($.calendar.formatDate( "D M y", new Date(2001, 4 - 1, 9), settings),
+ "lun. avril 01", "Format date D M y with settings" );
+ equal($.calendar.formatDate( "DD MM yy", new Date(2001, 4 - 1, 9), settings),
+ "lundi avril 2001", "Format date DD MM yy with settings" );
+ equal($.calendar.formatDate( "DD, MM d, yy", new Date(2001, 4 - 1, 9), settings),
+ "lundi, avril 9, 2001", "Format date DD, MM d, yy with settings" );
+ equal($.calendar.formatDate( "'jour' d 'de' MM (''DD''), yy",
+ new Date(2001, 4 - 1, 9), settings), "jour 9 de avril ('lundi'), 2001",
+ "Format date 'jour' d 'de' MM (''DD''), yy with settings" );
+});
+
+// TODO: Fix this test so it isn't mysteriously flaky in Browserstack on certain OS/Browser combos
+// test( "Ticket 6827: formatDate day of year calculation is wrong during day lights savings time", function(){
+// expect( 1 );
+// var time = $.calendar.formatDate( "oo", new Date( "2010/03/30 12:00:00 CDT" ));
+// equal(time, "089" );
+// });
+
+test( "Ticket 7602: Stop calendar from appearing with beforeShow event handler", function() {
+ expect( 3 );
+
+ var inp, dp;
+
+ inp = TestHelpers.calendar.init( "#inp", {
+ beforeShow: function() {
+ }
+ });
+ dp = $( "#ui-calendar-div" );
+ inp.calendar( "show" );
+ equal( dp.css( "display" ), "block", "beforeShow returns nothing" );
+ inp.calendar( "hide" ).calendar( "destroy" );
+
+ inp = TestHelpers.calendar.init( "#inp", {
+ beforeShow: function() {
+ return true;
+ }
+ });
+ dp = $( "#ui-calendar-div" );
+ inp.calendar( "show" );
+ equal( dp.css( "display" ), "block", "beforeShow returns true" );
+ inp.calendar( "hide" );
+ inp.calendar( "destroy" );
+
+ inp = TestHelpers.calendar.init( "#inp", {
+ beforeShow: function() {
+ return false;
+ }
+ });
+ dp = $( "#ui-calendar-div" );
+ inp.calendar( "show" );
+ equal( dp.css( "display" ), "none", "beforeShow returns false" );
+ inp.calendar( "destroy" );
+});
+*/
+
+})(jQuery);
diff --git a/tests/unit/calendar/calendar_test_helpers.js b/tests/unit/calendar/calendar_test_helpers.js
new file mode 100644
index 00000000000..032a2227ac6
--- /dev/null
+++ b/tests/unit/calendar/calendar_test_helpers.js
@@ -0,0 +1,24 @@
+TestHelpers.calendar = {
+ addMonths: function( date, offset ) {
+ var maxDay = 32 - new Date( date.getFullYear(), date.getMonth() + offset, 32 ).getDate();
+ date.setDate( Math.min( date.getDate(), maxDay ) );
+ date.setMonth( date.getMonth() + offset );
+ return date;
+ },
+ equalsDate: function( d1, d2, message ) {
+ if ( !d1 || !d2 ) {
+ ok( false, message + " - missing date" );
+ return;
+ }
+ d1 = new Date( d1.getFullYear(), d1.getMonth(), d1.getDate() );
+ d2 = new Date( d2.getFullYear(), d2.getMonth(), d2.getDate() );
+ equal( d1.toString(), d2.toString(), message );
+ },
+ focusGrid: function( element ) {
+ element.find( ":tabbable" ).last().simulate( "focus" );
+ $( ":focus" ).simulate( "keydown", { keyCode: $.ui.keyCode.TAB } );
+ $( ":focus" ).simulate( "keydown", { keyCode: $.ui.keyCode.TAB } );
+
+ return $( ":focus" );
+ }
+};
\ No newline at end of file
diff --git a/tests/unit/date/all.html b/tests/unit/date/all.html
new file mode 100644
index 00000000000..8f31592f14b
--- /dev/null
+++ b/tests/unit/date/all.html
@@ -0,0 +1,30 @@
+
+
+
+
+
jQuery UI Date Test Suite
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/unit/date/date.html b/tests/unit/date/date.html
new file mode 100644
index 00000000000..b2dd2c41e22
--- /dev/null
+++ b/tests/unit/date/date.html
@@ -0,0 +1,40 @@
+
+
+
+
+
jQuery UI Date Test Suite
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/unit/date/date_core.js b/tests/unit/date/date_core.js
new file mode 100644
index 00000000000..65665431c32
--- /dev/null
+++ b/tests/unit/date/date_core.js
@@ -0,0 +1,189 @@
+module( "date: core" );
+
+test( "Instantiation", function() {
+ expect( 2 );
+ ok( new $.date() instanceof $.date, "constructor function" );
+ ok( $.date() instanceof $.date, "instantiation without new" );
+});
+
+test( "Check Sets and Gets", 6, function() {
+ var date = $.date();
+ equal( date.setYear( 2012 ).year(), 2012, "Set year and retrieve" );
+ equal( date.setMonth( 9 ).month(), 9, "Set month and retrieve" );
+ equal( date.setDay( 15 ).day(), 15, "Set day and retrieve" );
+ equal( date.setFullDate( 2012, 9, 15 ).year(), 2012, "Set full date and retrieve year" );
+ equal( date.month(), 9, "Set full date and retrieve month" );
+ equal( date.day(), 15, "Set full date and retrieve day" );
+});
+
+test( "Date Adjustments - Normal Use Cases", 10, function() {
+ var date = $.date();
+
+ // Use October 15, 2012
+ date.setFullDate( 2012, 9, 15 );
+ equal( date.adjust( "D", 1 ).day(), 16, "Add 1 day" );
+ equal( date.adjust( "D", -1 ).day(), 15, "Subtract 1 day" );
+ equal( date.adjust( "M", 1 ).month(), 10, "Add 1 month" );
+ equal( date.adjust( "M", -1 ).month(), 9, "Subtract 1 month" );
+ equal( date.adjust( "Y", 1 ).year(), 2013, "Add 1 year" );
+ equal( date.adjust( "Y", -1 ).year(), 2012, "Subtract 1 year" );
+
+ // Check changing one value impact another. Ex: Day impacts month
+ // Use April 30th 2012
+ date.setFullDate( 2012, 3, 30 );
+ equal( date.adjust( "D", 1 ).month(), 4, "Add 1 day to change month from April to May" );
+ equal( date.adjust( "D", -1 ).month(), 3, "Subtract 1 day to change month from May to April" );
+
+ // Use December 31st 2012
+ date.setFullDate( 2012, 11, 31 );
+ equal( date.adjust( "D", 1 ).year(), 2013, "Add 1 day to change year from 2012 to 2013" );
+ equal( date.adjust( "D", -1 ).year(), 2012,
+ "Subtract 1 day to change month from 2013 to 2012" );
+});
+
+test( "Date Adjustments - Month Overflow Edge Cases", 2, function() {
+ var date = $.date();
+
+ // Use May 31 2012
+ date.setFullDate( 2012, 4, 31 );
+ equal( date.adjust( "M", 1 ).day(), 30,
+ "Add 1 month from May to June sets days to 30, last day in June (prevent Overflow)" );
+ equal( date.adjust( "M", -1 ).day(), 30,
+ "Subtract 1 month from June to May sets days to 30 in May" );
+});
+
+test( "Date Adjustments - Leap Year Edge Cases", 1, function() {
+ var date = $.date();
+
+ // Use February 29 2012 a Leap year
+ date.setFullDate( 2012, 1, 29 );
+ equal( date.adjust( "Y", 1 ).day(), 28,
+ "Feb 29 2012, add a year to convert to Feb 28, 2013" );
+});
+
+test( "List days of Week", 2, function() {
+ var date = $.date(),
+ offset0 = [
+ { "fullname": "Sunday", "shortname": "Su" },
+ { "fullname": "Monday", "shortname": "Mo" },
+ { "fullname": "Tuesday", "shortname": "Tu" },
+ { "fullname": "Wednesday", "shortname": "We" },
+ { "fullname": "Thursday", "shortname": "Th" },
+ { "fullname": "Friday", "shortname": "Fr" },
+ { "fullname": "Saturday", "shortname": "Sa" }
+ ],
+ offset1 = [
+ { "fullname": "Montag", "shortname": "Mo." },
+ { "fullname": "Dienstag", "shortname": "Di." },
+ { "fullname": "Mittwoch", "shortname": "Mi." },
+ { "fullname": "Donnerstag", "shortname": "Do." },
+ { "fullname": "Freitag", "shortname": "Fr." },
+ { "fullname": "Samstag", "shortname": "Sa." },
+ { "fullname": "Sonntag", "shortname": "So." }
+ ];
+
+ deepEqual( date.weekdays(), offset0, "Get weekdays with start of day on 0 (English)" );
+ Globalize.locale( "de-DE" );
+ deepEqual( date.weekdays(), offset1, "Get weekdays with start of day on 1 (Germany)" );
+
+ // Revert Globalize changes back to English
+ Globalize.locale( "en" );
+});
+
+test( "Leap Year Check", 8, function() {
+ var date = $.date();
+ ok( date.setYear( 2008 ).isLeapYear(), "2008 is a Leap Year" );
+ ok( !date.setYear( 2009 ).isLeapYear(), "2009 is not a Leap Year" );
+ ok( !date.setYear( 2010 ).isLeapYear(), "2010 is not a Leap Year" );
+ ok( !date.setYear( 2011 ).isLeapYear(), "2011 is not a Leap Year" );
+ ok( date.isLeapYear( 2012 ), "2012 is a Leap Year" );
+ ok( !date.isLeapYear( 2013 ), "2013 is not a Leap Year" );
+ ok( !date.isLeapYear( 2014 ), "2014 is not a Leap year" );
+ ok( !date.isLeapYear( 2015 ), "2015 is not a Leap year" );
+});
+
+test( "Days in Month", 3, function() {
+ var date = $.date();
+ date.setFullDate( 2012, 1, 1 );
+ equal( date.daysInMonth(), 29, "Leap Year implicit check for 29 days" );
+ equal( date.daysInMonth( 2012, 1 ), 29, "Leap Year explicit check for 29 days" );
+ equal( date.daysInMonth( 2011, 3 ), 30, "April has 30 days" );
+});
+
+test( "Month Name", 2, function() {
+ var date = $.date();
+ equal( date.setMonth( 3 ).monthName(), "April", "Month name return April (English)" );
+ Globalize.locale( "de-DE" );
+ equal( date.setMonth( 2 ).monthName(), "März", "Month name return March (German)" );
+ Globalize.locale( "en" );
+});
+
+test( "Clone", 2, function() {
+ var date = $.date(),
+ date2 = date.clone();
+ ok( date2, "Created cloned object" );
+ notEqual( date.adjust( "Y", 1 ).year(), date2.year(), "Object manipulated independently" );
+});
+
+test( "Days", 1, function() {
+ //TODO needs work
+ var date = $.date();
+ date.eachDay = function( day ) {
+ if ( day.lead && day.date > 20 ) {
+ day.selectable = false;
+ day.render = true;
+ day.title = "These are the days of last month";
+ day.extraClasses = "ui-state-disabled";
+ }
+ if ( day.lead && day.date < 3 ) {
+ day.selectable = true;
+ day.render = true;
+ day.extraClasses = "ui-state-disabled";
+ }
+ if ( day.date === 1 ) {
+ day.extraClasses = "ui-state-error";
+ day.title = "Something bad explaining the error highlight";
+ }
+ if ( day.today ) {
+ day.title = "A good day!";
+ }
+ };
+ ok( date.days(), "Date days() returns");
+});
+
+test( "Months", 5, function(){
+ var date = $.date(),
+ firstMonth = date.months( 1 )[ 0 ],
+ lastMonth = date.months( 1 )[ 1 ];
+
+ ok( firstMonth.first );
+ ok( !lastMonth.first );
+ ok( lastMonth.last );
+ ok( !lastMonth.first );
+
+ ok( firstMonth.month() === lastMonth.month() - 1 );
+});
+
+test( "Equal", 4, function() {
+ var date = $.date();
+ date.setFullDate( 2012, 9, 16 );
+ ok( date.equal( new Date( 2012, 9, 16 ) ), "Does date equal provide date" );
+ ok( !date.equal( new Date( 2011, 9, 16 ) ), "Does date year not equal provide date" );
+ ok( !date.equal( new Date( 2012, 8, 16 ) ), "Does date month not equal provide date" );
+ ok( !date.equal( new Date( 2012, 9, 15 ) ), "Does date day not equal provide date" );
+});
+
+test( "Date", 1, function() {
+ var date = $.date();
+ ok( date.date() instanceof Date, "Date returned" );
+});
+
+test( "Format", 4, function() {
+ var date = $.date();
+ date.setFullDate( 2012, 9, 16 );
+ equal( date.format({ date: "short" }), "10/16/12", "Checking default US format" );
+ equal( date.format({ pattern: "yyyy/MM/dd" }), "2012/10/16", "Checking yyyy/MM/dd format" );
+ equal( date.format({ pattern: "yy/dd/MM" }), "12/16/10", "Checking yy/dd/MM format" );
+ equal( date.format({ pattern: "MMMM dd, yyyy" }), "October 16, 2012",
+ "Checking MMMM dd, yyyy format" );
+});
diff --git a/tests/unit/datepicker/datepicker.html b/tests/unit/datepicker/datepicker.html
index 4d2b3fd5b27..7e12c04bcb2 100644
--- a/tests/unit/datepicker/datepicker.html
+++ b/tests/unit/datepicker/datepicker.html
@@ -5,19 +5,23 @@
jQuery UI Datepicker Test Suite
+
+
+
@@ -36,8 +40,8 @@
diff --git a/tests/unit/datepicker/datepicker_common.js b/tests/unit/datepicker/datepicker_common.js
index 1eecc85cb50..fb4f8d340fd 100644
--- a/tests/unit/datepicker/datepicker_common.js
+++ b/tests/unit/datepicker/datepicker_common.js
@@ -1,7 +1,26 @@
-/*
TestHelpers.commonWidgetTests( "datepicker", {
defaults: {
- disabled: false
+ appendTo: null,
+ buttons: [],
+ dateFormat: { date: "short" },
+ disabled: false,
+ eachDay: $.noop,
+ max: null,
+ min: null,
+ numberOfMonths: 1,
+ position: {
+ my: "left top",
+ at: "left bottom"
+ },
+ showWeek: false,
+ show: true,
+ hide: true,
+
+ // callbacks
+ beforeOpen: null,
+ close: null,
+ create: null,
+ open: null,
+ select: null
}
});
-*/
diff --git a/tests/unit/datepicker/datepicker_core.js b/tests/unit/datepicker/datepicker_core.js
index 65b07e2f6ca..71ac0d9cf73 100644
--- a/tests/unit/datepicker/datepicker_core.js
+++ b/tests/unit/datepicker/datepicker_core.js
@@ -1,528 +1,372 @@
-/*
- * datepicker_core.js
- */
+(function( $ ) {
-(function($) {
-
-module( "datepicker: core", {
- setup: function() {
- $( "body" ).focus();
- }
-});
+module( "datepicker: core" );
TestHelpers.testJshint( "datepicker" );
-test("initialization - Reinitialization after body had been emptied.", function() {
- expect( 1 );
- var bodyContent = $("body").children(), inp = $("#inp");
- $("#inp").datepicker();
- $("body").empty().append(inp);
- $("#inp").datepicker();
- ok( $("#"+$.datepicker._mainDivId).length===1, "Datepicker container added" );
- $("body").empty().append(bodyContent); // Returning to initial state for later tests
-});
+test( "input's value determines starting date", function() {
+ expect( 3 );
-test( "widget method - empty collection", function() {
- expect( 1 );
- $( "#nonExist" ).datepicker(); // should create nothing
- ok( !$( "#ui-datepicker-div" ).length, "Non init on empty collection" );
-});
+ var input = $( "#datepicker" ).val( "1/1/14" ).datepicker(),
+ picker = input.datepicker( "widget" );
-test("widget method", function() {
- expect( 1 );
- var actual = $("#inp").datepicker().datepicker("widget")[0];
- deepEqual($("body > #ui-datepicker-div:last-child")[0], actual);
+ input.datepicker( "open" );
+
+ equal( picker.find( ".ui-calendar-month" ).html(), "January", "correct month displayed" );
+ equal( picker.find( ".ui-calendar-year" ).html(), "2014", "correct year displayed" );
+ equal( picker.find( ".ui-state-active" ).html(), "1", "correct day highlighted" );
+
+ input.val( "" ).datepicker( "destroy" );
});
asyncTest( "baseStructure", function() {
- expect( 58 );
- var header, title, table, thead, week, panel, inl, child,
+ expect( 15 );
+
+ var header, title, table, child, buttonpane,
inp = TestHelpers.datepicker.initNewInput(),
- dp = $( "#ui-datepicker-div" );
+ dp = inp.datepicker( "widget" );
function step1() {
- TestHelpers.datepicker.onFocus( inp, function() {
+ inp.focus();
+
+ setTimeout(function() {
ok( dp.is( ":visible" ), "Structure - datepicker visible" );
- ok( !dp.is( ".ui-datepicker-rtl" ), "Structure - not right-to-left" );
- ok( !dp.is( ".ui-datepicker-multi" ), "Structure - not multi-month" );
- equal( dp.children().length, 2, "Structure - child count" );
+ equal( dp.children().length, 2, "Structure - child count (header, calendar)" );
header = dp.children( ":first" );
- ok( header.is( "div.ui-datepicker-header" ), "Structure - header division" );
+ ok( header.is( "div.ui-calendar-header" ), "Structure - header division" );
equal( header.children().length, 3, "Structure - header child count" );
- ok( header.children( ":first" ).is( "a.ui-datepicker-prev" ) && header.children( ":first" ).html() !== "", "Structure - prev link" );
- ok( header.children( ":eq(1)" ).is( "a.ui-datepicker-next" ) && header.children( ":eq(1)" ).html() !== "", "Structure - next link" );
- title = header.children( ":last" );
- ok( title.is( "div.ui-datepicker-title" ) && title.html() !== "","Structure - title division" );
+ title = header.children( ":last" ).children( ":first" );
equal( title.children().length, 2, "Structure - title child count" );
- ok( title.children( ":first" ).is( "span.ui-datepicker-month" ) && title.children( ":first" ).text() !== "", "Structure - month text" );
- ok( title.children( ":last" ).is( "span.ui-datepicker-year" ) && title.children( ":last" ).text() !== "", "Structure - year text" );
table = dp.children( ":eq(1)" );
- ok( table.is( "table.ui-datepicker-calendar" ), "Structure - month table" );
+ ok( table.is( "table.ui-calendar-calendar" ), "Structure - month table" );
ok( table.children( ":first" ).is( "thead" ), "Structure - month table thead" );
-
- thead = table.children( ":first" ).children( ":first" );
- ok( thead.is( "tr" ), "Structure - month table title row" );
- equal( thead.find( "th" ).length, 7, "Structure - month table title cells" );
ok( table.children( ":eq(1)" ).is( "tbody" ), "Structure - month table body" );
- ok( table.children( ":eq(1)" ).children( "tr" ).length >= 4, "Structure - month table week count" );
-
- week = table.children( ":eq(1)" ).children( ":first" );
- ok( week.is( "tr" ), "Structure - month table week row" );
- equal( week.children().length, 7, "Structure - week child count" );
- ok( week.children( ":first" ).is( "td.ui-datepicker-week-end" ), "Structure - month table first day cell" );
- ok( week.children( ":last" ).is( "td.ui-datepicker-week-end" ), "Structure - month table second day cell" );
- inp.datepicker( "hide" ).datepicker( "destroy" );
+ inp.datepicker( "close" );
step2();
- });
+ }, 50 );
}
function step2() {
- // Editable month/year and button panel
- inp = TestHelpers.datepicker.initNewInput({
- changeMonth: true,
- changeYear: true,
- showButtonPanel: true
+ inp.datepicker( "option", "buttons", {
+ "test": function() {},
+ "test button": function() {}
});
- TestHelpers.datepicker.onFocus( inp, function() {
- title = dp.find( "div.ui-datepicker-title" );
- ok( title.children( ":first" ).is( "select.ui-datepicker-month" ), "Structure - month selector" );
- ok( title.children( ":last" ).is( "select.ui-datepicker-year" ), "Structure - year selector" );
-
- panel = dp.children( ":last" );
- ok( panel.is( "div.ui-datepicker-buttonpane" ), "Structure - button panel division" );
- equal( panel.children().length, 2, "Structure - button panel child count" );
- ok( panel.children( ":first" ).is( "button.ui-datepicker-current" ), "Structure - today button" );
- ok( panel.children( ":last" ).is( "button.ui-datepicker-close" ), "Structure - close button" );
-
- inp.datepicker( "hide" ).datepicker( "destroy" );
+ inp.focus();
+
+ setTimeout(function() {
+ equal( dp.children().length, 3, "Structure buttons - child count (header, calendar, buttonpane)" );
+
+ buttonpane = dp.children( ".ui-calendar-buttonpane" );
+ equal( buttonpane.children( "div.ui-calendar-buttonset" ).length, 1, "Structure buttons - buttonset" );
+ equal( buttonpane.find( "button.ui-button:first" ).text(), "test", "Structure buttons - buttonset" );
+ equal( buttonpane.find( "button.ui-button:eq(1)" ).text(), "test button", "Structure buttons - buttonset" );
+
+ inp.datepicker( "close" ).datepicker( "destroy" );
step3();
- });
+ }, 50 );
}
function step3() {
// Multi-month 2
- inp = TestHelpers.datepicker.initNewInput({ numberOfMonths: 2 });
- TestHelpers.datepicker.onFocus( inp, function() {
- ok( dp.is( ".ui-datepicker-multi" ), "Structure multi [2] - multi-month" );
+ inp = TestHelpers.datepicker.initNewInput({ numberOfMonths: 2 } );
+ dp = inp.datepicker( "widget" );
+ inp.focus();
+ setTimeout(function() {
+ ok( dp.is( ".ui-calendar-multi" ), "Structure multi [2] - multi-month" );
equal( dp.children().length, 3, "Structure multi [2] - child count" );
- child = dp.children( ":first" );
- ok( child.is( "div.ui-datepicker-group" ) && child.is( "div.ui-datepicker-group-first" ), "Structure multi [2] - first month division" );
-
- child = dp.children( ":eq(1)" );
- ok( child.is( "div.ui-datepicker-group" ) && child.is( "div.ui-datepicker-group-last" ), "Structure multi [2] - second month division" );
-
child = dp.children( ":eq(2)" );
- ok( child.is( "div.ui-datepicker-row-break" ), "Structure multi [2] - row break" );
- ok( dp.is( ".ui-datepicker-multi-2" ), "Structure multi [2] - multi-2" );
+ ok( child.is( "div.ui-calendar-row-break" ), "Structure multi [2] - row break" );
- inp.datepicker( "hide" ).datepicker( "destroy" );
- step4();
- });
- }
-
- function step4() {
- // Multi-month 3
- inp = TestHelpers.datepicker.initNewInput({ numberOfMonths: 3 });
- TestHelpers.datepicker.onFocus( inp, function() {
- ok( dp.is( ".ui-datepicker-multi-3" ), "Structure multi [3] - multi-3" );
- ok( !dp.is( ".ui-datepicker-multi-2" ), "Structure multi [3] - Trac #6704" );
-
- inp.datepicker( "hide" ).datepicker( "destroy" );
- step5();
+ inp.datepicker( "close" ).datepicker( "destroy" );
});
+ start();
}
- function step5() {
- // Multi-month [2, 2]
- inp = TestHelpers.datepicker.initNewInput({ numberOfMonths: [ 2, 2 ] });
- TestHelpers.datepicker.onFocus( inp, function() {
- ok( dp.is( ".ui-datepicker-multi" ), "Structure multi - multi-month" );
- equal( dp.children().length, 6, "Structure multi [2,2] - child count" );
-
- child = dp.children( ":first" );
- ok( child.is( "div.ui-datepicker-group" ) && child.is( "div.ui-datepicker-group-first" ), "Structure multi [2,2] - first month division" );
-
- child = dp.children( ":eq(1)" );
- ok( child.is( "div.ui-datepicker-group" ) && child.is( "div.ui-datepicker-group-last" ), "Structure multi [2,2] - second month division" );
-
- child = dp.children( ":eq(2)" );
- ok( child.is( "div.ui-datepicker-row-break" ), "Structure multi [2,2] - row break" );
-
- child = dp.children( ":eq(3)" );
- ok( child.is( "div.ui-datepicker-group" ) && child.is( "div.ui-datepicker-group-first" ), "Structure multi [2,2] - third month division" );
-
- child = dp.children( ":eq(4)" );
- ok( child.is( "div.ui-datepicker-group" ) && child.is( "div.ui-datepicker-group-last" ), "Structure multi [2,2] - fourth month division" );
-
- child = dp.children( ":eq(5)" );
- ok( child.is( "div.ui-datepicker-row-break" ), "Structure multi [2,2] - row break" );
-
- inp.datepicker( "hide" ).datepicker( "destroy" );
-
- // Inline
- inl = TestHelpers.datepicker.init( "#inl" );
- dp = inl.children();
-
- ok( dp.is( ".ui-datepicker-inline" ), "Structure inline - main div" );
- ok( !dp.is( ".ui-datepicker-rtl" ), "Structure inline - not right-to-left" );
- ok( !dp.is( ".ui-datepicker-multi" ), "Structure inline - not multi-month" );
- equal( dp.children().length, 2, "Structure inline - child count" );
-
- header = dp.children( ":first" );
- ok( header.is( "div.ui-datepicker-header" ), "Structure inline - header division" );
- equal( header.children().length, 3, "Structure inline - header child count" );
+ step1();
+});
- table = dp.children( ":eq(1)" );
- ok( table.is( "table.ui-datepicker-calendar" ), "Structure inline - month table" );
- ok( table.children( ":first" ).is( "thead" ), "Structure inline - month table thead" );
- ok( table.children( ":eq(1)" ).is( "tbody" ), "Structure inline - month table body" );
+asyncTest( "Keyboard handling: input", function() {
+ expect( 10 );
+ var input = $( "#datepicker" ).datepicker(),
+ picker, instance;
- inl.datepicker( "destroy" );
+ function step1() {
+ TestHelpers.datepicker.init( input );
+ picker = input.datepicker( "widget" );
- // Inline multi-month
- inl = TestHelpers.datepicker.init( "#inl", { numberOfMonths: 2 } );
- dp = inl.children();
+ ok( !picker.is( ":visible" ), "datepicker closed" );
- ok( dp.is( ".ui-datepicker-inline" ) && dp.is( ".ui-datepicker-multi" ), "Structure inline multi - main div" );
- equal( dp.children().length, 3, "Structure inline multi - child count" );
+ input.val( "" ).simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } );
+ setTimeout(function() {
+ ok( picker.is( ":visible" ), "Keystroke down opens datepicker" );
+ input.datepicker( "destroy" );
+ step2();
+ }, 100 );
+ }
- child = dp.children( ":first" );
- ok( child.is( "div.ui-datepicker-group" ) && child.is( "div.ui-datepicker-group-first" ), "Structure inline multi - first month division" );
+ function step2() {
+ TestHelpers.datepicker.init( input );
+ picker = input.datepicker( "widget" );
- child = dp.children( ":eq(1)" );
- ok( child.is( "div.ui-datepicker-group" ) && child.is( "div.ui-datepicker-group-last" ), "Structure inline multi - second month division" );
+ ok( !picker.is( ":visible" ), "datepicker closed" );
- child = dp.children( ":eq(2)" );
- ok( child.is( "div.ui-datepicker-row-break" ), "Structure inline multi - row break" );
+ input.val( "" ).simulate( "keydown", { keyCode: $.ui.keyCode.UP } );
+ setTimeout(function() {
+ ok( picker.is( ":visible" ), "Keystroke up opens datepicker" );
+ input.datepicker( "destroy" );
+ step3();
+ }, 100 );
+ }
- inl.datepicker( "destroy" );
- start();
- });
+ function step3() {
+ TestHelpers.datepicker.init( input );
+ instance = input.datepicker( "instance" );
+
+ // Enter = Select preset date
+ input
+ .val( "1/1/14" )
+ .datepicker( "refresh" )
+ .datepicker( "open" )
+ .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } );
+ TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), new Date( 2014, 0, 1 ),
+ "Keystroke enter - preset" );
+
+ input
+ .val( "" )
+ .datepicker( "open" );
+ ok( instance.isOpen, "datepicker is open before escape" );
+
+ input.simulate( "keydown", { keyCode: $.ui.keyCode.ESCAPE } );
+ ok( !instance.isOpen, "escape closes the datepicker" );
+
+ input
+ .val( "1/1/14" )
+ .datepicker( "open" )
+ .simulate( "keydown", { keyCode: $.ui.keyCode.ESCAPE } );
+ TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), new Date( 2014, 0, 1 ),
+ "Keystroke esc - preset" );
+
+ input
+ .val( "1/1/14" )
+ .datepicker( "open" )
+ .simulate( "keydown", { ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP } )
+ .simulate( "keydown", { keyCode: $.ui.keyCode.ESCAPE } );
+ TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), new Date( 2014, 0, 1 ),
+ "Keystroke esc - abandoned" );
+
+ input
+ .val( "1/2/14" )
+ .simulate( "keyup" );
+ TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), new Date( 2014, 0, 2 ),
+ "Picker updated as user types into input" );
+
+ input.datepicker( "destroy" );
+ start();
}
step1();
});
-asyncTest( "customStructure", function() {
- expect( 20 );
- var header, panel, title, thead,
- inp = TestHelpers.datepicker.initNewInput( $.datepicker.regional.he ),
- dp = $( "#ui-datepicker-div" );
-
- function step1() {
- inp.datepicker( "option", "showButtonPanel", true );
+asyncTest( "keyboard handling: calendar", function() {
+ expect( 7 );
- TestHelpers.datepicker.onFocus( inp, function() {
- ok( dp.is( ".ui-datepicker-rtl" ), "Structure RTL - right-to-left" );
+ var input = $( "#datepicker" );
- header = dp.children( ":first" );
- ok( header.is( "div.ui-datepicker-header" ), "Structure RTL - header division" );
- equal( header.children().length, 3, "Structure RTL - header child count" );
- ok( header.children( ":first" ).is( "a.ui-datepicker-next" ), "Structure RTL - prev link" );
- ok( header.children( ":eq(1)" ).is( "a.ui-datepicker-prev" ), "Structure RTL - next link" );
-
- panel = dp.children( ":last" );
- ok( panel.is( "div.ui-datepicker-buttonpane" ), "Structure RTL - button division" );
- equal( panel.children().length, 2, "Structure RTL - button panel child count" );
- ok( panel.children( ":first" ).is( "button.ui-datepicker-close" ), "Structure RTL - close button" );
- ok( panel.children( ":last" ).is( "button.ui-datepicker-current" ), "Structure RTL - today button" );
-
- inp.datepicker( "hide" ).datepicker( "destroy" );
- step2();
- });
+ function step1() {
+ input.val( "1/1/14" );
+ TestHelpers.datepicker.init( input );
+ input.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } );
+
+ setTimeout(function() {
+ $( ":focus" ).simulate( "keydown", { keyCode: $.ui.keyCode.LEFT } );
+ setTimeout(function() {
+ $( ":focus" ).simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } );
+ TestHelpers.datepicker.equalsDate(
+ input.datepicker( "valueAsDate" ),
+ new Date( 2013, 12 - 1, 31 ),
+ "Keystroke left to switch to previous day"
+ );
+ input.datepicker( "destroy" );
+ step2();
+ }, 50 );
+ }, 100 );
}
- // Hide prev/next
function step2() {
- inp = TestHelpers.datepicker.initNewInput({
- hideIfNoPrevNext: true,
- minDate: new Date( 2008, 2 - 1, 4 ),
- maxDate: new Date( 2008, 2 - 1, 14 )
- });
- inp.val( "02/10/2008" );
-
- TestHelpers.datepicker.onFocus( inp, function() {
- header = dp.children( ":first" );
- ok( header.is( "div.ui-datepicker-header" ), "Structure hide prev/next - header division" );
- equal( header.children().length, 1, "Structure hide prev/next - links child count" );
- ok( header.children( ":first" ).is( "div.ui-datepicker-title" ), "Structure hide prev/next - title division" );
-
- inp.datepicker( "hide" ).datepicker( "destroy" );
+ input.val( "1/1/14" );
+ TestHelpers.datepicker.init( input );
+ input.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } );
+
+ setTimeout(function() {
+ $( ":focus" )
+ .simulate( "keydown", { keyCode: $.ui.keyCode.RIGHT } )
+ .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } );
+
+ TestHelpers.datepicker.equalsDate(
+ input.datepicker( "valueAsDate" ),
+ new Date( 2014, 1 - 1, 2 ),
+ "Keystroke right to switch to next day"
+ );
+ input.datepicker( "destroy" );
step3();
- });
+ }, 100 );
}
- // Changeable Month with read-only year
function step3() {
- inp = TestHelpers.datepicker.initNewInput({ changeMonth: true });
-
- TestHelpers.datepicker.onFocus( inp, function() {
- title = dp.children( ":first" ).children( ":last" );
- equal( title.children().length, 2, "Structure changeable month - title child count" );
- ok( title.children( ":first" ).is( "select.ui-datepicker-month" ), "Structure changeable month - month selector" );
- ok( title.children( ":last" ).is( "span.ui-datepicker-year" ), "Structure changeable month - read-only year" );
-
- inp.datepicker( "hide" ).datepicker( "destroy" );
- step4();
- });
+ input.val( "1/1/14" );
+ TestHelpers.datepicker.init( input );
+ input.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } );
+
+ setTimeout(function() {
+ $( ":focus" ).simulate( "keydown", { keyCode: $.ui.keyCode.UP } );
+ setTimeout(function() {
+ $( ":focus" ).simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } );
+ TestHelpers.datepicker.equalsDate(
+ input.datepicker( "valueAsDate" ),
+ new Date( 2013, 12 - 1, 25 ),
+ "Keystroke up to move to the previous week"
+ );
+ input.datepicker( "destroy" );
+ step4();
+ }, 50 );
+ }, 100 );
}
- // Changeable year with read-only month
function step4() {
- inp = TestHelpers.datepicker.initNewInput({ changeYear: true });
-
- TestHelpers.datepicker.onFocus( inp, function() {
- title = dp.children( ":first" ).children( ":last" );
- equal( title.children().length, 2, "Structure changeable year - title child count" );
- ok( title.children( ":first" ).is( "span.ui-datepicker-month" ), "Structure changeable year - read-only month" );
- ok( title.children( ":last" ).is( "select.ui-datepicker-year" ), "Structure changeable year - year selector" );
-
- inp.datepicker( "hide" ).datepicker( "destroy" );
- step5();
- });
+ input.val( "1/1/14" );
+ TestHelpers.datepicker.init( input );
+ input.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } );
+
+ setTimeout(function() {
+ $( ":focus" ).simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } );
+ setTimeout(function() {
+ $( ":focus" ).simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } );
+
+ TestHelpers.datepicker.equalsDate(
+ input.datepicker( "valueAsDate" ),
+ new Date( 2014, 1 - 1, 8 ),
+ "Keystroke down to move to the next week"
+ );
+ input.datepicker( "destroy" );
+ step5();
+ }, 50 );
+ }, 100 );
}
- // Read-only first day of week
function step5() {
- inp = TestHelpers.datepicker.initNewInput({ changeFirstDay: false });
+ input.val( "1/1/14" );
+ TestHelpers.datepicker.init( input );
+ input.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } );
+
+ setTimeout(function() {
+ $( ":focus" ).simulate( "keydown", { keyCode: $.ui.keyCode.PAGE_DOWN } );
+ setTimeout(function() {
+ $( ":focus" ).simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } );
+ TestHelpers.datepicker.equalsDate(
+ input.datepicker( "valueAsDate" ),
+ new Date( 2014, 2 - 1, 1 ),
+ "Keystroke Page Down moves date to next month"
+ );
+ input.datepicker( "destroy" );
+ step6();
+ }, 50 );
+ }, 100 );
+ }
- TestHelpers.datepicker.onFocus( inp, function() {
- thead = dp.find( ".ui-datepicker-calendar thead tr" );
- equal( thead.children().length, 7, "Structure read-only first day - thead child count" );
- equal( thead.find( "a" ).length, 0, "Structure read-only first day - thead links count" );
+ function step6() {
+ input.val( "1/1/14" );
+ TestHelpers.datepicker.init( input );
+ input.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } );
+
+ setTimeout(function() {
+ $( ":focus" ).simulate( "keydown", { keyCode: $.ui.keyCode.PAGE_DOWN, altKey: true } );
+ setTimeout(function() {
+ $( ":focus" ).simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } );
+ TestHelpers.datepicker.equalsDate(
+ input.datepicker( "valueAsDate" ),
+ new Date( 2015, 1 - 1, 1 ),
+ "Keystroke Page Down + Ctrl moves date to next year"
+ );
+ input.datepicker( "destroy" );
+ step7();
+ }, 50 );
+ }, 100 );
+ }
- inp.datepicker( "hide" ).datepicker( "destroy" );
- start();
- });
+ // Check for moving to short months
+ function step7() {
+ input.val( "3/31/14" );
+ TestHelpers.datepicker.init( input );
+ input.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } );
+
+ setTimeout(function() {
+ $( ":focus" ).simulate( "keydown", { keyCode: $.ui.keyCode.PAGE_UP } );
+ setTimeout(function() {
+ $( ":focus" ).simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } );
+ TestHelpers.datepicker.equalsDate(
+ input.datepicker( "valueAsDate" ),
+ new Date( 2014, 2 - 1, 28 ),
+ "Keystroke Page Up and short months"
+ );
+ input.datepicker( "destroy" );
+ start();
+ }, 50 );
+ }, 100 );
}
- // TODO: figure out why this setTimeout is needed in IE,
- // it only is necessary when the previous baseStructure tests runs first
- // Support: IE
- setTimeout( step1 );
+ step1();
});
-test("keystrokes", function() {
- expect( 26 );
- var inp = TestHelpers.datepicker.init("#inp"),
- date = new Date();
- inp.val("").datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date, "Keystroke enter");
- inp.val("02/04/2008").datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), new Date(2008, 2 - 1, 4),
- "Keystroke enter - preset");
- inp.val("02/04/2008").datepicker("show").
- simulate("keydown", {ctrlKey: true, keyCode: $.ui.keyCode.HOME}).
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date, "Keystroke ctrl+home");
- inp.val("02/04/2008").datepicker("show").
- simulate("keydown", {ctrlKey: true, keyCode: $.ui.keyCode.END});
- ok(inp.datepicker("getDate") == null, "Keystroke ctrl+end");
- inp.val("").datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.ESCAPE});
- ok(inp.datepicker("getDate") == null, "Keystroke esc");
- inp.val("02/04/2008").datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.ESCAPE});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), new Date(2008, 2 - 1, 4),
- "Keystroke esc - preset");
- inp.val("02/04/2008").datepicker("show").
- simulate("keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP}).
- simulate("keydown", {keyCode: $.ui.keyCode.ESCAPE});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), new Date(2008, 2 - 1, 4),
- "Keystroke esc - abandoned");
- // Moving by day or week
- inp.val("").datepicker("show").
- simulate("keydown", {ctrlKey: true, keyCode: $.ui.keyCode.LEFT}).
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- date.setDate(date.getDate() - 1);
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date, "Keystroke ctrl+left");
- inp.val("").datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.LEFT}).
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- date.setDate(date.getDate() + 1);
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date, "Keystroke left");
- inp.val("").datepicker("show").
- simulate("keydown", {ctrlKey: true, keyCode: $.ui.keyCode.RIGHT}).
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- date.setDate(date.getDate() + 1);
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date, "Keystroke ctrl+right");
- inp.val("").datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.RIGHT}).
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- date.setDate(date.getDate() - 1);
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date, "Keystroke right");
- inp.val("").datepicker("show").
- simulate("keydown", {ctrlKey: true, keyCode: $.ui.keyCode.UP}).
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- date.setDate(date.getDate() - 7);
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date, "Keystroke ctrl+up");
- inp.val("").datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.UP}).
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- date.setDate(date.getDate() + 7);
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date, "Keystroke up");
- inp.val("").datepicker("show").
- simulate("keydown", {ctrlKey: true, keyCode: $.ui.keyCode.DOWN}).
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- date.setDate(date.getDate() + 7);
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date, "Keystroke ctrl+down");
- inp.val("").datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.DOWN}).
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- date.setDate(date.getDate() - 7);
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date, "Keystroke down");
- // Moving by month or year
- inp.val("02/04/2008").datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.PAGE_UP}).
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), new Date(2008, 1 - 1, 4),
- "Keystroke pgup");
- inp.val("02/04/2008").datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.PAGE_DOWN}).
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), new Date(2008, 3 - 1, 4),
- "Keystroke pgdn");
- inp.val("02/04/2008").datepicker("show").
- simulate("keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP}).
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), new Date(2007, 2 - 1, 4),
- "Keystroke ctrl+pgup");
- inp.val("02/04/2008").datepicker("show").
- simulate("keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN}).
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), new Date(2009, 2 - 1, 4),
- "Keystroke ctrl+pgdn");
- // Check for moving to short months
- inp.val("03/31/2008").datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.PAGE_UP}).
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), new Date(2008, 2 - 1, 29),
- "Keystroke pgup - Feb");
- inp.val("01/30/2008").datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.PAGE_DOWN}).
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), new Date(2008, 2 - 1, 29),
- "Keystroke pgdn - Feb");
- inp.val("02/29/2008").datepicker("show").
- simulate("keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP}).
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), new Date(2007, 2 - 1, 28),
- "Keystroke ctrl+pgup - Feb");
- inp.val("02/29/2008").datepicker("show").
- simulate("keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN}).
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), new Date(2009, 2 - 1, 28),
- "Keystroke ctrl+pgdn - Feb");
- // Goto current
- inp.datepicker("option", {gotoCurrent: true}).
- datepicker("hide").val("02/04/2008").datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.PAGE_DOWN}).
- simulate("keydown", {ctrlKey: true, keyCode: $.ui.keyCode.HOME}).
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), new Date(2008, 2 - 1, 4),
- "Keystroke ctrl+home");
- // Change steps
- inp.datepicker("option", {stepMonths: 2, gotoCurrent: false}).
- datepicker("hide").val("02/04/2008").datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.PAGE_UP}).
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), new Date(2007, 12 - 1, 4),
- "Keystroke pgup step 2");
- inp.val("02/04/2008").datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.PAGE_DOWN}).
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), new Date(2008, 4 - 1, 4),
- "Keystroke pgdn step 2");
+// TODO: implement
+test( "ARIA", function() {
+ expect( 0 );
});
-test("mouse", function() {
- expect( 15 );
- var inl,
- inp = TestHelpers.datepicker.init("#inp"),
- dp = $("#ui-datepicker-div"),
- date = new Date();
- inp.val("").datepicker("show");
- $(".ui-datepicker-calendar tbody a:contains(10)", dp).simulate("click", {});
- date.setDate(10);
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date, "Mouse click");
- inp.val("02/04/2008").datepicker("show");
- $(".ui-datepicker-calendar tbody a:contains(12)", dp).simulate("click", {});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), new Date(2008, 2 - 1, 12),
- "Mouse click - preset");
- inp.val("02/04/2008").datepicker("show");
- inp.val("").datepicker("show");
- $("button.ui-datepicker-close", dp).simulate("click", {});
- ok(inp.datepicker("getDate") == null, "Mouse click - close");
- inp.val("02/04/2008").datepicker("show");
- $("button.ui-datepicker-close", dp).simulate("click", {});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), new Date(2008, 2 - 1, 4),
- "Mouse click - close + preset");
- inp.val("02/04/2008").datepicker("show");
- $("a.ui-datepicker-prev", dp).simulate("click", {});
- $("button.ui-datepicker-close", dp).simulate("click", {});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), new Date(2008, 2 - 1, 4),
- "Mouse click - abandoned");
- // Current/previous/next
- inp.val("02/04/2008").datepicker("option", {showButtonPanel: true}).datepicker("show");
- $(".ui-datepicker-current", dp).simulate("click", {});
- $(".ui-datepicker-calendar tbody a:contains(14)", dp).simulate("click", {});
- date.setDate(14);
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date, "Mouse click - current");
- inp.val("02/04/2008").datepicker("show");
- $(".ui-datepicker-prev", dp).simulate("click");
- $(".ui-datepicker-calendar tbody a:contains(16)", dp).simulate("click");
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), new Date(2008, 1 - 1, 16),
- "Mouse click - previous");
- inp.val("02/04/2008").datepicker("show");
- $(".ui-datepicker-next", dp).simulate("click");
- $(".ui-datepicker-calendar tbody a:contains(18)", dp).simulate("click");
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), new Date(2008, 3 - 1, 18),
- "Mouse click - next");
- // Previous/next with minimum/maximum
- inp.datepicker("option", {minDate: new Date(2008, 2 - 1, 2),
- maxDate: new Date(2008, 2 - 1, 26)}).val("02/04/2008").datepicker("show");
- $(".ui-datepicker-prev", dp).simulate("click");
- $(".ui-datepicker-calendar tbody a:contains(16)", dp).simulate("click");
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), new Date(2008, 2 - 1, 16),
- "Mouse click - previous + min/max");
- inp.val("02/04/2008").datepicker("show");
- $(".ui-datepicker-next", dp).simulate("click");
- $(".ui-datepicker-calendar tbody a:contains(18)", dp).simulate("click");
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), new Date(2008, 2 - 1, 18),
- "Mouse click - next + min/max");
- // Inline
- inl = TestHelpers.datepicker.init("#inl");
- dp = $(".ui-datepicker-inline", inl);
- date = new Date();
- inl.datepicker("setDate", date);
- $(".ui-datepicker-calendar tbody a:contains(10)", dp).simulate("click", {});
- date.setDate(10);
- TestHelpers.datepicker.equalsDate(inl.datepicker("getDate"), date, "Mouse click inline");
- inl.datepicker("option", {showButtonPanel: true}).datepicker("setDate", new Date(2008, 2 - 1, 4));
- $(".ui-datepicker-calendar tbody a:contains(12)", dp).simulate("click", {});
- TestHelpers.datepicker.equalsDate(inl.datepicker("getDate"), new Date(2008, 2 - 1, 12), "Mouse click inline - preset");
- inl.datepicker("option", {showButtonPanel: true});
- $(".ui-datepicker-current", dp).simulate("click", {});
- $(".ui-datepicker-calendar tbody a:contains(14)", dp).simulate("click", {});
- date.setDate(14);
- TestHelpers.datepicker.equalsDate(inl.datepicker("getDate"), date, "Mouse click inline - current");
- inl.datepicker("setDate", new Date(2008, 2 - 1, 4));
- $(".ui-datepicker-prev", dp).simulate("click");
- $(".ui-datepicker-calendar tbody a:contains(16)", dp).simulate("click");
- TestHelpers.datepicker.equalsDate(inl.datepicker("getDate"), new Date(2008, 1 - 1, 16),
- "Mouse click inline - previous");
- inl.datepicker("setDate", new Date(2008, 2 - 1, 4));
- $(".ui-datepicker-next", dp).simulate("click");
- $(".ui-datepicker-calendar tbody a:contains(18)", dp).simulate("click");
- TestHelpers.datepicker.equalsDate(inl.datepicker("getDate"), new Date(2008, 3 - 1, 18),
- "Mouse click inline - next");
+asyncTest( "mouse", function() {
+ expect( 4 );
+
+ var input = TestHelpers.datepicker.init( $( "#datepicker" ).val( "" ) ),
+ picker = input.datepicker( "widget" );
+
+ input.datepicker( "open" );
+
+ setTimeout(function() {
+ input.val( "2/4/08" ).datepicker( "refresh" ).datepicker( "open" );
+ $( ".ui-calendar-calendar tbody a:contains(12)", picker ).simulate( "mousedown", {} );
+ TestHelpers.datepicker.equalsDate(
+ input.datepicker( "valueAsDate" ),
+ new Date( 2008, 2 - 1, 12 ),
+ "Mouse click - preset"
+ );
+
+ input.val( "" ).datepicker( "refresh" );
+ input.simulate( "click" );
+ ok( input.datepicker( "valueAsDate" ) === null, "Mouse click - close" );
+
+ input.val( "2/4/08" ).datepicker( "refresh" ).datepicker( "open" );
+ input.simulate( "click" );
+ TestHelpers.datepicker.equalsDate(
+ input.datepicker( "valueAsDate" ),
+ new Date( 2008, 2 - 1, 4 ),
+ "Mouse click - close + preset"
+ );
+
+ input.val( "2/4/08" ).datepicker( "refresh" ).datepicker( "open" );
+ $( "a.ui-calendar-prev", picker ).simulate( "click", {} );
+ input.simulate( "click" );
+ TestHelpers.datepicker.equalsDate(
+ input.datepicker( "valueAsDate" ),
+ new Date( 2008, 2 - 1, 4 ),
+ "Mouse click - abandoned"
+ );
+
+ start();
+ }, 100 );
});
-})(jQuery);
+})( jQuery );
diff --git a/tests/unit/datepicker/datepicker_events.js b/tests/unit/datepicker/datepicker_events.js
index dfc42ccf911..aacaa2a2f6c 100644
--- a/tests/unit/datepicker/datepicker_events.js
+++ b/tests/unit/datepicker/datepicker_events.js
@@ -1,153 +1,135 @@
-/*
- * datepicker_events.js
- */
-(function($) {
-
-module("datepicker: events");
-
-var selectedThis = null,
-selectedDate = null,
-selectedInst = null;
-
-function callback(date, inst) {
- selectedThis = this;
- selectedDate = date;
- selectedInst = inst;
-}
-
-function callback2(year, month, inst) {
- selectedThis = this;
- selectedDate = year + "/" + month;
- selectedInst = inst;
-}
-
-test("events", function() {
- expect( 26 );
- var dateStr, newMonthYear, inp2,
- inp = TestHelpers.datepicker.init("#inp", {onSelect: callback}),
- date = new Date();
- // onSelect
- inp.val("").datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- equal(selectedThis, inp[0], "Callback selected this");
- equal(selectedInst, $.data(inp[0], TestHelpers.datepicker.PROP_NAME), "Callback selected inst");
- equal(selectedDate, $.datepicker.formatDate("mm/dd/yy", date),
- "Callback selected date");
- inp.val("").datepicker("show").
- simulate("keydown", {ctrlKey: true, keyCode: $.ui.keyCode.DOWN}).
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- date.setDate(date.getDate() + 7);
- equal(selectedDate, $.datepicker.formatDate("mm/dd/yy", date),
- "Callback selected date - ctrl+down");
- inp.val("").datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.ESCAPE});
- equal(selectedDate, $.datepicker.formatDate("mm/dd/yy", date),
- "Callback selected date - esc");
- dateStr = "02/04/2008";
- inp.val(dateStr).datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- equal(dateStr, selectedDate,
- "onSelect is called after enter keydown");
- // onChangeMonthYear
- inp.datepicker("option", {onChangeMonthYear: callback2, onSelect: null}).
- val("").datepicker("show");
- newMonthYear = function(date) {
- return date.getFullYear() + "/" + (date.getMonth() + 1);
- };
- date = new Date();
- date.setDate(1);
- inp.simulate("keydown", {keyCode: $.ui.keyCode.PAGE_UP});
- date.setMonth(date.getMonth() - 1);
- equal(selectedThis, inp[0], "Callback change month/year this");
- equal(selectedInst, $.data(inp[0], TestHelpers.datepicker.PROP_NAME), "Callback change month/year inst");
- equal(selectedDate, newMonthYear(date),
- "Callback change month/year date - pgup");
- inp.simulate("keydown", {keyCode: $.ui.keyCode.PAGE_DOWN});
- date.setMonth(date.getMonth() + 1);
- equal(selectedDate, newMonthYear(date),
- "Callback change month/year date - pgdn");
- inp.simulate("keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP});
- date.setFullYear(date.getFullYear() - 1);
- equal(selectedDate, newMonthYear(date),
- "Callback change month/year date - ctrl+pgup");
- inp.simulate("keydown", {ctrlKey: true, keyCode: $.ui.keyCode.HOME});
- date.setFullYear(date.getFullYear() + 1);
- equal(selectedDate, newMonthYear(date),
- "Callback change month/year date - ctrl+home");
- inp.simulate("keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN});
- date.setFullYear(date.getFullYear() + 1);
- equal(selectedDate, newMonthYear(date),
- "Callback change month/year date - ctrl+pgdn");
- inp.datepicker("setDate", new Date(2007, 1 - 1, 26));
- equal(selectedDate, "2007/1", "Callback change month/year date - setDate");
- selectedDate = null;
- inp.datepicker("setDate", new Date(2007, 1 - 1, 12));
- ok(selectedDate == null, "Callback change month/year date - setDate no change");
- // onChangeMonthYear step by 2
- inp.datepicker("option", {stepMonths: 2}).
- datepicker("hide").val("").datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.PAGE_UP});
- date.setMonth(date.getMonth() - 14);
- equal(selectedDate, newMonthYear(date),
- "Callback change month/year by 2 date - pgup");
- inp.simulate("keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP});
- date.setMonth(date.getMonth() - 12);
- equal(selectedDate, newMonthYear(date),
- "Callback change month/year by 2 date - ctrl+pgup");
- inp.simulate("keydown", {keyCode: $.ui.keyCode.PAGE_DOWN});
- date.setMonth(date.getMonth() + 2);
- equal(selectedDate, newMonthYear(date),
- "Callback change month/year by 2 date - pgdn");
- inp.simulate("keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN});
- date.setMonth(date.getMonth() + 12);
- equal(selectedDate, newMonthYear(date),
- "Callback change month/year by 2 date - ctrl+pgdn");
- // onClose
- inp.datepicker("option", {onClose: callback, onChangeMonthYear: null, stepMonths: 1}).
- val("").datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.ESCAPE});
- equal(selectedThis, inp[0], "Callback close this");
- equal(selectedInst, $.data(inp[0], TestHelpers.datepicker.PROP_NAME), "Callback close inst");
- equal(selectedDate, "", "Callback close date - esc");
- inp.val("").datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- equal(selectedDate, $.datepicker.formatDate("mm/dd/yy", new Date()),
- "Callback close date - enter");
- inp.val("02/04/2008").datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.ESCAPE});
- equal(selectedDate, "02/04/2008", "Callback close date - preset");
- inp.val("02/04/2008").datepicker("show").
- simulate("keydown", {ctrlKey: true, keyCode: $.ui.keyCode.END});
- equal(selectedDate, "", "Callback close date - ctrl+end");
-
- inp2 = TestHelpers.datepicker.init("#inp2");
- inp2.datepicker().datepicker("option", {onClose: callback}).datepicker("show");
- inp.datepicker("show");
- equal(selectedThis, inp2[0], "Callback close this");
-});
+(function( $ ) {
+
+module( "datepicker: events" );
-test("beforeShowDay-getDate", function() {
+test( "beforeOpen", function() {
expect( 3 );
- var inp = TestHelpers.datepicker.init("#inp", {beforeShowDay: function() { inp.datepicker("getDate"); return [true, ""]; }}),
- dp = $("#ui-datepicker-div");
- inp.val("01/01/2010").datepicker("show");
- // contains non-breaking space
- equal($("div.ui-datepicker-title").text(),
- // support: IE <9, jQuery <1.8
- // In IE7/8 with jQuery <1.8, encoded spaces behave in strange ways
- $( "January 2010 " ).text(), "Initial month");
- $("a.ui-datepicker-next", dp).click();
- $("a.ui-datepicker-next", dp).click();
- // contains non-breaking space
- equal($("div.ui-datepicker-title").text(),
- $( "March 2010 " ).text(), "After next clicks");
- inp.datepicker("hide").datepicker("show");
- $("a.ui-datepicker-prev", dp).click();
- $("a.ui-datepicker-prev", dp).click();
- // contains non-breaking space
- equal($("div.ui-datepicker-title").text(),
- $( "November 2009 " ).text(), "After prev clicks");
- inp.datepicker("hide");
+
+ var input = TestHelpers.datepicker.init( "#datepicker", {
+ beforeOpen: function() {
+ ok( true, "beforeOpen event fired before open" );
+ ok( input.datepicker( "widget" ).is( ":hidden" ), "calendar hidden on beforeOpen" );
+ },
+ open: function() {
+ ok( input.datepicker( "widget" ).is( ":visible" ), "calendar open on open" );
+ }
+ });
+
+ input
+ .datepicker( "open" )
+ .datepicker( "close" )
+ .datepicker( "option", {
+ beforeOpen: function() {
+ return false;
+ },
+ open: function() {
+ ok( false, "calendar should not open when openBefore is canceled" );
+ }
+ })
+ .datepicker( "open" );
+});
+
+test( "close", function() {
+ expect( 4 );
+
+ var shouldFire,
+ input = TestHelpers.datepicker.init( "#datepicker", {
+ close: function() {
+ ok( shouldFire, "close event fired" );
+ }
+ });
+
+ shouldFire = false;
+ input.datepicker( "open" );
+ shouldFire = true;
+ input.datepicker( "close" );
+
+ shouldFire = false;
+ input.datepicker( "open" );
+ shouldFire = true;
+ $( "body" ).trigger( "mousedown" );
+
+ shouldFire = false;
+ input.datepicker( "open" );
+ shouldFire = true;
+ input.simulate( "keydown", { keyCode: $.ui.keyCode.ESCAPE } );
+
+ shouldFire = false;
+ input.datepicker( "open" );
+ shouldFire = true;
+ input.datepicker( "widget" ).find( "tbody tr:first td:first a" ).simulate( "mousedown" );
+
+});
+
+test( "open", function() {
+ expect( 2 );
+
+ var input = TestHelpers.datepicker.init( "#datepicker", {
+ open: function() {
+ ok( true, "open event fired on open" );
+ ok( widget.is( ":visible" ), "calendar open on open" );
+ }
+ }),
+ widget = input.datepicker( "widget" );
+
+ input.datepicker( "open" );
+});
+
+asyncTest( "select", function() {
+ expect( 4 );
+
+ var input = TestHelpers.datepicker.init( "#datepicker", {
+ select: function( event ) {
+ ok( true, "select event fired " + message );
+ equal(
+ event.originalEvent.type,
+ "calendarselect",
+ "select originalEvent " + message
+ );
+ }
+ }),
+ widget = input.datepicker( "widget" ),
+ message = "";
+
+ function step1() {
+ message = "on calendar cell click";
+ input
+ .simulate( "focus" )
+ .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } );
+ setTimeout(function() {
+ widget.find( "tbody tr:first td:first a" ).simulate( "mousedown" );
+ input.datepicker( "close" );
+ step2();
+ }, 100 );
+ }
+
+ function step2() {
+ message = "on calendar cell enter";
+ input
+ .simulate( "focus" )
+ .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } );
+ setTimeout(function() {
+ $( ":focus" )
+ .simulate( "keydown", { keyCode: $.ui.keyCode.RIGHT } )
+ .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } );
+ input.datepicker( "close" );
+ step3();
+ }, 100 );
+ }
+
+ function step3() {
+ message = "on calendar escape (not expected)";
+ input
+ .simulate( "focus" )
+ .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } );
+ setTimeout(function() {
+ $( ":focus" ).simulate( "keydown", { keyCode: $.ui.keyCode.ESCAPE } );
+ input.datepicker( "close" );
+ start();
+ }, 100 );
+ }
+
+ step1();
});
-})(jQuery);
+})( jQuery );
diff --git a/tests/unit/datepicker/datepicker_methods.js b/tests/unit/datepicker/datepicker_methods.js
index e52e126d2e6..ebee9432640 100644
--- a/tests/unit/datepicker/datepicker_methods.js
+++ b/tests/unit/datepicker/datepicker_methods.js
@@ -1,125 +1,149 @@
-/*
- * datepicker_methods.js
- */
-(function($) {
-
-module("datepicker: methods");
-
-test("destroy", function() {
- expect( 33 );
- var inl,
- inp = TestHelpers.datepicker.init("#inp");
- ok(inp.is(".hasDatepicker"), "Default - marker class set");
- ok($.data(inp[0], TestHelpers.datepicker.PROP_NAME), "Default - instance present");
- ok(inp.next().is("#alt"), "Default - button absent");
- inp.datepicker("destroy");
- inp = $("#inp");
- ok(!inp.is(".hasDatepicker"), "Default - marker class cleared");
- ok(!$.data(inp[0], TestHelpers.datepicker.PROP_NAME), "Default - instance absent");
- ok(inp.next().is("#alt"), "Default - button absent");
- // With button
- inp= TestHelpers.datepicker.init("#inp", {showOn: "both"});
- ok(inp.is(".hasDatepicker"), "Button - marker class set");
- ok($.data(inp[0], TestHelpers.datepicker.PROP_NAME), "Button - instance present");
- ok(inp.next().text() === "...", "Button - button added");
- inp.datepicker("destroy");
- inp = $("#inp");
- ok(!inp.is(".hasDatepicker"), "Button - marker class cleared");
- ok(!$.data(inp[0], TestHelpers.datepicker.PROP_NAME), "Button - instance absent");
- ok(inp.next().is("#alt"), "Button - button removed");
- // With append text
- inp = TestHelpers.datepicker.init("#inp", {appendText: "Testing"});
- ok(inp.is(".hasDatepicker"), "Append - marker class set");
- ok($.data(inp[0], TestHelpers.datepicker.PROP_NAME), "Append - instance present");
- ok(inp.next().text() === "Testing", "Append - append text added");
- inp.datepicker("destroy");
- inp = $("#inp");
- ok(!inp.is(".hasDatepicker"), "Append - marker class cleared");
- ok(!$.data(inp[0], TestHelpers.datepicker.PROP_NAME), "Append - instance absent");
- ok(inp.next().is("#alt"), "Append - append text removed");
- // With both
- inp= TestHelpers.datepicker.init("#inp", {showOn: "both", buttonImageOnly: true,
- buttonImage: "images/calendar.gif", appendText: "Testing"});
- ok(inp.is(".hasDatepicker"), "Both - marker class set");
- ok($.data(inp[0], TestHelpers.datepicker.PROP_NAME), "Both - instance present");
- ok(inp.next()[0].nodeName.toLowerCase() === "img", "Both - button added");
- ok(inp.next().next().text() === "Testing", "Both - append text added");
- inp.datepicker("destroy");
- inp = $("#inp");
- ok(!inp.is(".hasDatepicker"), "Both - marker class cleared");
- ok(!$.data(inp[0], TestHelpers.datepicker.PROP_NAME), "Both - instance absent");
- ok(inp.next().is("#alt"), "Both - button and append text absent");
- // Inline
- inl = TestHelpers.datepicker.init("#inl");
- ok(inl.is(".hasDatepicker"), "Inline - marker class set");
- ok(inl.html() !== "", "Inline - datepicker present");
- ok($.data(inl[0], TestHelpers.datepicker.PROP_NAME), "Inline - instance present");
- ok(inl.next().length === 0 || inl.next().is("p"), "Inline - button absent");
- inl.datepicker("destroy");
- inl = $("#inl");
- ok(!inl.is(".hasDatepicker"), "Inline - marker class cleared");
- ok(inl.html() === "", "Inline - datepicker absent");
- ok(!$.data(inl[0], TestHelpers.datepicker.PROP_NAME), "Inline - instance absent");
- ok(inl.next().length === 0 || inl.next().is("p"), "Inline - button absent");
+(function( $ ) {
+
+module( "datepicker: methods" );
+
+test( "destroy", function() {
+ expect( 6 );
+
+ var input = $( "#datepicker" ).datepicker();
+
+ ok( input.datepicker( "instance" ), "instance created" );
+ ok( input.attr( "aria-owns" ), "aria-owns attribute added" );
+ ok( input.attr( "aria-haspopup" ), "aria-haspopup attribute added" );
+ input.datepicker( "destroy" );
+ ok( !input.datepicker( "instance" ), "instance removed" );
+ ok( !input.attr( "aria-owns" ), "aria-owns attribute removed" );
+ ok( !input.attr( "aria-haspopup" ), "aria-haspopup attribute removed" );
+});
+
+test( "enable / disable", function() {
+ expect( 6 );
+
+ var inp = TestHelpers.datepicker.init( "#datepicker" ),
+ dp = inp.datepicker( "widget" );
+
+ ok( !inp.datepicker( "option", "disabled" ), "initially enabled" );
+ ok( !dp.hasClass( "ui-datepicker-disabled" ), "does not have disabled class name" );
+
+ inp.datepicker( "disable" );
+ ok( inp.datepicker( "option", "disabled" ), "disabled option is set" );
+ ok( dp.hasClass( "ui-datepicker-disabled" ), "datepicker has disabled class name" );
+
+ inp.datepicker( "enable" );
+ ok( !inp.datepicker( "option", "disabled" ), "enabled after enable() call" );
+ ok( !dp.hasClass( "ui-datepicker-disabled" ), "no longer has disabled class name" );
+});
+
+test( "widget", function() {
+ expect( 1 );
+
+ var actual = $( "#datepicker" ).datepicker().datepicker( "widget" );
+ deepEqual( $( "body > .ui-front" )[ 0 ], actual[ 0 ] );
+ actual.remove();
});
-test("enableDisable", function() {
- expect( 33 );
- var inl, dp,
- inp = TestHelpers.datepicker.init("#inp");
- ok(!inp.datepicker("isDisabled"), "Enable/disable - initially marked as enabled");
- ok(!inp[0].disabled, "Enable/disable - field initially enabled");
- inp.datepicker("disable");
- ok(inp.datepicker("isDisabled"), "Enable/disable - now marked as disabled");
- ok(inp[0].disabled, "Enable/disable - field now disabled");
- inp.datepicker("enable");
- ok(!inp.datepicker("isDisabled"), "Enable/disable - now marked as enabled");
- ok(!inp[0].disabled, "Enable/disable - field now enabled");
- inp.datepicker("destroy");
- // With a button
- inp = TestHelpers.datepicker.init("#inp", {showOn: "button"});
- ok(!inp.datepicker("isDisabled"), "Enable/disable button - initially marked as enabled");
- ok(!inp[0].disabled, "Enable/disable button - field initially enabled");
- ok(!inp.next("button")[0].disabled, "Enable/disable button - button initially enabled");
- inp.datepicker("disable");
- ok(inp.datepicker("isDisabled"), "Enable/disable button - now marked as disabled");
- ok(inp[0].disabled, "Enable/disable button - field now disabled");
- ok(inp.next("button")[0].disabled, "Enable/disable button - button now disabled");
- inp.datepicker("enable");
- ok(!inp.datepicker("isDisabled"), "Enable/disable button - now marked as enabled");
- ok(!inp[0].disabled, "Enable/disable button - field now enabled");
- ok(!inp.next("button")[0].disabled, "Enable/disable button - button now enabled");
- inp.datepicker("destroy");
- // With an image button
- inp = TestHelpers.datepicker.init("#inp", {showOn: "button", buttonImageOnly: true,
- buttonImage: "images/calendar.gif"});
- ok(!inp.datepicker("isDisabled"), "Enable/disable image - initially marked as enabled");
- ok(!inp[0].disabled, "Enable/disable image - field initially enabled");
- ok(parseFloat(inp.next("img").css("opacity")) === 1, "Enable/disable image - image initially enabled");
- inp.datepicker("disable");
- ok(inp.datepicker("isDisabled"), "Enable/disable image - now marked as disabled");
- ok(inp[0].disabled, "Enable/disable image - field now disabled");
- ok(parseFloat(inp.next("img").css("opacity")) !== 1, "Enable/disable image - image now disabled");
- inp.datepicker("enable");
- ok(!inp.datepicker("isDisabled"), "Enable/disable image - now marked as enabled");
- ok(!inp[0].disabled, "Enable/disable image - field now enabled");
- ok(parseFloat(inp.next("img").css("opacity")) === 1, "Enable/disable image - image now enabled");
- inp.datepicker("destroy");
- // Inline
- inl = TestHelpers.datepicker.init("#inl", {changeYear: true});
- dp = $(".ui-datepicker-inline", inl);
- ok(!inl.datepicker("isDisabled"), "Enable/disable inline - initially marked as enabled");
- ok(!dp.children().is(".ui-state-disabled"), "Enable/disable inline - not visually disabled initially");
- ok(!dp.find("select").prop("disabled"), "Enable/disable inline - form element enabled initially");
- inl.datepicker("disable");
- ok(inl.datepicker("isDisabled"), "Enable/disable inline - now marked as disabled");
- ok(dp.children().is(".ui-state-disabled"), "Enable/disable inline - visually disabled");
- ok(dp.find("select").prop("disabled"), "Enable/disable inline - form element disabled");
- inl.datepicker("enable");
- ok(!inl.datepicker("isDisabled"), "Enable/disable inline - now marked as enabled");
- ok(!dp.children().is(".ui-state-disabled"), "Enable/disable inline - not visiually disabled");
- ok(!dp.find("select").prop("disabled"), "Enable/disable inline - form element enabled");
- inl.datepicker("destroy");
+test( "open / close", function() {
+ expect( 7 );
+
+ var input = TestHelpers.datepicker.initNewInput({ show: false, hide: false }),
+ calendar = input.datepicker( "widget" );
+
+ ok( calendar.is( ":hidden" ), "calendar hidden on init" );
+
+ input.datepicker( "open" );
+ ok( calendar.is( ":visible" ), "open: calendar visible" );
+ equal( calendar.attr( "aria-hidden" ), "false", "open: calendar aria-hidden" );
+ equal( calendar.attr( "aria-expanded" ), "true", "close: calendar aria-expanded" );
+
+ input.datepicker( "close" );
+ ok( !calendar.is( ":visible" ), "close: calendar hidden" );
+ equal( calendar.attr( "aria-hidden" ), "true", "close: calendar aria-hidden" );
+ equal( calendar.attr( "aria-expanded" ), "false", "close: calendar aria-expanded" );
+});
+
+test( "value", function() {
+ expect( 4 );
+
+ var input = $( "#datepicker" ).datepicker(),
+ picker = input.datepicker( "widget" );
+
+ input.datepicker( "value", "1/1/14" );
+ equal( input.val(), "1/1/14", "input's value set" );
+
+ input.datepicker( "open" );
+ ok( picker.find( "a[data-timestamp]:first" ).hasClass( "ui-state-active" ), "first day marked as selected" );
+ equal( input.datepicker( "value" ), "1/1/14", "getter" );
+
+ input.val( "abc" );
+ equal( input.datepicker( "value" ), null, "Invalid values should return null." );
+});
+
+test( "valueAsDate", function() {
+ expect( 13 );
+
+ var minDate, maxDate, dateAndTimeToSet, dateAndTimeClone,
+ input = TestHelpers.datepicker.init( "#datepicker" ),
+ picker = input.datepicker( "widget" ),
+ date1 = new Date(2008, 6 - 1, 4),
+ date2 = new Date();
+
+ input.datepicker( "valueAsDate", new Date( 2014, 0, 1 ) );
+ equal( input.val(), "1/1/14", "Input's value set" );
+ ok( picker.find( "a[data-timestamp]:first" ).hasClass( "ui-state-active" ), "First day marked as selected" );
+ TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), new Date( 2014, 0, 1 ), "Getter" );
+
+ input.val( "a/b/c" );
+ equal( input.datepicker( "valueAsDate" ), null, "Invalid dates return null" );
+
+ input.val( "" ).datepicker( "destroy" );
+ input = TestHelpers.datepicker.init( "#datepicker" );
+
+ ok(input.datepicker( "valueAsDate" ) === null, "Set date - default" );
+ input.datepicker( "valueAsDate", date1);
+ TestHelpers.datepicker.equalsDate(input.datepicker( "valueAsDate" ), date1, "Set date - 2008-06-04" );
+
+ // With minimum/maximum
+ input = TestHelpers.datepicker.init( "#datepicker" );
+ date1 = new Date( 2008, 1 - 1, 4 );
+ date2 = new Date( 2008, 6 - 1, 4 );
+ minDate = new Date( 2008, 2 - 1, 29 );
+ maxDate = new Date( 2008, 3 - 1, 28 );
+
+ input.val( "" ).datepicker( "option", { min: minDate } ).datepicker( "valueAsDate", date2 );
+ TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), date2, "Set date min/max - value > min" );
+
+ input.datepicker( "valueAsDate", date1 );
+ TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), date2, "Set date min/max - value < min" );
+
+ input.val( "" ).datepicker( "option", { max: maxDate, min: null } ).datepicker( "valueAsDate", date1 );
+ TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), date1, "Set date min/max - value < max" );
+
+ input.datepicker( "valueAsDate", date2 );
+ TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), date1, "Set date min/max - value > max" );
+
+ input.val( "" ).datepicker( "option", { min: minDate } ).datepicker( "valueAsDate", date1 );
+ ok( input.datepicker( "valueAsDate" ) === null, "Set date min/max - value < min" );
+
+ input.datepicker( "valueAsDate", date2 );
+ ok( input.datepicker( "valueAsDate" ) === null, "Set date min/max - value > max" );
+
+ dateAndTimeToSet = new Date( 2008, 3 - 1, 28, 1, 11, 0 );
+ dateAndTimeClone = new Date( 2008, 3 - 1, 28, 1, 11, 0 );
+ input.datepicker( "valueAsDate", dateAndTimeToSet );
+ equal( dateAndTimeToSet.getTime(), dateAndTimeClone.getTime(), "Date object passed should not be changed by valueAsDate" );
+});
+
+test( "isValid", function() {
+ expect( 2 );
+ var input = $( "#datepicker" ).datepicker();
+
+ input.val( "1/1/14" );
+ ok( input.datepicker( "isValid" ) );
+
+ input.val( "1/1/abc" );
+ ok( !input.datepicker( "isValid" ) );
+
+ input.datepicker( "destroy" );
});
-})(jQuery);
+})( jQuery );
diff --git a/tests/unit/datepicker/datepicker_options.js b/tests/unit/datepicker/datepicker_options.js
index bcb2d28dde5..1a32348cde9 100644
--- a/tests/unit/datepicker/datepicker_options.js
+++ b/tests/unit/datepicker/datepicker_options.js
@@ -1,1123 +1,601 @@
-/*
- * datepicker_options.js
- */
+(function( $ ) {
+
+module( "datepicker: options" );
+
+test( "appendTo", function() {
+ expect( 6 );
+ var container,
+ detached = $( "
" ),
+ input = $( "#datepicker" );
+
+ input.datepicker();
+ container = input.datepicker( "widget" ).parent()[ 0 ];
+ equal( container, document.body, "defaults to body" );
+ input.datepicker( "destroy" );
+
+ input.datepicker({ appendTo: "#qunit-fixture" });
+ container = input.datepicker( "widget" ).parent()[ 0 ];
+ equal( container, $( "#qunit-fixture" )[ 0 ], "child of specified element" );
+ input.datepicker( "destroy" );
+
+ input.datepicker({ appendTo: "#does-not-exist" });
+ container = input.datepicker( "widget" ).parent()[ 0 ];
+ equal( container, document.body, "set to body if element does not exist" );
+ input.datepicker( "destroy" );
+
+ input.datepicker()
+ .datepicker( "option", "appendTo", "#qunit-fixture" );
+ container = input.datepicker( "widget" ).parent()[ 0 ];
+ equal( container, $( "#qunit-fixture" )[ 0 ], "modified after init" );
+ input.datepicker( "destroy" );
+
+ input.datepicker({ appendTo: detached });
+ container = input.datepicker( "widget" ).parent()[ 0 ];
+ equal( container, detached[ 0 ], "detached jQuery object" );
+ input.datepicker( "destroy" );
+
+ input.datepicker({ appendTo: detached[ 0 ] });
+ container = input.datepicker( "widget" ).parent()[ 0 ];
+ equal( container, detached[ 0 ], "detached DOM element" );
+ input.datepicker( "destroy" );
+});
-(function($) {
+test("buttons", function() {
+ expect(21);
+
+ var btn, i, newButtons,
+ buttons = {
+ "Ok": function( ev ) {
+ ok(true, "button click fires callback");
+ equal(this, element[0], "context of callback");
+ equal(ev.target, btn[0], "event target");
+ },
+ "Cancel": function( ev ) {
+ ok(true, "button click fires callback");
+ equal(this, element[0], "context of callback");
+ equal(ev.target, btn[1], "event target");
+ }
+ },
+ element = $( "#datepicker" ).datepicker({ buttons: buttons });
-module("datepicker: options");
+ btn = element.datepicker( "widget" ).find( ".ui-calendar-buttonpane button" );
+ equal( btn.length, 2, "number of buttons" );
-test("setDefaults", function() {
- expect( 3 );
- TestHelpers.datepicker.init("#inp");
- equal($.datepicker._defaults.showOn, "focus", "Initial showOn");
- $.datepicker.setDefaults({showOn: "button"});
- equal($.datepicker._defaults.showOn, "button", "Change default showOn");
- $.datepicker.setDefaults({showOn: "focus"});
- equal($.datepicker._defaults.showOn, "focus", "Restore showOn");
-});
+ i = 0;
+ $.each( buttons, function( key ) {
+ equal( btn.eq( i ).text(), key, "text of button " + ( i + 1 ) );
+ i++;
+ });
-test("option", function() {
- expect( 17 );
- var inp = TestHelpers.datepicker.init("#inp"),
- inst = $.data(inp[0], TestHelpers.datepicker.PROP_NAME);
- // Set option
- equal(inst.settings.showOn, null, "Initial setting showOn");
- equal($.datepicker._get(inst, "showOn"), "focus", "Initial instance showOn");
- equal($.datepicker._defaults.showOn, "focus", "Initial default showOn");
- inp.datepicker("option", "showOn", "button");
- equal(inst.settings.showOn, "button", "Change setting showOn");
- equal($.datepicker._get(inst, "showOn"), "button", "Change instance showOn");
- equal($.datepicker._defaults.showOn, "focus", "Retain default showOn");
- inp.datepicker("option", {showOn: "both"});
- equal(inst.settings.showOn, "both", "Change setting showOn");
- equal($.datepicker._get(inst, "showOn"), "both", "Change instance showOn");
- equal($.datepicker._defaults.showOn, "focus", "Retain default showOn");
- inp.datepicker("option", "showOn", undefined);
- equal(inst.settings.showOn, null, "Clear setting showOn");
- equal($.datepicker._get(inst, "showOn"), "focus", "Restore instance showOn");
- equal($.datepicker._defaults.showOn, "focus", "Retain default showOn");
- // Get option
- inp = TestHelpers.datepicker.init("#inp");
- equal(inp.datepicker("option", "showOn"), "focus", "Initial setting showOn");
- inp.datepicker("option", "showOn", "button");
- equal(inp.datepicker("option", "showOn"), "button", "Change instance showOn");
- inp.datepicker("option", "showOn", undefined);
- equal(inp.datepicker("option", "showOn"), "focus", "Reset instance showOn");
- deepEqual(inp.datepicker("option", "all"), {showAnim: ""}, "Get instance settings");
- deepEqual(inp.datepicker("option", "defaults"), $.datepicker._defaults,
- "Get default settings");
-});
+ ok( btn.parent().hasClass( "ui-calendar-buttonset" ), "buttons in container");
+ ok( element.datepicker( "widget" ).hasClass( "ui-calendar-buttons" ), "calendar wrapper adds class about having buttons" );
-test( "disabled", function() {
- expect(8);
- var inp = TestHelpers.datepicker.init("#inp");
- ok(!inp.datepicker("isDisabled"), "Initially marked as enabled");
- ok(!inp[0].disabled, "Field initially enabled");
- inp.datepicker("option", "disabled", true);
- ok(inp.datepicker("isDisabled"), "Marked as disabled");
- ok(inp[0].disabled, "Field now disabled");
- inp.datepicker("option", "disabled", false);
- ok(!inp.datepicker("isDisabled"), "Marked as enabled");
- ok(!inp[0].disabled, "Field now enabled");
- inp.datepicker("destroy");
-
- inp = TestHelpers.datepicker.init("#inp", { disabled: true });
- ok(inp.datepicker("isDisabled"), "Initially marked as disabled");
- ok(inp[0].disabled, "Field initially disabled");
+ btn.trigger("click");
+
+ newButtons = {
+ "Close": function( ev ) {
+ ok(true, "button click fires callback");
+ equal(this, element[0], "context of callback");
+ equal(ev.target, btn[0], "event target");
+ }
+ };
+
+ deepEqual(element.datepicker( "option", "buttons" ), buttons, ".datepicker('option', 'buttons') getter" );
+ element.datepicker( "option", "buttons", newButtons );
+ deepEqual(element.datepicker( "option", "buttons" ), newButtons, ".datepicker('option', 'buttons', ...) setter" );
+
+ btn = element.datepicker( "widget" ).find( ".ui-calendar-buttonpane button" );
+ equal(btn.length, 1, "number of buttons after setter");
+ btn.trigger("click");
+
+ i = 0;
+ $.each(newButtons, function( key ) {
+ equal(btn.eq(i).text(), key, "text of button " + (i+1));
+ i += 1;
+ });
+
+ element.datepicker( "option", "buttons", null );
+ btn = element.datepicker( "widget" ).find( ".ui-calendar-buttonpane button" );
+ equal( btn.length, 0, "all buttons have been removed" );
+ equal( element.find( ".ui-calendar-buttonset").length, 0, "buttonset has been removed" );
+ equal( element.parent().hasClass( "ui-calendar-buttons" ), false, "dialog wrapper removes class about having buttons" );
+
+ element.remove();
});
-test("change", function() {
- expect( 12 );
- var inp = TestHelpers.datepicker.init("#inp"),
- inst = $.data(inp[0], TestHelpers.datepicker.PROP_NAME);
- equal(inst.settings.showOn, null, "Initial setting showOn");
- equal($.datepicker._get(inst, "showOn"), "focus", "Initial instance showOn");
- equal($.datepicker._defaults.showOn, "focus", "Initial default showOn");
- inp.datepicker("change", "showOn", "button");
- equal(inst.settings.showOn, "button", "Change setting showOn");
- equal($.datepicker._get(inst, "showOn"), "button", "Change instance showOn");
- equal($.datepicker._defaults.showOn, "focus", "Retain default showOn");
- inp.datepicker("change", {showOn: "both"});
- equal(inst.settings.showOn, "both", "Change setting showOn");
- equal($.datepicker._get(inst, "showOn"), "both", "Change instance showOn");
- equal($.datepicker._defaults.showOn, "focus", "Retain default showOn");
- inp.datepicker("change", "showOn", undefined);
- equal(inst.settings.showOn, null, "Clear setting showOn");
- equal($.datepicker._get(inst, "showOn"), "focus", "Restore instance showOn");
- equal($.datepicker._defaults.showOn, "focus", "Retain default showOn");
+test("buttons - advanced", function() {
+ expect( 7 );
+
+ var buttons,
+ element = $( "#datepicker" ).datepicker({
+ buttons: [
+ {
+ text: "a button",
+ "class": "additional-class",
+ id: "my-button-id",
+ click: function() {
+ equal(this, element[0], "correct context");
+ },
+ icons: {
+ primary: "ui-icon-cancel"
+ },
+ showText: false
+ }
+ ]
+ });
+
+ buttons = element.datepicker( "widget" ).find( ".ui-calendar-buttonpane button" );
+ equal(buttons.length, 1, "correct number of buttons");
+ equal(buttons.attr("id"), "my-button-id", "correct id");
+ equal(buttons.text(), "a button", "correct label");
+ ok(buttons.hasClass("additional-class"), "additional classes added");
+ deepEqual( buttons.button("option", "icons"), { primary: "ui-icon-cancel", secondary: null } );
+ equal( buttons.button( "option", "text" ), false );
+ buttons.click();
+
+ element.remove();
});
-(function() {
- var url = window.location.search;
- url = decodeURIComponent( url.slice( url.indexOf( "swarmURL=" ) + 9 ) );
-
- // TODO: This test occassionally fails in IE in TestSwarm
- if ( $.ui.ie && url && url.indexOf( "http" ) === 0 ) {
- return;
- }
-
- asyncTest( "invocation", function() {
- var button, image,
- isOldIE = $.ui.ie && ( !document.documentMode || document.documentMode < 9 ),
- body = $( "body" );
-
- expect( isOldIE ? 25 : 29 );
-
- function step0() {
- var inp = TestHelpers.datepicker.initNewInput(),
- dp = $( "#ui-datepicker-div" );
-
- button = inp.siblings( "button" );
- ok( button.length === 0, "Focus - button absent" );
- image = inp.siblings( "img" );
- ok( image.length === 0, "Focus - image absent" );
-
- TestHelpers.datepicker.onFocus( inp, function() {
- ok( dp.is( ":visible" ), "Focus - rendered on focus" );
- inp.simulate( "keydown", { keyCode: $.ui.keyCode.ESCAPE } );
- ok( !dp.is( ":visible" ), "Focus - hidden on exit" );
- step1();
- });
- }
+test( "dateFormat", function() {
+ expect( 2 );
+ var input = $( "#datepicker" ).val( "1/1/14" ).datepicker(),
+ picker = input.datepicker( "widget" ),
+ firstDayLink = picker.find( "td[id]:first a" );
- function step1() {
+ input.datepicker( "open" );
+ firstDayLink.trigger( "mousedown" );
+ equal( input.val(), "1/1/14", "default formatting" );
- var inp = TestHelpers.datepicker.initNewInput(),
- dp = $( "#ui-datepicker-div" );
+ input.datepicker( "option", "dateFormat", { date: "full" } );
+ equal( input.val(), "Wednesday, January 1, 2014", "updated formatting" );
- TestHelpers.datepicker.onFocus( inp, function() {
- ok( dp.is( ":visible" ), "Focus - rendered on focus" );
- body.simulate( "mousedown", {} );
- ok( !dp.is( ":visible" ), "Focus - hidden on external click" );
- inp.datepicker( "hide" ).datepicker( "destroy" );
+ input.datepicker( "destroy" );
+});
- step2();
- });
+test( "eachDay", function() {
+ expect( 5 );
+ var timestamp,
+ input = $( "#datepicker" ).datepicker(),
+ picker = input.datepicker( "widget" ),
+ firstCell = picker.find( "td[id]:first" );
+
+ equal( firstCell.find( "a" ).length, 1, "days are selectable by default" );
+ timestamp = parseInt( firstCell.find( "a" ).attr( "data-timestamp" ), 10 );
+ equal( new Date( timestamp ).getDate(), 1, "first available day is the 1st by default" );
+
+ // Do not render the 1st of the month
+ input.datepicker( "option", "eachDay", function( day ) {
+ if ( day.date === 1 ) {
+ day.render = false;
}
-
- function step2() {
- var inp = TestHelpers.datepicker.initNewInput({
- showOn: "button",
- buttonText: "Popup"
- }),
- dp = $( "#ui-datepicker-div" );
-
- ok( !dp.is( ":visible" ), "Button - initially hidden" );
- button = inp.siblings( "button" );
- image = inp.siblings( "img" );
- ok( button.length === 1, "Button - button present" );
- ok( image.length === 0, "Button - image absent" );
- equal( button.text(), "Popup", "Button - button text" );
-
- TestHelpers.datepicker.onFocus( inp, function() {
- ok( !dp.is( ":visible" ), "Button - not rendered on focus" );
- button.click();
- ok( dp.is( ":visible" ), "Button - rendered on button click" );
- button.click();
- ok( !dp.is( ":visible" ), "Button - hidden on second button click" );
- inp.datepicker( "hide" ).datepicker( "destroy" );
-
- step3();
- });
+ });
+ firstCell = picker.find( "td[id]:first" );
+ timestamp = parseInt( firstCell.find( "a" ).attr( "data-timestamp" ), 10 );
+ equal( new Date( timestamp ).getDate(), 2, "first available day is the 2nd" );
+
+ // Display the 1st of the month but make it not selectable.
+ input.datepicker( "option", "eachDay", function( day ) {
+ if ( day.date === 1 ) {
+ day.selectable = false;
}
+ });
+ firstCell = picker.find( "td[id]:first" );
+ equal( firstCell.find( "a" ).length, 0, "the 1st is not selectable" );
- function step3() {
- var inp = TestHelpers.datepicker.initNewInput({
- showOn: "button",
- buttonImageOnly: true,
- buttonImage: "images/calendar.gif",
- buttonText: "Cal"
- }),
- dp = $( "#ui-datepicker-div" );
-
- ok( !dp.is( ":visible" ), "Image button - initially hidden" );
- button = inp.siblings( "button" );
- ok( button.length === 0, "Image button - button absent" );
- image = inp.siblings( "img" );
- ok( image.length === 1, "Image button - image present" );
- ok( /images\/calendar\.gif$/.test( image.attr( "src" ) ), "Image button - image source" );
- equal( image.attr( "title" ), "Cal", "Image button - image text" );
-
- TestHelpers.datepicker.onFocus( inp, function() {
- ok( !dp.is( ":visible" ), "Image button - not rendered on focus" );
- image.click();
- ok( dp.is( ":visible" ), "Image button - rendered on image click" );
- image.click();
- ok( !dp.is( ":visible" ), "Image button - hidden on second image click" );
- inp.datepicker( "hide" ).datepicker( "destroy" );
-
- step4();
- });
+ input.datepicker( "option", "eachDay", function( day ) {
+ if ( day.date === 1 ) {
+ day.extraClasses = "ui-custom";
}
+ });
+ ok( picker.find( "td[id]:first a" ).hasClass( "ui-custom" ), "extraClasses applied" );
- function step4() {
- var inp = TestHelpers.datepicker.initNewInput({
- showOn: "both",
- buttonImage: "images/calendar.gif"
- }),
- dp = $( "#ui-datepicker-div" );
-
- ok( !dp.is( ":visible" ), "Both - initially hidden" );
- button = inp.siblings( "button" );
- ok( button.length === 1, "Both - button present" );
- image = inp.siblings( "img" );
- ok( image.length === 0, "Both - image absent" );
- image = button.children( "img" );
- ok( image.length === 1, "Both - button image present" );
-
- // TODO: This test occasionally fails to focus in IE8 in BrowserStack
- if ( !isOldIE ) {
- TestHelpers.datepicker.onFocus( inp, function() {
- ok( dp.is( ":visible" ), "Both - rendered on focus" );
- body.simulate( "mousedown", {} );
- ok( !dp.is( ":visible" ), "Both - hidden on external click" );
- button.click();
- ok( dp.is( ":visible" ), "Both - rendered on button click" );
- button.click();
- ok( !dp.is( ":visible" ), "Both - hidden on second button click" );
- inp.datepicker( "hide" ).datepicker( "destroy" );
-
- start();
- });
- } else {
- start();
- }
- }
+ input.datepicker( "destroy" );
+});
+
+test( "numberOfMonths", function() {
+ // TODO implement this
+ expect( 0 );
+});
- step0();
+asyncTest( "position", function() {
+ expect( 3 );
+ var input = $( "
" ).datepicker().appendTo( "body" ).css({
+ position: "absolute",
+ top: 0,
+ left: 0
+ }),
+ container = input.datepicker( "widget" );
+
+ input.datepicker( "open" );
+ setTimeout(function() {
+ closeEnough( input.offset().left, container.offset().left, 1, "left sides line up by default" );
+ closeEnough( container.offset().top, input.offset().top + input.outerHeight(), 1,
+ "datepicker directly under input by default" );
+
+ // Change the position option using option()
+ input.datepicker( "option", "position", {
+ my: "left top",
+ at: "right bottom"
+ });
+ closeEnough( container.offset().left, input.offset().left + input.outerWidth(), 1,
+ "datepicker on right hand side of input after position change" );
+
+ input.remove();
+ start();
});
-})();
-
-test("otherMonths", function() {
- expect( 8 );
- var inp = TestHelpers.datepicker.init("#inp"),
- pop = $("#ui-datepicker-div");
- inp.val("06/01/2009").datepicker("show");
- equal(pop.find("tbody").text(),
- // support: IE <9, jQuery <1.8
- // In IE7/8 with jQuery <1.8, encoded spaces behave in strange ways
- $( "
\u00a0123456789101112131415161718192021222324252627282930\u00a0\u00a0\u00a0\u00a0 " ).text(),
- "Other months - none");
- ok(pop.find("td:last *").length === 0, "Other months - no content");
- inp.datepicker("hide").datepicker("option", "showOtherMonths", true).datepicker("show");
- equal(pop.find("tbody").text(), "311234567891011121314151617181920212223242526272829301234",
- "Other months - show");
- ok(pop.find("td:last span").length === 1, "Other months - span content");
- inp.datepicker("hide").datepicker("option", "selectOtherMonths", true).datepicker("show");
- equal(pop.find("tbody").text(), "311234567891011121314151617181920212223242526272829301234",
- "Other months - select");
- ok(pop.find("td:last a").length === 1, "Other months - link content");
- inp.datepicker("hide").datepicker("option", "showOtherMonths", false).datepicker("show");
- equal(pop.find("tbody").text(),
- // support: IE <9, jQuery <1.8
- // In IE7/8 with jQuery <1.8, encoded spaces behave in strange ways
- $( "
\u00a0123456789101112131415161718192021222324252627282930\u00a0\u00a0\u00a0\u00a0 " ).text(),
- "Other months - none");
- ok(pop.find("td:last *").length === 0, "Other months - no content");
});
-test("defaultDate", function() {
+test( "showWeek", function() {
+ expect( 7 );
+ var input = $( "#datepicker" ).datepicker(),
+ container = input.datepicker( "widget" );
+
+ equal( container.find( "thead th" ).length, 7, "just 7 days, no column cell" );
+ equal( container.find( ".ui-calendar-week-col" ).length, 0,
+ "no week column cells present" );
+ input.datepicker( "destroy" );
+
+ input = $( "#datepicker" ).datepicker({ showWeek: true });
+ container = input.datepicker( "widget" );
+ equal( container.find( "thead th" ).length, 8, "7 days + a column cell" );
+ ok( container.find( "thead th:first" ).is( ".ui-calendar-week-col" ),
+ "first cell should have ui-datepicker-week-col class name" );
+ equal( container.find( ".ui-calendar-week-col" ).length,
+ container.find( "tr" ).length, "one week cell for each week" );
+ input.datepicker( "destroy" );
+
+ input = $( "#datepicker" ).datepicker();
+ container = input.datepicker( "widget" );
+ equal( container.find( "thead th" ).length, 7, "no week column" );
+ input.datepicker( "option", "showWeek", true );
+ equal( container.find( "thead th" ).length, 8, "supports changing option after init" );
+});
+
+/*
+// TODO: Move to calendar and rewrite for value option
+test( "defaultDate", function() {
expect( 16 );
- var inp = TestHelpers.datepicker.init("#inp"),
+ var inp = TestHelpers.datepicker.init( "#inp" ),
date = new Date();
- inp.val("").datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date, "Default date null");
+ inp.val( "" ).datepicker( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ TestHelpers.datepicker.equalsDate(inp.datepicker( "getDate" ), date, "Default date null" );
// Numeric values
- inp.datepicker("option", {defaultDate: -2}).
- datepicker("hide").val("").datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
+ inp.datepicker( "option", {defaultDate: -2}).
+ datepicker( "hide" ).val( "" ).datepicker( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
date.setDate(date.getDate() - 2);
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date, "Default date -2");
+ TestHelpers.datepicker.equalsDate(inp.datepicker( "getDate" ), date, "Default date -2" );
date = new Date();
- inp.datepicker("option", {defaultDate: 3}).
- datepicker("hide").val("").datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
+ inp.datepicker( "option", {defaultDate: 3}).
+ datepicker( "hide" ).val( "" ).datepicker( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
date.setDate(date.getDate() + 3);
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date, "Default date 3");
+ TestHelpers.datepicker.equalsDate(inp.datepicker( "getDate" ), date, "Default date 3" );
date = new Date();
- inp.datepicker("option", {defaultDate: 1 / "a"}).
- datepicker("hide").val("").datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date, "Default date NaN");
+ inp.datepicker( "option", {defaultDate: 1 / "a"}).
+ datepicker( "hide" ).val( "" ).datepicker( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ TestHelpers.datepicker.equalsDate(inp.datepicker( "getDate" ), date, "Default date NaN" );
// String offset values
- inp.datepicker("option", {defaultDate: "-1d"}).
- datepicker("hide").val("").datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
+ inp.datepicker( "option", {defaultDate: "-1d"}).
+ datepicker( "hide" ).val( "" ).datepicker( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
date.setDate(date.getDate() - 1);
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date, "Default date -1d");
- inp.datepicker("option", {defaultDate: "+3D"}).
- datepicker("hide").val("").datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
+ TestHelpers.datepicker.equalsDate(inp.datepicker( "getDate" ), date, "Default date -1d" );
+ inp.datepicker( "option", {defaultDate: "+3D"}).
+ datepicker( "hide" ).val( "" ).datepicker( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
date.setDate(date.getDate() + 4);
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date, "Default date +3D");
- inp.datepicker("option", {defaultDate: " -2 w "}).
- datepicker("hide").val("").datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
+ TestHelpers.datepicker.equalsDate(inp.datepicker( "getDate" ), date, "Default date +3D" );
+ inp.datepicker( "option", {defaultDate: " -2 w "}).
+ datepicker( "hide" ).val( "" ).datepicker( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
date = new Date();
date.setDate(date.getDate() - 14);
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date, "Default date -2 w");
- inp.datepicker("option", {defaultDate: "+1 W"}).
- datepicker("hide").val("").datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
+ TestHelpers.datepicker.equalsDate(inp.datepicker( "getDate" ), date, "Default date -2 w" );
+ inp.datepicker( "option", {defaultDate: "+1 W"}).
+ datepicker( "hide" ).val( "" ).datepicker( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
date.setDate(date.getDate() + 21);
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date, "Default date +1 W");
- inp.datepicker("option", {defaultDate: " -1 m "}).
- datepicker("hide").val("").datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
+ TestHelpers.datepicker.equalsDate(inp.datepicker( "getDate" ), date, "Default date +1 W" );
+ inp.datepicker( "option", {defaultDate: " -1 m "}).
+ datepicker( "hide" ).val( "" ).datepicker( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
date = TestHelpers.datepicker.addMonths(new Date(), -1);
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date, "Default date -1 m");
- inp.datepicker("option", {defaultDate: "+2M"}).
- datepicker("hide").val("").datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
+ TestHelpers.datepicker.equalsDate(inp.datepicker( "getDate" ), date, "Default date -1 m" );
+ inp.datepicker( "option", {defaultDate: "+2M"}).
+ datepicker( "hide" ).val( "" ).datepicker( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
date = TestHelpers.datepicker.addMonths(new Date(), 2);
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date, "Default date +2M");
- inp.datepicker("option", {defaultDate: "-2y"}).
- datepicker("hide").val("").datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
+ TestHelpers.datepicker.equalsDate(inp.datepicker( "getDate" ), date, "Default date +2M" );
+ inp.datepicker( "option", {defaultDate: "-2y"}).
+ datepicker( "hide" ).val( "" ).datepicker( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
date = new Date();
date.setFullYear(date.getFullYear() - 2);
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date, "Default date -2y");
- inp.datepicker("option", {defaultDate: "+1 Y "}).
- datepicker("hide").val("").datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
+ TestHelpers.datepicker.equalsDate(inp.datepicker( "getDate" ), date, "Default date -2y" );
+ inp.datepicker( "option", {defaultDate: "+1 Y "}).
+ datepicker( "hide" ).val( "" ).datepicker( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
date.setFullYear(date.getFullYear() + 3);
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date, "Default date +1 Y");
- inp.datepicker("option", {defaultDate: "+1M +10d"}).
- datepicker("hide").val("").datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
+ TestHelpers.datepicker.equalsDate(inp.datepicker( "getDate" ), date, "Default date +1 Y" );
+ inp.datepicker( "option", {defaultDate: "+1M +10d"}).
+ datepicker( "hide" ).val( "" ).datepicker( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
date = TestHelpers.datepicker.addMonths(new Date(), 1);
date.setDate(date.getDate() + 10);
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date, "Default date +1M +10d");
+ TestHelpers.datepicker.equalsDate(inp.datepicker( "getDate" ), date, "Default date +1M +10d" );
// String date values
- inp.datepicker("option", {defaultDate: "07/04/2007"}).
- datepicker("hide").val("").datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
+ inp.datepicker( "option", {defaultDate: "07/04/2007"}).
+ datepicker( "hide" ).val( "" ).datepicker( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
date = new Date(2007, 7 - 1, 4);
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date, "Default date 07/04/2007");
- inp.datepicker("option", {dateFormat: "yy-mm-dd", defaultDate: "2007-04-02"}).
- datepicker("hide").val("").datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
+ TestHelpers.datepicker.equalsDate(inp.datepicker( "getDate" ), date, "Default date 07/04/2007" );
+ inp.datepicker( "option", {dateFormat: "yy-mm-dd", defaultDate: "2007-04-02"}).
+ datepicker( "hide" ).val( "" ).datepicker( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
date = new Date(2007, 4 - 1, 2);
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date, "Default date 2007-04-02");
+ TestHelpers.datepicker.equalsDate(inp.datepicker( "getDate" ), date, "Default date 2007-04-02" );
// Date value
date = new Date(2007, 1 - 1, 26);
- inp.datepicker("option", {dateFormat: "mm/dd/yy", defaultDate: date}).
- datepicker("hide").val("").datepicker("show").
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date, "Default date 01/26/2007");
+ inp.datepicker( "option", {dateFormat: "mm/dd/yy", defaultDate: date}).
+ datepicker( "hide" ).val( "" ).datepicker( "show" ).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ TestHelpers.datepicker.equalsDate(inp.datepicker( "getDate" ), date, "Default date 01/26/2007" );
});
+*/
-test("miscellaneous", function() {
- expect( 19 );
- var curYear, longNames, shortNames, date,
- dp = $("#ui-datepicker-div"),
- inp = TestHelpers.datepicker.init("#inp");
- // Year range
- function genRange(start, offset) {
- var i = start,
- range = "";
- for (; i < start + offset; i++) {
- range += i;
- }
- return range;
- }
- curYear = new Date().getFullYear();
- inp.val("02/04/2008").datepicker("show");
- equal(dp.find(".ui-datepicker-year").text(), "2008", "Year range - read-only default");
- inp.datepicker("hide").datepicker("option", {changeYear: true}).datepicker("show");
- equal(dp.find(".ui-datepicker-year").text(), genRange(2008 - 10, 21), "Year range - changeable default");
- inp.datepicker("hide").datepicker("option", {yearRange: "c-6:c+2", changeYear: true}).datepicker("show");
- equal(dp.find(".ui-datepicker-year").text(), genRange(2008 - 6, 9), "Year range - c-6:c+2");
- inp.datepicker("hide").datepicker("option", {yearRange: "2000:2010", changeYear: true}).datepicker("show");
- equal(dp.find(".ui-datepicker-year").text(), genRange(2000, 11), "Year range - 2000:2010");
- inp.datepicker("hide").datepicker("option", {yearRange: "-5:+3", changeYear: true}).datepicker("show");
- equal(dp.find(".ui-datepicker-year").text(), genRange(curYear - 5, 9), "Year range - -5:+3");
- inp.datepicker("hide").datepicker("option", {yearRange: "2000:-5", changeYear: true}).datepicker("show");
- equal(dp.find(".ui-datepicker-year").text(), genRange(2000, curYear - 2004), "Year range - 2000:-5");
- inp.datepicker("hide").datepicker("option", {yearRange: "", changeYear: true}).datepicker("show");
- equal(dp.find(".ui-datepicker-year").text(), genRange(curYear, 1), "Year range - -6:+2");
-
- // Navigation as date format
- inp.datepicker("option", {showButtonPanel: true});
- equal(dp.find(".ui-datepicker-prev").text(), "Prev", "Navigation prev - default");
- equal(dp.find(".ui-datepicker-current").text(), "Today", "Navigation current - default");
- equal(dp.find(".ui-datepicker-next").text(), "Next", "Navigation next - default");
- inp.datepicker("hide").datepicker("option", {navigationAsDateFormat: true, prevText: "< M", currentText: "MM", nextText: "M >"}).
- val("02/04/2008").datepicker("show");
- longNames = $.datepicker.regional[""].monthNames;
- shortNames = $.datepicker.regional[""].monthNamesShort;
- date = new Date();
- equal(dp.find(".ui-datepicker-prev").text(), "< " + shortNames[0], "Navigation prev - as date format");
- equal(dp.find(".ui-datepicker-current").text(),
- longNames[date.getMonth()], "Navigation current - as date format");
- equal(dp.find(".ui-datepicker-next").text(),
- shortNames[2] + " >", "Navigation next - as date format");
- inp.simulate("keydown", {keyCode: $.ui.keyCode.PAGE_DOWN});
- equal(dp.find(".ui-datepicker-prev").text(),
- "< " + shortNames[1], "Navigation prev - as date format + pgdn");
- equal(dp.find(".ui-datepicker-current").text(),
- longNames[date.getMonth()], "Navigation current - as date format + pgdn");
- equal(dp.find(".ui-datepicker-next").text(),
- shortNames[3] + " >", "Navigation next - as date format + pgdn");
- inp.datepicker("hide").datepicker("option", {gotoCurrent: true}).
- val("02/04/2008").datepicker("show");
- equal(dp.find(".ui-datepicker-prev").text(),
- "< " + shortNames[0], "Navigation prev - as date format + goto current");
- equal(dp.find(".ui-datepicker-current").text(),
- longNames[1], "Navigation current - as date format + goto current");
- equal(dp.find(".ui-datepicker-next").text(),
- shortNames[2] + " >", "Navigation next - as date format + goto current");
-});
+test( "min / max", function() {
+ expect( 14 );
-test("minMax", function() {
- expect( 23 );
+ /*
+ // TODO CTRL + PgUp / PgDn is not implemented yet, see wiki
var date,
- inp = TestHelpers.datepicker.init("#inp"),
- dp = $("#ui-datepicker-div"),
- lastYear = new Date(2007, 6 - 1, 4),
- nextYear = new Date(2009, 6 - 1, 4),
- minDate = new Date(2008, 2 - 1, 29),
- maxDate = new Date(2008, 12 - 1, 7);
- inp.val("06/04/2008").datepicker("show");
- inp.simulate("keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP}).
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), lastYear,
- "Min/max - null, null - ctrl+pgup");
- inp.val("06/04/2008").datepicker("show");
- inp.simulate("keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN}).
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), nextYear,
- "Min/max - null, null - ctrl+pgdn");
- inp.datepicker("option", {minDate: minDate}).
- datepicker("hide").val("06/04/2008").datepicker("show");
- inp.simulate("keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP}).
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), minDate,
- "Min/max - 02/29/2008, null - ctrl+pgup");
- inp.val("06/04/2008").datepicker("show");
- inp.simulate("keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN}).
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), nextYear,
- "Min/max - 02/29/2008, null - ctrl+pgdn");
- inp.datepicker("option", {maxDate: maxDate}).
- datepicker("hide").val("06/04/2008").datepicker("show");
- inp.simulate("keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP}).
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), minDate,
- "Min/max - 02/29/2008, 12/07/2008 - ctrl+pgup");
- inp.val("06/04/2008").datepicker("show");
- inp.simulate("keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN}).
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), maxDate,
- "Min/max - 02/29/2008, 12/07/2008 - ctrl+pgdn");
- inp.datepicker("option", {minDate: null}).
- datepicker("hide").val("06/04/2008").datepicker("show");
- inp.simulate("keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP}).
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), lastYear,
- "Min/max - null, 12/07/2008 - ctrl+pgup");
- inp.val("06/04/2008").datepicker("show");
- inp.simulate("keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN}).
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), maxDate,
- "Min/max - null, 12/07/2008 - ctrl+pgdn");
+ inp = TestHelpers.datepicker.init( "#datepicker" ),
+ dp = inp.datepicker( "widget" ),
+ lastYear = new Date( 2007, 6 - 1, 4 ),
+ nextYear = new Date( 2009, 6 - 1, 4 ),
+ minDate = new Date( 2008, 2 - 1, 29 ),
+ maxDate = new Date( 2008, 12 - 1, 7 );
+
+ inp.val( "06/04/2008" ).datepicker( "refresh" ).datepicker( "open" );
+ inp.simulate( "keydown", { ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP } ).
+ simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } );
+ TestHelpers.datepicker.equalsDate( inp.datepicker( "valueAsDate" ), lastYear, "Min/max - null, null - ctrl+pgup" );
+
+ inp.val( "06/04/2008" ).datepicker( "refresh" ).datepicker( "open" );
+ inp.simulate( "keydown", { ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN } ).
+ simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } );
+ TestHelpers.datepicker.equalsDate( inp.datepicker( "valueAsDate" ), nextYear, "Min/max - null, null - ctrl+pgdn" );
+
+ inp.datepicker( "option", { min: minDate } ).
+ datepicker( "close" ).val( "06/04/2008" ).datepicker( "refresh" ).datepicker( "open" );
+ inp.simulate( "keydown", { ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP } ).
+ simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } );
+ TestHelpers.datepicker.equalsDate( inp.datepicker( "valueAsDate" ), minDate, "Min/max - 02/29/2008, null - ctrl+pgup" );
+
+ inp.val( "06/04/2008" ).datepicker( "refresh" ).datepicker( "open" );
+ inp.simulate( "keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN}).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ TestHelpers.datepicker.equalsDate(inp.datepicker( "getDate" ), nextYear, "Min/max - 02/29/2008, null - ctrl+pgdn" );
+
+ inp.datepicker( "option", { max: maxDate } ).
+ datepicker( "hide" ).val( "06/04/2008" ).datepicker( "open" );
+ inp.simulate( "keydown", { ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP } ).
+ simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } );
+ TestHelpers.datepicker.equalsDate(inp.datepicker( "getDate" ), minDate, "Min/max - 02/29/2008, 12/07/2008 - ctrl+pgup" );
+
+ inp.val( "06/04/2008" ).datepicker( "open" );
+ inp.simulate( "keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN}).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ TestHelpers.datepicker.equalsDate(inp.datepicker( "valueAsDate" ), maxDate, "Min/max - 02/29/2008, 12/07/2008 - ctrl+pgdn" );
+
+ inp.datepicker( "option", {minDate: null}).
+ datepicker( "hide" ).val( "06/04/2008" ).datepicker( "open" );
+ inp.simulate( "keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP}).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ TestHelpers.datepicker.equalsDate(inp.datepicker( "valueAsDate" ), lastYear, "Min/max - null, 12/07/2008 - ctrl+pgup" );
+
+ inp.val( "06/04/2008" ).datepicker( "open" );
+ inp.simulate( "keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN}).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ TestHelpers.datepicker.equalsDate(inp.datepicker( "valueAsDate" ), maxDate, "Min/max - null, 12/07/2008 - ctrl+pgdn" );
+
// Relative dates
date = new Date();
date.setDate(date.getDate() - 7);
- inp.datepicker("option", {minDate: "-1w", maxDate: "+1 M +10 D "}).
- datepicker("hide").val("").datepicker("show");
- inp.simulate("keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP}).
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date,
- "Min/max - -1w, +1 M +10 D - ctrl+pgup");
+ inp.datepicker( "option", {minDate: "-1w", maxDate: "+1 M +10 D "}).
+ datepicker( "hide" ).val( "" ).datepicker( "open" );
+ inp.simulate( "keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP}).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ TestHelpers.datepicker.equalsDate(inp.datepicker( "valueAsDate" ), date, "Min/max - -1w, +1 M +10 D - ctrl+pgup" );
+
date = TestHelpers.datepicker.addMonths(new Date(), 1);
date.setDate(date.getDate() + 10);
- inp.val("").datepicker("show");
- inp.simulate("keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN}).
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date,
- "Min/max - -1w, +1 M +10 D - ctrl+pgdn");
+ inp.val( "" ).datepicker( "show" );
+ inp.simulate( "keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN}).
+ simulate( "keydown", {keyCode: $.ui.keyCode.ENTER});
+ TestHelpers.datepicker.equalsDate(inp.datepicker( "valueAsDate" ), date, "Min/max - -1w, +1 M +10 D - ctrl+pgdn" );
+ */
+
// With existing date
- inp = TestHelpers.datepicker.init("#inp");
- inp.val("06/04/2008").datepicker("option", {minDate: minDate});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), new Date(2008, 6 - 1, 4), "Min/max - setDate > min");
- inp.datepicker("option", {minDate: null}).val("01/04/2008").datepicker("option", {minDate: minDate});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), minDate, "Min/max - setDate < min");
- inp.datepicker("option", {minDate: null}).val("06/04/2008").datepicker("option", {maxDate: maxDate});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), new Date(2008, 6 - 1, 4), "Min/max - setDate < max");
- inp.datepicker("option", {maxDate: null}).val("01/04/2009").datepicker("option", {maxDate: maxDate});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), maxDate, "Min/max - setDate > max");
- inp.datepicker("option", {maxDate: null}).val("01/04/2008").datepicker("option", {minDate: minDate, maxDate: maxDate});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), minDate, "Min/max - setDate < min");
- inp.datepicker("option", {maxDate: null}).val("06/04/2008").datepicker("option", {minDate: minDate, maxDate: maxDate});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), new Date(2008, 6 - 1, 4), "Min/max - setDate > min, < max");
- inp.datepicker("option", {maxDate: null}).val("01/04/2009").datepicker("option", {minDate: minDate, maxDate: maxDate});
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), maxDate, "Min/max - setDate > max");
-
- inp.datepicker("option", {yearRange: "-0:+1"}).val("01/01/" + new Date().getFullYear());
- ok(dp.find(".ui-datepicker-prev").hasClass("ui-state-disabled"), "Year Range Test - previous button disabled at 1/1/minYear");
- inp.datepicker("setDate", "12/30/" + new Date().getFullYear());
- ok(dp.find(".ui-datepicker-next").hasClass("ui-state-disabled"), "Year Range Test - next button disabled at 12/30/maxYear");
-
- inp.datepicker("option", {
- minDate: new Date(1900, 0, 1),
- maxDate: "-6Y",
+ var inp = TestHelpers.datepicker.init( "#datepicker" ),
+ minDate = new Date( 2008, 2 - 1, 29 ),
+ maxDate = new Date( 2008, 12 - 1, 7 );
+
+ inp.val( "6/4/08" ).datepicker( "option", { min: minDate } );
+ TestHelpers.datepicker.equalsDate( inp.datepicker( "valueAsDate" ), new Date( 2008, 6 - 1, 4 ), "Min/max - value > min" );
+ ok( inp.datepicker( "isValid" ) );
+
+ inp.datepicker( "option", { min: null } ).val( "1/4/08" ).datepicker( "option", { min: minDate } );
+ TestHelpers.datepicker.equalsDate( inp.datepicker( "valueAsDate" ), new Date( 2008, 1 - 1, 4 ), "Min/max - value < min" );
+ ok( !inp.datepicker( "isValid" ) );
+
+ inp.datepicker( "option", { min: null } ).val( "6/4/08" ).datepicker( "option", { max: maxDate } );
+ TestHelpers.datepicker.equalsDate( inp.datepicker( "valueAsDate" ), new Date( 2008, 6 - 1, 4 ), "Min/max - value < max" );
+ ok( inp.datepicker( "isValid" ) );
+
+ inp.datepicker( "option", { max: null } ).val( "1/4/09" ).datepicker( "option", { max: maxDate } );
+ TestHelpers.datepicker.equalsDate( inp.datepicker( "valueAsDate" ), new Date( 2009, 1 - 1, 4 ), "Min/max - setDate > max" );
+ ok( !inp.datepicker( "isValid" ) );
+
+ inp.datepicker( "option", { max: null } ).val( "1/4/08" ).datepicker( "option", { min: minDate, max: maxDate } );
+ TestHelpers.datepicker.equalsDate( inp.datepicker( "valueAsDate" ), new Date( 2008, 1 - 1, 4 ), "Min/max - value < min" );
+ ok( !inp.datepicker( "isValid" ) );
+
+ inp.datepicker( "option", { max: null } ).val( "6/4/08" ).datepicker( "option", { min: minDate, max: maxDate } );
+ TestHelpers.datepicker.equalsDate( inp.datepicker( "valueAsDate" ), new Date( 2008, 6 - 1, 4 ), "Min/max - value > min, < max" );
+ ok( inp.datepicker( "isValid" ) );
+
+ inp.datepicker( "option", { max: null } ).val( "1/4/09" ).datepicker( "option", { min: minDate, max: maxDate } );
+ TestHelpers.datepicker.equalsDate( inp.datepicker( "valueAsDate" ), new Date( 2009, 1 - 1, 4 ), "Min/max - value > max" );
+ ok( !inp.datepicker( "isValid" ) );
+
+ /*
+ // TODO: enable when yearRange option is implemented
+ inp.datepicker( "option", {yearRange: "-0:+1"}).val( "01/01/" + new Date().getFullYear());
+ ok(dp.find( ".ui-calendar-prev" ).hasClass( "ui-state-disabled" ), "Year Range Test - previous button disabled at 1/1/minYear" );
+ inp.datepicker( "setDate", "12/30/" + new Date().getFullYear());
+ ok(dp.find( ".ui-calendar-next" ).hasClass( "ui-state-disabled" ), "Year Range Test - next button disabled at 12/30/maxYear" );
+
+ inp.datepicker( "option", {
+ min: new Date(1900, 0, 1),
+ max: "-6Y",
yearRange: "1900:-6"
}).val( "" );
- ok(dp.find(".ui-datepicker-next").hasClass("ui-state-disabled"), "Year Range Test - next button disabled");
- ok(!dp.find(".ui-datepicker-prev").hasClass("ui-state-disabled"), "Year Range Test - prev button enabled");
+ ok(dp.find( ".ui-calendar-next" ).hasClass( "ui-state-disabled" ), "Year Range Test - next button disabled" );
+ ok(!dp.find( ".ui-calendar-prev" ).hasClass( "ui-state-disabled" ), "Year Range Test - prev button enabled" );
- inp.datepicker("option", {
- minDate: new Date(1900, 0, 1),
- maxDate: "1/25/2007",
+ inp.datepicker( "option", {
+ min: new Date(1900, 0, 1),
+ max: "1/25/2007",
yearRange: "1900:2007"
}).val( "" );
- ok(dp.find(".ui-datepicker-next").hasClass("ui-state-disabled"), "Year Range Test - next button disabled");
- ok(!dp.find(".ui-datepicker-prev").hasClass("ui-state-disabled"), "Year Range Test - prev button enabled");
-});
-
-test("setDate", function() {
- expect( 24 );
- var inl, alt, minDate, maxDate, dateAndTimeToSet, dateAndTimeClone,
- inp = TestHelpers.datepicker.init("#inp"),
- date1 = new Date(2008, 6 - 1, 4),
- date2 = new Date();
- ok(inp.datepicker("getDate") == null, "Set date - default");
- inp.datepicker("setDate", date1);
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date1, "Set date - 2008-06-04");
- date1 = new Date();
- date1.setDate(date1.getDate() + 7);
- inp.datepicker("setDate", +7);
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date1, "Set date - +7");
- date2.setFullYear(date2.getFullYear() + 2);
- inp.datepicker("setDate", "+2y");
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date2, "Set date - +2y");
- inp.datepicker("setDate", date1, date2);
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date1, "Set date - two dates");
- inp.datepicker("setDate");
- ok(inp.datepicker("getDate") == null, "Set date - null");
- // Relative to current date
- date1 = new Date();
- date1.setDate(date1.getDate() + 7);
- inp.datepicker("setDate", "c +7");
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date1, "Set date - c +7");
- date1.setDate(date1.getDate() + 7);
- inp.datepicker("setDate", "c+7");
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date1, "Set date - c+7");
- date1.setDate(date1.getDate() - 21);
- inp.datepicker("setDate", "c -3 w");
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date1, "Set date - c -3 w");
- // Inline
- inl = TestHelpers.datepicker.init("#inl");
- date1 = new Date(2008, 6 - 1, 4);
- date2 = new Date();
- TestHelpers.datepicker.equalsDate(inl.datepicker("getDate"), date2, "Set date inline - default");
- inl.datepicker("setDate", date1);
- TestHelpers.datepicker.equalsDate(inl.datepicker("getDate"), date1, "Set date inline - 2008-06-04");
- date1 = new Date();
- date1.setDate(date1.getDate() + 7);
- inl.datepicker("setDate", +7);
- TestHelpers.datepicker.equalsDate(inl.datepicker("getDate"), date1, "Set date inline - +7");
- date2.setFullYear(date2.getFullYear() + 2);
- inl.datepicker("setDate", "+2y");
- TestHelpers.datepicker.equalsDate(inl.datepicker("getDate"), date2, "Set date inline - +2y");
- inl.datepicker("setDate", date1, date2);
- TestHelpers.datepicker.equalsDate(inl.datepicker("getDate"), date1, "Set date inline - two dates");
- inl.datepicker("setDate");
- ok(inl.datepicker("getDate") == null, "Set date inline - null");
- // Alternate field
- alt = $("#alt");
- inp.datepicker("option", {altField: "#alt", altFormat: "yy-mm-dd"});
- date1 = new Date(2008, 6 - 1, 4);
- inp.datepicker("setDate", date1);
- equal(inp.val(), "06/04/2008", "Set date alternate - 06/04/2008");
- equal(alt.val(), "2008-06-04", "Set date alternate - 2008-06-04");
- // With minimum/maximum
- inp = TestHelpers.datepicker.init("#inp");
- date1 = new Date(2008, 1 - 1, 4);
- date2 = new Date(2008, 6 - 1, 4);
- minDate = new Date(2008, 2 - 1, 29);
- maxDate = new Date(2008, 3 - 1, 28);
- inp.val("").datepicker("option", {minDate: minDate}).datepicker("setDate", date2);
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date2, "Set date min/max - setDate > min");
- inp.datepicker("setDate", date1);
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), minDate, "Set date min/max - setDate < min");
- inp.val("").datepicker("option", {maxDate: maxDate, minDate: null}).datepicker("setDate", date1);
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), date1, "Set date min/max - setDate < max");
- inp.datepicker("setDate", date2);
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), maxDate, "Set date min/max - setDate > max");
- inp.val("").datepicker("option", {minDate: minDate}).datepicker("setDate", date1);
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), minDate, "Set date min/max - setDate < min");
- inp.datepicker("setDate", date2);
- TestHelpers.datepicker.equalsDate(inp.datepicker("getDate"), maxDate, "Set date min/max - setDate > max");
- dateAndTimeToSet = new Date(2008, 3 - 1, 28, 1, 11, 0);
- dateAndTimeClone = new Date(2008, 3 - 1, 28, 1, 11, 0);
- inp.datepicker("setDate", dateAndTimeToSet);
- equal(dateAndTimeToSet.getTime(), dateAndTimeClone.getTime(), "Date object passed should not be changed by setDate");
-});
-
-test("altField", function() {
- expect( 10 );
- var inp = TestHelpers.datepicker.init("#inp"),
- alt = $("#alt");
- // No alternate field set
- alt.val("");
- inp.val("06/04/2008").datepicker("show");
- inp.simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- equal(inp.val(), "06/04/2008", "Alt field - dp - enter");
- equal(alt.val(), "", "Alt field - alt not set");
- // Alternate field set
- alt.val("");
- inp.datepicker("option", {altField: "#alt", altFormat: "yy-mm-dd"}).
- val("06/04/2008").datepicker("show");
- inp.simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- equal(inp.val(), "06/04/2008", "Alt field - dp - enter");
- equal(alt.val(), "2008-06-04", "Alt field - alt - enter");
- // Move from initial date
- alt.val("");
- inp.val("06/04/2008").datepicker("show");
- inp.simulate("keydown", {keyCode: $.ui.keyCode.PAGE_DOWN}).
- simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- equal(inp.val(), "07/04/2008", "Alt field - dp - pgdn");
- equal(alt.val(), "2008-07-04", "Alt field - alt - pgdn");
- // Alternate field set - closed
- alt.val("");
- inp.val("06/04/2008").datepicker("show");
- inp.simulate("keydown", {keyCode: $.ui.keyCode.PAGE_DOWN}).
- simulate("keydown", {keyCode: $.ui.keyCode.ESCAPE});
- equal(inp.val(), "06/04/2008", "Alt field - dp - pgdn/esc");
- equal(alt.val(), "", "Alt field - alt - pgdn/esc");
- // Clear date and alternate
- alt.val("");
- inp.val("06/04/2008").datepicker("show");
- inp.simulate("keydown", {ctrlKey: true, keyCode: $.ui.keyCode.END});
- equal(inp.val(), "", "Alt field - dp - ctrl+end");
- equal(alt.val(), "", "Alt field - alt - ctrl+end");
-});
-
-test("autoSize", function() {
- expect( 15 );
- var inp = TestHelpers.datepicker.init("#inp");
- equal(inp.prop("size"), 20, "Auto size - default");
- inp.datepicker("option", "autoSize", true);
- equal(inp.prop("size"), 10, "Auto size - mm/dd/yy");
- inp.datepicker("option", "dateFormat", "m/d/yy");
- equal(inp.prop("size"), 10, "Auto size - m/d/yy");
- inp.datepicker("option", "dateFormat", "D M d yy");
- equal(inp.prop("size"), 15, "Auto size - D M d yy");
- inp.datepicker("option", "dateFormat", "DD, MM dd, yy");
- equal(inp.prop("size"), 29, "Auto size - DD, MM dd, yy");
-
- // French
- inp.datepicker("option", $.extend({autoSize: false}, $.datepicker.regional.fr));
- equal(inp.prop("size"), 29, "Auto size - fr - default");
- inp.datepicker("option", "autoSize", true);
- equal(inp.prop("size"), 10, "Auto size - fr - dd/mm/yy");
- inp.datepicker("option", "dateFormat", "m/d/yy");
- equal(inp.prop("size"), 10, "Auto size - fr - m/d/yy");
- inp.datepicker("option", "dateFormat", "D M d yy");
- equal(inp.prop("size"), 18, "Auto size - fr - D M d yy");
- inp.datepicker("option", "dateFormat", "DD, MM dd, yy");
- equal(inp.prop("size"), 28, "Auto size - fr - DD, MM dd, yy");
-
- // Hebrew
- inp.datepicker("option", $.extend({autoSize: false}, $.datepicker.regional.he));
- equal(inp.prop("size"), 28, "Auto size - he - default");
- inp.datepicker("option", "autoSize", true);
- equal(inp.prop("size"), 10, "Auto size - he - dd/mm/yy");
- inp.datepicker("option", "dateFormat", "m/d/yy");
- equal(inp.prop("size"), 10, "Auto size - he - m/d/yy");
- inp.datepicker("option", "dateFormat", "D M d yy");
- equal(inp.prop("size"), 16, "Auto size - he - D M d yy");
- inp.datepicker("option", "dateFormat", "DD, MM dd, yy");
- equal(inp.prop("size"), 23, "Auto size - he - DD, MM dd, yy");
+ ok(dp.find( ".ui-calendar-next" ).hasClass( "ui-state-disabled" ), "Year Range Test - next button disabled" );
+ ok(!dp.find( ".ui-calendar-prev" ).hasClass( "ui-state-disabled" ), "Year Range Test - prev button enabled" );
+ */
});
-test("daylightSaving", function() {
+/*
+// TODO: Move this to $.date, Globalize or calendar widget
+test( "daylightSaving", function() {
expect( 25 );
- var inp = TestHelpers.datepicker.init("#inp"),
- dp = $("#ui-datepicker-div");
+ var inp = TestHelpers.datepicker.init( "#inp" ),
+ dp = $( "#ui-datepicker-div" );
ok(true, "Daylight saving - " + new Date());
// Australia, Sydney - AM change, southern hemisphere
- inp.val("04/01/2008").datepicker("show");
- $(".ui-datepicker-calendar td:eq(6) a", dp).simulate("click");
- equal(inp.val(), "04/05/2008", "Daylight saving - Australia 04/05/2008");
- inp.val("04/01/2008").datepicker("show");
- $(".ui-datepicker-calendar td:eq(7) a", dp).simulate("click");
- equal(inp.val(), "04/06/2008", "Daylight saving - Australia 04/06/2008");
- inp.val("04/01/2008").datepicker("show");
- $(".ui-datepicker-calendar td:eq(8) a", dp).simulate("click");
- equal(inp.val(), "04/07/2008", "Daylight saving - Australia 04/07/2008");
- inp.val("10/01/2008").datepicker("show");
- $(".ui-datepicker-calendar td:eq(6) a", dp).simulate("click");
- equal(inp.val(), "10/04/2008", "Daylight saving - Australia 10/04/2008");
- inp.val("10/01/2008").datepicker("show");
- $(".ui-datepicker-calendar td:eq(7) a", dp).simulate("click");
- equal(inp.val(), "10/05/2008", "Daylight saving - Australia 10/05/2008");
- inp.val("10/01/2008").datepicker("show");
- $(".ui-datepicker-calendar td:eq(8) a", dp).simulate("click");
- equal(inp.val(), "10/06/2008", "Daylight saving - Australia 10/06/2008");
+ inp.val( "04/01/2008" ).datepicker( "show" );
+ $( ".ui-calendar-calendar td:eq(6) a", dp).simulate( "click" );
+ equal(inp.val(), "04/05/2008", "Daylight saving - Australia 04/05/2008" );
+ inp.val( "04/01/2008" ).datepicker( "show" );
+ $( ".ui-calendar-calendar td:eq(7) a", dp).simulate( "click" );
+ equal(inp.val(), "04/06/2008", "Daylight saving - Australia 04/06/2008" );
+ inp.val( "04/01/2008" ).datepicker( "show" );
+ $( ".ui-calendar-calendar td:eq(8) a", dp).simulate( "click" );
+ equal(inp.val(), "04/07/2008", "Daylight saving - Australia 04/07/2008" );
+ inp.val( "10/01/2008" ).datepicker( "show" );
+ $( ".ui-calendar-calendar td:eq(6) a", dp).simulate( "click" );
+ equal(inp.val(), "10/04/2008", "Daylight saving - Australia 10/04/2008" );
+ inp.val( "10/01/2008" ).datepicker( "show" );
+ $( ".ui-calendar-calendar td:eq(7) a", dp).simulate( "click" );
+ equal(inp.val(), "10/05/2008", "Daylight saving - Australia 10/05/2008" );
+ inp.val( "10/01/2008" ).datepicker( "show" );
+ $( ".ui-calendar-calendar td:eq(8) a", dp).simulate( "click" );
+ equal(inp.val(), "10/06/2008", "Daylight saving - Australia 10/06/2008" );
// Brasil, Brasilia - midnight change, southern hemisphere
- inp.val("02/01/2008").datepicker("show");
- $(".ui-datepicker-calendar td:eq(20) a", dp).simulate("click");
- equal(inp.val(), "02/16/2008", "Daylight saving - Brasil 02/16/2008");
- inp.val("02/01/2008").datepicker("show");
- $(".ui-datepicker-calendar td:eq(21) a", dp).simulate("click");
- equal(inp.val(), "02/17/2008", "Daylight saving - Brasil 02/17/2008");
- inp.val("02/01/2008").datepicker("show");
- $(".ui-datepicker-calendar td:eq(22) a", dp).simulate("click");
- equal(inp.val(), "02/18/2008", "Daylight saving - Brasil 02/18/2008");
- inp.val("10/01/2008").datepicker("show");
- $(".ui-datepicker-calendar td:eq(13) a", dp).simulate("click");
- equal(inp.val(), "10/11/2008", "Daylight saving - Brasil 10/11/2008");
- inp.val("10/01/2008").datepicker("show");
- $(".ui-datepicker-calendar td:eq(14) a", dp).simulate("click");
- equal(inp.val(), "10/12/2008", "Daylight saving - Brasil 10/12/2008");
- inp.val("10/01/2008").datepicker("show");
- $(".ui-datepicker-calendar td:eq(15) a", dp).simulate("click");
- equal(inp.val(), "10/13/2008", "Daylight saving - Brasil 10/13/2008");
+ inp.val( "02/01/2008" ).datepicker( "show" );
+ $( ".ui-calendar-calendar td:eq(20) a", dp).simulate( "click" );
+ equal(inp.val(), "02/16/2008", "Daylight saving - Brasil 02/16/2008" );
+ inp.val( "02/01/2008" ).datepicker( "show" );
+ $( ".ui-calendar-calendar td:eq(21) a", dp).simulate( "click" );
+ equal(inp.val(), "02/17/2008", "Daylight saving - Brasil 02/17/2008" );
+ inp.val( "02/01/2008" ).datepicker( "show" );
+ $( ".ui-calendar-calendar td:eq(22) a", dp).simulate( "click" );
+ equal(inp.val(), "02/18/2008", "Daylight saving - Brasil 02/18/2008" );
+ inp.val( "10/01/2008" ).datepicker( "show" );
+ $( ".ui-calendar-calendar td:eq(13) a", dp).simulate( "click" );
+ equal(inp.val(), "10/11/2008", "Daylight saving - Brasil 10/11/2008" );
+ inp.val( "10/01/2008" ).datepicker( "show" );
+ $( ".ui-calendar-calendar td:eq(14) a", dp).simulate( "click" );
+ equal(inp.val(), "10/12/2008", "Daylight saving - Brasil 10/12/2008" );
+ inp.val( "10/01/2008" ).datepicker( "show" );
+ $( ".ui-calendar-calendar td:eq(15) a", dp).simulate( "click" );
+ equal(inp.val(), "10/13/2008", "Daylight saving - Brasil 10/13/2008" );
// Lebanon, Beirut - midnight change, northern hemisphere
- inp.val("03/01/2008").datepicker("show");
- $(".ui-datepicker-calendar td:eq(34) a", dp).simulate("click");
- equal(inp.val(), "03/29/2008", "Daylight saving - Lebanon 03/29/2008");
- inp.val("03/01/2008").datepicker("show");
- $(".ui-datepicker-calendar td:eq(35) a", dp).simulate("click");
- equal(inp.val(), "03/30/2008", "Daylight saving - Lebanon 03/30/2008");
- inp.val("03/01/2008").datepicker("show");
- $(".ui-datepicker-calendar td:eq(36) a", dp).simulate("click");
- equal(inp.val(), "03/31/2008", "Daylight saving - Lebanon 03/31/2008");
- inp.val("10/01/2008").datepicker("show");
- $(".ui-datepicker-calendar td:eq(27) a", dp).simulate("click");
- equal(inp.val(), "10/25/2008", "Daylight saving - Lebanon 10/25/2008");
- inp.val("10/01/2008").datepicker("show");
- $(".ui-datepicker-calendar td:eq(28) a", dp).simulate("click");
- equal(inp.val(), "10/26/2008", "Daylight saving - Lebanon 10/26/2008");
- inp.val("10/01/2008").datepicker("show");
- $(".ui-datepicker-calendar td:eq(29) a", dp).simulate("click");
- equal(inp.val(), "10/27/2008", "Daylight saving - Lebanon 10/27/2008");
+ inp.val( "03/01/2008" ).datepicker( "show" );
+ $( ".ui-calendar-calendar td:eq(34) a", dp).simulate( "click" );
+ equal(inp.val(), "03/29/2008", "Daylight saving - Lebanon 03/29/2008" );
+ inp.val( "03/01/2008" ).datepicker( "show" );
+ $( ".ui-calendar-calendar td:eq(35) a", dp).simulate( "click" );
+ equal(inp.val(), "03/30/2008", "Daylight saving - Lebanon 03/30/2008" );
+ inp.val( "03/01/2008" ).datepicker( "show" );
+ $( ".ui-calendar-calendar td:eq(36) a", dp).simulate( "click" );
+ equal(inp.val(), "03/31/2008", "Daylight saving - Lebanon 03/31/2008" );
+ inp.val( "10/01/2008" ).datepicker( "show" );
+ $( ".ui-calendar-calendar td:eq(27) a", dp).simulate( "click" );
+ equal(inp.val(), "10/25/2008", "Daylight saving - Lebanon 10/25/2008" );
+ inp.val( "10/01/2008" ).datepicker( "show" );
+ $( ".ui-calendar-calendar td:eq(28) a", dp).simulate( "click" );
+ equal(inp.val(), "10/26/2008", "Daylight saving - Lebanon 10/26/2008" );
+ inp.val( "10/01/2008" ).datepicker( "show" );
+ $( ".ui-calendar-calendar td:eq(29) a", dp).simulate( "click" );
+ equal(inp.val(), "10/27/2008", "Daylight saving - Lebanon 10/27/2008" );
// US, Eastern - AM change, northern hemisphere
- inp.val("03/01/2008").datepicker("show");
- $(".ui-datepicker-calendar td:eq(13) a", dp).simulate("click");
- equal(inp.val(), "03/08/2008", "Daylight saving - US 03/08/2008");
- inp.val("03/01/2008").datepicker("show");
- $(".ui-datepicker-calendar td:eq(14) a", dp).simulate("click");
- equal(inp.val(), "03/09/2008", "Daylight saving - US 03/09/2008");
- inp.val("03/01/2008").datepicker("show");
- $(".ui-datepicker-calendar td:eq(15) a", dp).simulate("click");
- equal(inp.val(), "03/10/2008", "Daylight saving - US 03/10/2008");
- inp.val("11/01/2008").datepicker("show");
- $(".ui-datepicker-calendar td:eq(6) a", dp).simulate("click");
- equal(inp.val(), "11/01/2008", "Daylight saving - US 11/01/2008");
- inp.val("11/01/2008").datepicker("show");
- $(".ui-datepicker-calendar td:eq(7) a", dp).simulate("click");
- equal(inp.val(), "11/02/2008", "Daylight saving - US 11/02/2008");
- inp.val("11/01/2008").datepicker("show");
- $(".ui-datepicker-calendar td:eq(8) a", dp).simulate("click");
- equal(inp.val(), "11/03/2008", "Daylight saving - US 11/03/2008");
-});
-
-var beforeShowThis = null,
- beforeShowInput = null,
- beforeShowInst = null,
- beforeShowDayThis = null,
- beforeShowDayOK = true;
-
-
-function beforeAll(input, inst) {
- beforeShowThis = this;
- beforeShowInput = input;
- beforeShowInst = inst;
- return {currentText: "Current"};
-}
-
-function beforeDay(date) {
- beforeShowDayThis = this;
- beforeShowDayOK &= (date > new Date(2008, 1 - 1, 26) &&
- date < new Date(2008, 3 - 1, 6));
- return [(date.getDate() % 2 === 0), (date.getDate() % 10 === 0 ? "day10" : ""),
- (date.getDate() % 3 === 0 ? "Divisble by 3" : "")];
-}
-
-test("callbacks", function() {
- expect( 13 );
- // Before show
- var dp, day20, day21,
- inp = TestHelpers.datepicker.init("#inp", {beforeShow: beforeAll}),
- inst = $.data(inp[0], "datepicker");
- equal($.datepicker._get(inst, "currentText"), "Today", "Before show - initial");
- inp.val("02/04/2008").datepicker("show");
- equal($.datepicker._get(inst, "currentText"), "Current", "Before show - changed");
- ok(beforeShowThis.id === inp[0].id, "Before show - this OK");
- ok(beforeShowInput.id === inp[0].id, "Before show - input OK");
- deepEqual(beforeShowInst, inst, "Before show - inst OK");
- inp.datepicker("hide").datepicker("destroy");
- // Before show day
- inp = TestHelpers.datepicker.init("#inp", {beforeShowDay: beforeDay});
- dp = $("#ui-datepicker-div");
- inp.val("02/04/2008").datepicker("show");
- ok(beforeShowDayThis.id === inp[0].id, "Before show day - this OK");
- ok(beforeShowDayOK, "Before show day - dates OK");
- day20 = dp.find(".ui-datepicker-calendar td:contains('20')");
- day21 = dp.find(".ui-datepicker-calendar td:contains('21')");
- ok(!day20.is(".ui-datepicker-unselectable"), "Before show day - unselectable 20");
- ok(day21.is(".ui-datepicker-unselectable"), "Before show day - unselectable 21");
- ok(day20.is(".day10"), "Before show day - CSS 20");
- ok(!day21.is(".day10"), "Before show day - CSS 21");
- ok(!day20.attr("title"), "Before show day - title 20");
- ok(day21.attr("title") === "Divisble by 3", "Before show day - title 21");
- inp.datepicker("hide").datepicker("destroy");
-});
-
-test("beforeShowDay - tooltips with quotes", function() {
- expect( 1 );
- var inp, dp;
- inp = TestHelpers.datepicker.init("#inp", {
- beforeShowDay: function() {
- return [ true, "", "'" ];
- }
- });
- dp = $("#ui-datepicker-div");
-
- inp.datepicker("show");
- equal( dp.find( ".ui-datepicker-calendar td:contains('9')").attr( "title" ), "'" );
- inp.datepicker("hide").datepicker("destroy");
-});
-
-test("localisation", function() {
- expect( 24 );
- var dp, month, day, date,
- inp = TestHelpers.datepicker.init("#inp", $.datepicker.regional.fr);
- inp.datepicker("option", {dateFormat: "DD, d MM yy", showButtonPanel:true, changeMonth:true, changeYear:true}).val("").datepicker("show");
- dp = $("#ui-datepicker-div");
- equal($(".ui-datepicker-close", dp).text(), "Fermer", "Localisation - close");
- $(".ui-datepicker-close", dp).simulate("mouseover");
- equal($(".ui-datepicker-prev", dp).text(), "Précédent", "Localisation - previous");
- equal($(".ui-datepicker-current", dp).text(), "Aujourd'hui", "Localisation - current");
- equal($(".ui-datepicker-next", dp).text(), "Suivant", "Localisation - next");
- month = 0;
- $(".ui-datepicker-month option", dp).each(function() {
- equal($(this).text(), $.datepicker.regional.fr.monthNamesShort[month],
- "Localisation - month " + month);
- month++;
- });
- day = 1;
- $(".ui-datepicker-calendar th", dp).each(function() {
- equal($(this).text(), $.datepicker.regional.fr.dayNamesMin[day],
- "Localisation - day " + day);
- day = (day + 1) % 7;
- });
- inp.simulate("keydown", {keyCode: $.ui.keyCode.ENTER});
- date = new Date();
- equal(inp.val(), $.datepicker.regional.fr.dayNames[date.getDay()] + ", " +
- date.getDate() + " " + $.datepicker.regional.fr.monthNames[date.getMonth()] +
- " " + date.getFullYear(), "Localisation - formatting");
-});
-
-test("noWeekends", function() {
- expect( 31 );
- var i, date;
- for (i = 1; i <= 31; i++) {
- date = new Date(2001, 1 - 1, i);
- deepEqual($.datepicker.noWeekends(date), [(i + 1) % 7 >= 2, ""],
- "No weekends " + date);
- }
-});
-
-test("iso8601Week", function() {
- expect( 12 );
- var date = new Date(2000, 12 - 1, 31);
- equal($.datepicker.iso8601Week(date), 52, "ISO 8601 week " + date);
- date = new Date(2001, 1 - 1, 1);
- equal($.datepicker.iso8601Week(date), 1, "ISO 8601 week " + date);
- date = new Date(2001, 1 - 1, 7);
- equal($.datepicker.iso8601Week(date), 1, "ISO 8601 week " + date);
- date = new Date(2001, 1 - 1, 8);
- equal($.datepicker.iso8601Week(date), 2, "ISO 8601 week " + date);
- date = new Date(2003, 12 - 1, 28);
- equal($.datepicker.iso8601Week(date), 52, "ISO 8601 week " + date);
- date = new Date(2003, 12 - 1, 29);
- equal($.datepicker.iso8601Week(date), 1, "ISO 8601 week " + date);
- date = new Date(2004, 1 - 1, 4);
- equal($.datepicker.iso8601Week(date), 1, "ISO 8601 week " + date);
- date = new Date(2004, 1 - 1, 5);
- equal($.datepicker.iso8601Week(date), 2, "ISO 8601 week " + date);
- date = new Date(2009, 12 - 1, 28);
- equal($.datepicker.iso8601Week(date), 53, "ISO 8601 week " + date);
- date = new Date(2010, 1 - 1, 3);
- equal($.datepicker.iso8601Week(date), 53, "ISO 8601 week " + date);
- date = new Date(2010, 1 - 1, 4);
- equal($.datepicker.iso8601Week(date), 1, "ISO 8601 week " + date);
- date = new Date(2010, 1 - 1, 10);
- equal($.datepicker.iso8601Week(date), 1, "ISO 8601 week " + date);
-});
-
-test("parseDate", function() {
- expect( 26 );
- TestHelpers.datepicker.init("#inp");
- var currentYear, gmtDate, fr, settings, zh;
- ok($.datepicker.parseDate("d m y", "") == null, "Parse date empty");
- TestHelpers.datepicker.equalsDate($.datepicker.parseDate("d m y", "3 2 01"),
- new Date(2001, 2 - 1, 3), "Parse date d m y");
- TestHelpers.datepicker.equalsDate($.datepicker.parseDate("dd mm yy", "03 02 2001"),
- new Date(2001, 2 - 1, 3), "Parse date dd mm yy");
- TestHelpers.datepicker.equalsDate($.datepicker.parseDate("d m y", "13 12 01"),
- new Date(2001, 12 - 1, 13), "Parse date d m y");
- TestHelpers.datepicker.equalsDate($.datepicker.parseDate("dd mm yy", "13 12 2001"),
- new Date(2001, 12 - 1, 13), "Parse date dd mm yy");
- TestHelpers.datepicker.equalsDate($.datepicker.parseDate("y-o", "01-34"),
- new Date(2001, 2 - 1, 3), "Parse date y-o");
- TestHelpers.datepicker.equalsDate($.datepicker.parseDate("yy-oo", "2001-347"),
- new Date(2001, 12 - 1, 13), "Parse date yy-oo");
- TestHelpers.datepicker.equalsDate($.datepicker.parseDate("oo yy", "348 2004"),
- new Date(2004, 12 - 1, 13), "Parse date oo yy");
- TestHelpers.datepicker.equalsDate($.datepicker.parseDate("D d M y", "Sat 3 Feb 01"),
- new Date(2001, 2 - 1, 3), "Parse date D d M y");
- TestHelpers.datepicker.equalsDate($.datepicker.parseDate("d MM DD yy", "3 February Saturday 2001"),
- new Date(2001, 2 - 1, 3), "Parse date dd MM DD yy");
- TestHelpers.datepicker.equalsDate($.datepicker.parseDate("DD, MM d, yy", "Saturday, February 3, 2001"),
- new Date(2001, 2 - 1, 3), "Parse date DD, MM d, yy");
- TestHelpers.datepicker.equalsDate($.datepicker.parseDate("'day' d 'of' MM (''DD''), yy",
- "day 3 of February ('Saturday'), 2001"), new Date(2001, 2 - 1, 3),
- "Parse date 'day' d 'of' MM (''DD''), yy");
- currentYear = new Date().getFullYear();
- TestHelpers.datepicker.equalsDate($.datepicker.parseDate("y-m-d", (currentYear - 2000) + "-02-03"),
- new Date(currentYear, 2 - 1, 3), "Parse date y-m-d - default cutuff");
- TestHelpers.datepicker.equalsDate($.datepicker.parseDate("y-m-d", (currentYear - 2000 + 10) + "-02-03"),
- new Date(currentYear+10, 2 - 1, 3), "Parse date y-m-d - default cutuff");
- TestHelpers.datepicker.equalsDate($.datepicker.parseDate("y-m-d", (currentYear - 2000 + 11) + "-02-03"),
- new Date(currentYear-89, 2 - 1, 3), "Parse date y-m-d - default cutuff");
- TestHelpers.datepicker.equalsDate($.datepicker.parseDate("y-m-d", "80-02-03", {shortYearCutoff: 80}),
- new Date(2080, 2 - 1, 3), "Parse date y-m-d - cutoff 80");
- TestHelpers.datepicker.equalsDate($.datepicker.parseDate("y-m-d", "81-02-03", {shortYearCutoff: 80}),
- new Date(1981, 2 - 1, 3), "Parse date y-m-d - cutoff 80");
- TestHelpers.datepicker.equalsDate($.datepicker.parseDate("y-m-d", (currentYear - 2000 + 60) + "-02-03", {shortYearCutoff: "+60"}),
- new Date(currentYear + 60, 2 - 1, 3), "Parse date y-m-d - cutoff +60");
- TestHelpers.datepicker.equalsDate($.datepicker.parseDate("y-m-d", (currentYear - 2000 + 61) + "-02-03", {shortYearCutoff: "+60"}),
- new Date(currentYear - 39, 2 - 1, 3), "Parse date y-m-d - cutoff +60");
- gmtDate = new Date(2001, 2 - 1, 3);
- gmtDate.setMinutes(gmtDate.getMinutes() - gmtDate.getTimezoneOffset());
- TestHelpers.datepicker.equalsDate($.datepicker.parseDate("@", "981158400000"), gmtDate, "Parse date @");
- TestHelpers.datepicker.equalsDate($.datepicker.parseDate("!", "631167552000000000"), gmtDate, "Parse date !");
-
- fr = $.datepicker.regional.fr;
- settings = {dayNamesShort: fr.dayNamesShort, dayNames: fr.dayNames,
- monthNamesShort: fr.monthNamesShort, monthNames: fr.monthNames};
- TestHelpers.datepicker.equalsDate($.datepicker.parseDate("D d M y", "Lun. 9 Avril 01", settings),
- new Date(2001, 4 - 1, 9), "Parse date D M y with settings");
- TestHelpers.datepicker.equalsDate($.datepicker.parseDate("d MM DD yy", "9 Avril Lundi 2001", settings),
- new Date(2001, 4 - 1, 9), "Parse date d MM DD yy with settings");
- TestHelpers.datepicker.equalsDate($.datepicker.parseDate("DD, MM d, yy", "Lundi, Avril 9, 2001", settings),
- new Date(2001, 4 - 1, 9), "Parse date DD, MM d, yy with settings");
- TestHelpers.datepicker.equalsDate($.datepicker.parseDate("'jour' d 'de' MM (''DD''), yy", "jour 9 de Avril ('Lundi'), 2001", settings),
- new Date(2001, 4 - 1, 9), "Parse date 'jour' d 'de' MM (''DD''), yy with settings");
-
- zh = $.datepicker.regional["zh-CN"];
- TestHelpers.datepicker.equalsDate($.datepicker.parseDate("yy M d", "2011 十一月 22", zh),
- new Date(2011, 11 - 1, 22), "Parse date yy M d with zh-CN");
+ inp.val( "03/01/2008" ).datepicker( "show" );
+ $( ".ui-calendar-calendar td:eq(13) a", dp).simulate( "click" );
+ equal(inp.val(), "03/08/2008", "Daylight saving - US 03/08/2008" );
+ inp.val( "03/01/2008" ).datepicker( "show" );
+ $( ".ui-calendar-calendar td:eq(14) a", dp).simulate( "click" );
+ equal(inp.val(), "03/09/2008", "Daylight saving - US 03/09/2008" );
+ inp.val( "03/01/2008" ).datepicker( "show" );
+ $( ".ui-calendar-calendar td:eq(15) a", dp).simulate( "click" );
+ equal(inp.val(), "03/10/2008", "Daylight saving - US 03/10/2008" );
+ inp.val( "11/01/2008" ).datepicker( "show" );
+ $( ".ui-calendar-calendar td:eq(6) a", dp).simulate( "click" );
+ equal(inp.val(), "11/01/2008", "Daylight saving - US 11/01/2008" );
+ inp.val( "11/01/2008" ).datepicker( "show" );
+ $( ".ui-calendar-calendar td:eq(7) a", dp).simulate( "click" );
+ equal(inp.val(), "11/02/2008", "Daylight saving - US 11/02/2008" );
+ inp.val( "11/01/2008" ).datepicker( "show" );
+ $( ".ui-calendar-calendar td:eq(8) a", dp).simulate( "click" );
+ equal(inp.val(), "11/03/2008", "Daylight saving - US 11/03/2008" );
});
+ */
-test("parseDateErrors", function() {
- expect( 17 );
- TestHelpers.datepicker.init("#inp");
- var fr, settings;
- function expectError(expr, value, error) {
- try {
- expr();
- ok(false, "Parsed error " + value);
- }
- catch (e) {
- equal(e, error, "Parsed error " + value);
- }
- }
- expectError(function() { $.datepicker.parseDate(null, "Sat 2 01"); },
- "Sat 2 01", "Invalid arguments");
- expectError(function() { $.datepicker.parseDate("d m y", null); },
- "null", "Invalid arguments");
- expectError(function() { $.datepicker.parseDate("d m y", "Sat 2 01"); },
- "Sat 2 01 - d m y", "Missing number at position 0");
- expectError(function() { $.datepicker.parseDate("dd mm yy", "Sat 2 01"); },
- "Sat 2 01 - dd mm yy", "Missing number at position 0");
- expectError(function() { $.datepicker.parseDate("d m y", "3 Feb 01"); },
- "3 Feb 01 - d m y", "Missing number at position 2");
- expectError(function() { $.datepicker.parseDate("dd mm yy", "3 Feb 01"); },
- "3 Feb 01 - dd mm yy", "Missing number at position 2");
- expectError(function() { $.datepicker.parseDate("d m y", "3 2 AD01"); },
- "3 2 AD01 - d m y", "Missing number at position 4");
- expectError(function() { $.datepicker.parseDate("d m yy", "3 2 AD01"); },
- "3 2 AD01 - dd mm yy", "Missing number at position 4");
- expectError(function() { $.datepicker.parseDate("y-o", "01-D01"); },
- "2001-D01 - y-o", "Missing number at position 3");
- expectError(function() { $.datepicker.parseDate("yy-oo", "2001-D01"); },
- "2001-D01 - yy-oo", "Missing number at position 5");
- expectError(function() { $.datepicker.parseDate("D d M y", "D7 3 Feb 01"); },
- "D7 3 Feb 01 - D d M y", "Unknown name at position 0");
- expectError(function() { $.datepicker.parseDate("D d M y", "Sat 3 M2 01"); },
- "Sat 3 M2 01 - D d M y", "Unknown name at position 6");
- expectError(function() { $.datepicker.parseDate("DD, MM d, yy", "Saturday- Feb 3, 2001"); },
- "Saturday- Feb 3, 2001 - DD, MM d, yy", "Unexpected literal at position 8");
- expectError(function() { $.datepicker.parseDate("'day' d 'of' MM (''DD''), yy",
- "day 3 of February (\"Saturday\"), 2001"); },
- "day 3 of Mon2 ('Day7'), 2001", "Unexpected literal at position 19");
- expectError(function() { $.datepicker.parseDate("d m y", "29 2 01"); },
- "29 2 01 - d m y", "Invalid date");
- fr = $.datepicker.regional.fr;
- settings = {dayNamesShort: fr.dayNamesShort, dayNames: fr.dayNames,
- monthNamesShort: fr.monthNamesShort, monthNames: fr.monthNames};
- expectError(function() { $.datepicker.parseDate("D d M y", "Mon 9 Avr 01", settings); },
- "Mon 9 Avr 01 - D d M y", "Unknown name at position 0");
- expectError(function() { $.datepicker.parseDate("D d M y", "Lun. 9 Apr 01", settings); },
- "Lun. 9 Apr 01 - D d M y", "Unknown name at position 7");
-});
-
-test("Ticket #7244: date parser does not fail when too many numbers are passed into the date function", function() {
- expect( 4 );
- var date;
- try{
- date = $.datepicker.parseDate("dd/mm/yy", "18/04/19881");
- ok(false, "Did not properly detect an invalid date");
- }catch(e){
- ok("invalid date detected");
- }
-
- try {
- date = $.datepicker.parseDate("dd/mm/yy", "18/04/1988 @ 2:43 pm");
- equal(date.getDate(), 18);
- equal(date.getMonth(), 3);
- equal(date.getFullYear(), 1988);
- } catch(e) {
- ok(false, "Did not properly parse date with extra text separated by whitespace");
- }
-});
-
-test("formatDate", function() {
- expect( 16 );
- TestHelpers.datepicker.init("#inp");
- var gmtDate, fr, settings;
- equal($.datepicker.formatDate("d m y", new Date(2001, 2 - 1, 3)),
- "3 2 01", "Format date d m y");
- equal($.datepicker.formatDate("dd mm yy", new Date(2001, 2 - 1, 3)),
- "03 02 2001", "Format date dd mm yy");
- equal($.datepicker.formatDate("d m y", new Date(2001, 12 - 1, 13)),
- "13 12 01", "Format date d m y");
- equal($.datepicker.formatDate("dd mm yy", new Date(2001, 12 - 1, 13)),
- "13 12 2001", "Format date dd mm yy");
- equal($.datepicker.formatDate("yy-o", new Date(2001, 2 - 1, 3)),
- "2001-34", "Format date yy-o");
- equal($.datepicker.formatDate("yy-oo", new Date(2001, 2 - 1, 3)),
- "2001-034", "Format date yy-oo");
- equal($.datepicker.formatDate("D M y", new Date(2001, 2 - 1, 3)),
- "Sat Feb 01", "Format date D M y");
- equal($.datepicker.formatDate("DD MM yy", new Date(2001, 2 - 1, 3)),
- "Saturday February 2001", "Format date DD MM yy");
- equal($.datepicker.formatDate("DD, MM d, yy", new Date(2001, 2 - 1, 3)),
- "Saturday, February 3, 2001", "Format date DD, MM d, yy");
- equal($.datepicker.formatDate("'day' d 'of' MM (''DD''), yy",
- new Date(2001, 2 - 1, 3)), "day 3 of February ('Saturday'), 2001",
- "Format date 'day' d 'of' MM ('DD'), yy");
- gmtDate = new Date(2001, 2 - 1, 3);
- gmtDate.setMinutes(gmtDate.getMinutes() - gmtDate.getTimezoneOffset());
- equal($.datepicker.formatDate("@", gmtDate), "981158400000", "Format date @");
- equal($.datepicker.formatDate("!", gmtDate), "631167552000000000", "Format date !");
- fr = $.datepicker.regional.fr;
- settings = {dayNamesShort: fr.dayNamesShort, dayNames: fr.dayNames,
- monthNamesShort: fr.monthNamesShort, monthNames: fr.monthNames};
- equal($.datepicker.formatDate("D M y", new Date(2001, 4 - 1, 9), settings),
- "lun. avril 01", "Format date D M y with settings");
- equal($.datepicker.formatDate("DD MM yy", new Date(2001, 4 - 1, 9), settings),
- "lundi avril 2001", "Format date DD MM yy with settings");
- equal($.datepicker.formatDate("DD, MM d, yy", new Date(2001, 4 - 1, 9), settings),
- "lundi, avril 9, 2001", "Format date DD, MM d, yy with settings");
- equal($.datepicker.formatDate("'jour' d 'de' MM (''DD''), yy",
- new Date(2001, 4 - 1, 9), settings), "jour 9 de avril ('lundi'), 2001",
- "Format date 'jour' d 'de' MM (''DD''), yy with settings");
-});
-
-// TODO: Fix this test so it isn't mysteriously flaky in Browserstack on certain OS/Browser combos
-// test("Ticket 6827: formatDate day of year calculation is wrong during day lights savings time", function(){
-// expect( 1 );
-// var time = $.datepicker.formatDate("oo", new Date("2010/03/30 12:00:00 CDT"));
-// equal(time, "089");
-// });
-
-test( "Ticket 7602: Stop datepicker from appearing with beforeShow event handler", function() {
+test( "Ticket 7602: Stop datepicker from appearing with beforeOpen event handler", function() {
expect( 3 );
- var inp, dp;
-
- inp = TestHelpers.datepicker.init( "#inp", {
- beforeShow: function() {
+ var input = TestHelpers.datepicker.init( "#datepicker", {
+ beforeOpen: function() {
}
});
- dp = $( "#ui-datepicker-div" );
- inp.datepicker( "show" );
- equal( dp.css( "display" ), "block", "beforeShow returns nothing" );
- inp.datepicker( "hide" ).datepicker( "destroy" );
- inp = TestHelpers.datepicker.init( "#inp", {
- beforeShow: function() {
+ input.datepicker( "open" );
+ equal( input.datepicker( "widget" ).css( "display" ), "block", "beforeOpen returns nothing" );
+ input.datepicker( "close" ).datepicker( "destroy" );
+
+ input = TestHelpers.datepicker.init( "#datepicker", {
+ beforeOpen: function() {
return true;
}
});
- dp = $( "#ui-datepicker-div" );
- inp.datepicker( "show" );
- equal( dp.css( "display" ), "block", "beforeShow returns true" );
- inp.datepicker( "hide" );
- inp.datepicker( "destroy" );
-
- inp = TestHelpers.datepicker.init( "#inp", {
- beforeShow: function() {
+ input.datepicker( "open" );
+ equal( input.datepicker( "widget" ).css( "display" ), "block", "beforeOpen returns true" );
+ input.datepicker( "close" ).datepicker( "destroy" );
+
+ input = TestHelpers.datepicker.init( "#datepicker", {
+ beforeOpen: function() {
return false;
}
});
- dp = $( "#ui-datepicker-div" );
- inp.datepicker( "show" );
- equal( dp.css( "display" ), "none","beforeShow returns false" );
- inp.datepicker( "destroy" );
+ input.datepicker( "open" );
+ equal( input.datepicker( "widget" ).css( "display" ), "none", "beforeOpen returns false" );
+ input.datepicker( "destroy" );
});
})(jQuery);
diff --git a/tests/unit/datepicker/datepicker_test_helpers.js b/tests/unit/datepicker/datepicker_test_helpers.js
index 34b41bbc6a5..f62e086b974 100644
--- a/tests/unit/datepicker/datepicker_test_helpers.js
+++ b/tests/unit/datepicker/datepicker_test_helpers.js
@@ -1,27 +1,26 @@
TestHelpers.datepicker = {
- addMonths: function(date, offset) {
- var maxDay = 32 - new Date(date.getFullYear(), date.getMonth() + offset, 32).getDate();
- date.setDate(Math.min(date.getDate(), maxDay));
- date.setMonth(date.getMonth() + offset);
+ addMonths: function( date, offset ) {
+ var maxDay = 32 - new Date( date.getFullYear(), date.getMonth() + offset, 32 ).getDate();
+ date.setDate( Math.min( date.getDate(), maxDay ) );
+ date.setMonth( date.getMonth() + offset );
return date;
},
- equalsDate: function(d1, d2, message) {
- if (!d1 || !d2) {
- ok(false, message + " - missing date");
+ equalsDate: function( d1, d2, message ) {
+ if ( !d1 || !d2 ) {
+ ok( false, message + " - missing date" );
return;
}
- d1 = new Date(d1.getFullYear(), d1.getMonth(), d1.getDate());
- d2 = new Date(d2.getFullYear(), d2.getMonth(), d2.getDate());
- equal(d1.toString(), d2.toString(), message);
+ d1 = new Date( d1.getFullYear(), d1.getMonth(), d1.getDate() );
+ d2 = new Date( d2.getFullYear(), d2.getMonth(), d2.getDate() );
+ equal( d1.toString(), d2.toString(), message );
},
init: function( id, options ) {
- $.datepicker.setDefaults( $.datepicker.regional[ "" ] );
- return $( id ).datepicker( $.extend( { showAnim: "" }, options || {} ) );
+ options = $.extend( { show: false, hide: false }, options || {} );
+ return $( id ).datepicker( options );
},
initNewInput: function( options ) {
- var id = $( "
" ).appendTo( "#qunit-fixture" );
- return TestHelpers.datepicker.init( id, options );
- },
- onFocus: TestHelpers.onFocus,
- PROP_NAME: "datepicker"
+ options = $.extend( { show: false, hide: false }, options || {} );
+ return $( "
" ).datepicker( options )
+ .appendTo( "#qunit-fixture" );
+ }
};
\ No newline at end of file
diff --git a/tests/unit/index.html b/tests/unit/index.html
index bd48590ec37..842ba7e6a8d 100644
--- a/tests/unit/index.html
+++ b/tests/unit/index.html
@@ -39,6 +39,7 @@
Widgets
Accordion
Autocomplete
+ Calendar
Button
Datepicker
Dialog
diff --git a/themes/base/base.css b/themes/base/base.css
index 479c3279d9b..b9adae8899c 100644
--- a/themes/base/base.css
+++ b/themes/base/base.css
@@ -13,6 +13,7 @@
@import url("accordion.css");
@import url("autocomplete.css");
@import url("button.css");
+@import url("calendar.css");
@import url("datepicker.css");
@import url("dialog.css");
@import url("draggable.css");
diff --git a/themes/base/calendar.css b/themes/base/calendar.css
new file mode 100644
index 00000000000..5925814bbff
--- /dev/null
+++ b/themes/base/calendar.css
@@ -0,0 +1,179 @@
+/*!
+ * jQuery UI Calendar @VERSION
+ * http://jqueryui.com
+ *
+ * Copyright 2014 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/calendar/#theming
+ */
+.ui-calendar {
+ width: 17em;
+ padding: .2em .2em 0;
+}
+.ui-calendar .ui-calendar-header {
+ position: relative;
+ padding: .2em 0;
+}
+.ui-calendar .ui-calendar-prev,
+.ui-calendar .ui-calendar-next {
+ position: absolute;
+ top: 2px;
+ width: 19px;
+ height: 18px;
+}
+.ui-calendar .ui-calendar-prev:not(.ui-state-hover):not(.ui-state-focus),
+.ui-calendar .ui-calendar-next:not(.ui-state-hover):not(.ui-state-focus) {
+ background: none;
+ border: none;
+}
+.ui-calendar .ui-calendar-prev-hover,
+.ui-calendar .ui-calendar-next-hover {
+ top: 1px;
+}
+.ui-calendar .ui-calendar-prev {
+ left: 2px;
+}
+.ui-calendar .ui-calendar-next {
+ right: 2px;
+}
+.ui-calendar .ui-calendar-prev-hover {
+ left: 1px;
+}
+.ui-calendar .ui-calendar-next-hover {
+ right: 1px;
+}
+.ui-calendar .ui-calendar-prev .ui-icon,
+.ui-calendar .ui-calendar-next .ui-icon {
+ display: block;
+ position: absolute;
+ left: 50%;
+ margin-left: -8px;
+ top: 50%;
+ margin-top: -8px;
+}
+.ui-calendar .ui-calendar-title {
+ line-height: 1.8em;
+ text-align: center;
+}
+.ui-calendar .ui-calendar-title select {
+ font-size: 1em;
+ margin: 1px 0;
+}
+.ui-calendar select.ui-calendar-month,
+.ui-calendar select.ui-calendar-year {
+ width: 49%;
+}
+.ui-calendar table {
+ width: 100%;
+ font-size: .9em;
+ border-collapse: collapse;
+ margin: 0 0 .4em;
+}
+.ui-calendar th {
+ padding: .7em .3em;
+ text-align: center;
+ font-weight: bold;
+ border: 0;
+}
+.ui-calendar td {
+ border: 0;
+ padding: 1px;
+}
+.ui-calendar td span,
+.ui-calendar td a {
+ display: block;
+ padding: .2em;
+ text-align: right;
+ text-decoration: none;
+}
+.ui-calendar .ui-calendar-buttonpane {
+ background-image: none;
+ margin: .7em 0 0 0;
+ padding: 0 .2em;
+ border-left: 0;
+ border-right: 0;
+ border-bottom: 0;
+}
+.ui-calendar .ui-calendar-buttonpane button {
+ float: right;
+ margin: .5em .2em .4em;
+ cursor: pointer;
+ padding: .2em .6em .3em .6em;
+ width: auto;
+ overflow: visible;
+}
+.ui-calendar .ui-calendar-buttonpane button.ui-calendar-current {
+ float: left;
+}
+
+/* with multiple calendars */
+.ui-calendar.ui-calendar-multi {
+ width: auto;
+ display: inline-block;
+}
+.ui-calendar-multi .ui-calendar-group {
+ float: left;
+}
+.ui-calendar-multi .ui-calendar-group table {
+ width: 95%;
+ margin: 0 2.5% .4em;
+}
+.ui-calendar-multi-2 .ui-calendar-group {
+ width: 50%;
+}
+.ui-calendar-multi-3 .ui-calendar-group {
+ width: 33.3%;
+}
+.ui-calendar-multi-4 .ui-calendar-group {
+ width: 25%;
+}
+.ui-calendar-multi .ui-calendar-group-last .ui-calendar-header,
+.ui-calendar-multi .ui-calendar-group-middle .ui-calendar-header {
+ border-left-width: 0;
+}
+.ui-calendar-multi .ui-calendar-buttonpane {
+ clear: left;
+}
+.ui-calendar-row-break {
+ clear: both;
+ width: 100%;
+ font-size: 0;
+}
+
+/* RTL support */
+.ui-calendar-rtl {
+ direction: rtl;
+}
+.ui-calendar-rtl .ui-calendar-prev {
+ right: 2px;
+ left: auto;
+}
+.ui-calendar-rtl .ui-calendar-next {
+ left: 2px;
+ right: auto;
+}
+.ui-calendar-rtl .ui-calendar-prev:hover {
+ right: 1px;
+ left: auto;
+}
+.ui-calendar-rtl .ui-calendar-next:hover {
+ left: 1px;
+ right: auto;
+}
+.ui-calendar-rtl .ui-calendar-buttonpane {
+ clear: right;
+}
+.ui-calendar-rtl .ui-calendar-buttonpane button {
+ float: left;
+}
+.ui-calendar-rtl .ui-calendar-buttonpane button.ui-calendar-current,
+.ui-calendar-rtl .ui-calendar-group {
+ float: right;
+}
+.ui-calendar-rtl .ui-calendar-group-last .ui-calendar-header,
+.ui-calendar-rtl .ui-calendar-group-middle .ui-calendar-header {
+ border-right-width: 0;
+ border-left-width: 1px;
+}
diff --git a/themes/base/datepicker.css b/themes/base/datepicker.css
index 0cff00afe96..ac84f640dee 100644
--- a/themes/base/datepicker.css
+++ b/themes/base/datepicker.css
@@ -8,168 +8,7 @@
*
* http://api.jqueryui.com/datepicker/#theming
*/
-.ui-datepicker {
- width: 17em;
- padding: .2em .2em 0;
- display: none;
-}
-.ui-datepicker .ui-datepicker-header {
- position: relative;
- padding: .2em 0;
-}
-.ui-datepicker .ui-datepicker-prev,
-.ui-datepicker .ui-datepicker-next {
- position: absolute;
- top: 2px;
- width: 1.8em;
- height: 1.8em;
-}
-.ui-datepicker .ui-datepicker-prev-hover,
-.ui-datepicker .ui-datepicker-next-hover {
- top: 1px;
-}
-.ui-datepicker .ui-datepicker-prev {
- left: 2px;
-}
-.ui-datepicker .ui-datepicker-next {
- right: 2px;
-}
-.ui-datepicker .ui-datepicker-prev-hover {
- left: 1px;
-}
-.ui-datepicker .ui-datepicker-next-hover {
- right: 1px;
-}
-.ui-datepicker .ui-datepicker-prev span,
-.ui-datepicker .ui-datepicker-next span {
- display: block;
- position: absolute;
- left: 50%;
- margin-left: -8px;
- top: 50%;
- margin-top: -8px;
-}
-.ui-datepicker .ui-datepicker-title {
- margin: 0 2.3em;
- line-height: 1.8em;
- text-align: center;
-}
-.ui-datepicker .ui-datepicker-title select {
- font-size: 1em;
- margin: 1px 0;
-}
-.ui-datepicker select.ui-datepicker-month,
-.ui-datepicker select.ui-datepicker-year {
- width: 49%;
-}
-.ui-datepicker table {
- width: 100%;
- font-size: .9em;
- border-collapse: collapse;
- margin: 0 0 .4em;
-}
-.ui-datepicker th {
- padding: .7em .3em;
- text-align: center;
- font-weight: bold;
- border: 0;
-}
-.ui-datepicker td {
- border: 0;
- padding: 1px;
-}
-.ui-datepicker td span,
-.ui-datepicker td a {
- display: block;
- padding: .2em;
- text-align: right;
- text-decoration: none;
-}
-.ui-datepicker .ui-datepicker-buttonpane {
- background-image: none;
- margin: .7em 0 0 0;
- padding: 0 .2em;
- border-left: 0;
- border-right: 0;
- border-bottom: 0;
-}
-.ui-datepicker .ui-datepicker-buttonpane button {
- float: right;
- margin: .5em .2em .4em;
- cursor: pointer;
- padding: .2em .6em .3em .6em;
- width: auto;
- overflow: visible;
-}
-.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current {
- float: left;
-}
-
-/* with multiple calendars */
-.ui-datepicker.ui-datepicker-multi {
- width: auto;
-}
-.ui-datepicker-multi .ui-datepicker-group {
- float: left;
-}
-.ui-datepicker-multi .ui-datepicker-group table {
- width: 95%;
- margin: 0 auto .4em;
-}
-.ui-datepicker-multi-2 .ui-datepicker-group {
- width: 50%;
-}
-.ui-datepicker-multi-3 .ui-datepicker-group {
- width: 33.3%;
-}
-.ui-datepicker-multi-4 .ui-datepicker-group {
- width: 25%;
-}
-.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,
-.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header {
- border-left-width: 0;
-}
-.ui-datepicker-multi .ui-datepicker-buttonpane {
- clear: left;
-}
-.ui-datepicker-row-break {
- clear: both;
- width: 100%;
- font-size: 0;
-}
-
-/* RTL support */
-.ui-datepicker-rtl {
- direction: rtl;
-}
-.ui-datepicker-rtl .ui-datepicker-prev {
- right: 2px;
- left: auto;
-}
-.ui-datepicker-rtl .ui-datepicker-next {
- left: 2px;
- right: auto;
-}
-.ui-datepicker-rtl .ui-datepicker-prev:hover {
- right: 1px;
- left: auto;
-}
-.ui-datepicker-rtl .ui-datepicker-next:hover {
- left: 1px;
- right: auto;
-}
-.ui-datepicker-rtl .ui-datepicker-buttonpane {
- clear: right;
-}
-.ui-datepicker-rtl .ui-datepicker-buttonpane button {
- float: left;
-}
-.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,
-.ui-datepicker-rtl .ui-datepicker-group {
- float: right;
-}
-.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,
-.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header {
- border-right-width: 0;
- border-left-width: 1px;
-}
+.ui-datepicker.ui-calendar {
+ display: none;
+ position: absolute;
+}
\ No newline at end of file
diff --git a/ui/calendar.js b/ui/calendar.js
new file mode 100644
index 00000000000..8043b11fbd9
--- /dev/null
+++ b/ui/calendar.js
@@ -0,0 +1,544 @@
+/*!
+ * jQuery UI Calendar @VERSION
+ * http://jqueryui.com
+ *
+ * Copyright 2014 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/calendar/
+ */
+(function( factory ) {
+ if ( typeof define === "function" && define.amd ) {
+
+ // AMD. Register as an anonymous module.
+ // TODO: Add globalize and $.date?
+ define([
+ "jquery",
+ "./core",
+ "./widget",
+ "./button"
+ ], factory );
+ } else {
+
+ // Browser globals
+ factory( jQuery );
+ }
+}(function( $ ) {
+
+return $.widget( "ui.calendar", {
+ version: "@VERSION",
+ options: {
+ buttons: [],
+ dateFormat: { date: "short" },
+ // TODO: review
+ eachDay: $.noop,
+ max: null,
+ min: null,
+ numberOfMonths: 1,
+ showWeek: false,
+ value: null,
+
+ // callbacks
+ select: null
+ },
+
+ _create: function() {
+ this.id = this.element.uniqueId().attr( "id" );
+ this.labels = Globalize.translate( "datepicker" );
+
+ this.date = $.date( this.options.value, this.options.dateFormat ).select();
+ this.date.eachDay = this.options.eachDay;
+
+ this._on( this.element, {
+ "click .ui-calendar-prev": function( event ) {
+ event.preventDefault();
+ this.date.adjust( "M", -this.options.numberOfMonths );
+ this.refresh();
+ },
+ "click .ui-calendar-next": function( event ) {
+ event.preventDefault();
+ this.date.adjust( "M", this.options.numberOfMonths );
+ this.refresh();
+ },
+ "mousedown .ui-calendar-calendar a": function( event ) {
+ event.preventDefault();
+ // TODO: exclude clicks on lead days or handle them correctly
+ // TODO: store/read more then just date, also required for multi month picker
+ this._select( event, $( event.currentTarget ).data( "timestamp" ) );
+ this.grid.focus( 1 );
+ },
+ "keydown .ui-calendar-calendar": "_handleKeydown"
+ });
+
+ this.element.on( "mouseenter.calendar mouseleave.calendar", ".ui-calendar-header a, .ui-calendar-calendar a", function() {
+ $( this ).toggleClass( "ui-state-hover" );
+ });
+
+ this._createCalendar();
+ },
+
+ _handleKeydown: function( event ) {
+ if ( jQuery.inArray( event.keyCode, [ 13, 33, 34, 35, 36, 37, 38, 39, 40 ] ) === -1 ) {
+ // only interested navigation keys
+ return;
+ }
+ event.preventDefault();
+
+ var activeCell = $( "#" + this.grid.attr( "aria-activedescendant" ) ),
+ oldMonth = this.date.month(),
+ oldYear = this.date.year();
+
+ // TODO: Handle for pickers with multiple months
+ switch ( event.keyCode ) {
+ case $.ui.keyCode.ENTER:
+ activeCell.children( "a:first" ).mousedown();
+ return;
+ case $.ui.keyCode.PAGE_UP:
+ this.date.adjust( event.altKey ? "Y" : "M", -1 );
+ break;
+ case $.ui.keyCode.PAGE_DOWN:
+ this.date.adjust( event.altKey ? "Y" : "M", 1 );
+ break;
+ case $.ui.keyCode.END:
+ this.date.setDay( this.date.daysInMonth() );
+ break;
+ case $.ui.keyCode.HOME:
+ this.date.setDay( 1 );
+ break;
+ case $.ui.keyCode.LEFT:
+ this.date.adjust( "D", -1 );
+ break;
+ case $.ui.keyCode.UP:
+ this.date.adjust( "D", -7 );
+ break;
+ case $.ui.keyCode.RIGHT:
+ this.date.adjust( "D", 1 );
+ break;
+ case $.ui.keyCode.DOWN:
+ this.date.adjust( "D", 7 );
+ break;
+ default:
+ return;
+ }
+
+ if ( this.date.month() !== oldMonth || this.date.year() !== oldYear ) {
+ this.refresh();
+ this.grid.focus( 1 );
+ }
+
+ this._setActiveDescendant();
+ },
+
+ _setActiveDescendant: function() {
+ var id = this.id + "-" + this.date.day();
+
+ this.grid
+ .attr( "aria-activedescendant", id )
+ .find( ".ui-state-focus" )
+ .removeClass( "ui-state-focus" );
+ $( "#" + id + " > a" ).addClass( "ui-state-focus" );
+ },
+
+ _createCalendar: function() {
+ var classes = "ui-calendar ui-widget ui-widget-content ui-helper-clearfix ui-corner-all",
+ pickerHtml = "";
+
+ if ( this.options.numberOfMonths === 1 ) {
+ pickerHtml = this._buildHeader() + this._buildGrid();
+ } else {
+ pickerHtml = this._buildMultiplePicker();
+ classes += " ui-calendar-multi";
+ }
+
+ this.element
+ .addClass( classes )
+ .attr({
+ role: "region",
+ "aria-labelledby": this.id + "-title"
+ })
+ .html( pickerHtml );
+
+ this._createButtonPane();
+
+ this.element.find( "button" ).button();
+
+ this.grid = this.element.find( ".ui-calendar-calendar" );
+ },
+
+ _buildMultiplePicker: function() {
+ var headerClass,
+ html = "",
+ currentDate = this.date,
+ months = this.date.months( this.options.numberOfMonths - 1 ),
+ i = 0;
+
+ for ( i; i < months.length; i++ ) {
+ // TODO: Shouldn't we pass date as a parameter to build* fns instead of setting this.date?
+ this.date = months[ i ];
+ headerClass = months[ i ].first ? "ui-corner-left" :
+ months[ i ].last ? "ui-corner-right" : "";
+
+ html += "" +
+ "";
+ html += this._buildGrid();
+ html += "
";
+ }
+
+ html += "
";
+
+ this.date = currentDate;
+
+ return html;
+ },
+
+ _buildHeader: function() {
+ return "";
+ },
+
+ _buildPreviousLink: function() {
+ return "" +
+ "" +
+ this.labels.prevText +
+ " " +
+ " ";
+ },
+
+ _buildNextLink: function() {
+ return "" +
+ "" +
+ this.labels.nextText +
+ " " +
+ " ";
+ },
+
+ _buildTitlebar: function() {
+ return "" +
+ "
" +
+ this._buildTitle() +
+ "
" +
+ "
, " +
+ this.labels.datePickerRole +
+ " " +
+ "
";
+ },
+
+ _buildTitle: function() {
+ return "" +
+ this.date.monthName() +
+ " " +
+ "" +
+ this.date.year() +
+ " ";
+ },
+
+ _buildGrid: function() {
+ return "" +
+ this._buildGridHeading() +
+ this._buildGridBody() +
+ "
";
+ },
+
+ _buildGridHeading: function() {
+ var cells = "",
+ i = 0;
+
+ if ( this.options.showWeek ) {
+ cells += "" + this.labels.weekHeader + " ";
+ }
+ for ( i; i < this.date.weekdays().length; i++ ) {
+ cells += this._buildGridHeaderCell( this.date.weekdays()[i] );
+ }
+
+ return "" +
+ "" + cells + " " +
+ " ";
+ },
+
+ _buildGridHeaderCell: function( day ) {
+ return "" +
+ "" +
+ day.shortname +
+ " " +
+ " ";
+ },
+
+ _buildGridBody: function() {
+ // TODO: this.date.days() is not cached, and it has O(n^2) complexity. It is run O(n) times.
+ // So, it equals O(n^3). Not good at all. Caching.
+ var days = this.date.days(),
+ i = 0,
+ rows = "";
+
+ for ( i; i < days.length; i++ ) {
+ rows += this._buildWeekRow( days[ i ] );
+ }
+
+ return "" + rows + " ";
+ },
+
+ _buildWeekRow: function( week ) {
+ var cells = "",
+ i = 0;
+
+ if ( this.options.showWeek ) {
+ cells += "" + week.number + " ";
+ }
+ for ( i; i < week.days.length; i++ ) {
+ cells += this._buildDayCell( week.days[i] );
+ }
+
+ return "" + cells + " ";
+ },
+
+ _buildDayCell: function( day ) {
+ var content = "",
+ attributes = [
+ "role='gridcell'",
+ "aria-selected='" + ( day.current ? true : false ) + "'"
+ ],
+ selectable = ( day.selectable && this._isValid( new Date( day.timestamp ) ) );
+
+ if ( day.render ) {
+ attributes.push( "id='" + this.id + "-" + day.date + "'" );
+
+ if ( !selectable ) {
+ attributes.push( "aria-disabled='true'" );
+ attributes.push( "class='ui-state-disabled'" );
+ }
+
+ content = this._buildDayElement( day, selectable );
+ }
+
+ return "" + content + " ";
+ },
+
+ _buildDayElement: function( day, selectable ) {
+ var classes = [ "ui-state-default" ],
+ content = "";
+
+ if ( day === this.date && selectable ) {
+ classes.push( "ui-state-focus" );
+ }
+ if ( day.current ) {
+ classes.push( "ui-state-active" );
+ }
+ if ( day.today ) {
+ classes.push( "ui-state-highlight" );
+ }
+ // TODO: Explain and document this
+ if ( day.extraClasses ) {
+ classes.push( day.extraClasses.split( " " ) );
+ }
+
+ classes = " class='" + classes.join( " " ) + "'";
+ if ( selectable ) {
+ content = "" + day.date + " ";
+ } else {
+ content = "" + day.date + " ";
+ }
+
+ if ( day.today ) {
+ content += ", " + this.labels.currentText + " ";
+ }
+
+ return content;
+ },
+
+ _createButtonPane: function() {
+ this.buttonPane = $( "" )
+ .addClass( "ui-calendar-buttonpane ui-widget-content ui-helper-clearfix" );
+
+ this.buttonSet = $( "
" )
+ .addClass( "ui-calendar-buttonset" )
+ .appendTo( this.buttonPane );
+
+ this._createButtons();
+ },
+
+ _createButtons: function() {
+ var that = this,
+ buttons = this.options.buttons;
+
+ // if we already have a button pane, remove it
+ this.buttonPane.remove();
+ this.buttonSet.empty();
+
+ if ( $.isEmptyObject( buttons ) || ( $.isArray( buttons ) && !buttons.length ) ) {
+ this.element.removeClass( "ui-calendar-buttons" );
+ return;
+ }
+
+ $.each( buttons, function( name, props ) {
+ var click, buttonOptions;
+ props = $.isFunction( props ) ?
+ { click: props, text: name } :
+ props;
+ // Default to a non-submitting button
+ props = $.extend( { type: "button" }, props );
+ // Change the context for the click callback to be the main element
+ click = props.click;
+ props.click = function() {
+ click.apply( that._buttonClickContext(), arguments );
+ };
+ buttonOptions = {
+ icons: props.icons,
+ text: props.showText
+ };
+ delete props.icons;
+ delete props.showText;
+ $( "
", props )
+ .button( buttonOptions )
+ .appendTo( that.buttonSet );
+ });
+ this.element.addClass( "ui-calendar-buttons" );
+ this.buttonPane.appendTo( this.element );
+ },
+
+ _buttonClickContext: function() {
+ return this.element[ 0 ];
+ },
+
+ // Refreshing the entire calendar during interaction confuses screen readers, specifically
+ // because the grid heading is marked up as a live region and will often not update if it's
+ // destroyed and recreated instead of just having its text change. Additionally, interacting
+ // with the prev and next links would cause loss of focus issues because the links being
+ // interacted with will disappear while focused.
+ refresh: function() {
+ this.labels = Globalize.translate( "datepicker" );
+ // determine which day gridcell to focus after refresh
+ // TODO: Prevent disabled cells from being focused
+ if ( this.options.numberOfMonths === 1 ) {
+ this.grid = $( this._buildGrid() );
+ $( ".ui-calendar-title", this.element ).html( this._buildTitle() );
+ $( ".ui-calendar-calendar", this.element ).replaceWith( this.grid );
+ } else {
+ this._refreshMultiplePicker();
+ }
+ },
+
+ _refreshMultiplePicker: function() {
+ for (var i = 0 ; i < this.options.numberOfMonths; i++ ) {
+ $( ".ui-calendar-title", this.element ).eq( i ).html( this._buildTitle() );
+ $( ".ui-calendar-calendar", this.element ).eq( i ).html( this._buildGrid() );
+ this.date.adjust( "M", 1 );
+ }
+ this.date.adjust( "M", -this.options.numberOfMonths );
+
+ // TODO: This assumes focus is on the first grid. For multi pickers, the widget needs
+ // to maintain the currently focused grid and base queries like this off of it.
+ $( this.element ).find( ".ui-state-focus" ).not( ":first" ).removeClass( "ui-state-focus" );
+ },
+
+ _select: function( event, time ) {
+ this._setOption( "value", new Date( time ) );
+ this._trigger( "select", event );
+ },
+
+ value: function( value ) {
+ if ( arguments.length ) {
+ this._setOption( "value", Globalize.parseDate( value, this.options.dateFormat ) );
+ } else {
+ return Globalize.format( this.option( "value" ), this.options.dateFormat );
+ }
+ },
+
+ valueAsDate: function( value ) {
+ if ( arguments.length ) {
+ this._setOption( "value", value );
+ } else {
+ return this.option( "value" );
+ }
+ },
+
+ _isValid: function( value ) {
+ if ( !( value instanceof Date ) ) {
+ return false;
+ }
+
+ if ( this.options.max instanceof Date ) {
+ if ( value > this.options.max ) {
+ return false;
+ }
+ }
+
+ if ( this.options.min instanceof Date ) {
+ if ( value < this.options.min ) {
+ return false;
+ }
+ }
+
+ return true;
+ },
+
+ _destroy: function() {
+ this.element
+ .off( ".calendar" )
+ .removeClass( "ui-calendar ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-calendar-multi" )
+ .removeAttr( "role aria-labelledby" )
+ .removeUniqueId()
+ .empty();
+ },
+
+ option: function( key ) {
+ if ( arguments.length === 0 || ( arguments.length === 1 && key === "value" ) ) {
+ this.options.value = this.date.selectedDate();
+ }
+
+ return this._superApply( arguments );
+ },
+
+ _setOption: function( key, value ) {
+ if ( key === "value" ) {
+ if ( this._isValid( value ) ) {
+ this.date.setTime( value.getTime() ).select();
+ this.refresh();
+ }
+ }
+
+ if ( key === "max" || key === "min" ) {
+ if ( value instanceof Date || value === null ) {
+ this._super( key, value );
+ this.refresh();
+ }
+ return;
+ }
+
+ this._super( key, value );
+
+ if ( key === "buttons" ) {
+ this._createButtons();
+ }
+
+ if ( key === "eachDay" ) {
+ this.date.eachDay = value;
+ this.refresh();
+ }
+
+ if ( key === "dateFormat" ) {
+ this.date.setFormat( value );
+ }
+
+ if ( key === "showWeek" ) {
+ this.refresh();
+ }
+ }
+});
+
+}));
diff --git a/ui/datepicker.js b/ui/datepicker.js
index 10b7d7eb5f2..c58e4d47e4b 100644
--- a/ui/datepicker.js
+++ b/ui/datepicker.js
@@ -14,7 +14,10 @@
// AMD. Register as an anonymous module.
define([
"jquery",
- "./core"
+ "./core",
+ "./widget",
+ "./calendar",
+ "./position"
], factory );
} else {
@@ -23,2051 +26,315 @@
}
}(function( $ ) {
-$.extend($.ui, { datepicker: { version: "@VERSION" } });
+var widget,
+ calendarOptions = [ "buttons", "dateFormat", "eachDay", "max", "min", "numberOfMonths", "showWeek" ];
-var datepicker_instActive;
+widget = $.widget( "ui.datepicker", {
+ version: "@VERSION",
+ options: {
+ appendTo: null,
+ position: {
+ my: "left top",
+ at: "left bottom"
+ },
+ show: true,
+ hide: true,
-function datepicker_getZindex( elem ) {
- var position, value;
- while ( elem.length && elem[ 0 ] !== document ) {
- // Ignore z-index if position is set to a value where z-index is ignored by the browser
- // This makes behavior of this function consistent across browsers
- // WebKit always returns auto if the element is positioned
- position = elem.css( "position" );
- if ( position === "absolute" || position === "relative" || position === "fixed" ) {
- // IE returns 0 when zIndex is not specified
- // other browsers return a string
- // we ignore the case of nested elements with an explicit value of 0
- //
- value = parseInt( elem.css( "zIndex" ), 10 );
- if ( !isNaN( value ) && value !== 0 ) {
- return value;
- }
- }
- elem = elem.parent();
- }
-
- return 0;
-}
-/* Date picker manager.
- Use the singleton instance of this class, $.datepicker, to interact with the date picker.
- Settings for (groups of) date pickers are maintained in an instance object,
- allowing multiple different settings on the same page. */
-
-function Datepicker() {
- this._curInst = null; // The current instance in use
- this._keyEvent = false; // If the last event was a key event
- this._disabledInputs = []; // List of date picker inputs that have been disabled
- this._datepickerShowing = false; // True if the popup picker is showing , false if not
- this._inDialog = false; // True if showing within a "dialog", false if not
- this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
- this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
- this._appendClass = "ui-datepicker-append"; // The name of the append marker class
- this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
- this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
- this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
- this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
- this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
- this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
- this.regional = []; // Available regional settings, indexed by language code
- this.regional[""] = { // Default regional settings
- closeText: "Done", // Display text for close link
- prevText: "Prev", // Display text for previous month link
- nextText: "Next", // Display text for next month link
- currentText: "Today", // Display text for current month link
- monthNames: ["January","February","March","April","May","June",
- "July","August","September","October","November","December"], // Names of months for drop-down and formatting
- monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // For formatting
- dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], // For formatting
- dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], // For formatting
- dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], // Column headings for days starting at Sunday
- weekHeader: "Wk", // Column header for week of the year
- dateFormat: "mm/dd/yy", // See format options on parseDate
- firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
- isRTL: false, // True if right-to-left language, false if left-to-right
- showMonthAfterYear: false, // True if the year select precedes month, false for month then year
- yearSuffix: "" // Additional text to append to the year in the month headers
- };
- this._defaults = { // Global defaults for all the date picker instances
- showOn: "focus", // "focus" for popup on focus,
- // "button" for trigger button, or "both" for either
- showAnim: "fadeIn", // Name of jQuery animation for popup
- showOptions: {}, // Options for enhanced animations
- defaultDate: null, // Used when field is blank: actual date,
- // +/-number for offset from today, null for today
- appendText: "", // Display text following the input box, e.g. showing the format
- buttonText: "...", // Text for trigger button
- buttonImage: "", // URL for trigger button image
- buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
- hideIfNoPrevNext: false, // True to hide next/previous month links
- // if not applicable, false to just disable them
- navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
- gotoCurrent: false, // True if today link goes back to current selection instead
- changeMonth: false, // True if month can be selected directly, false if only prev/next
- changeYear: false, // True if year can be selected directly, false if only prev/next
- yearRange: "c-10:c+10", // Range of years to display in drop-down,
- // either relative to today's year (-nn:+nn), relative to currently displayed year
- // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
- showOtherMonths: false, // True to show dates in other months, false to leave blank
- selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
- showWeek: false, // True to show week of the year, false to not show it
- calculateWeek: this.iso8601Week, // How to calculate the week of the year,
- // takes a Date and returns the number of the week for it
- shortYearCutoff: "+10", // Short year values < this are in the current century,
- // > this are in the previous century,
- // string value starting with "+" for current year + value
- minDate: null, // The earliest selectable date, or null for no limit
- maxDate: null, // The latest selectable date, or null for no limit
- duration: "fast", // Duration of display/closure
- beforeShowDay: null, // Function that takes a date and returns an array with
- // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
- // [2] = cell title (optional), e.g. $.datepicker.noWeekends
- beforeShow: null, // Function that takes an input field and
- // returns a set of custom settings for the date picker
- onSelect: null, // Define a callback function when a date is selected
- onChangeMonthYear: null, // Define a callback function when the month or year is changed
- onClose: null, // Define a callback function when the datepicker is closed
- numberOfMonths: 1, // Number of months to show at a time
- showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
- stepMonths: 1, // Number of months to step back/forward
- stepBigMonths: 12, // Number of months to step back/forward for the big links
- altField: "", // Selector for an alternate field to store selected dates into
- altFormat: "", // The date format to use for the alternate field
- constrainInput: true, // The input is constrained by the current date format
- showButtonPanel: false, // True to show button panel, false to not show it
- autoSize: false, // True to size the input for the date format, false to leave as is
- disabled: false // The initial disabled state
- };
- $.extend(this._defaults, this.regional[""]);
- this.regional.en = $.extend( true, {}, this.regional[ "" ]);
- this.regional[ "en-US" ] = $.extend( true, {}, this.regional.en );
- this.dpDiv = datepicker_bindHover($("
"));
-}
-
-$.extend(Datepicker.prototype, {
- /* Class name added to elements to indicate already configured with a date picker. */
- markerClassName: "hasDatepicker",
-
- //Keep track of the maximum number of rows displayed (see #7043)
- maxRows: 4,
-
- // TODO rename to "widget" when switching to widget factory
- _widgetDatepicker: function() {
- return this.dpDiv;
- },
-
- /* Override the default settings for all instances of the date picker.
- * @param settings object - the new settings to use as defaults (anonymous object)
- * @return the manager object
- */
- setDefaults: function(settings) {
- datepicker_extendRemove(this._defaults, settings || {});
- return this;
- },
-
- /* Attach the date picker to a jQuery selection.
- * @param target element - the target input field or division or span
- * @param settings object - the new settings to use for this date picker instance (anonymous)
- */
- _attachDatepicker: function(target, settings) {
- var nodeName, inline, inst;
- nodeName = target.nodeName.toLowerCase();
- inline = (nodeName === "div" || nodeName === "span");
- if (!target.id) {
- this.uuid += 1;
- target.id = "dp" + this.uuid;
- }
- inst = this._newInst($(target), inline);
- inst.settings = $.extend({}, settings || {});
- if (nodeName === "input") {
- this._connectDatepicker(target, inst);
- } else if (inline) {
- this._inlineDatepicker(target, inst);
- }
+ // callbacks
+ beforeOpen: null,
+ close: null,
+ open: null,
+ select: null
},
- /* Create a new instance object. */
- _newInst: function(target, inline) {
- var id = target[0].id.replace(/([^A-Za-z0-9_\-])/g, "\\\\$1"); // escape jQuery meta chars
- return {id: id, input: target, // associated target
- selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
- drawMonth: 0, drawYear: 0, // month being drawn
- inline: inline, // is datepicker inline or not
- dpDiv: (!inline ? this.dpDiv : // presentation div
- datepicker_bindHover($("
")))};
- },
-
- /* Attach the date picker to an input field. */
- _connectDatepicker: function(target, inst) {
- var input = $(target);
- inst.append = $([]);
- inst.trigger = $([]);
- if (input.hasClass(this.markerClassName)) {
- return;
- }
- this._attachments(input, inst);
- input.addClass(this.markerClassName).keydown(this._doKeyDown).
- keypress(this._doKeyPress).keyup(this._doKeyUp);
- this._autoSize(inst);
- $.data(target, "datepicker", inst);
- //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
- if( inst.settings.disabled ) {
- this._disableDatepicker( target );
- }
- },
-
- /* Make attachments based on settings. */
- _attachments: function(input, inst) {
- var showOn, buttonText, buttonImage,
- appendText = this._get(inst, "appendText"),
- isRTL = this._get(inst, "isRTL");
-
- if (inst.append) {
- inst.append.remove();
- }
- if (appendText) {
- inst.append = $("
" + appendText + " ");
- input[isRTL ? "before" : "after"](inst.append);
- }
-
- input.unbind("focus", this._showDatepicker);
+ _create: function() {
+ this.suppressExpandOnFocus = false;
- if (inst.trigger) {
- inst.trigger.remove();
+ if ( typeof this.options.max === "string" ) {
+ this.options.max = Globalize.parseDate( this.options.max , { pattern: "yyyy-MM-dd" } );
}
-
- showOn = this._get(inst, "showOn");
- if (showOn === "focus" || showOn === "both") { // pop-up date picker when in the marked field
- input.focus(this._showDatepicker);
- }
- if (showOn === "button" || showOn === "both") { // pop-up date picker when button clicked
- buttonText = this._get(inst, "buttonText");
- buttonImage = this._get(inst, "buttonImage");
- inst.trigger = $(this._get(inst, "buttonImageOnly") ?
- $("
").addClass(this._triggerClass).
- attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
- $("
").addClass(this._triggerClass).
- html(!buttonImage ? buttonText : $("
").attr(
- { src:buttonImage, alt:buttonText, title:buttonText })));
- input[isRTL ? "before" : "after"](inst.trigger);
- inst.trigger.click(function() {
- if ($.datepicker._datepickerShowing && $.datepicker._lastInput === input[0]) {
- $.datepicker._hideDatepicker();
- } else if ($.datepicker._datepickerShowing && $.datepicker._lastInput !== input[0]) {
- $.datepicker._hideDatepicker();
- $.datepicker._showDatepicker(input[0]);
- } else {
- $.datepicker._showDatepicker(input[0]);
- }
- return false;
- });
+ if ( typeof this.options.min === "string" ) {
+ this.options.min = Globalize.parseDate( this.options.min , { pattern: "yyyy-MM-dd" } );
}
- },
- /* Apply the maximum length for the date format. */
- _autoSize: function(inst) {
- if (this._get(inst, "autoSize") && !inst.inline) {
- var findMax, max, maxI, i,
- date = new Date(2009, 12 - 1, 20), // Ensure double digits
- dateFormat = this._get(inst, "dateFormat");
+ this._createCalendar();
- if (dateFormat.match(/[DM]/)) {
- findMax = function(names) {
- max = 0;
- maxI = 0;
- for (i = 0; i < names.length; i++) {
- if (names[i].length > max) {
- max = names[i].length;
- maxI = i;
- }
- }
- return maxI;
- };
- date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
- "monthNames" : "monthNamesShort"))));
- date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
- "dayNames" : "dayNamesShort"))) + 20 - date.getDay());
- }
- inst.input.attr("size", this._formatDate(inst, date).length);
- }
+ this._on( this._inputEvents );
+ this._on( this.calendar, this._calendarEvents );
+ this._on( this.document, this._documentEvents );
},
- /* Attach an inline date picker to a div. */
- _inlineDatepicker: function(target, inst) {
- var divSpan = $(target);
- if (divSpan.hasClass(this.markerClassName)) {
- return;
- }
- divSpan.addClass(this.markerClassName).append(inst.dpDiv);
- $.data(target, "datepicker", inst);
- this._setDate(inst, this._getDefaultDate(inst), true);
- this._updateDatepicker(inst);
- this._updateAlternate(inst);
- //If disabled option is true, disable the datepicker before showing it (see ticket #5665)
- if( inst.settings.disabled ) {
- this._disableDatepicker( target );
- }
- // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
- // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
- inst.dpDiv.css( "display", "block" );
+ _getCreateOptions: function() {
+ return {
+ max: this.element.attr( "max" ),
+ min: this.element.attr( "min" )
+ };
},
- /* Pop-up the date picker in a "dialog" box.
- * @param input element - ignored
- * @param date string or Date - the initial date to display
- * @param onSelect function - the function to call when a date is selected
- * @param settings object - update the dialog date picker instance's settings (anonymous object)
- * @param pos int[2] - coordinates for the dialog's position within the screen or
- * event - with x/y coordinates or
- * leave empty for default (screen centre)
- * @return the manager object
- */
- _dialogDatepicker: function(input, date, onSelect, settings, pos) {
- var id, browserWidth, browserHeight, scrollX, scrollY,
- inst = this._dialogInst; // internal instance
-
- if (!inst) {
- this.uuid += 1;
- id = "dp" + this.uuid;
- this._dialogInput = $("
");
- this._dialogInput.keydown(this._doKeyDown);
- $("body").append(this._dialogInput);
- inst = this._dialogInst = this._newInst(this._dialogInput, false);
- inst.settings = {};
- $.data(this._dialogInput[0], "datepicker", inst);
- }
- datepicker_extendRemove(inst.settings, settings || {});
- date = (date && date.constructor === Date ? this._formatDate(inst, date) : date);
- this._dialogInput.val(date);
+ _createCalendar: function() {
+ var that = this;
- this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
- if (!this._pos) {
- browserWidth = document.documentElement.clientWidth;
- browserHeight = document.documentElement.clientHeight;
- scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
- scrollY = document.documentElement.scrollTop || document.body.scrollTop;
- this._pos = // should use actual width/height below
- [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
- }
+ this.calendar = $( "
" )
+ .addClass( "ui-front ui-datepicker" )
+ .appendTo( this._appendTo() );
- // move input on screen for focus, but hidden behind dialog
- this._dialogInput.css("left", (this._pos[0] + 20) + "px").css("top", this._pos[1] + "px");
- inst.settings.onSelect = onSelect;
- this._inDialog = true;
- this.dpDiv.addClass(this._dialogClass);
- this._showDatepicker(this._dialogInput[0]);
- if ($.blockUI) {
- $.blockUI(this.dpDiv);
- }
- $.data(this._dialogInput[0], "datepicker", inst);
- return this;
- },
-
- /* Detach a datepicker from its control.
- * @param target element - the target input field or division or span
- */
- _destroyDatepicker: function(target) {
- var nodeName,
- $target = $(target),
- inst = $.data(target, "datepicker");
-
- if (!$target.hasClass(this.markerClassName)) {
- return;
- }
-
- nodeName = target.nodeName.toLowerCase();
- $.removeData(target, "datepicker");
- if (nodeName === "input") {
- inst.append.remove();
- inst.trigger.remove();
- $target.removeClass(this.markerClassName).
- unbind("focus", this._showDatepicker).
- unbind("keydown", this._doKeyDown).
- unbind("keypress", this._doKeyPress).
- unbind("keyup", this._doKeyUp);
- } else if (nodeName === "div" || nodeName === "span") {
- $target.removeClass(this.markerClassName).empty();
- }
- },
-
- /* Enable the date picker to a jQuery selection.
- * @param target element - the target input field or division or span
- */
- _enableDatepicker: function(target) {
- var nodeName, inline,
- $target = $(target),
- inst = $.data(target, "datepicker");
-
- if (!$target.hasClass(this.markerClassName)) {
- return;
- }
-
- nodeName = target.nodeName.toLowerCase();
- if (nodeName === "input") {
- target.disabled = false;
- inst.trigger.filter("button").
- each(function() { this.disabled = false; }).end().
- filter("img").css({opacity: "1.0", cursor: ""});
- } else if (nodeName === "div" || nodeName === "span") {
- inline = $target.children("." + this._inlineClass);
- inline.children().removeClass("ui-state-disabled");
- inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
- prop("disabled", false);
- }
- this._disabledInputs = $.map(this._disabledInputs,
- function(value) { return (value === target ? null : value); }); // delete entry
- },
-
- /* Disable the date picker to a jQuery selection.
- * @param target element - the target input field or division or span
- */
- _disableDatepicker: function(target) {
- var nodeName, inline,
- $target = $(target),
- inst = $.data(target, "datepicker");
+ // Initialize calendar widget
+ this.calendarInstance = this.calendar
+ .calendar( $.extend( {}, this.options, {
+ value: this._getParsedValue(),
+ select: function( event ) {
+ that.element.val( that.calendarInstance.value() );
+ that.close();
+ that._focusTrigger();
+ that._trigger( "select", event );
+ }
+ }) )
+ .calendar( "instance" );
- if (!$target.hasClass(this.markerClassName)) {
- return;
- }
+ this.calendarInstance._buttonClickContext = function() {
+ return that.element[ 0 ];
+ };
- nodeName = target.nodeName.toLowerCase();
- if (nodeName === "input") {
- target.disabled = true;
- inst.trigger.filter("button").
- each(function() { this.disabled = true; }).end().
- filter("img").css({opacity: "0.5", cursor: "default"});
- } else if (nodeName === "div" || nodeName === "span") {
- inline = $target.children("." + this._inlineClass);
- inline.children().addClass("ui-state-disabled");
- inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
- prop("disabled", true);
- }
- this._disabledInputs = $.map(this._disabledInputs,
- function(value) { return (value === target ? null : value); }); // delete entry
- this._disabledInputs[this._disabledInputs.length] = target;
- },
+ this._setHiddenPicker();
- /* Is the first field in a jQuery collection disabled as a datepicker?
- * @param target element - the target input field or division or span
- * @return boolean - true if disabled, false if enabled
- */
- _isDisabledDatepicker: function(target) {
- if (!target) {
- return false;
- }
- for (var i = 0; i < this._disabledInputs.length; i++) {
- if (this._disabledInputs[i] === target) {
- return true;
- }
- }
- return false;
- },
-
- /* Retrieve the instance data for the target control.
- * @param target element - the target input field or division or span
- * @return object - the associated instance data
- * @throws error if a jQuery problem getting data
- */
- _getInst: function(target) {
- try {
- return $.data(target, "datepicker");
- }
- catch (err) {
- throw "Missing instance data for this datepicker";
- }
+ this.element.attr({
+ "aria-haspopup": true,
+ "aria-owns": this.calendar.attr( "id" )
+ });
},
- /* Update or retrieve the settings for a date picker attached to an input field or division.
- * @param target element - the target input field or division or span
- * @param name object - the new settings to update or
- * string - the name of the setting to change or retrieve,
- * when retrieving also "all" for all instance settings or
- * "defaults" for all global defaults
- * @param value any - the new value for the setting
- * (omit if above is an object or to retrieve a value)
- */
- _optionDatepicker: function(target, name, value) {
- var settings, date, minDate, maxDate,
- inst = this._getInst(target);
-
- if (arguments.length === 2 && typeof name === "string") {
- return (name === "defaults" ? $.extend({}, $.datepicker._defaults) :
- (inst ? (name === "all" ? $.extend({}, inst.settings) :
- this._get(inst, name)) : null));
- }
-
- settings = name || {};
- if (typeof name === "string") {
- settings = {};
- settings[name] = value;
- }
-
- if (inst) {
- if (this._curInst === inst) {
- this._hideDatepicker();
- }
-
- date = this._getDateDatepicker(target, true);
- minDate = this._getMinMaxDate(inst, "min");
- maxDate = this._getMinMaxDate(inst, "max");
- datepicker_extendRemove(inst.settings, settings);
- // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
- if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) {
- inst.settings.minDate = this._formatDate(inst, minDate);
- }
- if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) {
- inst.settings.maxDate = this._formatDate(inst, maxDate);
+ _inputEvents: {
+ keydown: function( event ) {
+ switch ( event.keyCode ) {
+ case $.ui.keyCode.TAB:
+ // 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 ) {
+ this.close( event );
+ }
+ break;
+ case $.ui.keyCode.DOWN:
+ case $.ui.keyCode.UP:
+ clearTimeout( this.closeTimer );
+ this._delay( function() {
+ this.open( event );
+ this.calendarInstance.grid.focus( 1 );
+ }, 1 );
+ break;
}
- if ( "disabled" in settings ) {
- if ( settings.disabled ) {
- this._disableDatepicker(target);
- } else {
- this._enableDatepicker(target);
- }
+ },
+ keyup: function() {
+ if ( this.isValid() ) {
+ this.valueAsDate( this._getParsedValue() );
}
- this._attachments($(target), inst);
- this._autoSize(inst);
- this._setDate(inst, date);
- this._updateAlternate(inst);
- this._updateDatepicker(inst);
- }
- },
-
- // change method deprecated
- _changeDatepicker: function(target, name, value) {
- this._optionDatepicker(target, name, value);
- },
-
- /* Redraw the date picker attached to an input field or division.
- * @param target element - the target input field or division or span
- */
- _refreshDatepicker: function(target) {
- var inst = this._getInst(target);
- if (inst) {
- this._updateDatepicker(inst);
- }
- },
-
- /* Set the dates for a jQuery selection.
- * @param target element - the target input field or division or span
- * @param date Date - the new date
- */
- _setDateDatepicker: function(target, date) {
- var inst = this._getInst(target);
- if (inst) {
- this._setDate(inst, date);
- this._updateDatepicker(inst);
- this._updateAlternate(inst);
- }
- },
-
- /* Get the date(s) for the first entry in a jQuery selection.
- * @param target element - the target input field or division or span
- * @param noDefault boolean - true if no default date is to be used
- * @return Date - the current date
- */
- _getDateDatepicker: function(target, noDefault) {
- var inst = this._getInst(target);
- if (inst && !inst.inline) {
- this._setDateFromField(inst, noDefault);
- }
- return (inst ? this._getDate(inst) : null);
- },
-
- /* Handle keystrokes. */
- _doKeyDown: function(event) {
- var onSelect, dateStr, sel,
- inst = $.datepicker._getInst(event.target),
- handled = true,
- isRTL = inst.dpDiv.is(".ui-datepicker-rtl");
-
- inst._keyEvent = true;
- if ($.datepicker._datepickerShowing) {
- switch (event.keyCode) {
- case 9: $.datepicker._hideDatepicker();
- handled = false;
- break; // hide on tab out
- case 13: sel = $("td." + $.datepicker._dayOverClass + ":not(." +
- $.datepicker._currentClass + ")", inst.dpDiv);
- if (sel[0]) {
- $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
- }
-
- onSelect = $.datepicker._get(inst, "onSelect");
- if (onSelect) {
- dateStr = $.datepicker._formatDate(inst);
-
- // trigger custom callback
- onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
- } else {
- $.datepicker._hideDatepicker();
- }
-
- return false; // don't submit the form
- case 27: $.datepicker._hideDatepicker();
- break; // hide on escape
- case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
- -$.datepicker._get(inst, "stepBigMonths") :
- -$.datepicker._get(inst, "stepMonths")), "M");
- break; // previous month/year on page up/+ ctrl
- case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
- +$.datepicker._get(inst, "stepBigMonths") :
- +$.datepicker._get(inst, "stepMonths")), "M");
- break; // next month/year on page down/+ ctrl
- case 35: if (event.ctrlKey || event.metaKey) {
- $.datepicker._clearDate(event.target);
- }
- handled = event.ctrlKey || event.metaKey;
- break; // clear on ctrl or command +end
- case 36: if (event.ctrlKey || event.metaKey) {
- $.datepicker._gotoToday(event.target);
- }
- handled = event.ctrlKey || event.metaKey;
- break; // current on ctrl or command +home
- case 37: if (event.ctrlKey || event.metaKey) {
- $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), "D");
- }
- handled = event.ctrlKey || event.metaKey;
- // -1 day on ctrl or command +left
- if (event.originalEvent.altKey) {
- $.datepicker._adjustDate(event.target, (event.ctrlKey ?
- -$.datepicker._get(inst, "stepBigMonths") :
- -$.datepicker._get(inst, "stepMonths")), "M");
- }
- // next month/year on alt +left on Mac
- break;
- case 38: if (event.ctrlKey || event.metaKey) {
- $.datepicker._adjustDate(event.target, -7, "D");
- }
- handled = event.ctrlKey || event.metaKey;
- break; // -1 week on ctrl or command +up
- case 39: if (event.ctrlKey || event.metaKey) {
- $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), "D");
- }
- handled = event.ctrlKey || event.metaKey;
- // +1 day on ctrl or command +right
- if (event.originalEvent.altKey) {
- $.datepicker._adjustDate(event.target, (event.ctrlKey ?
- +$.datepicker._get(inst, "stepBigMonths") :
- +$.datepicker._get(inst, "stepMonths")), "M");
- }
- // next month/year on alt +right
- break;
- case 40: if (event.ctrlKey || event.metaKey) {
- $.datepicker._adjustDate(event.target, +7, "D");
- }
- handled = event.ctrlKey || event.metaKey;
- break; // +1 week on ctrl or command +down
- default: handled = false;
+ },
+ mousedown: function( event ) {
+ if ( this.isOpen ) {
+ this.suppressExpandOnFocus = true;
+ this.close();
+ return;
}
- } else if (event.keyCode === 36 && event.ctrlKey) { // display the date picker on ctrl+home
- $.datepicker._showDatepicker(this);
- } else {
- handled = false;
- }
-
- if (handled) {
- event.preventDefault();
- event.stopPropagation();
- }
- },
-
- /* Filter entered characters - based on date format. */
- _doKeyPress: function(event) {
- var chars, chr,
- inst = $.datepicker._getInst(event.target);
-
- if ($.datepicker._get(inst, "constrainInput")) {
- chars = $.datepicker._possibleChars($.datepicker._get(inst, "dateFormat"));
- chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode);
- return event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1);
- }
- },
-
- /* Synchronise manual entry and field/alternate field. */
- _doKeyUp: function(event) {
- var date,
- inst = $.datepicker._getInst(event.target);
-
- if (inst.input.val() !== inst.lastVal) {
- try {
- date = $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
- (inst.input ? inst.input.val() : null),
- $.datepicker._getFormatConfig(inst));
-
- if (date) { // only if valid
- $.datepicker._setDateFromField(inst);
- $.datepicker._updateAlternate(inst);
- $.datepicker._updateDatepicker(inst);
- }
+ this.open( event );
+ clearTimeout( this.closeTimer );
+ },
+ focus: function( event ) {
+ if ( !this.suppressExpandOnFocus && !this.isOpen ) {
+ this._delay( function() {
+ this.open( event );
+ }, 1);
}
- catch (err) {
+ this._delay( function() {
+ this.suppressExpandOnFocus = false;
+ }, 100 );
+ },
+ blur: function() {
+ this.suppressExpandOnFocus = false;
+ }
+ },
+
+ _calendarEvents: {
+ focusout: function( event ) {
+ // 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 );
+ },
+ // TODO on TAB (or shift TAB), make sure it ends up on something useful in DOM order
+ keyup: function( event ) {
+ if ( event.keyCode === $.ui.keyCode.ESCAPE && this.calendar.is( ":visible" ) ) {
+ this.close( event );
+ this._focusTrigger();
}
}
- return true;
},
- /* Pop-up the date picker for a given input field.
- * If false returned from beforeShow event handler do not show.
- * @param input element - the input field attached to the date picker or
- * event - if triggered by focus
- */
- _showDatepicker: function(input) {
- input = input.target || input;
- if (input.nodeName.toLowerCase() !== "input") { // find from button/image trigger
- input = $("input", input.parentNode)[0];
- }
-
- if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput === input) { // already here
- return;
- }
-
- var inst, beforeShow, beforeShowSettings, isFixed,
- offset, showAnim, duration;
-
- inst = $.datepicker._getInst(input);
- if ($.datepicker._curInst && $.datepicker._curInst !== inst) {
- $.datepicker._curInst.dpDiv.stop(true, true);
- if ( inst && $.datepicker._datepickerShowing ) {
- $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] );
+ _documentEvents: {
+ mousedown: function( event ) {
+ if ( !this.isOpen ) {
+ return;
}
- }
-
- beforeShow = $.datepicker._get(inst, "beforeShow");
- beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
- if(beforeShowSettings === false){
- return;
- }
- datepicker_extendRemove(inst.settings, beforeShowSettings);
-
- inst.lastVal = null;
- $.datepicker._lastInput = input;
- $.datepicker._setDateFromField(inst);
-
- if ($.datepicker._inDialog) { // hide cursor
- input.value = "";
- }
- if (!$.datepicker._pos) { // position below input
- $.datepicker._pos = $.datepicker._findPos(input);
- $.datepicker._pos[1] += input.offsetHeight; // add the height
- }
- isFixed = false;
- $(input).parents().each(function() {
- isFixed |= $(this).css("position") === "fixed";
- return !isFixed;
- });
-
- offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
- $.datepicker._pos = null;
- //to avoid flashes on Firefox
- inst.dpDiv.empty();
- // determine sizing offscreen
- inst.dpDiv.css({position: "absolute", display: "block", top: "-1000px"});
- $.datepicker._updateDatepicker(inst);
- // fix width for dynamic number of date pickers
- // and adjust position before showing
- offset = $.datepicker._checkOffset(inst, offset, isFixed);
- inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
- "static" : (isFixed ? "fixed" : "absolute")), display: "none",
- left: offset.left + "px", top: offset.top + "px"});
-
- if (!inst.inline) {
- showAnim = $.datepicker._get(inst, "showAnim");
- duration = $.datepicker._get(inst, "duration");
- inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 );
- $.datepicker._datepickerShowing = true;
-
- if ( $.effects && $.effects.effect[ showAnim ] ) {
- inst.dpDiv.show(showAnim, $.datepicker._get(inst, "showOptions"), duration);
- } else {
- inst.dpDiv[showAnim || "show"](showAnim ? duration : null);
+ if ( !$( event.target ).closest( this.element.add( this.calendar ) ).length ) {
+ this.close( event );
}
-
- if ( $.datepicker._shouldFocusInput( inst ) ) {
- inst.input.focus();
- }
-
- $.datepicker._curInst = inst;
}
},
- /* Generate the date picker content. */
- _updateDatepicker: function(inst) {
- this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
- datepicker_instActive = inst; // for delegate hover events
- inst.dpDiv.empty().append(this._generateHTML(inst));
- this._attachHandlers(inst);
- inst.dpDiv.find("." + this._dayOverClass + " a");
-
- var origyearshtml,
- numMonths = this._getNumberOfMonths(inst),
- cols = numMonths[1],
- width = 17;
+ _appendTo: function() {
+ var element = this.options.appendTo;
- inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");
- if (cols > 1) {
- inst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", (width * cols) + "em");
+ if ( element ) {
+ element = element.jquery || element.nodeType ?
+ $( element ) :
+ this.document.find( element ).eq( 0 );
}
- inst.dpDiv[(numMonths[0] !== 1 || numMonths[1] !== 1 ? "add" : "remove") +
- "Class"]("ui-datepicker-multi");
- inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") +
- "Class"]("ui-datepicker-rtl");
- if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
- inst.input.focus();
+ if ( !element || !element[ 0 ] ) {
+ element = this.element.closest( ".ui-front" );
}
- // deffered render of the years select (to avoid flashes on Firefox)
- if( inst.yearshtml ){
- origyearshtml = inst.yearshtml;
- setTimeout(function(){
- //assure that inst.yearshtml didn't change.
- if( origyearshtml === inst.yearshtml && inst.yearshtml ){
- inst.dpDiv.find("select.ui-datepicker-year:first").replaceWith(inst.yearshtml);
- }
- origyearshtml = inst.yearshtml = null;
- }, 0);
+ if ( !element.length ) {
+ element = this.document[ 0 ].body;
}
- },
- // #6694 - don't focus the input if it's already focused
- // this breaks the change event in IE
- // Support: IE and jQuery <1.9
- _shouldFocusInput: function( inst ) {
- return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" );
+ return element;
},
- /* Check positioning to remain on screen. */
- _checkOffset: function(inst, offset, isFixed) {
- var dpWidth = inst.dpDiv.outerWidth(),
- dpHeight = inst.dpDiv.outerHeight(),
- inputWidth = inst.input ? inst.input.outerWidth() : 0,
- inputHeight = inst.input ? inst.input.outerHeight() : 0,
- viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()),
- viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop());
-
- offset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0);
- offset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0;
- offset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
-
- // now check if datepicker is showing outside window viewport - move to a better place if so.
- offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
- Math.abs(offset.left + dpWidth - viewWidth) : 0);
- offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
- Math.abs(dpHeight + inputHeight) : 0);
-
- return offset;
+ _focusTrigger: function() {
+ this.suppressExpandOnFocus = true;
+ this.element.focus();
},
- /* Find an object's position on the screen. */
- _findPos: function(obj) {
- var position,
- inst = this._getInst(obj),
- isRTL = this._get(inst, "isRTL");
-
- while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden(obj))) {
- obj = obj[isRTL ? "previousSibling" : "nextSibling"];
- }
-
- position = $(obj).offset();
- return [position.left, position.top];
+ refresh: function() {
+ this.calendarInstance.valueAsDate( this._getParsedValue() );
+ this.calendarInstance.refresh();
},
- /* Hide the date picker from view.
- * @param input element - the input field attached to the date picker
- */
- _hideDatepicker: function(input) {
- var showAnim, duration, postProcess, onClose,
- inst = this._curInst;
-
- if (!inst || (input && inst !== $.data(input, "datepicker"))) {
+ open: function( event ) {
+ if ( this.isOpen ) {
return;
}
-
- if (this._datepickerShowing) {
- showAnim = this._get(inst, "showAnim");
- duration = this._get(inst, "duration");
- postProcess = function() {
- $.datepicker._tidyDialog(inst);
- };
-
- // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
- if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {
- inst.dpDiv.hide(showAnim, $.datepicker._get(inst, "showOptions"), duration, postProcess);
- } else {
- inst.dpDiv[(showAnim === "slideDown" ? "slideUp" :
- (showAnim === "fadeIn" ? "fadeOut" : "hide"))]((showAnim ? duration : null), postProcess);
- }
-
- if (!showAnim) {
- postProcess();
- }
- this._datepickerShowing = false;
-
- onClose = this._get(inst, "onClose");
- if (onClose) {
- onClose.apply((inst.input ? inst.input[0] : null), [(inst.input ? inst.input.val() : ""), inst]);
- }
-
- this._lastInput = null;
- if (this._inDialog) {
- this._dialogInput.css({ position: "absolute", left: "0", top: "-100px" });
- if ($.blockUI) {
- $.unblockUI();
- $("body").append(this.dpDiv);
- }
- }
- this._inDialog = false;
- }
- },
-
- /* Tidy up after a dialog display. */
- _tidyDialog: function(inst) {
- inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar");
- },
-
- /* Close date picker if clicked elsewhere. */
- _checkExternalClick: function(event) {
- if (!$.datepicker._curInst) {
+ if ( this._trigger( "beforeOpen", event ) === false ) {
return;
}
- var $target = $(event.target),
- inst = $.datepicker._getInst($target[0]);
+ this.calendarInstance.refresh();
+ this.calendar
+ .attr({
+ "aria-hidden": false,
+ "aria-expanded": true
+ })
+ .show()
+ .position( this._buildPosition() )
+ .hide();
+ this._show( this.calendar, this.options.show );
- if ( ( ( $target[0].id !== $.datepicker._mainDivId &&
- $target.parents("#" + $.datepicker._mainDivId).length === 0 &&
- !$target.hasClass($.datepicker.markerClassName) &&
- !$target.closest("." + $.datepicker._triggerClass).length &&
- $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) ||
- ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst !== inst ) ) {
- $.datepicker._hideDatepicker();
- }
- },
-
- /* Adjust one of the date sub-fields. */
- _adjustDate: function(id, offset, period) {
- var target = $(id),
- inst = this._getInst(target[0]);
+ // take trigger out of tab order to allow shift-tab to skip trigger
+ // TODO does this really make sense? related bug: tab-shift moves focus to last element on page
+ this.element.attr( "tabindex", -1 );
+ this.isOpen = true;
- if (this._isDisabledDatepicker(target[0])) {
- return;
- }
- this._adjustInstDate(inst, offset +
- (period === "M" ? this._get(inst, "showCurrentAtPos") : 0), // undo positioning
- period);
- this._updateDatepicker(inst);
+ this._trigger( "open", event );
},
- /* Action for current link. */
- _gotoToday: function(id) {
- var date,
- target = $(id),
- inst = this._getInst(target[0]);
+ close: function( event ) {
+ this._setHiddenPicker();
+ this._hide( this.calendar, this.options.hide );
- if (this._get(inst, "gotoCurrent") && inst.currentDay) {
- inst.selectedDay = inst.currentDay;
- inst.drawMonth = inst.selectedMonth = inst.currentMonth;
- inst.drawYear = inst.selectedYear = inst.currentYear;
- } else {
- date = new Date();
- inst.selectedDay = date.getDate();
- inst.drawMonth = inst.selectedMonth = date.getMonth();
- inst.drawYear = inst.selectedYear = date.getFullYear();
- }
- this._notifyChange(inst);
- this._adjustDate(target);
- },
-
- /* Action for selecting a new month/year. */
- _selectMonthYear: function(id, select, period) {
- var target = $(id),
- inst = this._getInst(target[0]);
+ this.element.attr( "tabindex" , 0 );
- inst["selected" + (period === "M" ? "Month" : "Year")] =
- inst["draw" + (period === "M" ? "Month" : "Year")] =
- parseInt(select.options[select.selectedIndex].value,10);
-
- this._notifyChange(inst);
- this._adjustDate(target);
+ this.isOpen = false;
+ this._trigger( "close", event );
},
- /* Action for selecting a day. */
- _selectDay: function(id, month, year, td) {
- var inst,
- target = $(id);
-
- if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
- return;
- }
-
- inst = this._getInst(target[0]);
- inst.selectedDay = inst.currentDay = $("a", td).html();
- inst.selectedMonth = inst.currentMonth = month;
- inst.selectedYear = inst.currentYear = year;
- this._selectDate(id, this._formatDate(inst,
- inst.currentDay, inst.currentMonth, inst.currentYear));
+ _setHiddenPicker: function() {
+ this.calendar.attr({
+ "aria-hidden": true,
+ "aria-expanded": false
+ });
},
- /* Erase the input field and hide the date picker. */
- _clearDate: function(id) {
- var target = $(id);
- this._selectDate(target, "");
+ _buildPosition: function() {
+ return $.extend( {}, { of: this.element }, this.options.position );
},
- /* Update the input field with the selected date. */
- _selectDate: function(id, dateStr) {
- var onSelect,
- target = $(id),
- inst = this._getInst(target[0]);
-
- dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
- if (inst.input) {
- inst.input.val(dateStr);
- }
- this._updateAlternate(inst);
-
- onSelect = this._get(inst, "onSelect");
- if (onSelect) {
- onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback
- } else if (inst.input) {
- inst.input.trigger("change"); // fire the change event
- }
-
- if (inst.inline){
- this._updateDatepicker(inst);
+ value: function( value ) {
+ if ( arguments.length ) {
+ this.valueAsDate( Globalize.parseDate( value , this.options.dateFormat ) );
} else {
- this._hideDatepicker();
- this._lastInput = inst.input[0];
- if (typeof(inst.input[0]) !== "object") {
- inst.input.focus(); // restore focus
- }
- this._lastInput = null;
+ return ( this._getParsedValue() !== null ) ? this.element.val() : null;
}
},
- /* Update any alternate field to synchronise with the main field. */
- _updateAlternate: function(inst) {
- var altFormat, date, dateStr,
- altField = this._get(inst, "altField");
-
- if (altField) { // update alternate field too
- altFormat = this._get(inst, "altFormat") || this._get(inst, "dateFormat");
- date = this._getDate(inst);
- dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
- $(altField).each(function() { $(this).val(dateStr); });
- }
- },
-
- /* Set as beforeShowDay function to prevent selection of weekends.
- * @param date Date - the date to customise
- * @return [boolean, string] - is this date selectable?, what is its CSS class?
- */
- noWeekends: function(date) {
- var day = date.getDay();
- return [(day > 0 && day < 6), ""];
- },
-
- /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
- * @param date Date - the date to get the week for
- * @return number - the number of the week within the year that contains this date
- */
- iso8601Week: function(date) {
- var time,
- checkDate = new Date(date.getTime());
-
- // Find Thursday of this week starting on Monday
- checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
-
- time = checkDate.getTime();
- checkDate.setMonth(0); // Compare with Jan 1
- checkDate.setDate(1);
- return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
- },
-
- /* Parse a string value into a date object.
- * See formatDate below for the possible formats.
- *
- * @param format string - the expected format of the date
- * @param value string - the date in the above format
- * @param settings Object - attributes include:
- * shortYearCutoff number - the cutoff year for determining the century (optional)
- * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
- * dayNames string[7] - names of the days from Sunday (optional)
- * monthNamesShort string[12] - abbreviated names of the months (optional)
- * monthNames string[12] - names of the months (optional)
- * @return Date - the extracted date value or null if value is blank
- */
- parseDate: function (format, value, settings) {
- if (format == null || value == null) {
- throw "Invalid arguments";
- }
-
- value = (typeof value === "object" ? value.toString() : value + "");
- if (value === "") {
- return null;
- }
-
- var iFormat, dim, extra,
- iValue = 0,
- shortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff,
- shortYearCutoff = (typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
- new Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10)),
- dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
- dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
- monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
- monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
- year = -1,
- month = -1,
- day = -1,
- doy = -1,
- literal = false,
- date,
- // Check whether a format character is doubled
- lookAhead = function(match) {
- var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
- if (matches) {
- iFormat++;
- }
- return matches;
- },
- // Extract a number from the string value
- getNumber = function(match) {
- var isDoubled = lookAhead(match),
- size = (match === "@" ? 14 : (match === "!" ? 20 :
- (match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))),
- digits = new RegExp("^\\d{1," + size + "}"),
- num = value.substring(iValue).match(digits);
- if (!num) {
- throw "Missing number at position " + iValue;
- }
- iValue += num[0].length;
- return parseInt(num[0], 10);
- },
- // Extract a name from the string value and convert to an index
- getName = function(match, shortNames, longNames) {
- var index = -1,
- names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
- return [ [k, v] ];
- }).sort(function (a, b) {
- return -(a[1].length - b[1].length);
- });
-
- $.each(names, function (i, pair) {
- var name = pair[1];
- if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) {
- index = pair[0];
- iValue += name.length;
- return false;
- }
- });
- if (index !== -1) {
- return index + 1;
- } else {
- throw "Unknown name at position " + iValue;
- }
- },
- // Confirm that a literal character matches the string value
- checkLiteral = function() {
- if (value.charAt(iValue) !== format.charAt(iFormat)) {
- throw "Unexpected literal at position " + iValue;
- }
- iValue++;
- };
-
- for (iFormat = 0; iFormat < format.length; iFormat++) {
- if (literal) {
- if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
- literal = false;
- } else {
- checkLiteral();
- }
- } else {
- switch (format.charAt(iFormat)) {
- case "d":
- day = getNumber("d");
- break;
- case "D":
- getName("D", dayNamesShort, dayNames);
- break;
- case "o":
- doy = getNumber("o");
- break;
- case "m":
- month = getNumber("m");
- break;
- case "M":
- month = getName("M", monthNamesShort, monthNames);
- break;
- case "y":
- year = getNumber("y");
- break;
- case "@":
- date = new Date(getNumber("@"));
- year = date.getFullYear();
- month = date.getMonth() + 1;
- day = date.getDate();
- break;
- case "!":
- date = new Date((getNumber("!") - this._ticksTo1970) / 10000);
- year = date.getFullYear();
- month = date.getMonth() + 1;
- day = date.getDate();
- break;
- case "'":
- if (lookAhead("'")){
- checkLiteral();
- } else {
- literal = true;
- }
- break;
- default:
- checkLiteral();
- }
+ valueAsDate: function( value ) {
+ if ( arguments.length ) {
+ if ( this.calendarInstance._isValid( value ) ) {
+ this.calendarInstance.valueAsDate( value );
+ this.element.val( Globalize.format( value, this.options.dateFormat ) );
}
+ } else {
+ return this._getParsedValue();
}
-
- if (iValue < value.length){
- extra = value.substr(iValue);
- if (!/^\s+/.test(extra)) {
- throw "Extra/unparsed characters found in date: " + extra;
- }
- }
-
- if (year === -1) {
- year = new Date().getFullYear();
- } else if (year < 100) {
- year += new Date().getFullYear() - new Date().getFullYear() % 100 +
- (year <= shortYearCutoff ? 0 : -100);
- }
-
- if (doy > -1) {
- month = 1;
- day = doy;
- do {
- dim = this._getDaysInMonth(year, month - 1);
- if (day <= dim) {
- break;
- }
- month++;
- day -= dim;
- } while (true);
- }
-
- date = this._daylightSavingAdjust(new Date(year, month - 1, day));
- if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) {
- throw "Invalid date"; // E.g. 31/02/00
- }
- return date;
- },
-
- /* Standard date formats. */
- ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
- COOKIE: "D, dd M yy",
- ISO_8601: "yy-mm-dd",
- RFC_822: "D, d M y",
- RFC_850: "DD, dd-M-y",
- RFC_1036: "D, d M y",
- RFC_1123: "D, d M yy",
- RFC_2822: "D, d M yy",
- RSS: "D, d M y", // RFC 822
- TICKS: "!",
- TIMESTAMP: "@",
- W3C: "yy-mm-dd", // ISO 8601
-
- _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
- Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
-
- /* Format a date object into a string value.
- * The format can be combinations of the following:
- * d - day of month (no leading zero)
- * dd - day of month (two digit)
- * o - day of year (no leading zeros)
- * oo - day of year (three digit)
- * D - day name short
- * DD - day name long
- * m - month of year (no leading zero)
- * mm - month of year (two digit)
- * M - month name short
- * MM - month name long
- * y - year (two digit)
- * yy - year (four digit)
- * @ - Unix timestamp (ms since 01/01/1970)
- * ! - Windows ticks (100ns since 01/01/0001)
- * "..." - literal text
- * '' - single quote
- *
- * @param format string - the desired format of the date
- * @param date Date - the date value to format
- * @param settings Object - attributes include:
- * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
- * dayNames string[7] - names of the days from Sunday (optional)
- * monthNamesShort string[12] - abbreviated names of the months (optional)
- * monthNames string[12] - names of the months (optional)
- * @return string - the date in the above format
- */
- formatDate: function (format, date, settings) {
- if (!date) {
- return "";
- }
-
- var iFormat,
- dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
- dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
- monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
- monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
- // Check whether a format character is doubled
- lookAhead = function(match) {
- var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
- if (matches) {
- iFormat++;
- }
- return matches;
- },
- // Format a number, with leading zero if necessary
- formatNumber = function(match, value, len) {
- var num = "" + value;
- if (lookAhead(match)) {
- while (num.length < len) {
- num = "0" + num;
- }
- }
- return num;
- },
- // Format a name, short or long as requested
- formatName = function(match, value, shortNames, longNames) {
- return (lookAhead(match) ? longNames[value] : shortNames[value]);
- },
- output = "",
- literal = false;
-
- if (date) {
- for (iFormat = 0; iFormat < format.length; iFormat++) {
- if (literal) {
- if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
- literal = false;
- } else {
- output += format.charAt(iFormat);
- }
- } else {
- switch (format.charAt(iFormat)) {
- case "d":
- output += formatNumber("d", date.getDate(), 2);
- break;
- case "D":
- output += formatName("D", date.getDay(), dayNamesShort, dayNames);
- break;
- case "o":
- output += formatNumber("o",
- Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
- break;
- case "m":
- output += formatNumber("m", date.getMonth() + 1, 2);
- break;
- case "M":
- output += formatName("M", date.getMonth(), monthNamesShort, monthNames);
- break;
- case "y":
- output += (lookAhead("y") ? date.getFullYear() :
- (date.getYear() % 100 < 10 ? "0" : "") + date.getYear() % 100);
- break;
- case "@":
- output += date.getTime();
- break;
- case "!":
- output += date.getTime() * 10000 + this._ticksTo1970;
- break;
- case "'":
- if (lookAhead("'")) {
- output += "'";
- } else {
- literal = true;
- }
- break;
- default:
- output += format.charAt(iFormat);
- }
- }
- }
- }
- return output;
- },
-
- /* Extract all possible characters from the date format. */
- _possibleChars: function (format) {
- var iFormat,
- chars = "",
- literal = false,
- // Check whether a format character is doubled
- lookAhead = function(match) {
- var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
- if (matches) {
- iFormat++;
- }
- return matches;
- };
-
- for (iFormat = 0; iFormat < format.length; iFormat++) {
- if (literal) {
- if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
- literal = false;
- } else {
- chars += format.charAt(iFormat);
- }
- } else {
- switch (format.charAt(iFormat)) {
- case "d": case "m": case "y": case "@":
- chars += "0123456789";
- break;
- case "D": case "M":
- return null; // Accept anything
- case "'":
- if (lookAhead("'")) {
- chars += "'";
- } else {
- literal = true;
- }
- break;
- default:
- chars += format.charAt(iFormat);
- }
- }
- }
- return chars;
- },
-
- /* Get a setting value, defaulting if necessary. */
- _get: function(inst, name) {
- return inst.settings[name] !== undefined ?
- inst.settings[name] : this._defaults[name];
- },
-
- /* Parse existing date and initialise date picker. */
- _setDateFromField: function(inst, noDefault) {
- if (inst.input.val() === inst.lastVal) {
- return;
- }
-
- var dateFormat = this._get(inst, "dateFormat"),
- dates = inst.lastVal = inst.input ? inst.input.val() : null,
- defaultDate = this._getDefaultDate(inst),
- date = defaultDate,
- settings = this._getFormatConfig(inst);
-
- try {
- date = this.parseDate(dateFormat, dates, settings) || defaultDate;
- } catch (event) {
- dates = (noDefault ? "" : dates);
- }
- inst.selectedDay = date.getDate();
- inst.drawMonth = inst.selectedMonth = date.getMonth();
- inst.drawYear = inst.selectedYear = date.getFullYear();
- inst.currentDay = (dates ? date.getDate() : 0);
- inst.currentMonth = (dates ? date.getMonth() : 0);
- inst.currentYear = (dates ? date.getFullYear() : 0);
- this._adjustInstDate(inst);
- },
-
- /* Retrieve the default date shown on opening. */
- _getDefaultDate: function(inst) {
- return this._restrictMinMax(inst,
- this._determineDate(inst, this._get(inst, "defaultDate"), new Date()));
- },
-
- /* A date may be specified as an exact value or a relative one. */
- _determineDate: function(inst, date, defaultDate) {
- var offsetNumeric = function(offset) {
- var date = new Date();
- date.setDate(date.getDate() + offset);
- return date;
- },
- offsetString = function(offset) {
- try {
- return $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
- offset, $.datepicker._getFormatConfig(inst));
- }
- catch (e) {
- // Ignore
- }
-
- var date = (offset.toLowerCase().match(/^c/) ?
- $.datepicker._getDate(inst) : null) || new Date(),
- year = date.getFullYear(),
- month = date.getMonth(),
- day = date.getDate(),
- pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
- matches = pattern.exec(offset);
-
- while (matches) {
- switch (matches[2] || "d") {
- case "d" : case "D" :
- day += parseInt(matches[1],10); break;
- case "w" : case "W" :
- day += parseInt(matches[1],10) * 7; break;
- case "m" : case "M" :
- month += parseInt(matches[1],10);
- day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
- break;
- case "y": case "Y" :
- year += parseInt(matches[1],10);
- day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
- break;
- }
- matches = pattern.exec(offset);
- }
- return new Date(year, month, day);
- },
- newDate = (date == null || date === "" ? defaultDate : (typeof date === "string" ? offsetString(date) :
- (typeof date === "number" ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
-
- newDate = (newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate);
- if (newDate) {
- newDate.setHours(0);
- newDate.setMinutes(0);
- newDate.setSeconds(0);
- newDate.setMilliseconds(0);
- }
- return this._daylightSavingAdjust(newDate);
- },
-
- /* Handle switch to/from daylight saving.
- * Hours may be non-zero on daylight saving cut-over:
- * > 12 when midnight changeover, but then cannot generate
- * midnight datetime, so jump to 1AM, otherwise reset.
- * @param date (Date) the date to check
- * @return (Date) the corrected date
- */
- _daylightSavingAdjust: function(date) {
- if (!date) {
- return null;
- }
- date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
- return date;
},
- /* Set the date(s) directly. */
- _setDate: function(inst, date, noChange) {
- var clear = !date,
- origMonth = inst.selectedMonth,
- origYear = inst.selectedYear,
- newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
-
- inst.selectedDay = inst.currentDay = newDate.getDate();
- inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
- inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
- if ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange) {
- this._notifyChange(inst);
- }
- this._adjustInstDate(inst);
- if (inst.input) {
- inst.input.val(clear ? "" : this._formatDate(inst));
- }
+ isValid: function() {
+ return this.calendarInstance._isValid( this._getParsedValue() );
},
- /* Retrieve the date(s) directly. */
- _getDate: function(inst) {
- var startDate = (!inst.currentYear || (inst.input && inst.input.val() === "") ? null :
- this._daylightSavingAdjust(new Date(
- inst.currentYear, inst.currentMonth, inst.currentDay)));
- return startDate;
+ _destroy: function() {
+ this.calendarInstance.destroy();
+ this.calendar.remove();
+ this.element.removeAttr( "aria-haspopup aria-owns" );
},
- /* Attach the onxxx handlers. These are declared statically so
- * they work with static code transformers like Caja.
- */
- _attachHandlers: function(inst) {
- var stepMonths = this._get(inst, "stepMonths"),
- id = "#" + inst.id.replace( /\\\\/g, "\\" );
- inst.dpDiv.find("[data-handler]").map(function () {
- var handler = {
- prev: function () {
- $.datepicker._adjustDate(id, -stepMonths, "M");
- },
- next: function () {
- $.datepicker._adjustDate(id, +stepMonths, "M");
- },
- hide: function () {
- $.datepicker._hideDatepicker();
- },
- today: function () {
- $.datepicker._gotoToday(id);
- },
- selectDay: function () {
- $.datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this);
- return false;
- },
- selectMonth: function () {
- $.datepicker._selectMonthYear(id, this, "M");
- return false;
- },
- selectYear: function () {
- $.datepicker._selectMonthYear(id, this, "Y");
- return false;
- }
- };
- $(this).bind(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]);
- });
+ widget: function() {
+ return this.calendar;
},
- /* Generate the HTML for the current state of the date picker. */
- _generateHTML: function(inst) {
- var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
- controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
- monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
- selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
- cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
- printDate, dRow, tbody, daySettings, otherMonth, unselectable,
- tempDate = new Date(),
- today = this._daylightSavingAdjust(
- new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time
- isRTL = this._get(inst, "isRTL"),
- showButtonPanel = this._get(inst, "showButtonPanel"),
- hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"),
- navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"),
- numMonths = this._getNumberOfMonths(inst),
- showCurrentAtPos = this._get(inst, "showCurrentAtPos"),
- stepMonths = this._get(inst, "stepMonths"),
- isMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1),
- currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
- new Date(inst.currentYear, inst.currentMonth, inst.currentDay))),
- minDate = this._getMinMaxDate(inst, "min"),
- maxDate = this._getMinMaxDate(inst, "max"),
- drawMonth = inst.drawMonth - showCurrentAtPos,
- drawYear = inst.drawYear;
-
- if (drawMonth < 0) {
- drawMonth += 12;
- drawYear--;
- }
- if (maxDate) {
- maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
- maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
- maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
- while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
- drawMonth--;
- if (drawMonth < 0) {
- drawMonth = 11;
- drawYear--;
- }
- }
- }
- inst.drawMonth = drawMonth;
- inst.drawYear = drawYear;
-
- prevText = this._get(inst, "prevText");
- prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
- this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
- this._getFormatConfig(inst)));
-
- prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
- "
" + prevText + " " :
- (hideIfNoPrevNext ? "" : "
" + prevText + " "));
-
- nextText = this._get(inst, "nextText");
- nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
- this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
- this._getFormatConfig(inst)));
-
- next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
- "
" + nextText + " " :
- (hideIfNoPrevNext ? "" : "
" + nextText + " "));
-
- currentText = this._get(inst, "currentText");
- gotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today);
- currentText = (!navigationAsDateFormat ? currentText :
- this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
-
- controls = (!inst.inline ? "
" +
- this._get(inst, "closeText") + " " : "");
-
- buttonPanel = (showButtonPanel) ? "
" + (isRTL ? controls : "") +
- (this._isInRange(inst, gotoDate) ? "" + currentText + " " : "") + (isRTL ? "" : controls) + "
" : "";
-
- firstDay = parseInt(this._get(inst, "firstDay"),10);
- firstDay = (isNaN(firstDay) ? 0 : firstDay);
-
- showWeek = this._get(inst, "showWeek");
- dayNames = this._get(inst, "dayNames");
- dayNamesMin = this._get(inst, "dayNamesMin");
- monthNames = this._get(inst, "monthNames");
- monthNamesShort = this._get(inst, "monthNamesShort");
- beforeShowDay = this._get(inst, "beforeShowDay");
- showOtherMonths = this._get(inst, "showOtherMonths");
- selectOtherMonths = this._get(inst, "selectOtherMonths");
- defaultDate = this._getDefaultDate(inst);
- html = "";
- dow;
- for (row = 0; row < numMonths[0]; row++) {
- group = "";
- this.maxRows = 4;
- for (col = 0; col < numMonths[1]; col++) {
- selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
- cornerClass = " ui-corner-all";
- calender = "";
- if (isMultiMonth) {
- calender += "
";
- }
- calender += "
" +
- "";
- thead = (showWeek ? "" + this._get(inst, "weekHeader") + " " : "");
- for (dow = 0; dow < 7; dow++) { // days of the week
- day = (dow + firstDay) % 7;
- thead += "= 5 ? " class='ui-datepicker-week-end'" : "") + ">" +
- "" + dayNamesMin[day] + " ";
- }
- calender += thead + " ";
- daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
- if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) {
- inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
- }
- leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
- curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
- numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
- this.maxRows = numRows;
- printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
- for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows
- calender += "";
- tbody = (!showWeek ? "" : "" +
- this._get(inst, "calculateWeek")(printDate) + " ");
- for (dow = 0; dow < 7; dow++) { // create date picker days
- daySettings = (beforeShowDay ?
- beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]);
- otherMonth = (printDate.getMonth() !== drawMonth);
- unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
- (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
- tbody += " " + // actions
- (otherMonth && !showOtherMonths ? " " : // display for other months
- (unselectable ? "" + printDate.getDate() + " " : "" + printDate.getDate() + " ")) + ""; // display selectable date
- printDate.setDate(printDate.getDate() + 1);
- printDate = this._daylightSavingAdjust(printDate);
- }
- calender += tbody + " ";
- }
- drawMonth++;
- if (drawMonth > 11) {
- drawMonth = 0;
- drawYear++;
- }
- calender += "
" + (isMultiMonth ? "
" +
- ((numMonths[0] > 0 && col === numMonths[1]-1) ? "
" : "") : "");
- group += calender;
- }
- html += group;
- }
- html += buttonPanel;
- inst._keyEvent = false;
- return html;
+ _getParsedValue: function() {
+ return Globalize.parseDate( this.element.val() , this.options.dateFormat );
},
- /* Generate the month and year header. */
- _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
- secondary, monthNames, monthNamesShort) {
-
- var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
- changeMonth = this._get(inst, "changeMonth"),
- changeYear = this._get(inst, "changeYear"),
- showMonthAfterYear = this._get(inst, "showMonthAfterYear"),
- html = "
",
- monthHtml = "";
-
- // month selection
- if (secondary || !changeMonth) {
- monthHtml += "" + monthNames[drawMonth] + " ";
- } else {
- inMinYear = (minDate && minDate.getFullYear() === drawYear);
- inMaxYear = (maxDate && maxDate.getFullYear() === drawYear);
- monthHtml += "";
- for ( month = 0; month < 12; month++) {
- if ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) {
- monthHtml += "" + monthNamesShort[month] + " ";
- }
- }
- monthHtml += " ";
- }
+ _setOption: function( key, value ) {
+ this._super( key, value );
- if (!showMonthAfterYear) {
- html += monthHtml + (secondary || !(changeMonth && changeYear) ? " " : "");
+ if ( $.inArray( key, calendarOptions ) !== -1 ) {
+ this.calendarInstance._setOption( key, value );
}
- // year selection
- if ( !inst.yearshtml ) {
- inst.yearshtml = "";
- if (secondary || !changeYear) {
- html += "" + drawYear + " ";
- } else {
- // determine range of years to display
- years = this._get(inst, "yearRange").split(":");
- thisYear = new Date().getFullYear();
- determineYear = function(value) {
- var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) :
- (value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) :
- parseInt(value, 10)));
- return (isNaN(year) ? thisYear : year);
- };
- year = determineYear(years[0]);
- endYear = Math.max(year, determineYear(years[1] || ""));
- year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
- endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
- inst.yearshtml += "";
- for (; year <= endYear; year++) {
- inst.yearshtml += "" + year + " ";
- }
- inst.yearshtml += " ";
-
- html += inst.yearshtml;
- inst.yearshtml = null;
- }
+ if ( key === "appendTo" ) {
+ this.calendar.appendTo( this._appendTo() );
}
- html += this._get(inst, "yearSuffix");
- if (showMonthAfterYear) {
- html += (secondary || !(changeMonth && changeYear) ? " " : "") + monthHtml;
+ if ( key === "dateFormat" ) {
+ this.element.val( this.calendarInstance.value() );
}
- html += "
"; // Close datepicker_header
- return html;
- },
-
- /* Adjust one of the date sub-fields. */
- _adjustInstDate: function(inst, offset, period) {
- var year = inst.drawYear + (period === "Y" ? offset : 0),
- month = inst.drawMonth + (period === "M" ? offset : 0),
- day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period === "D" ? offset : 0),
- date = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day)));
- inst.selectedDay = date.getDate();
- inst.drawMonth = inst.selectedMonth = date.getMonth();
- inst.drawYear = inst.selectedYear = date.getFullYear();
- if (period === "M" || period === "Y") {
- this._notifyChange(inst);
+ if ( key === "max" || key === "min" ) {
+ this.element.attr( key, Globalize.format( value, { pattern: "yyyy-MM-dd" } ) );
}
- },
-
- /* Ensure a date is within any min/max bounds. */
- _restrictMinMax: function(inst, date) {
- var minDate = this._getMinMaxDate(inst, "min"),
- maxDate = this._getMinMaxDate(inst, "max"),
- newDate = (minDate && date < minDate ? minDate : date);
- return (maxDate && newDate > maxDate ? maxDate : newDate);
- },
- /* Notify change of month/year. */
- _notifyChange: function(inst) {
- var onChange = this._get(inst, "onChangeMonthYear");
- if (onChange) {
- onChange.apply((inst.input ? inst.input[0] : null),
- [inst.selectedYear, inst.selectedMonth + 1, inst]);
+ if ( key === "position" ) {
+ this.calendar.position( this._buildPosition() );
}
- },
-
- /* Determine the number of months to show. */
- _getNumberOfMonths: function(inst) {
- var numMonths = this._get(inst, "numberOfMonths");
- return (numMonths == null ? [1, 1] : (typeof numMonths === "number" ? [1, numMonths] : numMonths));
- },
-
- /* Determine the current maximum date - ensure no time components are set. */
- _getMinMaxDate: function(inst, minMax) {
- return this._determineDate(inst, this._get(inst, minMax + "Date"), null);
- },
-
- /* Find the number of days in a given month. */
- _getDaysInMonth: function(year, month) {
- return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
- },
-
- /* Find the day of the week of the first of a month. */
- _getFirstDayOfMonth: function(year, month) {
- return new Date(year, month, 1).getDay();
- },
-
- /* Determines if we should allow a "next/prev" month display change. */
- _canAdjustMonth: function(inst, offset, curYear, curMonth) {
- var numMonths = this._getNumberOfMonths(inst),
- date = this._daylightSavingAdjust(new Date(curYear,
- curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
-
- if (offset < 0) {
- date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
- }
- return this._isInRange(inst, date);
- },
-
- /* Is the given date in the accepted range? */
- _isInRange: function(inst, date) {
- var yearSplit, currentYear,
- minDate = this._getMinMaxDate(inst, "min"),
- maxDate = this._getMinMaxDate(inst, "max"),
- minYear = null,
- maxYear = null,
- years = this._get(inst, "yearRange");
- if (years){
- yearSplit = years.split(":");
- currentYear = new Date().getFullYear();
- minYear = parseInt(yearSplit[0], 10);
- maxYear = parseInt(yearSplit[1], 10);
- if ( yearSplit[0].match(/[+\-].*/) ) {
- minYear += currentYear;
- }
- if ( yearSplit[1].match(/[+\-].*/) ) {
- maxYear += currentYear;
- }
- }
-
- return ((!minDate || date.getTime() >= minDate.getTime()) &&
- (!maxDate || date.getTime() <= maxDate.getTime()) &&
- (!minYear || date.getFullYear() >= minYear) &&
- (!maxYear || date.getFullYear() <= maxYear));
- },
-
- /* Provide the configuration settings for formatting/parsing. */
- _getFormatConfig: function(inst) {
- var shortYearCutoff = this._get(inst, "shortYearCutoff");
- shortYearCutoff = (typeof shortYearCutoff !== "string" ? shortYearCutoff :
- new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
- return {shortYearCutoff: shortYearCutoff,
- dayNamesShort: this._get(inst, "dayNamesShort"), dayNames: this._get(inst, "dayNames"),
- monthNamesShort: this._get(inst, "monthNamesShort"), monthNames: this._get(inst, "monthNames")};
- },
-
- /* Format the given date for display. */
- _formatDate: function(inst, day, month, year) {
- if (!day) {
- inst.currentDay = inst.selectedDay;
- inst.currentMonth = inst.selectedMonth;
- inst.currentYear = inst.selectedYear;
- }
- var date = (day ? (typeof day === "object" ? day :
- this._daylightSavingAdjust(new Date(year, month, day))) :
- this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
- return this.formatDate(this._get(inst, "dateFormat"), date, this._getFormatConfig(inst));
}
});
-/*
- * Bind hover events for datepicker elements.
- * Done via delegate so the binding only occurs once in the lifetime of the parent div.
- * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
- */
-function datepicker_bindHover(dpDiv) {
- var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
- return dpDiv.delegate(selector, "mouseout", function() {
- $(this).removeClass("ui-state-hover");
- if (this.className.indexOf("ui-datepicker-prev") !== -1) {
- $(this).removeClass("ui-datepicker-prev-hover");
- }
- if (this.className.indexOf("ui-datepicker-next") !== -1) {
- $(this).removeClass("ui-datepicker-next-hover");
- }
- })
- .delegate(selector, "mouseover", function(){
- if (!$.datepicker._isDisabledDatepicker( datepicker_instActive.inline ? dpDiv.parent()[0] : datepicker_instActive.input[0])) {
- $(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");
- $(this).addClass("ui-state-hover");
- if (this.className.indexOf("ui-datepicker-prev") !== -1) {
- $(this).addClass("ui-datepicker-prev-hover");
- }
- if (this.className.indexOf("ui-datepicker-next") !== -1) {
- $(this).addClass("ui-datepicker-next-hover");
- }
- }
- });
-}
-
-/* jQuery extend now ignores nulls! */
-function datepicker_extendRemove(target, props) {
- $.extend(target, props);
- for (var name in props) {
- if (props[name] == null) {
- target[name] = props[name];
- }
- }
- return target;
-}
-
-/* Invoke the datepicker functionality.
- @param options string - a command, optionally followed by additional parameters or
- Object - settings for attaching new datepicker functionality
- @return jQuery object */
-$.fn.datepicker = function(options){
-
- /* Verify an empty collection wasn't passed - Fixes #6976 */
- if ( !this.length ) {
- return this;
- }
-
- /* Initialise the date picker. */
- if (!$.datepicker.initialized) {
- $(document).mousedown($.datepicker._checkExternalClick);
- $.datepicker.initialized = true;
- }
-
- /* Append datepicker main container to body if not exist. */
- if ($("#"+$.datepicker._mainDivId).length === 0) {
- $("body").append($.datepicker.dpDiv);
- }
-
- var otherArgs = Array.prototype.slice.call(arguments, 1);
- if (typeof options === "string" && (options === "isDisabled" || options === "getDate" || options === "widget")) {
- return $.datepicker["_" + options + "Datepicker"].
- apply($.datepicker, [this[0]].concat(otherArgs));
- }
- if (options === "option" && arguments.length === 2 && typeof arguments[1] === "string") {
- return $.datepicker["_" + options + "Datepicker"].
- apply($.datepicker, [this[0]].concat(otherArgs));
- }
- return this.each(function() {
- typeof options === "string" ?
- $.datepicker["_" + options + "Datepicker"].
- apply($.datepicker, [this].concat(otherArgs)) :
- $.datepicker._attachDatepicker(this, options);
- });
-};
-
-$.datepicker = new Datepicker(); // singleton instance
-$.datepicker.initialized = false;
-$.datepicker.uuid = new Date().getTime();
-$.datepicker.version = "@VERSION";
+$.each( calendarOptions, function( index, option ) {
+ $.ui.datepicker.prototype.options[ option ] = $.ui.calendar.prototype.options[ option ];
+});
-return $.datepicker;
+return widget;
}));