# Date Picker

> Select a date, a range, or several dates from a calendar.

## Introduction

Add `datepicker` to a text input. `AutoInit()` starts every `.datepicker` except those marked `no-autoinit`.

The calendar is inline, not a modal. With the default options the calendar is hidden (`openByDefault: false`) and clicking the input does not reveal it. Pass `openByDefault: true` to show the calendar under the field.

 Birthdate

```
<div class="field">
  <input type="text" class="date-picker" id="birthdate">
  <label for="birthdate">Birthdate</label>
</div>
```

```
Expressive.Datepicker.init(document.querySelectorAll('.datepicker'), {
  openByDefault: true
});
```

Wrap the input in its own `.field` (or another small parent). The calendar is inserted after that parent, not after the input itself.

## Initialization

The IIFE bundle exposes `Expressive.Datepicker`. Call `init` yourself when you need options other than the defaults, or let `Expressive.AutoInit()` start every `.datepicker`. AutoInit uses the defaults, so the calendar stays hidden until you pass `openByDefault` (or a working `displayPlugin` pair, below).

```
document.addEventListener('DOMContentLoaded', function() {
  const elems = document.querySelectorAll('.datepicker');
  const instances = Expressive.Datepicker.init(elems, {
    openByDefault: true
  });
});
```

Per-instance options can also be passed through AutoInit:

```
Expressive.AutoInit(document.body, {
  Datepicker: { openByDefault: true }
});
```

## Display

The calendar is a `.datepicker-container` in the page. There is no overlay and no `autoClose` option.

### Always visible

`openByDefault: true` leaves the calendar in the layout. That is the reliable way to show it.

### Docked popover

`displayPlugin: 'docked'` wraps the calendar in a `.display-docked` popover that appears when the input is clicked or focused with Enter, and hides when you click outside. The plugin only animates the wrapper. If `openByDefault` is still `false`, the calendar inside stays `display: none`. Use both:

```
Expressive.Datepicker.init(elem, {
  displayPlugin: 'docked',
  openByDefault: true
});
```

The popover is positioned in document coordinates and then appended to the input’s parent. A `position: relative` parent — including `.field` — shifts that position, so the calendar will not sit next to the field. Prefer a static wrapper if you use docked, or keep the calendar inline with `openByDefault`.

Optional `displayPluginOptions`: `margin` (default `5`), `transition` (`10`), `duration` (`250`), and `align` (`'left'`).

`container` renders the calendar into a specific element and does not hide it. Use a selector or a DOM node.

## Options

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `format` | String or Function | `'mmm dd, yyyy'` | Output written to the input, or a function that takes a `Date` and returns a string. |
| `parse` | Function | `null` | Turn the current input string back into a `Date`. Receives `(value, format)`. |
| `isDateRange` | Boolean | `false` | Select a start date and an end date. |
| `dateRangeEndEl` | String | `null` | Selector for an existing end-date input. If omitted, a second input is created. |
| `isMultipleSelection` | Boolean | `false` | Toggle several dates. Extra inputs are created as dates are added. |
| `defaultDate` | Date | `null` | Initial date to view. Falls back to the input’s current value, then today. |
| `defaultEndDate` | Date | `null` | Initial end date when `isDateRange` is true. |
| `setDefaultDate` | Boolean | `false` | If true, `defaultDate` is also the selected value. |
| `setDefaultEndDate` | Boolean | `false` | If true, `defaultEndDate` is also the selected end value. |
| `disableWeekends` | Boolean | `false` | Prevent selecting Saturday and Sunday. |
| `disableDayFn` | Function | `null` | Return true to disable that day. Receives a `Date`. |
| `firstDay` | Number | `0` | First day of the week. `0` is Sunday, `1` is Monday. |
| `minDate` | Date | `null` | Earliest selectable date. |
| `maxDate` | Date | `null` | Latest selectable date. |
| `yearRange` | Number or Array | `10` | Years on either side of the viewed year, or `[minYear, maxYear]`. |
| `yearRangeReverse` | Boolean | `false` | Sort the year list in reverse order. |
| `isRTL` | Boolean | `false` | Render the calendar right-to-left. |
| `showMonthAfterYear` | Boolean | `false` | Show the month after the year in the title. |
| `showDaysInNextAndPreviousMonths` | Boolean | `false` | Render days that fall in the adjoining months. |
| `openByDefault` | Boolean | `false` | If true, the calendar is visible. If false, it is given `display: none`. |
| `container` | Element or String | `null` | Element or selector to render the calendar into. When set, the calendar is not hidden. |
| `showClearBtn` | Boolean | `false` | Show a Clear button in the footer. |
| `autoSubmit` | Boolean | `true` | If true, selecting a day writes the input immediately. If false, Ok and Cancel buttons are added. |
| `i18n` | Object | See below | Labels and month/weekday names. Partial objects are merged with the defaults. |
| `events` | Array | `[]` | Strings from `Date.toDateString()`. Matching days get a `has-event` class. The default stylesheet does not style that class. |
| `onSelect` | Function | `null` | Called when a date is selected. Receives the `Date`. |
| `onDraw` | Function | `null` | Called after the calendar HTML is redrawn. |
| `onInputInteraction` | Function | `null` | Called when the input is clicked or confirmed with Enter. |
| `onConfirm` | Function | `null` | Called when the Ok button is used. Only created when `autoSubmit` is false. |
| `onCancel` | Function | `null` | Called when the Cancel button is used. Only created when `autoSubmit` is false. |
| `displayPlugin` | String | `null` | Set to `'docked'` for a click-to-open popover. Pair with `openByDefault: true`. |
| `displayPluginOptions` | Object | `null` | Options for the docked plugin: `margin`, `transition`, `duration`, `align`. |

## Date format options

Use these tokens in the `format` string.

| Key | Description | Output |
| --- | --- | --- |
| `d` | Date of the month. | 1–31 |
| `dd` | Date of the month, two digits. | 01–31 |
| `ddd` | Weekday short name from `i18n`. | Sun–Sat |
| `dddd` | Weekday full name from `i18n`. | Sunday–Saturday |
| `m` | Month of the year. | 1–12 |
| `mm` | Month of the year, two digits. | 01–12 |
| `mmm` | Month short name from `i18n`. | Jan–Dec |
| `mmmm` | Month full name from `i18n`. | January–December |
| `yy` | Two-digit year. | 26 |
| `yyyy` | Four-digit year. | 2026 |

## Internationalization

Pass a partial `i18n` object. Missing keys keep the English defaults.

| Key | Default |
| --- | --- |
| `cancel` | `'Cancel'` |
| `clear` | `'Clear'` |
| `done` | `'Ok'` |
| `previousMonth` | `'‹'` |
| `nextMonth` | `'›'` |
| `months` | `['January', …, 'December']` |
| `monthsShort` | `['Jan', …, 'Dec']` |
| `weekdays` | `['Sunday', …, 'Saturday']` |
| `weekdaysShort` | `['Sun', …, 'Sat']` |
| `weekdaysAbbrev` | `['S', 'M', 'T', 'W', 'T', 'F', 'S']` |

## Date range

Set `isDateRange: true`. Click a start day, then an end day that is on or after it. Point `dateRangeEndEl` at a second input, or omit it and a second input is created next to the first.

 Start date

 End date

```
Expressive.Datepicker.init(document.getElementById('datepicker-range'), {
  openByDefault: true,
  isDateRange: true,
  dateRangeEndEl: '#datepicker-range-end'
});
```

## Multiple dates

Set `isMultipleSelection: true`. Click a day to add it; click it again to remove it. Each selected date gets its own input.

 Dates

```
Expressive.Datepicker.init(document.getElementById('datepicker-multi'), {
  openByDefault: true,
  isMultipleSelection: true
});
```

## Methods

> All methods are called on the plugin instance. You can get the instance like this:

```
const instance = Expressive.Datepicker.getInstance(elem);
```

The low-level `renderRow`, `renderBody`, and `renderTable` helpers accept only calendar rows, cells, and day buttons. Use `renderDay` to create cells. Unsupported elements or attributes, including event handlers and styles, throw `TypeError`; day buttons require `type="button"`. Arbitrary custom HTML is no longer accepted.

### .toString();

String form of the selected date, using `format`. You can pass another date and format.

```
instance.toString();
instance.toString(someDate, 'yyyy-mm-dd');
```

### .setDate();

Select a date and move the calendar to it.

**Date (optional):** Date to select.

```
instance.setDate(new Date());
```

### .gotoDate();

Change the visible month without changing the selection.

**Date:** Date whose month should be shown.

```
instance.gotoDate(new Date());
```

### .destroy();

Destroy the plugin instance, remove the calendar, and tear down its event handlers.

```
instance.destroy();
```

## Properties

| Name | Type | Description |
| --- | --- | --- |
| `el` | Element | The input the plugin was initialized with. |
| `options` | Object | The options the instance was initialized with. |
| `date` | Date | The selected date, or the range start. |
| `endDate` | Date | The range end, when `isDateRange` is true. |
| `dates` | Array | The selected dates when `isMultipleSelection` is true. |
