flatpickr
Version:
A lightweight, powerful javascript datetime picker
980 lines (691 loc) • 26.1 kB
JavaScript
var flatpickr = function(selector, config) {
'use strict';
let elements, instances, createInstance = element => {
if (element._flatpickr)
element._flatpickr.destroy();
element._flatpickr = new flatpickr.init(element, config);
return element._flatpickr;
};
if (selector.nodeName)
return createInstance(selector);
/*
Utilize the performance of native getters if applicable
https://jsperf.com/getelementsbyclassname-vs-queryselectorall/18
https://jsperf.com/jquery-vs-javascript-performance-comparison/22
*/
else if (/^\#[a-zA-Z0-9\-\_]*$/.test(selector))
return createInstance(document.getElementById(selector.slice(1)));
else if (/^\.[a-zA-Z0-9\-\_]*$/.test(selector))
elements = document.getElementsByClassName(selector.slice(1));
else
elements = document.querySelectorAll(selector);
instances = [].slice.call(elements).map(createInstance);
return {
calendars: instances,
byID: id => {
for(let i=0;i<instances.length;i++)
if(instances[i].element.id === id)
return instances[i];
}
};
};
/**
* @constructor
*/
flatpickr.init = function(element, instanceConfig) {
'use strict';
var createElement = (tag, className, content) => {
let element = document.createElement(tag);
if(content)
element.innerHTML = content;
if(className)
element.className = className;
return element;
};
// functions
var self = this,
init,
wrap,
uDate,
equalDates,
pad,
formatDate,
monthToStr,
isDisabled,
buildMonthNavigation,
buildWeekdays,
buildCalendar,
buildDays,
buildWeeks,
buildTime,
timeWrapper,
yearScroll,
updateValue,
updateNavigationCurrentMonth,
handleYearChange,
changeMonth,
getDaysinMonth,
documentClick,
calendarClick,
getRandomCalendarIdStr,
bind,
triggerChange;
// elements & variables
var calendarContainer = createElement('div', 'flatpickr-calendar'),
navigationCurrentMonth = createElement('span', 'flatpickr-current-month'),
monthsNav = document.createElement('div'),
prevMonthNav = document.createElement('span'),
cur_year = document.createElement('span'),
cur_month = document.createElement('span'),
nextMonthNav = document.createElement('span'),
calendar = createElement('div', "flatpickr-days"),
weekNumbers,
currentDate = new Date(),
wrapperElement = document.createElement('div'),
hourElement,
minuteElement,
am_pm,
clickEvt;
init = function() {
calendarContainer.id = getRandomCalendarIdStr();
instanceConfig = instanceConfig || {};
self.config = {};
self.element = element;
for (var config in self.defaultConfig)
self.config[config] =
instanceConfig[config] ||
self.element.dataset && self.element.dataset[config.toLowerCase()] ||
self.element.getAttribute("data-"+config)||
self.defaultConfig[config];
self.input = (self.config.wrap) ? element.querySelector("[data-input]") : element;
self.input.classList.add("flatpickr-input");
if(self.config.defaultDate)
self.config.defaultDate = uDate(self.config.defaultDate);
if (self.input.value || self.config.defaultDate)
self.selectedDateObj = uDate(self.config.defaultDate||self.input.value);
self.jumpToDate();
wrap();
buildCalendar();
bind();
self.uDate = uDate;
updateValue();
};
getRandomCalendarIdStr = function() {
let randNum, idStr;
do {
randNum = Math.round(Math.random()*Math.pow(10,10));
idStr = 'flatpickr-'+randNum;
} while(document.getElementById(idStr) !== null);
return idStr;
};
uDate = function(date, timeless){
timeless = timeless||false;
if (date === 'today'){
date = new Date();
timeless = true;
}
else if (typeof date === 'string'){
date = date.trim();
if (/^\d\d\d\d\-\d\d\-\d\d/.test(date)) // disable special utc datestring
date = new Date(date.replace(/(\d)-(\d)/g, "$1/$2") );
else if (/^(\d?\d):(\d\d)/.test(date)){ // time-only picker
let matches = date.match(/(\d?\d):(\d\d)/);
date = new Date();
date.setHours(matches[1], matches[2], 0, 0);
}
else if (Date.parse(date))
date = new Date(date);
else {
console.error(`flatpickr: invalid date string ${date}`);
console.info(self.element);
}
}
if(timeless && date)
date.setHours(0,0,0,0);
if(String(self.config.utc) === 'true' && date && !date.fp_isUTC)
date = date.fp_toUTC();
return date;
};
equalDates = (date1, date2) => (
date1.getFullYear() === date2.getFullYear() &&
date1.getMonth() === date2.getMonth() &&
date1.getDate() === date2.getDate()
);
wrap = function() {
wrapperElement.className = 'flatpickr-wrapper';
if(self.config.inline) {
// Wrap input and place calendar underneath
self.element.parentNode.insertBefore(wrapperElement, self.element);
wrapperElement.appendChild(self.element);
wrapperElement.classList.add('inline');
}
else
// Insert at bottom of BODY tag to display outside
// of relative positioned elements with css 'overflow: hidden;'
// property set.
document.body.appendChild(wrapperElement);
if (self.config.altInput){
// replicate self.element
self.altInput = document.createElement(self.input.nodeName);
self.altInput.placeholder = self.input.placeholder;
self.altInput.type = self.input.type||"text";
self.input.type='hidden';
wrapperElement.appendChild(self.altInput);
}
};
getDaysinMonth = function(givenMonth){
let yr = self.currentYear,
month = givenMonth||self.currentMonth;
if (month === 1 && ((yr % 4 === 0) && (yr % 100 !== 0)) || (yr % 400 === 0))
return 29;
return self.l10n.daysInMonth[month];
};
updateValue = function(){
let prev_date;
if (self.selectedDateObj && self.config.enableTime){
prev_date = self.selectedDateObj.getTime();
// update time
var hour = parseInt(hourElement.value, 10),
minute = (60+parseInt(minuteElement.value, 10))%60;
if (!self.config.time_24hr)
hour = hour%12 + 12*(am_pm.innerHTML=== "PM");
self.selectedDateObj.setHours(hour, minute);
hourElement.value =
pad(self.config.time_24hr ? hour : ((12 + hour)%12+12*(hour%12===0)));
minuteElement.value = pad(minute);
}
if (self.altInput && self.selectedDateObj)
self.altInput.value = formatDate(self.config.altFormat);
if (self.selectedDateObj)
self.input.value = formatDate(self.config.dateFormat);
if(prev_date && self.selectedDateObj.getTime() !== prev_date){
triggerChange();
}
};
pad = num =>("0" + num).slice(-2);
formatDate = function(dateFormat) {
if (self.config.noCalendar)
dateFormat = "";
if(self.config.enableTime)
dateFormat+= " " + self.config.timeFormat;
let formattedDate = '',
formats = {
D: () => self.l10n.weekdays.shorthand[ formats.w() ],
F: () => monthToStr(formats.n() - 1, false),
H: () => pad(self.selectedDateObj.getHours()),
K: () => self.selectedDateObj.getHours() > 11 ? "PM" : "AM",
M: () => monthToStr(formats.n() - 1, true),
U: () => self.selectedDateObj.getTime() / 1000,
Y: () => self.selectedDateObj.getFullYear(),
d: () => pad(formats.j()),
h: () => self.selectedDateObj.getHours()%12 ? self.selectedDateObj.getHours()%12 : 12,
i: () => pad(self.selectedDateObj.getMinutes()),
j: () => self.selectedDateObj.getDate(),
l: () => self.l10n.weekdays.longhand[ formats.w() ],
m: () => pad(formats.n()),
n: () => self.selectedDateObj.getMonth() + 1,
w: () => self.selectedDateObj.getDay(),
y: () => String(formats.Y()).substring(2)
},
formatPieces = dateFormat.split('');
for(let i = 0; i < formatPieces.length; i++){
let c = formatPieces[i];
if (formats[c] && formatPieces[i - 1] !== '\\')
formattedDate += formats[c]();
else if (c !== '\\')
formattedDate += c;
}
return formattedDate;
};
monthToStr = function(date, shorthand) {
return shorthand||self.config.shorthandCurrentMonth ? self.l10n.months.shorthand[date] : self.l10n.months.longhand[date];
};
isDisabled = function(check_date){
check_date = uDate(check_date, true); //timeless
let d;
for (let i = 0; i < self.config.disable.length; i++){
d = self.config.disable[i];
if (d instanceof Date || typeof d === 'string')
return uDate(d,true).getTime() == check_date.getTime();
if (check_date >= uDate(d.from) && check_date <= uDate(d.to))
return true;
}
return false;
};
yearScroll = event => {
event.preventDefault();
let delta = Math.max(-1, Math.min(1, (event.wheelDelta || -event.deltaY)));
self.currentYear = event.target.innerHTML = parseInt(event.target.innerHTML, 10) + delta;
self.redraw();
};
timeWrapper = function(e){
e.preventDefault();
let min = parseInt(e.target.min), max = parseInt(e.target.max),
step = parseInt(e.target.step),
delta = step * (Math.max(-1, Math.min(1, (e.wheelDelta || -e.deltaY)))),
newValue = (parseInt(e.target.value) + delta)%(max+(min===0));
if (newValue < min)
newValue = max + (min === 0) - step*(min === 0);
e.target.value = pad(newValue);
};
updateNavigationCurrentMonth = function() {
cur_month.innerHTML = monthToStr(self.currentMonth) +" ";
cur_year.innerHTML = self.currentYear;
};
handleYearChange = function() {
if (self.currentMonth < 0 || self.currentMonth > 11) {
self.currentYear += self.currentMonth % 11;
self.currentMonth = (self.currentMonth + 12) % 12;
}
};
documentClick = function(event) {
if(
wrapperElement.classList.contains("open") &&
(!wrapperElement.contains(event.target) && event.target != self.element)
)
self.close();
};
changeMonth = function(offset) {
self.currentMonth += offset;
handleYearChange();
updateNavigationCurrentMonth();
buildDays();
};
calendarClick = function(e) {
e.preventDefault();
if (e.target.classList.contains('slot'))
{
self.selectedDateObj = new Date(
self.currentYear, self.currentMonth, e.target.innerHTML
);
updateValue();
triggerChange();
buildDays();
if (!self.config.inline && !self.config.enableTime)
self.close();
}
};
buildCalendar = function() {
if (!self.config.noCalendar) {
buildMonthNavigation();
buildWeekdays();
if(self.config.weekNumbers)
buildWeeks();
buildDays();
calendarContainer.appendChild(calendar);
}
wrapperElement.appendChild(calendarContainer);
if(self.config.enableTime)
buildTime();
};
buildMonthNavigation = function() {
monthsNav.className = 'flatpickr-month';
prevMonthNav.className = "flatpickr-prev-month";
prevMonthNav.innerHTML = self.config.prevArrow;
nextMonthNav.className = "flatpickr-next-month";
nextMonthNav.innerHTML = self.config.nextArrow;
cur_month.className = "cur_month";
cur_year.className = "cur_year";
cur_year.title = "Scroll to increment";
navigationCurrentMonth.appendChild(cur_month);
navigationCurrentMonth.appendChild(cur_year);
monthsNav.appendChild(prevMonthNav);
monthsNav.appendChild(navigationCurrentMonth);
monthsNav.appendChild(nextMonthNav);
updateNavigationCurrentMonth();
calendarContainer.appendChild(monthsNav);
};
buildWeekdays = function() {
let weekdayContainer = createElement('div',"flatpickr-weekdays"),
firstDayOfWeek = self.l10n.firstDayOfWeek,
weekdays = self.l10n.weekdays.shorthand.slice();
if (firstDayOfWeek > 0 && firstDayOfWeek < weekdays.length) {
weekdays = [].concat(weekdays.splice(firstDayOfWeek, weekdays.length), weekdays.splice(0, firstDayOfWeek));
}
weekdayContainer.innerHTML = self.config.weekNumbers ? "<span>Wk</span>" : "";
weekdayContainer.innerHTML += '<span>' + weekdays.join('</span><span>') + '</span>';
calendarContainer.appendChild(weekdayContainer);
};
buildWeeks = function(){
calendarContainer.classList.add("hasWeeks");
weekNumbers = createElement("div", 'flatpickr-weeks');
calendarContainer.appendChild(weekNumbers);
};
buildDays = function() {
let firstOfMonth = (new Date(self.currentYear, self.currentMonth, 1).getDay() - self.l10n.firstDayOfWeek + 7)%7,
numDays = getDaysinMonth(),
prevMonthDays = getDaysinMonth((self.currentMonth - 1 + 12)%12),
dayNumber = prevMonthDays + 1 - firstOfMonth,
className,
cur_date,
date_is_disabled,
date_outside_minmax;
if(self.config.weekNumbers && weekNumbers)
weekNumbers.innerHTML = '';
calendar.innerHTML = '';
self.config.minDate = uDate(self.config.minDate, true);
self.config.maxDate = uDate(self.config.maxDate, true);
// prepend days from the ending of previous month
for(; dayNumber <= prevMonthDays; dayNumber++)
calendar.appendChild(createElement("span", "disabled flatpickr-day", dayNumber));
// Start at 1 since there is no 0th day
for (dayNumber = 1; dayNumber <= 42 - firstOfMonth; dayNumber++) {
if (dayNumber <= numDays || dayNumber%7 === 1) // avoids new date objects for appended dates
cur_date = new Date(self.currentYear, self.currentMonth, dayNumber,0,0,0,0);
if(self.config.weekNumbers && weekNumbers && dayNumber%7 === 1)
weekNumbers.appendChild(
createElement("span", "disabled flatpickr-day", cur_date.fp_getWeek())
);
date_outside_minmax =
(self.config.minDate && cur_date < self.config.minDate) ||
(self.config.maxDate && cur_date > self.config.maxDate);
date_is_disabled = dayNumber > numDays || date_outside_minmax || isDisabled(cur_date);
className = date_is_disabled ? "disabled flatpickr-day" : "slot flatpickr-day";
if (!date_is_disabled && !self.selectedDateObj && equalDates(cur_date, currentDate))
className += ' today';
if (!date_is_disabled && self.selectedDateObj && equalDates(cur_date, self.selectedDateObj))
className += ' selected';
calendar.appendChild(
createElement("span", className, (dayNumber > numDays ? dayNumber % numDays : dayNumber))
);
}
};
buildTime = function(){
let timeContainer = createElement("div", "flatpickr-time"),
separator = createElement("span", "flatpickr-time-separator", ":");
hourElement = createElement("input", "flatpickr-hour");
minuteElement = createElement("input", "flatpickr-minute");
hourElement.type = minuteElement.type = "number";
hourElement.value =
self.selectedDateObj ? pad(self.selectedDateObj.getHours()) : 12;
minuteElement.value =
self.selectedDateObj ? pad(self.selectedDateObj.getMinutes()) : "00";
hourElement.step = self.config.hourIncrement;
minuteElement.step = self.config.minuteIncrement;
hourElement.min = +!self.config.time_24hr; // 0 in 24hr mode, 1 in 12hr mode
hourElement.max = self.config.time_24hr ? 23 : 12;
minuteElement.min = 0;
minuteElement.max = 59;
hourElement.title = minuteElement.title = "Scroll to increment";
timeContainer.appendChild(hourElement);
timeContainer.appendChild(separator);
timeContainer.appendChild(minuteElement);
if (!self.config.time_24hr){ // add am_pm if appropriate
am_pm = createElement("span", "flatpickr-am-pm", ["AM","PM"][(hourElement.value > 11)|0]);
am_pm.title="Click to toggle";
timeContainer.appendChild(am_pm);
}
// picking time only
if (self.config.noCalendar && !self.selectedDateObj)
self.selectedDateObj = new Date();
calendarContainer.appendChild(timeContainer);
};
bind = function() {
function am_pm_toggle(e){
e.preventDefault();
am_pm.innerHTML = ["AM","PM"][(am_pm.innerHTML === "AM")|0];
}
if (String(self.config.clickOpens)==='true'){
self.input.addEventListener('focus' , self.open);
if(self.altInput)
self.altInput.addEventListener('focus' , self.open);
}
if (self.config.wrap && self.element.querySelector("[data-open]"))
self.element.querySelector("[data-open]").addEventListener('click' , self.open);
if (self.config.wrap && self.element.querySelector("[data-close]"))
self.element.querySelector("[data-close]").addEventListener('click' , self.close);
if (self.config.wrap && self.element.querySelector("[data-toggle]"))
self.element.querySelector("[data-toggle]").addEventListener('click' , self.toggle);
if (self.config.wrap && self.element.querySelector("[data-clear]"))
self.element.querySelector("[data-clear]").addEventListener('click' , self.clear);
prevMonthNav.addEventListener('click', () => { changeMonth(-1); });
nextMonthNav.addEventListener('click', () => { changeMonth(1); });
cur_year.addEventListener('wheel', yearScroll);
calendar.addEventListener('click', calendarClick);
document.addEventListener('click', documentClick, true);
if (self.config.enableTime){
hourElement.addEventListener("wheel", timeWrapper);
minuteElement.addEventListener("wheel", timeWrapper);
hourElement.addEventListener("mouseout", updateValue);
minuteElement.addEventListener("mouseout", updateValue);
hourElement.addEventListener("change", updateValue);
minuteElement.addEventListener("change", updateValue);
hourElement.addEventListener("click", hourElement.select);
minuteElement.addEventListener("click", minuteElement.select);
if (!self.config.time_24hr) {
am_pm.addEventListener("focus", am_pm.blur);
am_pm.addEventListener("click", am_pm_toggle);
am_pm.addEventListener("wheel", am_pm_toggle);
am_pm.addEventListener("mouseout", updateValue);
}
}
if(document.createEvent){
clickEvt = document.createEvent("MouseEvent");
// without all these args ms edge spergs out
clickEvt.initMouseEvent("click",true,true,window,0,0,0,0,0,false,false,false,false,0,null);
}
else
clickEvt = new MouseEvent('click', {
'view': window,
'bubbles': true,
'cancelable': true
});
};
self.open = function() {
if (self.input.disabled || self.config.inline)
return;
self.input.blur();
self.input.classList.add('active');
if(self.altInput){
self.altInput.blur();
self.altInput.classList.add('active');
}
wrapperElement.classList.add('open');
self.positionCalendar();
if (self.config.onOpen)
self.config.onOpen(self.selectedDateObj, self.input.value);
};
// For calendars inserted in BODY (as opposed to inline wrapper)
// it's necessary to properly calculate top/left position.
self.positionCalendar = function() {
let bounds = self.input.getBoundingClientRect(),
// account for scroll & input height
top = (window.pageYOffset + self.input.offsetHeight + bounds.top),
left = (window.pageXOffset + bounds.left);
wrapperElement.style.top = top + 'px';
wrapperElement.style.left = left + 'px';
};
self.toggle = function() {
if (self.input.disabled)
return;
wrapperElement.classList.toggle('open');
self.positionCalendar();
if(self.altInput)
self.altInput.classList.toggle('active');
self.input.classList.toggle('active');
};
self.close = function() {
wrapperElement.classList.remove('open');
self.input.classList.remove('active');
if (self.altInput)
self.altInput.classList.remove('active');
if (self.config.onClose)
self.config.onClose(self.selectedDateObj, self.input.value);
};
self.clear = function() {
self.input.value="";
self.selectedDateObj = null;
self.jumpToDate();
};
triggerChange = function(){
self.input.dispatchEvent(clickEvt);
if (self.config.onChange)
self.config.onChange(self.selectedDateObj, self.input.value);
};
self.destroy = function() {
document.removeEventListener('click', documentClick, false);
if(self.config.inline) {
let parent = self.element.parentNode,
element = parent.removeChild(self.element);
parent.removeChild(calendarContainer);
parent.parentNode.replaceChild(element, parent);
}
else
document.getElementsByTagName("body")[0].removeChild(wrapperElement);
};
self.redraw = function(){
updateNavigationCurrentMonth();
buildDays();
};
self.jumpToDate = function(jumpDate){
jumpDate = uDate(
jumpDate||self.selectedDateObj||self.config.defaultDate||self.config.minDate||currentDate
);
self.currentYear = jumpDate.getFullYear();
self.currentMonth = jumpDate.getMonth();
self.redraw();
};
self.setDate = function(date, triggerChangeEvent){
if(!( uDate(date) instanceof Date )){
console.error(`flatpickr: setDate() - invalid date: ${date}`);
return;
}
self.selectedDateObj = uDate(date);
self.jumpToDate(self.selectedDateObj);
updateValue();
if(triggerChangeEvent||false)
triggerChange();
};
self.setTime = function(hour, minute, triggerChangeEvent) {
if(!self.selectedDateObj)
return;
self.selectedDateObj.setHours(hour, minute, 0, 0);
updateValue();
if(triggerChangeEvent||false)
triggerChange();
};
self.set = function(key, value){
if (key in self.config) {
self.config[key] = value;
self.jumpToDate();
}
};
try { init(); }
catch(error) {} // skip and carry on
return self;
};
flatpickr.init.prototype = {
l10n: {
weekdays: {
shorthand: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
longhand: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
},
months: {
shorthand: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
longhand: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
},
daysInMonth: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
firstDayOfWeek: 0
},
defaultConfig : {
/* if true, dates will be parsed, formatted, and displayed in UTC.
preloading date strings w/ timezones is recommended but not necessary */
utc: false,
// noCalendar: true will hide the calendar. use for a time picker along w/ enableTime
noCalendar: false,
// wrap: see https://chmln.github.io/flatpickr/#strap
wrap: false,
weekNumbers: false,
/* clicking on input opens the date(time)picker. disable if you wish to open the calendar manually with .open() */
clickOpens: true,
// more date format chars at https://chmln.github.io/flatpickr/#dateformat
dateFormat: 'Y-m-d',
// altInput - see https://chmln.github.io/flatpickr/#altinput
altInput: false,
altFormat: "F j, Y",
// defaultDate - either a datestring or a date object. used for datetimepicker's initial value
defaultDate: null,
// the minimum date that user can pick (inclusive)
minDate: null,
// the maximum date that user can pick (inclusive)
maxDate: null,
// see https://chmln.github.io/flatpickr/#disable
disable: [],
shorthandCurrentMonth: false,
inline: false,
// code for previous/next icons. this is where you put your custom icon code e.g. fontawesome
prevArrow: '<',
nextArrow: '>',
// enables the time picker functionality
enableTime: false,
timeFormat: "h:i K",
// display time picker in 24 hour mode
time_24hr: false,
// step size used when scrolling/incrementing on the hour element
hourIncrement: 1,
// step size used when scrolling/incrementing on the minute element
minuteIncrement: 5,
// onChange callback when user selects/changes selected date or time
onChange: null, //function(dateObj, dateStr){}
// called every time calendar is opened
onOpen: null, // function(dateObj, dateStr){}
// called every time calendar is opened
onClose: null // function(dateObj, dateStr){}
}
};
Date.prototype.fp_incr = function(days){
return new Date(
this.getFullYear(),
this.getMonth(),
this.getDate() + parseInt(days, 10)
);
};
Date.prototype.fp_isUTC = false;
Date.prototype.fp_toUTC = function(){
let new_date = new Date(this.getTime() + this.getTimezoneOffset() * 60000);
new_date.fp_isUTC = true;
return new_date;
};
Date.prototype.fp_getWeek = function() {
let date = new Date(this.getTime());
date.setHours(0,0,0,0);
// Thursday in current week decides the year.
date.setDate(date.getDate() + 3 - (date.getDay() + 6) % 7);
// January 4 is always in week 1.
var week1 = new Date(date.getFullYear(), 0, 4);
// Adjust to Thursday in week 1 and count number of weeks from date to week1.
return 1 + Math.round(((date.getTime() - week1.getTime()) / 86400000 - 3 + (week1.getDay() + 6) % 7) / 7);
};
// classList polyfill
if (!("classList" in document.documentElement) && Object.defineProperty && typeof HTMLElement !== 'undefined') {
Object.defineProperty(HTMLElement.prototype, 'classList', {
get: function() {
var self = this;
function update(fn) {
return function(value) {
var classes = self.className.split(/\s+/),
index = classes.indexOf(value);
fn(classes, index, value);
self.className = classes.join(" ");
};
}
var ret = {
add: update(function(classes, index, value) {
return ~index || classes.push(value);
}),
remove: update(function(classes, index) {
return ~index && classes.splice(index, 1);
}),
toggle: update(function(classes, index, value) {
return ~index ? classes.splice(index, 1) : classes.push(value);
}),
contains: function(value) {
return !!~self.className.split(/\s+/).indexOf(value);
}
};
return ret;
}
});
}
if (typeof module !=='undefined')
module.exports = flatpickr;