86b98694b3fdaba152b1c69458feaf31ae073bafa2d5a990b1d61ad059ab77abb642cefc38dce92be6ed88502fc27317d0c2a09c4c1076acbd93a9460d1439 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. <template>
  2. <transition name="el-zoom-in-top" @after-leave="$emit('dodestroy')">
  3. <div
  4. v-show="visible"
  5. class="el-time-panel el-popper"
  6. :class="popperClass">
  7. <div class="el-time-panel__content" :class="{ 'has-seconds': showSeconds }">
  8. <time-spinner
  9. ref="spinner"
  10. @change="handleChange"
  11. :arrow-control="useArrow"
  12. :show-seconds="showSeconds"
  13. :am-pm-mode="amPmMode"
  14. @select-range="setSelectionRange"
  15. :date="date">
  16. </time-spinner>
  17. </div>
  18. <div class="el-time-panel__footer">
  19. <button
  20. type="button"
  21. class="el-time-panel__btn cancel"
  22. @click="handleCancel">{{ t('el.datepicker.cancel') }}</button>
  23. <button
  24. type="button"
  25. class="el-time-panel__btn"
  26. :class="{confirm: !disabled}"
  27. @click="handleConfirm()">{{ t('el.datepicker.confirm') }}</button>
  28. </div>
  29. </div>
  30. </transition>
  31. </template>
  32. <script type="text/babel">
  33. import { limitTimeRange, isDate, clearMilliseconds, timeWithinRange } from 'element-ui/src/utils/date-util';
  34. import Locale from 'element-ui/src/mixins/locale';
  35. import TimeSpinner from '../basic/time-spinner';
  36. export default {
  37. mixins: [Locale],
  38. components: {
  39. TimeSpinner
  40. },
  41. props: {
  42. visible: Boolean,
  43. timeArrowControl: Boolean
  44. },
  45. watch: {
  46. visible(val) {
  47. if (val) {
  48. this.oldValue = this.value;
  49. this.$nextTick(() => this.$refs.spinner.emitSelectRange('hours'));
  50. } else {
  51. this.needInitAdjust = true;
  52. }
  53. },
  54. value(newVal) {
  55. let date;
  56. if (newVal instanceof Date) {
  57. date = limitTimeRange(newVal, this.selectableRange, this.format);
  58. } else if (!newVal) {
  59. date = this.defaultValue ? new Date(this.defaultValue) : new Date();
  60. }
  61. this.date = date;
  62. if (this.visible && this.needInitAdjust) {
  63. this.$nextTick(_ => this.adjustSpinners());
  64. this.needInitAdjust = false;
  65. }
  66. },
  67. selectableRange(val) {
  68. this.$refs.spinner.selectableRange = val;
  69. },
  70. defaultValue(val) {
  71. if (!isDate(this.value)) {
  72. this.date = val ? new Date(val) : new Date();
  73. }
  74. }
  75. },
  76. data() {
  77. return {
  78. popperClass: '',
  79. format: 'HH:mm:ss',
  80. value: '',
  81. defaultValue: null,
  82. date: new Date(),
  83. oldValue: new Date(),
  84. selectableRange: [],
  85. selectionRange: [0, 2],
  86. disabled: false,
  87. arrowControl: false,
  88. needInitAdjust: true
  89. };
  90. },
  91. computed: {
  92. showSeconds() {
  93. return (this.format || '').indexOf('ss') !== -1;
  94. },
  95. useArrow() {
  96. return this.arrowControl || this.timeArrowControl || false;
  97. },
  98. amPmMode() {
  99. if ((this.format || '').indexOf('A') !== -1) return 'A';
  100. if ((this.format || '').indexOf('a') !== -1) return 'a';
  101. return '';
  102. }
  103. },
  104. methods: {
  105. handleCancel() {
  106. this.$emit('pick', this.oldValue, false);
  107. },
  108. handleChange(date) {
  109. // this.visible avoids edge cases, when use scrolls during panel closing animation
  110. if (this.visible) {
  111. this.date = clearMilliseconds(date);
  112. // if date is out of range, do not emit
  113. if (this.isValidValue(this.date)) {
  114. this.$emit('pick', this.date, true);
  115. }
  116. }
  117. },
  118. setSelectionRange(start, end) {
  119. this.$emit('select-range', start, end);
  120. this.selectionRange = [start, end];
  121. },
  122. handleConfirm(visible = false, first) {
  123. if (first) return;
  124. const date = clearMilliseconds(limitTimeRange(this.date, this.selectableRange, this.format));
  125. this.$emit('pick', date, visible, first);
  126. },
  127. handleKeydown(event) {
  128. const keyCode = event.keyCode;
  129. const mapping = { 38: -1, 40: 1, 37: -1, 39: 1 };
  130. // Left or Right
  131. if (keyCode === 37 || keyCode === 39) {
  132. const step = mapping[keyCode];
  133. this.changeSelectionRange(step);
  134. event.preventDefault();
  135. return;
  136. }
  137. // Up or Down
  138. if (keyCode === 38 || keyCode === 40) {
  139. const step = mapping[keyCode];
  140. this.$refs.spinner.scrollDown(step);
  141. event.preventDefault();
  142. return;
  143. }
  144. },
  145. isValidValue(date) {
  146. return timeWithinRange(date, this.selectableRange, this.format);
  147. },
  148. adjustSpinners() {
  149. return this.$refs.spinner.adjustSpinners();
  150. },
  151. changeSelectionRange(step) {
  152. const list = [0, 3].concat(this.showSeconds ? [6] : []);
  153. const mapping = ['hours', 'minutes'].concat(this.showSeconds ? ['seconds'] : []);
  154. const index = list.indexOf(this.selectionRange[0]);
  155. const next = (index + step + list.length) % list.length;
  156. this.$refs.spinner.emitSelectRange(mapping[next]);
  157. }
  158. },
  159. mounted() {
  160. this.$nextTick(() => this.handleConfirm(true, true));
  161. this.$emit('mounted');
  162. }
  163. };
  164. </script>