datepicker.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. import { TAPi18n } from '/imports/i18n';
  2. import moment from 'moment';
  3. // Helper function to replace HH with H for 24 hours format, because H allows also single-digit hours
  4. function adjustedTimeFormat() {
  5. return moment
  6. .localeData()
  7. .longDateFormat('LT')
  8. .replace(/HH/i, 'H');
  9. }
  10. export class DatePicker extends BlazeComponent {
  11. template() {
  12. return 'datepicker';
  13. }
  14. onCreated(defaultTime = '1970-01-01 08:00:00') {
  15. this.error = new ReactiveVar('');
  16. this.card = this.data();
  17. this.date = new ReactiveVar(moment.invalid());
  18. this.defaultTime = defaultTime;
  19. }
  20. startDayOfWeek() {
  21. const currentUser = Meteor.user();
  22. if (currentUser) {
  23. return currentUser.getStartDayOfWeek();
  24. } else {
  25. return 1;
  26. }
  27. }
  28. onRendered() {
  29. const $picker = this.$('.js-datepicker')
  30. .datepicker({
  31. todayHighlight: true,
  32. todayBtn: 'linked',
  33. language: TAPi18n.getLanguage(),
  34. weekStart: this.startDayOfWeek(),
  35. calendarWeeks: true,
  36. })
  37. .on(
  38. 'changeDate',
  39. function(evt) {
  40. this.find('#date').value = moment(evt.date).format('L');
  41. this.error.set('');
  42. const timeInput = this.find('#time');
  43. timeInput.focus();
  44. if (!timeInput.value && this.defaultTime) {
  45. const currentHour = evt.date.getHours();
  46. const defaultMoment = moment(
  47. currentHour > 0 ? evt.date : this.defaultTime,
  48. ); // default to 8:00 am local time
  49. timeInput.value = defaultMoment.format('LT');
  50. }
  51. }.bind(this),
  52. );
  53. if (this.date.get().isValid()) {
  54. $picker.datepicker('update', this.date.get().toDate());
  55. }
  56. }
  57. showDate() {
  58. if (this.date.get().isValid()) return this.date.get().format('L');
  59. return '';
  60. }
  61. showTime() {
  62. if (this.date.get().isValid()) return this.date.get().format('LT');
  63. return '';
  64. }
  65. dateFormat() {
  66. return moment.localeData().longDateFormat('L');
  67. }
  68. timeFormat() {
  69. return moment.localeData().longDateFormat('LT');
  70. }
  71. events() {
  72. return [
  73. {
  74. 'keyup .js-date-field'() {
  75. // parse for localized date format in strict mode
  76. const dateMoment = moment(this.find('#date').value, 'L', true);
  77. if (dateMoment.isValid()) {
  78. this.error.set('');
  79. this.$('.js-datepicker').datepicker('update', dateMoment.toDate());
  80. }
  81. },
  82. 'keyup .js-time-field'() {
  83. // parse for localized time format in strict mode
  84. const dateMoment = moment(
  85. this.find('#time').value,
  86. adjustedTimeFormat(),
  87. true,
  88. );
  89. if (dateMoment.isValid()) {
  90. this.error.set('');
  91. }
  92. },
  93. 'submit .edit-date'(evt) {
  94. evt.preventDefault();
  95. // if no time was given, init with 12:00
  96. const time =
  97. evt.target.time.value ||
  98. moment(new Date().setHours(12, 0, 0)).format('LT');
  99. const newTime = moment(time, adjustedTimeFormat(), true);
  100. const newDate = moment(evt.target.date.value, 'L', true);
  101. const dateString = `${evt.target.date.value} ${time}`;
  102. const newCompleteDate = moment(
  103. dateString,
  104. `L ${adjustedTimeFormat()}`,
  105. true,
  106. );
  107. if (!newTime.isValid()) {
  108. this.error.set('invalid-time');
  109. evt.target.time.focus();
  110. }
  111. if (!newDate.isValid()) {
  112. this.error.set('invalid-date');
  113. evt.target.date.focus();
  114. }
  115. if (newCompleteDate.isValid()) {
  116. this._storeDate(newCompleteDate.toDate());
  117. Popup.back();
  118. } else if (!this.error) {
  119. this.error.set('invalid');
  120. }
  121. },
  122. 'click .js-delete-date'(evt) {
  123. evt.preventDefault();
  124. this._deleteDate();
  125. Popup.back();
  126. },
  127. },
  128. ];
  129. }
  130. }