bootstrap-datepicker-rails 1.5.0 → 1.6.0.pre.alpha

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.
Files changed (22) 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 +489 -292
  4. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.ca.js +1 -0
  5. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.de.js +1 -0
  6. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.en-GB.js +1 -0
  7. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.es.js +1 -0
  8. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.fr-CH.js +1 -0
  9. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.fr.js +1 -0
  10. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.hy.js +3 -3
  11. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.it.js +1 -0
  12. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.ko.js +1 -1
  13. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.lt.js +4 -1
  14. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.nb.js +2 -1
  15. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.nl-BE.js +1 -0
  16. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.nl.js +1 -0
  17. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.pt-BR.js +1 -0
  18. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.pt.js +1 -0
  19. data/vendor/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.sk.js +3 -1
  20. data/vendor/assets/stylesheets/bootstrap-datepicker.css +4 -2
  21. data/vendor/assets/stylesheets/bootstrap-datepicker3.css +59 -169
  22. metadata +5 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 893265b2259ced6eef712d77dce05885d7c26261
4
- data.tar.gz: 9c736834f91e8d235145b470ef2f16a00885a8ff
3
+ metadata.gz: e4acd455f5b4675e2e6022e57cefb11d34c71a1b
4
+ data.tar.gz: 06c3fcb8a7f24c4f236c78ec1afaf13131568f58
5
5
  SHA512:
6
- metadata.gz: 302a1b4c222329efed3557b0636905c677ddf1cb51bb18909c7c35181ef33d310f5aae99b0b4655cad35d3ce2d4d8d710358285565f5a714492b013c721c5839
7
- data.tar.gz: d306ea2cdde4ec2bae774d348d59499c3bd35bbfe6598660eb9e562126cf6f0183214f725bfcb17144ad071846871a015f6bde8d91a0d89287f9a491d6c3bda2
6
+ metadata.gz: bed03af6d4a6e3284a07c8a83d8a12bfc510e42f10dc860ae98376a1c59a1e248447fd6e6c77fac08ee64b208451492fa4e0fc166f43988aa467d97ddf20a443
7
+ data.tar.gz: 03b8c534282d7c855c3359caa263722643a3150c8acb9848dc972e372870dd2606f12a16c2953af3692cfe99be01dd0f5f783646f631d40d309fdbc0b56afabc
@@ -1,5 +1,5 @@
1
1
  module BootstrapDatepickerRails
2
2
  module Rails
3
- VERSION = "1.5.0"
3
+ VERSION = "1.6.0-alpha"
4
4
  end
5
5
  end
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Datepicker for Bootstrap v1.5.0 (https://github.com/eternicode/bootstrap-datepicker)
2
+ * Datepicker for Bootstrap v1.6.0-alpha (https://github.com/eternicode/bootstrap-datepicker)
3
3
  *
4
4
  * Copyright 2012 Stefan Petre
5
5
  * Improvements by Andrew Rowls
@@ -84,6 +84,7 @@
84
84
  // Picker object
85
85
 
86
86
  var Datepicker = function(element, options){
87
+ $(element).data('datepicker', this);
87
88
  this._process_options(options);
88
89
 
89
90
  this.dates = new DateArray();
@@ -99,6 +100,15 @@
99
100
  this.component = false;
100
101
 
101
102
  this.picker = $(DPGlobal.template);
103
+
104
+ // Checking templates and inserting
105
+ if (this._check_template(this.o.templates.leftArrow)) {
106
+ this.picker.find('.prev').html(this.o.templates.leftArrow);
107
+ }
108
+ if (this._check_template(this.o.templates.rightArrow)) {
109
+ this.picker.find('.next').html(this.o.templates.rightArrow);
110
+ }
111
+
102
112
  this._buildEvents();
103
113
  this._attachEvents();
104
114
 
@@ -116,7 +126,7 @@
116
126
  this.viewMode = this.o.startView;
117
127
 
118
128
  if (this.o.calendarWeeks)
119
- this.picker.find('tfoot .today, tfoot .clear')
129
+ this.picker.find('thead .datepicker-title, tfoot .today, tfoot .clear')
120
130
  .attr('colspan', function(i, val){
121
131
  return parseInt(val) + 1;
122
132
  });
@@ -145,6 +155,44 @@
145
155
  Datepicker.prototype = {
146
156
  constructor: Datepicker,
147
157
 
158
+ _resolveViewName: function(view, default_value){
159
+ if (view === 0 || view === 'days' || view === 'month') {
160
+ return 0;
161
+ }
162
+ if (view === 1 || view === 'months' || view === 'year') {
163
+ return 1;
164
+ }
165
+ if (view === 2 || view === 'years' || view === 'decade') {
166
+ return 2;
167
+ }
168
+ if (view === 3 || view === 'decades' || view === 'century') {
169
+ return 3;
170
+ }
171
+ if (view === 4 || view === 'centuries' || view === 'millennium') {
172
+ return 4;
173
+ }
174
+ return default_value === undefined ? false : default_value;
175
+ },
176
+
177
+ _check_template: function(tmp){
178
+ try {
179
+ // If empty
180
+ if (tmp === undefined || tmp === "") {
181
+ return false;
182
+ }
183
+ // If no html, everything ok
184
+ if ((tmp.match(/[<>]/g) || []).length <= 0) {
185
+ return true;
186
+ }
187
+ // Checking if html is fine
188
+ var jDom = $(tmp);
189
+ return jDom.length > 0;
190
+ }
191
+ catch (ex) {
192
+ return false;
193
+ }
194
+ },
195
+
148
196
  _process_options: function(opts){
149
197
  // Store raw options for reference
150
198
  this._o = $.extend({}, this._o, opts);
@@ -161,45 +209,12 @@
161
209
  }
162
210
  o.language = lang;
163
211
 
164
- switch (o.startView){
165
- case 2:
166
- case 'decade':
167
- o.startView = 2;
168
- break;
169
- case 1:
170
- case 'year':
171
- o.startView = 1;
172
- break;
173
- default:
174
- o.startView = 0;
175
- }
176
-
177
- switch (o.minViewMode){
178
- case 1:
179
- case 'months':
180
- o.minViewMode = 1;
181
- break;
182
- case 2:
183
- case 'years':
184
- o.minViewMode = 2;
185
- break;
186
- default:
187
- o.minViewMode = 0;
188
- }
189
-
190
- switch (o.maxViewMode) {
191
- case 0:
192
- case 'days':
193
- o.maxViewMode = 0;
194
- break;
195
- case 1:
196
- case 'months':
197
- o.maxViewMode = 1;
198
- break;
199
- default:
200
- o.maxViewMode = 2;
201
- }
212
+ // Retrieve view index from any aliases
213
+ o.startView = this._resolveViewName(o.startView, 0);
214
+ o.minViewMode = this._resolveViewName(o.minViewMode, 0);
215
+ o.maxViewMode = this._resolveViewName(o.maxViewMode, 4);
202
216
 
217
+ // Check that the start view is between min and max
203
218
  o.startView = Math.min(o.startView, o.maxViewMode);
204
219
  o.startView = Math.max(o.startView, o.minViewMode);
205
220
 
@@ -212,7 +227,7 @@
212
227
  o.multidateSeparator = String(o.multidateSeparator);
213
228
 
214
229
  o.weekStart %= 7;
215
- o.weekEnd = ((o.weekStart + 6) % 7);
230
+ o.weekEnd = (o.weekStart + 6) % 7;
216
231
 
217
232
  var format = DPGlobal.parseFormat(o.format);
218
233
  if (o.startDate !== -Infinity){
@@ -220,7 +235,7 @@
220
235
  if (o.startDate instanceof Date)
221
236
  o.startDate = this._local_to_utc(this._zero_time(o.startDate));
222
237
  else
223
- o.startDate = DPGlobal.parseDate(o.startDate, format, o.language);
238
+ o.startDate = DPGlobal.parseDate(o.startDate, format, o.language, o.assumeNearbyYear);
224
239
  }
225
240
  else {
226
241
  o.startDate = -Infinity;
@@ -231,7 +246,7 @@
231
246
  if (o.endDate instanceof Date)
232
247
  o.endDate = this._local_to_utc(this._zero_time(o.endDate));
233
248
  else
234
- o.endDate = DPGlobal.parseDate(o.endDate, format, o.language);
249
+ o.endDate = DPGlobal.parseDate(o.endDate, format, o.language, o.assumeNearbyYear);
235
250
  }
236
251
  else {
237
252
  o.endDate = Infinity;
@@ -255,11 +270,11 @@
255
270
  o.datesDisabled = o.datesDisabled||[];
256
271
  if (!$.isArray(o.datesDisabled)) {
257
272
  var datesDisabled = [];
258
- datesDisabled.push(DPGlobal.parseDate(o.datesDisabled, format, o.language));
273
+ datesDisabled.push(DPGlobal.parseDate(o.datesDisabled, format, o.language, o.assumeNearbyYear));
259
274
  o.datesDisabled = datesDisabled;
260
275
  }
261
276
  o.datesDisabled = $.map(o.datesDisabled,function(d){
262
- return DPGlobal.parseDate(d, format, o.language);
277
+ return DPGlobal.parseDate(d, format, o.language, o.assumeNearbyYear);
263
278
  });
264
279
 
265
280
  var plc = String(o.orientation).toLowerCase().split(/\s+/g),
@@ -301,8 +316,6 @@
301
316
  } else {
302
317
  o.defaultViewDate = UTCToday();
303
318
  }
304
- o.showOnFocus = o.showOnFocus !== undefined ? o.showOnFocus : true;
305
- o.zIndexOffset = o.zIndexOffset !== undefined ? o.zIndexOffset : 10;
306
319
  },
307
320
  _events: [],
308
321
  _secondaryEvents: [],
@@ -458,7 +471,8 @@
458
471
  },
459
472
 
460
473
  show: function(){
461
- if (this.element.attr('readonly') && this.o.enableOnReadonly === false)
474
+ var element = this.component ? this.element.find('input') : this.element;
475
+ if (element.attr('readonly') && this.o.enableOnReadonly === false)
462
476
  return;
463
477
  if (!this.isInline)
464
478
  this.picker.appendTo(this.o.container);
@@ -495,7 +509,7 @@
495
509
  return this;
496
510
  },
497
511
 
498
- remove: function(){
512
+ destroy: function(){
499
513
  this.hide();
500
514
  this._detachEvents();
501
515
  this._detachSecondaryEvents();
@@ -597,6 +611,7 @@
597
611
 
598
612
  setDate: alias('setDates'),
599
613
  setUTCDate: alias('setUTCDates'),
614
+ remove: alias('destroy'),
600
615
 
601
616
  setValue: function(){
602
617
  var formatted = this.getFormattedDate();
@@ -621,6 +636,10 @@
621
636
  }).join(this.o.multidateSeparator);
622
637
  },
623
638
 
639
+ getStartDate: function(){
640
+ return this.o.startDate;
641
+ },
642
+
624
643
  setStartDate: function(startDate){
625
644
  this._process_options({startDate: startDate});
626
645
  this.update();
@@ -628,6 +647,10 @@
628
647
  return this;
629
648
  },
630
649
 
650
+ getEndDate: function(){
651
+ return this.o.endDate;
652
+ },
653
+
631
654
  setEndDate: function(endDate){
632
655
  this._process_options({endDate: endDate});
633
656
  this.update();
@@ -662,7 +685,7 @@
662
685
  visualPadding = 10,
663
686
  container = $(this.o.container),
664
687
  windowWidth = container.width(),
665
- scrollTop = container.scrollTop(),
688
+ scrollTop = this.o.container === 'body' ? $(document).scrollTop() : container.scrollTop(),
666
689
  appendOffset = container.offset();
667
690
 
668
691
  var parentsZindex = [];
@@ -677,6 +700,10 @@
677
700
  var left = offset.left - appendOffset.left,
678
701
  top = offset.top - appendOffset.top;
679
702
 
703
+ if (this.o.container !== 'body') {
704
+ top += scrollTop;
705
+ }
706
+
680
707
  this.picker.removeClass(
681
708
  'datepicker-orient-top datepicker-orient-bottom '+
682
709
  'datepicker-orient-right datepicker-orient-left'
@@ -697,7 +724,7 @@
697
724
  } else if (left + calendarWidth > windowWidth) {
698
725
  // the calendar passes the widow right edge. Align it to component right side
699
726
  this.picker.addClass('datepicker-orient-right');
700
- left = offset.left + width - calendarWidth;
727
+ left += width - calendarWidth;
701
728
  } else {
702
729
  // Default to left
703
730
  this.picker.addClass('datepicker-orient-left');
@@ -764,12 +791,11 @@
764
791
  }
765
792
 
766
793
  dates = $.map(dates, $.proxy(function(date){
767
- return DPGlobal.parseDate(date, this.o.format, this.o.language);
794
+ return DPGlobal.parseDate(date, this.o.format, this.o.language, this.o.assumeNearbyYear);
768
795
  }, this));
769
796
  dates = $.grep(dates, $.proxy(function(date){
770
797
  return (
771
- date < this.o.startDate ||
772
- date > this.o.endDate ||
798
+ !this.dateWithinRange(date) ||
773
799
  !date
774
800
  );
775
801
  }, this), true);
@@ -812,17 +838,22 @@
812
838
  html += '<th class="cw">&#160;</th>';
813
839
  }
814
840
  while (dowCnt < this.o.weekStart + 7){
815
- html += '<th class="dow">'+dates[this.o.language].daysMin[(dowCnt++)%7]+'</th>';
841
+ html += '<th class="dow';
842
+ if ($.inArray(dowCnt, this.o.daysOfWeekDisabled) > -1)
843
+ html += ' disabled';
844
+ html += '">'+dates[this.o.language].daysMin[(dowCnt++)%7]+'</th>';
816
845
  }
817
846
  html += '</tr>';
818
847
  this.picker.find('.datepicker-days thead').append(html);
819
848
  },
820
849
 
821
850
  fillMonths: function(){
851
+ var localDate = this._utc_to_local(this.viewDate);
822
852
  var html = '',
823
853
  i = 0;
824
854
  while (i < 12){
825
- html += '<span class="month">'+dates[this.o.language].monthsShort[i++]+'</span>';
855
+ var focused = localDate && localDate.getMonth() === i ? ' focused' : '';
856
+ html += '<span class="month' + focused + '">' + dates[this.o.language].monthsShort[i++]+'</span>';
826
857
  }
827
858
  this.picker.find('.datepicker-months td').html(html);
828
859
  },
@@ -859,18 +890,12 @@
859
890
  }
860
891
  if (this.dates.contains(date) !== -1)
861
892
  cls.push('active');
862
- if (date.valueOf() < this.o.startDate || date.valueOf() > this.o.endDate ||
863
- $.inArray(date.getUTCDay(), this.o.daysOfWeekDisabled) !== -1){
893
+ if (!this.dateWithinRange(date) || this.dateIsDisabled(date)){
864
894
  cls.push('disabled');
865
895
  }
866
896
  if ($.inArray(date.getUTCDay(), this.o.daysOfWeekHighlighted) !== -1){
867
897
  cls.push('highlighted');
868
898
  }
869
- if (this.o.datesDisabled.length > 0 &&
870
- $.grep(this.o.datesDisabled, function(d){
871
- return isUTCEquals(date, d); }).length > 0) {
872
- cls.push('disabled', 'disabled-date');
873
- }
874
899
 
875
900
  if (this.range){
876
901
  if (date > this.range[0] && date < this.range[this.range.length-1]){
@@ -889,6 +914,66 @@
889
914
  return cls;
890
915
  },
891
916
 
917
+ _fill_yearsView: function(selector, cssClass, factor, step, currentYear, startYear, endYear, callback){
918
+ var html, view, year, steps, startStep, endStep, thisYear, i, classes, tooltip, before;
919
+
920
+ html = '';
921
+ view = this.picker.find(selector);
922
+ year = parseInt(currentYear / factor, 10) * factor;
923
+ startStep = parseInt(startYear / step, 10) * step;
924
+ endStep = parseInt(endYear / step, 10) * step;
925
+ steps = $.map(this.dates, function(d){
926
+ return parseInt(d.getUTCFullYear() / step, 10) * step;
927
+ });
928
+
929
+ view.find('.datepicker-switch').text(year + '-' + (year + step * 9));
930
+
931
+ thisYear = year - step;
932
+ for (i = -1; i < 11; i += 1) {
933
+ classes = [cssClass];
934
+ tooltip = null;
935
+
936
+ if (i === -1) {
937
+ classes.push('old');
938
+ } else if (i === 10) {
939
+ classes.push('new');
940
+ }
941
+ if ($.inArray(thisYear, steps) !== -1) {
942
+ classes.push('active');
943
+ }
944
+ if (thisYear < startStep || thisYear > endStep) {
945
+ classes.push('disabled');
946
+ }
947
+ if (thisYear === this.viewDate.getFullYear()) {
948
+ classes.push('focused');
949
+ }
950
+
951
+ if (callback !== $.noop) {
952
+ before = callback(new Date(thisYear, 0, 1));
953
+ if (before === undefined) {
954
+ before = {};
955
+ } else if (typeof(before) === 'boolean') {
956
+ before = {enabled: before};
957
+ } else if (typeof(before) === 'string') {
958
+ before = {classes: before};
959
+ }
960
+ if (before.enabled === false) {
961
+ classes.push('disabled');
962
+ }
963
+ if (before.classes) {
964
+ classes = classes.concat(before.classes.split(/\s+/));
965
+ }
966
+ if (before.tooltip) {
967
+ tooltip = before.tooltip;
968
+ }
969
+ }
970
+
971
+ html += '<span class="' + classes.join(' ') + '"' + (tooltip ? ' title="' + tooltip + '"' : '') + '>' + thisYear + '</span>';
972
+ thisYear += step;
973
+ }
974
+ view.find('td').html(html);
975
+ },
976
+
892
977
  fill: function(){
893
978
  var d = new Date(this.viewDate),
894
979
  year = d.getUTCFullYear(),
@@ -900,11 +985,12 @@
900
985
  todaytxt = dates[this.o.language].today || dates['en'].today || '',
901
986
  cleartxt = dates[this.o.language].clear || dates['en'].clear || '',
902
987
  titleFormat = dates[this.o.language].titleFormat || dates['en'].titleFormat,
903
- tooltip;
988
+ tooltip,
989
+ before;
904
990
  if (isNaN(year) || isNaN(month))
905
991
  return;
906
- this.picker.find('.datepicker-days thead .datepicker-switch')
907
- .text(DPGlobal.formatDate(new UTCDate(year, month), titleFormat, this.o.language));
992
+ this.picker.find('.datepicker-days .datepicker-switch')
993
+ .text(DPGlobal.formatDate(d, titleFormat, this.o.language));
908
994
  this.picker.find('tfoot .today')
909
995
  .text(todaytxt)
910
996
  .toggle(this.o.todayBtn !== false);
@@ -951,7 +1037,7 @@
951
1037
  clsName.push('day');
952
1038
 
953
1039
  if (this.o.beforeShowDay !== $.noop){
954
- var before = this.o.beforeShowDay(this._utc_to_local(prevMonth));
1040
+ before = this.o.beforeShowDay(this._utc_to_local(prevMonth));
955
1041
  if (before === undefined)
956
1042
  before = {};
957
1043
  else if (typeof(before) === 'boolean')
@@ -976,9 +1062,10 @@
976
1062
  }
977
1063
  this.picker.find('.datepicker-days tbody').empty().append(html.join(''));
978
1064
 
1065
+ var monthsTitle = dates[this.o.language].monthsTitle || dates['en'].monthsTitle || 'Months';
979
1066
  var months = this.picker.find('.datepicker-months')
980
1067
  .find('.datepicker-switch')
981
- .text(this.o.maxViewMode < 2 ? 'Months' : year)
1068
+ .text(this.o.maxViewMode < 2 ? monthsTitle : year)
982
1069
  .end()
983
1070
  .find('span').removeClass('active');
984
1071
 
@@ -1009,51 +1096,41 @@
1009
1096
  });
1010
1097
  }
1011
1098
 
1012
- html = '';
1013
- year = parseInt(year/10, 10) * 10;
1014
- var yearCont = this.picker.find('.datepicker-years')
1015
- .find('.datepicker-switch')
1016
- .text(year + '-' + (year + 9))
1017
- .end()
1018
- .find('td');
1019
- year -= 1;
1020
- var years = $.map(this.dates, function(d){
1021
- return d.getUTCFullYear();
1022
- }),
1023
- classes;
1024
- for (var i = -1; i < 11; i++){
1025
- classes = ['year'];
1026
- tooltip = null;
1027
-
1028
- if (i === -1)
1029
- classes.push('old');
1030
- else if (i === 10)
1031
- classes.push('new');
1032
- if ($.inArray(year, years) !== -1)
1033
- classes.push('active');
1034
- if (year < startYear || year > endYear)
1035
- classes.push('disabled');
1099
+ // Generating decade/years picker
1100
+ this._fill_yearsView(
1101
+ '.datepicker-years',
1102
+ 'year',
1103
+ 10,
1104
+ 1,
1105
+ year,
1106
+ startYear,
1107
+ endYear,
1108
+ this.o.beforeShowYear
1109
+ );
1036
1110
 
1037
- if (this.o.beforeShowYear !== $.noop) {
1038
- var yrBefore = this.o.beforeShowYear(new Date(year, 0, 1));
1039
- if (yrBefore === undefined)
1040
- yrBefore = {};
1041
- else if (typeof(yrBefore) === 'boolean')
1042
- yrBefore = {enabled: yrBefore};
1043
- else if (typeof(yrBefore) === 'string')
1044
- yrBefore = {classes: yrBefore};
1045
- if (yrBefore.enabled === false)
1046
- classes.push('disabled');
1047
- if (yrBefore.classes)
1048
- classes = classes.concat(yrBefore.classes.split(/\s+/));
1049
- if (yrBefore.tooltip)
1050
- tooltip = yrBefore.tooltip;
1051
- }
1111
+ // Generating century/decades picker
1112
+ this._fill_yearsView(
1113
+ '.datepicker-decades',
1114
+ 'decade',
1115
+ 100,
1116
+ 10,
1117
+ year,
1118
+ startYear,
1119
+ endYear,
1120
+ this.o.beforeShowDecade
1121
+ );
1052
1122
 
1053
- html += '<span class="' + classes.join(' ') + '"' + (tooltip ? ' title="'+tooltip+'"' : '') + '>' + year + '</span>';
1054
- year += 1;
1055
- }
1056
- yearCont.html(html);
1123
+ // Generating millennium/centuries picker
1124
+ this._fill_yearsView(
1125
+ '.datepicker-centuries',
1126
+ 'century',
1127
+ 1000,
1128
+ 100,
1129
+ year,
1130
+ startYear,
1131
+ endYear,
1132
+ this.o.beforeShowCentury
1133
+ );
1057
1134
  },
1058
1135
 
1059
1136
  updateNavArrows: function(){
@@ -1080,6 +1157,8 @@
1080
1157
  break;
1081
1158
  case 1:
1082
1159
  case 2:
1160
+ case 3:
1161
+ case 4:
1083
1162
  if (this.o.startDate !== -Infinity && year <= this.o.startDate.getUTCFullYear() || this.o.maxViewMode < 2){
1084
1163
  this.picker.find('.prev').css({visibility: 'hidden'});
1085
1164
  }
@@ -1099,103 +1178,135 @@
1099
1178
  click: function(e){
1100
1179
  e.preventDefault();
1101
1180
  e.stopPropagation();
1102
- var target = $(e.target).closest('span, td, th'),
1103
- year, month, day;
1104
- if (target.length === 1){
1105
- switch (target[0].nodeName.toLowerCase()){
1106
- case 'th':
1107
- switch (target[0].className){
1108
- case 'datepicker-switch':
1109
- this.showMode(1);
1110
- break;
1111
- case 'prev':
1112
- case 'next':
1113
- var dir = DPGlobal.modes[this.viewMode].navStep * (target[0].className === 'prev' ? -1 : 1);
1114
- switch (this.viewMode){
1115
- case 0:
1116
- this.viewDate = this.moveMonth(this.viewDate, dir);
1117
- this._trigger('changeMonth', this.viewDate);
1118
- break;
1119
- case 1:
1120
- case 2:
1121
- this.viewDate = this.moveYear(this.viewDate, dir);
1122
- if (this.viewMode === 1)
1123
- this._trigger('changeYear', this.viewDate);
1124
- break;
1125
- }
1126
- this.fill();
1127
- break;
1128
- case 'today':
1129
- var date = new Date();
1130
- date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);
1131
1181
 
1132
- this.showMode(-2);
1133
- var which = this.o.todayBtn === 'linked' ? null : 'view';
1134
- this._setDate(date, which);
1135
- break;
1136
- case 'clear':
1137
- this.clearDates();
1138
- break;
1182
+ var target, dir, day, year, month, monthChanged, yearChanged;
1183
+ target = $(e.target);
1184
+
1185
+ // Clicked on the switch
1186
+ if (target.hasClass('datepicker-switch')){
1187
+ this.showMode(1);
1188
+ }
1189
+
1190
+ // Clicked on prev or next
1191
+ var navArrow = target.closest('.prev, .next');
1192
+ if (navArrow.length > 0) {
1193
+ dir = DPGlobal.modes[this.viewMode].navStep * (navArrow.hasClass('prev') ? -1 : 1);
1194
+ if (this.viewMode === 0){
1195
+ this.viewDate = this.moveMonth(this.viewDate, dir);
1196
+ this._trigger('changeMonth', this.viewDate);
1197
+ } else {
1198
+ this.viewDate = this.moveYear(this.viewDate, dir);
1199
+ if (this.viewMode === 1){
1200
+ this._trigger('changeYear', this.viewDate);
1201
+ }
1202
+ }
1203
+ this.fill();
1204
+ }
1205
+
1206
+ // Clicked on today button
1207
+ if (target.hasClass('today')){
1208
+ this.showMode(-2);
1209
+ this._setDate(UTCToday(), this.o.todayBtn === 'linked' ? null : 'view');
1210
+ }
1211
+
1212
+ // Clicked on clear button
1213
+ if (target.hasClass('clear')){
1214
+ this.clearDates();
1215
+ }
1216
+
1217
+ if (!target.hasClass('disabled')){
1218
+ // Clicked on a day
1219
+ if (target.hasClass('day')){
1220
+ day = parseInt(target.text(), 10) || 1;
1221
+ year = this.viewDate.getUTCFullYear();
1222
+ month = this.viewDate.getUTCMonth();
1223
+
1224
+ // From last month
1225
+ if (target.hasClass('old')){
1226
+ if (month === 0) {
1227
+ month = 11;
1228
+ year = year - 1;
1229
+ monthChanged = true;
1230
+ yearChanged = true;
1231
+ } else {
1232
+ month = month - 1;
1233
+ monthChanged = true;
1234
+ }
1235
+ }
1236
+
1237
+ // From next month
1238
+ if (target.hasClass('new')) {
1239
+ if (month === 11){
1240
+ month = 0;
1241
+ year = year + 1;
1242
+ monthChanged = true;
1243
+ yearChanged = true;
1244
+ } else {
1245
+ month = month + 1;
1246
+ monthChanged = true;
1247
+ }
1248
+ }
1249
+ this._setDate(UTCDate(year, month, day));
1250
+ if (yearChanged) {
1251
+ this._trigger('changeYear', this.viewDate);
1252
+ }
1253
+ if (monthChanged) {
1254
+ this._trigger('changeMonth', this.viewDate);
1255
+ }
1256
+ }
1257
+
1258
+ // Clicked on a month
1259
+ if (target.hasClass('month')) {
1260
+ this.viewDate.setUTCDate(1);
1261
+ day = 1;
1262
+ month = target.parent().find('span').index(target);
1263
+ year = this.viewDate.getUTCFullYear();
1264
+ this.viewDate.setUTCMonth(month);
1265
+ this._trigger('changeMonth', this.viewDate);
1266
+ if (this.o.minViewMode === 1){
1267
+ this._setDate(UTCDate(year, month, day));
1268
+ this.showMode();
1269
+ } else {
1270
+ this.showMode(-1);
1271
+ }
1272
+ this.fill();
1273
+ }
1274
+
1275
+ // Clicked on a year
1276
+ if (target.hasClass('year')
1277
+ || target.hasClass('decade')
1278
+ || target.hasClass('century')) {
1279
+ this.viewDate.setUTCDate(1);
1280
+
1281
+ day = 1;
1282
+ month = 0;
1283
+ year = parseInt(target.text(), 10)||0;
1284
+ this.viewDate.setUTCFullYear(year);
1285
+
1286
+ if (target.hasClass('year')){
1287
+ this._trigger('changeYear', this.viewDate);
1288
+ if (this.o.minViewMode === 2){
1289
+ this._setDate(UTCDate(year, month, day));
1139
1290
  }
1140
- break;
1141
- case 'span':
1142
- if (!target.hasClass('disabled')){
1143
- this.viewDate.setUTCDate(1);
1144
- if (target.hasClass('month')){
1145
- day = 1;
1146
- month = target.parent().find('span').index(target);
1147
- year = this.viewDate.getUTCFullYear();
1148
- this.viewDate.setUTCMonth(month);
1149
- this._trigger('changeMonth', this.viewDate);
1150
- if (this.o.minViewMode === 1){
1151
- this._setDate(UTCDate(year, month, day));
1152
- this.showMode();
1153
- } else {
1154
- this.showMode(-1);
1155
- }
1156
- }
1157
- else {
1158
- day = 1;
1159
- month = 0;
1160
- year = parseInt(target.text(), 10)||0;
1161
- this.viewDate.setUTCFullYear(year);
1162
- this._trigger('changeYear', this.viewDate);
1163
- if (this.o.minViewMode === 2){
1164
- this._setDate(UTCDate(year, month, day));
1165
- }
1166
- this.showMode(-1);
1167
- }
1168
- this.fill();
1291
+ }
1292
+ if (target.hasClass('decade')){
1293
+ this._trigger('changeDecade', this.viewDate);
1294
+ if (this.o.minViewMode === 3){
1295
+ this._setDate(UTCDate(year, month, day));
1169
1296
  }
1170
- break;
1171
- case 'td':
1172
- if (target.hasClass('day') && !target.hasClass('disabled')){
1173
- day = parseInt(target.text(), 10)||1;
1174
- year = this.viewDate.getUTCFullYear();
1175
- month = this.viewDate.getUTCMonth();
1176
- if (target.hasClass('old')){
1177
- if (month === 0){
1178
- month = 11;
1179
- year -= 1;
1180
- }
1181
- else {
1182
- month -= 1;
1183
- }
1184
- }
1185
- else if (target.hasClass('new')){
1186
- if (month === 11){
1187
- month = 0;
1188
- year += 1;
1189
- }
1190
- else {
1191
- month += 1;
1192
- }
1193
- }
1297
+ }
1298
+ if (target.hasClass('century')){
1299
+ this._trigger('changeCentury', this.viewDate);
1300
+ if (this.o.minViewMode === 4){
1194
1301
  this._setDate(UTCDate(year, month, day));
1195
1302
  }
1196
- break;
1303
+ }
1304
+
1305
+ this.showMode(-1);
1306
+ this.fill();
1197
1307
  }
1198
1308
  }
1309
+
1199
1310
  if (this.picker.is(':visible') && this._focused_from){
1200
1311
  $(this._focused_from).focus();
1201
1312
  }
@@ -1228,12 +1339,12 @@
1228
1339
  _setDate: function(date, which){
1229
1340
  if (!which || which === 'date')
1230
1341
  this._toggle_multidate(date && new Date(date));
1231
- if (!which || which === 'view')
1342
+ if (!which || which === 'view')
1232
1343
  this.viewDate = date && new Date(date);
1233
1344
 
1234
1345
  this.fill();
1235
1346
  this.setValue();
1236
- if (!which || which !== 'view') {
1347
+ if (!which || which !== 'view') {
1237
1348
  this._trigger('changeDate');
1238
1349
  }
1239
1350
  var element;
@@ -1251,6 +1362,17 @@
1251
1362
  }
1252
1363
  },
1253
1364
 
1365
+ moveDay: function(date, dir){
1366
+ var newDate = new Date(date);
1367
+ newDate.setUTCDate(date.getUTCDate() + dir);
1368
+
1369
+ return newDate;
1370
+ },
1371
+
1372
+ moveWeek: function(date, dir){
1373
+ return this.moveDay(date, dir * 7);
1374
+ },
1375
+
1254
1376
  moveMonth: function(date, dir){
1255
1377
  if (!isValidDate(date))
1256
1378
  return this.o.defaultViewDate;
@@ -1305,6 +1427,33 @@
1305
1427
  return this.moveMonth(date, dir*12);
1306
1428
  },
1307
1429
 
1430
+ moveAvailableDate: function(date, dir, fn){
1431
+ do {
1432
+ date = this[fn](date, dir);
1433
+
1434
+ if (!this.dateWithinRange(date))
1435
+ return false;
1436
+
1437
+ fn = 'moveDay';
1438
+ }
1439
+ while (this.dateIsDisabled(date));
1440
+
1441
+ return date;
1442
+ },
1443
+
1444
+ weekOfDateIsDisabled: function(date){
1445
+ return $.inArray(date.getUTCDay(), this.o.daysOfWeekDisabled) !== -1;
1446
+ },
1447
+
1448
+ dateIsDisabled: function(date){
1449
+ return (
1450
+ this.weekOfDateIsDisabled(date) ||
1451
+ $.grep(this.o.datesDisabled, function(d){
1452
+ return isUTCEquals(date, d);
1453
+ }).length > 0
1454
+ );
1455
+ },
1456
+
1308
1457
  dateWithinRange: function(date){
1309
1458
  return date >= this.o.startDate && date <= this.o.endDate;
1310
1459
  },
@@ -1318,7 +1467,7 @@
1318
1467
  return;
1319
1468
  }
1320
1469
  var dateChanged = false,
1321
- dir, newDate, newViewDate,
1470
+ dir, newViewDate,
1322
1471
  focusDate = this.focusDate || this.viewDate;
1323
1472
  switch (e.keyCode){
1324
1473
  case 27: // escape
@@ -1333,69 +1482,52 @@
1333
1482
  e.stopPropagation();
1334
1483
  break;
1335
1484
  case 37: // left
1336
- case 39: // right
1337
- if (!this.o.keyboardNavigation)
1338
- break;
1339
- dir = e.keyCode === 37 ? -1 : 1;
1340
- if (e.ctrlKey){
1341
- newDate = this.moveYear(this.dates.get(-1) || UTCToday(), dir);
1342
- newViewDate = this.moveYear(focusDate, dir);
1343
- this._trigger('changeYear', this.viewDate);
1344
- }
1345
- else if (e.shiftKey){
1346
- newDate = this.moveMonth(this.dates.get(-1) || UTCToday(), dir);
1347
- newViewDate = this.moveMonth(focusDate, dir);
1348
- this._trigger('changeMonth', this.viewDate);
1349
- }
1350
- else {
1351
- newDate = new Date(this.dates.get(-1) || UTCToday());
1352
- newDate.setUTCDate(newDate.getUTCDate() + dir);
1353
- newViewDate = new Date(focusDate);
1354
- newViewDate.setUTCDate(focusDate.getUTCDate() + dir);
1355
- }
1356
- if (this.dateWithinRange(newViewDate)){
1357
- this.focusDate = this.viewDate = newViewDate;
1358
- this.setValue();
1359
- this.fill();
1360
- e.preventDefault();
1361
- }
1362
- break;
1363
1485
  case 38: // up
1486
+ case 39: // right
1364
1487
  case 40: // down
1365
- if (!this.o.keyboardNavigation)
1488
+ if (!this.o.keyboardNavigation || this.o.daysOfWeekDisabled.length === 7)
1366
1489
  break;
1367
- dir = e.keyCode === 38 ? -1 : 1;
1368
- if (e.ctrlKey){
1369
- newDate = this.moveYear(this.dates.get(-1) || UTCToday(), dir);
1370
- newViewDate = this.moveYear(focusDate, dir);
1371
- this._trigger('changeYear', this.viewDate);
1372
- }
1373
- else if (e.shiftKey){
1374
- newDate = this.moveMonth(this.dates.get(-1) || UTCToday(), dir);
1375
- newViewDate = this.moveMonth(focusDate, dir);
1376
- this._trigger('changeMonth', this.viewDate);
1377
- }
1378
- else {
1379
- newDate = new Date(this.dates.get(-1) || UTCToday());
1380
- newDate.setUTCDate(newDate.getUTCDate() + dir * 7);
1381
- newViewDate = new Date(focusDate);
1382
- newViewDate.setUTCDate(focusDate.getUTCDate() + dir * 7);
1383
- }
1384
- if (this.dateWithinRange(newViewDate)){
1490
+ dir = e.keyCode === 37 || e.keyCode === 38 ? -1 : 1;
1491
+ if (this.viewMode === 0) {
1492
+ if (e.ctrlKey){
1493
+ newViewDate = this.moveAvailableDate(focusDate, dir, 'moveYear');
1494
+
1495
+ if (newViewDate)
1496
+ this._trigger('changeYear', this.viewDate);
1497
+ }
1498
+ else if (e.shiftKey){
1499
+ newViewDate = this.moveAvailableDate(focusDate, dir, 'moveMonth');
1500
+
1501
+ if (newViewDate)
1502
+ this._trigger('changeMonth', this.viewDate);
1503
+ }
1504
+ else if (e.keyCode === 37 || e.keyCode === 39){
1505
+ newViewDate = this.moveAvailableDate(focusDate, dir, 'moveDay');
1506
+ }
1507
+ else if (!this.weekOfDateIsDisabled(focusDate)){
1508
+ newViewDate = this.moveAvailableDate(focusDate, dir, 'moveWeek');
1509
+ }
1510
+ } else if (this.viewMode === 1) {
1511
+ if (e.keyCode === 38 || e.keyCode === 40) {
1512
+ dir = dir * 4;
1513
+ }
1514
+ newViewDate = this.moveAvailableDate(focusDate, dir, 'moveMonth');
1515
+ } else if (this.viewMode === 2) {
1516
+ if (e.keyCode === 38 || e.keyCode === 40) {
1517
+ dir = dir * 4;
1518
+ }
1519
+ newViewDate = this.moveAvailableDate(focusDate, dir, 'moveYear');
1520
+ }
1521
+ if (newViewDate){
1385
1522
  this.focusDate = this.viewDate = newViewDate;
1386
1523
  this.setValue();
1387
1524
  this.fill();
1388
1525
  e.preventDefault();
1389
1526
  }
1390
1527
  break;
1391
- case 32: // spacebar
1392
- // Spacebar is used in manually typing dates in some formats.
1393
- // As such, its behavior should not be hijacked.
1394
- break;
1395
1528
  case 13: // enter
1396
- if (!this.o.forceParse) {
1397
- break;
1398
- }
1529
+ if (!this.o.forceParse)
1530
+ break;
1399
1531
  focusDate = this.focusDate || this.dates.get(-1) || this.viewDate;
1400
1532
  if (this.o.keyboardNavigation) {
1401
1533
  this._toggle_multidate(focusDate);
@@ -1407,11 +1539,7 @@
1407
1539
  this.fill();
1408
1540
  if (this.picker.is(':visible')){
1409
1541
  e.preventDefault();
1410
- if (typeof e.stopPropagation === 'function') {
1411
- e.stopPropagation(); // All modern browsers, IE9+
1412
- } else {
1413
- e.cancelBubble = true; // IE6,7,8 ignore "stopPropagation"
1414
- }
1542
+ e.stopPropagation();
1415
1543
  if (this.o.autoclose)
1416
1544
  this.hide();
1417
1545
  }
@@ -1455,6 +1583,7 @@
1455
1583
  };
1456
1584
 
1457
1585
  var DateRangePicker = function(element, options){
1586
+ $(element).data('datepicker', this);
1458
1587
  this.element = $(element);
1459
1588
  this.inputs = $.map(options.inputs, function(i){
1460
1589
  return i.jquery ? i[0] : i;
@@ -1585,14 +1714,15 @@
1585
1714
  // Options priority: js args, data-attrs, locales, defaults
1586
1715
  opts = $.extend({}, defaults, locopts, elopts, options);
1587
1716
  if ($this.hasClass('input-daterange') || opts.inputs){
1588
- var ropts = {
1717
+ $.extend(opts, {
1589
1718
  inputs: opts.inputs || $this.find('input').toArray()
1590
- };
1591
- $this.data('datepicker', (data = new DateRangePicker(this, $.extend(opts, ropts))));
1719
+ });
1720
+ data = new DateRangePicker(this, opts);
1592
1721
  }
1593
1722
  else {
1594
- $this.data('datepicker', (data = new Datepicker(this, opts)));
1723
+ data = new Datepicker(this, opts);
1595
1724
  }
1725
+ $this.data('datepicker', data);
1596
1726
  }
1597
1727
  if (typeof option === 'string' && typeof data[option] === 'function'){
1598
1728
  internal_return = data[option].apply(data, args);
@@ -1614,10 +1744,13 @@
1614
1744
  $.fn.datepicker = datepickerPlugin;
1615
1745
 
1616
1746
  var defaults = $.fn.datepicker.defaults = {
1747
+ assumeNearbyYear: false,
1617
1748
  autoclose: false,
1618
1749
  beforeShowDay: $.noop,
1619
1750
  beforeShowMonth: $.noop,
1620
1751
  beforeShowYear: $.noop,
1752
+ beforeShowDecade: $.noop,
1753
+ beforeShowCentury: $.noop,
1621
1754
  calendarWeeks: false,
1622
1755
  clearBtn: false,
1623
1756
  toggleActive: false,
@@ -1630,7 +1763,7 @@
1630
1763
  keyboardNavigation: true,
1631
1764
  language: 'en',
1632
1765
  minViewMode: 0,
1633
- maxViewMode: 2,
1766
+ maxViewMode: 4,
1634
1767
  multidate: false,
1635
1768
  multidateSeparator: ',',
1636
1769
  orientation: "auto",
@@ -1642,9 +1775,15 @@
1642
1775
  weekStart: 0,
1643
1776
  disableTouchKeyboard: false,
1644
1777
  enableOnReadonly: true,
1778
+ showOnFocus: true,
1779
+ zIndexOffset: 10,
1645
1780
  container: 'body',
1646
1781
  immediateUpdates: false,
1647
- title: ''
1782
+ title: '',
1783
+ templates: {
1784
+ leftArrow: '&laquo;',
1785
+ rightArrow: '&raquo;'
1786
+ }
1648
1787
  };
1649
1788
  var locale_opts = $.fn.datepicker.locale_opts = [
1650
1789
  'format',
@@ -1681,6 +1820,16 @@
1681
1820
  clsName: 'years',
1682
1821
  navFnc: 'FullYear',
1683
1822
  navStep: 10
1823
+ },
1824
+ {
1825
+ clsName: 'decades',
1826
+ navFnc: 'FullDecade',
1827
+ navStep: 100
1828
+ },
1829
+ {
1830
+ clsName: 'centuries',
1831
+ navFnc: 'FullCentury',
1832
+ navStep: 1000
1684
1833
  }],
1685
1834
  isLeapYear: function(year){
1686
1835
  return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0));
@@ -1689,7 +1838,7 @@
1689
1838
  return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
1690
1839
  },
1691
1840
  validParts: /dd?|DD?|mm?|MM?|yy(?:yy)?/g,
1692
- nonpunctuation: /[^ -\/:-@\[\u3400-\u9fff-`{-~\t\n\r]+/g,
1841
+ nonpunctuation: /[^ -\/:-@\u5e74\u6708\u65e5\[-`{-~\t\n\r]+/g,
1693
1842
  parseFormat: function(format){
1694
1843
  if (typeof format.toValue === 'function' && typeof format.toDisplay === 'function')
1695
1844
  return format;
@@ -1702,7 +1851,7 @@
1702
1851
  }
1703
1852
  return {separators: separators, parts: parts};
1704
1853
  },
1705
- parseDate: function(date, format, language){
1854
+ parseDate: function(date, format, language, assumeNearby){
1706
1855
  if (!date)
1707
1856
  return undefined;
1708
1857
  if (date instanceof Date)
@@ -1713,39 +1862,73 @@
1713
1862
  return format.toValue(date, format, language);
1714
1863
  var part_re = /([\-+]\d+)([dmwy])/,
1715
1864
  parts = date.match(/([\-+]\d+)([dmwy])/g),
1716
- part, dir, i;
1865
+ fn_map = {
1866
+ d: 'moveDay',
1867
+ m: 'moveMonth',
1868
+ w: 'moveWeek',
1869
+ y: 'moveYear'
1870
+ },
1871
+ dateAliases = {
1872
+ yesterday: '-1d',
1873
+ today: '+0d',
1874
+ tomorrow: '+1d'
1875
+ },
1876
+ part, dir, i, fn;
1717
1877
  if (/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/.test(date)){
1718
1878
  date = new Date();
1719
1879
  for (i=0; i < parts.length; i++){
1720
1880
  part = part_re.exec(parts[i]);
1721
1881
  dir = parseInt(part[1]);
1722
- switch (part[2]){
1723
- case 'd':
1724
- date.setUTCDate(date.getUTCDate() + dir);
1725
- break;
1726
- case 'm':
1727
- date = Datepicker.prototype.moveMonth.call(Datepicker.prototype, date, dir);
1728
- break;
1729
- case 'w':
1730
- date.setUTCDate(date.getUTCDate() + dir * 7);
1731
- break;
1732
- case 'y':
1733
- date = Datepicker.prototype.moveYear.call(Datepicker.prototype, date, dir);
1734
- break;
1735
- }
1882
+ fn = fn_map[part[2]];
1883
+ date = Datepicker.prototype[fn](date, dir);
1736
1884
  }
1737
- return UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), 0, 0, 0);
1885
+ return UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate());
1738
1886
  }
1887
+
1888
+ if (typeof dateAliases[date] !== 'undefined') {
1889
+ date = dateAliases[date];
1890
+ parts = date.match(/([\-+]\d+)([dmwy])/g);
1891
+
1892
+ if (/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/.test(date)){
1893
+ date = new Date();
1894
+ for (i=0; i < parts.length; i++){
1895
+ part = part_re.exec(parts[i]);
1896
+ dir = parseInt(part[1]);
1897
+ fn = fn_map[part[2]];
1898
+ date = Datepicker.prototype[fn](date, dir);
1899
+ }
1900
+
1901
+ return UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate());
1902
+ }
1903
+ }
1904
+
1739
1905
  parts = date && date.match(this.nonpunctuation) || [];
1740
1906
  date = new Date();
1907
+
1908
+ function applyNearbyYear(year, threshold){
1909
+ if (threshold === true)
1910
+ threshold = 10;
1911
+
1912
+ // if year is 2 digits or less, than the user most likely is trying to get a recent century
1913
+ if (year < 100){
1914
+ year += 2000;
1915
+ // if the new year is more than threshold years in advance, use last century
1916
+ if (year > ((new Date()).getFullYear()+threshold)){
1917
+ year -= 100;
1918
+ }
1919
+ }
1920
+
1921
+ return year;
1922
+ }
1923
+
1741
1924
  var parsed = {},
1742
1925
  setters_order = ['yyyy', 'yy', 'M', 'MM', 'm', 'mm', 'd', 'dd'],
1743
1926
  setters_map = {
1744
1927
  yyyy: function(d,v){
1745
- return d.setUTCFullYear(v);
1928
+ return d.setUTCFullYear(assumeNearby ? applyNearbyYear(v, assumeNearby) : v);
1746
1929
  },
1747
1930
  yy: function(d,v){
1748
- return d.setUTCFullYear(2000+v);
1931
+ return d.setUTCFullYear(assumeNearby ? applyNearbyYear(v, assumeNearby) : v);
1749
1932
  },
1750
1933
  m: function(d,v){
1751
1934
  if (isNaN(d))
@@ -1765,7 +1948,7 @@
1765
1948
  val, filtered;
1766
1949
  setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m'];
1767
1950
  setters_map['dd'] = setters_map['d'];
1768
- date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);
1951
+ date = UTCToday();
1769
1952
  var fparts = format.parts.slice();
1770
1953
  // Remove noop parts
1771
1954
  if (parts.length !== fparts.length){
@@ -1844,9 +2027,9 @@
1844
2027
  '<th colspan="7" class="datepicker-title"></th>'+
1845
2028
  '</tr>'+
1846
2029
  '<tr>'+
1847
- '<th class="prev">&#171;</th>'+
2030
+ '<th class="prev">&laquo;</th>'+
1848
2031
  '<th colspan="5" class="datepicker-switch"></th>'+
1849
- '<th class="next">&#187;</th>'+
2032
+ '<th class="next">&raquo;</th>'+
1850
2033
  '</tr>'+
1851
2034
  '</thead>',
1852
2035
  contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>',
@@ -1881,6 +2064,20 @@
1881
2064
  DPGlobal.footTemplate+
1882
2065
  '</table>'+
1883
2066
  '</div>'+
2067
+ '<div class="datepicker-decades">'+
2068
+ '<table class="table-condensed">'+
2069
+ DPGlobal.headTemplate+
2070
+ DPGlobal.contTemplate+
2071
+ DPGlobal.footTemplate+
2072
+ '</table>'+
2073
+ '</div>'+
2074
+ '<div class="datepicker-centuries">'+
2075
+ '<table class="table-condensed">'+
2076
+ DPGlobal.headTemplate+
2077
+ DPGlobal.contTemplate+
2078
+ DPGlobal.footTemplate+
2079
+ '</table>'+
2080
+ '</div>'+
1884
2081
  '</div>';
1885
2082
 
1886
2083
  $.fn.datepicker.DPGlobal = DPGlobal;
@@ -1896,7 +2093,7 @@
1896
2093
 
1897
2094
  /* DATEPICKER VERSION
1898
2095
  * =================== */
1899
- $.fn.datepicker.version = '1.5.0';
2096
+ $.fn.datepicker.version = '1.6.0-alpha';
1900
2097
 
1901
2098
  /* DATEPICKER DATA-API
1902
2099
  * ================== */