PageSourceSearch

https://www.zoner.cz/account/Scripts/datepicker/js/bootstrap-datep…?fcd86033-94a7-46e3-87d0-fe37767719b6

js zoner.cz collected 2026-10-02 06:44:03 UTC 57,898 bytes, 2,039 lines download raw bytes

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

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.