Refactor/datepicker (#1623)

* DatePicker: replace native input with el-input

* DatePicker: support size prop, closes #1069, closes #1440

* DatePicker: show correct date for initial value, fixed #1129

* TimePicker: fix empty value when panel appears, fixed #1583

* DatePicker: trigger clickoutside when clicking icon, fixed #1604

* DatePicker: fix year type in year panel, fixed #1607

* DatePicker: fix test

* DatePicker: add doc
pull/1644/head
cinwell.li 2016-12-09 00:06:34 +08:00 committed by baiyaaaaa
parent c7cfcc36bc
commit 55dfb0c296
23 changed files with 160 additions and 308 deletions

View File

@ -254,6 +254,7 @@ Picking a date range is supported.
|---------- |-------------- |---------- |-------------------------------- |-------- | |---------- |-------------- |---------- |-------------------------------- |-------- |
| 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 | — |
| editable | whether the input is editable | boolean | - | true | | editable | whether the input is editable | boolean | - | true |
| placeholder | placeholder | string | — | — | | placeholder | placeholder | 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 |

View File

@ -210,6 +210,7 @@ Select date and time in one picker.
| 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 |
| editable | whether the input is editable | boolean | - | true | | editable | whether the input is editable | boolean | - | true |
|size | size of Input | string | large/small/mini | — |
| placeholder | placeholder | string | — | — | | placeholder | placeholder | 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`, <br>hour `HH`, minute `mm`, second `ss` | yyyy-MM-dd | | format | format of the picker | string | year `yyyy` month `MM` day `dd`, <br>hour `HH`, minute `mm`, second `ss` | yyyy-MM-dd |

View File

@ -146,6 +146,7 @@ Can pick an arbitrary time range.
| 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 |
| editable | whether the input is editable | boolean | - | true | | editable | whether the input is editable | boolean | - | true |
|size | size of Input | string | large/small/mini | — |
| placeholder | placeholder | string | — | — | | placeholder | placeholder | string | — | — |
| format | format of the picker | string | hour `HH`, minute `mm`, second `ss` | HH:mm:ss | | format | format of the picker | string | 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 | | value | value of the picker | date for Time Picker, and string for Time Select | hour `HH`, minute `mm`, second `ss` | HH:mm:ss |

View File

@ -289,6 +289,7 @@
| readonly | 完全只读 | boolean | — | false | | readonly | 完全只读 | boolean | — | false |
| disabled | 禁用 | boolean | - | false | | disabled | 禁用 | boolean | - | false |
| editable | 文本框可输入 | boolean | - | true | | editable | 文本框可输入 | boolean | - | true |
| size | 输入框尺寸 | string | large, small, mini | — |
| placeholder | 占位内容 | string | — | — | | placeholder | 占位内容 | string | — | — |
| type | 显示类型 | string | year/month/date/week/<br>datetime/datetimerange/daterange | date | | type | 显示类型 | string | year/month/date/week/<br>datetime/datetimerange/daterange | date |
| format | 时间日期格式化 | string | 年 `yyyy`,月 `MM`,日 `dd`<br>小时 `HH`,分 `mm`,秒 `ss` | yyyy-MM-dd | | format | 时间日期格式化 | string | 年 `yyyy`,月 `MM`,日 `dd`<br>小时 `HH`,分 `mm`,秒 `ss` | yyyy-MM-dd |

View File

@ -233,6 +233,7 @@
| readonly | 完全只读 | boolean | — | false | | readonly | 完全只读 | boolean | — | false |
| disabled | 禁用 | boolean | - | false | | disabled | 禁用 | boolean | - | false |
| editable | 文本框可输入 | boolean | - | true | | editable | 文本框可输入 | boolean | - | true |
| size | 输入框尺寸 | string | large, small, mini | — |
| placeholder | 占位内容 | string | — | — | | placeholder | 占位内容 | string | — | — |
| type | 显示类型 | string | year/month/date/week/<br>datetime/datetimerange/daterange | date | | type | 显示类型 | string | year/month/date/week/<br>datetime/datetimerange/daterange | date |
| format | 时间日期格式化 | string | 年 `yyyy`,月 `MM`,日 `dd`<br>小时 `HH`,分 `mm`,秒 `ss` | yyyy-MM-dd | | format | 时间日期格式化 | string | 年 `yyyy`,月 `MM`,日 `dd`<br>小时 `HH`,分 `mm`,秒 `ss` | yyyy-MM-dd |

View File

@ -153,6 +153,7 @@
| readonly | 完全只读 | boolean | — | false | | readonly | 完全只读 | boolean | — | false |
| disabled | 禁用 | boolean | - | false | | disabled | 禁用 | boolean | - | false |
| editable | 文本框可输入 | boolean | - | true | | editable | 文本框可输入 | boolean | - | true |
| size | 输入框尺寸 | string | large, small, mini | — |
| placeholder | 占位内容 | string | — | — | | placeholder | 占位内容 | string | — | — |
| format | 时间格式化(TimePicker) | string | 小时:`HH`,分:`mm`,秒:`ss` | 'HH:mm:ss' | | format | 时间格式化(TimePicker) | string | 小时:`HH`,分:`mm`,秒:`ss` | 'HH:mm:ss' |
| value | 绑定值 | TimePicker: Date<br>TimeSelect: String | - | - | | value | 绑定值 | TimePicker: Date<br>TimeSelect: String | - | - |

View File

@ -136,12 +136,10 @@
}, },
handleScroll(type) { handleScroll(type) {
window.setTimeout(() => {
const ajust = {}; const ajust = {};
ajust[`${type}s`] = Math.min(Math.floor((this.$refs[type].scrollTop - 80) / 32 + 3), 59); ajust[`${type}s`] = Math.min(Math.floor((this.$refs[type].scrollTop - 80) / 32 + 3), 59);
this.$emit('change', ajust); this.$emit('change', ajust);
}, 0);
}, },
ajustScrollTop() { ajustScrollTop() {

View File

@ -67,17 +67,17 @@
date.setFullYear(year); date.setFullYear(year);
style.disabled = typeof this.disabledDate === 'function' && style.disabled = typeof this.disabledDate === 'function' &&
this.disabledDate(date); this.disabledDate(date);
style.current = this.year === year; style.current = Number(this.year) === year;
return style; return style;
}, },
nextTenYear() { nextTenYear() {
this.$emit('pick', this.year + 10, false); this.$emit('pick', Number(this.year) + 10, false);
}, },
prevTenYear() { prevTenYear() {
this.$emit('pick', this.year - 10, false); this.$emit('pick', Number(this.year) - 10, false);
}, },
handleYearTableClick(event) { handleYearTableClick(event) {

View File

@ -21,20 +21,23 @@
<div class="el-date-range-picker__time-header" v-if="showTime"> <div class="el-date-range-picker__time-header" v-if="showTime">
<span class="el-date-range-picker__editors-wrap"> <span class="el-date-range-picker__editors-wrap">
<span class="el-date-range-picker__time-picker-wrap"> <span class="el-date-range-picker__time-picker-wrap">
<input <el-input
size="small"
ref="minInput"
:placeholder="t('el.datepicker.startDate')" :placeholder="t('el.datepicker.startDate')"
class="el-date-range-picker__editor" class="el-date-range-picker__editor"
:value="minVisibleDate" :value="minVisibleDate"
@input="handleDateInput($event, 'min')" @input.native="handleDateInput($event, 'min')"
@change="handleDateChange($event, 'min')"/> @change.native="handleDateChange($event, 'min')" />
</span> </span>
<span class="el-date-range-picker__time-picker-wrap"> <span class="el-date-range-picker__time-picker-wrap">
<input <el-input
size="small"
:placeholder="t('el.datepicker.startTime')" :placeholder="t('el.datepicker.startTime')"
class="el-date-range-picker__editor" class="el-date-range-picker__editor"
:value="minVisibleTime" :value="minVisibleTime"
@focus="minTimePickerVisible = !minTimePickerVisible" @focus="minTimePickerVisible = !minTimePickerVisible"
@change="handleTimeChange($event, 'min')"/> @change.native="handleTimeChange($event, 'min')" />
<time-picker <time-picker
:picker-width="minPickerWidth" :picker-width="minPickerWidth"
ref="minTimePicker" ref="minTimePicker"
@ -47,24 +50,25 @@
<span class="el-icon-arrow-right"></span> <span class="el-icon-arrow-right"></span>
<span class="el-date-range-picker__editors-wrap is-right"> <span class="el-date-range-picker__editors-wrap is-right">
<span class="el-date-range-picker__time-picker-wrap"> <span class="el-date-range-picker__time-picker-wrap">
<input <el-input
ref="minInput" size="small"
:placeholder="t('el.datepicker.endDate')" :placeholder="t('el.datepicker.endDate')"
class="el-date-range-picker__editor" class="el-date-range-picker__editor"
:value="maxVisibleDate" :value="maxVisibleDate"
:readonly="!minDate" :readonly="!minDate"
@input="handleDateInput($event, 'max')" @input.native="handleDateInput($event, 'max')"
@change="handleDateChange($event, 'max')" /> @change.native="handleDateChange($event, 'max')" />
</span> </span>
<span class="el-date-range-picker__time-picker-wrap"> <span class="el-date-range-picker__time-picker-wrap">
<input <el-input
size="small"
ref="maxInput" ref="maxInput"
:placeholder="t('el.datepicker.endTime')" :placeholder="t('el.datepicker.endTime')"
class="el-date-range-picker__editor" class="el-date-range-picker__editor"
:value="maxVisibleTime" :value="maxVisibleTime"
@focus="minDate && (maxTimePickerVisible = !maxTimePickerVisible)" @focus="minDate && (maxTimePickerVisible = !maxTimePickerVisible)"
:readonly="!minDate" :readonly="!minDate"
@change="handleTimeChange($event, 'max')" /> @change.native="handleTimeChange($event, 'max')" />
<time-picker <time-picker
:picker-width="maxPickerWidth" :picker-width="maxPickerWidth"
ref="maxTimePicker" ref="maxTimePicker"
@ -142,6 +146,9 @@
<script type="text/babel"> <script type="text/babel">
import { nextMonth, prevMonth, toDate, formatDate, parseDate } from '../util'; import { nextMonth, prevMonth, toDate, formatDate, parseDate } from '../util';
import Locale from 'element-ui/src/mixins/locale'; import Locale from 'element-ui/src/mixins/locale';
import TimePicker from './time';
import DateTable from '../basic/date-table';
import ElInput from 'element-ui/packages/input';
export default { export default {
mixins: [Locale], mixins: [Locale],
@ -234,8 +241,8 @@
showTime(val) { showTime(val) {
if (!val) return; if (!val) return;
this.$nextTick(_ => { this.$nextTick(_ => {
const minInputElm = this.$refs.minInput; const minInputElm = this.$refs.minInput.$el;
const maxInputElm = this.$refs.maxInput; const maxInputElm = this.$refs.maxInput.$el;
if (minInputElm) { if (minInputElm) {
this.minPickerWidth = minInputElm.getBoundingClientRect().width + 10; this.minPickerWidth = minInputElm.getBoundingClientRect().width + 10;
} }
@ -275,6 +282,7 @@
} else if (Array.isArray(newVal)) { } else if (Array.isArray(newVal)) {
this.minDate = newVal[0] ? toDate(newVal[0]) : null; this.minDate = newVal[0] ? toDate(newVal[0]) : null;
this.maxDate = newVal[1] ? toDate(newVal[1]) : null; this.maxDate = newVal[1] ? toDate(newVal[1]) : null;
this.date = new Date(this.minDate);
} }
} }
}, },
@ -455,9 +463,6 @@
} }
}, },
components: { components: { TimePicker, DateTable, ElInput }
TimePicker: require('./time'),
DateTable: require('../basic/date-table')
}
}; };
</script> </script>

View File

@ -22,20 +22,20 @@
<div class="el-picker-panel__body"> <div class="el-picker-panel__body">
<div class="el-date-picker__time-header" v-if="showTime"> <div class="el-date-picker__time-header" v-if="showTime">
<span class="el-date-picker__editor-wrap"> <span class="el-date-picker__editor-wrap">
<input <el-input
:placehoder="t('el.datepicker.selectDate')" :placeholder="t('el.datepicker.selectDate')"
type="text" :value="visibleDate"
v-model.lazy="visibleDate" size="small"
class="el-date-picker__editor"> @change.native="visibleDate = $event.target.value" />
</span> </span>
<span class="el-date-picker__editor-wrap"> <span class="el-date-picker__editor-wrap">
<input <el-input
ref="input" ref="input"
@focus="timePickerVisible = !timePickerVisible" @focus="timePickerVisible = !timePickerVisible"
v-model.lazy="visibleTime" :placeholder="t('el.datepicker.selectTime')"
:placehoder="t('el.datepicker.selectTime')" :value="visibleTime"
type="text" size="small"
class="el-date-picker__editor"> @change.native="visibleTime = $event.target.value" />
<time-picker <time-picker
ref="timepicker" ref="timepicker"
:date="date" :date="date"
@ -128,6 +128,11 @@
<script type="text/babel"> <script type="text/babel">
import { formatDate, parseDate } from '../util'; import { formatDate, parseDate } 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 TimePicker from './time';
import YearTable from '../basic/year-table';
import MonthTable from '../basic/month-table';
import DateTable from '../basic/date-table';
export default { export default {
mixins: [Locale], mixins: [Locale],
@ -137,7 +142,7 @@
/* istanbul ignore if */ /* istanbul ignore if */
if (!val) return; if (!val) return;
this.$nextTick(_ => { this.$nextTick(_ => {
const inputElm = this.$refs.input; const inputElm = this.$refs.input.$el;
if (inputElm) { if (inputElm) {
this.pickerWidth = inputElm.getBoundingClientRect().width + 10; this.pickerWidth = inputElm.getBoundingClientRect().width + 10;
} }
@ -345,10 +350,7 @@
}, },
components: { components: {
TimePicker: require('./time'), TimePicker, YearTable, MonthTable, DateTable, ElInput
YearTable: require('../basic/year-table'),
MonthTable: require('../basic/month-table'),
DateTable: require('../basic/date-table')
}, },
mounted() { mounted() {

View File

@ -1,5 +1,8 @@
<template> <template>
<transition name="el-zoom-in-top" @after-leave="$emit('dodestroy')"> <transition
name="el-zoom-in-top"
@before-enter="panelCreated"
@after-leave="$emit('dodestroy')">
<div <div
v-show="visible" v-show="visible"
:style="{ width: width + 'px' }" :style="{ width: width + 'px' }"
@ -52,6 +55,7 @@
<script type="text/babel"> <script type="text/babel">
import { parseDate, limitRange } from '../util'; import { parseDate, limitRange } from '../util';
import Locale from 'element-ui/src/mixins/locale'; import Locale from 'element-ui/src/mixins/locale';
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');
@ -75,9 +79,7 @@
export default { export default {
mixins: [Locale], mixins: [Locale],
components: { components: { TimeSpinner },
TimeSpinner: require('../basic/time-spinner')
},
computed: { computed: {
showSeconds() { showSeconds() {
@ -87,26 +89,6 @@
props: ['value'], props: ['value'],
watch: {
value(val) {
const time = clacTime(val);
if (time.minTime === this.minTime && time.maxTime === this.maxTime) {
return;
}
this.handleMinChange({
hours: time.minTime.getHours(),
minutes: time.minTime.getMinutes(),
seconds: time.minTime.getSeconds()
});
this.handleMaxChange({
hours: time.maxTime.getHours(),
minutes: time.maxTime.getMinutes(),
seconds: time.maxTime.getSeconds()
});
}
},
data() { data() {
const time = clacTime(this.$options.defaultValue); const time = clacTime(this.$options.defaultValue);
@ -127,6 +109,24 @@
}, },
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()
});
this.handleMaxChange({
hours: time.maxTime.getHours(),
minutes: time.maxTime.getMinutes(),
seconds: time.maxTime.getSeconds()
});
},
handleClear() { handleClear() {
this.handleCancel(); this.handleCancel();
}, },

View File

@ -1,35 +1,26 @@
<template> <template>
<span <el-input
class="el-date-editor" class="el-date-editor"
v-clickoutside="handleClose"
:class="{
'is-have-trigger': haveTrigger,
'is-active': pickerVisible,
'is-filled': !!this.internalValue
}">
<input
class="el-date-editor__editor"
:class="{ 'is-disabled': disabled }"
:readonly="!editable || readonly" :readonly="!editable || readonly"
:disabled="disabled" :disabled="disabled"
type="text" :size="size"
v-clickoutside="handleClose"
:placeholder="placeholder" :placeholder="placeholder"
@focus="handleFocus" @focus="handleFocus"
@blur="handleBlur" @blur="handleBlur"
@keydown="handleKeydown" @keydown.native="handleKeydown"
ref="reference" :value="visualValue"
v-model.lazy="visualValue" /> @change.native="visualValue = $event.target.value"
ref="reference">
<span <i slot="icon"
@click.stop="handleClickIcon" class="el-input__icon"
class="el-date-editor__trigger el-icon" @click="handleClickIcon"
:class="[showClose ? 'el-icon-close' : triggerClass]" :class="[showClose ? 'el-icon-close' : triggerClass]"
@mouseenter="handleMouseEnterIcon" @mouseenter="handleMouseEnterIcon"
@mouseleave="showClose = false" @mouseleave="showClose = false"
v-if="haveTrigger"> v-if="haveTrigger">
</span> </i>
</span> </el-input>
</template> </template>
<script> <script>
@ -38,6 +29,7 @@ import Clickoutside from 'element-ui/src/utils/clickoutside';
import { formatDate, parseDate, getWeekNumber } from './util'; import { formatDate, parseDate, 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 ElInput from 'element-ui/packages/input';
const NewPopper = { const NewPopper = {
props: { props: {
@ -77,10 +69,6 @@ const DATE_FORMATTER = function(value, format) {
return formatDate(value, format); return formatDate(value, format);
}; };
const DATE_PARSER = function(text, format) { const DATE_PARSER = function(text, format) {
text = text.split(':');
if (text.length > 1) text = text.map(item => item.slice(-2));
text = text.join(':');
return parseDate(text, format); return parseDate(text, format);
}; };
const RANGE_FORMATTER = function(value, format) { const RANGE_FORMATTER = function(value, format) {
@ -193,6 +181,7 @@ export default {
mixins: [Emitter, NewPopper], mixins: [Emitter, NewPopper],
props: { props: {
size: String,
format: String, format: String,
readonly: Boolean, readonly: Boolean,
placeholder: String, placeholder: String,
@ -210,6 +199,8 @@ export default {
pickerOptions: {} pickerOptions: {}
}, },
components: { ElInput },
directives: { Clickoutside }, directives: { Clickoutside },
data() { data() {
@ -229,7 +220,6 @@ export default {
if (!val && this.picker && typeof this.picker.handleClear === 'function') { if (!val && this.picker && typeof this.picker.handleClear === 'function') {
this.picker.handleClear(); this.picker.handleClear();
} }
this.dispatch('ElFormItem', 'el.form.change');
}, },
value: { value: {
immediate: true, immediate: true,
@ -240,10 +230,19 @@ export default {
}, },
computed: { computed: {
reference() {
return this.$refs.reference.$el;
},
refInput() {
if (this.reference) return this.reference.querySelector('input');
return {};
},
valueIsEmpty() { valueIsEmpty() {
const val = this.internalValue; const val = this.internalValue;
if (Array.isArray(val)) { if (Array.isArray(val)) {
for (let i = 0, j = val.length; i < j; i++) { for (let i = 0, len = val.length; i < len; i++) {
if (val[i]) { if (val[i]) {
return false; return false;
} }
@ -282,6 +281,7 @@ export default {
visualValue: { visualValue: {
get() { get() {
const value = this.internalValue; const value = this.internalValue;
if (!value) return;
const formatter = ( const formatter = (
TYPE_VALUE_RESOLVER_MAP[this.type] || TYPE_VALUE_RESOLVER_MAP[this.type] ||
TYPE_VALUE_RESOLVER_MAP['default'] TYPE_VALUE_RESOLVER_MAP['default']
@ -323,6 +323,7 @@ export default {
handleMouseEnterIcon() { handleMouseEnterIcon() {
if (this.readonly || this.disabled) return; if (this.readonly || this.disabled) return;
if (!this.valueIsEmpty) { if (!this.valueIsEmpty) {
this.visualValue = this.refInput.value;
this.showClose = true; this.showClose = true;
} }
}, },
@ -358,9 +359,6 @@ export default {
handleKeydown(event) { handleKeydown(event) {
const keyCode = event.keyCode; const keyCode = event.keyCode;
const target = event.target; const target = event.target;
let selectionStart = target.selectionStart;
let selectionEnd = target.selectionEnd;
let length = target.value.length;
// tab // tab
if (keyCode === 9) { if (keyCode === 9) {
@ -369,30 +367,6 @@ export default {
} else if (keyCode === 13) { } else if (keyCode === 13) {
this.pickerVisible = this.picker.visible = false; this.pickerVisible = this.picker.visible = false;
this.visualValue = target.value; this.visualValue = target.value;
target.blur();
// left
} else if (keyCode === 37) {
event.preventDefault();
if (selectionEnd === length && selectionStart === length) {
target.selectionStart = length - 2;
} else if (selectionStart >= 3) {
target.selectionStart -= 3;
} else {
target.selectionStart = 0;
}
target.selectionEnd = target.selectionStart + 2;
// right
} else if (keyCode === 39) {
event.preventDefault();
if (selectionEnd === 0 && selectionStart === 0) {
target.selectionEnd = 2;
} else if (selectionEnd <= length - 3) {
target.selectionEnd += 3;
} else {
target.selectionEnd = length;
}
target.selectionStart = target.selectionEnd - 2;
} }
}, },
@ -409,7 +383,7 @@ export default {
this.panel.defaultValue = this.internalValue; this.panel.defaultValue = this.internalValue;
this.picker = new Vue(this.panel).$mount(document.createElement('div')); this.picker = new Vue(this.panel).$mount(document.createElement('div'));
this.popperElm = this.picker.$el; this.popperElm = this.picker.$el;
this.picker.width = this.$refs.reference.getBoundingClientRect().width; this.picker.width = this.reference.getBoundingClientRect().width;
this.picker.showTime = this.type === 'datetime' || this.type === 'datetimerange'; this.picker.showTime = this.type === 'datetime' || this.type === 'datetimerange';
this.picker.selectionMode = this.selectionMode; this.picker.selectionMode = this.selectionMode;
if (this.format) { if (this.format) {
@ -453,10 +427,8 @@ export default {
}); });
this.picker.$on('select-range', (start, end) => { this.picker.$on('select-range', (start, end) => {
setTimeout(() => { this.refInput.setSelectionRange(start, end);
this.$refs.reference.setSelectionRange(start, end); this.refInput.focus();
this.$refs.reference.focus();
}, 0);
}); });
} else { } else {
this.pickerVisible = this.picker.visible = true; this.pickerVisible = this.picker.visible = true;
@ -466,10 +438,10 @@ export default {
if (this.internalValue instanceof Date) { if (this.internalValue instanceof Date) {
this.picker.date = new Date(this.internalValue.getTime()); this.picker.date = new Date(this.internalValue.getTime());
this.picker.resetView && this.picker.resetView();
} else { } else {
this.picker.value = this.internalValue; this.picker.value = this.internalValue;
} }
this.picker.resetView && this.picker.resetView();
this.$nextTick(() => { this.$nextTick(() => {
this.picker.ajustScrollTop && this.picker.ajustScrollTop(); this.picker.ajustScrollTop && this.picker.ajustScrollTop();

View File

@ -15,7 +15,9 @@
<slot name="prepend"></slot> <slot name="prepend"></slot>
</div> </div>
<!-- input 图标 --> <!-- input 图标 -->
<slot name="icon">
<i class="el-input__icon" :class="'el-icon-' + icon" v-if="icon" @click="handleIconClick"></i> <i class="el-input__icon" :class="'el-icon-' + icon" v-if="icon" @click="handleIconClick"></i>
</slot>
<input <input
v-if="type !== 'textarea'" v-if="type !== 'textarea'"
class="el-input__inner" class="el-input__inner"

View File

@ -15,13 +15,13 @@
--color-success: #13ce66; --color-success: #13ce66;
--color-warning: #f7ba2a; --color-warning: #f7ba2a;
--color-danger: #ff4949; --color-danger: #ff4949;
--color-info: #50BFFF; --color-info: #50bfff;
--color-blue: #2e90fe; --color-blue: #2e90fe;
--color-blue-light: #5da9ff; --color-blue-light: #5da9ff;
--color-blue-lighter: rgba(var(--color-blue), 0.12); --color-blue-lighter: rgba(var(--color-blue), 0.12);
--color-white: #fff; --color-white: #fff;
--color-black: #000; --color-black: #000;
--color-grey: #C0CCDA; --color-grey: #c0ccda;
/* Link /* Link
-------------------------- */ -------------------------- */
@ -140,7 +140,7 @@
--select-input-color: var(--color-grey); --select-input-color: var(--color-grey);
--select-multiple-input-color: #666; --select-multiple-input-color: #666;
--select-input-focus-background: #2ea0ff; --select-input-focus-background: var(--color-primary);
--select-input-font-size: 12px; --select-input-font-size: 12px;
--select-tag-height: 24px; --select-tag-height: 24px;
@ -164,7 +164,7 @@
--select-dropdown-max-height: 274px; --select-dropdown-max-height: 274px;
--select-dropdown-padding: 6px 0; --select-dropdown-padding: 6px 0;
--select-dropdown-empty-padding: 10px 0; --select-dropdown-empty-padding: 10px 0;
--select-dropdown-border: solid 1px #d3dce6; --select-dropdown-border: solid 1px var(--disabled-border-base);
/* Alert /* Alert
-------------------------- */ -------------------------- */
@ -256,7 +256,7 @@
--input-disabled-fill: var(--disabled-fill-base); --input-disabled-fill: var(--disabled-fill-base);
--input-disabled-border: var(--disabled-border-base); --input-disabled-border: var(--disabled-border-base);
--input-disabled-color: var(--disabled-color-base); --input-disabled-color: var(--disabled-color-base);
--input-disabled-placeholder-color: #C0CCDA; --input-disabled-placeholder-color: var(--color-grey);
--input-large-font-size: 16px; --input-large-font-size: 16px;
--input-large-height: 42px; --input-large-height: 42px;
@ -339,9 +339,9 @@
--button-ghost-fill: transparent; --button-ghost-fill: transparent;
--button-ghost-border: none; --button-ghost-border: none;
--button-disabled-color: #C0CCDA; --button-disabled-color: var(--color-grey);
--button-disabled-fill: #EFF2F7; --button-disabled-fill: #EFF2F7;
--button-disabled-border: #D3DCE6; --button-disabled-border: var(--disabled-border-base);
--button-primary-border: var(--color-primary); --button-primary-border: var(--color-primary);
--button-primary-color: var(--color-white); --button-primary-color: var(--color-white);
@ -374,7 +374,7 @@
/* Switch /* Switch
-------------------------- */ -------------------------- */
--switch-on-color: var(--color-primary); --switch-on-color: var(--color-primary);
--switch-off-color: #C0CCDA; --switch-off-color: var(--color-grey);
--switch-disabled-color: #E5E9F3; --switch-disabled-color: #E5E9F3;
--switch-disabled-text-color: #F9FAFC; --switch-disabled-text-color: #F9FAFC;
@ -413,7 +413,7 @@
--pagination-button-size: 28px; --pagination-button-size: 28px;
--pagination-button-disabled-color: #e4e4e4; --pagination-button-disabled-color: #e4e4e4;
--pagination-button-disabled-fill: var(--color-white); --pagination-button-disabled-fill: var(--color-white);
--pagination-border-color: #D3DCE6; --pagination-border-color: var(--disabled-border-base);
--pagination-hover-fill: var(--color-primary); --pagination-hover-fill: var(--color-primary);
--pagination-hover-color: var(--color-white); --pagination-hover-color: var(--color-white);
@ -421,7 +421,7 @@
-------------------------- */ -------------------------- */
--popover-fill: var(--color-white); --popover-fill: var(--color-white);
--popover-font-size: 12px; --popover-font-size: 12px;
--popover-border-color: #d3dce6; --popover-border-color: var(--disabled-border-base);
--popover-arrow-size: 6px; --popover-arrow-size: 6px;
--popover-padding: 10px; --popover-padding: 10px;
--popover-title-font-size: 13px; --popover-title-font-size: 13px;
@ -511,7 +511,7 @@
--------------------------*/ --------------------------*/
--menu-item-color: var(--link-color); --menu-item-color: var(--link-color);
--menu-item-fill: #eff2f7; --menu-item-fill: #eff2f7;
--menu-item-hover-fill: #d3dce6; --menu-item-hover-fill: var(--disabled-border-base);
--submenu-item-fill: #e5e9f2; --submenu-item-fill: #e5e9f2;
--dark-menu-item-color: var(--link-color); --dark-menu-item-color: var(--link-color);
@ -533,14 +533,13 @@
--datepicker-off-color: #ddd; --datepicker-off-color: #ddd;
--datepicker-header-color: var(--border-color-hover); --datepicker-header-color: var(--border-color-hover);
--datepicker-icon-color: #99a9bf; --datepicker-icon-color: #99a9bf;
--datepicker-trigger-color: #c0ccda; --datepicker-border-color: var(--disabled-border-base);
--datepicker-border-color: #d3dce6;
--datepicker-inner-border-color: #e4e4e4; --datepicker-inner-border-color: #e4e4e4;
--datepicker-cell-hover-color: #e5e9f2; --datepicker-cell-hover-color: #e5e9f2;
--datepicker-inrange-color: #D3ECFF; --datepicker-inrange-color: #D3ECFF;
--datepicker-inrange-hover-color: #AFDCFF; --datepicker-inrange-hover-color: #AFDCFF;
--datepicker-active-color: var(--color-primary); --datepicker-active-color: var(--color-primary);
--datepicker-text-hover-color: #20a0ff; --datepicker-text-hover-color: var(--color-primary);
/* Loading /* Loading
--------------------------*/ --------------------------*/

View File

@ -32,23 +32,6 @@
padding: 0 5px; padding: 0 5px;
} }
@e editor {
position: relative;
border: 1px solid #c0ccda;
border-radius: 4px;
padding: 5px 10px;
box-sizing: border-box;
height: 28px;
outline: none;
appearance: none;
transition: border 0.3s;
width: 100%;
&:hover {
border-color: #20a0ff;
}
}
@e time-header { @e time-header {
position: relative; position: relative;
border-bottom: 1px solid var(--datepicker-inner-border-color); border-bottom: 1px solid var(--datepicker-inner-border-color);

View File

@ -29,23 +29,6 @@
margin: 0; margin: 0;
} }
@e editor {
position: relative;
border: 1px solid #c0ccda;
border-radius: 4px;
padding: 5px 10px;
box-sizing: border-box;
height: 28px;
outline: none;
appearance: none;
transition: border 0.3s;
width: 100%;
&:hover {
border-color: #20a0ff;
}
}
@e header { @e header {
position: relative; position: relative;
text-align: center; text-align: center;
@ -122,7 +105,7 @@
top: 13px; top: 13px;
right: 0; right: 0;
z-index: 1; z-index: 1;
background: #fff; background: var(--color-white);
} }
} }
} }

View File

@ -49,7 +49,7 @@
&.start-date, &.start-date,
&.end-date { &.end-date {
background-color: var(--datepicker-active-color) !important; background-color: var(--datepicker-active-color) !important;
color: #fff; color: var(--color-white);
} }
&.disabled { &.disabled {

View File

@ -45,7 +45,7 @@
cursor: pointer; cursor: pointer;
&:hover { &:hover {
background-color: #e5e9f2; background-color: var(--datepicker-cell-hover-color);
} }
&.active { &.active {

View File

@ -5,115 +5,15 @@
@b date-editor { @b date-editor {
position: relative; position: relative;
display: inline-block; display: inline-block;
box-sizing: border-box;
height: 36px;
width: 182px;
@e editor {
border: 1px solid #c0ccda;
border-radius: 4px;
line-height: 18px;
height: 36px;
padding: 3px 10px;
width: 100%;
box-sizing: border-box;
transition: border 0.3s;
color: #666;
font-size: 14px;
@when disabled {
background-color: var(--disabled-fill-base);
border-color: var(--disabled-border-base);
color: var(--disabled-color-base);
cursor: not-allowed;
&::placeholder {
color: var(--input-disabled-placeholder-color);
}
}
&::placeholder {
color: #bbb;
font-size: 14px;
}
}
@e trigger {
&.el-icon {
cursor: pointer;
position: absolute;
display: inline-block;
width: 16px;
right: 10px;
top: 0;
bottom: 0;
color: var(--datepicker-trigger-color);
font-size: 16px;
line-height: 38px;
}
}
@e clear {
cursor: pointer;
position: absolute;
width: 20px;
right: 0;
top: 0;
bottom: 0;
line-height: 36px;
color: var(--datepicker-icon-color);
&:hover {
color: var(--datepicker-text-hover-color);
}
}
@when have-trigger {
.el-date-editor__editor {
padding-right: 20px;
}
.el-date-editor__clear {
right: 22px;
}
}
&.lg {
.el-date-editor__editor {
padding: 6px 4px;
}
}
&.sm {
.el-date-editor__editor {
padding: 1px 1px;
}
}
.el-picker-panel { .el-picker-panel {
position: absolute; position: absolute;
min-width: 180px; min-width: 180px;
box-sizing: border-box; box-sizing: border-box;
box-shadow: 0 2px 6px #ccc; box-shadow: 0 2px 6px #ccc;
background: #fff; background: var(--color-white);
z-index: 10; z-index: 10;
top: 41px; top: 41px;
} }
} }
.el-date-editor__editor:focus,
.el-date-editor:hover > .el-date-editor__editor,
.el-date-editor.is-active > .el-date-editor__editor {
outline: none;
border-color: var(--datepicker-active-color);
}
.el-date-editor .el-date-editor__clear {
display: none;
}
.el-date-editor.is-filled:hover .el-date-editor__clear,
.el-date-editor.is-filled.is-active > .el-date-editor__clear {
display: inline-block;
}
} }

View File

@ -3,14 +3,14 @@
@component-namespace el { @component-namespace el {
@b time-panel { @b time-panel {
margin: 5px 0; margin: 5px 0;
border: solid 1px #d3dce6; border: solid 1px var(--datepicker-border-color);
background-color: #fff; background-color: var(--color-white);
box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px 0 rgba(0, 0, 0, .04); box-shadow: var(--box-shadow-base);
border-radius: 2px; border-radius: 2px;
position: absolute; position: absolute;
width: 180px; width: 180px;
left: 0; left: 0;
z-index: 1000; z-index: var(--index-top);
user-select: none; user-select: none;
@e content { @e content {
@ -21,12 +21,12 @@
&::after, &::before { &::after, &::before {
content: ":"; content: ":";
top: 50%; top: 50%;
color: #fff; color: var(--color-white);
position: absolute; position: absolute;
font-size: 14px; font-size: 14px;
margin-top: -15px; margin-top: -15px;
line-height: 16px; line-height: 16px;
background-color: #20a0ff; background-color: var(--datepicker-active-color);
height: 32px; height: 32px;
z-index: -1; z-index: -1;
left: 0; left: 0;
@ -69,7 +69,7 @@
&.confirm { &.confirm {
font-weight: 800; font-weight: 800;
color: #20a0ff; color: var(--datepicker-active-color);
} }
} }

View File

@ -37,12 +37,12 @@
font-size: 12px; font-size: 12px;
&:hover:not(.disabled):not(.active) { &:hover:not(.disabled):not(.active) {
background: #E5E9F2; background: var(--datepicker-cell-hover-color);
cursor: pointer; cursor: pointer;
} }
&.active:not(.disabled) { &.active:not(.disabled) {
color: #fff; color: var(--color-white);
} }
&.disabled { &.disabled {

View File

@ -7,20 +7,21 @@
font-size: var(--font-size-base); font-size: var(--font-size-base);
@e inner { @e inner {
display: block; appearance: none;
padding: 3px 10px; background-color: var(--color-white);
box-sizing: border-box;
width: 100%;
height: var(--input-height);
color: var(--input-color);
background-color: #fff;
background-image: none; background-image: none;
border: var(--input-border);
border-radius: 4px; border-radius: 4px;
transition: var(--border-transition-base); border: var(--input-border);
outline: none; box-sizing: border-box;
color: var(--input-color);
display: block;
font-size: inherit; font-size: inherit;
height: var(--input-height);
line-height: normal; line-height: normal;
outline: none;
padding: 3px 10px;
transition: var(--border-transition-base);
width: 100%;
&::placeholder { &::placeholder {
color: var(--input-placeholder-color); color: var(--input-placeholder-color);
@ -29,6 +30,7 @@
&:hover { &:hover {
border-color: var(--input-hover-border); border-color: var(--input-hover-border);
} }
&:focus { &:focus {
outline: none; outline: none;
border-color: var(--input-focus-border); border-color: var(--input-focus-border);

View File

@ -82,7 +82,7 @@ describe('DatePicker', () => {
const $el = vm.$refs.compo.picker.$el; const $el = vm.$refs.compo.picker.$el;
$el.querySelector('td.available').click(); $el.querySelector('td.available').click();
vm.$nextTick(_ => { vm.$nextTick(_ => {
vm.$el.querySelector('.el-date-editor__trigger').click(); vm.$el.querySelector('.el-input__icon').click();
setTimeout(_ => { setTimeout(_ => {
expect(vm.value).to.empty; expect(vm.value).to.empty;
done(); done();
@ -264,7 +264,7 @@ describe('DatePicker', () => {
const input = vm.picker.$el.querySelectorAll('.el-date-picker__editor-wrap input')[1]; const input = vm.picker.$el.querySelectorAll('.el-date-picker__editor-wrap input')[1];
input.value = '20:30:33'; input.value = '20:30:33';
triggerEvent(input, 'change'); triggerEvent(input, 'change', true);
setTimeout(_ => { setTimeout(_ => {
expect(vm.picker.date.getHours()).to.equal(20); expect(vm.picker.date.getHours()).to.equal(20);
expect(vm.picker.date.getMinutes()).to.equal(30); expect(vm.picker.date.getMinutes()).to.equal(30);
@ -277,7 +277,7 @@ describe('DatePicker', () => {
const input = vm.picker.$el.querySelector('.el-date-picker__editor-wrap input'); const input = vm.picker.$el.querySelector('.el-date-picker__editor-wrap input');
input.value = '2017-2-2'; input.value = '2017-2-2';
triggerEvent(input, 'change'); triggerEvent(input, 'change', true);
setTimeout(_ => { setTimeout(_ => {
expect(vm.picker.date.getFullYear()).to.equal(2017); expect(vm.picker.date.getFullYear()).to.equal(2017);
expect(vm.picker.date.getMonth()).to.equal(1); expect(vm.picker.date.getMonth()).to.equal(1);
@ -432,7 +432,7 @@ describe('DatePicker', () => {
const input = vm.picker.$el.querySelectorAll('.el-date-range-picker__editors-wrap input')[1]; const input = vm.picker.$el.querySelectorAll('.el-date-range-picker__editors-wrap input')[1];
input.value = '10:22:14'; input.value = '10:22:14';
triggerEvent(input, 'change'); triggerEvent(input, 'change', true);
setTimeout(_ => { setTimeout(_ => {
expect(vm.picker.minDate.getHours()).to.equal(10); expect(vm.picker.minDate.getHours()).to.equal(10);
expect(vm.picker.minDate.getMinutes()).to.equal(22); expect(vm.picker.minDate.getMinutes()).to.equal(22);
@ -445,7 +445,7 @@ describe('DatePicker', () => {
const input = vm.picker.$el.querySelectorAll('.el-date-range-picker__editors-wrap input')[3]; const input = vm.picker.$el.querySelectorAll('.el-date-range-picker__editors-wrap input')[3];
input.value = '10:22:14'; input.value = '10:22:14';
triggerEvent(input, 'change'); triggerEvent(input, 'change', true);
setTimeout(_ => { setTimeout(_ => {
expect(vm.picker.maxDate.getHours()).to.equal(10); expect(vm.picker.maxDate.getHours()).to.equal(10);
expect(vm.picker.maxDate.getMinutes()).to.equal(22); expect(vm.picker.maxDate.getMinutes()).to.equal(22);
@ -547,7 +547,7 @@ describe('DatePicker', () => {
setTimeout(_ => { setTimeout(_ => {
triggerEvent(input, 'input'); triggerEvent(input, 'input');
input.value = '1989-6-4'; input.value = '1989-6-4';
triggerEvent(input, 'change'); triggerEvent(input, 'change', true);
setTimeout(_ => { setTimeout(_ => {
const minDate = vm.picker.minDate; const minDate = vm.picker.minDate;
@ -581,7 +581,7 @@ describe('DatePicker', () => {
setTimeout(_ => { setTimeout(_ => {
triggerEvent(input, 'input'); triggerEvent(input, 'input');
input.value = '1989-6-4'; input.value = '1989-6-4';
triggerEvent(input, 'change'); triggerEvent(input, 'change', true);
setTimeout(_ => { setTimeout(_ => {
expect(vm.picker.maxDate > vm.picker.minDate).to.true; expect(vm.picker.maxDate > vm.picker.minDate).to.true;
done(); done();