470 lines
12 KiB
JavaScript
470 lines
12 KiB
JavaScript
/*eslint no-unused-vars: ["error", { "varsIgnorePattern": "initialize|on[A-Z]*" }]*/
|
||
var templates = {
|
||
input: `<div class="field">
|
||
<div class="control">
|
||
<input type="text" class="input date">
|
||
</div>
|
||
</div>`,
|
||
inline: `<div class="date"></div>`,
|
||
range: `<div class="field has-addons date">
|
||
<div class="control">
|
||
<input type="text" name="range-start" class="input">
|
||
</div>
|
||
<div class="control">
|
||
<a class="button is-static">to</a>
|
||
</div>
|
||
<div class="control">
|
||
<input type="text" name="range-end" class="input">
|
||
</div>
|
||
</div>`,
|
||
};
|
||
var beforeShowFns = {
|
||
beforeShowDay(date) {
|
||
if (date.getMonth() == new Date().getMonth()) {
|
||
switch (date.getDate()) {
|
||
case 4:
|
||
return {
|
||
content: '<span class="tooltip" data-tooltip="Example tooltip">4</span>',
|
||
classes: 'has-background-info'
|
||
};
|
||
case 8:
|
||
return false;
|
||
case 12:
|
||
return "has-text-success";
|
||
}
|
||
}
|
||
},
|
||
beforeShowMonth(date) {
|
||
switch (date.getMonth()) {
|
||
case 6:
|
||
if (date.getFullYear() === new Date().getFullYear()) {
|
||
return {content: '🎉'};
|
||
}
|
||
break;
|
||
case 8:
|
||
return false;
|
||
}
|
||
},
|
||
beforeShowYear(date) {
|
||
switch (date.getFullYear()) {
|
||
case 2017:
|
||
return false;
|
||
case 2020:
|
||
return {content: '<span class="tooltip is-tooltip-bottom" data-tooltip="Tooltip text">2020</span>'};
|
||
}
|
||
},
|
||
beforeShowDecade(date) {
|
||
switch (date.getFullYear()) {
|
||
case 2000:
|
||
return false;
|
||
case 2100:
|
||
return {
|
||
content: '💯',
|
||
classes: 'is-background-success',
|
||
};
|
||
}
|
||
},
|
||
};
|
||
var buttonClass;
|
||
|
||
const today = new Date().setHours(0, 0, 0, 0);
|
||
const defaultOptions = {
|
||
allowOneSidedRange: false,
|
||
autohide: false,
|
||
beforeShowDay: null,
|
||
beforeShowDecade: null,
|
||
beforeShowMonth: null,
|
||
beforeShowYear: null,
|
||
calendarWeeks: false,
|
||
clearBtn: false,
|
||
dateDelimiter: ',',
|
||
datesDisabled: [],
|
||
daysOfWeekDisabled: [],
|
||
daysOfWeekHighlighted: [],
|
||
defaultViewDate: today,
|
||
disableTouchKeyboard: false,
|
||
format: 'mm/dd/yyyy',
|
||
language: 'en',
|
||
maxDate: null,
|
||
maxNumberOfDates: 1,
|
||
maxView: 3,
|
||
minDate: null,
|
||
nextArrow: '»',
|
||
orientation: 'auto',
|
||
pickLevel: 0,
|
||
prevArrow: '«',
|
||
showDaysOfWeek: true,
|
||
showOnClick: true,
|
||
showOnFocus: true,
|
||
startView: 0,
|
||
title: '',
|
||
todayBtn: false,
|
||
todayHighlight: false,
|
||
updateOnBlur: true,
|
||
weekStart: 0,
|
||
};
|
||
const languages = {
|
||
'ar-tn': 'Arabic-Tunisia',
|
||
ar: 'Arabic',
|
||
az: 'Azerbaijani',
|
||
bg: 'Bulgarian',
|
||
bm: 'Bamanankan',
|
||
bn: 'Bengali (Bangla)',
|
||
br: 'Breton',
|
||
bs: 'Bosnian',
|
||
ca: 'Catalan',
|
||
cs: 'Czech',
|
||
cy: 'Welsh',
|
||
da: 'Danish',
|
||
de: 'German',
|
||
el: 'Greek',
|
||
'en-AU': 'Australian English',
|
||
'en-CA': 'Canadian English',
|
||
'en-GB': 'British English',
|
||
'en-IE': 'Irish English',
|
||
'en-NZ': 'New Zealand English',
|
||
'en-ZA': 'South African English',
|
||
eo: 'Esperanto',
|
||
es: 'Spanish',
|
||
et: 'Estonian',
|
||
eu: 'Basque',
|
||
fa: 'Persian',
|
||
fi: 'Finnish',
|
||
fo: 'Faroese',
|
||
'fr-CH': 'French (Switzerland)',
|
||
fr: 'French',
|
||
gl: 'Galician',
|
||
he: 'Hebrew',
|
||
hi: 'Hindi',
|
||
hr: 'Croatian',
|
||
hu: 'Hungarian',
|
||
hy: 'Armenian',
|
||
id: 'Bahasa',
|
||
is: 'Icelandic',
|
||
'it-CH': 'Italian (Switzerland)',
|
||
it: 'Italian',
|
||
ja: 'Japanese',
|
||
ka: 'Georgian',
|
||
kk: 'Kazakh',
|
||
km: 'Khmer',
|
||
ko: 'Korean',
|
||
lt: 'Lithuanian',
|
||
lv: 'Latvian',
|
||
me: 'Montenegrin',
|
||
mk: 'Macedonian',
|
||
mn: 'Mongolian',
|
||
mr: 'Marathi',
|
||
ms: 'Malay',
|
||
'nl-BE': 'Belgium-Dutch',
|
||
nl: 'Dutch',
|
||
no: 'Norwegian',
|
||
oc: 'Occitan',
|
||
pl: 'Polish',
|
||
'pt-BR': 'Brazilian',
|
||
pt: 'Portuguese',
|
||
ro: 'Romanian',
|
||
ru: 'Russian',
|
||
si: 'Sinhala',
|
||
sk: 'Slovak',
|
||
sl: 'Slovene',
|
||
sq: 'Albanian',
|
||
'sr-latn': 'Serbian latin',
|
||
sr: 'Serbian cyrillic',
|
||
sv: 'Swedish',
|
||
sw: 'Swahili',
|
||
ta: 'Tamil',
|
||
tg: 'Tajik',
|
||
th: 'Thai',
|
||
tk: 'Turkmen',
|
||
tr: 'Turkish',
|
||
uk: 'Ukrainian',
|
||
'uz-cyrl': 'Uzbek cyrillic',
|
||
'uz-latn': 'Uzbek latin',
|
||
vi: 'Vietnamese',
|
||
'zh-CN': 'Simplified Chinese',
|
||
'zh-TW': 'Traditional Chinese',
|
||
};
|
||
const range = document.createRange();
|
||
const sandbox = document.getElementById('sandbox');
|
||
const options = document.getElementById('options');
|
||
const jsonFields = ['datesDisabled'];
|
||
|
||
function parseHTML(html) {
|
||
return range.createContextualFragment(html);
|
||
}
|
||
|
||
function getBeforeShowFnSrc(name) {
|
||
return beforeShowFns[name].toString();
|
||
}
|
||
|
||
function switchPicker(type) {
|
||
const options = buttonClass ? {buttonClass} : {};
|
||
if (window.demoPicker) {
|
||
const currentOpts = window.demoPicker instanceof DateRangePicker
|
||
? window.demoPicker.datepickers[0]._options
|
||
: window.demoPicker._options;
|
||
Object.keys(defaultOptions).reduce((opts, key) => {
|
||
if (key in currentOpts && String(currentOpts[key] !== String(defaultOptions[key]))) {
|
||
opts[key] = currentOpts[key];
|
||
}
|
||
return opts;
|
||
}, options);
|
||
|
||
window.demoPicker.destroy();
|
||
sandbox.removeChild(sandbox.firstChild);
|
||
}
|
||
sandbox.appendChild(parseHTML(templates[type]));
|
||
|
||
const el = sandbox.querySelector('.date');
|
||
window.demoPicker = type === 'range'
|
||
? new DateRangePicker(el, options)
|
||
: new Datepicker(el, options);
|
||
}
|
||
|
||
const setOptions = function setOptions(name, value) {
|
||
window.demoPicker.setOptions({[name]: value});
|
||
refreshOptionForm();
|
||
};
|
||
const refreshOptionForm = function refreshOptionForm() {
|
||
const demoPicker = window.demoPicker;
|
||
const rangePicker = demoPicker instanceof DateRangePicker;
|
||
const datepicker = rangePicker ? demoPicker.datepickers[0] : demoPicker;
|
||
const optsForm = document.getElementById('options');
|
||
const {config, _options} = datepicker;
|
||
const configDefaults = {
|
||
minDate: new Date(today).setFullYear(0, 0, 1),
|
||
maxDate: undefined,
|
||
};
|
||
const formElemByName = name => optsForm.querySelector(`[name="${name}"]`);
|
||
const formatDate = val => Datepicker.formatDate(val, config.format, config.lang);
|
||
|
||
if (!rangePicker) {
|
||
const allowOneSided = formElemByName('allowOneSidedRange');
|
||
if (allowOneSided.checked) {
|
||
allowOneSided.checked = false;
|
||
}
|
||
}
|
||
Object.entries(datepicker.config).forEach(entry => {
|
||
const [key, val] = entry;
|
||
let el;
|
||
switch (key) {
|
||
case 'format':
|
||
case 'weekStart':
|
||
el = formElemByName(key);
|
||
if (el.value || val !== defaultOptions[key]) {
|
||
el.value = val;
|
||
}
|
||
break;
|
||
case 'minDate':
|
||
case 'maxDate':
|
||
el = formElemByName(key);
|
||
if (val === configDefaults[key]) {
|
||
if (!el.value || el.value === 'null') {
|
||
break;
|
||
}
|
||
if (_options[key] === null) {
|
||
el.value = '';
|
||
break;
|
||
}
|
||
}
|
||
el.value = formatDate(val);
|
||
break;
|
||
case 'datesDisabled':
|
||
el = formElemByName(key);
|
||
if (val.length === 0) {
|
||
if (!el.value || el.value === '[]') {
|
||
break;
|
||
}
|
||
if (String(_options.datesDisabled) === '[]') {
|
||
el.value = '';
|
||
break;
|
||
}
|
||
}
|
||
el.value = JSON.stringify(val.map(item => formatDate(item)));
|
||
break;
|
||
case 'daysOfWeekDisabled':
|
||
case 'daysOfWeekHighlighted':
|
||
optsForm.querySelectorAll(`[name=${key}`).forEach(chkbox => {
|
||
chkbox.checked = val.includes(Number.parseInt(chkbox.value, 10));
|
||
});
|
||
break;
|
||
case 'defaultViewDate':
|
||
el = formElemByName(key);
|
||
if (val === defaultOptions[key]) {
|
||
if (!el.value || el.value === 'today') {
|
||
break;
|
||
}
|
||
if (_options[key] === 'today') {
|
||
el.value = '';
|
||
break;
|
||
}
|
||
}
|
||
el.value = formatDate(val);
|
||
break;
|
||
case 'maxView':
|
||
case 'pickLevel':
|
||
case 'startView':
|
||
formElemByName(key).value = val;
|
||
break;
|
||
case 'maxNumberOfDates':
|
||
el = formElemByName(key);
|
||
if (rangePicker) {
|
||
if (el.value) {
|
||
el.value = '';
|
||
}
|
||
break;
|
||
}
|
||
if (el.value || val !== defaultOptions[key]) {
|
||
el.value = val;
|
||
}
|
||
break;
|
||
}
|
||
});
|
||
};
|
||
const handleArrayOption = function handleArrayOption(name) {
|
||
const checkedInputs = options.querySelectorAll(`input[name=${name}]:checked`);
|
||
setOptions(name, Array.from(checkedInputs).map(el => Number(el.value)));
|
||
};
|
||
|
||
function updateOption(name, value) {
|
||
switch (name) {
|
||
case 'beforeShowDay':
|
||
case 'beforeShowMonth':
|
||
case 'beforeShowYear':
|
||
case 'beforeShowDecade':
|
||
setOptions(name, value ? beforeShowFns[name] : null);
|
||
return;
|
||
case 'daysOfWeekDisabled':
|
||
case 'daysOfWeekHighlighted':
|
||
handleArrayOption(name, value);
|
||
return;
|
||
}
|
||
|
||
let newValue;
|
||
if (typeof value === 'string') {
|
||
switch (value) {
|
||
case '':
|
||
newValue = defaultOptions[name];
|
||
break;
|
||
case 'null':
|
||
newValue = null;
|
||
break;
|
||
case 'false':
|
||
newValue = false;
|
||
break;
|
||
case 'true':
|
||
newValue = true;
|
||
break;
|
||
default:
|
||
newValue = Number(value);
|
||
if (isNaN(newValue)) {
|
||
newValue = value;
|
||
}
|
||
}
|
||
} else {
|
||
newValue = value;
|
||
}
|
||
setOptions(name, newValue);
|
||
}
|
||
|
||
function addError(el, message) {
|
||
const field = el.parentElement.parentElement;
|
||
field.appendChild(parseHTML(`<p class="help is-danger">${message}</p>`));
|
||
el.classList.add('is-danger');
|
||
}
|
||
|
||
function removeErrors(el) {
|
||
const field = el.parentElement.parentElement;
|
||
field.querySelectorAll('.help.is-danger').forEach((errMsg) => {
|
||
field.removeChild(errMsg);
|
||
});
|
||
el.classList.remove('is-danger');
|
||
}
|
||
|
||
function onChangeType(ev) {
|
||
switchPicker(ev.target.value);
|
||
refreshOptionForm();
|
||
}
|
||
|
||
function onChnageDirection(ev) {
|
||
const defaultDir = window.getComputedStyle(document.body).direction;
|
||
const dir = ev.target.value;
|
||
const mainElem = document.querySelector('main');
|
||
|
||
if (dir !== defaultDir) {
|
||
mainElem.dir = dir;
|
||
} else {
|
||
mainElem.removeAttribute('dir');
|
||
}
|
||
}
|
||
|
||
function onChangeInputOption(ev) {
|
||
updateOption(ev.target.name, ev.target.value);
|
||
}
|
||
|
||
function onChangeTextareaOption(ev) {
|
||
let {value, name} = ev.target;
|
||
if (jsonFields.includes(name)) {
|
||
removeErrors(ev.target);
|
||
if (value.length > 0) {
|
||
try {
|
||
value = JSON.parse(value);
|
||
} catch (err) {
|
||
addError(ev.target, 'Invalid JSON string');
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
if (name === 'datesDisabled') {
|
||
if (value && !Array.isArray(value)) {
|
||
addError(ev.target, 'This option must be an array');
|
||
return;
|
||
}
|
||
}
|
||
updateOption(name, value);
|
||
}
|
||
|
||
function onClickCheckboxOptions(ev) {
|
||
ev.stopPropagation();
|
||
|
||
let checkbox;
|
||
let checked;
|
||
if (ev.target.tagName === 'INPUT') {
|
||
checkbox = ev.target;
|
||
checked = checkbox.checked;
|
||
} else {
|
||
ev.preventDefault();
|
||
checkbox = ev.currentTarget.querySelector('input');
|
||
checked = checkbox.checked = !checkbox.checked;
|
||
}
|
||
|
||
const value = checkbox.value === 'true' ? checked : checkbox.value;
|
||
updateOption(checkbox.name, value);
|
||
}
|
||
|
||
function initialize() {
|
||
// load languages
|
||
const selectElem = options.querySelector('select[name=language]');
|
||
Object.keys(languages).forEach((lang) => {
|
||
document.body.appendChild(parseHTML(`<script src="../dist/js/locales/${lang}.js"></script>`));
|
||
selectElem.appendChild(parseHTML(`<option value="${lang}">${lang} – ${languages[lang]}</option>`));
|
||
});
|
||
|
||
document.querySelector('.toggle-btn').addEventListener('click', () => {
|
||
document.body.classList.toggle('open');
|
||
});
|
||
|
||
document.querySelectorAll('.code-wrap pre').forEach((el) => {
|
||
el.textContent = getBeforeShowFnSrc(el.id.replace('code-', ''));
|
||
});
|
||
|
||
// collapsibles
|
||
document.querySelectorAll('.collapse-button').forEach((el) => {
|
||
el.addEventListener('click', () => {
|
||
const target = document.getElementById(el.dataset.target);
|
||
el.classList.toggle('is-active');
|
||
target.classList.toggle('is-active');
|
||
});
|
||
});
|
||
}
|