ndr_ui 4.1.1 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (138) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +119 -0
  3. data/CODE_OF_CONDUCT.md +13 -0
  4. data/app/assets/fonts/bootstrap-icons.woff +0 -0
  5. data/app/assets/fonts/bootstrap-icons.woff2 +0 -0
  6. data/app/assets/javascripts/ndr_ui/index.js +1 -0
  7. data/app/assets/stylesheets/ndr_ui/bootstrap-icons.scss +2090 -0
  8. data/app/assets/stylesheets/ndr_ui/index.scss +5 -3
  9. data/app/builders/ndr_ui/bootstrap/datepicker.rb +4 -4
  10. data/app/builders/ndr_ui/bootstrap/form_control_class.rb +2 -2
  11. data/app/builders/ndr_ui/bootstrap/inline_errors_and_warnings.rb +2 -2
  12. data/app/builders/ndr_ui/bootstrap/input_group_addons.rb +4 -10
  13. data/app/builders/ndr_ui/bootstrap/readonly.rb +12 -12
  14. data/app/builders/ndr_ui/bootstrap_builder.rb +32 -25
  15. data/app/helpers/ndr_ui/bootstrap/{accordion.rb → accordion_helper.rb} +49 -16
  16. data/app/helpers/ndr_ui/bootstrap/breadcrumbs_helper.rb +4 -4
  17. data/app/helpers/ndr_ui/bootstrap/card_helper.rb +94 -0
  18. data/app/helpers/ndr_ui/bootstrap/dropdown_helper.rb +16 -13
  19. data/app/helpers/ndr_ui/bootstrap/modal_helper.rb +15 -13
  20. data/app/helpers/ndr_ui/bootstrap_helper.rb +68 -64
  21. data/app/helpers/ndr_ui/css_helper.rb +1 -4
  22. data/lib/ndr_ui/engine.rb +2 -1
  23. data/lib/ndr_ui/version.rb +1 -1
  24. data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/css/bootstrap-datepicker.css +39 -36
  25. data/vendor/assets/bootstrap-datepicker-1.7.1-dist/css/bootstrap-datepicker.css.map +1 -0
  26. data/vendor/assets/bootstrap-datepicker-1.7.1-dist/css/bootstrap-datepicker.min.css +7 -0
  27. data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/css/bootstrap-datepicker.standalone.css +40 -37
  28. data/vendor/assets/bootstrap-datepicker-1.7.1-dist/css/bootstrap-datepicker.standalone.css.map +1 -0
  29. data/vendor/assets/bootstrap-datepicker-1.7.1-dist/css/bootstrap-datepicker.standalone.min.css +7 -0
  30. data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/css/bootstrap-datepicker3.css +53 -50
  31. data/vendor/assets/bootstrap-datepicker-1.7.1-dist/css/bootstrap-datepicker3.css.map +1 -0
  32. data/vendor/assets/bootstrap-datepicker-1.7.1-dist/css/bootstrap-datepicker3.min.css +7 -0
  33. data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/css/bootstrap-datepicker3.standalone.css +55 -52
  34. data/vendor/assets/bootstrap-datepicker-1.7.1-dist/css/bootstrap-datepicker3.standalone.css.map +1 -0
  35. data/vendor/assets/bootstrap-datepicker-1.7.1-dist/css/bootstrap-datepicker3.standalone.min.css +7 -0
  36. data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/js/bootstrap-datepicker.js +355 -450
  37. data/vendor/assets/bootstrap-datepicker-1.7.1-dist/js/bootstrap-datepicker.min.js +8 -0
  38. data/vendor/assets/bootstrap-datepicker-1.7.1-dist/locales/bootstrap-datepicker-en-CA.min.js +1 -0
  39. data/vendor/assets/bootstrap-datepicker-1.7.1-dist/locales/bootstrap-datepicker.ar-tn.min.js +1 -0
  40. data/vendor/assets/bootstrap-datepicker-1.7.1-dist/locales/bootstrap-datepicker.bn.min.js +1 -0
  41. data/vendor/assets/bootstrap-datepicker-1.7.1-dist/locales/bootstrap-datepicker.br.min.js +1 -0
  42. data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.cs.min.js +1 -1
  43. data/vendor/assets/bootstrap-datepicker-1.7.1-dist/locales/bootstrap-datepicker.da.min.js +1 -0
  44. data/vendor/assets/bootstrap-datepicker-1.7.1-dist/locales/bootstrap-datepicker.en-IE.min.js +1 -0
  45. data/vendor/assets/bootstrap-datepicker-1.7.1-dist/locales/bootstrap-datepicker.en-NZ.min.js +1 -0
  46. data/vendor/assets/bootstrap-datepicker-1.7.1-dist/locales/bootstrap-datepicker.en-ZA.min.js +1 -0
  47. data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.eu.min.js +1 -1
  48. data/vendor/assets/bootstrap-datepicker-1.7.1-dist/locales/bootstrap-datepicker.hi.min.js +1 -0
  49. data/vendor/assets/bootstrap-datepicker-1.7.1-dist/locales/bootstrap-datepicker.hy.min.js +1 -0
  50. data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.ka.min.js +1 -1
  51. data/vendor/assets/bootstrap-datepicker-1.7.1-dist/locales/bootstrap-datepicker.kh.min.js +1 -0
  52. data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.kk.min.js +1 -1
  53. data/vendor/assets/bootstrap-datepicker-1.7.1-dist/locales/bootstrap-datepicker.km.min.js +1 -0
  54. data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.kr.min.js +1 -1
  55. data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.lv.min.js +1 -1
  56. data/vendor/assets/bootstrap-datepicker-1.7.1-dist/locales/bootstrap-datepicker.oc.min.js +1 -0
  57. data/vendor/assets/bootstrap-datepicker-1.7.1-dist/locales/bootstrap-datepicker.pl.min.js +1 -0
  58. data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.ro.min.js +1 -1
  59. data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.rs-latin.min.js +1 -1
  60. data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.rs.min.js +1 -1
  61. data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.ru.min.js +1 -1
  62. data/vendor/assets/bootstrap-datepicker-1.7.1-dist/locales/bootstrap-datepicker.si.min.js +1 -0
  63. data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.sl.min.js +1 -1
  64. data/vendor/assets/bootstrap-datepicker-1.7.1-dist/locales/bootstrap-datepicker.ta.min.js +1 -0
  65. data/vendor/assets/bootstrap-datepicker-1.7.1-dist/locales/bootstrap-datepicker.tg.min.js +1 -0
  66. data/vendor/assets/bootstrap-datepicker-1.7.1-dist/locales/bootstrap-datepicker.uz-cyrl.min.js +1 -0
  67. data/vendor/assets/bootstrap-datepicker-1.7.1-dist/locales/bootstrap-datepicker.uz-latn.min.js +1 -0
  68. data/vendor/assets/datepicker-scss-fix/bootstrap-datepicker-scss-fix.scss +1 -1
  69. metadata +148 -104
  70. data/app/helpers/ndr_ui/bootstrap/panel_helper.rb +0 -87
  71. data/vendor/assets/bootstrap-datepicker-1.6.0-dist/css/bootstrap-datepicker.css.map +0 -1
  72. data/vendor/assets/bootstrap-datepicker-1.6.0-dist/css/bootstrap-datepicker.min.css +0 -9
  73. data/vendor/assets/bootstrap-datepicker-1.6.0-dist/css/bootstrap-datepicker.min.css.map +0 -1
  74. data/vendor/assets/bootstrap-datepicker-1.6.0-dist/css/bootstrap-datepicker.standalone.css.map +0 -1
  75. data/vendor/assets/bootstrap-datepicker-1.6.0-dist/css/bootstrap-datepicker.standalone.min.css +0 -9
  76. data/vendor/assets/bootstrap-datepicker-1.6.0-dist/css/bootstrap-datepicker.standalone.min.css.map +0 -1
  77. data/vendor/assets/bootstrap-datepicker-1.6.0-dist/css/bootstrap-datepicker3.css.map +0 -1
  78. data/vendor/assets/bootstrap-datepicker-1.6.0-dist/css/bootstrap-datepicker3.min.css +0 -9
  79. data/vendor/assets/bootstrap-datepicker-1.6.0-dist/css/bootstrap-datepicker3.min.css.map +0 -1
  80. data/vendor/assets/bootstrap-datepicker-1.6.0-dist/css/bootstrap-datepicker3.standalone.css.map +0 -1
  81. data/vendor/assets/bootstrap-datepicker-1.6.0-dist/css/bootstrap-datepicker3.standalone.min.css +0 -9
  82. data/vendor/assets/bootstrap-datepicker-1.6.0-dist/css/bootstrap-datepicker3.standalone.min.css.map +0 -1
  83. data/vendor/assets/bootstrap-datepicker-1.6.0-dist/js/bootstrap-datepicker.min.js +0 -9
  84. data/vendor/assets/bootstrap-datepicker-1.6.0-dist/locales/bootstrap-datepicker.da.min.js +0 -1
  85. data/vendor/assets/bootstrap-datepicker-1.6.0-dist/locales/bootstrap-datepicker.hy.min.js +0 -1
  86. data/vendor/assets/bootstrap-datepicker-1.6.0-dist/locales/bootstrap-datepicker.kh.min.js +0 -1
  87. data/vendor/assets/bootstrap-datepicker-1.6.0-dist/locales/bootstrap-datepicker.pl.min.js +0 -1
  88. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.ar.min.js +0 -0
  89. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.az.min.js +0 -0
  90. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.bg.min.js +0 -0
  91. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.bs.min.js +0 -0
  92. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.ca.min.js +0 -0
  93. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.cy.min.js +0 -0
  94. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.de.min.js +0 -0
  95. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.el.min.js +0 -0
  96. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.en-AU.min.js +0 -0
  97. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.en-GB.min.js +0 -0
  98. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.eo.min.js +0 -0
  99. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.es.min.js +0 -0
  100. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.et.min.js +0 -0
  101. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.fa.min.js +0 -0
  102. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.fi.min.js +0 -0
  103. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.fo.min.js +0 -0
  104. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.fr-CH.min.js +0 -0
  105. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.fr.min.js +0 -0
  106. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.gl.min.js +0 -0
  107. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.he.min.js +0 -0
  108. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.hr.min.js +0 -0
  109. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.hu.min.js +0 -0
  110. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.id.min.js +0 -0
  111. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.is.min.js +0 -0
  112. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.it-CH.min.js +0 -0
  113. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.it.min.js +0 -0
  114. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.ja.min.js +0 -0
  115. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.ko.min.js +0 -0
  116. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.lt.min.js +0 -0
  117. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.me.min.js +0 -0
  118. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.mk.min.js +0 -0
  119. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.mn.min.js +0 -0
  120. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.ms.min.js +0 -0
  121. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.nb.min.js +0 -0
  122. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.nl-BE.min.js +0 -0
  123. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.nl.min.js +0 -0
  124. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.no.min.js +0 -0
  125. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.pt-BR.min.js +0 -0
  126. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.pt.min.js +0 -0
  127. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.sk.min.js +0 -0
  128. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.sq.min.js +0 -0
  129. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.sr-latin.min.js +0 -0
  130. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.sr.min.js +0 -0
  131. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.sv.min.js +0 -0
  132. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.sw.min.js +0 -0
  133. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.th.min.js +0 -0
  134. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.tr.min.js +0 -0
  135. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.uk.min.js +0 -0
  136. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.vi.min.js +0 -0
  137. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.zh-CN.min.js +0 -0
  138. /data/vendor/assets/{bootstrap-datepicker-1.6.0-dist → bootstrap-datepicker-1.7.1-dist}/locales/bootstrap-datepicker.zh-TW.min.js +0 -0
@@ -1,10 +1,10 @@
1
1
  /*!
2
- * Datepicker for Bootstrap v1.6.0 (https://github.com/eternicode/bootstrap-datepicker)
2
+ * Datepicker for Bootstrap v1.7.1 (https://github.com/uxsolutions/bootstrap-datepicker)
3
3
  *
4
- * Copyright 2012 Stefan Petre
5
- * Improvements by Andrew Rowls
6
4
  * Licensed under the Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0)
7
- */(function(factory){
5
+ */
6
+
7
+ (function(factory){
8
8
  if (typeof define === "function" && define.amd) {
9
9
  define(["jquery"], factory);
10
10
  } else if (typeof exports === 'object') {
@@ -13,7 +13,6 @@
13
13
  factory(jQuery);
14
14
  }
15
15
  }(function($, undefined){
16
-
17
16
  function UTCDate(){
18
17
  return new Date(Date.UTC.apply(Date, arguments));
19
18
  }
@@ -28,8 +27,12 @@
28
27
  date1.getUTCDate() === date2.getUTCDate()
29
28
  );
30
29
  }
31
- function alias(method){
30
+ function alias(method, deprecationMsg){
32
31
  return function(){
32
+ if (deprecationMsg !== undefined) {
33
+ $.fn.datepicker.deprecated(deprecationMsg);
34
+ }
35
+
33
36
  return this[method].apply(this, arguments);
34
37
  };
35
38
  }
@@ -47,7 +50,8 @@
47
50
  // $.inArray doesn't work with Dates
48
51
  var val = d && d.valueOf();
49
52
  for (var i=0, l=this.length; i < l; i++)
50
- if (this[i].valueOf() === val)
53
+ // Use date arithmetic to allow dates with different times to match
54
+ if (0 <= this[i].valueOf() - val && this[i].valueOf() - val < 1000*60*60*24)
51
55
  return i;
52
56
  return -1;
53
57
  },
@@ -84,7 +88,7 @@
84
88
  // Picker object
85
89
 
86
90
  var Datepicker = function(element, options){
87
- $(element).data('datepicker', this);
91
+ $.data(element, 'datepicker', this);
88
92
  this._process_options(options);
89
93
 
90
94
  this.dates = new DateArray();
@@ -92,12 +96,12 @@
92
96
  this.focusDate = null;
93
97
 
94
98
  this.element = $(element);
95
- this.isInline = false;
96
99
  this.isInput = this.element.is('input');
100
+ this.inputField = this.isInput ? this.element : this.element.find('input');
97
101
  this.component = this.element.hasClass('date') ? this.element.find('.add-on, .input-group-addon, .btn') : false;
98
- this.hasInput = this.component && this.element.find('input').length;
99
102
  if (this.component && this.component.length === 0)
100
103
  this.component = false;
104
+ this.isInline = !this.component && this.element.is('div');
101
105
 
102
106
  this.picker = $(DPGlobal.template);
103
107
 
@@ -105,6 +109,7 @@
105
109
  if (this._check_template(this.o.templates.leftArrow)) {
106
110
  this.picker.find('.prev').html(this.o.templates.leftArrow);
107
111
  }
112
+
108
113
  if (this._check_template(this.o.templates.rightArrow)) {
109
114
  this.picker.find('.next').html(this.o.templates.rightArrow);
110
115
  }
@@ -123,29 +128,29 @@
123
128
  this.picker.addClass('datepicker-rtl');
124
129
  }
125
130
 
126
- 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
+ }
127
137
 
128
- if (this.o.calendarWeeks)
129
- this.picker.find('thead .datepicker-title, tfoot .today, tfoot .clear')
130
- .attr('colspan', function(i, val){
131
- return parseInt(val) + 1;
132
- });
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
+ });
133
145
 
134
146
  this._allow_update = false;
135
-
136
- this.setStartDate(this._o.startDate);
137
- this.setEndDate(this._o.endDate);
138
- this.setDaysOfWeekDisabled(this.o.daysOfWeekDisabled);
139
- this.setDaysOfWeekHighlighted(this.o.daysOfWeekHighlighted);
140
- this.setDatesDisabled(this.o.datesDisabled);
147
+ this.setViewMode(this.o.startView);
148
+ this._allow_update = true;
141
149
 
142
150
  this.fillDow();
143
151
  this.fillMonths();
144
152
 
145
- this._allow_update = true;
146
-
147
153
  this.update();
148
- this.showMode();
149
154
 
150
155
  if (this.isInline){
151
156
  this.show();
@@ -155,23 +160,21 @@
155
160
  Datepicker.prototype = {
156
161
  constructor: Datepicker,
157
162
 
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;
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);
175
178
  },
176
179
 
177
180
  _check_template: function(tmp){
@@ -210,13 +213,12 @@
210
213
  o.language = lang;
211
214
 
212
215
  // 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);
216
+ o.startView = this._resolveViewName(o.startView);
217
+ o.minViewMode = this._resolveViewName(o.minViewMode);
218
+ o.maxViewMode = this._resolveViewName(o.maxViewMode);
216
219
 
217
- // Check that the start view is between min and max
218
- o.startView = Math.min(o.startView, o.maxViewMode);
219
- 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));
220
222
 
221
223
  // true, false, or Number > 0
222
224
  if (o.multidate !== true){
@@ -253,27 +255,14 @@
253
255
  }
254
256
  }
255
257
 
256
- o.daysOfWeekDisabled = o.daysOfWeekDisabled||[];
257
- if (!$.isArray(o.daysOfWeekDisabled))
258
- o.daysOfWeekDisabled = o.daysOfWeekDisabled.split(/[,\s]*/);
259
- o.daysOfWeekDisabled = $.map(o.daysOfWeekDisabled, function(d){
260
- return parseInt(d, 10);
261
- });
262
-
263
- o.daysOfWeekHighlighted = o.daysOfWeekHighlighted||[];
264
- if (!$.isArray(o.daysOfWeekHighlighted))
265
- o.daysOfWeekHighlighted = o.daysOfWeekHighlighted.split(/[,\s]*/);
266
- o.daysOfWeekHighlighted = $.map(o.daysOfWeekHighlighted, function(d){
267
- return parseInt(d, 10);
268
- });
258
+ o.daysOfWeekDisabled = this._resolveDaysOfWeek(o.daysOfWeekDisabled||[]);
259
+ o.daysOfWeekHighlighted = this._resolveDaysOfWeek(o.daysOfWeekHighlighted||[]);
269
260
 
270
261
  o.datesDisabled = o.datesDisabled||[];
271
262
  if (!$.isArray(o.datesDisabled)) {
272
- var datesDisabled = [];
273
- datesDisabled.push(DPGlobal.parseDate(o.datesDisabled, format, o.language, o.assumeNearbyYear));
274
- o.datesDisabled = datesDisabled;
263
+ o.datesDisabled = o.datesDisabled.split(',');
275
264
  }
276
- o.datesDisabled = $.map(o.datesDisabled,function(d){
265
+ o.datesDisabled = $.map(o.datesDisabled, function(d){
277
266
  return DPGlobal.parseDate(d, format, o.language, o.assumeNearbyYear);
278
267
  });
279
268
 
@@ -308,7 +297,9 @@
308
297
  });
309
298
  o.orientation.y = _plc[0] || 'auto';
310
299
  }
311
- 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) {
312
303
  var year = o.defaultViewDate.year || new Date().getFullYear();
313
304
  var month = o.defaultViewDate.month || 0;
314
305
  var day = o.defaultViewDate.day || 1;
@@ -325,8 +316,7 @@
325
316
  if (evs[i].length === 2){
326
317
  ch = undefined;
327
318
  ev = evs[i][1];
328
- }
329
- else if (evs[i].length === 3){
319
+ } else if (evs[i].length === 3){
330
320
  ch = evs[i][1];
331
321
  ev = evs[i][2];
332
322
  }
@@ -339,8 +329,7 @@
339
329
  if (evs[i].length === 2){
340
330
  ch = undefined;
341
331
  ev = evs[i][1];
342
- }
343
- else if (evs[i].length === 3){
332
+ } else if (evs[i].length === 3){
344
333
  ch = evs[i][1];
345
334
  ev = evs[i][2];
346
335
  }
@@ -366,22 +355,21 @@
366
355
  [this.element, events]
367
356
  ];
368
357
  }
369
- else if (this.component && this.hasInput) { // component: input + button
358
+ // component: input + button
359
+ else if (this.component && this.inputField.length) {
370
360
  this._events = [
371
361
  // For components that are not readonly, allow keyboard nav
372
- [this.element.find('input'), events],
362
+ [this.inputField, events],
373
363
  [this.component, {
374
364
  click: $.proxy(this.show, this)
375
365
  }]
376
366
  ];
377
367
  }
378
- else if (this.element.is('div')){ // inline datepicker
379
- this.isInline = true;
380
- }
381
368
  else {
382
369
  this._events = [
383
370
  [this.element, {
384
- click: $.proxy(this.show, this)
371
+ click: $.proxy(this.show, this),
372
+ keydown: $.proxy(this.keydown, this)
385
373
  }]
386
374
  ];
387
375
  }
@@ -413,18 +401,24 @@
413
401
  [this.picker, {
414
402
  click: $.proxy(this.click, this)
415
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
+ }],
416
410
  [$(window), {
417
411
  resize: $.proxy(this.place, this)
418
412
  }],
419
413
  [$(document), {
420
- mousedown: $.proxy(function(e){
414
+ 'mousedown touchstart': $.proxy(function(e){
421
415
  // Clicked outside the datepicker, hide it
422
416
  if (!(
423
417
  this.element.is(e.target) ||
424
418
  this.element.find(e.target).length ||
425
419
  this.picker.is(e.target) ||
426
420
  this.picker.find(e.target).length ||
427
- this.picker.hasClass('datepicker-inline')
421
+ this.isInline
428
422
  )){
429
423
  this.hide();
430
424
  }
@@ -453,13 +447,13 @@
453
447
  this.element.trigger({
454
448
  type: event,
455
449
  date: local_date,
450
+ viewMode: this.viewMode,
456
451
  dates: $.map(this.dates, this._utc_to_local),
457
452
  format: $.proxy(function(ix, format){
458
453
  if (arguments.length === 0){
459
454
  ix = this.dates.length - 1;
460
455
  format = this.o.format;
461
- }
462
- else if (typeof ix === 'string'){
456
+ } else if (typeof ix === 'string'){
463
457
  format = ix;
464
458
  ix = this.dates.length - 1;
465
459
  }
@@ -471,8 +465,7 @@
471
465
  },
472
466
 
473
467
  show: function(){
474
- var element = this.component ? this.element.find('input') : this.element;
475
- if (element.attr('readonly') && this.o.enableOnReadonly === false)
468
+ if (this.inputField.prop('disabled') || (this.inputField.prop('readonly') && this.o.enableOnReadonly === false))
476
469
  return;
477
470
  if (!this.isInline)
478
471
  this.picker.appendTo(this.o.container);
@@ -487,23 +480,14 @@
487
480
  },
488
481
 
489
482
  hide: function(){
490
- if (this.isInline)
491
- return this;
492
- if (!this.picker.is(':visible'))
483
+ if (this.isInline || !this.picker.is(':visible'))
493
484
  return this;
494
485
  this.focusDate = null;
495
486
  this.picker.hide().detach();
496
487
  this._detachSecondaryEvents();
497
- this.viewMode = this.o.startView;
498
- this.showMode();
499
-
500
- if (
501
- this.o.forceParse &&
502
- (
503
- this.isInput && this.element.val() ||
504
- this.hasInput && this.element.find('input').val()
505
- )
506
- )
488
+ this.setViewMode(this.o.startView);
489
+
490
+ if (this.o.forceParse && this.inputField.val())
507
491
  this.setValue();
508
492
  this._trigger('hide');
509
493
  return this;
@@ -521,25 +505,33 @@
521
505
  return this;
522
506
  },
523
507
 
524
- paste: function(evt){
508
+ paste: function(e){
525
509
  var dateString;
526
- if (evt.originalEvent.clipboardData && evt.originalEvent.clipboardData.types
527
- && $.inArray('text/plain', evt.originalEvent.clipboardData.types) !== -1) {
528
- dateString = evt.originalEvent.clipboardData.getData('text/plain');
529
- }
530
- else if (window.clipboardData) {
510
+ if (e.originalEvent.clipboardData && e.originalEvent.clipboardData.types
511
+ && $.inArray('text/plain', e.originalEvent.clipboardData.types) !== -1) {
512
+ dateString = e.originalEvent.clipboardData.getData('text/plain');
513
+ } else if (window.clipboardData) {
531
514
  dateString = window.clipboardData.getData('Text');
532
- }
533
- else {
515
+ } else {
534
516
  return;
535
517
  }
536
518
  this.setDate(dateString);
537
519
  this.update();
538
- evt.preventDefault();
520
+ e.preventDefault();
539
521
  },
540
522
 
541
523
  _utc_to_local: function(utc){
542
- 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;
543
535
  },
544
536
  _local_to_utc: function(local){
545
537
  return local && new Date(local.getTime() - (local.getTimezoneOffset()*60000));
@@ -548,7 +540,7 @@
548
540
  return local && new Date(local.getFullYear(), local.getMonth(), local.getDate());
549
541
  },
550
542
  _zero_utc_time: function(utc){
551
- return utc && new Date(Date.UTC(utc.getUTCFullYear(), utc.getUTCMonth(), utc.getUTCDate()));
543
+ return utc && UTCDate(utc.getUTCFullYear(), utc.getUTCMonth(), utc.getUTCDate());
552
544
  },
553
545
 
554
546
  getDates: function(){
@@ -567,7 +559,7 @@
567
559
 
568
560
  getUTCDate: function(){
569
561
  var selected_date = this.dates.get(-1);
570
- if (typeof selected_date !== 'undefined') {
562
+ if (selected_date !== undefined) {
571
563
  return new Date(selected_date);
572
564
  } else {
573
565
  return null;
@@ -575,17 +567,7 @@
575
567
  },
576
568
 
577
569
  clearDates: function(){
578
- var element;
579
- if (this.isInput) {
580
- element = this.element;
581
- } else if (this.component) {
582
- element = this.element.find('input');
583
- }
584
-
585
- if (element) {
586
- element.val('');
587
- }
588
-
570
+ this.inputField.val('');
589
571
  this.update();
590
572
  this._trigger('changeDate');
591
573
 
@@ -593,6 +575,7 @@
593
575
  this.hide();
594
576
  }
595
577
  },
578
+
596
579
  setDates: function(){
597
580
  var args = $.isArray(arguments[0]) ? arguments[0] : arguments;
598
581
  this.update.apply(this, args);
@@ -603,26 +586,17 @@
603
586
 
604
587
  setUTCDates: function(){
605
588
  var args = $.isArray(arguments[0]) ? arguments[0] : arguments;
606
- this.update.apply(this, $.map(args, this._utc_to_local));
607
- this._trigger('changeDate');
608
- this.setValue();
589
+ this.setDates.apply(this, $.map(args, this._utc_to_local));
609
590
  return this;
610
591
  },
611
592
 
612
593
  setDate: alias('setDates'),
613
594
  setUTCDate: alias('setUTCDates'),
614
- remove: alias('destroy'),
595
+ remove: alias('destroy', 'Method `remove` is deprecated and will be removed in version 2.0. Use `destroy` instead'),
615
596
 
616
597
  setValue: function(){
617
598
  var formatted = this.getFormattedDate();
618
- if (!this.isInput){
619
- if (this.component){
620
- this.element.find('input').val(formatted);
621
- }
622
- }
623
- else {
624
- this.element.val(formatted);
625
- }
599
+ this.inputField.val(formatted);
626
600
  return this;
627
601
  },
628
602
 
@@ -661,7 +635,6 @@
661
635
  setDaysOfWeekDisabled: function(daysOfWeekDisabled){
662
636
  this._process_options({daysOfWeekDisabled: daysOfWeekDisabled});
663
637
  this.update();
664
- this.updateNavArrows();
665
638
  return this;
666
639
  },
667
640
 
@@ -674,7 +647,7 @@
674
647
  setDatesDisabled: function(datesDisabled){
675
648
  this._process_options({datesDisabled: datesDisabled});
676
649
  this.update();
677
- this.updateNavArrows();
650
+ return this;
678
651
  },
679
652
 
680
653
  place: function(){
@@ -688,17 +661,17 @@
688
661
  scrollTop = this.o.container === 'body' ? $(document).scrollTop() : container.scrollTop(),
689
662
  appendOffset = container.offset();
690
663
 
691
- var parentsZindex = [];
664
+ var parentsZindex = [0];
692
665
  this.element.parents().each(function(){
693
666
  var itemZIndex = $(this).css('z-index');
694
- if (itemZIndex !== 'auto' && itemZIndex !== 0) parentsZindex.push(parseInt(itemZIndex));
667
+ if (itemZIndex !== 'auto' && Number(itemZIndex) !== 0) parentsZindex.push(Number(itemZIndex));
695
668
  });
696
669
  var zIndex = Math.max.apply(Math, parentsZindex) + this.o.zIndexOffset;
697
670
  var offset = this.component ? this.component.parent().offset() : this.element.offset();
698
671
  var height = this.component ? this.component.outerHeight(true) : this.element.outerHeight(false);
699
672
  var width = this.component ? this.component.outerWidth(true) : this.element.outerWidth(false);
700
- var left = offset.left - appendOffset.left,
701
- top = offset.top - appendOffset.top;
673
+ var left = offset.left - appendOffset.left;
674
+ var top = offset.top - appendOffset.top;
702
675
 
703
676
  if (this.o.container !== 'body') {
704
677
  top += scrollTop;
@@ -726,8 +699,13 @@
726
699
  this.picker.addClass('datepicker-orient-right');
727
700
  left += width - calendarWidth;
728
701
  } else {
729
- // Default to left
730
- 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
+ }
731
709
  }
732
710
  }
733
711
 
@@ -778,11 +756,10 @@
778
756
  dates.push(date);
779
757
  }, this));
780
758
  fromArgs = true;
781
- }
782
- else {
759
+ } else {
783
760
  dates = this.isInput
784
761
  ? this.element.val()
785
- : this.element.data('date') || this.element.find('input').val();
762
+ : this.element.data('date') || this.inputField.val();
786
763
  if (dates && this.o.multidate)
787
764
  dates = dates.split(this.o.multidateSeparator);
788
765
  else
@@ -801,59 +778,63 @@
801
778
  }, this), true);
802
779
  this.dates.replace(dates);
803
780
 
804
- if (this.dates.length)
805
- this.viewDate = new Date(this.dates.get(-1));
806
- else if (this.viewDate < this.o.startDate)
807
- this.viewDate = new Date(this.o.startDate);
808
- else if (this.viewDate > this.o.endDate)
809
- this.viewDate = new Date(this.o.endDate);
810
- else
811
- this.viewDate = this.o.defaultViewDate;
781
+ if (this.o.updateViewDate) {
782
+ if (this.dates.length)
783
+ this.viewDate = new Date(this.dates.get(-1));
784
+ else if (this.viewDate < this.o.startDate)
785
+ this.viewDate = new Date(this.o.startDate);
786
+ else if (this.viewDate > this.o.endDate)
787
+ this.viewDate = new Date(this.o.endDate);
788
+ else
789
+ this.viewDate = this.o.defaultViewDate;
790
+ }
812
791
 
813
792
  if (fromArgs){
814
793
  // setting date by clicking
815
794
  this.setValue();
795
+ this.element.change();
816
796
  }
817
- else if (dates.length){
797
+ else if (this.dates.length){
818
798
  // setting date by typing
819
- if (String(oldDates) !== String(this.dates))
799
+ if (String(oldDates) !== String(this.dates) && fromArgs) {
820
800
  this._trigger('changeDate');
801
+ this.element.change();
802
+ }
821
803
  }
822
- if (!this.dates.length && oldDates.length)
804
+ if (!this.dates.length && oldDates.length) {
823
805
  this._trigger('clearDate');
806
+ this.element.change();
807
+ }
824
808
 
825
809
  this.fill();
826
- this.element.change();
827
810
  return this;
828
811
  },
829
812
 
830
813
  fillDow: function(){
814
+ if (this.o.showWeekDays) {
831
815
  var dowCnt = this.o.weekStart,
832
816
  html = '<tr>';
833
817
  if (this.o.calendarWeeks){
834
- this.picker.find('.datepicker-days .datepicker-switch')
835
- .attr('colspan', function(i, val){
836
- return parseInt(val) + 1;
837
- });
838
818
  html += '<th class="cw">&#160;</th>';
839
819
  }
840
820
  while (dowCnt < this.o.weekStart + 7){
841
821
  html += '<th class="dow';
842
- if ($.inArray(dowCnt, this.o.daysOfWeekDisabled) > -1)
822
+ if ($.inArray(dowCnt, this.o.daysOfWeekDisabled) !== -1)
843
823
  html += ' disabled';
844
824
  html += '">'+dates[this.o.language].daysMin[(dowCnt++)%7]+'</th>';
845
825
  }
846
826
  html += '</tr>';
847
827
  this.picker.find('.datepicker-days thead').append(html);
828
+ }
848
829
  },
849
830
 
850
831
  fillMonths: function(){
851
832
  var localDate = this._utc_to_local(this.viewDate);
852
- var html = '',
853
- i = 0;
854
- while (i < 12){
855
- var focused = localDate && localDate.getMonth() === i ? ' focused' : '';
856
- html += '<span class="month' + focused + '">' + dates[this.o.language].monthsShort[i++]+'</span>';
833
+ var html = '';
834
+ var focused;
835
+ for (var i = 0; i < 12; i++){
836
+ focused = localDate && localDate.getMonth() === i ? ' focused' : '';
837
+ html += '<span class="month' + focused + '">' + dates[this.o.language].monthsShort[i] + '</span>';
857
838
  }
858
839
  this.picker.find('.datepicker-months td').html(html);
859
840
  },
@@ -872,27 +853,26 @@
872
853
  var cls = [],
873
854
  year = this.viewDate.getUTCFullYear(),
874
855
  month = this.viewDate.getUTCMonth(),
875
- today = new Date();
856
+ today = UTCToday();
876
857
  if (date.getUTCFullYear() < year || (date.getUTCFullYear() === year && date.getUTCMonth() < month)){
877
858
  cls.push('old');
878
- }
879
- else if (date.getUTCFullYear() > year || (date.getUTCFullYear() === year && date.getUTCMonth() > month)){
859
+ } else if (date.getUTCFullYear() > year || (date.getUTCFullYear() === year && date.getUTCMonth() > month)){
880
860
  cls.push('new');
881
861
  }
882
862
  if (this.focusDate && date.valueOf() === this.focusDate.valueOf())
883
863
  cls.push('focused');
884
- // Compare internal UTC date with local today, not UTC today
885
- if (this.o.todayHighlight &&
886
- date.getUTCFullYear() === today.getFullYear() &&
887
- date.getUTCMonth() === today.getMonth() &&
888
- date.getUTCDate() === today.getDate()){
864
+ // Compare internal UTC date with UTC today, not local today
865
+ if (this.o.todayHighlight && isUTCEquals(date, today)) {
889
866
  cls.push('today');
890
867
  }
891
868
  if (this.dates.contains(date) !== -1)
892
869
  cls.push('active');
893
- if (!this.dateWithinRange(date) || this.dateIsDisabled(date)){
870
+ if (!this.dateWithinRange(date)){
894
871
  cls.push('disabled');
895
872
  }
873
+ if (this.dateIsDisabled(date)){
874
+ cls.push('disabled', 'disabled-date');
875
+ }
896
876
  if ($.inArray(date.getUTCDay(), this.o.daysOfWeekHighlighted) !== -1){
897
877
  cls.push('highlighted');
898
878
  }
@@ -914,47 +894,44 @@
914
894
  return cls;
915
895
  },
916
896
 
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;
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;
927
906
  });
928
907
 
929
- view.find('.datepicker-switch').text(year + '-' + (year + step * 9));
930
-
931
- thisYear = year - step;
932
- for (i = -1; i < 11; i += 1) {
908
+ var classes, tooltip, before;
909
+ for (var currVal = startVal - step; currVal <= endVal + step; currVal += step) {
933
910
  classes = [cssClass];
934
911
  tooltip = null;
935
912
 
936
- if (i === -1) {
913
+ if (currVal === startVal - step) {
937
914
  classes.push('old');
938
- } else if (i === 10) {
915
+ } else if (currVal === endVal + step) {
939
916
  classes.push('new');
940
917
  }
941
- if ($.inArray(thisYear, steps) !== -1) {
918
+ if ($.inArray(currVal, selected) !== -1) {
942
919
  classes.push('active');
943
920
  }
944
- if (thisYear < startStep || thisYear > endStep) {
921
+ if (currVal < startYear || currVal > endYear) {
945
922
  classes.push('disabled');
946
923
  }
947
- if (thisYear === this.viewDate.getFullYear()) {
924
+ if (currVal === focusedVal) {
948
925
  classes.push('focused');
949
926
  }
950
927
 
951
- if (callback !== $.noop) {
952
- before = callback(new Date(thisYear, 0, 1));
928
+ if (beforeFn !== $.noop) {
929
+ before = beforeFn(new Date(currVal, 0, 1));
953
930
  if (before === undefined) {
954
931
  before = {};
955
- } else if (typeof(before) === 'boolean') {
932
+ } else if (typeof before === 'boolean') {
956
933
  before = {enabled: before};
957
- } else if (typeof(before) === 'string') {
934
+ } else if (typeof before === 'string') {
958
935
  before = {classes: before};
959
936
  }
960
937
  if (before.enabled === false) {
@@ -968,9 +945,10 @@
968
945
  }
969
946
  }
970
947
 
971
- html += '<span class="' + classes.join(' ') + '"' + (tooltip ? ' title="' + tooltip + '"' : '') + '>' + thisYear + '</span>';
972
- thisYear += step;
948
+ html += '<span class="' + classes.join(' ') + '"' + (tooltip ? ' title="' + tooltip + '"' : '') + '>' + currVal + '</span>';
973
949
  }
950
+
951
+ view.find('.datepicker-switch').text(startVal + '-' + endVal);
974
952
  view.find('td').html(html);
975
953
  },
976
954
 
@@ -993,18 +971,17 @@
993
971
  .text(DPGlobal.formatDate(d, titleFormat, this.o.language));
994
972
  this.picker.find('tfoot .today')
995
973
  .text(todaytxt)
996
- .toggle(this.o.todayBtn !== false);
974
+ .css('display', this.o.todayBtn === true || this.o.todayBtn === 'linked' ? 'table-cell' : 'none');
997
975
  this.picker.find('tfoot .clear')
998
976
  .text(cleartxt)
999
- .toggle(this.o.clearBtn !== false);
977
+ .css('display', this.o.clearBtn === true ? 'table-cell' : 'none');
1000
978
  this.picker.find('thead .datepicker-title')
1001
979
  .text(this.o.title)
1002
- .toggle(this.o.title !== '');
980
+ .css('display', typeof this.o.title === 'string' && this.o.title !== '' ? 'table-cell' : 'none');
1003
981
  this.updateNavArrows();
1004
982
  this.fillMonths();
1005
- var prevMonth = UTCDate(year, month-1, 28),
1006
- day = DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth());
1007
- prevMonth.setUTCDate(day);
983
+ var prevMonth = UTCDate(year, month, 0),
984
+ day = prevMonth.getUTCDate();
1008
985
  prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.o.weekStart + 7)%7);
1009
986
  var nextMonth = new Date(prevMonth);
1010
987
  if (prevMonth.getUTCFullYear() < 100){
@@ -1013,36 +990,38 @@
1013
990
  nextMonth.setUTCDate(nextMonth.getUTCDate() + 42);
1014
991
  nextMonth = nextMonth.valueOf();
1015
992
  var html = [];
1016
- var clsName;
993
+ var weekDay, clsName;
1017
994
  while (prevMonth.valueOf() < nextMonth){
1018
- if (prevMonth.getUTCDay() === this.o.weekStart){
995
+ weekDay = prevMonth.getUTCDay();
996
+ if (weekDay === this.o.weekStart){
1019
997
  html.push('<tr>');
1020
998
  if (this.o.calendarWeeks){
1021
999
  // ISO 8601: First week contains first thursday.
1022
1000
  // ISO also states week starts on Monday, but we can be more abstract here.
1023
1001
  var
1024
1002
  // Start of current week: based on weekstart/current date
1025
- ws = new Date(+prevMonth + (this.o.weekStart - prevMonth.getUTCDay() - 7) % 7 * 864e5),
1003
+ ws = new Date(+prevMonth + (this.o.weekStart - weekDay - 7) % 7 * 864e5),
1026
1004
  // Thursday of this week
1027
1005
  th = new Date(Number(ws) + (7 + 4 - ws.getUTCDay()) % 7 * 864e5),
1028
1006
  // First Thursday of year, year from thursday
1029
- 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),
1030
1008
  // Calendar week: ms between thursdays, div ms per day, div 7 days
1031
- calWeek = (th - yth) / 864e5 / 7 + 1;
1009
+ calWeek = (th - yth) / 864e5 / 7 + 1;
1032
1010
  html.push('<td class="cw">'+ calWeek +'</td>');
1033
-
1034
1011
  }
1035
1012
  }
1036
1013
  clsName = this.getClassNames(prevMonth);
1037
1014
  clsName.push('day');
1038
1015
 
1016
+ var content = prevMonth.getUTCDate();
1017
+
1039
1018
  if (this.o.beforeShowDay !== $.noop){
1040
1019
  before = this.o.beforeShowDay(this._utc_to_local(prevMonth));
1041
1020
  if (before === undefined)
1042
1021
  before = {};
1043
- else if (typeof(before) === 'boolean')
1022
+ else if (typeof before === 'boolean')
1044
1023
  before = {enabled: before};
1045
- else if (typeof(before) === 'string')
1024
+ else if (typeof before === 'string')
1046
1025
  before = {classes: before};
1047
1026
  if (before.enabled === false)
1048
1027
  clsName.push('disabled');
@@ -1050,24 +1029,33 @@
1050
1029
  clsName = clsName.concat(before.classes.split(/\s+/));
1051
1030
  if (before.tooltip)
1052
1031
  tooltip = before.tooltip;
1032
+ if (before.content)
1033
+ content = before.content;
1053
1034
  }
1054
1035
 
1055
- clsName = $.unique(clsName);
1056
- html.push('<td class="'+clsName.join(' ')+'"' + (tooltip ? ' title="'+tooltip+'"' : '') + '>'+prevMonth.getUTCDate() + '</td>');
1036
+ //Check if uniqueSort exists (supported by jquery >=1.12 and >=2.2)
1037
+ //Fallback to unique function for older jquery versions
1038
+ if ($.isFunction($.uniqueSort)) {
1039
+ clsName = $.uniqueSort(clsName);
1040
+ } else {
1041
+ clsName = $.unique(clsName);
1042
+ }
1043
+
1044
+ html.push('<td class="'+clsName.join(' ')+'"' + (tooltip ? ' title="'+tooltip+'"' : '') + ' data-date="' + prevMonth.getTime().toString() + '">' + content + '</td>');
1057
1045
  tooltip = null;
1058
- if (prevMonth.getUTCDay() === this.o.weekEnd){
1046
+ if (weekDay === this.o.weekEnd){
1059
1047
  html.push('</tr>');
1060
1048
  }
1061
- prevMonth.setUTCDate(prevMonth.getUTCDate()+1);
1049
+ prevMonth.setUTCDate(prevMonth.getUTCDate() + 1);
1062
1050
  }
1063
- this.picker.find('.datepicker-days tbody').empty().append(html.join(''));
1051
+ this.picker.find('.datepicker-days tbody').html(html.join(''));
1064
1052
 
1065
1053
  var monthsTitle = dates[this.o.language].monthsTitle || dates['en'].monthsTitle || 'Months';
1066
1054
  var months = this.picker.find('.datepicker-months')
1067
1055
  .find('.datepicker-switch')
1068
1056
  .text(this.o.maxViewMode < 2 ? monthsTitle : year)
1069
1057
  .end()
1070
- .find('span').removeClass('active');
1058
+ .find('tbody span').removeClass('active');
1071
1059
 
1072
1060
  $.each(this.dates, function(i, d){
1073
1061
  if (d.getUTCFullYear() === year)
@@ -1091,9 +1079,9 @@
1091
1079
  var before = that.o.beforeShowMonth(moDate);
1092
1080
  if (before === undefined)
1093
1081
  before = {};
1094
- else if (typeof(before) === 'boolean')
1082
+ else if (typeof before === 'boolean')
1095
1083
  before = {enabled: before};
1096
- else if (typeof(before) === 'string')
1084
+ else if (typeof before === 'string')
1097
1085
  before = {classes: before};
1098
1086
  if (before.enabled === false && !$(month).hasClass('disabled'))
1099
1087
  $(month).addClass('disabled');
@@ -1109,7 +1097,6 @@
1109
1097
  '.datepicker-years',
1110
1098
  'year',
1111
1099
  10,
1112
- 1,
1113
1100
  year,
1114
1101
  startYear,
1115
1102
  endYear,
@@ -1121,7 +1108,6 @@
1121
1108
  '.datepicker-decades',
1122
1109
  'decade',
1123
1110
  100,
1124
- 10,
1125
1111
  year,
1126
1112
  startYear,
1127
1113
  endYear,
@@ -1133,7 +1119,6 @@
1133
1119
  '.datepicker-centuries',
1134
1120
  'century',
1135
1121
  1000,
1136
- 100,
1137
1122
  year,
1138
1123
  startYear,
1139
1124
  endYear,
@@ -1147,73 +1132,53 @@
1147
1132
 
1148
1133
  var d = new Date(this.viewDate),
1149
1134
  year = d.getUTCFullYear(),
1150
- 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;
1151
1143
  switch (this.viewMode){
1152
1144
  case 0:
1153
- if (this.o.startDate !== -Infinity && year <= this.o.startDate.getUTCFullYear() && month <= this.o.startDate.getUTCMonth()){
1154
- this.picker.find('.prev').css({visibility: 'hidden'});
1155
- }
1156
- else {
1157
- this.picker.find('.prev').css({visibility: 'visible'});
1158
- }
1159
- if (this.o.endDate !== Infinity && year >= this.o.endDate.getUTCFullYear() && month >= this.o.endDate.getUTCMonth()){
1160
- this.picker.find('.next').css({visibility: 'hidden'});
1161
- }
1162
- else {
1163
- this.picker.find('.next').css({visibility: 'visible'});
1164
- }
1145
+ prevIsDisabled = year <= startYear && month <= startMonth;
1146
+ nextIsDisabled = year >= endYear && month >= endMonth;
1165
1147
  break;
1166
- case 1:
1167
- case 2:
1168
- case 3:
1169
1148
  case 4:
1170
- if (this.o.startDate !== -Infinity && year <= this.o.startDate.getUTCFullYear() || this.o.maxViewMode < 2){
1171
- this.picker.find('.prev').css({visibility: 'hidden'});
1172
- }
1173
- else {
1174
- this.picker.find('.prev').css({visibility: 'visible'});
1175
- }
1176
- if (this.o.endDate !== Infinity && year >= this.o.endDate.getUTCFullYear() || this.o.maxViewMode < 2){
1177
- this.picker.find('.next').css({visibility: 'hidden'});
1178
- }
1179
- else {
1180
- this.picker.find('.next').css({visibility: 'visible'});
1181
- }
1149
+ factor *= 10;
1150
+ /* falls through */
1151
+ case 3:
1152
+ factor *= 10;
1153
+ /* falls through */
1154
+ case 2:
1155
+ factor *= 10;
1156
+ /* falls through */
1157
+ case 1:
1158
+ prevIsDisabled = Math.floor(year / factor) * factor <= startYear;
1159
+ nextIsDisabled = Math.floor(year / factor) * factor + factor >= endYear;
1182
1160
  break;
1183
1161
  }
1162
+
1163
+ this.picker.find('.prev').toggleClass('disabled', prevIsDisabled);
1164
+ this.picker.find('.next').toggleClass('disabled', nextIsDisabled);
1184
1165
  },
1185
1166
 
1186
1167
  click: function(e){
1187
1168
  e.preventDefault();
1188
1169
  e.stopPropagation();
1189
1170
 
1190
- var target, dir, day, year, month, monthChanged, yearChanged;
1171
+ var target, dir, day, year, month;
1191
1172
  target = $(e.target);
1192
1173
 
1193
1174
  // Clicked on the switch
1194
- if (target.hasClass('datepicker-switch')){
1195
- this.showMode(1);
1196
- }
1197
-
1198
- // Clicked on prev or next
1199
- var navArrow = target.closest('.prev, .next');
1200
- if (navArrow.length > 0) {
1201
- dir = DPGlobal.modes[this.viewMode].navStep * (navArrow.hasClass('prev') ? -1 : 1);
1202
- if (this.viewMode === 0){
1203
- this.viewDate = this.moveMonth(this.viewDate, dir);
1204
- this._trigger('changeMonth', this.viewDate);
1205
- } else {
1206
- this.viewDate = this.moveYear(this.viewDate, dir);
1207
- if (this.viewMode === 1){
1208
- this._trigger('changeYear', this.viewDate);
1209
- }
1210
- }
1211
- this.fill();
1175
+ if (target.hasClass('datepicker-switch') && this.viewMode !== this.o.maxViewMode){
1176
+ this.setViewMode(this.viewMode + 1);
1212
1177
  }
1213
1178
 
1214
1179
  // Clicked on today button
1215
- if (target.hasClass('today')){
1216
- this.showMode(-2);
1180
+ if (target.hasClass('today') && !target.hasClass('day')){
1181
+ this.setViewMode(0);
1217
1182
  this._setDate(UTCToday(), this.o.todayBtn === 'linked' ? null : 'view');
1218
1183
  }
1219
1184
 
@@ -1223,104 +1188,70 @@
1223
1188
  }
1224
1189
 
1225
1190
  if (!target.hasClass('disabled')){
1226
- // Clicked on a day
1227
- if (target.hasClass('day')){
1228
- day = parseInt(target.text(), 10) || 1;
1229
- year = this.viewDate.getUTCFullYear();
1230
- month = this.viewDate.getUTCMonth();
1231
-
1232
- // From last month
1233
- if (target.hasClass('old')){
1234
- if (month === 0) {
1235
- month = 11;
1236
- year = year - 1;
1237
- monthChanged = true;
1238
- yearChanged = true;
1239
- } else {
1240
- month = month - 1;
1241
- monthChanged = true;
1242
- }
1243
- }
1244
-
1245
- // From next month
1246
- if (target.hasClass('new')) {
1247
- if (month === 11){
1248
- month = 0;
1249
- year = year + 1;
1250
- monthChanged = true;
1251
- yearChanged = true;
1252
- } else {
1253
- month = month + 1;
1254
- monthChanged = true;
1255
- }
1256
- }
1257
- this._setDate(UTCDate(year, month, day));
1258
- if (yearChanged) {
1259
- this._trigger('changeYear', this.viewDate);
1260
- }
1261
- if (monthChanged) {
1262
- this._trigger('changeMonth', this.viewDate);
1263
- }
1264
- }
1265
-
1266
- // Clicked on a month
1267
- if (target.hasClass('month')) {
1268
- this.viewDate.setUTCDate(1);
1269
- day = 1;
1270
- month = target.parent().find('span').index(target);
1271
- year = this.viewDate.getUTCFullYear();
1272
- this.viewDate.setUTCMonth(month);
1273
- this._trigger('changeMonth', this.viewDate);
1274
- if (this.o.minViewMode === 1){
1275
- this._setDate(UTCDate(year, month, day));
1276
- this.showMode();
1277
- } else {
1278
- this.showMode(-1);
1279
- }
1280
- this.fill();
1281
- }
1282
-
1283
- // Clicked on a year
1284
- if (target.hasClass('year')
1191
+ // Clicked on a month, year, decade, century
1192
+ if (target.hasClass('month')
1193
+ || target.hasClass('year')
1285
1194
  || target.hasClass('decade')
1286
1195
  || target.hasClass('century')) {
1287
1196
  this.viewDate.setUTCDate(1);
1288
1197
 
1289
1198
  day = 1;
1290
- month = 0;
1291
- year = parseInt(target.text(), 10)||0;
1292
- this.viewDate.setUTCFullYear(year);
1293
-
1294
- if (target.hasClass('year')){
1295
- this._trigger('changeYear', this.viewDate);
1296
- if (this.o.minViewMode === 2){
1297
- this._setDate(UTCDate(year, month, day));
1298
- }
1299
- }
1300
- if (target.hasClass('decade')){
1301
- this._trigger('changeDecade', this.viewDate);
1302
- if (this.o.minViewMode === 3){
1303
- this._setDate(UTCDate(year, month, day));
1304
- }
1305
- }
1306
- if (target.hasClass('century')){
1307
- this._trigger('changeCentury', this.viewDate);
1308
- if (this.o.minViewMode === 4){
1309
- this._setDate(UTCDate(year, month, day));
1310
- }
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);
1311
1207
  }
1312
1208
 
1313
- this.showMode(-1);
1314
- this.fill();
1209
+ this._trigger(DPGlobal.viewModes[this.viewMode - 1].e, this.viewDate);
1210
+
1211
+ if (this.viewMode === this.o.minViewMode){
1212
+ this._setDate(UTCDate(year, month, day));
1213
+ } else {
1214
+ this.setViewMode(this.viewMode - 1);
1215
+ this.fill();
1216
+ }
1315
1217
  }
1316
1218
  }
1317
1219
 
1318
1220
  if (this.picker.is(':visible') && this._focused_from){
1319
- $(this._focused_from).focus();
1221
+ this._focused_from.focus();
1320
1222
  }
1321
1223
  delete this._focused_from;
1322
1224
  },
1323
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
+
1324
1255
  _toggle_multidate: function(date){
1325
1256
  var ix = this.dates.contains(date);
1326
1257
  if (!date){
@@ -1347,7 +1278,7 @@
1347
1278
  _setDate: function(date, which){
1348
1279
  if (!which || which === 'date')
1349
1280
  this._toggle_multidate(date && new Date(date));
1350
- if (!which || which === 'view')
1281
+ if ((!which && this.o.updateViewDate) || which === 'view')
1351
1282
  this.viewDate = date && new Date(date);
1352
1283
 
1353
1284
  this.fill();
@@ -1355,16 +1286,7 @@
1355
1286
  if (!which || which !== 'view') {
1356
1287
  this._trigger('changeDate');
1357
1288
  }
1358
- var element;
1359
- if (this.isInput){
1360
- element = this.element;
1361
- }
1362
- else if (this.component){
1363
- element = this.element.find('input');
1364
- }
1365
- if (element){
1366
- element.change();
1367
- }
1289
+ this.inputField.trigger('change');
1368
1290
  if (this.o.autoclose && (!which || which === 'date')){
1369
1291
  this.hide();
1370
1292
  }
@@ -1407,8 +1329,7 @@
1407
1329
  new_month = month + dir;
1408
1330
  new_date.setUTCMonth(new_month);
1409
1331
  // Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11
1410
- if (new_month < 0 || new_month > 11)
1411
- new_month = (new_month + 12) % 12;
1332
+ new_month = (new_month + 12) % 12;
1412
1333
  }
1413
1334
  else {
1414
1335
  // For magnitudes >1, move one month at a time...
@@ -1502,17 +1423,14 @@
1502
1423
 
1503
1424
  if (newViewDate)
1504
1425
  this._trigger('changeYear', this.viewDate);
1505
- }
1506
- else if (e.shiftKey){
1426
+ } else if (e.shiftKey){
1507
1427
  newViewDate = this.moveAvailableDate(focusDate, dir, 'moveMonth');
1508
1428
 
1509
1429
  if (newViewDate)
1510
1430
  this._trigger('changeMonth', this.viewDate);
1511
- }
1512
- else if (e.keyCode === 37 || e.keyCode === 39){
1431
+ } else if (e.keyCode === 37 || e.keyCode === 39){
1513
1432
  newViewDate = this.moveAvailableDate(focusDate, dir, 'moveDay');
1514
- }
1515
- else if (!this.weekOfDateIsDisabled(focusDate)){
1433
+ } else if (!this.weekOfDateIsDisabled(focusDate)){
1516
1434
  newViewDate = this.moveAvailableDate(focusDate, dir, 'moveWeek');
1517
1435
  }
1518
1436
  } else if (this.viewMode === 1) {
@@ -1564,45 +1482,38 @@
1564
1482
  this._trigger('changeDate');
1565
1483
  else
1566
1484
  this._trigger('clearDate');
1567
- var element;
1568
- if (this.isInput){
1569
- element = this.element;
1570
- }
1571
- else if (this.component){
1572
- element = this.element.find('input');
1573
- }
1574
- if (element){
1575
- element.change();
1576
- }
1485
+ this.inputField.trigger('change');
1577
1486
  }
1578
1487
  },
1579
1488
 
1580
- showMode: function(dir){
1581
- if (dir){
1582
- this.viewMode = Math.max(this.o.minViewMode, Math.min(this.o.maxViewMode, this.viewMode + dir));
1583
- }
1489
+ setViewMode: function(viewMode){
1490
+ this.viewMode = viewMode;
1584
1491
  this.picker
1585
1492
  .children('div')
1586
1493
  .hide()
1587
- .filter('.datepicker-' + DPGlobal.modes[this.viewMode].clsName)
1494
+ .filter('.datepicker-' + DPGlobal.viewModes[this.viewMode].clsName)
1588
1495
  .show();
1589
1496
  this.updateNavArrows();
1497
+ this._trigger('changeViewMode', new Date(this.viewDate));
1590
1498
  }
1591
1499
  };
1592
1500
 
1593
1501
  var DateRangePicker = function(element, options){
1594
- $(element).data('datepicker', this);
1502
+ $.data(element, 'datepicker', this);
1595
1503
  this.element = $(element);
1596
1504
  this.inputs = $.map(options.inputs, function(i){
1597
1505
  return i.jquery ? i[0] : i;
1598
1506
  });
1599
1507
  delete options.inputs;
1600
1508
 
1509
+ this.keepEmptyValues = options.keepEmptyValues;
1510
+ delete options.keepEmptyValues;
1511
+
1601
1512
  datepickerPlugin.call($(this.inputs), options)
1602
1513
  .on('changeDate', $.proxy(this.dateUpdated, this));
1603
1514
 
1604
1515
  this.pickers = $.map(this.inputs, function(i){
1605
- return $(i).data('datepicker');
1516
+ return $.data(i, 'datepicker');
1606
1517
  });
1607
1518
  this.updateDates();
1608
1519
  };
@@ -1629,13 +1540,14 @@
1629
1540
  return;
1630
1541
  this.updating = true;
1631
1542
 
1632
- var dp = $(e.target).data('datepicker');
1543
+ var dp = $.data(e.target, 'datepicker');
1633
1544
 
1634
- if (typeof(dp) === "undefined") {
1545
+ if (dp === undefined) {
1635
1546
  return;
1636
1547
  }
1637
1548
 
1638
1549
  var new_date = dp.getUTCDate(),
1550
+ keep_empty_values = this.keepEmptyValues,
1639
1551
  i = $.inArray(e.target, this.inputs),
1640
1552
  j = i - 1,
1641
1553
  k = i + 1,
@@ -1644,7 +1556,7 @@
1644
1556
  return;
1645
1557
 
1646
1558
  $.each(this.pickers, function(i, p){
1647
- if (!p.getUTCDate())
1559
+ if (!p.getUTCDate() && (p === dp || !keep_empty_values))
1648
1560
  p.setUTCDate(new_date);
1649
1561
  });
1650
1562
 
@@ -1653,8 +1565,7 @@
1653
1565
  while (j >= 0 && new_date < this.dates[j]){
1654
1566
  this.pickers[j--].setUTCDate(new_date);
1655
1567
  }
1656
- }
1657
- else if (new_date > this.dates[k]){
1568
+ } else if (new_date > this.dates[k]){
1658
1569
  // Date being moved later/right
1659
1570
  while (k < l && new_date > this.dates[k]){
1660
1571
  this.pickers[k++].setUTCDate(new_date);
@@ -1664,10 +1575,12 @@
1664
1575
 
1665
1576
  delete this.updating;
1666
1577
  },
1667
- remove: function(){
1668
- $.map(this.pickers, function(p){ p.remove(); });
1578
+ destroy: function(){
1579
+ $.map(this.pickers, function(p){ p.destroy(); });
1580
+ $(this.inputs).off('changeDate', this.dateUpdated);
1669
1581
  delete this.element.data().datepicker;
1670
- }
1582
+ },
1583
+ remove: alias('destroy', 'Method `remove` is deprecated and will be removed in version 2.0. Use `destroy` instead')
1671
1584
  };
1672
1585
 
1673
1586
  function opts_from_el(el, prefix){
@@ -1768,6 +1681,7 @@
1768
1681
  endDate: Infinity,
1769
1682
  forceParse: true,
1770
1683
  format: 'mm/dd/yyyy',
1684
+ keepEmptyValues: false,
1771
1685
  keyboardNavigation: true,
1772
1686
  language: 'en',
1773
1687
  minViewMode: 0,
@@ -1780,6 +1694,7 @@
1780
1694
  startView: 0,
1781
1695
  todayBtn: false,
1782
1696
  todayHighlight: false,
1697
+ updateViewDate: true,
1783
1698
  weekStart: 0,
1784
1699
  disableTouchKeyboard: false,
1785
1700
  enableOnReadonly: true,
@@ -1789,9 +1704,10 @@
1789
1704
  immediateUpdates: false,
1790
1705
  title: '',
1791
1706
  templates: {
1792
- leftArrow: '&laquo;',
1793
- rightArrow: '&raquo;'
1794
- }
1707
+ leftArrow: '&#x00AB;',
1708
+ rightArrow: '&#x00BB;'
1709
+ },
1710
+ showWeekDays: true
1795
1711
  };
1796
1712
  var locale_opts = $.fn.datepicker.locale_opts = [
1797
1713
  'format',
@@ -1813,38 +1729,37 @@
1813
1729
  };
1814
1730
 
1815
1731
  var DPGlobal = {
1816
- modes: [
1732
+ viewModes: [
1817
1733
  {
1734
+ names: ['days', 'month'],
1818
1735
  clsName: 'days',
1819
- navFnc: 'Month',
1820
- navStep: 1
1736
+ e: 'changeMonth'
1821
1737
  },
1822
1738
  {
1739
+ names: ['months', 'year'],
1823
1740
  clsName: 'months',
1824
- navFnc: 'FullYear',
1741
+ e: 'changeYear',
1825
1742
  navStep: 1
1826
1743
  },
1827
1744
  {
1745
+ names: ['years', 'decade'],
1828
1746
  clsName: 'years',
1829
- navFnc: 'FullYear',
1747
+ e: 'changeDecade',
1830
1748
  navStep: 10
1831
1749
  },
1832
1750
  {
1751
+ names: ['decades', 'century'],
1833
1752
  clsName: 'decades',
1834
- navFnc: 'FullDecade',
1753
+ e: 'changeCentury',
1835
1754
  navStep: 100
1836
1755
  },
1837
1756
  {
1757
+ names: ['centuries', 'millennium'],
1838
1758
  clsName: 'centuries',
1839
- navFnc: 'FullCentury',
1759
+ e: 'changeMillennium',
1840
1760
  navStep: 1000
1841
- }],
1842
- isLeapYear: function(year){
1843
- return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0));
1844
- },
1845
- getDaysInMonth: function(year, month){
1846
- return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
1847
- },
1761
+ }
1762
+ ],
1848
1763
  validParts: /dd?|DD?|mm?|MM?|yy(?:yy)?/g,
1849
1764
  nonpunctuation: /[^ -\/:-@\u5e74\u6708\u65e5\[-`{-~\t\n\r]+/g,
1850
1765
  parseFormat: function(format){
@@ -1867,10 +1782,8 @@
1867
1782
  if (typeof format === 'string')
1868
1783
  format = DPGlobal.parseFormat(format);
1869
1784
  if (format.toValue)
1870
- return format.toValue(date, format, language);
1871
- var part_re = /([\-+]\d+)([dmwy])/,
1872
- parts = date.match(/([\-+]\d+)([dmwy])/g),
1873
- fn_map = {
1785
+ return format.toValue(date, format, language);
1786
+ var fn_map = {
1874
1787
  d: 'moveDay',
1875
1788
  m: 'moveMonth',
1876
1789
  w: 'moveWeek',
@@ -1881,37 +1794,23 @@
1881
1794
  today: '+0d',
1882
1795
  tomorrow: '+1d'
1883
1796
  },
1884
- part, dir, i, fn;
1885
- if (/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/.test(date)){
1797
+ parts, part, dir, i, fn;
1798
+ if (date in dateAliases){
1799
+ date = dateAliases[date];
1800
+ }
1801
+ if (/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/i.test(date)){
1802
+ parts = date.match(/([\-+]\d+)([dmwy])/gi);
1886
1803
  date = new Date();
1887
1804
  for (i=0; i < parts.length; i++){
1888
- part = part_re.exec(parts[i]);
1889
- dir = parseInt(part[1]);
1890
- fn = fn_map[part[2]];
1805
+ part = parts[i].match(/([\-+]\d+)([dmwy])/i);
1806
+ dir = Number(part[1]);
1807
+ fn = fn_map[part[2].toLowerCase()];
1891
1808
  date = Datepicker.prototype[fn](date, dir);
1892
1809
  }
1893
- return UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate());
1894
- }
1895
-
1896
- if (typeof dateAliases[date] !== 'undefined') {
1897
- date = dateAliases[date];
1898
- parts = date.match(/([\-+]\d+)([dmwy])/g);
1899
-
1900
- if (/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/.test(date)){
1901
- date = new Date();
1902
- for (i=0; i < parts.length; i++){
1903
- part = part_re.exec(parts[i]);
1904
- dir = parseInt(part[1]);
1905
- fn = fn_map[part[2]];
1906
- date = Datepicker.prototype[fn](date, dir);
1907
- }
1908
-
1909
- return UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate());
1910
- }
1810
+ return Datepicker.prototype._zero_utc_time(date);
1911
1811
  }
1912
1812
 
1913
1813
  parts = date && date.match(this.nonpunctuation) || [];
1914
- date = new Date();
1915
1814
 
1916
1815
  function applyNearbyYear(year, threshold){
1917
1816
  if (threshold === true)
@@ -1935,9 +1834,6 @@
1935
1834
  yyyy: function(d,v){
1936
1835
  return d.setUTCFullYear(assumeNearby ? applyNearbyYear(v, assumeNearby) : v);
1937
1836
  },
1938
- yy: function(d,v){
1939
- return d.setUTCFullYear(assumeNearby ? applyNearbyYear(v, assumeNearby) : v);
1940
- },
1941
1837
  m: function(d,v){
1942
1838
  if (isNaN(d))
1943
1839
  return d;
@@ -1954,6 +1850,7 @@
1954
1850
  }
1955
1851
  },
1956
1852
  val, filtered;
1853
+ setters_map['yy'] = setters_map['yyyy'];
1957
1854
  setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m'];
1958
1855
  setters_map['dd'] = setters_map['d'];
1959
1856
  date = UTCToday();
@@ -2035,9 +1932,9 @@
2035
1932
  '<th colspan="7" class="datepicker-title"></th>'+
2036
1933
  '</tr>'+
2037
1934
  '<tr>'+
2038
- '<th class="prev">&laquo;</th>'+
1935
+ '<th class="prev">'+defaults.templates.leftArrow+'</th>'+
2039
1936
  '<th colspan="5" class="datepicker-switch"></th>'+
2040
- '<th class="next">&raquo;</th>'+
1937
+ '<th class="next">'+defaults.templates.rightArrow+'</th>'+
2041
1938
  '</tr>'+
2042
1939
  '</thead>',
2043
1940
  contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>',
@@ -2052,7 +1949,7 @@
2052
1949
  };
2053
1950
  DPGlobal.template = '<div class="datepicker">'+
2054
1951
  '<div class="datepicker-days">'+
2055
- '<table class=" table-condensed">'+
1952
+ '<table class="table-condensed">'+
2056
1953
  DPGlobal.headTemplate+
2057
1954
  '<tbody></tbody>'+
2058
1955
  DPGlobal.footTemplate+
@@ -2101,7 +1998,15 @@
2101
1998
 
2102
1999
  /* DATEPICKER VERSION
2103
2000
  * =================== */
2104
- $.fn.datepicker.version = '1.6.0';
2001
+ $.fn.datepicker.version = '1.7.1';
2002
+
2003
+ $.fn.datepicker.deprecated = function(msg){
2004
+ var console = window.console;
2005
+ if (console && console.warn) {
2006
+ console.warn('DEPRECATED: ' + msg);
2007
+ }
2008
+ };
2009
+
2105
2010
 
2106
2011
  /* DATEPICKER DATA-API
2107
2012
  * ================== */