PageSourceSearch

https://carlsbergmalaysia.com.my/assets/scripts/libs/pikaday.js

js carlsbergmalaysia.com.my collected 2026-10-03 21:39:02 UTC 35,585 bytes, 1,086 lines download raw bytes

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

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.