update DatePicker
update DatePicker
This commit is contained in:
parent
10f622acb9
commit
c46f385a83
9 changed files with 565 additions and 56 deletions
|
@ -1,9 +1,7 @@
|
|||
<template>
|
||||
<div
|
||||
:class="[prefixCls]"
|
||||
v-clickoutside="handleClose"
|
||||
@mouseenter="handleMouseenter"
|
||||
@mouseleave="handleMouseleave">
|
||||
v-clickoutside="handleClose">
|
||||
<i-input
|
||||
v-el:reference
|
||||
:class="[prefixCls + '-editor']"
|
||||
|
@ -11,10 +9,13 @@
|
|||
:disabled="disabled"
|
||||
:size="size"
|
||||
:placeholder="placeholder"
|
||||
:value.sync="visualValue"
|
||||
:value="visualValue"
|
||||
@on-change="handleInputChange"
|
||||
@on-focus="handleFocus"
|
||||
@on-blur="handleBlur"
|
||||
@on-click="handleIconClick"
|
||||
@mouseenter="handleInputMouseenter"
|
||||
@mouseleave="handleInputMouseleave"
|
||||
:icon="iconType"></i-input>
|
||||
<Drop v-show="visible" :placement="placement" transition="slide-up" v-ref:drop>
|
||||
<div v-el:picker></div>
|
||||
|
@ -27,13 +28,14 @@
|
|||
import Drop from '../../components/select/dropdown.vue';
|
||||
import clickoutside from '../../directives/clickoutside';
|
||||
import { oneOf } from '../../utils/assist';
|
||||
import { formatDate } from './util';
|
||||
import { formatDate, parseDate } from './util';
|
||||
|
||||
const prefixCls = 'ivu-date-picker';
|
||||
|
||||
const DEFAULT_FORMATS = {
|
||||
date: 'yyyy-MM-dd',
|
||||
month: 'yyyy-MM',
|
||||
year: 'yyyy',
|
||||
datetime: 'yyyy-MM-dd HH:mm:ss',
|
||||
time: 'HH:mm:ss',
|
||||
timerange: 'HH:mm:ss',
|
||||
|
@ -41,6 +43,96 @@
|
|||
datetimerange: 'yyyy-MM-dd HH:mm:ss'
|
||||
};
|
||||
|
||||
const RANGE_SEPARATOR = ' - ';
|
||||
|
||||
const DATE_FORMATTER = function(value, format) {
|
||||
return formatDate(value, format);
|
||||
};
|
||||
const DATE_PARSER = function(text, format) {
|
||||
return parseDate(text, format);
|
||||
};
|
||||
const RANGE_FORMATTER = function(value, format) {
|
||||
if (Array.isArray(value) && value.length === 2) {
|
||||
const start = value[0];
|
||||
const end = value[1];
|
||||
|
||||
if (start && end) {
|
||||
return formatDate(start, format) + RANGE_SEPARATOR + formatDate(end, format);
|
||||
}
|
||||
}
|
||||
return '';
|
||||
};
|
||||
const RANGE_PARSER = function(text, format) {
|
||||
const array = text.split(RANGE_SEPARATOR);
|
||||
if (array.length === 2) {
|
||||
const range1 = array[0];
|
||||
const range2 = array[1];
|
||||
|
||||
return [parseDate(range1, format), parseDate(range2, format)];
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
const TYPE_VALUE_RESOLVER_MAP = {
|
||||
default: {
|
||||
formatter(value) {
|
||||
if (!value) return '';
|
||||
return '' + value;
|
||||
},
|
||||
parser(text) {
|
||||
if (text === undefined || text === '') return null;
|
||||
return text;
|
||||
}
|
||||
},
|
||||
date: {
|
||||
formatter: DATE_FORMATTER,
|
||||
parser: DATE_PARSER
|
||||
},
|
||||
datetime: {
|
||||
formatter: DATE_FORMATTER,
|
||||
parser: DATE_PARSER
|
||||
},
|
||||
daterange: {
|
||||
formatter: RANGE_FORMATTER,
|
||||
parser: RANGE_PARSER
|
||||
},
|
||||
datetimerange: {
|
||||
formatter: RANGE_FORMATTER,
|
||||
parser: RANGE_PARSER
|
||||
},
|
||||
timerange: {
|
||||
formatter: RANGE_FORMATTER,
|
||||
parser: RANGE_PARSER
|
||||
},
|
||||
time: {
|
||||
formatter: DATE_FORMATTER,
|
||||
parser: DATE_PARSER
|
||||
},
|
||||
month: {
|
||||
formatter: DATE_FORMATTER,
|
||||
parser: DATE_PARSER
|
||||
},
|
||||
year: {
|
||||
formatter: DATE_FORMATTER,
|
||||
parser: DATE_PARSER
|
||||
},
|
||||
number: {
|
||||
formatter(value) {
|
||||
if (!value) return '';
|
||||
return '' + value;
|
||||
},
|
||||
parser(text) {
|
||||
let result = Number(text);
|
||||
|
||||
if (!isNaN(text)) {
|
||||
return result;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const PLACEMENT_MAP = {
|
||||
left: 'bottom-start',
|
||||
center: 'bottom-center',
|
||||
|
@ -101,6 +193,47 @@
|
|||
},
|
||||
placement () {
|
||||
return PLACEMENT_MAP[this.align];
|
||||
},
|
||||
selectionMode() {
|
||||
if (this.type === 'week') {
|
||||
return 'week';
|
||||
} else if (this.type === 'month') {
|
||||
return 'month';
|
||||
} else if (this.type === 'year') {
|
||||
return 'year';
|
||||
}
|
||||
|
||||
return 'day';
|
||||
},
|
||||
visualValue: {
|
||||
get () {
|
||||
const value = this.internalValue;
|
||||
if (!value) return;
|
||||
const formatter = (
|
||||
TYPE_VALUE_RESOLVER_MAP[this.type] ||
|
||||
TYPE_VALUE_RESOLVER_MAP['default']
|
||||
).formatter;
|
||||
const format = DEFAULT_FORMATS[this.type];
|
||||
|
||||
return formatter(value, this.format || format);
|
||||
},
|
||||
|
||||
set (value) {
|
||||
if (value) {
|
||||
const type = this.type;
|
||||
const parser = (
|
||||
TYPE_VALUE_RESOLVER_MAP[type] ||
|
||||
TYPE_VALUE_RESOLVER_MAP['default']
|
||||
).parser;
|
||||
const parsedValue = parser(value, this.format || DEFAULT_FORMATS[type]);
|
||||
|
||||
if (parsedValue) {
|
||||
if (this.picker) this.picker.value = parsedValue;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (this.picker) this.picker.value = value;
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -113,29 +246,51 @@
|
|||
handleBlur () {
|
||||
|
||||
},
|
||||
handleMouseenter () {
|
||||
handleInputChange (val) {
|
||||
this.visualValue = val;
|
||||
},
|
||||
handleInputMouseenter () {
|
||||
if (this.readonly || this.disabled) return;
|
||||
if (this.visualValue) {
|
||||
this.showClose = true;
|
||||
}
|
||||
},
|
||||
handleMouseleave () {
|
||||
handleInputMouseleave () {
|
||||
this.showClose = false;
|
||||
},
|
||||
handleIconClick () {
|
||||
|
||||
if (!this.showClose) return;
|
||||
this.visible = false;
|
||||
this.internalValue = '';
|
||||
this.value = '';
|
||||
},
|
||||
showPicker () {
|
||||
if (!this.picker) {
|
||||
this.picker = new Vue(this.panel).$mount(this.$els.picker);
|
||||
this.picker.value = this.internalValue;
|
||||
this.picker.selectionMode = this.selectionMode;
|
||||
if (this.format) this.picker.format = this.format;
|
||||
|
||||
const options = this.options;
|
||||
for (const option in options) {
|
||||
this.picker[option] = options[option];
|
||||
}
|
||||
|
||||
this.picker.$on('on-pick', (date, visible = false) => {
|
||||
this.$emit('on-change', date);
|
||||
this.value = date;
|
||||
this.visible = visible;
|
||||
this.picker.resetView && this.picker.resetView();
|
||||
});
|
||||
|
||||
// todo $on('on-range')
|
||||
}
|
||||
if (this.internalValue instanceof Date) {
|
||||
this.picker.date = new Date(this.internalValue.getTime());
|
||||
} else {
|
||||
this.picker.value = this.internalValue;
|
||||
}
|
||||
this.picker.resetView && this.picker.resetView();
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
@ -143,14 +298,24 @@
|
|||
if (val) {
|
||||
this.showPicker();
|
||||
this.$refs.drop.update();
|
||||
this.$emit('on-open-change', true);
|
||||
} else {
|
||||
if (this.picker) {
|
||||
this.picker.resetView && this.picker.resetView();
|
||||
}
|
||||
this.$refs.drop.destroy();
|
||||
this.$emit('on-open-change', false);
|
||||
}
|
||||
},
|
||||
internalValue(val) {
|
||||
if (!val && this.picker && typeof this.picker.handleClear === 'function') {
|
||||
this.picker.handleClear();
|
||||
}
|
||||
},
|
||||
value: {
|
||||
immediate: true,
|
||||
handler (val) {
|
||||
this.internalValue = formatDate(val);
|
||||
this.internalValue = val;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue