From 73a3d4e2915840306a826c4b47d03807f9de67b8 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Fri, 16 May 2014 00:19:32 +0200 Subject: [PATCH 01/94] Datepicker: Introduce value option Change status caching, fix existing value related methods, introduce $.date construction with date object, add selected getter --- external/date.js | 6 ++++ ui/datepicker.js | 85 +++++++++++++++++++++++++++++------------------- 2 files changed, 58 insertions(+), 33 deletions(-) diff --git a/external/date.js b/external/date.js index 06a67553205..71963981129 100644 --- a/external/date.js +++ b/external/date.js @@ -26,6 +26,9 @@ $.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; @@ -180,6 +183,9 @@ $.date.prototype = { this.selected = this.clone(); return this; }, + selectedDate: function() { + return this.selected; + }, clone: function() { var date = this.dateObject; return new $.date( new Date( date.getFullYear(), date.getMonth(), diff --git a/ui/datepicker.js b/ui/datepicker.js index f2dfa2d1594..28a3e478325 100644 --- a/ui/datepicker.js +++ b/ui/datepicker.js @@ -45,6 +45,7 @@ $.widget( "ui.datepicker", { showWeek: false, show: true, hide: true, + value: null, // callbacks beforeOpen: null, @@ -54,17 +55,22 @@ $.widget( "ui.datepicker", { }, _create: function() { - this.date = $.date( null, this.options.dateFormat ); - - this.date.eachDay = this.options.eachDay; this.id = "ui-datepicker-" + idIncrement; idIncrement++; + if ( this.element.is( "input" ) ) { + if ( !this.options.value && this.isValid() ) { + this.options.value = this._getParsedValue(); + } this._createPicker(); } else { this.inline = true; this.picker = this.element; } + + this.date = $.date( this.options.value, this.options.dateFormat ).select(); + this.date.eachDay = this.options.eachDay; + this._on( this.picker, { "click .ui-datepicker-prev": function( event ) { event.preventDefault(); @@ -106,7 +112,7 @@ $.widget( "ui.datepicker", { _handleKeydown: function( event ) { if ( jQuery.inArray( event.keyCode, [ 13, 33, 34, 35, 36, 37, 38, 39, 40 ] ) === -1 ) { - //only interested navigation keys + // only interested navigation keys return; } event.preventDefault(); @@ -171,7 +177,7 @@ $.widget( "ui.datepicker", { _createPicker: function() { this.picker = $( "
" ) .addClass( "ui-front" ) - // TODO add a ui-datepicker-popup class, move position:absolte to that + // TODO add a ui-datepicker-popup class, move position:absolute to that .css( "position", "absolute" ) .uniqueId() .hide(); @@ -217,6 +223,7 @@ $.widget( "ui.datepicker", { } } break; + // TODO this is not in specs, keep? case $.ui.keyCode.END: if ( event.ctrlKey ) { this.element.val( "" ); @@ -230,12 +237,12 @@ $.widget( "ui.datepicker", { }, keyup: function() { if ( this.isValid() && !this.inline ) { - this.date.setTime( this.element.val() ).select(); + this.date.setTime( this._getParsedValue() ).select(); this.refresh(); } }, mousedown: function( event ) { - if (this.isOpen) { + if ( this.isOpen ) { suppressExpandOnFocus = true; this.close(); return; @@ -312,6 +319,7 @@ $.widget( "ui.datepicker", { return element; }, + _createTmpl: function() { this._createDatepicker(); this.picker.find( "button" ).button(); @@ -323,6 +331,7 @@ $.widget( "ui.datepicker", { this.picker.find( ".ui-datepicker" ).css( "display", "block" ); this.grid = this.picker.find( ".ui-datepicker-calendar" ); }, + _createDatepicker: function() { var multiClasses = [], pickerHtml = ""; @@ -345,6 +354,7 @@ $.widget( "ui.datepicker", { .html( pickerHtml ) .appendTo( this.picker ); }, + _buildMultiplePicker: function() { var headerClass, html = "", @@ -572,8 +582,8 @@ $.widget( "ui.datepicker", { // 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 + // 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() ); @@ -605,10 +615,6 @@ $.widget( "ui.datepicker", { 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 @@ -649,46 +655,38 @@ $.widget( "ui.datepicker", { }, _buildPosition: function() { - return $.extend( {}, { - of: this.element - }, this.options.position ); + return $.extend( {}, { of: this.element }, this.options.position ); }, _select: function( event, time ) { - this.date.setTime( time ).select(); - this.refresh(); + this._setOption( "value", new Date( time ) ); 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() + date: this.value() }); }, - _value: function( value ) { - this.date.setTime( value ).select(); - if ( !this.inline ) { - this.element.val( this.date.format() ); - } - this.refresh(); - }, - value: function( value ) { if ( arguments.length ) { - this._value( value ); + this._setOption( "value", Globalize.parseDate( value, this.options.dateFormat ) ); } else { - return this.isValid() ? this.date.format() : this.element.val(); + if ( this.inline ) { + return Globalize.format( this.date.selected(), this.options.dateFormat ); + } else { + return this.element.val(); + } } }, valueAsDate: function( value ) { if ( arguments.length ) { - this._value( value ); + this._setOption( "value", value ); } else { - return this.isValid() ? this.date.date() : null; + return this.option( "value" ); } }, @@ -697,7 +695,7 @@ $.widget( "ui.datepicker", { return true; } - return Globalize.parseDate( this.element.val(), this.options.dateFormat ) !== null; + return this._getParsedValue() !== null; }, _destroy: function() { @@ -715,7 +713,28 @@ $.widget( "ui.datepicker", { return this.picker; }, + _getParsedValue: function() { + return Globalize.parseDate( this.element.val(), this.options.dateFormat ); + }, + + option: function( key ) { + if ( arguments.length === 0 || ( arguments.length === 1 && key === "value" ) ) { + this.options.value = this.inline ? this.date.selected() : this._getParsedValue(); + } + return this._superApply( arguments ); + }, + _setOption: function( key, value ) { + if ( key === "value" ) { + if ( value instanceof Date ) { + this.date.setTime( value.getTime() ).select(); + this.refresh(); + if ( !this.inline ) { + this.element.val( this.date.format() ); + } + } + } + this._super( key, value ); if ( key === "appendTo" ) { From 500ba8de08fa92cc5c957ae4dc1330df3b0ac795 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Tue, 3 Jun 2014 23:18:51 +0200 Subject: [PATCH 02/94] Calendar: Add calendar widget Add calendar widget by copying and renaming datepicker widget files --- Gruntfile.js | 1 + build/tasks/testswarm.js | 1 + demos/calendar/buttonbar.html | 33 + demos/calendar/date-formats.html | 59 + demos/calendar/default.html | 31 + demos/calendar/dropdown-month-year.html | 34 + demos/calendar/index.html | 28 + demos/calendar/localization.html | 40 + demos/calendar/min-max.html | 31 + demos/calendar/multiple-calendars.html | 34 + demos/calendar/other-months.html | 40 + demos/calendar/show-week.html | 35 + demos/index.html | 1 + tests/unit/all.html | 1 + tests/unit/calendar/all.html | 26 + tests/unit/calendar/calendar.html | 49 + tests/unit/calendar/calendar_common.js | 7 + tests/unit/calendar/calendar_core.js | 711 ++++++++++ tests/unit/calendar/calendar_events.js | 150 +++ tests/unit/calendar/calendar_methods.js | 130 ++ tests/unit/calendar/calendar_options.js | 1273 ++++++++++++++++++ tests/unit/calendar/calendar_test_helpers.js | 28 + tests/unit/index.html | 1 + themes/base/base.css | 1 + themes/base/calendar.css | 179 +++ ui/calendar.js | 766 +++++++++++ 26 files changed, 3690 insertions(+) create mode 100644 demos/calendar/buttonbar.html create mode 100644 demos/calendar/date-formats.html create mode 100644 demos/calendar/default.html create mode 100644 demos/calendar/dropdown-month-year.html create mode 100644 demos/calendar/index.html create mode 100644 demos/calendar/localization.html create mode 100644 demos/calendar/min-max.html create mode 100644 demos/calendar/multiple-calendars.html create mode 100644 demos/calendar/other-months.html create mode 100644 demos/calendar/show-week.html create mode 100644 tests/unit/calendar/all.html create mode 100644 tests/unit/calendar/calendar.html create mode 100644 tests/unit/calendar/calendar_common.js create mode 100644 tests/unit/calendar/calendar_core.js create mode 100644 tests/unit/calendar/calendar_events.js create mode 100644 tests/unit/calendar/calendar_methods.js create mode 100644 tests/unit/calendar/calendar_options.js create mode 100644 tests/unit/calendar/calendar_test_helpers.js create mode 100644 themes/base/calendar.css create mode 100644 ui/calendar.js 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/calendar/buttonbar.html b/demos/calendar/buttonbar.html new file mode 100644 index 00000000000..77da1ab5749 --- /dev/null +++ b/demos/calendar/buttonbar.html @@ -0,0 +1,33 @@ + + + + + jQuery UI Calendar - Display button bar + + + + + + + + + + + + + + + +

Date:

+ +
+

Display a button for selecting Today's date and a Done button for closing the calendar with the boolean showButtonPanel option. Each button is enabled by default when the bar is displayed, but can be turned off with additional options. Button text is customizable.

+
+ + diff --git a/demos/calendar/date-formats.html b/demos/calendar/date-formats.html new file mode 100644 index 00000000000..95adf01fd64 --- /dev/null +++ b/demos/calendar/date-formats.html @@ -0,0 +1,59 @@ + + + + + jQuery UI Calendar - Format date + + + + + + + + + + + + + + + +

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/calendar/default.html b/demos/calendar/default.html new file mode 100644 index 00000000000..26c4c2eb3d5 --- /dev/null +++ b/demos/calendar/default.html @@ -0,0 +1,31 @@ + + + + + jQuery UI Calendar - Default functionality + + + + + + + + + + + + + + + +

Date:

+ +
+

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/calendar/dropdown-month-year.html b/demos/calendar/dropdown-month-year.html new file mode 100644 index 00000000000..30d4fa80b87 --- /dev/null +++ b/demos/calendar/dropdown-month-year.html @@ -0,0 +1,34 @@ + + + + + jQuery UI Calendar - Display month & year menus + + + + + + + + + + + + + + + +

Date:

+ +
+

Show month and year dropdowns in place of the static month/year header to facilitate navigation through large timeframes. Add the boolean changeMonth and changeYear options.

+
+ + diff --git a/demos/calendar/index.html b/demos/calendar/index.html new file mode 100644 index 00000000000..48097f5983e --- /dev/null +++ b/demos/calendar/index.html @@ -0,0 +1,28 @@ + + + + + + jQuery UI Calendar Demos + + + + + + + diff --git a/demos/calendar/localization.html b/demos/calendar/localization.html new file mode 100644 index 00000000000..8f97bbcc8ef --- /dev/null +++ b/demos/calendar/localization.html @@ -0,0 +1,40 @@ + + + + + jQuery UI Calendar - Localize calendar + + + + + + + + + + + + + + + +

Date:   +

+ +
+

Localize the calendar calendar language and format (English / Western formatting is the default). The calendar includes built-in support for languages that read right-to-left, such as Arabic and Hebrew.

+
+ + diff --git a/demos/calendar/min-max.html b/demos/calendar/min-max.html new file mode 100644 index 00000000000..94826c71a71 --- /dev/null +++ b/demos/calendar/min-max.html @@ -0,0 +1,31 @@ + + + + + jQuery UI Calendar - Restrict date range + + + + + + + + + + + + + + + +

Date:

+ +
+

Restrict the range of selectable dates with the minDate and maxDate options. Set the beginning and end dates as actual dates (new Date(2009, 1 - 1, 26)), as a numeric offset from today (-20), or as a string of periods and units ('+1M +10D'). For the last, use 'D' for days, 'W' for weeks, 'M' for months, or 'Y' for years.

+
+ + diff --git a/demos/calendar/multiple-calendars.html b/demos/calendar/multiple-calendars.html new file mode 100644 index 00000000000..9fe2b7ab526 --- /dev/null +++ b/demos/calendar/multiple-calendars.html @@ -0,0 +1,34 @@ + + + + + jQuery UI Calendar - Display multiple months + + + + + + + + + + + + + + + +

Date:

+ +
+

Set the numberOfMonths option to an integer of 2 or more to show multiple months in a single calendar.

+
+ + diff --git a/demos/calendar/other-months.html b/demos/calendar/other-months.html new file mode 100644 index 00000000000..3ad1aba37d9 --- /dev/null +++ b/demos/calendar/other-months.html @@ -0,0 +1,40 @@ + + + + + jQuery UI Calendar - Dates in other months + + + + + + + + + + + + + + + +

Date:

+ +
+

The calendar can show dates that come from other than the main month + being displayed. These other dates can also be made selectable.

+
+ + diff --git a/demos/calendar/show-week.html b/demos/calendar/show-week.html new file mode 100644 index 00000000000..e7fcb84957b --- /dev/null +++ b/demos/calendar/show-week.html @@ -0,0 +1,35 @@ + + + + + jQuery UI Calendar - Show week of the year + + + + + + + + + + + + + + + +

Date:

+ +
+

The calendar can show the week of the year. The calculation follows + Unicode CLDR specification. + This means that some days from one year may be placed into weeks 'belonging' to another year.

+
+ + diff --git a/demos/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/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..26c46415a6e --- /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..5a5256a6bab --- /dev/null +++ b/tests/unit/calendar/calendar.html @@ -0,0 +1,49 @@ + + + + + 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..b0df728acb6 --- /dev/null +++ b/tests/unit/calendar/calendar_common.js @@ -0,0 +1,7 @@ +/* +TestHelpers.commonWidgetTests( "calendar", { + defaults: { + disabled: false + } +}); +*/ diff --git a/tests/unit/calendar/calendar_core.js b/tests/unit/calendar/calendar_core.js new file mode 100644 index 00000000000..18f00274ec3 --- /dev/null +++ b/tests/unit/calendar/calendar_core.js @@ -0,0 +1,711 @@ +(function( $ ) { + +module( "calendar: core" ); + +TestHelpers.testJshint( "calendar" ); + +test( "input's value determines starting date", function() { + expect( 3 ); + + var input = $( "#calendar" ).val( "1/1/14" ).calendar(), + picker = input.calendar( "widget" ); + + input.calendar( "open" ); + + equal( picker.find( ".ui-calendar-month" ).html(), "January", "correct month displayed" ); + equal( picker.find( ".ui-calendar-year" ).html(), "2014", "correct year displayed" ); + equal( picker.find( ".ui-state-focus" ).html(), "1", "correct day highlighted" ); + + input.val( "" ).calendar( "destroy" ); +}); + +asyncTest( "baseStructure", function() { + expect( 42 ); + var header, title, table, thead, week, panel, inl, child, + inp = TestHelpers.calendar.initNewInput(), + dp = inp.calendar( "widget" ).find( ".ui-calendar" ); + + function step1() { + inp.focus(); + setTimeout(function() { + ok( dp.is( ":visible" ), "Structure - calendar visible" ); + 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, 3, "Structure - child count (header, calendar, buttonpane)" ); + + 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" ); + // TODO: Preserve these class names or let the user use :first-child and :last-child? + // ok( week.children( ":first" ).is( "td.ui-calendar-week-end" ), "Structure - month table first day cell" ); + // ok( week.children( ":last" ).is( "td.ui-calendar-week-end" ), "Structure - month table second day cell" ); + + inp.calendar( "close" ).calendar( "destroy" ); + step2(); + }); + } + + function step2() { + // Editable month/year and button panel + inp = TestHelpers.calendar.initNewInput({ + changeMonth: true, + changeYear: true, + showButtonPanel: true + }); + dp = inp.calendar( "widget" ).find( ".ui-calendar" ); + inp.focus(); + setTimeout(function() { + title = dp.find( "div.ui-calendar-title" ); + // TODO: Re-add tests when changeMonth and changeYear are re-implemented + //ok( title.children( ":first" ).is( "select.ui-calendar-month" ), "Structure - month selector" ); + //ok( title.children( ":last" ).is( "select.ui-calendar-year" ), "Structure - year selector" ); + + panel = dp.children( ":last" ); + ok( panel.is( "div.ui-calendar-buttonpane" ), "Structure - button panel division" ); + equal( panel.children().length, 2, "Structure - button panel child count" ); + ok( panel.children( ":first" ).is( "button.ui-calendar-current" ), "Structure - today button" ); + ok( panel.children( ":last" ).is( "button.ui-calendar-close" ), "Structure - close button" ); + + inp.calendar( "close" ).calendar( "destroy" ); + step3(); + }); + } + + function step3() { + // Multi-month 2 + inp = TestHelpers.calendar.initNewInput({ numberOfMonths: 2 } ); + dp = inp.calendar( "widget" ).find( ".ui-calendar" ); + inp.focus(); + setTimeout(function() { + ok( dp.is( ".ui-calendar-multi" ), "Structure multi [2] - multi-month" ); + equal( dp.children().length, 4, "Structure multi [2] - child count" ); + + child = dp.children( ":first" ); + // TODO: Implement ui-calendar-group-first class name + // ok( child.is( "div.ui-calendar-group" ) && child.is( "div.ui-calendar-group-first" ), "Structure multi [2] - first month division" ); + + child = dp.children( ":eq(1)" ); + // TODO: Implement ui-calendar-group-last class name + // ok( child.is( "div.ui-calendar-group" ) && child.is( "div.ui-calendar-group-last" ), "Structure multi [2] - second month division" ); + + child = dp.children( ":eq(2)" ); + ok( child.is( "div.ui-calendar-row-break" ), "Structure multi [2] - row break" ); + ok( dp.is( ".ui-calendar-multi-2" ), "Structure multi [2] - multi-2" ); + + inp.calendar( "close" ).calendar( "destroy" ); + step4(); + }); + } + + function step4() { + // Multi-month 3 + inp = TestHelpers.calendar.initNewInput({ numberOfMonths: 3 } ); + dp = inp.calendar( "widget" ).find( ".ui-calendar" ); + inp.focus(); + setTimeout(function() { + ok( dp.is( ".ui-calendar-multi-3" ), "Structure multi [3] - multi-3" ); + ok( !dp.is( ".ui-calendar-multi-2" ), "Structure multi [3] - Trac #6704" ); + + inp.calendar( "close" ).calendar( "destroy" ); + step5(); + }); + } + + function step5() { + // Multi-month [2, 2] + inp = TestHelpers.calendar.initNewInput({ numberOfMonths: [ 2, 2 ] } ); + dp = inp.calendar( "widget" ).find( ".ui-calendar" ); + inp.focus(); + setTimeout(function() { + /* + TODO: Re-add after array form of the numberOfMonths option is implemented. + ok( dp.is( ".ui-calendar-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-calendar-group" ) && child.is( "div.ui-calendar-group-first" ), "Structure multi [2,2] - first month division" ); + + child = dp.children( ":eq(1)" ); + ok( child.is( "div.ui-calendar-group" ) && child.is( "div.ui-calendar-group-last" ), "Structure multi [2,2] - second month division" ); + + child = dp.children( ":eq(2)" ); + ok( child.is( "div.ui-calendar-row-break" ), "Structure multi [2,2] - row break" ); + + child = dp.children( ":eq(3)" ); + ok( child.is( "div.ui-calendar-group" ) && child.is( "div.ui-calendar-group-first" ), "Structure multi [2,2] - third month division" ); + + child = dp.children( ":eq(4)" ); + ok( child.is( "div.ui-calendar-group" ) && child.is( "div.ui-calendar-group-last" ), "Structure multi [2,2] - fourth month division" ); + + child = dp.children( ":eq(5)" ); + ok( child.is( "div.ui-calendar-row-break" ), "Structure multi [2,2] - row break" ); + */ + inp.calendar( "close" ).calendar( "destroy" ); + step6(); + }); + } + + function step6() { + // Inline + inl = TestHelpers.calendar.init( "#inline" ); + dp = inl.children(); + + ok( dp.is( ".ui-calendar-inline" ), "Structure inline - main div" ); + ok( !dp.is( ".ui-calendar-rtl" ), "Structure inline - not right-to-left" ); + ok( !dp.is( ".ui-calendar-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-calendar-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-calendar-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.calendar( "destroy" ); + + step7(); + } + + function step7() { + // Inline multi-month + inl = TestHelpers.calendar.init( "#inline", { numberOfMonths: 2 } ); + dp = inl.calendar( "widget" ).find( ".ui-calendar" ); + + ok( dp.is( ".ui-calendar-inline" ) && dp.is( ".ui-calendar-multi" ), "Structure inline multi - main div" ); + equal( dp.children().length, 4, "Structure inline multi - child count" ); + + child = dp.children( ":first" ); + // TODO: Implement ui-calendar-group-first class name + // ok( child.is( "div.ui-calendar-group" ) && child.is( "div.ui-calendar-group-first" ), "Structure inline multi - first month division" ); + + child = dp.children( ":eq(1)" ); + // TODO: Implement ui-calendar-group-last class name + // ok( child.is( "div.ui-calendar-group" ) && child.is( "div.ui-calendar-group-last" ), "Structure inline multi - second month division" ); + + child = dp.children( ":eq(2)" ); + ok( child.is( "div.ui-calendar-row-break" ), "Structure inline multi - row break" ); + + inl.calendar( "destroy" ); + start(); + } + + step1(); +}); + +// Skip these tests for now as none are implemented yet. +/* +asyncTest( "customStructure", function() { + expect( 0 ); + + var header, panel, title, + inp = TestHelpers.calendar.initNewInput(), + dp = inp.calendar( "widget" ).find( ".ui-calendar" ); + + start(); + + function step1() { + Globalize.culture( "he" ); + inp.focus(); + + setTimeout(function() { + ok( dp.is( ".ui-calendar-rtl" ), "Structure RTL - right-to-left" ); + + header = dp.children( ":first" ); + ok( header.is( "div.ui-calendar-header" ), "Structure RTL - header division" ); + equal( header.children().length, 3, "Structure RTL - header child count" ); + ok( header.children( ":first" ).is( "a.ui-calendar-next" ), "Structure RTL - prev link" ); + ok( header.children( ":eq(1)" ).is( "a.ui-calendar-prev" ), "Structure RTL - next link" ); + + panel = dp.children( ":last" ); + ok( panel.is( "div.ui-calendar-buttonpane" ), "Structure RTL - button division" ); + equal( panel.children().length, 2, "Structure RTL - button panel child count" ); + ok( panel.children( ":first" ).is( "button.ui-calendar-close" ), "Structure RTL - close button" ); + ok( panel.children( ":last" ).is( "button.ui-calendar-current" ), "Structure RTL - today button" ); + + inp.calendar( "close" ).calendar( "destroy" ); + Globalize.culture( "en-US" ); + step2(); + }); + } + + // Hide prev/next + // TODO: If we decide the hideIfNoPrevNext option is being removed these tests can be as well. + function stepX() { + inp = TestHelpers.calendar.initNewInput({ + hideIfNoPrevNext: true, + minDate: new Date( 2008, 2 - 1, 4 ), + maxDate: new Date( 2008, 2 - 1, 14 ) + }); + inp.val( "02/10/2008" ); + + TestHelpers.calendar.onFocus( inp, function() { + header = dp.children( ":first" ); + ok( header.is( "div.ui-calendar-header" ), "Structure hide prev/next - header division" ); + equal( header.children().length, 1, "Structure hide prev/next - links child count" ); + ok( header.children( ":first" ).is( "div.ui-calendar-title" ), "Structure hide prev/next - title division" ); + + inp.calendar( "hide" ).calendar( "destroy" ); + step3(); + }); + } + + // Changeable Month with read-only year + function step2() { + inp = TestHelpers.calendar.initNewInput({ changeMonth: true } ); + dp = inp.calendar( "widget" ).find( ".ui-calendar" ); + + inp.focus(); + setTimeout(function() { + title = dp.children( ":first" ).children( ":last" ); + + // TODO: Implement changeMonth option + // equal( title.children().length, 2, "Structure changeable month - title child count" ); + // ok( title.children( ":first" ).is( "select.ui-calendar-month" ), "Structure changeable month - month selector" ); + // ok( title.children( ":last" ).is( "span.ui-calendar-year" ), "Structure changeable month - read-only year" ); + + inp.calendar( "close" ).calendar( "destroy" ); + step3(); + }); + } + + // Changeable year with read-only month + function step3() { + inp = TestHelpers.calendar.initNewInput({ changeYear: true } ); + + TestHelpers.calendar.onFocus( inp, function() { + title = dp.children( ":first" ).children( ":last" ); + + // TODO: Implement changeYear option + // equal( title.children().length, 2, "Structure changeable year - title child count" ); + // ok( title.children( ":first" ).is( "span.ui-calendar-month" ), "Structure changeable year - read-only month" ); + // ok( title.children( ":last" ).is( "select.ui-calendar-year" ), "Structure changeable year - year selector" ); + + inp.calendar( "close" ).calendar( "destroy" ); + start(); + }); + } + + // TODO: figure out why this setTimeout is needed in IE, + // it only is necessary when the previous baseStructure tests runs first + // Support: IE + setTimeout( step1 ); +}); +*/ + +test( "Keyboard handling", function() { + expect( 9 ); + var input = $( "#calendar" ).calendar(), + instance = input.calendar( "instance" ), + date = new Date(); + + input.calendar( "open" ) + .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); + TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), date, "Keystroke enter" ); + + // Enter = Select today's date by default + input.val( "1/1/14" ).calendar( "open" ) + .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); + TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), new Date( 2014, 0, 1 ), + "Keystroke enter - preset" ); + + // Control + Home = Change the calendar to the current month + input.val( "1/1/14" ).calendar( "open" ) + .simulate( "keydown", { ctrlKey: true, keyCode: $.ui.keyCode.HOME } ) + .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); + TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), date, "Keystroke ctrl+home" ); + + // Control + End = Close the calendar and clear the input + input.val( "1/1/14" ).calendar( "open" ) + .simulate( "keydown", { ctrlKey: true, keyCode: $.ui.keyCode.END } ); + equal( input.val(), "", "Keystroke ctrl+end" ); + + input.val( "" ).calendar( "open" ); + ok( instance.isOpen, "calendar is open before escape" ); + input.simulate( "keydown", { keyCode: $.ui.keyCode.ESCAPE } ); + ok( !instance.isOpen, "escape closes the calendar" ); + + input.val( "1/1/14" ).calendar( "open" ) + .simulate( "keydown", { keyCode: $.ui.keyCode.ESCAPE } ); + TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), new Date( 2014, 0, 1 ), + "Keystroke esc - preset" ); + + input.val( "1/1/14" ).calendar( "open" ) + .simulate( "keydown", { ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP } ) + .simulate( "keydown", { keyCode: $.ui.keyCode.ESCAPE } ); + TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), new Date( 2014, 0, 1 ), + "Keystroke esc - abandoned" ); + + input.val( "1/2/14" ) + .simulate( "keyup" ); + TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), new Date( 2014, 0, 2 ), + "Picker updated as user types into input" ); + + input.calendar( "destroy" ); +}); + +asyncTest( "keyboard handling", function() { + expect( 14 ); + var picker, + input = $( "#calendar" ), + date = new Date(); + + function step1() { + input.calendar(); + picker = input.calendar( "widget" ); + ok( !picker.is( ":visible" ), "calendar closed" ); + input.val( "" ) + .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + + setTimeout(function() { + ok( picker.is( ":visible" ), "Keystroke down opens calendar" ); + input.calendar( "destroy" ); + step2(); + }); + } + + function step2() { + input.calendar(); + picker = input.calendar( "widget" ); + ok( !picker.is( ":visible" ), "calendar closed" ); + input.val( "" ) + .simulate( "keydown", { keyCode: $.ui.keyCode.UP } ); + + setTimeout(function() { + ok( picker.is( ":visible" ), "Keystroke up opens calendar" ); + input.calendar( "destroy" ); + step3(); + }); + } + + function step3() { + input.calendar() + .val( "1/1/14" ) + .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + + setTimeout(function() { + $( ":focus" ) + .simulate( "keydown", { keyCode: $.ui.keyCode.LEFT } ) + .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); + date = new Date( 2013, 12 - 1, 31 ); + TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), date, + "Keystroke left to switch to previous day" ); + + input.calendar( "destroy" ); + step4(); + }, 100 ); + } + + function step4() { + input.calendar() + .val( "1/1/14" ) + .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + + setTimeout(function() { + $( ":focus" ) + .simulate( "keydown", { keyCode: $.ui.keyCode.RIGHT } ) + .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); + date = new Date( 2014, 1 - 1, 2 ); + TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), date, + "Keystroke right to switch to next day" ); + + input.calendar( "destroy" ); + step5(); + }, 100 ); + } + + function step5() { + input.calendar() + .val( "1/1/14" ) + .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + + setTimeout(function() { + $( ":focus" ) + .simulate( "keydown", { keyCode: $.ui.keyCode.UP } ) + .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); + date = new Date( 2013, 12 - 1, 25 ); + TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), date, + "Keystroke up to move to the previous week" ); + + input.calendar( "destroy" ); + step6(); + }, 100 ); + } + + function step6() { + input.calendar() + .val( "1/1/14" ) + .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.calendar.equalsDate( input.calendar( "valueAsDate" ), date, + "Keystroke down to move to the next week" ); + + input.calendar( "destroy" ); + step7(); + }, 100 ); + } + + function step7() { + input.calendar() + .val( "1/1/14" ) + .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( 2013, 12 - 1, 1 ); + TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), date, + "Keystroke Page Up moves date to previous month" ); + + input.calendar( "destroy" ); + step8(); + }, 100 ); + } + + function step8() { + input.calendar() + .val( "1/1/14" ) + .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.calendar.equalsDate( input.calendar( "valueAsDate" ), date, + "Keystroke Page Up + Ctrl moves date to previous year" ); + + input.calendar( "destroy" ); + step9(); + }, 100 ); + } + + function step9() { + input.calendar() + .val( "1/1/14" ) + .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.calendar.equalsDate( input.calendar( "valueAsDate" ), date, + "Keystroke Page Down moves date to next month" ); + + input.calendar( "destroy" ); + step10(); + }, 100 ); + } + + function step10() { + input.calendar() + .val( "1/1/14" ) + .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.calendar.equalsDate( input.calendar( "valueAsDate" ), date, + "Keystroke Page Down + Ctrl moves date to next year" ); + + input.calendar( "destroy" ); + step11(); + }, 100 ); + } + + // Check for moving to short months + function step11() { + input.calendar() + .val( "3/31/14" ) + .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.calendar.equalsDate( input.calendar( "valueAsDate" ), date, + "Keystroke Page Up and short months" ); + + input.calendar( "destroy" ); + step12(); + }, 100 ); + } + + function step12() { + input.calendar() + .val( "1/30/16" ) + .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.calendar.equalsDate( input.calendar( "valueAsDate" ), date, + "Keystroke Page Down and leap years" ); + + input.calendar( "destroy" ); + start(); + }, 100 ); + } + + 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.calendar.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.calendar.equalsDate( input.calendar( "valueAsDate" ), new Date( 2008, 4 - 1, 4 ), + "Keystroke pgdn step 2" ); +*/ + +test( "mouse", function() { + expect( 13 ); + var input = $( "#calendar" ).calendar(), + picker = input.calendar( "widget" ), + inline = $( "#inline" ).calendar, + date = new Date(); + + input.val( "" ).calendar( "open" ); + $( ".ui-calendar-calendar tbody a:contains(10)", picker ).simulate( "mousedown", {} ); + date.setDate( 10 ); + TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), date, "Mouse click" ); + + input.val( "2/4/08" ).calendar( "open" ); + $( ".ui-calendar-calendar tbody a:contains(12)", picker ).simulate( "mousedown", {} ); + TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), new Date( 2008, 2 - 1, 12 ), + "Mouse click - preset" ) ; + + input.val( "" ).calendar( "open" ); + $( "button.ui-calendar-close", picker ).simulate( "click", {} ); + ok( input.calendar( "valueAsDate" ) == null, "Mouse click - close" ); + + input.val( "2/4/08" ).calendar( "open" ); + $( "button.ui-calendar-close", picker ).simulate( "click", {} ); + TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), new Date( 2008, 2 - 1, 4 ), + "Mouse click - close + preset" ); + + input.val( "2/4/08" ).calendar( "open" ); + $( "a.ui-calendar-prev", picker ).simulate( "click", {} ); + $( "button.ui-calendar-close", picker ).simulate( "click", {} ); + TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), new Date( 2008, 2 - 1, 4 ), + "Mouse click - abandoned" ); + + // Current/previous/next + input.val( "" ).calendar( "open" ); + $( ".ui-calendar-current", picker ).simulate( "click", {} ); + date.setDate( new Date().getDate() ); + TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), date, "Mouse click - current" ); + + input.val( "2/4/08" ).calendar( "open" ); + $( ".ui-calendar-prev", picker ).simulate( "click" ); + $( ".ui-calendar-calendar tbody a:contains(16)", picker ).simulate( "mousedown" ); + TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), new Date( 2008, 1 - 1, 16 ), + "Mouse click - previous" ); + + input.val( "2/4/08" ).calendar( "open" ); + $( ".ui-calendar-next", picker ).simulate( "click" ); + $( ".ui-calendar-calendar tbody a:contains(18)", picker ).simulate( "mousedown" ); + TestHelpers.calendar.equalsDate( input.calendar( "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.calendar( "option", { + minDate: new Date( 2008, 2 - 1, 2 ), + maxDate: new Date( 2008, 2 - 1, 26 ) + }).val( "2/4/08" ).calendar( "open" ); + $( ".ui-calendar-prev", picker ).simulate( "click" ); + $( ".ui-calendar-calendar tbody a:contains(16)", picker ).simulate( "mousedown" ); + TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), new Date( 2008, 2 - 1, 16 ), + "Mouse click - previous + min/max" ); + + input.val( "2/4/08" ).calendar( "open" ); + $( ".ui-calendar-next", picker ).simulate( "click" ); + $( ".ui-calendar-calendar tbody a:contains(18)", picker ).simulate( "mousedown" ); + TestHelpers.calendar.equalsDate(input.calendar( "valueAsDate" ), new Date( 2008, 2 - 1, 18 ), + "Mouse click - next + min/max" ); + */ + + // Inline + inline = TestHelpers.calendar.init( "#inline" ); + picker = $( ".ui-calendar-inline", inline ); + date = new Date(); + inline.calendar( "valueAsDate", date ); + $( ".ui-calendar-calendar tbody a:contains(10)", picker ).simulate( "mousedown", {} ); + date.setDate( 10 ); + TestHelpers.calendar.equalsDate( inline.calendar( "valueAsDate" ), date, "Mouse click inline" ); + + inline.calendar( "option", { showButtonPanel: true } ) + .calendar( "valueAsDate", new Date( 2008, 2 - 1, 4 )); + $( ".ui-calendar-calendar tbody a:contains(12)", picker ).simulate( "mousedown", {} ); + TestHelpers.calendar.equalsDate( inline.calendar( "valueAsDate" ), new Date( 2008, 2 - 1, 12 ), + "Mouse click inline - preset" ); + + inline.calendar( "option", { showButtonPanel: true } ); + $( ".ui-calendar-current", picker ).simulate( "click", {} ); + $( ".ui-calendar-calendar tbody a:contains(14)", picker ).simulate( "mousedown", {} ); + date.setDate( 14 ); + TestHelpers.calendar.equalsDate( inline.calendar( "valueAsDate" ), date, "Mouse click inline - current" ); + + inline.calendar( "valueAsDate", new Date( 2008, 2 - 1, 4) ); + $( ".ui-calendar-prev", picker ).simulate( "click" ); + $( ".ui-calendar-calendar tbody a:contains(16)", picker ).simulate( "mousedown" ); + TestHelpers.calendar.equalsDate( inline.calendar( "valueAsDate" ), new Date( 2008, 1 - 1, 16 ), + "Mouse click inline - previous" ); + + inline.calendar( "valueAsDate", new Date( 2008, 2 - 1, 4) ); + $( ".ui-calendar-next", picker ).simulate( "click" ); + $( ".ui-calendar-calendar tbody a:contains(18)", picker ).simulate( "mousedown" ); + TestHelpers.calendar.equalsDate( inline.calendar( "valueAsDate" ), new Date( 2008, 3 - 1, 18 ), + "Mouse click inline - next" ); + + input.calendar( "destroy" ); + inline.calendar( "destroy" ); +}); + +})( 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..89547463cf8 --- /dev/null +++ b/tests/unit/calendar/calendar_methods.js @@ -0,0 +1,130 @@ +(function( $ ) { + +module( "calendar: methods" ); + +test( "destroy", function() { + expect( 10 ); + var input = $( "#calendar" ).calendar(), + inline = $( "#inline" ).calendar(); + + ok( input.calendar( "instance" ), "instance created" ); + ok( input.attr( "aria-owns" ), "aria-owns attribute added" ); + ok( input.attr( "aria-haspopup" ), "aria-haspopup attribute added" ); + input.calendar( "destroy" ); + ok( !input.calendar( "instance" ), "instance removed" ); + ok( !input.attr( "aria-owns" ), "aria-owns attribute removed" ); + ok( !input.attr( "aria-haspopup" ), "aria-haspopup attribute removed" ); + + ok( inline.calendar( "instance" ), "instance created" ); + ok( inline.children().length > 0, "inline calendar has children" ); + inline.calendar( "destroy" ); + ok( !inline.calendar( "instance" ), "instance removed" ); + ok( inline.children().length === 0, "inline picker no longer has children" ); +}); + +test( "enable / disable", function() { + expect( 6 ); + var inl, + inp = TestHelpers.calendar.init( "#calendar" ), + dp = inp.calendar( "widget" ); + + ok( !inp.calendar( "option", "disabled" ), "initially enabled" ); + ok( !dp.hasClass( "ui-calendar-disabled" ), "does not have disabled class name" ); + + inp.calendar( "disable" ); + ok( inp.calendar( "option", "disabled" ), "disabled option is set" ); + ok( dp.hasClass( "ui-calendar-disabled" ), "calendar has disabled class name" ); + + inp.calendar( "enable" ); + ok( !inp.calendar( "option", "disabled" ), "enabled after enable() call" ); + ok( !dp.hasClass( "ui-calendar-disabled" ), "no longer has disabled class name" ); + + // Inline + inl = TestHelpers.calendar.init( "#inline" ); + dp = inl.calendar( "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 = $( "#calendar" ).calendar().calendar( "widget" ); + deepEqual( $( "body > .ui-front" )[ 0 ], actual[ 0 ] ); + actual.remove(); +}); + +test( "close", function() { + expect( 0 ); +}); + +test( "open", function() { + expect( 0 ); +}); + +test( "value", function() { + expect( 6 ); + var input = $( "#calendar" ).calendar(), + picker = input.calendar( "widget" ), + inline = $( "#inline" ).calendar(); + + input.calendar( "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" ); + equal( input.calendar( "value" ), "1/1/14", "getter" ); + + input.val( "abc" ); + equal( input.calendar( "value" ), "abc", + "Invalid values should be returned without formatting." ); + + inline.calendar( "value", "1/1/14" ); + ok( inline.find( "a[data-timestamp]:first" ).hasClass( "ui-state-focus" ), + "first day marked as selected" ); + equal( inline.calendar( "value" ), "1/1/14", "getter" ); + + input.calendar( "destroy" ); + inline.calendar( "destroy" ); +}); + +test( "valueAsDate", function() { + expect( 6 ); + var input = $( "#calendar" ).calendar(), + picker = input.calendar( "widget" ), + inline = $( "#inline" ).calendar(); + + input.calendar( "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.calendar.equalsDate( input.calendar( "valueAsDate" ), + new Date( 2014, 0, 1 ), "getter" ); + + input.val( "a/b/c" ); + equal( input.calendar( "valueAsDate" ), null, "Invalid dates return null" ); + + inline.calendar( "valueAsDate", new Date( 2014, 0, 1 ) ); + ok( inline.find( "a[data-timestamp]:first" ).hasClass( "ui-state-focus" ), + "first day marked as selected" ); + TestHelpers.calendar.equalsDate( inline.calendar( "valueAsDate" ), + new Date( 2014, 0, 1 ), "getter" ); + + input.calendar( "destroy" ); + inline.calendar( "destroy" ); +}); + +test( "isValid", function() { + expect( 2 ); + var input = $( "#calendar" ).calendar(); + + input.val( "1/1/14" ); + ok( input.calendar( "isValid" ) ); + + input.val( "1/1/abc" ); + ok( !input.calendar( "isValid" ) ); + + input.calendar( "destroy" ); +}); + +})( 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..fa53c408fb6 --- /dev/null +++ b/tests/unit/calendar/calendar_test_helpers.js @@ -0,0 +1,28 @@ +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 ); + }, + init: function( id, options ) { + options = $.extend( { show: false }, options || {} ); + return $( id ).calendar( options ); + }, + initNewInput: function( options ) { + options = $.extend( { show: false }, options || {} ); + return $( "" ).calendar( options ) + .appendTo( "#qunit-fixture" ); + }, + onFocus: TestHelpers.onFocus, + PROP_NAME: "calendar" +}; \ 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..38dc8897170 --- /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; + display: none; +} +.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: 100%; +} +.ui-calendar-multi .ui-calendar-group { + float: left; +} +.ui-calendar-multi .ui-calendar-group table { + width: 95%; + margin: 0 auto .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/ui/calendar.js b/ui/calendar.js new file mode 100644 index 00000000000..14093b50b21 --- /dev/null +++ b/ui/calendar.js @@ -0,0 +1,766 @@ +/*! + * 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. + define([ + "jquery", + "./core", + "./widget", + "./button" + ], factory ); + } else { + + // Browser globals + factory( jQuery ); + } +}(function( $ ) { + +// TODO use uniqueId, if possible +var idIncrement = 0, + // TODO move this to the instance + suppressExpandOnFocus = false; + +return $.widget( "ui.calendar", { + 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, + value: null, + + // callbacks + beforeOpen: null, + close: null, + open: null, + select: null + }, + + _create: function() { + this.id = "ui-calendar-" + idIncrement; + idIncrement++; + + if ( this.element.is( "input" ) ) { + if ( !this.options.value && this.isValid() ) { + this.options.value = this._getParsedValue(); + } + this._createPicker(); + } else { + this.inline = true; + this.picker = this.element; + } + + this.date = $.date( this.options.value, this.options.dateFormat ).select(); + this.date.eachDay = this.options.eachDay; + + this._on( this.picker, { + "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(); + }, + "click .ui-calendar-current": function( event ) { + event.preventDefault(); + this._select( event, new Date().getTime() ); + }, + "click .ui-calendar-close": function( event ) { + event.preventDefault(); + this.close( event ); + }, + "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" ) ); + if ( this.inline ) { + this.grid.focus( 1 ); + } + }, + "keydown .ui-calendar-calendar": "_handleKeydown" + }); + + // TODO use hoverable (no delegation support)? convert to _on? + this.picker.delegate( ".ui-calendar-header a, .ui-calendar-calendar a", "mouseenter.calendar mouseleave.calendar", function() { + $( this ).toggleClass( "ui-state-hover" ); + }); + + this._createTmpl(); + }, + + _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 newId, newCell, + 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 ); + } + else { + newId = this.id + "-" + this.date.day(); + newCell = $( "#" + newId ); + + // TODO unnecessary optimization? is it really needed? + if ( !newCell.length ) { + return; + } + this.grid.attr("aria-activedescendant", newId); + + this.grid.find( ".ui-state-focus" ).removeClass( "ui-state-focus" ); + newCell.children( "a" ).addClass( "ui-state-focus" ); + } + }, + + _createPicker: function() { + this.picker = $( "
      " ) + .addClass( "ui-front" ) + // TODO add a ui-calendar-popup class, move position:absolute 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(); + 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; + // TODO this is not in specs, keep? + 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._getParsedValue() ).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 ) { + this._delay( function() { + if ( !this.isOpen ) { + this.open( event ); + } + }, 1); + } + this._delay( function() { + suppressExpandOnFocus = false; + }, 100 ); + }, + blur: function() { + 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(); + } + } + }); + + this._on( this.document, { + click: function( event ) { + if ( this.isOpen && !$( event.target ).closest( this.element.add( this.picker ) ).length ) { + this.close( event ); + } + } + }); + }, + + _appendTo: function() { + var element = this.options.appendTo; + + if ( element ) { + element = element.jquery || element.nodeType ? + $( element ) : + this.document.find( element ).eq( 0 ); + } + + if ( !element ) { + element = this.element.closest( ".ui-front" ); + } + + if ( !element.length ) { + element = this.document[ 0 ].body; + } + + return element; + }, + + _createTmpl: function() { + this._createDatepicker(); + this.picker.find( "button" ).button(); + + if ( this.inline ) { + this.picker.children().addClass( "ui-calendar-inline" ); + } + // against display:none in calendar.css + this.picker.find( ".ui-calendar" ).css( "display", "block" ); + this.grid = this.picker.find( ".ui-calendar-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-calendar-multi" ); + multiClasses.push( "ui-calendar-multi-" + this.options.numberOfMonths ); + } + + $( "
      " ) + .addClass( "ui-calendar 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( "calendar" ); + + return ""; + }, + + _buildNextLink: function() { + var labels = Globalize.translate( "calendar" ); + + return ""; + }, + + _buildTitlebar: function() { + var labels = Globalize.translate( "calendar" ); + + 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( "calendar" ); + + 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( "calendar" ); + + 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( "calendar" ); + + return "
      " + + "" + + "" + + "
      "; + }, + + _focusTrigger: function() { + suppressExpandOnFocus = true; + this.element.focus(); + }, + + // 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() { + // 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.picker ).html( this._buildTitle() ); + $( ".ui-calendar-calendar", this.picker ).replaceWith( this.grid ); + } else { + this._refreshMultiplePicker(); + } + }, + + _refreshMultiplePicker: function() { + var i = 0; + + for ( ; i < this.options.numberOfMonths; i++ ) { + $( ".ui-calendar-title", this.picker ).eq( i ).html( this._buildTitle() ); + $( ".ui-calendar-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" ); + }, + + open: function( event ) { + if ( this.inline || this.isOpen ) { + return; + } + if ( this._trigger( "beforeOpen", event ) === false ) { + return; + } + + this.refresh(); + + this.picker + .attr( "aria-hidden", "false" ) + .attr( "aria-expanded", "true" ) + .show() + .position( this._buildPosition() ) + .hide(); + + this._show( this.picker, 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 + this.element.attr( "tabindex", -1 ); + this.isOpen = true; + + this._trigger( "open", event ); + }, + + close: function( event ) { + if ( this.inline ) { + return; + } + + this._setHiddenPicker(); + this._hide( this.picker, this.options.hide ); + + this.element.attr( "tabindex" , 0 ); + + this.isOpen = false; + this._trigger( "close", event ); + }, + + _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._setOption( "value", new Date( time ) ); + if ( !this.inline ) { + this.close(); + this._focusTrigger(); + } + this._trigger( "select", event, { + // TODO replace with value option to initialise and read + date: this.value() + }); + }, + + value: function( value ) { + if ( arguments.length ) { + this._setOption( "value", Globalize.parseDate( value, this.options.dateFormat ) ); + } else { + if ( this.inline ) { + return Globalize.format( this.date.selected(), this.options.dateFormat ); + } else { + return this.element.val(); + } + } + }, + + valueAsDate: function( value ) { + if ( arguments.length ) { + this._setOption( "value", value ); + } else { + return this.option( "value" ); + } + }, + + isValid: function() { + if ( this.inline ) { + return true; + } + + return this._getParsedValue() !== null; + }, + + _destroy: function() { + if ( this.inline ) { + this.picker.empty(); + } else { + this.picker.remove(); + this.element + .removeAttr( "aria-haspopup" ) + .removeAttr( "aria-owns" ); + } + }, + + widget: function() { + return this.picker; + }, + + _getParsedValue: function() { + return Globalize.parseDate( this.element.val(), this.options.dateFormat ); + }, + + option: function( key ) { + if ( arguments.length === 0 || ( arguments.length === 1 && key === "value" ) ) { + this.options.value = this.inline ? this.date.selected() : this._getParsedValue(); + } + return this._superApply( arguments ); + }, + + _setOption: function( key, value ) { + if ( key === "value" ) { + if ( value instanceof Date ) { + this.date.setTime( value.getTime() ).select(); + this.refresh(); + if ( !this.inline ) { + this.element.val( this.date.format() ); + } + } + } + + this._super( key, value ); + + if ( key === "appendTo" ) { + this.picker.appendTo( this._appendTo() ); + } + + if ( key === "eachDay" ) { + this.date.eachDay = this.options.eachDay; + this.refresh(); + } + + if ( key === "dateFormat" ) { + this.date.setFormat( this.options.dateFormat ); + if ( !this.inline ) { + this.element.val( this.date.format() ); + } + } + + if ( key === "showWeek" ) { + this.refresh(); + } + + if ( key === "position" ) { + this.picker.position( this._buildPosition() ); + } + } +}); + +})); From 3d52c371e6dd4b4ca771cfccf5ee9400fa1a0edf Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Thu, 5 Jun 2014 01:19:34 +0200 Subject: [PATCH 03/94] Calendar: Add missing AMD dependency todo comment --- ui/calendar.js | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/calendar.js b/ui/calendar.js index 14093b50b21..5d29c930816 100644 --- a/ui/calendar.js +++ b/ui/calendar.js @@ -12,6 +12,7 @@ if ( typeof define === "function" && define.amd ) { // AMD. Register as an anonymous module. + // ToDo Add globalize and $.date? define([ "jquery", "./core", From 4a6d8203d5940299bcd44567b3ee6658cf66832d Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Wed, 4 Jun 2014 00:08:03 +0200 Subject: [PATCH 04/94] Calendar: remove datepicker functionality, options and methods --- demos/calendar/default.html | 2 +- ui/calendar.js | 328 +++--------------------------------- 2 files changed, 29 insertions(+), 301 deletions(-) diff --git a/demos/calendar/default.html b/demos/calendar/default.html index 26c4c2eb3d5..b35e9e769bd 100644 --- a/demos/calendar/default.html +++ b/demos/calendar/default.html @@ -22,7 +22,7 @@ -

      Date:

      +

      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/ui/calendar.js b/ui/calendar.js index 5d29c930816..dac8964d6c6 100644 --- a/ui/calendar.js +++ b/ui/calendar.js @@ -27,30 +27,18 @@ }(function( $ ) { // TODO use uniqueId, if possible -var idIncrement = 0, - // TODO move this to the instance - suppressExpandOnFocus = false; +var idIncrement = 0; return $.widget( "ui.calendar", { 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, value: null, // callbacks - beforeOpen: null, - close: null, - open: null, select: null }, @@ -58,20 +46,10 @@ return $.widget( "ui.calendar", { this.id = "ui-calendar-" + idIncrement; idIncrement++; - if ( this.element.is( "input" ) ) { - if ( !this.options.value && this.isValid() ) { - this.options.value = this._getParsedValue(); - } - this._createPicker(); - } else { - this.inline = true; - this.picker = this.element; - } - this.date = $.date( this.options.value, this.options.dateFormat ).select(); this.date.eachDay = this.options.eachDay; - this._on( this.picker, { + this._on( this.element, { "click .ui-calendar-prev": function( event ) { event.preventDefault(); this.date.adjust( "M", -this.options.numberOfMonths ); @@ -86,24 +64,18 @@ return $.widget( "ui.calendar", { event.preventDefault(); this._select( event, new Date().getTime() ); }, - "click .ui-calendar-close": function( event ) { - event.preventDefault(); - this.close( event ); - }, "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" ) ); - if ( this.inline ) { - this.grid.focus( 1 ); - } + this.grid.focus( 1 ); }, "keydown .ui-calendar-calendar": "_handleKeydown" }); // TODO use hoverable (no delegation support)? convert to _on? - this.picker.delegate( ".ui-calendar-header a, .ui-calendar-calendar a", "mouseenter.calendar mouseleave.calendar", function() { + this.element.delegate( ".ui-calendar-header a, .ui-calendar-calendar a", "mouseenter.calendar mouseleave.calendar", function() { $( this ).toggleClass( "ui-state-hover" ); }); @@ -174,162 +146,13 @@ return $.widget( "ui.calendar", { } }, - _createPicker: function() { - this.picker = $( "
      " ) - .addClass( "ui-front" ) - // TODO add a ui-calendar-popup class, move position:absolute 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(); - 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; - // TODO this is not in specs, keep? - 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._getParsedValue() ).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 ) { - this._delay( function() { - if ( !this.isOpen ) { - this.open( event ); - } - }, 1); - } - this._delay( function() { - suppressExpandOnFocus = false; - }, 100 ); - }, - blur: function() { - 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(); - } - } - }); - - this._on( this.document, { - click: function( event ) { - if ( this.isOpen && !$( event.target ).closest( this.element.add( this.picker ) ).length ) { - this.close( event ); - } - } - }); - }, - - _appendTo: function() { - var element = this.options.appendTo; - - if ( element ) { - element = element.jquery || element.nodeType ? - $( element ) : - this.document.find( element ).eq( 0 ); - } - - if ( !element ) { - element = this.element.closest( ".ui-front" ); - } - - if ( !element.length ) { - element = this.document[ 0 ].body; - } - - return element; - }, - _createTmpl: function() { this._createDatepicker(); - this.picker.find( "button" ).button(); + this.element.find( "button" ).button(); - if ( this.inline ) { - this.picker.children().addClass( "ui-calendar-inline" ); - } // against display:none in calendar.css - this.picker.find( ".ui-calendar" ).css( "display", "block" ); - this.grid = this.picker.find( ".ui-calendar-calendar" ); + this.element.find( ".ui-calendar" ).css( "display", "block" ); + this.grid = this.element.find( ".ui-calendar-calendar" ); }, _createDatepicker: function() { @@ -352,7 +175,7 @@ return $.widget( "ui.calendar", { "aria-labelledby": this.id + "-title" }) .html( pickerHtml ) - .appendTo( this.picker ); + .appendTo( this.element ); }, _buildMultiplePicker: function() { @@ -400,10 +223,9 @@ return $.widget( "ui.calendar", { }, _buildPreviousLink: function() { - var labels = Globalize.translate( "calendar" ); + var labels = Globalize.translate( "datepicker" ); - return "" + - "" + "
      "; }, - _focusTrigger: function() { - suppressExpandOnFocus = true; - this.element.focus(); - }, - // 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 @@ -586,8 +401,8 @@ return $.widget( "ui.calendar", { // TODO: Prevent disabled cells from being focused if ( this.options.numberOfMonths === 1 ) { this.grid = $( this._buildGrid() ); - $( ".ui-calendar-title", this.picker ).html( this._buildTitle() ); - $( ".ui-calendar-calendar", this.picker ).replaceWith( this.grid ); + $( ".ui-calendar-title", this.element ).html( this._buildTitle() ); + $( ".ui-calendar-calendar", this.element ).replaceWith( this.grid ); } else { this._refreshMultiplePicker(); } @@ -597,74 +412,25 @@ return $.widget( "ui.calendar", { var i = 0; for ( ; i < this.options.numberOfMonths; i++ ) { - $( ".ui-calendar-title", this.picker ).eq( i ).html( this._buildTitle() ); - $( ".ui-calendar-calendar", this.picker ).eq( i ).html( this._buildGrid() ); + $( ".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.picker ).find( ".ui-state-focus" ).not( ":first" ).removeClass( "ui-state-focus" ); - }, - - open: function( event ) { - if ( this.inline || this.isOpen ) { - return; - } - if ( this._trigger( "beforeOpen", event ) === false ) { - return; - } - - this.refresh(); - - this.picker - .attr( "aria-hidden", "false" ) - .attr( "aria-expanded", "true" ) - .show() - .position( this._buildPosition() ) - .hide(); - - this._show( this.picker, 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 - this.element.attr( "tabindex", -1 ); - this.isOpen = true; - - this._trigger( "open", event ); - }, - - close: function( event ) { - if ( this.inline ) { - return; - } - - this._setHiddenPicker(); - this._hide( this.picker, this.options.hide ); - - this.element.attr( "tabindex" , 0 ); - - this.isOpen = false; - this._trigger( "close", event ); + $( this.element ).find( ".ui-state-focus" ).not( ":first" ).removeClass( "ui-state-focus" ); }, _setHiddenPicker: function() { - this.picker + this.element .attr( "aria-hidden", "true" ) .attr( "aria-expanded", "false" ); }, - _buildPosition: function() { - return $.extend( {}, { of: this.element }, this.options.position ); - }, - _select: function( event, time ) { this._setOption( "value", new Date( time ) ); - if ( !this.inline ) { - this.close(); - this._focusTrigger(); - } this._trigger( "select", event, { // TODO replace with value option to initialise and read date: this.value() @@ -675,11 +441,7 @@ return $.widget( "ui.calendar", { if ( arguments.length ) { this._setOption( "value", Globalize.parseDate( value, this.options.dateFormat ) ); } else { - if ( this.inline ) { - return Globalize.format( this.date.selected(), this.options.dateFormat ); - } else { - return this.element.val(); - } + return Globalize.format( this.option( "value" ), this.options.dateFormat ); } }, @@ -691,36 +453,16 @@ return $.widget( "ui.calendar", { } }, - isValid: function() { - if ( this.inline ) { - return true; - } - - return this._getParsedValue() !== null; - }, - _destroy: function() { - if ( this.inline ) { - this.picker.empty(); - } else { - this.picker.remove(); - this.element - .removeAttr( "aria-haspopup" ) - .removeAttr( "aria-owns" ); - } - }, - - widget: function() { - return this.picker; - }, - - _getParsedValue: function() { - return Globalize.parseDate( this.element.val(), this.options.dateFormat ); + this.element + .empty() + .removeAttr( "aria-haspopup" ) + .removeAttr( "aria-owns" ); }, option: function( key ) { if ( arguments.length === 0 || ( arguments.length === 1 && key === "value" ) ) { - this.options.value = this.inline ? this.date.selected() : this._getParsedValue(); + this.options.value = this.date.selectedDate(); } return this._superApply( arguments ); }, @@ -730,18 +472,11 @@ return $.widget( "ui.calendar", { if ( value instanceof Date ) { this.date.setTime( value.getTime() ).select(); this.refresh(); - if ( !this.inline ) { - this.element.val( this.date.format() ); - } } } this._super( key, value ); - if ( key === "appendTo" ) { - this.picker.appendTo( this._appendTo() ); - } - if ( key === "eachDay" ) { this.date.eachDay = this.options.eachDay; this.refresh(); @@ -749,18 +484,11 @@ return $.widget( "ui.calendar", { if ( key === "dateFormat" ) { this.date.setFormat( this.options.dateFormat ); - if ( !this.inline ) { - this.element.val( this.date.format() ); - } } if ( key === "showWeek" ) { this.refresh(); } - - if ( key === "position" ) { - this.picker.position( this._buildPosition() ); - } } }); From b3831f2be0ed609bf8f309aa13556628ec9f7b1d Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Wed, 4 Jun 2014 00:30:40 +0200 Subject: [PATCH 05/94] Calendar: Fix focus highlighting when month is changed --- ui/calendar.js | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/ui/calendar.js b/ui/calendar.js index dac8964d6c6..d41b65bd92e 100644 --- a/ui/calendar.js +++ b/ui/calendar.js @@ -89,8 +89,7 @@ return $.widget( "ui.calendar", { } event.preventDefault(); - var newId, newCell, - activeCell = $( "#" + this.grid.attr( "aria-activedescendant" ) ), + var activeCell = $( "#" + this.grid.attr( "aria-activedescendant" ) ), oldMonth = this.date.month(), oldYear = this.date.year(); @@ -131,19 +130,17 @@ return $.widget( "ui.calendar", { this.refresh(); this.grid.focus( 1 ); } - else { - newId = this.id + "-" + this.date.day(); - newCell = $( "#" + newId ); - // TODO unnecessary optimization? is it really needed? - if ( !newCell.length ) { - return; - } - this.grid.attr("aria-activedescendant", newId); + this._setActiveDescendant(); + }, - this.grid.find( ".ui-state-focus" ).removeClass( "ui-state-focus" ); - newCell.children( "a" ).addClass( "ui-state-focus" ); - } + _setActiveDescendant: function() { + var newId = this.id + "-" + this.date.day(), + newCell = $( "#" + newId ); + + this.grid.attr( "aria-activedescendant", newId ); + this.grid.find( ".ui-state-focus" ).removeClass( "ui-state-focus" ); + newCell.children( "a" ).addClass( "ui-state-focus" ); }, _createTmpl: function() { @@ -345,7 +342,7 @@ return $.widget( "ui.calendar", { classes = [ "ui-state-default" ], labels = Globalize.translate( "datepicker" ); - if ( day.date === this.date.day() ) { + if ( day === this.date ) { classes.push( "ui-state-focus" ); } if ( day.current ) { From cb13f3ed249309b603e69df1c1fca686b3abcabb Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Wed, 4 Jun 2014 00:59:16 +0200 Subject: [PATCH 06/94] Calendar: Make use of uniqueId method --- ui/calendar.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/ui/calendar.js b/ui/calendar.js index d41b65bd92e..2790eaac99b 100644 --- a/ui/calendar.js +++ b/ui/calendar.js @@ -26,9 +26,6 @@ } }(function( $ ) { -// TODO use uniqueId, if possible -var idIncrement = 0; - return $.widget( "ui.calendar", { options: { dateFormat: { date: "short" }, @@ -43,8 +40,7 @@ return $.widget( "ui.calendar", { }, _create: function() { - this.id = "ui-calendar-" + idIncrement; - idIncrement++; + this.id = this.element.uniqueId().attr( "id" ); this.date = $.date( this.options.value, this.options.dateFormat ).select(); this.date.eachDay = this.options.eachDay; @@ -453,8 +449,7 @@ return $.widget( "ui.calendar", { _destroy: function() { this.element .empty() - .removeAttr( "aria-haspopup" ) - .removeAttr( "aria-owns" ); + .removeUniqueId(); }, option: function( key ) { From 8bf93c27c14fd0acb09e5c88d98b48ebf5974f7a Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Wed, 4 Jun 2014 19:07:23 +0200 Subject: [PATCH 07/94] Calendar: Add _isValid method Add a basic _isValid method for both widgets to check for valid dates. --- ui/calendar.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ui/calendar.js b/ui/calendar.js index 2790eaac99b..decef2ba08a 100644 --- a/ui/calendar.js +++ b/ui/calendar.js @@ -425,7 +425,6 @@ return $.widget( "ui.calendar", { _select: function( event, time ) { this._setOption( "value", new Date( time ) ); this._trigger( "select", event, { - // TODO replace with value option to initialise and read date: this.value() }); }, @@ -446,6 +445,11 @@ return $.widget( "ui.calendar", { } }, + _isValid: function( value ) { + // ToDo implement min / max option + return ( value instanceof Date ); + }, + _destroy: function() { this.element .empty() @@ -461,7 +465,7 @@ return $.widget( "ui.calendar", { _setOption: function( key, value ) { if ( key === "value" ) { - if ( value instanceof Date ) { + if ( this._isValid( value ) ) { this.date.setTime( value.getTime() ).select(); this.refresh(); } From ac0fc77ee4b9bfaa79fd6b9a304e3ff4c63260fe Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Wed, 4 Jun 2014 19:09:16 +0200 Subject: [PATCH 08/94] Datepicker: $.date.selected() should return the actual date object The method should return the actual date object instead of the copied $.date object --- external/date.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/date.js b/external/date.js index 71963981129..1bc5b836038 100644 --- a/external/date.js +++ b/external/date.js @@ -184,7 +184,7 @@ $.date.prototype = { return this; }, selectedDate: function() { - return this.selected; + return this.selected.date(); }, clone: function() { var date = this.dateObject; From afd7e79caa83afd5a461d4af03cce1e3a19719a2 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Wed, 4 Jun 2014 19:13:32 +0200 Subject: [PATCH 09/94] Datepicker: Remove calendar functionality, options and methods --- demos/datepicker/default.html | 1 + themes/base/datepicker.css | 172 +---------- ui/datepicker.js | 552 ++++------------------------------ 3 files changed, 68 insertions(+), 657 deletions(-) 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 @@ + -

      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/ui/calendar.js b/ui/calendar.js index decef2ba08a..5e02b43e61c 100644 --- a/ui/calendar.js +++ b/ui/calendar.js @@ -31,6 +31,8 @@ return $.widget( "ui.calendar", { dateFormat: { date: "short" }, // TODO review eachDay: $.noop, + max: null, + min: null, numberOfMonths: 1, showWeek: false, value: null, @@ -315,30 +317,33 @@ return $.widget( "ui.calendar", { }, _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"; + var content = "", + attributes = [ + "role='gridcell'", + "aria-selected='" + day.current ? true : false + "'" + ], + selectable = ( day.selectable && this._isValid( new Date( day.timestamp ) ) ); if ( day.render ) { - if ( day.selectable ) { - contents = this._buildDayLink( day ); - } else { - contents = this._buildDayDisplay( day ); + 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 "" + - contents + - ""; + return "" + content + ""; }, - _buildDayLink: function( day ) { - var link, - classes = [ "ui-state-default" ], - labels = Globalize.translate( "datepicker" ); + _buildDayElement: function( day, selectable ) { + var classes = [ "ui-state-default" ], + labels = Globalize.translate( "datepicker" ), + content = ""; - if ( day === this.date ) { + if ( day === this.date && selectable ) { classes.push( "ui-state-focus" ); } if ( day.current ) { @@ -347,33 +352,23 @@ return $.widget( "ui.calendar", { if ( day.today ) { classes.push( "ui-state-highlight" ); } + // ToDo Explain and document this if ( day.extraClasses ) { classes.push( day.extraClasses.split( " " ) ); } - link = "" + - day.date + ""; - if ( day.today ) { - link += ", " + labels.currentText + ""; + classes = " class='" + classes.join( " " ) + "'"; + if ( selectable ) { + content = "" + day.date + ""; + } else { + content = "" + day.date + ""; } - 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( " " ) ); + content += ", " + labels.currentText + ""; } - return "" + day.date + ""; + return content; }, _buildButtons: function() { @@ -446,8 +441,23 @@ return $.widget( "ui.calendar", { }, _isValid: function( value ) { - // ToDo implement min / max option - return ( value instanceof Date ); + 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 < $.date( this.options.min ).adjust( "D", -1 ).date() ) { + return false; + } + } + + return true; }, _destroy: function() { @@ -471,6 +481,12 @@ return $.widget( "ui.calendar", { } } + if ( key === "max" || key === "min" ) { + if ( !( value instanceof Date ) ) { + return; + } + } + this._super( key, value ); if ( key === "eachDay" ) { From 5c715d1c8dffd61ecb60c81e45dc50e9cff1db76 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Wed, 4 Jun 2014 23:24:54 +0200 Subject: [PATCH 11/94] Datepicker: Add min and max option --- demos/datepicker/min-max.html | 13 +++++++++++-- ui/datepicker.js | 6 +++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/demos/datepicker/min-max.html b/demos/datepicker/min-max.html index 6dcc16a48bc..196710c1ab9 100644 --- a/demos/datepicker/min-max.html +++ b/demos/datepicker/min-max.html @@ -11,12 +11,21 @@ + @@ -25,7 +34,7 @@

      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/ui/datepicker.js b/ui/datepicker.js index 072bfe803f8..b6f056622c5 100644 --- a/ui/datepicker.js +++ b/ui/datepicker.js @@ -34,6 +34,8 @@ $.widget( "ui.datepicker", { appendTo: null, dateFormat: { date: "short" }, eachDay: $.noop, + max: null, + min: null, numberOfMonths: 1, position: { my: "left top", @@ -68,6 +70,8 @@ $.widget( "ui.datepicker", { .calendar({ dateFormat: this.options.dateFormat, eachDay: this.options.eachDay, + max: this.options.max, + min: this.options.min, numberOfMonths: this.options.numberOfMonths, showWeek: this.options.showWeek, value: this._getParsedValue(), @@ -337,7 +341,7 @@ $.widget( "ui.datepicker", { this.calendar.position( this._buildPosition() ); } - if ( $.inArray( key, [ "showWeek", "numberOfMonths", "dateFormat", "eachDay" ] ) ) { + if ( $.inArray( key, [ "showWeek", "numberOfMonths", "dateFormat", "eachDay", "min", "max" ] ) ) { this.calendarInstance._setOption( key, value ); } } From c05841d07fe4de8216f9f9eb917b24f517ec065c Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Wed, 4 Jun 2014 23:40:39 +0200 Subject: [PATCH 12/94] Datepicker: Remove select callback reference --- ui/datepicker.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/datepicker.js b/ui/datepicker.js index b6f056622c5..9fd3c97c22d 100644 --- a/ui/datepicker.js +++ b/ui/datepicker.js @@ -75,11 +75,11 @@ $.widget( "ui.datepicker", { numberOfMonths: this.options.numberOfMonths, showWeek: this.options.showWeek, value: this._getParsedValue(), - select: function( event, data ) { - that.element.val( data.date ); + select: function( event ) { + that.element.val( that.calendarInstance.value() ); that.close(); that._focusTrigger(); - that._trigger( "select", event, data); + that._trigger( "select", event ); } }) .calendar( "instance" ); From fdcc7694fa86de83b6fbc017b6e8ddd7bd0b7683 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Wed, 4 Jun 2014 23:41:13 +0200 Subject: [PATCH 13/94] Calendar: Remove select callback reference --- ui/calendar.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ui/calendar.js b/ui/calendar.js index 5e02b43e61c..ec889953158 100644 --- a/ui/calendar.js +++ b/ui/calendar.js @@ -419,9 +419,7 @@ return $.widget( "ui.calendar", { _select: function( event, time ) { this._setOption( "value", new Date( time ) ); - this._trigger( "select", event, { - date: this.value() - }); + this._trigger( "select", event ); }, value: function( value ) { From f011135a24c17620c4fb98b7e343b21d96ff0ad6 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Thu, 5 Jun 2014 00:38:13 +0200 Subject: [PATCH 14/94] Calendar: Fix min / max option incl. refresh after setting option --- demos/calendar/min-max.html | 9 ++++----- demos/datepicker/min-max.html | 7 +++---- ui/calendar.js | 12 +++++++----- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/demos/calendar/min-max.html b/demos/calendar/min-max.html index 2fddbcbc3bd..067b6f02f66 100644 --- a/demos/calendar/min-max.html +++ b/demos/calendar/min-max.html @@ -16,12 +16,11 @@ + - - - - - - - - - - - - - -Date:
      - -
      -

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

      -
      - - From cd45e92e59f104f480b7c9513b5bdf063a10a73d Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Thu, 5 Jun 2014 01:17:58 +0200 Subject: [PATCH 17/94] Datepicker: Read and write min / max attributes --- ui/datepicker.js | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/ui/datepicker.js b/ui/datepicker.js index 9fd3c97c22d..89ce26bc136 100644 --- a/ui/datepicker.js +++ b/ui/datepicker.js @@ -57,6 +57,16 @@ $.widget( "ui.datepicker", { return; } + var max = this.element.attr( "max" ), + min = this.element.attr( "min" ); + + if ( this.options.max === null && max ) { + this.options.max = this._parseDate( max ); + } + if ( this.options.min === null && min ) { + this.options.min = this._parseDate( min ); + } + this._createCalendar(); }, @@ -286,7 +296,7 @@ $.widget( "ui.datepicker", { value: function( value ) { if ( arguments.length ) { - var date = Globalize.parseDate( value, this.options.dateFormat ); + var date = this._parseDate( value ); if ( this.calendarInstance._isValid( date ) ) { this.valueAsDate( date ); this.element.val( value ); @@ -323,7 +333,11 @@ $.widget( "ui.datepicker", { }, _getParsedValue: function() { - return Globalize.parseDate( this.element.val(), this.options.dateFormat ); + return this._parseDate( this.element.val() ); + }, + + _parseDate: function( string ) { + return Globalize.parseDate( string , this.options.dateFormat ); }, _setOption: function( key, value ) { @@ -337,6 +351,10 @@ $.widget( "ui.datepicker", { this.element.val( this.date.format() ); } + if ( key === "max" || key === "min" ) { + this.element.attr( key, Globalize.format( value, this.options.dateFormat ) ); + } + if ( key === "position" ) { this.calendar.position( this._buildPosition() ); } From 4b5f47047aca72163bdd00c35a9f34dbfe9d2f78 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Thu, 5 Jun 2014 01:41:00 +0200 Subject: [PATCH 18/94] Datepicker tests: Add Calendar widget dependency to unit tests --- tests/unit/datepicker/datepicker.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/unit/datepicker/datepicker.html b/tests/unit/datepicker/datepicker.html index f55dd97900c..ce426313023 100644 --- a/tests/unit/datepicker/datepicker.html +++ b/tests/unit/datepicker/datepicker.html @@ -14,11 +14,12 @@ + diff --git a/ui/datepicker.js b/ui/datepicker.js index 7cbce700693..7f21e2353c2 100644 --- a/ui/datepicker.js +++ b/ui/datepicker.js @@ -316,7 +316,7 @@ widget = $.widget( "ui.datepicker", { _setOption: function( key, value ) { this._super( key, value ); - if ( $.inArray( key, calendarOptions ) ) { + if ( $.inArray( key, calendarOptions ) !== -1 ) { this.calendarInstance._setOption( key, value ); } @@ -325,7 +325,7 @@ widget = $.widget( "ui.datepicker", { } if ( key === "dateFormat" ) { - this.element.val( this.date.format() ); + this.element.val( this.calendarInstance.value() ); } if ( key === "max" || key === "min" ) { From bcdc7d8240b99f28d238a2f9a1a3d1fb3bdb4e10 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Fri, 13 Jun 2014 18:29:58 +0200 Subject: [PATCH 34/94] Datepicker tests: Adjust methods unit tests according to specs --- tests/unit/datepicker/datepicker_methods.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/unit/datepicker/datepicker_methods.js b/tests/unit/datepicker/datepicker_methods.js index 75cfb7372e2..c2a766a3379 100644 --- a/tests/unit/datepicker/datepicker_methods.js +++ b/tests/unit/datepicker/datepicker_methods.js @@ -40,10 +40,12 @@ test( "widget", function() { }); test( "close", function() { + // ToDo implement this expect( 0 ); }); test( "open", function() { + // ToDo implement this expect( 0 ); }); @@ -54,12 +56,13 @@ test( "value", function() { 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" ), + 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", + equal( input.datepicker( "value" ), null, "Invalid values should be returned without formatting." ); }); @@ -70,7 +73,7 @@ test( "valueAsDate", function() { 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" ), + 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" ); From 44d9bc8bf88e2c78885ec854e904fd4c9f12b25f Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Fri, 13 Jun 2014 19:22:00 +0200 Subject: [PATCH 35/94] Datepicker: Fix some core unit tests, remove unneeded tests --- tests/unit/datepicker/datepicker_core.js | 98 ++++++++++-------------- 1 file changed, 42 insertions(+), 56 deletions(-) diff --git a/tests/unit/datepicker/datepicker_core.js b/tests/unit/datepicker/datepicker_core.js index 4a9e0e25d18..65a0c5c6fdc 100644 --- a/tests/unit/datepicker/datepicker_core.js +++ b/tests/unit/datepicker/datepicker_core.js @@ -20,13 +20,15 @@ test( "input's value determines starting date", function() { }); asyncTest( "baseStructure", function() { - expect( 25 ); + expect( 23 ); + var header, title, table, thead, week, child, inp = TestHelpers.datepicker.initNewInput(), dp = inp.datepicker( "widget" ); function step1() { inp.focus(); + setTimeout(function() { ok( dp.is( ":visible" ), "Structure - datepicker visible" ); ok( !dp.is( ".ui-calendar-rtl" ), "Structure - not right-to-left" ); @@ -58,13 +60,10 @@ asyncTest( "baseStructure", function() { 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-calendar-week-end" ), "Structure - month table first day cell" ); - ok( week.children( ":last" ).is( "td.ui-calendar-week-end" ), "Structure - month table second day cell" ); inp.datepicker( "close" ).datepicker( "destroy" ); step2(); - }); + }, 50 ); } function step2() { @@ -76,14 +75,6 @@ asyncTest( "baseStructure", function() { ok( dp.is( ".ui-calendar-multi" ), "Structure multi [2] - multi-month" ); equal( dp.children().length, 4, "Structure multi [2] - child count" ); - // TODO: Implement ui-datepicker-group-first class name -// child = dp.children( ":first" ); -// ok( child.is( "div.ui-calendar-group" ) && child.is( "div.ui-calendar-group-first" ), "Structure multi [2] - first month division" ); - - // TODO: Implement ui-datepicker-group-last class name -// child = dp.children( ":eq(1)" ); -// ok( child.is( "div.ui-calendar-group" ) && child.is( "div.ui-calendar-group-last" ), "Structure multi [2] - second month division" ); - child = dp.children( ":eq(2)" ); ok( child.is( "div.ui-calendar-row-break" ), "Structure multi [2] - row break" ); @@ -96,17 +87,20 @@ asyncTest( "baseStructure", function() { }); test( "Keyboard handling", function() { - expect( 9 ); + expect( 8 ); var input = $( "#datepicker" ).datepicker(), instance = input.datepicker( "instance" ), date = new Date(); + // Enter = Select today's date by default 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" ) + // Enter = Select preset date + input.val( "1/1/14" ) + .datepicker( "refresh" ) + .datepicker( "open" ) .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), new Date( 2014, 0, 1 ), "Keystroke enter - preset" ); @@ -117,11 +111,6 @@ test( "Keyboard handling", function() { .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 } ); @@ -163,7 +152,7 @@ asyncTest( "keyboard handling", function() { ok( picker.is( ":visible" ), "Keystroke down opens datepicker" ); input.datepicker( "destroy" ); step2(); - }); + }, 50 ); } function step2() { @@ -177,12 +166,12 @@ asyncTest( "keyboard handling", function() { ok( picker.is( ":visible" ), "Keystroke up opens datepicker" ); input.datepicker( "destroy" ); step3(); - }); + }, 50 ); } function step3() { - input.datepicker() - .val( "1/1/14" ) + input.val( "1/1/14" ) + .datepicker() .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); setTimeout(function() { @@ -199,8 +188,8 @@ asyncTest( "keyboard handling", function() { } function step4() { - input.datepicker() - .val( "1/1/14" ) + input.val( "1/1/14" ) + .datepicker() .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); setTimeout(function() { @@ -217,8 +206,8 @@ asyncTest( "keyboard handling", function() { } function step5() { - input.datepicker() - .val( "1/1/14" ) + input.val( "1/1/14" ) + .datepicker() .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); setTimeout(function() { @@ -235,8 +224,8 @@ asyncTest( "keyboard handling", function() { } function step6() { - input.datepicker() - .val( "1/1/14" ) + input.val( "1/1/14" ) + .datepicker() .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); setTimeout(function() { @@ -253,8 +242,8 @@ asyncTest( "keyboard handling", function() { } function step7() { - input.datepicker() - .val( "1/1/14" ) + input.val( "1/1/14" ) + .datepicker() .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); setTimeout(function() { @@ -271,8 +260,8 @@ asyncTest( "keyboard handling", function() { } function step8() { - input.datepicker() - .val( "1/1/14" ) + input.val( "1/1/14" ) + .datepicker() .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); setTimeout(function() { @@ -289,8 +278,8 @@ asyncTest( "keyboard handling", function() { } function step9() { - input.datepicker() - .val( "1/1/14" ) + input.val( "1/1/14" ) + .datepicker() .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); setTimeout(function() { @@ -307,8 +296,8 @@ asyncTest( "keyboard handling", function() { } function step10() { - input.datepicker() - .val( "1/1/14" ) + input.val( "1/1/14" ) + .datepicker() .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); setTimeout(function() { @@ -326,8 +315,8 @@ asyncTest( "keyboard handling", function() { // Check for moving to short months function step11() { - input.datepicker() - .val( "3/31/14" ) + input.val( "3/31/14" ) + .datepicker() .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); setTimeout(function() { @@ -344,8 +333,8 @@ asyncTest( "keyboard handling", function() { } function step12() { - input.datepicker() - .val( "1/30/16" ) + input.val( "1/30/16" ) + .datepicker() .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); setTimeout(function() { @@ -381,7 +370,7 @@ asyncTest( "keyboard handling", function() { */ test( "mouse", function() { - expect( 8 ); + expect( 10 ); var input = $( "#datepicker" ).datepicker(), picker = input.datepicker( "widget" ), date = new Date(); @@ -391,50 +380,48 @@ test( "mouse", function() { date.setDate( 10 ); TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), date, "Mouse click" ); - input.val( "2/4/08" ).datepicker( "open" ); + 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( "open" ); + input.val( "" ).datepicker( "refresh" ).datepicker( "open" ); $( "button.ui-calendar-close", picker ).simulate( "click", {} ); ok( input.datepicker( "valueAsDate" ) == null, "Mouse click - close" ); - input.val( "2/4/08" ).datepicker( "open" ); + input.val( "2/4/08" ).datepicker( "refresh" ).datepicker( "open" ); $( "button.ui-calendar-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" ); + input.val( "2/4/08" ).datepicker( "refresh" ).datepicker( "open" ); $( "a.ui-calendar-prev", picker ).simulate( "click", {} ); $( "button.ui-calendar-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" ); + input.val( "" ).datepicker( "refresh" ).datepicker( "open" ); $( ".ui-calendar-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" ); + input.val( "2/4/08" ).datepicker( "refresh" ).datepicker( "open" ); $( ".ui-calendar-prev", picker ).simulate( "click" ); $( ".ui-calendar-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" ); + input.val( "2/4/08" ).datepicker( "refresh" ).datepicker( "open" ); $( ".ui-calendar-next", picker ).simulate( "click" ); $( ".ui-calendar-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 ) + min: new Date( 2008, 2 - 1, 2 ), + max: new Date( 2008, 2 - 1, 26 ) }).val( "2/4/08" ).datepicker( "open" ); $( ".ui-calendar-prev", picker ).simulate( "click" ); $( ".ui-calendar-calendar tbody a:contains(16)", picker ).simulate( "mousedown" ); @@ -446,7 +433,6 @@ test( "mouse", function() { $( ".ui-calendar-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" ); - */ }); })( jQuery ); From 66392536fe5922400662702ea141069eccbcba6c Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Mon, 16 Jun 2014 18:07:06 +0200 Subject: [PATCH 36/94] Datepicker tests: Remove unneeded options unit tests, add todo comments --- tests/unit/datepicker/datepicker_options.js | 671 +------------------- 1 file changed, 7 insertions(+), 664 deletions(-) diff --git a/tests/unit/datepicker/datepicker_options.js b/tests/unit/datepicker/datepicker_options.js index e6807f4b72e..117a60f0de8 100644 --- a/tests/unit/datepicker/datepicker_options.js +++ b/tests/unit/datepicker/datepicker_options.js @@ -155,48 +155,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" ); -}); - +// TODO: Rewrite test( "disabled", function() { expect(8); var inp = TestHelpers.datepicker.init( "#inp" ); @@ -215,196 +174,7 @@ test( "disabled", function() { 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: Rewrite for value option test( "defaultDate", function() { expect( 16 ); var inp = TestHelpers.datepicker.init( "#inp" ), @@ -501,68 +271,7 @@ test( "defaultDate", function() { 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-calendar-year" ).text(), "2008", "Year range - read-only default" ); - inp.datepicker( "hide" ).datepicker( "option", {changeYear: true}).datepicker( "show" ); - equal(dp.find( ".ui-calendar-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-calendar-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-calendar-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-calendar-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-calendar-year" ).text(), genRange(2000, curYear - 2004), "Year range - 2000:-5" ); - inp.datepicker( "hide" ).datepicker( "option", {yearRange: "", changeYear: true}).datepicker( "show" ); - equal(dp.find( ".ui-calendar-year" ).text(), genRange(curYear, 1), "Year range - -6:+2" ); - - // Navigation as date format - inp.datepicker( "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.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-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.datepicker( "hide" ).datepicker( "option", {gotoCurrent: true}). - val( "02/04/2008" ).datepicker( "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" ); -}); - +// TODO: Rewrite test( "minMax", function() { expect( 23 ); var date, @@ -670,6 +379,7 @@ test( "minMax", function() { ok(!dp.find( ".ui-calendar-prev" ).hasClass( "ui-state-disabled" ), "Year Range Test - prev button enabled" ); }); +// TODO: Rewrite for valueAsDate / value test( "setDate", function() { expect( 24 ); var inl, alt, minDate, maxDate, dateAndTimeToSet, dateAndTimeClone, @@ -732,83 +442,7 @@ test( "setDate", function() { 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" ); -}); - +// TODO: Move this to $.date, Globalize or calendar widget test( "daylightSaving", function() { expect( 25 ); var inp = TestHelpers.datepicker.init( "#inp" ), @@ -892,73 +526,7 @@ test( "daylightSaving", function() { 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-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.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-calendar-calendar td:contains('9')" ).attr( "title" ), "'" ); - inp.datepicker( "hide" ).datepicker( "destroy" ); -}); - +// TODO: Move to calendar. Perhaps adda calendar_external test file? test( "localisation", function() { expect( 24 ); var dp, month, day, date, @@ -989,232 +557,7 @@ test( "localisation", function() { " " + 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" ); -// }); - +// TODO: Rewrite this for beforeOpen test( "Ticket 7602: Stop datepicker from appearing with beforeShow event handler", function() { expect( 3 ); From 9ccf4b975ce976474d24f0a38412bc4b43633e55 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Mon, 16 Jun 2014 20:56:02 +0200 Subject: [PATCH 37/94] Datepicker tests: Rewrite unit test for beforeOpen event (#7602) --- tests/unit/datepicker/datepicker_options.js | 42 ++++++++++----------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/tests/unit/datepicker/datepicker_options.js b/tests/unit/datepicker/datepicker_options.js index 117a60f0de8..b26c39bebde 100644 --- a/tests/unit/datepicker/datepicker_options.js +++ b/tests/unit/datepicker/datepicker_options.js @@ -557,42 +557,38 @@ test( "localisation", function() { " " + date.getFullYear(), "Localisation - formatting" ); }); -// TODO: Rewrite this for beforeOpen -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; + var input; - inp = TestHelpers.datepicker.init( "#inp", { - beforeShow: function() { + 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" ); + input.datepicker( "open" ); + equal( input.datepicker( "widget" ).css( "display" ), "block", "beforeOpen returns nothing" ); + input.datepicker( "close" ).datepicker( "destroy" ); - inp = TestHelpers.datepicker.init( "#inp", { - beforeShow: function() { + 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" ); + input.datepicker( "open" ); + equal( input.datepicker( "widget" ).css( "display" ), "block", "beforeOpen returns true" ); + input.datepicker( "close" ).datepicker( "destroy" ); - inp = TestHelpers.datepicker.init( "#inp", { - beforeShow: function() { + 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); From 45818781d73f3f77802fcbb0819fcf86ae3845dd Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Mon, 16 Jun 2014 21:44:36 +0200 Subject: [PATCH 38/94] Datepicker tests: Re-enable some min / max option unit tests --- tests/unit/datepicker/datepicker_options.js | 154 +++++++++++--------- 1 file changed, 87 insertions(+), 67 deletions(-) diff --git a/tests/unit/datepicker/datepicker_options.js b/tests/unit/datepicker/datepicker_options.js index b26c39bebde..b7f279839d6 100644 --- a/tests/unit/datepicker/datepicker_options.js +++ b/tests/unit/datepicker/datepicker_options.js @@ -97,6 +97,7 @@ test( "eachDay", function() { }); test( "numberOfMonths", function() { + // TODO implement this expect( 0 ); }); @@ -270,115 +271,134 @@ test( "defaultDate", function() { simulate( "keydown", {keyCode: $.ui.keyCode.ENTER}); TestHelpers.datepicker.equalsDate(inp.datepicker( "getDate" ), date, "Default date 01/26/2007" ); }); +*/ -// TODO: Rewrite -test( "minMax", function() { - expect( 23 ); +test( "min / max", function() { + expect( 7 ); + + /* + // 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 = 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 - null, null - ctrl+pgdn" ); - inp.datepicker( "option", {minDate: minDate}). - datepicker( "hide" ).val( "06/04/2008" ).datepicker( "show" ); - inp.simulate( "keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP}). - simulate( "keydown", {keyCode: $.ui.keyCode.ENTER}); - TestHelpers.datepicker.equalsDate(inp.datepicker( "getDate" ), minDate, - "Min/max - 02/29/2008, null - ctrl+pgup" ); - inp.val( "06/04/2008" ).datepicker( "show" ); - inp.simulate( "keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN}). - simulate( "keydown", {keyCode: $.ui.keyCode.ENTER}); - TestHelpers.datepicker.equalsDate(inp.datepicker( "getDate" ), nextYear, - "Min/max - 02/29/2008, null - ctrl+pgdn" ); - inp.datepicker( "option", {maxDate: maxDate}). - datepicker( "hide" ).val( "06/04/2008" ).datepicker( "show" ); - inp.simulate( "keydown", {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP}). - simulate( "keydown", {keyCode: $.ui.keyCode.ENTER}); - TestHelpers.datepicker.equalsDate(inp.datepicker( "getDate" ), minDate, - "Min/max - 02/29/2008, 12/07/2008 - ctrl+pgup" ); - inp.val( "06/04/2008" ).datepicker( "show" ); + 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" ); + + inp.datepicker( "option", { min: null } ).val( "1/4/08" ).datepicker( "option", { min: minDate } ); + TestHelpers.datepicker.equalsDate( inp.datepicker( "valueAsDate" ), minDate, "Min/max - value < min" ); + 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" ); + + inp.datepicker( "option", { max: null } ).val( "1/4/09" ).datepicker( "option", { max: maxDate } ); + TestHelpers.datepicker.equalsDate( inp.datepicker( "valueAsDate" ), maxDate, "Min/max - setDate > max" ); + + inp.datepicker( "option", { max: null } ).val( "1/4/08" ).datepicker( "option", { min: minDate, max: maxDate } ); + TestHelpers.datepicker.equalsDate( inp.datepicker( "valueAsDate" ), minDate, "Min/max - value < min" ); + + 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" ); + + inp.datepicker( "option", { max: null } ).val( "1/4/09" ).datepicker( "option", { min: minDate, max: maxDate } ); + TestHelpers.datepicker.equalsDate( inp.datepicker( "valueAsDate" ), maxDate, "Min/max - value > max" ); + + /* + // TODO: enable when yearRange option is implemented inp.datepicker( "option", {yearRange: "-0:+1"}).val( "01/01/" + new Date().getFullYear()); ok(dp.find( ".ui-calendar-prev" ).hasClass( "ui-state-disabled" ), "Year Range Test - previous button disabled at 1/1/minYear" ); inp.datepicker( "setDate", "12/30/" + new Date().getFullYear()); ok(dp.find( ".ui-calendar-next" ).hasClass( "ui-state-disabled" ), "Year Range Test - next button disabled at 12/30/maxYear" ); inp.datepicker( "option", { - minDate: new Date(1900, 0, 1), - maxDate: "-6Y", + min: new Date(1900, 0, 1), + max: "-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.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-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: Rewrite for valueAsDate / value test( "setDate", function() { expect( 24 ); From 16101b678847f29bd0a8c13dd78afa70f5214601 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Mon, 16 Jun 2014 21:49:45 +0200 Subject: [PATCH 39/94] Datepicker tests: Adjust min / max option unit tests to specification Datepicker should return input value even if invalid regarding min and max option. Test for correct min / max setting by using isValid method. --- tests/unit/datepicker/datepicker_options.js | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/tests/unit/datepicker/datepicker_options.js b/tests/unit/datepicker/datepicker_options.js index b7f279839d6..9817fe9b190 100644 --- a/tests/unit/datepicker/datepicker_options.js +++ b/tests/unit/datepicker/datepicker_options.js @@ -274,7 +274,7 @@ test( "defaultDate", function() { */ test( "min / max", function() { - expect( 7 ); + expect( 14 ); /* // TODO CTRL + PgUp / PgDn is not implemented yet, see wiki @@ -353,24 +353,31 @@ test( "min / max", function() { 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" ), minDate, "Min/max - value < min" ); + 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" ), maxDate, "Min/max - setDate > max" ); + 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" ), minDate, "Min/max - value < min" ); + 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" ), maxDate, "Min/max - value > max" ); + 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 From fe0d260ea6edff0f10ad7acf28eab7a8079c8f1e Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Mon, 16 Jun 2014 22:02:08 +0200 Subject: [PATCH 40/94] Datepicker tests: clean up method tests --- tests/unit/datepicker/datepicker_methods.js | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/tests/unit/datepicker/datepicker_methods.js b/tests/unit/datepicker/datepicker_methods.js index c2a766a3379..d65b5cbf56a 100644 --- a/tests/unit/datepicker/datepicker_methods.js +++ b/tests/unit/datepicker/datepicker_methods.js @@ -40,12 +40,12 @@ test( "widget", function() { }); test( "close", function() { - // ToDo implement this + // TODO: implement this expect( 0 ); }); test( "open", function() { - // ToDo implement this + // TODO: implement this expect( 0 ); }); @@ -57,13 +57,11 @@ test( "value", function() { input.datepicker( "value", "1/1/14" ); equal( input.val(), "1/1/14", "input's value set" ); input.datepicker( "open" ); - ok( picker.find( "a[data-timestamp]:first" ).hasClass( "ui-state-active" ), - "first day marked as selected" ); + ok( picker.find( "a[data-timestamp]:first" ).hasClass( "ui-state-active" ), "first day marked as selected" ); equal( input.datepicker( "value" ), "1/1/14", "getter" ); input.val( "abc" ); - equal( input.datepicker( "value" ), null, - "Invalid values should be returned without formatting." ); + equal( input.datepicker( "value" ), null, "Invalid values should return null." ); }); test( "valueAsDate", function() { @@ -73,10 +71,8 @@ test( "valueAsDate", function() { input.datepicker( "valueAsDate", new Date( 2014, 0, 1 ) ); equal( input.val(), "1/1/14", "input's value set" ); - ok( picker.find( "a[data-timestamp]:first" ).hasClass( "ui-state-active" ), - "first day marked as selected" ); - TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), - new Date( 2014, 0, 1 ), "getter" ); + 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" ); From c0002220aa6ed2e4f82b46ef0114a6cc117ccc49 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Mon, 16 Jun 2014 22:11:50 +0200 Subject: [PATCH 41/94] Calendar: Add version property --- ui/calendar.js | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/calendar.js b/ui/calendar.js index 44a18641989..6bd478a9533 100644 --- a/ui/calendar.js +++ b/ui/calendar.js @@ -27,6 +27,7 @@ }(function( $ ) { return $.widget( "ui.calendar", { + version: "@VERSION", options: { dateFormat: { date: "short" }, // TODO review From be230db360046c0ecac4ada9337f2d5d711982bf Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Mon, 16 Jun 2014 22:12:07 +0200 Subject: [PATCH 42/94] Datepicker: Add version property --- ui/datepicker.js | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/datepicker.js b/ui/datepicker.js index 7f21e2353c2..1216ec0da2e 100644 --- a/ui/datepicker.js +++ b/ui/datepicker.js @@ -32,6 +32,7 @@ var widget, suppressExpandOnFocus = false; widget = $.widget( "ui.datepicker", { + version: "@VERSION", options: { appendTo: null, position: { From b9bbce45665b358b036d807dcdc636b6b01468d7 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Mon, 16 Jun 2014 22:12:27 +0200 Subject: [PATCH 43/94] Datepicker tests: Add common unit tests --- tests/unit/datepicker/datepicker_common.js | 24 +++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/tests/unit/datepicker/datepicker_common.js b/tests/unit/datepicker/datepicker_common.js index 1eecc85cb50..4a2ece05da8 100644 --- a/tests/unit/datepicker/datepicker_common.js +++ b/tests/unit/datepicker/datepicker_common.js @@ -1,7 +1,25 @@ -/* TestHelpers.commonWidgetTests( "datepicker", { defaults: { - disabled: false + appendTo: null, + 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 } }); -*/ From 0db381cde089fe3890045f00a1fd3504b46fe717 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Tue, 17 Jun 2014 00:46:08 +0200 Subject: [PATCH 44/94] Datepicker tests: Add open and close unit tests --- tests/unit/datepicker/datepicker_methods.js | 23 ++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/tests/unit/datepicker/datepicker_methods.js b/tests/unit/datepicker/datepicker_methods.js index d65b5cbf56a..f5236e30ce8 100644 --- a/tests/unit/datepicker/datepicker_methods.js +++ b/tests/unit/datepicker/datepicker_methods.js @@ -39,14 +39,23 @@ test( "widget", function() { actual.remove(); }); -test( "close", function() { - // TODO: implement this - expect( 0 ); -}); +test( "open / close", function() { + expect( 7 ); + + var input = TestHelpers.datepicker.initNewInput({ show: false, hide: false }), + calendar = input.datepicker( "widget" ); -test( "open", function() { - // TODO: implement this - expect( 0 ); + 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-disabled" ); + equal( calendar.attr( "aria-expanded" ), "true", "close: calendar aria-expanded" ); + + input.datepicker( "close" ); + ok( !calendar.is( ":visible" ), "close: calendar hidden" ); + equal( calendar.attr( "aria-hidden" ), "true", "close: calendar aria-disabled" ); + equal( calendar.attr( "aria-expanded" ), "false", "close: calendar aria-expanded" ); }); test( "value", function() { From 94e2ac5e9959c704d82ae5370150c247fbaa7ef8 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Tue, 17 Jun 2014 00:49:38 +0200 Subject: [PATCH 45/94] Datepicker tests: Remove unneeded disabled / enabled options Remove unneeded disabled / enabled options as tests exists for disable and enable methods. --- tests/unit/datepicker/datepicker_options.js | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/tests/unit/datepicker/datepicker_options.js b/tests/unit/datepicker/datepicker_options.js index 9817fe9b190..036a9c55a30 100644 --- a/tests/unit/datepicker/datepicker_options.js +++ b/tests/unit/datepicker/datepicker_options.js @@ -156,25 +156,6 @@ test( "showWeek", function() { }); /* -// TODO: Rewrite -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" ); -}); - // TODO: Rewrite for value option test( "defaultDate", function() { expect( 16 ); From b22a5bf66c408795143810c6d03c5829055c1418 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Tue, 17 Jun 2014 11:27:46 +0200 Subject: [PATCH 46/94] Datepicker tests: Rewrite setDate tests as valueAsDate method tests --- tests/unit/datepicker/datepicker_methods.js | 56 +++++++++++++++-- tests/unit/datepicker/datepicker_options.js | 69 +-------------------- 2 files changed, 52 insertions(+), 73 deletions(-) diff --git a/tests/unit/datepicker/datepicker_methods.js b/tests/unit/datepicker/datepicker_methods.js index f5236e30ce8..a4209740ea6 100644 --- a/tests/unit/datepicker/datepicker_methods.js +++ b/tests/unit/datepicker/datepicker_methods.js @@ -74,17 +74,61 @@ test( "value", function() { }); test( "valueAsDate", function() { - expect( 4 ); - var input = $( "#datepicker" ).datepicker(), - picker = input.datepicker( "widget" ); + expect( 14 ); + + var minDate, maxDate, dateAndTimeToSet, dateAndTimeClone, + input = TestHelpers.datepicker.init( "#datepicker" ), + picker = input.datepicker( "widget" ), + date1 = new Date(2008, 6 - 1, 4), + date2 = new Date(); input.datepicker( "valueAsDate", new Date( 2014, 0, 1 ) ); - equal( input.val(), "1/1/14", "input's value set" ); - ok( picker.find( "a[data-timestamp]:first" ).hasClass( "ui-state-active" ), "first day marked as selected" ); - TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), new Date( 2014, 0, 1 ), "getter" ); + equal( input.val(), "1/1/14", "Input's value set" ); + ok( picker.find( "a[data-timestamp]:first" ).hasClass( "ui-state-active" ), "First day marked as selected" ); + TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), new Date( 2014, 0, 1 ), "Getter" ); input.val( "a/b/c" ); equal( input.datepicker( "valueAsDate" ), null, "Invalid dates return null" ); + + input.val( "" ).datepicker( "destroy" ); + input = TestHelpers.datepicker.init( "#datepicker" ); + + ok(input.datepicker( "valueAsDate" ) == null, "Set date - default" ); + input.datepicker( "valueAsDate", date1); + TestHelpers.datepicker.equalsDate(input.datepicker( "valueAsDate" ), date1, "Set date - 2008-06-04" ); + + input.datepicker( "valueAsDate", date1, date2); + TestHelpers.datepicker.equalsDate(input.datepicker( "valueAsDate" ), date1, "Set date - two dates" ); + + // 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 036a9c55a30..f73ee569d80 100644 --- a/tests/unit/datepicker/datepicker_options.js +++ b/tests/unit/datepicker/datepicker_options.js @@ -156,7 +156,7 @@ test( "showWeek", function() { }); /* -// TODO: Rewrite for value option +// TODO: Move to calendar and rewrite for value option test( "defaultDate", function() { expect( 16 ); var inp = TestHelpers.datepicker.init( "#inp" ), @@ -386,70 +386,6 @@ test( "min / max", function() { }); /* - -// TODO: Rewrite for valueAsDate / value -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" ); - // 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" ); -}); - // TODO: Move this to $.date, Globalize or calendar widget test( "daylightSaving", function() { expect( 25 ); @@ -535,7 +471,7 @@ test( "daylightSaving", function() { }); // TODO: Move to calendar. Perhaps adda calendar_external test file? -test( "localisation", function() { +test( "localization", function() { expect( 24 ); var dp, month, day, date, inp = TestHelpers.datepicker.init( "#inp", $.datepicker.regional.fr); @@ -564,7 +500,6 @@ test( "localisation", function() { date.getDate() + " " + $.datepicker.regional.fr.monthNames[date.getMonth()] + " " + date.getFullYear(), "Localisation - formatting" ); }); - */ test( "Ticket 7602: Stop datepicker from appearing with beforeOpen event handler", function() { From 9b06cc9bb772772101ba3bf818b534fb34673a16 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Tue, 17 Jun 2014 11:28:29 +0200 Subject: [PATCH 47/94] Calendar: Make it possible to set min / max option to null --- ui/calendar.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/calendar.js b/ui/calendar.js index 6bd478a9533..f3cc63141ef 100644 --- a/ui/calendar.js +++ b/ui/calendar.js @@ -475,7 +475,7 @@ return $.widget( "ui.calendar", { } if ( key === "max" || key === "min" ) { - if ( value instanceof Date ) { + if ( value instanceof Date || value === null ) { this._super( key, value ); this.refresh(); } From d54374193dd526bfd1448c2ff683ea8d04e89d02 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Tue, 17 Jun 2014 16:25:24 +0200 Subject: [PATCH 48/94] Datepicker: Improve document click event --- ui/datepicker.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ui/datepicker.js b/ui/datepicker.js index 1216ec0da2e..519cc477d3f 100644 --- a/ui/datepicker.js +++ b/ui/datepicker.js @@ -191,8 +191,12 @@ widget = $.widget( "ui.datepicker", { }, _documentEvents: { - click: function( event ) { - if ( this.isOpen && !$( event.target ).closest( this.element.add( this.calendar ) ).length ) { + mousedown: function( event ) { + if ( !this.isOpen ) { + return; + } + + if ( !$( event.target ).closest( this.element.add( this.calendar ) ).length ) { this.close( event ); } } From 1d6c9fc6c4e844ccfaa63f93afc43a62ff568e3e Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Tue, 17 Jun 2014 19:05:06 +0200 Subject: [PATCH 49/94] Calendar: Fix broken day table cell attributes --- ui/calendar.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/calendar.js b/ui/calendar.js index f3cc63141ef..fc29da9027b 100644 --- a/ui/calendar.js +++ b/ui/calendar.js @@ -313,7 +313,7 @@ return $.widget( "ui.calendar", { var content = "", attributes = [ "role='gridcell'", - "aria-selected='" + day.current ? true : false + "'" + "aria-selected='" + ( day.current ? true : false ) + "'" ], selectable = ( day.selectable && this._isValid( new Date( day.timestamp ) ) ); From 4129f7a13ec424d8285a3bc204017e5d27f8f045 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Tue, 17 Jun 2014 19:53:08 +0200 Subject: [PATCH 50/94] Datepicker tests: Rewrite event unit tests --- tests/unit/datepicker/datepicker_events.js | 260 +++++++++--------- .../datepicker/datepicker_test_helpers.js | 6 +- 2 files changed, 129 insertions(+), 137 deletions(-) diff --git a/tests/unit/datepicker/datepicker_events.js b/tests/unit/datepicker/datepicker_events.js index 9ee254e5351..6739f843589 100644 --- a/tests/unit/datepicker/datepicker_events.js +++ b/tests/unit/datepicker/datepicker_events.js @@ -1,150 +1,144 @@ -// 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 ); + + 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" ); -test( "select", function() { - expect( 0 ); + 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( 6 ); + + 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 input enter"; + input + .simulate( "focus" ) + .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); + input.datepicker( "close" ); + step2(); + } + + function step2() { + 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" ); + step3(); + }, 100 ); + } + + function step3() { + 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" ); + step4(); + }, 100 ); + } + + function step4() { + 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_test_helpers.js b/tests/unit/datepicker/datepicker_test_helpers.js index 1d922c72220..23f5025b48b 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 || {} ); return $( "" ).datepicker( options ) .appendTo( "#qunit-fixture" ); - }, - onFocus: TestHelpers.onFocus, - PROP_NAME: "datepicker" + } }; \ No newline at end of file From 3bf80f8111490060f8a73e2d9ff4929cb798ff22 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Tue, 17 Jun 2014 19:54:02 +0200 Subject: [PATCH 51/94] Datepicker tests: Code style improvements, add todo comment for ARIA --- tests/unit/datepicker/datepicker_core.js | 156 +++++++++++++++-------- 1 file changed, 101 insertions(+), 55 deletions(-) diff --git a/tests/unit/datepicker/datepicker_core.js b/tests/unit/datepicker/datepicker_core.js index 65a0c5c6fdc..79135278647 100644 --- a/tests/unit/datepicker/datepicker_core.js +++ b/tests/unit/datepicker/datepicker_core.js @@ -86,19 +86,21 @@ asyncTest( "baseStructure", function() { step1(); }); -test( "Keyboard handling", function() { +test( "Keyboard handling: input", function() { expect( 8 ); var input = $( "#datepicker" ).datepicker(), instance = input.datepicker( "instance" ), date = new Date(); // Enter = Select today's date by default - input.datepicker( "open" ) + input + .datepicker( "open" ) .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), date, "Keystroke enter" ); // Enter = Select preset date - input.val( "1/1/14" ) + input + .val( "1/1/14" ) .datepicker( "refresh" ) .datepicker( "open" ) .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); @@ -106,28 +108,37 @@ test( "Keyboard handling", function() { "Keystroke enter - preset" ); // Control + Home = Change the calendar to the current month - input.val( "1/1/14" ).datepicker( "open" ) + 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" ); - input.val( "" ).datepicker( "open" ); + 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" ) + 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" ) + 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" ) + 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" ); @@ -135,19 +146,19 @@ test( "Keyboard handling", function() { input.datepicker( "destroy" ); }); -asyncTest( "keyboard handling", function() { +asyncTest( "keyboard handling: calendar", function() { expect( 14 ); + var picker, - input = $( "#datepicker" ), - date = new Date(); + input = $( "#datepicker" ); function step1() { input.datepicker(); 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" ); @@ -158,10 +169,10 @@ asyncTest( "keyboard handling", function() { function step2() { input.datepicker(); 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" ); @@ -170,7 +181,8 @@ asyncTest( "keyboard handling", function() { } function step3() { - input.val( "1/1/14" ) + input + .val( "1/1/14" ) .datepicker() .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); @@ -178,17 +190,20 @@ asyncTest( "keyboard handling", 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" ); + TestHelpers.datepicker.equalsDate( + input.datepicker( "valueAsDate" ), + new Date( 2013, 12 - 1, 31 ), + "Keystroke left to switch to previous day" + ); input.datepicker( "destroy" ); step4(); }, 100 ); } function step4() { - input.val( "1/1/14" ) + input + .val( "1/1/14" ) .datepicker() .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); @@ -196,17 +211,20 @@ asyncTest( "keyboard handling", 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" ); + TestHelpers.datepicker.equalsDate( + input.datepicker( "valueAsDate" ), + new Date( 2014, 1 - 1, 2 ), + "Keystroke right to switch to next day" + ); input.datepicker( "destroy" ); step5(); }, 100 ); } function step5() { - input.val( "1/1/14" ) + input + .val( "1/1/14" ) .datepicker() .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); @@ -214,17 +232,20 @@ asyncTest( "keyboard handling", 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" ); + TestHelpers.datepicker.equalsDate( + input.datepicker( "valueAsDate" ), + new Date( 2013, 12 - 1, 25 ), + "Keystroke up to move to the previous week" + ); input.datepicker( "destroy" ); step6(); }, 100 ); } function step6() { - input.val( "1/1/14" ) + input + .val( "1/1/14" ) .datepicker() .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); @@ -232,17 +253,20 @@ asyncTest( "keyboard handling", 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" ); + TestHelpers.datepicker.equalsDate( + input.datepicker( "valueAsDate" ), + new Date( 2014, 1 - 1, 8 ), + "Keystroke down to move to the next week" + ); input.datepicker( "destroy" ); step7(); }, 100 ); } function step7() { - input.val( "1/1/14" ) + input + .val( "1/1/14" ) .datepicker() .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); @@ -250,17 +274,20 @@ asyncTest( "keyboard handling", function() { $( ":focus" ) .simulate( "keydown", { keyCode: $.ui.keyCode.PAGE_UP } ) .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( 2013, 12 - 1, 1 ), + "Keystroke Page Up moves date to previous month" + ); input.datepicker( "destroy" ); step8(); }, 100 ); } function step8() { - input.val( "1/1/14" ) + input + .val( "1/1/14" ) .datepicker() .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); @@ -268,17 +295,20 @@ asyncTest( "keyboard handling", 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" ); + TestHelpers.datepicker.equalsDate( + input.datepicker( "valueAsDate" ), + new Date( 2013, 1 - 1, 1 ), + "Keystroke Page Up + Ctrl moves date to previous year" + ); input.datepicker( "destroy" ); step9(); }, 100 ); } function step9() { - input.val( "1/1/14" ) + input + .val( "1/1/14" ) .datepicker() .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); @@ -286,17 +316,20 @@ asyncTest( "keyboard handling", 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" ); + TestHelpers.datepicker.equalsDate( + input.datepicker( "valueAsDate" ), + new Date( 2014, 2 - 1, 1 ), + "Keystroke Page Down moves date to next month" + ); input.datepicker( "destroy" ); step10(); }, 100 ); } function step10() { - input.val( "1/1/14" ) + input + .val( "1/1/14" ) .datepicker() .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); @@ -304,10 +337,12 @@ asyncTest( "keyboard handling", 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" ); + TestHelpers.datepicker.equalsDate( + input.datepicker( "valueAsDate" ), + new Date( 2015, 1 - 1, 1 ), + "Keystroke Page Down + Ctrl moves date to next year" + ); input.datepicker( "destroy" ); step11(); }, 100 ); @@ -315,7 +350,8 @@ asyncTest( "keyboard handling", function() { // Check for moving to short months function step11() { - input.val( "3/31/14" ) + input + .val( "3/31/14" ) .datepicker() .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); @@ -323,17 +359,20 @@ asyncTest( "keyboard handling", 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" ); + TestHelpers.datepicker.equalsDate( + input.datepicker( "valueAsDate" ), + new Date( 2014, 2 - 1, 28 ), + "Keystroke Page Up and short months" + ); input.datepicker( "destroy" ); step12(); }, 100 ); } function step12() { - input.val( "1/30/16" ) + input + .val( "1/30/16" ) .datepicker() .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); @@ -341,10 +380,12 @@ asyncTest( "keyboard handling", 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" ); + TestHelpers.datepicker.equalsDate( + input.datepicker( "valueAsDate" ), + new Date( 2016, 2 - 1, 29 ), + "Keystroke Page Down and leap years" + ); input.datepicker( "destroy" ); start(); }, 100 ); @@ -369,6 +410,11 @@ asyncTest( "keyboard handling", function() { "Keystroke pgdn step 2" ); */ +// TODO: implement +test( "ARIA", function() { + expect( 0 ); +}); + test( "mouse", function() { expect( 10 ); var input = $( "#datepicker" ).datepicker(), From 35922bced172775656cfdede4dae9506e6fe7fff Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Tue, 17 Jun 2014 20:48:20 +0200 Subject: [PATCH 52/94] Datepicker tests: Fix calendar keyboard control tests Fix calendar keyboard control tests by disabling animation and adding delay --- tests/unit/datepicker/datepicker_core.js | 277 +++++++++++------------ 1 file changed, 134 insertions(+), 143 deletions(-) diff --git a/tests/unit/datepicker/datepicker_core.js b/tests/unit/datepicker/datepicker_core.js index 79135278647..c041be19682 100644 --- a/tests/unit/datepicker/datepicker_core.js +++ b/tests/unit/datepicker/datepicker_core.js @@ -153,7 +153,7 @@ asyncTest( "keyboard handling: calendar", function() { input = $( "#datepicker" ); function step1() { - input.datepicker(); + TestHelpers.datepicker.init( input ); picker = input.datepicker( "widget" ); ok( !picker.is( ":visible" ), "datepicker closed" ); @@ -163,11 +163,11 @@ asyncTest( "keyboard handling: calendar", function() { ok( picker.is( ":visible" ), "Keystroke down opens datepicker" ); input.datepicker( "destroy" ); step2(); - }, 50 ); + }, 100 ); } function step2() { - input.datepicker(); + TestHelpers.datepicker.init( input ); picker = input.datepicker( "widget" ); ok( !picker.is( ":visible" ), "datepicker closed" ); @@ -177,35 +177,33 @@ asyncTest( "keyboard handling: calendar", function() { ok( picker.is( ":visible" ), "Keystroke up opens datepicker" ); input.datepicker( "destroy" ); step3(); - }, 50 ); + }, 100 ); } function step3() { - input - .val( "1/1/14" ) - .datepicker() - .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + input.val( "1/1/14" ); + TestHelpers.datepicker.init( input ); + input.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); setTimeout(function() { - $( ":focus" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.LEFT } ) - .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" ); - step4(); + $( ":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" ); + step4(); + }, 50 ); }, 100 ); } function step4() { - input - .val( "1/1/14" ) - .datepicker() - .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + input.val( "1/1/14" ); + TestHelpers.datepicker.init( input ); + input.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); setTimeout(function() { $( ":focus" ) @@ -223,171 +221,164 @@ asyncTest( "keyboard handling: calendar", function() { } function step5() { - input - .val( "1/1/14" ) - .datepicker() - .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + input.val( "1/1/14" ); + TestHelpers.datepicker.init( input ); + input.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); setTimeout(function() { - $( ":focus" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.UP } ) - .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" ); - step6(); + $( ":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" ); + step6(); + }, 50 ); }, 100 ); } function step6() { - input - .val( "1/1/14" ) - .datepicker() - .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + 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 } ); - - TestHelpers.datepicker.equalsDate( - input.datepicker( "valueAsDate" ), - new Date( 2014, 1 - 1, 8 ), - "Keystroke down to move to the next week" - ); - input.datepicker( "destroy" ); - step7(); + $( ":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" ); + step7(); + }, 50 ); }, 100 ); } function step7() { - input - .val( "1/1/14" ) - .datepicker() - .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + 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 } ); - - TestHelpers.datepicker.equalsDate( - input.datepicker( "valueAsDate" ), - new Date( 2013, 12 - 1, 1 ), - "Keystroke Page Up moves date to previous month" - ); - input.datepicker( "destroy" ); - step8(); + $( ":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( 2013, 12 - 1, 1 ), + "Keystroke Page Up moves date to previous month" + ); + input.datepicker( "destroy" ); + step8(); + }, 50 ); }, 100 ); } function step8() { - input - .val( "1/1/14" ) - .datepicker() - .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + 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 } ); - - TestHelpers.datepicker.equalsDate( - input.datepicker( "valueAsDate" ), - new Date( 2013, 1 - 1, 1 ), - "Keystroke Page Up + Ctrl moves date to previous year" - ); - input.datepicker( "destroy" ); - step9(); + $( ":focus" ).simulate( "keydown", { keyCode: $.ui.keyCode.PAGE_UP, altKey: true } ); + setTimeout(function() { + $( ":focus" ).simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); + TestHelpers.datepicker.equalsDate( + input.datepicker( "valueAsDate" ), + new Date( 2013, 1 - 1, 1 ), + "Keystroke Page Up + Ctrl moves date to previous year" + ); + input.datepicker( "destroy" ); + step9(); + }, 50 ); }, 100 ); } function step9() { - input - .val( "1/1/14" ) - .datepicker() - .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + 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 } ); - - TestHelpers.datepicker.equalsDate( - input.datepicker( "valueAsDate" ), - new Date( 2014, 2 - 1, 1 ), - "Keystroke Page Down moves date to next month" - ); - input.datepicker( "destroy" ); - step10(); + $( ":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" ); + step10(); + }, 50 ); }, 100 ); } function step10() { - input - .val( "1/1/14" ) - .datepicker() - .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + 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 } ); - - TestHelpers.datepicker.equalsDate( - input.datepicker( "valueAsDate" ), - new Date( 2015, 1 - 1, 1 ), - "Keystroke Page Down + Ctrl moves date to next year" - ); - input.datepicker( "destroy" ); - step11(); + $( ":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" ); + step11(); + }, 50 ); }, 100 ); } // Check for moving to short months function step11() { - input - .val( "3/31/14" ) - .datepicker() - .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + input.val( "3/31/14" ); + TestHelpers.datepicker.init( input ); + input.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); setTimeout(function() { - $( ":focus" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.PAGE_UP } ) - .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" ); - step12(); + $( ":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" ); + step12(); + }, 50 ); }, 100 ); } function step12() { - input - .val( "1/30/16" ) - .datepicker() - .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + input.val( "1/30/16" ); + 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 } ); - - TestHelpers.datepicker.equalsDate( - input.datepicker( "valueAsDate" ), - new Date( 2016, 2 - 1, 29 ), - "Keystroke Page Down and leap years" - ); - input.datepicker( "destroy" ); - start(); + $( ":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( 2016, 2 - 1, 29 ), + "Keystroke Page Down and leap years" + ); + input.datepicker( "destroy" ); + start(); + }, 50 ); }, 100 ); } From 9cf822f4418b104e2c6720de533ac2b5552b22df Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Wed, 18 Jun 2014 00:50:08 +0200 Subject: [PATCH 53/94] Datepicker tests: Fix mouse core unit tests by adding delay --- tests/unit/datepicker/datepicker_core.js | 178 +++++++++++++++-------- 1 file changed, 120 insertions(+), 58 deletions(-) diff --git a/tests/unit/datepicker/datepicker_core.js b/tests/unit/datepicker/datepicker_core.js index c041be19682..1c336157485 100644 --- a/tests/unit/datepicker/datepicker_core.js +++ b/tests/unit/datepicker/datepicker_core.js @@ -406,70 +406,132 @@ test( "ARIA", function() { expect( 0 ); }); -test( "mouse", function() { +asyncTest( "mouse", function() { expect( 10 ); - var input = $( "#datepicker" ).datepicker(), + + var input = TestHelpers.datepicker.init( $( "#datepicker" ).val( "" ) ), picker = input.datepicker( "widget" ), date = new Date(); - input.val( "" ).datepicker( "open" ); - $( ".ui-calendar-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( "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" ).datepicker( "open" ); - $( "button.ui-calendar-close", picker ).simulate( "click", {} ); - ok( input.datepicker( "valueAsDate" ) == null, "Mouse click - close" ); - - input.val( "2/4/08" ).datepicker( "refresh" ).datepicker( "open" ); - $( "button.ui-calendar-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( "refresh" ).datepicker( "open" ); - $( "a.ui-calendar-prev", picker ).simulate( "click", {} ); - $( "button.ui-calendar-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( "refresh" ).datepicker( "open" ); - $( ".ui-calendar-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( "refresh" ).datepicker( "open" ); - $( ".ui-calendar-prev", picker ).simulate( "click" ); - $( ".ui-calendar-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( "refresh" ).datepicker( "open" ); - $( ".ui-calendar-next", picker ).simulate( "click" ); - $( ".ui-calendar-calendar tbody a:contains(18)", picker ).simulate( "mousedown" ); - TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), new Date( 2008, 3 - 1, 18 ), - "Mouse click - next" ); + function step1() { + input.datepicker( "open" ); + + setTimeout(function() { + $( "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( "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" ).datepicker( "open" ); + $( "button.ui-calendar-close", picker ).simulate( "click", {} ); + ok( input.datepicker( "valueAsDate" ) == null, "Mouse click - close" ); + + input.val( "2/4/08" ).datepicker( "refresh" ).datepicker( "open" ); + $( "button.ui-calendar-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( "refresh" ).datepicker( "open" ); + $( "a.ui-calendar-prev", picker ).simulate( "click", {} ); + $( "button.ui-calendar-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( "refresh" ).datepicker( "open" ); + $( ".ui-calendar-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( "refresh" ).datepicker( "open" ); + $( ".ui-calendar-prev", picker ).simulate( "click" ); + $( ".ui-calendar-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( "refresh" ).datepicker( "open" ); + $( ".ui-calendar-next", picker ).simulate( "click" ); + $( ".ui-calendar-calendar tbody a:contains(18)", picker ).simulate( "mousedown" ); + TestHelpers.datepicker.equalsDate( + input.datepicker( "valueAsDate" ), + new Date( 2008, 3 - 1, 18 ), + "Mouse click - next" + ); + + step2(); + }, 100 ); + } // Previous/next with minimum/maximum - input.datepicker( "option", { - min: new Date( 2008, 2 - 1, 2 ), - max: new Date( 2008, 2 - 1, 26 ) - }).val( "2/4/08" ).datepicker( "open" ); - $( ".ui-calendar-prev", picker ).simulate( "click" ); - $( ".ui-calendar-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-calendar-next", picker ).simulate( "click" ); - $( ".ui-calendar-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" ); + function step2() { + input + .datepicker( "destroy" ) + .val( "3/4/08" ); + input = TestHelpers.datepicker.init( "#datepicker", { + min: new Date( 2008, 2 - 1, 2 ), + max: new Date( 2008, 2 - 1, 26 ) + }); + picker = input.datepicker( "widget" ); + input.datepicker( "open" ); + setTimeout(function() { + $( ".ui-calendar-prev", picker ).simulate( "click" ); + $( "tbody a:contains(16)", picker ).simulate( "mousedown" ); + TestHelpers.datepicker.equalsDate( + input.datepicker( "valueAsDate" ), + new Date( 2008, 2 - 1, 16 ), + "Mouse click - previous + min/max" + ); + step3(); + }, 100 ); + } + + function step3() { + input + .datepicker( "destroy" ) + .val( "1/4/08" ); + input = TestHelpers.datepicker.init( "#datepicker", { + min: new Date( 2008, 2 - 1, 2 ), + max: new Date( 2008, 2 - 1, 26 ) + }); + picker = input.datepicker( "widget" ); + input.datepicker( "open" ); + setTimeout(function() { + $( ".ui-calendar-next", picker ).simulate( "click" ); + $( "tbody a:contains(18)", picker ).simulate( "mousedown" ); + TestHelpers.datepicker.equalsDate( + input.datepicker( "valueAsDate" ), + new Date( 2008, 2 - 1, 18 ), + "Mouse click - next + min/max" + ); + start(); + }, 100 ); + } + + step1(); }); })( jQuery ); From c73fa4723b3506c409cb982f3555f6959e111491 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Wed, 18 Jun 2014 00:56:21 +0200 Subject: [PATCH 54/94] Datepicker tests: Code style --- tests/unit/datepicker/datepicker_options.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/unit/datepicker/datepicker_options.js b/tests/unit/datepicker/datepicker_options.js index f73ee569d80..6432c8eddcc 100644 --- a/tests/unit/datepicker/datepicker_options.js +++ b/tests/unit/datepicker/datepicker_options.js @@ -505,12 +505,11 @@ test( "localization", function() { test( "Ticket 7602: Stop datepicker from appearing with beforeOpen event handler", function() { expect( 3 ); - var input; - - input = TestHelpers.datepicker.init( "#datepicker", { + var input = TestHelpers.datepicker.init( "#datepicker", { beforeOpen: function() { } }); + input.datepicker( "open" ); equal( input.datepicker( "widget" ).css( "display" ), "block", "beforeOpen returns nothing" ); input.datepicker( "close" ).datepicker( "destroy" ); From 2cc638971eca5bea15f2476df645f8d3a7b15579 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Wed, 18 Jun 2014 00:57:59 +0200 Subject: [PATCH 55/94] Datepicker tests: Unify show / hide options in helper create method --- tests/unit/datepicker/datepicker_test_helpers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/datepicker/datepicker_test_helpers.js b/tests/unit/datepicker/datepicker_test_helpers.js index 23f5025b48b..f62e086b974 100644 --- a/tests/unit/datepicker/datepicker_test_helpers.js +++ b/tests/unit/datepicker/datepicker_test_helpers.js @@ -19,7 +19,7 @@ TestHelpers.datepicker = { 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" ); } From 4cfbc5ffc40186a0c82872d933eb47c50562ed75 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Wed, 18 Jun 2014 01:15:14 +0200 Subject: [PATCH 56/94] Datepicker: Fix alternate field demo --- demos/datepicker/alt-field.html | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/demos/datepicker/alt-field.html b/demos/datepicker/alt-field.html index 89463fcdad9..3ea5d1f18f1 100644 --- a/demos/datepicker/alt-field.html +++ b/demos/datepicker/alt-field.html @@ -11,14 +11,15 @@ + + diff --git a/demos/datepicker/buttonbar.html b/demos/datepicker/buttonbar.html index 446bc9fe495..fbca87eee8c 100644 --- a/demos/datepicker/buttonbar.html +++ b/demos/datepicker/buttonbar.html @@ -11,6 +11,7 @@ + diff --git a/demos/datepicker/dropdown-month-year.html b/demos/datepicker/dropdown-month-year.html index c6102917f43..40b5aa31ff8 100644 --- a/demos/datepicker/dropdown-month-year.html +++ b/demos/datepicker/dropdown-month-year.html @@ -11,6 +11,7 @@ + diff --git a/demos/datepicker/icon-trigger.html b/demos/datepicker/icon-trigger.html index 03fb91f812f..c694631e1ab 100644 --- a/demos/datepicker/icon-trigger.html +++ b/demos/datepicker/icon-trigger.html @@ -10,6 +10,7 @@ + diff --git a/demos/datepicker/localization.html b/demos/datepicker/localization.html index 61aa7c9a2da..701e5c36b66 100644 --- a/demos/datepicker/localization.html +++ b/demos/datepicker/localization.html @@ -11,6 +11,7 @@ + diff --git a/demos/datepicker/multiple-calendars.html b/demos/datepicker/multiple-calendars.html index 3d8278cd625..8ec6775a648 100644 --- a/demos/datepicker/multiple-calendars.html +++ b/demos/datepicker/multiple-calendars.html @@ -11,6 +11,7 @@ + diff --git a/demos/datepicker/other-months.html b/demos/datepicker/other-months.html index bfb3f1af36f..7db6b1b8aef 100644 --- a/demos/datepicker/other-months.html +++ b/demos/datepicker/other-months.html @@ -11,6 +11,7 @@ + diff --git a/demos/datepicker/show-week.html b/demos/datepicker/show-week.html index 321698373ce..1c90cb1d6a6 100644 --- a/demos/datepicker/show-week.html +++ b/demos/datepicker/show-week.html @@ -11,6 +11,7 @@ + From faddce606e130256cd93812504cbea2c04b9707c Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Wed, 18 Jun 2014 01:35:51 +0200 Subject: [PATCH 58/94] Calendar: Fix multiple calendar styles (follow-up) --- themes/base/calendar.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/themes/base/calendar.css b/themes/base/calendar.css index 608afed4465..f7ff0645473 100644 --- a/themes/base/calendar.css +++ b/themes/base/calendar.css @@ -110,14 +110,14 @@ /* with multiple calendars */ .ui-calendar.ui-calendar-multi { - width: 100%; + width: auto } .ui-calendar-multi .ui-calendar-group { float: left; } .ui-calendar-multi .ui-calendar-group table { width: 95%; - margin: 0 auto .4em; + margin: 0 2.5% .4em; } .ui-calendar-multi-2 .ui-calendar-group { width: 50%; From 32f099878015c4e0cf47352670dc205f4c6c3cfe Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Wed, 18 Jun 2014 01:44:13 +0200 Subject: [PATCH 59/94] Calendar: Fix German localization --- external/localization.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/external/localization.js b/external/localization.js index 98d8f813052..75a661b4b04 100644 --- a/external/localization.js +++ b/external/localization.js @@ -2767,10 +2767,10 @@ var regions = { "dateFormat": "d" }, "de": { - "closeText": "schlie\u00dfen", + "closeText": "Schlie\u00dfen", "prevText": "<zur\u00fcck", "nextText": "Vor>", - "currentText": "heute", + "currentText": "Heute", "weekHeader": "Wo", "dateFormat": "d" }, From b75b0f109f2755163b01d2e94eaa28a61744b19d Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Wed, 18 Jun 2014 01:46:16 +0200 Subject: [PATCH 60/94] Datepicker: Sort and clean up demo index --- demos/datepicker/index.html | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/demos/datepicker/index.html b/demos/datepicker/index.html index 58612fa9f49..75ecba67564 100644 --- a/demos/datepicker/index.html +++ b/demos/datepicker/index.html @@ -9,18 +9,18 @@ From ea2a10266ee3da6f87682423d72f5a657e1153f6 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Wed, 18 Jun 2014 02:05:26 +0200 Subject: [PATCH 61/94] Datepicker: Improve date formats demo --- demos/datepicker/date-formats.html | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/demos/datepicker/date-formats.html b/demos/datepicker/date-formats.html index 8c15cf5a5af..4f507631dca 100644 --- a/demos/datepicker/date-formats.html +++ b/demos/datepicker/date-formats.html @@ -17,24 +17,17 @@ From d252d9c60f4bcacc3a8ad53cdff0d170b1a42ff6 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Wed, 18 Jun 2014 02:29:11 +0200 Subject: [PATCH 63/94] Datepicker tests: Fix method test messages --- tests/unit/datepicker/datepicker_methods.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/datepicker/datepicker_methods.js b/tests/unit/datepicker/datepicker_methods.js index a4209740ea6..cf41313922a 100644 --- a/tests/unit/datepicker/datepicker_methods.js +++ b/tests/unit/datepicker/datepicker_methods.js @@ -49,12 +49,12 @@ test( "open / close", function() { input.datepicker( "open" ); ok( calendar.is( ":visible" ), "open: calendar visible" ); - equal( calendar.attr( "aria-hidden" ), "false", "open: calendar aria-disabled" ); + equal( calendar.attr( "aria-hidden" ), "false", "open: calendar aria-hidden" ); equal( calendar.attr( "aria-expanded" ), "true", "close: calendar aria-expanded" ); input.datepicker( "close" ); ok( !calendar.is( ":visible" ), "close: calendar hidden" ); - equal( calendar.attr( "aria-hidden" ), "true", "close: calendar aria-disabled" ); + equal( calendar.attr( "aria-hidden" ), "true", "close: calendar aria-hidden" ); equal( calendar.attr( "aria-expanded" ), "false", "close: calendar aria-expanded" ); }); From 7368572d30b5ff537fae1cb6358e95a0bc6c33c7 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Wed, 18 Jun 2014 02:31:31 +0200 Subject: [PATCH 64/94] Datepicker: Several minor code improvements Several minor code improvements and make suppressExpandOnFocus an internal variable --- ui/datepicker.js | 46 ++++++++++++++++++++++------------------------ 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/ui/datepicker.js b/ui/datepicker.js index 519cc477d3f..ac68de1e885 100644 --- a/ui/datepicker.js +++ b/ui/datepicker.js @@ -27,9 +27,7 @@ }(function( $ ) { var widget, - calendarOptions = [ "dateFormat", "eachDay", "max", "min", "numberOfMonths", "showWeek" ], - // TODO move this to the instance? - suppressExpandOnFocus = false; + calendarOptions = [ "dateFormat", "eachDay", "max", "min", "numberOfMonths", "showWeek" ]; widget = $.widget( "ui.datepicker", { version: "@VERSION", @@ -50,6 +48,8 @@ widget = $.widget( "ui.datepicker", { }, _create: function() { + this.suppressExpandOnFocus = false; + if ( typeof this.options.max === "string" ) { this.options.max = Globalize.parseDate( this.options.max , { pattern: "yyyy-MM-dd" } ); } @@ -93,9 +93,10 @@ widget = $.widget( "ui.datepicker", { this._setHiddenPicker(); - this.element - .attr( "aria-haspopup", "true" ) - .attr( "aria-owns", this.calendar.attr( "id" ) ); + this.element.attr({ + "aria-haspopup": true, + "aria-owns": this.calendar.attr( "id" ) + }); }, _inputEvents: { @@ -142,7 +143,7 @@ widget = $.widget( "ui.datepicker", { }, mousedown: function( event ) { if ( this.isOpen ) { - suppressExpandOnFocus = true; + this.suppressExpandOnFocus = true; this.close(); return; } @@ -150,19 +151,17 @@ widget = $.widget( "ui.datepicker", { clearTimeout( this.closeTimer ); }, focus: function( event ) { - if ( !suppressExpandOnFocus ) { + if ( !this.suppressExpandOnFocus && !this.isOpen ) { this._delay( function() { - if ( !this.isOpen ) { - this.open( event ); - } + this.open( event ); }, 1); } this._delay( function() { - suppressExpandOnFocus = false; + this.suppressExpandOnFocus = false; }, 100 ); }, blur: function() { - suppressExpandOnFocus = false; + this.suppressExpandOnFocus = false; } }, @@ -223,7 +222,7 @@ widget = $.widget( "ui.datepicker", { }, _focusTrigger: function() { - suppressExpandOnFocus = true; + this.suppressExpandOnFocus = true; this.element.focus(); }, @@ -241,14 +240,14 @@ widget = $.widget( "ui.datepicker", { } this.calendarInstance.refresh(); - this.calendar - .attr( "aria-hidden", "false" ) - .attr( "aria-expanded", "true" ) + .attr({ + "aria-hidden": false, + "aria-expanded": true + }) .show() .position( this._buildPosition() ) .hide(); - this._show( this.calendar, this.options.show ); // take trigger out of tab order to allow shift-tab to skip trigger @@ -270,9 +269,10 @@ widget = $.widget( "ui.datepicker", { }, _setHiddenPicker: function() { - this.calendar - .attr( "aria-hidden", "true" ) - .attr( "aria-expanded", "false" ); + this.calendar.attr({ + "aria-hidden": true, + "aria-expanded": false + }); }, _buildPosition: function() { @@ -305,9 +305,7 @@ widget = $.widget( "ui.datepicker", { _destroy: function() { this.calendarInstance.destroy(); this.calendar.remove(); - this.element - .removeAttr( "aria-haspopup" ) - .removeAttr( "aria-owns" ); + this.element.removeAttr( "aria-haspopup aria-owns" ); }, widget: function() { From 747994ff947a393a8b67948081d71eb22813c358 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Wed, 18 Jun 2014 02:49:30 +0200 Subject: [PATCH 65/94] Calendar: Fix hover event setting and removing --- ui/calendar.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/calendar.js b/ui/calendar.js index fc29da9027b..02fb4132c6d 100644 --- a/ui/calendar.js +++ b/ui/calendar.js @@ -73,8 +73,7 @@ return $.widget( "ui.calendar", { "keydown .ui-calendar-calendar": "_handleKeydown" }); - // TODO use hoverable (no delegation support)? convert to _on? - this.element.delegate( ".ui-calendar-header a, .ui-calendar-calendar a", "mouseenter.calendar mouseleave.calendar", function() { + this.element.on( "mouseenter.calendar mouseleave.calendar", ".ui-calendar-header a, .ui-calendar-calendar a", function() { $( this ).toggleClass( "ui-state-hover" ); }); @@ -453,6 +452,7 @@ return $.widget( "ui.calendar", { _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() From 1745d904b5823c43dcaee46f26c7d5b2e40dff39 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Thu, 19 Jun 2014 15:12:27 +0200 Subject: [PATCH 66/94] Calendar: Improve code style and clean up --- ui/calendar.js | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/ui/calendar.js b/ui/calendar.js index 02fb4132c6d..595f5e33c7e 100644 --- a/ui/calendar.js +++ b/ui/calendar.js @@ -12,7 +12,7 @@ if ( typeof define === "function" && define.amd ) { // AMD. Register as an anonymous module. - // ToDo Add globalize and $.date? + // TODO: Add globalize and $.date? define([ "jquery", "./core", @@ -30,7 +30,7 @@ return $.widget( "ui.calendar", { version: "@VERSION", options: { dateFormat: { date: "short" }, - // TODO review + // TODO: review eachDay: $.noop, max: null, min: null, @@ -65,8 +65,8 @@ return $.widget( "ui.calendar", { }, "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 + // 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 ); }, @@ -133,12 +133,12 @@ return $.widget( "ui.calendar", { }, _setActiveDescendant: function() { - var newId = this.id + "-" + this.date.day(), - newCell = $( "#" + newId ); + var id = this.id + "-" + this.date.day(); - this.grid.attr( "aria-activedescendant", newId ); - this.grid.find( ".ui-state-focus" ).removeClass( "ui-state-focus" ); - newCell.children( "a" ).addClass( "ui-state-focus" ); + this.grid + .attr( "aria-activedescendant", id ) + .removeClass( "ui-state-focus" ); + $( "#" + id + " a" ).addClass( "ui-state-focus" ); }, _createCalendar: function() { @@ -173,7 +173,7 @@ return $.widget( "ui.calendar", { 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? + // 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" : ""; @@ -305,6 +305,7 @@ return $.widget( "ui.calendar", { for ( i; i < week.days.length; i++ ) { cells += this._buildDayCell( week.days[i] ); } + return "" + cells + ""; }, @@ -344,7 +345,7 @@ return $.widget( "ui.calendar", { if ( day.today ) { classes.push( "ui-state-highlight" ); } - // ToDo Explain and document this + // TODO: Explain and document this if ( day.extraClasses ) { classes.push( day.extraClasses.split( " " ) ); } @@ -389,9 +390,7 @@ return $.widget( "ui.calendar", { }, _refreshMultiplePicker: function() { - var i = 0; - - for ( ; i < this.options.numberOfMonths; i++ ) { + 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 ); @@ -403,12 +402,6 @@ return $.widget( "ui.calendar", { $( this.element ).find( ".ui-state-focus" ).not( ":first" ).removeClass( "ui-state-focus" ); }, - _setHiddenPicker: function() { - this.element - .attr( "aria-hidden", "true" ) - .attr( "aria-expanded", "false" ); - }, - _select: function( event, time ) { this._setOption( "value", new Date( time ) ); this._trigger( "select", event ); @@ -463,6 +456,7 @@ return $.widget( "ui.calendar", { if ( arguments.length === 0 || ( arguments.length === 1 && key === "value" ) ) { this.options.value = this.date.selectedDate(); } + return this._superApply( arguments ); }, From 4dfcb79a0926dbc8457c312b849afd2c64b39247 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Thu, 19 Jun 2014 17:37:37 +0200 Subject: [PATCH 67/94] Calendar: Focus class is not removed when using arrow keys --- ui/calendar.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui/calendar.js b/ui/calendar.js index 595f5e33c7e..7e21db2dd9a 100644 --- a/ui/calendar.js +++ b/ui/calendar.js @@ -137,8 +137,9 @@ return $.widget( "ui.calendar", { this.grid .attr( "aria-activedescendant", id ) + .find( ".ui-state-focus" ) .removeClass( "ui-state-focus" ); - $( "#" + id + " a" ).addClass( "ui-state-focus" ); + $( "#" + id + " > a" ).addClass( "ui-state-focus" ); }, _createCalendar: function() { From a5acd0f704535328aa06c7bab1269a7acc00db15 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Thu, 19 Jun 2014 17:42:21 +0200 Subject: [PATCH 68/94] Datepicker: Remove unwanted CTRL+HOME shortcut --- tests/unit/datepicker/datepicker_core.js | 9 +-------- ui/datepicker.js | 11 ----------- 2 files changed, 1 insertion(+), 19 deletions(-) diff --git a/tests/unit/datepicker/datepicker_core.js b/tests/unit/datepicker/datepicker_core.js index 1c336157485..b55267aa686 100644 --- a/tests/unit/datepicker/datepicker_core.js +++ b/tests/unit/datepicker/datepicker_core.js @@ -87,7 +87,7 @@ asyncTest( "baseStructure", function() { }); test( "Keyboard handling: input", function() { - expect( 8 ); + expect( 7 ); var input = $( "#datepicker" ).datepicker(), instance = input.datepicker( "instance" ), date = new Date(); @@ -107,13 +107,6 @@ test( "Keyboard handling: input", function() { 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" ); - input .val( "" ) .datepicker( "open" ); diff --git a/ui/datepicker.js b/ui/datepicker.js index ac68de1e885..d9a6e95a724 100644 --- a/ui/datepicker.js +++ b/ui/datepicker.js @@ -123,17 +123,6 @@ widget = $.widget( "ui.datepicker", { this.calendarInstance.grid.focus( 1 ); }, 1 ); break; - case $.ui.keyCode.HOME: - if ( event.ctrlKey ) { - this.valueAsDate( new Date() ); - event.preventDefault(); - if ( this.isOpen ) { - this.calendarInstance.refresh(); - } else { - this.open( event ); - } - } - break; } }, keyup: function() { From 2bf33f58ddd58dd7321de31639a143b95469ee4b Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Thu, 19 Jun 2014 18:11:17 +0200 Subject: [PATCH 69/94] Datepicker: Rename multiple calendars demo to multiple months --- demos/datepicker/index.html | 2 +- .../{multiple-calendars.html => multiple-months.html} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename demos/datepicker/{multiple-calendars.html => multiple-months.html} (100%) diff --git a/demos/datepicker/index.html b/demos/datepicker/index.html index 75ecba67564..ec9e94788cf 100644 --- a/demos/datepicker/index.html +++ b/demos/datepicker/index.html @@ -19,7 +19,7 @@
    • Localize calendar
    • Restrict date range
    • Dates in other months
    • -
    • Display multiple months
    • +
    • Display multiple months
    • Show week of the year
    diff --git a/demos/datepicker/multiple-calendars.html b/demos/datepicker/multiple-months.html similarity index 100% rename from demos/datepicker/multiple-calendars.html rename to demos/datepicker/multiple-months.html From 2c9e7e228c9252888e2426ce43cfc08336a9dcb5 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Thu, 19 Jun 2014 18:36:57 +0200 Subject: [PATCH 70/94] Datepicker: Remove support for enter key on input --- tests/unit/datepicker/datepicker_core.js | 11 ++--------- tests/unit/datepicker/datepicker_events.js | 19 +++++-------------- ui/datepicker.js | 3 --- 3 files changed, 7 insertions(+), 26 deletions(-) diff --git a/tests/unit/datepicker/datepicker_core.js b/tests/unit/datepicker/datepicker_core.js index b55267aa686..786b89cb6df 100644 --- a/tests/unit/datepicker/datepicker_core.js +++ b/tests/unit/datepicker/datepicker_core.js @@ -87,16 +87,9 @@ asyncTest( "baseStructure", function() { }); test( "Keyboard handling: input", function() { - expect( 7 ); + expect( 6 ); var input = $( "#datepicker" ).datepicker(), - instance = input.datepicker( "instance" ), - date = new Date(); - - // Enter = Select today's date by default - input - .datepicker( "open" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); - TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), date, "Keystroke enter" ); + instance = input.datepicker( "instance" ); // Enter = Select preset date input diff --git a/tests/unit/datepicker/datepicker_events.js b/tests/unit/datepicker/datepicker_events.js index 6739f843589..aacaa2a2f6c 100644 --- a/tests/unit/datepicker/datepicker_events.js +++ b/tests/unit/datepicker/datepicker_events.js @@ -76,7 +76,7 @@ test( "open", function() { }); asyncTest( "select", function() { - expect( 6 ); + expect( 4 ); var input = TestHelpers.datepicker.init( "#datepicker", { select: function( event ) { @@ -92,15 +92,6 @@ asyncTest( "select", function() { message = ""; function step1() { - message = "on input enter"; - input - .simulate( "focus" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); - input.datepicker( "close" ); - step2(); - } - - function step2() { message = "on calendar cell click"; input .simulate( "focus" ) @@ -108,11 +99,11 @@ asyncTest( "select", function() { setTimeout(function() { widget.find( "tbody tr:first td:first a" ).simulate( "mousedown" ); input.datepicker( "close" ); - step3(); + step2(); }, 100 ); } - function step3() { + function step2() { message = "on calendar cell enter"; input .simulate( "focus" ) @@ -122,11 +113,11 @@ asyncTest( "select", function() { .simulate( "keydown", { keyCode: $.ui.keyCode.RIGHT } ) .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); input.datepicker( "close" ); - step4(); + step3(); }, 100 ); } - function step4() { + function step3() { message = "on calendar escape (not expected)"; input .simulate( "focus" ) diff --git a/ui/datepicker.js b/ui/datepicker.js index d9a6e95a724..e4424bd1597 100644 --- a/ui/datepicker.js +++ b/ui/datepicker.js @@ -112,9 +112,6 @@ widget = $.widget( "ui.datepicker", { this.close( event ); } break; - case $.ui.keyCode.ENTER: - this.calendarInstance._handleKeydown( event ); - break; case $.ui.keyCode.DOWN: case $.ui.keyCode.UP: clearTimeout( this.closeTimer ); From 7c159a8f5450b63dabe53f26451f99b6866028e3 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Thu, 19 Jun 2014 18:59:28 +0200 Subject: [PATCH 71/94] Datepicker: Improve localization handling, fix return indenting --- ui/calendar.js | 63 +++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 34 deletions(-) diff --git a/ui/calendar.js b/ui/calendar.js index 7e21db2dd9a..4b1e1859ae4 100644 --- a/ui/calendar.js +++ b/ui/calendar.js @@ -44,6 +44,7 @@ return $.widget( "ui.calendar", { _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; @@ -204,41 +205,39 @@ return $.widget( "ui.calendar", { _buildHeader: function() { return "
    " + - this._buildPreviousLink() + - this._buildNextLink() + - this._buildTitlebar() + - "
    "; + 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 + "" + - "
    "; + "
    " + + this._buildTitle() + + "
    " + + ", " + + this.labels.datePickerRole + + "" + + "
    "; }, _buildTitle: function() { @@ -260,27 +259,26 @@ return $.widget( "ui.calendar", { _buildGridHeading: function() { var cells = "", - i = 0, - labels = Globalize.translate( "datepicker" ); + i = 0; if ( this.options.showWeek ) { - cells += "" + labels.weekHeader + ""; + cells += "" + this.labels.weekHeader + ""; } for ( i; i < this.date.weekdays().length; i++ ) { cells += this._buildGridHeaderCell( this.date.weekdays()[i] ); } return "" + - "" + cells + "" + - ""; + "" + cells + "" + + ""; }, _buildGridHeaderCell: function( day ) { return "" + - "" + - day.shortname + - "" + - ""; + "" + + day.shortname + + "" + + ""; }, _buildGridBody: function() { @@ -334,7 +332,6 @@ return $.widget( "ui.calendar", { _buildDayElement: function( day, selectable ) { var classes = [ "ui-state-default" ], - labels = Globalize.translate( "datepicker" ), content = ""; if ( day === this.date && selectable ) { @@ -359,18 +356,16 @@ return $.widget( "ui.calendar", { } if ( day.today ) { - content += ", " + labels.currentText + ""; + content += ", " + this.labels.currentText + ""; } return content; }, _buildButtons: function() { - var labels = Globalize.translate( "datepicker" ); - return "
    " + - "" + - "
    "; + "" + + ""; }, // Refreshing the entire calendar during interaction confuses screen readers, specifically From 17dc9fa7351622bb8251c51cdb54b2177f0e6f4c Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Thu, 19 Jun 2014 19:51:13 +0200 Subject: [PATCH 72/94] Calendar: Fix German localization --- external/localization.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/localization.js b/external/localization.js index 75a661b4b04..4fd436aca00 100644 --- a/external/localization.js +++ b/external/localization.js @@ -2768,7 +2768,7 @@ var regions = { }, "de": { "closeText": "Schlie\u00dfen", - "prevText": "<zur\u00fcck", + "prevText": "<Zur\u00fcck", "nextText": "Vor>", "currentText": "Heute", "weekHeader": "Wo", From 0f66ab8faf20d52db8147fa668407467194b9fa0 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Thu, 19 Jun 2014 19:52:01 +0200 Subject: [PATCH 73/94] Calendar: Update localization provided by Globalize on refresh --- ui/calendar.js | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/calendar.js b/ui/calendar.js index 4b1e1859ae4..c2991d7a32c 100644 --- a/ui/calendar.js +++ b/ui/calendar.js @@ -374,6 +374,7 @@ return $.widget( "ui.calendar", { // 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 ) { From 17b48e6898793f9b9261e8dcf9b0ea5391f014de Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Thu, 19 Jun 2014 19:56:31 +0200 Subject: [PATCH 74/94] Datepicker tests: Add basic localization unit tests --- tests/unit/datepicker/datepicker_core.js | 37 ++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/tests/unit/datepicker/datepicker_core.js b/tests/unit/datepicker/datepicker_core.js index 786b89cb6df..e442115e041 100644 --- a/tests/unit/datepicker/datepicker_core.js +++ b/tests/unit/datepicker/datepicker_core.js @@ -86,6 +86,43 @@ asyncTest( "baseStructure", function() { step1(); }); +test( "Localization", function() { + expect( 10 ); + + var defaultLocale = Globalize.locale(), + input = $( "#datepicker" ), + date = new Date( 2014, 0, 1 ), + initDatepicker = function() { + input + .datepicker() + .datepicker( "valueAsDate", date ) + .datepicker( "open" ); + }, + testLocalization = function( message ) { + picker = input.datepicker( "widget" ); + + equal( picker.find( ".ui-calendar-month" ).text(), "Januar", message + "titlebar year" ); + equal( picker.find( "thead th:first" ).text(), "Mo.", message + "teader first day" ); + equal( picker.find( "thead th:last" ).text(), "So.", message + "header last day" ); + equal( picker.find( ".ui-calendar-prev" ).text(), "", message + "header next" ); + }, + picker; + + Globalize.locale( "de-DE" ); + initDatepicker(); + testLocalization( "Init: " ); + input.datepicker( "destroy" ); + + Globalize.locale( defaultLocale.locale ); + initDatepicker(); + Globalize.locale( "de-DE" ); + input.datepicker( "refresh" ); + testLocalization( "After init: " ); + + Globalize.locale( defaultLocale.locale ); +}); + test( "Keyboard handling: input", function() { expect( 6 ); var input = $( "#datepicker" ).datepicker(), From e02bc85f14dd8811813166cd5efc8f0e02a78fa1 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Thu, 19 Jun 2014 20:06:09 +0200 Subject: [PATCH 75/94] Calendar: Improve comment --- ui/calendar.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui/calendar.js b/ui/calendar.js index c2991d7a32c..f4da98f1e01 100644 --- a/ui/calendar.js +++ b/ui/calendar.js @@ -282,7 +282,8 @@ return $.widget( "ui.calendar", { }, _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. + // 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 = ""; From 74acf6510a2513224e51e0f37b92903284f271a2 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Thu, 19 Jun 2014 22:50:30 +0200 Subject: [PATCH 76/94] Calendar: Rename multiple calendars demo to multiple months --- demos/calendar/index.html | 8 ++++---- .../{multiple-calendars.html => multiple-month.html} | 0 2 files changed, 4 insertions(+), 4 deletions(-) rename demos/calendar/{multiple-calendars.html => multiple-month.html} (100%) diff --git a/demos/calendar/index.html b/demos/calendar/index.html index 48097f5983e..cfdd15a6ac5 100644 --- a/demos/calendar/index.html +++ b/demos/calendar/index.html @@ -15,10 +15,10 @@
  • Populate alternate field
  • Display inline
  • Display button bar
  • -
  • Display month & year menus
  • -
  • Dates in other months
  • -
  • Show week of the year
  • -
  • Display multiple months
  • +
  • Display month & year menus
  • +
  • Dates in other months
  • +
  • Show week of the year
  • +
  • Display multiple months
  • Icon trigger
  • Animations
  • Date Range
  • diff --git a/demos/calendar/multiple-calendars.html b/demos/calendar/multiple-month.html similarity index 100% rename from demos/calendar/multiple-calendars.html rename to demos/calendar/multiple-month.html From 0da34e2d91c907dcd5154fe69412d9220a3f5881 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Thu, 19 Jun 2014 22:52:12 +0200 Subject: [PATCH 77/94] Calendar: Sort and clean up demo index --- demos/calendar/index.html | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/demos/calendar/index.html b/demos/calendar/index.html index cfdd15a6ac5..0335beacb74 100644 --- a/demos/calendar/index.html +++ b/demos/calendar/index.html @@ -9,19 +9,14 @@ From 7d8c8b4ff817d18804d740b78240dd6e1c8d0ae7 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Thu, 19 Jun 2014 23:04:04 +0200 Subject: [PATCH 78/94] Calendar: Fix demos after widget split --- demos/calendar/buttonbar.html | 2 +- demos/calendar/date-formats.html | 27 +++++++++---------------- demos/calendar/dropdown-month-year.html | 2 +- demos/calendar/localization.html | 17 ++++++++-------- demos/calendar/multiple-month.html | 2 +- demos/calendar/other-months.html | 2 +- demos/calendar/show-week.html | 2 +- 7 files changed, 24 insertions(+), 30 deletions(-) diff --git a/demos/calendar/buttonbar.html b/demos/calendar/buttonbar.html index 77da1ab5749..10162ebf1a2 100644 --- a/demos/calendar/buttonbar.html +++ b/demos/calendar/buttonbar.html @@ -24,7 +24,7 @@ -

    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 index 95adf01fd64..33df9cacb59 100644 --- a/demos/calendar/date-formats.html +++ b/demos/calendar/date-formats.html @@ -16,24 +16,17 @@ -

    Date:   -

    +
    +

    Localize the calendar calendar language and format (English / Western formatting is the default). The calendar includes built-in support for languages that read right-to-left, such as Arabic and Hebrew.

    diff --git a/demos/calendar/multiple-month.html b/demos/calendar/multiple-month.html index 9fe2b7ab526..40cc30e2d72 100644 --- a/demos/calendar/multiple-month.html +++ b/demos/calendar/multiple-month.html @@ -25,7 +25,7 @@ -

    Date:

    +

    Set the numberOfMonths option to an integer of 2 or more to show multiple months in a single calendar.

    diff --git a/demos/calendar/other-months.html b/demos/calendar/other-months.html index 3ad1aba37d9..4e3ee3e3b88 100644 --- a/demos/calendar/other-months.html +++ b/demos/calendar/other-months.html @@ -30,7 +30,7 @@ -

    Date:

    +

    The calendar can show dates that come from other than the main month diff --git a/demos/calendar/show-week.html b/demos/calendar/show-week.html index e7fcb84957b..bb9ae4cc9b6 100644 --- a/demos/calendar/show-week.html +++ b/demos/calendar/show-week.html @@ -24,7 +24,7 @@ -

    Date:

    +

    The calendar can show the week of the year. The calculation follows From b952338ad787c94548120e561cbb9ce2b5676140 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Fri, 20 Jun 2014 00:13:20 +0200 Subject: [PATCH 79/94] Calendar: Add buttons option --- demos/calendar/buttonbar.html | 6 ++- ui/calendar.js | 70 ++++++++++++++++++++++++++++++----- 2 files changed, 65 insertions(+), 11 deletions(-) diff --git a/demos/calendar/buttonbar.html b/demos/calendar/buttonbar.html index 10162ebf1a2..235192da1f8 100644 --- a/demos/calendar/buttonbar.html +++ b/demos/calendar/buttonbar.html @@ -17,7 +17,11 @@ diff --git a/ui/calendar.js b/ui/calendar.js index f4da98f1e01..b795a01e524 100644 --- a/ui/calendar.js +++ b/ui/calendar.js @@ -29,6 +29,7 @@ return $.widget( "ui.calendar", { version: "@VERSION", options: { + buttons: [], dateFormat: { date: "short" }, // TODO: review eachDay: $.noop, @@ -60,10 +61,6 @@ return $.widget( "ui.calendar", { this.date.adjust( "M", this.options.numberOfMonths ); this.refresh(); }, - "click .ui-calendar-current": function( event ) { - event.preventDefault(); - this._select( event, new Date().getTime() ); - }, "mousedown .ui-calendar-calendar a": function( event ) { event.preventDefault(); // TODO: exclude clicks on lead days or handle them correctly @@ -148,7 +145,7 @@ return $.widget( "ui.calendar", { pickerHtml = ""; if ( this.options.numberOfMonths === 1 ) { - pickerHtml = this._buildHeader() + this._buildGrid() + this._buildButtons(); + pickerHtml = this._buildHeader() + this._buildGrid(); } else { pickerHtml = this._buildMultiplePicker(); classes += " ui-calendar-multi"; @@ -162,6 +159,8 @@ return $.widget( "ui.calendar", { }) .html( pickerHtml ); + this._createButtonPane(); + this.element.find( "button" ).button(); this.grid = this.element.find( ".ui-calendar-calendar" ); @@ -196,7 +195,6 @@ return $.widget( "ui.calendar", { } html += "

    "; - html += this._buildButtons(); this.date = currentDate; @@ -363,10 +361,58 @@ return $.widget( "ui.calendar", { return content; }, - _buildButtons: function() { - return "
    " + - "" + - "
    "; + _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-dialog-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-dialog-buttons" ); + this.buttonPane.appendTo( this.element ); + }, + + _buttonClickContext: function() { + return this.element[ 0 ]; }, // Refreshing the entire calendar during interaction confuses screen readers, specifically @@ -476,6 +522,10 @@ return $.widget( "ui.calendar", { this._super( key, value ); + if ( key === "buttons" ) { + this._createButtons(); + } + if ( key === "eachDay" ) { this.date.eachDay = value; this.refresh(); From 211c8a90b0d8254ea537d424fad4eabdb209ef7b Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Fri, 20 Jun 2014 00:15:39 +0200 Subject: [PATCH 80/94] Datepicker: Add buttons option --- demos/datepicker/buttonbar.html | 11 ++++++++++- ui/datepicker.js | 6 +++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/demos/datepicker/buttonbar.html b/demos/datepicker/buttonbar.html index fbca87eee8c..51abfeef955 100644 --- a/demos/datepicker/buttonbar.html +++ b/demos/datepicker/buttonbar.html @@ -18,7 +18,16 @@ diff --git a/ui/datepicker.js b/ui/datepicker.js index e4424bd1597..c58e4d47e4b 100644 --- a/ui/datepicker.js +++ b/ui/datepicker.js @@ -27,7 +27,7 @@ }(function( $ ) { var widget, - calendarOptions = [ "dateFormat", "eachDay", "max", "min", "numberOfMonths", "showWeek" ]; + calendarOptions = [ "buttons", "dateFormat", "eachDay", "max", "min", "numberOfMonths", "showWeek" ]; widget = $.widget( "ui.datepicker", { version: "@VERSION", @@ -91,6 +91,10 @@ widget = $.widget( "ui.datepicker", { }) ) .calendar( "instance" ); + this.calendarInstance._buttonClickContext = function() { + return that.element[ 0 ]; + }; + this._setHiddenPicker(); this.element.attr({ From 6fdcaa3ced29a2417813ded6b7f83b3067c4aa90 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Fri, 20 Jun 2014 00:23:24 +0200 Subject: [PATCH 81/94] Datepicker tests: Rework structure unit tests for buttons option --- tests/unit/datepicker/datepicker_common.js | 1 + tests/unit/datepicker/datepicker_core.js | 43 ++++++++++++++-------- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/tests/unit/datepicker/datepicker_common.js b/tests/unit/datepicker/datepicker_common.js index 4a2ece05da8..fb4f8d340fd 100644 --- a/tests/unit/datepicker/datepicker_common.js +++ b/tests/unit/datepicker/datepicker_common.js @@ -1,6 +1,7 @@ TestHelpers.commonWidgetTests( "datepicker", { defaults: { appendTo: null, + buttons: [], dateFormat: { date: "short" }, disabled: false, eachDay: $.noop, diff --git a/tests/unit/datepicker/datepicker_core.js b/tests/unit/datepicker/datepicker_core.js index e442115e041..342262d6074 100644 --- a/tests/unit/datepicker/datepicker_core.js +++ b/tests/unit/datepicker/datepicker_core.js @@ -20,9 +20,9 @@ test( "input's value determines starting date", function() { }); asyncTest( "baseStructure", function() { - expect( 23 ); + expect( 27 ); - var header, title, table, thead, week, child, + var header, title, table, thead, week, child, buttonpane, inp = TestHelpers.datepicker.initNewInput(), dp = inp.datepicker( "widget" ); @@ -33,7 +33,7 @@ asyncTest( "baseStructure", function() { ok( dp.is( ":visible" ), "Structure - datepicker visible" ); 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, 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-calendar-header" ), "Structure - header division" ); @@ -61,19 +61,39 @@ asyncTest( "baseStructure", function() { ok( week.is( "tr" ), "Structure - month table week row" ); equal( week.children().length, 7, "Structure - week child count" ); - inp.datepicker( "close" ).datepicker( "destroy" ); + inp.datepicker( "close" ); step2(); }, 50 ); } function step2() { + inp.datepicker( "option", "buttons", { + "test": function() {}, + "test button": function() {} + }); + inp.focus(); + + setTimeout(function() { + equal( dp.children().length, 3, "Structure buttons - child count (header, calendar, buttonpane)" ); + + buttonpane = dp.children( ".ui-calendar-buttonpane" ); + equal( buttonpane.children( "div.ui-calendar-buttonset" ).length, 1, "Structure buttons - buttonset" ); + equal( buttonpane.find( "button.ui-button:first" ).text(), "test", "Structure buttons - buttonset" ); + equal( buttonpane.find( "button.ui-button:eq(1)" ).text(), "test button", "Structure buttons - buttonset" ); + + inp.datepicker( "close" ).datepicker( "destroy" ); + step3(); + }, 50 ); + } + + function step3() { // Multi-month 2 inp = TestHelpers.datepicker.initNewInput({ numberOfMonths: 2 } ); dp = inp.datepicker( "widget" ); inp.focus(); setTimeout(function() { ok( dp.is( ".ui-calendar-multi" ), "Structure multi [2] - multi-month" ); - equal( dp.children().length, 4, "Structure multi [2] - child count" ); + 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" ); @@ -430,7 +450,7 @@ test( "ARIA", function() { }); asyncTest( "mouse", function() { - expect( 10 ); + expect( 9 ); var input = TestHelpers.datepicker.init( $( "#datepicker" ).val( "" ) ), picker = input.datepicker( "widget" ), @@ -477,16 +497,7 @@ asyncTest( "mouse", function() { "Mouse click - abandoned" ); - // Current/previous/next - input.val( "" ).datepicker( "refresh" ).datepicker( "open" ); - $( ".ui-calendar-current", picker ).simulate( "click", {} ); - date.setDate( new Date().getDate() ); - TestHelpers.datepicker.equalsDate( - input.datepicker( "valueAsDate" ), - date, - "Mouse click - current" - ); - + // Previous/next input.val( "2/4/08" ).datepicker( "refresh" ).datepicker( "open" ); $( ".ui-calendar-prev", picker ).simulate( "click" ); $( ".ui-calendar-calendar tbody a:contains(16)", picker ).simulate( "mousedown" ); From 4973eea2b665f7a7b38119c483d1a16a46bd4294 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Fri, 20 Jun 2014 00:26:04 +0200 Subject: [PATCH 82/94] Datepicker: Remove outdated localization tests --- tests/unit/datepicker/datepicker_options.js | 31 --------------------- 1 file changed, 31 deletions(-) diff --git a/tests/unit/datepicker/datepicker_options.js b/tests/unit/datepicker/datepicker_options.js index 6432c8eddcc..7ab21b9d4a2 100644 --- a/tests/unit/datepicker/datepicker_options.js +++ b/tests/unit/datepicker/datepicker_options.js @@ -469,37 +469,6 @@ test( "daylightSaving", function() { $( ".ui-calendar-calendar td:eq(8) a", dp).simulate( "click" ); equal(inp.val(), "11/03/2008", "Daylight saving - US 11/03/2008" ); }); - -// TODO: Move to calendar. Perhaps adda calendar_external test file? -test( "localization", 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-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(), $.datepicker.regional.fr.monthNamesShort[month], - "Localisation - month " + month); - month++; - }); - day = 1; - $( ".ui-calendar-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( "Ticket 7602: Stop datepicker from appearing with beforeOpen event handler", function() { From 6cd5b1aac576c914639f1a6d0848eb562b275781 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Fri, 20 Jun 2014 00:38:06 +0200 Subject: [PATCH 83/94] Calendar: Fix wrong class in _createButtons method --- ui/calendar.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/calendar.js b/ui/calendar.js index b795a01e524..8043b11fbd9 100644 --- a/ui/calendar.js +++ b/ui/calendar.js @@ -381,7 +381,7 @@ return $.widget( "ui.calendar", { this.buttonSet.empty(); if ( $.isEmptyObject( buttons ) || ( $.isArray( buttons ) && !buttons.length ) ) { - this.element.removeClass( "ui-dialog-buttons" ); + this.element.removeClass( "ui-calendar-buttons" ); return; } @@ -407,7 +407,7 @@ return $.widget( "ui.calendar", { .button( buttonOptions ) .appendTo( that.buttonSet ); }); - this.element.addClass( "ui-dialog-buttons" ); + this.element.addClass( "ui-calendar-buttons" ); this.buttonPane.appendTo( this.element ); }, From e087c576788947ad504bf6d0fb88f02f22b78cea Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Fri, 20 Jun 2014 00:38:39 +0200 Subject: [PATCH 84/94] Datepicker: Add option unit tests for buttons option --- tests/unit/datepicker/datepicker_options.js | 96 +++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/tests/unit/datepicker/datepicker_options.js b/tests/unit/datepicker/datepicker_options.js index 7ab21b9d4a2..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(), From 320cea072a8ed964e1f06a401ddd9d6119b9b4d1 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Fri, 20 Jun 2014 01:01:16 +0200 Subject: [PATCH 85/94] Datepicker: Fix multiple calendar styles (follow-up) --- themes/base/calendar.css | 3 ++- themes/base/datepicker.css | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/themes/base/calendar.css b/themes/base/calendar.css index f7ff0645473..5925814bbff 100644 --- a/themes/base/calendar.css +++ b/themes/base/calendar.css @@ -110,7 +110,8 @@ /* with multiple calendars */ .ui-calendar.ui-calendar-multi { - width: auto + width: auto; + display: inline-block; } .ui-calendar-multi .ui-calendar-group { float: left; diff --git a/themes/base/datepicker.css b/themes/base/datepicker.css index 4fde1fdcf56..ac84f640dee 100644 --- a/themes/base/datepicker.css +++ b/themes/base/datepicker.css @@ -8,7 +8,7 @@ * * http://api.jqueryui.com/datepicker/#theming */ -.ui-datepicker { +.ui-datepicker.ui-calendar { display: none; position: absolute; } \ No newline at end of file From 7d3d764f6cd58421a0ced26367d2a7fc48d47843 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Fri, 20 Jun 2014 01:03:19 +0200 Subject: [PATCH 86/94] Datepicker: Remove duplicate demos --- demos/datepicker/buttonbar.html | 43 --------------------- demos/datepicker/date-range.html | 46 ----------------------- demos/datepicker/dropdown-month-year.html | 35 ----------------- demos/datepicker/index.html | 7 ---- demos/datepicker/min-max.html | 39 ------------------- demos/datepicker/multiple-months.html | 35 ----------------- demos/datepicker/other-months.html | 41 -------------------- demos/datepicker/show-week.html | 36 ------------------ 8 files changed, 282 deletions(-) delete mode 100644 demos/datepicker/buttonbar.html delete mode 100644 demos/datepicker/date-range.html delete mode 100644 demos/datepicker/dropdown-month-year.html delete mode 100644 demos/datepicker/min-max.html delete mode 100644 demos/datepicker/multiple-months.html delete mode 100644 demos/datepicker/other-months.html delete mode 100644 demos/datepicker/show-week.html diff --git a/demos/datepicker/buttonbar.html b/demos/datepicker/buttonbar.html deleted file mode 100644 index 51abfeef955..00000000000 --- a/demos/datepicker/buttonbar.html +++ /dev/null @@ -1,43 +0,0 @@ - - - - - jQuery UI Datepicker - Display button bar - - - - - - - - - - - - - - - - -

    Date:

    - -
    -

    Display a button for selecting Today's date and a Done button for closing the calendar with the boolean showButtonPanel option. Each button is enabled by default when the bar is displayed, but can be turned off with additional options. Button text is customizable.

    -
    - - diff --git a/demos/datepicker/date-range.html b/demos/datepicker/date-range.html deleted file mode 100644 index a15ee5fc232..00000000000 --- a/demos/datepicker/date-range.html +++ /dev/null @@ -1,46 +0,0 @@ - - - - - jQuery UI Datepicker - Select a Date Range - - - - - - - - - - - - - - - - - - - - - -
    -

    Select the date range to search for.

    -
    - - diff --git a/demos/datepicker/dropdown-month-year.html b/demos/datepicker/dropdown-month-year.html deleted file mode 100644 index 40b5aa31ff8..00000000000 --- a/demos/datepicker/dropdown-month-year.html +++ /dev/null @@ -1,35 +0,0 @@ - - - - - jQuery UI Datepicker - Display month & year menus - - - - - - - - - - - - - - - - -

    Date:

    - -
    -

    Show month and year dropdowns in place of the static month/year header to facilitate navigation through large timeframes. Add the boolean changeMonth and changeYear options.

    -
    - - diff --git a/demos/datepicker/index.html b/demos/datepicker/index.html index ec9e94788cf..5587564831f 100644 --- a/demos/datepicker/index.html +++ b/demos/datepicker/index.html @@ -11,16 +11,9 @@
  • Default functionality
  • Populate alternate field
  • Animations
  • -
  • Display button bar
  • Format date
  • -
  • Date Range
  • -
  • Display month & year menus
  • Icon trigger
  • Localize calendar
  • -
  • Restrict date range
  • -
  • Dates in other months
  • -
  • Display multiple months
  • -
  • Show week of the year
  • diff --git a/demos/datepicker/min-max.html b/demos/datepicker/min-max.html deleted file mode 100644 index 27420af760f..00000000000 --- a/demos/datepicker/min-max.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - - jQuery UI Datepicker - Restrict date range - - - - - - - - - - - - - - - - -

    Date:

    - -
    -

    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-months.html b/demos/datepicker/multiple-months.html deleted file mode 100644 index 8ec6775a648..00000000000 --- a/demos/datepicker/multiple-months.html +++ /dev/null @@ -1,35 +0,0 @@ - - - - - jQuery UI Datepicker - Display multiple months - - - - - - - - - - - - - - - - -

    Date:

    - -
    -

    Set the numberOfMonths option to an integer of 2 or more to show multiple months in a single datepicker.

    -
    - - diff --git a/demos/datepicker/other-months.html b/demos/datepicker/other-months.html deleted file mode 100644 index 7db6b1b8aef..00000000000 --- a/demos/datepicker/other-months.html +++ /dev/null @@ -1,41 +0,0 @@ - - - - - jQuery UI Datepicker - Dates in other months - - - - - - - - - - - - - - - - -

    Date:

    - -
    -

    The datepicker can show dates that come from other than the main month - being displayed. These other dates can also be made selectable.

    -
    - - diff --git a/demos/datepicker/show-week.html b/demos/datepicker/show-week.html deleted file mode 100644 index 1c90cb1d6a6..00000000000 --- a/demos/datepicker/show-week.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - - jQuery UI Datepicker - Show week of the year - - - - - - - - - - - - - - - - -

    Date:

    - -
    -

    The datepicker can show the week of the year. The calculation follows - Unicode CLDR specification. - This means that some days from one year may be placed into weeks 'belonging' to another year.

    -
    - - From d5b87f4d358fb4188fdac8c31f3e161439bc09b8 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Fri, 20 Jun 2014 01:04:34 +0200 Subject: [PATCH 87/94] Calendar: Rename multiple calendars demo to multiple months (follow-up) --- demos/calendar/index.html | 2 +- demos/calendar/{multiple-month.html => multiple-months.html} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename demos/calendar/{multiple-month.html => multiple-months.html} (100%) diff --git a/demos/calendar/index.html b/demos/calendar/index.html index 0335beacb74..a6f0f5e7ac5 100644 --- a/demos/calendar/index.html +++ b/demos/calendar/index.html @@ -14,7 +14,7 @@
  • Display month & year menus
  • Localize calendar
  • Restrict date range
  • -
  • Display multiple months
  • +
  • Display multiple months
  • Dates in other months
  • Show week of the year
  • diff --git a/demos/calendar/multiple-month.html b/demos/calendar/multiple-months.html similarity index 100% rename from demos/calendar/multiple-month.html rename to demos/calendar/multiple-months.html From 46e2a5eecc36cb313ceebc82088652b523173a1a Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Fri, 20 Jun 2014 17:46:24 +0200 Subject: [PATCH 88/94] Calendar tests: Rewrite core unit tests based on datepicker tests Remove duplicated core unit tests from datepicker tests. --- tests/unit/calendar/calendar.html | 9 +- tests/unit/calendar/calendar_core.js | 896 ++++++------------- tests/unit/calendar/calendar_test_helpers.js | 18 +- tests/unit/datepicker/datepicker_core.js | 407 +++------ 4 files changed, 402 insertions(+), 928 deletions(-) diff --git a/tests/unit/calendar/calendar.html b/tests/unit/calendar/calendar.html index 5a5256a6bab..022dc42ded1 100644 --- a/tests/unit/calendar/calendar.html +++ b/tests/unit/calendar/calendar.html @@ -19,8 +19,7 @@ "ui/core.js", "ui/widget.js", "ui/button.js", - "ui/calendar.js", - "ui/position.js" + "ui/calendar.js" ] }); @@ -39,10 +38,8 @@
    - - - -
    +
    +
    diff --git a/tests/unit/calendar/calendar_core.js b/tests/unit/calendar/calendar_core.js index 18f00274ec3..49278345753 100644 --- a/tests/unit/calendar/calendar_core.js +++ b/tests/unit/calendar/calendar_core.js @@ -4,708 +4,388 @@ module( "calendar: core" ); TestHelpers.testJshint( "calendar" ); -test( "input's value determines starting date", function() { - expect( 3 ); +test( "baseStructure", function() { + expect( 26 ); - var input = $( "#calendar" ).val( "1/1/14" ).calendar(), - picker = input.calendar( "widget" ); - - input.calendar( "open" ); - - equal( picker.find( ".ui-calendar-month" ).html(), "January", "correct month displayed" ); - equal( picker.find( ".ui-calendar-year" ).html(), "2014", "correct year displayed" ); - equal( picker.find( ".ui-state-focus" ).html(), "1", "correct day highlighted" ); - - input.val( "" ).calendar( "destroy" ); -}); - -asyncTest( "baseStructure", function() { - expect( 42 ); - var header, title, table, thead, week, panel, inl, child, - inp = TestHelpers.calendar.initNewInput(), - dp = inp.calendar( "widget" ).find( ".ui-calendar" ); + var header, title, table, thead, week, child, buttonpane, + element = $( "#calendar" ).calendar(), + dp = element.calendar( "widget" ); function step1() { - inp.focus(); - setTimeout(function() { - ok( dp.is( ":visible" ), "Structure - calendar visible" ); - 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, 3, "Structure - child count (header, calendar, buttonpane)" ); - - 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" ); - // TODO: Preserve these class names or let the user use :first-child and :last-child? - // ok( week.children( ":first" ).is( "td.ui-calendar-week-end" ), "Structure - month table first day cell" ); - // ok( week.children( ":last" ).is( "td.ui-calendar-week-end" ), "Structure - month table second day cell" ); - - inp.calendar( "close" ).calendar( "destroy" ); - step2(); - }); - } - - function step2() { - // Editable month/year and button panel - inp = TestHelpers.calendar.initNewInput({ - changeMonth: true, - changeYear: true, - showButtonPanel: true - }); - dp = inp.calendar( "widget" ).find( ".ui-calendar" ); - inp.focus(); - setTimeout(function() { - title = dp.find( "div.ui-calendar-title" ); - // TODO: Re-add tests when changeMonth and changeYear are re-implemented - //ok( title.children( ":first" ).is( "select.ui-calendar-month" ), "Structure - month selector" ); - //ok( title.children( ":last" ).is( "select.ui-calendar-year" ), "Structure - year selector" ); - - panel = dp.children( ":last" ); - ok( panel.is( "div.ui-calendar-buttonpane" ), "Structure - button panel division" ); - equal( panel.children().length, 2, "Structure - button panel child count" ); - ok( panel.children( ":first" ).is( "button.ui-calendar-current" ), "Structure - today button" ); - ok( panel.children( ":last" ).is( "button.ui-calendar-close" ), "Structure - close button" ); - - inp.calendar( "close" ).calendar( "destroy" ); - step3(); - }); - } - - function step3() { - // Multi-month 2 - inp = TestHelpers.calendar.initNewInput({ numberOfMonths: 2 } ); - dp = inp.calendar( "widget" ).find( ".ui-calendar" ); - inp.focus(); - setTimeout(function() { - ok( dp.is( ".ui-calendar-multi" ), "Structure multi [2] - multi-month" ); - equal( dp.children().length, 4, "Structure multi [2] - child count" ); - - child = dp.children( ":first" ); - // TODO: Implement ui-calendar-group-first class name - // ok( child.is( "div.ui-calendar-group" ) && child.is( "div.ui-calendar-group-first" ), "Structure multi [2] - first month division" ); - - child = dp.children( ":eq(1)" ); - // TODO: Implement ui-calendar-group-last class name - // ok( child.is( "div.ui-calendar-group" ) && child.is( "div.ui-calendar-group-last" ), "Structure multi [2] - second month division" ); - - child = dp.children( ":eq(2)" ); - ok( child.is( "div.ui-calendar-row-break" ), "Structure multi [2] - row break" ); - ok( dp.is( ".ui-calendar-multi-2" ), "Structure multi [2] - multi-2" ); - - inp.calendar( "close" ).calendar( "destroy" ); - step4(); - }); - } - - function step4() { - // Multi-month 3 - inp = TestHelpers.calendar.initNewInput({ numberOfMonths: 3 } ); - dp = inp.calendar( "widget" ).find( ".ui-calendar" ); - inp.focus(); - setTimeout(function() { - ok( dp.is( ".ui-calendar-multi-3" ), "Structure multi [3] - multi-3" ); - ok( !dp.is( ".ui-calendar-multi-2" ), "Structure multi [3] - Trac #6704" ); - - inp.calendar( "close" ).calendar( "destroy" ); - step5(); - }); - } - - function step5() { - // Multi-month [2, 2] - inp = TestHelpers.calendar.initNewInput({ numberOfMonths: [ 2, 2 ] } ); - dp = inp.calendar( "widget" ).find( ".ui-calendar" ); - inp.focus(); - setTimeout(function() { - /* - TODO: Re-add after array form of the numberOfMonths option is implemented. - ok( dp.is( ".ui-calendar-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-calendar-group" ) && child.is( "div.ui-calendar-group-first" ), "Structure multi [2,2] - first month division" ); - - child = dp.children( ":eq(1)" ); - ok( child.is( "div.ui-calendar-group" ) && child.is( "div.ui-calendar-group-last" ), "Structure multi [2,2] - second month division" ); - - child = dp.children( ":eq(2)" ); - ok( child.is( "div.ui-calendar-row-break" ), "Structure multi [2,2] - row break" ); - - child = dp.children( ":eq(3)" ); - ok( child.is( "div.ui-calendar-group" ) && child.is( "div.ui-calendar-group-first" ), "Structure multi [2,2] - third month division" ); - - child = dp.children( ":eq(4)" ); - ok( child.is( "div.ui-calendar-group" ) && child.is( "div.ui-calendar-group-last" ), "Structure multi [2,2] - fourth month division" ); - - child = dp.children( ":eq(5)" ); - ok( child.is( "div.ui-calendar-row-break" ), "Structure multi [2,2] - row break" ); - */ - inp.calendar( "close" ).calendar( "destroy" ); - step6(); - }); - } - - function step6() { - // Inline - inl = TestHelpers.calendar.init( "#inline" ); - dp = inl.children(); - - ok( dp.is( ".ui-calendar-inline" ), "Structure inline - main div" ); - ok( !dp.is( ".ui-calendar-rtl" ), "Structure inline - not right-to-left" ); - ok( !dp.is( ".ui-calendar-multi" ), "Structure inline - not multi-month" ); - equal( dp.children().length, 3, "Structure inline - child count (header, calendar, buttonpane)" ); + 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 inline - header division" ); - equal( header.children().length, 3, "Structure inline - header child count" ); - - table = dp.children( ":eq(1)" ); - ok( table.is( "table.ui-calendar-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.calendar( "destroy" ); - - step7(); - } - - function step7() { - // Inline multi-month - inl = TestHelpers.calendar.init( "#inline", { numberOfMonths: 2 } ); - dp = inl.calendar( "widget" ).find( ".ui-calendar" ); - - ok( dp.is( ".ui-calendar-inline" ) && dp.is( ".ui-calendar-multi" ), "Structure inline multi - main div" ); - equal( dp.children().length, 4, "Structure inline multi - child count" ); - - child = dp.children( ":first" ); - // TODO: Implement ui-calendar-group-first class name - // ok( child.is( "div.ui-calendar-group" ) && child.is( "div.ui-calendar-group-first" ), "Structure inline multi - first month division" ); - - child = dp.children( ":eq(1)" ); - // TODO: Implement ui-calendar-group-last class name - // ok( child.is( "div.ui-calendar-group" ) && child.is( "div.ui-calendar-group-last" ), "Structure inline multi - second month division" ); - - child = dp.children( ":eq(2)" ); - ok( child.is( "div.ui-calendar-row-break" ), "Structure inline multi - row break" ); - - inl.calendar( "destroy" ); - start(); - } - - step1(); -}); + 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" ); -// Skip these tests for now as none are implemented yet. -/* -asyncTest( "customStructure", function() { - expect( 0 ); + 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" ); - var header, panel, title, - inp = TestHelpers.calendar.initNewInput(), - dp = inp.calendar( "widget" ).find( ".ui-calendar" ); + 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" ); - start(); + 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" ); - function step1() { - Globalize.culture( "he" ); - inp.focus(); + 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" ); - setTimeout(function() { - ok( dp.is( ".ui-calendar-rtl" ), "Structure RTL - right-to-left" ); - - header = dp.children( ":first" ); - ok( header.is( "div.ui-calendar-header" ), "Structure RTL - header division" ); - equal( header.children().length, 3, "Structure RTL - header child count" ); - ok( header.children( ":first" ).is( "a.ui-calendar-next" ), "Structure RTL - prev link" ); - ok( header.children( ":eq(1)" ).is( "a.ui-calendar-prev" ), "Structure RTL - next link" ); - - panel = dp.children( ":last" ); - ok( panel.is( "div.ui-calendar-buttonpane" ), "Structure RTL - button division" ); - equal( panel.children().length, 2, "Structure RTL - button panel child count" ); - ok( panel.children( ":first" ).is( "button.ui-calendar-close" ), "Structure RTL - close button" ); - ok( panel.children( ":last" ).is( "button.ui-calendar-current" ), "Structure RTL - today button" ); - - inp.calendar( "close" ).calendar( "destroy" ); - Globalize.culture( "en-US" ); - step2(); - }); + step2(); } - // Hide prev/next - // TODO: If we decide the hideIfNoPrevNext option is being removed these tests can be as well. - function stepX() { - inp = TestHelpers.calendar.initNewInput({ - hideIfNoPrevNext: true, - minDate: new Date( 2008, 2 - 1, 4 ), - maxDate: new Date( 2008, 2 - 1, 14 ) - }); - inp.val( "02/10/2008" ); - - TestHelpers.calendar.onFocus( inp, function() { - header = dp.children( ":first" ); - ok( header.is( "div.ui-calendar-header" ), "Structure hide prev/next - header division" ); - equal( header.children().length, 1, "Structure hide prev/next - links child count" ); - ok( header.children( ":first" ).is( "div.ui-calendar-title" ), "Structure hide prev/next - title division" ); - - inp.calendar( "hide" ).calendar( "destroy" ); - step3(); - }); - } - - // Changeable Month with read-only year function step2() { - inp = TestHelpers.calendar.initNewInput({ changeMonth: true } ); - dp = inp.calendar( "widget" ).find( ".ui-calendar" ); + element.calendar( "option", "buttons", { + "test": function() {}, + "test button": function() {} + }); - inp.focus(); - setTimeout(function() { - title = dp.children( ":first" ).children( ":last" ); + equal( dp.children().length, 3, "Structure buttons - child count (header, calendar, buttonpane)" ); - // TODO: Implement changeMonth option - // equal( title.children().length, 2, "Structure changeable month - title child count" ); - // ok( title.children( ":first" ).is( "select.ui-calendar-month" ), "Structure changeable month - month selector" ); - // ok( title.children( ":last" ).is( "span.ui-calendar-year" ), "Structure changeable month - read-only year" ); + 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.calendar( "close" ).calendar( "destroy" ); - step3(); - }); + element.calendar( "destroy" ); + step3(); } - // Changeable year with read-only month function step3() { - inp = TestHelpers.calendar.initNewInput({ changeYear: true } ); + // Multi-month 2 + element = $( "#calendar" ).calendar( { numberOfMonths: 2 } ); + dp = element.calendar( "widget" ); - TestHelpers.calendar.onFocus( inp, function() { - title = dp.children( ":first" ).children( ":last" ); + ok( dp.is( ".ui-calendar-multi" ), "Structure multi [2] - multi-month" ); + equal( dp.children().length, 3, "Structure multi [2] - child count" ); - // TODO: Implement changeYear option - // equal( title.children().length, 2, "Structure changeable year - title child count" ); - // ok( title.children( ":first" ).is( "span.ui-calendar-month" ), "Structure changeable year - read-only month" ); - // ok( title.children( ":last" ).is( "select.ui-calendar-year" ), "Structure changeable year - year selector" ); + child = dp.children( ":eq(2)" ); + ok( child.is( "div.ui-calendar-row-break" ), "Structure multi [2] - row break" ); - inp.calendar( "close" ).calendar( "destroy" ); - start(); - }); + element.calendar( "destroy" ); } - // TODO: figure out why this setTimeout is needed in IE, - // it only is necessary when the previous baseStructure tests runs first - // Support: IE - setTimeout( step1 ); + step1(); }); -*/ - -test( "Keyboard handling", function() { - expect( 9 ); - var input = $( "#calendar" ).calendar(), - instance = input.calendar( "instance" ), - date = new Date(); - input.calendar( "open" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); - TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), date, "Keystroke enter" ); - - // Enter = Select today's date by default - input.val( "1/1/14" ).calendar( "open" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); - TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), new Date( 2014, 0, 1 ), - "Keystroke enter - preset" ); - - // Control + Home = Change the calendar to the current month - input.val( "1/1/14" ).calendar( "open" ) - .simulate( "keydown", { ctrlKey: true, keyCode: $.ui.keyCode.HOME } ) - .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); - TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), date, "Keystroke ctrl+home" ); - - // Control + End = Close the calendar and clear the input - input.val( "1/1/14" ).calendar( "open" ) - .simulate( "keydown", { ctrlKey: true, keyCode: $.ui.keyCode.END } ); - equal( input.val(), "", "Keystroke ctrl+end" ); - - input.val( "" ).calendar( "open" ); - ok( instance.isOpen, "calendar is open before escape" ); - input.simulate( "keydown", { keyCode: $.ui.keyCode.ESCAPE } ); - ok( !instance.isOpen, "escape closes the calendar" ); - - input.val( "1/1/14" ).calendar( "open" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.ESCAPE } ); - TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), new Date( 2014, 0, 1 ), - "Keystroke esc - preset" ); - - input.val( "1/1/14" ).calendar( "open" ) - .simulate( "keydown", { ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP } ) - .simulate( "keydown", { keyCode: $.ui.keyCode.ESCAPE } ); - TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), new Date( 2014, 0, 1 ), - "Keystroke esc - abandoned" ); - - input.val( "1/2/14" ) - .simulate( "keyup" ); - TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), new Date( 2014, 0, 2 ), - "Picker updated as user types into input" ); - - input.calendar( "destroy" ); +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( 14 ); - var picker, - input = $( "#calendar" ), - date = new Date(); + expect( 10 ); + + var element = $( "#calendar" ); function step1() { - input.calendar(); - picker = input.calendar( "widget" ); - ok( !picker.is( ":visible" ), "calendar closed" ); - input.val( "" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + element.calendar({ value: new Date( 2014, 1 - 1, 1 ) }); + TestHelpers.calendar.focusGrid( element ).simulate( "keydown", { keyCode: $.ui.keyCode.LEFT } ); setTimeout(function() { - ok( picker.is( ":visible" ), "Keystroke down opens calendar" ); - input.calendar( "destroy" ); + $( ":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() { - input.calendar(); - picker = input.calendar( "widget" ); - ok( !picker.is( ":visible" ), "calendar closed" ); - input.val( "" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.UP } ); - - setTimeout(function() { - ok( picker.is( ":visible" ), "Keystroke up opens calendar" ); - input.calendar( "destroy" ); - step3(); - }); + 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() { - input.calendar() - .val( "1/1/14" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + 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.LEFT } ) - .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); - date = new Date( 2013, 12 - 1, 31 ); - TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), date, - "Keystroke left to switch to previous day" ); - - input.calendar( "destroy" ); + $( ":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(); - }, 100 ); + }, 50 ); } function step4() { - input.calendar() - .val( "1/1/14" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + 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.RIGHT } ) - .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); - date = new Date( 2014, 1 - 1, 2 ); - TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), date, - "Keystroke right to switch to next day" ); - - input.calendar( "destroy" ); + $( ":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(); - }, 100 ); + }, 50 ); } function step5() { - input.calendar() - .val( "1/1/14" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + 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.UP } ) - .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); - date = new Date( 2013, 12 - 1, 25 ); - TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), date, - "Keystroke up to move to the previous week" ); - - input.calendar( "destroy" ); + $( ":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(); - }, 100 ); + }, 50 ); } function step6() { - input.calendar() - .val( "1/1/14" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + 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.DOWN } ) - .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); - date = new Date( 2014, 1 - 1, 8 ); - TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), date, - "Keystroke down to move to the next week" ); - - input.calendar( "destroy" ); + $( ":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(); - }, 100 ); + }, 50 ); } function step7() { - input.calendar() - .val( "1/1/14" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + 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.PAGE_UP } ) - .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); - date = new Date( 2013, 12 - 1, 1 ); - TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), date, - "Keystroke Page Up moves date to previous month" ); - - input.calendar( "destroy" ); + $( ":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(); - }, 100 ); + }, 50 ); } function step8() { - input.calendar() - .val( "1/1/14" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + 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.PAGE_UP, altKey: true } ) - .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); - date = new Date( 2013, 1 - 1, 1 ); - TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), date, - "Keystroke Page Up + Ctrl moves date to previous year" ); - - input.calendar( "destroy" ); + $( ":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(); - }, 100 ); + }, 50 ); } + // Check for moving to short months function step9() { - input.calendar() - .val( "1/1/14" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + 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.PAGE_DOWN } ) - .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); - date = new Date( 2014, 2 - 1, 1 ); - TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), date, - "Keystroke Page Down moves date to next month" ); - - input.calendar( "destroy" ); + $( ":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(); - }, 100 ); + }, 50 ); } function step10() { - input.calendar() - .val( "1/1/14" ) - .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.calendar.equalsDate( input.calendar( "valueAsDate" ), date, - "Keystroke Page Down + Ctrl moves date to next year" ); - - input.calendar( "destroy" ); - step11(); - }, 100 ); - } - - // Check for moving to short months - function step11() { - input.calendar() - .val( "3/31/14" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + 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.PAGE_UP } ) - .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); - date = new Date( 2014, 2 - 1, 28 ); - TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), date, - "Keystroke Page Up and short months" ); - - input.calendar( "destroy" ); - step12(); - }, 100 ); - } - - function step12() { - input.calendar() - .val( "1/30/16" ) - .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.calendar.equalsDate( input.calendar( "valueAsDate" ), date, - "Keystroke Page Down and leap years" ); - - input.calendar( "destroy" ); + $( ":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(); - }, 100 ); + }, 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.calendar.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.calendar.equalsDate( input.calendar( "valueAsDate" ), new Date( 2008, 4 - 1, 4 ), - "Keystroke pgdn step 2" ); -*/ - -test( "mouse", function() { - expect( 13 ); - var input = $( "#calendar" ).calendar(), - picker = input.calendar( "widget" ), - inline = $( "#inline" ).calendar, + // 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(); - input.val( "" ).calendar( "open" ); - $( ".ui-calendar-calendar tbody a:contains(10)", picker ).simulate( "mousedown", {} ); - date.setDate( 10 ); - TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), date, "Mouse click" ); - - input.val( "2/4/08" ).calendar( "open" ); - $( ".ui-calendar-calendar tbody a:contains(12)", picker ).simulate( "mousedown", {} ); - TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), new Date( 2008, 2 - 1, 12 ), - "Mouse click - preset" ) ; - - input.val( "" ).calendar( "open" ); - $( "button.ui-calendar-close", picker ).simulate( "click", {} ); - ok( input.calendar( "valueAsDate" ) == null, "Mouse click - close" ); - - input.val( "2/4/08" ).calendar( "open" ); - $( "button.ui-calendar-close", picker ).simulate( "click", {} ); - TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), new Date( 2008, 2 - 1, 4 ), - "Mouse click - close + preset" ); - - input.val( "2/4/08" ).calendar( "open" ); - $( "a.ui-calendar-prev", picker ).simulate( "click", {} ); - $( "button.ui-calendar-close", picker ).simulate( "click", {} ); - TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), new Date( 2008, 2 - 1, 4 ), - "Mouse click - abandoned" ); - - // Current/previous/next - input.val( "" ).calendar( "open" ); - $( ".ui-calendar-current", picker ).simulate( "click", {} ); - date.setDate( new Date().getDate() ); - TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), date, "Mouse click - current" ); - - input.val( "2/4/08" ).calendar( "open" ); - $( ".ui-calendar-prev", picker ).simulate( "click" ); - $( ".ui-calendar-calendar tbody a:contains(16)", picker ).simulate( "mousedown" ); - TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), new Date( 2008, 1 - 1, 16 ), - "Mouse click - previous" ); - - input.val( "2/4/08" ).calendar( "open" ); - $( ".ui-calendar-next", picker ).simulate( "click" ); - $( ".ui-calendar-calendar tbody a:contains(18)", picker ).simulate( "mousedown" ); - TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), new Date( 2008, 3 - 1, 18 ), - "Mouse click - next" ); - - /* - // TODO: Re-add when min and max options are introduced. + 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 - input.calendar( "option", { - minDate: new Date( 2008, 2 - 1, 2 ), - maxDate: new Date( 2008, 2 - 1, 26 ) - }).val( "2/4/08" ).calendar( "open" ); - $( ".ui-calendar-prev", picker ).simulate( "click" ); - $( ".ui-calendar-calendar tbody a:contains(16)", picker ).simulate( "mousedown" ); - TestHelpers.calendar.equalsDate( input.calendar( "valueAsDate" ), new Date( 2008, 2 - 1, 16 ), - "Mouse click - previous + min/max" ); - - input.val( "2/4/08" ).calendar( "open" ); - $( ".ui-calendar-next", picker ).simulate( "click" ); - $( ".ui-calendar-calendar tbody a:contains(18)", picker ).simulate( "mousedown" ); - TestHelpers.calendar.equalsDate(input.calendar( "valueAsDate" ), new Date( 2008, 2 - 1, 18 ), - "Mouse click - next + min/max" ); - */ - - // Inline - inline = TestHelpers.calendar.init( "#inline" ); - picker = $( ".ui-calendar-inline", inline ); - date = new Date(); - inline.calendar( "valueAsDate", date ); - $( ".ui-calendar-calendar tbody a:contains(10)", picker ).simulate( "mousedown", {} ); - date.setDate( 10 ); - TestHelpers.calendar.equalsDate( inline.calendar( "valueAsDate" ), date, "Mouse click inline" ); - - inline.calendar( "option", { showButtonPanel: true } ) - .calendar( "valueAsDate", new Date( 2008, 2 - 1, 4 )); - $( ".ui-calendar-calendar tbody a:contains(12)", picker ).simulate( "mousedown", {} ); - TestHelpers.calendar.equalsDate( inline.calendar( "valueAsDate" ), new Date( 2008, 2 - 1, 12 ), - "Mouse click inline - preset" ); - - inline.calendar( "option", { showButtonPanel: true } ); - $( ".ui-calendar-current", picker ).simulate( "click", {} ); - $( ".ui-calendar-calendar tbody a:contains(14)", picker ).simulate( "mousedown", {} ); - date.setDate( 14 ); - TestHelpers.calendar.equalsDate( inline.calendar( "valueAsDate" ), date, "Mouse click inline - current" ); - - inline.calendar( "valueAsDate", new Date( 2008, 2 - 1, 4) ); - $( ".ui-calendar-prev", picker ).simulate( "click" ); - $( ".ui-calendar-calendar tbody a:contains(16)", picker ).simulate( "mousedown" ); - TestHelpers.calendar.equalsDate( inline.calendar( "valueAsDate" ), new Date( 2008, 1 - 1, 16 ), - "Mouse click inline - previous" ); - - inline.calendar( "valueAsDate", new Date( 2008, 2 - 1, 4) ); - $( ".ui-calendar-next", picker ).simulate( "click" ); - $( ".ui-calendar-calendar tbody a:contains(18)", picker ).simulate( "mousedown" ); - TestHelpers.calendar.equalsDate( inline.calendar( "valueAsDate" ), new Date( 2008, 3 - 1, 18 ), - "Mouse click inline - next" ); - - input.calendar( "destroy" ); - inline.calendar( "destroy" ); + 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_test_helpers.js b/tests/unit/calendar/calendar_test_helpers.js index fa53c408fb6..032a2227ac6 100644 --- a/tests/unit/calendar/calendar_test_helpers.js +++ b/tests/unit/calendar/calendar_test_helpers.js @@ -14,15 +14,11 @@ TestHelpers.calendar = { d2 = new Date( d2.getFullYear(), d2.getMonth(), d2.getDate() ); equal( d1.toString(), d2.toString(), message ); }, - init: function( id, options ) { - options = $.extend( { show: false }, options || {} ); - return $( id ).calendar( options ); - }, - initNewInput: function( options ) { - options = $.extend( { show: false }, options || {} ); - return $( "" ).calendar( options ) - .appendTo( "#qunit-fixture" ); - }, - onFocus: TestHelpers.onFocus, - PROP_NAME: "calendar" + 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/datepicker/datepicker_core.js b/tests/unit/datepicker/datepicker_core.js index 342262d6074..71ac0d9cf73 100644 --- a/tests/unit/datepicker/datepicker_core.js +++ b/tests/unit/datepicker/datepicker_core.js @@ -20,9 +20,9 @@ test( "input's value determines starting date", function() { }); asyncTest( "baseStructure", function() { - expect( 27 ); + expect( 15 ); - var header, title, table, thead, week, child, buttonpane, + var header, title, table, child, buttonpane, inp = TestHelpers.datepicker.initNewInput(), dp = inp.datepicker( "widget" ); @@ -31,35 +31,19 @@ asyncTest( "baseStructure", function() { setTimeout(function() { ok( dp.is( ":visible" ), "Structure - datepicker visible" ); - 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" ); inp.datepicker( "close" ); step2(); @@ -106,94 +90,10 @@ asyncTest( "baseStructure", function() { step1(); }); -test( "Localization", function() { +asyncTest( "Keyboard handling: input", function() { expect( 10 ); - - var defaultLocale = Globalize.locale(), - input = $( "#datepicker" ), - date = new Date( 2014, 0, 1 ), - initDatepicker = function() { - input - .datepicker() - .datepicker( "valueAsDate", date ) - .datepicker( "open" ); - }, - testLocalization = function( message ) { - picker = input.datepicker( "widget" ); - - equal( picker.find( ".ui-calendar-month" ).text(), "Januar", message + "titlebar year" ); - equal( picker.find( "thead th:first" ).text(), "Mo.", message + "teader first day" ); - equal( picker.find( "thead th:last" ).text(), "So.", message + "header last day" ); - equal( picker.find( ".ui-calendar-prev" ).text(), "", message + "header next" ); - }, - picker; - - Globalize.locale( "de-DE" ); - initDatepicker(); - testLocalization( "Init: " ); - input.datepicker( "destroy" ); - - Globalize.locale( defaultLocale.locale ); - initDatepicker(); - Globalize.locale( "de-DE" ); - input.datepicker( "refresh" ); - testLocalization( "After init: " ); - - Globalize.locale( defaultLocale.locale ); -}); - -test( "Keyboard handling: input", function() { - expect( 6 ); var input = $( "#datepicker" ).datepicker(), - instance = input.datepicker( "instance" ); - - // Enter = Select preset date - input - .val( "1/1/14" ) - .datepicker( "refresh" ) - .datepicker( "open" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); - TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), new Date( 2014, 0, 1 ), - "Keystroke enter - preset" ); - - input - .val( "" ) - .datepicker( "open" ); - ok( instance.isOpen, "datepicker is open before escape" ); - - input.simulate( "keydown", { keyCode: $.ui.keyCode.ESCAPE } ); - ok( !instance.isOpen, "escape closes the datepicker" ); - - input - .val( "1/1/14" ) - .datepicker( "open" ) - .simulate( "keydown", { keyCode: $.ui.keyCode.ESCAPE } ); - TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), new Date( 2014, 0, 1 ), - "Keystroke esc - preset" ); - - input - .val( "1/1/14" ) - .datepicker( "open" ) - .simulate( "keydown", { ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP } ) - .simulate( "keydown", { keyCode: $.ui.keyCode.ESCAPE } ); - TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), new Date( 2014, 0, 1 ), - "Keystroke esc - abandoned" ); - - input - .val( "1/2/14" ) - .simulate( "keyup" ); - TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), new Date( 2014, 0, 2 ), - "Picker updated as user types into input" ); - - input.datepicker( "destroy" ); -}); - -asyncTest( "keyboard handling: calendar", function() { - expect( 14 ); - - var picker, - input = $( "#datepicker" ); + picker, instance; function step1() { TestHelpers.datepicker.init( input ); @@ -224,6 +124,60 @@ asyncTest( "keyboard handling: calendar", function() { } function step3() { + TestHelpers.datepicker.init( input ); + instance = input.datepicker( "instance" ); + + // Enter = Select preset date + input + .val( "1/1/14" ) + .datepicker( "refresh" ) + .datepicker( "open" ) + .simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); + TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), new Date( 2014, 0, 1 ), + "Keystroke enter - preset" ); + + input + .val( "" ) + .datepicker( "open" ); + ok( instance.isOpen, "datepicker is open before escape" ); + + input.simulate( "keydown", { keyCode: $.ui.keyCode.ESCAPE } ); + ok( !instance.isOpen, "escape closes the datepicker" ); + + input + .val( "1/1/14" ) + .datepicker( "open" ) + .simulate( "keydown", { keyCode: $.ui.keyCode.ESCAPE } ); + TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), new Date( 2014, 0, 1 ), + "Keystroke esc - preset" ); + + input + .val( "1/1/14" ) + .datepicker( "open" ) + .simulate( "keydown", { ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP } ) + .simulate( "keydown", { keyCode: $.ui.keyCode.ESCAPE } ); + TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), new Date( 2014, 0, 1 ), + "Keystroke esc - abandoned" ); + + input + .val( "1/2/14" ) + .simulate( "keyup" ); + TestHelpers.datepicker.equalsDate( input.datepicker( "valueAsDate" ), new Date( 2014, 0, 2 ), + "Picker updated as user types into input" ); + + input.datepicker( "destroy" ); + start(); + } + + step1(); +}); + +asyncTest( "keyboard handling: calendar", function() { + expect( 7 ); + + var input = $( "#datepicker" ); + + function step1() { input.val( "1/1/14" ); TestHelpers.datepicker.init( input ); input.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); @@ -238,12 +192,12 @@ asyncTest( "keyboard handling: calendar", function() { "Keystroke left to switch to previous day" ); input.datepicker( "destroy" ); - step4(); + step2(); }, 50 ); }, 100 ); } - function step4() { + function step2() { input.val( "1/1/14" ); TestHelpers.datepicker.init( input ); input.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); @@ -259,11 +213,11 @@ asyncTest( "keyboard handling: calendar", function() { "Keystroke right to switch to next day" ); input.datepicker( "destroy" ); - step5(); + step3(); }, 100 ); } - function step5() { + function step3() { input.val( "1/1/14" ); TestHelpers.datepicker.init( input ); input.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); @@ -278,12 +232,12 @@ asyncTest( "keyboard handling: calendar", function() { "Keystroke up to move to the previous week" ); input.datepicker( "destroy" ); - step6(); + step4(); }, 50 ); }, 100 ); } - function step6() { + function step4() { input.val( "1/1/14" ); TestHelpers.datepicker.init( input ); input.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); @@ -299,52 +253,12 @@ asyncTest( "keyboard handling: calendar", function() { "Keystroke down to move to the next week" ); input.datepicker( "destroy" ); - step7(); - }, 50 ); - }, 100 ); - } - - function step7() { - 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 } ); - setTimeout(function() { - $( ":focus" ).simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); - TestHelpers.datepicker.equalsDate( - input.datepicker( "valueAsDate" ), - new Date( 2013, 12 - 1, 1 ), - "Keystroke Page Up moves date to previous month" - ); - input.datepicker( "destroy" ); - step8(); - }, 50 ); - }, 100 ); - } - - function step8() { - 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 } ); - setTimeout(function() { - $( ":focus" ).simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); - TestHelpers.datepicker.equalsDate( - input.datepicker( "valueAsDate" ), - new Date( 2013, 1 - 1, 1 ), - "Keystroke Page Up + Ctrl moves date to previous year" - ); - input.datepicker( "destroy" ); - step9(); + step5(); }, 50 ); }, 100 ); } - function step9() { + function step5() { input.val( "1/1/14" ); TestHelpers.datepicker.init( input ); input.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); @@ -359,12 +273,12 @@ asyncTest( "keyboard handling: calendar", function() { "Keystroke Page Down moves date to next month" ); input.datepicker( "destroy" ); - step10(); + step6(); }, 50 ); }, 100 ); } - function step10() { + function step6() { input.val( "1/1/14" ); TestHelpers.datepicker.init( input ); input.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); @@ -379,13 +293,13 @@ asyncTest( "keyboard handling: calendar", function() { "Keystroke Page Down + Ctrl moves date to next year" ); input.datepicker( "destroy" ); - step11(); + step7(); }, 50 ); }, 100 ); } // Check for moving to short months - function step11() { + function step7() { input.val( "3/31/14" ); TestHelpers.datepicker.init( input ); input.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); @@ -400,26 +314,6 @@ asyncTest( "keyboard handling: calendar", function() { "Keystroke Page Up and short months" ); input.datepicker( "destroy" ); - step12(); - }, 50 ); - }, 100 ); - } - - function step12() { - input.val( "1/30/16" ); - TestHelpers.datepicker.init( input ); - input.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); - - setTimeout(function() { - $( ":focus" ).simulate( "keydown", { keyCode: $.ui.keyCode.PAGE_DOWN } ); - setTimeout(function() { - $( ":focus" ).simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); - TestHelpers.datepicker.equalsDate( - input.datepicker( "valueAsDate" ), - new Date( 2016, 2 - 1, 29 ), - "Keystroke Page Down and leap years" - ); - input.datepicker( "destroy" ); start(); }, 50 ); }, 100 ); @@ -428,144 +322,51 @@ asyncTest( "keyboard handling: calendar", function() { 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" ); -*/ - // TODO: implement test( "ARIA", function() { expect( 0 ); }); asyncTest( "mouse", function() { - expect( 9 ); + expect( 4 ); var input = TestHelpers.datepicker.init( $( "#datepicker" ).val( "" ) ), - picker = input.datepicker( "widget" ), - date = new Date(); - - function step1() { - input.datepicker( "open" ); - - setTimeout(function() { - $( "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( "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" ).datepicker( "open" ); - $( "button.ui-calendar-close", picker ).simulate( "click", {} ); - ok( input.datepicker( "valueAsDate" ) == null, "Mouse click - close" ); - - input.val( "2/4/08" ).datepicker( "refresh" ).datepicker( "open" ); - $( "button.ui-calendar-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( "refresh" ).datepicker( "open" ); - $( "a.ui-calendar-prev", picker ).simulate( "click", {} ); - $( "button.ui-calendar-close", picker ).simulate( "click", {} ); - TestHelpers.datepicker.equalsDate( - input.datepicker( "valueAsDate" ), - new Date( 2008, 2 - 1, 4 ), - "Mouse click - abandoned" - ); - - // Previous/next - input.val( "2/4/08" ).datepicker( "refresh" ).datepicker( "open" ); - $( ".ui-calendar-prev", picker ).simulate( "click" ); - $( ".ui-calendar-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( "refresh" ).datepicker( "open" ); - $( ".ui-calendar-next", picker ).simulate( "click" ); - $( ".ui-calendar-calendar tbody a:contains(18)", picker ).simulate( "mousedown" ); - TestHelpers.datepicker.equalsDate( - input.datepicker( "valueAsDate" ), - new Date( 2008, 3 - 1, 18 ), - "Mouse click - next" - ); - - step2(); - }, 100 ); - } - - // Previous/next with minimum/maximum - function step2() { - input - .datepicker( "destroy" ) - .val( "3/4/08" ); - input = TestHelpers.datepicker.init( "#datepicker", { - min: new Date( 2008, 2 - 1, 2 ), - max: new Date( 2008, 2 - 1, 26 ) - }); picker = input.datepicker( "widget" ); - input.datepicker( "open" ); - setTimeout(function() { - $( ".ui-calendar-prev", picker ).simulate( "click" ); - $( "tbody a:contains(16)", picker ).simulate( "mousedown" ); - TestHelpers.datepicker.equalsDate( - input.datepicker( "valueAsDate" ), - new Date( 2008, 2 - 1, 16 ), - "Mouse click - previous + min/max" - ); - step3(); - }, 100 ); - } - function step3() { - input - .datepicker( "destroy" ) - .val( "1/4/08" ); - input = TestHelpers.datepicker.init( "#datepicker", { - min: new Date( 2008, 2 - 1, 2 ), - max: new Date( 2008, 2 - 1, 26 ) - }); - picker = input.datepicker( "widget" ); - input.datepicker( "open" ); - setTimeout(function() { - $( ".ui-calendar-next", picker ).simulate( "click" ); - $( "tbody a:contains(18)", picker ).simulate( "mousedown" ); - TestHelpers.datepicker.equalsDate( - input.datepicker( "valueAsDate" ), - new Date( 2008, 2 - 1, 18 ), - "Mouse click - next + min/max" - ); - start(); - }, 100 ); - } + input.datepicker( "open" ); - step1(); + 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 ); From 8c43f0296c27fba5a823ea24177c97db7ea752bc Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Fri, 20 Jun 2014 17:50:12 +0200 Subject: [PATCH 89/94] Calendar tests: Add common unit tests --- tests/unit/calendar/calendar_common.js | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/tests/unit/calendar/calendar_common.js b/tests/unit/calendar/calendar_common.js index b0df728acb6..a669fdfc2c1 100644 --- a/tests/unit/calendar/calendar_common.js +++ b/tests/unit/calendar/calendar_common.js @@ -1,7 +1,17 @@ -/* TestHelpers.commonWidgetTests( "calendar", { defaults: { - disabled: false + buttons: [], + dateFormat: { date: "short" }, + disabled: false, + eachDay: $.noop, + max: null, + min: null, + numberOfMonths: 1, + showWeek: false, + value: null, + + // callbacks + create: null, + select: null } }); -*/ From e484b9f59f422391562ec2e69aee368317352bf0 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Sat, 28 Jun 2014 01:44:55 +0200 Subject: [PATCH 90/94] Calendar tests: Fix title --- tests/unit/calendar/all.html | 2 +- tests/unit/calendar/calendar.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/calendar/all.html b/tests/unit/calendar/all.html index 26c46415a6e..87683cf0605 100644 --- a/tests/unit/calendar/all.html +++ b/tests/unit/calendar/all.html @@ -2,7 +2,7 @@ - jQuery UI calendar Test Suite + jQuery UI Calendar Test Suite diff --git a/tests/unit/calendar/calendar.html b/tests/unit/calendar/calendar.html index 022dc42ded1..e2527e02cf5 100644 --- a/tests/unit/calendar/calendar.html +++ b/tests/unit/calendar/calendar.html @@ -2,7 +2,7 @@ - jQuery UI calendar Test Suite + jQuery UI Calendar Test Suite From 0c4e4c2feadce716e6ef7560efde33bec78dd3fc Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Tue, 1 Jul 2014 22:43:06 +0200 Subject: [PATCH 91/94] Calendar: Set selected property to null by default --- external/date.js | 1 + 1 file changed, 1 insertion(+) diff --git a/external/date.js b/external/date.js index 1bc5b836038..edc47c161f6 100644 --- a/external/date.js +++ b/external/date.js @@ -32,6 +32,7 @@ $.date = function( date, globalFormat ) { this.dateObject = this.dateObject || new Date(); this.globalFormat = globalFormat; + this.selected = null; }; $.date.prototype = { From 8ac904175b35d74efc96ba93d1d385c8dc7fb130 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Tue, 1 Jul 2014 22:49:46 +0200 Subject: [PATCH 92/94] Calendar tests: Rewrite method unit tests based on datepicker tests --- tests/unit/calendar/calendar_methods.js | 175 +++++++++----------- tests/unit/datepicker/datepicker_methods.js | 12 +- 2 files changed, 84 insertions(+), 103 deletions(-) diff --git a/tests/unit/calendar/calendar_methods.js b/tests/unit/calendar/calendar_methods.js index 89547463cf8..59078e398cb 100644 --- a/tests/unit/calendar/calendar_methods.js +++ b/tests/unit/calendar/calendar_methods.js @@ -3,128 +3,107 @@ module( "calendar: methods" ); test( "destroy", function() { - expect( 10 ); - var input = $( "#calendar" ).calendar(), - inline = $( "#inline" ).calendar(); - - ok( input.calendar( "instance" ), "instance created" ); - ok( input.attr( "aria-owns" ), "aria-owns attribute added" ); - ok( input.attr( "aria-haspopup" ), "aria-haspopup attribute added" ); - input.calendar( "destroy" ); - ok( !input.calendar( "instance" ), "instance removed" ); - ok( !input.attr( "aria-owns" ), "aria-owns attribute removed" ); - ok( !input.attr( "aria-haspopup" ), "aria-haspopup attribute removed" ); - - ok( inline.calendar( "instance" ), "instance created" ); - ok( inline.children().length > 0, "inline calendar has children" ); - inline.calendar( "destroy" ); - ok( !inline.calendar( "instance" ), "instance removed" ); - ok( inline.children().length === 0, "inline picker no longer has children" ); + 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 inl, - inp = TestHelpers.calendar.init( "#calendar" ), - dp = inp.calendar( "widget" ); - - ok( !inp.calendar( "option", "disabled" ), "initially enabled" ); - ok( !dp.hasClass( "ui-calendar-disabled" ), "does not have disabled class name" ); - inp.calendar( "disable" ); - ok( inp.calendar( "option", "disabled" ), "disabled option is set" ); - ok( dp.hasClass( "ui-calendar-disabled" ), "calendar has disabled class name" ); + var element = $( "#calendar" ).calendar(); - inp.calendar( "enable" ); - ok( !inp.calendar( "option", "disabled" ), "enabled after enable() call" ); - ok( !dp.hasClass( "ui-calendar-disabled" ), "no longer has disabled class name" ); + ok( !element.calendar( "option", "disabled" ), "initially enabled" ); + ok( !element.hasClass( "ui-calendar-disabled" ), "does not have disabled class name" ); - // Inline - inl = TestHelpers.calendar.init( "#inline" ); - dp = inl.calendar( "instance" ); + element.calendar( "disable" ); + ok( element.calendar( "option", "disabled" ), "disabled option is set" ); + ok( element.hasClass( "ui-calendar-disabled" ), "calendar has disabled class name" ); - // 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. + 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 actual = $( "#calendar" ).calendar().calendar( "widget" ); - deepEqual( $( "body > .ui-front" )[ 0 ], actual[ 0 ] ); - actual.remove(); -}); -test( "close", function() { - expect( 0 ); -}); + var element = $( "#calendar" ).calendar(), + widget = element.calendar( "widget" ); -test( "open", function() { - expect( 0 ); + deepEqual( widget[ 0 ], element[ 0 ] ); }); test( "value", function() { - expect( 6 ); - var input = $( "#calendar" ).calendar(), - picker = input.calendar( "widget" ), - inline = $( "#inline" ).calendar(); - - input.calendar( "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" ); - equal( input.calendar( "value" ), "1/1/14", "getter" ); - - input.val( "abc" ); - equal( input.calendar( "value" ), "abc", - "Invalid values should be returned without formatting." ); - - inline.calendar( "value", "1/1/14" ); - ok( inline.find( "a[data-timestamp]:first" ).hasClass( "ui-state-focus" ), - "first day marked as selected" ); - equal( inline.calendar( "value" ), "1/1/14", "getter" ); - - input.calendar( "destroy" ); - inline.calendar( "destroy" ); + 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( 6 ); - var input = $( "#calendar" ).calendar(), - picker = input.calendar( "widget" ), - inline = $( "#inline" ).calendar(); - - input.calendar( "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.calendar.equalsDate( input.calendar( "valueAsDate" ), - new Date( 2014, 0, 1 ), "getter" ); - - input.val( "a/b/c" ); - equal( input.calendar( "valueAsDate" ), null, "Invalid dates return null" ); - - inline.calendar( "valueAsDate", new Date( 2014, 0, 1 ) ); - ok( inline.find( "a[data-timestamp]:first" ).hasClass( "ui-state-focus" ), - "first day marked as selected" ); - TestHelpers.calendar.equalsDate( inline.calendar( "valueAsDate" ), - new Date( 2014, 0, 1 ), "getter" ); - - input.calendar( "destroy" ); - inline.calendar( "destroy" ); -}); + 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" ); -test( "isValid", function() { - expect( 2 ); - var input = $( "#calendar" ).calendar(); + element.calendar( "valueAsDate", date2 ); + TestHelpers.calendar.equalsDate( element.calendar( "valueAsDate" ), date1, "Set date min/max - value > max" ); - input.val( "1/1/14" ); - ok( input.calendar( "isValid" ) ); + element.calendar( "option", { min: minDate } ).calendar( "valueAsDate", date1 ); + TestHelpers.calendar.equalsDate( element.calendar( "valueAsDate" ), date1, "Set date min/max - value < min" ); - input.val( "1/1/abc" ); - ok( !input.calendar( "isValid" ) ); + element.calendar( "valueAsDate", date2 ); + TestHelpers.calendar.equalsDate( element.calendar( "valueAsDate" ), date1, "Set date min/max - value > max" ); - input.calendar( "destroy" ); + 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/datepicker/datepicker_methods.js b/tests/unit/datepicker/datepicker_methods.js index cf41313922a..ebee9432640 100644 --- a/tests/unit/datepicker/datepicker_methods.js +++ b/tests/unit/datepicker/datepicker_methods.js @@ -4,6 +4,7 @@ module( "datepicker: methods" ); test( "destroy", function() { expect( 6 ); + var input = $( "#datepicker" ).datepicker(); ok( input.datepicker( "instance" ), "instance created" ); @@ -17,6 +18,7 @@ test( "destroy", function() { test( "enable / disable", function() { expect( 6 ); + var inp = TestHelpers.datepicker.init( "#datepicker" ), dp = inp.datepicker( "widget" ); @@ -34,6 +36,7 @@ test( "enable / disable", function() { test( "widget", function() { expect( 1 ); + var actual = $( "#datepicker" ).datepicker().datepicker( "widget" ); deepEqual( $( "body > .ui-front" )[ 0 ], actual[ 0 ] ); actual.remove(); @@ -60,11 +63,13 @@ test( "open / close", function() { test( "value", function() { expect( 4 ); + var input = $( "#datepicker" ).datepicker(), picker = input.datepicker( "widget" ); input.datepicker( "value", "1/1/14" ); equal( input.val(), "1/1/14", "input's value set" ); + input.datepicker( "open" ); ok( picker.find( "a[data-timestamp]:first" ).hasClass( "ui-state-active" ), "first day marked as selected" ); equal( input.datepicker( "value" ), "1/1/14", "getter" ); @@ -74,7 +79,7 @@ test( "value", function() { }); test( "valueAsDate", function() { - expect( 14 ); + expect( 13 ); var minDate, maxDate, dateAndTimeToSet, dateAndTimeClone, input = TestHelpers.datepicker.init( "#datepicker" ), @@ -93,13 +98,10 @@ test( "valueAsDate", function() { input.val( "" ).datepicker( "destroy" ); input = TestHelpers.datepicker.init( "#datepicker" ); - ok(input.datepicker( "valueAsDate" ) == null, "Set date - default" ); + ok(input.datepicker( "valueAsDate" ) === null, "Set date - default" ); input.datepicker( "valueAsDate", date1); TestHelpers.datepicker.equalsDate(input.datepicker( "valueAsDate" ), date1, "Set date - 2008-06-04" ); - input.datepicker( "valueAsDate", date1, date2); - TestHelpers.datepicker.equalsDate(input.datepicker( "valueAsDate" ), date1, "Set date - two dates" ); - // With minimum/maximum input = TestHelpers.datepicker.init( "#datepicker" ); date1 = new Date( 2008, 1 - 1, 4 ); From 6a2a59838d32cc77937ee8dd380ee69d1ef6ac60 Mon Sep 17 00:00:00 2001 From: Felix Nagel Date: Wed, 2 Jul 2014 19:22:49 +0200 Subject: [PATCH 93/94] Calendar: Adjust files to match reorganization of external directory --- demos/calendar/buttonbar.html | 4 ++-- demos/calendar/date-formats.html | 4 ++-- demos/calendar/default.html | 4 ++-- demos/calendar/dropdown-month-year.html | 4 ++-- demos/calendar/localization.html | 4 ++-- demos/calendar/min-max.html | 4 ++-- demos/calendar/multiple-months.html | 4 ++-- demos/calendar/other-months.html | 4 ++-- demos/calendar/show-week.html | 4 ++-- tests/unit/date/all.html | 22 +++++++++++----------- tests/unit/date/date.html | 6 +++--- 11 files changed, 32 insertions(+), 32 deletions(-) diff --git a/demos/calendar/buttonbar.html b/demos/calendar/buttonbar.html index 235192da1f8..7a2098b3f6d 100644 --- a/demos/calendar/buttonbar.html +++ b/demos/calendar/buttonbar.html @@ -4,8 +4,8 @@ jQuery UI Calendar - Display button bar - - + + diff --git a/demos/calendar/date-formats.html b/demos/calendar/date-formats.html index 33df9cacb59..e3f4e045762 100644 --- a/demos/calendar/date-formats.html +++ b/demos/calendar/date-formats.html @@ -4,8 +4,8 @@ jQuery UI Calendar - Format date - - + + diff --git a/demos/calendar/default.html b/demos/calendar/default.html index b35e9e769bd..8c77174b435 100644 --- a/demos/calendar/default.html +++ b/demos/calendar/default.html @@ -4,8 +4,8 @@ jQuery UI Calendar - Default functionality - - + + diff --git a/demos/calendar/dropdown-month-year.html b/demos/calendar/dropdown-month-year.html index c5773894607..050a89157ff 100644 --- a/demos/calendar/dropdown-month-year.html +++ b/demos/calendar/dropdown-month-year.html @@ -4,8 +4,8 @@ jQuery UI Calendar - Display month & year menus - - + + diff --git a/demos/calendar/localization.html b/demos/calendar/localization.html index 64c51e22fd5..fa933fe11b5 100644 --- a/demos/calendar/localization.html +++ b/demos/calendar/localization.html @@ -4,8 +4,8 @@ jQuery UI Calendar - Localize calendar - - + + diff --git a/demos/calendar/min-max.html b/demos/calendar/min-max.html index 067b6f02f66..5b9b5fd825f 100644 --- a/demos/calendar/min-max.html +++ b/demos/calendar/min-max.html @@ -4,8 +4,8 @@ jQuery UI Calendar - Restrict date range - - + + diff --git a/demos/calendar/multiple-months.html b/demos/calendar/multiple-months.html index 40cc30e2d72..f67609d143e 100644 --- a/demos/calendar/multiple-months.html +++ b/demos/calendar/multiple-months.html @@ -4,8 +4,8 @@ jQuery UI Calendar - Display multiple months - - + + diff --git a/demos/calendar/other-months.html b/demos/calendar/other-months.html index 4e3ee3e3b88..0228c62df5b 100644 --- a/demos/calendar/other-months.html +++ b/demos/calendar/other-months.html @@ -4,8 +4,8 @@ jQuery UI Calendar - Dates in other months - - + + diff --git a/demos/calendar/show-week.html b/demos/calendar/show-week.html index bb9ae4cc9b6..08687aa0dea 100644 --- a/demos/calendar/show-week.html +++ b/demos/calendar/show-week.html @@ -4,8 +4,8 @@ jQuery UI Calendar - Show week of the year - - + + 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 - - + + - + - + diff --git a/tests/unit/calendar/calendar.html b/tests/unit/calendar/calendar.html index e2527e02cf5..ed536414fbc 100644 --- a/tests/unit/calendar/calendar.html +++ b/tests/unit/calendar/calendar.html @@ -5,11 +5,11 @@ jQuery UI Calendar Test Suite - + - - + +