tramway-core 1.5.5.1 → 1.5.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2035 @@
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 = $.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 || '',
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 > 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]){
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';
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
+ }));