123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303 |
- import baseComponent from '../helpers/baseComponent'
- import classNames from '../helpers/libs/classNames'
- import eventsMixin from '../helpers/mixins/eventsMixin'
- import NP from './utils'
- const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || Math.pow(2, 53) - 1
- const toNumberWhenUserInput = (num) => {
- if (/\.\d*0$/.test(num) || num.length > 16) {
- return num
- }
- if (isNaN(num)) {
- return num
- }
- return Number(num)
- }
- const getValidValue = (value, min, max) => {
- let val = parseFloat(value)
- if (isNaN(val)) {
- return value
- }
- if (val < min) {
- val = min
- }
- if (val > max) {
- val = max
- }
- return val
- }
- const defaultEvents = {
- onChange() {},
- onFocus() {},
- onBlur() {},
- }
- baseComponent({
- behaviors: [eventsMixin({ defaultEvents })],
- externalClasses: ['wux-sub-class', 'wux-input-class', 'wux-add-class'],
- relations: {
- '../field/index': {
- type: 'ancestor',
- },
- },
- properties: {
- prefixCls: {
- type: String,
- value: 'wux-input-number',
- },
- shape: {
- type: String,
- value: 'square',
- },
- min: {
- type: Number,
- value: -MAX_SAFE_INTEGER,
- },
- max: {
- type: Number,
- value: MAX_SAFE_INTEGER,
- },
- step: {
- type: Number,
- value: 1,
- },
- defaultValue: {
- type: Number,
- value: 0,
- },
- value: {
- type: Number,
- value: 0,
- },
- disabled: {
- type: Boolean,
- value: true,
- },
- readOnly: {
- type: Boolean,
- value: false,
- },
- longpress: {
- type: Boolean,
- value: false,
- },
- color: {
- type: String,
- value: 'balanced',
- },
- controlled: {
- type: Boolean,
- value: false,
- },
- digits: {
- type: Number,
- value: -1,
- },
- },
- data: {
- inputValue: 0,
- disabledMin: false,
- disabledMax: false,
- },
- computed: {
- classes: ['prefixCls, shape, color, disabled, readOnly, disabledMin, disabledMax', function(prefixCls, shape, color, disabled, readOnly, disabledMin, disabledMax) {
- const wrap = classNames(prefixCls, {
- [`${prefixCls}--${shape}`]: shape,
- })
- const sub = classNames(`${prefixCls}__selector`, {
- [`${prefixCls}__selector--sub`]: true,
- [`${prefixCls}__selector--${color}`]: color,
- [`${prefixCls}__selector--disabled`]: disabledMin,
- })
- const add = classNames(`${prefixCls}__selector`, {
- [`${prefixCls}__selector--add`]: true,
- [`${prefixCls}__selector--${color}`]: color,
- [`${prefixCls}__selector--disabled`]: disabledMax,
- })
- const icon = `${prefixCls}__icon`
- const input = classNames(`${prefixCls}__input`, {
- [`${prefixCls}__input--disabled`]: disabled,
- [`${prefixCls}__input--readonly`]: readOnly,
- })
- return {
- wrap,
- sub,
- add,
- icon,
- input,
- }
- }],
- },
- observers: {
- value(newVal) {
- if (this.data.controlled) {
- this.setValue(newVal, false)
- }
- },
- 'inputValue, min, max'(inputValue, min, max) {
- const disabledMin = inputValue <= min
- const disabledMax = inputValue >= max
- this.setData({
- disabledMin,
- disabledMax,
- })
- },
- },
- methods: {
- /**
- * 更新值
- */
- updated(inputValue) {
- if (this.hasFieldDecorator) return
- if (this.data.inputValue !== inputValue) {
- this.setData({ inputValue })
- }
- },
- /**
- * 设置值
- */
- setValue(value, runCallbacks = true) {
- const { min, max, digits } = this.data
- let inputValue = NP.strip(getValidValue(value, min, max))
- // Fix digits
- if (digits !== -1) {
- inputValue = NP.round(inputValue, digits)
- }
- this.updated(inputValue)
- if (runCallbacks) {
- this.triggerEvent('change', { value: inputValue })
- }
- },
- /**
- * 数字计算函数
- */
- calculation(type, isLoop) {
- const {
- disabledMax,
- disabledMin,
- inputValue,
- step,
- longpress,
- controlled,
- } = this.data
- // add
- if (type === 'add') {
- if (disabledMax) return
- this.setValue(NP.plus(inputValue, step))
- }
- // sub
- if (type === 'sub') {
- if (disabledMin) return
- this.setValue(NP.minus(inputValue, step))
- }
- // longpress
- if (longpress && isLoop) {
- this.timeout = setTimeout(() => this.calculation(type, isLoop), 100)
- }
- },
- /**
- * 当键盘输入时,触发 input 事件
- */
- onInput(e) {
- this.clearInputTimer()
- this.inputTime = setTimeout(() => {
- const value = toNumberWhenUserInput(e.detail.value)
- this.setValue(value)
- }, 300)
- },
- /**
- * 输入框聚焦时触发
- */
- onFocus(e) {
- this.triggerEvent('focus', e.detail)
- },
- /**
- * 输入框失去焦点时触发
- */
- onBlur(e) {
- // always set input value same as value
- this.setData({
- inputValue: this.data.inputValue,
- })
- this.triggerEvent('blur', e.detail)
- },
- /**
- * 手指触摸后,超过350ms再离开
- */
- onLongpress(e) {
- const { type } = e.currentTarget.dataset
- const { longpress } = this.data
- if (longpress) {
- this.calculation(type, true)
- }
- },
- /**
- * 手指触摸后马上离开
- */
- onTap(e) {
- const { type } = e.currentTarget.dataset
- const { longpress } = this.data
- if (!longpress || longpress && !this.timeout) {
- this.calculation(type, false)
- }
- },
- /**
- * 手指触摸动作结束
- */
- onTouchEnd() {
- this.clearTimer()
- },
- /**
- * 手指触摸动作被打断,如来电提醒,弹窗
- */
- onTouchCancel() {
- this.clearTimer()
- },
- /**
- * 清除长按的定时器
- */
- clearTimer() {
- if (this.timeout) {
- clearTimeout(this.timeout)
- this.timeout = null
- }
- },
- /**
- * 清除输入框的定时器
- */
- clearInputTimer() {
- if (this.inputTime) {
- clearTimeout(this.inputTime)
- this.inputTime = null
- }
- },
- },
- attached() {
- const { defaultValue, value, controlled } = this.data
- const inputValue = controlled ? value : defaultValue
- this.setValue(inputValue, false)
- },
- detached() {
- this.clearTimer()
- this.clearInputTimer()
- },
- })
|