effective_form_inputs 1.1.0 → 1.1.1

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: a75831223cd401c30495c973058cfc192ba3fced
4
- data.tar.gz: b8fd17c7f18fbb59b3392d96277c50177948c432
3
+ metadata.gz: 241ea780a6568932a54496fd403ce8f6f82a35b4
4
+ data.tar.gz: 110a5a40184312a73a24f62e16209af13c38bad7
5
5
  SHA512:
6
- metadata.gz: 712f1cd5a0063b6be125c10fef55cc494bc27b379a6e9169c0e2d49bead07a44e86fb1ecbd488b0c4a54c5564ee81711688670be814738142f3a9892a910c267
7
- data.tar.gz: 56a35b5d732b3401a44f5a61d85a2bcb6b2ee34b62c633637b12e4e47f2a768786c16448c579a03b91836dba34730196bdf3de480fb6bb633c586616cfd90048
6
+ metadata.gz: 45876febc7abe649b5abd5836bca0e3cf2ca729624ef659c205a4ddf2fe58e8dcc3db4679aab587d07b5259e80b909d468f7d464d26693d97bf552ae6fd2b30f
7
+ data.tar.gz: c02d4f28b5dc96d69f47a32ae400c39319ae35da6dda616ae271bc7d658d2ab173d6037546ff08362f8d38c0e0c5035b39c16167ac1841df12fc2631d6ba81d7
data/README.md CHANGED
@@ -223,6 +223,25 @@ For a full list of options, please refer to:
223
223
  http://eonasdan.github.io/bootstrap-datetimepicker/Options/
224
224
 
225
225
 
226
+ ### Set Date
227
+
228
+ Use the following JavaScript to programatically set the date:
229
+
230
+ ```javascript
231
+ $('#start_at').data('DateTimePicker').date('2016-05-08')
232
+ ```
233
+
234
+ ### Disabled Dates
235
+
236
+ Provide a String, Date, or Range to set the disabled dates.
237
+
238
+ ```ruby
239
+ :input_js => { disabledDates: '2020-01-01' }
240
+ :input_js => { disabledDates: Time.zone.now }
241
+ :input_js => { disabledDates: Time.zone.now.beginning_of_month..Time.zone.now.end_of_month }
242
+ :input_js => { disabledDates: [Time.zone.now, Time.zone.now + 1.day] }
243
+ ```
244
+
226
245
  ## Effective Date Picker
227
246
 
228
247
  This custom form input is based on the following awesome project:
@@ -281,13 +300,6 @@ For a full list of options, please refer to:
281
300
 
282
301
  http://eonasdan.github.io/bootstrap-datetimepicker/Options/
283
302
 
284
- ### Set Date
285
-
286
- Use the following JavaScript to programatically set the date:
287
-
288
- ```javascript
289
- $('#start_at').data('DateTimePicker').date('2016-05-08')
290
- ```
291
303
 
292
304
  ## Effective Email
293
305
 
@@ -1,4 +1,4 @@
1
- /*! version : 4.17.37
1
+ /*! version : 4.17.45
2
2
  =========================================================
3
3
  bootstrap-datetimejs
4
4
  https://github.com/Eonasdan/bootstrap-datetimepicker
@@ -39,7 +39,7 @@
39
39
  // AMD is used - Register as an anonymous module.
40
40
  define(['jquery', 'moment'], factory);
41
41
  } else if (typeof exports === 'object') {
42
- factory(require('jquery'), require('moment'));
42
+ module.exports = factory(require('jquery'), require('moment'));
43
43
  } else {
44
44
  // Neither AMD nor CommonJS used. Use global variables.
45
45
  if (typeof jQuery === 'undefined') {
@@ -132,40 +132,34 @@
132
132
  * Private functions
133
133
  *
134
134
  ********************************************************************************/
135
+
136
+ hasTimeZone = function () {
137
+ return moment.tz !== undefined && options.timeZone !== undefined && options.timeZone !== null && options.timeZone !== '';
138
+ },
139
+
135
140
  getMoment = function (d) {
136
- var tzEnabled = false,
137
- returnMoment,
138
- currentZoneOffset,
139
- incomingZoneOffset,
140
- timeZoneIndicator,
141
- dateWithTimeZoneInfo;
141
+ var returnMoment;
142
142
 
143
- if (moment.tz !== undefined && options.timeZone !== undefined && options.timeZone !== null && options.timeZone !== '') {
144
- tzEnabled = true;
145
- }
146
143
  if (d === undefined || d === null) {
147
- if (tzEnabled) {
148
- returnMoment = moment().tz(options.timeZone).startOf('d');
149
- } else {
150
- returnMoment = moment().startOf('d');
151
- }
144
+ returnMoment = moment(); //TODO should this use format? and locale?
145
+ } else if (moment.isDate(d) || moment.isMoment(d)) {
146
+ // If the date that is passed in is already a Date() or moment() object,
147
+ // pass it directly to moment.
148
+ returnMoment = moment(d);
149
+ } else if (hasTimeZone()) { // There is a string to parse and a default time zone
150
+ // parse with the tz function which takes a default time zone if it is not in the format string
151
+ returnMoment = moment.tz(d, parseFormats, options.useStrict, options.timeZone);
152
152
  } else {
153
- if (tzEnabled) {
154
- currentZoneOffset = moment().tz(options.timeZone).utcOffset();
155
- incomingZoneOffset = moment(d, parseFormats, options.useStrict).utcOffset();
156
- if (incomingZoneOffset !== currentZoneOffset) {
157
- timeZoneIndicator = moment().tz(options.timeZone).format('Z');
158
- dateWithTimeZoneInfo = moment(d, parseFormats, options.useStrict).format('YYYY-MM-DD[T]HH:mm:ss') + timeZoneIndicator;
159
- returnMoment = moment(dateWithTimeZoneInfo, parseFormats, options.useStrict).tz(options.timeZone);
160
- } else {
161
- returnMoment = moment(d, parseFormats, options.useStrict).tz(options.timeZone);
162
- }
163
- } else {
164
- returnMoment = moment(d, parseFormats, options.useStrict);
165
- }
153
+ returnMoment = moment(d, parseFormats, options.useStrict);
166
154
  }
155
+
156
+ if (hasTimeZone()) {
157
+ returnMoment.tz(options.timeZone);
158
+ }
159
+
167
160
  return returnMoment;
168
161
  },
162
+
169
163
  isEnabled = function (granularity) {
170
164
  if (typeof granularity !== 'string' || granularity.length > 1) {
171
165
  throw new TypeError('isEnabled expects a single character string parameter');
@@ -188,6 +182,7 @@
188
182
  return false;
189
183
  }
190
184
  },
185
+
191
186
  hasTime = function () {
192
187
  return (isEnabled('h') || isEnabled('m') || isEnabled('s'));
193
188
  },
@@ -243,13 +238,11 @@
243
238
 
244
239
  if (isEnabled('h')) {
245
240
  topRow.append($('<td>')
246
- .append($('<a>').attr({href: '#', tabindex: '-1', 'title': options.tooltips.incrementHour}).addClass('btn').attr('data-action', 'incrementHours')
247
- .append($('<span>').addClass(options.icons.up))));
241
+ .append($('<a>').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.incrementHour }).addClass('btn').attr('data-action', 'incrementHours').append($('<span>').addClass(options.icons.up))));
248
242
  middleRow.append($('<td>')
249
- .append($('<span>').addClass('timepicker-hour').attr({'data-time-component':'hours', 'title': options.tooltips.pickHour}).attr('data-action', 'showHours')));
243
+ .append($('<span>').addClass('timepicker-hour').attr({ 'data-time-component': 'hours', 'title': options.tooltips.pickHour }).attr('data-action', 'showHours')));
250
244
  bottomRow.append($('<td>')
251
- .append($('<a>').attr({href: '#', tabindex: '-1', 'title': options.tooltips.decrementHour}).addClass('btn').attr('data-action', 'decrementHours')
252
- .append($('<span>').addClass(options.icons.down))));
245
+ .append($('<a>').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.decrementHour }).addClass('btn').attr('data-action', 'decrementHours').append($('<span>').addClass(options.icons.down))));
253
246
  }
254
247
  if (isEnabled('m')) {
255
248
  if (isEnabled('h')) {
@@ -258,12 +251,12 @@
258
251
  bottomRow.append($('<td>').addClass('separator'));
259
252
  }
260
253
  topRow.append($('<td>')
261
- .append($('<a>').attr({href: '#', tabindex: '-1', 'title': options.tooltips.incrementMinute}).addClass('btn').attr('data-action', 'incrementMinutes')
254
+ .append($('<a>').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.incrementMinute }).addClass('btn').attr('data-action', 'incrementMinutes')
262
255
  .append($('<span>').addClass(options.icons.up))));
263
256
  middleRow.append($('<td>')
264
- .append($('<span>').addClass('timepicker-minute').attr({'data-time-component': 'minutes', 'title': options.tooltips.pickMinute}).attr('data-action', 'showMinutes')));
257
+ .append($('<span>').addClass('timepicker-minute').attr({ 'data-time-component': 'minutes', 'title': options.tooltips.pickMinute }).attr('data-action', 'showMinutes')));
265
258
  bottomRow.append($('<td>')
266
- .append($('<a>').attr({href: '#', tabindex: '-1', 'title': options.tooltips.decrementMinute}).addClass('btn').attr('data-action', 'decrementMinutes')
259
+ .append($('<a>').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.decrementMinute }).addClass('btn').attr('data-action', 'decrementMinutes')
267
260
  .append($('<span>').addClass(options.icons.down))));
268
261
  }
269
262
  if (isEnabled('s')) {
@@ -273,19 +266,19 @@
273
266
  bottomRow.append($('<td>').addClass('separator'));
274
267
  }
275
268
  topRow.append($('<td>')
276
- .append($('<a>').attr({href: '#', tabindex: '-1', 'title': options.tooltips.incrementSecond}).addClass('btn').attr('data-action', 'incrementSeconds')
269
+ .append($('<a>').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.incrementSecond }).addClass('btn').attr('data-action', 'incrementSeconds')
277
270
  .append($('<span>').addClass(options.icons.up))));
278
271
  middleRow.append($('<td>')
279
- .append($('<span>').addClass('timepicker-second').attr({'data-time-component': 'seconds', 'title': options.tooltips.pickSecond}).attr('data-action', 'showSeconds')));
272
+ .append($('<span>').addClass('timepicker-second').attr({ 'data-time-component': 'seconds', 'title': options.tooltips.pickSecond }).attr('data-action', 'showSeconds')));
280
273
  bottomRow.append($('<td>')
281
- .append($('<a>').attr({href: '#', tabindex: '-1', 'title': options.tooltips.decrementSecond}).addClass('btn').attr('data-action', 'decrementSeconds')
274
+ .append($('<a>').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.decrementSecond }).addClass('btn').attr('data-action', 'decrementSeconds')
282
275
  .append($('<span>').addClass(options.icons.down))));
283
276
  }
284
277
 
285
278
  if (!use24Hours) {
286
279
  topRow.append($('<td>').addClass('separator'));
287
280
  middleRow.append($('<td>')
288
- .append($('<button>').addClass('btn btn-primary').attr({'data-action': 'togglePeriod', tabindex: '-1', 'title': options.tooltips.togglePeriod})));
281
+ .append($('<button>').addClass('btn btn-primary').attr({ 'data-action': 'togglePeriod', tabindex: '-1', 'title': options.tooltips.togglePeriod })));
289
282
  bottomRow.append($('<td>').addClass('separator'));
290
283
  }
291
284
 
@@ -319,16 +312,16 @@
319
312
  getToolbar = function () {
320
313
  var row = [];
321
314
  if (options.showTodayButton) {
322
- row.push($('<td>').append($('<a>').attr({'data-action':'today', 'title': options.tooltips.today}).append($('<span>').addClass(options.icons.today))));
315
+ row.push($('<td>').append($('<a>').attr({ 'data-action': 'today', 'title': options.tooltips.today }).append($('<span>').addClass(options.icons.today))));
323
316
  }
324
317
  if (!options.sideBySide && hasDate() && hasTime()) {
325
- row.push($('<td>').append($('<a>').attr({'data-action':'togglePicker', 'title': options.tooltips.selectTime}).append($('<span>').addClass(options.icons.time))));
318
+ row.push($('<td>').append($('<a>').attr({ 'data-action': 'togglePicker', 'title': options.tooltips.selectTime }).append($('<span>').addClass(options.icons.time))));
326
319
  }
327
320
  if (options.showClear) {
328
- row.push($('<td>').append($('<a>').attr({'data-action':'clear', 'title': options.tooltips.clear}).append($('<span>').addClass(options.icons.clear))));
321
+ row.push($('<td>').append($('<a>').attr({ 'data-action': 'clear', 'title': options.tooltips.clear }).append($('<span>').addClass(options.icons.clear))));
329
322
  }
330
323
  if (options.showClose) {
331
- row.push($('<td>').append($('<a>').attr({'data-action':'close', 'title': options.tooltips.close}).append($('<span>').addClass(options.icons.close))));
324
+ row.push($('<td>').append($('<a>').attr({ 'data-action': 'close', 'title': options.tooltips.close }).append($('<span>').addClass(options.icons.close))));
332
325
  }
333
326
  return $('<table>').addClass('table-condensed').append($('<tbody>').append($('<tr>').append(row)));
334
327
  },
@@ -347,6 +340,7 @@
347
340
  if (use24Hours) {
348
341
  template.addClass('usetwentyfour');
349
342
  }
343
+
350
344
  if (isEnabled('s') && !use24Hours) {
351
345
  template.addClass('wider');
352
346
  }
@@ -459,20 +453,20 @@
459
453
  widget.removeClass('pull-right');
460
454
  }
461
455
 
462
- // find the first parent element that has a relative css positioning
463
- if (parent.css('position') !== 'relative') {
456
+ // find the first parent element that has a non-static css positioning
457
+ if (parent.css('position') === 'static') {
464
458
  parent = parent.parents().filter(function () {
465
- return $(this).css('position') === 'relative';
459
+ return $(this).css('position') !== 'static';
466
460
  }).first();
467
461
  }
468
462
 
469
463
  if (parent.length === 0) {
470
- throw new Error('datetimepicker component should be placed within a relative positioned container');
464
+ throw new Error('datetimepicker component should be placed within a non-static positioned container');
471
465
  }
472
466
 
473
467
  widget.css({
474
468
  top: vertical === 'top' ? 'auto' : position.top + element.outerHeight(),
475
- bottom: vertical === 'top' ? position.top + element.outerHeight() : 'auto',
469
+ bottom: vertical === 'top' ? parent.outerHeight() - (parent === element ? 0 : position.top) : 'auto',
476
470
  left: horizontal === 'left' ? (parent === element ? 0 : position.left) : 'auto',
477
471
  right: horizontal === 'left' ? 'auto' : parent.outerWidth() - element.outerWidth() - (parent === element ? 0 : position.left)
478
472
  });
@@ -654,9 +648,12 @@
654
648
  updateDecades = function () {
655
649
  var decadesView = widget.find('.datepicker-decades'),
656
650
  decadesViewHeader = decadesView.find('th'),
657
- startDecade = moment({y: viewDate.year() - (viewDate.year() % 100) - 1}),
651
+ startDecade = moment({ y: viewDate.year() - (viewDate.year() % 100) - 1 }),
658
652
  endDecade = startDecade.clone().add(100, 'y'),
659
653
  startedAt = startDecade.clone(),
654
+ minDateDecade = false,
655
+ maxDateDecade = false,
656
+ endDecadeYear,
660
657
  html = '';
661
658
 
662
659
  decadesViewHeader.eq(0).find('span').attr('title', options.tooltips.prevCentury);
@@ -664,19 +661,22 @@
664
661
 
665
662
  decadesView.find('.disabled').removeClass('disabled');
666
663
 
667
- if (startDecade.isSame(moment({y: 1900})) || (options.minDate && options.minDate.isAfter(startDecade, 'y'))) {
664
+ if (startDecade.isSame(moment({ y: 1900 })) || (options.minDate && options.minDate.isAfter(startDecade, 'y'))) {
668
665
  decadesViewHeader.eq(0).addClass('disabled');
669
666
  }
670
667
 
671
668
  decadesViewHeader.eq(1).text(startDecade.year() + '-' + endDecade.year());
672
669
 
673
- if (startDecade.isSame(moment({y: 2000})) || (options.maxDate && options.maxDate.isBefore(endDecade, 'y'))) {
670
+ if (startDecade.isSame(moment({ y: 2000 })) || (options.maxDate && options.maxDate.isBefore(endDecade, 'y'))) {
674
671
  decadesViewHeader.eq(2).addClass('disabled');
675
672
  }
676
673
 
677
674
  while (!startDecade.isAfter(endDecade, 'y')) {
678
- html += '<span data-action="selectDecade" class="decade' + (startDecade.isSame(date, 'y') ? ' active' : '') +
679
- (!isValid(startDecade, 'y') ? ' disabled' : '') + '" data-selection="' + (startDecade.year() + 6) + '">' + (startDecade.year() + 1) + ' - ' + (startDecade.year() + 12) + '</span>';
675
+ endDecadeYear = startDecade.year() + 12;
676
+ minDateDecade = options.minDate && options.minDate.isAfter(startDecade, 'y') && options.minDate.year() <= endDecadeYear;
677
+ maxDateDecade = options.maxDate && options.maxDate.isAfter(startDecade, 'y') && options.maxDate.year() <= endDecadeYear;
678
+ html += '<span data-action="selectDecade" class="decade' + (date.isAfter(startDecade) && date.year() <= endDecadeYear ? ' active' : '') +
679
+ (!isValid(startDecade, 'y') && !minDateDecade && !maxDateDecade ? ' disabled' : '') + '" data-selection="' + (startDecade.year() + 6) + '">' + (startDecade.year() + 1) + ' - ' + (startDecade.year() + 12) + '</span>';
680
680
  startDecade.add(12, 'y');
681
681
  }
682
682
  html += '<span></span><span></span><span></span>'; //push the dangling block over, at least this way it's even
@@ -691,7 +691,7 @@
691
691
  currentDate,
692
692
  html = [],
693
693
  row,
694
- clsName,
694
+ clsNames = [],
695
695
  i;
696
696
 
697
697
  if (!hasDate()) {
@@ -722,26 +722,31 @@
722
722
  }
723
723
  html.push(row);
724
724
  }
725
- clsName = '';
725
+ clsNames = ['day'];
726
726
  if (currentDate.isBefore(viewDate, 'M')) {
727
- clsName += ' old';
727
+ clsNames.push('old');
728
728
  }
729
729
  if (currentDate.isAfter(viewDate, 'M')) {
730
- clsName += ' new';
730
+ clsNames.push('new');
731
731
  }
732
732
  if (currentDate.isSame(date, 'd') && !unset) {
733
- clsName += ' active';
733
+ clsNames.push('active');
734
734
  }
735
735
  if (!isValid(currentDate, 'd')) {
736
- clsName += ' disabled';
736
+ clsNames.push('disabled');
737
737
  }
738
738
  if (currentDate.isSame(getMoment(), 'd')) {
739
- clsName += ' today';
739
+ clsNames.push('today');
740
740
  }
741
741
  if (currentDate.day() === 0 || currentDate.day() === 6) {
742
- clsName += ' weekend';
742
+ clsNames.push('weekend');
743
743
  }
744
- row.append('<td data-action="selectDay" data-day="' + currentDate.format('L') + '" class="day' + clsName + '">' + currentDate.date() + '</td>');
744
+ notifyEvent({
745
+ type: 'dp.classify',
746
+ date: currentDate,
747
+ classNames: clsNames
748
+ });
749
+ row.append('<td data-action="selectDay" data-day="' + currentDate.format('L') + '" class="' + clsNames.join(' ') + '">' + currentDate.date() + '</td>');
745
750
  currentDate.add(1, 'd');
746
751
  }
747
752
 
@@ -861,8 +866,16 @@
861
866
 
862
867
  targetMoment = targetMoment.clone().locale(options.locale);
863
868
 
869
+ if (hasTimeZone()) {
870
+ targetMoment.tz(options.timeZone);
871
+ }
872
+
864
873
  if (options.stepping !== 1) {
865
- targetMoment.minutes((Math.round(targetMoment.minutes() / options.stepping) * options.stepping) % 60).seconds(0);
874
+ targetMoment.minutes((Math.round(targetMoment.minutes() / options.stepping) * options.stepping)).seconds(0);
875
+
876
+ while (options.minDate && targetMoment.isBefore(options.minDate)) {
877
+ targetMoment.add(options.stepping, 'minutes');
878
+ }
866
879
  }
867
880
 
868
881
  if (isValid(targetMoment)) {
@@ -880,16 +893,25 @@
880
893
  } else {
881
894
  if (!options.keepInvalid) {
882
895
  input.val(unset ? '' : date.format(actualFormat));
896
+ } else {
897
+ notifyEvent({
898
+ type: 'dp.change',
899
+ date: targetMoment,
900
+ oldDate: oldDate
901
+ });
883
902
  }
884
903
  notifyEvent({
885
904
  type: 'dp.error',
886
- date: targetMoment
905
+ date: targetMoment,
906
+ oldDate: oldDate
887
907
  });
888
908
  }
889
909
  },
890
910
 
911
+ /**
912
+ * Hides the widget. Possibly will emit dp.hide
913
+ */
891
914
  hide = function () {
892
- ///<summary>Hides the widget. Possibly will emit dp.hide</summary>
893
915
  var transitioning = false;
894
916
  if (!widget) {
895
917
  return picker;
@@ -925,6 +947,9 @@
925
947
 
926
948
  input.blur();
927
949
 
950
+ currentViewMode = 0;
951
+ viewDate = date.clone();
952
+
928
953
  return picker;
929
954
  },
930
955
 
@@ -932,6 +957,18 @@
932
957
  setValue(null);
933
958
  },
934
959
 
960
+ parseInputDate = function (inputDate) {
961
+ if (options.parseInputDate === undefined) {
962
+ if (!moment.isMoment(inputDate) || inputDate instanceof Date) {
963
+ inputDate = getMoment(inputDate);
964
+ }
965
+ } else {
966
+ inputDate = options.parseInputDate(inputDate);
967
+ }
968
+ //inputDate.locale(options.locale);
969
+ return inputDate;
970
+ },
971
+
935
972
  /********************************************************************************
936
973
  *
937
974
  * Widget UI interaction functions
@@ -1161,8 +1198,10 @@
1161
1198
  return false;
1162
1199
  },
1163
1200
 
1201
+ /**
1202
+ * Shows the widget. Possibly will emit dp.show and dp.change
1203
+ */
1164
1204
  show = function () {
1165
- ///<summary>Shows the widget. Possibly will emit dp.show and dp.change</summary>
1166
1205
  var currentMoment,
1167
1206
  useCurrentGranularity = {
1168
1207
  'year': function (m) {
@@ -1187,14 +1226,13 @@
1187
1226
  }
1188
1227
  if (input.val() !== undefined && input.val().trim().length !== 0) {
1189
1228
  setValue(parseInputDate(input.val().trim()));
1190
- } else if (options.useCurrent && unset && ((input.is('input') && input.val().trim().length === 0) || options.inline)) {
1229
+ } else if (unset && options.useCurrent && (options.inline || (input.is('input') && input.val().trim().length === 0))) {
1191
1230
  currentMoment = getMoment();
1192
1231
  if (typeof options.useCurrent === 'string') {
1193
1232
  currentMoment = useCurrentGranularity[options.useCurrent](currentMoment);
1194
1233
  }
1195
1234
  setValue(currentMoment);
1196
1235
  }
1197
-
1198
1236
  widget = getTemplate();
1199
1237
 
1200
1238
  fillDow();
@@ -1214,9 +1252,8 @@
1214
1252
  if (component && component.hasClass('btn')) {
1215
1253
  component.toggleClass('active');
1216
1254
  }
1217
- widget.show();
1218
1255
  place();
1219
-
1256
+ widget.show();
1220
1257
  if (options.focusOnShow && !input.is(':focus')) {
1221
1258
  input.focus();
1222
1259
  }
@@ -1227,25 +1264,13 @@
1227
1264
  return picker;
1228
1265
  },
1229
1266
 
1267
+ /**
1268
+ * Shows or hides the widget
1269
+ */
1230
1270
  toggle = function () {
1231
- /// <summary>Shows or hides the widget</summary>
1232
1271
  return (widget ? hide() : show());
1233
1272
  },
1234
1273
 
1235
- parseInputDate = function (inputDate) {
1236
- if (options.parseInputDate === undefined) {
1237
- if (moment.isMoment(inputDate) || inputDate instanceof Date) {
1238
- inputDate = moment(inputDate);
1239
- } else {
1240
- inputDate = getMoment(inputDate);
1241
- }
1242
- } else {
1243
- inputDate = options.parseInputDate(inputDate);
1244
- }
1245
- inputDate.locale(options.locale);
1246
- return inputDate;
1247
- },
1248
-
1249
1274
  keydown = function (e) {
1250
1275
  var handler = null,
1251
1276
  index,
@@ -1513,7 +1538,7 @@
1513
1538
  }
1514
1539
 
1515
1540
  if ((typeof newFormat !== 'string') && ((typeof newFormat !== 'boolean') || (newFormat !== false))) {
1516
- throw new TypeError('format() expects a sting or boolean:false parameter ' + newFormat);
1541
+ throw new TypeError('format() expects a string or boolean:false parameter ' + newFormat);
1517
1542
  }
1518
1543
 
1519
1544
  options.format = newFormat;
@@ -1528,6 +1553,10 @@
1528
1553
  return options.timeZone;
1529
1554
  }
1530
1555
 
1556
+ if (typeof newZone !== 'string') {
1557
+ throw new TypeError('newZone() expects a string parameter');
1558
+ }
1559
+
1531
1560
  options.timeZone = newZone;
1532
1561
 
1533
1562
  return picker;
@@ -1645,8 +1674,8 @@
1645
1674
  var tries = 0;
1646
1675
  while (!isValid(date, 'd')) {
1647
1676
  date.add(1, 'd');
1648
- if (tries === 7) {
1649
- throw 'Tried 7 times to find a valid date';
1677
+ if (tries === 31) {
1678
+ throw 'Tried 31 times to find a valid date';
1650
1679
  }
1651
1680
  tries++;
1652
1681
  }
@@ -1748,6 +1777,8 @@
1748
1777
  if (typeof defaultDate === 'string') {
1749
1778
  if (defaultDate === 'now' || defaultDate === 'moment') {
1750
1779
  defaultDate = getMoment();
1780
+ } else {
1781
+ defaultDate = getMoment(defaultDate);
1751
1782
  }
1752
1783
  }
1753
1784
 
@@ -2084,6 +2115,10 @@
2084
2115
  };
2085
2116
 
2086
2117
  picker.keyBinds = function (keyBinds) {
2118
+ if (arguments.length === 0) {
2119
+ return options.keyBinds;
2120
+ }
2121
+
2087
2122
  options.keyBinds = keyBinds;
2088
2123
  return picker;
2089
2124
  };
@@ -2269,16 +2304,12 @@
2269
2304
  update();
2270
2305
  return picker;
2271
2306
  };
2272
-
2307
+ /**
2308
+ * Returns the component's model current viewDate, a moment object or null if not set. 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.
2309
+ * @param {Takes string, viewDate, moment, null parameter.} newDate
2310
+ * @returns {viewDate.clone()}
2311
+ */
2273
2312
  picker.viewDate = function (newDate) {
2274
- ///<signature helpKeyword="$.fn.datetimepicker.viewDate">
2275
- ///<summary>Returns the component's model current viewDate, a moment object or null if not set.</summary>
2276
- ///<returns type="Moment">viewDate.clone()</returns>
2277
- ///</signature>
2278
- ///<signature>
2279
- ///<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>
2280
- ///<param name="newDate" locid="$.fn.datetimepicker.date_p:newDate">Takes string, viewDate, moment, null parameter.</param>
2281
- ///</signature>
2282
2313
  if (arguments.length === 0) {
2283
2314
  return viewDate.clone();
2284
2315
  }
@@ -2302,7 +2333,7 @@
2302
2333
  input = element;
2303
2334
  } else {
2304
2335
  input = element.find(options.datepickerInput);
2305
- if (input.size() === 0) {
2336
+ if (input.length === 0) {
2306
2337
  input = element.find('input');
2307
2338
  } else if (!input.is('input')) {
2308
2339
  throw new Error('CSS class "' + options.datepickerInput + '" cannot be applied to non input element');
@@ -2311,7 +2342,7 @@
2311
2342
 
2312
2343
  if (element.hasClass('input-group')) {
2313
2344
  // in case there is more then one 'input-group-addon' Issue #48
2314
- if (element.find('.datepickerbutton').size() === 0) {
2345
+ if (element.find('.datepickerbutton').length === 0) {
2315
2346
  component = element.find('.input-group-addon');
2316
2347
  } else {
2317
2348
  component = element.find('.datepickerbutton');
@@ -2355,19 +2386,68 @@
2355
2386
  *
2356
2387
  ********************************************************************************/
2357
2388
 
2389
+ /**
2390
+ * See (http://jquery.com/).
2391
+ * @name jQuery
2392
+ * @class
2393
+ * See the jQuery Library (http://jquery.com/) for full details. This just
2394
+ * documents the function and classes that are added to jQuery by this plug-in.
2395
+ */
2396
+ /**
2397
+ * See (http://jquery.com/)
2398
+ * @name fn
2399
+ * @class
2400
+ * See the jQuery Library (http://jquery.com/) for full details. This just
2401
+ * documents the function and classes that are added to jQuery by this plug-in.
2402
+ * @memberOf jQuery
2403
+ */
2404
+ /**
2405
+ * Show comments
2406
+ * @class datetimepicker
2407
+ * @memberOf jQuery.fn
2408
+ */
2358
2409
  $.fn.datetimepicker = function (options) {
2359
- return this.each(function () {
2360
- var $this = $(this);
2361
- if (!$this.data('DateTimePicker')) {
2362
- // create a private copy of the defaults object
2363
- options = $.extend(true, {}, $.fn.datetimepicker.defaults, options);
2364
- $this.data('DateTimePicker', dateTimePicker($this, options));
2365
- }
2366
- });
2410
+ options = options || {};
2411
+
2412
+ var args = Array.prototype.slice.call(arguments, 1),
2413
+ isInstance = true,
2414
+ thisMethods = ['destroy', 'hide', 'show', 'toggle'],
2415
+ returnValue;
2416
+
2417
+ if (typeof options === 'object') {
2418
+ return this.each(function () {
2419
+ var $this = $(this),
2420
+ _options;
2421
+ if (!$this.data('DateTimePicker')) {
2422
+ // create a private copy of the defaults object
2423
+ _options = $.extend(true, {}, $.fn.datetimepicker.defaults, options);
2424
+ $this.data('DateTimePicker', dateTimePicker($this, _options));
2425
+ }
2426
+ });
2427
+ } else if (typeof options === 'string') {
2428
+ this.each(function () {
2429
+ var $this = $(this),
2430
+ instance = $this.data('DateTimePicker');
2431
+ if (!instance) {
2432
+ throw new Error('bootstrap-datetimepicker("' + options + '") method was called on an element that is not using DateTimePicker');
2433
+ }
2434
+
2435
+ returnValue = instance[options].apply(instance, args);
2436
+ isInstance = returnValue === instance;
2437
+ });
2438
+
2439
+ if (isInstance || $.inArray(options, thisMethods) > -1) {
2440
+ return this;
2441
+ }
2442
+
2443
+ return returnValue;
2444
+ }
2445
+
2446
+ throw new TypeError('Invalid arguments for DateTimePicker: ' + options);
2367
2447
  };
2368
2448
 
2369
2449
  $.fn.datetimepicker.defaults = {
2370
- timeZone: 'Etc/UTC',
2450
+ timeZone: '',
2371
2451
  format: false,
2372
2452
  dayViewHeaderFormat: 'MMMM YYYY',
2373
2453
  extraFormats: false,
@@ -2531,6 +2611,9 @@
2531
2611
  // if(toggle.length > 0) toggle.click();
2532
2612
  //},
2533
2613
  'control space': function (widget) {
2614
+ if (!widget) {
2615
+ return;
2616
+ }
2534
2617
  if (widget.find('.timepicker').is(':visible')) {
2535
2618
  widget.find('.btn[data-action="togglePeriod"]').click();
2536
2619
  }
@@ -2549,4 +2632,6 @@
2549
2632
  enabledHours: false,
2550
2633
  viewDate: false
2551
2634
  };
2635
+
2636
+ return $.fn.datetimepicker;
2552
2637
  }));
@@ -1 +1,10 @@
1
1
  $(document).on 'dp.hide', (event) -> $(event.target).trigger('keyup')
2
+
3
+ # When an input with field named "start_*" is changed, set it's corresponding "end_*" minDate
4
+ $(document).on 'dp.change', (event) ->
5
+ $obj = $(event.target)
6
+
7
+ return if $obj.attr('name').indexOf('[start_') == -1
8
+
9
+ end_date = $obj.attr('name').replace('[start_', '[end_')
10
+ try $obj.closest('form').find("input[name='#{end_date}'].initialized").data('DateTimePicker').minDate(event.date)
@@ -1 +1 @@
1
- @import '../effective_date_time_picker/bootstrap-datetimepicker';
1
+ @import '../effective_date_time_picker/input';
@@ -1,12 +1,13 @@
1
1
  /*!
2
2
  * Datetimepicker for Bootstrap 3
3
- * version : 4.17.37
3
+ * version : 4.17.45
4
4
  * https://github.com/Eonasdan/bootstrap-datetimepicker/
5
5
  */
6
6
  .bootstrap-datetimepicker-widget {
7
7
  list-style: none;
8
8
  }
9
9
  .bootstrap-datetimepicker-widget.dropdown-menu {
10
+ display: block;
10
11
  margin: 2px 0;
11
12
  padding: 4px;
12
13
  width: 19em;
@@ -35,7 +36,7 @@
35
36
  .bootstrap-datetimepicker-widget.dropdown-menu.bottom:before {
36
37
  border-left: 7px solid transparent;
37
38
  border-right: 7px solid transparent;
38
- border-bottom: 7px solid #cccccc;
39
+ border-bottom: 7px solid #ccc;
39
40
  border-bottom-color: rgba(0, 0, 0, 0.2);
40
41
  top: -7px;
41
42
  left: 7px;
@@ -50,7 +51,7 @@
50
51
  .bootstrap-datetimepicker-widget.dropdown-menu.top:before {
51
52
  border-left: 7px solid transparent;
52
53
  border-right: 7px solid transparent;
53
- border-top: 7px solid #cccccc;
54
+ border-top: 7px solid #ccc;
54
55
  border-top-color: rgba(0, 0, 0, 0.2);
55
56
  bottom: -7px;
56
57
  left: 6px;
@@ -310,7 +311,7 @@
310
311
  .bootstrap-datetimepicker-widget table td.active,
311
312
  .bootstrap-datetimepicker-widget table td.active:hover {
312
313
  background-color: #337ab7;
313
- color: #ffffff;
314
+ color: #fff;
314
315
  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
315
316
  }
316
317
  .bootstrap-datetimepicker-widget table td.active.today:before {
@@ -336,7 +337,7 @@
336
337
  }
337
338
  .bootstrap-datetimepicker-widget table td span.active {
338
339
  background-color: #337ab7;
339
- color: #ffffff;
340
+ color: #fff;
340
341
  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
341
342
  }
342
343
  .bootstrap-datetimepicker-widget table td span.old {
@@ -1,5 +1,7 @@
1
1
  .bootstrap-datetimepicker-widget {
2
2
  font-weight: normal;
3
+
4
+ .disabled { opacity: 0.5; text-decoration: line-through; }
3
5
  }
4
6
 
5
7
  .bootstrap-datetimepicker-widget table td,
@@ -29,6 +29,27 @@ module Inputs
29
29
  val.kind_of?(Time) ? val.to_date : val
30
30
  end
31
31
 
32
+ def js_options
33
+ opts = super
34
+ return opts unless opts[:disabledDates]
35
+
36
+ opts[:disabledDates] = Array(opts[:disabledDates]).map do |obj|
37
+ if obj.respond_to?(:strftime)
38
+ obj.strftime('%F')
39
+ elsif obj.kind_of?(Range) && obj.first.respond_to?(:strftime)
40
+ [obj.first].tap do |dates|
41
+ dates << (dates.last + 1.day) until (dates.last + 1.day) > obj.last
42
+ end
43
+ elsif obj.kind_of?(String)
44
+ obj
45
+ else
46
+ raise 'unexpected disabledDates data. Expected a DateTime, Range of DateTimes or String'
47
+ end
48
+ end.flatten.compact
49
+
50
+ opts
51
+ end
52
+
32
53
  def html_options
33
54
  super.tap do |html_options|
34
55
  if js_options[:format] == default_input_js[:format] # Unless someone changed from the default
@@ -24,6 +24,27 @@ module Inputs
24
24
  end
25
25
  end
26
26
 
27
+ def js_options
28
+ opts = super
29
+ return opts unless opts[:disabledDates]
30
+
31
+ opts[:disabledDates] = Array(opts[:disabledDates]).map do |obj|
32
+ if obj.respond_to?(:strftime)
33
+ obj.strftime('%F')
34
+ elsif obj.kind_of?(Range) && obj.first.respond_to?(:strftime)
35
+ [obj.first].tap do |dates|
36
+ dates << (dates.last + 1.day) until (dates.last + 1.day) > obj.last
37
+ end
38
+ elsif obj.kind_of?(String)
39
+ obj
40
+ else
41
+ raise 'unexpected disabledDates data. Expected a DateTime, Range of DateTimes or String'
42
+ end
43
+ end.flatten.compact
44
+
45
+ opts
46
+ end
47
+
27
48
  def html_options
28
49
  super.tap do |html_options|
29
50
  if js_options[:format] == default_input_js[:format] # Unless someone changed from the default
@@ -1,3 +1,3 @@
1
1
  module EffectiveFormInputs
2
- VERSION = '1.1.0'.freeze
2
+ VERSION = '1.1.1'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: effective_form_inputs
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Code and Effect
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-05-19 00:00:00.000000000 Z
11
+ date: 2017-06-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails