import KeyCode from '../_util/KeyCode' import contains from '../_util/Dom/contains' import LazyRenderBox from './LazyRenderBox' import BaseMixin from '../_util/BaseMixin' import getTransitionProps from '../_util/getTransitionProps' import getScrollBarSize from '../_util/getScrollBarSize' import getDialogPropTypes from './IDialogPropTypes' const IDialogPropTypes = getDialogPropTypes() let uuid = 0 let openCount = 0 /* eslint react/no-is-mounted:0 */ function noop () {} function getScroll (w, top) { let ret = w[`page${top ? 'Y' : 'X'}Offset`] const method = `scroll${top ? 'Top' : 'Left'}` if (typeof ret !== 'number') { const d = w.document ret = d.documentElement[method] if (typeof ret !== 'number') { ret = d.body[method] } } return ret } function setTransformOrigin (node, value) { const style = node.style; ['Webkit', 'Moz', 'Ms', 'ms'].forEach((prefix) => { style[`${prefix}TransformOrigin`] = value }) style[`transformOrigin`] = value } function offset (el) { const rect = el.getBoundingClientRect() const pos = { left: rect.left, top: rect.top, } const doc = el.ownerDocument const w = doc.defaultView || doc.parentWindow pos.left += getScroll(w) pos.top += getScroll(w, true) return pos } const initDefaultProps = (propTypes, defaultProps) => { return Object.keys(defaultProps).map(k => propTypes[k].def(defaultProps[k])) } export default { mixins: [BaseMixin], props: { ...IDialogPropTypes, ...initDefaultProps(IDialogPropTypes, { mask: true, visible: false, keyboard: true, closable: true, maskClosable: true, destroyOnClose: false, prefixCls: 'rc-dialog', }), }, data () { return { destroyPopup: false, } }, // private inTransition: boolean; // private titleId: string; // private openTime: number; // private lastOutSideFocusNode: HTMLElement | null; // private wrap: HTMLElement; // private dialog: any; // private sentinel: HTMLElement; // private bodyIsOverflowing: boolean; // private scrollbarWidth: number; beforeMount () { this.inTransition = false this.titleId = `rcDialogTitle${uuid++}` }, mounted () { this.$nextTick(() => { this.updatedCallback(false) }) }, watch: { visible (val) { if (val) { this.destroyPopup = false } this.$nextTick(() => { this.updatedCallback(!val) }) }, }, beforeDestroy () { if (this.visible || this.inTransition) { this.removeScrollingEffect() } }, methods: { updatedCallback (visible) { const mousePosition = this.mousePosition if (this.visible) { // first show if (!visible) { this.openTime = Date.now() // this.lastOutSideFocusNode = document.activeElement this.addScrollingEffect() // this.$refs.wrap.focus() this.tryFocus() const dialogNode = this.$refs.dialog.$el if (mousePosition) { const elOffset = offset(dialogNode) setTransformOrigin(dialogNode, `${mousePosition.x - elOffset.left}px ${mousePosition.y - elOffset.top}px`) } else { setTransformOrigin(dialogNode, '') } } } else if (visible) { this.inTransition = true if (this.mask && this.lastOutSideFocusNode) { try { this.lastOutSideFocusNode.focus() } catch (e) { this.lastOutSideFocusNode = null } this.lastOutSideFocusNode = null } } }, tryFocus () { if (!contains(this.$refs.wrap, document.activeElement)) { this.lastOutSideFocusNode = document.activeElement this.$refs.wrap.focus() } }, onAnimateLeave () { const { afterClose, destroyOnClose } = this // need demo? // https://github.com/react-component/dialog/pull/28 if (this.$refs.wrap) { this.$refs.wrap.style.display = 'none' } if (destroyOnClose) { this.destroyPopup = true } this.inTransition = false this.removeScrollingEffect() if (afterClose) { afterClose() } }, onMaskClick (e) { // android trigger click on open (fastclick??) if (Date.now() - this.openTime < 300) { return } if (e.target === e.currentTarget) { this.close(e) } }, onKeydown (e) { const props = this.$props if (props.keyboard && e.keyCode === KeyCode.ESC) { e.stopPropagation() this.close(e) return } // keep focus inside dialog if (props.visible) { if (e.keyCode === KeyCode.TAB) { const activeElement = document.activeElement const dialogRoot = this.$refs.wrap if (e.shiftKey) { if (activeElement === dialogRoot) { this.$refs.sentinel.focus() } } else if (activeElement === this.$refs.sentinel) { dialogRoot.focus() } } } }, getDialogElement () { const { closable, prefixCls, width, height, title, footer: tempFooter, bodyStyle, visible, bodyProps } = this const dest = {} if (width !== undefined) { dest.width = typeof width === 'number' ? `${width}px` : width } if (height !== undefined) { dest.height = typeof height === 'number' ? `${height}px` : height } let footer if (tempFooter) { footer = (
) } let header if (title) { header = (