update pikaday.js

This commit is contained in:
Régis Hanol 2017-06-23 17:50:13 +02:00
parent 73a4a05c5b
commit 9206741190
1 changed files with 185 additions and 50 deletions

View File

@ -59,22 +59,6 @@
}
},
fireEvent = function(el, eventName, data)
{
var ev;
if (document.createEvent) {
ev = document.createEvent('HTMLEvents');
ev.initEvent(eventName, true, false);
ev = extend(ev, data);
el.dispatchEvent(ev);
} else if (document.createEventObject) {
ev = document.createEventObject();
ev = extend(ev, data);
el.fireEvent('on' + eventName, ev);
}
},
trim = function(str)
{
return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g,'');
@ -160,6 +144,22 @@
return to;
},
fireEvent = function(el, eventName, data)
{
var ev;
if (document.createEvent) {
ev = document.createEvent('HTMLEvents');
ev.initEvent(eventName, true, false);
ev = extend(ev, data);
el.dispatchEvent(ev);
} else if (document.createEventObject) {
ev = document.createEventObject();
ev = extend(ev, data);
el.fireEvent('on' + eventName, ev);
}
},
adjustCalendar = function(calendar) {
if (calendar.month < 0) {
calendar.year -= Math.ceil(Math.abs(calendar.month)/12);
@ -183,6 +183,9 @@
// automatically show/hide the picker on `field` focus (default `true` if `field` is set)
bound: undefined,
// data-attribute on the input field with an aria assistance tekst (only applied when `bound` is set)
ariaLabel: 'Use the arrow keys to pick a date',
// position of the datepicker, relative to the field (default to bottom & left)
// ('bottom' & 'left' keywords are not used, 'top' & 'right' are modifier on the bottom/left position)
position: 'bottom left',
@ -193,6 +196,13 @@
// the default output format for `.toString()` and `field` value
format: 'YYYY-MM-DD',
// the toString function which gets passed a current date object and format
// and returns a string
toString: null,
// used to create date object from current input string
parse: null,
// the initial date to view when first opened
defaultDate: null,
@ -216,6 +226,9 @@
// show week numbers at head of row
showWeekNumber: false,
// Week picker mode
pickWholeWeek: false,
// used internally (don't config outside)
minYear: 0,
maxYear: 9999,
@ -236,6 +249,9 @@
// Render days of the calendar grid that fall in the next or previous month
showDaysInNextAndPreviousMonths: false,
// Allows user to select days that fall in the next or previous month
enableSelectionDaysInNextAndPreviousMonths: false,
// how many months are visible
numberOfMonths: 1,
@ -246,6 +262,9 @@
// Specify a DOM element to render the calendar in
container: undefined,
// Blur field when date is selected
blurFieldOnSelect : true,
// internationalization
i18n: {
previousMonth : 'Previous Month',
@ -258,11 +277,17 @@
// Theme Classname
theme: null,
// events array
events: [],
// callback function
onSelect: null,
onOpen: null,
onClose: null,
onDraw: null
onDraw: null,
// Enable keyboard input
keyboardInput: true
},
@ -281,9 +306,15 @@
renderDay = function(opts)
{
var arr = [];
var ariaSelected = 'false';
if (opts.isEmpty) {
if (opts.showDaysInNextAndPreviousMonths) {
arr.push('is-outside-current-month');
if(!opts.enableSelectionDaysInNextAndPreviousMonths) {
arr.push('is-selection-disabled');
}
} else {
return '<td class="is-empty"></td>';
}
@ -296,6 +327,10 @@
}
if (opts.isSelected) {
arr.push('is-selected');
ariaSelected = 'true';
}
if (opts.hasEvent) {
arr.push('has-event');
}
if (opts.isInRange) {
arr.push('is-inrange');
@ -306,7 +341,7 @@
if (opts.isEndRange) {
arr.push('is-endrange');
}
return '<td data-day="' + opts.day + '" class="' + arr.join(' ') + '">' +
return '<td data-day="' + opts.day + '" class="' + arr.join(' ') + '" aria-selected="' + ariaSelected + '">' +
'<button class="pika-button pika-day" type="button" ' +
'data-pika-year="' + opts.year + '" data-pika-month="' + opts.month + '" data-pika-day="' + opts.day + '">' +
opts.day +
@ -321,9 +356,9 @@
return '<td class="pika-week">' + weekNum + '</td>';
},
renderRow = function(days, isRTL)
renderRow = function(days, isRTL, pickWholeWeek, isRowSelected)
{
return '<tr>' + (isRTL ? days.reverse() : days).join('') + '</tr>';
return '<tr class="pika-row' + (pickWholeWeek ? ' pick-whole-week' : '') + (isRowSelected ? ' is-selected' : '') + '">' + (isRTL ? days.reverse() : days).join('') + '</tr>';
},
renderBody = function(rows)
@ -343,13 +378,13 @@
return '<thead><tr>' + (opts.isRTL ? arr.reverse() : arr).join('') + '</tr></thead>';
},
renderTitle = function(instance, c, year, month, refYear)
renderTitle = function(instance, c, year, month, refYear, randId)
{
var i, j, arr,
opts = instance._o,
isMinYear = year === opts.minYear,
isMaxYear = year === opts.maxYear,
html = '<div class="pika-title">',
html = '<div id="' + randId + '" class="pika-title" role="heading" aria-live="assertive">',
monthHtml,
yearHtml,
prev = true,
@ -361,6 +396,7 @@
((isMinYear && i < opts.minMonth) || (isMaxYear && i > opts.maxMonth) ? 'disabled="disabled"' : '') + '>' +
opts.i18n.months[i] + '</option>');
}
monthHtml = '<div class="pika-label">' + opts.i18n.months[month] + '<select class="pika-select pika-select-month" tabindex="-1">' + arr.join('') + '</select></div>';
if (isArray(opts.yearRange)) {
@ -402,9 +438,9 @@
return html += '</div>';
},
renderTable = function(opts, data)
renderTable = function(opts, data, randId)
{
return '<table cellpadding="0" cellspacing="0" class="pika-table">' + renderHead(opts) + renderBody(data) + '</table>';
return '<table cellpadding="0" cellspacing="0" class="pika-table" role="grid" aria-labelledby="' + randId + '">' + renderHead(opts) + renderBody(data) + '</table>';
},
@ -433,7 +469,7 @@
if (opts.bound) {
sto(function() {
self.hide();
if (opts.field) {
if (opts.blurFieldOnSelect && opts.field) {
opts.field.blur();
}
}, 100);
@ -474,6 +510,36 @@
}
};
self._onKeyChange = function(e)
{
e = e || window.event;
if (self.isVisible()) {
switch(e.keyCode){
case 13:
case 27:
if (opts.field) {
opts.field.blur();
}
break;
case 37:
e.preventDefault();
self.adjustDate('subtract', 1);
break;
case 38:
self.adjustDate('subtract', 7);
break;
case 39:
self.adjustDate('add', 1);
break;
case 40:
self.adjustDate('add', 7);
break;
}
}
};
self._onInputChange = function(e)
{
var date;
@ -481,7 +547,9 @@
if (e.firedBy === self) {
return;
}
if (hasMoment) {
if (opts.parse) {
date = opts.parse(opts.field.value, opts.format);
} else if (hasMoment) {
date = moment(opts.field.value, opts.format, opts.formatStrict);
date = (date && date.isValid()) ? date.toDate() : null;
}
@ -557,6 +625,10 @@
addEvent(self.el, 'touchend', self._onMouseDown, true);
addEvent(self.el, 'change', self._onChange);
if (opts.keyboardInput) {
addEvent(document, 'keydown', self._onKeyChange);
}
if (opts.field) {
if (opts.container) {
opts.container.appendChild(self.el);
@ -670,7 +742,17 @@
*/
toString: function(format)
{
return !isDate(this._d) ? '' : hasMoment ? moment(this._d).format(format || this._o.format) : this._d.toDateString();
format = format || this._o.format;
if (!isDate(this._d)) {
return '';
}
if (this._o.toString) {
return this._o.toString(this._d, format);
}
if (hasMoment) {
return moment(this._d).format(format);
}
return this._d.toDateString();
},
/**
@ -777,6 +859,22 @@
this.adjustCalendars();
},
adjustDate: function(sign, days) {
var day = this.getDate() || new Date();
var difference = parseInt(days)*24*60*60*1000;
var newDay;
if (sign === 'add') {
newDay = new Date(day.valueOf() + difference);
} else if (sign === 'subtract') {
newDay = new Date(day.valueOf() - difference);
}
this.setDate(newDay);
},
adjustCalendars: function() {
this.calendars[0] = adjustCalendar(this.calendars[0]);
for (var c = 1; c < this._o.numberOfMonths; c++) {
@ -832,10 +930,18 @@
*/
setMinDate: function(value)
{
setToStartOfDay(value);
this._o.minDate = value;
this._o.minYear = value.getFullYear();
this._o.minMonth = value.getMonth();
if(value instanceof Date) {
setToStartOfDay(value);
this._o.minDate = value;
this._o.minYear = value.getFullYear();
this._o.minMonth = value.getMonth();
} else {
this._o.minDate = defaults.minDate;
this._o.minYear = defaults.minYear;
this._o.minMonth = defaults.minMonth;
this._o.startRange = defaults.startRange;
}
this.draw();
},
@ -844,10 +950,18 @@
*/
setMaxDate: function(value)
{
setToStartOfDay(value);
this._o.maxDate = value;
this._o.maxYear = value.getFullYear();
this._o.maxMonth = value.getMonth();
if(value instanceof Date) {
setToStartOfDay(value);
this._o.maxDate = value;
this._o.maxYear = value.getFullYear();
this._o.maxMonth = value.getMonth();
} else {
this._o.maxDate = defaults.maxDate;
this._o.maxYear = defaults.maxYear;
this._o.maxMonth = defaults.maxMonth;
this._o.endRange = defaults.endRange;
}
this.draw();
},
@ -874,7 +988,8 @@
maxYear = opts.maxYear,
minMonth = opts.minMonth,
maxMonth = opts.maxMonth,
html = '';
html = '',
randId;
if (this._y <= minYear) {
this._y = minYear;
@ -889,8 +1004,10 @@
}
}
randId = 'pika-title-' + Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 2);
for (var c = 0; c < opts.numberOfMonths; c++) {
html += '<div class="pika-lendar">' + renderTitle(this, c, this.calendars[c].year, this.calendars[c].month, this.calendars[0].year) + this.render(this.calendars[c].year, this.calendars[c].month) + '</div>';
html += '<div class="pika-lendar">' + renderTitle(this, c, this.calendars[c].year, this.calendars[c].month, this.calendars[0].year, randId) + this.render(this.calendars[c].year, this.calendars[c].month, randId) + '</div>';
}
this.el.innerHTML = html;
@ -906,6 +1023,11 @@
if (typeof this._o.onDraw === 'function') {
this._o.onDraw(this);
}
if (opts.bound) {
// let the screen reader user know to use arrow keys
opts.field.setAttribute('aria-label', opts.ariaLabel);
}
},
adjustPosition: function()
@ -962,7 +1084,7 @@
/**
* render HTML for a particular month
*/
render: function(year, month)
render: function(year, month, randId)
{
var opts = this._o,
now = new Date(),
@ -988,11 +1110,13 @@
after -= 7;
}
cells += 7 - after;
var isWeekSelected = false;
for (var i = 0, r = 0; i < cells; i++)
{
var day = new Date(year, month, 1 + (i - before)),
isSelected = isDate(this._d) ? compareDates(day, this._d) : false,
isToday = compareDates(day, now),
hasEvent = opts.events.indexOf(day.toDateString()) !== -1 ? true : false,
isEmpty = i < before || i >= (days + before),
dayNumber = 1 + (i - before),
monthNumber = month,
@ -1021,6 +1145,7 @@
day: dayNumber,
month: monthNumber,
year: yearNumber,
hasEvent: hasEvent,
isSelected: isSelected,
isToday: isToday,
isDisabled: isDisabled,
@ -1028,21 +1153,27 @@
isStartRange: isStartRange,
isEndRange: isEndRange,
isInRange: isInRange,
showDaysInNextAndPreviousMonths: opts.showDaysInNextAndPreviousMonths
showDaysInNextAndPreviousMonths: opts.showDaysInNextAndPreviousMonths,
enableSelectionDaysInNextAndPreviousMonths: opts.enableSelectionDaysInNextAndPreviousMonths
};
if (opts.pickWholeWeek && isSelected) {
isWeekSelected = true;
}
row.push(renderDay(dayConfig));
if (++r === 7) {
if (opts.showWeekNumber) {
row.unshift(renderWeek(i - before, month, year));
}
data.push(renderRow(row, opts.isRTL));
data.push(renderRow(row, opts.isRTL, opts.pickWholeWeek, isWeekSelected));
row = [];
r = 0;
isWeekSelected = false;
}
}
return renderTable(opts, data);
return renderTable(opts, data, randId);
},
isVisible: function()
@ -1052,10 +1183,10 @@
show: function()
{
if (!this._v) {
removeClass(this.el, 'is-hidden');
if (!this.isVisible()) {
this._v = true;
this.draw();
removeClass(this.el, 'is-hidden');
if (this._o.bound) {
addEvent(document, 'click', this._onClick);
this.adjustPosition();
@ -1089,16 +1220,21 @@
*/
destroy: function()
{
var opts = this._o;
this.hide();
removeEvent(this.el, 'mousedown', this._onMouseDown, true);
removeEvent(this.el, 'touchend', this._onMouseDown, true);
removeEvent(this.el, 'change', this._onChange);
if (this._o.field) {
removeEvent(this._o.field, 'change', this._onInputChange);
if (this._o.bound) {
removeEvent(this._o.trigger, 'click', this._onInputClick);
removeEvent(this._o.trigger, 'focus', this._onInputFocus);
removeEvent(this._o.trigger, 'blur', this._onInputBlur);
if (opts.keyboardInput) {
removeEvent(document, 'keydown', this._onKeyChange);
}
if (opts.field) {
removeEvent(opts.field, 'change', this._onInputChange);
if (opts.bound) {
removeEvent(opts.trigger, 'click', this._onInputClick);
removeEvent(opts.trigger, 'focus', this._onInputFocus);
removeEvent(opts.trigger, 'blur', this._onInputBlur);
}
}
if (this.el.parentNode) {
@ -1109,5 +1245,4 @@
};
return Pikaday;
}));