bootstrap-datepicker-rails 1.6.4.1 → 1.7.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/lib/bootstrap-datepicker-rails/version.rb +1 -1
  3. data/vendor/assets/javascripts/bootstrap-datepicker/core.js +331 -397
  4. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker-en-CA.js +18 -0
  5. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.ar-tn.js +15 -0
  6. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.bn.js +19 -0
  7. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.br.js +18 -0
  8. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.cs.js +1 -0
  9. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.da.js +8 -6
  10. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.eu.js +5 -1
  11. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.hi.js +18 -0
  12. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.hy.js +5 -4
  13. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.ka.js +1 -1
  14. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.kh.js +9 -3
  15. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.km.js +15 -0
  16. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.kr.js +2 -0
  17. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.lv.js +1 -0
  18. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.oc.js +17 -0
  19. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.pl.js +7 -7
  20. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.ro.js +2 -1
  21. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.rs-latin.js +4 -0
  22. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.rs.js +4 -0
  23. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.ru.js +2 -1
  24. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.si.js +18 -0
  25. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.sl.js +2 -1
  26. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.ta.js +18 -0
  27. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.tg.js +19 -0
  28. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.uz-cyrl.js +18 -0
  29. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.uz-latn.js +18 -0
  30. data/vendor/assets/stylesheets/bootstrap-datepicker.css +11 -5
  31. data/vendor/assets/stylesheets/bootstrap-datepicker3.css +11 -5
  32. metadata +15 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3d6aca95c5f880c6e27ff17d0a0a841d54932bdd
4
- data.tar.gz: 26a0b29b42f6cf351854a6f157a356c8472ebb30
3
+ metadata.gz: e6d9437ec47d901edbc9145062e3b42184ab5d02
4
+ data.tar.gz: 3a409a8beb5c437e7f415a9dc802f13aadb0e261
5
5
  SHA512:
6
- metadata.gz: b819389cee934d6389935caef8dfca0e04df3fc139158a8a5a51de55cdc452b5dc3098dc28cc794a148507f40cbe9cd5bd79176ac13750b8c340422b0c56a44b
7
- data.tar.gz: 7b22978cb0a96675833ced8f09c07a3e60fccc3e7ed10ded7f075970f3be054c2af43252939e98939b57b277a4e7cd5516400fb482a0f994e2936765af0d5ccb
6
+ metadata.gz: 53c13bd180552f76804a8eaea5617ee219bc125db3c486cb6b0f2a1afb642c1ef87bb5e1e42ec51a1ebd3bac067db08acf387e815d58186477de87a1e7f6adb2
7
+ data.tar.gz: ab990de96a3f0ced09c25850b09c48576b04def8834fc17e8b41c6c08760c7009857a4c22fc1917a19ba23ddf9c93e1f33ec1ea97d05c7ab27f92e02720cfa38
@@ -1,5 +1,5 @@
1
1
  module BootstrapDatepickerRails
2
2
  module Rails
3
- VERSION = "1.6.4.1"
3
+ VERSION = "1.7.1.1"
4
4
  end
5
5
  end
@@ -1,10 +1,10 @@
1
1
  /*!
2
- * Datepicker for Bootstrap v1.6.4 (https://github.com/eternicode/bootstrap-datepicker)
2
+ * Datepicker for Bootstrap v1.7.1 (https://github.com/uxsolutions/bootstrap-datepicker)
3
3
  *
4
- * Copyright 2012 Stefan Petre
5
- * Improvements by Andrew Rowls
6
4
  * Licensed under the Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0)
7
- */(function(factory){
5
+ */
6
+
7
+ (function(factory){
8
8
  if (typeof define === "function" && define.amd) {
9
9
  define(["jquery"], factory);
10
10
  } else if (typeof exports === 'object') {
@@ -13,7 +13,6 @@
13
13
  factory(jQuery);
14
14
  }
15
15
  }(function($, undefined){
16
-
17
16
  function UTCDate(){
18
17
  return new Date(Date.UTC.apply(Date, arguments));
19
18
  }
@@ -28,8 +27,12 @@
28
27
  date1.getUTCDate() === date2.getUTCDate()
29
28
  );
30
29
  }
31
- function alias(method){
30
+ function alias(method, deprecationMsg){
32
31
  return function(){
32
+ if (deprecationMsg !== undefined) {
33
+ $.fn.datepicker.deprecated(deprecationMsg);
34
+ }
35
+
33
36
  return this[method].apply(this, arguments);
34
37
  };
35
38
  }
@@ -47,7 +50,8 @@
47
50
  // $.inArray doesn't work with Dates
48
51
  var val = d && d.valueOf();
49
52
  for (var i=0, l=this.length; i < l; i++)
50
- if (this[i].valueOf() === val)
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)
51
55
  return i;
52
56
  return -1;
53
57
  },
@@ -84,7 +88,7 @@
84
88
  // Picker object
85
89
 
86
90
  var Datepicker = function(element, options){
87
- $(element).data('datepicker', this);
91
+ $.data(element, 'datepicker', this);
88
92
  this._process_options(options);
89
93
 
90
94
  this.dates = new DateArray();
@@ -95,7 +99,6 @@
95
99
  this.isInput = this.element.is('input');
96
100
  this.inputField = this.isInput ? this.element : this.element.find('input');
97
101
  this.component = this.element.hasClass('date') ? this.element.find('.add-on, .input-group-addon, .btn') : false;
98
- this.hasInput = this.component && this.inputField.length;
99
102
  if (this.component && this.component.length === 0)
100
103
  this.component = false;
101
104
  this.isInline = !this.component && this.element.is('div');
@@ -106,6 +109,7 @@
106
109
  if (this._check_template(this.o.templates.leftArrow)) {
107
110
  this.picker.find('.prev').html(this.o.templates.leftArrow);
108
111
  }
112
+
109
113
  if (this._check_template(this.o.templates.rightArrow)) {
110
114
  this.picker.find('.next').html(this.o.templates.rightArrow);
111
115
  }
@@ -124,29 +128,29 @@
124
128
  this.picker.addClass('datepicker-rtl');
125
129
  }
126
130
 
127
- this.viewMode = this.o.startView;
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
+ }
128
137
 
129
- if (this.o.calendarWeeks)
130
- this.picker.find('thead .datepicker-title, tfoot .today, tfoot .clear')
131
- .attr('colspan', function(i, val){
132
- return parseInt(val) + 1;
133
- });
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
+ });
134
145
 
135
146
  this._allow_update = false;
136
-
137
- this.setStartDate(this._o.startDate);
138
- this.setEndDate(this._o.endDate);
139
- this.setDaysOfWeekDisabled(this.o.daysOfWeekDisabled);
140
- this.setDaysOfWeekHighlighted(this.o.daysOfWeekHighlighted);
141
- this.setDatesDisabled(this.o.datesDisabled);
147
+ this.setViewMode(this.o.startView);
148
+ this._allow_update = true;
142
149
 
143
150
  this.fillDow();
144
151
  this.fillMonths();
145
152
 
146
- this._allow_update = true;
147
-
148
153
  this.update();
149
- this.showMode();
150
154
 
151
155
  if (this.isInline){
152
156
  this.show();
@@ -156,23 +160,21 @@
156
160
  Datepicker.prototype = {
157
161
  constructor: Datepicker,
158
162
 
159
- _resolveViewName: function(view, default_value){
160
- if (view === 0 || view === 'days' || view === 'month') {
161
- return 0;
162
- }
163
- if (view === 1 || view === 'months' || view === 'year') {
164
- return 1;
165
- }
166
- if (view === 2 || view === 'years' || view === 'decade') {
167
- return 2;
168
- }
169
- if (view === 3 || view === 'decades' || view === 'century') {
170
- return 3;
171
- }
172
- if (view === 4 || view === 'centuries' || view === 'millennium') {
173
- return 4;
174
- }
175
- return default_value === undefined ? false : default_value;
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);
176
178
  },
177
179
 
178
180
  _check_template: function(tmp){
@@ -211,13 +213,12 @@
211
213
  o.language = lang;
212
214
 
213
215
  // Retrieve view index from any aliases
214
- o.startView = this._resolveViewName(o.startView, 0);
215
- o.minViewMode = this._resolveViewName(o.minViewMode, 0);
216
- o.maxViewMode = this._resolveViewName(o.maxViewMode, 4);
216
+ o.startView = this._resolveViewName(o.startView);
217
+ o.minViewMode = this._resolveViewName(o.minViewMode);
218
+ o.maxViewMode = this._resolveViewName(o.maxViewMode);
217
219
 
218
- // Check that the start view is between min and max
219
- o.startView = Math.min(o.startView, o.maxViewMode);
220
- o.startView = Math.max(o.startView, o.minViewMode);
220
+ // Check view is between min and max
221
+ o.startView = Math.max(this.o.minViewMode, Math.min(this.o.maxViewMode, o.startView));
221
222
 
222
223
  // true, false, or Number > 0
223
224
  if (o.multidate !== true){
@@ -254,27 +255,14 @@
254
255
  }
255
256
  }
256
257
 
257
- o.daysOfWeekDisabled = o.daysOfWeekDisabled||[];
258
- if (!$.isArray(o.daysOfWeekDisabled))
259
- o.daysOfWeekDisabled = o.daysOfWeekDisabled.split(/[,\s]*/);
260
- o.daysOfWeekDisabled = $.map(o.daysOfWeekDisabled, function(d){
261
- return parseInt(d, 10);
262
- });
263
-
264
- o.daysOfWeekHighlighted = o.daysOfWeekHighlighted||[];
265
- if (!$.isArray(o.daysOfWeekHighlighted))
266
- o.daysOfWeekHighlighted = o.daysOfWeekHighlighted.split(/[,\s]*/);
267
- o.daysOfWeekHighlighted = $.map(o.daysOfWeekHighlighted, function(d){
268
- return parseInt(d, 10);
269
- });
258
+ o.daysOfWeekDisabled = this._resolveDaysOfWeek(o.daysOfWeekDisabled||[]);
259
+ o.daysOfWeekHighlighted = this._resolveDaysOfWeek(o.daysOfWeekHighlighted||[]);
270
260
 
271
261
  o.datesDisabled = o.datesDisabled||[];
272
262
  if (!$.isArray(o.datesDisabled)) {
273
- o.datesDisabled = [
274
- o.datesDisabled
275
- ];
263
+ o.datesDisabled = o.datesDisabled.split(',');
276
264
  }
277
- o.datesDisabled = $.map(o.datesDisabled,function(d){
265
+ o.datesDisabled = $.map(o.datesDisabled, function(d){
278
266
  return DPGlobal.parseDate(d, format, o.language, o.assumeNearbyYear);
279
267
  });
280
268
 
@@ -309,7 +297,9 @@
309
297
  });
310
298
  o.orientation.y = _plc[0] || 'auto';
311
299
  }
312
- if (o.defaultViewDate) {
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) {
313
303
  var year = o.defaultViewDate.year || new Date().getFullYear();
314
304
  var month = o.defaultViewDate.month || 0;
315
305
  var day = o.defaultViewDate.day || 1;
@@ -326,8 +316,7 @@
326
316
  if (evs[i].length === 2){
327
317
  ch = undefined;
328
318
  ev = evs[i][1];
329
- }
330
- else if (evs[i].length === 3){
319
+ } else if (evs[i].length === 3){
331
320
  ch = evs[i][1];
332
321
  ev = evs[i][2];
333
322
  }
@@ -340,8 +329,7 @@
340
329
  if (evs[i].length === 2){
341
330
  ch = undefined;
342
331
  ev = evs[i][1];
343
- }
344
- else if (evs[i].length === 3){
332
+ } else if (evs[i].length === 3){
345
333
  ch = evs[i][1];
346
334
  ev = evs[i][2];
347
335
  }
@@ -367,7 +355,8 @@
367
355
  [this.element, events]
368
356
  ];
369
357
  }
370
- else if (this.component && this.hasInput) { // component: input + button
358
+ // component: input + button
359
+ else if (this.component && this.inputField.length) {
371
360
  this._events = [
372
361
  // For components that are not readonly, allow keyboard nav
373
362
  [this.inputField, events],
@@ -412,11 +401,17 @@
412
401
  [this.picker, {
413
402
  click: $.proxy(this.click, this)
414
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
+ }],
415
410
  [$(window), {
416
411
  resize: $.proxy(this.place, this)
417
412
  }],
418
413
  [$(document), {
419
- mousedown: $.proxy(function(e){
414
+ 'mousedown touchstart': $.proxy(function(e){
420
415
  // Clicked outside the datepicker, hide it
421
416
  if (!(
422
417
  this.element.is(e.target) ||
@@ -452,13 +447,13 @@
452
447
  this.element.trigger({
453
448
  type: event,
454
449
  date: local_date,
450
+ viewMode: this.viewMode,
455
451
  dates: $.map(this.dates, this._utc_to_local),
456
452
  format: $.proxy(function(ix, format){
457
453
  if (arguments.length === 0){
458
454
  ix = this.dates.length - 1;
459
455
  format = this.o.format;
460
- }
461
- else if (typeof ix === 'string'){
456
+ } else if (typeof ix === 'string'){
462
457
  format = ix;
463
458
  ix = this.dates.length - 1;
464
459
  }
@@ -490,8 +485,7 @@
490
485
  this.focusDate = null;
491
486
  this.picker.hide().detach();
492
487
  this._detachSecondaryEvents();
493
- this.viewMode = this.o.startView;
494
- this.showMode();
488
+ this.setViewMode(this.o.startView);
495
489
 
496
490
  if (this.o.forceParse && this.inputField.val())
497
491
  this.setValue();
@@ -511,25 +505,33 @@
511
505
  return this;
512
506
  },
513
507
 
514
- paste: function(evt){
508
+ paste: function(e){
515
509
  var dateString;
516
- if (evt.originalEvent.clipboardData && evt.originalEvent.clipboardData.types
517
- && $.inArray('text/plain', evt.originalEvent.clipboardData.types) !== -1) {
518
- dateString = evt.originalEvent.clipboardData.getData('text/plain');
519
- }
520
- else if (window.clipboardData) {
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) {
521
514
  dateString = window.clipboardData.getData('Text');
522
- }
523
- else {
515
+ } else {
524
516
  return;
525
517
  }
526
518
  this.setDate(dateString);
527
519
  this.update();
528
- evt.preventDefault();
520
+ e.preventDefault();
529
521
  },
530
522
 
531
523
  _utc_to_local: function(utc){
532
- return utc && new Date(utc.getTime() + (utc.getTimezoneOffset()*60000));
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;
533
535
  },
534
536
  _local_to_utc: function(local){
535
537
  return local && new Date(local.getTime() - (local.getTimezoneOffset()*60000));
@@ -538,7 +540,7 @@
538
540
  return local && new Date(local.getFullYear(), local.getMonth(), local.getDate());
539
541
  },
540
542
  _zero_utc_time: function(utc){
541
- return utc && new Date(Date.UTC(utc.getUTCFullYear(), utc.getUTCMonth(), utc.getUTCDate()));
543
+ return utc && UTCDate(utc.getUTCFullYear(), utc.getUTCMonth(), utc.getUTCDate());
542
544
  },
543
545
 
544
546
  getDates: function(){
@@ -557,7 +559,7 @@
557
559
 
558
560
  getUTCDate: function(){
559
561
  var selected_date = this.dates.get(-1);
560
- if (typeof selected_date !== 'undefined') {
562
+ if (selected_date !== undefined) {
561
563
  return new Date(selected_date);
562
564
  } else {
563
565
  return null;
@@ -565,10 +567,7 @@
565
567
  },
566
568
 
567
569
  clearDates: function(){
568
- if (this.inputField) {
569
- this.inputField.val('');
570
- }
571
-
570
+ this.inputField.val('');
572
571
  this.update();
573
572
  this._trigger('changeDate');
574
573
 
@@ -576,6 +575,7 @@
576
575
  this.hide();
577
576
  }
578
577
  },
578
+
579
579
  setDates: function(){
580
580
  var args = $.isArray(arguments[0]) ? arguments[0] : arguments;
581
581
  this.update.apply(this, args);
@@ -586,15 +586,13 @@
586
586
 
587
587
  setUTCDates: function(){
588
588
  var args = $.isArray(arguments[0]) ? arguments[0] : arguments;
589
- this.update.apply(this, $.map(args, this._utc_to_local));
590
- this._trigger('changeDate');
591
- this.setValue();
589
+ this.setDates.apply(this, $.map(args, this._utc_to_local));
592
590
  return this;
593
591
  },
594
592
 
595
593
  setDate: alias('setDates'),
596
594
  setUTCDate: alias('setUTCDates'),
597
- remove: alias('destroy'),
595
+ remove: alias('destroy', 'Method `remove` is deprecated and will be removed in version 2.0. Use `destroy` instead'),
598
596
 
599
597
  setValue: function(){
600
598
  var formatted = this.getFormattedDate();
@@ -637,7 +635,6 @@
637
635
  setDaysOfWeekDisabled: function(daysOfWeekDisabled){
638
636
  this._process_options({daysOfWeekDisabled: daysOfWeekDisabled});
639
637
  this.update();
640
- this.updateNavArrows();
641
638
  return this;
642
639
  },
643
640
 
@@ -650,7 +647,7 @@
650
647
  setDatesDisabled: function(datesDisabled){
651
648
  this._process_options({datesDisabled: datesDisabled});
652
649
  this.update();
653
- this.updateNavArrows();
650
+ return this;
654
651
  },
655
652
 
656
653
  place: function(){
@@ -664,17 +661,17 @@
664
661
  scrollTop = this.o.container === 'body' ? $(document).scrollTop() : container.scrollTop(),
665
662
  appendOffset = container.offset();
666
663
 
667
- var parentsZindex = [];
664
+ var parentsZindex = [0];
668
665
  this.element.parents().each(function(){
669
666
  var itemZIndex = $(this).css('z-index');
670
- if (itemZIndex !== 'auto' && itemZIndex !== 0) parentsZindex.push(parseInt(itemZIndex));
667
+ if (itemZIndex !== 'auto' && Number(itemZIndex) !== 0) parentsZindex.push(Number(itemZIndex));
671
668
  });
672
669
  var zIndex = Math.max.apply(Math, parentsZindex) + this.o.zIndexOffset;
673
670
  var offset = this.component ? this.component.parent().offset() : this.element.offset();
674
671
  var height = this.component ? this.component.outerHeight(true) : this.element.outerHeight(false);
675
672
  var width = this.component ? this.component.outerWidth(true) : this.element.outerWidth(false);
676
- var left = offset.left - appendOffset.left,
677
- top = offset.top - appendOffset.top;
673
+ var left = offset.left - appendOffset.left;
674
+ var top = offset.top - appendOffset.top;
678
675
 
679
676
  if (this.o.container !== 'body') {
680
677
  top += scrollTop;
@@ -702,8 +699,13 @@
702
699
  this.picker.addClass('datepicker-orient-right');
703
700
  left += width - calendarWidth;
704
701
  } else {
705
- // Default to left
706
- this.picker.addClass('datepicker-orient-left');
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
+ }
707
709
  }
708
710
  }
709
711
 
@@ -754,8 +756,7 @@
754
756
  dates.push(date);
755
757
  }, this));
756
758
  fromArgs = true;
757
- }
758
- else {
759
+ } else {
759
760
  dates = this.isInput
760
761
  ? this.element.val()
761
762
  : this.element.data('date') || this.inputField.val();
@@ -777,59 +778,63 @@
777
778
  }, this), true);
778
779
  this.dates.replace(dates);
779
780
 
780
- if (this.dates.length)
781
- this.viewDate = new Date(this.dates.get(-1));
782
- else if (this.viewDate < this.o.startDate)
783
- this.viewDate = new Date(this.o.startDate);
784
- else if (this.viewDate > this.o.endDate)
785
- this.viewDate = new Date(this.o.endDate);
786
- else
787
- this.viewDate = this.o.defaultViewDate;
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
+ }
788
791
 
789
792
  if (fromArgs){
790
793
  // setting date by clicking
791
794
  this.setValue();
795
+ this.element.change();
792
796
  }
793
- else if (dates.length){
797
+ else if (this.dates.length){
794
798
  // setting date by typing
795
- if (String(oldDates) !== String(this.dates))
799
+ if (String(oldDates) !== String(this.dates) && fromArgs) {
796
800
  this._trigger('changeDate');
801
+ this.element.change();
802
+ }
797
803
  }
798
- if (!this.dates.length && oldDates.length)
804
+ if (!this.dates.length && oldDates.length) {
799
805
  this._trigger('clearDate');
806
+ this.element.change();
807
+ }
800
808
 
801
809
  this.fill();
802
- this.element.change();
803
810
  return this;
804
811
  },
805
812
 
806
813
  fillDow: function(){
814
+ if (this.o.showWeekDays) {
807
815
  var dowCnt = this.o.weekStart,
808
816
  html = '<tr>';
809
817
  if (this.o.calendarWeeks){
810
- this.picker.find('.datepicker-days .datepicker-switch')
811
- .attr('colspan', function(i, val){
812
- return parseInt(val) + 1;
813
- });
814
818
  html += '<th class="cw">&#160;</th>';
815
819
  }
816
820
  while (dowCnt < this.o.weekStart + 7){
817
821
  html += '<th class="dow';
818
- if ($.inArray(dowCnt, this.o.daysOfWeekDisabled) > -1)
822
+ if ($.inArray(dowCnt, this.o.daysOfWeekDisabled) !== -1)
819
823
  html += ' disabled';
820
824
  html += '">'+dates[this.o.language].daysMin[(dowCnt++)%7]+'</th>';
821
825
  }
822
826
  html += '</tr>';
823
827
  this.picker.find('.datepicker-days thead').append(html);
828
+ }
824
829
  },
825
830
 
826
831
  fillMonths: function(){
827
832
  var localDate = this._utc_to_local(this.viewDate);
828
- var html = '',
829
- i = 0;
830
- while (i < 12){
831
- var focused = localDate && localDate.getMonth() === i ? ' focused' : '';
832
- html += '<span class="month' + focused + '">' + dates[this.o.language].monthsShort[i++]+'</span>';
833
+ 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>';
833
838
  }
834
839
  this.picker.find('.datepicker-months td').html(html);
835
840
  },
@@ -848,20 +853,16 @@
848
853
  var cls = [],
849
854
  year = this.viewDate.getUTCFullYear(),
850
855
  month = this.viewDate.getUTCMonth(),
851
- today = new Date();
856
+ today = UTCToday();
852
857
  if (date.getUTCFullYear() < year || (date.getUTCFullYear() === year && date.getUTCMonth() < month)){
853
858
  cls.push('old');
854
- }
855
- else if (date.getUTCFullYear() > year || (date.getUTCFullYear() === year && date.getUTCMonth() > month)){
859
+ } else if (date.getUTCFullYear() > year || (date.getUTCFullYear() === year && date.getUTCMonth() > month)){
856
860
  cls.push('new');
857
861
  }
858
862
  if (this.focusDate && date.valueOf() === this.focusDate.valueOf())
859
863
  cls.push('focused');
860
- // Compare internal UTC date with local today, not UTC today
861
- if (this.o.todayHighlight &&
862
- date.getUTCFullYear() === today.getFullYear() &&
863
- date.getUTCMonth() === today.getMonth() &&
864
- date.getUTCDate() === today.getDate()){
864
+ // Compare internal UTC date with UTC today, not local today
865
+ if (this.o.todayHighlight && isUTCEquals(date, today)) {
865
866
  cls.push('today');
866
867
  }
867
868
  if (this.dates.contains(date) !== -1)
@@ -870,8 +871,8 @@
870
871
  cls.push('disabled');
871
872
  }
872
873
  if (this.dateIsDisabled(date)){
873
- cls.push('disabled', 'disabled-date');
874
- }
874
+ cls.push('disabled', 'disabled-date');
875
+ }
875
876
  if ($.inArray(date.getUTCDay(), this.o.daysOfWeekHighlighted) !== -1){
876
877
  cls.push('highlighted');
877
878
  }
@@ -893,47 +894,44 @@
893
894
  return cls;
894
895
  },
895
896
 
896
- _fill_yearsView: function(selector, cssClass, factor, step, currentYear, startYear, endYear, callback){
897
- var html, view, year, steps, startStep, endStep, thisYear, i, classes, tooltip, before;
898
-
899
- html = '';
900
- view = this.picker.find(selector);
901
- year = parseInt(currentYear / factor, 10) * factor;
902
- startStep = parseInt(startYear / step, 10) * step;
903
- endStep = parseInt(endYear / step, 10) * step;
904
- steps = $.map(this.dates, function(d){
905
- return parseInt(d.getUTCFullYear() / step, 10) * step;
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
906
  });
907
907
 
908
- view.find('.datepicker-switch').text(year + '-' + (year + step * 9));
909
-
910
- thisYear = year - step;
911
- for (i = -1; i < 11; i += 1) {
908
+ var classes, tooltip, before;
909
+ for (var currVal = startVal - step; currVal <= endVal + step; currVal += step) {
912
910
  classes = [cssClass];
913
911
  tooltip = null;
914
912
 
915
- if (i === -1) {
913
+ if (currVal === startVal - step) {
916
914
  classes.push('old');
917
- } else if (i === 10) {
915
+ } else if (currVal === endVal + step) {
918
916
  classes.push('new');
919
917
  }
920
- if ($.inArray(thisYear, steps) !== -1) {
918
+ if ($.inArray(currVal, selected) !== -1) {
921
919
  classes.push('active');
922
920
  }
923
- if (thisYear < startStep || thisYear > endStep) {
921
+ if (currVal < startYear || currVal > endYear) {
924
922
  classes.push('disabled');
925
923
  }
926
- if (thisYear === this.viewDate.getFullYear()) {
924
+ if (currVal === focusedVal) {
927
925
  classes.push('focused');
928
926
  }
929
927
 
930
- if (callback !== $.noop) {
931
- before = callback(new Date(thisYear, 0, 1));
928
+ if (beforeFn !== $.noop) {
929
+ before = beforeFn(new Date(currVal, 0, 1));
932
930
  if (before === undefined) {
933
931
  before = {};
934
- } else if (typeof(before) === 'boolean') {
932
+ } else if (typeof before === 'boolean') {
935
933
  before = {enabled: before};
936
- } else if (typeof(before) === 'string') {
934
+ } else if (typeof before === 'string') {
937
935
  before = {classes: before};
938
936
  }
939
937
  if (before.enabled === false) {
@@ -947,9 +945,10 @@
947
945
  }
948
946
  }
949
947
 
950
- html += '<span class="' + classes.join(' ') + '"' + (tooltip ? ' title="' + tooltip + '"' : '') + '>' + thisYear + '</span>';
951
- thisYear += step;
948
+ html += '<span class="' + classes.join(' ') + '"' + (tooltip ? ' title="' + tooltip + '"' : '') + '>' + currVal + '</span>';
952
949
  }
950
+
951
+ view.find('.datepicker-switch').text(startVal + '-' + endVal);
953
952
  view.find('td').html(html);
954
953
  },
955
954
 
@@ -972,18 +971,17 @@
972
971
  .text(DPGlobal.formatDate(d, titleFormat, this.o.language));
973
972
  this.picker.find('tfoot .today')
974
973
  .text(todaytxt)
975
- .toggle(this.o.todayBtn !== false);
974
+ .css('display', this.o.todayBtn === true || this.o.todayBtn === 'linked' ? 'table-cell' : 'none');
976
975
  this.picker.find('tfoot .clear')
977
976
  .text(cleartxt)
978
- .toggle(this.o.clearBtn !== false);
977
+ .css('display', this.o.clearBtn === true ? 'table-cell' : 'none');
979
978
  this.picker.find('thead .datepicker-title')
980
979
  .text(this.o.title)
981
- .toggle(this.o.title !== '');
980
+ .css('display', typeof this.o.title === 'string' && this.o.title !== '' ? 'table-cell' : 'none');
982
981
  this.updateNavArrows();
983
982
  this.fillMonths();
984
- var prevMonth = UTCDate(year, month-1, 28),
985
- day = DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth());
986
- prevMonth.setUTCDate(day);
983
+ var prevMonth = UTCDate(year, month, 0),
984
+ day = prevMonth.getUTCDate();
987
985
  prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.o.weekStart + 7)%7);
988
986
  var nextMonth = new Date(prevMonth);
989
987
  if (prevMonth.getUTCFullYear() < 100){
@@ -992,35 +990,38 @@
992
990
  nextMonth.setUTCDate(nextMonth.getUTCDate() + 42);
993
991
  nextMonth = nextMonth.valueOf();
994
992
  var html = [];
995
- var clsName;
993
+ var weekDay, clsName;
996
994
  while (prevMonth.valueOf() < nextMonth){
997
- if (prevMonth.getUTCDay() === this.o.weekStart){
995
+ weekDay = prevMonth.getUTCDay();
996
+ if (weekDay === this.o.weekStart){
998
997
  html.push('<tr>');
999
998
  if (this.o.calendarWeeks){
1000
999
  // ISO 8601: First week contains first thursday.
1001
1000
  // ISO also states week starts on Monday, but we can be more abstract here.
1002
1001
  var
1003
1002
  // Start of current week: based on weekstart/current date
1004
- ws = new Date(+prevMonth + (this.o.weekStart - prevMonth.getUTCDay() - 7) % 7 * 864e5),
1003
+ ws = new Date(+prevMonth + (this.o.weekStart - weekDay - 7) % 7 * 864e5),
1005
1004
  // Thursday of this week
1006
1005
  th = new Date(Number(ws) + (7 + 4 - ws.getUTCDay()) % 7 * 864e5),
1007
1006
  // First Thursday of year, year from thursday
1008
- yth = new Date(Number(yth = UTCDate(th.getUTCFullYear(), 0, 1)) + (7 + 4 - yth.getUTCDay())%7*864e5),
1007
+ yth = new Date(Number(yth = UTCDate(th.getUTCFullYear(), 0, 1)) + (7 + 4 - yth.getUTCDay()) % 7 * 864e5),
1009
1008
  // Calendar week: ms between thursdays, div ms per day, div 7 days
1010
- calWeek = (th - yth) / 864e5 / 7 + 1;
1009
+ calWeek = (th - yth) / 864e5 / 7 + 1;
1011
1010
  html.push('<td class="cw">'+ calWeek +'</td>');
1012
1011
  }
1013
1012
  }
1014
1013
  clsName = this.getClassNames(prevMonth);
1015
1014
  clsName.push('day');
1016
1015
 
1016
+ var content = prevMonth.getUTCDate();
1017
+
1017
1018
  if (this.o.beforeShowDay !== $.noop){
1018
1019
  before = this.o.beforeShowDay(this._utc_to_local(prevMonth));
1019
1020
  if (before === undefined)
1020
1021
  before = {};
1021
- else if (typeof(before) === 'boolean')
1022
+ else if (typeof before === 'boolean')
1022
1023
  before = {enabled: before};
1023
- else if (typeof(before) === 'string')
1024
+ else if (typeof before === 'string')
1024
1025
  before = {classes: before};
1025
1026
  if (before.enabled === false)
1026
1027
  clsName.push('disabled');
@@ -1028,6 +1029,8 @@
1028
1029
  clsName = clsName.concat(before.classes.split(/\s+/));
1029
1030
  if (before.tooltip)
1030
1031
  tooltip = before.tooltip;
1032
+ if (before.content)
1033
+ content = before.content;
1031
1034
  }
1032
1035
 
1033
1036
  //Check if uniqueSort exists (supported by jquery >=1.12 and >=2.2)
@@ -1038,21 +1041,21 @@
1038
1041
  clsName = $.unique(clsName);
1039
1042
  }
1040
1043
 
1041
- html.push('<td class="'+clsName.join(' ')+'"' + (tooltip ? ' title="'+tooltip+'"' : '') + '>'+prevMonth.getUTCDate() + '</td>');
1044
+ html.push('<td class="'+clsName.join(' ')+'"' + (tooltip ? ' title="'+tooltip+'"' : '') + ' data-date="' + prevMonth.getTime().toString() + '">' + content + '</td>');
1042
1045
  tooltip = null;
1043
- if (prevMonth.getUTCDay() === this.o.weekEnd){
1046
+ if (weekDay === this.o.weekEnd){
1044
1047
  html.push('</tr>');
1045
1048
  }
1046
- prevMonth.setUTCDate(prevMonth.getUTCDate()+1);
1049
+ prevMonth.setUTCDate(prevMonth.getUTCDate() + 1);
1047
1050
  }
1048
- this.picker.find('.datepicker-days tbody').empty().append(html.join(''));
1051
+ this.picker.find('.datepicker-days tbody').html(html.join(''));
1049
1052
 
1050
1053
  var monthsTitle = dates[this.o.language].monthsTitle || dates['en'].monthsTitle || 'Months';
1051
1054
  var months = this.picker.find('.datepicker-months')
1052
1055
  .find('.datepicker-switch')
1053
1056
  .text(this.o.maxViewMode < 2 ? monthsTitle : year)
1054
1057
  .end()
1055
- .find('span').removeClass('active');
1058
+ .find('tbody span').removeClass('active');
1056
1059
 
1057
1060
  $.each(this.dates, function(i, d){
1058
1061
  if (d.getUTCFullYear() === year)
@@ -1076,9 +1079,9 @@
1076
1079
  var before = that.o.beforeShowMonth(moDate);
1077
1080
  if (before === undefined)
1078
1081
  before = {};
1079
- else if (typeof(before) === 'boolean')
1082
+ else if (typeof before === 'boolean')
1080
1083
  before = {enabled: before};
1081
- else if (typeof(before) === 'string')
1084
+ else if (typeof before === 'string')
1082
1085
  before = {classes: before};
1083
1086
  if (before.enabled === false && !$(month).hasClass('disabled'))
1084
1087
  $(month).addClass('disabled');
@@ -1094,7 +1097,6 @@
1094
1097
  '.datepicker-years',
1095
1098
  'year',
1096
1099
  10,
1097
- 1,
1098
1100
  year,
1099
1101
  startYear,
1100
1102
  endYear,
@@ -1106,7 +1108,6 @@
1106
1108
  '.datepicker-decades',
1107
1109
  'decade',
1108
1110
  100,
1109
- 10,
1110
1111
  year,
1111
1112
  startYear,
1112
1113
  endYear,
@@ -1118,7 +1119,6 @@
1118
1119
  '.datepicker-centuries',
1119
1120
  'century',
1120
1121
  1000,
1121
- 100,
1122
1122
  year,
1123
1123
  startYear,
1124
1124
  endYear,
@@ -1132,73 +1132,53 @@
1132
1132
 
1133
1133
  var d = new Date(this.viewDate),
1134
1134
  year = d.getUTCFullYear(),
1135
- month = d.getUTCMonth();
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;
1136
1143
  switch (this.viewMode){
1137
1144
  case 0:
1138
- if (this.o.startDate !== -Infinity && year <= this.o.startDate.getUTCFullYear() && month <= this.o.startDate.getUTCMonth()){
1139
- this.picker.find('.prev').css({visibility: 'hidden'});
1140
- }
1141
- else {
1142
- this.picker.find('.prev').css({visibility: 'visible'});
1143
- }
1144
- if (this.o.endDate !== Infinity && year >= this.o.endDate.getUTCFullYear() && month >= this.o.endDate.getUTCMonth()){
1145
- this.picker.find('.next').css({visibility: 'hidden'});
1146
- }
1147
- else {
1148
- this.picker.find('.next').css({visibility: 'visible'});
1149
- }
1145
+ prevIsDisabled = year <= startYear && month <= startMonth;
1146
+ nextIsDisabled = year >= endYear && month >= endMonth;
1150
1147
  break;
1151
- case 1:
1152
- case 2:
1153
- case 3:
1154
1148
  case 4:
1155
- if (this.o.startDate !== -Infinity && year <= this.o.startDate.getUTCFullYear() || this.o.maxViewMode < 2){
1156
- this.picker.find('.prev').css({visibility: 'hidden'});
1157
- }
1158
- else {
1159
- this.picker.find('.prev').css({visibility: 'visible'});
1160
- }
1161
- if (this.o.endDate !== Infinity && year >= this.o.endDate.getUTCFullYear() || this.o.maxViewMode < 2){
1162
- this.picker.find('.next').css({visibility: 'hidden'});
1163
- }
1164
- else {
1165
- this.picker.find('.next').css({visibility: 'visible'});
1166
- }
1149
+ factor *= 10;
1150
+ /* falls through */
1151
+ case 3:
1152
+ factor *= 10;
1153
+ /* falls through */
1154
+ case 2:
1155
+ factor *= 10;
1156
+ /* falls through */
1157
+ case 1:
1158
+ prevIsDisabled = Math.floor(year / factor) * factor <= startYear;
1159
+ nextIsDisabled = Math.floor(year / factor) * factor + factor >= endYear;
1167
1160
  break;
1168
1161
  }
1162
+
1163
+ this.picker.find('.prev').toggleClass('disabled', prevIsDisabled);
1164
+ this.picker.find('.next').toggleClass('disabled', nextIsDisabled);
1169
1165
  },
1170
1166
 
1171
1167
  click: function(e){
1172
1168
  e.preventDefault();
1173
1169
  e.stopPropagation();
1174
1170
 
1175
- var target, dir, day, year, month, monthChanged, yearChanged;
1171
+ var target, dir, day, year, month;
1176
1172
  target = $(e.target);
1177
1173
 
1178
1174
  // Clicked on the switch
1179
- if (target.hasClass('datepicker-switch')){
1180
- this.showMode(1);
1181
- }
1182
-
1183
- // Clicked on prev or next
1184
- var navArrow = target.closest('.prev, .next');
1185
- if (navArrow.length > 0) {
1186
- dir = DPGlobal.modes[this.viewMode].navStep * (navArrow.hasClass('prev') ? -1 : 1);
1187
- if (this.viewMode === 0){
1188
- this.viewDate = this.moveMonth(this.viewDate, dir);
1189
- this._trigger('changeMonth', this.viewDate);
1190
- } else {
1191
- this.viewDate = this.moveYear(this.viewDate, dir);
1192
- if (this.viewMode === 1){
1193
- this._trigger('changeYear', this.viewDate);
1194
- }
1195
- }
1196
- this.fill();
1175
+ if (target.hasClass('datepicker-switch') && this.viewMode !== this.o.maxViewMode){
1176
+ this.setViewMode(this.viewMode + 1);
1197
1177
  }
1198
1178
 
1199
1179
  // Clicked on today button
1200
1180
  if (target.hasClass('today') && !target.hasClass('day')){
1201
- this.showMode(-2);
1181
+ this.setViewMode(0);
1202
1182
  this._setDate(UTCToday(), this.o.todayBtn === 'linked' ? null : 'view');
1203
1183
  }
1204
1184
 
@@ -1208,104 +1188,70 @@
1208
1188
  }
1209
1189
 
1210
1190
  if (!target.hasClass('disabled')){
1211
- // Clicked on a day
1212
- if (target.hasClass('day')){
1213
- day = parseInt(target.text(), 10) || 1;
1214
- year = this.viewDate.getUTCFullYear();
1215
- month = this.viewDate.getUTCMonth();
1216
-
1217
- // From last month
1218
- if (target.hasClass('old')){
1219
- if (month === 0) {
1220
- month = 11;
1221
- year = year - 1;
1222
- monthChanged = true;
1223
- yearChanged = true;
1224
- } else {
1225
- month = month - 1;
1226
- monthChanged = true;
1227
- }
1228
- }
1229
-
1230
- // From next month
1231
- if (target.hasClass('new')) {
1232
- if (month === 11){
1233
- month = 0;
1234
- year = year + 1;
1235
- monthChanged = true;
1236
- yearChanged = true;
1237
- } else {
1238
- month = month + 1;
1239
- monthChanged = true;
1240
- }
1241
- }
1242
- this._setDate(UTCDate(year, month, day));
1243
- if (yearChanged) {
1244
- this._trigger('changeYear', this.viewDate);
1245
- }
1246
- if (monthChanged) {
1247
- this._trigger('changeMonth', this.viewDate);
1248
- }
1249
- }
1250
-
1251
- // Clicked on a month
1252
- if (target.hasClass('month')) {
1253
- this.viewDate.setUTCDate(1);
1254
- day = 1;
1255
- month = target.parent().find('span').index(target);
1256
- year = this.viewDate.getUTCFullYear();
1257
- this.viewDate.setUTCMonth(month);
1258
- this._trigger('changeMonth', this.viewDate);
1259
- if (this.o.minViewMode === 1){
1260
- this._setDate(UTCDate(year, month, day));
1261
- this.showMode();
1262
- } else {
1263
- this.showMode(-1);
1264
- }
1265
- this.fill();
1266
- }
1267
-
1268
- // Clicked on a year
1269
- if (target.hasClass('year')
1191
+ // Clicked on a month, year, decade, century
1192
+ if (target.hasClass('month')
1193
+ || target.hasClass('year')
1270
1194
  || target.hasClass('decade')
1271
1195
  || target.hasClass('century')) {
1272
1196
  this.viewDate.setUTCDate(1);
1273
1197
 
1274
1198
  day = 1;
1275
- month = 0;
1276
- year = parseInt(target.text(), 10)||0;
1277
- this.viewDate.setUTCFullYear(year);
1278
-
1279
- if (target.hasClass('year')){
1280
- this._trigger('changeYear', this.viewDate);
1281
- if (this.o.minViewMode === 2){
1282
- this._setDate(UTCDate(year, month, day));
1283
- }
1284
- }
1285
- if (target.hasClass('decade')){
1286
- this._trigger('changeDecade', this.viewDate);
1287
- if (this.o.minViewMode === 3){
1288
- this._setDate(UTCDate(year, month, day));
1289
- }
1290
- }
1291
- if (target.hasClass('century')){
1292
- this._trigger('changeCentury', this.viewDate);
1293
- if (this.o.minViewMode === 4){
1294
- this._setDate(UTCDate(year, month, day));
1295
- }
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);
1296
1207
  }
1297
1208
 
1298
- this.showMode(-1);
1299
- this.fill();
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
+ }
1300
1217
  }
1301
1218
  }
1302
1219
 
1303
1220
  if (this.picker.is(':visible') && this._focused_from){
1304
- $(this._focused_from).focus();
1221
+ this._focused_from.focus();
1305
1222
  }
1306
1223
  delete this._focused_from;
1307
1224
  },
1308
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
+
1309
1255
  _toggle_multidate: function(date){
1310
1256
  var ix = this.dates.contains(date);
1311
1257
  if (!date){
@@ -1332,7 +1278,7 @@
1332
1278
  _setDate: function(date, which){
1333
1279
  if (!which || which === 'date')
1334
1280
  this._toggle_multidate(date && new Date(date));
1335
- if (!which || which === 'view')
1281
+ if ((!which && this.o.updateViewDate) || which === 'view')
1336
1282
  this.viewDate = date && new Date(date);
1337
1283
 
1338
1284
  this.fill();
@@ -1340,9 +1286,7 @@
1340
1286
  if (!which || which !== 'view') {
1341
1287
  this._trigger('changeDate');
1342
1288
  }
1343
- if (this.inputField){
1344
- this.inputField.change();
1345
- }
1289
+ this.inputField.trigger('change');
1346
1290
  if (this.o.autoclose && (!which || which === 'date')){
1347
1291
  this.hide();
1348
1292
  }
@@ -1385,8 +1329,7 @@
1385
1329
  new_month = month + dir;
1386
1330
  new_date.setUTCMonth(new_month);
1387
1331
  // Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11
1388
- if (new_month < 0 || new_month > 11)
1389
- new_month = (new_month + 12) % 12;
1332
+ new_month = (new_month + 12) % 12;
1390
1333
  }
1391
1334
  else {
1392
1335
  // For magnitudes >1, move one month at a time...
@@ -1480,17 +1423,14 @@
1480
1423
 
1481
1424
  if (newViewDate)
1482
1425
  this._trigger('changeYear', this.viewDate);
1483
- }
1484
- else if (e.shiftKey){
1426
+ } else if (e.shiftKey){
1485
1427
  newViewDate = this.moveAvailableDate(focusDate, dir, 'moveMonth');
1486
1428
 
1487
1429
  if (newViewDate)
1488
1430
  this._trigger('changeMonth', this.viewDate);
1489
- }
1490
- else if (e.keyCode === 37 || e.keyCode === 39){
1431
+ } else if (e.keyCode === 37 || e.keyCode === 39){
1491
1432
  newViewDate = this.moveAvailableDate(focusDate, dir, 'moveDay');
1492
- }
1493
- else if (!this.weekOfDateIsDisabled(focusDate)){
1433
+ } else if (!this.weekOfDateIsDisabled(focusDate)){
1494
1434
  newViewDate = this.moveAvailableDate(focusDate, dir, 'moveWeek');
1495
1435
  }
1496
1436
  } else if (this.viewMode === 1) {
@@ -1542,38 +1482,38 @@
1542
1482
  this._trigger('changeDate');
1543
1483
  else
1544
1484
  this._trigger('clearDate');
1545
- if (this.inputField){
1546
- this.inputField.change();
1547
- }
1485
+ this.inputField.trigger('change');
1548
1486
  }
1549
1487
  },
1550
1488
 
1551
- showMode: function(dir){
1552
- if (dir){
1553
- this.viewMode = Math.max(this.o.minViewMode, Math.min(this.o.maxViewMode, this.viewMode + dir));
1554
- }
1489
+ setViewMode: function(viewMode){
1490
+ this.viewMode = viewMode;
1555
1491
  this.picker
1556
1492
  .children('div')
1557
1493
  .hide()
1558
- .filter('.datepicker-' + DPGlobal.modes[this.viewMode].clsName)
1494
+ .filter('.datepicker-' + DPGlobal.viewModes[this.viewMode].clsName)
1559
1495
  .show();
1560
1496
  this.updateNavArrows();
1497
+ this._trigger('changeViewMode', new Date(this.viewDate));
1561
1498
  }
1562
1499
  };
1563
1500
 
1564
1501
  var DateRangePicker = function(element, options){
1565
- $(element).data('datepicker', this);
1502
+ $.data(element, 'datepicker', this);
1566
1503
  this.element = $(element);
1567
1504
  this.inputs = $.map(options.inputs, function(i){
1568
1505
  return i.jquery ? i[0] : i;
1569
1506
  });
1570
1507
  delete options.inputs;
1571
1508
 
1509
+ this.keepEmptyValues = options.keepEmptyValues;
1510
+ delete options.keepEmptyValues;
1511
+
1572
1512
  datepickerPlugin.call($(this.inputs), options)
1573
1513
  .on('changeDate', $.proxy(this.dateUpdated, this));
1574
1514
 
1575
1515
  this.pickers = $.map(this.inputs, function(i){
1576
- return $(i).data('datepicker');
1516
+ return $.data(i, 'datepicker');
1577
1517
  });
1578
1518
  this.updateDates();
1579
1519
  };
@@ -1600,13 +1540,14 @@
1600
1540
  return;
1601
1541
  this.updating = true;
1602
1542
 
1603
- var dp = $(e.target).data('datepicker');
1543
+ var dp = $.data(e.target, 'datepicker');
1604
1544
 
1605
- if (typeof(dp) === "undefined") {
1545
+ if (dp === undefined) {
1606
1546
  return;
1607
1547
  }
1608
1548
 
1609
1549
  var new_date = dp.getUTCDate(),
1550
+ keep_empty_values = this.keepEmptyValues,
1610
1551
  i = $.inArray(e.target, this.inputs),
1611
1552
  j = i - 1,
1612
1553
  k = i + 1,
@@ -1615,7 +1556,7 @@
1615
1556
  return;
1616
1557
 
1617
1558
  $.each(this.pickers, function(i, p){
1618
- if (!p.getUTCDate())
1559
+ if (!p.getUTCDate() && (p === dp || !keep_empty_values))
1619
1560
  p.setUTCDate(new_date);
1620
1561
  });
1621
1562
 
@@ -1624,8 +1565,7 @@
1624
1565
  while (j >= 0 && new_date < this.dates[j]){
1625
1566
  this.pickers[j--].setUTCDate(new_date);
1626
1567
  }
1627
- }
1628
- else if (new_date > this.dates[k]){
1568
+ } else if (new_date > this.dates[k]){
1629
1569
  // Date being moved later/right
1630
1570
  while (k < l && new_date > this.dates[k]){
1631
1571
  this.pickers[k++].setUTCDate(new_date);
@@ -1635,10 +1575,12 @@
1635
1575
 
1636
1576
  delete this.updating;
1637
1577
  },
1638
- remove: function(){
1639
- $.map(this.pickers, function(p){ p.remove(); });
1578
+ destroy: function(){
1579
+ $.map(this.pickers, function(p){ p.destroy(); });
1580
+ $(this.inputs).off('changeDate', this.dateUpdated);
1640
1581
  delete this.element.data().datepicker;
1641
- }
1582
+ },
1583
+ remove: alias('destroy', 'Method `remove` is deprecated and will be removed in version 2.0. Use `destroy` instead')
1642
1584
  };
1643
1585
 
1644
1586
  function opts_from_el(el, prefix){
@@ -1739,6 +1681,7 @@
1739
1681
  endDate: Infinity,
1740
1682
  forceParse: true,
1741
1683
  format: 'mm/dd/yyyy',
1684
+ keepEmptyValues: false,
1742
1685
  keyboardNavigation: true,
1743
1686
  language: 'en',
1744
1687
  minViewMode: 0,
@@ -1751,6 +1694,7 @@
1751
1694
  startView: 0,
1752
1695
  todayBtn: false,
1753
1696
  todayHighlight: false,
1697
+ updateViewDate: true,
1754
1698
  weekStart: 0,
1755
1699
  disableTouchKeyboard: false,
1756
1700
  enableOnReadonly: true,
@@ -1760,9 +1704,10 @@
1760
1704
  immediateUpdates: false,
1761
1705
  title: '',
1762
1706
  templates: {
1763
- leftArrow: '&laquo;',
1764
- rightArrow: '&raquo;'
1765
- }
1707
+ leftArrow: '&#x00AB;',
1708
+ rightArrow: '&#x00BB;'
1709
+ },
1710
+ showWeekDays: true
1766
1711
  };
1767
1712
  var locale_opts = $.fn.datepicker.locale_opts = [
1768
1713
  'format',
@@ -1784,38 +1729,37 @@
1784
1729
  };
1785
1730
 
1786
1731
  var DPGlobal = {
1787
- modes: [
1732
+ viewModes: [
1788
1733
  {
1734
+ names: ['days', 'month'],
1789
1735
  clsName: 'days',
1790
- navFnc: 'Month',
1791
- navStep: 1
1736
+ e: 'changeMonth'
1792
1737
  },
1793
1738
  {
1739
+ names: ['months', 'year'],
1794
1740
  clsName: 'months',
1795
- navFnc: 'FullYear',
1741
+ e: 'changeYear',
1796
1742
  navStep: 1
1797
1743
  },
1798
1744
  {
1745
+ names: ['years', 'decade'],
1799
1746
  clsName: 'years',
1800
- navFnc: 'FullYear',
1747
+ e: 'changeDecade',
1801
1748
  navStep: 10
1802
1749
  },
1803
1750
  {
1751
+ names: ['decades', 'century'],
1804
1752
  clsName: 'decades',
1805
- navFnc: 'FullDecade',
1753
+ e: 'changeCentury',
1806
1754
  navStep: 100
1807
1755
  },
1808
1756
  {
1757
+ names: ['centuries', 'millennium'],
1809
1758
  clsName: 'centuries',
1810
- navFnc: 'FullCentury',
1759
+ e: 'changeMillennium',
1811
1760
  navStep: 1000
1812
- }],
1813
- isLeapYear: function(year){
1814
- return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0));
1815
- },
1816
- getDaysInMonth: function(year, month){
1817
- return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
1818
- },
1761
+ }
1762
+ ],
1819
1763
  validParts: /dd?|DD?|mm?|MM?|yy(?:yy)?/g,
1820
1764
  nonpunctuation: /[^ -\/:-@\u5e74\u6708\u65e5\[-`{-~\t\n\r]+/g,
1821
1765
  parseFormat: function(format){
@@ -1838,10 +1782,8 @@
1838
1782
  if (typeof format === 'string')
1839
1783
  format = DPGlobal.parseFormat(format);
1840
1784
  if (format.toValue)
1841
- return format.toValue(date, format, language);
1842
- var part_re = /([\-+]\d+)([dmwy])/,
1843
- parts = date.match(/([\-+]\d+)([dmwy])/g),
1844
- fn_map = {
1785
+ return format.toValue(date, format, language);
1786
+ var fn_map = {
1845
1787
  d: 'moveDay',
1846
1788
  m: 'moveMonth',
1847
1789
  w: 'moveWeek',
@@ -1852,37 +1794,23 @@
1852
1794
  today: '+0d',
1853
1795
  tomorrow: '+1d'
1854
1796
  },
1855
- part, dir, i, fn;
1856
- if (/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/.test(date)){
1797
+ parts, part, dir, i, fn;
1798
+ if (date in dateAliases){
1799
+ date = dateAliases[date];
1800
+ }
1801
+ if (/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/i.test(date)){
1802
+ parts = date.match(/([\-+]\d+)([dmwy])/gi);
1857
1803
  date = new Date();
1858
1804
  for (i=0; i < parts.length; i++){
1859
- part = part_re.exec(parts[i]);
1860
- dir = parseInt(part[1]);
1861
- fn = fn_map[part[2]];
1805
+ part = parts[i].match(/([\-+]\d+)([dmwy])/i);
1806
+ dir = Number(part[1]);
1807
+ fn = fn_map[part[2].toLowerCase()];
1862
1808
  date = Datepicker.prototype[fn](date, dir);
1863
1809
  }
1864
- return UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate());
1865
- }
1866
-
1867
- if (typeof dateAliases[date] !== 'undefined') {
1868
- date = dateAliases[date];
1869
- parts = date.match(/([\-+]\d+)([dmwy])/g);
1870
-
1871
- if (/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/.test(date)){
1872
- date = new Date();
1873
- for (i=0; i < parts.length; i++){
1874
- part = part_re.exec(parts[i]);
1875
- dir = parseInt(part[1]);
1876
- fn = fn_map[part[2]];
1877
- date = Datepicker.prototype[fn](date, dir);
1878
- }
1879
-
1880
- return UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate());
1881
- }
1810
+ return Datepicker.prototype._zero_utc_time(date);
1882
1811
  }
1883
1812
 
1884
1813
  parts = date && date.match(this.nonpunctuation) || [];
1885
- date = new Date();
1886
1814
 
1887
1815
  function applyNearbyYear(year, threshold){
1888
1816
  if (threshold === true)
@@ -1906,9 +1834,6 @@
1906
1834
  yyyy: function(d,v){
1907
1835
  return d.setUTCFullYear(assumeNearby ? applyNearbyYear(v, assumeNearby) : v);
1908
1836
  },
1909
- yy: function(d,v){
1910
- return d.setUTCFullYear(assumeNearby ? applyNearbyYear(v, assumeNearby) : v);
1911
- },
1912
1837
  m: function(d,v){
1913
1838
  if (isNaN(d))
1914
1839
  return d;
@@ -1925,6 +1850,7 @@
1925
1850
  }
1926
1851
  },
1927
1852
  val, filtered;
1853
+ setters_map['yy'] = setters_map['yyyy'];
1928
1854
  setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m'];
1929
1855
  setters_map['dd'] = setters_map['d'];
1930
1856
  date = UTCToday();
@@ -2006,9 +1932,9 @@
2006
1932
  '<th colspan="7" class="datepicker-title"></th>'+
2007
1933
  '</tr>'+
2008
1934
  '<tr>'+
2009
- '<th class="prev">&laquo;</th>'+
1935
+ '<th class="prev">'+defaults.templates.leftArrow+'</th>'+
2010
1936
  '<th colspan="5" class="datepicker-switch"></th>'+
2011
- '<th class="next">&raquo;</th>'+
1937
+ '<th class="next">'+defaults.templates.rightArrow+'</th>'+
2012
1938
  '</tr>'+
2013
1939
  '</thead>',
2014
1940
  contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>',
@@ -2072,7 +1998,15 @@
2072
1998
 
2073
1999
  /* DATEPICKER VERSION
2074
2000
  * =================== */
2075
- $.fn.datepicker.version = '1.6.4';
2001
+ $.fn.datepicker.version = '1.7.1';
2002
+
2003
+ $.fn.datepicker.deprecated = function(msg){
2004
+ var console = window.console;
2005
+ if (console && console.warn) {
2006
+ console.warn('DEPRECATED: ' + msg);
2007
+ }
2008
+ };
2009
+
2076
2010
 
2077
2011
  /* DATEPICKER DATA-API
2078
2012
  * ================== */