1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import _extends from 'babel-runtime/helpers/extends';
import _typeof from 'babel-runtime/helpers/typeof';
import PropTypes from '../_util/vue-types';
import { alignElement, alignPoint } from 'dom-align';
import addEventListener from '../_util/Dom/addEventListener';
import { isWindow, buffer, isSamePoint } from './util';
import { cloneElement } from '../_util/vnode.js';
import clonedeep from 'lodash/cloneDeep';
function getElement(func) {
if (typeof func !== 'function' || !func) return null;
return func();
}
function getPoint(point) {
if ((typeof point === 'undefined' ? 'undefined' : _typeof(point)) !== 'object' || !point) return null;
return point;
}
export default {
props: {
childrenProps: PropTypes.object,
align: PropTypes.object.isRequired,
target: PropTypes.oneOfType([PropTypes.func, PropTypes.object]).def(function () {
return window;
}),
monitorBufferTime: PropTypes.number.def(50),
monitorWindowResize: PropTypes.bool.def(false),
disabled: PropTypes.bool.def(false)
},
data: function data() {
this.aligned = false;
return {};
},
mounted: function mounted() {
var _this = this;
this.$nextTick(function () {
_this.prevProps = _extends({}, _this.$props);
var props = _this.$props;
// if parent ref not attached .... use document.getElementById
!_this.aligned && _this.forceAlign();
if (!props.disabled && props.monitorWindowResize) {
_this.startMonitorWindowResize();
}
});
},
updated: function updated() {
var _this2 = this;
this.$nextTick(function () {
var prevProps = _this2.prevProps;
var props = _this2.$props;
var reAlign = false;
if (!props.disabled) {
var source = _this2.$el;
var sourceRect = source ? source.getBoundingClientRect() : null;
if (prevProps.disabled) {
reAlign = true;
} else {
var lastElement = getElement(prevProps.target);
var currentElement = getElement(props.target);
var lastPoint = getPoint(prevProps.target);
var currentPoint = getPoint(props.target);
if (isWindow(lastElement) && isWindow(currentElement)) {
// Skip if is window
reAlign = false;
} else if (lastElement !== currentElement || // Element change
lastElement && !currentElement && currentPoint || // Change from element to point
lastPoint && currentPoint && currentElement || // Change from point to element
currentPoint && !isSamePoint(lastPoint, currentPoint)) {
reAlign = true;
}
// If source element size changed
var preRect = _this2.sourceRect || {};
if (!reAlign && source && (preRect.width !== sourceRect.width || preRect.height !== sourceRect.height)) {
reAlign = true;
}
}
_this2.sourceRect = sourceRect;
}
if (reAlign) {
_this2.forceAlign();
}
if (props.monitorWindowResize && !props.disabled) {
_this2.startMonitorWindowResize();
} else {
_this2.stopMonitorWindowResize();
}
_this2.prevProps = _extends({}, _this2.$props, { align: clonedeep(_this2.$props.align) });
});
},
beforeDestroy: function beforeDestroy() {
this.stopMonitorWindowResize();
},
methods: {
startMonitorWindowResize: function startMonitorWindowResize() {
if (!this.resizeHandler) {
this.bufferMonitor = buffer(this.forceAlign, this.$props.monitorBufferTime);
this.resizeHandler = addEventListener(window, 'resize', this.bufferMonitor);
}
},
stopMonitorWindowResize: function stopMonitorWindowResize() {
if (this.resizeHandler) {
this.bufferMonitor.clear();
this.resizeHandler.remove();
this.resizeHandler = null;
}
},
forceAlign: function forceAlign() {
var _$props = this.$props,
disabled = _$props.disabled,
target = _$props.target,
align = _$props.align;
if (!disabled && target) {
var source = this.$el;
var result = void 0;
var element = getElement(target);
var point = getPoint(target);
if (element) {
result = alignElement(source, element, align);
} else if (point) {
result = alignPoint(source, point, align);
}
this.aligned = true;
this.$listeners.align && this.$listeners.align(source, result);
}
}
},
render: function render() {
var childrenProps = this.$props.childrenProps;
var child = this.$slots['default'][0];
if (childrenProps) {
return cloneElement(child, { props: childrenProps });
}
return child;
}
};