mirror of
https://gitee.com/ElemeFE/element.git
synced 2024-12-03 04:39:09 +08:00
*-picker: refactor (#7367)
* Revert "Picker only emit user change (#6214)"
This reverts commit 1912c473ef
.
* picker/util: add helper methods
range: n => Array
modify{Date, Time}: Date => Date
clear{Time, Milliseconds}: Date => Date
limitTimeRange: Date => Date
timeWithinRange: Date, [Date] => Boolean
* time-spinner: refactory
* time-panel: refactory
* picker refactory
* date-panel, *-table: refactory
* time-select: refactory
* test: update time-picker
* test: update date-picker
* time-range: refactory
* date-range: refactory
* test: update time-select
* test: update form date-picker/time-picker
* docs: update date-picker
This commit is contained in:
parent
1e57f25d19
commit
f93798446e
@ -57,7 +57,11 @@
|
|||||||
value4: '',
|
value4: '',
|
||||||
value5: '',
|
value5: '',
|
||||||
value6: '',
|
value6: '',
|
||||||
value7: ''
|
value7: '',
|
||||||
|
value8: '',
|
||||||
|
value9: '',
|
||||||
|
value10: '',
|
||||||
|
value11: ''
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -275,25 +279,116 @@ Picking a date range is supported.
|
|||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
### Default Value
|
||||||
|
|
||||||
|
If user hasn't picked a date, shows today's calendar by default. You can use `default-value` to set another date. Its value should be parsable by `new Date()`.
|
||||||
|
|
||||||
|
If type is `daterange`, `default-value` sets the left side calendar.
|
||||||
|
|
||||||
|
:::demo
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<div class="block">
|
||||||
|
<span class="demonstration">date</span>
|
||||||
|
<el-date-picker
|
||||||
|
v-model="value8"
|
||||||
|
type="date"
|
||||||
|
placeholder="Pick a date"
|
||||||
|
default-value="2010-10-01">
|
||||||
|
</el-date-picker>
|
||||||
|
</div>
|
||||||
|
<div class="block">
|
||||||
|
<span class="demonstration">daterange</span>
|
||||||
|
<el-date-picker
|
||||||
|
v-model="value9"
|
||||||
|
type="daterange"
|
||||||
|
start-placeholder="Start Date"
|
||||||
|
end-placeholder="End Date"
|
||||||
|
default-value="2010-10-01">
|
||||||
|
</el-date-picker>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
value8: '',
|
||||||
|
value9: ''
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
|
||||||
|
### Formatted Value
|
||||||
|
|
||||||
|
By default, DatePicker emits `Date` object. You can use `value-format` to designate the format of emitted value, it accepts the same format string of `format` attribute.
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
This feature is at alpha stage. Feedback welcome.
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::demo
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<div class="block">
|
||||||
|
<span class="demonstration">Emits Date object</span>
|
||||||
|
<div class="demonstration">Value: {{ value10 }}</div>
|
||||||
|
<el-date-picker
|
||||||
|
v-model="value10"
|
||||||
|
type="date"
|
||||||
|
placeholder="Pick a Date"
|
||||||
|
format="yyyy/MM/dd">
|
||||||
|
</el-date-picker>
|
||||||
|
</div>
|
||||||
|
<div class="block">
|
||||||
|
<span class="demonstration">Emits formatted date</span>
|
||||||
|
<div class="demonstration">Value: {{ value11 }}</div>
|
||||||
|
<el-date-picker
|
||||||
|
v-model="value11"
|
||||||
|
type="date"
|
||||||
|
placeholder="Pick a Date"
|
||||||
|
format="yyyy/MM/dd"
|
||||||
|
value-format="yyyy-MM-dd">
|
||||||
|
</el-date-picker>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
value10: '',
|
||||||
|
value11: '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
|
||||||
### Attributes
|
### Attributes
|
||||||
| Attribute | Description | Type | Accepted Values | Default |
|
| Attribute | Description | Type | Accepted Values | Default |
|
||||||
|---------- |-------------- |---------- |-------------------------------- |-------- |
|
|---------- |-------------- |---------- |-------------------------------- |-------- |
|
||||||
| readonly | whether DatePicker is read only | boolean | — | false |
|
| readonly | whether DatePicker is read only | boolean | — | false |
|
||||||
| disabled | whether DatePicker is disabled | boolean | — | false |
|
| disabled | whether DatePicker is disabled | boolean | — | false |
|
||||||
|size | size of Input | string | large/small/mini | — |
|
| size | size of Input | string | large/small/mini | — |
|
||||||
| editable | whether the input is editable | boolean | — | true |
|
| editable | whether the input is editable | boolean | — | true |
|
||||||
| clearable | Whether to show clear button | boolean | — | true |
|
| clearable | Whether to show clear button | boolean | — | true |
|
||||||
| placeholder | placeholder in non-range mode | string | — | — |
|
| placeholder | placeholder in non-range mode | string | — | — |
|
||||||
| start-placeholder | placeholder for the start date in range mode | string | — | — |
|
| start-placeholder | placeholder for the start date in range mode | string | — | — |
|
||||||
| end-placeholder | placeholder for the end date in range mode | string | — | — |
|
| end-placeholder | placeholder for the end date in range mode | string | — | — |
|
||||||
| type | type of the picker | string | year/month/date/datetime/ week/datetimerange/daterange | date |
|
| type | type of the picker | string | year/month/date/datetime/ week/datetimerange/daterange | date |
|
||||||
| format | format of the picker | string | year `yyyy` month `MM` day `dd`, hour `HH`, minute `mm`, second `ss` | yyyy-MM-dd |
|
| format | format of the input box | string | year `yyyy`, month `MM`, day `dd`, hour `HH`, minute `mm`, second `ss` | yyyy-MM-dd |
|
||||||
| align | alignment | left/center/right | left |
|
| align | alignment | left/center/right | left |
|
||||||
| popper-class | custom class name for DatePicker's dropdown | string | — | — |
|
| popper-class | custom class name for DatePicker's dropdown | string | — | — |
|
||||||
| picker-options | additional options, check the table below | object | — | {} |
|
| picker-options | additional options, check the table below | object | — | {} |
|
||||||
| range-separator | range separator | string | - | '-' |
|
| range-separator | range separator | string | — | '-' |
|
||||||
| default-value | optional default time of the picker | Date | anything accepted by `new Date()` | - |
|
| default-value | optional, default date of the calendar | Date | anything accepted by `new Date()` | — |
|
||||||
|name | same as `name` in native input | string | — | — |
|
| value-format | optional, format of bounded value | string | year `yyyy`, month `MM`, day `dd`, hour `HH`, minute `mm`, second `ss` | — |
|
||||||
|
| name | same as `name` in native input | string | — | — |
|
||||||
|
|
||||||
### Picker Options
|
### Picker Options
|
||||||
| Attribute | Description | Type | Accepted Values | Default |
|
| Attribute | Description | Type | Accepted Values | Default |
|
||||||
@ -313,7 +408,7 @@ Picking a date range is supported.
|
|||||||
### Events
|
### Events
|
||||||
| Event Name | Description | Parameters |
|
| Event Name | Description | Parameters |
|
||||||
|---------|--------|---------|
|
|---------|--------|---------|
|
||||||
| change | triggers when input value changes | formatted value |
|
| change | triggers when user confirms the value | component's bounded value |
|
||||||
| blur | triggers when Input blurs | (event: Event) |
|
| blur | triggers when Input blurs | (event: Event) |
|
||||||
| focus | triggers when Input focuses | (event: Event) |
|
| focus | triggers when Input focuses | (event: Event) |
|
||||||
|
|
||||||
|
@ -251,7 +251,9 @@ DateTimePicker is derived from DatePicker and TimePicker. For a more detailed ex
|
|||||||
| popper-class | custom class name for DateTimePicker's dropdown | string | — | — |
|
| popper-class | custom class name for DateTimePicker's dropdown | string | — | — |
|
||||||
| picker-options | additional options, check the table below | object | — | {} |
|
| picker-options | additional options, check the table below | object | — | {} |
|
||||||
| range-separator | range separator | string | - | '-' |
|
| range-separator | range separator | string | - | '-' |
|
||||||
|name | same as `name` in native input | string | — | — |
|
| default-value | optional, default date of the calendar | Date | anything accepted by `new Date()` | — |
|
||||||
|
| value-format | optional, format of bounded value | string | year `yyyy`, month `MM`, day `dd`, hour `HH`, minute `mm`, second `ss` | — |
|
||||||
|
| name | same as `name` in native input | string | — | — |
|
||||||
|
|
||||||
### Picker Options
|
### Picker Options
|
||||||
| Attribute | Description | Type | Accepted Values | Default |
|
| Attribute | Description | Type | Accepted Values | Default |
|
||||||
@ -269,7 +271,7 @@ DateTimePicker is derived from DatePicker and TimePicker. For a more detailed ex
|
|||||||
### Events
|
### Events
|
||||||
| Event Name | Description | Parameters |
|
| Event Name | Description | Parameters |
|
||||||
|---------|--------|---------|
|
|---------|--------|---------|
|
||||||
| change | triggers when input value changes | formatted value |
|
| change | triggers when user confirms the value | component's bounded value |
|
||||||
| blur | triggers when Input blurs | (event: Event) |
|
| blur | triggers when Input blurs | (event: Event) |
|
||||||
| focus | triggers when Input focuses | (event: Event) |
|
| focus | triggers when Input focuses | (event: Event) |
|
||||||
|
|
||||||
|
@ -161,12 +161,14 @@ Can pick an arbitrary time range.
|
|||||||
| placeholder | placeholder in non-range mode | string | — | — |
|
| placeholder | placeholder in non-range mode | string | — | — |
|
||||||
| start-placeholder | placeholder for the start time in range mode | string | — | — |
|
| start-placeholder | placeholder for the start time in range mode | string | — | — |
|
||||||
| end-placeholder | placeholder for the end time in range mode | string | — | — |
|
| end-placeholder | placeholder for the end time in range mode | string | — | — |
|
||||||
| value | value of the picker | date for Time Picker, and string for Time Select | hour `HH`, minute `mm`, second `ss` | HH:mm:ss |
|
| value | value of the picker | Date for Time Picker, and string for Time Select | hour `HH`, minute `mm`, second `ss` | HH:mm:ss |
|
||||||
| align | alignment | left / center / right | left |
|
| align | alignment | left / center / right | left |
|
||||||
| popper-class | custom class name for TimePicker's dropdown | string | — | — |
|
| popper-class | custom class name for TimePicker's dropdown | string | — | — |
|
||||||
| picker-options | additional options, check the table below | object | — | {} |
|
| picker-options | additional options, check the table below | object | — | {} |
|
||||||
| range-separator | range separator | string | - | '-' |
|
| range-separator | range separator | string | - | '-' |
|
||||||
|name | same as `name` in native input | string | — | — |
|
| default-value | optional, default date of the calendar | Date for TimePicker, string for TimeSelect | anything accepted by `new Date()` for TimePicker, selectable value for TimeSelect | — |
|
||||||
|
| value-format | optional, only for TimePicker, format of bounded value | string | hour `HH`, minute `mm`, second `ss` | — |
|
||||||
|
| name | same as `name` in native input | string | — | — |
|
||||||
|
|
||||||
### Time Select Options
|
### Time Select Options
|
||||||
| Attribute | Description | Type | Accepted Values | Default |
|
| Attribute | Description | Type | Accepted Values | Default |
|
||||||
@ -187,6 +189,6 @@ Can pick an arbitrary time range.
|
|||||||
### Events
|
### Events
|
||||||
| Event Name | Description | Parameters |
|
| Event Name | Description | Parameters |
|
||||||
|---------|--------|---------|
|
|---------|--------|---------|
|
||||||
| change | triggers when input value changes | formatted value |
|
| change | triggers when user confirms the value | component's bounded value |
|
||||||
| blur | triggers when Input blurs | (event: Event) |
|
| blur | triggers when Input blurs | (event: Event) |
|
||||||
| focus | triggers when Input focuses | (event: Event) |
|
| focus | triggers when Input focuses | (event: Event) |
|
||||||
|
@ -65,7 +65,11 @@
|
|||||||
value4: '',
|
value4: '',
|
||||||
value5: '',
|
value5: '',
|
||||||
value6: '',
|
value6: '',
|
||||||
value7: ''
|
value7: '',
|
||||||
|
value8: '',
|
||||||
|
value9: '',
|
||||||
|
value10: '',
|
||||||
|
value11: ''
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -285,6 +289,96 @@
|
|||||||
```
|
```
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
### 默认显示日期
|
||||||
|
|
||||||
|
未选择日期时,默认显示今天的日历。使用`default-value`可以指定其他日期,该值需要能够被`new Date()`解析。
|
||||||
|
类型为`daterange`时,指定左侧日历的日期。
|
||||||
|
|
||||||
|
:::demo
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<div class="block">
|
||||||
|
<span class="demonstration">date</span>
|
||||||
|
<el-date-picker
|
||||||
|
v-model="value8"
|
||||||
|
type="date"
|
||||||
|
placeholder="选择日期"
|
||||||
|
default-value="2010-10-01">
|
||||||
|
</el-date-picker>
|
||||||
|
</div>
|
||||||
|
<div class="block">
|
||||||
|
<span class="demonstration">daterange</span>
|
||||||
|
<el-date-picker
|
||||||
|
v-model="value9"
|
||||||
|
type="daterange"
|
||||||
|
start-placeholder="开始日期"
|
||||||
|
end-placeholder="结束日期"
|
||||||
|
default-value="2010-10-01">
|
||||||
|
</el-date-picker>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
value8: '',
|
||||||
|
value9: ''
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
|
||||||
|
### 返回值格式
|
||||||
|
|
||||||
|
默认情况下,组件接受并返回`Date`对象。
|
||||||
|
使用`value-format`指定返回值的格式,支持的格式与`format`相同。
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
该功能处于测试阶段,欢迎提供反馈。
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::demo
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<div class="block">
|
||||||
|
<span class="demonstration">默认为 Date 对象</span>
|
||||||
|
<div class="demonstration">组件值:{{ value10 }}</div>
|
||||||
|
<el-date-picker
|
||||||
|
v-model="value10"
|
||||||
|
type="date"
|
||||||
|
placeholder="选择日期"
|
||||||
|
format="yyyy 年 MM 月 dd 日">
|
||||||
|
</el-date-picker>
|
||||||
|
</div>
|
||||||
|
<div class="block">
|
||||||
|
<span class="demonstration">使用 value-format 进行格式化</span>
|
||||||
|
<div class="demonstration">组件值:{{ value11 }}</div>
|
||||||
|
<el-date-picker
|
||||||
|
v-model="value11"
|
||||||
|
type="date"
|
||||||
|
placeholder="选择日期"
|
||||||
|
format="yyyy 年 MM 月 dd 日"
|
||||||
|
value-format="yyyy-MM-dd">
|
||||||
|
</el-date-picker>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
value10: '',
|
||||||
|
value11: '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
|
||||||
### Attributes
|
### Attributes
|
||||||
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
||||||
|---------- |-------------- |---------- |-------------------------------- |-------- |
|
|---------- |-------------- |---------- |-------------------------------- |-------- |
|
||||||
@ -297,12 +391,13 @@
|
|||||||
| start-placeholder | 范围选择时开始日期的占位内容 | string | — | — |
|
| start-placeholder | 范围选择时开始日期的占位内容 | string | — | — |
|
||||||
| end-placeholder | 范围选择时结束日期的占位内容 | string | — | — |
|
| end-placeholder | 范围选择时结束日期的占位内容 | string | — | — |
|
||||||
| type | 显示类型 | string | year/month/date/week/ datetime/datetimerange/daterange | date |
|
| type | 显示类型 | string | year/month/date/week/ datetime/datetimerange/daterange | date |
|
||||||
| format | 时间日期格式化 | string | 年 `yyyy`,月 `MM`,日 `dd`,小时 `HH`,分 `mm`,秒 `ss` | yyyy-MM-dd |
|
| format | 输入框的时间日期格式 | string | 年 `yyyy`,月 `MM`,日 `dd`,小时 `HH`,分 `mm`,秒 `ss` | yyyy-MM-dd |
|
||||||
| align | 对齐方式 | string | left, center, right | left |
|
| align | 对齐方式 | string | left, center, right | left |
|
||||||
| popper-class | DatePicker 下拉框的类名 | string | — | — |
|
| popper-class | DatePicker 下拉框的类名 | string | — | — |
|
||||||
|picker-options | 当前时间日期选择器特有的选项参考下表 | object | — | {} |
|
| picker-options | 当前时间日期选择器特有的选项参考下表 | object | — | {} |
|
||||||
| range-separator | 选择范围时的分隔符 | string | - | '-' |
|
| range-separator | 选择范围时的分隔符 | string | — | '-' |
|
||||||
| default-value | 可选,DatePicker打开时默认显示的时间 | Date | 可被new Date()解析 | - |
|
| default-value | 可选,选择器打开时默认显示的时间 | Date | 可被`new Date()`解析 | — |
|
||||||
|
| value-format | 可选,绑定值的格式 | string | 年 `yyyy`,月 `MM`,日 `dd`,小时 `HH`,分 `mm`,秒 `ss` | — |
|
||||||
| name | 原生属性 | string | — | — |
|
| name | 原生属性 | string | — | — |
|
||||||
|
|
||||||
### Picker Options
|
### Picker Options
|
||||||
@ -322,7 +417,7 @@
|
|||||||
### Events
|
### Events
|
||||||
| 事件名称 | 说明 | 回调参数 |
|
| 事件名称 | 说明 | 回调参数 |
|
||||||
|---------|--------|---------|
|
|---------|--------|---------|
|
||||||
| change | 当 input 的值改变时触发,返回值和文本框一致 | 格式化后的值 |
|
| change | 用户确认选定的值时触发 | 组件绑定值 |
|
||||||
| blur | 当 input 失去焦点时触发 | (event: Event) |
|
| blur | 当 input 失去焦点时触发 | (event: Event) |
|
||||||
| focus | 当 input 获得焦点时触发 | (event: Event) |
|
| focus | 当 input 获得焦点时触发 | (event: Event) |
|
||||||
|
|
||||||
|
@ -250,6 +250,8 @@ DateTimePicker 由 DatePicker 和 TimePicker 派生,`Picker Options` 或者其
|
|||||||
| popper-class | DateTimePicker 下拉框的类名 | string | — | — |
|
| popper-class | DateTimePicker 下拉框的类名 | string | — | — |
|
||||||
| picker-options | 当前时间日期选择器特有的选项参考下表 | object | — | {} |
|
| picker-options | 当前时间日期选择器特有的选项参考下表 | object | — | {} |
|
||||||
| range-separator | 选择范围时的分隔符 | string | - | '-' |
|
| range-separator | 选择范围时的分隔符 | string | - | '-' |
|
||||||
|
| default-value | 可选,选择器打开时默认显示的时间 | Date | 可被`new Date()`解析 | — |
|
||||||
|
| value-format | 可选,绑定值的格式 | string | 年 `yyyy`,月 `MM`,日 `dd`,小时 `HH`,分 `mm`,秒 `ss` | — |
|
||||||
| name | 原生属性 | string | — | — |
|
| name | 原生属性 | string | — | — |
|
||||||
|
|
||||||
### Picker Options
|
### Picker Options
|
||||||
@ -268,7 +270,7 @@ DateTimePicker 由 DatePicker 和 TimePicker 派生,`Picker Options` 或者其
|
|||||||
### Events
|
### Events
|
||||||
| Event Name | Description | Parameters |
|
| Event Name | Description | Parameters |
|
||||||
|---------|--------|---------|
|
|---------|--------|---------|
|
||||||
| change | 当 input 的值改变时触发,返回值和文本框一致 | formatted value |
|
| change | 用户确认选定的值时触发 | 组件绑定值 |
|
||||||
| blur | 当 input 失去焦点时触发 | (event: Event) |
|
| blur | 当 input 失去焦点时触发 | (event: Event) |
|
||||||
| focus | 当 input 获得焦点时触发 | (event: Event) |
|
| focus | 当 input 获得焦点时触发 | (event: Event) |
|
||||||
|
|
||||||
|
@ -166,6 +166,8 @@
|
|||||||
| popper-class | TimePicker 下拉框的类名 | string | — | — |
|
| popper-class | TimePicker 下拉框的类名 | string | — | — |
|
||||||
| picker-options | 当前时间日期选择器特有的选项参考下表 | object | — | {} |
|
| picker-options | 当前时间日期选择器特有的选项参考下表 | object | — | {} |
|
||||||
| range-separator | 选择范围时的分隔符 | string | - | '-' |
|
| range-separator | 选择范围时的分隔符 | string | - | '-' |
|
||||||
|
| value-format | 可选,仅TimePicker时可用,绑定值的格式,同DatePicker | string | 小时 `HH`,分 `mm`,秒 `ss` | — |
|
||||||
|
| default-value | 可选,选择器打开时默认显示的时间 | Date(TimePicker) / string(TimeSelect) | 可被`new Date()`解析(TimePicker) / 可选值(TimeSelect) | — |
|
||||||
| name | 原生属性 | string | — | — |
|
| name | 原生属性 | string | — | — |
|
||||||
|
|
||||||
### Time Select Options
|
### Time Select Options
|
||||||
@ -186,7 +188,7 @@
|
|||||||
### Events
|
### Events
|
||||||
| 事件名 | 说明 | 参数 |
|
| 事件名 | 说明 | 参数 |
|
||||||
|---------|--------|---------|
|
|---------|--------|---------|
|
||||||
| change | 当 input 的值改变时触发,返回值和文本框一致 | formatted value |
|
| change | 用户确认选定的值时触发 | 组件绑定值 |
|
||||||
| blur | 当 input 失去焦点时触发 | (event: Event) |
|
| blur | 当 input 失去焦点时触发 | (event: Event) |
|
||||||
| focus | 当 input 获得焦点时触发 | (event: Event) |
|
| focus | 当 input 获得焦点时触发 | (event: Event) |
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getFirstDayOfMonth, getDayCountOfMonth, getWeekNumber, getStartDateOfMonth, DAY_DURATION } from '../util';
|
import { getFirstDayOfMonth, getDayCountOfMonth, getWeekNumber, getStartDateOfMonth, DAY_DURATION, isDate } from '../util';
|
||||||
import { hasClass } from 'element-ui/src/utils/dom';
|
import { hasClass } from 'element-ui/src/utils/dom';
|
||||||
import Locale from 'element-ui/src/mixins/locale';
|
import Locale from 'element-ui/src/mixins/locale';
|
||||||
|
|
||||||
@ -51,14 +51,17 @@
|
|||||||
validator: val => val >= 1 && val <= 7
|
validator: val => val >= 1 && val <= 7
|
||||||
},
|
},
|
||||||
|
|
||||||
|
value: {},
|
||||||
|
|
||||||
|
defaultValue: {
|
||||||
|
validator(val) {
|
||||||
|
// either: null, valid Date object, Array of valid Date objects
|
||||||
|
return val === null || isDate(val) || (Array.isArray(val) && val.every(isDate));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
date: {},
|
date: {},
|
||||||
|
|
||||||
year: {},
|
|
||||||
|
|
||||||
month: {},
|
|
||||||
|
|
||||||
week: {},
|
|
||||||
|
|
||||||
selectionMode: {
|
selectionMode: {
|
||||||
default: 'day'
|
default: 'day'
|
||||||
},
|
},
|
||||||
@ -98,8 +101,12 @@
|
|||||||
return WEEKS.concat(WEEKS).slice(week, week + 7);
|
return WEEKS.concat(WEEKS).slice(week, week + 7);
|
||||||
},
|
},
|
||||||
|
|
||||||
monthDate() {
|
year() {
|
||||||
return this.date.getDate();
|
return this.date.getFullYear();
|
||||||
|
},
|
||||||
|
|
||||||
|
month() {
|
||||||
|
return this.date.getMonth();
|
||||||
},
|
},
|
||||||
|
|
||||||
startDate() {
|
startDate() {
|
||||||
@ -107,6 +114,7 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
rows() {
|
rows() {
|
||||||
|
// TODO: refactory rows / getCellClasses
|
||||||
const date = new Date(this.year, this.month, 1);
|
const date = new Date(this.year, this.month, 1);
|
||||||
let day = getFirstDayOfMonth(date); // day of first day
|
let day = getFirstDayOfMonth(date); // day of first day
|
||||||
const dateCountOfMonth = getDayCountOfMonth(date.getFullYear(), date.getMonth());
|
const dateCountOfMonth = getDayCountOfMonth(date.getFullYear(), date.getMonth());
|
||||||
@ -220,7 +228,7 @@
|
|||||||
this.$emit('pick', {
|
this.$emit('pick', {
|
||||||
minDate: this.minDate,
|
minDate: this.minDate,
|
||||||
maxDate: this.maxDate
|
maxDate: this.maxDate
|
||||||
}, true, false);
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -232,9 +240,16 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
cellMatchesDate(cell, date) {
|
||||||
|
const value = new Date(date);
|
||||||
|
return this.year === value.getFullYear() &&
|
||||||
|
this.month === value.getMonth() &&
|
||||||
|
Number(cell.text) === value.getDate();
|
||||||
|
},
|
||||||
|
|
||||||
getCellClasses(cell) {
|
getCellClasses(cell) {
|
||||||
const selectionMode = this.selectionMode;
|
const selectionMode = this.selectionMode;
|
||||||
const monthDate = this.monthDate;
|
const defaultValue = this.defaultValue ? Array.isArray(this.defaultValue) ? this.defaultValue : [this.defaultValue] : [];
|
||||||
|
|
||||||
let classes = [];
|
let classes = [];
|
||||||
if ((cell.type === 'normal' || cell.type === 'today') && !cell.disabled) {
|
if ((cell.type === 'normal' || cell.type === 'today') && !cell.disabled) {
|
||||||
@ -246,8 +261,11 @@
|
|||||||
classes.push(cell.type);
|
classes.push(cell.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectionMode === 'day' && (cell.type === 'normal' || cell.type === 'today') &&
|
if (cell.type === 'normal' && defaultValue.some(date => this.cellMatchesDate(cell, date))) {
|
||||||
Number(this.year) === this.date.getFullYear() && this.month === this.date.getMonth() && monthDate === Number(cell.text)) {
|
classes.push('default');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectionMode === 'day' && (cell.type === 'normal' || cell.type === 'today') && this.cellMatchesDate(cell, this.value)) {
|
||||||
classes.push('current');
|
classes.push('current');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -307,7 +325,7 @@
|
|||||||
|
|
||||||
newDate.setDate(parseInt(cell.text, 10));
|
newDate.setDate(parseInt(cell.text, 10));
|
||||||
|
|
||||||
return getWeekNumber(newDate) === this.week;
|
return getWeekNumber(newDate) === getWeekNumber(this.date);
|
||||||
},
|
},
|
||||||
|
|
||||||
markRange(maxDate) {
|
markRange(maxDate) {
|
||||||
|
@ -49,45 +49,43 @@
|
|||||||
|
|
||||||
<script type="text/babel">
|
<script type="text/babel">
|
||||||
import Locale from 'element-ui/src/mixins/locale';
|
import Locale from 'element-ui/src/mixins/locale';
|
||||||
|
import { isDate, range, getDayCountOfMonth } from '../util';
|
||||||
import { hasClass } from 'element-ui/src/utils/dom';
|
import { hasClass } from 'element-ui/src/utils/dom';
|
||||||
|
|
||||||
|
const datesInMonth = (year, month) => {
|
||||||
|
const numOfDays = getDayCountOfMonth(year, month);
|
||||||
|
const firstDay = new Date(year, month, 1);
|
||||||
|
const ONE_DAY = 8.64e7;
|
||||||
|
return range(numOfDays).map(n => new Date(firstDay.getTime() + n * ONE_DAY));
|
||||||
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
disabledDate: {},
|
disabledDate: {},
|
||||||
date: {},
|
value: {},
|
||||||
month: {
|
defaultValue: {
|
||||||
type: Number
|
validator(val) {
|
||||||
}
|
// null or valid Date Object
|
||||||
|
return val === null || (val instanceof Date && isDate(val));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
date: {}
|
||||||
},
|
},
|
||||||
mixins: [Locale],
|
mixins: [Locale],
|
||||||
methods: {
|
methods: {
|
||||||
getCellStyle(month) {
|
getCellStyle(month) {
|
||||||
const style = {};
|
const style = {};
|
||||||
|
const year = this.date.getFullYear();
|
||||||
|
const today = new Date();
|
||||||
|
|
||||||
var year = this.date.getFullYear();
|
style.disabled = typeof this.disabledDate === 'function'
|
||||||
var date = new Date(0);
|
? datesInMonth(year, month).every(this.disabledDate)
|
||||||
date.setFullYear(year);
|
: false;
|
||||||
date.setMonth(month, 1);
|
style.current = this.value.getFullYear() === year && this.value.getMonth() === month;
|
||||||
date.setHours(0);
|
style.today = today.getFullYear() === year && today.getMonth() === month;
|
||||||
var nextMonth = new Date(date);
|
style.default = this.defaultValue &&
|
||||||
nextMonth.setMonth(month + 1);
|
this.defaultValue.getFullYear() === year &&
|
||||||
|
this.defaultValue.getMonth() === month;
|
||||||
var flag = false;
|
|
||||||
if (typeof this.disabledDate === 'function') {
|
|
||||||
|
|
||||||
while (date < nextMonth) {
|
|
||||||
if (this.disabledDate(date)) {
|
|
||||||
date = new Date(date.getTime() + 8.64e7);
|
|
||||||
flag = true;
|
|
||||||
} else {
|
|
||||||
flag = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
style.disabled = flag;
|
|
||||||
style.current = this.month === month;
|
|
||||||
|
|
||||||
return style;
|
return style;
|
||||||
},
|
},
|
||||||
|
@ -7,9 +7,9 @@
|
|||||||
view-class="el-time-spinner__list"
|
view-class="el-time-spinner__list"
|
||||||
noresize
|
noresize
|
||||||
tag="ul"
|
tag="ul"
|
||||||
ref="hour">
|
ref="hours">
|
||||||
<li
|
<li
|
||||||
@click="handleClick('hours', { value: hour, disabled: disabled }, true)"
|
@click="handleClick('hours', { value: hour, disabled: disabled })"
|
||||||
v-for="(disabled, hour) in hoursList"
|
v-for="(disabled, hour) in hoursList"
|
||||||
track-by="hour"
|
track-by="hour"
|
||||||
class="el-time-spinner__item"
|
class="el-time-spinner__item"
|
||||||
@ -22,9 +22,9 @@
|
|||||||
view-class="el-time-spinner__list"
|
view-class="el-time-spinner__list"
|
||||||
noresize
|
noresize
|
||||||
tag="ul"
|
tag="ul"
|
||||||
ref="minute">
|
ref="minutes">
|
||||||
<li
|
<li
|
||||||
@click="handleClick('minutes', key, true)"
|
@click="handleClick('minutes', { value: key, disabled: false })"
|
||||||
v-for="(minute, key) in 60"
|
v-for="(minute, key) in 60"
|
||||||
class="el-time-spinner__item"
|
class="el-time-spinner__item"
|
||||||
:class="{ 'active': key === minutes }">{{ ('0' + key).slice(-2) }}</li>
|
:class="{ 'active': key === minutes }">{{ ('0' + key).slice(-2) }}</li>
|
||||||
@ -37,9 +37,9 @@
|
|||||||
view-class="el-time-spinner__list"
|
view-class="el-time-spinner__list"
|
||||||
noresize
|
noresize
|
||||||
tag="ul"
|
tag="ul"
|
||||||
ref="second">
|
ref="seconds">
|
||||||
<li
|
<li
|
||||||
@click="handleClick('seconds', key, true)"
|
@click="handleClick('seconds', { value: key, disabled: false })"
|
||||||
v-for="(second, key) in 60"
|
v-for="(second, key) in 60"
|
||||||
class="el-time-spinner__item"
|
class="el-time-spinner__item"
|
||||||
:class="{ 'active': key === seconds }">{{ ('0' + key).slice(-2) }}</li>
|
:class="{ 'active': key === seconds }">{{ ('0' + key).slice(-2) }}</li>
|
||||||
@ -48,83 +48,38 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script type="text/babel">
|
<script type="text/babel">
|
||||||
import { getRangeHours } from '../util';
|
import { getRangeHours, modifyTime } from '../util';
|
||||||
import ElScrollbar from 'element-ui/packages/scrollbar';
|
import ElScrollbar from 'element-ui/packages/scrollbar';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { ElScrollbar },
|
components: { ElScrollbar },
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
hours: {
|
date: {},
|
||||||
type: Number,
|
defaultValue: {}, // reserved for future use
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
|
|
||||||
minutes: {
|
|
||||||
type: Number,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
|
|
||||||
seconds: {
|
|
||||||
type: Number,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
|
|
||||||
showSeconds: {
|
showSeconds: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
|
||||||
hoursPrivate(newVal, oldVal) {
|
|
||||||
if (!(newVal >= 0 && newVal <= 23)) {
|
|
||||||
this.hoursPrivate = oldVal;
|
|
||||||
}
|
|
||||||
this.adjustElTop('hour', newVal);
|
|
||||||
this.$emit('change', { hours: newVal });
|
|
||||||
},
|
|
||||||
|
|
||||||
minutesPrivate(newVal, oldVal) {
|
|
||||||
if (!(newVal >= 0 && newVal <= 59)) {
|
|
||||||
this.minutesPrivate = oldVal;
|
|
||||||
}
|
|
||||||
this.adjustElTop('minute', newVal);
|
|
||||||
this.$emit('change', { minutes: newVal });
|
|
||||||
},
|
|
||||||
|
|
||||||
secondsPrivate(newVal, oldVal) {
|
|
||||||
if (!(newVal >= 0 && newVal <= 59)) {
|
|
||||||
this.secondsPrivate = oldVal;
|
|
||||||
}
|
|
||||||
this.adjustElTop('second', newVal);
|
|
||||||
this.$emit('change', { seconds: newVal });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
|
hours() {
|
||||||
|
return this.date.getHours();
|
||||||
|
},
|
||||||
|
minutes() {
|
||||||
|
return this.date.getMinutes();
|
||||||
|
},
|
||||||
|
seconds() {
|
||||||
|
return this.date.getSeconds();
|
||||||
|
},
|
||||||
hoursList() {
|
hoursList() {
|
||||||
return getRangeHours(this.selectableRange);
|
return getRangeHours(this.selectableRange);
|
||||||
},
|
|
||||||
|
|
||||||
hourEl() {
|
|
||||||
return this.$refs.hour.wrap;
|
|
||||||
},
|
|
||||||
|
|
||||||
minuteEl() {
|
|
||||||
return this.$refs.minute.wrap;
|
|
||||||
},
|
|
||||||
|
|
||||||
secondEl() {
|
|
||||||
return this.$refs.second.wrap;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
hoursPrivate: 0,
|
|
||||||
minutesPrivate: 0,
|
|
||||||
secondsPrivate: 0,
|
|
||||||
selectableRange: [],
|
selectableRange: [],
|
||||||
currentScrollbar: null
|
currentScrollbar: null
|
||||||
};
|
};
|
||||||
@ -137,59 +92,71 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
handleClick(type, value, disabled) {
|
modifyDateField(type, value) {
|
||||||
if (value.disabled) {
|
switch (type) {
|
||||||
return;
|
case 'hours': this.$emit('change', modifyTime(this.date, value, this.minutes, this.seconds)); break;
|
||||||
|
case 'minutes': this.$emit('change', modifyTime(this.date, this.hours, value, this.seconds)); break;
|
||||||
|
case 'seconds': this.$emit('change', modifyTime(this.date, this.hours, this.minutes, value)); break;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
this[type + 'Private'] = value.value >= 0 ? value.value : value;
|
handleClick(type, {value, disabled}) {
|
||||||
|
if (!disabled) {
|
||||||
this.emitSelectRange(type);
|
this.modifyDateField(type, value);
|
||||||
|
this.emitSelectRange(type);
|
||||||
|
this.adjustSpinner(type, value);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
emitSelectRange(type) {
|
emitSelectRange(type) {
|
||||||
if (type === 'hours') {
|
if (type === 'hours') {
|
||||||
this.$emit('select-range', 0, 2);
|
this.$emit('select-range', 0, 2);
|
||||||
this.adjustElTop('minute', this.minutes);
|
this.adjustSpinner('minutes', this.minutes);
|
||||||
this.adjustElTop('second', this.seconds);
|
this.adjustSpinner('seconds', this.seconds);
|
||||||
} else if (type === 'minutes') {
|
} else if (type === 'minutes') {
|
||||||
this.$emit('select-range', 3, 5);
|
this.$emit('select-range', 3, 5);
|
||||||
this.adjustElTop('hour', this.hours);
|
this.adjustSpinner('hours', this.hours);
|
||||||
this.adjustElTop('second', this.seconds);
|
this.adjustSpinner('seconds', this.seconds);
|
||||||
} else if (type === 'seconds') {
|
} else if (type === 'seconds') {
|
||||||
this.$emit('select-range', 6, 8);
|
this.$emit('select-range', 6, 8);
|
||||||
this.adjustElTop('minute', this.minutes);
|
this.adjustSpinner('minutes', this.minutes);
|
||||||
this.adjustElTop('hour', this.hours);
|
this.adjustSpinner('hours', this.hours);
|
||||||
}
|
}
|
||||||
this.currentScrollbar = type;
|
this.currentScrollbar = type;
|
||||||
},
|
},
|
||||||
|
|
||||||
bindScrollEvent() {
|
bindScrollEvent() {
|
||||||
const bindFuntion = (type) => {
|
const bindFuntion = (type) => {
|
||||||
this[`${type}El`].onscroll = (e) => {
|
this.$refs[type].wrap.onscroll = (e) => {
|
||||||
|
// TODO: scroll is emitted when set scrollTop programatically
|
||||||
|
// should find better solutions in the future!
|
||||||
this.handleScroll(type, e);
|
this.handleScroll(type, e);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
bindFuntion('hour');
|
bindFuntion('hours');
|
||||||
bindFuntion('minute');
|
bindFuntion('minutes');
|
||||||
bindFuntion('second');
|
bindFuntion('seconds');
|
||||||
},
|
},
|
||||||
|
|
||||||
handleScroll(type) {
|
handleScroll(type) {
|
||||||
const adjust = {};
|
const value = Math.min(Math.floor((this.$refs[type].wrap.scrollTop - 80) / 32 + 3), (type === 'hours' ? 23 : 59));
|
||||||
adjust[`${type}s`] = Math.min(Math.floor((this[`${type}El`].scrollTop - 80) / 32 + 3), (`${type}` === 'hour' ? 23 : 59));
|
this.modifyDateField(type, value);
|
||||||
this.$emit('change', adjust);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
adjustScrollTop() {
|
// NOTE: used by datetime / date-range panel
|
||||||
this.adjustElTop('hour', this.hours);
|
// renamed from adjustScrollTop
|
||||||
this.adjustElTop('minute', this.minutes);
|
// should try to refactory it
|
||||||
this.adjustElTop('second', this.seconds);
|
adjustSpinners() {
|
||||||
|
this.adjustSpinner('hours', this.hours);
|
||||||
|
this.adjustSpinner('minutes', this.minutes);
|
||||||
|
this.adjustSpinner('seconds', this.seconds);
|
||||||
},
|
},
|
||||||
|
|
||||||
adjustElTop(type, value) {
|
adjustSpinner(type, value) {
|
||||||
if (!this[`${type}El`]) return;
|
const el = this.$refs[type].wrap;
|
||||||
this[`${type}El`].scrollTop = Math.max(0, (value - 2.5) * 32 + 80);
|
if (el) {
|
||||||
|
el.scrollTop = Math.max(0, (value - 2.5) * 32 + 80);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
scrollDown(step) {
|
scrollDown(step) {
|
||||||
@ -217,8 +184,8 @@
|
|||||||
now = (now + step + 60) % 60;
|
now = (now + step + 60) % 60;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$emit('change', { [label]: now });
|
this.modifyDateField(label, now);
|
||||||
this.adjustElTop(label.slice(0, -1), now);
|
this.adjustSpinner(label, now);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -45,62 +45,57 @@
|
|||||||
|
|
||||||
<script type="text/babel">
|
<script type="text/babel">
|
||||||
import { hasClass } from 'element-ui/src/utils/dom';
|
import { hasClass } from 'element-ui/src/utils/dom';
|
||||||
|
import { isDate, range } from '../util';
|
||||||
|
|
||||||
|
const isLeapYear = year => year % 400 === 0 || (year % 100 !== 0 && year % 4 === 0);
|
||||||
|
|
||||||
|
const datesInYear = year => {
|
||||||
|
const numOfDays = isLeapYear(year) ? 366 : 365;
|
||||||
|
const firstDay = new Date(year, 0, 1);
|
||||||
|
const ONE_DAY = 8.64e7;
|
||||||
|
return range(numOfDays).map(n => new Date(firstDay.getTime() + ONE_DAY));
|
||||||
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
disabledDate: {},
|
disabledDate: {},
|
||||||
date: {},
|
value: {},
|
||||||
year: {}
|
defaultValue: {
|
||||||
|
validator(val) {
|
||||||
|
// null or valid Date Object
|
||||||
|
return val === null || (val instanceof Date && isDate(val));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
date: {}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
startYear() {
|
startYear() {
|
||||||
return Math.floor(this.year / 10) * 10;
|
return Math.floor(this.date.getFullYear() / 10) * 10;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
getCellStyle(year) {
|
getCellStyle(year) {
|
||||||
const style = {};
|
const style = {};
|
||||||
|
const today = new Date();
|
||||||
|
|
||||||
var date = new Date(year, 0, 1, 0);
|
style.disabled = typeof this.disabledDate === 'function'
|
||||||
var nextYear = new Date(date);
|
? datesInYear(year).every(this.disabledDate)
|
||||||
nextYear.setFullYear(year + 1);
|
: false;
|
||||||
|
style.current = this.value.getFullYear() === year;
|
||||||
var flag = false;
|
style.today = today.getFullYear() === year;
|
||||||
if (typeof this.disabledDate === 'function') {
|
style.default = this.defaultValue && this.defaultValue.getFullYear() === year;
|
||||||
|
|
||||||
while (date < nextYear) {
|
|
||||||
if (this.disabledDate(date)) {
|
|
||||||
date = new Date(date.getTime() + 8.64e7);
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((date - nextYear) === 0) flag = true;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
style.disabled = flag;
|
|
||||||
style.current = Number(this.year) === year;
|
|
||||||
|
|
||||||
return style;
|
return style;
|
||||||
},
|
},
|
||||||
|
|
||||||
nextTenYear() {
|
|
||||||
this.$emit('pick', Number(this.year) + 10, false, true);
|
|
||||||
},
|
|
||||||
|
|
||||||
prevTenYear() {
|
|
||||||
this.$emit('pick', Number(this.year) - 10, false, true);
|
|
||||||
},
|
|
||||||
|
|
||||||
handleYearTableClick(event) {
|
handleYearTableClick(event) {
|
||||||
const target = event.target;
|
const target = event.target;
|
||||||
if (target.tagName === 'A') {
|
if (target.tagName === 'A') {
|
||||||
if (hasClass(target.parentNode, 'disabled')) return;
|
if (hasClass(target.parentNode, 'disabled')) return;
|
||||||
const year = target.textContent || target.innerText;
|
const year = target.textContent || target.innerText;
|
||||||
this.$emit('pick', Number(year), true, true);
|
this.$emit('pick', Number(year));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,6 @@
|
|||||||
@change.native="handleTimeChange($event, 'min')" />
|
@change.native="handleTimeChange($event, 'min')" />
|
||||||
<time-picker
|
<time-picker
|
||||||
ref="minTimePicker"
|
ref="minTimePicker"
|
||||||
:date="minDate"
|
|
||||||
@pick="handleMinTimePick"
|
@pick="handleMinTimePick"
|
||||||
:visible="minTimePickerVisible"
|
:visible="minTimePickerVisible"
|
||||||
@mounted="$refs.minTimePicker.format=timeFormat">
|
@mounted="$refs.minTimePicker.format=timeFormat">
|
||||||
@ -70,7 +69,6 @@
|
|||||||
@change.native="handleTimeChange($event, 'max')" />
|
@change.native="handleTimeChange($event, 'max')" />
|
||||||
<time-picker
|
<time-picker
|
||||||
ref="maxTimePicker"
|
ref="maxTimePicker"
|
||||||
:date="maxDate"
|
|
||||||
@pick="handleMaxTimePick"
|
@pick="handleMaxTimePick"
|
||||||
:visible="maxTimePickerVisible"
|
:visible="maxTimePickerVisible"
|
||||||
@mounted="$refs.maxTimePicker.format=timeFormat">
|
@mounted="$refs.maxTimePicker.format=timeFormat">
|
||||||
@ -92,9 +90,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<date-table
|
<date-table
|
||||||
selection-mode="range"
|
selection-mode="range"
|
||||||
:date="date"
|
:date="leftDate"
|
||||||
:year="leftYear"
|
:default-value="defaultValue"
|
||||||
:month="leftMonth"
|
|
||||||
:min-date="minDate"
|
:min-date="minDate"
|
||||||
:max-date="maxDate"
|
:max-date="maxDate"
|
||||||
:range-state="rangeState"
|
:range-state="rangeState"
|
||||||
@ -119,8 +116,7 @@
|
|||||||
<date-table
|
<date-table
|
||||||
selection-mode="range"
|
selection-mode="range"
|
||||||
:date="rightDate"
|
:date="rightDate"
|
||||||
:year="rightYear"
|
:default-value="defaultValue"
|
||||||
:month="rightMonth"
|
|
||||||
:min-date="minDate"
|
:min-date="minDate"
|
||||||
:max-date="maxDate"
|
:max-date="maxDate"
|
||||||
:range-state="rangeState"
|
:range-state="rangeState"
|
||||||
@ -147,17 +143,31 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script type="text/babel">
|
<script type="text/babel">
|
||||||
import { nextMonth, prevMonth, toDate, formatDate, parseDate } from '../util';
|
import {
|
||||||
|
formatDate,
|
||||||
|
parseDate,
|
||||||
|
isDate,
|
||||||
|
modifyDate,
|
||||||
|
modifyTime,
|
||||||
|
prevMonth,
|
||||||
|
nextMonth
|
||||||
|
} from '../util';
|
||||||
import Locale from 'element-ui/src/mixins/locale';
|
import Locale from 'element-ui/src/mixins/locale';
|
||||||
import TimePicker from './time';
|
import TimePicker from './time';
|
||||||
import DateTable from '../basic/date-table';
|
import DateTable from '../basic/date-table';
|
||||||
import ElInput from 'element-ui/packages/input';
|
import ElInput from 'element-ui/packages/input';
|
||||||
|
|
||||||
const calcDefaultValue = defaultValue => {
|
const advanceDate = (date, amount) => {
|
||||||
|
return new Date(new Date(date).getTime() + amount);
|
||||||
|
};
|
||||||
|
|
||||||
|
const calcDefaultValue = (defaultValue) => {
|
||||||
if (Array.isArray(defaultValue)) {
|
if (Array.isArray(defaultValue)) {
|
||||||
return defaultValue[0] ? new Date(defaultValue[0]) : new Date();
|
return [new Date(defaultValue[0]), new Date(defaultValue[1])];
|
||||||
|
} else if (defaultValue) {
|
||||||
|
return [new Date(defaultValue), advanceDate(defaultValue, 24 * 60 * 60 * 1000)];
|
||||||
} else {
|
} else {
|
||||||
return new Date(defaultValue);
|
return [new Date(), advanceDate(Date.now, 24 * 60 * 60 * 1000)];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -170,7 +180,7 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
leftLabel() {
|
leftLabel() {
|
||||||
return this.date.getFullYear() + ' ' + this.t('el.datepicker.year') + ' ' + this.t(`el.datepicker.month${ this.date.getMonth() + 1 }`);
|
return this.leftDate.getFullYear() + ' ' + this.t('el.datepicker.year') + ' ' + this.t(`el.datepicker.month${ this.leftDate.getMonth() + 1 }`);
|
||||||
},
|
},
|
||||||
|
|
||||||
rightLabel() {
|
rightLabel() {
|
||||||
@ -178,11 +188,15 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
leftYear() {
|
leftYear() {
|
||||||
return this.date.getFullYear();
|
return this.leftDate.getFullYear();
|
||||||
},
|
},
|
||||||
|
|
||||||
leftMonth() {
|
leftMonth() {
|
||||||
return this.date.getMonth();
|
return this.leftDate.getMonth();
|
||||||
|
},
|
||||||
|
|
||||||
|
leftMonthDate() {
|
||||||
|
return this.leftDate.getDate();
|
||||||
},
|
},
|
||||||
|
|
||||||
rightYear() {
|
rightYear() {
|
||||||
@ -193,6 +207,10 @@
|
|||||||
return this.rightDate.getMonth();
|
return this.rightDate.getMonth();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
rightMonthDate() {
|
||||||
|
return this.rightDate.getDate();
|
||||||
|
},
|
||||||
|
|
||||||
minVisibleDate() {
|
minVisibleDate() {
|
||||||
return this.minDate ? formatDate(this.minDate) : '';
|
return this.minDate ? formatDate(this.minDate) : '';
|
||||||
},
|
},
|
||||||
@ -209,18 +227,12 @@
|
|||||||
return (this.maxDate || this.minDate) ? formatDate(this.maxDate || this.minDate, 'HH:mm:ss') : '';
|
return (this.maxDate || this.minDate) ? formatDate(this.maxDate || this.minDate, 'HH:mm:ss') : '';
|
||||||
},
|
},
|
||||||
|
|
||||||
rightDate() {
|
dateFormat() {
|
||||||
const newDate = new Date(this.date);
|
if (this.format) {
|
||||||
const month = newDate.getMonth();
|
return this.format.replace('HH:mm', '').replace(':ss', '').trim();
|
||||||
newDate.setDate(1);
|
|
||||||
|
|
||||||
if (month === 11) {
|
|
||||||
newDate.setFullYear(newDate.getFullYear() + 1);
|
|
||||||
newDate.setMonth(0);
|
|
||||||
} else {
|
} else {
|
||||||
newDate.setMonth(month + 1);
|
return 'yyyy-MM-dd';
|
||||||
}
|
}
|
||||||
return newDate;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
timeFormat() {
|
timeFormat() {
|
||||||
@ -235,9 +247,12 @@
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
popperClass: '',
|
popperClass: '',
|
||||||
date: this.$options.defaultValue ? calcDefaultValue(this.$options.defaultValue) : new Date(),
|
value: [],
|
||||||
|
defaultValue: null,
|
||||||
minDate: '',
|
minDate: '',
|
||||||
maxDate: '',
|
maxDate: '',
|
||||||
|
leftDate: new Date(),
|
||||||
|
rightDate: nextMonth(new Date()),
|
||||||
rangeState: {
|
rangeState: {
|
||||||
endDate: null,
|
endDate: null,
|
||||||
selecting: false,
|
selecting: false,
|
||||||
@ -246,7 +261,6 @@
|
|||||||
},
|
},
|
||||||
showTime: false,
|
showTime: false,
|
||||||
shortcuts: '',
|
shortcuts: '',
|
||||||
value: '',
|
|
||||||
visible: '',
|
visible: '',
|
||||||
disabledDate: '',
|
disabledDate: '',
|
||||||
firstDayOfWeek: 7,
|
firstDayOfWeek: 7,
|
||||||
@ -257,11 +271,10 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
minDate() {
|
minDate(val) {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
if (this.maxDate && this.maxDate < this.minDate) {
|
if (this.$refs.maxTimePicker && this.maxDate && this.maxDate < this.minDate) {
|
||||||
const format = 'HH:mm:ss';
|
const format = 'HH:mm:ss';
|
||||||
|
|
||||||
this.$refs.maxTimePicker.selectableRange = [
|
this.$refs.maxTimePicker.selectableRange = [
|
||||||
[
|
[
|
||||||
parseDate(formatDate(this.minDate, format), format),
|
parseDate(formatDate(this.minDate, format), format),
|
||||||
@ -270,14 +283,39 @@
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
if (val && this.$refs.minTimePicker) {
|
||||||
|
this.$refs.minTimePicker.date = val;
|
||||||
|
this.$refs.minTimePicker.value = val;
|
||||||
|
this.$refs.minTimePicker.adjustSpinners();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
maxDate(val) {
|
||||||
|
if (val && this.$refs.maxTimePicker) {
|
||||||
|
this.$refs.maxTimePicker.date = val;
|
||||||
|
this.$refs.maxTimePicker.value = val;
|
||||||
|
this.$refs.maxTimePicker.adjustSpinners();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
minTimePickerVisible(val) {
|
minTimePickerVisible(val) {
|
||||||
if (val) this.$nextTick(() => this.$refs.minTimePicker.adjustScrollTop());
|
if (val) {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs.minTimePicker.date = this.minDate;
|
||||||
|
this.$refs.minTimePicker.value = this.minDate;
|
||||||
|
this.$refs.minTimePicker.adjustSpinners();
|
||||||
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
maxTimePickerVisible(val) {
|
maxTimePickerVisible(val) {
|
||||||
if (val) this.$nextTick(() => this.$refs.maxTimePicker.adjustScrollTop());
|
if (val) {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs.maxTimePicker.date = this.maxDate;
|
||||||
|
this.$refs.maxTimePicker.value = this.maxDate;
|
||||||
|
this.$refs.maxTimePicker.adjustSpinners();
|
||||||
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
value(newVal) {
|
value(newVal) {
|
||||||
@ -285,10 +323,24 @@
|
|||||||
this.minDate = null;
|
this.minDate = null;
|
||||||
this.maxDate = null;
|
this.maxDate = null;
|
||||||
} else if (Array.isArray(newVal)) {
|
} else if (Array.isArray(newVal)) {
|
||||||
this.minDate = newVal[0] ? toDate(newVal[0]) : null;
|
this.minDate = isDate(newVal[0]) ? new Date(newVal[0]) : null;
|
||||||
this.maxDate = newVal[1] ? toDate(newVal[1]) : null;
|
this.maxDate = isDate(newVal[1]) ? new Date(newVal[1]) : null;
|
||||||
if (this.minDate) this.date = new Date(this.minDate);
|
// NOTE: currently, maxDate = minDate + 1 month
|
||||||
this.handleConfirm(true, false);
|
// should allow them to be set individually in the future
|
||||||
|
if (this.minDate) {
|
||||||
|
this.leftDate = this.minDate;
|
||||||
|
this.rightDate = nextMonth(this.leftDate);
|
||||||
|
} else {
|
||||||
|
this.leftDate = calcDefaultValue(this.defaultValue)[0];
|
||||||
|
this.rightDate = nextMonth(this.leftDate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
defaultValue(val) {
|
||||||
|
if (!Array.isArray(this.value)) {
|
||||||
|
this.leftDate = calcDefaultValue(val)[0];
|
||||||
|
this.rightDate = nextMonth(this.leftDate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -297,52 +349,52 @@
|
|||||||
handleClear() {
|
handleClear() {
|
||||||
this.minDate = null;
|
this.minDate = null;
|
||||||
this.maxDate = null;
|
this.maxDate = null;
|
||||||
this.date = this.$options.defaultValue ? calcDefaultValue(this.$options.defaultValue) : new Date();
|
this.leftDate = calcDefaultValue(this.defaultValue)[0];
|
||||||
|
this.rightDate = nextMonth(this.leftDate);
|
||||||
this.handleConfirm(false);
|
this.handleConfirm(false);
|
||||||
},
|
},
|
||||||
|
|
||||||
handleDateInput(event, type) {
|
|
||||||
const value = event.target.value;
|
|
||||||
const parsedValue = parseDate(value, 'yyyy-MM-dd');
|
|
||||||
|
|
||||||
if (parsedValue) {
|
|
||||||
if (typeof this.disabledDate === 'function' &&
|
|
||||||
this.disabledDate(new Date(parsedValue))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const target = new Date(type === 'min' ? this.minDate : this.maxDate);
|
|
||||||
if (target) {
|
|
||||||
target.setFullYear(parsedValue.getFullYear());
|
|
||||||
target.setMonth(parsedValue.getMonth(), parsedValue.getDate());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
handleChangeRange(val) {
|
handleChangeRange(val) {
|
||||||
this.minDate = val.minDate;
|
this.minDate = val.minDate;
|
||||||
this.maxDate = val.maxDate;
|
this.maxDate = val.maxDate;
|
||||||
this.rangeState = val.rangeState;
|
this.rangeState = val.rangeState;
|
||||||
},
|
},
|
||||||
|
|
||||||
handleDateChange(event, type) {
|
handleDateInput(event, type) {
|
||||||
const value = event.target.value;
|
const value = event.target.value;
|
||||||
const parsedValue = parseDate(value, 'yyyy-MM-dd');
|
if (value.length !== this.dateFormat.length) return;
|
||||||
|
const parsedValue = parseDate(value, this.dateFormat);
|
||||||
|
|
||||||
if (parsedValue) {
|
if (parsedValue) {
|
||||||
const target = new Date(type === 'min' ? this.minDate : this.maxDate);
|
if (typeof this.disabledDate === 'function' &&
|
||||||
if (target) {
|
this.disabledDate(new Date(parsedValue))) {
|
||||||
target.setFullYear(parsedValue.getFullYear());
|
return;
|
||||||
target.setMonth(parsedValue.getMonth(), parsedValue.getDate());
|
|
||||||
}
|
}
|
||||||
if (type === 'min') {
|
if (type === 'min') {
|
||||||
if (target < this.maxDate) {
|
this.minDate = new Date(parsedValue);
|
||||||
this.minDate = new Date(target.getTime());
|
this.leftDate = new Date(parsedValue);
|
||||||
|
this.rightDate = nextMonth(this.leftDate);
|
||||||
|
} else {
|
||||||
|
this.maxDate = new Date(parsedValue);
|
||||||
|
this.leftDate = prevMonth(parsedValue);
|
||||||
|
this.rightDate = new Date(parsedValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
handleDateChange(event, type) {
|
||||||
|
const value = event.target.value;
|
||||||
|
const parsedValue = parseDate(value, this.dateFormat);
|
||||||
|
if (parsedValue) {
|
||||||
|
if (type === 'min') {
|
||||||
|
this.minDate = modifyDate(this.minDate, parsedValue.getFullYear(), parsedValue.getMonth(), parsedValue.getDate());
|
||||||
|
if (this.minDate > this.maxDate) {
|
||||||
|
this.maxDate = this.minDate;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (target > this.minDate) {
|
this.maxDate = modifyDate(this.maxDate, parsedValue.getFullYear(), parsedValue.getMonth(), parsedValue.getDate());
|
||||||
this.maxDate = new Date(target.getTime());
|
if (this.maxDate < this.minDate) {
|
||||||
if (this.minDate && this.minDate > this.maxDate) {
|
this.minDate = this.maxDate;
|
||||||
this.minDate = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -350,29 +402,27 @@
|
|||||||
|
|
||||||
handleTimeChange(event, type) {
|
handleTimeChange(event, type) {
|
||||||
const value = event.target.value;
|
const value = event.target.value;
|
||||||
const parsedValue = parseDate(value, 'HH:mm:ss');
|
const parsedValue = parseDate(value, this.timeFormat);
|
||||||
if (parsedValue) {
|
if (parsedValue) {
|
||||||
const target = new Date(type === 'min' ? this.minDate : this.maxDate);
|
|
||||||
if (target) {
|
|
||||||
target.setHours(parsedValue.getHours());
|
|
||||||
target.setMinutes(parsedValue.getMinutes());
|
|
||||||
target.setSeconds(parsedValue.getSeconds());
|
|
||||||
}
|
|
||||||
if (type === 'min') {
|
if (type === 'min') {
|
||||||
if (target < this.maxDate) {
|
this.minDate = modifyTime(this.minDate, parsedValue.getHours(), parsedValue.getMinutes(), parsedValue.getSeconds());
|
||||||
this.minDate = new Date(target.getTime());
|
if (this.minDate > this.maxDate) {
|
||||||
|
this.maxDate = this.minDate;
|
||||||
}
|
}
|
||||||
|
this.$refs.minTimePicker.value = this.minDate;
|
||||||
|
this.minTimePickerVisible = false;
|
||||||
} else {
|
} else {
|
||||||
if (target > this.minDate) {
|
this.maxDate = modifyTime(this.maxDate, parsedValue.getHours(), parsedValue.getMinutes(), parsedValue.getSeconds());
|
||||||
this.maxDate = new Date(target.getTime());
|
if (this.maxDate < this.minDate) {
|
||||||
|
this.minDate = this.maxDate;
|
||||||
}
|
}
|
||||||
|
this.$refs.maxTimePicker.value = this.minDate;
|
||||||
|
this.maxTimePickerVisible = false;
|
||||||
}
|
}
|
||||||
this.$refs[type + 'TimePicker'].value = target;
|
|
||||||
this[type + 'TimePickerVisible'] = false;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
handleRangePick(val, close = true, user = true) {
|
handleRangePick(val, close = true) {
|
||||||
if (this.maxDate === val.maxDate && this.minDate === val.minDate) {
|
if (this.maxDate === val.maxDate && this.minDate === val.minDate) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -380,11 +430,7 @@
|
|||||||
this.maxDate = val.maxDate;
|
this.maxDate = val.maxDate;
|
||||||
this.minDate = val.minDate;
|
this.minDate = val.minDate;
|
||||||
if (!close || this.showTime) return;
|
if (!close || this.showTime) return;
|
||||||
this.handleConfirm(false, user);
|
this.handleConfirm();
|
||||||
},
|
|
||||||
|
|
||||||
changeToToday() {
|
|
||||||
this.date = new Date();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
handleShortcutClick(shortcut) {
|
handleShortcutClick(shortcut) {
|
||||||
@ -393,76 +439,68 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
resetView() {
|
handleMinTimePick(value, visible, first) {
|
||||||
this.minTimePickerVisible = false;
|
|
||||||
this.maxTimePickerVisible = false;
|
|
||||||
},
|
|
||||||
|
|
||||||
setTime(date, value) {
|
|
||||||
let oldDate = new Date(date.getTime());
|
|
||||||
let hour = value.getHours();
|
|
||||||
let minute = value.getMinutes();
|
|
||||||
let second = value.getSeconds();
|
|
||||||
oldDate.setHours(hour);
|
|
||||||
oldDate.setMinutes(minute);
|
|
||||||
oldDate.setSeconds(second);
|
|
||||||
return new Date(oldDate.getTime());
|
|
||||||
},
|
|
||||||
|
|
||||||
handleMinTimePick(value, visible, user, first) {
|
|
||||||
this.minDate = this.minDate || new Date();
|
this.minDate = this.minDate || new Date();
|
||||||
if (value) {
|
if (value) {
|
||||||
this.minDate = this.setTime(this.minDate, value);
|
this.minDate = modifyTime(this.minDate, value.getHours(), value.getMinutes(), value.getSeconds());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!first) {
|
if (!first) {
|
||||||
this.minTimePickerVisible = visible;
|
this.minTimePickerVisible = visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.maxDate && this.maxDate.getTime() < this.minDate.getTime()) {
|
||||||
|
this.maxDate = new Date(this.minDate);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
handleMaxTimePick(value, visible, user, first) {
|
handleMaxTimePick(value, visible, first) {
|
||||||
if (!this.maxDate) {
|
|
||||||
const now = new Date();
|
|
||||||
if (now >= this.minDate) {
|
|
||||||
this.maxDate = new Date();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.maxDate && value) {
|
if (this.maxDate && value) {
|
||||||
this.maxDate = this.setTime(this.maxDate, value);
|
this.maxDate = modifyTime(this.maxDate, value.getHours(), value.getMinutes(), value.getSeconds());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!first) {
|
if (!first) {
|
||||||
this.maxTimePickerVisible = visible;
|
this.maxTimePickerVisible = visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.maxDate && this.minDate && this.minDate.getTime() > this.maxDate.getTime()) {
|
||||||
|
this.minDate = new Date(this.maxDate);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
prevMonth() {
|
prevMonth() {
|
||||||
this.date = prevMonth(this.date);
|
this.leftDate = prevMonth(this.leftDate);
|
||||||
|
this.rightDate = nextMonth(this.leftDate);
|
||||||
},
|
},
|
||||||
|
|
||||||
nextMonth() {
|
nextMonth() {
|
||||||
this.date = nextMonth(this.date);
|
this.leftDate = nextMonth(this.leftDate);
|
||||||
|
this.rightDate = nextMonth(this.leftDate);
|
||||||
},
|
},
|
||||||
|
|
||||||
nextYear() {
|
nextYear() {
|
||||||
const date = this.date;
|
this.leftDate = modifyDate(this.leftDate, this.leftYear + 1, this.leftMonth, this.leftMonthDate);
|
||||||
date.setFullYear(date.getFullYear() + 1);
|
this.rightDate = nextMonth(this.leftDate);
|
||||||
this.resetDate();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
prevYear() {
|
prevYear() {
|
||||||
const date = this.date;
|
this.leftDate = modifyDate(this.leftDate, this.leftYear - 1, this.leftMonth, this.leftMonthDate);
|
||||||
date.setFullYear(date.getFullYear() - 1);
|
this.rightDate = nextMonth(this.leftDate);
|
||||||
this.resetDate();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
handleConfirm(visible = false, user = true) {
|
handleConfirm(visible = false) {
|
||||||
this.$emit('pick', [this.minDate, this.maxDate], visible, user);
|
this.$emit('pick', [this.minDate, this.maxDate], visible);
|
||||||
},
|
},
|
||||||
|
|
||||||
resetDate() {
|
isValidValue(value) {
|
||||||
this.date = new Date(this.date);
|
return Array.isArray(value) &&
|
||||||
|
value && value[0] && value[1] &&
|
||||||
|
isDate(value[0]) && isDate(value[1]) &&
|
||||||
|
value[0].getTime() <= value[1].getTime() && (
|
||||||
|
typeof this.disabledDate === 'function'
|
||||||
|
? !this.disabledDate(value[0]) && !this.disabledDate(value[1])
|
||||||
|
: true
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
:placeholder="t('el.datepicker.selectDate')"
|
:placeholder="t('el.datepicker.selectDate')"
|
||||||
:value="visibleDate"
|
:value="visibleDate"
|
||||||
size="small"
|
size="small"
|
||||||
@change.native="visibleDate = $event.target.value" />
|
@change.native="handleVisibleDateChange" />
|
||||||
</span>
|
</span>
|
||||||
<span class="el-date-picker__editor-wrap">
|
<span class="el-date-picker__editor-wrap">
|
||||||
<el-input
|
<el-input
|
||||||
@ -32,7 +32,7 @@
|
|||||||
:placeholder="t('el.datepicker.selectTime')"
|
:placeholder="t('el.datepicker.selectTime')"
|
||||||
:value="visibleTime"
|
:value="visibleTime"
|
||||||
size="small"
|
size="small"
|
||||||
@change.native="visibleTime = $event.target.value" />
|
@change.native="handleVisibleTimeChange" />
|
||||||
<time-picker
|
<time-picker
|
||||||
ref="timepicker"
|
ref="timepicker"
|
||||||
:date="date"
|
:date="date"
|
||||||
@ -82,27 +82,27 @@
|
|||||||
<date-table
|
<date-table
|
||||||
v-show="currentView === 'date'"
|
v-show="currentView === 'date'"
|
||||||
@pick="handleDatePick"
|
@pick="handleDatePick"
|
||||||
:year="year"
|
|
||||||
:month="month"
|
|
||||||
:date="date"
|
|
||||||
:week="week"
|
|
||||||
:selection-mode="selectionMode"
|
:selection-mode="selectionMode"
|
||||||
:first-day-of-week="firstDayOfWeek"
|
:first-day-of-week="firstDayOfWeek"
|
||||||
|
:value="new Date(value)"
|
||||||
|
:default-value="defaultValue ? new Date(defaultValue) : null"
|
||||||
|
:date="date"
|
||||||
:disabled-date="disabledDate">
|
:disabled-date="disabledDate">
|
||||||
</date-table>
|
</date-table>
|
||||||
<year-table
|
<year-table
|
||||||
ref="yearTable"
|
|
||||||
:year="year"
|
|
||||||
:date="date"
|
|
||||||
v-show="currentView === 'year'"
|
v-show="currentView === 'year'"
|
||||||
@pick="handleYearPick"
|
@pick="handleYearPick"
|
||||||
|
:value="new Date(value)"
|
||||||
|
:default-value="defaultValue ? new Date(defaultValue) : null"
|
||||||
|
:date="date"
|
||||||
:disabled-date="disabledDate">
|
:disabled-date="disabledDate">
|
||||||
</year-table>
|
</year-table>
|
||||||
<month-table
|
<month-table
|
||||||
:month="month"
|
|
||||||
:date="date"
|
|
||||||
v-show="currentView === 'month'"
|
v-show="currentView === 'month'"
|
||||||
@pick="handleMonthPick"
|
@pick="handleMonthPick"
|
||||||
|
:value="new Date(value)"
|
||||||
|
:default-value="defaultValue ? new Date(defaultValue) : null"
|
||||||
|
:date="date"
|
||||||
:disabled-date="disabledDate">
|
:disabled-date="disabledDate">
|
||||||
</month-table>
|
</month-table>
|
||||||
</div>
|
</div>
|
||||||
@ -126,7 +126,20 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script type="text/babel">
|
<script type="text/babel">
|
||||||
import { formatDate, parseDate, getWeekNumber } from '../util';
|
import {
|
||||||
|
formatDate,
|
||||||
|
parseDate,
|
||||||
|
getWeekNumber,
|
||||||
|
isDate,
|
||||||
|
modifyDate,
|
||||||
|
modifyTime,
|
||||||
|
clearMilliseconds,
|
||||||
|
clearTime,
|
||||||
|
prevYear,
|
||||||
|
nextYear,
|
||||||
|
prevMonth,
|
||||||
|
nextMonth
|
||||||
|
} from '../util';
|
||||||
import Locale from 'element-ui/src/mixins/locale';
|
import Locale from 'element-ui/src/mixins/locale';
|
||||||
import ElInput from 'element-ui/packages/input';
|
import ElInput from 'element-ui/packages/input';
|
||||||
import TimePicker from './time';
|
import TimePicker from './time';
|
||||||
@ -138,23 +151,33 @@
|
|||||||
mixins: [Locale],
|
mixins: [Locale],
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
value(newVal) {
|
showTime(val) {
|
||||||
if (!newVal) return;
|
/* istanbul ignore if */
|
||||||
newVal = new Date(newVal);
|
if (!val) return;
|
||||||
if (!isNaN(newVal)) {
|
this.$nextTick(_ => {
|
||||||
if (typeof this.disabledDate === 'function' &&
|
const inputElm = this.$refs.input.$el;
|
||||||
this.disabledDate(new Date(newVal))) {
|
if (inputElm) {
|
||||||
return;
|
this.pickerWidth = inputElm.getBoundingClientRect().width + 10;
|
||||||
}
|
}
|
||||||
this.date = newVal;
|
});
|
||||||
this.year = newVal.getFullYear();
|
},
|
||||||
this.month = newVal.getMonth();
|
|
||||||
this.$emit('pick', newVal, false, false);
|
value(val) {
|
||||||
|
if (isDate(val)) {
|
||||||
|
this.date = new Date(val);
|
||||||
|
} else {
|
||||||
|
this.date = this.defaultValue ? new Date(this.defaultValue) : new Date();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
defaultValue(val) {
|
||||||
|
if (!isDate(this.value)) {
|
||||||
|
this.date = val ? new Date(val) : new Date();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
timePickerVisible(val) {
|
timePickerVisible(val) {
|
||||||
if (val) this.$nextTick(() => this.$refs.timepicker.adjustScrollTop());
|
if (val) this.$nextTick(() => this.$refs.timepicker.adjustSpinners());
|
||||||
},
|
},
|
||||||
|
|
||||||
selectionMode(newVal) {
|
selectionMode(newVal) {
|
||||||
@ -166,25 +189,31 @@
|
|||||||
} else if (newVal === 'week') {
|
} else if (newVal === 'week') {
|
||||||
this.week = getWeekNumber(this.date);
|
this.week = getWeekNumber(this.date);
|
||||||
}
|
}
|
||||||
},
|
|
||||||
|
|
||||||
date(newVal) {
|
|
||||||
this.year = newVal.getFullYear();
|
|
||||||
this.month = newVal.getMonth();
|
|
||||||
if (this.selectionMode === 'week') this.week = getWeekNumber(newVal);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
handleClear() {
|
handleClear() {
|
||||||
this.date = this.$options.defaultValue ? new Date(this.$options.defaultValue) : new Date();
|
this.date = this.defaultValue ? new Date(this.defaultValue) : new Date();
|
||||||
this.$emit('pick');
|
this.$emit('pick');
|
||||||
},
|
},
|
||||||
|
|
||||||
resetDate() {
|
emit(value, ...args) {
|
||||||
this.date = new Date(this.date);
|
if (!value) {
|
||||||
|
this.emit('pick', value, ...args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.showTime) {
|
||||||
|
this.$emit('pick', clearMilliseconds(value), ...args);
|
||||||
|
} else {
|
||||||
|
this.$emit('pick', clearTime(value), ...args);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// resetDate() {
|
||||||
|
// this.date = new Date(this.date);
|
||||||
|
// },
|
||||||
|
|
||||||
showMonthPicker() {
|
showMonthPicker() {
|
||||||
this.currentView = 'month';
|
this.currentView = 'month';
|
||||||
},
|
},
|
||||||
@ -203,38 +232,26 @@
|
|||||||
// },
|
// },
|
||||||
|
|
||||||
prevMonth() {
|
prevMonth() {
|
||||||
this.month--;
|
this.date = prevMonth(this.date);
|
||||||
if (this.month < 0) {
|
|
||||||
this.month = 11;
|
|
||||||
this.year--;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
nextMonth() {
|
nextMonth() {
|
||||||
this.month++;
|
this.date = nextMonth(this.date);
|
||||||
if (this.month > 11) {
|
},
|
||||||
this.month = 0;
|
|
||||||
this.year++;
|
prevYear() {
|
||||||
|
if (this.currentView === 'year') {
|
||||||
|
this.date = prevYear(this.date, 10);
|
||||||
|
} else {
|
||||||
|
this.date = prevYear(this.date);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
nextYear() {
|
nextYear() {
|
||||||
if (this.currentView === 'year') {
|
if (this.currentView === 'year') {
|
||||||
this.$refs.yearTable.nextTenYear();
|
this.date = nextYear(this.date, 10);
|
||||||
} else {
|
} else {
|
||||||
this.year++;
|
this.date = nextYear(this.date);
|
||||||
this.date.setFullYear(this.year);
|
|
||||||
this.resetDate();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
prevYear() {
|
|
||||||
if (this.currentView === 'year') {
|
|
||||||
this.$refs.yearTable.prevTenYear();
|
|
||||||
} else {
|
|
||||||
this.year--;
|
|
||||||
this.date.setFullYear(this.year);
|
|
||||||
this.resetDate();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -244,80 +261,61 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
handleTimePick(picker, visible) {
|
handleTimePick(value, visible, first) {
|
||||||
if (picker) {
|
const newDate = modifyTime(this.date, value.getHours(), value.getMinutes(), value.getSeconds());
|
||||||
let oldDate = new Date(this.date.getTime());
|
if (typeof this.disabledDate === 'function' && this.disabledDate(newDate)) {
|
||||||
let hour = picker.getHours();
|
this.$refs.timepicker.disabled = true;
|
||||||
let minute = picker.getMinutes();
|
return;
|
||||||
let second = picker.getSeconds();
|
|
||||||
oldDate.setHours(hour);
|
|
||||||
oldDate.setMinutes(minute);
|
|
||||||
oldDate.setSeconds(second);
|
|
||||||
if (typeof this.disabledDate === 'function' && this.disabledDate(oldDate)) {
|
|
||||||
this.$refs.timepicker.disabled = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.$refs.timepicker.disabled = false;
|
|
||||||
this.date = new Date(oldDate.getTime());
|
|
||||||
}
|
}
|
||||||
|
this.$refs.timepicker.disabled = false;
|
||||||
|
this.date = newDate;
|
||||||
|
this.emit(this.date, true);
|
||||||
|
|
||||||
this.timePickerVisible = visible;
|
if (!first) {
|
||||||
|
this.timePickerVisible = visible;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
handleMonthPick(month) {
|
handleMonthPick(month) {
|
||||||
this.month = month;
|
if (this.selectionMode === 'month') {
|
||||||
const selectionMode = this.selectionMode;
|
this.date = modifyDate(this.date, this.year, month, 1);
|
||||||
if (selectionMode !== 'month') {
|
this.emit(this.date);
|
||||||
this.date.setMonth(month);
|
} else {
|
||||||
|
this.date = modifyDate(this.date, this.year, month, this.monthDate);
|
||||||
|
// TODO: should emit intermediate value ??
|
||||||
|
// this.emit(this.date);
|
||||||
this.currentView = 'date';
|
this.currentView = 'date';
|
||||||
this.resetDate();
|
|
||||||
} else {
|
|
||||||
this.date.setMonth(month);
|
|
||||||
this.year && this.date.setFullYear(this.year);
|
|
||||||
this.resetDate();
|
|
||||||
const value = new Date(this.date.getFullYear(), month, 1);
|
|
||||||
this.$emit('pick', value);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
handleDatePick(value, close, user = true) {
|
handleDatePick(value) {
|
||||||
if (this.selectionMode === 'day') {
|
if (this.selectionMode === 'day') {
|
||||||
if (!this.showTime) {
|
this.date = modifyDate(this.date, value.getFullYear(), value.getMonth(), value.getDate());
|
||||||
this.$emit('pick', new Date(value.getTime()), false, user);
|
this.emit(this.date, this.showTime);
|
||||||
}
|
|
||||||
this.date.setFullYear(value.getFullYear());
|
|
||||||
this.date.setMonth(value.getMonth(), value.getDate());
|
|
||||||
} else if (this.selectionMode === 'week') {
|
} else if (this.selectionMode === 'week') {
|
||||||
this.week = value.week;
|
this.emit(value.date);
|
||||||
this.$emit('pick', value.date, false, user);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.resetDate();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
handleYearPick(year, close = true, user) {
|
handleYearPick(year) {
|
||||||
this.year = year;
|
|
||||||
if (!close) return;
|
|
||||||
|
|
||||||
this.date.setFullYear(year);
|
|
||||||
if (this.selectionMode === 'year') {
|
if (this.selectionMode === 'year') {
|
||||||
this.$emit('pick', new Date(year, 0, 1), false, user);
|
this.date = modifyDate(this.date, year, 0, 1);
|
||||||
|
this.emit(this.date);
|
||||||
} else {
|
} else {
|
||||||
|
this.date = modifyDate(this.date, year, this.month, this.monthDate);
|
||||||
|
// TODO: should emit intermediate value ??
|
||||||
|
// this.emit(this.date, true);
|
||||||
this.currentView = 'month';
|
this.currentView = 'month';
|
||||||
}
|
}
|
||||||
|
|
||||||
this.resetDate();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
changeToNow() {
|
changeToNow() {
|
||||||
this.date.setTime(+new Date());
|
this.date = new Date();
|
||||||
this.$emit('pick', new Date(this.date.getTime()));
|
this.emit(this.date);
|
||||||
this.resetDate();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
confirm() {
|
confirm() {
|
||||||
this.date.setMilliseconds(0);
|
this.emit(this.date);
|
||||||
this.$emit('pick', this.date);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
resetView() {
|
resetView() {
|
||||||
@ -328,24 +326,18 @@
|
|||||||
} else {
|
} else {
|
||||||
this.currentView = 'date';
|
this.currentView = 'date';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.selectionMode !== 'week') {
|
|
||||||
this.year = this.date.getFullYear();
|
|
||||||
this.month = this.date.getMonth();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
handleEnter() {
|
handleEnter() {
|
||||||
document.body.addEventListener('keydown', this.handleKeyDown);
|
document.body.addEventListener('keydown', this.handleKeydown);
|
||||||
},
|
},
|
||||||
|
|
||||||
handleLeave() {
|
handleLeave() {
|
||||||
this.$refs.timepicker && this.$refs.timepicker.$emit('pick');
|
|
||||||
this.$emit('dodestory');
|
this.$emit('dodestory');
|
||||||
document.body.removeEventListener('keydown', this.handleKeyDown);
|
document.body.removeEventListener('keydown', this.handleKeydown);
|
||||||
},
|
},
|
||||||
|
|
||||||
handleKeyDown(e) {
|
handleKeydown(e) {
|
||||||
const keyCode = e.keyCode;
|
const keyCode = e.keyCode;
|
||||||
const list = [38, 40, 37, 39];
|
const list = [38, 40, 37, 39];
|
||||||
if (this.visible && !this.timePickerVisible) {
|
if (this.visible && !this.timePickerVisible) {
|
||||||
@ -354,11 +346,8 @@
|
|||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
|
if (keyCode === 13) { // Enter
|
||||||
if (keyCode === 13) {
|
this.$emit('pick', this.date, false);
|
||||||
this.confirm();
|
|
||||||
event.stopPropagation();
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -389,8 +378,39 @@
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
this.date = newDate;
|
this.date = newDate;
|
||||||
|
this.$emit('pick', newDate, true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
handleVisibleTimeChange(event) {
|
||||||
|
const time = parseDate(event.target.value, this.timeFormat);
|
||||||
|
if (time) {
|
||||||
|
this.date = modifyDate(time, this.year, this.month, this.monthDate);
|
||||||
|
this.$refs.timepicker.value = this.date;
|
||||||
|
this.timePickerVisible = false;
|
||||||
|
this.$emit('pick', this.date, true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
handleVisibleDateChange(event) {
|
||||||
|
const date = parseDate(event.target.value, this.dateFormat);
|
||||||
|
if (date) {
|
||||||
|
if (typeof this.disabledDate === 'function' && this.disabledDate(date)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.date = modifyTime(date, this.date.getHours(), this.date.getMinutes(), this.date.getSeconds());
|
||||||
|
this.resetView();
|
||||||
|
this.$emit('pick', this.date, true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
isValidValue(value) {
|
||||||
|
return value && !isNaN(value) && (
|
||||||
|
typeof this.disabledDate === 'function'
|
||||||
|
? !this.disabledDate(value)
|
||||||
|
: true
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -398,18 +418,12 @@
|
|||||||
TimePicker, YearTable, MonthTable, DateTable, ElInput
|
TimePicker, YearTable, MonthTable, DateTable, ElInput
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
|
||||||
if (this.date && !this.year) {
|
|
||||||
this.year = this.date.getFullYear();
|
|
||||||
this.month = this.date.getMonth();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
popperClass: '',
|
popperClass: '',
|
||||||
date: this.$options.defaultValue ? new Date(this.$options.defaultValue) : new Date(),
|
date: new Date(),
|
||||||
value: '',
|
value: '',
|
||||||
|
defaultValue: null,
|
||||||
showTime: false,
|
showTime: false,
|
||||||
selectionMode: 'day',
|
selectionMode: 'day',
|
||||||
shortcuts: '',
|
shortcuts: '',
|
||||||
@ -417,9 +431,6 @@
|
|||||||
currentView: 'date',
|
currentView: 'date',
|
||||||
disabledDate: '',
|
disabledDate: '',
|
||||||
firstDayOfWeek: 7,
|
firstDayOfWeek: 7,
|
||||||
year: null,
|
|
||||||
month: null,
|
|
||||||
week: null,
|
|
||||||
showWeekNumber: false,
|
showWeekNumber: false,
|
||||||
timePickerVisible: false,
|
timePickerVisible: false,
|
||||||
format: ''
|
format: ''
|
||||||
@ -427,57 +438,40 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
|
year() {
|
||||||
|
return this.date.getFullYear();
|
||||||
|
},
|
||||||
|
|
||||||
|
month() {
|
||||||
|
return this.date.getMonth();
|
||||||
|
},
|
||||||
|
|
||||||
|
week() {
|
||||||
|
return getWeekNumber(this.date);
|
||||||
|
},
|
||||||
|
|
||||||
|
monthDate() {
|
||||||
|
return this.date.getDate();
|
||||||
|
},
|
||||||
|
|
||||||
footerVisible() {
|
footerVisible() {
|
||||||
return this.showTime;
|
return this.showTime;
|
||||||
},
|
},
|
||||||
|
|
||||||
visibleTime: {
|
visibleTime() {
|
||||||
get() {
|
const date = this.value || this.defaultValue;
|
||||||
return formatDate(this.date, this.timeFormat);
|
return date ? formatDate(date, this.timeFormat) : '';
|
||||||
},
|
|
||||||
|
|
||||||
set(val) {
|
|
||||||
if (val) {
|
|
||||||
const date = parseDate(val, this.timeFormat);
|
|
||||||
if (date) {
|
|
||||||
date.setFullYear(this.date.getFullYear());
|
|
||||||
date.setMonth(this.date.getMonth());
|
|
||||||
date.setDate(this.date.getDate());
|
|
||||||
this.date = date;
|
|
||||||
this.$refs.timepicker.value = date;
|
|
||||||
this.timePickerVisible = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
visibleDate: {
|
visibleDate() {
|
||||||
get() {
|
const date = this.value || this.defaultValue;
|
||||||
return formatDate(this.date, this.dateFormat);
|
return date ? formatDate(date, this.dateFormat) : '';
|
||||||
},
|
|
||||||
|
|
||||||
set(val) {
|
|
||||||
const date = parseDate(val, this.dateFormat);
|
|
||||||
if (!date) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (typeof this.disabledDate === 'function' && this.disabledDate(date)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
date.setHours(this.date.getHours());
|
|
||||||
date.setMinutes(this.date.getMinutes());
|
|
||||||
date.setSeconds(this.date.getSeconds());
|
|
||||||
this.date = date;
|
|
||||||
this.resetView();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
yearLabel() {
|
yearLabel() {
|
||||||
const year = this.year;
|
|
||||||
if (!year) return '';
|
|
||||||
const yearTranslation = this.t('el.datepicker.year');
|
const yearTranslation = this.t('el.datepicker.year');
|
||||||
if (this.currentView === 'year') {
|
if (this.currentView === 'year') {
|
||||||
const startYear = Math.floor(year / 10) * 10;
|
const startYear = Math.floor(this.year / 10) * 10;
|
||||||
if (yearTranslation) {
|
if (yearTranslation) {
|
||||||
return startYear + ' ' + yearTranslation + ' - ' + (startYear + 9) + ' ' + yearTranslation;
|
return startYear + ' ' + yearTranslation + ' - ' + (startYear + 9) + ' ' + yearTranslation;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<transition
|
<transition
|
||||||
name="el-zoom-in-top"
|
name="el-zoom-in-top"
|
||||||
@before-enter="panelCreated"
|
|
||||||
@after-leave="$emit('dodestroy')">
|
@after-leave="$emit('dodestroy')">
|
||||||
<div
|
<div
|
||||||
v-show="visible"
|
v-show="visible"
|
||||||
@ -18,9 +17,7 @@
|
|||||||
:show-seconds="showSeconds"
|
:show-seconds="showSeconds"
|
||||||
@change="handleMinChange"
|
@change="handleMinChange"
|
||||||
@select-range="setMinSelectionRange"
|
@select-range="setMinSelectionRange"
|
||||||
:hours="minHours"
|
:date="minDate">
|
||||||
:minutes="minMinutes"
|
|
||||||
:seconds="minSeconds">
|
|
||||||
</time-spinner>
|
</time-spinner>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -34,9 +31,7 @@
|
|||||||
:show-seconds="showSeconds"
|
:show-seconds="showSeconds"
|
||||||
@change="handleMaxChange"
|
@change="handleMaxChange"
|
||||||
@select-range="setMaxSelectionRange"
|
@select-range="setMaxSelectionRange"
|
||||||
:hours="maxHours"
|
:date="maxDate">
|
||||||
:minutes="maxMinutes"
|
|
||||||
:seconds="maxSeconds">
|
|
||||||
</time-spinner>
|
</time-spinner>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -57,27 +52,30 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script type="text/babel">
|
<script type="text/babel">
|
||||||
import { parseDate, limitRange } from '../util';
|
import {
|
||||||
|
parseDate,
|
||||||
|
limitTimeRange,
|
||||||
|
modifyDate,
|
||||||
|
clearMilliseconds,
|
||||||
|
timeWithinRange
|
||||||
|
} from '../util';
|
||||||
import Locale from 'element-ui/src/mixins/locale';
|
import Locale from 'element-ui/src/mixins/locale';
|
||||||
import TimeSpinner from '../basic/time-spinner';
|
import TimeSpinner from '../basic/time-spinner';
|
||||||
|
|
||||||
const MIN_TIME = parseDate('00:00:00', 'HH:mm:ss');
|
const MIN_TIME = parseDate('00:00:00', 'HH:mm:ss');
|
||||||
const MAX_TIME = parseDate('23:59:59', 'HH:mm:ss');
|
const MAX_TIME = parseDate('23:59:59', 'HH:mm:ss');
|
||||||
const isDisabled = function(minTime, maxTime) {
|
|
||||||
const minValue = minTime.getHours() * 3600 + minTime.getMinutes() * 60 + minTime.getSeconds();
|
|
||||||
const maxValue = maxTime.getHours() * 3600 + maxTime.getMinutes() * 60 + maxTime.getSeconds();
|
|
||||||
|
|
||||||
return minValue > maxValue;
|
const minTimeOfDay = function(date) {
|
||||||
|
return modifyDate(MIN_TIME, date.getFullYear(), date.getMonth(), date.getDate());
|
||||||
|
};
|
||||||
|
|
||||||
|
const maxTimeOfDay = function(date) {
|
||||||
|
return modifyDate(MAX_TIME, date.getFullYear(), date.getMonth(), date.getDate());
|
||||||
};
|
};
|
||||||
const clacTime = function(time) {
|
|
||||||
time = Array.isArray(time) ? time : [time];
|
|
||||||
const minTime = time[0] || new Date();
|
|
||||||
const date = new Date();
|
|
||||||
date.setHours(date.getHours() + 1);
|
|
||||||
const maxTime = time[1] || date;
|
|
||||||
|
|
||||||
if (minTime > maxTime) return clacTime();
|
// increase time by amount of milliseconds, but within the range of day
|
||||||
return { minTime, maxTime };
|
const advanceTime = function(date, amount) {
|
||||||
|
return new Date(Math.min(date.getTime() + amount, maxTimeOfDay(date).getTime()));
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -96,25 +94,21 @@
|
|||||||
|
|
||||||
spinner() {
|
spinner() {
|
||||||
return this.selectionRange[0] < this.offset ? this.$refs.minSpinner : this.$refs.maxSpinner;
|
return this.selectionRange[0] < this.offset ? this.$refs.minSpinner : this.$refs.maxSpinner;
|
||||||
|
},
|
||||||
|
|
||||||
|
btnDisabled() {
|
||||||
|
return this.minDate.getTime() > this.maxDate.getTime();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
props: ['value'],
|
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
const time = clacTime(this.$options.defaultValue);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
popperClass: '',
|
popperClass: '',
|
||||||
minTime: time.minTime,
|
minDate: new Date(),
|
||||||
maxTime: time.maxTime,
|
maxDate: new Date(),
|
||||||
btnDisabled: isDisabled(time.minTime, time.maxTime),
|
value: [],
|
||||||
maxHours: time.maxTime.getHours(),
|
oldValue: [new Date(), new Date()],
|
||||||
maxMinutes: time.maxTime.getMinutes(),
|
defaultValue: null,
|
||||||
maxSeconds: time.maxTime.getSeconds(),
|
|
||||||
minHours: time.minTime.getHours(),
|
|
||||||
minMinutes: time.minTime.getMinutes(),
|
|
||||||
minSeconds: time.minTime.getSeconds(),
|
|
||||||
format: 'HH:mm:ss',
|
format: 'HH:mm:ss',
|
||||||
visible: false,
|
visible: false,
|
||||||
selectionRange: [0, 2]
|
selectionRange: [0, 2]
|
||||||
@ -122,89 +116,62 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
value(newVal) {
|
value(value) {
|
||||||
this.panelCreated();
|
if (Array.isArray(value)) {
|
||||||
this.$nextTick(_ => this.adjustScrollTop());
|
this.minDate = new Date(value[0]);
|
||||||
|
this.maxDate = new Date(value[1]);
|
||||||
|
} else {
|
||||||
|
if (Array.isArray(this.defaultValue)) {
|
||||||
|
this.minDate = new Date(this.defaultValue[0]);
|
||||||
|
this.maxDate = new Date(this.defaultValue[1]);
|
||||||
|
} else if (this.defaultValue) {
|
||||||
|
this.minDate = new Date(this.defaultValue);
|
||||||
|
this.maxDate = advanceTime(new Date(this.defaultValue), 60 * 60 * 1000);
|
||||||
|
} else {
|
||||||
|
this.minDate = new Date();
|
||||||
|
this.maxDate = advanceTime(new Date(), 60 * 60 * 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.visible) {
|
||||||
|
this.$nextTick(_ => this.adjustSpinners());
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
visible(val) {
|
visible(val) {
|
||||||
if (val) {
|
if (val) {
|
||||||
|
this.oldValue = this.value;
|
||||||
this.$nextTick(() => this.$refs.minSpinner.emitSelectRange('hours'));
|
this.$nextTick(() => this.$refs.minSpinner.emitSelectRange('hours'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
panelCreated() {
|
|
||||||
const time = clacTime(this.value);
|
|
||||||
if (time.minTime === this.minTime && time.maxTime === this.maxTime) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.handleMinChange({
|
|
||||||
hours: time.minTime.getHours(),
|
|
||||||
minutes: time.minTime.getMinutes(),
|
|
||||||
seconds: time.minTime.getSeconds()
|
|
||||||
}, true);
|
|
||||||
this.handleMaxChange({
|
|
||||||
hours: time.maxTime.getHours(),
|
|
||||||
minutes: time.maxTime.getMinutes(),
|
|
||||||
seconds: time.maxTime.getSeconds()
|
|
||||||
}, true);
|
|
||||||
},
|
|
||||||
|
|
||||||
handleClear() {
|
handleClear() {
|
||||||
this.handleCancel();
|
this.$emit('pick', []);
|
||||||
},
|
},
|
||||||
|
|
||||||
handleCancel() {
|
handleCancel() {
|
||||||
this.$emit('pick');
|
this.$emit('pick', this.oldValue);
|
||||||
},
|
},
|
||||||
|
|
||||||
handleChange(notUser) {
|
handleMinChange(date) {
|
||||||
if (this.minTime > this.maxTime) return;
|
this.minDate = clearMilliseconds(date);
|
||||||
MIN_TIME.setFullYear(this.minTime.getFullYear());
|
|
||||||
MIN_TIME.setMonth(this.minTime.getMonth(), this.minTime.getDate());
|
|
||||||
MAX_TIME.setFullYear(this.maxTime.getFullYear());
|
|
||||||
MAX_TIME.setMonth(this.maxTime.getMonth(), this.maxTime.getDate());
|
|
||||||
this.$refs.minSpinner.selectableRange = [[MIN_TIME, this.maxTime]];
|
|
||||||
this.$refs.maxSpinner.selectableRange = [[this.minTime, MAX_TIME]];
|
|
||||||
this.handleConfirm(true, false, notUser);
|
|
||||||
},
|
|
||||||
|
|
||||||
handleMaxChange(date, notUser) {
|
|
||||||
if (date.hours !== undefined) {
|
|
||||||
this.maxTime.setHours(date.hours);
|
|
||||||
this.maxHours = this.maxTime.getHours();
|
|
||||||
}
|
|
||||||
if (date.minutes !== undefined) {
|
|
||||||
this.maxTime.setMinutes(date.minutes);
|
|
||||||
this.maxMinutes = this.maxTime.getMinutes();
|
|
||||||
}
|
|
||||||
if (date.seconds !== undefined) {
|
|
||||||
this.maxTime.setSeconds(date.seconds);
|
|
||||||
this.maxSeconds = this.maxTime.getSeconds();
|
|
||||||
}
|
|
||||||
this.handleChange();
|
this.handleChange();
|
||||||
},
|
},
|
||||||
|
|
||||||
handleMinChange(date, notUser) {
|
handleMaxChange(date) {
|
||||||
if (date.hours !== undefined) {
|
this.maxDate = clearMilliseconds(date);
|
||||||
this.minTime.setHours(date.hours);
|
|
||||||
this.minHours = this.minTime.getHours();
|
|
||||||
}
|
|
||||||
if (date.minutes !== undefined) {
|
|
||||||
this.minTime.setMinutes(date.minutes);
|
|
||||||
this.minMinutes = this.minTime.getMinutes();
|
|
||||||
}
|
|
||||||
if (date.seconds !== undefined) {
|
|
||||||
this.minTime.setSeconds(date.seconds);
|
|
||||||
this.minSeconds = this.minTime.getSeconds();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.handleChange();
|
this.handleChange();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
handleChange() {
|
||||||
|
if (this.isValidValue([this.minDate, this.maxDate])) {
|
||||||
|
this.$refs.minSpinner.selectableRange = [[minTimeOfDay(this.minDate), this.maxDate]];
|
||||||
|
this.$refs.maxSpinner.selectableRange = [[this.minDate, maxTimeOfDay(this.maxDate)]];
|
||||||
|
this.$emit('pick', [this.minDate, this.maxDate], true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
setMinSelectionRange(start, end) {
|
setMinSelectionRange(start, end) {
|
||||||
this.$emit('select-range', start, end, 'min');
|
this.$emit('select-range', start, end, 'min');
|
||||||
this.selectionRange = [start, end];
|
this.selectionRange = [start, end];
|
||||||
@ -215,24 +182,19 @@
|
|||||||
this.selectionRange = [start + this.offset, end + this.offset];
|
this.selectionRange = [start + this.offset, end + this.offset];
|
||||||
},
|
},
|
||||||
|
|
||||||
handleConfirm(visible = false, first = false, notUser = false) {
|
handleConfirm(visible = false) {
|
||||||
const minSelectableRange = this.$refs.minSpinner.selectableRange;
|
const minSelectableRange = this.$refs.minSpinner.selectableRange;
|
||||||
const maxSelectableRange = this.$refs.maxSpinner.selectableRange;
|
const maxSelectableRange = this.$refs.maxSpinner.selectableRange;
|
||||||
|
|
||||||
this.minTime = limitRange(this.minTime, minSelectableRange);
|
this.minDate = limitTimeRange(this.minDate, minSelectableRange, this.format);
|
||||||
this.maxTime = limitRange(this.maxTime, maxSelectableRange);
|
this.maxDate = limitTimeRange(this.maxDate, maxSelectableRange, this.format);
|
||||||
|
|
||||||
if (first) return;
|
this.$emit('pick', [this.minDate, this.maxDate], visible);
|
||||||
this.$emit('pick', [this.minTime, this.maxTime], visible, !notUser);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
adjustScrollTop() {
|
adjustSpinners() {
|
||||||
this.$refs.minSpinner.adjustScrollTop();
|
this.$refs.minSpinner.adjustSpinners();
|
||||||
this.$refs.maxSpinner.adjustScrollTop();
|
this.$refs.maxSpinner.adjustSpinners();
|
||||||
},
|
|
||||||
|
|
||||||
scrollDown(step) {
|
|
||||||
this.spinner.scrollDown(step);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
changeSelectionRange(step) {
|
changeSelectionRange(step) {
|
||||||
@ -246,11 +208,34 @@
|
|||||||
} else {
|
} else {
|
||||||
this.$refs.maxSpinner.emitSelectRange(mapping[next - half]);
|
this.$refs.maxSpinner.emitSelectRange(mapping[next - half]);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
|
||||||
|
|
||||||
mounted() {
|
isValidValue(date) {
|
||||||
this.$nextTick(() => this.handleConfirm(true, true));
|
return Array.isArray(date) &&
|
||||||
|
timeWithinRange(this.minDate, this.$refs.minSpinner.selectableRange) &&
|
||||||
|
timeWithinRange(this.maxDate, this.$refs.maxSpinner.selectableRange);
|
||||||
|
},
|
||||||
|
|
||||||
|
handleKeydown(event) {
|
||||||
|
const keyCode = event.keyCode;
|
||||||
|
const mapping = { 38: -1, 40: 1, 37: -1, 39: 1 };
|
||||||
|
|
||||||
|
// Left or Right
|
||||||
|
if (keyCode === 37 || keyCode === 39) {
|
||||||
|
const step = mapping[keyCode];
|
||||||
|
this.changeSelectionRange(step);
|
||||||
|
event.preventDefault();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Up or Down
|
||||||
|
if (keyCode === 38 || keyCode === 40) {
|
||||||
|
const step = mapping[keyCode];
|
||||||
|
this.spinner.scrollDown(step);
|
||||||
|
event.preventDefault();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
<el-scrollbar noresize wrap-class="el-picker-panel__content">
|
<el-scrollbar noresize wrap-class="el-picker-panel__content">
|
||||||
<div class="time-select-item"
|
<div class="time-select-item"
|
||||||
v-for="item in items"
|
v-for="item in items"
|
||||||
:class="{ selected: value === item.value, disabled: item.disabled }"
|
:class="{ selected: value === item.value, disabled: item.disabled, default: item.value === defaultValue }"
|
||||||
:disabled="item.disabled"
|
:disabled="item.disabled"
|
||||||
@click="handleClick(item)">{{ item.value }}</div>
|
@click="handleClick(item)">{{ item.value }}</div>
|
||||||
</el-scrollbar>
|
</el-scrollbar>
|
||||||
@ -78,11 +78,6 @@
|
|||||||
watch: {
|
watch: {
|
||||||
value(val) {
|
value(val) {
|
||||||
if (!val) return;
|
if (!val) return;
|
||||||
if (this.minTime && compareTime(val, this.minTime) < 0) {
|
|
||||||
this.$emit('pick', '', false, false);
|
|
||||||
} else if (this.maxTime && compareTime(val, this.maxTime) > 0) {
|
|
||||||
this.$emit('pick', '', false, false);
|
|
||||||
}
|
|
||||||
this.$nextTick(() => this.scrollToOption());
|
this.$nextTick(() => this.scrollToOption());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -95,34 +90,47 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
handleClear() {
|
handleClear() {
|
||||||
this.$emit('pick', '', false, false);
|
this.$emit('pick');
|
||||||
},
|
},
|
||||||
|
|
||||||
scrollToOption(className = 'selected') {
|
scrollToOption(selector = '.selected') {
|
||||||
const menu = this.$refs.popper.querySelector('.el-picker-panel__content');
|
const menu = this.$refs.popper.querySelector('.el-picker-panel__content');
|
||||||
scrollIntoView(menu, menu.getElementsByClassName(className)[0]);
|
scrollIntoView(menu, menu.querySelector(selector));
|
||||||
},
|
},
|
||||||
|
|
||||||
handleMenuEnter() {
|
handleMenuEnter() {
|
||||||
this.$nextTick(() => this.scrollToOption());
|
const selected = this.items.map(item => item.value).indexOf(this.value) !== -1;
|
||||||
|
const hasDefault = this.items.map(item => item.value).indexOf(this.defaultValue) !== -1;
|
||||||
|
const option = (selected && '.selected') || (hasDefault && '.default') || '.time-select-item:not(.disabled)';
|
||||||
|
this.$nextTick(() => this.scrollToOption(option));
|
||||||
},
|
},
|
||||||
|
|
||||||
scrollDown(step) {
|
scrollDown(step) {
|
||||||
const items = this.items;
|
const items = this.items;
|
||||||
|
const length = items.length;
|
||||||
|
let total = items.length;
|
||||||
let index = items.map(item => item.value).indexOf(this.value);
|
let index = items.map(item => item.value).indexOf(this.value);
|
||||||
let length = items.length;
|
while (total--) {
|
||||||
let total = Math.abs(step);
|
index = (index + step + length) % length;
|
||||||
step = step > 0 ? 1 : -1;
|
if (!items[index].disabled) {
|
||||||
while (length-- && total) {
|
this.$emit('pick', items[index].value, true);
|
||||||
index = (index + step + items.length) % items.length;
|
return;
|
||||||
const item = items[index];
|
|
||||||
if (!item.disabled) {
|
|
||||||
total--;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!items[index].disabled) {
|
},
|
||||||
this.value = items[index].value;
|
|
||||||
this.$emit('pick', this.value, true);
|
isValidValue(date) {
|
||||||
|
return this.items.filter(item => !item.disabled).map(item => item.value).indexOf(date) !== -1;
|
||||||
|
},
|
||||||
|
|
||||||
|
handleKeydown(event) {
|
||||||
|
const keyCode = event.keyCode;
|
||||||
|
if (keyCode === 38 || keyCode === 40) {
|
||||||
|
const mapping = { 40: 1, 38: -1 };
|
||||||
|
const offset = mapping[keyCode.toString()];
|
||||||
|
this.scrollDown(offset);
|
||||||
|
event.stopPropagation();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -134,6 +142,7 @@
|
|||||||
end: '18:00',
|
end: '18:00',
|
||||||
step: '00:30',
|
step: '00:30',
|
||||||
value: '',
|
value: '',
|
||||||
|
defaultValue: '',
|
||||||
visible: false,
|
visible: false,
|
||||||
minTime: '',
|
minTime: '',
|
||||||
maxTime: '',
|
maxTime: '',
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<transition name="el-zoom-in-top" @after-leave="$emit('dodestroy')">
|
<transition name="el-zoom-in-top" @after-leave="$emit('dodestroy')">
|
||||||
<div
|
<div
|
||||||
v-show="currentVisible"
|
v-show="visible"
|
||||||
class="el-time-panel el-popper"
|
class="el-time-panel el-popper"
|
||||||
:class="popperClass">
|
:class="popperClass">
|
||||||
<div class="el-time-panel__content" :class="{ 'has-seconds': showSeconds }">
|
<div class="el-time-panel__content" :class="{ 'has-seconds': showSeconds }">
|
||||||
@ -10,9 +10,7 @@
|
|||||||
@change="handleChange"
|
@change="handleChange"
|
||||||
:show-seconds="showSeconds"
|
:show-seconds="showSeconds"
|
||||||
@select-range="setSelectionRange"
|
@select-range="setSelectionRange"
|
||||||
:hours="hours"
|
:date="date">
|
||||||
:minutes="minutes"
|
|
||||||
:seconds="seconds">
|
|
||||||
</time-spinner>
|
</time-spinner>
|
||||||
</div>
|
</div>
|
||||||
<div class="el-time-panel__footer">
|
<div class="el-time-panel__footer">
|
||||||
@ -31,7 +29,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script type="text/babel">
|
<script type="text/babel">
|
||||||
import { limitRange } from '../util';
|
import { limitTimeRange, isDate, clearMilliseconds, timeWithinRange } from '../util';
|
||||||
import Locale from 'element-ui/src/mixins/locale';
|
import Locale from 'element-ui/src/mixins/locale';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -42,21 +40,13 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
date: {
|
|
||||||
default() {
|
|
||||||
return new Date();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
visible: Boolean
|
visible: Boolean
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
visible(val) {
|
visible(val) {
|
||||||
this.currentVisible = val;
|
|
||||||
if (val) {
|
if (val) {
|
||||||
this.oldHours = this.hours;
|
this.oldValue = this.value;
|
||||||
this.oldMinutes = this.minutes;
|
|
||||||
this.oldSeconds = this.seconds;
|
|
||||||
this.$nextTick(() => this.$refs.spinner.emitSelectRange('hours'));
|
this.$nextTick(() => this.$refs.spinner.emitSelectRange('hours'));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -64,27 +54,25 @@
|
|||||||
value(newVal) {
|
value(newVal) {
|
||||||
let date;
|
let date;
|
||||||
if (newVal instanceof Date) {
|
if (newVal instanceof Date) {
|
||||||
date = limitRange(newVal, this.selectableRange);
|
date = limitTimeRange(newVal, this.selectableRange, this.format);
|
||||||
} else if (!newVal) {
|
} else if (!newVal) {
|
||||||
date = new Date();
|
date = this.defaultValue ? new Date(this.defaultValue) : new Date();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.handleChange({
|
this.date = date;
|
||||||
hours: date.getHours(),
|
if (this.visible) {
|
||||||
minutes: date.getMinutes(),
|
this.$nextTick(_ => this.adjustSpinners());
|
||||||
seconds: date.getSeconds()
|
}
|
||||||
}, true);
|
|
||||||
this.$nextTick(_ => this.adjustScrollTop());
|
|
||||||
},
|
},
|
||||||
|
|
||||||
selectableRange(val) {
|
selectableRange(val) {
|
||||||
this.$refs.spinner.selectableRange = val;
|
this.$refs.spinner.selectableRange = val;
|
||||||
},
|
},
|
||||||
|
|
||||||
date(val) {
|
defaultValue(val) {
|
||||||
if (!val) return;
|
if (!isDate(this.value)) {
|
||||||
this.currentDate = val;
|
this.date = val ? new Date(val) : new Date();
|
||||||
this.reinitDate();
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -93,15 +81,10 @@
|
|||||||
popperClass: '',
|
popperClass: '',
|
||||||
format: 'HH:mm:ss',
|
format: 'HH:mm:ss',
|
||||||
value: '',
|
value: '',
|
||||||
hours: 0,
|
defaultValue: null,
|
||||||
minutes: 0,
|
date: new Date(),
|
||||||
seconds: 0,
|
oldValue: new Date(),
|
||||||
oldHours: 0,
|
|
||||||
oldMinutes: 0,
|
|
||||||
oldSeconds: 0,
|
|
||||||
selectableRange: [],
|
selectableRange: [],
|
||||||
currentDate: this.$options.defaultValue || this.date || new Date(),
|
|
||||||
currentVisible: this.visible || false,
|
|
||||||
selectionRange: [0, 2],
|
selectionRange: [0, 2],
|
||||||
disabled: false
|
disabled: false
|
||||||
};
|
};
|
||||||
@ -114,35 +97,16 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
handleClear() {
|
|
||||||
this.$emit('pick', '', false, true);
|
|
||||||
},
|
|
||||||
|
|
||||||
handleCancel() {
|
handleCancel() {
|
||||||
this.currentDate.setHours(this.oldHours);
|
this.$emit('pick', this.oldValue);
|
||||||
this.currentDate.setMinutes(this.oldMinutes);
|
|
||||||
this.currentDate.setSeconds(this.oldSeconds);
|
|
||||||
this.hours = this.currentDate.getHours();
|
|
||||||
this.minutes = this.currentDate.getMinutes();
|
|
||||||
this.seconds = this.currentDate.getSeconds();
|
|
||||||
const date = new Date(limitRange(this.currentDate, this.selectableRange, 'HH:mm:ss'));
|
|
||||||
this.$emit('pick', date, false, true);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
handleChange(date, notUser) {
|
handleChange(date) {
|
||||||
if (date.hours !== undefined) {
|
this.date = clearMilliseconds(date);
|
||||||
this.currentDate.setHours(date.hours);
|
// if date is out of range, do not emit
|
||||||
this.hours = this.currentDate.getHours();
|
if (this.isValidValue(this.date)) {
|
||||||
|
this.$emit('pick', this.date, true);
|
||||||
}
|
}
|
||||||
if (date.minutes !== undefined) {
|
|
||||||
this.currentDate.setMinutes(date.minutes);
|
|
||||||
this.minutes = this.currentDate.getMinutes();
|
|
||||||
}
|
|
||||||
if (date.seconds !== undefined) {
|
|
||||||
this.currentDate.setSeconds(date.seconds);
|
|
||||||
this.seconds = this.currentDate.getSeconds();
|
|
||||||
}
|
|
||||||
this.handleConfirm(true, null, notUser);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
setSelectionRange(start, end) {
|
setSelectionRange(start, end) {
|
||||||
@ -150,18 +114,39 @@
|
|||||||
this.selectionRange = [start, end];
|
this.selectionRange = [start, end];
|
||||||
},
|
},
|
||||||
|
|
||||||
handleConfirm(visible = false, first, notUser = false) {
|
handleConfirm(visible = false, first) {
|
||||||
if (first) return;
|
if (first) return;
|
||||||
const date = new Date(limitRange(this.currentDate, this.selectableRange, 'HH:mm:ss'));
|
const date = clearMilliseconds(limitTimeRange(this.date, this.selectableRange, this.format));
|
||||||
this.$emit('pick', date, visible, !notUser, false);
|
this.$emit('pick', date, visible, first);
|
||||||
},
|
},
|
||||||
|
|
||||||
adjustScrollTop() {
|
handleKeydown(event) {
|
||||||
return this.$refs.spinner.adjustScrollTop();
|
const keyCode = event.keyCode;
|
||||||
|
const mapping = { 38: -1, 40: 1, 37: -1, 39: 1 };
|
||||||
|
|
||||||
|
// Left or Right
|
||||||
|
if (keyCode === 37 || keyCode === 39) {
|
||||||
|
const step = mapping[keyCode];
|
||||||
|
this.changeSelectionRange(step);
|
||||||
|
event.preventDefault();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Up or Down
|
||||||
|
if (keyCode === 38 || keyCode === 40) {
|
||||||
|
const step = mapping[keyCode];
|
||||||
|
this.$refs.spinner.scrollDown(step);
|
||||||
|
event.preventDefault();
|
||||||
|
return;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
scrollDown(step) {
|
isValidValue(date) {
|
||||||
this.$refs.spinner.scrollDown(step);
|
return timeWithinRange(date, this.selectableRange, this.format);
|
||||||
|
},
|
||||||
|
|
||||||
|
adjustSpinners() {
|
||||||
|
return this.$refs.spinner.adjustSpinners();
|
||||||
},
|
},
|
||||||
|
|
||||||
changeSelectionRange(step) {
|
changeSelectionRange(step) {
|
||||||
@ -170,19 +155,9 @@
|
|||||||
const index = list.indexOf(this.selectionRange[0]);
|
const index = list.indexOf(this.selectionRange[0]);
|
||||||
const next = (index + step + list.length) % list.length;
|
const next = (index + step + list.length) % list.length;
|
||||||
this.$refs.spinner.emitSelectRange(mapping[next]);
|
this.$refs.spinner.emitSelectRange(mapping[next]);
|
||||||
},
|
|
||||||
|
|
||||||
reinitDate() {
|
|
||||||
this.hours = this.currentDate.getHours();
|
|
||||||
this.minutes = this.currentDate.getMinutes();
|
|
||||||
this.seconds = this.currentDate.getSeconds();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
created() {
|
|
||||||
this.reinitDate();
|
|
||||||
},
|
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.$nextTick(() => this.handleConfirm(true, true));
|
this.$nextTick(() => this.handleConfirm(true, true));
|
||||||
this.$emit('mounted');
|
this.$emit('mounted');
|
||||||
|
@ -13,9 +13,10 @@
|
|||||||
@blur="handleBlur"
|
@blur="handleBlur"
|
||||||
@keydown.native="handleKeydown"
|
@keydown.native="handleKeydown"
|
||||||
:value="displayValue"
|
:value="displayValue"
|
||||||
|
@input="value => userInput = value"
|
||||||
@mouseenter.native="handleMouseEnter"
|
@mouseenter.native="handleMouseEnter"
|
||||||
@mouseleave.native="showClose = false"
|
@mouseleave.native="showClose = false"
|
||||||
@change.native="displayValue = $event.target.value"
|
@change.native="handleChange"
|
||||||
:validateEvent="false"
|
:validateEvent="false"
|
||||||
:prefix-icon="triggerClass"
|
:prefix-icon="triggerClass"
|
||||||
ref="reference">
|
ref="reference">
|
||||||
@ -36,6 +37,7 @@
|
|||||||
@click="handleRangeClick"
|
@click="handleRangeClick"
|
||||||
@mouseenter="handleMouseEnter"
|
@mouseenter="handleMouseEnter"
|
||||||
@mouseleave="showClose = false"
|
@mouseleave="showClose = false"
|
||||||
|
@keydown="handleKeydown"
|
||||||
ref="reference"
|
ref="reference"
|
||||||
v-clickoutside="handleClose"
|
v-clickoutside="handleClose"
|
||||||
v-else>
|
v-else>
|
||||||
@ -43,15 +45,17 @@
|
|||||||
<input
|
<input
|
||||||
:placeholder="startPlaceholder"
|
:placeholder="startPlaceholder"
|
||||||
:value="displayValue && displayValue[0]"
|
:value="displayValue && displayValue[0]"
|
||||||
@keydown="handleKeydown"
|
@input="handleStartInput"
|
||||||
@change="handleStartChange"
|
@change="handleStartChange"
|
||||||
|
@focus="handleFocus"
|
||||||
class="el-range-input">
|
class="el-range-input">
|
||||||
<span class="el-range-separator">{{ rangeSeparator }}</span>
|
<span class="el-range-separator">{{ rangeSeparator }}</span>
|
||||||
<input
|
<input
|
||||||
:placeholder="endPlaceholder"
|
:placeholder="endPlaceholder"
|
||||||
:value="displayValue && displayValue[1]"
|
:value="displayValue && displayValue[1]"
|
||||||
@keydown="handleKeydown"
|
@input="handleEndInput"
|
||||||
@change="handleEndChange"
|
@change="handleEndChange"
|
||||||
|
@focus="handleFocus"
|
||||||
class="el-range-input">
|
class="el-range-input">
|
||||||
<i
|
<i
|
||||||
@click="handleClickIcon"
|
@click="handleClickIcon"
|
||||||
@ -65,7 +69,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import Clickoutside from 'element-ui/src/utils/clickoutside';
|
import Clickoutside from 'element-ui/src/utils/clickoutside';
|
||||||
import { formatDate, parseDate, getWeekNumber, equalDate, isDate } from './util';
|
import { formatDate, parseDate, isDate, getWeekNumber } from './util';
|
||||||
import Popper from 'element-ui/src/utils/vue-popper';
|
import Popper from 'element-ui/src/utils/vue-popper';
|
||||||
import Emitter from 'element-ui/src/mixins/emitter';
|
import Emitter from 'element-ui/src/mixins/emitter';
|
||||||
import Focus from 'element-ui/src/mixins/focus';
|
import Focus from 'element-ui/src/mixins/focus';
|
||||||
@ -225,6 +229,26 @@ const PLACEMENT_MAP = {
|
|||||||
right: 'bottom-end'
|
right: 'bottom-end'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const parseAsFormatAndType = (value, cutsomFormat, type, rangeSeparator = '-') => {
|
||||||
|
if (!value) return null;
|
||||||
|
const parser = (
|
||||||
|
TYPE_VALUE_RESOLVER_MAP[type] ||
|
||||||
|
TYPE_VALUE_RESOLVER_MAP['default']
|
||||||
|
).parser;
|
||||||
|
const format = cutsomFormat || DEFAULT_FORMATS[type];
|
||||||
|
return parser(value, format, rangeSeparator);
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatAsFormatAndType = (value, cutsomFormat, type) => {
|
||||||
|
if (!value) return null;
|
||||||
|
const formatter = (
|
||||||
|
TYPE_VALUE_RESOLVER_MAP[type] ||
|
||||||
|
TYPE_VALUE_RESOLVER_MAP['default']
|
||||||
|
).formatter;
|
||||||
|
const format = cutsomFormat || DEFAULT_FORMATS[type];
|
||||||
|
return formatter(value, format);
|
||||||
|
};
|
||||||
|
|
||||||
// only considers date-picker's value: Date or [Date, Date]
|
// only considers date-picker's value: Date or [Date, Date]
|
||||||
const valueEquals = function(a, b) {
|
const valueEquals = function(a, b) {
|
||||||
const aIsArray = a instanceof Array;
|
const aIsArray = a instanceof Array;
|
||||||
@ -245,6 +269,7 @@ export default {
|
|||||||
props: {
|
props: {
|
||||||
size: String,
|
size: String,
|
||||||
format: String,
|
format: String,
|
||||||
|
valueFormat: String,
|
||||||
readonly: Boolean,
|
readonly: Boolean,
|
||||||
placeholder: String,
|
placeholder: String,
|
||||||
startPlaceholder: String,
|
startPlaceholder: String,
|
||||||
@ -280,33 +305,44 @@ export default {
|
|||||||
return {
|
return {
|
||||||
pickerVisible: false,
|
pickerVisible: false,
|
||||||
showClose: false,
|
showClose: false,
|
||||||
currentValue: '',
|
userInput: null,
|
||||||
|
valueOnOpen: null, // value when picker opens, used to determine whether to emit change
|
||||||
unwatchPickerOptions: null
|
unwatchPickerOptions: null
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
pickerVisible(val) {
|
pickerVisible(val) {
|
||||||
if (!val) this.dispatch('ElFormItem', 'el.form.blur');
|
|
||||||
if (this.readonly || this.disabled) return;
|
if (this.readonly || this.disabled) return;
|
||||||
val ? this.showPicker() : this.hidePicker();
|
if (val) {
|
||||||
},
|
this.showPicker();
|
||||||
currentValue(val) {
|
this.valueOnOpen = this.value;
|
||||||
if (val) return;
|
|
||||||
if (this.picker && typeof this.picker.handleClear === 'function') {
|
|
||||||
this.picker.handleClear();
|
|
||||||
} else {
|
} else {
|
||||||
this.$emit('input');
|
this.hidePicker();
|
||||||
|
this.emitChange(this.value);
|
||||||
|
// flush user input if it is parsable
|
||||||
|
// this.displayValue here is not a typo, it merges text for both panels in range mode
|
||||||
|
const parsedValue = this.parseString(this.displayValue);
|
||||||
|
if (this.userInput && parsedValue && this.isValidValue(parsedValue)) {
|
||||||
|
this.userInput = null;
|
||||||
|
}
|
||||||
|
this.dispatch('ElFormItem', 'el.form.blur');
|
||||||
|
this.blur();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
value: {
|
parsedValue: {
|
||||||
immediate: true,
|
immediate: true,
|
||||||
handler(val) {
|
handler(val) {
|
||||||
this.currentValue = isDate(val) ? new Date(val) : val;
|
if (this.picker) {
|
||||||
|
this.picker.value = val;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
displayValue(val) {
|
defaultValue(val) {
|
||||||
this.dispatch('ElFormItem', 'el.form.change');
|
// NOTE: should eventually move to jsx style picker + panel ?
|
||||||
|
if (this.picker) {
|
||||||
|
this.picker.defaultValue = val;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -328,7 +364,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
valueIsEmpty() {
|
valueIsEmpty() {
|
||||||
const val = this.currentValue;
|
const val = this.value;
|
||||||
if (Array.isArray(val)) {
|
if (Array.isArray(val)) {
|
||||||
for (let i = 0, len = val.length; i < len; i++) {
|
for (let i = 0, len = val.length; i < len; i++) {
|
||||||
if (val[i]) {
|
if (val[i]) {
|
||||||
@ -366,36 +402,24 @@ export default {
|
|||||||
return HAVE_TRIGGER_TYPES.indexOf(this.type) !== -1;
|
return HAVE_TRIGGER_TYPES.indexOf(this.type) !== -1;
|
||||||
},
|
},
|
||||||
|
|
||||||
displayValue: {
|
displayValue() {
|
||||||
get() {
|
const formattedValue = formatAsFormatAndType(this.parsedValue, this.format, this.type, this.rangeSeparator);
|
||||||
const value = this.currentValue;
|
if (Array.isArray(this.userInput)) {
|
||||||
if (!value) return;
|
return [
|
||||||
const formatter = (
|
this.userInput[0] || (formattedValue && formattedValue[0]) || '',
|
||||||
TYPE_VALUE_RESOLVER_MAP[this.type] ||
|
this.userInput[1] || (formattedValue && formattedValue[1]) || ''
|
||||||
TYPE_VALUE_RESOLVER_MAP['default']
|
];
|
||||||
).formatter;
|
} else {
|
||||||
const format = DEFAULT_FORMATS[this.type];
|
return this.userInput !== null ? this.userInput : formattedValue || '';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
return formatter(value, this.format || format);
|
parsedValue() {
|
||||||
},
|
const isParsed = isDate(this.value) || (Array.isArray(this.value) && this.value.every(isDate));
|
||||||
|
if (this.valueFormat && !isParsed) {
|
||||||
set(value) {
|
return parseAsFormatAndType(this.value, this.valueFormat, this.type, this.rangeSeparator) || this.value;
|
||||||
if (value) {
|
} else {
|
||||||
const type = this.type;
|
return this.value;
|
||||||
const parser = (
|
|
||||||
TYPE_VALUE_RESOLVER_MAP[type] ||
|
|
||||||
TYPE_VALUE_RESOLVER_MAP['default']
|
|
||||||
).parser;
|
|
||||||
const parsedValue = parser(value, this.format || DEFAULT_FORMATS[type]);
|
|
||||||
|
|
||||||
if (parsedValue && this.picker) {
|
|
||||||
this.picker.value = parsedValue;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.$emit('input', value);
|
|
||||||
this.picker.value = value;
|
|
||||||
}
|
|
||||||
this.$forceUpdate();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -410,6 +434,41 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
blur() {
|
||||||
|
this.refInput.forEach(input => input.blur());
|
||||||
|
},
|
||||||
|
|
||||||
|
// {parse, formatTo} Value deals maps component value with internal Date
|
||||||
|
// parseValue validates value according to panel, requires picker to be mounted
|
||||||
|
parseValue(value, customFormat) {
|
||||||
|
if (!value || (!Array.isArray(value) || !value.every(val => val))) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const format = customFormat || this.valueFormat;
|
||||||
|
const parsedValue = parseAsFormatAndType(value, format, this.type, this.rangeSeparator);
|
||||||
|
return this.isValidValue(parsedValue) ? parsedValue : null;
|
||||||
|
},
|
||||||
|
|
||||||
|
formatToValue(date, customFormat) {
|
||||||
|
if (this.valueFormat && (isDate(date) || Array.isArray(date))) {
|
||||||
|
const format = customFormat || this.valueFormat;
|
||||||
|
return formatAsFormatAndType(date, format, this.type, this.rangeSeparator);
|
||||||
|
} else {
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// {parse, formatTo} String deals with user input
|
||||||
|
parseString(value) {
|
||||||
|
const type = Array.isArray(value) ? this.type : this.type.replace('range', '');
|
||||||
|
return parseAsFormatAndType(value, this.format, type);
|
||||||
|
},
|
||||||
|
|
||||||
|
formatToString(value) {
|
||||||
|
const type = Array.isArray(value) ? this.type : this.type.replace('range', '');
|
||||||
|
return formatAsFormatAndType(value, this.format, type);
|
||||||
|
},
|
||||||
|
|
||||||
handleMouseEnter() {
|
handleMouseEnter() {
|
||||||
if (this.readonly || this.disabled) return;
|
if (this.readonly || this.disabled) return;
|
||||||
if (!this.valueIsEmpty && this.clearable) {
|
if (!this.valueIsEmpty && this.clearable) {
|
||||||
@ -417,47 +476,76 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
handleStartChange(event) {
|
handleChange() {
|
||||||
if (this.displayValue && this.displayValue[1]) {
|
if (this.userInput) {
|
||||||
this.displayValue = [event.target.value, this.displayValue[1]];
|
const value = this.parseString(this.displayValue);
|
||||||
|
if (value) {
|
||||||
|
this.picker.value = value;
|
||||||
|
if (this.isValidValue(value)) {
|
||||||
|
this.emitInput(value);
|
||||||
|
this.userInput = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
handleStartInput(event) {
|
||||||
|
if (this.userInput) {
|
||||||
|
this.userInput = [event.target.value, this.userInput[1]];
|
||||||
} else {
|
} else {
|
||||||
this.displayValue = [event.target.value, event.target.value];
|
this.userInput = [event.target.value, null];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
handleEndInput(event) {
|
||||||
|
if (this.userInput) {
|
||||||
|
this.userInput = [this.userInput[0], event.target.value];
|
||||||
|
} else {
|
||||||
|
this.userInput = [null, event.target.value];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
handleStartChange(event) {
|
||||||
|
const value = this.parseString(this.userInput && this.userInput[0]);
|
||||||
|
if (value) {
|
||||||
|
this.userInput = [this.formatToString(value), this.displayValue[1]];
|
||||||
|
const newValue = [value, this.picker.value && this.picker.value[1]];
|
||||||
|
this.picker.value = newValue;
|
||||||
|
if (this.isValidValue(newValue)) {
|
||||||
|
this.emitInput(newValue);
|
||||||
|
this.userInput = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
handleEndChange(event) {
|
handleEndChange(event) {
|
||||||
if (this.displayValue && this.displayValue[0]) {
|
const value = this.parseString(this.userInput && this.userInput[1]);
|
||||||
this.displayValue = [this.displayValue[0], event.target.value];
|
if (value) {
|
||||||
} else {
|
this.userInput = [this.displayValue[0], this.formatToString(value)];
|
||||||
this.displayValue = [event.target.value, event.target.value];
|
const newValue = [this.picker.value && this.picker.value[0], value];
|
||||||
|
this.picker.value = newValue;
|
||||||
|
if (this.isValidValue(newValue)) {
|
||||||
|
this.emitInput(newValue);
|
||||||
|
this.userInput = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
handleClickIcon(event) {
|
handleClickIcon(event) {
|
||||||
if (this.readonly || this.disabled) return;
|
if (this.readonly || this.disabled) return;
|
||||||
if (this.showClose) {
|
if (this.showClose) {
|
||||||
this.currentValue = this.$options.defaultValue || '';
|
|
||||||
this.showClose = false;
|
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
this.emitInput(null);
|
||||||
|
this.emitChange(null);
|
||||||
|
this.showClose = false;
|
||||||
|
if (this.picker && typeof this.picker.handleClear === 'function') {
|
||||||
|
this.picker.handleClear();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.pickerVisible = !this.pickerVisible;
|
this.pickerVisible = !this.pickerVisible;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
dateChanged(dateA, dateB) {
|
|
||||||
if (Array.isArray(dateA)) {
|
|
||||||
let len = dateA.length;
|
|
||||||
if (!dateB) return true;
|
|
||||||
while (len--) {
|
|
||||||
if (!equalDate(dateA[len], dateB[len])) return true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!equalDate(dateA, dateB)) return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
handleClose() {
|
handleClose() {
|
||||||
this.pickerVisible = false;
|
this.pickerVisible = false;
|
||||||
if (this.ranged) {
|
if (this.ranged) {
|
||||||
@ -481,10 +569,54 @@ export default {
|
|||||||
handleKeydown(event) {
|
handleKeydown(event) {
|
||||||
const keyCode = event.keyCode;
|
const keyCode = event.keyCode;
|
||||||
|
|
||||||
// TAB or ESC
|
// ESC
|
||||||
if (keyCode === 9 || keyCode === 27) {
|
if (keyCode === 27) {
|
||||||
this.pickerVisible = false;
|
this.pickerVisible = false;
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tab
|
||||||
|
if (keyCode === 9) {
|
||||||
|
if (!this.ranged) {
|
||||||
|
this.handleChange();
|
||||||
|
this.pickerVisible = this.picker.visible = false;
|
||||||
|
this.blur();
|
||||||
|
event.stopPropagation();
|
||||||
|
} else {
|
||||||
|
// user may change focus between two input
|
||||||
|
setTimeout(() => {
|
||||||
|
if (this.refInput.indexOf(document.activeElement) === -1) {
|
||||||
|
this.pickerVisible = false;
|
||||||
|
this.blur();
|
||||||
|
event.stopPropagation();
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enter
|
||||||
|
if (keyCode === 13 && this.displayValue) {
|
||||||
|
const value = this.parseString(this.displayValue);
|
||||||
|
if (this.isValidValue(value)) {
|
||||||
|
this.handleChange();
|
||||||
|
this.pickerVisible = this.picker.visible = false;
|
||||||
|
this.blur();
|
||||||
|
}
|
||||||
|
event.stopPropagation();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if user is typing, do not let picker handle key input
|
||||||
|
if (this.userInput) {
|
||||||
|
event.stopPropagation();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// delegate other keys to panel
|
||||||
|
if (this.picker && this.picker.handleKeydown) {
|
||||||
|
this.picker.handleKeydown(event);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -514,22 +646,17 @@ export default {
|
|||||||
|
|
||||||
this.updatePopper();
|
this.updatePopper();
|
||||||
|
|
||||||
if (this.currentValue instanceof Date) {
|
this.picker.value = this.parsedValue;
|
||||||
this.picker.date = new Date(this.currentValue.getTime());
|
|
||||||
} else {
|
|
||||||
this.picker.value = this.currentValue;
|
|
||||||
}
|
|
||||||
this.picker.resetView && this.picker.resetView();
|
this.picker.resetView && this.picker.resetView();
|
||||||
|
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.picker.adjustScrollTop && this.picker.adjustScrollTop();
|
this.picker.adjustSpinners && this.picker.adjustSpinners();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
mountPicker() {
|
mountPicker() {
|
||||||
const defaultValue = this.defaultValue || this.currentValue;
|
this.picker = new Vue(this.panel).$mount();
|
||||||
const panel = merge({}, this.panel, { defaultValue });
|
this.picker.defaultValue = this.defaultValue;
|
||||||
this.picker = new Vue(panel).$mount();
|
|
||||||
this.picker.popperClass = this.popperClass;
|
this.picker.popperClass = this.popperClass;
|
||||||
this.popperElm = this.picker.$el;
|
this.popperElm = this.picker.$el;
|
||||||
this.picker.width = this.reference.getBoundingClientRect().width;
|
this.picker.width = this.reference.getBoundingClientRect().width;
|
||||||
@ -566,15 +693,10 @@ export default {
|
|||||||
this.picker.resetView && this.picker.resetView();
|
this.picker.resetView && this.picker.resetView();
|
||||||
|
|
||||||
this.picker.$on('dodestroy', this.doDestroy);
|
this.picker.$on('dodestroy', this.doDestroy);
|
||||||
this.picker.$on('pick', (date = '', visible = false, user = true) => {
|
this.picker.$on('pick', (date = '', visible = false) => {
|
||||||
// do not emit if values are same
|
this.userInput = null;
|
||||||
if (!valueEquals(this.value, date)) {
|
|
||||||
this.$emit('input', date);
|
|
||||||
if (user && this.value !== date) {
|
|
||||||
this.$nextTick(() => this.$emit('change', this.displayValue));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
this.pickerVisible = this.picker.visible = visible;
|
this.pickerVisible = this.picker.visible = visible;
|
||||||
|
this.emitInput(date);
|
||||||
this.picker.resetView && this.picker.resetView();
|
this.picker.resetView && this.picker.resetView();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -599,6 +721,33 @@ export default {
|
|||||||
}
|
}
|
||||||
this.picker.$el.parentNode.removeChild(this.picker.$el);
|
this.picker.$el.parentNode.removeChild(this.picker.$el);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
emitChange(val) {
|
||||||
|
const formatted = this.formatToValue(val);
|
||||||
|
if (!valueEquals(this.valueOnOpen, formatted)) {
|
||||||
|
this.$emit('change', formatted);
|
||||||
|
this.dispatch('ElFormItem', 'el.form.change', formatted);
|
||||||
|
this.valueOnOpen = formatted;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
emitInput(val) {
|
||||||
|
const formatted = this.formatToValue(val);
|
||||||
|
if (!valueEquals(this.value, formatted)) {
|
||||||
|
this.$emit('input', formatted);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
isValidValue(value) {
|
||||||
|
if (!this.picker) {
|
||||||
|
this.mountPicker();
|
||||||
|
}
|
||||||
|
if (this.picker.isValidValue) {
|
||||||
|
return value && this.picker.isValidValue(value);
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -35,35 +35,5 @@ export default {
|
|||||||
|
|
||||||
created() {
|
created() {
|
||||||
this.panel = getPanel(this.type);
|
this.panel = getPanel(this.type);
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
handleKeydown(event) {
|
|
||||||
const keyCode = event.keyCode;
|
|
||||||
|
|
||||||
// TAB or ESC or Enter
|
|
||||||
if (keyCode === 9 || keyCode === 27 || keyCode === 13) {
|
|
||||||
!this.ranged && (this.pickerVisible = false);
|
|
||||||
event.stopPropagation();
|
|
||||||
this.picker.confirm && this.picker.confirm();
|
|
||||||
!this.ranged && (this.currentValue = this.picker.date);
|
|
||||||
if (this.$refs.reference.$refs) {
|
|
||||||
this.$refs.reference.$refs.input.blur();
|
|
||||||
} else {
|
|
||||||
[].slice.call(this.$refs.reference.querySelectorAll('input')).forEach(input => {
|
|
||||||
input.blur();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const list = [38, 40, 37, 39];
|
|
||||||
if (list.indexOf(keyCode) !== -1) {
|
|
||||||
if (this.type === 'daterange' || this.type === 'datetimerange') return;
|
|
||||||
this.picker.handleKeyControl(keyCode);
|
|
||||||
event.stopPropagation();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -34,49 +34,5 @@ export default {
|
|||||||
created() {
|
created() {
|
||||||
this.type = this.isRange ? 'timerange' : 'time';
|
this.type = this.isRange ? 'timerange' : 'time';
|
||||||
this.panel = this.isRange ? TimeRangePanel : TimePanel;
|
this.panel = this.isRange ? TimeRangePanel : TimePanel;
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
handleKeydown(event) {
|
|
||||||
const keyCode = event.keyCode;
|
|
||||||
|
|
||||||
// TAB or ESC
|
|
||||||
if (keyCode === 9 || keyCode === 27) {
|
|
||||||
this.pickerVisible = false;
|
|
||||||
event.stopPropagation();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const mapping = { 38: -1, 40: 1, 37: -1, 39: 1 };
|
|
||||||
|
|
||||||
// Left or Right
|
|
||||||
if (keyCode === 37 || keyCode === 39) {
|
|
||||||
const step = mapping[keyCode];
|
|
||||||
this.picker.changeSelectionRange(step);
|
|
||||||
event.preventDefault();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Up or Down
|
|
||||||
if (keyCode === 38 || keyCode === 40) {
|
|
||||||
const step = mapping[keyCode];
|
|
||||||
this.picker.scrollDown(step);
|
|
||||||
event.preventDefault();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keyCode === 13) {
|
|
||||||
!this.isRange && this.picker.handleConfirm();
|
|
||||||
if (this.$refs.reference.$refs) {
|
|
||||||
this.$refs.reference.$refs.input.blur();
|
|
||||||
} else {
|
|
||||||
[].slice.call(this.$refs.reference.querySelectorAll('input')).forEach(input => {
|
|
||||||
input.blur();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
event.preventDefault();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -9,35 +9,5 @@ export default {
|
|||||||
beforeCreate() {
|
beforeCreate() {
|
||||||
this.type = 'time-select';
|
this.type = 'time-select';
|
||||||
this.panel = Panel;
|
this.panel = Panel;
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
handleKeydown(event) {
|
|
||||||
const keyCode = event.keyCode;
|
|
||||||
// TAB or ESC or Enter
|
|
||||||
if (keyCode === 9 || keyCode === 27 || keyCode === 13) {
|
|
||||||
const input = this.$refs.reference;
|
|
||||||
const index = this.picker.items.map(v => v.value).indexOf(input.currentValue);
|
|
||||||
const exist = index !== -1;
|
|
||||||
if (!exist) {
|
|
||||||
input.currentValue = this.currentValue;
|
|
||||||
} else {
|
|
||||||
this.picker.handleClick(this.picker.items[index]);
|
|
||||||
}
|
|
||||||
this.pickerVisible = false;
|
|
||||||
input.$refs.input.blur();
|
|
||||||
event.stopPropagation();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keyCode === 38 || keyCode === 40) {
|
|
||||||
const mapping = { 40: 1, 38: -1 };
|
|
||||||
const offset = mapping[keyCode.toString()];
|
|
||||||
this.picker.scrollDown(offset);
|
|
||||||
this.currentValue = this.picker.value;
|
|
||||||
event.stopPropagation();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -21,10 +21,6 @@ const newArray = function(start, end) {
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const equalDate = function(dateA, dateB) {
|
|
||||||
return dateA === dateB || new Date(dateA).getTime() === new Date(dateB).getTime();
|
|
||||||
};
|
|
||||||
|
|
||||||
export const toDate = function(date) {
|
export const toDate = function(date) {
|
||||||
return isDate(date) ? new Date(date) : null;
|
return isDate(date) ? new Date(date) : null;
|
||||||
};
|
};
|
||||||
@ -93,44 +89,6 @@ export const getWeekNumber = function(src) {
|
|||||||
return 1 + Math.round(((date.getTime() - week1.getTime()) / 86400000 - 3 + (week1.getDay() + 6) % 7) / 7);
|
return 1 + Math.round(((date.getTime() - week1.getTime()) / 86400000 - 3 + (week1.getDay() + 6) % 7) / 7);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const prevMonth = function(src) {
|
|
||||||
const year = src.getFullYear();
|
|
||||||
const month = src.getMonth();
|
|
||||||
const date = src.getDate();
|
|
||||||
|
|
||||||
const newYear = month === 0 ? year - 1 : year;
|
|
||||||
const newMonth = month === 0 ? 11 : month - 1;
|
|
||||||
|
|
||||||
const newMonthDayCount = getDayCountOfMonth(newYear, newMonth);
|
|
||||||
if (newMonthDayCount < date) {
|
|
||||||
src.setDate(newMonthDayCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
src.setMonth(newMonth);
|
|
||||||
src.setFullYear(newYear);
|
|
||||||
|
|
||||||
return new Date(src.getTime());
|
|
||||||
};
|
|
||||||
|
|
||||||
export const nextMonth = function(src) {
|
|
||||||
const year = src.getFullYear();
|
|
||||||
const month = src.getMonth();
|
|
||||||
const date = src.getDate();
|
|
||||||
|
|
||||||
const newYear = month === 11 ? year + 1 : year;
|
|
||||||
const newMonth = month === 11 ? 0 : month + 1;
|
|
||||||
|
|
||||||
const newMonthDayCount = getDayCountOfMonth(newYear, newMonth);
|
|
||||||
if (newMonthDayCount < date) {
|
|
||||||
src.setDate(newMonthDayCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
src.setMonth(newMonth);
|
|
||||||
src.setFullYear(newYear);
|
|
||||||
|
|
||||||
return new Date(src.getTime());
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getRangeHours = function(ranges) {
|
export const getRangeHours = function(ranges) {
|
||||||
const hours = [];
|
const hours = [];
|
||||||
let disabledHours = [];
|
let disabledHours = [];
|
||||||
@ -154,26 +112,105 @@ export const getRangeHours = function(ranges) {
|
|||||||
return hours;
|
return hours;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const limitRange = function(date, ranges, format = 'yyyy-MM-dd HH:mm:ss') {
|
export const range = function(n) {
|
||||||
if (!ranges || !ranges.length) return date;
|
// see https://stackoverflow.com/questions/3746725/create-a-javascript-array-containing-1-n
|
||||||
|
return Array.apply(null, {length: n}).map((_, n) => n);
|
||||||
|
};
|
||||||
|
|
||||||
const len = ranges.length;
|
export const modifyDate = function(date, y, m, d) {
|
||||||
|
return new Date(y, m, d, date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds());
|
||||||
|
};
|
||||||
|
|
||||||
date = dateUtil.parse(dateUtil.format(date, format), format);
|
export const modifyTime = function(date, h, m, s) {
|
||||||
for (let i = 0; i < len; i++) {
|
return new Date(date.getFullYear(), date.getMonth(), date.getDate(), h, m, s, date.getMilliseconds());
|
||||||
const range = ranges[i];
|
};
|
||||||
if (date >= range[0] && date <= range[1]) {
|
|
||||||
return date;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let maxDate = ranges[0][0];
|
export const clearTime = function(date) {
|
||||||
let minDate = ranges[0][0];
|
return new Date(date.getFullYear(), date.getMonth(), date.getDate());
|
||||||
|
};
|
||||||
|
|
||||||
ranges.forEach(range => {
|
export const clearMilliseconds = function(date) {
|
||||||
minDate = new Date(Math.min(range[0], minDate));
|
return new Date(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), 0);
|
||||||
maxDate = new Date(Math.max(range[1], maxDate));
|
};
|
||||||
|
|
||||||
|
export const limitTimeRange = function(date, ranges, format = 'HH:mm:ss') {
|
||||||
|
// TODO: refactory a more elegant solution
|
||||||
|
if (ranges.length === 0) return date;
|
||||||
|
const normalizeDate = date => dateUtil.parse(dateUtil.format(date, format), format);
|
||||||
|
const ndate = normalizeDate(date);
|
||||||
|
const nranges = ranges.map(range => range.map(normalizeDate));
|
||||||
|
if (nranges.some(nrange => ndate >= nrange[0] && ndate <= nrange[1])) return date;
|
||||||
|
|
||||||
|
let minDate = nranges[0][0];
|
||||||
|
let maxDate = nranges[0][0];
|
||||||
|
|
||||||
|
nranges.forEach(nrange => {
|
||||||
|
minDate = new Date(Math.min(nrange[0], minDate));
|
||||||
|
maxDate = new Date(Math.max(nrange[1], minDate));
|
||||||
});
|
});
|
||||||
|
|
||||||
return date < minDate ? minDate : maxDate;
|
const ret = ndate < minDate ? minDate : maxDate;
|
||||||
|
// preserve Year/Month/Date
|
||||||
|
return modifyDate(
|
||||||
|
ret,
|
||||||
|
date.getFullYear(),
|
||||||
|
date.getMonth(),
|
||||||
|
date.getDate()
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const timeWithinRange = function(date, selectableRange, format) {
|
||||||
|
const limitedDate = limitTimeRange(date, selectableRange, format);
|
||||||
|
return limitedDate.getTime() === date.getTime();
|
||||||
|
};
|
||||||
|
|
||||||
|
export const prevMonth = function(date) {
|
||||||
|
let year = date.getFullYear();
|
||||||
|
let month = date.getMonth();
|
||||||
|
if (month === 0) {
|
||||||
|
year -= 1;
|
||||||
|
month = 11;
|
||||||
|
} else {
|
||||||
|
month -= 1;
|
||||||
|
}
|
||||||
|
const monthDate = Math.min(date.getDate(), getDayCountOfMonth(year, month));
|
||||||
|
return modifyDate(date, year, month, monthDate);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const nextMonth = function(date) {
|
||||||
|
let year = date.getFullYear();
|
||||||
|
let month = date.getMonth();
|
||||||
|
if (month === 11) {
|
||||||
|
year += 1;
|
||||||
|
month = 0;
|
||||||
|
} else {
|
||||||
|
month += 1;
|
||||||
|
}
|
||||||
|
const monthDate = Math.min(date.getDate(), getDayCountOfMonth(year, month));
|
||||||
|
return modifyDate(date, year, month, monthDate);
|
||||||
|
};
|
||||||
|
|
||||||
|
// check for leap year Feburary
|
||||||
|
export const prevYear = function(date, amount = 1) {
|
||||||
|
const year = date.getFullYear() - amount;
|
||||||
|
const month = date.getMonth();
|
||||||
|
const monthDate = Math.min(date.getDate(), getDayCountOfMonth(year, month));
|
||||||
|
return modifyDate(date, year, month, monthDate);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const nextYear = function(date, amount = 1) {
|
||||||
|
const year = date.getFullYear() + amount;
|
||||||
|
const month = date.getMonth();
|
||||||
|
const monthDate = Math.min(date.getDate(), getDayCountOfMonth(year, month));
|
||||||
|
return modifyDate(date, year, month, monthDate);
|
||||||
|
};
|
||||||
|
|
||||||
|
// {prev, next} Date works for daylight saving time
|
||||||
|
// add / subtract one day's duration does not work
|
||||||
|
export const prevDate = function(date, amount = 1) {
|
||||||
|
return new Date(date.getFullYear(), date.getMonth(), date.getDate() - amount);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const nextDate = function(date, amount = 1) {
|
||||||
|
return new Date(date.getFullYear(), date.getMonth(), date.getDate() + amount);
|
||||||
};
|
};
|
||||||
|
@ -6,7 +6,18 @@ import {
|
|||||||
} from '../util';
|
} from '../util';
|
||||||
import DatePicker from 'packages/date-picker';
|
import DatePicker from 'packages/date-picker';
|
||||||
|
|
||||||
const DELAY = 10;
|
const DELAY = 50;
|
||||||
|
|
||||||
|
const LEFT = 37;
|
||||||
|
const ENTER = 13;
|
||||||
|
const TAB = 9;
|
||||||
|
|
||||||
|
const keyDown = (el, keyCode) => {
|
||||||
|
const evt = document.createEvent('Events');
|
||||||
|
evt.initEvent('keydown', true, true);
|
||||||
|
evt.keyCode = keyCode;
|
||||||
|
el.dispatchEvent(evt);
|
||||||
|
};
|
||||||
|
|
||||||
describe('DatePicker', () => {
|
describe('DatePicker', () => {
|
||||||
let vm;
|
let vm;
|
||||||
@ -177,19 +188,18 @@ describe('DatePicker', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('change event', done => {
|
it('change event', done => {
|
||||||
let inputValue;
|
let onChangeValue;
|
||||||
|
|
||||||
vm = createVue({
|
vm = createVue({
|
||||||
template: `
|
template: `
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
ref="compo"
|
ref="compo"
|
||||||
v-model="value"
|
v-model="value"
|
||||||
format="yyyy-MM"
|
|
||||||
@change="handleChange" />`,
|
@change="handleChange" />`,
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
handleChange(val) {
|
handleChange(val) {
|
||||||
inputValue = val;
|
onChangeValue = val;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -208,15 +218,17 @@ describe('DatePicker', () => {
|
|||||||
setTimeout(_ => {
|
setTimeout(_ => {
|
||||||
const picker = vm.$refs.compo.picker;
|
const picker = vm.$refs.compo.picker;
|
||||||
|
|
||||||
picker.$el.querySelector('td.available').click();
|
// programatic modification of bound value does not emit cange
|
||||||
vm.$nextTick(_ => {
|
vm.value = new Date(2000, 9, 2);
|
||||||
const date = picker.date;
|
setTimeout(_ => {
|
||||||
let month = date.getMonth() + 1;
|
expect(onChangeValue).to.not.exist;
|
||||||
if (month < 10) month = '0' + month;
|
// user interaction does emit change
|
||||||
|
picker.$el.querySelector('td.available').click();
|
||||||
expect(inputValue).to.equal(`${date.getFullYear()}-${ month }`);
|
setTimeout(_ => {
|
||||||
done();
|
expect(onChangeValue.getTime()).to.equal(vm.value.getTime());
|
||||||
});
|
done();
|
||||||
|
}, DELAY);
|
||||||
|
}, DELAY);
|
||||||
}, DELAY);
|
}, DELAY);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -356,44 +368,212 @@ describe('DatePicker', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('default value', done => {
|
describe('value-format', () => {
|
||||||
let defaultValue = '2000-01-01';
|
it('emits', done => {
|
||||||
let expectValue = new Date(2000, 0, 1);
|
vm = createVue({
|
||||||
|
template: `
|
||||||
vm = createVue({
|
<el-date-picker
|
||||||
template: `<el-date-picker v-model="value" ref="compo" default-value="${defaultValue}" />`,
|
ref="compo"
|
||||||
data() {
|
v-model="value"
|
||||||
return {
|
type="date"
|
||||||
value: ''
|
@change="handleChange"
|
||||||
};
|
value-format="dd-MM-yyyy" />`,
|
||||||
}
|
data() {
|
||||||
}, true);
|
return {
|
||||||
|
value: '',
|
||||||
const input = vm.$el.querySelector('input');
|
handleChange: null
|
||||||
|
};
|
||||||
input.focus();
|
}
|
||||||
setTimeout(_ => {
|
}, true);
|
||||||
const $el = vm.$refs.compo.picker.$el;
|
const spy = sinon.spy();
|
||||||
$el.querySelector('td.current').click();
|
vm.handleChange = spy;
|
||||||
|
vm.$refs.compo.$el.querySelector('input').focus();
|
||||||
setTimeout(_ => {
|
setTimeout(_ => {
|
||||||
expect(+vm.value).to.equal(+expectValue);
|
vm.$refs.compo.picker.$el.querySelector('.el-date-table td.available').click();
|
||||||
|
setTimeout(_ => {
|
||||||
|
const today = new Date();
|
||||||
|
const yyyy = today.getFullYear();
|
||||||
|
const MM = ('0' + (today.getMonth() + 1)).slice(-2);
|
||||||
|
const dd = '01'; // first available one should be first day of month
|
||||||
|
const expectValue = `${dd}-${MM}-${yyyy}`;
|
||||||
|
expect(vm.value).to.equal(expectValue);
|
||||||
|
expect(spy.calledOnce).to.be.true;
|
||||||
|
expect(spy.calledWith(expectValue)).to.be.true;
|
||||||
|
done();
|
||||||
|
}, DELAY);
|
||||||
|
}, DELAY);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('accepts', done => {
|
||||||
|
vm = createVue({
|
||||||
|
template: `
|
||||||
|
<el-date-picker
|
||||||
|
ref="compo"
|
||||||
|
v-model="value"
|
||||||
|
type="date"
|
||||||
|
value-format="dd-MM-yyyy" />`,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
value: '01-02-2000'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
vm.$refs.compo.$el.querySelector('input').focus();
|
||||||
|
setTimeout(_ => {
|
||||||
|
const date = vm.$refs.compo.picker.date;
|
||||||
|
expect(date.getFullYear()).to.equal(2000);
|
||||||
|
expect(date.getMonth()).to.equal(1);
|
||||||
|
expect(date.getDate()).to.equal(1);
|
||||||
done();
|
done();
|
||||||
}, 10);
|
}, DELAY);
|
||||||
}, 10);
|
});
|
||||||
|
|
||||||
|
it('translates format to value-format', done => {
|
||||||
|
vm = createVue({
|
||||||
|
template: `
|
||||||
|
<el-date-picker
|
||||||
|
ref="compo"
|
||||||
|
v-model="value"
|
||||||
|
type="date"
|
||||||
|
value-format="dd-MM-yyyy"
|
||||||
|
format="yyyy-MM-dd" />`,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
value: ''
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
const input = vm.$refs.compo.$el.querySelector('input');
|
||||||
|
input.focus();
|
||||||
|
setTimeout(_ => {
|
||||||
|
input.value = '2000-10-01';
|
||||||
|
triggerEvent(input, 'input');
|
||||||
|
keyDown(input, ENTER);
|
||||||
|
setTimeout(_ => {
|
||||||
|
expect(vm.value).to.equal('01-10-2000');
|
||||||
|
done();
|
||||||
|
}, DELAY);
|
||||||
|
}, DELAY);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('works for daterange', done => {
|
||||||
|
vm = createVue({
|
||||||
|
template: `
|
||||||
|
<el-date-picker
|
||||||
|
ref="compo"
|
||||||
|
v-model="value"
|
||||||
|
type="daterange"
|
||||||
|
value-format="dd-MM-yyyy" />`,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
value: ''
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
const inputs = vm.$refs.compo.$el.querySelectorAll('input');
|
||||||
|
inputs[0].focus();
|
||||||
|
setTimeout(_ => {
|
||||||
|
inputs[0].value = '2000-10-01';
|
||||||
|
triggerEvent(inputs[0], 'input');
|
||||||
|
keyDown(inputs[0], TAB);
|
||||||
|
setTimeout(_ => {
|
||||||
|
inputs[1].focus();
|
||||||
|
inputs[1].value = '2000-10-02';
|
||||||
|
triggerEvent(inputs[1], 'input');
|
||||||
|
keyDown(inputs[0], ENTER);
|
||||||
|
setTimeout(_ => {
|
||||||
|
expect(vm.value).to.eql(['01-10-2000', '02-10-2000']);
|
||||||
|
done();
|
||||||
|
}, DELAY);
|
||||||
|
}, DELAY);
|
||||||
|
}, DELAY);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('default value', done => {
|
||||||
|
it('it works', done => {
|
||||||
|
let defaultValue = '2000-01-01';
|
||||||
|
let expectValue = new Date(2000, 0, 1);
|
||||||
|
|
||||||
|
vm = createVue({
|
||||||
|
template: `<el-date-picker v-model="value" ref="compo" default-value="${defaultValue}" />`,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
value: ''
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
vm.$el.querySelector('input').focus();
|
||||||
|
setTimeout(_ => {
|
||||||
|
const $el = vm.$refs.compo.picker.$el;
|
||||||
|
expect($el.querySelector('.el-month-table td.default')).to.exist;
|
||||||
|
expect($el.querySelector('.el-year-table td.default')).to.exist;
|
||||||
|
const defaultEls = $el.querySelectorAll('.el-date-table td.default');
|
||||||
|
expect(defaultEls.length).to.equal(1);
|
||||||
|
defaultEls[0].click();
|
||||||
|
setTimeout(_ => {
|
||||||
|
expect(vm.value).to.eql(expectValue);
|
||||||
|
done();
|
||||||
|
}, DELAY);
|
||||||
|
}, DELAY);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('is reactive, works with clear', done => {
|
||||||
|
let defaultValue = '2000-01-01';
|
||||||
|
let expectValue = new Date(2000, 0, 1);
|
||||||
|
|
||||||
|
vm = createVue({
|
||||||
|
template: '<el-date-picker v-model="value" ref="compo" :default-value="defaultValue" />',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
value: new Date(),
|
||||||
|
defaultValue: null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
const input = vm.$el.querySelector('input');
|
||||||
|
input.focus();
|
||||||
|
setTimeout(_ => {
|
||||||
|
let $el = vm.$refs.compo.picker.$el;
|
||||||
|
expect($el.querySelector('.el-date-table td.current')).to.exist;
|
||||||
|
vm.defaultValue = defaultValue;
|
||||||
|
triggerEvent(vm.$refs.compo.$el, 'mouseenter');
|
||||||
|
setTimeout(_ => {
|
||||||
|
vm.$el.querySelector('.el-icon-circle-close').click();
|
||||||
|
setTimeout(_ => {
|
||||||
|
input.focus();
|
||||||
|
setTimeout(() => {
|
||||||
|
$el = vm.$refs.compo.picker.$el;
|
||||||
|
expect($el.querySelector('.el-date-table td.current')).to.not.exist;
|
||||||
|
expect($el.querySelector('.el-date-table td.default')).to.exist;
|
||||||
|
$el.querySelector('.el-date-table td.default').click();
|
||||||
|
setTimeout(() => {
|
||||||
|
expect(vm.value).to.eql(expectValue);
|
||||||
|
done();
|
||||||
|
}, DELAY);
|
||||||
|
}, DELAY);
|
||||||
|
}, DELAY);
|
||||||
|
}, DELAY);
|
||||||
|
}, DELAY);
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('keydown', () => {
|
describe('keydown', () => {
|
||||||
let input;
|
let input, datePicker;
|
||||||
let keyDown = function(el, keyCode) {
|
|
||||||
const evt = document.createEvent('Events');
|
|
||||||
|
|
||||||
evt.initEvent('keydown', true, true);
|
|
||||||
evt.keyCode = keyCode;
|
|
||||||
el.dispatchEvent(evt);
|
|
||||||
};
|
|
||||||
|
|
||||||
beforeEach(done => {
|
beforeEach(done => {
|
||||||
vm = createTest(DatePicker, true);
|
vm = createVue({
|
||||||
|
template: '<el-date-picker ref="compo" v-model="value"></el-date-picker>',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
value: ''
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
datePicker = vm.$refs.compo;
|
||||||
input = vm.$el.querySelector('input');
|
input = vm.$el.querySelector('input');
|
||||||
input.blur();
|
input.blur();
|
||||||
input.focus();
|
input.focus();
|
||||||
@ -402,37 +582,131 @@ describe('DatePicker', () => {
|
|||||||
|
|
||||||
afterEach(() => destroyVM(vm));
|
afterEach(() => destroyVM(vm));
|
||||||
|
|
||||||
it('tab', () => {
|
it('tab', done => {
|
||||||
keyDown(input, 9);
|
keyDown(input, TAB);
|
||||||
expect(vm.pickerVisible).to.false;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('enter', done => {
|
|
||||||
input.value = '2000-10-1';
|
|
||||||
triggerEvent(input, 'change', true);
|
|
||||||
setTimeout(_ => {
|
setTimeout(_ => {
|
||||||
expect(vm.pickerVisible).to.false;
|
expect(datePicker.pickerVisible).to.false;
|
||||||
expect(vm.picker.date.getFullYear()).to.equal(2000);
|
|
||||||
expect(vm.picker.date.getMonth()).to.equal(9);
|
|
||||||
expect(vm.picker.date.getDate()).to.equal(1);
|
|
||||||
done();
|
done();
|
||||||
}, DELAY);
|
}, DELAY);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('left', () => {
|
it('enter', done => {
|
||||||
input.value = '2000-10-1';
|
input.value = '2000-10-1';
|
||||||
keyDown(input, 13);
|
triggerEvent(input, 'input');
|
||||||
input.focus();
|
vm.$nextTick(_ => {
|
||||||
keyDown(input, 37);
|
keyDown(input, ENTER);
|
||||||
expect(input.selectionStart > 0).to.true;
|
setTimeout(_ => {
|
||||||
|
expect(datePicker.pickerVisible).to.false;
|
||||||
|
expect(datePicker.picker.date.getFullYear()).to.equal(2000);
|
||||||
|
expect(datePicker.picker.date.getMonth()).to.equal(9);
|
||||||
|
expect(datePicker.picker.date.getDate()).to.equal(1);
|
||||||
|
done();
|
||||||
|
}, DELAY);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('right', () => {
|
it('arrow keys during typing does not navigate', done => {
|
||||||
input.value = '2000-10-1';
|
const inputText = '2000-10-1';
|
||||||
keyDown(input, 13);
|
input.value = inputText;
|
||||||
input.focus();
|
triggerEvent(input, 'input');
|
||||||
keyDown(input, 39);
|
keyDown(input, LEFT);
|
||||||
expect(input.selectionStart > 0).to.true;
|
vm.$nextTick(_ => {
|
||||||
|
expect(input.value).to.equal(inputText);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('arrow keys navigates', done => {
|
||||||
|
const date = new Date(2000, 9, 1);
|
||||||
|
const prevDate = new Date(2000, 9, 0);
|
||||||
|
vm.value = date;
|
||||||
|
vm.$nextTick(_ => {
|
||||||
|
keyDown(input, LEFT);
|
||||||
|
setTimeout(_ => {
|
||||||
|
expect(datePicker.pickerVisible).to.true;
|
||||||
|
expect(datePicker.picker.date.getFullYear()).to.equal(prevDate.getFullYear());
|
||||||
|
expect(datePicker.picker.date.getMonth()).to.equal(prevDate.getMonth());
|
||||||
|
expect(datePicker.picker.date.getDate()).to.equal(prevDate.getDate());
|
||||||
|
done();
|
||||||
|
}, DELAY);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('nagivation', _ => {
|
||||||
|
const click = (el, cbk = () => {}) => {
|
||||||
|
el.click();
|
||||||
|
setTimeout(cbk, DELAY);
|
||||||
|
};
|
||||||
|
|
||||||
|
let prevMonth, prevYear, nextMonth, nextYear, getYearLabel, getMonthLabel;
|
||||||
|
|
||||||
|
const navigationTest = (value, cbk) => {
|
||||||
|
vm = createVue({
|
||||||
|
template: '<el-date-picker v-model="value" ref="compo" />',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
vm.$refs.compo.$el.querySelector('input').focus();
|
||||||
|
setTimeout(_ => {
|
||||||
|
const $el = vm.$refs.compo.picker.$el;
|
||||||
|
prevMonth = $el.querySelector('button.el-icon-arrow-left');
|
||||||
|
prevYear = $el.querySelector('button.el-icon-d-arrow-left');
|
||||||
|
nextMonth = $el.querySelector('button.el-icon-arrow-right');
|
||||||
|
nextYear = $el.querySelector('button.el-icon-d-arrow-right');
|
||||||
|
getYearLabel = () => $el.querySelectorAll('.el-date-picker__header-label')[0].textContent;
|
||||||
|
getMonthLabel = () => $el.querySelectorAll('.el-date-picker__header-label')[1].textContent;
|
||||||
|
cbk();
|
||||||
|
}, DELAY);
|
||||||
|
};
|
||||||
|
|
||||||
|
it('month, year', done => {
|
||||||
|
navigationTest(new Date(2000, 0, 1), _ => {
|
||||||
|
expect(getYearLabel()).to.include('2000');
|
||||||
|
expect(getMonthLabel()).to.include('1');
|
||||||
|
click(prevMonth, _ => {
|
||||||
|
expect(getYearLabel()).to.include('1999');
|
||||||
|
expect(getMonthLabel()).to.include('12');
|
||||||
|
click(prevYear, _ => {
|
||||||
|
expect(getYearLabel()).to.include('1998');
|
||||||
|
expect(getMonthLabel()).to.include('12');
|
||||||
|
click(nextMonth, _ => {
|
||||||
|
expect(getYearLabel()).to.include('1999');
|
||||||
|
expect(getMonthLabel()).to.include('1');
|
||||||
|
click(nextYear, _ => {
|
||||||
|
expect(getYearLabel()).to.include('2000');
|
||||||
|
expect(getMonthLabel()).to.include('1');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('month with fewer dates', done => {
|
||||||
|
// July has 31 days, June has 30
|
||||||
|
navigationTest(new Date(2000, 6, 31), _ => {
|
||||||
|
click(prevMonth, _ => {
|
||||||
|
expect(getYearLabel()).to.include('2000');
|
||||||
|
expect(getMonthLabel()).to.include('6');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('year with fewer Feburary dates', done => {
|
||||||
|
// Feburary 2008 has 29 days, Feburary 2007 has 28
|
||||||
|
navigationTest(new Date(2008, 1, 29), _ => {
|
||||||
|
click(prevYear, _ => {
|
||||||
|
expect(getYearLabel()).to.include('2007');
|
||||||
|
expect(getMonthLabel()).to.include('2');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -567,6 +841,67 @@ describe('DatePicker', () => {
|
|||||||
}, DELAY);
|
}, DELAY);
|
||||||
}, DELAY);
|
}, DELAY);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('default value', () => {
|
||||||
|
it('single', done => {
|
||||||
|
let defaultValue = '2000-10-01';
|
||||||
|
let expectValue = [new Date(2000, 9, 1), new Date(2000, 9, 2)];
|
||||||
|
|
||||||
|
vm = createVue({
|
||||||
|
template: '<el-date-picker type="daterange" v-model="value" ref="compo" :default-value="defaultValue" />',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
value: '',
|
||||||
|
defaultValue
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
vm.$el.querySelector('input').focus();
|
||||||
|
setTimeout(_ => {
|
||||||
|
const $el = vm.$refs.compo.picker.$el;
|
||||||
|
const defaultEls = $el.querySelectorAll('.el-date-table td.default');
|
||||||
|
expect(defaultEls.length).to.equal(1);
|
||||||
|
defaultEls[0].click();
|
||||||
|
setTimeout(_ => {
|
||||||
|
$el.querySelector('.el-date-table td.default + td').click();
|
||||||
|
setTimeout(_ => {
|
||||||
|
expect(vm.value).to.eql(expectValue);
|
||||||
|
done();
|
||||||
|
}, DELAY);
|
||||||
|
}, DELAY);
|
||||||
|
}, DELAY);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('array', done => {
|
||||||
|
let defaultValue = ['2000-01-01', '2000-02-01'];
|
||||||
|
let expectValue = [new Date(2000, 0, 1), new Date(2000, 1, 1)];
|
||||||
|
|
||||||
|
vm = createVue({
|
||||||
|
template: '<el-date-picker type="daterange" v-model="value" ref="compo" :default-value="defaultValue" />',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
value: '',
|
||||||
|
defaultValue
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
vm.$el.querySelector('input').focus();
|
||||||
|
setTimeout(_ => {
|
||||||
|
const defaultEls = vm.$refs.compo.picker.$el.querySelectorAll('.el-date-table td.default');
|
||||||
|
expect(defaultEls.length).to.equal(2);
|
||||||
|
defaultEls[0].click();
|
||||||
|
setTimeout(_ => {
|
||||||
|
defaultEls[1].click();
|
||||||
|
setTimeout(_ => {
|
||||||
|
expect(vm.value).to.eql(expectValue);
|
||||||
|
done();
|
||||||
|
}, DELAY);
|
||||||
|
}, DELAY);
|
||||||
|
}, DELAY);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('type:week', () => {
|
describe('type:week', () => {
|
||||||
@ -909,16 +1244,6 @@ describe('DatePicker', () => {
|
|||||||
expect(vm.picker.$el.querySelector('.disabled')).to.be.ok;
|
expect(vm.picker.$el.querySelector('.disabled')).to.be.ok;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('set disabled value', done => {
|
|
||||||
const date = new Date(1999, 10, 10, 10, 10, 10);
|
|
||||||
vm.picker.value = date;
|
|
||||||
|
|
||||||
setTimeout(_ => {
|
|
||||||
expect(vm.picker.date > date).to.true;
|
|
||||||
done();
|
|
||||||
}, DELAY);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('set value', done => {
|
it('set value', done => {
|
||||||
const date = new Date(3000, 10, 10, 10, 10, 10);
|
const date = new Date(3000, 10, 10, 10, 10, 10);
|
||||||
vm.picker.value = date;
|
vm.picker.value = date;
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import { createVue, destroyVM } from '../util';
|
import { createVue, destroyVM } from '../util';
|
||||||
|
|
||||||
|
const DELAY = 50;
|
||||||
|
|
||||||
describe('Form', () => {
|
describe('Form', () => {
|
||||||
let vm;
|
let vm;
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@ -362,7 +364,7 @@ describe('Form', () => {
|
|||||||
template: `
|
template: `
|
||||||
<el-form :model="form" :rules="rules" ref="form">
|
<el-form :model="form" :rules="rules" ref="form">
|
||||||
<el-form-item label="记住密码" prop="date" ref="field">
|
<el-form-item label="记住密码" prop="date" ref="field">
|
||||||
<el-date-picker type="date" placeholder="选择日期" v-model="form.date" style="width: 100%;"></el-date-picker>
|
<el-date-picker type="date" ref="picker" placeholder="选择日期" v-model="form.date" style="width: 100%;"></el-date-picker>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
`,
|
`,
|
||||||
@ -377,26 +379,38 @@ describe('Form', () => {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
setValue(value) {
|
|
||||||
this.form.date = value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, true);
|
}, true);
|
||||||
vm.$refs.form.validate(valid => {
|
vm.$refs.form.validate(valid => {
|
||||||
let field = vm.$refs.field;
|
let field = vm.$refs.field;
|
||||||
expect(valid).to.not.true;
|
expect(valid).to.not.true;
|
||||||
vm.$refs.form.$nextTick(_ => {
|
setTimeout(_ => {
|
||||||
expect(field.validateMessage).to.equal('请选择日期');
|
expect(field.validateMessage).to.equal('请选择日期');
|
||||||
|
// programatic modification does not trigger change
|
||||||
vm.setValue(new Date());
|
vm.value = new Date();
|
||||||
|
setTimeout(_ => {
|
||||||
vm.$refs.form.$nextTick(_ => {
|
expect(field.validateMessage).to.equal('请选择日期');
|
||||||
expect(field.validateMessage).to.equal('');
|
vm.value = '';
|
||||||
done();
|
// user modification triggers change
|
||||||
});
|
const input = vm.$refs.picker.$el.querySelector('input');
|
||||||
});
|
input.blur();
|
||||||
|
input.focus();
|
||||||
|
setTimeout(_ => {
|
||||||
|
const keyDown = (el, keyCode) => {
|
||||||
|
const evt = document.createEvent('Events');
|
||||||
|
evt.initEvent('keydown', true, true);
|
||||||
|
evt.keyCode = keyCode;
|
||||||
|
el.dispatchEvent(evt);
|
||||||
|
};
|
||||||
|
keyDown(input, 37);
|
||||||
|
keyDown(input, 13);
|
||||||
|
setTimeout(_ => {
|
||||||
|
expect(field.validateMessage).to.equal('');
|
||||||
|
done();
|
||||||
|
}, DELAY);
|
||||||
|
}, DELAY);
|
||||||
|
}, DELAY);
|
||||||
|
}, DELAY);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('timepicker', done => {
|
it('timepicker', done => {
|
||||||
@ -404,7 +418,7 @@ describe('Form', () => {
|
|||||||
template: `
|
template: `
|
||||||
<el-form :model="form" :rules="rules" ref="form">
|
<el-form :model="form" :rules="rules" ref="form">
|
||||||
<el-form-item label="记住密码" prop="date" ref="field">
|
<el-form-item label="记住密码" prop="date" ref="field">
|
||||||
<el-time-picker type="fixed-time" placeholder="选择时间" v-model="form.date" style="width: 100%;"></el-time-picker>
|
<el-time-picker type="fixed-time" ref="picker" placeholder="选择时间" v-model="form.date" style="width: 100%;"></el-time-picker>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
`,
|
`,
|
||||||
@ -419,25 +433,31 @@ describe('Form', () => {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
setValue(value) {
|
|
||||||
this.form.date = value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, true);
|
}, true);
|
||||||
vm.$refs.form.validate(valid => {
|
vm.$refs.form.validate(valid => {
|
||||||
let field = vm.$refs.field;
|
let field = vm.$refs.field;
|
||||||
expect(valid).to.not.true;
|
expect(valid).to.not.true;
|
||||||
vm.$refs.form.$nextTick(_ => {
|
setTimeout(_ => {
|
||||||
expect(field.validateMessage).to.equal('请选择时间');
|
expect(field.validateMessage).to.equal('请选择时间');
|
||||||
vm.setValue(new Date());
|
// programatic modification does not trigger change
|
||||||
|
vm.value = new Date();
|
||||||
vm.$refs.form.$nextTick(_ => {
|
setTimeout(_ => {
|
||||||
expect(field.validateMessage).to.equal('');
|
expect(field.validateMessage).to.equal('请选择时间');
|
||||||
done();
|
vm.value = '';
|
||||||
});
|
// user modification triggers change
|
||||||
});
|
const input = vm.$refs.picker.$el.querySelector('input');
|
||||||
|
input.blur();
|
||||||
|
input.focus();
|
||||||
|
setTimeout(_ => {
|
||||||
|
vm.$refs.picker.picker.$el.querySelector('.confirm').click();
|
||||||
|
setTimeout(_ => {
|
||||||
|
expect(field.validateMessage).to.equal('');
|
||||||
|
done();
|
||||||
|
}, DELAY);
|
||||||
|
}, DELAY);
|
||||||
|
}, DELAY);
|
||||||
|
}, DELAY);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('checkbox group', done => {
|
it('checkbox group', done => {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { createTest, destroyVM, createVue } from '../util';
|
import { createTest, destroyVM, createVue } from '../util';
|
||||||
import TimePicker from 'packages/time-picker';
|
import TimePicker from 'packages/time-picker';
|
||||||
import Vue from 'vue';
|
|
||||||
|
const DELAY = 100;
|
||||||
|
|
||||||
describe('TimePicker', () => {
|
describe('TimePicker', () => {
|
||||||
let vm;
|
let vm;
|
||||||
@ -15,7 +16,6 @@ describe('TimePicker', () => {
|
|||||||
});
|
});
|
||||||
expect(vm.$el.querySelector('input').getAttribute('placeholder')).to.equal('test');
|
expect(vm.$el.querySelector('input').getAttribute('placeholder')).to.equal('test');
|
||||||
expect(vm.$el.querySelector('input').getAttribute('readonly')).to.ok;
|
expect(vm.$el.querySelector('input').getAttribute('readonly')).to.ok;
|
||||||
destroyVM(vm);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('format', () => {
|
it('format', () => {
|
||||||
@ -24,7 +24,6 @@ describe('TimePicker', () => {
|
|||||||
value: new Date(2016, 9, 10, 18, 40)
|
value: new Date(2016, 9, 10, 18, 40)
|
||||||
});
|
});
|
||||||
expect(vm.$el.querySelector('input').value).to.equal('18-40-00');
|
expect(vm.$el.querySelector('input').value).to.equal('18-40-00');
|
||||||
destroyVM(vm);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('default value', done => {
|
it('default value', done => {
|
||||||
@ -44,20 +43,28 @@ describe('TimePicker', () => {
|
|||||||
expect(times[0].textContent).to.equal('18');
|
expect(times[0].textContent).to.equal('18');
|
||||||
expect(times[1].textContent).to.equal('40');
|
expect(times[1].textContent).to.equal('40');
|
||||||
expect(times[2].textContent).to.equal('00');
|
expect(times[2].textContent).to.equal('00');
|
||||||
destroyVM(vm);
|
|
||||||
done();
|
done();
|
||||||
}, 100);
|
}, DELAY);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('select time', done => {
|
it('select time', done => {
|
||||||
vm = createTest(TimePicker, true);
|
vm = createVue({
|
||||||
const input = vm.$el.querySelector('input');
|
template: '<el-time-picker ref="compo" v-model="value"></el-time-picker>',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
value: ''
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
const timePicker = vm.$refs.compo;
|
||||||
|
const input = timePicker.$el.querySelector('input');
|
||||||
|
|
||||||
input.blur();
|
input.blur();
|
||||||
input.focus();
|
input.focus();
|
||||||
|
|
||||||
Vue.nextTick(_ => {
|
setTimeout(_ => {
|
||||||
const list = vm.picker.$el.querySelectorAll('.el-time-spinner__list');
|
const list = timePicker.picker.$el.querySelectorAll('.el-time-spinner__list');
|
||||||
|
|
||||||
const hoursEl = list[0];
|
const hoursEl = list[0];
|
||||||
const minutesEl = list[1];
|
const minutesEl = list[1];
|
||||||
const secondsEl = list[2];
|
const secondsEl = list[2];
|
||||||
@ -65,57 +72,75 @@ describe('TimePicker', () => {
|
|||||||
const minuteEl = minutesEl.querySelectorAll('.el-time-spinner__item')[36];
|
const minuteEl = minutesEl.querySelectorAll('.el-time-spinner__item')[36];
|
||||||
const secondEl = secondsEl.querySelectorAll('.el-time-spinner__item')[20];
|
const secondEl = secondsEl.querySelectorAll('.el-time-spinner__item')[20];
|
||||||
|
|
||||||
|
// click hour, minute, second one at a time.
|
||||||
hourEl.click();
|
hourEl.click();
|
||||||
minuteEl.click();
|
vm.$nextTick(_ => {
|
||||||
secondEl.click();
|
minuteEl.click();
|
||||||
|
vm.$nextTick(_ => {
|
||||||
Vue.nextTick(_ => {
|
secondEl.click();
|
||||||
const date = vm.picker.currentDate;
|
setTimeout(_ => {
|
||||||
|
const date = timePicker.picker.date;
|
||||||
expect(hourEl.classList.contains('active')).to.true;
|
expect(hourEl.classList.contains('active')).to.true;
|
||||||
expect(minuteEl.classList.contains('active')).to.true;
|
expect(minuteEl.classList.contains('active')).to.true;
|
||||||
expect(secondEl.classList.contains('active')).to.true;
|
expect(secondEl.classList.contains('active')).to.true;
|
||||||
expect(date.getHours()).to.equal(4);
|
expect(date.getHours()).to.equal(4);
|
||||||
expect(date.getMinutes()).to.equal(36);
|
expect(date.getMinutes()).to.equal(36);
|
||||||
expect(date.getSeconds()).to.equal(20);
|
expect(date.getSeconds()).to.equal(20);
|
||||||
destroyVM(vm);
|
done();
|
||||||
done();
|
}, DELAY);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
}, DELAY);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('click cancel button', done => {
|
it('click cancel button', done => {
|
||||||
vm = createTest(TimePicker, true);
|
vm = createVue({
|
||||||
const input = vm.$el.querySelector('input');
|
template: '<el-time-picker ref="compo" v-model="value"></el-time-picker>',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
value: ''
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
const timePicker = vm.$refs.compo;
|
||||||
|
const input = timePicker.$el.querySelector('input');
|
||||||
|
|
||||||
input.blur();
|
input.blur();
|
||||||
input.focus();
|
input.focus();
|
||||||
|
|
||||||
Vue.nextTick(_ => {
|
setTimeout(_ => {
|
||||||
vm.picker.$el.querySelector('.el-time-panel__btn.cancel').click();
|
timePicker.picker.$el.querySelector('.el-time-panel__btn.cancel').click();
|
||||||
|
|
||||||
Vue.nextTick(_ => {
|
setTimeout(_ => {
|
||||||
expect(vm.picker.currentDate).to.empty;
|
expect(vm.value).to.equal('');
|
||||||
done();
|
done();
|
||||||
});
|
}, DELAY);
|
||||||
});
|
}, DELAY);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('click confirm button', done => {
|
it('click confirm button', done => {
|
||||||
vm = createTest(TimePicker, true);
|
vm = createVue({
|
||||||
const input = vm.$el.querySelector('input');
|
template: '<el-time-picker ref="compo" v-model="value"></el-time-picker>',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
value: ''
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
const timePicker = vm.$refs.compo;
|
||||||
|
const input = timePicker.$el.querySelector('input');
|
||||||
|
|
||||||
input.blur();
|
input.blur();
|
||||||
input.focus();
|
input.focus();
|
||||||
|
|
||||||
Vue.nextTick(_ => {
|
setTimeout(_ => {
|
||||||
vm.picker.$el.querySelector('.el-time-panel__btn.confirm').click();
|
timePicker.picker.$el.querySelector('.el-time-panel__btn.confirm').click();
|
||||||
|
|
||||||
Vue.nextTick(_ => {
|
setTimeout(_ => {
|
||||||
expect(vm.picker.currentDate).to.exist;
|
expect(vm.value.toISOString()).to.exist;
|
||||||
done();
|
done();
|
||||||
});
|
}, DELAY);
|
||||||
});
|
}, DELAY);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('set format', done => {
|
it('set format', done => {
|
||||||
@ -130,7 +155,6 @@ describe('TimePicker', () => {
|
|||||||
|
|
||||||
setTimeout(_ => {
|
setTimeout(_ => {
|
||||||
expect(vm.picker.$el.querySelectorAll('.el-time-spinner__wrapper')[2].style.display).to.equal('none');
|
expect(vm.picker.$el.querySelectorAll('.el-time-spinner__wrapper')[2].style.display).to.equal('none');
|
||||||
destroyVM(vm);
|
|
||||||
done();
|
done();
|
||||||
}, 20);
|
}, 20);
|
||||||
});
|
});
|
||||||
@ -147,9 +171,8 @@ describe('TimePicker', () => {
|
|||||||
|
|
||||||
setTimeout(_ => {
|
setTimeout(_ => {
|
||||||
expect(vm.picker.$el.querySelectorAll('.el-time-spinner__wrapper')[2].style.display).to.equal('none');
|
expect(vm.picker.$el.querySelectorAll('.el-time-spinner__wrapper')[2].style.display).to.equal('none');
|
||||||
destroyVM(vm);
|
|
||||||
done();
|
done();
|
||||||
}, 20);
|
}, DELAY);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('selectableRange', done => {
|
it('selectableRange', done => {
|
||||||
@ -172,9 +195,8 @@ describe('TimePicker', () => {
|
|||||||
|
|
||||||
hoursEl.querySelectorAll('.disabled')[0].click();
|
hoursEl.querySelectorAll('.disabled')[0].click();
|
||||||
expect(disabledHours).to.not.include.members([18, 19, 20]);
|
expect(disabledHours).to.not.include.members([18, 19, 20]);
|
||||||
destroyVM(vm);
|
|
||||||
done();
|
done();
|
||||||
}, 20);
|
}, DELAY);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('event focus and blur', done => {
|
it('event focus and blur', done => {
|
||||||
@ -229,48 +251,66 @@ describe('TimePicker', () => {
|
|||||||
|
|
||||||
describe('TimePicker(range)', () => {
|
describe('TimePicker(range)', () => {
|
||||||
let vm;
|
let vm;
|
||||||
beforeEach(done => {
|
|
||||||
|
afterEach(() => destroyVM(vm));
|
||||||
|
|
||||||
|
it('create', done => {
|
||||||
vm = createTest(TimePicker, {
|
vm = createTest(TimePicker, {
|
||||||
isRange: true,
|
isRange: true,
|
||||||
value: [new Date(2016, 9, 10, 18, 40), new Date(2016, 9, 10, 19, 40)]
|
value: [new Date(2016, 9, 10, 18, 40), new Date(2016, 9, 10, 19, 40)]
|
||||||
}, true);
|
}, true);
|
||||||
const input = vm.$el.querySelector('input');
|
|
||||||
|
|
||||||
input.click();
|
vm.$el.querySelector('input').click();
|
||||||
setTimeout(done, 20);
|
|
||||||
|
setTimeout(_ => {
|
||||||
|
expect(vm.picker.$el.querySelectorAll('.el-time-range-picker__cell')).to.length(2);
|
||||||
|
expect(vm.picker.minDate.getTime()).to.equal(new Date(2016, 9, 10, 18, 40).getTime());
|
||||||
|
expect(vm.picker.maxDate.getTime()).to.equal(new Date(2016, 9, 10, 19, 40).getTime());
|
||||||
|
done();
|
||||||
|
}, DELAY);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => destroyVM(vm));
|
it('default value', done => {
|
||||||
|
const defaultValue = [new Date(2000, 9, 1, 10, 0, 0), new Date(2000, 9, 1, 11, 0, 0)];
|
||||||
it('create', () => {
|
vm = createVue({
|
||||||
expect(vm.picker.$el.querySelectorAll('.el-time-range-picker__cell')).to.length(2);
|
template: '<el-time-picker ref="compo" is-range v-model="value" :default-value="defaultValue"></el-time-picker>',
|
||||||
});
|
data() {
|
||||||
|
return {
|
||||||
it('default value', () => {
|
value: '',
|
||||||
expect(vm.picker.minTime.getTime()).to.equal(new Date(2016, 9, 10, 18, 40).getTime());
|
defaultValue
|
||||||
expect(vm.picker.maxTime.getTime()).to.equal(new Date(2016, 9, 10, 19, 40).getTime());
|
};
|
||||||
});
|
}
|
||||||
|
|
||||||
it('minTime < maxTime', done => {
|
|
||||||
const vm2 = createTest(TimePicker, {
|
|
||||||
isRange: true,
|
|
||||||
value: [new Date(2016, 9, 10, 23, 40), new Date(2016, 9, 10, 10, 40)]
|
|
||||||
}, true);
|
}, true);
|
||||||
const input = vm2.$el.querySelector('input');
|
|
||||||
|
|
||||||
input.click();
|
const timePicker = vm.$refs.compo;
|
||||||
setTimeout(() => {
|
timePicker.$el.querySelector('input').click();
|
||||||
expect(vm2.picker.maxTime >= vm2.picker.minTime).to.true;
|
|
||||||
destroyVM(vm2);
|
setTimeout(_ => {
|
||||||
|
expect(timePicker.picker.minDate.getTime()).to.equal(defaultValue[0].getTime());
|
||||||
|
expect(timePicker.picker.maxDate.getTime()).to.equal(defaultValue[1].getTime());
|
||||||
done();
|
done();
|
||||||
}, 100);
|
}, DELAY);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('click cancel button', done => {
|
it('cancel button', done => {
|
||||||
vm.picker.$el.querySelector('.el-time-panel__btn.cancel').click();
|
vm = createVue({
|
||||||
Vue.nextTick(_ => {
|
template: '<el-time-picker ref="compo" is-range v-model="value"></el-time-picker>',
|
||||||
expect(vm.picker.currentDate).to.empty;
|
data() {
|
||||||
done();
|
return {
|
||||||
});
|
value: ''
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
const timePicker = vm.$refs.compo;
|
||||||
|
timePicker.$el.querySelector('input').click();
|
||||||
|
setTimeout(_ => {
|
||||||
|
timePicker.picker.$el.querySelector('.cancel').click();
|
||||||
|
setTimeout(_ => {
|
||||||
|
expect(timePicker.picker.visible).to.false;
|
||||||
|
expect(vm.value).to.equal('');
|
||||||
|
done();
|
||||||
|
}, DELAY);
|
||||||
|
}, DELAY);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -27,7 +27,6 @@ describe('TimeSelect', () => {
|
|||||||
expect(vm.picker.end).to.equal('18:30');
|
expect(vm.picker.end).to.equal('18:30');
|
||||||
expect(vm.picker.step).to.equal('00:15');
|
expect(vm.picker.step).to.equal('00:15');
|
||||||
expect(vm.$el.querySelector('input').getAttribute('placeholder')).to.equal('test');
|
expect(vm.$el.querySelector('input').getAttribute('placeholder')).to.equal('test');
|
||||||
destroyVM(vm);
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -60,7 +59,6 @@ describe('TimeSelect', () => {
|
|||||||
target.click();
|
target.click();
|
||||||
Vue.nextTick(_ => {
|
Vue.nextTick(_ => {
|
||||||
expect(vm.value).to.equal(time);
|
expect(vm.value).to.equal(time);
|
||||||
destroyVM(vm);
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -79,7 +77,6 @@ describe('TimeSelect', () => {
|
|||||||
expect(input.value).to.equal('14:30');
|
expect(input.value).to.equal('14:30');
|
||||||
expect(vm.picker.$el.querySelector('.selected')).to.be.ok;
|
expect(vm.picker.$el.querySelector('.selected')).to.be.ok;
|
||||||
expect(vm.picker.$el.querySelector('.selected').textContent).to.equal('14:30');
|
expect(vm.picker.$el.querySelector('.selected').textContent).to.equal('14:30');
|
||||||
destroyVM(vm);
|
|
||||||
done();
|
done();
|
||||||
}, 50);
|
}, 50);
|
||||||
});
|
});
|
||||||
@ -104,7 +101,6 @@ describe('TimeSelect', () => {
|
|||||||
const elm = elms[elms.length - 1];
|
const elm = elms[elms.length - 1];
|
||||||
|
|
||||||
expect(elm.textContent).to.equal('14:30');
|
expect(elm.textContent).to.equal('14:30');
|
||||||
destroyVM(vm);
|
|
||||||
done();
|
done();
|
||||||
}, 50);
|
}, 50);
|
||||||
});
|
});
|
||||||
@ -134,8 +130,7 @@ describe('TimeSelect', () => {
|
|||||||
vm.value = '10:30';
|
vm.value = '10:30';
|
||||||
|
|
||||||
setTimeout(_ => {
|
setTimeout(_ => {
|
||||||
expect(picker.picker.value).to.equal('09:30');
|
expect(picker.picker.value).to.equal('10:30');
|
||||||
destroyVM(vm);
|
|
||||||
done();
|
done();
|
||||||
}, 50);
|
}, 50);
|
||||||
}, 50);
|
}, 50);
|
||||||
@ -161,7 +156,6 @@ describe('TimeSelect', () => {
|
|||||||
const elm = picker.picker.$el.querySelector('.disabled');
|
const elm = picker.picker.$el.querySelector('.disabled');
|
||||||
|
|
||||||
expect(elm.textContent).to.equal('14:30');
|
expect(elm.textContent).to.equal('14:30');
|
||||||
destroyVM(vm);
|
|
||||||
done();
|
done();
|
||||||
}, 50);
|
}, 50);
|
||||||
});
|
});
|
||||||
@ -191,8 +185,7 @@ describe('TimeSelect', () => {
|
|||||||
vm.value = '10:30';
|
vm.value = '10:30';
|
||||||
|
|
||||||
setTimeout(_ => {
|
setTimeout(_ => {
|
||||||
expect(picker.picker.value).to.equal('09:30');
|
expect(picker.picker.value).to.equal('10:30');
|
||||||
destroyVM(vm);
|
|
||||||
done();
|
done();
|
||||||
}, 50);
|
}, 50);
|
||||||
}, 50);
|
}, 50);
|
||||||
@ -242,7 +235,6 @@ describe('TimeSelect', () => {
|
|||||||
|
|
||||||
vm.$nextTick(_ => {
|
vm.$nextTick(_ => {
|
||||||
expect(spy.calledOnce).to.be.true;
|
expect(spy.calledOnce).to.be.true;
|
||||||
destroyVM(vm);
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user