bootstrap3-datetimepicker-rails 4.0.0 → 4.7.14

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5d6e6ae4f217127f3562db4629ff366c6ef760c4
4
- data.tar.gz: 6f102779311ce6a65c1937ee2c64f64dc6a3ca35
3
+ metadata.gz: 2b9d7d21db6bacf96ec8077966448a038acd6d67
4
+ data.tar.gz: ca7423c5be979aaba72c6efac641388052295500
5
5
  SHA512:
6
- metadata.gz: b64abe901e720c6213d783b01ca4ed3f96edbb27bbb9475e36c7ff4f9351ae2f5d9e8fd54c5e6c24d759f2589210518e5b36e912b75fa0988d351ac466407983
7
- data.tar.gz: eed1390c3116875844a3e41bfdd3c2159ed2739f6138cee7dfca13466f74e3b04dfa395b4188dd2d941ed14971c5bdd92982e33a2b9fc6cca288188304a41ecc
6
+ metadata.gz: 62da4f1e8be61b478151235e2bf1db718403cf4f12a760fedd21dd15fd07a5a9dae016c1cce35400a8d12f04ac429fb029bbe7c096c155ba9b6116225c900c2b
7
+ data.tar.gz: 6918e1b85f676a0a0574cef9ea1361f6a7f647418d61d57e36799d3390124967989872021914dadd10ffe54e2133d6399a9d9bc76a09057c079a5a030925119d
data/README.md CHANGED
@@ -14,7 +14,7 @@ actively maintained and works with [Bootstrap3](http://getbootstrap.com).
14
14
  Add these lines to your application's Gemfile:
15
15
  ```ruby
16
16
  gem 'momentjs-rails', '>= 2.9.0'
17
- gem 'bootstrap3-datetimepicker-rails', '~> 4.0.0'
17
+ gem 'bootstrap3-datetimepicker-rails', '~> 4.7.14'
18
18
  ```
19
19
 
20
20
  And then execute:
@@ -1,5 +1,5 @@
1
1
  module Bootstrap3Datetimepicker
2
2
  module Rails
3
- VERSION = '4.0.0'
3
+ VERSION = '4.7.14'
4
4
  end
5
5
  end
@@ -1,9 +1,11 @@
1
- /*
2
- //! version : 4.0.0
1
+ /*! version : 4.7.14
3
2
  =========================================================
4
3
  bootstrap-datetimejs
5
4
  https://github.com/Eonasdan/bootstrap-datetimepicker
5
+ Copyright (c) 2015 Jonathan Peterson
6
6
  =========================================================
7
+ */
8
+ /*
7
9
  The MIT License (MIT)
8
10
 
9
11
  Copyright (c) 2015 Jonathan Peterson
@@ -26,6 +28,11 @@
26
28
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27
29
  THE SOFTWARE.
28
30
  */
31
+ /*global define:false */
32
+ /*global exports:false */
33
+ /*global require:false */
34
+ /*global jQuery:false */
35
+ /*global moment:false */
29
36
  (function (factory) {
30
37
  'use strict';
31
38
  if (typeof define === 'function' && define.amd) {
@@ -35,10 +42,10 @@
35
42
  factory(require('jquery'), require('moment'));
36
43
  } else {
37
44
  // Neither AMD nor CommonJS used. Use global variables.
38
- if (!jQuery) {
45
+ if (typeof jQuery === 'undefined') {
39
46
  throw 'bootstrap-datetimepicker requires jQuery to be loaded first';
40
47
  }
41
- if (!moment) {
48
+ if (typeof moment === 'undefined') {
42
49
  throw 'bootstrap-datetimepicker requires Moment.js to be loaded first';
43
50
  }
44
51
  factory(jQuery, moment);
@@ -51,7 +58,7 @@
51
58
 
52
59
  var dateTimePicker = function (element, options) {
53
60
  var picker = {},
54
- date = moment(),
61
+ date = moment().startOf('d'),
55
62
  viewDate = date.clone(),
56
63
  unset = true,
57
64
  input,
@@ -83,6 +90,37 @@
83
90
  verticalModes = ['top', 'bottom', 'auto'],
84
91
  horizontalModes = ['left', 'right', 'auto'],
85
92
  toolbarPlacements = ['default', 'top', 'bottom'],
93
+ keyMap = {
94
+ 'up': 38,
95
+ 38: 'up',
96
+ 'down': 40,
97
+ 40: 'down',
98
+ 'left': 37,
99
+ 37: 'left',
100
+ 'right': 39,
101
+ 39: 'right',
102
+ 'tab': 9,
103
+ 9: 'tab',
104
+ 'escape': 27,
105
+ 27: 'escape',
106
+ 'enter': 13,
107
+ 13: 'enter',
108
+ 'pageUp': 33,
109
+ 33: 'pageUp',
110
+ 'pageDown': 34,
111
+ 34: 'pageDown',
112
+ 'shift': 16,
113
+ 16: 'shift',
114
+ 'control': 17,
115
+ 17: 'control',
116
+ 'space': 32,
117
+ 32: 'space',
118
+ 't': 84,
119
+ 84: 't',
120
+ 'delete': 46,
121
+ 46: 'delete'
122
+ },
123
+ keyState = {},
86
124
 
87
125
  /********************************************************************************
88
126
  *
@@ -162,12 +200,12 @@
162
200
 
163
201
  if (isEnabled('h')) {
164
202
  topRow.append($('<td>')
165
- .append($('<a>').attr('href', '#').addClass('btn').attr('data-action', 'incrementHours')
203
+ .append($('<a>').attr({href: '#', tabindex: '-1'}).addClass('btn').attr('data-action', 'incrementHours')
166
204
  .append($('<span>').addClass(options.icons.up))));
167
205
  middleRow.append($('<td>')
168
206
  .append($('<span>').addClass('timepicker-hour').attr('data-time-component', 'hours').attr('data-action', 'showHours')));
169
207
  bottomRow.append($('<td>')
170
- .append($('<a>').attr('href', '#').addClass('btn').attr('data-action', 'decrementHours')
208
+ .append($('<a>').attr({href: '#', tabindex: '-1'}).addClass('btn').attr('data-action', 'decrementHours')
171
209
  .append($('<span>').addClass(options.icons.down))));
172
210
  }
173
211
  if (isEnabled('m')) {
@@ -177,12 +215,12 @@
177
215
  bottomRow.append($('<td>').addClass('separator'));
178
216
  }
179
217
  topRow.append($('<td>')
180
- .append($('<a>').attr('href', '#').addClass('btn').attr('data-action', 'incrementMinutes')
218
+ .append($('<a>').attr({href: '#', tabindex: '-1'}).addClass('btn').attr('data-action', 'incrementMinutes')
181
219
  .append($('<span>').addClass(options.icons.up))));
182
220
  middleRow.append($('<td>')
183
221
  .append($('<span>').addClass('timepicker-minute').attr('data-time-component', 'minutes').attr('data-action', 'showMinutes')));
184
222
  bottomRow.append($('<td>')
185
- .append($('<a>').attr('href', '#').addClass('btn').attr('data-action', 'decrementMinutes')
223
+ .append($('<a>').attr({href: '#', tabindex: '-1'}).addClass('btn').attr('data-action', 'decrementMinutes')
186
224
  .append($('<span>').addClass(options.icons.down))));
187
225
  }
188
226
  if (isEnabled('s')) {
@@ -192,12 +230,12 @@
192
230
  bottomRow.append($('<td>').addClass('separator'));
193
231
  }
194
232
  topRow.append($('<td>')
195
- .append($('<a>').attr('href', '#').addClass('btn').attr('data-action', 'incrementSeconds')
233
+ .append($('<a>').attr({href: '#', tabindex: '-1'}).addClass('btn').attr('data-action', 'incrementSeconds')
196
234
  .append($('<span>').addClass(options.icons.up))));
197
235
  middleRow.append($('<td>')
198
236
  .append($('<span>').addClass('timepicker-second').attr('data-time-component', 'seconds').attr('data-action', 'showSeconds')));
199
237
  bottomRow.append($('<td>')
200
- .append($('<a>').attr('href', '#').addClass('btn').attr('data-action', 'decrementSeconds')
238
+ .append($('<a>').attr({href: '#', tabindex: '-1'}).addClass('btn').attr('data-action', 'decrementSeconds')
201
239
  .append($('<span>').addClass(options.icons.down))));
202
240
  }
203
241
 
@@ -246,6 +284,9 @@
246
284
  if (options.showClear) {
247
285
  row.push($('<td>').append($('<a>').attr('data-action', 'clear').append($('<span>').addClass(options.icons.clear))));
248
286
  }
287
+ if (options.showClose) {
288
+ row.push($('<td>').append($('<a>').attr('data-action', 'close').append($('<span>').addClass(options.icons.close))));
289
+ }
249
290
  return $('<table>').addClass('table-condensed').append($('<tbody>').append($('<tr>').append(row)));
250
291
  },
251
292
 
@@ -256,6 +297,10 @@
256
297
  content = $('<ul>').addClass('list-unstyled'),
257
298
  toolbar = $('<li>').addClass('picker-switch' + (options.collapse ? ' accordion-toggle' : '')).append(getToolbar());
258
299
 
300
+ if (options.inline) {
301
+ template.removeClass('dropdown-menu');
302
+ }
303
+
259
304
  if (use24Hours) {
260
305
  template.addClass('usetwentyfour');
261
306
  }
@@ -289,9 +334,15 @@
289
334
  },
290
335
 
291
336
  dataToOptions = function () {
292
- var eData = element.data(),
337
+ var eData,
293
338
  dataOptions = {};
294
339
 
340
+ if (element.is('input') || options.inline) {
341
+ eData = element.data();
342
+ } else {
343
+ eData = element.find('input').data();
344
+ }
345
+
295
346
  if (eData.dateOptions && eData.dateOptions instanceof Object) {
296
347
  dataOptions = $.extend(true, dataOptions, eData.dateOptions);
297
348
  }
@@ -306,7 +357,8 @@
306
357
  },
307
358
 
308
359
  place = function () {
309
- var offset = (component || element).position(),
360
+ var position = (component || element).position(),
361
+ offset = (component || element).offset(),
310
362
  vertical = options.widgetPositioning.vertical,
311
363
  horizontal = options.widgetPositioning.horizontal,
312
364
  parent;
@@ -315,6 +367,9 @@
315
367
  parent = options.widgetParent.append(widget);
316
368
  } else if (element.is('input')) {
317
369
  parent = element.parent().append(widget);
370
+ } else if (options.inline) {
371
+ parent = element.append(widget);
372
+ return;
318
373
  } else {
319
374
  parent = element;
320
375
  element.children().first().after(widget);
@@ -322,8 +377,8 @@
322
377
 
323
378
  // Top and bottom logic
324
379
  if (vertical === 'auto') {
325
- if ((component || element).offset().top + widget.height() > $(window).height() + $(window).scrollTop() &&
326
- widget.height() + element.outerHeight() < (component || element).offset().top) {
380
+ if (offset.top + widget.height() * 1.5 >= $(window).height() + $(window).scrollTop() &&
381
+ widget.height() + element.outerHeight() < offset.top) {
327
382
  vertical = 'top';
328
383
  } else {
329
384
  vertical = 'bottom';
@@ -332,7 +387,8 @@
332
387
 
333
388
  // Left and right logic
334
389
  if (horizontal === 'auto') {
335
- if (parent.width() < offset.left + widget.outerWidth()) {
390
+ if (parent.width() < offset.left + widget.outerWidth() / 2 &&
391
+ offset.left + widget.outerWidth() > $(window).width()) {
336
392
  horizontal = 'right';
337
393
  } else {
338
394
  horizontal = 'left';
@@ -363,10 +419,10 @@
363
419
  }
364
420
 
365
421
  widget.css({
366
- top: vertical === 'top' ? 'auto' : offset.top + element.outerHeight(),
367
- bottom: vertical === 'top' ? offset.top + element.outerHeight() : 'auto',
422
+ top: vertical === 'top' ? 'auto' : position.top + element.outerHeight(),
423
+ bottom: vertical === 'top' ? position.top + element.outerHeight() : 'auto',
368
424
  left: horizontal === 'left' ? parent.css('padding-left') : 'auto',
369
- right: horizontal === 'left' ? 'auto' : parent.css('padding-right')
425
+ right: horizontal === 'left' ? 'auto' : parent.width() - element.outerWidth()
370
426
  });
371
427
  },
372
428
 
@@ -402,29 +458,23 @@
402
458
  widget.find('.datepicker-days thead').append(row);
403
459
  },
404
460
 
405
- isInDisabledDates = function (date) {
406
- if (!options.disabledDates) {
407
- return false;
408
- }
409
- return options.disabledDates[date.format('YYYY-MM-DD')] === true;
461
+ isInDisabledDates = function (testDate) {
462
+ return options.disabledDates[testDate.format('YYYY-MM-DD')] === true;
410
463
  },
411
464
 
412
- isInEnabledDates = function (date) {
413
- if (!options.enabledDates) {
414
- return false;
415
- }
416
- return options.enabledDates[date.format('YYYY-MM-DD')] === true;
465
+ isInEnabledDates = function (testDate) {
466
+ return options.enabledDates[testDate.format('YYYY-MM-DD')] === true;
417
467
  },
418
468
 
419
469
  isValid = function (targetMoment, granularity) {
420
470
  if (!targetMoment.isValid()) {
421
471
  return false;
422
472
  }
423
- if (options.disabledDates && isInDisabledDates(targetMoment)) {
473
+ if (options.disabledDates && isInDisabledDates(targetMoment) && granularity !== 'M') {
424
474
  return false;
425
475
  }
426
- if (options.enabledDates && isInEnabledDates(targetMoment)) {
427
- return true;
476
+ if (options.enabledDates && !isInEnabledDates(targetMoment) && granularity !== 'M') {
477
+ return false;
428
478
  }
429
479
  if (options.minDate && targetMoment.isBefore(options.minDate, granularity)) {
430
480
  return false;
@@ -432,7 +482,7 @@
432
482
  if (options.maxDate && targetMoment.isAfter(options.maxDate, granularity)) {
433
483
  return false;
434
484
  }
435
- if (granularity === 'd' && options.daysOfWeekDisabled.indexOf(targetMoment.day()) !== -1) {
485
+ if (granularity === 'd' && options.daysOfWeekDisabled.indexOf(targetMoment.day()) !== -1) { //widget && widget.find('.datepicker-days').length > 0
436
486
  return false;
437
487
  }
438
488
  return true;
@@ -680,7 +730,9 @@
680
730
  oldDate: oldDate
681
731
  });
682
732
  } else {
683
- input.val(unset ? '' : date.format(actualFormat));
733
+ if (!options.keepInvalid) {
734
+ input.val(unset ? '' : date.format(actualFormat));
735
+ }
684
736
  notifyEvent({
685
737
  type: 'dp.error',
686
738
  date: targetMoment
@@ -700,6 +752,7 @@
700
752
  transitioning = true;
701
753
  return false;
702
754
  }
755
+ return true;
703
756
  });
704
757
  if (transitioning) {
705
758
  return picker;
@@ -723,6 +776,10 @@
723
776
  return picker;
724
777
  },
725
778
 
779
+ clear = function () {
780
+ setValue(null);
781
+ },
782
+
726
783
  /********************************************************************************
727
784
  *
728
785
  * Widget UI interaction functions
@@ -748,10 +805,13 @@
748
805
  viewDate.month(month);
749
806
  if (currentViewMode === minViewModeNumber) {
750
807
  setValue(date.clone().year(viewDate.year()).month(viewDate.month()));
751
- hide();
808
+ if (!options.inline) {
809
+ hide();
810
+ }
811
+ } else {
812
+ showMode(-1);
813
+ fillDate();
752
814
  }
753
- showMode(-1);
754
- fillDate();
755
815
  },
756
816
 
757
817
  selectYear: function (e) {
@@ -759,10 +819,13 @@
759
819
  viewDate.year(year);
760
820
  if (currentViewMode === minViewModeNumber) {
761
821
  setValue(date.clone().year(viewDate.year()));
762
- hide();
822
+ if (!options.inline) {
823
+ hide();
824
+ }
825
+ } else {
826
+ showMode(-1);
827
+ fillDate();
763
828
  }
764
- showMode(-1);
765
- fillDate();
766
829
  },
767
830
 
768
831
  selectDay: function (e) {
@@ -774,7 +837,7 @@
774
837
  day.add(1, 'M');
775
838
  }
776
839
  setValue(day.date(parseInt($(e.target).text(), 10)));
777
- if (!hasTime() && !options.keepOpen) {
840
+ if (!hasTime() && !options.keepOpen && !options.inline) {
778
841
  hide();
779
842
  }
780
843
  },
@@ -819,8 +882,13 @@
819
882
  if (collapseData && collapseData.transitioning) {
820
883
  return;
821
884
  }
822
- expanded.collapse('hide');
823
- closed.collapse('show');
885
+ if (expanded.collapse) { // if collapse plugin is available through bootstrap.js then use it
886
+ expanded.collapse('hide');
887
+ closed.collapse('show');
888
+ } else { // otherwise just toggle in class on the two views
889
+ expanded.removeClass('in');
890
+ closed.addClass('in');
891
+ }
824
892
  if ($this.is('span')) {
825
893
  $this.toggleClass(options.icons.time + ' ' + options.icons.date);
826
894
  } else {
@@ -882,13 +950,13 @@
882
950
  actions.showPicker.call(picker);
883
951
  },
884
952
 
885
- clear: function () {
886
- setValue(null);
887
- },
953
+ clear: clear,
888
954
 
889
955
  today: function () {
890
956
  setValue(moment());
891
- }
957
+ },
958
+
959
+ close: hide
892
960
  },
893
961
 
894
962
  doAction = function (e) {
@@ -919,10 +987,10 @@
919
987
  }
920
988
  };
921
989
 
922
- if (input.prop('disabled') || input.prop('readonly') || widget) {
990
+ if (input.prop('disabled') || (!options.ignoreReadonly && input.prop('readonly')) || widget) {
923
991
  return picker;
924
992
  }
925
- if (options.useCurrent && unset) { // && input.val().trim().length !== 0) { this broke the jasmine test
993
+ if (options.useCurrent && unset && ((input.is('input') && input.val().trim().length === 0) || options.inline)) {
926
994
  currentMoment = moment();
927
995
  if (typeof options.useCurrent === 'string') {
928
996
  currentMoment = useCurrentGranularity[options.useCurrent](currentMoment);
@@ -966,22 +1034,80 @@
966
1034
  return (widget ? hide() : show());
967
1035
  },
968
1036
 
969
- parseInputDate = function (date) {
970
- if (moment.isMoment(date) || date instanceof Date) {
971
- date = moment(date);
1037
+ parseInputDate = function (inputDate) {
1038
+ if (moment.isMoment(inputDate) || inputDate instanceof Date) {
1039
+ inputDate = moment(inputDate);
972
1040
  } else {
973
- date = moment(date, parseFormats, options.useStrict);
1041
+ inputDate = moment(inputDate, parseFormats, options.useStrict);
974
1042
  }
975
- date.locale(options.locale);
976
- return date;
1043
+ inputDate.locale(options.locale);
1044
+ return inputDate;
977
1045
  },
978
1046
 
979
1047
  keydown = function (e) {
980
- if (e.keyCode === 27) { // allow escape to hide picker
981
- hide();
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
+ var handler = null,
1059
+ index,
1060
+ index2,
1061
+ pressedKeys = [],
1062
+ pressedModifiers = {},
1063
+ currentKey = e.which,
1064
+ keyBindKeys,
1065
+ allModifiersPressed,
1066
+ pressed = 'p';
1067
+
1068
+ keyState[currentKey] = pressed;
1069
+
1070
+ for (index in keyState) {
1071
+ if (keyState.hasOwnProperty(index) && keyState[index] === pressed) {
1072
+ pressedKeys.push(index);
1073
+ if (parseInt(index, 10) !== currentKey) {
1074
+ pressedModifiers[index] = true;
1075
+ }
1076
+ }
1077
+ }
1078
+
1079
+ for (index in options.keyBinds) {
1080
+ if (options.keyBinds.hasOwnProperty(index) && typeof (options.keyBinds[index]) === 'function') {
1081
+ keyBindKeys = index.split(' ');
1082
+ if (keyBindKeys.length === pressedKeys.length && keyMap[currentKey] === keyBindKeys[keyBindKeys.length - 1]) {
1083
+ allModifiersPressed = true;
1084
+ for (index2 = keyBindKeys.length - 2; index2 >= 0; index2--) {
1085
+ if (!(keyMap[keyBindKeys[index2]] in pressedModifiers)) {
1086
+ allModifiersPressed = false;
1087
+ break;
1088
+ }
1089
+ }
1090
+ if (allModifiersPressed) {
1091
+ handler = options.keyBinds[index];
1092
+ break;
1093
+ }
1094
+ }
1095
+ }
1096
+ }
1097
+
1098
+ if (handler) {
1099
+ handler.call(picker, widget);
1100
+ e.stopPropagation();
1101
+ e.preventDefault();
982
1102
  }
983
1103
  },
984
1104
 
1105
+ keyup = function (e) {
1106
+ keyState[e.which] = 'r';
1107
+ e.stopPropagation();
1108
+ e.preventDefault();
1109
+ },
1110
+
985
1111
  change = function (e) {
986
1112
  var val = $(e.target).val().trim(),
987
1113
  parsedDate = val ? parseInputDate(val) : null;
@@ -993,8 +1119,9 @@
993
1119
  attachDatePickerElementEvents = function () {
994
1120
  input.on({
995
1121
  'change': change,
996
- 'blur': hide,
997
- 'keydown': keydown
1122
+ 'blur': options.debug ? '' : hide,
1123
+ 'keydown': keydown,
1124
+ 'keyup': keyup
998
1125
  });
999
1126
 
1000
1127
  if (element.is('input')) {
@@ -1011,7 +1138,8 @@
1011
1138
  input.off({
1012
1139
  'change': change,
1013
1140
  'blur': hide,
1014
- 'keydown': keydown
1141
+ 'keydown': keydown,
1142
+ 'keyup': keyup
1015
1143
  });
1016
1144
 
1017
1145
  if (element.is('input')) {
@@ -1041,10 +1169,14 @@
1041
1169
  initFormatting = function () {
1042
1170
  var format = options.format || 'L LT';
1043
1171
 
1044
- actualFormat = format.replace(/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g, function (input) {
1045
- return date.localeData().longDateFormat(input) || input;
1172
+ actualFormat = format.replace(/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g, function (formatInput) {
1173
+ var newinput = date.localeData().longDateFormat(formatInput) || formatInput;
1174
+ return newinput.replace(/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g, function (formatInput2) { //temp fix for #740
1175
+ return date.localeData().longDateFormat(formatInput2) || formatInput2;
1176
+ });
1046
1177
  });
1047
1178
 
1179
+
1048
1180
  parseFormats = options.extraFormats ? options.extraFormats.slice() : [];
1049
1181
  if (parseFormats.indexOf(format) < 0 && parseFormats.indexOf(actualFormat) < 0) {
1050
1182
  parseFormats.push(actualFormat);
@@ -1109,6 +1241,17 @@
1109
1241
  return picker;
1110
1242
  };
1111
1243
 
1244
+ picker.ignoreReadonly = function (ignoreReadonly) {
1245
+ if (arguments.length === 0) {
1246
+ return options.ignoreReadonly;
1247
+ }
1248
+ if (typeof ignoreReadonly !== 'boolean') {
1249
+ throw new TypeError('ignoreReadonly () expects a boolean parameter');
1250
+ }
1251
+ options.ignoreReadonly = ignoreReadonly;
1252
+ return picker;
1253
+ };
1254
+
1112
1255
  picker.options = function (newOptions) {
1113
1256
  if (arguments.length === 0) {
1114
1257
  return $.extend(true, {}, options);
@@ -1249,56 +1392,74 @@
1249
1392
  return picker;
1250
1393
  };
1251
1394
 
1252
- picker.maxDate = function (date) {
1395
+ picker.maxDate = function (maxDate) {
1253
1396
  if (arguments.length === 0) {
1254
1397
  return options.maxDate ? options.maxDate.clone() : options.maxDate;
1255
1398
  }
1256
1399
 
1257
- if ((typeof date === 'boolean') && date === false) {
1400
+ if ((typeof maxDate === 'boolean') && maxDate === false) {
1258
1401
  options.maxDate = false;
1259
1402
  update();
1260
1403
  return picker;
1261
1404
  }
1262
1405
 
1263
- var parsedDate = parseInputDate(date);
1406
+ if (typeof maxDate === 'string') {
1407
+ if (maxDate === 'now' || maxDate === 'moment') {
1408
+ maxDate = moment();
1409
+ }
1410
+ }
1411
+
1412
+ var parsedDate = parseInputDate(maxDate);
1264
1413
 
1265
1414
  if (!parsedDate.isValid()) {
1266
- throw new TypeError('maxDate() Could not parse date parameter: ' + date);
1415
+ throw new TypeError('maxDate() Could not parse date parameter: ' + maxDate);
1267
1416
  }
1268
1417
  if (options.minDate && parsedDate.isBefore(options.minDate)) {
1269
1418
  throw new TypeError('maxDate() date parameter is before options.minDate: ' + parsedDate.format(actualFormat));
1270
1419
  }
1271
1420
  options.maxDate = parsedDate;
1272
- if (options.maxDate.isBefore(date)) {
1421
+ if (options.maxDate.isBefore(maxDate)) {
1273
1422
  setValue(options.maxDate);
1274
1423
  }
1424
+ if (viewDate.isAfter(parsedDate)) {
1425
+ viewDate = parsedDate.clone();
1426
+ }
1275
1427
  update();
1276
1428
  return picker;
1277
1429
  };
1278
1430
 
1279
- picker.minDate = function (date) {
1431
+ picker.minDate = function (minDate) {
1280
1432
  if (arguments.length === 0) {
1281
1433
  return options.minDate ? options.minDate.clone() : options.minDate;
1282
1434
  }
1283
1435
 
1284
- if ((typeof date === 'boolean') && date === false) {
1436
+ if ((typeof minDate === 'boolean') && minDate === false) {
1285
1437
  options.minDate = false;
1286
1438
  update();
1287
1439
  return picker;
1288
1440
  }
1289
1441
 
1290
- var parsedDate = parseInputDate(date);
1442
+ if (typeof minDate === 'string') {
1443
+ if (minDate === 'now' || minDate === 'moment') {
1444
+ minDate = moment();
1445
+ }
1446
+ }
1447
+
1448
+ var parsedDate = parseInputDate(minDate);
1291
1449
 
1292
1450
  if (!parsedDate.isValid()) {
1293
- throw new TypeError('minDate() Could not parse date parameter: ' + date);
1451
+ throw new TypeError('minDate() Could not parse date parameter: ' + minDate);
1294
1452
  }
1295
1453
  if (options.maxDate && parsedDate.isAfter(options.maxDate)) {
1296
1454
  throw new TypeError('minDate() date parameter is after options.maxDate: ' + parsedDate.format(actualFormat));
1297
1455
  }
1298
1456
  options.minDate = parsedDate;
1299
- if (options.minDate.isAfter(date)) {
1457
+ if (options.minDate.isAfter(minDate)) {
1300
1458
  setValue(options.minDate);
1301
1459
  }
1460
+ if (viewDate.isBefore(parsedDate)) {
1461
+ viewDate = parsedDate.clone();
1462
+ }
1302
1463
  update();
1303
1464
  return picker;
1304
1465
  };
@@ -1311,6 +1472,13 @@
1311
1472
  options.defaultDate = false;
1312
1473
  return picker;
1313
1474
  }
1475
+
1476
+ if (typeof defaultDate === 'string') {
1477
+ if (defaultDate === 'now' || defaultDate === 'moment') {
1478
+ defaultDate = moment();
1479
+ }
1480
+ }
1481
+
1314
1482
  var parsedDate = parseInputDate(defaultDate);
1315
1483
  if (!parsedDate.isValid()) {
1316
1484
  throw new TypeError('defaultDate() Could not parse date parameter: ' + defaultDate);
@@ -1321,7 +1489,7 @@
1321
1489
 
1322
1490
  options.defaultDate = parsedDate;
1323
1491
 
1324
- if (options.defaultDate && input.val().trim() === '') {
1492
+ if (options.defaultDate && input.val().trim() === '' && input.attr('placeholder') === undefined) {
1325
1493
  setValue(options.defaultDate);
1326
1494
  }
1327
1495
  return picker;
@@ -1442,21 +1610,21 @@
1442
1610
  return picker;
1443
1611
  };
1444
1612
 
1445
- picker.viewMode = function (newViewMode) {
1613
+ picker.viewMode = function (viewMode) {
1446
1614
  if (arguments.length === 0) {
1447
1615
  return options.viewMode;
1448
1616
  }
1449
1617
 
1450
- if (typeof newViewMode !== 'string') {
1618
+ if (typeof viewMode !== 'string') {
1451
1619
  throw new TypeError('viewMode() expects a string parameter');
1452
1620
  }
1453
1621
 
1454
- if (viewModes.indexOf(newViewMode) === -1) {
1622
+ if (viewModes.indexOf(viewMode) === -1) {
1455
1623
  throw new TypeError('viewMode() parameter must be one of (' + viewModes.join(', ') + ') value');
1456
1624
  }
1457
1625
 
1458
- options.viewMode = newViewMode;
1459
- currentViewMode = Math.max(viewModes.indexOf(newViewMode), minViewModeNumber);
1626
+ options.viewMode = viewMode;
1627
+ currentViewMode = Math.max(viewModes.indexOf(viewMode), minViewModeNumber);
1460
1628
 
1461
1629
  showMode();
1462
1630
  return picker;
@@ -1514,16 +1682,16 @@
1514
1682
  return picker;
1515
1683
  };
1516
1684
 
1517
- picker.calendarWeeks = function (showCalendarWeeks) {
1685
+ picker.calendarWeeks = function (calendarWeeks) {
1518
1686
  if (arguments.length === 0) {
1519
1687
  return options.calendarWeeks;
1520
1688
  }
1521
1689
 
1522
- if (typeof showCalendarWeeks !== 'boolean') {
1690
+ if (typeof calendarWeeks !== 'boolean') {
1523
1691
  throw new TypeError('calendarWeeks() expects parameter to be a boolean value');
1524
1692
  }
1525
1693
 
1526
- options.calendarWeeks = showCalendarWeeks;
1694
+ options.calendarWeeks = calendarWeeks;
1527
1695
  update();
1528
1696
  return picker;
1529
1697
  };
@@ -1571,7 +1739,7 @@
1571
1739
  widgetParent = $(widgetParent);
1572
1740
  }
1573
1741
 
1574
- if (widgetParent !== null && (typeof widgetParent !== 'string' && !(widgetParent instanceof jQuery))) {
1742
+ if (widgetParent !== null && (typeof widgetParent !== 'string' && !(widgetParent instanceof $))) {
1575
1743
  throw new TypeError('widgetParent() expects a string or a jQuery object parameter');
1576
1744
  }
1577
1745
 
@@ -1585,7 +1753,7 @@
1585
1753
 
1586
1754
  picker.keepOpen = function (keepOpen) {
1587
1755
  if (arguments.length === 0) {
1588
- return options.format;
1756
+ return options.keepOpen;
1589
1757
  }
1590
1758
 
1591
1759
  if (typeof keepOpen !== 'boolean') {
@@ -1596,15 +1764,85 @@
1596
1764
  return picker;
1597
1765
  };
1598
1766
 
1767
+ picker.inline = function (inline) {
1768
+ if (arguments.length === 0) {
1769
+ return options.inline;
1770
+ }
1771
+
1772
+ if (typeof inline !== 'boolean') {
1773
+ throw new TypeError('inline() expects a boolean parameter');
1774
+ }
1775
+
1776
+ options.inline = inline;
1777
+ return picker;
1778
+ };
1779
+
1780
+ picker.clear = function () {
1781
+ clear();
1782
+ return picker;
1783
+ };
1784
+
1785
+ picker.keyBinds = function (keyBinds) {
1786
+ options.keyBinds = keyBinds;
1787
+ return picker;
1788
+ };
1789
+
1790
+ picker.debug = function (debug) {
1791
+ if (typeof debug !== 'boolean') {
1792
+ throw new TypeError('debug() expects a boolean parameter');
1793
+ }
1794
+
1795
+ options.debug = debug;
1796
+ return picker;
1797
+ };
1798
+
1799
+ picker.showClose = function (showClose) {
1800
+ if (arguments.length === 0) {
1801
+ return options.showClose;
1802
+ }
1803
+
1804
+ if (typeof showClose !== 'boolean') {
1805
+ throw new TypeError('showClose() expects a boolean parameter');
1806
+ }
1807
+
1808
+ options.showClose = showClose;
1809
+ return picker;
1810
+ };
1811
+
1812
+ picker.keepInvalid = function (keepInvalid) {
1813
+ if (arguments.length === 0) {
1814
+ return options.keepInvalid;
1815
+ }
1816
+
1817
+ if (typeof keepInvalid !== 'boolean') {
1818
+ throw new TypeError('keepInvalid() expects a boolean parameter');
1819
+ }
1820
+ options.keepInvalid = keepInvalid;
1821
+ return picker;
1822
+ };
1823
+
1824
+ picker.datepickerInput = function (datepickerInput) {
1825
+ if (arguments.length === 0) {
1826
+ return options.datepickerInput;
1827
+ }
1828
+
1829
+ if (typeof datepickerInput !== 'string') {
1830
+ throw new TypeError('datepickerInput() expects a string parameter');
1831
+ }
1832
+
1833
+ options.datepickerInput = datepickerInput;
1834
+ return picker;
1835
+ };
1836
+
1599
1837
  // initializing element and component attributes
1600
1838
  if (element.is('input')) {
1601
1839
  input = element;
1602
1840
  } else {
1603
- input = element.find('.datepickerinput');
1841
+ input = element.find(options.datepickerInput);
1604
1842
  if (input.size() === 0) {
1605
1843
  input = element.find('input');
1606
1844
  } else if (!input.is('input')) {
1607
- throw new Error('CSS class "datepickerinput" cannot be applied to non input element');
1845
+ throw new Error('CSS class "' + options.datepickerInput + '" cannot be applied to non input element');
1608
1846
  }
1609
1847
  }
1610
1848
 
@@ -1617,7 +1855,7 @@
1617
1855
  }
1618
1856
  }
1619
1857
 
1620
- if (!input.is('input')) {
1858
+ if (!options.inline && !input.is('input')) {
1621
1859
  throw new Error('Could not initialize DateTimePicker without an input element');
1622
1860
  }
1623
1861
 
@@ -1632,13 +1870,15 @@
1632
1870
  if (input.prop('disabled')) {
1633
1871
  picker.disable();
1634
1872
  }
1635
-
1636
- if (input.val().trim().length !== 0) {
1873
+ if (input.is('input') && input.val().trim().length !== 0) {
1637
1874
  setValue(parseInputDate(input.val().trim()));
1638
- } else if (options.defaultDate) {
1875
+ }
1876
+ else if (options.defaultDate && input.attr('placeholder') === undefined) {
1639
1877
  setValue(options.defaultDate);
1640
1878
  }
1641
-
1879
+ if (options.inline) {
1880
+ show();
1881
+ }
1642
1882
  return picker;
1643
1883
  };
1644
1884
 
@@ -1680,7 +1920,8 @@
1680
1920
  previous: 'glyphicon glyphicon-chevron-left',
1681
1921
  next: 'glyphicon glyphicon-chevron-right',
1682
1922
  today: 'glyphicon glyphicon-screenshot',
1683
- clear: 'glyphicon glyphicon-trash'
1923
+ clear: 'glyphicon glyphicon-trash',
1924
+ close: 'glyphicon glyphicon-remove'
1684
1925
  },
1685
1926
  useStrict: false,
1686
1927
  sideBySide: false,
@@ -1690,11 +1931,121 @@
1690
1931
  toolbarPlacement: 'default',
1691
1932
  showTodayButton: false,
1692
1933
  showClear: false,
1934
+ showClose: false,
1693
1935
  widgetPositioning: {
1694
1936
  horizontal: 'auto',
1695
1937
  vertical: 'auto'
1696
1938
  },
1697
1939
  widgetParent: null,
1698
- keepOpen: false
1940
+ ignoreReadonly: false,
1941
+ keepOpen: false,
1942
+ inline: false,
1943
+ keepInvalid: false,
1944
+ datepickerInput: '.datepickerinput',
1945
+ keyBinds: {
1946
+ up: function (widget) {
1947
+ if (!widget) {
1948
+ return;
1949
+ }
1950
+ var d = this.date() || moment();
1951
+ if (widget.find('.datepicker').is(':visible')) {
1952
+ this.date(d.clone().subtract(7, 'd'));
1953
+ } else {
1954
+ this.date(d.clone().add(1, 'm'));
1955
+ }
1956
+ },
1957
+ down: function (widget) {
1958
+ if (!widget) {
1959
+ this.show();
1960
+ return;
1961
+ }
1962
+ var d = this.date() || moment();
1963
+ if (widget.find('.datepicker').is(':visible')) {
1964
+ this.date(d.clone().add(7, 'd'));
1965
+ } else {
1966
+ this.date(d.clone().subtract(1, 'm'));
1967
+ }
1968
+ },
1969
+ 'control up': function (widget) {
1970
+ if (!widget) {
1971
+ return;
1972
+ }
1973
+ var d = this.date() || moment();
1974
+ if (widget.find('.datepicker').is(':visible')) {
1975
+ this.date(d.clone().subtract(1, 'y'));
1976
+ } else {
1977
+ this.date(d.clone().add(1, 'h'));
1978
+ }
1979
+ },
1980
+ 'control down': function (widget) {
1981
+ if (!widget) {
1982
+ return;
1983
+ }
1984
+ var d = this.date() || moment();
1985
+ if (widget.find('.datepicker').is(':visible')) {
1986
+ this.date(d.clone().add(1, 'y'));
1987
+ } else {
1988
+ this.date(d.clone().subtract(1, 'h'));
1989
+ }
1990
+ },
1991
+ left: function (widget) {
1992
+ if (!widget) {
1993
+ return;
1994
+ }
1995
+ var d = this.date() || moment();
1996
+ if (widget.find('.datepicker').is(':visible')) {
1997
+ this.date(d.clone().subtract(1, 'd'));
1998
+ }
1999
+ },
2000
+ right: function (widget) {
2001
+ if (!widget) {
2002
+ return;
2003
+ }
2004
+ var d = this.date() || moment();
2005
+ if (widget.find('.datepicker').is(':visible')) {
2006
+ this.date(d.clone().add(1, 'd'));
2007
+ }
2008
+ },
2009
+ pageUp: function (widget) {
2010
+ if (!widget) {
2011
+ return;
2012
+ }
2013
+ var d = this.date() || moment();
2014
+ if (widget.find('.datepicker').is(':visible')) {
2015
+ this.date(d.clone().subtract(1, 'M'));
2016
+ }
2017
+ },
2018
+ pageDown: function (widget) {
2019
+ if (!widget) {
2020
+ return;
2021
+ }
2022
+ var d = this.date() || moment();
2023
+ if (widget.find('.datepicker').is(':visible')) {
2024
+ this.date(d.clone().add(1, 'M'));
2025
+ }
2026
+ },
2027
+ enter: function () {
2028
+ this.hide();
2029
+ },
2030
+ escape: function () {
2031
+ this.hide();
2032
+ },
2033
+ //tab: function (widget) { //this break the flow of the form. disabling for now
2034
+ // var toggle = widget.find('.picker-switch a[data-action="togglePicker"]');
2035
+ // if(toggle.length > 0) toggle.click();
2036
+ //},
2037
+ 'control space': function (widget) {
2038
+ if (widget.find('.timepicker').is(':visible')) {
2039
+ widget.find('.btn[data-action="togglePeriod"]').click();
2040
+ }
2041
+ },
2042
+ t: function () {
2043
+ this.date(moment());
2044
+ },
2045
+ 'delete': function () {
2046
+ this.clear();
2047
+ }
2048
+ },
2049
+ debug: false
1699
2050
  };
1700
2051
  }));