UNPKG

42.1 kBJavaScriptView Raw
1import moment from 'moment';
2
3var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
4
5function createCommonjsModule(fn, basedir, module) {
6 return module = {
7 path: basedir,
8 exports: {},
9 require: function (path, base) {
10 return commonjsRequire(path, (base === undefined || base === null) ? module.path : base);
11 }
12 }, fn(module, module.exports), module.exports;
13}
14
15function commonjsRequire () {
16 throw new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs');
17}
18
19var pikaday = createCommonjsModule(function (module, exports) {
20/*!
21 * Pikaday
22 *
23 * Copyright © 2014 David Bushell | BSD & MIT license | https://github.com/dbushell/Pikaday
24 */
25(function (root, factory)
26{
27
28 var moment$1;
29 {
30 // CommonJS module
31 // Load moment.js as an optional dependency
32 try { moment$1 = moment; } catch (e) {}
33 module.exports = factory(moment$1);
34 }
35}(commonjsGlobal, function (moment)
36{
37
38 /**
39 * feature detection and helper functions
40 */
41 var hasMoment = typeof moment === 'function',
42
43 hasEventListeners = !!window.addEventListener,
44
45 document = window.document,
46
47 sto = window.setTimeout,
48
49 addEvent = function(el, e, callback, capture)
50 {
51 if (hasEventListeners) {
52 el.addEventListener(e, callback, !!capture);
53 } else {
54 el.attachEvent('on' + e, callback);
55 }
56 },
57
58 removeEvent = function(el, e, callback, capture)
59 {
60 if (hasEventListeners) {
61 el.removeEventListener(e, callback, !!capture);
62 } else {
63 el.detachEvent('on' + e, callback);
64 }
65 },
66
67 trim = function(str)
68 {
69 return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g,'');
70 },
71
72 hasClass = function(el, cn)
73 {
74 return (' ' + el.className + ' ').indexOf(' ' + cn + ' ') !== -1;
75 },
76
77 addClass = function(el, cn)
78 {
79 if (!hasClass(el, cn)) {
80 el.className = (el.className === '') ? cn : el.className + ' ' + cn;
81 }
82 },
83
84 removeClass = function(el, cn)
85 {
86 el.className = trim((' ' + el.className + ' ').replace(' ' + cn + ' ', ' '));
87 },
88
89 isArray = function(obj)
90 {
91 return (/Array/).test(Object.prototype.toString.call(obj));
92 },
93
94 isDate = function(obj)
95 {
96 return (/Date/).test(Object.prototype.toString.call(obj)) && !isNaN(obj.getTime());
97 },
98
99 isWeekend = function(date)
100 {
101 var day = date.getDay();
102 return day === 0 || day === 6;
103 },
104
105 isLeapYear = function(year)
106 {
107 // solution by Matti Virkkunen: http://stackoverflow.com/a/4881951
108 return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
109 },
110
111 getDaysInMonth = function(year, month)
112 {
113 return [31, isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
114 },
115
116 setToStartOfDay = function(date)
117 {
118 if (isDate(date)) date.setHours(0,0,0,0);
119 },
120
121 compareDates = function(a,b)
122 {
123 // weak date comparison (use setToStartOfDay(date) to ensure correct result)
124 return a.getTime() === b.getTime();
125 },
126
127 extend = function(to, from, overwrite)
128 {
129 var prop, hasProp;
130 for (prop in from) {
131 hasProp = to[prop] !== undefined;
132 if (hasProp && typeof from[prop] === 'object' && from[prop] !== null && from[prop].nodeName === undefined) {
133 if (isDate(from[prop])) {
134 if (overwrite) {
135 to[prop] = new Date(from[prop].getTime());
136 }
137 }
138 else if (isArray(from[prop])) {
139 if (overwrite) {
140 to[prop] = from[prop].slice(0);
141 }
142 } else {
143 to[prop] = extend({}, from[prop], overwrite);
144 }
145 } else if (overwrite || !hasProp) {
146 to[prop] = from[prop];
147 }
148 }
149 return to;
150 },
151
152 fireEvent = function(el, eventName, data)
153 {
154 var ev;
155
156 if (document.createEvent) {
157 ev = document.createEvent('HTMLEvents');
158 ev.initEvent(eventName, true, false);
159 ev = extend(ev, data);
160 el.dispatchEvent(ev);
161 } else if (document.createEventObject) {
162 ev = document.createEventObject();
163 ev = extend(ev, data);
164 el.fireEvent('on' + eventName, ev);
165 }
166 },
167
168 adjustCalendar = function(calendar) {
169 if (calendar.month < 0) {
170 calendar.year -= Math.ceil(Math.abs(calendar.month)/12);
171 calendar.month += 12;
172 }
173 if (calendar.month > 11) {
174 calendar.year += Math.floor(Math.abs(calendar.month)/12);
175 calendar.month -= 12;
176 }
177 return calendar;
178 },
179
180 /**
181 * defaults and localisation
182 */
183 defaults = {
184
185 // bind the picker to a form field
186 field: null,
187
188 // automatically show/hide the picker on `field` focus (default `true` if `field` is set)
189 bound: undefined,
190
191 // position of the datepicker, relative to the field (default to bottom & left)
192 // ('bottom' & 'left' keywords are not used, 'top' & 'right' are modifier on the bottom/left position)
193 position: 'bottom left',
194
195 // automatically fit in the viewport even if it means repositioning from the position option
196 reposition: true,
197
198 // the default output format for `.toString()` and `field` value
199 format: 'YYYY-MM-DD',
200
201 // the toString function which gets passed a current date object and format
202 // and returns a string
203 toString: null,
204
205 // used to create date object from current input string
206 parse: null,
207
208 // the initial date to view when first opened
209 defaultDate: null,
210
211 // make the `defaultDate` the initial selected value
212 setDefaultDate: false,
213
214 // first day of week (0: Sunday, 1: Monday etc)
215 firstDay: 0,
216
217 // the default flag for moment's strict date parsing
218 formatStrict: false,
219
220 // the minimum/earliest date that can be selected
221 minDate: null,
222 // the maximum/latest date that can be selected
223 maxDate: null,
224
225 // number of years either side, or array of upper/lower range
226 yearRange: 10,
227
228 // show week numbers at head of row
229 showWeekNumber: false,
230
231 // Week picker mode
232 pickWholeWeek: false,
233
234 // used internally (don't config outside)
235 minYear: 0,
236 maxYear: 9999,
237 minMonth: undefined,
238 maxMonth: undefined,
239
240 startRange: null,
241 endRange: null,
242
243 isRTL: false,
244
245 // Additional text to append to the year in the calendar title
246 yearSuffix: '',
247
248 // Render the month after year in the calendar title
249 showMonthAfterYear: false,
250
251 // Render days of the calendar grid that fall in the next or previous month
252 showDaysInNextAndPreviousMonths: false,
253
254 // Allows user to select days that fall in the next or previous month
255 enableSelectionDaysInNextAndPreviousMonths: false,
256
257 // how many months are visible
258 numberOfMonths: 1,
259
260 // when numberOfMonths is used, this will help you to choose where the main calendar will be (default `left`, can be set to `right`)
261 // only used for the first display or when a selected date is not visible
262 mainCalendar: 'left',
263
264 // Specify a DOM element to render the calendar in
265 container: undefined,
266
267 // Blur field when date is selected
268 blurFieldOnSelect : true,
269
270 // internationalization
271 i18n: {
272 previousMonth : 'Previous Month',
273 nextMonth : 'Next Month',
274 months : ['January','February','March','April','May','June','July','August','September','October','November','December'],
275 weekdays : ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],
276 weekdaysShort : ['Sun','Mon','Tue','Wed','Thu','Fri','Sat']
277 },
278
279 // Theme Classname
280 theme: null,
281
282 // events array
283 events: [],
284
285 // callback function
286 onSelect: null,
287 onOpen: null,
288 onClose: null,
289 onDraw: null,
290
291 // Enable keyboard input
292 keyboardInput: true
293 },
294
295
296 /**
297 * templating functions to abstract HTML rendering
298 */
299 renderDayName = function(opts, day, abbr)
300 {
301 day += opts.firstDay;
302 while (day >= 7) {
303 day -= 7;
304 }
305 return abbr ? opts.i18n.weekdaysShort[day] : opts.i18n.weekdays[day];
306 },
307
308 renderDay = function(opts)
309 {
310 var arr = [];
311 var ariaSelected = 'false';
312 if (opts.isEmpty) {
313 if (opts.showDaysInNextAndPreviousMonths) {
314 arr.push('is-outside-current-month');
315
316 if(!opts.enableSelectionDaysInNextAndPreviousMonths) {
317 arr.push('is-selection-disabled');
318 }
319
320 } else {
321 return '<td class="is-empty"></td>';
322 }
323 }
324 if (opts.isDisabled) {
325 arr.push('is-disabled');
326 }
327 if (opts.isToday) {
328 arr.push('is-today');
329 }
330 if (opts.isSelected) {
331 arr.push('is-selected');
332 ariaSelected = 'true';
333 }
334 if (opts.hasEvent) {
335 arr.push('has-event');
336 }
337 if (opts.isInRange) {
338 arr.push('is-inrange');
339 }
340 if (opts.isStartRange) {
341 arr.push('is-startrange');
342 }
343 if (opts.isEndRange) {
344 arr.push('is-endrange');
345 }
346 return '<td data-day="' + opts.day + '" class="' + arr.join(' ') + '" aria-selected="' + ariaSelected + '">' +
347 '<button tabIndex="-1" class="pika-button pika-day" type="button" ' +
348 'data-pika-year="' + opts.year + '" data-pika-month="' + opts.month + '" data-pika-day="' + opts.day + '">' +
349 opts.day +
350 '</button>' +
351 '</td>';
352 },
353
354 renderWeek = function (d, m, y) {
355 // Lifted from http://javascript.about.com/library/blweekyear.htm, lightly modified.
356 var onejan = new Date(y, 0, 1),
357 weekNum = Math.ceil((((new Date(y, m, d) - onejan) / 86400000) + onejan.getDay()+1)/7);
358 return '<td class="pika-week">' + weekNum + '</td>';
359 },
360
361 renderRow = function(days, isRTL, pickWholeWeek, isRowSelected)
362 {
363 return '<tr class="pika-row' + (pickWholeWeek ? ' pick-whole-week' : '') + (isRowSelected ? ' is-selected' : '') + '">' + (isRTL ? days.reverse() : days).join('') + '</tr>';
364 },
365
366 renderBody = function(rows)
367 {
368 return '<tbody>' + rows.join('') + '</tbody>';
369 },
370
371 renderHead = function(opts)
372 {
373 var i, arr = [];
374 if (opts.showWeekNumber) {
375 arr.push('<th></th>');
376 }
377 for (i = 0; i < 7; i++) {
378 arr.push('<th scope="col"><abbr title="' + renderDayName(opts, i) + '">' + renderDayName(opts, i, true) + '</abbr></th>');
379 }
380 return '<thead><tr>' + (opts.isRTL ? arr.reverse() : arr).join('') + '</tr></thead>';
381 },
382
383 renderTitle = function(instance, c, year, month, refYear, randId)
384 {
385 var i, j, arr,
386 opts = instance._o,
387 isMinYear = year === opts.minYear,
388 isMaxYear = year === opts.maxYear,
389 html = '<div id="' + randId + '" class="pika-title">',
390 monthHtml,
391 yearHtml,
392 prev = true,
393 next = true;
394
395 for (arr = [], i = 0; i < 12; i++) {
396 arr.push('<option value="' + (year === refYear ? i - c : 12 + i - c) + '"' +
397 (i === month ? ' selected="selected"': '') +
398 ((isMinYear && i < opts.minMonth) || (isMaxYear && i > opts.maxMonth) ? 'disabled="disabled"' : '') + '>' +
399 opts.i18n.months[i] + '</option>');
400 }
401
402 monthHtml = '<div class="pika-label">' + opts.i18n.months[month] + '<select aria-label="select month" class="pika-select pika-select-month" tabindex="-1">' + arr.join('') + '</select></div>';
403
404 if (isArray(opts.yearRange)) {
405 i = opts.yearRange[0];
406 j = opts.yearRange[1] + 1;
407 } else {
408 i = year - opts.yearRange;
409 j = 1 + year + opts.yearRange;
410 }
411
412 for (arr = []; i < j && i <= opts.maxYear; i++) {
413 if (i >= opts.minYear) {
414 arr.push('<option value="' + i + '"' + (i === year ? ' selected="selected"': '') + '>' + (i) + '</option>');
415 }
416 }
417 yearHtml = '<div class="pika-label">' + year + opts.yearSuffix + '<select aria-label="select year" class="pika-select pika-select-year" tabindex="-1">' + arr.join('') + '</select></div>';
418
419 if (opts.showMonthAfterYear) {
420 html += yearHtml + monthHtml;
421 } else {
422 html += monthHtml + yearHtml;
423 }
424
425 if (isMinYear && (month === 0 || opts.minMonth >= month)) {
426 prev = false;
427 }
428
429 if (isMaxYear && (month === 11 || opts.maxMonth <= month)) {
430 next = false;
431 }
432
433 if (c === 0) {
434 html += '<button tabIndex="-1" class="pika-prev' + (prev ? '' : ' is-disabled') + '" type="button">' + opts.i18n.previousMonth + '</button>';
435 }
436 if (c === (instance._o.numberOfMonths - 1) ) {
437 html += '<button tabIndex="-1" class="pika-next' + (next ? '' : ' is-disabled') + '" type="button">' + opts.i18n.nextMonth + '</button>';
438 }
439
440 return html += '</div>';
441 },
442
443 renderTable = function(opts, data, randId)
444 {
445 return '<table cellpadding="0" cellspacing="0" class="pika-table" role="grid" aria-labelledby="' + randId + '">' + renderHead(opts) + renderBody(data) + '</table>';
446 },
447
448
449 /**
450 * Pikaday constructor
451 */
452 Pikaday = function(options)
453 {
454 var self = this,
455 opts = self.config(options);
456
457 self._onMouseDown = function(e)
458 {
459 if (!self._v) {
460 return;
461 }
462 e = e || window.event;
463 var target = e.target || e.srcElement;
464 if (!target) {
465 return;
466 }
467
468 if (!hasClass(target, 'is-disabled')) {
469 if (hasClass(target, 'pika-button') && !hasClass(target, 'is-empty') && !hasClass(target.parentNode, 'is-disabled')) {
470 self.setDate(new Date(target.getAttribute('data-pika-year'), target.getAttribute('data-pika-month'), target.getAttribute('data-pika-day')));
471 if (opts.bound) {
472 sto(function() {
473 self.hide();
474 if (opts.blurFieldOnSelect && opts.field) {
475 opts.field.blur();
476 }
477 }, 100);
478 }
479 }
480 else if (hasClass(target, 'pika-prev')) {
481 self.prevMonth();
482 }
483 else if (hasClass(target, 'pika-next')) {
484 self.nextMonth();
485 }
486 }
487 if (!hasClass(target, 'pika-select')) {
488 // if this is touch event prevent mouse events emulation
489 if (e.preventDefault) {
490 e.preventDefault();
491 } else {
492 e.returnValue = false;
493 return false;
494 }
495 } else {
496 self._c = true;
497 }
498 };
499
500 self._onChange = function(e)
501 {
502 e = e || window.event;
503 var target = e.target || e.srcElement;
504 if (!target) {
505 return;
506 }
507 if (hasClass(target, 'pika-select-month')) {
508 self.gotoMonth(target.value);
509 }
510 else if (hasClass(target, 'pika-select-year')) {
511 self.gotoYear(target.value);
512 }
513 };
514
515 self._onKeyChange = function(e)
516 {
517 e = e || window.event;
518 // ignore if event comes from input box
519 if (self.isVisible() && e.target && e.target.type !== 'text') {
520
521 switch(e.keyCode){
522 case 13:
523 case 27:
524 if (opts.field) {
525 opts.field.blur();
526 }
527 break;
528 case 37:
529 e.preventDefault();
530 self.adjustDate('subtract', 1);
531 break;
532 case 38:
533 self.adjustDate('subtract', 7);
534 break;
535 case 39:
536 self.adjustDate('add', 1);
537 break;
538 case 40:
539 self.adjustDate('add', 7);
540 break;
541 }
542 }
543 };
544
545 self._onInputChange = function(e)
546 {
547 var date;
548
549 if (e.firedBy === self) {
550 return;
551 }
552 if (opts.parse) {
553 date = opts.parse(opts.field.value, opts.format);
554 } else if (hasMoment) {
555 date = moment(opts.field.value, opts.format, opts.formatStrict);
556 date = (date && date.isValid()) ? date.toDate() : null;
557 }
558 else {
559 date = new Date(Date.parse(opts.field.value));
560 }
561 // if (isDate(date)) {
562 // self.setDate(date);
563 // }
564 // if (!self._v) {
565 // self.show();
566 // }
567 };
568
569 self._onInputFocus = function()
570 {
571 self.show();
572 };
573
574 self._onInputClick = function()
575 {
576 self.show();
577 };
578
579 self._onInputBlur = function()
580 {
581 // IE allows pika div to gain focus; catch blur the input field
582 var pEl = document.activeElement;
583 do {
584 if (hasClass(pEl, 'pika-single')) {
585 return;
586 }
587 }
588 while ((pEl = pEl.parentNode));
589
590 if (!self._c) {
591 self._b = sto(function() {
592 self.hide();
593 }, 50);
594 }
595 self._c = false;
596 };
597
598 self._onClick = function(e)
599 {
600 e = e || window.event;
601 var target = e.target || e.srcElement,
602 pEl = target;
603 if (!target) {
604 return;
605 }
606 if (!hasEventListeners && hasClass(target, 'pika-select')) {
607 if (!target.onchange) {
608 target.setAttribute('onchange', 'return;');
609 addEvent(target, 'change', self._onChange);
610 }
611 }
612 do {
613 if (hasClass(pEl, 'pika-single') || pEl === opts.trigger) {
614 return;
615 }
616 }
617 while ((pEl = pEl.parentNode));
618 if (self._v && target !== opts.trigger && pEl !== opts.trigger) {
619 self.hide();
620 }
621 };
622
623 self.el = document.createElement('div');
624 self.el.className = 'pika-single' + (opts.isRTL ? ' is-rtl' : '') + (opts.theme ? ' ' + opts.theme : '');
625
626 addEvent(self.el, 'mousedown', self._onMouseDown, true);
627 addEvent(self.el, 'touchend', self._onMouseDown, true);
628 addEvent(self.el, 'change', self._onChange);
629
630 if (opts.keyboardInput) {
631 addEvent(document, 'keydown', self._onKeyChange);
632 }
633
634 if (opts.field) {
635 if (opts.container) {
636 opts.container.appendChild(self.el);
637 } else if (opts.bound) {
638 document.body.appendChild(self.el);
639 } else {
640 opts.field.parentNode.insertBefore(self.el, opts.field.nextSibling);
641 }
642 addEvent(opts.field, 'change', self._onInputChange);
643
644 if (!opts.defaultDate) {
645 if (hasMoment && opts.field.value) {
646 opts.defaultDate = moment(opts.field.value, opts.format).toDate();
647 } else {
648 opts.defaultDate = new Date(Date.parse(opts.field.value));
649 }
650 opts.setDefaultDate = true;
651 }
652 }
653
654 var defDate = opts.defaultDate;
655
656 if (isDate(defDate)) {
657 if (opts.setDefaultDate) {
658 self.setDate(defDate, true);
659 } else {
660 self.gotoDate(defDate);
661 }
662 } else {
663 self.gotoDate(new Date());
664 }
665
666 if (opts.bound) {
667 this.hide();
668 self.el.className += ' is-bound';
669 addEvent(opts.trigger, 'click', self._onInputClick);
670 addEvent(opts.trigger, 'focus', self._onInputFocus);
671 addEvent(opts.trigger, 'blur', self._onInputBlur);
672 } else {
673 this.show();
674 }
675 };
676
677
678 /**
679 * public Pikaday API
680 */
681 Pikaday.prototype = {
682
683
684 /**
685 * configure functionality
686 */
687 config: function(options)
688 {
689 if (!this._o) {
690 this._o = extend({}, defaults, true);
691 }
692
693 var opts = extend(this._o, options, true);
694
695 opts.isRTL = !!opts.isRTL;
696
697 opts.field = (opts.field && opts.field.nodeName) ? opts.field : null;
698
699 opts.theme = (typeof opts.theme) === 'string' && opts.theme ? opts.theme : null;
700
701 opts.bound = !!(opts.bound !== undefined ? opts.field && opts.bound : opts.field);
702
703 opts.trigger = (opts.trigger && opts.trigger.nodeName) ? opts.trigger : opts.field;
704
705 opts.disableWeekends = !!opts.disableWeekends;
706
707 opts.disableDayFn = (typeof opts.disableDayFn) === 'function' ? opts.disableDayFn : null;
708
709 var nom = parseInt(opts.numberOfMonths, 10) || 1;
710 opts.numberOfMonths = nom > 4 ? 4 : nom;
711
712 if (!isDate(opts.minDate)) {
713 opts.minDate = false;
714 }
715 if (!isDate(opts.maxDate)) {
716 opts.maxDate = false;
717 }
718 if ((opts.minDate && opts.maxDate) && opts.maxDate < opts.minDate) {
719 opts.maxDate = opts.minDate = false;
720 }
721 if (opts.minDate) {
722 this.setMinDate(opts.minDate);
723 }
724 if (opts.maxDate) {
725 this.setMaxDate(opts.maxDate);
726 }
727
728 if (isArray(opts.yearRange)) {
729 var fallback = new Date().getFullYear() - 10;
730 opts.yearRange[0] = parseInt(opts.yearRange[0], 10) || fallback;
731 opts.yearRange[1] = parseInt(opts.yearRange[1], 10) || fallback;
732 } else {
733 opts.yearRange = Math.abs(parseInt(opts.yearRange, 10)) || defaults.yearRange;
734 if (opts.yearRange > 100) {
735 opts.yearRange = 100;
736 }
737 }
738
739 return opts;
740 },
741
742 /**
743 * return a formatted string of the current selection (using Moment.js if available)
744 */
745 toString: function(format)
746 {
747 format = format || this._o.format;
748 if (!isDate(this._d)) {
749 return '';
750 }
751 if (this._o.toString) {
752 return this._o.toString(this._d, format);
753 }
754 if (hasMoment) {
755 return moment(this._d).format(format);
756 }
757 return this._d.toDateString();
758 },
759
760 /**
761 * return a Moment.js object of the current selection (if available)
762 */
763 getMoment: function()
764 {
765 return hasMoment ? moment(this._d) : null;
766 },
767
768 /**
769 * set the current selection from a Moment.js object (if available)
770 */
771 setMoment: function(date, preventOnSelect)
772 {
773 if (hasMoment && moment.isMoment(date)) {
774 this.setDate(date.toDate(), preventOnSelect);
775 }
776 },
777
778 /**
779 * return a Date object of the current selection
780 */
781 getDate: function()
782 {
783 return isDate(this._d) ? new Date(this._d.getTime()) : null;
784 },
785
786 /**
787 * set the current selection
788 */
789 setDate: function(date, preventOnSelect)
790 {
791 if (!date) {
792 this._d = null;
793
794 if (this._o.field) {
795 this._o.field.value = '';
796 fireEvent(this._o.field, 'change', { firedBy: this });
797 }
798
799 return this.draw();
800 }
801 if (typeof date === 'string') {
802 date = new Date(Date.parse(date));
803 }
804 if (!isDate(date)) {
805 return;
806 }
807
808 var min = this._o.minDate,
809 max = this._o.maxDate;
810
811 if (isDate(min) && date < min) {
812 date = min;
813 } else if (isDate(max) && date > max) {
814 date = max;
815 }
816
817 this._d = new Date(date.getTime());
818 setToStartOfDay(this._d);
819 this.gotoDate(this._d);
820
821 if (this._o.field) {
822 this._o.field.value = this.toString();
823 fireEvent(this._o.field, 'change', { firedBy: this });
824 }
825 if (!preventOnSelect && typeof this._o.onSelect === 'function') {
826 this._o.onSelect.call(this, this.getDate());
827 }
828 },
829
830 /**
831 * change view to a specific date
832 */
833 gotoDate: function(date)
834 {
835 var newCalendar = true;
836
837 if (!isDate(date)) {
838 return;
839 }
840
841 if (this.calendars) {
842 var firstVisibleDate = new Date(this.calendars[0].year, this.calendars[0].month, 1),
843 lastVisibleDate = new Date(this.calendars[this.calendars.length-1].year, this.calendars[this.calendars.length-1].month, 1),
844 visibleDate = date.getTime();
845 // get the end of the month
846 lastVisibleDate.setMonth(lastVisibleDate.getMonth()+1);
847 lastVisibleDate.setDate(lastVisibleDate.getDate()-1);
848 newCalendar = (visibleDate < firstVisibleDate.getTime() || lastVisibleDate.getTime() < visibleDate);
849 }
850
851 if (newCalendar) {
852 this.calendars = [{
853 month: date.getMonth(),
854 year: date.getFullYear()
855 }];
856 if (this._o.mainCalendar === 'right') {
857 this.calendars[0].month += 1 - this._o.numberOfMonths;
858 }
859 }
860
861 this.adjustCalendars();
862 },
863
864 adjustDate: function(sign, days) {
865
866 var day = this.getDate() || new Date();
867 var difference = parseInt(days)*24*60*60*1000;
868
869 var newDay;
870
871 if (sign === 'add') {
872 newDay = new Date(day.valueOf() + difference);
873 } else if (sign === 'subtract') {
874 newDay = new Date(day.valueOf() - difference);
875 }
876
877 this.setDate(newDay);
878 },
879
880 adjustCalendars: function() {
881 this.calendars[0] = adjustCalendar(this.calendars[0]);
882 for (var c = 1; c < this._o.numberOfMonths; c++) {
883 this.calendars[c] = adjustCalendar({
884 month: this.calendars[0].month + c,
885 year: this.calendars[0].year
886 });
887 }
888 this.draw();
889 },
890
891 gotoToday: function()
892 {
893 this.gotoDate(new Date());
894 },
895
896 /**
897 * change view to a specific month (zero-index, e.g. 0: January)
898 */
899 gotoMonth: function(month)
900 {
901 if (!isNaN(month)) {
902 this.calendars[0].month = parseInt(month, 10);
903 this.adjustCalendars();
904 }
905 },
906
907 nextMonth: function()
908 {
909 this.calendars[0].month++;
910 this.adjustCalendars();
911 },
912
913 prevMonth: function()
914 {
915 this.calendars[0].month--;
916 this.adjustCalendars();
917 },
918
919 /**
920 * change view to a specific full year (e.g. "2012")
921 */
922 gotoYear: function(year)
923 {
924 if (!isNaN(year)) {
925 this.calendars[0].year = parseInt(year, 10);
926 this.adjustCalendars();
927 }
928 },
929
930 /**
931 * change the minDate
932 */
933 setMinDate: function(value)
934 {
935 if(value instanceof Date) {
936 setToStartOfDay(value);
937 this._o.minDate = value;
938 this._o.minYear = value.getFullYear();
939 this._o.minMonth = value.getMonth();
940 } else {
941 this._o.minDate = defaults.minDate;
942 this._o.minYear = defaults.minYear;
943 this._o.minMonth = defaults.minMonth;
944 this._o.startRange = defaults.startRange;
945 }
946
947 this.draw();
948 },
949
950 /**
951 * change the maxDate
952 */
953 setMaxDate: function(value)
954 {
955 if(value instanceof Date) {
956 setToStartOfDay(value);
957 this._o.maxDate = value;
958 this._o.maxYear = value.getFullYear();
959 this._o.maxMonth = value.getMonth();
960 } else {
961 this._o.maxDate = defaults.maxDate;
962 this._o.maxYear = defaults.maxYear;
963 this._o.maxMonth = defaults.maxMonth;
964 this._o.endRange = defaults.endRange;
965 }
966
967 this.draw();
968 },
969
970 setStartRange: function(value)
971 {
972 this._o.startRange = value;
973 },
974
975 setEndRange: function(value)
976 {
977 this._o.endRange = value;
978 },
979
980 /**
981 * refresh the HTML
982 */
983 draw: function(force)
984 {
985 if (!this._v && !force) {
986 return;
987 }
988 var opts = this._o,
989 minYear = opts.minYear,
990 maxYear = opts.maxYear,
991 minMonth = opts.minMonth,
992 maxMonth = opts.maxMonth,
993 html = '',
994 randId;
995
996 if (this._y <= minYear) {
997 this._y = minYear;
998 if (!isNaN(minMonth) && this._m < minMonth) {
999 this._m = minMonth;
1000 }
1001 }
1002 if (this._y >= maxYear) {
1003 this._y = maxYear;
1004 if (!isNaN(maxMonth) && this._m > maxMonth) {
1005 this._m = maxMonth;
1006 }
1007 }
1008
1009 for (var c = 0; c < opts.numberOfMonths; c++) {
1010 randId = 'pika-title-' + Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 2);
1011 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>';
1012 }
1013
1014 this.el.innerHTML = html;
1015
1016 if (opts.bound) {
1017 if(opts.field.type !== 'hidden') {
1018 sto(function() {
1019 opts.trigger.focus();
1020 }, 1);
1021 }
1022 }
1023
1024 if (typeof this._o.onDraw === 'function') {
1025 this._o.onDraw(this);
1026 }
1027
1028 if (opts.bound) {
1029 // let the screen reader user know to use arrow keys
1030 opts.field.setAttribute('aria-label', 'Use the arrow keys to pick a date');
1031 }
1032 },
1033
1034 adjustPosition: function()
1035 {
1036 var field, pEl, width, height, viewportWidth, viewportHeight, scrollTop, left, top, clientRect;
1037
1038 if (this._o.container) return;
1039
1040 this.el.style.position = 'absolute';
1041
1042 field = this._o.trigger;
1043 pEl = field;
1044 width = this.el.offsetWidth;
1045 height = this.el.offsetHeight;
1046 viewportWidth = window.innerWidth || document.documentElement.clientWidth;
1047 viewportHeight = window.innerHeight || document.documentElement.clientHeight;
1048 scrollTop = window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop;
1049
1050 if (typeof field.getBoundingClientRect === 'function') {
1051 clientRect = field.getBoundingClientRect();
1052 left = clientRect.left + window.pageXOffset;
1053 top = clientRect.bottom + window.pageYOffset;
1054 } else {
1055 left = pEl.offsetLeft;
1056 top = pEl.offsetTop + pEl.offsetHeight;
1057 while((pEl = pEl.offsetParent)) {
1058 left += pEl.offsetLeft;
1059 top += pEl.offsetTop;
1060 }
1061 }
1062
1063 // default position is bottom & left
1064 if ((this._o.reposition && left + width > viewportWidth) ||
1065 (
1066 this._o.position.indexOf('right') > -1 &&
1067 left - width + field.offsetWidth > 0
1068 )
1069 ) {
1070 left = left - width + field.offsetWidth;
1071 }
1072 if ((this._o.reposition && top + height > viewportHeight + scrollTop) ||
1073 (
1074 this._o.position.indexOf('top') > -1 &&
1075 top - height - field.offsetHeight > 0
1076 )
1077 ) {
1078 top = top - height - field.offsetHeight;
1079 }
1080
1081 this.el.style.left = left + 'px';
1082 this.el.style.top = top + 'px';
1083 },
1084
1085 /**
1086 * render HTML for a particular month
1087 */
1088 render: function(year, month, randId)
1089 {
1090 var opts = this._o,
1091 now = new Date(),
1092 days = getDaysInMonth(year, month),
1093 before = new Date(year, month, 1).getDay(),
1094 data = [],
1095 row = [];
1096 setToStartOfDay(now);
1097 if (opts.firstDay > 0) {
1098 before -= opts.firstDay;
1099 if (before < 0) {
1100 before += 7;
1101 }
1102 }
1103 var previousMonth = month === 0 ? 11 : month - 1,
1104 nextMonth = month === 11 ? 0 : month + 1,
1105 yearOfPreviousMonth = month === 0 ? year - 1 : year,
1106 yearOfNextMonth = month === 11 ? year + 1 : year,
1107 daysInPreviousMonth = getDaysInMonth(yearOfPreviousMonth, previousMonth);
1108 var cells = days + before,
1109 after = cells;
1110 while(after > 7) {
1111 after -= 7;
1112 }
1113 cells += 7 - after;
1114 var isWeekSelected = false;
1115 for (var i = 0, r = 0; i < cells; i++)
1116 {
1117 var day = new Date(year, month, 1 + (i - before)),
1118 isSelected = isDate(this._d) ? compareDates(day, this._d) : false,
1119 isToday = compareDates(day, now),
1120 hasEvent = opts.events.indexOf(day.toDateString()) !== -1 ? true : false,
1121 isEmpty = i < before || i >= (days + before),
1122 dayNumber = 1 + (i - before),
1123 monthNumber = month,
1124 yearNumber = year,
1125 isStartRange = opts.startRange && compareDates(opts.startRange, day),
1126 isEndRange = opts.endRange && compareDates(opts.endRange, day),
1127 isInRange = opts.startRange && opts.endRange && opts.startRange < day && day < opts.endRange,
1128 isDisabled = (opts.minDate && day < opts.minDate) ||
1129 (opts.maxDate && day > opts.maxDate) ||
1130 (opts.disableWeekends && isWeekend(day)) ||
1131 (opts.disableDayFn && opts.disableDayFn(day));
1132
1133 if (isEmpty) {
1134 if (i < before) {
1135 dayNumber = daysInPreviousMonth + dayNumber;
1136 monthNumber = previousMonth;
1137 yearNumber = yearOfPreviousMonth;
1138 } else {
1139 dayNumber = dayNumber - days;
1140 monthNumber = nextMonth;
1141 yearNumber = yearOfNextMonth;
1142 }
1143 }
1144
1145 var dayConfig = {
1146 day: dayNumber,
1147 month: monthNumber,
1148 year: yearNumber,
1149 hasEvent: hasEvent,
1150 isSelected: isSelected,
1151 isToday: isToday,
1152 isDisabled: isDisabled,
1153 isEmpty: isEmpty,
1154 isStartRange: isStartRange,
1155 isEndRange: isEndRange,
1156 isInRange: isInRange,
1157 showDaysInNextAndPreviousMonths: opts.showDaysInNextAndPreviousMonths,
1158 enableSelectionDaysInNextAndPreviousMonths: opts.enableSelectionDaysInNextAndPreviousMonths
1159 };
1160
1161 if (opts.pickWholeWeek && isSelected) {
1162 isWeekSelected = true;
1163 }
1164
1165 row.push(renderDay(dayConfig));
1166
1167 if (++r === 7) {
1168 if (opts.showWeekNumber) {
1169 row.unshift(renderWeek(i - before, month, year));
1170 }
1171 data.push(renderRow(row, opts.isRTL, opts.pickWholeWeek, isWeekSelected));
1172 row = [];
1173 r = 0;
1174 isWeekSelected = false;
1175 }
1176 }
1177 return renderTable(opts, data, randId);
1178 },
1179
1180 isVisible: function()
1181 {
1182 return this._v;
1183 },
1184
1185 show: function()
1186 {
1187 if (!this.isVisible()) {
1188 this._v = true;
1189 this.draw();
1190 removeClass(this.el, 'is-hidden');
1191 if (this._o.bound) {
1192 addEvent(document, 'click', this._onClick);
1193 this.adjustPosition();
1194 }
1195 if (typeof this._o.onOpen === 'function') {
1196 this._o.onOpen.call(this);
1197 }
1198 }
1199 },
1200
1201 hide: function()
1202 {
1203 var v = this._v;
1204 if (v !== false) {
1205 if (this._o.bound) {
1206 removeEvent(document, 'click', this._onClick);
1207 }
1208 this.el.style.position = 'static'; // reset
1209 this.el.style.left = 'auto';
1210 this.el.style.top = 'auto';
1211 addClass(this.el, 'is-hidden');
1212 this._v = false;
1213 if (v !== undefined && typeof this._o.onClose === 'function') {
1214 this._o.onClose.call(this);
1215 }
1216 }
1217 },
1218
1219 /**
1220 * GAME OVER
1221 */
1222 destroy: function()
1223 {
1224 var opts = this._o;
1225
1226 this.hide();
1227 removeEvent(this.el, 'mousedown', this._onMouseDown, true);
1228 removeEvent(this.el, 'touchend', this._onMouseDown, true);
1229 removeEvent(this.el, 'change', this._onChange);
1230 if (opts.keyboardInput) {
1231 removeEvent(document, 'keydown', this._onKeyChange);
1232 }
1233 if (opts.field) {
1234 removeEvent(opts.field, 'change', this._onInputChange);
1235 if (opts.bound) {
1236 removeEvent(opts.trigger, 'click', this._onInputClick);
1237 removeEvent(opts.trigger, 'focus', this._onInputFocus);
1238 removeEvent(opts.trigger, 'blur', this._onInputBlur);
1239 }
1240 }
1241 if (this.el.parentNode) {
1242 this.el.parentNode.removeChild(this.el);
1243 }
1244 }
1245
1246 };
1247
1248 return Pikaday;
1249}));
1250});
1251
1252export { pikaday as p };