index.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. // Utils
  2. import { createNamespace, addUnit } from '../utils';
  3. import { preventDefault } from '../utils/dom/event'; // Mixins
  4. import { TouchMixin } from '../mixins/touch';
  5. import { FieldMixin } from '../mixins/field'; // Components
  6. import Icon from '../icon';
  7. var _createNamespace = createNamespace('rate'),
  8. createComponent = _createNamespace[0],
  9. bem = _createNamespace[1];
  10. function getRateStatus(value, index, allowHalf) {
  11. if (value >= index) {
  12. return 'full';
  13. }
  14. if (value + 0.5 >= index && allowHalf) {
  15. return 'half';
  16. }
  17. return 'void';
  18. }
  19. export default createComponent({
  20. mixins: [TouchMixin, FieldMixin],
  21. props: {
  22. size: [Number, String],
  23. color: String,
  24. gutter: [Number, String],
  25. readonly: Boolean,
  26. disabled: Boolean,
  27. allowHalf: Boolean,
  28. voidColor: String,
  29. iconPrefix: String,
  30. disabledColor: String,
  31. value: {
  32. type: Number,
  33. default: 0
  34. },
  35. icon: {
  36. type: String,
  37. default: 'star'
  38. },
  39. voidIcon: {
  40. type: String,
  41. default: 'star-o'
  42. },
  43. count: {
  44. type: [Number, String],
  45. default: 5
  46. },
  47. touchable: {
  48. type: Boolean,
  49. default: true
  50. }
  51. },
  52. computed: {
  53. list: function list() {
  54. var list = [];
  55. for (var i = 1; i <= this.count; i++) {
  56. list.push(getRateStatus(this.value, i, this.allowHalf));
  57. }
  58. return list;
  59. },
  60. sizeWithUnit: function sizeWithUnit() {
  61. return addUnit(this.size);
  62. },
  63. gutterWithUnit: function gutterWithUnit() {
  64. return addUnit(this.gutter);
  65. }
  66. },
  67. mounted: function mounted() {
  68. this.bindTouchEvent(this.$el);
  69. },
  70. methods: {
  71. select: function select(index) {
  72. if (!this.disabled && !this.readonly && index !== this.value) {
  73. this.$emit('input', index);
  74. this.$emit('change', index);
  75. }
  76. },
  77. onTouchStart: function onTouchStart(event) {
  78. var _this = this;
  79. if (this.readonly || this.disabled || !this.touchable) {
  80. return;
  81. }
  82. this.touchStart(event);
  83. var rects = this.$refs.items.map(function (item) {
  84. return item.getBoundingClientRect();
  85. });
  86. var ranges = [];
  87. rects.forEach(function (rect, index) {
  88. if (_this.allowHalf) {
  89. ranges.push({
  90. score: index + 0.5,
  91. left: rect.left
  92. }, {
  93. score: index + 1,
  94. left: rect.left + rect.width / 2
  95. });
  96. } else {
  97. ranges.push({
  98. score: index + 1,
  99. left: rect.left
  100. });
  101. }
  102. });
  103. this.ranges = ranges;
  104. },
  105. onTouchMove: function onTouchMove(event) {
  106. if (this.readonly || this.disabled || !this.touchable) {
  107. return;
  108. }
  109. this.touchMove(event);
  110. if (this.direction === 'horizontal') {
  111. preventDefault(event);
  112. var clientX = event.touches[0].clientX;
  113. this.select(this.getScoreByPosition(clientX));
  114. }
  115. },
  116. getScoreByPosition: function getScoreByPosition(x) {
  117. for (var i = this.ranges.length - 1; i > 0; i--) {
  118. if (x > this.ranges[i].left) {
  119. return this.ranges[i].score;
  120. }
  121. }
  122. return this.allowHalf ? 0.5 : 1;
  123. },
  124. genStar: function genStar(status, index) {
  125. var _this2 = this;
  126. var h = this.$createElement;
  127. var icon = this.icon,
  128. color = this.color,
  129. count = this.count,
  130. voidIcon = this.voidIcon,
  131. disabled = this.disabled,
  132. voidColor = this.voidColor,
  133. disabledColor = this.disabledColor;
  134. var score = index + 1;
  135. var isFull = status === 'full';
  136. var isVoid = status === 'void';
  137. var style;
  138. if (this.gutterWithUnit && score !== +count) {
  139. style = {
  140. paddingRight: this.gutterWithUnit
  141. };
  142. }
  143. return h("div", {
  144. "ref": "items",
  145. "refInFor": true,
  146. "key": index,
  147. "attrs": {
  148. "role": "radio",
  149. "tabindex": "0",
  150. "aria-setsize": count,
  151. "aria-posinset": score,
  152. "aria-checked": String(!isVoid)
  153. },
  154. "style": style,
  155. "class": bem('item')
  156. }, [h(Icon, {
  157. "attrs": {
  158. "size": this.sizeWithUnit,
  159. "name": isFull ? icon : voidIcon,
  160. "color": disabled ? disabledColor : isFull ? color : voidColor,
  161. "classPrefix": this.iconPrefix,
  162. "data-score": score
  163. },
  164. "class": bem('icon', {
  165. disabled: disabled,
  166. full: isFull
  167. }),
  168. "on": {
  169. "click": function click() {
  170. _this2.select(score);
  171. }
  172. }
  173. }), this.allowHalf && h(Icon, {
  174. "attrs": {
  175. "size": this.sizeWithUnit,
  176. "name": isVoid ? voidIcon : icon,
  177. "color": disabled ? disabledColor : isVoid ? voidColor : color,
  178. "classPrefix": this.iconPrefix,
  179. "data-score": score - 0.5
  180. },
  181. "class": bem('icon', ['half', {
  182. disabled: disabled,
  183. full: !isVoid
  184. }]),
  185. "on": {
  186. "click": function click() {
  187. _this2.select(score - 0.5);
  188. }
  189. }
  190. })]);
  191. }
  192. },
  193. render: function render() {
  194. var _this3 = this;
  195. var h = arguments[0];
  196. return h("div", {
  197. "class": bem({
  198. readonly: this.readonly,
  199. disabled: this.disabled
  200. }),
  201. "attrs": {
  202. "tabindex": "0",
  203. "role": "radiogroup"
  204. }
  205. }, [this.list.map(function (status, index) {
  206. return _this3.genStar(status, index);
  207. })]);
  208. }
  209. });