ant-design-vue/components/vc-rate/src/Rate.jsx

214 lines
5.0 KiB
Vue
Raw Normal View History

2019-01-12 03:33:27 +00:00
import PropTypes from '../../_util/vue-types';
import classNames from 'classnames';
import KeyCode from '../../_util/KeyCode';
import {
initDefaultProps,
hasProp,
getOptionProps,
getComponentFromProp,
} from '../../_util/props-util';
import BaseMixin from '../../_util/BaseMixin';
import { getOffsetLeft } from './util';
import Star from './Star';
2018-03-21 05:06:19 +00:00
const rateProps = {
disabled: PropTypes.bool,
value: PropTypes.number,
defaultValue: PropTypes.number,
count: PropTypes.number,
allowHalf: PropTypes.bool,
allowClear: PropTypes.bool,
prefixCls: PropTypes.string,
character: PropTypes.any,
tabIndex: PropTypes.number,
autoFocus: PropTypes.bool,
2019-01-12 03:33:27 +00:00
};
2018-03-21 05:06:19 +00:00
2019-01-12 03:33:27 +00:00
function noop() {}
2018-03-21 07:45:01 +00:00
2018-03-21 05:06:19 +00:00
export default {
name: 'Rate',
mixins: [BaseMixin],
props: initDefaultProps(rateProps, {
defaultValue: 0,
count: 5,
allowHalf: false,
allowClear: true,
prefixCls: 'rc-rate',
tabIndex: 0,
character: '★',
}),
2018-03-21 07:45:01 +00:00
model: {
2018-03-21 05:06:19 +00:00
prop: 'value',
event: 'change',
},
2019-01-12 03:33:27 +00:00
data() {
let value = this.value;
2018-03-21 05:06:19 +00:00
if (!hasProp(this, 'value')) {
2019-01-12 03:33:27 +00:00
value = this.defaultValue;
2018-03-21 05:06:19 +00:00
}
return {
sValue: value,
focused: false,
cleanedValue: null,
hoverValue: undefined,
2019-01-12 03:33:27 +00:00
};
2018-03-21 05:06:19 +00:00
},
2019-01-12 03:33:27 +00:00
mounted() {
2018-03-21 05:06:19 +00:00
this.$nextTick(() => {
if (this.autoFocus && !this.disabled) {
2019-01-12 03:33:27 +00:00
this.focus();
2018-03-21 05:06:19 +00:00
}
2019-01-12 03:33:27 +00:00
});
2018-03-21 05:06:19 +00:00
},
watch: {
2019-01-12 03:33:27 +00:00
value(val) {
2018-03-21 05:06:19 +00:00
this.setState({
sValue: val,
2019-01-12 03:33:27 +00:00
});
2018-03-21 05:06:19 +00:00
},
},
methods: {
2019-01-12 03:33:27 +00:00
onHover(event, index) {
const hoverValue = this.getStarValue(index, event.pageX);
const { cleanedValue } = this;
2018-03-21 05:06:19 +00:00
if (hoverValue !== cleanedValue) {
this.setState({
hoverValue,
cleanedValue: null,
2019-01-12 03:33:27 +00:00
});
2018-03-21 05:06:19 +00:00
}
2019-01-12 03:33:27 +00:00
this.$emit('hoverChange', hoverValue);
2018-03-21 05:06:19 +00:00
},
2019-01-12 03:33:27 +00:00
onMouseLeave() {
2018-03-21 05:06:19 +00:00
this.setState({
hoverValue: undefined,
cleanedValue: null,
2019-01-12 03:33:27 +00:00
});
this.$emit('hoverChange', undefined);
2018-03-21 05:06:19 +00:00
},
2019-01-12 03:33:27 +00:00
onClick(event, index) {
const value = this.getStarValue(index, event.pageX);
let isReset = false;
2018-03-21 05:06:19 +00:00
if (this.allowClear) {
2019-01-12 03:33:27 +00:00
isReset = value === this.sValue;
2018-03-21 05:06:19 +00:00
}
2019-01-12 03:33:27 +00:00
this.onMouseLeave(true);
this.changeValue(isReset ? 0 : value);
2018-03-21 05:06:19 +00:00
this.setState({
cleanedValue: isReset ? value : null,
2019-01-12 03:33:27 +00:00
});
2018-03-21 05:06:19 +00:00
},
2019-01-12 03:33:27 +00:00
onFocus() {
2018-03-21 05:06:19 +00:00
this.setState({
focused: true,
2019-01-12 03:33:27 +00:00
});
this.$emit('focus');
2018-03-21 05:06:19 +00:00
},
2019-01-12 03:33:27 +00:00
onBlur() {
2018-03-21 05:06:19 +00:00
this.setState({
focused: false,
2019-01-12 03:33:27 +00:00
});
this.$emit('blur');
2018-03-21 05:06:19 +00:00
},
2019-01-12 03:33:27 +00:00
onKeyDown(event) {
const { keyCode } = event;
const { count, allowHalf } = this;
let { sValue } = this;
2018-03-21 05:06:19 +00:00
if (keyCode === KeyCode.RIGHT && sValue < count) {
if (allowHalf) {
2019-01-12 03:33:27 +00:00
sValue += 0.5;
2018-03-21 05:06:19 +00:00
} else {
2019-01-12 03:33:27 +00:00
sValue += 1;
2018-03-21 05:06:19 +00:00
}
2019-01-12 03:33:27 +00:00
this.changeValue(sValue);
event.preventDefault();
2018-03-21 05:06:19 +00:00
} else if (keyCode === KeyCode.LEFT && sValue > 0) {
if (allowHalf) {
2019-01-12 03:33:27 +00:00
sValue -= 0.5;
2018-03-21 05:06:19 +00:00
} else {
2019-01-12 03:33:27 +00:00
sValue -= 1;
2018-03-21 05:06:19 +00:00
}
2019-01-12 03:33:27 +00:00
this.changeValue(sValue);
event.preventDefault();
2018-03-21 05:06:19 +00:00
}
2019-01-12 03:33:27 +00:00
this.$emit('keydown', event);
2018-03-21 05:06:19 +00:00
},
2019-01-12 03:33:27 +00:00
getStarDOM(index) {
return this.$refs['stars' + index].$el;
2018-03-21 05:06:19 +00:00
},
2019-01-12 03:33:27 +00:00
getStarValue(index, x) {
let value = index + 1;
2018-03-21 05:06:19 +00:00
if (this.allowHalf) {
2019-01-12 03:33:27 +00:00
const starEle = this.getStarDOM(index);
const leftDis = getOffsetLeft(starEle);
const width = starEle.clientWidth;
if (x - leftDis < width / 2) {
value -= 0.5;
2018-03-21 05:06:19 +00:00
}
}
2019-01-12 03:33:27 +00:00
return value;
2018-03-21 05:06:19 +00:00
},
2019-01-12 03:33:27 +00:00
focus() {
2018-03-21 05:06:19 +00:00
if (!this.disabled) {
2019-01-12 03:33:27 +00:00
this.$refs.rateRef.focus();
2018-03-21 05:06:19 +00:00
}
},
2019-01-12 03:33:27 +00:00
blur() {
if (!this.disabled) {
2019-01-12 03:33:27 +00:00
this.$refs.rateRef.blur();
}
},
2019-01-12 03:33:27 +00:00
changeValue(value) {
2018-03-21 05:06:19 +00:00
if (!hasProp(this, 'value')) {
this.setState({
sValue: value,
2019-01-12 03:33:27 +00:00
});
2018-03-21 05:06:19 +00:00
}
2019-01-12 03:33:27 +00:00
this.$emit('change', value);
2018-03-21 05:06:19 +00:00
},
},
2019-01-12 03:33:27 +00:00
render() {
const { count, allowHalf, prefixCls, disabled, tabIndex } = getOptionProps(this);
const { sValue, hoverValue, focused } = this;
const stars = [];
const disabledClass = disabled ? `${prefixCls}-disabled` : '';
const character = getComponentFromProp(this, 'character');
2018-03-21 05:06:19 +00:00
for (let index = 0; index < count; index++) {
const starProps = {
props: {
index,
count,
2018-03-21 05:06:19 +00:00
disabled,
prefixCls: `${prefixCls}-star`,
allowHalf,
value: hoverValue === undefined ? sValue : hoverValue,
2018-12-10 14:38:49 +00:00
character,
2018-03-21 05:06:19 +00:00
focused,
},
on: {
click: this.onClick,
hover: this.onHover,
},
key: index,
ref: `stars${index}`,
2019-01-12 03:33:27 +00:00
};
stars.push(<Star {...starProps} />);
2018-03-21 05:06:19 +00:00
}
return (
<ul
class={classNames(prefixCls, disabledClass)}
2018-03-21 07:45:01 +00:00
onMouseleave={disabled ? noop : this.onMouseLeave}
2018-03-21 05:06:19 +00:00
tabIndex={disabled ? -1 : tabIndex}
2018-03-21 07:45:01 +00:00
onFocus={disabled ? noop : this.onFocus}
onBlur={disabled ? noop : this.onBlur}
onKeydown={disabled ? noop : this.onKeyDown}
2019-01-12 03:33:27 +00:00
ref="rateRef"
role="radiogroup"
2018-03-21 05:06:19 +00:00
>
{stars}
</ul>
2019-01-12 03:33:27 +00:00
);
2018-03-21 05:06:19 +00:00
},
2019-01-12 03:33:27 +00:00
};