element/packages/input-number/src/input-number.vue

212 lines
5.7 KiB
Vue
Raw Normal View History

2016-07-27 06:15:02 +00:00
<template>
<div class="el-input-number"
:class="[
2016-10-25 03:33:39 +00:00
size ? 'el-input-number--' + size : '',
{ 'is-disabled': disabled },
{ 'is-without-controls': !controls}
2016-07-27 06:15:02 +00:00
]"
>
<span
v-if="controls"
2017-02-22 02:28:03 +00:00
class="el-input-number__decrease"
2016-07-27 06:15:02 +00:00
:class="{'is-disabled': minDisabled}"
2016-08-11 07:51:13 +00:00
v-repeat-click="decrease"
2016-07-27 06:15:02 +00:00
>
2017-02-22 02:28:03 +00:00
<i class="el-icon-minus"></i>
2016-07-27 06:15:02 +00:00
</span>
<span
v-if="controls"
2017-02-22 02:28:03 +00:00
class="el-input-number__increase"
2016-07-27 06:15:02 +00:00
:class="{'is-disabled': maxDisabled}"
2016-08-11 07:51:13 +00:00
v-repeat-click="increase"
2016-07-27 06:15:02 +00:00
>
2017-02-22 02:28:03 +00:00
<i class="el-icon-plus"></i>
2016-07-27 06:15:02 +00:00
</span>
<el-input
2017-01-10 16:39:35 +00:00
:value="currentValue"
@keydown.up.native.prevent="increase"
@keydown.down.native.prevent="decrease"
@blur="handleBlur"
@input="debounceHandleInput"
:disabled="disabled"
:size="size"
:max="max"
:min="min"
2016-12-27 11:14:22 +00:00
ref="input"
>
<template slot="prepend" v-if="$slots.prepend">
<slot name="prepend"></slot>
</template>
<template slot="append" v-if="$slots.append">
<slot name="append"></slot>
</template>
</el-input>
2016-07-27 06:15:02 +00:00
</div>
</template>
<script>
2016-10-25 13:35:41 +00:00
import ElInput from 'element-ui/packages/input';
2016-12-26 03:41:15 +00:00
import { once, on } from 'element-ui/src/utils/dom';
import debounce from 'throttle-debounce/debounce';
2016-07-27 06:15:02 +00:00
export default {
name: 'ElInputNumber',
directives: {
repeatClick: {
2016-08-11 07:51:13 +00:00
bind(el, binding, vnode) {
2016-07-27 06:15:02 +00:00
let interval = null;
let startTime;
const handler = () => vnode.context[binding.expression].apply();
2016-12-26 02:45:20 +00:00
const clear = () => {
2016-07-27 06:15:02 +00:00
if (new Date() - startTime < 100) {
handler();
}
clearInterval(interval);
interval = null;
};
2016-12-26 02:45:20 +00:00
on(el, 'mousedown', () => {
2016-07-27 06:15:02 +00:00
startTime = new Date();
once(document, 'mouseup', clear);
clearInterval(interval);
2016-12-26 02:45:20 +00:00
interval = setInterval(handler, 100);
2016-07-27 06:15:02 +00:00
});
}
}
},
components: {
ElInput
},
props: {
step: {
type: Number,
default: 1
},
max: {
type: Number,
default: Infinity
},
min: {
type: Number,
default: -Infinity
},
value: {
default: 0
},
disabled: Boolean,
size: String,
controls: {
type: Boolean,
default: true
},
debounce: {
type: Number,
default: 300
}
},
2016-07-27 06:15:02 +00:00
data() {
return {
2017-01-11 17:52:57 +00:00
currentValue: 0
2016-07-27 06:15:02 +00:00
};
},
2016-08-11 07:51:13 +00:00
watch: {
2017-01-11 17:52:57 +00:00
value: {
immediate: true,
handler(value) {
let newVal = Number(value);
if (isNaN(newVal)) return;
if (newVal >= this.max) newVal = this.max;
if (newVal <= this.min) newVal = this.min;
2017-01-10 16:39:35 +00:00
this.currentValue = newVal;
2017-01-11 17:52:57 +00:00
this.$emit('input', newVal);
2016-08-11 07:51:13 +00:00
}
}
},
2016-07-27 06:15:02 +00:00
computed: {
minDisabled() {
return this._decrease(this.value, this.step) < this.min;
2016-07-27 06:15:02 +00:00
},
maxDisabled() {
return this._increase(this.value, this.step) > this.max;
},
precision() {
const { value, step, getPrecision } = this;
return Math.max(getPrecision(value), getPrecision(step));
2016-07-27 06:15:02 +00:00
}
},
methods: {
toPrecision(num, precision) {
if (precision === undefined) precision = this.precision;
return parseFloat(parseFloat(Number(num).toFixed(precision)));
2016-09-01 07:56:04 +00:00
},
getPrecision(value) {
const valueString = value.toString();
const dotPosition = valueString.indexOf('.');
let precision = 0;
if (dotPosition !== -1) {
precision = valueString.length - dotPosition - 1;
2016-09-01 07:56:04 +00:00
}
return precision;
},
_increase(val, step) {
if (typeof val !== 'number') return this.currentValue;
const precisionFactor = Math.pow(10, this.precision);
return this.toPrecision((precisionFactor * val + precisionFactor * step) / precisionFactor);
},
_decrease(val, step) {
if (typeof val !== 'number') return this.currentValue;
const precisionFactor = Math.pow(10, this.precision);
return this.toPrecision((precisionFactor * val - precisionFactor * step) / precisionFactor);
2016-09-01 07:56:04 +00:00
},
2016-07-27 06:15:02 +00:00
increase() {
if (this.disabled || this.maxDisabled) return;
2016-11-24 06:48:56 +00:00
const value = this.value || 0;
const newVal = this._increase(value, this.step);
if (newVal > this.max) return;
2017-01-10 16:39:35 +00:00
this.setCurrentValue(newVal);
2016-07-27 06:15:02 +00:00
},
decrease() {
if (this.disabled || this.minDisabled) return;
2016-11-24 06:48:56 +00:00
const value = this.value || 0;
const newVal = this._decrease(value, this.step);
if (newVal < this.min) return;
2017-01-10 16:39:35 +00:00
this.setCurrentValue(newVal);
},
handleBlur() {
2016-12-27 11:14:22 +00:00
this.$refs.input.setCurrentValue(this.currentValue);
2017-01-10 16:39:35 +00:00
},
setCurrentValue(newVal) {
const oldVal = this.currentValue;
2017-01-11 17:52:57 +00:00
if (newVal >= this.max) newVal = this.max;
if (newVal <= this.min) newVal = this.min;
if (oldVal === newVal) {
this.$refs.input.setCurrentValue(this.currentValue);
return;
}
2017-01-11 17:52:57 +00:00
this.$emit('change', newVal, oldVal);
this.$emit('input', newVal);
this.currentValue = newVal;
2017-01-10 16:39:35 +00:00
},
handleInput(value) {
if (value === '') {
return;
}
2017-01-10 16:39:35 +00:00
const newVal = Number(value);
if (!isNaN(newVal)) {
this.setCurrentValue(newVal);
} else {
this.$refs.input.setCurrentValue(this.currentValue);
2017-01-10 16:39:35 +00:00
}
2016-07-27 06:15:02 +00:00
}
},
created() {
this.debounceHandleInput = debounce(this.debounce, value => {
this.handleInput(value);
});
2016-07-27 06:15:02 +00:00
}
};
</script>