effective_form_inputs 1.1.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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