A lightweight, flexible, and powerful vanilla JavaScript datepicker with multiple selection modes. No dependencies required.
- Four Selection Modes: Single, Multiple, Range, and Multi-Range
- Zero Dependencies: Pure vanilla JavaScript
- Lightweight: ~5.5kB minified
- Customizable: Extensive configuration options
- Responsive: Works on all devices
- Accessible: ARIA-compliant
- i18n Support: Built-in internationalization
- Date Restrictions: Min/max dates, disabled dates, past/future blocking
- Smart Controls: Quick select weekdays, weekends, or all days
- Custom Formatting: Flexible date format patterns
<!-- CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/leoanangmh/flexidatepicker@latest/dist/flexidatepicker.min.css">
<!-- JavaScript -->
<script src="https://cdn.jsdelivr.net/gh/leoanangmh/flexidatepicker@latest/dist/flexidatepicker.umd.min.js"></script>npm install flexidatepickeryarn add flexidatepickerDownload the latest release from the releases page and include the files in your project:
<link rel="stylesheet" href="path/to/flexidatepicker.min.css">
<script src="path/to/flexidatepicker.js"></script><input type="text" id="single-date" placeholder="Select a date">
<script>
new FlexiDatepicker('#single-date', {
mode: 'single',
dateFormat: 'MMM d, yyyy'
});
</script><input type="text" id="multiple-dates" placeholder="Select multiple dates">
<script>
new FlexiDatepicker('#multiple-dates', {
mode: 'multiple'
});
</script><input type="text" id="date-range" placeholder="Select a range">
<script>
new FlexiDatepicker('#date-range', {
mode: 'range',
dateFormat: 'MM/dd/yyyy'
});
</script><input type="text" id="multi-range" placeholder="Select multiple ranges">
<script>
new FlexiDatepicker('#multi-range', {
mode: 'multi-range',
showSelectWeekdays: true,
showSelectWeekends: true
});
</script>| Option | Type | Default | Description |
|---|---|---|---|
mode |
String | 'multi-range' |
Selection mode: 'single', 'multiple', 'range', 'multi-range' |
locale |
String | 'en-US' |
Locale for date formatting |
dateFormat |
String | 'MMM d, yyyy' |
Date display format |
initialValue |
String/Array/Object | null |
Initial value for edit mode (see Initial Value) |
| Option | Type | Default | Description |
|---|---|---|---|
selectedDatesDisplaySelector |
String | null |
CSS selector for external display element |
showClearAll |
Boolean | true |
Show "Clear All" button |
showSelectWeekdays |
Boolean | true |
Show "Select Weekdays" button (multiple/multi-range modes) |
showSelectWeekends |
Boolean | true |
Show "Select Weekends" button (multiple/multi-range modes) |
showSelectAllDays |
Boolean | true |
Show "Select All Days" button (multiple/multi-range modes) |
dualCalendar |
Boolean | true |
Show Dual Calendar |
| Option | Type | Default | Description |
|---|---|---|---|
enableTime |
Boolean | false |
Enable time selection |
timeFormat |
String | '24h' |
Time format: '24h' or '12h' |
defaultTime |
String | '00:00' |
Default time value in 24-hour format (HH:MM) |
minuteIncrement |
Number | 1 |
Minute increment for time picker |
Note: All time values in initialValue and callback data use 24-hour format (HH:MM), regardless of the timeFormat display setting.
| Option | Type | Default | Description |
|---|---|---|---|
disabledDates |
Array | [] |
Array of disabled dates (strings or objects with from/to) |
disablePast |
Boolean | false |
Disable all past dates |
disableFuture |
Boolean | false |
Disable all future dates |
minDate |
String | null |
Minimum selectable date (YYYY-MM-DD) |
maxDate |
String | null |
Maximum selectable date (YYYY-MM-DD) |
| Option | Type | Default | Description |
|---|---|---|---|
onSelectionChange |
Function | null |
Callback when selection changes. Receives { ranges: [], dates: [] } |
| Pattern | Description | Example |
|---|---|---|
yyyy |
4-digit year | 2025 |
yy |
2-digit year | 25 |
MMMM |
Full month name | January |
MMM |
Short month name | Jan |
MM |
2-digit month | 01 |
M |
Month number | 1 |
dd |
2-digit day | 05 |
d |
Day number | 5 |
'MMM d, yyyy' // Jan 5, 2025
'MM/dd/yyyy' // 01/05/2025
'd MMMM yyyy' // 5 January 2025
'yyyy-MM-dd' // 2025-01-05new FlexiDatepicker('#datepicker', {
mode: 'range',
onSelectionChange: function(data) {
console.log('Selected ranges:', data.ranges);
console.log('Selected dates:', data.dates);
// Update your UI or send to server
if (data.ranges.length > 0) {
const range = data.ranges[0];
console.log(`From ${range.start} to ${range.end}`);
}
}
});new FlexiDatepicker('#datepicker', {
mode: 'single',
disabledDates: [
'2025-01-01', // New Year's Day
'2025-12-25', // Christmas
{ from: '2025-07-01', to: '2025-07-07' } // Vacation week
],
disablePast: true,
minDate: '2025-01-01',
maxDate: '2025-12-31'
});<input type="text" id="datepicker" placeholder="Select dates">
<div id="selected-display"></div>
<script>
new FlexiDatepicker('#datepicker', {
mode: 'multi-range',
selectedDatesDisplaySelector: '#selected-display'
});
</script>new FlexiDatepicker('#datepicker', {
mode: 'range',
locale: 'es-ES', // Spanish locale
dateFormat: 'd/M/yyyy',
showClearAll: true,
showSelectWeekdays: false
});FlexiDatepicker supports time selection for all modes. When enableTime is enabled, users can select both date and time.
new FlexiDatepicker('#datepicker', {
mode: 'single',
enableTime: true,
timeFormat: '24h', // or '12h' for AM/PM format
defaultTime: '09:00'
});Each selected date can have its own time:
new FlexiDatepicker('#datepicker', {
mode: 'multiple',
enableTime: true,
timeFormat: '12h',
defaultTime: '10:00'
});Supports start time and end time for the range:
new FlexiDatepicker('#datepicker', {
mode: 'range',
enableTime: true,
timeFormat: '24h',
defaultTime: '08:00'
});Each range can have its own start and end times:
new FlexiDatepicker('#datepicker', {
mode: 'multi-range',
enableTime: true,
timeFormat: '12h',
minuteIncrement: 15 // 15-minute intervals
});The initialValue option allows you to pre-populate the datepicker with selected dates or ranges. This is particularly useful for edit mode when you want to display existing selections.
// Using a single date string
new FlexiDatepicker('#datepicker', {
mode: 'single',
initialValue: '2025-01-15'
});
// With time (when enableTime is true)
new FlexiDatepicker('#datepicker', {
mode: 'single',
enableTime: true,
initialValue: {
date: '2025-01-15',
time: '14:30' // Always use 24-hour format (HH:MM)
}
});// Array of date strings
new FlexiDatepicker('#datepicker', {
mode: 'multiple',
initialValue: ['2025-01-15', '2025-01-20', '2025-01-25']
});
// With times (when enableTime is true)
new FlexiDatepicker('#datepicker', {
mode: 'multiple',
enableTime: true,
initialValue: [
{ date: '2025-01-15', time: '09:00' },
{ date: '2025-01-20', time: '14:30' },
{ date: '2025-01-25', time: '16:00' }
]
});// Using an object with start and end
new FlexiDatepicker('#datepicker', {
mode: 'range',
initialValue: {
start: '2025-01-10',
end: '2025-01-20'
}
});
// With times (when enableTime is true)
new FlexiDatepicker('#datepicker', {
mode: 'range',
enableTime: true,
initialValue: {
start: '2025-01-10',
end: '2025-01-20',
startTime: '09:00',
endTime: '17:00'
}
});// Array of range objects
new FlexiDatepicker('#datepicker', {
mode: 'multi-range',
initialValue: [
{ start: '2025-01-10', end: '2025-01-15' },
{ start: '2025-01-20', end: '2025-01-25' },
{ start: '2025-02-01', end: '2025-02-05' }
]
});
// With times (when enableTime is true)
new FlexiDatepicker('#datepicker', {
mode: 'multi-range',
enableTime: true,
initialValue: [
{ start: '2025-01-10', end: '2025-01-15', startTime: '09:00', endTime: '17:00' },
{ start: '2025-01-20', end: '2025-01-25', startTime: '10:00', endTime: '18:00' }
]
});// Load existing data from your backend/database
const existingBooking = {
checkIn: '2025-03-15',
checkOut: '2025-03-20'
};
// Initialize datepicker with existing values
new FlexiDatepicker('#booking-dates', {
mode: 'range',
initialValue: {
start: existingBooking.checkIn,
end: existingBooking.checkOut
},
onSelectionChange: function(data) {
// Update your form or send to server
console.log('Updated dates:', data.ranges);
}
});Contributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
MIT License - see the LICENSE file for details
Built with vanilla JavaScript for maximum compatibility and performance.