UNPKG

vxe-table-select-area

Version:

一个基于 vxe-table 的可区域选中复制、粘贴的组件

259 lines (257 loc) 8.04 kB
import GlobalConfig from '../../v-x-e-table/src/conf' import vSize from '../../mixins/size' import UtilTools from '../../tools/utils' import DomTools from '../../tools/dom' import { GlobalEvent } from '../../tools/event' export default { name: 'VxePulldown', mixins: [vSize], props: { value: Boolean, disabled: Boolean, placement: String, size: { type: String, default: () => GlobalConfig.size }, destroyOnClose: Boolean, transfer: Boolean }, data () { return { inited: false, panelIndex: 0, panelStyle: null, panelPlacement: null, currentValue: null, visiblePanel: false, animatVisible: false, isActivated: false } }, watch: { value (value) { if (value) { this.showPanel() } else { this.hidePanel() } } }, created () { GlobalEvent.on(this, 'mousewheel', this.handleGlobalMousewheelEvent) GlobalEvent.on(this, 'mousedown', this.handleGlobalMousedownEvent) GlobalEvent.on(this, 'blur', this.handleGlobalBlurEvent) }, beforeDestroy () { const panelElem = this.$refs.panel if (panelElem && panelElem.parentNode) { panelElem.parentNode.removeChild(panelElem) } }, destroyed () { GlobalEvent.off(this, 'mousewheel') GlobalEvent.off(this, 'mousedown') GlobalEvent.off(this, 'blur') }, render (h) { const { $scopedSlots, inited, vSize, destroyOnClose, transfer, isActivated, disabled, animatVisible, visiblePanel, panelStyle, panelPlacement } = this const defaultSlot = $scopedSlots.default const downSlot = $scopedSlots.dropdown return h('div', { class: ['vxe-pulldown', { [`size--${vSize}`]: vSize, 'is--visivle': visiblePanel, 'is--disabled': disabled, 'is--active': isActivated }] }, [ h('div', { ref: 'content', class: 'vxe-pulldown--content' }, defaultSlot ? defaultSlot.call(this, { $pulldown: this }, h) : []), h('div', { ref: 'panel', class: ['vxe-table--ignore-clear vxe-pulldown--panel', { [`size--${vSize}`]: vSize, 'is--transfer': transfer, 'animat--leave': animatVisible, 'animat--enter': visiblePanel }], attrs: { placement: panelPlacement }, style: panelStyle }, downSlot ? [ h('div', { class: 'vxe-pulldown--wrapper' }, !inited || (destroyOnClose && !visiblePanel && !animatVisible) ? [] : downSlot.call(this, { $pulldown: this }, h)) ] : []) ]) }, methods: { handleGlobalMousewheelEvent (evnt) { const { $refs, disabled, visiblePanel } = this if (!disabled) { if (visiblePanel) { if (DomTools.getEventTargetNode(evnt, $refs.panel).flag) { this.updatePlacement() } else { this.hidePanel() this.$emit('hide-panel', { $event: evnt }) } } } }, handleGlobalMousedownEvent (evnt) { const { $refs, $el, disabled, visiblePanel } = this if (!disabled) { this.isActivated = DomTools.getEventTargetNode(evnt, $el).flag || DomTools.getEventTargetNode(evnt, $refs.panel).flag if (visiblePanel && !this.isActivated) { this.hidePanel() this.$emit('hide-panel', { $event: evnt }) } } }, handleGlobalBlurEvent (evnt) { if (this.visiblePanel) { this.isActivated = false this.hidePanel() this.$emit('hide-panel', { $event: evnt }) } }, updateZindex () { if (this.panelIndex < UtilTools.getLastZIndex()) { this.panelIndex = UtilTools.nextZIndex() } }, isPanelVisible () { return this.visiblePanel }, /** * 切换下拉面板 */ togglePanel () { if (this.visiblePanel) { return this.hidePanel() } return this.showPanel() }, /** * 显示下拉面板 */ showPanel () { if (!this.inited) { this.inited = true if (this.transfer) { document.body.appendChild(this.$refs.panel) } } return new Promise(resolve => { if (!this.disabled) { clearTimeout(this.hidePanelTimeout) this.isActivated = true this.animatVisible = true setTimeout(() => { this.visiblePanel = true this.$emit('update:input', true) this.updatePlacement() setTimeout(() => { resolve(this.updatePlacement()) }, 40) }, 10) this.updateZindex() } else { resolve(this.$nextTick()) } }) }, /** * 隐藏下拉面板 */ hidePanel () { this.visiblePanel = false this.$emit('update:input', false) return new Promise(resolve => { if (this.animatVisible) { this.hidePanelTimeout = setTimeout(() => { this.animatVisible = false resolve(this.$nextTick()) }, 350) } else { resolve(this.$nextTick()) } }) }, /** * 手动更新位置 */ updatePlacement () { return this.$nextTick().then(() => { const { $refs, transfer, placement, panelIndex, visiblePanel } = this if (visiblePanel) { const panelElem = $refs.panel const targetElem = $refs.content if (panelElem && targetElem) { const targetHeight = targetElem.offsetHeight const targetWidth = targetElem.offsetWidth const panelHeight = panelElem.offsetHeight const panelWidth = panelElem.offsetWidth const marginSize = 5 const panelStyle = { zIndex: panelIndex } const { boundingTop, boundingLeft, visibleHeight, visibleWidth } = DomTools.getAbsolutePos(targetElem) let panelPlacement = 'bottom' if (transfer) { let left = boundingLeft let top = boundingTop + targetHeight if (placement === 'top') { panelPlacement = 'top' top = boundingTop - panelHeight } else if (!placement) { // 如果下面不够放,则向上 if (top + panelHeight + marginSize > visibleHeight) { panelPlacement = 'top' top = boundingTop - panelHeight } // 如果上面不够放,则向下(优先) if (top < marginSize) { panelPlacement = 'bottom' top = boundingTop + targetHeight } } // 如果溢出右边 if (left + panelWidth + marginSize > visibleWidth) { left -= left + panelWidth + marginSize - visibleWidth } // 如果溢出左边 if (left < marginSize) { left = marginSize } Object.assign(panelStyle, { left: `${left}px`, top: `${top}px`, minWidth: `${targetWidth}px` }) } else { if (placement === 'top') { panelPlacement = 'top' panelStyle.bottom = `${targetHeight}px` } else if (!placement) { // 如果下面不够放,则向上 if (boundingTop + targetHeight + panelHeight > visibleHeight) { // 如果上面不够放,则向下(优先) if (boundingTop - targetHeight - panelHeight > marginSize) { panelPlacement = 'top' panelStyle.bottom = `${targetHeight}px` } } } } this.panelStyle = panelStyle this.panelPlacement = panelPlacement } } return this.$nextTick() }) } } }