type: widget
release: 0.0
status: in development
demo/documentation: http://view.jqueryui.com/datepicker/demos/datepicker/
1 - Description:
This is a brand new planning page to discuss the code refactor of the current datepicker plugin:
http://jqueryui.com/demos/datepicker/
To have a fresh start on the planning on this refactor, the older wiki page that covered current and future datepicker and calendar ideas is archived here: DatePickerCalendar
The specific code and functionality changes we want to address in this refactor are:
-
Refactor the code to use the widget factory and follow the jQuery UI API
-
Use the new Globalize project for i18n and l10n: https://github.com/jquery/globalize
-
Improve datepicker positioning/z-index issues in dialogs and overlays, especially in IE
-
Add the ability to customize the buttons in the bottom button bar. This would allow users to add a "clear form" button, shortcuts like "today" or "next delivery date". This API should match dialog's button option.
Sampling of feature requests that we might want to consider adding or accommodating as an extension to core picker:
-
Show week numbers - worth including?
-
Select multiple days on a calendar
-
Select a range on a calendar
-
Disable or highlight/decorate list of specific dates or days of the week
- Add time selection.
- Handle all new HTML5 date and datetime types:
- date
- datetime
- month
- week
- time
- datetime-local
Existing Refactors
2 - Visual Design:
3 - Functional Specifications/Requirements:
Options:
- appendTo - DATEPICKER ONLY
-
disabled (inherited from widget factory)
-
dateFormat (String or Object, default: { date: "short" })
-
eachDay (function, default: $.noop)
-
hide (string, default: null) - DATEPICKER ONLY
-
max (date or string, default: null)
-
The maximum selectable date by the datepicker. Dates greater than max will not be enabled for selection.
-
For consistency with the native picker, do not change the input's value when this option changes - even if the value is now invalid. See http://bugs.jqueryui.com/ticket/9688.
-
Given string is parsed according to dateFormat option. Support for input attribute using format yyyy-MM-dd
-
min (date or string, default: null)
-
The minimum selectable date by the datepicker. Dates less than min will not be enabled for selection.
-
For consistency with the native picker, do not change the input's value when this option changes - even if the value is now invalid. See http://bugs.jqueryui.com/ticket/9688.
-
Given string is parsed according to dateFormat option. Support for input attribute using format yyyy-MM-dd
-
numberOfMonths (number, default: 1)
-
position (position options, default: { my: 'left top', at 'left bottom' }) - DATEPICKER ONLY
-
show (string, default: null) - DATEPICKER ONLY
-
showWeek (boolean, default: false)
-
value (date or string, default: null) - CALENDAR ONLY
-
buttons (object or array, default: null)
Methods:
- destroy (inherited from widget factory)
- disable (inherited from widget factory)
- enable (inherited from widget factory)
- option (inherited from widget factory)
- widget (inherited from widget factory)
- isValid - DATEPICKER ONLY
- Determine whether the datepicker's input contains a valid date (bounded by min and max and subject to dateFormat).
- close - DATEPICKER ONLY
- Programmatically close the datepicker. Use the open method to open it again.
- open - DATEPICKER ONLY
- Programmatically open the datepicker. Use the close method to close it again.
- refresh
- Updates the calendar widget and the input value.
- value
- Get or set the value as a string, bounded by min and max options.
- valueAsDate - DATEPICKER ONLY
- Get or set the value as a Date object, bounded by min and max options.
Events:
- close - DATEPICKER ONLY
- This event is triggered when the datepicker is closed
- beforeOpen - DATEPICKER ONLY
- This event is triggered before the datepicker is opened
- If canceled, the datepicker will not open
- open - DATEPICKER ONLY
- This event is triggered when the datepicker is opened
- select
- Triggered when a date is selected from the picker
- change
- Triggered when date has changed
Globalization:
4 - Markup & Style:
4.1 Initial markup examples
<input>
<input min="1970-01-01" max="2020-12-31" value="2009-05-22">
4.2 Recommended transformed HTML markup
(The HTML markup structure and classes that will be used by the scripts in the enhanced version)
4.3 Accessibility recommendation
(Detailed recommendations for ARIA, HTML markup, CSS and javascript that will contribute to universal access and full section 508 accessibility for screen readers, mobile devices and any other devices)
Issues with current datepicker:
- Lack of ARIA roles and properties to identify keyboard interaction and label controls
- Tab key is used to open and close the date picker
- use grid roles to override table markup semantics to identify the interactive behavior of the date picker
- improve labeling of dates in grid and calendar navigation controls
- Keyboard focus is indicated using color alone
- Manage keyboard focus based on user interaction, keep focus in a predictable and useful place in the calendar grid
- the next/prev month icons are invisble in high contrast mode, not indication of focused day is available.
- the controls/links in the date picker do not recieve programmtaic focus.
- Expansions for day abbreviations not provided
- (1194.21.a) Keyboard navigation and selection not fully supported in popup version.
- (1194.22.g, 1194.22.h) Row and column headers (Its not clear to me whether this makes sense for the datepicker since its not really a data table).
See example:
http://oaa-accessibility.org/example/15/
Reason for separating templates: Refreshing the entire datepicker during interaction confuses screen readers, specifically because the date picker title is marked up as a live region and will often not be announced if it's destroyed and recreated (as opposed to having its text contents change). Additionally, with a single template approach, clicking the "prev" and "next" links would lead to the entire template to being refreshed. The would cause a loss of focus because the focused link itself would be removed as well. Separating the templates gets rid of these accessibility issues, and also allows developers to modify parts of the datepicker without having to duplicate the entire template.
Proposed Keyboard Support (Default Date Picker)
Feature
|
Keyboard
|
|
---|
Open Date Picker |
- Tab into date textbox automatically opens and moves focus to Date Picker Dialog box
- Focus should be on the current date gridcell in the calendar grid after the dialog box opens; or If a date had already been entered in the textbox focus should be in the date gridcell identified in the texbox
|
|
Close Date Picker and no change to textbox |
- ESCape closes Date Picker Dialog box and moves focus to text box with no change to the date in the textbox
- Enter key on the Close Button closes Date Picker Dialog box and moves focus to text box with no change to the date in the textbox
|
|
Close Date Picker and update date in textbox |
- Enter key when focus is on a date gridcell in the calendard grid closes Date Picker Dialog box and moves focus to text box with the last selected date from the calendar grid populating the textbox
|
|
Navigate dates (Calendar Grid) |
- up, down, left and right keys move focus and selected date between gridcells in the calendar grid
|
|
Tab Navigation |
- Keyboard focus stays in date picker dialog box until dialog box closes
- Tab moves between:
- Close button
- Month navigation buttons (next month, previous month)
- Calendar grid
|
|
Other Features
Feature
|
Description
|
---|
entering date in textbox |
- Allow other formats (e.g. Jan, mm-dd-yyy...) and auto correct
- If only one format provide help information on the date format allowed (MM/DD/YYYY)
- Use aria-describedby to reference the formatting information
|
close button??? |
- Should date picker have a close button???
|
Labeling date cells |
- Use aria-label or aria-labelledby on each gridcell to create an accessible name for each grid cell options:
- "Day-of-week the day" (e.g Saturday the 10th)
- "Day Day-of Week" (e.g. 10th Saturday)
- aria-describedby to date and year information
|
Changes in month/Year |
- Live region to announce changes in month and year
|
Keyboard Testing:
W3C
Keyboard navigation on days that are not included the currently displayed month should move to the month automatically and lead to the day in the next or previous month.
- Tab -
-
Like other widgets, the date picker widget receives focus by tabbing into it. Once focus is received,focus is repositioned on today's date in a grid of days and weeks. A second tab will take the user out of the date picker widget. Focus initially is placed on today's date.
- User can tab to date input field to trigger the datepicker. Another [TAB] closes the datepicker.
- There is only visual focus on the date indicated by a pale yellow background.
- Shift+Tab -
- reverses the direction of the tab order. Once in the widget, a Shift+Tab will take the user to the previous focusable element in the tab order. (See above)
- Up Arrow and Down Arrow -
- goes to the same day of the week in the previous or next week respectively. If the user advances past the end of the month they continue into the next or previous month as appropriate. Only [CTRL] + [Arrow Key] will allow user to navigate the calendar.
- Left Arrow and Right Arrow -
- advances one day to the next, also in a continuum. Visually focus is moved from day to day and wraps from row to row in a grid of days and weeks.
- Shift+Control+Page Up - Moves to the same date in the previous year.
- Shift+Control+Page Down - Moves to the same date in the next year.
- Singleton Mode: acts as a toggle either selecting or deselecting the date.
- Contiguous Mode: Similar to selecting a range of text. Space selects the first date.
- Home - Moves to the first day of the current month.
- End - Moves to the last day of the current month.
- Page Up - Moves to the same date in the previous month.
- Page Down - Moves to the same date in the next month.
- Enter -
- If the calendar is a popup attached to some other widget (e.g., a text field), then Enter dismisses the popup, and the selected date(s) are shown in the associated widget.
- If the calendar is a static region on the page, then Enter confirms the selected date(s).
- Escape - in the case of a popup date picker, closes the widget without any action.
Color Contrast
- Need to change the styling of the element with role=gridcell with focus changing more than just background color
- Border style
- Border thickness
- Bold text date in cell
ARIA Support
- aria-activedescendant is being use to manage keyboard element being communicated as having focus to users of assistive technology
- Need to add aria-label or aria-labelledby attribute to each element with "role=gridcell" to provide "labels" to assistive technology
- Label should read "day of week" + "date" for example "Monday the 11th"
- Add aria-describedby attribute to each element with "role=gridcell" the div with the Year/Month information (e.g. div#ui-id-1-month-label)
- The button element inside the element with role="gridcell" should have "aria-hidden=true" attribute since it is not focusable and is read by some screen readers as "contains interactive elements"
- Don NOT use "aria-hidden" on elements with "role=gridcell", it hides the grid from ATs
- To have the change in Month/Year spoken automatically to screen reader users, add "role=alert" to the div containing the month year information e.g. div#ui-id-1-month-label)
4.4 CSS & Theme
(Description of the CSS classes to be used for all states, how custom theming and Themeroller support will work.)
5 - Latest version of plugin:
http://view.jqueryui.com/datepicker/demos/datepicker/default.html
6 - Open issues being discussed
Options and methods which needs discussion
- defaultDate
- multiple calendar related
- stepMonths
- showCurrentAtPos
Here's all the current options and methods.
Options:
- altField
- The new datepicker has a select event, so this is trivial functionality to add on yourself.
- remove
- altFormat
- appendText
- Trivial to add on.
- remove
- autoSize
- This automatically sizes the input to accommodate the selected date based on its format. I'm at a loss for why you would need to do this.
- remove (show how to replicate?)
- beforeShow
- Using the widget factory makes this mechanism obsolete and it would be tricky to preserve this functionality.
- remove
- beforeShowDay
- Currently the "eachDay" option provides comparable features, with a saner usage. Need to review that.
- remove (show to to replicate with "eachDay")
- buttonImage
- remove (show how to replicate)
- buttonImageOnly
- remove (show how to replicate)
- buttonText
- remove (show how to replicate)
- calculateWeek
- Should be done in Globalize (create a test)
- remove
- changeMonth
- Add a demo or create an extension for calendar
- remove
- changeYear
- Add a demo or create an extension for calendar
- remove
- closeText
- No buttons built into the datepicker.
- remove
- constrainInput
- Suppressing user input is a UX bad practice. I don't believe we should provide this functionality.
- remove
- currentText
- No buttons built into the datepicker.
- remove
- dateFormat
- dayNames
- dayNamesMin
- dayNamesShort
- remove (show how to replicate with Globalize - see comments on this page)
- defaultDate
- duration
- This functionality will be handled by the new show and hide options
- remove
- firstDay
- Use Globalize instead
- Remove
- gotoCurrent
- No buttons built into the datepicker.
- remove
- hideIfNoPrevNext
- Trivial to hide links at the desired time with CSS.
- remove (show how to replicate with CSS)
- isRTL
- This is functionality we'll want and a sane API.
- Does Globalize provide the needed functionality?
- Check if the current implementation is correct
- preserve?
- maxDate
- Keep, but rename to "max"
- preserve
- minDate
- Keep, but rename to "min"
- preserve
- monthNames
- monthNamesShort
- remove (show how to replicate with Globalize - see comments on this page)
- navigationAsDateFormat
- Not sure anybody uses this but I could see how it might be useful.
- remove (ensure this can be preserved via an extension point (_buildPrevButton() / _buildNextButton() )
- nextText
- We should preserve this, just like dialog's closeText option.
- preserve
- numberOfMonths
- Exists in the rewrite, the multi-month support is not working properly yet.
- Question: Do we continue to support the array form of this option? See http://jsfiddle.net/tj_vantoll/GmyXj/. Seems like something we should probably do but it's not accounted for in the rewrite for now.
- preserve?
- onChangeMonthYear
- What is the use case?
- remove (show how to use changeYear extension)
- onClose
- Replaced by close event
- remove (show how to replicate with close event)
- onSelect
- Replaced by select event
- remove (show how to replicate with select event)
- prevText
- We should preserve this, just like dialog's closeText option.
- preserve
- selectOtherMonths
- Covered by the "eachDay" option
- Create helper methods ($.ui.datepicker.xzy) to set eachDay option (if requested by users)
- Same for noWeekends
- remove (show how to replicate)
- shortYearCutoff
- Check if this is handled by Globalize
- What does moment.js do?
- remove
- showAnim
- Replaced by the show option.
- remove (show how to replicate with the show option)
- showButtonPanel
- Replaced by the buttons option.
- remove
- showCurrentAtPos
- I've always found the name of this option confusing but this is functionality I think we need to preserve.
- preserve?
- showMonthAfterYear
- This should be handled by Globalize.
- remove
- showOn
- Trivial to add on this functionality.
- remove (show how to replicate)
- showOptions
- Replaced by show option
- remove (show how to replicate)
- showOtherMonths
- Covered by the "eachDay" option
- Perhaps we want to create a helper method for this (see selectOtherMonths option)
- remove
- showWeek
- Implemented in the rewrite, seems fine to keep it
- preserve
- stepMonths
- Seems reasonable, but under discussion
- preserve?
- weekHeader
- If showWeek remains, this needs to stay, but perhaps be renamed
- remove?
- yearRange
- Use changeYear demo / extension
- remove
- yearSuffix
- This should be handled by Globalize.
- remove
Methods:
- destroy()
- dialog()
- getDate()
- Use valueAsDate method
- remove
- hide()
- isDisabled()
- Replaced by disabled option
- remove
- option()
- refresh()
- Seems like this would be inconsistent with our current refresh methods. Also I'm not sure what the use case even is for this.
- remove?
- setDate()
- Replaced by the value() method
- remove
- show()
- widget()
Next Steps / ToDo (Felix)
- a11y functionality
- figure out how to handle multiple month
- differences between datepicker and calendar widget
- RTL / bidi support
- There is some existing CSS
- In master, this controls arrow keys, prev/next icons, and corner radius on headers in multi-month
- Can this be determined from the locale instead of exposing an option?
- Infos from PR #1341
- Fix RTL LTR direction (available at cldr.main("layout/orientation/characterOrder"), values are left-to-right or right-to-left)
- RTL in master is just flat out wrong with changing DOM positions. Just let the browser do the right thing.
- Non-code related
- Start creating an upgrade guide
- Create getter / setter methods for this.gridId and this.viewDate as extension point
- Tests
- Add tests for Globalize based upon old code base (see comment and code)
- Add assertion that verifies where the focus should be (see comment)
- Use multiple timezones when running tests on travis (see comment)
- Handle timezone issues (extract Date creation, calculate offset, see comment)
- Add calendar and datepicker to the requirejs task in the Gruntfile
- Demos
- Re-order demo lists in index.html files (link to comment)
- dropdown-month-year: Broken (as not implemented)
- Implement this as a demo or an extension WIP
- icon-trigger: has open tasks
- keep this demo until we work on the migration guide for the new API, where we include this example, then delete the demo as it's promoting bad practice
- Visual tests
- Datepicker in Dialog has stacking issues
Proposed functionality of the value method / option
value method:
- get or set the currently selected value as a string
- string must be formatted as defined in option.dateFormat
- setter changes input value if valid string was passed (bounded by min and max options)
- getter returns
- the formatted current input as a string if valid (valid date string and min / max option)
- the current input value as a string if able to parse (valid date string)
- null if not able to parse
value option / valueAsDate method:
- get or set the currently selected value as a Date object
- setter changes input value if valid date object was passed (bounded by min and max options)
- getter returns
- the formatted current input as a date object if valid (valid date object and min / max option)
- the current input value as a date object if valid (valid date object)
- null if not a valid date object
Split Datepicker Widget in Datepicker and Calendar Widget
Calendar Widget
- basic functionality for displaying a calendar UI
- specs probably as listed in section 1 but without pop-up related methods and events (appendTo, hide, show, position, open, close, ...)
- has value option and methods
Datepicker Widget
- input based as the current, stable Datepicker Widget
- uses a internal reference of the Calendar Widget
- specs as listed in section 1
- has no value option because it's based upon a native input
- has value and valueAsDate methods
- remove inline functionality (use Calendar widget instead)
See PR: https://github.com/jquery/jquery-ui/pull/1260
external/date.js
Currently, `date.js` is located under `/external`. But, it is NOT an external library. It's NOT hosted (neither version-controlled) anywhere except in here. Aside from confusing, this makes AMD or CommonJS setup hard/awkward. So, we need to either make it an external library or move it into `./ui` (where all our sources files live).
Globalize related
Currently, `external/localization.js` holds CLDR data. We need to figure out how to deal with this data in demos and tests.
The translation data ("done", "prev", "next"; button names basically) is configured via the labels option.
Week numbers are currently implemented. Should they be removed and just shown in a demo with an extension?
Change eachDay to provide an actual element and simplify the custom API. Idea (not full implementation): https://gist.github.com/scottgonzalez/fadc55ffadff5241ffb1
When parsing min and max attributes, require them to follow the HTML spec. Same should be applied to spinner (though that is a breaking change)
Do we want to support an array for numberOfMonths?
Do we need a refresh() method? When would it be used?
What is the use case for the beforeOpen event?
Need to add a culture/locale option to match spinner or decide to remove it from spinner. -> Option has been added to datepicker.
Does this handle non-Gregorian calendars?
Handle year before month in header based on locale.
Compared to master, the default date format is different, is that intended? Master has 4 digit years, rewrite only 2