PageSourceSearch

https://www.gironde-habitat.fr/wp-content/themes/gironde-habitat/a…/js/bootstrap-datepicker.min.js?ver=1.0.0

js gironde-habitat.fr collected 2026-09-24 10:28:05 UTC 58,701 bytes, 2,096 lines download raw bytes

1/*!
2 * Datepicker for Bootstrap v1.6.4 (https://github.com/eternicode/bootstrap-datepicker)
3 *
4 * Copyright 2012 Stefan Petre
5 * Improvements by Andrew Rowls
6 * Licensed under the Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0)
7 */(function(factory){
8    if (typeof define === "function" && define.amd) {
9        define(["jquery"], factory);
10    } else if (typeof exports === 'object') {
11        factory(require('jquery'));
12    } else {
13        factory(jQuery);
14    }
15}(function($, undefined){
16
17	function UTCDate(){
18		return new Date(Date.UTC.apply(Date, arguments));
19	}
20	function UTCToday(){
21		var today = new Date();
22		return UTCDate(today.getFullYear(), today.getMonth(), today.getDate());
23	}
24	function isUTCEquals(date1, date2) {
25		return (
26			date1.getUTCFullYear() === date2.getUTCFullYear() &&
27			date1.getUTCMonth() === date2.getUTCMonth() &&
28			date1.getUTCDate() === date2.getUTCDate()
29		);
30	}
31	function alias(method){
32		return function(){
33			return this[method].apply(this, arguments);
34		};
35	}
36	function isValidDate(d) {
37		return d && !isNaN(d.getTime());
38	}
39
40	var DateArray = (function(){
41		var extras = {
42			get: function(i){
43				return this.slice(i)[0];
44			},
45			contains: function(d){
46				// Array.indexOf is not cross-browser;
47				// $.inArray doesn't work with Dates
48				var val = d && d.valueOf();
49				for (var i=0, l=this.length; i < l; i++)
50					if (this[i].valueOf() === val)
51						return i;
52				return -1;
53			},
54			remove: function(i){
55				this.splice(i,1);
56			},
57			replace: function(new_array){
58				if (!new_array)
59					return;
60				if (!$.isArray(new_array))
61					new_array = [new_array];
62				this.clear();
63				this.push.apply(this, new_array);
64			},
65			clear: function(){
66				this.length = 0;
67			},
68			copy: function(){
69				var a = new DateArray();
70				a.replace(this);
71				return a;
72			}
73		};
74
75		return function(){
76			var a = [];
77			a.push.apply(a, arguments);
78			$.extend(a, extras);
79			return a;
80		};
81	})();
82
83
84	// Picker object
85
86	var Datepicker = function(element, options){
87		$(element).data('datepicker', this);
88		this._process_options(options);
89
90		this.dates = new DateArray();
91		this.viewDate = this.o.defaultViewDate;
92		this.focusDate = null;
93
94		this.element = $(element);
95		this.isInput = this.element.is('input');
96		this.inputField = this.isInput ? this.element : this.element.find('input');
97		this.component = this.element.hasClass('date') ? this.element.find('.add-on, .input-group-addon, .btn') : false;
98		this.hasInput = this.component && this.inputField.length;
99		if (this.component && this.component.length === 0)
100			this.component = false;
101		this.isInline = !this.component && this.element.is('div');
102
103		this.picker = $(DPGlobal.template);
104
105		// Checking templates and inserting
106		if (this._check_template(this.o.templates.leftArrow)) {
107			this.picker.find('.prev').html(this.o.templates.leftArrow);
108		}
109		if (this._check_template(this.o.templates.rightArrow)) {
110			this.picker.find('.next').html(this.o.templates.rightArrow);
111		}
112
113		this._buildEvents();
114		this._attachEvents();
115
116		if (this.isInline){
117			this.picker.addClass('datepicker-inline').appendTo(this.element);
118		}
119		else {
120			this.picker.addClass('datepicker-dropdown dropdown-menu');
121		}
122
123		if (this.o.rtl){
124			this.picker.addClass('datepicker-rtl');
125		}
126
127		this.viewMode = this.o.startView;
128
129		if (this.o.calendarWeeks)
130			this.picker.find('thead .datepicker-title, tfoot .today, tfoot .clear')
131						.attr('colspan', function(i, val){
132							return parseInt(val) + 1;
133						});
134
135		this._allow_update = false;
136
137		this.setStartDate(this._o.startDate);
138		this.setEndDate(this._o.endDate);
139		this.setDaysOfWeekDisabled(this.o.daysOfWeekDisabled);
140		this.setDaysOfWeekHighlighted(this.o.daysOfWeekHighlighted);
141		this.setDatesDisabled(this.o.datesDisabled);
142
143		this.fillDow();
144		this.fillMonths();
145
146		this._allow_update = true;
147
148		this.update();
149		this.showMode();
150
151		if (this.isInline){
152			this.show();
153		}
154	};
155
156	Datepicker.prototype = {
157		constructor: Datepicker,
158
159		_resolveViewName: function(view, default_value){
160			if (view === 0 || view === 'days' || view === 'month') {
161				return 0;
162			}
163			if (view === 1 || view === 'months' || view === 'year') {
164				return 1;
165			}
166			if (view === 2 || view === 'years' || view === 'decade') {
167				return 2;
168			}
169			if (view === 3 || view === 'decades' || view === 'century') {
170				return 3;
171			}
172			if (view === 4 || view === 'centuries' || view === 'millennium') {
173				return 4;
174			}
175			return default_value === undefined ? false : default_value;
176		},
177
178		_check_template: function(tmp){
179			try {
180				// If empty
181				if (tmp === undefined || tmp === "") {
182					return false;
vendor: 18,355 bytes, lines 183-849
183				}
184				// If no html, everything ok
185				if ((tmp.match(/[<>]/g) || []).length <= 0) {
186					return true;
187				}
188				// Checking if html is fine
189				var jDom = $(tmp);
190				return jDom.length > 0;
191			}
192			catch (ex) {
193				return false;
194			}
195		},
196
197		_process_options: function(opts){
198			// Store raw options for reference
199			this._o = $.extend({}, this._o, opts);
200			// Processed options
201			var o = this.o = $.extend({}, this._o);
202
203			// Check if "de-DE" style date is available, if not language should
204			// fallback to 2 letter code eg "de"
205			var lang = o.language;
206			if (!dates[lang]){
207				lang = lang.split('-')[0];
208				if (!dates[lang])
209					lang = defaults.language;
210			}
211			o.language = lang;
212
213			// Retrieve view index from any aliases
214			o.startView = this._resolveViewName(o.startView, 0);
215			o.minViewMode = this._resolveViewName(o.minViewMode, 0);
216			o.maxViewMode = this._resolveViewName(o.maxViewMode, 4);
217
218			// Check that the start view is between min and max
219			o.startView = Math.min(o.startView, o.maxViewMode);
220			o.startView = Math.max(o.startView, o.minViewMode);
221
222			// true, false, or Number > 0
223			if (o.multidate !== true){
224				o.multidate = Number(o.multidate) || false;
225				if (o.multidate !== false)
226					o.multidate = Math.max(0, o.multidate);
227			}
228			o.multidateSeparator = String(o.multidateSeparator);
229
230			o.weekStart %= 7;
231			o.weekEnd = (o.weekStart + 6) % 7;
232
233			var format = DPGlobal.parseFormat(o.format);
234			if (o.startDate !== -Infinity){
235				if (!!o.startDate){
236					if (o.startDate instanceof Date)
237						o.startDate = this._local_to_utc(this._zero_time(o.startDate));
238					else
239						o.startDate = DPGlobal.parseDate(o.startDate, format, o.language, o.assumeNearbyYear);
240				}
241				else {
242					o.startDate = -Infinity;
243				}
244			}
245			if (o.endDate !== Infinity){
246				if (!!o.endDate){
247					if (o.endDate instanceof Date)
248						o.endDate = this._local_to_utc(this._zero_time(o.endDate));
249					else
250						o.endDate = DPGlobal.parseDate(o.endDate, format, o.language, o.assumeNearbyYear);
251				}
252				else {
253					o.endDate = Infinity;
254				}
255			}
256
257			o.daysOfWeekDisabled = o.daysOfWeekDisabled||[];
258			if (!$.isArray(o.daysOfWeekDisabled))
259				o.daysOfWeekDisabled = o.daysOfWeekDisabled.split(/[,\s]*/);
260			o.daysOfWeekDisabled = $.map(o.daysOfWeekDisabled, function(d){
261				return parseInt(d, 10);
262			});
263
264			o.daysOfWeekHighlighted = o.daysOfWeekHighlighted||[];
265			if (!$.isArray(o.daysOfWeekHighlighted))
266				o.daysOfWeekHighlighted = o.daysOfWeekHighlighted.split(/[,\s]*/);
267			o.daysOfWeekHighlighted = $.map(o.daysOfWeekHighlighted, function(d){
268				return parseInt(d, 10);
269			});
270
271			o.datesDisabled = o.datesDisabled||[];
272			if (!$.isArray(o.datesDisabled)) {
273				o.datesDisabled = [
274					o.datesDisabled
275				];
276			}
277			o.datesDisabled = $.map(o.datesDisabled,function(d){
278				return DPGlobal.parseDate(d, format, o.language, o.assumeNearbyYear);
279			});
280
281			var plc = String(o.orientation).toLowerCase().split(/\s+/g),
282				_plc = o.orientation.toLowerCase();
283			plc = $.grep(plc, function(word){
284				return /^auto|left|right|top|bottom$/.test(word);
285			});
286			o.orientation = {x: 'auto', y: 'auto'};
287			if (!_plc || _plc === 'auto')
288				; // no action
289			else if (plc.length === 1){
290				switch (plc[0]){
291					case 'top':
292					case 'bottom':
293						o.orientation.y = plc[0];
294						break;
295					case 'left':
296					case 'right':
297						o.orientation.x = plc[0];
298						break;
299				}
300			}
301			else {
302				_plc = $.grep(plc, function(word){
303					return /^left|right$/.test(word);
304				});
305				o.orientation.x = _plc[0] || 'auto';
306
307				_plc = $.grep(plc, function(word){
308					return /^top|bottom$/.test(word);
309				});
310				o.orientation.y = _plc[0] || 'auto';
311			}
312			if (o.defaultViewDate) {
313				var year = o.defaultViewDate.year || new Date().getFullYear();
314				var month = o.defaultViewDate.month || 0;
315				var day = o.defaultViewDate.day || 1;
316				o.defaultViewDate = UTCDate(year, month, day);
317			} else {
318				o.defaultViewDate = UTCToday();
319			}
320		},
321		_events: [],
322		_secondaryEvents: [],
323		_applyEvents: function(evs){
324			for (var i=0, el, ch, ev; i < evs.length; i++){
325				el = evs[i][0];
326				if (evs[i].length === 2){
327					ch = undefined;
328					ev = evs[i][1];
329				}
330				else if (evs[i].length === 3){
331					ch = evs[i][1];
332					ev = evs[i][2];
333				}
334				el.on(ev, ch);
335			}
336		},
337		_unapplyEvents: function(evs){
338			for (var i=0, el, ev, ch; i < evs.length; i++){
339				el = evs[i][0];
340				if (evs[i].length === 2){
341					ch = undefined;
342					ev = evs[i][1];
343				}
344				else if (evs[i].length === 3){
345					ch = evs[i][1];
346					ev = evs[i][2];
347				}
348				el.off(ev, ch);
349			}
350		},
351		_buildEvents: function(){
352            var events = {
353                keyup: $.proxy(function(e){
354                    if ($.inArray(e.keyCode, [27, 37, 39, 38, 40, 32, 13, 9]) === -1)
355                        this.update();
356                }, this),
357                keydown: $.proxy(this.keydown, this),
358                paste: $.proxy(this.paste, this)
359            };
360
361            if (this.o.showOnFocus === true) {
362                events.focus = $.proxy(this.show, this);
363            }
364
365            if (this.isInput) { // single input
366                this._events = [
367                    [this.element, events]
368                ];
369            }
370            else if (this.component && this.hasInput) { // component: input + button
371                this._events = [
372                    // For components that are not readonly, allow keyboard nav
373                    [this.inputField, events],
374                    [this.component, {
375                        click: $.proxy(this.show, this)
376                    }]
377                ];
378            }
379			else {
380				this._events = [
381					[this.element, {
382						click: $.proxy(this.show, this),
383						keydown: $.proxy(this.keydown, this)
384					}]
385				];
386			}
387			this._events.push(
388				// Component: listen for blur on element descendants
389				[this.element, '*', {
390					blur: $.proxy(function(e){
391						this._focused_from = e.target;
392					}, this)
393				}],
394				// Input: listen for blur on element
395				[this.element, {
396					blur: $.proxy(function(e){
397						this._focused_from = e.target;
398					}, this)
399				}]
400			);
401
402			if (this.o.immediateUpdates) {
403				// Trigger input updates immediately on changed year/month
404				this._events.push([this.element, {
405					'changeYear changeMonth': $.proxy(function(e){
406						this.update(e.date);
407					}, this)
408				}]);
409			}
410
411			this._secondaryEvents = [
412				[this.picker, {
413					click: $.proxy(this.click, this)
414				}],
415				[$(window), {
416					resize: $.proxy(this.place, this)
417				}],
418				[$(document), {
419					mousedown: $.proxy(function(e){
420						// Clicked outside the datepicker, hide it
421						if (!(
422							this.element.is(e.target) ||
423							this.element.find(e.target).length ||
424							this.picker.is(e.target) ||
425							this.picker.find(e.target).length ||
426							this.isInline
427						)){
428							this.hide();
429						}
430					}, this)
431				}]
432			];
433		},
434		_attachEvents: function(){
435			this._detachEvents();
436			this._applyEvents(this._events);
437		},
438		_detachEvents: function(){
439			this._unapplyEvents(this._events);
440		},
441		_attachSecondaryEvents: function(){
442			this._detachSecondaryEvents();
443			this._applyEvents(this._secondaryEvents);
444		},
445		_detachSecondaryEvents: function(){
446			this._unapplyEvents(this._secondaryEvents);
447		},
448		_trigger: function(event, altdate){
449			var date = altdate || this.dates.get(-1),
450				local_date = this._utc_to_local(date);
451
452			this.element.trigger({
453				type: event,
454				date: local_date,
455				dates: $.map(this.dates, this._utc_to_local),
456				format: $.proxy(function(ix, format){
457					if (arguments.length === 0){
458						ix = this.dates.length - 1;
459						format = this.o.format;
460					}
461					else if (typeof ix === 'string'){
462						format = ix;
463						ix = this.dates.length - 1;
464					}
465					format = format || this.o.format;
466					var date = this.dates.get(ix);
467					return DPGlobal.formatDate(date, format, this.o.language);
468				}, this)
469			});
470		},
471
472		show: function(){
473			if (this.inputField.prop('disabled') || (this.inputField.prop('readonly') && this.o.enableOnReadonly === false))
474				return;
475			if (!this.isInline)
476				this.picker.appendTo(this.o.container);
477			this.place();
478			this.picker.show();
479			this._attachSecondaryEvents();
480			this._trigger('show');
481			if ((window.navigator.msMaxTouchPoints || 'ontouchstart' in document) && this.o.disableTouchKeyboard) {
482				$(this.element).blur();
483			}
484			return this;
485		},
486
487		hide: function(){
488			if (this.isInline || !this.picker.is(':visible'))
489				return this;
490			this.focusDate = null;
491			this.picker.hide().detach();
492			this._detachSecondaryEvents();
493			this.viewMode = this.o.startView;
494			this.showMode();
495
496			if (this.o.forceParse && this.inputField.val())
497				this.setValue();
498			this._trigger('hide');
499			return this;
500		},
501
502		destroy: function(){
503			this.hide();
504			this._detachEvents();
505			this._detachSecondaryEvents();
506			this.picker.remove();
507			delete this.element.data().datepicker;
508			if (!this.isInput){
509				delete this.element.data().date;
510			}
511			return this;
512		},
513
514		paste: function(evt){
515			var dateString;
516			if (evt.originalEvent.clipboardData && evt.originalEvent.clipboardData.types
517				&& $.inArray('text/plain', evt.originalEvent.clipboardData.types) !== -1) {
518				dateString = evt.originalEvent.clipboardData.getData('text/plain');
519			}
520			else if (window.clipboardData) {
521				dateString = window.clipboardData.getData('Text');
522			}
523			else {
524				return;
525			}
526			this.setDate(dateString);
527			this.update();
528			evt.preventDefault();
529		},
530
531		_utc_to_local: function(utc){
532			return utc && new Date(utc.getTime() + (utc.getTimezoneOffset()*60000));
533		},
534		_local_to_utc: function(local){
535			return local && new Date(local.getTime() - (local.getTimezoneOffset()*60000));
536		},
537		_zero_time: function(local){
538			return local && new Date(local.getFullYear(), local.getMonth(), local.getDate());
539		},
540		_zero_utc_time: function(utc){
541			return utc && new Date(Date.UTC(utc.getUTCFullYear(), utc.getUTCMonth(), utc.getUTCDate()));
542		},
543
544		getDates: function(){
545			return $.map(this.dates, this._utc_to_local);
546		},
547
548		getUTCDates: function(){
549			return $.map(this.dates, function(d){
550				return new Date(d);
551			});
552		},
553
554		getDate: function(){
555			return this._utc_to_local(this.getUTCDate());
556		},
557
558		getUTCDate: function(){
559			var selected_date = this.dates.get(-1);
560			if (typeof selected_date !== 'undefined') {
561				return new Date(selected_date);
562			} else {
563				return null;
564			}
565		},
566
567		clearDates: function(){
568			if (this.inputField) {
569				this.inputField.val('');
570			}
571
572			this.update();
573			this._trigger('changeDate');
574
575			if (this.o.autoclose) {
576				this.hide();
577			}
578		},
579		setDates: function(){
580			var args = $.isArray(arguments[0]) ? arguments[0] : arguments;
581			this.update.apply(this, args);
582			this._trigger('changeDate');
583			this.setValue();
584			return this;
585		},
586
587		setUTCDates: function(){
588			var args = $.isArray(arguments[0]) ? arguments[0] : arguments;
589			this.update.apply(this, $.map(args, this._utc_to_local));
590			this._trigger('changeDate');
591			this.setValue();
592			return this;
593		},
594
595		setDate: alias('setDates'),
596		setUTCDate: alias('setUTCDates'),
597		remove: alias('destroy'),
598
599		setValue: function(){
600			var formatted = this.getFormattedDate();
601			this.inputField.val(formatted);
602			return this;
603		},
604
605		getFormattedDate: function(format){
606			if (format === undefined)
607				format = this.o.format;
608
609			var lang = this.o.language;
610			return $.map(this.dates, function(d){
611				return DPGlobal.formatDate(d, format, lang);
612			}).join(this.o.multidateSeparator);
613		},
614
615		getStartDate: function(){
616			return this.o.startDate;
617		},
618
619		setStartDate: function(startDate){
620			this._process_options({startDate: startDate});
621			this.update();
622			this.updateNavArrows();
623			return this;
624		},
625
626		getEndDate: function(){
627			return this.o.endDate;
628		},
629
630		setEndDate: function(endDate){
631			this._process_options({endDate: endDate});
632			this.update();
633			this.updateNavArrows();
634			return this;
635		},
636
637		setDaysOfWeekDisabled: function(daysOfWeekDisabled){
638			this._process_options({daysOfWeekDisabled: daysOfWeekDisabled});
639			this.update();
640			this.updateNavArrows();
641			return this;
642		},
643
644		setDaysOfWeekHighlighted: function(daysOfWeekHighlighted){
645			this._process_options({daysOfWeekHighlighted: daysOfWeekHighlighted});
646			this.update();
647			return this;
648		},
649
650		setDatesDisabled: function(datesDisabled){
651			this._process_options({datesDisabled: datesDisabled});
652			this.update();
653			this.updateNavArrows();
654		},
655
656		place: function(){
657			if (this.isInline)
658				return this;
659			var calendarWidth = this.picker.outerWidth(),
660				calendarHeight = this.picker.outerHeight(),
661				visualPadding = 10,
662				container = $(this.o.container),
663				windowWidth = container.width(),
664				scrollTop = this.o.container === 'body' ? $(document).scrollTop() : container.scrollTop(),
665				appendOffset = container.offset();
666
667			var parentsZindex = [];
668			this.element.parents().each(function(){
669				var itemZIndex = $(this).css('z-index');
670				if (itemZIndex !== 'auto' && itemZIndex !== 0) parentsZindex.push(parseInt(itemZIndex));
671			});
672			var zIndex = Math.max.apply(Math, parentsZindex) + this.o.zIndexOffset;
673			var offset = this.component ? this.component.parent().offset() : this.element.offset();
674			var height = this.component ? this.component.outerHeight(true) : this.element.outerHeight(false);
675			var width = this.component ? this.component.outerWidth(true) : this.element.outerWidth(false);
676			var left = offset.left - appendOffset.left,
677				top = offset.top - appendOffset.top;
678
679			if (this.o.container !== 'body') {
680				top += scrollTop;
681			}
682
683			this.picker.removeClass(
684				'datepicker-orient-top datepicker-orient-bottom '+
685				'datepicker-orient-right datepicker-orient-left'
686			);
687
688			if (this.o.orientation.x !== 'auto'){
689				this.picker.addClass('datepicker-orient-' + this.o.orientation.x);
690				if (this.o.orientation.x === 'right')
691					left -= calendarWidth - width;
692			}
693			// auto x orientation is best-placement: if it crosses a window
694			// edge, fudge it sideways
695			else {
696				if (offset.left < 0) {
697					// component is outside the window on the left side. Move it into visible range
698					this.picker.addClass('datepicker-orient-left');
699					left -= offset.left - visualPadding;
700				} else if (left + calendarWidth > windowWidth) {
701					// the calendar passes the widow right edge. Align it to component right side
702					this.picker.addClass('datepicker-orient-right');
703					left += width - calendarWidth;
704				} else {
705					// Default to left
706					this.picker.addClass('datepicker-orient-left');
707				}
708			}
709
710			// auto y orientation is best-situation: top or bottom, no fudging,
711			// decision based on which shows more of the calendar
712			var yorient = this.o.orientation.y,
713				top_overflow;
714			if (yorient === 'auto'){
715				top_overflow = -scrollTop + top - calendarHeight;
716				yorient = top_overflow < 0 ? 'bottom' : 'top';
717			}
718
719			this.picker.addClass('datepicker-orient-' + yorient);
720			if (yorient === 'top')
721				top -= calendarHeight + parseInt(this.picker.css('padding-top'));
722			else
723				top += height;
724
725			if (this.o.rtl) {
726				var right = windowWidth - (left + width);
727				this.picker.css({
728					top: top,
729					right: right,
730					zIndex: zIndex
731				});
732			} else {
733				this.picker.css({
734					top: top,
735					left: left,
736					zIndex: zIndex
737				});
738			}
739			return this;
740		},
741
742		_allow_update: true,
743		update: function(){
744			if (!this._allow_update)
745				return this;
746
747			var oldDates = this.dates.copy(),
748				dates = [],
749				fromArgs = false;
750			if (arguments.length){
751				$.each(arguments, $.proxy(function(i, date){
752					if (date instanceof Date)
753						date = this._local_to_utc(date);
754					dates.push(date);
755				}, this));
756				fromArgs = true;
757			}
758			else {
759				dates = this.isInput
760						? this.element.val()
761						: this.element.data('date') || this.inputField.val();
762				if (dates && this.o.multidate)
763					dates = dates.split(this.o.multidateSeparator);
764				else
765					dates = [dates];
766				delete this.element.data().date;
767			}
768
769			dates = $.map(dates, $.proxy(function(date){
770				return DPGlobal.parseDate(date, this.o.format, this.o.language, this.o.assumeNearbyYear);
771			}, this));
772			dates = $.grep(dates, $.proxy(function(date){
773				return (
774					!this.dateWithinRange(date) ||
775					!date
776				);
777			}, this), true);
778			this.dates.replace(dates);
779
780			if (this.dates.length)
781				this.viewDate = new Date(this.dates.get(-1));
782			else if (this.viewDate < this.o.startDate)
783				this.viewDate = new Date(this.o.startDate);
784			else if (this.viewDate > this.o.endDate)
785				this.viewDate = new Date(this.o.endDate);
786			else
787				this.viewDate = this.o.defaultViewDate;
788
789			if (fromArgs){
790				// setting date by clicking
791				this.setValue();
792			}
793			else if (dates.length){
794				// setting date by typing
795				if (String(oldDates) !== String(this.dates))
796					this._trigger('changeDate');
797			}
798			if (!this.dates.length && oldDates.length)
799				this._trigger('clearDate');
800
801			this.fill();
802			this.element.change();
803			return this;
804		},
805
806		fillDow: function(){
807			var dowCnt = this.o.weekStart,
808				html = '<tr>';
809			if (this.o.calendarWeeks){
810				this.picker.find('.datepicker-days .datepicker-switch')
811					.attr('colspan', function(i, val){
812						return parseInt(val) + 1;
813					});
814				html += '<th class="cw">&#160;</th>';
815			}
816			while (dowCnt < this.o.weekStart + 7){
817				html += '<th class="dow';
818        if ($.inArray(dowCnt, this.o.daysOfWeekDisabled) > -1)
819          html += ' disabled';
820        html += '">'+dates[this.o.language].daysMin[(dowCnt++)%7]+'</th>';
821			}
822			html += '</tr>';
823			this.picker.find('.datepicker-days thead').append(html);
824		},
825
826		fillMonths: function(){
827      var localDate = this._utc_to_local(this.viewDate);
828			var html = '',
829			i = 0;
830			while (i < 12){
831        var focused = localDate && localDate.getMonth() === i ? ' focused' : '';
832				html += '<span class="month' + focused + '">' + dates[this.o.language].monthsShort[i++]+'</span>';
833			}
834			this.picker.find('.datepicker-months td').html(html);
835		},
836
837		setRange: function(range){
838			if (!range || !range.length)
839				delete this.range;
840			else
841				this.range = $.map(range, function(d){
842					return d.valueOf();
843				});
844			this.fill();
845		},
846
847		getClassNames: function(date){
848			var cls = [],
849				year = this.viewDate.getUTCFullYear(),
850				month = this.viewDate.getUTCMonth(),
851				today = new Date();
852			if (date.getUTCFullYear() < year || (date.getUTCFullYear() === year && date.getUTCMonth() < month)){
853				cls.push('old');
854			}
855			else if (date.getUTCFullYear() > year || (date.getUTCFullYear() === year && date.getUTCMonth() > month)){
856				cls.push('new');
857			}
858			if (this.focusDate && date.valueOf() === this.focusDate.valueOf())
859				cls.push('focused');
860			// Compare internal UTC date with local today, not UTC today
861			if (this.o.todayHighlight &&
862				date.getUTCFullYear() === today.getFullYear() &&
863				date.getUTCMonth() === today.getMonth() &&
864				date.getUTCDate() === today.getDate()){
865				cls.push('today');
866			}
867			if (this.dates.contains(date) !== -1)
868				cls.push('active');
869			if (!this.dateWithinRange(date)){
870				cls.push('disabled');
871			}
872			if (this.dateIsDisabled(date)){
873				cls.push('disabled', 'disabled-date');	
874			} 
875			if ($.inArray(date.getUTCDay(), this.o.daysOfWeekHighlighted) !== -1){
876				cls.push('highlighted');
877			}
878
879			if (this.range){
880				if (date > this.range[0] && date < this.range[this.range.length-1]){
881					cls.push('range');
882				}
883				if ($.inArray(date.valueOf(), this.range) !== -1){
884					cls.push('selected');
885				}
886				if (date.valueOf() === this.range[0]){
887          cls.push('range-start');
888        }
889        if (date.valueOf() === this.range[this.range.length-1]){
890          cls.push('range-end');
891        }
892			}
893			return cls;
894		},
895
896		_fill_yearsView: function(selector, cssClass, factor, step, currentYear, startYear, endYear, callback){
897			var html, view, year, steps, startStep, endStep, thisYear, i, classes, tooltip, before;
898
899			html      = '';
900			view      = this.picker.find(selector);
901			year      = parseInt(currentYear / factor, 10) * factor;
902			startStep = parseInt(startYear / step, 10) * step;
903			endStep   = parseInt(endYear / step, 10) * step;
904			steps     = $.map(this.dates, function(d){
905				return parseInt(d.getUTCFullYear() / step, 10) * step;
906			});
907
908			view.find('.datepicker-switch').text(year + '-' + (year + step * 9));
909
910			thisYear = year - step;
911			for (i = -1; i < 11; i += 1) {
912				classes = [cssClass];
913				tooltip = null;
914
915				if (i === -1) {
916					classes.push('old');
917				} else if (i === 10) {
918					classes.push('new');
919				}
920				if ($.inArray(thisYear, steps) !== -1) {
921					classes.push('active');
922				}
923				if (thisYear < startStep || thisYear > endStep) {
924					classes.push('disabled');
925				}
926        if (thisYear === this.viewDate.getFullYear()) {
927				  classes.push('focused');
928        }
929
930				if (callback !== $.noop) {
931					before = callback(new Date(thisYear, 0, 1));
932					if (before === undefined) {
933						before = {};
934					} else if (typeof(before) === 'boolean') {
935						before = {enabled: before};
936					} else if (typeof(before) === 'string') {
937						before = {classes: before};
938					}
939					if (before.enabled === false) {
940						classes.push('disabled');
941					}
942					if (before.classes) {
943						classes = classes.concat(before.classes.split(/\s+/));
944					}
945					if (before.tooltip) {
946						tooltip = before.tooltip;
947					}
948				}
949
950				html += '<span class="' + classes.join(' ') + '"' + (tooltip ? ' title="' + tooltip + '"' : '') + '>' + thisYear + '</span>';
951				thisYear += step;
952			}
953			view.find('td').html(html);
954		},
955
956		fill: function(){
957			var d = new Date(this.viewDate),
958				year = d.getUTCFullYear(),
959				month = d.getUTCMonth(),
960				startYear = this.o.startDate !== -Infinity ? this.o.startDate.getUTCFullYear() : -Infinity,
961				startMonth = this.o.startDate !== -Infinity ? this.o.startDate.getUTCMonth() : -Infinity,
962				endYear = this.o.endDate !== Infinity ? this.o.endDate.getUTCFullYear() : Infinity,
963				endMonth = this.o.endDate !== Infinity ? this.o.endDate.getUTCMonth() : Infinity,
964				todaytxt = dates[this.o.language].today || dates['en'].today || '',
965				cleartxt = dates[this.o.language].clear || dates['en'].clear || '',
966				titleFormat = dates[this.o.language].titleFormat || dates['en'].titleFormat,
967				tooltip,
968				before;
969			if (isNaN(year) || isNaN(month))
970				return;
971			this.picker.find('.datepicker-days .datepicker-switch')
972						.text(DPGlobal.formatDate(d, titleFormat, this.o.language));
973			this.picker.find('tfoot .today')
974						.text(todaytxt)
975						.toggle(this.o.todayBtn !== false);
976			this.picker.find('tfoot .clear')
977						.text(cleartxt)
978						.toggle(this.o.clearBtn !== false);
979			this.picker.find('thead .datepicker-title')
980						.text(this.o.title)
981						.toggle(this.o.title !== '');
982			this.updateNavArrows();
983			this.fillMonths();
984			var prevMonth = UTCDate(year, month-1, 28),
985				day = DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth());
986			prevMonth.setUTCDate(day);
987			prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.o.weekStart + 7)%7);
988			var nextMonth = new Date(prevMonth);
989			if (prevMonth.getUTCFullYear() < 100){
990        nextMonth.setUTCFullYear(prevMonth.getUTCFullYear());
991      }
992			nextMonth.setUTCDate(nextMonth.getUTCDate() + 42);
993			nextMonth = nextMonth.valueOf();
994			var html = [];
995			var clsName;
996			while (prevMonth.valueOf() < nextMonth){
997				if (prevMonth.getUTCDay() === this.o.weekStart){
998					html.push('<tr>');
999					if (this.o.calendarWeeks){
1000						// ISO 8601: First week contains first thursday.
1001						// ISO also states week starts on Monday, but we can be more abstract here.
1002						var
1003							// Start of current week: based on weekstart/current date
1004							ws = new Date(+prevMonth + (this.o.weekStart - prevMonth.getUTCDay() - 7) % 7 * 864e5),
1005							// Thursday of this week
1006							th = new Date(Number(ws) + (7 + 4 - ws.getUTCDay()) % 7 * 864e5),
1007							// First Thursday of year, year from thursday
1008							yth = new Date(Number(yth = UTCDate(th.getUTCFullYear(), 0, 1)) + (7 + 4 - yth.getUTCDay())%7*864e5),
1009							// Calendar week: ms between thursdays, div ms per day, div 7 days
1010							calWeek =  (th - yth) / 864e5 / 7 + 1;
1011						html.push('<td class="cw">'+ calWeek +'</td>');
1012					}
1013				}
1014				clsName = this.getClassNames(prevMonth);
1015				clsName.push('day');
1016
1017				if (this.o.beforeShowDay !== $.noop){
1018					before = this.o.beforeShowDay(this._utc_to_local(prevMonth));
1019					if (before === undefined)
1020						before = {};
1021					else if (typeof(before) === 'boolean')
1022						before = {enabled: before};
1023					else if (typeof(before) === 'string')
1024						before = {classes: before};
1025					if (before.enabled === false)
1026						clsName.push('disabled');
1027					if (before.classes)
1028						clsName = clsName.concat(before.classes.split(/\s+/));
1029					if (before.tooltip)
1030						tooltip = before.tooltip;
1031				}
1032
1033				//Check if uniqueSort exists (supported by jquery >=1.12 and >=2.2)
1034				//Fallback to unique function for older jquery versions
1035				if ($.isFunction($.uniqueSort)) {
1036					clsName = $.uniqueSort(clsName);
1037				} else {
1038					clsName = $.unique(clsName);
1039				}
1040
1041				html.push('<td class="'+clsName.join(' ')+'"' + (tooltip ? ' title="'+tooltip+'"' : '') + '>'+prevMonth.getUTCDate() + '</td>');
1042				tooltip = null;
1043				if (prevMonth.getUTCDay() === this.o.weekEnd){
1044					html.push('</tr>');
1045				}
1046				prevMonth.setUTCDate(prevMonth.getUTCDate()+1);
1047			}
1048			this.picker.find('.datepicker-days tbody').empty().append(html.join(''));
1049
1050			var monthsTitle = dates[this.o.language].monthsTitle || dates['en'].monthsTitle || 'Months';
1051			var months = this.picker.find('.datepicker-months')
1052						.find('.datepicker-switch')
1053							.text(this.o.maxViewMode < 2 ? monthsTitle : year)
1054							.end()
1055						.find('span').removeClass('active');
1056
1057			$.each(this.dates, function(i, d){
1058				if (d.getUTCFullYear() === year)
1059					months.eq(d.getUTCMonth()).addClass('active');
1060			});
1061
1062			if (year < startYear || year > endYear){
1063				months.addClass('disabled');
1064			}
1065			if (year === startYear){
1066				months.slice(0, startMonth).addClass('disabled');
1067			}
1068			if (year === endYear){
1069				months.slice(endMonth+1).addClass('disabled');
1070			}
1071
1072			if (this.o.beforeShowMonth !== $.noop){
1073				var that = this;
1074				$.each(months, function(i, month){
1075          var moDate = new Date(year, i, 1);
1076          var before = that.o.beforeShowMonth(moDate);
1077					if (before === undefined)
1078						before = {};
1079					else if (typeof(before) === 'boolean')
1080						before = {enabled: before};
1081					else if (typeof(before) === 'string')
1082						before = {classes: before};
1083					if (before.enabled === false && !$(month).hasClass('disabled'))
1084					    $(month).addClass('disabled');
1085					if (before.classes)
1086					    $(month).addClass(before.classes);
1087					if (before.tooltip)
1088					    $(month).prop('title', before.tooltip);
1089				});
1090			}
1091
1092			// Generating decade/years picker
1093			this._fill_yearsView(
1094				'.datepicker-years',
1095				'year',
1096				10,
1097				1,
1098				year,
1099				startYear,
1100				endYear,
1101				this.o.beforeShowYear
1102			);
1103
1104			// Generating century/decades picker
1105			this._fill_yearsView(
1106				'.datepicker-decades',
1107				'decade',
1108				100,
1109				10,
1110				year,
1111				startYear,
1112				endYear,
1113				this.o.beforeShowDecade
1114			);
1115
1116			// Generating millennium/centuries picker
1117			this._fill_yearsView(
1118				'.datepicker-centuries',
1119				'century',
1120				1000,
1121				100,
1122				year,
1123				startYear,
1124				endYear,
1125				this.o.beforeShowCentury
1126			);
1127		},
1128
1129		updateNavArrows: function(){
1130			if (!this._allow_update)
1131				return;
1132
1133			var d = new Date(this.viewDate),
1134				year = d.getUTCFullYear(),
1135				month = d.getUTCMonth();
1136			switch (this.viewMode){
1137				case 0:
1138					if (this.o.startDate !== -Infinity && year <= this.o.startDate.getUTCFullYear() && month <= this.o.startDate.getUTCMonth()){
1139						this.picker.find('.prev').css({visibility: 'hidden'});
1140					}
1141					else {
1142						this.picker.find('.prev').css({visibility: 'visible'});
1143					}
1144					if (this.o.endDate !== Infinity && year >= this.o.endDate.getUTCFullYear() && month >= this.o.endDate.getUTCMonth()){
1145						this.picker.find('.next').css({visibility: 'hidden'});
1146					}
1147					else {
1148						this.picker.find('.next').css({visibility: 'visible'});
1149					}
1150					break;
1151				case 1:
1152				case 2:
1153				case 3:
1154				case 4:
1155					if (this.o.startDate !== -Infinity && year <= this.o.startDate.getUTCFullYear() || this.o.maxViewMode < 2){
1156						this.picker.find('.prev').css({visibility: 'hidden'});
1157					}
1158					else {
1159						this.picker.find('.prev').css({visibility: 'visible'});
1160					}
1161					if (this.o.endDate !== Infinity && year >= this.o.endDate.getUTCFullYear() || this.o.maxViewMode < 2){
1162						this.picker.find('.next').css({visibility: 'hidden'});
1163					}
1164					else {
1165						this.picker.find('.next').css({visibility: 'visible'});
1166					}
1167					break;
1168			}
1169		},
1170
1171		click: function(e){
1172			e.preventDefault();
1173			e.stopPropagation();
1174
1175			var target, dir, day, year, month, monthChanged, yearChanged;
1176			target = $(e.target);
1177
1178			// Clicked on the switch
1179			if (target.hasClass('datepicker-switch')){
1180				this.showMode(1);
1181			}
1182
1183			// Clicked on prev or next
1184			var navArrow = target.closest('.prev, .next');
1185			if (navArrow.length > 0) {
1186				dir = DPGlobal.modes[this.viewMode].navStep * (navArrow.hasClass('prev') ? -1 : 1);
1187				if (this.viewMode === 0){
1188					this.viewDate = this.moveMonth(this.viewDate, dir);
1189					this._trigger('changeMonth', this.viewDate);
1190				} else {
1191					this.viewDate = this.moveYear(this.viewDate, dir);
1192					if (this.viewMode === 1){
1193						this._trigger('changeYear', this.viewDate);
1194					}
1195				}
1196				this.fill();
1197			}
1198
1199			// Clicked on today button
1200			if (target.hasClass('today') && !target.hasClass('day')){
1201				this.showMode(-2);
1202				this._setDate(UTCToday(), this.o.todayBtn === 'linked' ? null : 'view');
1203			}
1204
1205			// Clicked on clear button
1206			if (target.hasClass('clear')){
1207				this.clearDates();
1208			}
1209
1210			if (!target.hasClass('disabled')){
1211				// Clicked on a day
1212				if (target.hasClass('day')){
1213					day = parseInt(target.text(), 10) || 1;
1214					year = this.viewDate.getUTCFullYear();
1215					month = this.viewDate.getUTCMonth();
1216
1217					// From last month
1218					if (target.hasClass('old')){
1219						if (month === 0) {
1220							month = 11;
1221							year = year - 1;
1222							monthChanged = true;
1223							yearChanged = true;
1224						} else {
1225							month = month - 1;
1226							monthChanged = true;
1227 						}
1228 					}
1229
1230					// From next month
1231					if (target.hasClass('new')) {
1232						if (month === 11){
1233							month = 0;
1234							year = year + 1;
1235							monthChanged = true;
1236							yearChanged = true;
1237 						} else {
1238							month = month + 1;
1239							monthChanged = true;
1240 						}
1241					}
1242					this._setDate(UTCDate(year, month, day));
1243					if (yearChanged) {
1244						this._trigger('changeYear', this.viewDate);
1245					}
1246					if (monthChanged) {
1247						this._trigger('changeMonth', this.viewDate);
1248					}
1249				}
1250
1251				// Clicked on a month
1252				if (target.hasClass('month')) {
1253					this.viewDate.setUTCDate(1);
1254					day = 1;
1255					month = target.parent().find('span').index(target);
1256					year = this.viewDate.getUTCFullYear();
1257					this.viewDate.setUTCMonth(month);
1258					this._trigger('changeMonth', this.viewDate);
1259					if (this.o.minViewMode === 1){
1260						this._setDate(UTCDate(year, month, day));
1261						this.showMode();
1262					} else {
1263						this.showMode(-1);
1264					}
1265					this.fill();
1266				}
1267
1268				// Clicked on a year
1269				if (target.hasClass('year')
1270						|| target.hasClass('decade')
1271						|| target.hasClass('century')) {
1272					this.viewDate.setUTCDate(1);
1273
1274					day = 1;
1275					month = 0;
1276					year = parseInt(target.text(), 10)||0;
1277					this.viewDate.setUTCFullYear(year);
1278
1279					if (target.hasClass('year')){
1280						this._trigger('changeYear', this.viewDate);
1281						if (this.o.minViewMode === 2){
1282							this._setDate(UTCDate(year, month, day));
1283						}
1284					}
1285					if (target.hasClass('decade')){
1286						this._trigger('changeDecade', this.viewDate);
1287						if (this.o.minViewMode === 3){
1288							this._setDate(UTCDate(year, month, day));
1289						}
1290					}
1291					if (target.hasClass('century')){
1292						this._trigger('changeCentury', this.viewDate);
1293						if (this.o.minViewMode === 4){
1294							this._setDate(UTCDate(year, month, day));
1295						}
1296					}
1297
1298					this.showMode(-1);
1299					this.fill();
1300				}
1301			}
1302
1303			if (this.picker.is(':visible') && this._focused_from){
1304				$(this._focused_from).focus();
1305			}
1306			delete this._focused_from;
1307		},
1308
1309		_toggle_multidate: function(date){
1310			var ix = this.dates.contains(date);
1311			if (!date){
1312				this.dates.clear();
1313			}
1314
1315			if (ix !== -1){
1316				if (this.o.multidate === true || this.o.multidate > 1 || this.o.toggleActive){
1317					this.dates.remove(ix);
1318				}
1319			} else if (this.o.multidate === false) {
1320				this.dates.clear();
1321				this.dates.push(date);
1322			}
1323			else {
1324				this.dates.push(date);
1325			}
1326
1327			if (typeof this.o.multidate === 'number')
1328				while (this.dates.length > this.o.multidate)
1329					this.dates.remove(0);
1330		},
1331
1332		_setDate: function(date, which){
1333			if (!which || which === 'date')
1334				this._toggle_multidate(date && new Date(date));
1335			if (!which || which === 'view')
1336				this.viewDate = date && new Date(date);
1337
1338			this.fill();
1339			this.setValue();
1340			if (!which || which !== 'view') {
1341				this._trigger('changeDate');
1342			}
1343			if (this.inputField){
1344				this.inputField.change();
1345			}
1346			if (this.o.autoclose && (!which || which === 'date')){
1347				this.hide();
1348			}
1349		},
1350
1351		moveDay: function(date, dir){
1352			var newDate = new Date(date);
1353			newDate.setUTCDate(date.getUTCDate() + dir);
1354
1355			return newDate;
1356		},
1357
1358		moveWeek: function(date, dir){
1359			return this.moveDay(date, dir * 7);
1360		},
1361
1362		moveMonth: function(date, dir){
1363			if (!isValidDate(date))
1364				return this.o.defaultViewDate;
1365			if (!dir)
1366				return date;
1367			var new_date = new Date(date.valueOf()),
1368				day = new_date.getUTCDate(),
vendor: 19,731 bytes, lines 1369-2075
1369				month = new_date.getUTCMonth(),
1370				mag = Math.abs(dir),
1371				new_month, test;
1372			dir = dir > 0 ? 1 : -1;
1373			if (mag === 1){
1374				test = dir === -1
1375					// If going back one month, make sure month is not current month
1376					// (eg, Mar 31 -> Feb 31 == Feb 28, not Mar 02)
1377					? function(){
1378						return new_date.getUTCMonth() === month;
1379					}
1380					// If going forward one month, make sure month is as expected
1381					// (eg, Jan 31 -> Feb 31 == Feb 28, not Mar 02)
1382					: function(){
1383						return new_date.getUTCMonth() !== new_month;
1384					};
1385				new_month = month + dir;
1386				new_date.setUTCMonth(new_month);
1387				// Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11
1388				if (new_month < 0 || new_month > 11)
1389					new_month = (new_month + 12) % 12;
1390			}
1391			else {
1392				// For magnitudes >1, move one month at a time...
1393				for (var i=0; i < mag; i++)
1394					// ...which might decrease the day (eg, Jan 31 to Feb 28, etc)...
1395					new_date = this.moveMonth(new_date, dir);
1396				// ...then reset the day, keeping it in the new month
1397				new_month = new_date.getUTCMonth();
1398				new_date.setUTCDate(day);
1399				test = function(){
1400					return new_month !== new_date.getUTCMonth();
1401				};
1402			}
1403			// Common date-resetting loop -- if date is beyond end of month, make it
1404			// end of month
1405			while (test()){
1406				new_date.setUTCDate(--day);
1407				new_date.setUTCMonth(new_month);
1408			}
1409			return new_date;
1410		},
1411
1412		moveYear: function(date, dir){
1413			return this.moveMonth(date, dir*12);
1414		},
1415
1416		moveAvailableDate: function(date, dir, fn){
1417			do {
1418				date = this[fn](date, dir);
1419
1420				if (!this.dateWithinRange(date))
1421					return false;
1422
1423				fn = 'moveDay';
1424			}
1425			while (this.dateIsDisabled(date));
1426
1427			return date;
1428		},
1429
1430		weekOfDateIsDisabled: function(date){
1431			return $.inArray(date.getUTCDay(), this.o.daysOfWeekDisabled) !== -1;
1432		},
1433
1434		dateIsDisabled: function(date){
1435			return (
1436				this.weekOfDateIsDisabled(date) ||
1437				$.grep(this.o.datesDisabled, function(d){
1438					return isUTCEquals(date, d);
1439				}).length > 0
1440			);
1441		},
1442
1443		dateWithinRange: function(date){
1444			return date >= this.o.startDate && date <= this.o.endDate;
1445		},
1446
1447		keydown: function(e){
1448			if (!this.picker.is(':visible')){
1449				if (e.keyCode === 40 || e.keyCode === 27) { // allow down to re-show picker
1450					this.show();
1451					e.stopPropagation();
1452        }
1453				return;
1454			}
1455			var dateChanged = false,
1456				dir, newViewDate,
1457				focusDate = this.focusDate || this.viewDate;
1458			switch (e.keyCode){
1459				case 27: // escape
1460					if (this.focusDate){
1461						this.focusDate = null;
1462						this.viewDate = this.dates.get(-1) || this.viewDate;
1463						this.fill();
1464					}
1465					else
1466						this.hide();
1467					e.preventDefault();
1468					e.stopPropagation();
1469					break;
1470				case 37: // left
1471				case 38: // up
1472				case 39: // right
1473				case 40: // down
1474					if (!this.o.keyboardNavigation || this.o.daysOfWeekDisabled.length === 7)
1475						break;
1476					dir = e.keyCode === 37 || e.keyCode === 38 ? -1 : 1;
1477          if (this.viewMode === 0) {
1478  					if (e.ctrlKey){
1479  						newViewDate = this.moveAvailableDate(focusDate, dir, 'moveYear');
1480
1481  						if (newViewDate)
1482  							this._trigger('changeYear', this.viewDate);
1483  					}
1484  					else if (e.shiftKey){
1485  						newViewDate = this.moveAvailableDate(focusDate, dir, 'moveMonth');
1486
1487  						if (newViewDate)
1488  							this._trigger('changeMonth', this.viewDate);
1489  					}
1490  					else if (e.keyCode === 37 || e.keyCode === 39){
1491  						newViewDate = this.moveAvailableDate(focusDate, dir, 'moveDay');
1492  					}
1493  					else if (!this.weekOfDateIsDisabled(focusDate)){
1494  						newViewDate = this.moveAvailableDate(focusDate, dir, 'moveWeek');
1495  					}
1496          } else if (this.viewMode === 1) {
1497            if (e.keyCode === 38 || e.keyCode === 40) {
1498              dir = dir * 4;
1499            }
1500            newViewDate = this.moveAvailableDate(focusDate, dir, 'moveMonth');
1501          } else if (this.viewMode === 2) {
1502            if (e.keyCode === 38 || e.keyCode === 40) {
1503              dir = dir * 4;
1504            }
1505            newViewDate = this.moveAvailableDate(focusDate, dir, 'moveYear');
1506          }
1507					if (newViewDate){
1508						this.focusDate = this.viewDate = newViewDate;
1509						this.setValue();
1510						this.fill();
1511						e.preventDefault();
1512					}
1513					break;
1514				case 13: // enter
1515					if (!this.o.forceParse)
1516						break;
1517					focusDate = this.focusDate || this.dates.get(-1) || this.viewDate;
1518					if (this.o.keyboardNavigation) {
1519						this._toggle_multidate(focusDate);
1520						dateChanged = true;
1521					}
1522					this.focusDate = null;
1523					this.viewDate = this.dates.get(-1) || this.viewDate;
1524					this.setValue();
1525					this.fill();
1526					if (this.picker.is(':visible')){
1527						e.preventDefault();
1528						e.stopPropagation();
1529						if (this.o.autoclose)
1530							this.hide();
1531					}
1532					break;
1533				case 9: // tab
1534					this.focusDate = null;
1535					this.viewDate = this.dates.get(-1) || this.viewDate;
1536					this.fill();
1537					this.hide();
1538					break;
1539			}
1540			if (dateChanged){
1541				if (this.dates.length)
1542					this._trigger('changeDate');
1543				else
1544					this._trigger('clearDate');
1545				if (this.inputField){
1546					this.inputField.change();
1547				}
1548			}
1549		},
1550
1551		showMode: function(dir){
1552			if (dir){
1553				this.viewMode = Math.max(this.o.minViewMode, Math.min(this.o.maxViewMode, this.viewMode + dir));
1554			}
1555			this.picker
1556				.children('div')
1557				.hide()
1558				.filter('.datepicker-' + DPGlobal.modes[this.viewMode].clsName)
1559					.show();
1560			this.updateNavArrows();
1561		}
1562	};
1563
1564	var DateRangePicker = function(element, options){
1565		$(element).data('datepicker', this);
1566		this.element = $(element);
1567		this.inputs = $.map(options.inputs, function(i){
1568			return i.jquery ? i[0] : i;
1569		});
1570		delete options.inputs;
1571
1572		datepickerPlugin.call($(this.inputs), options)
1573			.on('changeDate', $.proxy(this.dateUpdated, this));
1574
1575		this.pickers = $.map(this.inputs, function(i){
1576			return $(i).data('datepicker');
1577		});
1578		this.updateDates();
1579	};
1580	DateRangePicker.prototype = {
1581		updateDates: function(){
1582			this.dates = $.map(this.pickers, function(i){
1583				return i.getUTCDate();
1584			});
1585			this.updateRanges();
1586		},
1587		updateRanges: function(){
1588			var range = $.map(this.dates, function(d){
1589				return d.valueOf();
1590			});
1591			$.each(this.pickers, function(i, p){
1592				p.setRange(range);
1593			});
1594		},
1595		dateUpdated: function(e){
1596			// `this.updating` is a workaround for preventing infinite recursion
1597			// between `changeDate` triggering and `setUTCDate` calling.  Until
1598			// there is a better mechanism.
1599			if (this.updating)
1600				return;
1601			this.updating = true;
1602
1603			var dp = $(e.target).data('datepicker');
1604
1605			if (typeof(dp) === "undefined") {
1606				return;
1607			}
1608
1609			var new_date = dp.getUTCDate(),
1610				i = $.inArray(e.target, this.inputs),
1611				j = i - 1,
1612				k = i + 1,
1613				l = this.inputs.length;
1614			if (i === -1)
1615				return;
1616
1617			$.each(this.pickers, function(i, p){
1618				if (!p.getUTCDate())
1619					p.setUTCDate(new_date);
1620			});
1621
1622			if (new_date < this.dates[j]){
1623				// Date being moved earlier/left
1624				while (j >= 0 && new_date < this.dates[j]){
1625					this.pickers[j--].setUTCDate(new_date);
1626				}
1627			}
1628			else if (new_date > this.dates[k]){
1629				// Date being moved later/right
1630				while (k < l && new_date > this.dates[k]){
1631					this.pickers[k++].setUTCDate(new_date);
1632				}
1633			}
1634			this.updateDates();
1635
1636			delete this.updating;
1637		},
1638		remove: function(){
1639			$.map(this.pickers, function(p){ p.remove(); });
1640			delete this.element.data().datepicker;
1641		}
1642	};
1643
1644	function opts_from_el(el, prefix){
1645		// Derive options from element data-attrs
1646		var data = $(el).data(),
1647			out = {}, inkey,
1648			replace = new RegExp('^' + prefix.toLowerCase() + '([A-Z])');
1649		prefix = new RegExp('^' + prefix.toLowerCase());
1650		function re_lower(_,a){
1651			return a.toLowerCase();
1652		}
1653		for (var key in data)
1654			if (prefix.test(key)){
1655				inkey = key.replace(replace, re_lower);
1656				out[inkey] = data[key];
1657			}
1658		return out;
1659	}
1660
1661	function opts_from_locale(lang){
1662		// Derive options from locale plugins
1663		var out = {};
1664		// Check if "de-DE" style date is available, if not language should
1665		// fallback to 2 letter code eg "de"
1666		if (!dates[lang]){
1667			lang = lang.split('-')[0];
1668			if (!dates[lang])
1669				return;
1670		}
1671		var d = dates[lang];
1672		$.each(locale_opts, function(i,k){
1673			if (k in d)
1674				out[k] = d[k];
1675		});
1676		return out;
1677	}
1678
1679	var old = $.fn.datepicker;
1680	var datepickerPlugin = function(option){
1681		var args = Array.apply(null, arguments);
1682		args.shift();
1683		var internal_return;
1684		this.each(function(){
1685			var $this = $(this),
1686				data = $this.data('datepicker'),
1687				options = typeof option === 'object' && option;
1688			if (!data){
1689				var elopts = opts_from_el(this, 'date'),
1690					// Preliminary otions
1691					xopts = $.extend({}, defaults, elopts, options),
1692					locopts = opts_from_locale(xopts.language),
1693					// Options priority: js args, data-attrs, locales, defaults
1694					opts = $.extend({}, defaults, locopts, elopts, options);
1695				if ($this.hasClass('input-daterange') || opts.inputs){
1696					$.extend(opts, {
1697						inputs: opts.inputs || $this.find('input').toArray()
1698					});
1699					data = new DateRangePicker(this, opts);
1700				}
1701				else {
1702					data = new Datepicker(this, opts);
1703				}
1704				$this.data('datepicker', data);
1705			}
1706			if (typeof option === 'string' && typeof data[option] === 'function'){
1707				internal_return = data[option].apply(data, args);
1708			}
1709		});
1710
1711		if (
1712			internal_return === undefined ||
1713			internal_return instanceof Datepicker ||
1714			internal_return instanceof DateRangePicker
1715		)
1716			return this;
1717
1718		if (this.length > 1)
1719			throw new Error('Using only allowed for the collection of a single element (' + option + ' function)');
1720		else
1721			return internal_return;
1722	};
1723	$.fn.datepicker = datepickerPlugin;
1724
1725	var defaults = $.fn.datepicker.defaults = {
1726		assumeNearbyYear: false,
1727		autoclose: false,
1728		beforeShowDay: $.noop,
1729		beforeShowMonth: $.noop,
1730		beforeShowYear: $.noop,
1731		beforeShowDecade: $.noop,
1732		beforeShowCentury: $.noop,
1733		calendarWeeks: false,
1734		clearBtn: false,
1735		toggleActive: false,
1736		daysOfWeekDisabled: [],
1737		daysOfWeekHighlighted: [],
1738		datesDisabled: [],
1739		endDate: Infinity,
1740		forceParse: true,
1741		format: 'mm/dd/yyyy',
1742		keyboardNavigation: true,
1743		language: 'en',
1744		minViewMode: 0,
1745		maxViewMode: 4,
1746		multidate: false,
1747		multidateSeparator: ',',
1748		orientation: "auto",
1749		rtl: false,
1750		startDate: -Infinity,
1751		startView: 0,
1752		todayBtn: false,
1753		todayHighlight: false,
1754		weekStart: 0,
1755		disableTouchKeyboard: false,
1756		enableOnReadonly: true,
1757		showOnFocus: true,
1758		zIndexOffset: 10,
1759		container: 'body',
1760		immediateUpdates: false,
1761		title: '',
1762		templates: {
1763			leftArrow: '&laquo;',
1764			rightArrow: '&raquo;'
1765		}
1766	};
1767	var locale_opts = $.fn.datepicker.locale_opts = [
1768		'format',
1769		'rtl',
1770		'weekStart'
1771	];
1772	$.fn.datepicker.Constructor = Datepicker;
1773	var dates = $.fn.datepicker.dates = {
1774		en: {
1775			days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
1776			daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
1777			daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"],
1778			months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
1779			monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
1780			today: "Today",
1781			clear: "Clear",
1782			titleFormat: "MM yyyy"
1783		}
1784	};
1785
1786	var DPGlobal = {
1787		modes: [
1788			{
1789				clsName: 'days',
1790				navFnc: 'Month',
1791				navStep: 1
1792			},
1793			{
1794				clsName: 'months',
1795				navFnc: 'FullYear',
1796				navStep: 1
1797			},
1798			{
1799				clsName: 'years',
1800				navFnc: 'FullYear',
1801				navStep: 10
1802			},
1803			{
1804				clsName: 'decades',
1805				navFnc: 'FullDecade',
1806				navStep: 100
1807			},
1808			{
1809				clsName: 'centuries',
1810				navFnc: 'FullCentury',
1811				navStep: 1000
1812		}],
1813		isLeapYear: function(year){
1814			return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0));
1815		},
1816		getDaysInMonth: function(year, month){
1817			return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
1818		},
1819		validParts: /dd?|DD?|mm?|MM?|yy(?:yy)?/g,
1820		nonpunctuation: /[^ -\/:-@\u5e74\u6708\u65e5\[-`{-~\t\n\r]+/g,
1821		parseFormat: function(format){
1822			if (typeof format.toValue === 'function' && typeof format.toDisplay === 'function')
1823                return format;
1824            // IE treats \0 as a string end in inputs (truncating the value),
1825			// so it's a bad format delimiter, anyway
1826			var separators = format.replace(this.validParts, '\0').split('\0'),
1827				parts = format.match(this.validParts);
1828			if (!separators || !separators.length || !parts || parts.length === 0){
1829				throw new Error("Invalid date format.");
1830			}
1831			return {separators: separators, parts: parts};
1832		},
1833		parseDate: function(date, format, language, assumeNearby){
1834			if (!date)
1835				return undefined;
1836			if (date instanceof Date)
1837				return date;
1838			if (typeof format === 'string')
1839				format = DPGlobal.parseFormat(format);
1840			if (format.toValue)
1841                return format.toValue(date, format, language);
1842            var part_re = /([\-+]\d+)([dmwy])/,
1843				parts = date.match(/([\-+]\d+)([dmwy])/g),
1844				fn_map = {
1845					d: 'moveDay',
1846					m: 'moveMonth',
1847					w: 'moveWeek',
1848					y: 'moveYear'
1849				},
1850				dateAliases = {
1851					yesterday: '-1d',
1852					today: '+0d',
1853					tomorrow: '+1d'
1854				},
1855				part, dir, i, fn;
1856			if (/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/.test(date)){
1857				date = new Date();
1858				for (i=0; i < parts.length; i++){
1859					part = part_re.exec(parts[i]);
1860					dir = parseInt(part[1]);
1861					fn = fn_map[part[2]];
1862					date = Datepicker.prototype[fn](date, dir);
1863				}
1864				return UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate());
1865			}
1866
1867			if (typeof dateAliases[date] !== 'undefined') {
1868				date = dateAliases[date];
1869				parts = date.match(/([\-+]\d+)([dmwy])/g);
1870
1871				if (/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/.test(date)){
1872					date = new Date();
1873				  	for (i=0; i < parts.length; i++){
1874						part = part_re.exec(parts[i]);
1875						dir = parseInt(part[1]);
1876						fn = fn_map[part[2]];
1877						date = Datepicker.prototype[fn](date, dir);
1878				  	}
1879
1880			  		return UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate());
1881				}
1882			}
1883
1884			parts = date && date.match(this.nonpunctuation) || [];
1885			date = new Date();
1886
1887			function applyNearbyYear(year, threshold){
1888				if (threshold === true)
1889					threshold = 10;
1890
1891				// if year is 2 digits or less, than the user most likely is trying to get a recent century
1892				if (year < 100){
1893					year += 2000;
1894					// if the new year is more than threshold years in advance, use last century
1895					if (year > ((new Date()).getFullYear()+threshold)){
1896						year -= 100;
1897					}
1898				}
1899
1900				return year;
1901			}
1902
1903			var parsed = {},
1904				setters_order = ['yyyy', 'yy', 'M', 'MM', 'm', 'mm', 'd', 'dd'],
1905				setters_map = {
1906					yyyy: function(d,v){
1907						return d.setUTCFullYear(assumeNearby ? applyNearbyYear(v, assumeNearby) : v);
1908					},
1909					yy: function(d,v){
1910						return d.setUTCFullYear(assumeNearby ? applyNearbyYear(v, assumeNearby) : v);
1911					},
1912					m: function(d,v){
1913						if (isNaN(d))
1914							return d;
1915						v -= 1;
1916						while (v < 0) v += 12;
1917						v %= 12;
1918						d.setUTCMonth(v);
1919						while (d.getUTCMonth() !== v)
1920							d.setUTCDate(d.getUTCDate()-1);
1921						return d;
1922					},
1923					d: function(d,v){
1924						return d.setUTCDate(v);
1925					}
1926				},
1927				val, filtered;
1928			setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m'];
1929			setters_map['dd'] = setters_map['d'];
1930			date = UTCToday();
1931			var fparts = format.parts.slice();
1932			// Remove noop parts
1933			if (parts.length !== fparts.length){
1934				fparts = $(fparts).filter(function(i,p){
1935					return $.inArray(p, setters_order) !== -1;
1936				}).toArray();
1937			}
1938			// Process remainder
1939			function match_part(){
1940				var m = this.slice(0, parts[i].length),
1941					p = parts[i].slice(0, m.length);
1942				return m.toLowerCase() === p.toLowerCase();
1943			}
1944			if (parts.length === fparts.length){
1945				var cnt;
1946				for (i=0, cnt = fparts.length; i < cnt; i++){
1947					val = parseInt(parts[i], 10);
1948					part = fparts[i];
1949					if (isNaN(val)){
1950						switch (part){
1951							case 'MM':
1952								filtered = $(dates[language].months).filter(match_part);
1953								val = $.inArray(filtered[0], dates[language].months) + 1;
1954								break;
1955							case 'M':
1956								filtered = $(dates[language].monthsShort).filter(match_part);
1957								val = $.inArray(filtered[0], dates[language].monthsShort) + 1;
1958								break;
1959						}
1960					}
1961					parsed[part] = val;
1962				}
1963				var _date, s;
1964				for (i=0; i < setters_order.length; i++){
1965					s = setters_order[i];
1966					if (s in parsed && !isNaN(parsed[s])){
1967						_date = new Date(date);
1968						setters_map[s](_date, parsed[s]);
1969						if (!isNaN(_date))
1970							date = _date;
1971					}
1972				}
1973			}
1974			return date;
1975		},
1976		formatDate: function(date, format, language){
1977			if (!date)
1978				return '';
1979			if (typeof format === 'string')
1980				format = DPGlobal.parseFormat(format);
1981			if (format.toDisplay)
1982                return format.toDisplay(date, format, language);
1983            var val = {
1984				d: date.getUTCDate(),
1985				D: dates[language].daysShort[date.getUTCDay()],
1986				DD: dates[language].days[date.getUTCDay()],
1987				m: date.getUTCMonth() + 1,
1988				M: dates[language].monthsShort[date.getUTCMonth()],
1989				MM: dates[language].months[date.getUTCMonth()],
1990				yy: date.getUTCFullYear().toString().substring(2),
1991				yyyy: date.getUTCFullYear()
1992			};
1993			val.dd = (val.d < 10 ? '0' : '') + val.d;
1994			val.mm = (val.m < 10 ? '0' : '') + val.m;
1995			date = [];
1996			var seps = $.extend([], format.separators);
1997			for (var i=0, cnt = format.parts.length; i <= cnt; i++){
1998				if (seps.length)
1999					date.push(seps.shift());
2000				date.push(val[format.parts[i]]);
2001			}
2002			return date.join('');
2003		},
2004		headTemplate: '<thead>'+
2005			              '<tr>'+
2006			                '<th colspan="7" class="datepicker-title"></th>'+
2007			              '</tr>'+
2008							'<tr>'+
2009								'<th class="prev">&laquo;</th>'+
2010								'<th colspan="5" class="datepicker-switch"></th>'+
2011								'<th class="next">&raquo;</th>'+
2012							'</tr>'+
2013						'</thead>',
2014		contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>',
2015		footTemplate: '<tfoot>'+
2016							'<tr>'+
2017								'<th colspan="7" class="today"></th>'+
2018							'</tr>'+
2019							'<tr>'+
2020								'<th colspan="7" class="clear"></th>'+
2021							'</tr>'+
2022						'</tfoot>'
2023	};
2024	DPGlobal.template = '<div class="datepicker">'+
2025							'<div class="datepicker-days">'+
2026								'<table class="table-condensed">'+
2027									DPGlobal.headTemplate+
2028									'<tbody></tbody>'+
2029									DPGlobal.footTemplate+
2030								'</table>'+
2031							'</div>'+
2032							'<div class="datepicker-months">'+
2033								'<table class="table-condensed">'+
2034									DPGlobal.headTemplate+
2035									DPGlobal.contTemplate+
2036									DPGlobal.footTemplate+
2037								'</table>'+
2038							'</div>'+
2039							'<div class="datepicker-years">'+
2040								'<table class="table-condensed">'+
2041									DPGlobal.headTemplate+
2042									DPGlobal.contTemplate+
2043									DPGlobal.footTemplate+
2044								'</table>'+
2045							'</div>'+
2046							'<div class="datepicker-decades">'+
2047								'<table class="table-condensed">'+
2048									DPGlobal.headTemplate+
2049									DPGlobal.contTemplate+
2050									DPGlobal.footTemplate+
2051								'</table>'+
2052							'</div>'+
2053							'<div class="datepicker-centuries">'+
2054								'<table class="table-condensed">'+
2055									DPGlobal.headTemplate+
2056									DPGlobal.contTemplate+
2057									DPGlobal.footTemplate+
2058								'</table>'+
2059							'</div>'+
2060						'</div>';
2061
2062	$.fn.datepicker.DPGlobal = DPGlobal;
2063
2064
2065	/* DATEPICKER NO CONFLICT
2066	* =================== */
2067
2068	$.fn.datepicker.noConflict = function(){
2069		$.fn.datepicker = old;
2070		return this;
2071	};
2072
2073	/* DATEPICKER VERSION
2074	 * =================== */
2075	$.fn.datepicker.version = '1.6.4';
vendor: 463 bytes, lines 2075-2096
2075
2076
2077	/* DATEPICKER DATA-API
2078	* ================== */
2079
2080	$(document).on(
2081		'focus.datepicker.data-api click.datepicker.data-api',
2082		'[data-provide="datepicker"]',
2083		function(e){
2084			var $this = $(this);
2085			if ($this.data('datepicker'))
2086				return;
2087			e.preventDefault();
2088			// component click requires us to explicitly show it
2089			datepickerPlugin.call($this, 'show');
2090		}
2091	);
2092	$(function(){
2093		datepickerPlugin.call($('[data-provide="datepicker-inline"]'));
2094	});
2095
2096}));

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.