update DatePicker

update DatePicker
This commit is contained in:
梁灏 2016-12-15 20:16:58 +08:00
parent 10f622acb9
commit c46f385a83
9 changed files with 565 additions and 56 deletions

View file

@ -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;
}
}
},