bootstrap-datepicker-rails 1.4.0 → 1.8.0.1

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