vanillajs-datepicker
Version:
A vanilla JavaScript remake of bootstrap-datepicker for Bulma and other CSS frameworks
692 lines (644 loc) • 25.6 kB
HTML
<html class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Vanilla JS Datepicker Demo</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/foundation-sites@6.7.5/dist/css/foundation-prototype.min.css" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.7.0/build/styles/github.min.css">
<link rel="stylesheet" type="text/css" href="../dist/css/datepicker-foundation.css">
<style type="text/css">
main .section {
padding: 3rem 1.5rem;
}
aside {
position: fixed;
top: 0;
bottom: 0;
right: -300px;
width: 300px;
overflow: auto;
background-color: #fff;
box-shadow: inset 1px 1px rgba(0, 0, 0, 10%);
transition: right 0.3s;
}
.open aside {
right: 0;
}
aside hr {
margin-top: 0.5rem;
}
.code-wrap {
position: relative;
margin-bottom: 1rem;
}
label + .code-wrap {
/*margin-top: calc(-1rem + 1px);*/
margin-top: -0.5rem;
}
.code-wrap pre {
background-color: whitesmoke;
padding: 1.25rem 1.5rem;
max-height: 320px;
overflow-y: auto;
}
.code-wrap pre:not(.is-active) {
height: 0;
overflow: hidden;
opacity: 0.5;
}
.code-wrap .collapse-button {
position: absolute;
top: 0;
right: 0;
left: auto;
cursor: pointer;
padding: 0.125rem 0.25rem;
font-size: 0.75rem;
}
.code-wrap pre:not(.is-active) + .collapse-button {
background-color: transparent;
}
.code-wrap pre code {
border: initial;
background-color: initial;
}
.code-wrap pre code.hljs {
display: initial;
overflow: initial;
background: initial;
padding: initial;
}
.option-type-selector {
display: flex;
align-items: center;
}
.option-type-selector input {
margin-bottom: 0;
}
.option-type-selector input:first-of-type {
margin-left: 0.5rem;
}
.option-type-selector label {
line-height: 1;
}
.is-hidden {
display: none;
}
.check-group {
display: flex;
flex-wrap: wrap;
}
.field.has-tip {
display: block;
border-bottom: 0;
}
.toggle-button {
position: fixed;
top: 0.75rem;
right: 0.75rem;
width: 1.5rem;
background-color: #fff;
line-height: 1.5rem;
border: 1px solid rgba(0, 0, 0, 10%);
border-radius: 2px;
box-shadow: 1px 1px rgba(0, 0, 0, 10%);
cursor: pointer;
}
.toggle-button::before {
content: '\25c0';
padding-left: 0.25rem;
}
.open .toggle-button::before {
content: '\25b6';
}
@media (min-width: 481px) {
main {
margin-right: 38.1966%;
}
aside {
right: 0;
width: 38.1966%;
}
.toggle-button {
display: none;
}
}
@media (min-width: 1024px) {
.code-wrap pre {
max-height: calc(39vw - 7.5rem);
}
}
.text-success {
color: #3adb76 ;
}
.text-warning {
color: #ffae00 ;
}
.text-alert {
color: #cc4b37 ;
}
.background-success {
background-color: #3adb76 ;
}
.background-warning {
background-color: #ffae00 ;
}
.background-alert {
background-color: #cc4b37 ;
}
.flex-wrap {
flex-wrap: wrap;
}
#elem-attribs .check-group {
padding-left: 0.5rem;
padding-right: 0.5rem;
}
#elem-attribs .check-group-item {
margin-left: 0.5rem;
margin-right: 0.5rem;
}
#elem-attribs .check-group-item label {
margin-right: 0.5rem;
}
</style>
</head>
<body>
<main>
<section class="section container-fluid">
<div class="row">
<div class="columns">
<p>Vanilla JS Datepicker</p>
<h1 class="title">Demo</h1>
<div id="sandbox">
<div class="field"><input type="text" class="date"></div>
</div>
<div id="elem-attribs" class="flex-container flex-wrap">
<label>Attribute:</label>
<div class="check-group">
<div class="check-group-item">
<input type="checkbox" data-target="input" name="readonly" value="">
<label>readonly</label>
</div>
<div class="check-group-item">
<input type="checkbox" data-target="input" name="disabled" value="">
<label class="margin-horizontal-1">disabled</label>
</div>
<div class="check-group-item" style="display: none;">
<input type="checkbox" data-target=".date" name="tabindex" value="0">
<label>tabindex="0"</label>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="columns">
<p><small>Style: <a href="index.html">Bulma</a> | <a href="bs5.html">Bootstrap</a> | <em>Foundation</em> | <a href="plain-css.html">Plain CSS</a></small></p>
</div>
</div>
</section>
</main>
<aside>
<section class="section">
<div class="grid-x grid-padding-x grid-padding-y">
<div class="cell">
<h4 class="subtitle">Type</h4>
<form id="types">
<div class="field">
<input type="radio" id="type-input" name="type" value="input" checked>
<label for="type-input">Input</label>
<input type="radio" id="type-inline" name="type" value="inline">
<label for="type-inline">Inline</label>
<input type="radio" id="type-range" name="type" value="range">
<label for="type-range">Range</label>
</div>
</form>
</div>
<div class="cell">
<hr>
<h4 class="subtitle">Options</h4>
<form id="options">
<div class="field" data-tooltip title="Only effective in range picker">
<input type="checkbox" id="allowOneSidedRange" name="allowOneSidedRange" value="true">
<label for="allowOneSidedRange">allowOneSidedRange</label>
</div>
<div class="field">
<input type="checkbox" id="autohide" name="autohide" value="true">
<label for="autohide">autohide</label>
</div>
<div class="field">
<input type="checkbox" id="beforeShowDay" name="beforeShowDay" value="true">
<label for="beforeShowDay">beforeShowDay</label>
<div class="code-wrap">
<pre id="code-beforeShowDay"><code class="language-javascript"></code></pre>
<div class="collapse-button" data-target="code-beforeShowDay">show/hide</div>
</div>
</div>
<div class="field">
<input type="checkbox" id="beforeShowMonth" name="beforeShowMonth" value="true">
<label for="beforeShowMonth">beforeShowMonth</label>
<div class="code-wrap">
<pre id="code-beforeShowMonth"><code class="language-javascript"></code></pre>
<div class="collapse-button" data-target="code-beforeShowMonth">show/hide</div>
</div>
</div>
<div class="field">
<input type="checkbox" id="beforeShowYear" name="beforeShowYear" value="true">
<label for="beforeShowYear">beforeShowYear</label>
<div class="code-wrap">
<pre id="code-beforeShowYear"><code class="language-javascript"></code></pre>
<div class="collapse-button" data-target="code-beforeShowYear">show/hide</div>
</div>
</div>
<div class="field">
<input type="checkbox" id="beforeShowDecade" name="beforeShowDecade" value="true">
<label for="beforeShowDecade">beforeShowDecade</label>
<div class="code-wrap">
<pre id="code-beforeShowDecade"><code class="language-javascript"></code></pre>
<div class="collapse-button" data-target="code-beforeShowDecade">show/hide</div>
</div>
</div>
<div class="field">
<input type="checkbox" id="clearButton" name="clearButton" value="true">
<label for="clearButton">clearButton</label>
</div>
<div class="field">
<label>
dateDelimiter
<input type="text" name="dateDelimiter" placeholder=",">
</label>
</div>
<div class="field">
<label>datesDisabled</label>
<div class="option-type-selector">
use
<input type="radio" id="datesDisabledFn-array" name="datesDisabledFn" value="" checked>
<label for="datesDisabledFn-array">array</label>
<input type="radio" id="datesDisabledFn-function" name="datesDisabledFn" value="1">
<label for="datesDisabledFn-function">function</label>
</div>
<div id="datesDisabled-arr" class="field" data-tooltip title="enter in JSON format">
<textarea name="datesDisabled" placeholder="[]"></textarea>
<span class="form-error is-visible"></span>
</div>
<div id="datesDisabled-fn" class="code-wrap is-hidden">
<pre id="code-datesDisabled"><code class="language-javascript"></code></pre>
<div class="collapse-button" data-target="code-datesDisabled">show/hide</div>
</div>
</div>
<div class="field">
<label>daysOfWeekDisabled</label>
<div class="check-group">
<div class="check-group-item">
<input type="checkbox" id="daysOfWeekDisabled-0" name="daysOfWeekDisabled" value="0">
<label for="daysOfWeekDisabled-0">0</label>
</div>
<div class="check-group-item">
<input type="checkbox" id="daysOfWeekDisabled-1" name="daysOfWeekDisabled" value="1">
<label for="daysOfWeekDisabled-1">1</label>
</div>
<div class="check-group-item">
<input type="checkbox" id="daysOfWeekDisabled-2" name="daysOfWeekDisabled" value="2">
<label for="daysOfWeekDisabled-2">2</label>
</div>
<div class="check-group-item">
<input type="checkbox" id="daysOfWeekDisabled-3" name="daysOfWeekDisabled" value="3">
<label for="daysOfWeekDisabled-3">3</label>
</div>
<div class="check-group-item">
<input type="checkbox" id="daysOfWeekDisabled-4" name="daysOfWeekDisabled" value="4">
<label for="daysOfWeekDisabled-4">4</label>
</div>
<div class="check-group-item">
<input type="checkbox" id="daysOfWeekDisabled-5" name="daysOfWeekDisabled" value="5">
<label for="daysOfWeekDisabled-5">5</label>
</div>
<div class="check-group-item">
<input type="checkbox" id="daysOfWeekDisabled-6" name="daysOfWeekDisabled" value="6">
<label for="daysOfWeekDisabled-6">6</label>
</div>
</div>
</div>
<div class="field">
<label>daysOfWeekHighlighted</label>
<div class="check-group">
<div class="check-group-item">
<input type="checkbox" id="daysOfWeekHighlighted-0" name="daysOfWeekHighlighted" value="0">
<label for="daysOfWeekHighlighted-0">0</label>
</div>
<div class="check-group-item">
<input type="checkbox" id="daysOfWeekHighlighted-1" name="daysOfWeekHighlighted" value="1">
<label for="daysOfWeekHighlighted-1">1</label>
</div>
<div class="check-group-item">
<input type="checkbox" id="daysOfWeekHighlighted-2" name="daysOfWeekHighlighted" value="2">
<label for="daysOfWeekHighlighted-2">2</label>
</div>
<div class="check-group-item">
<input type="checkbox" id="daysOfWeekHighlighted-3" name="daysOfWeekHighlighted" value="3">
<label for="daysOfWeekHighlighted-3">3</label>
</div>
<div class="check-group-item">
<input type="checkbox" id="daysOfWeekHighlighted-4" name="daysOfWeekHighlighted" value="4">
<label for="daysOfWeekHighlighted-4">4</label>
</div>
<div class="check-group-item">
<input type="checkbox" id="daysOfWeekHighlighted-5" name="daysOfWeekHighlighted" value="5">
<label for="daysOfWeekHighlighted-5">5</label>
</div>
<div class="check-group-item">
<input type="checkbox" id="daysOfWeekHighlighted-6" name="daysOfWeekHighlighted" value="6">
<label for="daysOfWeekHighlighted-6">6</label>
</div>
</div>
</div>
<div class="field">
<label>
defaultViewDate
<input type="text" name="defaultViewDate" placeholder="today">
</label>
</div>
<div class="field">
<input type="checkbox" id="enableOnReadonly" name="enableOnReadonly" value="true" checked>
<label for="enableOnReadonly">enableOnReadonly</label>
</div>
<div class="field">
<label>
format
<input type="text" name="format" placeholder="mm/dd/yyyy">
</label>
</div>
<div class="field">
<label>
language
<select name="language" >
<option value="en">en – English (US)</option>
</select>
</label>
</div>
<div class="field">
<label>
maxDate
<input type="text" name="maxDate" placeholder="null">
</label>
</div>
<div class="field" data-tooltip title="Not effective in range picker">
<label>
maxNumberOfDates
<input type="text" name="maxNumberOfDates" placeholder="1">
</label>
</div>
<div class="field">
<label>
maxView
<select name="maxView">
<option value="0">0 – days</option>
<option value="1">1 – months</option>
<option value="2">2 – years</option>
<option value="3" selected>3 – decades</option>
</select>
</label>
</div>
<div class="field">
<label>
minDate
<input type="text" name="minDate" placeholder="null">
</label>
</div>
<div class="field">
<label>
nextArrow
<textarea name="nextArrow" placeholder="»"></textarea>
</label>
</div>
<div class="field">
<label>
orientation
<select name="orientation" >
<option value="auto">auto</option>
<option value="top auto">top auto</option>
<option value="bottom auto">bottom auto</option>
<option value="auto left">auto left</option>
<option value="top left">top left</option>
<option value="bottom left">bottom left</option>
<option value="auto right">auto right</option>
<option value="top right">top right</option>
<option value="bottom right">bottom right</option>
</select>
</label>
</div>
<div class="field">
<label>
pickLevel
<select name="pickLevel">
<option value="0">0 – date</option>
<option value="1">1 – month</option>
<option value="2">2 – year</option>
</select>
</label>
</div>
<div class="field">
<label>
prevArrow
<textarea name="prevArrow" placeholder="«"></textarea>
</label>
</div>
<div class="field">
<input type="checkbox" id="showDaysOfWeek" name="showDaysOfWeek" value="true" checked>
<label for="showDaysOfWeek">showDaysOfWeek</label>
</div>
<div class="field">
<input type="checkbox" id="showOnClick" name="showOnClick" value="true" checked>
<label for="showOnClick">showOnClick</label>
</div>
<div class="field">
<input type="checkbox" id="showOnFocus" name="showOnFocus" value="true" checked>
<label for="showOnFocus">showOnFocus</label>
</div>
<div class="field">
<label>
startView
<select name="startView">
<option value="0">0 – days</option>
<option value="1">1 – months</option>
<option value="2">2 – years</option>
<option value="3">3 – decades</option>
</select>
</label>
</div>
<div class="field">
<label>
title
<input type="text" name="title">
</label>
</div>
<div class="field">
<input type="checkbox" id="todayButton" name="todayButton" value="true">
<label for="todayButton">todayButton</label>
</div>
<div class="field">
<label>
todayButtonMode
<select name="todayButtonMode">
<option value="0">0 – focus</option>
<option value="1">1 – select</option>
</select>
</label>
</div>
<div class="field">
<input type="checkbox" id="todayHighlight" name="todayHighlight" value="true">
<label for="todayHighlight">todayHighlight</label>
</div>
<div class="field">
<input type="checkbox" id="updateOnBlur" name="updateOnBlur" value="true" checked>
<label for="updateOnBlur">updateOnBlur</label>
</div>
<div class="field">
<label>
weekNumbers
<select name="weekNumbers">
<option value="0">0 – None</option>
<option value="1">1 – ISO 8601</option>
<option value="2">2 – Western traditional</option>
<option value="3">3 – Middle Eastern</option>
<option value="4">4 – Guess from weekStart</option>
</select>
</label>
</div>
<div class="field">
<label>
weekStart
<input type="text" name="weekStart" placeholder="0">
</label>
</div>
</form>
</div>
<div class="cell">
<hr>
<h4 class="subtitle">Text direction</h4>
<form id="direction">
<div class="field">
<input type="radio" id="direction-ltr" name="direction" value="ltr" checked>
<label for="direction-ltr">LTR</label>
<input type="radio" id="direction-rtl" name="direction" value="rtl">
<label for="direction-rtl">RTL</label>
</div>
</form>
</div>
</div>
</section>
</aside>
<div class="toggle-button"></div>
<script src="https://code.jquery.com/jquery-3.6.3.min.js" integrity="sha256-pvPw+upLPUjgMXY0G+8O0xUf+/Im1MZjXxxgOcBQBXU=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/foundation-sites@6.7.5/dist/js/foundation.min.js" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.7.0/build/highlight.min.js"></script>
<script src="../dist/js/datepicker-full.js"></script>
<script src="./live-demo.js"></script>
<script>
/*global $ initialize onChangeType onChnageDirection onChangeInputOption onChangeInputOption onChangeTextareaOption onClickcheckboxOptions switchPicker */
window.templates = {
inline: `<div class="date"></div>`,
range: `<div class="input-group date input-daterange">
<input type="text" name="range-start" class="input-group-field">
<span class="input-group-label" disabled>to</span>
<input type="text" name="range-end" class="input-group-field">
</div>`,
};
window.beforeShowFns = {
beforeShowDay(date) {
if (date.getMonth() == new Date().getMonth()) {
switch (date.getDate()) {
case 4:
return {
content: '<span data-tooltip title="Example tooltip">4</span>',
classes: 'background-warning'
};
case 8:
return {content: '🎱'};
case 12:
return "text-success";
}
}
},
beforeShowMonth(date) {
switch (date.getMonth()) {
case 6:
if (date.getFullYear() === new Date().getFullYear()) {
return {content: '🎉'};
}
break;
case 8:
return 'highlighted';
}
},
beforeShowYear(date) {
switch (date.getFullYear()) {
case 2020:
return 'font-italic text-underline';
case 2025:
return {content: '<span data-tooltip data-placement="bottom" title="Tooltip text">2025</span>'};
}
},
beforeShowDecade(date) {
switch (date.getFullYear()) {
case 2000:
return 'font-bold';
case 2100:
return {
content: '2💯',
classes: 'background-success',
};
}
},
};
window.addError = (el, message) => {
el.classList.add('is-invalid-input');
el.parentElement.querySelector('.form-error').textContent = message;
};
window.removeErrors = (el) => {
el.classList.remove('is-invalid-input');
el.parentElement.querySelector('.form-error').textContent = '';
};
$(document).foundation();
initialize();
hljs.highlightAll();
document.getElementById('types').querySelectorAll('input').forEach((el) => {
el.addEventListener('change', onChangeType);
});
document.getElementById('direction').querySelectorAll('input').forEach((el) => {
el.addEventListener('change', onChnageDirection);
});
const optsForm = document.getElementById('options');
optsForm.querySelectorAll('input[type=text], input[type=radio], select').forEach((el) => {
el.addEventListener('change', onChangeInputOption);
});
optsForm.querySelectorAll('textarea').forEach((el) => {
let listener;
if (el.dataset.validator) {
el.addEventListener('change', (ev) => {
if (el.classList.contains(Foundation.Abide.defaults.inputErrorClass)) {
return;
}
onChangeTextareaOption(ev);
});
} else {
listener = onChangeTextareaOption;
}
el.addEventListener('change', listener);
});
optsForm.querySelectorAll('input[type=checkbox]').forEach((el) => {
el.addEventListener('click', onClickCheckboxOptions);
});
switchPicker('input');
const initTooltips = () => {
document.querySelectorAll('[data-tooltip]').forEach((el) => {
if (!el.classList.contains('has-tip')) {
new Foundation.Tooltip($(el));
}
});
};
setInterval(initTooltips, 1000);
</script>
</body>
</html>