PageSourceSearch

https://tempatsenang.com/wp-content/themes/tempatsenang/assets/ven…/js/bootstrap-datepicker.js

js tempatsenang.com collected 2026-10-05 11:09:57 UTC 57,647 bytes, 2,035 lines download raw bytes

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

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.