// Utils import { createNamespace } from '../utils'; import { preventDefault } from '../utils/dom/event'; import { getScrollTop, getScroller } from '../utils/dom/scroll'; // Mixins import { TouchMixin } from '../mixins/touch'; // Components import Loading from '../loading'; var _createNamespace = createNamespace('pull-refresh'), createComponent = _createNamespace[0], bem = _createNamespace[1], t = _createNamespace[2]; var DEFAULT_HEAD_HEIGHT = 50; var TEXT_STATUS = ['pulling', 'loosing', 'success']; export default createComponent({ mixins: [TouchMixin], props: { disabled: Boolean, successText: String, pullingText: String, loosingText: String, loadingText: String, pullDistance: [Number, String], value: { type: Boolean, required: true }, successDuration: { type: [Number, String], default: 500 }, animationDuration: { type: [Number, String], default: 300 }, headHeight: { type: [Number, String], default: DEFAULT_HEAD_HEIGHT } }, data: function data() { return { status: 'normal', distance: 0, duration: 0 }; }, computed: { touchable: function touchable() { return this.status !== 'loading' && this.status !== 'success' && !this.disabled; }, headStyle: function headStyle() { if (this.headHeight !== DEFAULT_HEAD_HEIGHT) { return { height: this.headHeight + "px" }; } } }, watch: { value: function value(loading) { this.duration = this.animationDuration; if (loading) { this.setStatus(+this.headHeight, true); } else if (this.slots('success') || this.successText) { this.showSuccessTip(); } else { this.setStatus(0, false); } } }, mounted: function mounted() { this.bindTouchEvent(this.$refs.track); this.scrollEl = getScroller(this.$el); }, methods: { checkPullStart: function checkPullStart(event) { this.ceiling = getScrollTop(this.scrollEl) === 0; if (this.ceiling) { this.duration = 0; this.touchStart(event); } }, onTouchStart: function onTouchStart(event) { if (this.touchable) { this.checkPullStart(event); } }, onTouchMove: function onTouchMove(event) { if (!this.touchable) { return; } if (!this.ceiling) { this.checkPullStart(event); } this.touchMove(event); if (this.ceiling && this.deltaY >= 0 && this.direction === 'vertical') { preventDefault(event); this.setStatus(this.ease(this.deltaY)); } }, onTouchEnd: function onTouchEnd() { var _this = this; if (this.touchable && this.ceiling && this.deltaY) { this.duration = this.animationDuration; if (this.status === 'loosing') { this.setStatus(+this.headHeight, true); this.$emit('input', true); // ensure value change can be watched this.$nextTick(function () { _this.$emit('refresh'); }); } else { this.setStatus(0); } } }, ease: function ease(distance) { var pullDistance = +(this.pullDistance || this.headHeight); if (distance > pullDistance) { if (distance < pullDistance * 2) { distance = pullDistance + (distance - pullDistance) / 2; } else { distance = pullDistance * 1.5 + (distance - pullDistance * 2) / 4; } } return Math.round(distance); }, setStatus: function setStatus(distance, isLoading) { var status; if (isLoading) { status = 'loading'; } else if (distance === 0) { status = 'normal'; } else { status = distance < (this.pullDistance || this.headHeight) ? 'pulling' : 'loosing'; } this.distance = distance; if (status !== this.status) { this.status = status; } }, genStatus: function genStatus() { var h = this.$createElement; var status = this.status, distance = this.distance; var slot = this.slots(status, { distance: distance }); if (slot) { return slot; } var nodes = []; var text = this[status + "Text"] || t(status); if (TEXT_STATUS.indexOf(status) !== -1) { nodes.push(h("div", { "class": bem('text') }, [text])); } if (status === 'loading') { nodes.push(h(Loading, { "attrs": { "size": "16" } }, [text])); } return nodes; }, showSuccessTip: function showSuccessTip() { var _this2 = this; this.status = 'success'; setTimeout(function () { _this2.setStatus(0); }, this.successDuration); } }, render: function render() { var h = arguments[0]; var trackStyle = { transitionDuration: this.duration + "ms", transform: this.distance ? "translate3d(0," + this.distance + "px, 0)" : '' }; return h("div", { "class": bem() }, [h("div", { "ref": "track", "class": bem('track'), "style": trackStyle }, [h("div", { "class": bem('head'), "style": this.headStyle }, [this.genStatus()]), this.slots()])]); } });