You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
184 lines
5.7 KiB
184 lines
5.7 KiB
import { VantComponent } from '../common/component'; |
|
import { isDef } from '../common/validator'; |
|
const LONG_PRESS_START_TIME = 600; |
|
const LONG_PRESS_INTERVAL = 200; |
|
// add num and avoid float number |
|
function add(num1, num2) { |
|
const cardinal = Math.pow(10, 10); |
|
return Math.round((num1 + num2) * cardinal) / cardinal; |
|
} |
|
function equal(value1, value2) { |
|
return String(value1) === String(value2); |
|
} |
|
VantComponent({ |
|
field: true, |
|
classes: ['input-class', 'plus-class', 'minus-class'], |
|
props: { |
|
value: { |
|
type: null, |
|
}, |
|
integer: { |
|
type: Boolean, |
|
observer: 'check', |
|
}, |
|
disabled: Boolean, |
|
inputWidth: String, |
|
buttonSize: String, |
|
asyncChange: Boolean, |
|
disableInput: Boolean, |
|
decimalLength: { |
|
type: Number, |
|
value: null, |
|
observer: 'check', |
|
}, |
|
min: { |
|
type: null, |
|
value: 1, |
|
observer: 'check', |
|
}, |
|
max: { |
|
type: null, |
|
value: Number.MAX_SAFE_INTEGER, |
|
observer: 'check', |
|
}, |
|
step: { |
|
type: null, |
|
value: 1, |
|
}, |
|
showPlus: { |
|
type: Boolean, |
|
value: true, |
|
}, |
|
showMinus: { |
|
type: Boolean, |
|
value: true, |
|
}, |
|
disablePlus: Boolean, |
|
disableMinus: Boolean, |
|
longPress: { |
|
type: Boolean, |
|
value: true, |
|
}, |
|
theme: String, |
|
alwaysEmbed: Boolean, |
|
}, |
|
data: { |
|
currentValue: '', |
|
}, |
|
watch: { |
|
value() { |
|
this.observeValue(); |
|
}, |
|
}, |
|
created() { |
|
this.setData({ |
|
currentValue: this.format(this.data.value).newValue, |
|
}); |
|
}, |
|
methods: { |
|
observeValue() { |
|
const { value } = this.data; |
|
this.setData({ currentValue: this.format(value).newValue }); |
|
}, |
|
check() { |
|
const { newValue } = this.format(this.data.currentValue); |
|
if (!equal(newValue, this.data.currentValue)) { |
|
this.setData({ currentValue: newValue }); |
|
} |
|
}, |
|
isDisabled(type) { |
|
const { disabled, disablePlus, disableMinus, currentValue, max, min } = this.data; |
|
if (type === 'plus') { |
|
return disabled || disablePlus || +currentValue >= +max; |
|
} |
|
return disabled || disableMinus || +currentValue <= +min; |
|
}, |
|
onFocus(event) { |
|
this.$emit('focus', event.detail); |
|
}, |
|
onBlur(event) { |
|
const data = this.format(event.detail.value); |
|
this.setData({ currentValue: data.newValue }); |
|
this.emitChange(data); |
|
this.$emit('blur', Object.assign(Object.assign({}, event.detail), { value: +data.newValue })); |
|
}, |
|
// filter illegal characters |
|
filter(value) { |
|
value = String(value).replace(/[^0-9.-]/g, ''); |
|
if (this.data.integer && value.indexOf('.') !== -1) { |
|
value = value.split('.')[0]; |
|
} |
|
return value; |
|
}, |
|
format(value) { |
|
// filter illegal characters and format integer |
|
const safeValue = this.filter(value); |
|
// format range |
|
const rangeValue = Math.max(Math.min(this.data.max, +safeValue), this.data.min); |
|
// format decimal |
|
const newValue = isDef(this.data.decimalLength) |
|
? rangeValue.toFixed(this.data.decimalLength) |
|
: String(rangeValue); |
|
return { value, newValue }; |
|
}, |
|
onInput(event) { |
|
const { value = '' } = event.detail || {}; |
|
// allow input to be empty |
|
if (value === '') { |
|
return; |
|
} |
|
const formatted = this.format(value); |
|
this.emitChange(formatted); |
|
}, |
|
emitChange(data) { |
|
const { value, newValue } = data; |
|
if (!this.data.asyncChange) { |
|
// fix when input 11. parsed to 11, unable to enter decimal |
|
this.setData({ currentValue: +value === +newValue ? value : newValue }); |
|
} |
|
this.$emit('change', +newValue); |
|
}, |
|
onChange() { |
|
const { type } = this; |
|
if (this.isDisabled(type)) { |
|
this.$emit('overlimit', type); |
|
return; |
|
} |
|
const diff = type === 'minus' ? -this.data.step : +this.data.step; |
|
const value = this.format(String(add(+this.data.currentValue, diff))); |
|
this.emitChange(value); |
|
this.$emit(type); |
|
}, |
|
longPressStep() { |
|
this.longPressTimer = setTimeout(() => { |
|
this.onChange(); |
|
this.longPressStep(); |
|
}, LONG_PRESS_INTERVAL); |
|
}, |
|
onTap(event) { |
|
const { type } = event.currentTarget.dataset; |
|
this.type = type; |
|
this.onChange(); |
|
}, |
|
onTouchStart(event) { |
|
if (!this.data.longPress) { |
|
return; |
|
} |
|
clearTimeout(this.longPressTimer); |
|
const { type } = event.currentTarget.dataset; |
|
this.type = type; |
|
this.isLongPress = false; |
|
this.longPressTimer = setTimeout(() => { |
|
this.isLongPress = true; |
|
this.onChange(); |
|
this.longPressStep(); |
|
}, LONG_PRESS_START_TIME); |
|
}, |
|
onTouchEnd() { |
|
if (!this.data.longPress) { |
|
return; |
|
} |
|
clearTimeout(this.longPressTimer); |
|
}, |
|
}, |
|
});
|
|
|