A versatile date picker with day and month selection modes, multiple selection support, and various formatting options.
Great for booking systems! If users don't have a specific date in mind, they can easily pick a few different dates, a whole month, or even several months at once
First demo (click it):
View on GitHubThis example demonstrates the month selection mode with multiple month selection enabled and restriction to 3 month at once, and possibility to select certain date in other tab, with the initialization of preselected values and the month tab active by default.
//Few Months picker initialization
const monthPicker = new DatepickerTabs('#month-input', {
mode: 'month',
multipleMonths: true,
maxMonthSelection: 3,
monthFormat: 'MMM YYYY'
});
To show selected value in the "Selected Values:" section here in this example - use this "onDateChange" parameter to constructor.
// This code below is used to show selection in "Selected Values:" section, so you probably won't need it
onDateChange: function(dates) {
const monthResult = document.getElementById('month-result');
if (dates) {
monthResult.textContent = monthPicker.getDatesAsString(dates)
} else {
monthResult.textContent = 'No months selected';
}
}
This example demonstrates the one month selection mode with NO date selection.
//Single Month mode picker only
const monthPickerOnly = new DatepickerTabs('#month-mode-example', {
mode: 'month',
displayType: 'month',
multipleMonths: false,
monthFormat: 'MMM YYYY',
});
This example demonstrates the day selection mode with single date selection.
//Single day mode picker only
const dayPickerOnly = new DatepickerTabs('#day-mode-example', {
displayType: 'day',
dateFormat: 'DD MMM YYYY',
multipleMonths: false,
});
Check out the latest features: Week starting on Monday, disabled days of week, and disabled specific dates.
This example has weeks starting on Monday, weekends disabled, and holidays disabled.
//Business Day Picker
const businessDayPicker = new DatepickerTabs('#business-day-input', {
startWeekOnMonday: true, // Week starts on Monday
disabledDaysOfWeek: [0, 6], // Disable Sunday (0) and Saturday (6)
disabledDates: [
'25/12/2025', // Christmas Day
'01/01/2025', // New Year's Day
'04/07/2025' // Independence Day
],
dateFormat: 'DD/MM/YYYY'
});
Configure your DatepickerTabs with the options below, test it out, and generate code to use in your project.
This tests that the date picker correctly positions itself when near the bottom of the viewport. (scroll that way so input is in the botton of the page)
A versatile date picker with day and month selection modes, multiple selection support, and various formatting options. Ideal for booking systems where users might want to select specific dates, a whole month, or even several months at once.
Clone or download the package from GitHub. Include CSS and JavaScript files in your HTML:
git clone https://github.com/swayoleg/datepicker-tabs.git
<link rel="stylesheet" href="dist/css/datepicker-tabs.min.css">
<script src="dist/js/datepicker-tabs.min.js"></script>
Alternatively, you can use JSDelivr
With a specific version (1.0.4 in this example):
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/swayoleg/datepicker-tabs@1.0.4/dist/css/datepicker-tabs.min.css">
<script src="https://cdn.jsdelivr.net/gh/swayoleg/datepicker-tabs@1.0.4/dist/js/datepicker-tabs.min.js"></script>
Or with the latest develop version:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/swayoleg/datepicker-tabs@develop/dist/css/datepicker-tabs.min.css">
<script src="https://cdn.jsdelivr.net/gh/swayoleg/datepicker-tabs@develop/dist/js/datepicker-tabs.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/datepicker-tabs@latest/dist/css/datepicker-tabs.min.css">
<script src="https://unpkg.com/datepicker-tabs@latest/dist/js/datepicker-tabs.min.js"></script>
npm install datepicker-tabs
Initialize the date picker on an input element:
// Initialize on a single input with ID
const picker = new DatepickerTabs('#date-input');
// Initialize on multiple inputs with class
const pickers = new DatepickerTabs('.date-input-class');
You can customize the date picker by passing an options object:
const picker = new DatepickerTabs('#date-input', {
// Basic configuration
mode: 'month', // 'day' or 'month' mode
displayType: 'tabs', // Display as 'tabs', 'day', or 'month'
// Selection options
multipleDays: false, // Allow multiple day selection
multipleMonths: true, // Allow multiple month selection
maxMonthSelection: 6, // Max selectable months (when multipleMonths=true)
// Date range options
startDate: null, // Initial selected date
minDate: null, // Minimum selectable date
maxDate: new Date(2026, 11, 31), // Maximum selectable date
futureSaturdaysOnly: true, // Only enable future Saturdays in day mode
startWeekOnMonday: false, // Start weeks on Monday instead of Sunday
disabledDaysOfWeek: [0, 6], // Disable days of week (0=Sunday, 6=Saturday)
disabledDates: [ // Disable specific dates
'25/12/2025', // Christmas Day
new Date(2025, 0, 1) // New Year's Day (also accepts Date objects)
],
// Localization
monthNames: ['January', 'February'], // Custom month names (shorthand provided for example)
dayNames: ['Sun', 'Mon'], // Custom day names (shorthand provided for example)
dateFormat: 'DD/MM/YYYY', // Date display format
monthFormat: 'MMM YYYY', // Month display format
// UI settings
position: 'bottom', // 'bottom' or 'top' position
zIndex: 9999, // Picker z-index
// Persistence
cookieName: 'datepickerTabsMode',// Cookie name for mode storage
// Year offset settings
backwardsYearsOffset: 5, // How many years to show before current year
forwardsYearsOffset: 5, // How many years to show after current year
// Callbacks
onDateChange: function(date) { // Date selection callback
console.log('Selected date:', date);
},
// Container customization
containerId: '', // Custom container ID to render calendar (if not provided, one will be generated)
});
mode
: Mode of operation: 'day' or 'month' (default: 'day')displayType
: Display type: 'tabs', 'day', or 'month' (default: 'tabs')multipleDays
: Allow multiple date selection (default: false)multipleMonths
: Allow multiple month selection (default: false)maxMonthSelection
: Maximum number of months that can be selected (default: null)startDate
: Initial selected date (default: null)minDate
: Minimum selectable date (default: null)maxDate
: Maximum selectable date (default: null)futureSaturdaysOnly
: Option for day mode to only enable Saturdays in the future (default: false)startWeekOnMonday
: Start weeks on Monday instead of Sunday (default: false)disabledDaysOfWeek
: Array of days of week to disable, where 0 is Sunday and 6 is Saturday (default: [])disabledDates
: Array of specific dates to disable - accepts Date objects or date strings (default: [])monthNames
: Array of month names (default: ['January', 'February', ...])dayNames
: Array of day names (default: ['Sun', 'Mon', ...])cookieName
: Cookie name for mode persistence (default: 'datepickerTabsMode')backwardsYearsOffset
: How many years to show before current year (default: 5)forwardsYearsOffset
: How many years to show after current year (default: 5)dateFormat
: Format for displaying dates (default: 'DD MMM YYYY')monthFormat
: Format for displaying months (default: 'MMM YYYY')position
: Position of the picker: 'bottom' or 'top' (default: 'bottom')zIndex
: z-index for the picker container (default: 9999)onDateChange
: Callback function when date(s) change (default: null)containerId
: Custom container ID to render calendar (default: '')The date picker supports the following tokens for date formatting:
DD
: Day of month with leading zero (01-31)D
: Day of month without leading zero (1-31)MMM
: Month name short (Jan, Feb, etc.)MMMM
: Month name full (January, February, etc.)MM
: Month number with leading zero (01-12)M
: Month number without leading zero (1-12)YYYY
: Full year (2023)YY
: Short year (23)Examples:
DD MMM YYYY = 01 Jan 2025
DD/MM/YYYY = 01/01/2025
MM/DD/YYYY = 01/01/2025
YYYY-MM-DD = 2025-01-01
// Set a single date
picker.setDate(new Date());
// Set multiple dates
picker.setMultipleDays(true);
picker.setDate([new Date(2023, 0, 1), new Date(2023, 1, 1)]);
// Clear selection
picker.setDate(null);
const selectedDate = picker.getDate();
picker.setMode('month');
picker.getMode();
picker.setDisplayType('day');
picker.setMultipleDays(true);
picker.setMultipleMonths(true);
picker.setDateFormat('YYYY-MM-DD');
picker.setMonthFormat('MM/YYYY');
picker.setMinDate(new Date(2023, 0, 1));
picker.setMaxDate(new Date(2024, 11, 31));
picker.setMaxMonthSelection(3);
picker.show();
picker.hide();
picker.destroy();
The date picker fires the following custom events:
datepickerShow
: Fired when the date picker is showndatepickerHide
: Fired when the date picker is hiddendatepickerModeChange
: Fired when the mode is changeddatepickerApply
: Fired when dates are applieddatepickerClear
: Fired when dates are clearedYou can listen for these events on the element where the date picker is initialized:
document.getElementById('date-input').addEventListener('datepickerApply', function(e) {
console.log('Applied date(s):', e.detail);
});
const datePicker = new DatepickerTabs('#date-input');
const monthPicker = new DatepickerTabs('#month-input', {
mode: 'month',
multipleMonths: true,
maxMonthSelection: 3
});
const constrainedPicker = new DatepickerTabs('#date-input', {
minDate: new Date(2023, 0, 1),
maxDate: new Date(2023, 11, 31),
dateFormat: 'YYYY-MM-DD'
});
const monthOnlyPicker = new DatepickerTabs('#month-only-picker', {
mode: 'month',
displayType: 'month',
multipleMonths: false,
monthFormat: 'MMM YYYY',
});
const saturdayPicker = new DatepickerTabs('#event-date', {
futureSaturdaysOnly: true,
dateFormat: 'DD/MM/YYYY'
});
const businessDayPicker = new DatepickerTabs('#business-date', {
startWeekOnMonday: true, // Week starts on Monday
disabledDaysOfWeek: [0, 6], // Disable Sunday (0) and Saturday (6)
disabledDates: [
'2025-12-25', // Christmas (in YYYY-MM-DD format)
'2025-01-01', // New Year's Day
new Date(2025, 6, 4) // Independence Day (also works with Date objects)
],
dateFormat: 'YYYY-MM-DD'
});
To ensure smooth integration and optimal user experience, follow these best practices:
onDateChange
callback to update the UI dynamically. For example:
// Example usage of onDateChange
const picker = new DatepickerTabs('#date-input', {
onDateChange: function(date) {
console.log('Selected date:', date);
// Add your UI update logic here.
}
});
.custom-datepickertabs-container
to prevent conflicts with global styles.startWeekOnMonday
with disabledDaysOfWeek
to create a more intuitive experience.
DatepickerTabs includes a comprehensive test suite to ensure functionality works as expected. There are multiple ways to test the library components.
You can test the date parsing function with prepared test-cases directly in your browser:
This guide explains how to set up Jest to test your DatepickerTabs component directly, without using a stub implementation.
First, install the necessary dependencies:
npm install --save-dev jest jest-environment-jsdom babel-jest @babel/core @babel/preset-env
Create the required configuration files or rewrite them if needed:
babel.config.js
- For transpiling modern JavaScriptjest.setup.js
- For setting up the test environment__tests__/direct-import.test.js
- The actual testsUpdate your package.json
with test scripts if not updated:
"scripts": {
"build": "gulp build",
"dev": "gulp",
"test": "jest",
"prepare": "npm run build"
},
"jest": {
"testEnvironment": "jsdom",
"setupFiles": ["./jest.setup.js"],
"testMatch": [
"**/__tests__/**/*.test.js"
]
}
datepicker-tabs/
├── __tests__/
│ ├── direct-import.test.js
├── babel.config.js
├── jest.setup.js
└── package.json
To run the test suite:
npm test
The test suite is organized as follows:
__tests__/
- Contains all test files
direct-import.test.js
- Tests directly importing the DatepickerTabs classThe library includes comprehensive tests for the date parsing functionality, covering various formats and edge cases:
// Example test for date parsing
test('should parse a date in DD/MM/YYYY format', () => {
const date = datepicker.parseDate('25/05/2025', 'DD/MM/YYYY');
expect(date instanceof Date).toBe(true);
expect(date.getDate()).toBe(25);
expect(date.getMonth()).toBe(4); // May is month 4 (zero-based)
expect(date.getFullYear()).toBe(2025);
});
We test multiple date formats:
And various edge cases like:
When adding new functionality, please include corresponding tests. Follow these guidelines:
__tests__
directoryExample of adding a parametrized test:
const testCases = [
{
name: "DD/MM/YYYY - standard date",
input: "04/07/2025",
format: "DD/MM/YYYY",
expected: new Date(2025, 6, 4) // July 4th, 2025
},
// Add more test cases...
];
test.each(testCases)('$name', ({ input, format, expected }) => {
const result = datepicker.parseDate(input, format);
if (expected === null) {
expect(result).toBeNull();
} else {
expect(result instanceof Date).toBe(true);
expect(result.getDate()).toBe(expected.getDate());
expect(result.getMonth()).toBe(expected.getMonth());
expect(result.getFullYear()).toBe(expected.getFullYear());
}
});
To extend the test suite, simply add more test cases in direct-import.test.js
. For example:
test('should handle special case X', () => {
const picker = new DatepickerTabs('#date-input');
// Your test logic
expect(result).toEqual(expectedValue);
});
jest.setup.js
to make sure necessary DOM APIs are properly mocked.