date_picker 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/lib/date_picker/form_tag_helper.rb +6 -1
  3. data/lib/date_picker/styles/bootstrap.rb +2 -2
  4. data/lib/date_picker/version.rb +1 -1
  5. data/test/dummy/app/models/event.rb +7 -0
  6. data/test/dummy/bower.json +0 -1
  7. data/test/dummy/config/application.rb +2 -1
  8. data/test/dummy/db/development.sqlite3 +0 -0
  9. data/test/dummy/log/development.log +560 -0
  10. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/-OQAivyOU9P9ZAQ_y2trK_-N68_KZTTs-DggI7rEtV0.cache +2 -0
  11. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/2ANZSFEU9Y8883vrveeHrMkljTbZDFZjWodiOw-4_Mc.cache +2 -0
  12. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/2ue6fqDvMQFxbulk_l8s1sfDI8JjKBcOeZPftypE6Pc.cache +1 -0
  13. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/38E_4_y76yBlQpE8HJjOah6zDJCC-wqH4mcQaK0UL9c.cache +1 -0
  14. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/555Va3PB92_a2AQmwxFqDpppNN98rCJfaTXNrtIvQlY.cache +0 -0
  15. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/58Va14-8g080EO7U8YxBrWxWH0Qr8gn3BLdPS-zKsuk.cache +0 -0
  16. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/66sWxMCCzRVWUujKumZwet2XyEhSst8zigZDeKxtz7k.cache +1 -0
  17. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/6c8RqN_iKGxrlpU9kmE4piMTyi6YveDs403lDEvCZEI.cache +0 -0
  18. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/7uHMi2DhIqL4sozu3L9KdTIh4qRh4kDwTw8wIo2k9us.cache +0 -0
  19. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/A9UKKgpcQS_bV-aMc8rD1Qu8hPTSpihdwdy-ejQb0mA.cache +1 -0
  20. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/Aclgag9GTw3jn13itmrL8vGzg189879Cdb1CxBM8YXg.cache +2 -0
  21. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/AzapYGohYHvX-jGdH6tgXcVgeKqRJ9dJ9pvMvuYpNMo.cache +0 -0
  22. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/B5lIcQ9vf5wgTus70iuvWxkAE_xESV27FLK_iDtI0EY.cache +1 -0
  23. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/BqHQMAB-ELafPl_sMF5n9fy9J9ZNOMc5DOqf8_tL-OQ.cache +0 -0
  24. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/F4upoYy8YAs33dZYFwekywdF6bmiPbQZPwIk2ArDTXE.cache +0 -0
  25. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/JMJFOO2mH2xI-0hAy-EeYA23aHL1S4-icXLuzYrodzc.cache +0 -0
  26. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/JetsuzQv5yb-T0l2WvKI3GvbQ_nDU0ECMYnfRliFnno.cache +1 -0
  27. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/K0-51T1-fiBjKvLPRPmIVnr2IcC6uTZ2qlg4zXUzm20.cache +0 -0
  28. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/KlxUfYmC26KA405DB037sh4a34cPerHlhTqiPUphgQ0.cache +2 -0
  29. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/LHGKiqiXX4pIWAWw0cCT3qjAfEvhqHZXmCX_7Nz1OCM.cache +0 -0
  30. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/LmUmswBXcM1QeLiJ2p2G9gNRj39Cl_rJ7ozkvtiab4I.cache +1 -0
  31. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/MXIq1eBOfj1ueMAr8iJUuiPw5HBe9WFMxE0Oi_bQ8Yg.cache +1 -0
  32. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/N5AQcrKLar_U5rSRr0DAtN8_a9YMaZJT-hU6qw-lTAw.cache +9 -0
  33. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/NSXZAot11kWgUqAWk28pHk3Wk0HJu27z4eYUbkZuqa0.cache +0 -0
  34. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/NXcLQLxrGRQoxi2WB4es6tt4iPz2E06Dj7gEXSj5zkQ.cache +1 -0
  35. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/OELa8fL_6NiJFnO0qYfrT-FIojPLG8gS3TZtocTkHZc.cache +0 -0
  36. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/OWyC9BF-hDFFyj0SikiKkaX_39O4TvVsT3QxmdjtK-0.cache +2 -0
  37. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/QTXtB-rs9ebieZrqsw98wERUd5h9W7HvjMq8PGAGoxA.cache +0 -0
  38. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/QdZ0Ei6ZlU9XbmrTWqH1ooq60iXZh7XQ4vaTe01xz5I.cache +1 -0
  39. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/SUmt0T4xyK4cJt4FK6hLg1DVCEfL1oBFbpR_Fn8LFb4.cache +0 -0
  40. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/Sf579fo1XrM5H_gkUQC8Q5sJeXbGcz38F9wO78RwCjQ.cache +1 -0
  41. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/WUgBJoBGEucS48X8sj4JFo_l7MQRgLr3ZHeY1EY8iOY.cache +0 -0
  42. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/WyEseCj1JAct7Zy1iS4fTBqDwEHnAFYXoobmpq4NU4Y.cache +0 -0
  43. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/XkWj0epqQjwcDQkUhpPEz9Ws-W5NjhmrcvutlMBmHS8.cache +1 -0
  44. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/YAOvP7ZFCuCxaRQHkCrW5logCs-229Fyj9xDcW53aWA.cache +2 -0
  45. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/YVP4hjoeo9cOxkA-So_iF85TP_hajWWmr4381I3bhvo.cache +0 -0
  46. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/YwMkInig25fMRiXbu4BMLn9839e0KsnGMPjdn_UHowc.cache +0 -0
  47. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/ZSqknXg6zfmOsfnNU_VBlVZpVdYqxcWJ4iRtcH2bUXA.cache +1 -0
  48. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/_-dZnwSCjdWeA_hXdtRWU5Pem1vxMOpDEVJKYTincTs.cache +0 -0
  49. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/aOYS3w0KCfX6uoINv4VE1fD7iwwKxMjH12073qKxbGY.cache +1 -0
  50. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/bRnLCEIiUFbWSQW7D5OOeIv_MdP73gGzfZV2rMs0rt4.cache +0 -0
  51. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/bss5BE7NeR_7AJVJ1J87vPj-gBXbcmSKSjZc9ruG3aY.cache +0 -0
  52. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/bui4vYOiOA_Xv3iHJUOI6M2Asla4_CfTUwvH8EP0ALQ.cache +2 -0
  53. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/cY96L-sEcUMqUsjeCOIRE5eZ-912i_ftgvvugaPCcZ4.cache +0 -0
  54. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/deAn4dZCHtEdTP1ffOcaA1jCNfkmkSizVKOD421MFbM.cache +0 -0
  55. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/h0p5bxXYrn5lWZ_jaG5xzx5H_JWGcpOE-AqpcQ1yqaA.cache +2 -0
  56. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/hcn-zg5FtPDGrWaj2CHNLt-Mt7Nb0AFKBWM3T7NCh3o.cache +0 -0
  57. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/hodd-s_Rz80YNWqb_ziDSgKRK3ov2d3vqWlF-PLY6vk.cache +0 -0
  58. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/jHdCk5kG0rOdll4zcjjPd0pPGU9PzUBE2MfLU83G8QU.cache +9 -0
  59. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/jafUaM18fOh5BfsBbH2zLPvXuHZqo89o72OD7MuqgwA.cache +1 -0
  60. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/kSNzc3dJCBL5eUTJXtSzMHAmYf5YShtOyZ5wDGja9-w.cache +0 -0
  61. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/kYtB6gWmJ9wG5dj9L6r3vfOldAtcIO5kgZ09DAWf2gg.cache +2 -0
  62. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/nLlJmM1IJrQP1NYweF8MBUn3V5zj5QpCq4c7lnii_gU.cache +1 -0
  63. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/ppnKh8HHcBF-WYFo8P3ZMgrVUoT48OihA9pRcdnSUJ4.cache +0 -0
  64. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/q7jAL_JEbPHXEtzTVG46_HiU6LeX1cTqLs4zyVkOBhw.cache +0 -0
  65. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/r0hTIia-ZeuKklUR5a9zlc0z_o6Z4__a4fG7WNLUd4U.cache +0 -0
  66. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/r7WA4ETigY4fGAmUQ8PSPHqtCXooDqOidNtjsWTbP4E.cache +1 -0
  67. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/t7d1xK96yF7Qk1_XrkFpkeQY3MieEHdNsohdRO2cZSI.cache +0 -0
  68. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/tBOQQXF_7FhywD-fijv2QCflxLm4xcMy9EOBVHMoXlI.cache +0 -0
  69. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/tLiIOUHwpYwWc8zthL_sI_78QZJvS5eDNTa4uRt6Gic.cache +2 -0
  70. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/ugfJlMXXQWf2uapF0DqywRxrQSvbmAkOD6pttYDbWBI.cache +0 -0
  71. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/v4xqfjzrUzZW5a6FzNYiez0yDf75GgHq1jr-pBhqedo.cache +1 -0
  72. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/vP9vcm3n4AlQADvK2eFkPmgM4BIrrGugd1FjDp09HOI.cache +1 -0
  73. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/vu4iDwUcLG80tLkdb6wYP9qryIQR-3AQJGEcDugALV8.cache +1 -0
  74. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/w4SAbXtkx1wTaR9hFnRex0F5fpypGeDnsp8cGP7ByCM.cache +0 -0
  75. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/wkgELuOuckRcA4pZ90TJBfB85KQpciJrtO6aDSUY2rU.cache +0 -0
  76. data/test/dummy/tmp/cache/assets/development/sprockets/v3.0/xlacmyhLXW_PnX4fE3jc2qkszqeYtkHNN1o22-s_xLs.cache +1 -0
  77. data/test/dummy/vendor/assets/components/eonasdan-bootstrap-datetimepicker/CONTRIBUTING.md +5 -0
  78. data/test/dummy/vendor/assets/components/eonasdan-bootstrap-datetimepicker/README.md +11 -6
  79. data/test/dummy/vendor/assets/components/eonasdan-bootstrap-datetimepicker/bower.json +3 -6
  80. data/test/dummy/vendor/assets/components/eonasdan-bootstrap-datetimepicker/build/css/bootstrap-datetimepicker.css +7 -1
  81. data/test/dummy/vendor/assets/components/eonasdan-bootstrap-datetimepicker/build/css/bootstrap-datetimepicker.min.css +7 -1
  82. data/test/dummy/vendor/assets/components/eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min.js +4 -2
  83. data/test/dummy/vendor/assets/components/eonasdan-bootstrap-datetimepicker/component.json +3 -3
  84. data/test/dummy/vendor/assets/components/eonasdan-bootstrap-datetimepicker/composer.json +2 -5
  85. data/test/dummy/vendor/assets/components/eonasdan-bootstrap-datetimepicker/package.json +9 -1
  86. data/test/dummy/vendor/assets/components/eonasdan-bootstrap-datetimepicker/src/js/bootstrap-datetimepicker.js +440 -64
  87. data/test/dummy/vendor/assets/components/eonasdan-bootstrap-datetimepicker/src/less/_bootstrap-datetimepicker.less +9 -1
  88. data/test/dummy/vendor/assets/components/eonasdan-bootstrap-datetimepicker/src/less/bootstrap-datetimepicker-build.less +3 -3
  89. data/test/dummy/vendor/assets/components/eonasdan-bootstrap-datetimepicker/src/nuget/Bootstrap.v3.Datetimepicker.CSS.nuspec +2 -2
  90. data/test/dummy/vendor/assets/components/eonasdan-bootstrap-datetimepicker/src/nuget/Bootstrap.v3.Datetimepicker.nuspec +1 -1
  91. data/test/dummy/vendor/assets/components/eonasdan-bootstrap-datetimepicker/src/sass/_bootstrap-datetimepicker.scss +343 -0
  92. data/test/dummy/vendor/assets/components/eonasdan-bootstrap-datetimepicker/src/sass/bootstrap-datetimepicker-build.scss +16 -0
  93. metadata +140 -16
@@ -1,4 +1,4 @@
1
- /*! version : 4.7.14
1
+ /*! version : 4.13.28
2
2
  =========================================================
3
3
  bootstrap-datetimejs
4
4
  https://github.com/Eonasdan/bootstrap-datetimepicker
@@ -84,9 +84,14 @@
84
84
  clsName: 'years',
85
85
  navFnc: 'y',
86
86
  navStep: 10
87
+ },
88
+ {
89
+ clsName: 'decades',
90
+ navFnc: 'y',
91
+ navStep: 100
87
92
  }
88
93
  ],
89
- viewModes = ['days', 'months', 'years'],
94
+ viewModes = ['days', 'months', 'years', 'decades'],
90
95
  verticalModes = ['top', 'bottom', 'auto'],
91
96
  horizontalModes = ['left', 'right', 'auto'],
92
97
  toolbarPlacements = ['default', 'top', 'bottom'],
@@ -149,7 +154,6 @@
149
154
  return false;
150
155
  }
151
156
  },
152
-
153
157
  hasTime = function () {
154
158
  return (isEnabled('h') || isEnabled('m') || isEnabled('s'));
155
159
  },
@@ -186,6 +190,11 @@
186
190
  .append(contTemplate.clone())
187
191
  ),
188
192
  $('<div>').addClass('datepicker-years')
193
+ .append($('<table>').addClass('table-condensed')
194
+ .append(headTemplate.clone())
195
+ .append(contTemplate.clone())
196
+ ),
197
+ $('<div>').addClass('datepicker-decades')
189
198
  .append($('<table>').addClass('table-condensed')
190
199
  .append(headTemplate.clone())
191
200
  .append(contTemplate.clone())
@@ -200,12 +209,12 @@
200
209
 
201
210
  if (isEnabled('h')) {
202
211
  topRow.append($('<td>')
203
- .append($('<a>').attr({href: '#', tabindex: '-1'}).addClass('btn').attr('data-action', 'incrementHours')
212
+ .append($('<a>').attr({href: '#', tabindex: '-1', 'title':'Increment Hour'}).addClass('btn').attr('data-action', 'incrementHours')
204
213
  .append($('<span>').addClass(options.icons.up))));
205
214
  middleRow.append($('<td>')
206
- .append($('<span>').addClass('timepicker-hour').attr('data-time-component', 'hours').attr('data-action', 'showHours')));
215
+ .append($('<span>').addClass('timepicker-hour').attr({'data-time-component':'hours', 'title':'Pick Hour'}).attr('data-action', 'showHours')));
207
216
  bottomRow.append($('<td>')
208
- .append($('<a>').attr({href: '#', tabindex: '-1'}).addClass('btn').attr('data-action', 'decrementHours')
217
+ .append($('<a>').attr({href: '#', tabindex: '-1', 'title':'Decrement Hour'}).addClass('btn').attr('data-action', 'decrementHours')
209
218
  .append($('<span>').addClass(options.icons.down))));
210
219
  }
211
220
  if (isEnabled('m')) {
@@ -215,12 +224,12 @@
215
224
  bottomRow.append($('<td>').addClass('separator'));
216
225
  }
217
226
  topRow.append($('<td>')
218
- .append($('<a>').attr({href: '#', tabindex: '-1'}).addClass('btn').attr('data-action', 'incrementMinutes')
227
+ .append($('<a>').attr({href: '#', tabindex: '-1', 'title':'Increment Minute'}).addClass('btn').attr('data-action', 'incrementMinutes')
219
228
  .append($('<span>').addClass(options.icons.up))));
220
229
  middleRow.append($('<td>')
221
- .append($('<span>').addClass('timepicker-minute').attr('data-time-component', 'minutes').attr('data-action', 'showMinutes')));
230
+ .append($('<span>').addClass('timepicker-minute').attr({'data-time-component': 'minutes', 'title':'Pick Minute'}).attr('data-action', 'showMinutes')));
222
231
  bottomRow.append($('<td>')
223
- .append($('<a>').attr({href: '#', tabindex: '-1'}).addClass('btn').attr('data-action', 'decrementMinutes')
232
+ .append($('<a>').attr({href: '#', tabindex: '-1', 'title':'Decrement Minute'}).addClass('btn').attr('data-action', 'decrementMinutes')
224
233
  .append($('<span>').addClass(options.icons.down))));
225
234
  }
226
235
  if (isEnabled('s')) {
@@ -230,19 +239,19 @@
230
239
  bottomRow.append($('<td>').addClass('separator'));
231
240
  }
232
241
  topRow.append($('<td>')
233
- .append($('<a>').attr({href: '#', tabindex: '-1'}).addClass('btn').attr('data-action', 'incrementSeconds')
242
+ .append($('<a>').attr({href: '#', tabindex: '-1', 'title':'Increment Second'}).addClass('btn').attr('data-action', 'incrementSeconds')
234
243
  .append($('<span>').addClass(options.icons.up))));
235
244
  middleRow.append($('<td>')
236
- .append($('<span>').addClass('timepicker-second').attr('data-time-component', 'seconds').attr('data-action', 'showSeconds')));
245
+ .append($('<span>').addClass('timepicker-second').attr({'data-time-component': 'seconds', 'title':'Pick Second'}).attr('data-action', 'showSeconds')));
237
246
  bottomRow.append($('<td>')
238
- .append($('<a>').attr({href: '#', tabindex: '-1'}).addClass('btn').attr('data-action', 'decrementSeconds')
247
+ .append($('<a>').attr({href: '#', tabindex: '-1', 'title':'Decrement Second'}).addClass('btn').attr('data-action', 'decrementSeconds')
239
248
  .append($('<span>').addClass(options.icons.down))));
240
249
  }
241
250
 
242
251
  if (!use24Hours) {
243
252
  topRow.append($('<td>').addClass('separator'));
244
253
  middleRow.append($('<td>')
245
- .append($('<button>').addClass('btn btn-primary').attr('data-action', 'togglePeriod')));
254
+ .append($('<button>').addClass('btn btn-primary').attr({'data-action': 'togglePeriod', tabindex: '-1', 'title':'Toggle Period'})));
246
255
  bottomRow.append($('<td>').addClass('separator'));
247
256
  }
248
257
 
@@ -276,16 +285,16 @@
276
285
  getToolbar = function () {
277
286
  var row = [];
278
287
  if (options.showTodayButton) {
279
- row.push($('<td>').append($('<a>').attr('data-action', 'today').append($('<span>').addClass(options.icons.today))));
288
+ row.push($('<td>').append($('<a>').attr({'data-action':'today', 'title':'Go to today'}).append($('<span>').addClass(options.icons.today))));
280
289
  }
281
290
  if (!options.sideBySide && hasDate() && hasTime()) {
282
- row.push($('<td>').append($('<a>').attr('data-action', 'togglePicker').append($('<span>').addClass(options.icons.time))));
291
+ row.push($('<td>').append($('<a>').attr({'data-action':'togglePicker', 'title':'Select Time'}).append($('<span>').addClass(options.icons.time))));
283
292
  }
284
293
  if (options.showClear) {
285
- row.push($('<td>').append($('<a>').attr('data-action', 'clear').append($('<span>').addClass(options.icons.clear))));
294
+ row.push($('<td>').append($('<a>').attr({'data-action':'clear', 'title':'Clear selection'}).append($('<span>').addClass(options.icons.clear))));
286
295
  }
287
296
  if (options.showClose) {
288
- row.push($('<td>').append($('<a>').attr('data-action', 'close').append($('<span>').addClass(options.icons.close))));
297
+ row.push($('<td>').append($('<a>').attr({'data-action':'close', 'title':'Close the picker'}).append($('<span>').addClass(options.icons.close))));
289
298
  }
290
299
  return $('<table>').addClass('table-condensed').append($('<tbody>').append($('<tr>').append(row)));
291
300
  },
@@ -304,6 +313,9 @@
304
313
  if (use24Hours) {
305
314
  template.addClass('usetwentyfour');
306
315
  }
316
+ if (isEnabled('s') && !use24Hours) {
317
+ template.addClass('wider');
318
+ }
307
319
  if (options.sideBySide && hasDate() && hasTime()) {
308
320
  template.addClass('timepicker-sbs');
309
321
  template.append(
@@ -366,7 +378,7 @@
366
378
  if (options.widgetParent) {
367
379
  parent = options.widgetParent.append(widget);
368
380
  } else if (element.is('input')) {
369
- parent = element.parent().append(widget);
381
+ parent = element.after(widget).parent();
370
382
  } else if (options.inline) {
371
383
  parent = element.append(widget);
372
384
  return;
@@ -421,8 +433,8 @@
421
433
  widget.css({
422
434
  top: vertical === 'top' ? 'auto' : position.top + element.outerHeight(),
423
435
  bottom: vertical === 'top' ? position.top + element.outerHeight() : 'auto',
424
- left: horizontal === 'left' ? parent.css('padding-left') : 'auto',
425
- right: horizontal === 'left' ? 'auto' : parent.width() - element.outerWidth()
436
+ left: horizontal === 'left' ? (parent === element ? 0 : position.left) : 'auto',
437
+ right: horizontal === 'left' ? 'auto' : parent.outerWidth() - element.outerWidth() - (parent === element ? 0 : position.left)
426
438
  });
427
439
  },
428
440
 
@@ -433,19 +445,30 @@
433
445
  element.trigger(e);
434
446
  },
435
447
 
448
+ viewUpdate = function (e) {
449
+ if (e === 'y') {
450
+ e = 'YYYY';
451
+ }
452
+ notifyEvent({
453
+ type: 'dp.update',
454
+ change: e,
455
+ viewDate: viewDate.clone()
456
+ });
457
+ },
458
+
436
459
  showMode = function (dir) {
437
460
  if (!widget) {
438
461
  return;
439
462
  }
440
463
  if (dir) {
441
- currentViewMode = Math.max(minViewModeNumber, Math.min(2, currentViewMode + dir));
464
+ currentViewMode = Math.max(minViewModeNumber, Math.min(3, currentViewMode + dir));
442
465
  }
443
466
  widget.find('.datepicker > div').hide().filter('.datepicker-' + datePickerModes[currentViewMode].clsName).show();
444
467
  },
445
468
 
446
469
  fillDow = function () {
447
470
  var row = $('<tr>'),
448
- currentDate = viewDate.clone().startOf('w');
471
+ currentDate = viewDate.clone().startOf('w').startOf('d');
449
472
 
450
473
  if (options.calendarWeeks === true) {
451
474
  row.append($('<th>').addClass('cw').text('#'));
@@ -466,14 +489,22 @@
466
489
  return options.enabledDates[testDate.format('YYYY-MM-DD')] === true;
467
490
  },
468
491
 
492
+ isInDisabledHours = function (testDate) {
493
+ return options.disabledHours[testDate.format('H')] === true;
494
+ },
495
+
496
+ isInEnabledHours = function (testDate) {
497
+ return options.enabledHours[testDate.format('H')] === true;
498
+ },
499
+
469
500
  isValid = function (targetMoment, granularity) {
470
501
  if (!targetMoment.isValid()) {
471
502
  return false;
472
503
  }
473
- if (options.disabledDates && isInDisabledDates(targetMoment) && granularity !== 'M') {
504
+ if (options.disabledDates && granularity !== 'M' && isInDisabledDates(targetMoment)) {
474
505
  return false;
475
506
  }
476
- if (options.enabledDates && !isInEnabledDates(targetMoment) && granularity !== 'M') {
507
+ if (options.enabledDates && granularity !== 'M' && !isInEnabledDates(targetMoment)) {
477
508
  return false;
478
509
  }
479
510
  if (options.minDate && targetMoment.isBefore(options.minDate, granularity)) {
@@ -482,15 +513,33 @@
482
513
  if (options.maxDate && targetMoment.isAfter(options.maxDate, granularity)) {
483
514
  return false;
484
515
  }
485
- if (granularity === 'd' && options.daysOfWeekDisabled.indexOf(targetMoment.day()) !== -1) { //widget && widget.find('.datepicker-days').length > 0
516
+ if (options.daysOfWeekDisabled && granularity === 'd' && options.daysOfWeekDisabled.indexOf(targetMoment.day()) !== -1) {
486
517
  return false;
487
518
  }
519
+ if (options.disabledHours && (granularity === 'h' || granularity === 'm' || granularity === 's') && isInDisabledHours(targetMoment)) {
520
+ return false;
521
+ }
522
+ if (options.enabledHours && (granularity === 'h' || granularity === 'm' || granularity === 's') && !isInEnabledHours(targetMoment)) {
523
+ return false;
524
+ }
525
+ if (options.disabledTimeIntervals && (granularity === 'h' || granularity === 'm' || granularity === 's')) {
526
+ var found = false;
527
+ $.each(options.disabledTimeIntervals, function () {
528
+ if (targetMoment.isBetween(this[0], this[1])) {
529
+ found = true;
530
+ return false;
531
+ }
532
+ });
533
+ if (found) {
534
+ return false;
535
+ }
536
+ }
488
537
  return true;
489
538
  },
490
539
 
491
540
  fillMonths = function () {
492
541
  var spans = [],
493
- monthsShort = viewDate.clone().startOf('y').hour(12); // hour is changed to avoid DST issues in some browsers
542
+ monthsShort = viewDate.clone().startOf('y').startOf('d');
494
543
  while (monthsShort.isSame(viewDate, 'y')) {
495
544
  spans.push($('<span>').attr('data-action', 'selectMonth').addClass('month').text(monthsShort.format('MMM')));
496
545
  monthsShort.add(1, 'M');
@@ -503,6 +552,10 @@
503
552
  monthsViewHeader = monthsView.find('th'),
504
553
  months = monthsView.find('tbody').find('span');
505
554
 
555
+ monthsViewHeader.eq(0).find('span').attr('title', 'Previous Year');
556
+ monthsViewHeader.eq(1).attr('title', 'Select Year');
557
+ monthsViewHeader.eq(2).find('span').attr('title', 'Next Year');
558
+
506
559
  monthsView.find('.disabled').removeClass('disabled');
507
560
 
508
561
  if (!isValid(viewDate.clone().subtract(1, 'y'), 'y')) {
@@ -516,7 +569,7 @@
516
569
  }
517
570
 
518
571
  months.removeClass('active');
519
- if (date.isSame(viewDate, 'y')) {
572
+ if (date.isSame(viewDate, 'y') && !unset) {
520
573
  months.eq(date.month()).addClass('active');
521
574
  }
522
575
 
@@ -534,6 +587,10 @@
534
587
  endYear = viewDate.clone().add(6, 'y'),
535
588
  html = '';
536
589
 
590
+ yearsViewHeader.eq(0).find('span').attr('title', 'Previous Decade');
591
+ yearsViewHeader.eq(1).attr('title', 'Select Decade');
592
+ yearsViewHeader.eq(2).find('span').attr('title', 'Next Decade');
593
+
537
594
  yearsView.find('.disabled').removeClass('disabled');
538
595
 
539
596
  if (options.minDate && options.minDate.isAfter(startYear, 'y')) {
@@ -547,25 +604,62 @@
547
604
  }
548
605
 
549
606
  while (!startYear.isAfter(endYear, 'y')) {
550
- html += '<span data-action="selectYear" class="year' + (startYear.isSame(date, 'y') ? ' active' : '') + (!isValid(startYear, 'y') ? ' disabled' : '') + '">' + startYear.year() + '</span>';
607
+ html += '<span data-action="selectYear" class="year' + (startYear.isSame(date, 'y') && !unset ? ' active' : '') + (!isValid(startYear, 'y') ? ' disabled' : '') + '">' + startYear.year() + '</span>';
551
608
  startYear.add(1, 'y');
552
609
  }
553
610
 
554
611
  yearsView.find('td').html(html);
555
612
  },
556
613
 
614
+ updateDecades = function () {
615
+ var decadesView = widget.find('.datepicker-decades'),
616
+ decadesViewHeader = decadesView.find('th'),
617
+ startDecade = viewDate.isBefore(moment({y: 1999})) ? moment({y: 1899}) : moment({y: 1999}),
618
+ endDecade = startDecade.clone().add(100, 'y'),
619
+ html = '';
620
+
621
+ decadesViewHeader.eq(0).find('span').attr('title', 'Previous Century');
622
+ decadesViewHeader.eq(2).find('span').attr('title', 'Next Century');
623
+
624
+ decadesView.find('.disabled').removeClass('disabled');
625
+
626
+ if (startDecade.isSame(moment({y: 1900})) || (options.minDate && options.minDate.isAfter(startDecade, 'y'))) {
627
+ decadesViewHeader.eq(0).addClass('disabled');
628
+ }
629
+
630
+ decadesViewHeader.eq(1).text(startDecade.year() + '-' + endDecade.year());
631
+
632
+ if (startDecade.isSame(moment({y: 2000})) || (options.maxDate && options.maxDate.isBefore(endDecade, 'y'))) {
633
+ decadesViewHeader.eq(2).addClass('disabled');
634
+ }
635
+
636
+ while (!startDecade.isAfter(endDecade, 'y')) {
637
+ html += '<span data-action="selectDecade" class="decade' + (startDecade.isSame(date, 'y') ? ' active' : '') +
638
+ (!isValid(startDecade, 'y') ? ' disabled' : '') + '" data-selection="' + (startDecade.year() + 6) + '">' + (startDecade.year() + 1) + ' - ' + (startDecade.year() + 12) + '</span>';
639
+ startDecade.add(12, 'y');
640
+ }
641
+ html += '<span></span><span></span><span></span>'; //push the dangling block over, at least this way it's even
642
+
643
+ decadesView.find('td').html(html);
644
+ },
645
+
557
646
  fillDate = function () {
558
647
  var daysView = widget.find('.datepicker-days'),
559
648
  daysViewHeader = daysView.find('th'),
560
649
  currentDate,
561
650
  html = [],
562
651
  row,
563
- clsName;
652
+ clsName,
653
+ i;
564
654
 
565
655
  if (!hasDate()) {
566
656
  return;
567
657
  }
568
658
 
659
+ daysViewHeader.eq(0).find('span').attr('title', 'Previous Month');
660
+ daysViewHeader.eq(1).attr('title', 'Select Month');
661
+ daysViewHeader.eq(2).find('span').attr('title', 'Next Month');
662
+
569
663
  daysView.find('.disabled').removeClass('disabled');
570
664
  daysViewHeader.eq(1).text(viewDate.format(options.dayViewHeaderFormat));
571
665
 
@@ -576,9 +670,9 @@
576
670
  daysViewHeader.eq(2).addClass('disabled');
577
671
  }
578
672
 
579
- currentDate = viewDate.clone().startOf('M').startOf('week');
673
+ currentDate = viewDate.clone().startOf('M').startOf('w').startOf('d');
580
674
 
581
- while (!viewDate.clone().endOf('M').endOf('w').isBefore(currentDate, 'd')) {
675
+ for (i = 0; i < 42; i++) { //always display 42 days (should show 6 weeks)
582
676
  if (currentDate.weekday() === 0) {
583
677
  row = $('<tr>');
584
678
  if (options.calendarWeeks) {
@@ -605,7 +699,7 @@
605
699
  if (currentDate.day() === 0 || currentDate.day() === 6) {
606
700
  clsName += ' weekend';
607
701
  }
608
- row.append('<td data-action="selectDay" class="day' + clsName + '">' + currentDate.date() + '</td>');
702
+ row.append('<td data-action="selectDay" data-day="' + currentDate.format('L') + '" class="day' + clsName + '">' + currentDate.date() + '</td>');
609
703
  currentDate.add(1, 'd');
610
704
  }
611
705
 
@@ -614,6 +708,8 @@
614
708
  updateMonths();
615
709
 
616
710
  updateYears();
711
+
712
+ updateDecades();
617
713
  },
618
714
 
619
715
  fillHours = function () {
@@ -673,9 +769,20 @@
673
769
  },
674
770
 
675
771
  fillTime = function () {
676
- var timeComponents = widget.find('.timepicker span[data-time-component]');
772
+ var toggle, newDate, timeComponents;
773
+ timeComponents = widget.find('.timepicker span[data-time-component]');
774
+
677
775
  if (!use24Hours) {
678
- widget.find('.timepicker [data-action=togglePeriod]').text(date.format('A'));
776
+ toggle = widget.find('.timepicker [data-action=togglePeriod]');
777
+ newDate = date.clone().add((date.hours() >= 12) ? -12 : 12, 'h');
778
+
779
+ toggle.text(date.format('A'));
780
+
781
+ if (isValid(newDate, 'h')) {
782
+ toggle.removeClass('disabled');
783
+ } else {
784
+ toggle.addClass('disabled');
785
+ }
679
786
  }
680
787
  timeComponents.filter('[data-time-component=hours]').text(date.format(use24Hours ? 'HH' : 'hh'));
681
788
  timeComponents.filter('[data-time-component=minutes]').text(date.format('mm'));
@@ -722,8 +829,8 @@
722
829
  viewDate = date.clone();
723
830
  input.val(date.format(actualFormat));
724
831
  element.data('date', date.format(actualFormat));
725
- update();
726
832
  unset = false;
833
+ update();
727
834
  notifyEvent({
728
835
  type: 'dp.change',
729
836
  date: date.clone(),
@@ -741,6 +848,7 @@
741
848
  },
742
849
 
743
850
  hide = function () {
851
+ ///<summary>Hides the widget. Possibly will emit dp.hide</summary>
744
852
  var transitioning = false;
745
853
  if (!widget) {
746
854
  return picker;
@@ -787,13 +895,17 @@
787
895
  ********************************************************************************/
788
896
  actions = {
789
897
  next: function () {
790
- viewDate.add(datePickerModes[currentViewMode].navStep, datePickerModes[currentViewMode].navFnc);
898
+ var navFnc = datePickerModes[currentViewMode].navFnc;
899
+ viewDate.add(datePickerModes[currentViewMode].navStep, navFnc);
791
900
  fillDate();
901
+ viewUpdate(navFnc);
792
902
  },
793
903
 
794
904
  previous: function () {
795
- viewDate.subtract(datePickerModes[currentViewMode].navStep, datePickerModes[currentViewMode].navFnc);
905
+ var navFnc = datePickerModes[currentViewMode].navFnc;
906
+ viewDate.subtract(datePickerModes[currentViewMode].navStep, navFnc);
796
907
  fillDate();
908
+ viewUpdate(navFnc);
797
909
  },
798
910
 
799
911
  pickerSwitch: function () {
@@ -812,6 +924,7 @@
812
924
  showMode(-1);
813
925
  fillDate();
814
926
  }
927
+ viewUpdate('M');
815
928
  },
816
929
 
817
930
  selectYear: function (e) {
@@ -826,6 +939,22 @@
826
939
  showMode(-1);
827
940
  fillDate();
828
941
  }
942
+ viewUpdate('YYYY');
943
+ },
944
+
945
+ selectDecade: function (e) {
946
+ var year = parseInt($(e.target).data('selection'), 10) || 0;
947
+ viewDate.year(year);
948
+ if (currentViewMode === minViewModeNumber) {
949
+ setValue(date.clone().year(viewDate.year()));
950
+ if (!options.inline) {
951
+ hide();
952
+ }
953
+ } else {
954
+ showMode(-1);
955
+ fillDate();
956
+ }
957
+ viewUpdate('YYYY');
829
958
  },
830
959
 
831
960
  selectDay: function (e) {
@@ -843,27 +972,45 @@
843
972
  },
844
973
 
845
974
  incrementHours: function () {
846
- setValue(date.clone().add(1, 'h'));
975
+ var newDate = date.clone().add(1, 'h');
976
+ if (isValid(newDate, 'h')) {
977
+ setValue(newDate);
978
+ }
847
979
  },
848
980
 
849
981
  incrementMinutes: function () {
850
- setValue(date.clone().add(options.stepping, 'm'));
982
+ var newDate = date.clone().add(options.stepping, 'm');
983
+ if (isValid(newDate, 'm')) {
984
+ setValue(newDate);
985
+ }
851
986
  },
852
987
 
853
988
  incrementSeconds: function () {
854
- setValue(date.clone().add(1, 's'));
989
+ var newDate = date.clone().add(1, 's');
990
+ if (isValid(newDate, 's')) {
991
+ setValue(newDate);
992
+ }
855
993
  },
856
994
 
857
995
  decrementHours: function () {
858
- setValue(date.clone().subtract(1, 'h'));
996
+ var newDate = date.clone().subtract(1, 'h');
997
+ if (isValid(newDate, 'h')) {
998
+ setValue(newDate);
999
+ }
859
1000
  },
860
1001
 
861
1002
  decrementMinutes: function () {
862
- setValue(date.clone().subtract(options.stepping, 'm'));
1003
+ var newDate = date.clone().subtract(options.stepping, 'm');
1004
+ if (isValid(newDate, 'm')) {
1005
+ setValue(newDate);
1006
+ }
863
1007
  },
864
1008
 
865
1009
  decrementSeconds: function () {
866
- setValue(date.clone().subtract(1, 's'));
1010
+ var newDate = date.clone().subtract(1, 's');
1011
+ if (isValid(newDate, 's')) {
1012
+ setValue(newDate);
1013
+ }
867
1014
  },
868
1015
 
869
1016
  togglePeriod: function () {
@@ -953,7 +1100,9 @@
953
1100
  clear: clear,
954
1101
 
955
1102
  today: function () {
956
- setValue(moment());
1103
+ if (isValid(moment(), 'd')) {
1104
+ setValue(moment());
1105
+ }
957
1106
  },
958
1107
 
959
1108
  close: hide
@@ -968,6 +1117,7 @@
968
1117
  },
969
1118
 
970
1119
  show = function () {
1120
+ ///<summary>Shows the widget. Possibly will emit dp.show and dp.change</summary>
971
1121
  var currentMoment,
972
1122
  useCurrentGranularity = {
973
1123
  'year': function (m) {
@@ -990,7 +1140,9 @@
990
1140
  if (input.prop('disabled') || (!options.ignoreReadonly && input.prop('readonly')) || widget) {
991
1141
  return picker;
992
1142
  }
993
- if (options.useCurrent && unset && ((input.is('input') && input.val().trim().length === 0) || options.inline)) {
1143
+ if (input.val().trim().length !== 0) {
1144
+ setValue(parseInputDate(input.val().trim()));
1145
+ } else if (options.useCurrent && unset && ((input.is('input') && input.val().trim().length === 0) || options.inline)) {
994
1146
  currentMoment = moment();
995
1147
  if (typeof options.useCurrent === 'string') {
996
1148
  currentMoment = useCurrentGranularity[options.useCurrent](currentMoment);
@@ -1020,7 +1172,7 @@
1020
1172
  widget.show();
1021
1173
  place();
1022
1174
 
1023
- if (!input.is(':focus')) {
1175
+ if (options.focusOnShow && !input.is(':focus')) {
1024
1176
  input.focus();
1025
1177
  }
1026
1178
 
@@ -1031,6 +1183,7 @@
1031
1183
  },
1032
1184
 
1033
1185
  toggle = function () {
1186
+ /// <summary>Shows or hides the widget</summary>
1034
1187
  return (widget ? hide() : show());
1035
1188
  },
1036
1189
 
@@ -1045,16 +1198,6 @@
1045
1198
  },
1046
1199
 
1047
1200
  keydown = function (e) {
1048
- //if (e.keyCode === 27 && widget) { // allow escape to hide picker
1049
- // hide();
1050
- // return false;
1051
- //}
1052
- //if (e.keyCode === 40 && !widget) { // allow down to show picker
1053
- // show();
1054
- // e.preventDefault();
1055
- //}
1056
- //return true;
1057
-
1058
1201
  var handler = null,
1059
1202
  index,
1060
1203
  index2,
@@ -1121,7 +1264,8 @@
1121
1264
  'change': change,
1122
1265
  'blur': options.debug ? '' : hide,
1123
1266
  'keydown': keydown,
1124
- 'keyup': keyup
1267
+ 'keyup': keyup,
1268
+ 'focus': options.allowInputToggle ? show : ''
1125
1269
  });
1126
1270
 
1127
1271
  if (element.is('input')) {
@@ -1139,7 +1283,8 @@
1139
1283
  'change': change,
1140
1284
  'blur': hide,
1141
1285
  'keydown': keydown,
1142
- 'keyup': keyup
1286
+ 'keyup': keyup,
1287
+ 'focus': options.allowInputToggle ? hide : ''
1143
1288
  });
1144
1289
 
1145
1290
  if (element.is('input')) {
@@ -1166,6 +1311,17 @@
1166
1311
  return (Object.keys(givenDatesIndexed).length) ? givenDatesIndexed : false;
1167
1312
  },
1168
1313
 
1314
+ indexGivenHours = function (givenHoursArray) {
1315
+ // Store given enabledHours and disabledHours as keys.
1316
+ // This way we can check their existence in O(1) time instead of looping through whole array.
1317
+ // (for example: options.enabledHours['2014-02-27'] === true)
1318
+ var givenHoursIndexed = {};
1319
+ $.each(givenHoursArray, function () {
1320
+ givenHoursIndexed[this] = true;
1321
+ });
1322
+ return (Object.keys(givenHoursIndexed).length) ? givenHoursIndexed : false;
1323
+ },
1324
+
1169
1325
  initFormatting = function () {
1170
1326
  var format = options.format || 'L LT';
1171
1327
 
@@ -1182,7 +1338,7 @@
1182
1338
  parseFormats.push(actualFormat);
1183
1339
  }
1184
1340
 
1185
- use24Hours = (actualFormat.toLowerCase().indexOf('a') < 1 && actualFormat.indexOf('h') < 1);
1341
+ use24Hours = (actualFormat.toLowerCase().indexOf('a') < 1 && actualFormat.replace(/\[.*?\]/g, '').indexOf('h') < 1);
1186
1342
 
1187
1343
  if (isEnabled('y')) {
1188
1344
  minViewModeNumber = 2;
@@ -1212,6 +1368,7 @@
1212
1368
  *
1213
1369
  ********************************************************************************/
1214
1370
  picker.destroy = function () {
1371
+ ///<summary>Destroys the widget and removes all attached event listeners</summary>
1215
1372
  hide();
1216
1373
  detachDatePickerElementEvents();
1217
1374
  element.removeData('DateTimePicker');
@@ -1225,6 +1382,8 @@
1225
1382
  picker.hide = hide;
1226
1383
 
1227
1384
  picker.disable = function () {
1385
+ ///<summary>Disables the input element, the component is attached to, by adding a disabled="true" attribute to it.
1386
+ ///If the widget was visible before that call it is hidden. Possibly emits dp.hide</summary>
1228
1387
  hide();
1229
1388
  if (component && component.hasClass('btn')) {
1230
1389
  component.addClass('disabled');
@@ -1234,6 +1393,7 @@
1234
1393
  };
1235
1394
 
1236
1395
  picker.enable = function () {
1396
+ ///<summary>Enables the input element, the component is attached to, by removing disabled attribute from it.</summary>
1237
1397
  if (component && component.hasClass('btn')) {
1238
1398
  component.removeClass('disabled');
1239
1399
  }
@@ -1272,6 +1432,14 @@
1272
1432
  };
1273
1433
 
1274
1434
  picker.date = function (newDate) {
1435
+ ///<signature helpKeyword="$.fn.datetimepicker.date">
1436
+ ///<summary>Returns the component's model current date, a moment object or null if not set.</summary>
1437
+ ///<returns type="Moment">date.clone()</returns>
1438
+ ///</signature>
1439
+ ///<signature>
1440
+ ///<summary>Sets the components model current moment to it. Passing a null value unsets the components model current moment. Parsing of the newDate parameter is made using moment library with the options.format and options.useStrict components configuration.</summary>
1441
+ ///<param name="newDate" locid="$.fn.datetimepicker.date_p:newDate">Takes string, Date, moment, null parameter.</param>
1442
+ ///</signature>
1275
1443
  if (arguments.length === 0) {
1276
1444
  if (unset) {
1277
1445
  return null;
@@ -1288,6 +1456,9 @@
1288
1456
  };
1289
1457
 
1290
1458
  picker.format = function (newFormat) {
1459
+ ///<summary>test su</summary>
1460
+ ///<param name="newFormat">info about para</param>
1461
+ ///<returns type="string|boolean">returns foo</returns>
1291
1462
  if (arguments.length === 0) {
1292
1463
  return options.format;
1293
1464
  }
@@ -1333,6 +1504,15 @@
1333
1504
  };
1334
1505
 
1335
1506
  picker.disabledDates = function (dates) {
1507
+ ///<signature helpKeyword="$.fn.datetimepicker.disabledDates">
1508
+ ///<summary>Returns an array with the currently set disabled dates on the component.</summary>
1509
+ ///<returns type="array">options.disabledDates</returns>
1510
+ ///</signature>
1511
+ ///<signature>
1512
+ ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of
1513
+ ///options.enabledDates if such exist.</summary>
1514
+ ///<param name="dates" locid="$.fn.datetimepicker.disabledDates_p:dates">Takes an [ string or Date or moment ] of values and allows the user to select only from those days.</param>
1515
+ ///</signature>
1336
1516
  if (arguments.length === 0) {
1337
1517
  return (options.disabledDates ? $.extend({}, options.disabledDates) : options.disabledDates);
1338
1518
  }
@@ -1352,6 +1532,14 @@
1352
1532
  };
1353
1533
 
1354
1534
  picker.enabledDates = function (dates) {
1535
+ ///<signature helpKeyword="$.fn.datetimepicker.enabledDates">
1536
+ ///<summary>Returns an array with the currently set enabled dates on the component.</summary>
1537
+ ///<returns type="array">options.enabledDates</returns>
1538
+ ///</signature>
1539
+ ///<signature>
1540
+ ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of options.disabledDates if such exist.</summary>
1541
+ ///<param name="dates" locid="$.fn.datetimepicker.enabledDates_p:dates">Takes an [ string or Date or moment ] of values and allows the user to select only from those days.</param>
1542
+ ///</signature>
1355
1543
  if (arguments.length === 0) {
1356
1544
  return (options.enabledDates ? $.extend({}, options.enabledDates) : options.enabledDates);
1357
1545
  }
@@ -1375,6 +1563,12 @@
1375
1563
  return options.daysOfWeekDisabled.splice(0);
1376
1564
  }
1377
1565
 
1566
+ if ((typeof daysOfWeekDisabled === 'boolean') && !daysOfWeekDisabled) {
1567
+ options.daysOfWeekDisabled = false;
1568
+ update();
1569
+ return picker;
1570
+ }
1571
+
1378
1572
  if (!(daysOfWeekDisabled instanceof Array)) {
1379
1573
  throw new TypeError('daysOfWeekDisabled() expects an array parameter');
1380
1574
  }
@@ -1388,6 +1582,17 @@
1388
1582
  }
1389
1583
  return previousValue;
1390
1584
  }, []).sort();
1585
+ if (options.useCurrent && !options.keepInvalid) {
1586
+ var tries = 0;
1587
+ while (!isValid(date, 'd')) {
1588
+ date.add(1, 'd');
1589
+ if (tries === 7) {
1590
+ throw 'Tried 7 times to find a valid date';
1591
+ }
1592
+ tries++;
1593
+ }
1594
+ setValue(date);
1595
+ }
1391
1596
  update();
1392
1597
  return picker;
1393
1598
  };
@@ -1418,7 +1623,7 @@
1418
1623
  throw new TypeError('maxDate() date parameter is before options.minDate: ' + parsedDate.format(actualFormat));
1419
1624
  }
1420
1625
  options.maxDate = parsedDate;
1421
- if (options.maxDate.isBefore(maxDate)) {
1626
+ if (options.useCurrent && !options.keepInvalid && date.isAfter(maxDate)) {
1422
1627
  setValue(options.maxDate);
1423
1628
  }
1424
1629
  if (viewDate.isAfter(parsedDate)) {
@@ -1454,7 +1659,7 @@
1454
1659
  throw new TypeError('minDate() date parameter is after options.maxDate: ' + parsedDate.format(actualFormat));
1455
1660
  }
1456
1661
  options.minDate = parsedDate;
1457
- if (options.minDate.isAfter(minDate)) {
1662
+ if (options.useCurrent && !options.keepInvalid && date.isBefore(minDate)) {
1458
1663
  setValue(options.minDate);
1459
1664
  }
1460
1665
  if (viewDate.isBefore(parsedDate)) {
@@ -1465,6 +1670,14 @@
1465
1670
  };
1466
1671
 
1467
1672
  picker.defaultDate = function (defaultDate) {
1673
+ ///<signature helpKeyword="$.fn.datetimepicker.defaultDate">
1674
+ ///<summary>Returns a moment with the options.defaultDate option configuration or false if not set</summary>
1675
+ ///<returns type="Moment">date.clone()</returns>
1676
+ ///</signature>
1677
+ ///<signature>
1678
+ ///<summary>Will set the picker's inital date. If a boolean:false value is passed the options.defaultDate parameter is cleared.</summary>
1679
+ ///<param name="defaultDate" locid="$.fn.datetimepicker.defaultDate_p:defaultDate">Takes a string, Date, moment, boolean:false</param>
1680
+ ///</signature>
1468
1681
  if (arguments.length === 0) {
1469
1682
  return options.defaultDate ? options.defaultDate.clone() : options.defaultDate;
1470
1683
  }
@@ -1489,7 +1702,7 @@
1489
1702
 
1490
1703
  options.defaultDate = parsedDate;
1491
1704
 
1492
- if (options.defaultDate && input.val().trim() === '' && input.attr('placeholder') === undefined) {
1705
+ if (options.defaultDate && options.inline || (input.val().trim() === '' && input.attr('placeholder') === undefined)) {
1493
1706
  setValue(options.defaultDate);
1494
1707
  }
1495
1708
  return picker;
@@ -1764,6 +1977,19 @@
1764
1977
  return picker;
1765
1978
  };
1766
1979
 
1980
+ picker.focusOnShow = function (focusOnShow) {
1981
+ if (arguments.length === 0) {
1982
+ return options.focusOnShow;
1983
+ }
1984
+
1985
+ if (typeof focusOnShow !== 'boolean') {
1986
+ throw new TypeError('focusOnShow() expects a boolean parameter');
1987
+ }
1988
+
1989
+ options.focusOnShow = focusOnShow;
1990
+ return picker;
1991
+ };
1992
+
1767
1993
  picker.inline = function (inline) {
1768
1994
  if (arguments.length === 0) {
1769
1995
  return options.inline;
@@ -1796,6 +2022,19 @@
1796
2022
  return picker;
1797
2023
  };
1798
2024
 
2025
+ picker.allowInputToggle = function (allowInputToggle) {
2026
+ if (arguments.length === 0) {
2027
+ return options.allowInputToggle;
2028
+ }
2029
+
2030
+ if (typeof allowInputToggle !== 'boolean') {
2031
+ throw new TypeError('allowInputToggle() expects a boolean parameter');
2032
+ }
2033
+
2034
+ options.allowInputToggle = allowInputToggle;
2035
+ return picker;
2036
+ };
2037
+
1799
2038
  picker.showClose = function (showClose) {
1800
2039
  if (arguments.length === 0) {
1801
2040
  return options.showClose;
@@ -1834,6 +2073,137 @@
1834
2073
  return picker;
1835
2074
  };
1836
2075
 
2076
+ picker.disabledTimeIntervals = function (disabledTimeIntervals) {
2077
+ ///<signature helpKeyword="$.fn.datetimepicker.disabledTimeIntervals">
2078
+ ///<summary>Returns an array with the currently set disabled dates on the component.</summary>
2079
+ ///<returns type="array">options.disabledTimeIntervals</returns>
2080
+ ///</signature>
2081
+ ///<signature>
2082
+ ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of
2083
+ ///options.enabledDates if such exist.</summary>
2084
+ ///<param name="dates" locid="$.fn.datetimepicker.disabledTimeIntervals_p:dates">Takes an [ string or Date or moment ] of values and allows the user to select only from those days.</param>
2085
+ ///</signature>
2086
+ if (arguments.length === 0) {
2087
+ return (options.disabledTimeIntervals ? $.extend({}, options.disabledTimeIntervals) : options.disabledTimeIntervals);
2088
+ }
2089
+
2090
+ if (!disabledTimeIntervals) {
2091
+ options.disabledTimeIntervals = false;
2092
+ update();
2093
+ return picker;
2094
+ }
2095
+ if (!(disabledTimeIntervals instanceof Array)) {
2096
+ throw new TypeError('disabledTimeIntervals() expects an array parameter');
2097
+ }
2098
+ options.disabledTimeIntervals = disabledTimeIntervals;
2099
+ update();
2100
+ return picker;
2101
+ };
2102
+
2103
+ picker.disabledHours = function (hours) {
2104
+ ///<signature helpKeyword="$.fn.datetimepicker.disabledHours">
2105
+ ///<summary>Returns an array with the currently set disabled hours on the component.</summary>
2106
+ ///<returns type="array">options.disabledHours</returns>
2107
+ ///</signature>
2108
+ ///<signature>
2109
+ ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of
2110
+ ///options.enabledHours if such exist.</summary>
2111
+ ///<param name="hours" locid="$.fn.datetimepicker.disabledHours_p:hours">Takes an [ int ] of values and disallows the user to select only from those hours.</param>
2112
+ ///</signature>
2113
+ if (arguments.length === 0) {
2114
+ return (options.disabledHours ? $.extend({}, options.disabledHours) : options.disabledHours);
2115
+ }
2116
+
2117
+ if (!hours) {
2118
+ options.disabledHours = false;
2119
+ update();
2120
+ return picker;
2121
+ }
2122
+ if (!(hours instanceof Array)) {
2123
+ throw new TypeError('disabledHours() expects an array parameter');
2124
+ }
2125
+ options.disabledHours = indexGivenHours(hours);
2126
+ options.enabledHours = false;
2127
+ if (options.useCurrent && !options.keepInvalid) {
2128
+ var tries = 0;
2129
+ while (!isValid(date, 'h')) {
2130
+ date.add(1, 'h');
2131
+ if (tries === 24) {
2132
+ throw 'Tried 24 times to find a valid date';
2133
+ }
2134
+ tries++;
2135
+ }
2136
+ setValue(date);
2137
+ }
2138
+ update();
2139
+ return picker;
2140
+ };
2141
+
2142
+ picker.enabledHours = function (hours) {
2143
+ ///<signature helpKeyword="$.fn.datetimepicker.enabledHours">
2144
+ ///<summary>Returns an array with the currently set enabled hours on the component.</summary>
2145
+ ///<returns type="array">options.enabledHours</returns>
2146
+ ///</signature>
2147
+ ///<signature>
2148
+ ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of options.disabledHours if such exist.</summary>
2149
+ ///<param name="hours" locid="$.fn.datetimepicker.enabledHours_p:hours">Takes an [ int ] of values and allows the user to select only from those hours.</param>
2150
+ ///</signature>
2151
+ if (arguments.length === 0) {
2152
+ return (options.enabledHours ? $.extend({}, options.enabledHours) : options.enabledHours);
2153
+ }
2154
+
2155
+ if (!hours) {
2156
+ options.enabledHours = false;
2157
+ update();
2158
+ return picker;
2159
+ }
2160
+ if (!(hours instanceof Array)) {
2161
+ throw new TypeError('enabledHours() expects an array parameter');
2162
+ }
2163
+ options.enabledHours = indexGivenHours(hours);
2164
+ options.disabledHours = false;
2165
+ if (options.useCurrent && !options.keepInvalid) {
2166
+ var tries = 0;
2167
+ while (!isValid(date, 'h')) {
2168
+ date.add(1, 'h');
2169
+ if (tries === 24) {
2170
+ throw 'Tried 24 times to find a valid date';
2171
+ }
2172
+ tries++;
2173
+ }
2174
+ setValue(date);
2175
+ }
2176
+ update();
2177
+ return picker;
2178
+ };
2179
+
2180
+ picker.viewDate = function (newDate) {
2181
+ ///<signature helpKeyword="$.fn.datetimepicker.viewDate">
2182
+ ///<summary>Returns the component's model current viewDate, a moment object or null if not set.</summary>
2183
+ ///<returns type="Moment">viewDate.clone()</returns>
2184
+ ///</signature>
2185
+ ///<signature>
2186
+ ///<summary>Sets the components model current moment to it. Passing a null value unsets the components model current moment. Parsing of the newDate parameter is made using moment library with the options.format and options.useStrict components configuration.</summary>
2187
+ ///<param name="newDate" locid="$.fn.datetimepicker.date_p:newDate">Takes string, viewDate, moment, null parameter.</param>
2188
+ ///</signature>
2189
+ if (arguments.length === 0) {
2190
+ return viewDate.clone();
2191
+ }
2192
+
2193
+ if (!newDate) {
2194
+ viewDate = date.clone();
2195
+ return picker;
2196
+ }
2197
+
2198
+ if (typeof newDate !== 'string' && !moment.isMoment(newDate) && !(newDate instanceof Date)) {
2199
+ throw new TypeError('viewDate() parameter must be one of [string, moment or Date]');
2200
+ }
2201
+
2202
+ viewDate = parseInputDate(newDate);
2203
+ viewUpdate();
2204
+ return picker;
2205
+ };
2206
+
1837
2207
  // initializing element and component attributes
1838
2208
  if (element.is('input')) {
1839
2209
  input = element;
@@ -1925,7 +2295,7 @@
1925
2295
  },
1926
2296
  useStrict: false,
1927
2297
  sideBySide: false,
1928
- daysOfWeekDisabled: [],
2298
+ daysOfWeekDisabled: false,
1929
2299
  calendarWeeks: false,
1930
2300
  viewMode: 'days',
1931
2301
  toolbarPlacement: 'default',
@@ -1939,6 +2309,7 @@
1939
2309
  widgetParent: null,
1940
2310
  ignoreReadonly: false,
1941
2311
  keepOpen: false,
2312
+ focusOnShow: true,
1942
2313
  inline: false,
1943
2314
  keepInvalid: false,
1944
2315
  datepickerInput: '.datepickerinput',
@@ -2046,6 +2417,11 @@
2046
2417
  this.clear();
2047
2418
  }
2048
2419
  },
2049
- debug: false
2420
+ debug: false,
2421
+ allowInputToggle: false,
2422
+ disabledTimeIntervals: false,
2423
+ disabledHours: false,
2424
+ enabledHours: false,
2425
+ viewDate: false
2050
2426
  };
2051
2427
  }));