diff --git a/Gruntfile.js b/Gruntfile.js index b8610b6f641..3d9a11963db 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 78% rename from demos/datepicker/buttonbar.html rename to demos/calendar/buttonbar.html index 446bc9fe495..7a2098b3f6d 100644 --- a/demos/datepicker/buttonbar.html +++ b/demos/calendar/buttonbar.html @@ -2,7 +2,7 @@ - jQuery UI Datepicker - Display button bar + jQuery UI Calendar - Display button bar @@ -11,20 +11,24 @@ + - -

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:
+ +

+ +
+

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/datepicker/inline.html b/demos/calendar/default.html similarity index 58% rename from demos/datepicker/inline.html rename to demos/calendar/default.html index 5d482919020..8c77174b435 100644 --- a/demos/datepicker/inline.html +++ b/demos/calendar/default.html @@ -2,7 +2,7 @@ - jQuery UI Datepicker - Display inline + jQuery UI Calendar - Default functionality @@ -11,21 +11,21 @@ + - -Date:
+
-

Display the datepicker embedded in the page instead of in an overlay. Simply call .datepicker() on a div instead of an input.

+

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 82% rename from demos/datepicker/dropdown-month-year.html rename to demos/calendar/dropdown-month-year.html index c6102917f43..050a89157ff 100644 --- a/demos/datepicker/dropdown-month-year.html +++ b/demos/calendar/dropdown-month-year.html @@ -2,7 +2,7 @@ - jQuery UI Datepicker - Display month & year menus + jQuery UI Calendar - Display month & year menus @@ -11,12 +11,12 @@ + - + + + + + + + + + + + + + +
+

+ +
+

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/datepicker/min-max.html b/demos/calendar/min-max.html similarity index 52% rename from demos/datepicker/min-max.html rename to demos/calendar/min-max.html index 6dcc16a48bc..5b9b5fd825f 100644 --- a/demos/datepicker/min-max.html +++ b/demos/calendar/min-max.html @@ -2,7 +2,7 @@ - jQuery UI Datepicker - Restrict date range + jQuery UI Calendar - Restrict date range @@ -11,21 +11,28 @@ + - -

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.

+

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 75% rename from demos/datepicker/multiple-calendars.html rename to demos/calendar/multiple-months.html index 3d8278cd625..f67609d143e 100644 --- a/demos/datepicker/multiple-calendars.html +++ b/demos/calendar/multiple-months.html @@ -2,7 +2,7 @@ - jQuery UI Datepicker - Display multiple months + jQuery UI Calendar - Display multiple months @@ -11,12 +11,12 @@ + - @@ -11,12 +11,12 @@ + - @@ -11,12 +11,12 @@ + - + + diff --git a/demos/datepicker/date-formats.html b/demos/datepicker/date-formats.html index 2c5045b6f33..4f507631dca 100644 --- a/demos/datepicker/date-formats.html +++ b/demos/datepicker/date-formats.html @@ -11,29 +11,23 @@ + - - - - - - - - - - - - - - - - - - -
-

Select the date range to search for.

-
- - diff --git a/demos/datepicker/default.html b/demos/datepicker/default.html index be0c453c2b3..b2439b29ab3 100644 --- a/demos/datepicker/default.html +++ b/demos/datepicker/default.html @@ -12,6 +12,7 @@ + + 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/localization.html b/demos/datepicker/localization.html index 61aa7c9a2da..5818518dec4 100644 --- a/demos/datepicker/localization.html +++ b/demos/datepicker/localization.html @@ -11,16 +11,18 @@ + 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 index 06a67553205..edc47c161f6 100644 --- a/external/date.js +++ b/external/date.js @@ -26,9 +26,13 @@ $.date = function( 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 = { @@ -180,6 +184,9 @@ $.date.prototype = { 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(), diff --git a/external/localization.js b/external/localization.js index 98d8f813052..4fd436aca00 100644 --- a/external/localization.js +++ b/external/localization.js @@ -2767,10 +2767,10 @@ var regions = { "dateFormat": "d" }, "de": { - "closeText": "schlie\u00dfen", - "prevText": "<zur\u00fcck", + "closeText": "Schlie\u00dfen", + "prevText": "<Zur\u00fcck", "nextText": "Vor>", - "currentText": "heute", + "currentText": "Heute", "weekHeader": "Wo", "dateFormat": "d" }, 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 index ca2d66e37d9..8f31592f14b 100644 --- a/tests/unit/date/all.html +++ b/tests/unit/date/all.html @@ -1,20 +1,20 @@ - - jQuery UI Date Test Suite + + jQuery UI Date Test Suite - + - - - - - + + + + + - + diff --git a/tests/unit/date/date.html b/tests/unit/date/date.html index d759fdeaee7..b2dd2c41e22 100644 --- a/tests/unit/date/date.html +++ b/tests/unit/date/date.html @@ -5,14 +5,14 @@ jQuery UI Date Test Suite - - + + TestHelpers.loadResources({ - css: [ "core", "datepicker" ], + css: [ "core", "calendar" , "datepicker" ], js: [ "ui/core.js", "ui/widget.js", "ui/button.js", + "ui/calendar.js", "ui/position.js", "ui/datepicker.js" ] @@ -39,10 +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 189f03d932a..71ac0d9cf73 100644 --- a/tests/unit/datepicker/datepicker_core.js +++ b/tests/unit/datepicker/datepicker_core.js @@ -12,600 +12,361 @@ test( "input's value determines starting date", function() { input.datepicker( "open" ); - equal( picker.find( ".ui-datepicker-month" ).html(), "January", "correct month displayed" ); - equal( picker.find( ".ui-datepicker-year" ).html(), "2014", "correct year displayed" ); - equal( picker.find( ".ui-state-focus" ).html(), "1", "correct day highlighted" ); + 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( 42 ); - var header, title, table, thead, week, panel, inl, child, + expect( 15 ); + + var header, title, table, child, buttonpane, inp = TestHelpers.datepicker.initNewInput(), - dp = inp.datepicker( "widget" ).find( ".ui-datepicker" ); + dp = inp.datepicker( "widget" ); function step1() { 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, 3, "Structure - child count (header, calendar, buttonpane)" ); + 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( ".ui-datepicker-prev" ) && header.children( ":first" ).html() !== "", "Structure - prev link" ); - ok( header.children( ":eq(1)" ).is( ".ui-datepicker-next" ) && header.children( ":eq(1)" ).html() !== "", "Structure - next link" ); title = header.children( ":last" ).children( ":first" ); - ok( title.is( "div.ui-datepicker-title" ) && title.html() !== "", "Structure - title division" ); 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" ); - // TODO: Preserve these class names or let the user use :first-child and :last-child? - // 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( "close" ).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() {} }); - dp = inp.datepicker( "widget" ).find( ".ui-datepicker" ); inp.focus(); + setTimeout(function() { - title = dp.find( "div.ui-datepicker-title" ); - // TODO: Re-add tests when changeMonth and changeYear are re-implemented - //ok( title.children( ":first" ).is( "select.ui-datepicker-month" ), "Structure - month selector" ); - //ok( title.children( ":last" ).is( "select.ui-datepicker-year" ), "Structure - year selector" ); + equal( dp.children().length, 3, "Structure buttons - child count (header, calendar, buttonpane)" ); - 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" ); + 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 } ); - dp = inp.datepicker( "widget" ).find( ".ui-datepicker" ); - inp.focus(); - setTimeout(function() { - ok( dp.is( ".ui-datepicker-multi" ), "Structure multi [2] - multi-month" ); - equal( dp.children().length, 4, "Structure multi [2] - child count" ); - - child = dp.children( ":first" ); - // TODO: Implement ui-datepicker-group-first class name - // 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)" ); - // TODO: Implement ui-datepicker-group-last class name - // 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" ); - - inp.datepicker( "close" ).datepicker( "destroy" ); - step4(); - }); - } - - function step4() { - // Multi-month 3 - inp = TestHelpers.datepicker.initNewInput({ numberOfMonths: 3 } ); - dp = inp.datepicker( "widget" ).find( ".ui-datepicker" ); + dp = inp.datepicker( "widget" ); inp.focus(); setTimeout(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( "close" ).datepicker( "destroy" ); - step5(); - }); - } - - function step5() { - // Multi-month [2, 2] - inp = TestHelpers.datepicker.initNewInput({ numberOfMonths: [ 2, 2 ] } ); - dp = inp.datepicker( "widget" ).find( ".ui-datepicker" ); - inp.focus(); - setTimeout(function() { - /* - TODO: Re-add after array form of the numberOfMonths option is implemented. - 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" ); + 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-datepicker-row-break" ), "Structure multi [2,2] - row break" ); + ok( child.is( "div.ui-calendar-row-break" ), "Structure multi [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( "close" ).datepicker( "destroy" ); - step6(); }); - } - - function step6() { - // Inline - inl = TestHelpers.datepicker.init( "#inline" ); - 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, 3, "Structure inline - child count (header, calendar, buttonpane)" ); - - 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" ); - - 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" ); - - inl.datepicker( "destroy" ); - - step7(); - } - - function step7() { - // Inline multi-month - inl = TestHelpers.datepicker.init( "#inline", { numberOfMonths: 2 } ); - dp = inl.datepicker( "widget" ).find( ".ui-datepicker" ); - - ok( dp.is( ".ui-datepicker-inline" ) && dp.is( ".ui-datepicker-multi" ), "Structure inline multi - main div" ); - equal( dp.children().length, 4, "Structure inline multi - child count" ); - - child = dp.children( ":first" ); - // TODO: Implement ui-datepicker-group-first class name - // ok( child.is( "div.ui-datepicker-group" ) && child.is( "div.ui-datepicker-group-first" ), "Structure inline multi - first month division" ); - - child = dp.children( ":eq(1)" ); - // TODO: Implement ui-datepicker-group-last class name - // ok( child.is( "div.ui-datepicker-group" ) && child.is( "div.ui-datepicker-group-last" ), "Structure inline multi - second month division" ); - - child = dp.children( ":eq(2)" ); - ok( child.is( "div.ui-datepicker-row-break" ), "Structure inline multi - row break" ); - - inl.datepicker( "destroy" ); start(); } step1(); }); -test( "Keyboard handling", function() { - expect( 9 ); +asyncTest( "Keyboard handling: input", function() { + expect( 10 ); var input = $( "#datepicker" ).datepicker(), - instance = input.datepicker( "instance" ), - date = new Date(); - - input.datepicker( "open" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); - TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), date, "Keystroke enter" ); - - // Enter = Select today's date by default - input.val( "1/1/14" ).datepicker( "open" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); - TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), new Date( 2014, 0, 1 ), - "Keystroke enter - preset" ); - - // Control + Home = Change the calendar to the current month - input.val( "1/1/14" ).datepicker( "open" ) - .simulate( "keydown", { ctrlKey: true, keyCode: $.ui.keyCode.HOME } ) - .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); - TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), date, "Keystroke ctrl+home" ); - - // Control + End = Close the calendar and clear the input - input.val( "1/1/14" ).datepicker( "open" ) - .simulate( "keydown", { ctrlKey: true, keyCode: $.ui.keyCode.END } ); - equal( input.val(), "", "Keystroke ctrl+end" ); - - 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" ); -}); - -asyncTest( "keyboard handling", function() { - expect( 14 ); - var picker, - input = $( "#datepicker" ), - date = new Date(); + picker, instance; function step1() { - input.datepicker(); + TestHelpers.datepicker.init( input ); picker = input.datepicker( "widget" ); + ok( !picker.is( ":visible" ), "datepicker closed" ); - input.val( "" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + input.val( "" ).simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); setTimeout(function() { ok( picker.is( ":visible" ), "Keystroke down opens datepicker" ); input.datepicker( "destroy" ); step2(); - }); + }, 100 ); } function step2() { - input.datepicker(); + TestHelpers.datepicker.init( input ); picker = input.datepicker( "widget" ); + ok( !picker.is( ":visible" ), "datepicker closed" ); - input.val( "" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.UP } ); + input.val( "" ).simulate( "keydown", { keyCode: $.ui.keyCode.UP } ); setTimeout(function() { ok( picker.is( ":visible" ), "Keystroke up opens datepicker" ); input.datepicker( "destroy" ); step3(); - }); + }, 100 ); } function step3() { - input.datepicker() + TestHelpers.datepicker.init( input ); + instance = input.datepicker( "instance" ); + + // Enter = Select preset date + input .val( "1/1/14" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + .datepicker( "refresh" ) + .datepicker( "open" ) + .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); + TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), new Date( 2014, 0, 1 ), + "Keystroke enter - preset" ); - setTimeout(function() { - $( ":focus" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.LEFT } ) - .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); - date = new Date( 2013, 12 - 1, 31 ); - TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), date, - "Keystroke left to switch to previous day" ); + input + .val( "" ) + .datepicker( "open" ); + ok( instance.isOpen, "datepicker is open before escape" ); - input.datepicker( "destroy" ); - step4(); - }, 100 ); - } + input.simulate( "keydown", { keyCode: $.ui.keyCode.ESCAPE } ); + ok( !instance.isOpen, "escape closes the datepicker" ); - function step4() { - input.datepicker() + input .val( "1/1/14" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + .datepicker( "open" ) + .simulate( "keydown", { keyCode: $.ui.keyCode.ESCAPE } ); + TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), new Date( 2014, 0, 1 ), + "Keystroke esc - preset" ); - setTimeout(function() { - $( ":focus" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.RIGHT } ) - .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); - date = new Date( 2014, 1 - 1, 2 ); - TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), date, - "Keystroke right to switch to next day" ); - - input.datepicker( "destroy" ); - step5(); - }, 100 ); + 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(); } - function step5() { - input.datepicker() - .val( "1/1/14" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + step1(); +}); - setTimeout(function() { - $( ":focus" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.UP } ) - .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); - date = new Date( 2013, 12 - 1, 25 ); - TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), date, - "Keystroke up to move to the previous week" ); +asyncTest( "keyboard handling: calendar", function() { + expect( 7 ); - input.datepicker( "destroy" ); - step6(); - }, 100 ); - } + var input = $( "#datepicker" ); - function step6() { - input.datepicker() - .val( "1/1/14" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + 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.DOWN } ) - .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); - date = new Date( 2014, 1 - 1, 8 ); - TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), date, - "Keystroke down to move to the next week" ); - - input.datepicker( "destroy" ); - step7(); + $( ":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 ); } - function step7() { - input.datepicker() - .val( "1/1/14" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + function step2() { + 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_UP } ) + .simulate( "keydown", { keyCode: $.ui.keyCode.RIGHT } ) .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); - date = new Date( 2013, 12 - 1, 1 ); - TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), date, - "Keystroke Page Up moves date to previous month" ); + TestHelpers.datepicker.equalsDate( + input.datepicker( "valueAsDate" ), + new Date( 2014, 1 - 1, 2 ), + "Keystroke right to switch to next day" + ); input.datepicker( "destroy" ); - step8(); + step3(); }, 100 ); } - function step8() { - input.datepicker() - .val( "1/1/14" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + function step3() { + 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_UP, altKey: true } ) - .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); - date = new Date( 2013, 1 - 1, 1 ); - TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), date, - "Keystroke Page Up + Ctrl moves date to previous year" ); - - input.datepicker( "destroy" ); - step9(); + $( ":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 ); } - function step9() { - input.datepicker() - .val( "1/1/14" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + function 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.PAGE_DOWN } ) - .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); - date = new Date( 2014, 2 - 1, 1 ); - TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), date, - "Keystroke Page Down moves date to next month" ); - - input.datepicker( "destroy" ); - step10(); + $( ":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 ); } - function step10() { - input.datepicker() - .val( "1/1/14" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + function 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.PAGE_DOWN, altKey: true } ) - .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); - date = new Date( 2015, 1 - 1, 1 ); - TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), date, - "Keystroke Page Down + Ctrl moves date to next year" ); - - input.datepicker( "destroy" ); - step11(); + $( ":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 ); } - // Check for moving to short months - function step11() { - input.datepicker() - .val( "3/31/14" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + 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_UP } ) - .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); - date = new Date( 2014, 2 - 1, 28 ); - TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), date, - "Keystroke Page Up and short months" ); - - input.datepicker( "destroy" ); - step12(); + $( ":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 ); } - function step12() { - input.datepicker() - .val( "1/30/16" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + // 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_DOWN } ) - .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); - date = new Date( 2016, 2 - 1, 29 ); - TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), date, - "Keystroke Page Down and leap years" ); - - input.datepicker( "destroy" ); - start(); + $( ":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 ); } step1(); }); -/* - // TODO: Re-add tests if we implement a stepMonths option - input.datepicker( "option", { stepMonths: 2, gotoCurrent: false } ) - .datepicker( "close" ).val( "02/04/2008" ).datepicker( "open" ) - .late( "keydown", { keyCode: $.ui.keyCode.PAGE_UP } ) - .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); - TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), new Date( 2007, 12 - 1, 4 ), - "Keystroke pgup step 2" ); - - input.val( "02/04/2008" ).datepicker( "open" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.PAGE_DOWN } ) - .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); - TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), new Date( 2008, 4 - 1, 4 ), - "Keystroke pgdn step 2" ); -*/ - -test( "mouse", function() { - expect( 13 ); - var input = $( "#datepicker" ).datepicker(), - picker = input.datepicker( "widget" ), - inline = $( "#inline" ).datepicker, - date = new Date(); - - input.val( "" ).datepicker( "open" ); - $( ".ui-datepicker-calendar tbody a:contains(10)", picker ).simulate( "mousedown", {} ); - date.setDate( 10 ); - TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), date, "Mouse click" ); - - input.val( "2/4/08" ).datepicker( "open" ); - $( ".ui-datepicker-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( "open" ); - $( "button.ui-datepicker-close", picker ).simulate( "click", {} ); - ok( input.datepicker( "valueAsDate" ) == null, "Mouse click - close" ); - - input.val( "2/4/08" ).datepicker( "open" ); - $( "button.ui-datepicker-close", picker ).simulate( "click", {} ); - TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), new Date( 2008, 2 - 1, 4 ), - "Mouse click - close + preset" ); - - input.val( "2/4/08" ).datepicker( "open" ); - $( "a.ui-datepicker-prev", picker ).simulate( "click", {} ); - $( "button.ui-datepicker-close", picker ).simulate( "click", {} ); - TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), new Date( 2008, 2 - 1, 4 ), - "Mouse click - abandoned" ); - - // Current/previous/next - input.val( "" ).datepicker( "open" ); - $( ".ui-datepicker-current", picker ).simulate( "click", {} ); - date.setDate( new Date().getDate() ); - TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), date, "Mouse click - current" ); - - input.val( "2/4/08" ).datepicker( "open" ); - $( ".ui-datepicker-prev", picker ).simulate( "click" ); - $( ".ui-datepicker-calendar tbody a:contains(16)", picker ).simulate( "mousedown" ); - TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), new Date( 2008, 1 - 1, 16 ), - "Mouse click - previous" ); - - input.val( "2/4/08" ).datepicker( "open" ); - $( ".ui-datepicker-next", picker ).simulate( "click" ); - $( ".ui-datepicker-calendar tbody a:contains(18)", picker ).simulate( "mousedown" ); - TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), new Date( 2008, 3 - 1, 18 ), - "Mouse click - next" ); - - /* - // TODO: Re-add when min and max options are introduced. - // Previous/next with minimum/maximum - input.datepicker( "option", { - minDate: new Date( 2008, 2 - 1, 2 ), - maxDate: new Date( 2008, 2 - 1, 26 ) - }).val( "2/4/08" ).datepicker( "open" ); - $( ".ui-datepicker-prev", picker ).simulate( "click" ); - $( ".ui-datepicker-calendar tbody a:contains(16)", picker ).simulate( "mousedown" ); - TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), new Date( 2008, 2 - 1, 16 ), - "Mouse click - previous + min/max" ); - - input.val( "2/4/08" ).datepicker( "open" ); - $( ".ui-datepicker-next", picker ).simulate( "click" ); - $( ".ui-datepicker-calendar tbody a:contains(18)", picker ).simulate( "mousedown" ); - TestHelpers.datepicker.equalsDate(input.datepicker( "valueAsDate" ), new Date( 2008, 2 - 1, 18 ), - "Mouse click - next + min/max" ); - */ - - // Inline - inline = TestHelpers.datepicker.init( "#inline" ); - picker = $( ".ui-datepicker-inline", inline ); - date = new Date(); - inline.datepicker( "valueAsDate", date ); - $( ".ui-datepicker-calendar tbody a:contains(10)", picker ).simulate( "mousedown", {} ); - date.setDate( 10 ); - TestHelpers.datepicker.equalsDate( inline.datepicker( "valueAsDate" ), date, "Mouse click inline" ); - - inline.datepicker( "option", { showButtonPanel: true } ) - .datepicker( "valueAsDate", new Date( 2008, 2 - 1, 4 )); - $( ".ui-datepicker-calendar tbody a:contains(12)", picker ).simulate( "mousedown", {} ); - TestHelpers.datepicker.equalsDate( inline.datepicker( "valueAsDate" ), new Date( 2008, 2 - 1, 12 ), - "Mouse click inline - preset" ); - - inline.datepicker( "option", { showButtonPanel: true } ); - $( ".ui-datepicker-current", picker ).simulate( "click", {} ); - $( ".ui-datepicker-calendar tbody a:contains(14)", picker ).simulate( "mousedown", {} ); - date.setDate( 14 ); - TestHelpers.datepicker.equalsDate( inline.datepicker( "valueAsDate" ), date, "Mouse click inline - current" ); - - inline.datepicker( "valueAsDate", new Date( 2008, 2 - 1, 4) ); - $( ".ui-datepicker-prev", picker ).simulate( "click" ); - $( ".ui-datepicker-calendar tbody a:contains(16)", picker ).simulate( "mousedown" ); - TestHelpers.datepicker.equalsDate( inline.datepicker( "valueAsDate" ), new Date( 2008, 1 - 1, 16 ), - "Mouse click inline - previous" ); - - inline.datepicker( "valueAsDate", new Date( 2008, 2 - 1, 4) ); - $( ".ui-datepicker-next", picker ).simulate( "click" ); - $( ".ui-datepicker-calendar tbody a:contains(18)", picker ).simulate( "mousedown" ); - TestHelpers.datepicker.equalsDate( inline.datepicker( "valueAsDate" ), new Date( 2008, 3 - 1, 18 ), - "Mouse click inline - next" ); - - input.datepicker( "destroy" ); - inline.datepicker( "destroy" ); +// TODO: implement +test( "ARIA", function() { + expect( 0 ); +}); + +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 ); diff --git a/tests/unit/datepicker/datepicker_events.js b/tests/unit/datepicker/datepicker_events.js index 9ee254e5351..aacaa2a2f6c 100644 --- a/tests/unit/datepicker/datepicker_events.js +++ b/tests/unit/datepicker/datepicker_events.js @@ -1,150 +1,135 @@ -// 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( "datepicker: events" ); test( "beforeOpen", function() { - expect( 0 ); + expect( 3 ); + + 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( 0 ); + 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( 0 ); -}); + expect( 2 ); -test( "select", function() { - expect( 0 ); + 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" ); }); -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" ); +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 ); - */ diff --git a/tests/unit/datepicker/datepicker_methods.js b/tests/unit/datepicker/datepicker_methods.js index 7efea106918..ebee9432640 100644 --- a/tests/unit/datepicker/datepicker_methods.js +++ b/tests/unit/datepicker/datepicker_methods.js @@ -3,9 +3,9 @@ module( "datepicker: methods" ); test( "destroy", function() { - expect( 10 ); - var input = $( "#datepicker" ).datepicker(), - inline = $( "#inline" ).datepicker(); + expect( 6 ); + + var input = $( "#datepicker" ).datepicker(); ok( input.datepicker( "instance" ), "instance created" ); ok( input.attr( "aria-owns" ), "aria-owns attribute added" ); @@ -14,18 +14,12 @@ test( "destroy", function() { ok( !input.datepicker( "instance" ), "instance removed" ); ok( !input.attr( "aria-owns" ), "aria-owns attribute removed" ); ok( !input.attr( "aria-haspopup" ), "aria-haspopup attribute removed" ); - - ok( inline.datepicker( "instance" ), "instance created" ); - ok( inline.children().length > 0, "inline datepicker has children" ); - inline.datepicker( "destroy" ); - ok( !inline.datepicker( "instance" ), "instance removed" ); - ok( inline.children().length === 0, "inline picker no longer has children" ); }); test( "enable / disable", function() { expect( 6 ); - var inl, - inp = TestHelpers.datepicker.init( "#datepicker" ), + + var inp = TestHelpers.datepicker.init( "#datepicker" ), dp = inp.datepicker( "widget" ); ok( !inp.datepicker( "option", "disabled" ), "initially enabled" ); @@ -38,80 +32,105 @@ test( "enable / disable", function() { inp.datepicker( "enable" ); ok( !inp.datepicker( "option", "disabled" ), "enabled after enable() call" ); ok( !dp.hasClass( "ui-datepicker-disabled" ), "no longer has disabled class name" ); - - // Inline - inl = TestHelpers.datepicker.init( "#inline" ); - dp = inl.datepicker( "instance" ); - - // TODO: Disabling inline pickers does not work. - // TODO: When changeMonth and changeYear options are implemented ensure their dropdowns - // are properly disabled when in an inline picker. }); test( "widget", function() { expect( 1 ); + var actual = $( "#datepicker" ).datepicker().datepicker( "widget" ); deepEqual( $( "body > .ui-front" )[ 0 ], actual[ 0 ] ); actual.remove(); }); -test( "close", function() { - expect( 0 ); -}); +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" ); -test( "open", function() { - expect( 0 ); + 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( 6 ); + expect( 4 ); + var input = $( "#datepicker" ).datepicker(), - picker = input.datepicker( "widget" ), - inline = $( "#inline" ).datepicker(); + picker = input.datepicker( "widget" ); input.datepicker( "value", "1/1/14" ); equal( input.val(), "1/1/14", "input's value set" ); - ok( picker.find( "a[data-timestamp]:first" ).hasClass( "ui-state-focus" ), - "first day marked as selected" ); + + 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" ), "abc", - "Invalid values should be returned without formatting." ); - - inline.datepicker( "value", "1/1/14" ); - ok( inline.find( "a[data-timestamp]:first" ).hasClass( "ui-state-focus" ), - "first day marked as selected" ); - equal( inline.datepicker( "value" ), "1/1/14", "getter" ); - - input.datepicker( "destroy" ); - inline.datepicker( "destroy" ); + equal( input.datepicker( "value" ), null, "Invalid values should return null." ); }); test( "valueAsDate", function() { - expect( 6 ); - var input = $( "#datepicker" ).datepicker(), + expect( 13 ); + + var minDate, maxDate, dateAndTimeToSet, dateAndTimeClone, + input = TestHelpers.datepicker.init( "#datepicker" ), picker = input.datepicker( "widget" ), - inline = $( "#inline" ).datepicker(); + 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-focus" ), - "first day marked as selected" ); - TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), - new Date( 2014, 0, 1 ), "getter" ); + 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" ); - inline.datepicker( "valueAsDate", new Date( 2014, 0, 1 ) ); - ok( inline.find( "a[data-timestamp]:first" ).hasClass( "ui-state-focus" ), - "first day marked as selected" ); - TestHelpers.datepicker.equalsDate( inline.datepicker( "valueAsDate" ), - new Date( 2014, 0, 1 ), "getter" ); + input.val( "" ).datepicker( "destroy" ); + input = TestHelpers.datepicker.init( "#datepicker" ); - input.datepicker( "destroy" ); - inline.datepicker( "destroy" ); + 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() { diff --git a/tests/unit/datepicker/datepicker_options.js b/tests/unit/datepicker/datepicker_options.js index 173e19e5203..1a32348cde9 100644 --- a/tests/unit/datepicker/datepicker_options.js +++ b/tests/unit/datepicker/datepicker_options.js @@ -40,6 +40,102 @@ test( "appendTo", function() { input.datepicker( "destroy" ); }); +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 }); + + btn = element.datepicker( "widget" ).find( ".ui-calendar-buttonpane button" ); + equal( btn.length, 2, "number of buttons" ); + + i = 0; + $.each( buttons, function( key ) { + equal( btn.eq( i ).text(), key, "text of button " + ( i + 1 ) ); + i++; + }); + + 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" ); + + 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("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(); +}); + test( "dateFormat", function() { expect( 2 ); var input = $( "#datepicker" ).val( "1/1/14" ).datepicker(), @@ -97,6 +193,7 @@ test( "eachDay", function() { }); test( "numberOfMonths", function() { + // TODO implement this expect( 0 ); }); @@ -134,16 +231,16 @@ test( "showWeek", function() { container = input.datepicker( "widget" ); equal( container.find( "thead th" ).length, 7, "just 7 days, no column cell" ); - equal( container.find( ".ui-datepicker-week-col" ).length, 0, + 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-datepicker-week-col" ), + 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-datepicker-week-col" ).length, + equal( container.find( ".ui-calendar-week-col" ).length, container.find( "tr" ).length, "one week cell for each week" ); input.datepicker( "destroy" ); @@ -155,256 +252,7 @@ test( "showWeek", function() { }); /* -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" ); -}); - -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" ); -}); - -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" ); -}); - -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" ); -}); - -(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(); - }); - } - - function step1() { - - var inp = TestHelpers.datepicker.initNewInput(), - dp = $( "#ui-datepicker-div" ); - - 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" ); - - step2(); - }); - } - - 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(); - }); - } - - 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(); - }); - } - - 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(); - } - } - - step0(); - }); -})(); - -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" ); -}); - +// TODO: Move to calendar and rewrite for value option test( "defaultDate", function() { expect( 16 ); var inp = TestHelpers.datepicker.init( "#inp" ), @@ -500,333 +348,141 @@ test( "defaultDate", function() { 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 = 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", {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" ); + 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( "getDate" ), maxDate, - "Min/max - 02/29/2008, 12/07/2008 - ctrl+pgdn" ); + 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( "show" ); + 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" ), lastYear, - "Min/max - null, 12/07/2008 - ctrl+pgup" ); - inp.val( "06/04/2008" ).datepicker( "show" ); + 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( "getDate" ), maxDate, - "Min/max - null, 12/07/2008 - ctrl+pgdn" ); + 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" ); + 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( "getDate" ), date, - "Min/max - -1w, +1 M +10 D - ctrl+pgup" ); + 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" ); + 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" ); + 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-datepicker-prev" ).hasClass( "ui-state-disabled" ), "Year Range Test - previous button disabled at 1/1/minYear" ); + 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-datepicker-next" ).hasClass( "ui-state-disabled" ), "Year Range Test - next button disabled at 12/30/maxYear" ); + ok(dp.find( ".ui-calendar-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", + 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", + 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" ); + */ }); +/* +// TODO: Move this to $.date, Globalize or calendar widget test( "daylightSaving", function() { expect( 25 ); var inp = TestHelpers.datepicker.init( "#inp" ), @@ -834,440 +490,112 @@ test( "daylightSaving", function() { 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" ); + $( ".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-datepicker-calendar td:eq(7) a", dp).simulate( "click" ); + $( ".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-datepicker-calendar td:eq(8) a", dp).simulate( "click" ); + $( ".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-datepicker-calendar td:eq(6) a", dp).simulate( "click" ); + $( ".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-datepicker-calendar td:eq(7) a", dp).simulate( "click" ); + $( ".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-datepicker-calendar td:eq(8) a", dp).simulate( "click" ); + $( ".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" ); + $( ".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-datepicker-calendar td:eq(21) a", dp).simulate( "click" ); + $( ".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-datepicker-calendar td:eq(22) a", dp).simulate( "click" ); + $( ".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-datepicker-calendar td:eq(13) a", dp).simulate( "click" ); + $( ".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-datepicker-calendar td:eq(14) a", dp).simulate( "click" ); + $( ".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-datepicker-calendar td:eq(15) a", dp).simulate( "click" ); + $( ".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" ); + $( ".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-datepicker-calendar td:eq(35) a", dp).simulate( "click" ); + $( ".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-datepicker-calendar td:eq(36) a", dp).simulate( "click" ); + $( ".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-datepicker-calendar td:eq(27) a", dp).simulate( "click" ); + $( ".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-datepicker-calendar td:eq(28) a", dp).simulate( "click" ); + $( ".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-datepicker-calendar td:eq(29) a", dp).simulate( "click" ); + $( ".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" ); + $( ".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-datepicker-calendar td:eq(14) a", dp).simulate( "click" ); + $( ".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-datepicker-calendar td:eq(15) a", dp).simulate( "click" ); + $( ".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-datepicker-calendar td:eq(6) a", dp).simulate( "click" ); + $( ".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-datepicker-calendar td:eq(7) a", dp).simulate( "click" ); + $( ".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-datepicker-calendar td:eq(8) a", dp).simulate( "click" ); + $( ".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.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" ); -}); - -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 1d922c72220..f62e086b974 100644 --- a/tests/unit/datepicker/datepicker_test_helpers.js +++ b/tests/unit/datepicker/datepicker_test_helpers.js @@ -15,14 +15,12 @@ TestHelpers.datepicker = { equal( d1.toString(), d2.toString(), message ); }, init: function( id, options ) { - options = $.extend( { show: false }, options || {} ); + options = $.extend( { show: false, hide: false }, options || {} ); return $( id ).datepicker( options ); }, initNewInput: function( options ) { - options = $.extend( { show: false }, options || {} ); + options = $.extend( { show: false, hide: false }, options || {} ); return $( "" ).datepicker( options ) .appendTo( "#qunit-fixture" ); - }, - onFocus: TestHelpers.onFocus, - PROP_NAME: "datepicker" + } }; \ 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 aa47853507f..ac84f640dee 100644 --- a/themes/base/datepicker.css +++ b/themes/base/datepicker.css @@ -8,173 +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: 19px; - height: 18px; -} -.ui-datepicker .ui-datepicker-prev:not(.ui-state-hover):not(.ui-state-focus), -.ui-datepicker .ui-datepicker-next:not(.ui-state-hover):not(.ui-state-focus) { - background: none; - border: none; -} -.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 .ui-icon, -.ui-datepicker .ui-datepicker-next .ui-icon { - 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 += "
      " + + "
      "; + if ( months[ i ].first ) { + html += this._buildPreviousLink(); + } + if ( months[ i ].last ) { + html += this._buildNextLink(); + } + + html += this._buildTitlebar(); + html += "
      "; + html += this._buildGrid(); + html += "
      "; + } + + html += "
      "; + + this.date = currentDate; + + return html; + }, + + _buildHeader: function() { + return "
      " + + this._buildPreviousLink() + + this._buildNextLink() + + this._buildTitlebar() + + "
      "; + }, + + _buildPreviousLink: function() { + return ""; + }, + + _buildNextLink: function() { + return ""; + }, + + _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 f2dfa2d1594..c58e4d47e4b 100644 --- a/ui/datepicker.js +++ b/ui/datepicker.js @@ -16,7 +16,7 @@ "jquery", "./core", "./widget", - "./button", + "./calendar", "./position" ], factory ); } else { @@ -26,23 +26,17 @@ } }(function( $ ) { -// TODO use uniqueId, if possible -var idIncrement = 0, - // TODO move this to the instance - suppressExpandOnFocus = false; +var widget, + calendarOptions = [ "buttons", "dateFormat", "eachDay", "max", "min", "numberOfMonths", "showWeek" ]; -$.widget( "ui.datepicker", { +widget = $.widget( "ui.datepicker", { + version: "@VERSION", options: { appendTo: null, - dateFormat: { date: "short" }, - // TODO review - eachDay: $.noop, - numberOfMonths: 1, position: { my: "left top", at: "left bottom" }, - showWeek: false, show: true, hide: true, @@ -54,243 +48,147 @@ $.widget( "ui.datepicker", { }, _create: function() { - this.date = $.date( null, this.options.dateFormat ); + this.suppressExpandOnFocus = false; - this.date.eachDay = this.options.eachDay; - this.id = "ui-datepicker-" + idIncrement; - idIncrement++; - if ( this.element.is( "input" ) ) { - this._createPicker(); - } else { - this.inline = true; - this.picker = this.element; + if ( typeof this.options.max === "string" ) { + this.options.max = Globalize.parseDate( this.options.max , { pattern: "yyyy-MM-dd" } ); + } + if ( typeof this.options.min === "string" ) { + this.options.min = Globalize.parseDate( this.options.min , { pattern: "yyyy-MM-dd" } ); } - this._on( this.picker, { - "click .ui-datepicker-prev": function( event ) { - event.preventDefault(); - this.date.adjust( "M", -this.options.numberOfMonths ); - this.refresh(); - }, - "click .ui-datepicker-next": function( event ) { - event.preventDefault(); - this.date.adjust( "M", this.options.numberOfMonths ); - this.refresh(); - }, - "click .ui-datepicker-current": function( event ) { - event.preventDefault(); - this._select( event, new Date().getTime() ); - }, - "click .ui-datepicker-close": function( event ) { - event.preventDefault(); - this.close( event ); - }, - "mousedown .ui-datepicker-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" ) ); - if ( this.inline ) { - this.grid.focus( 1 ); - } - }, - "keydown .ui-datepicker-calendar": "_handleKeydown" - }); - // TODO use hoverable (no delegation support)? convert to _on? - this.picker.delegate( ".ui-datepicker-header a, .ui-datepicker-calendar a", "mouseenter.datepicker mouseleave.datepicker", function() { - $( this ).toggleClass( "ui-state-hover" ); - }); + this._createCalendar(); - this._createTmpl(); + this._on( this._inputEvents ); + this._on( this.calendar, this._calendarEvents ); + this._on( this.document, this._documentEvents ); }, - _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(); + _getCreateOptions: function() { + return { + max: this.element.attr( "max" ), + min: this.element.attr( "min" ) + }; + }, - var newId, newCell, - activeCell = $( "#" + this.grid.attr( "aria-activedescendant" ) ), - oldMonth = this.date.month(), - oldYear = this.date.year(); + _createCalendar: function() { + var that = this; - // 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; - } + this.calendar = $( "
      " ) + .addClass( "ui-front ui-datepicker" ) + .appendTo( this._appendTo() ); - if ( this.date.month() !== oldMonth || this.date.year() !== oldYear ) { - this.refresh(); - this.grid.focus( 1 ); - } else { - newId = this.id + "-" + this.date.day(); - newCell = $( "#" + newId ); + // 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" ); - // TODO unnecessary optimization? is it really needed? - if ( !newCell.length ) { - return; - } + this.calendarInstance._buttonClickContext = function() { + return that.element[ 0 ]; + }; - this.grid.attr("aria-activedescendant", newId); + this._setHiddenPicker(); - this.grid.find( ".ui-state-focus" ).removeClass( "ui-state-focus" ); - newCell.children( "a" ).addClass( "ui-state-focus" ); - } + this.element.attr({ + "aria-haspopup": true, + "aria-owns": this.calendar.attr( "id" ) + }); }, - _createPicker: function() { - this.picker = $( "
      " ) - .addClass( "ui-front" ) - // TODO add a ui-datepicker-popup class, move position:absolte to that - .css( "position", "absolute" ) - .uniqueId() - .hide(); - this._setHiddenPicker(); - this.picker.appendTo( this._appendTo() ); - - this.element - .attr( "aria-haspopup", "true" ) - .attr( "aria-owns", this.picker.attr( "id" ) ); - - this._on({ - 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.picker.hide(); + _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.ESCAPE: - if ( this.isOpen ) { - this.close( event ); - } - break; - case $.ui.keyCode.ENTER: - this._handleKeydown( event ); - break; - case $.ui.keyCode.DOWN: - case $.ui.keyCode.UP: - clearTimeout( this.closeTimer ); - this._delay( function() { - this.open( event ); - this.grid.focus( 1 ); - }, 1 ); - break; - case $.ui.keyCode.HOME: - if ( event.ctrlKey ) { - this.date.setTime( new Date() ); - event.preventDefault(); - if ( this.isOpen ) { - this.refresh(); - } else { - this.open( event ); - } - } - break; - case $.ui.keyCode.END: - if ( event.ctrlKey ) { - this.element.val( "" ); - event.preventDefault(); - if ( this.isOpen ) { - this.close( event ); - } - } - break; - } - }, - keyup: function() { - if ( this.isValid() && !this.inline ) { - this.date.setTime( this.element.val() ).select(); - this.refresh(); - } - }, - mousedown: function( event ) { - if (this.isOpen) { - suppressExpandOnFocus = true; - this.close(); - return; - } - this.open( event ); - clearTimeout( this.closeTimer ); - }, - focus: function( event ) { - if ( !suppressExpandOnFocus ) { + } + break; + case $.ui.keyCode.DOWN: + case $.ui.keyCode.UP: + clearTimeout( this.closeTimer ); this._delay( function() { - if ( !this.isOpen ) { - this.open( event ); - } - }, 1); - } + this.open( event ); + this.calendarInstance.grid.focus( 1 ); + }, 1 ); + break; + } + }, + keyup: function() { + if ( this.isValid() ) { + this.valueAsDate( this._getParsedValue() ); + } + }, + mousedown: function( event ) { + if ( this.isOpen ) { + this.suppressExpandOnFocus = true; + this.close(); + return; + } + this.open( event ); + clearTimeout( this.closeTimer ); + }, + focus: function( event ) { + if ( !this.suppressExpandOnFocus && !this.isOpen ) { this._delay( function() { - suppressExpandOnFocus = false; - }, 100 ); - }, - blur: function() { - suppressExpandOnFocus = false; + this.open( event ); + }, 1); } - }); + this._delay( function() { + this.suppressExpandOnFocus = false; + }, 100 ); + }, + blur: function() { + this.suppressExpandOnFocus = false; + } + }, - this._on( this.picker, { - 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.picker.is( ":visible" ) ) { - this.close( event ); - this._focusTrigger(); - } + _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(); } - }); + } + }, - this._on( this.document, { - click: function( event ) { - if ( this.isOpen && !$( event.target ).closest( this.element.add( this.picker ) ).length ) { - this.close( event ); - } + _documentEvents: { + mousedown: function( event ) { + if ( !this.isOpen ) { + return; } - }); + + if ( !$( event.target ).closest( this.element.add( this.calendar ) ).length ) { + this.close( event ); + } + } }, _appendTo: function() { @@ -302,7 +200,7 @@ $.widget( "ui.datepicker", { this.document.find( element ).eq( 0 ); } - if ( !element ) { + if ( !element || !element[ 0 ] ) { element = this.element.closest( ".ui-front" ); } @@ -312,313 +210,35 @@ $.widget( "ui.datepicker", { return element; }, - _createTmpl: function() { - this._createDatepicker(); - this.picker.find( "button" ).button(); - - if ( this.inline ) { - this.picker.children().addClass( "ui-datepicker-inline" ); - } - // against display:none in datepicker.css - this.picker.find( ".ui-datepicker" ).css( "display", "block" ); - this.grid = this.picker.find( ".ui-datepicker-calendar" ); - }, - _createDatepicker: function() { - var multiClasses = [], - pickerHtml = ""; - - if (this.options.numberOfMonths === 1 ) { - pickerHtml = this._buildHeader() + this._buildGrid() + this._buildButtons(); - } else { - pickerHtml = this._buildMultiplePicker(); - multiClasses.push( "ui-datepicker-multi" ); - multiClasses.push( "ui-datepicker-multi-" + this.options.numberOfMonths ); - } - - $( "
      " ) - .addClass( "ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all" ) - .addClass( multiClasses.join( " " ) ) - .attr({ - role: "region", - "aria-labelledby": this.id + "-title" - }) - .html( pickerHtml ) - .appendTo( this.picker ); - }, - _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 += "
      " + - "
      "; - if ( months[ i ].first ) { - html += this._buildPreviousLink(); - } - if ( months[ i ].last ) { - html += this._buildNextLink(); - } - - html += this._buildTitlebar(); - html += "
      "; - html += this._buildGrid(); - html += "
      "; - } - - html += "
      "; - html += this._buildButtons(); - - this.date = currentDate; - - return html; - }, - - _buildHeader: function() { - return "
      " + - this._buildPreviousLink() + - this._buildNextLink() + - this._buildTitlebar() + - "
      "; - }, - - _buildPreviousLink: function() { - var labels = Globalize.translate( "datepicker" ); - - return ""; - }, - - _buildNextLink: function() { - var labels = Globalize.translate( "datepicker" ); - - return ""; - }, - - _buildTitlebar: function() { - var labels = Globalize.translate( "datepicker" ); - - return "
      " + - "
      " + - this._buildTitle() + - "
      " + - ", " + labels.datePickerRole + "" + - "
      "; - }, - - _buildTitle: function() { - return "" + - this.date.monthName() + - " " + - "" + - this.date.year() + - ""; - }, - - _buildGrid: function() { - return "" + - this._buildGridHeading() + - this._buildGridBody() + - "
      "; - }, - - _buildGridHeading: function() { - var cells = "", - i = 0, - labels = Globalize.translate( "datepicker" ); - - if ( this.options.showWeek ) { - cells += "" + 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() { - // 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 contents = "", - idAttribute = day.render ? ( "id=" + this.id + "-" + day.date ) : "", - ariaSelectedAttribute = "aria-selected=" + ( day.current ? "true" : "false" ), - ariaDisabledAttribute = day.selectable ? "" : "aria-disabled=true"; - - if ( day.render ) { - if ( day.selectable ) { - contents = this._buildDayLink( day ); - } else { - contents = this._buildDayDisplay( day ); - } - } - - return "" + - contents + - ""; - }, - - _buildDayLink: function( day ) { - var link, - classes = [ "ui-state-default" ], - labels = Globalize.translate( "datepicker" ); - - if ( day.date === this.date.day() ) { - classes.push( "ui-state-focus" ); - } - if ( day.current ) { - classes.push( "ui-state-active" ); - } - if ( day.today ) { - classes.push( "ui-state-highlight" ); - } - if ( day.extraClasses ) { - classes.push( day.extraClasses.split( " " ) ); - } - - link = "" + - day.date + ""; - if ( day.today ) { - link += ", " + labels.currentText + ""; - } - - return link; - }, - - _buildDayDisplay: function( day ) { - var classes = []; - - if ( day.current ) { - classes.push( "ui-state-active" ); - } - if ( day.today ) { - classes.push( "ui-state-highlight" ); - } - if ( day.extraClasses ) { - classes.push( day.extraClasses.split( " " ) ); - } - - return "" + day.date + ""; - }, - - _buildButtons: function() { - var labels = Globalize.translate( "datepicker" ); - - return "
      " + - "" + - "" + - "
      "; - }, _focusTrigger: function() { - suppressExpandOnFocus = true; + this.suppressExpandOnFocus = true; this.element.focus(); }, - // Refreshing the entire datepicker 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() { - //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-datepicker-title", this.picker ).html( this._buildTitle() ); - $( ".ui-datepicker-calendar", this.picker ).replaceWith( this.grid ); - } else { - this._refreshMultiplePicker(); - } - }, - - _refreshMultiplePicker: function() { - for ( var i = 0; i < this.options.numberOfMonths; i++ ) { - $( ".ui-datepicker-title", this.picker ).eq( i ).html( this._buildTitle() ); - $( ".ui-datepicker-calendar", this.picker ).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.picker ).find( ".ui-state-focus" ).not( ":first" ).removeClass( "ui-state-focus" ); + this.calendarInstance.valueAsDate( this._getParsedValue() ); + this.calendarInstance.refresh(); }, open: function( event ) { - if ( this.inline || this.isOpen ) { + if ( this.isOpen ) { return; } if ( this._trigger( "beforeOpen", event ) === false ) { return; } - // TODO explain this - this.date = $.date( this.element.val(), this.options.dateFormat ); - this.date.eachDay = this.options.eachDay; - this.date.select(); - this.refresh(); - - this.picker - .attr( "aria-hidden", "false" ) - .attr( "aria-expanded", "true" ) + this.calendarInstance.refresh(); + this.calendar + .attr({ + "aria-hidden": false, + "aria-expanded": true + }) .show() .position( this._buildPosition() ) .hide(); - - this._show( this.picker, this.options.show ); + this._show( this.calendar, this.options.show ); // 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 @@ -629,12 +249,8 @@ $.widget( "ui.datepicker", { }, close: function( event ) { - if ( this.inline ) { - return; - } - this._setHiddenPicker(); - this._hide( this.picker, this.options.hide ); + this._hide( this.calendar, this.options.hide ); this.element.attr( "tabindex" , 0 ); @@ -643,105 +259,82 @@ $.widget( "ui.datepicker", { }, _setHiddenPicker: function() { - this.picker - .attr( "aria-hidden", "true" ) - .attr( "aria-expanded", "false" ); - }, - - _buildPosition: function() { - return $.extend( {}, { - of: this.element - }, this.options.position ); - }, - - _select: function( event, time ) { - this.date.setTime( time ).select(); - this.refresh(); - if ( !this.inline ) { - this.element.val( this.date.format() ); - this.close(); - this._focusTrigger(); - } - this._trigger( "select", event, { - // TODO replace with value option to initialise and read - date: this.date.format() + this.calendar.attr({ + "aria-hidden": true, + "aria-expanded": false }); }, - _value: function( value ) { - this.date.setTime( value ).select(); - if ( !this.inline ) { - this.element.val( this.date.format() ); - } - this.refresh(); + _buildPosition: function() { + return $.extend( {}, { of: this.element }, this.options.position ); }, value: function( value ) { if ( arguments.length ) { - this._value( value ); + this.valueAsDate( Globalize.parseDate( value , this.options.dateFormat ) ); } else { - return this.isValid() ? this.date.format() : this.element.val(); + return ( this._getParsedValue() !== null ) ? this.element.val() : null; } }, valueAsDate: function( value ) { if ( arguments.length ) { - this._value( value ); + if ( this.calendarInstance._isValid( value ) ) { + this.calendarInstance.valueAsDate( value ); + this.element.val( Globalize.format( value, this.options.dateFormat ) ); + } } else { - return this.isValid() ? this.date.date() : null; + return this._getParsedValue(); } }, isValid: function() { - if ( this.inline ) { - return true; - } - - return Globalize.parseDate( this.element.val(), this.options.dateFormat ) !== null; + return this.calendarInstance._isValid( this._getParsedValue() ); }, _destroy: function() { - if ( this.inline ) { - this.picker.empty(); - } else { - this.picker.remove(); - this.element - .removeAttr( "aria-haspopup" ) - .removeAttr( "aria-owns" ); - } + this.calendarInstance.destroy(); + this.calendar.remove(); + this.element.removeAttr( "aria-haspopup aria-owns" ); }, widget: function() { - return this.picker; + return this.calendar; + }, + + _getParsedValue: function() { + return Globalize.parseDate( this.element.val() , this.options.dateFormat ); }, _setOption: function( key, value ) { this._super( key, value ); - if ( key === "appendTo" ) { - this.picker.appendTo( this._appendTo() ); + if ( $.inArray( key, calendarOptions ) !== -1 ) { + this.calendarInstance._setOption( key, value ); } - if ( key === "eachDay" ) { - this.date.eachDay = this.options.eachDay; - this.refresh(); + if ( key === "appendTo" ) { + this.calendar.appendTo( this._appendTo() ); } if ( key === "dateFormat" ) { - this.date.setFormat( this.options.dateFormat ); - if ( !this.inline ) { - this.element.val( this.date.format() ); - } + this.element.val( this.calendarInstance.value() ); } - if ( key === "showWeek" ) { - this.refresh(); + if ( key === "max" || key === "min" ) { + this.element.attr( key, Globalize.format( value, { pattern: "yyyy-MM-dd" } ) ); } if ( key === "position" ) { - this.picker.position( this._buildPosition() ); + this.calendar.position( this._buildPosition() ); } } }); +$.each( calendarOptions, function( index, option ) { + $.ui.datepicker.prototype.options[ option ] = $.ui.calendar.prototype.options[ option ]; +}); + +return widget; + }));