PageSourceSearch

https://www.kv-rhk.de/:webjars/pikaday/pikaday.js?fp=8ed889b78e8e

js kv-rhk.de collected 2026-09-24 12:41:54 UTC 42,544 bytes, 1,298 lines download raw bytes

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

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.