1
|
import $ from 'jquery';
|
2
|
import { each, toNode } from './index';
|
3
|
|
4
|
var dirs = {
|
5
|
x: ['width', 'left', 'right'],
|
6
|
y: ['height', 'top', 'bottom']
|
7
|
};
|
8
|
|
9
|
export function position(element, target, attach, targetAttach, offset, targetOffset, flip, boundary) {
|
10
|
|
11
|
attach = getPos(attach);
|
12
|
targetAttach = getPos(targetAttach);
|
13
|
|
14
|
var flipped = {element: attach, target: targetAttach};
|
15
|
|
16
|
if (!element) {
|
17
|
return flipped;
|
18
|
}
|
19
|
|
20
|
var dim = getDimensions(element),
|
21
|
targetDim = getDimensions(target),
|
22
|
position = targetDim;
|
23
|
|
24
|
moveTo(position, attach, dim, -1);
|
25
|
moveTo(position, targetAttach, targetDim, 1);
|
26
|
|
27
|
offset = getOffsets(offset, dim.width, dim.height);
|
28
|
targetOffset = getOffsets(targetOffset, targetDim.width, targetDim.height);
|
29
|
|
30
|
offset['x'] += targetOffset['x'];
|
31
|
offset['y'] += targetOffset['y'];
|
32
|
|
33
|
position.left += offset['x'];
|
34
|
position.top += offset['y'];
|
35
|
|
36
|
boundary = getDimensions(boundary || window);
|
37
|
|
38
|
if (flip) {
|
39
|
each(dirs, (dir, [prop, align, alignFlip]) => {
|
40
|
|
41
|
if (!(flip === true || ~flip.indexOf(dir))) {
|
42
|
return;
|
43
|
}
|
44
|
|
45
|
var elemOffset = attach[dir] === align
|
46
|
? -dim[prop]
|
47
|
: attach[dir] === alignFlip
|
48
|
? dim[prop]
|
49
|
: 0,
|
50
|
targetOffset = targetAttach[dir] === align
|
51
|
? targetDim[prop]
|
52
|
: targetAttach[dir] === alignFlip
|
53
|
? -targetDim[prop]
|
54
|
: 0;
|
55
|
|
56
|
if (position[align] < boundary[align] || position[align] + dim[prop] > boundary[alignFlip]) {
|
57
|
|
58
|
var newVal = position[align] + elemOffset + targetOffset - offset[dir] * 2;
|
59
|
|
60
|
if (newVal >= boundary[align] && newVal + dim[prop] <= boundary[alignFlip]) {
|
61
|
position[align] = newVal;
|
62
|
|
63
|
['element', 'target'].forEach((el) => {
|
64
|
flipped[el][dir] = !elemOffset
|
65
|
? flipped[el][dir]
|
66
|
: flipped[el][dir] === dirs[dir][1]
|
67
|
? dirs[dir][2]
|
68
|
: dirs[dir][1];
|
69
|
});
|
70
|
}
|
71
|
}
|
72
|
|
73
|
});
|
74
|
}
|
75
|
|
76
|
$(element).offset({left: position.left, top: position.top});
|
77
|
|
78
|
return flipped;
|
79
|
}
|
80
|
|
81
|
export function getDimensions(element) {
|
82
|
|
83
|
element = toNode(element);
|
84
|
|
85
|
var window = getWindow(element), top = window.pageYOffset, left = window.pageXOffset;
|
86
|
|
87
|
if (!element.ownerDocument) {
|
88
|
return {
|
89
|
top,
|
90
|
left,
|
91
|
height: window.innerHeight,
|
92
|
width: window.innerWidth,
|
93
|
bottom: top + window.innerHeight,
|
94
|
right: left + window.innerWidth,
|
95
|
}
|
96
|
}
|
97
|
|
98
|
var display = false;
|
99
|
if (!element.offsetHeight) {
|
100
|
display = element.style.display;
|
101
|
element.style.display = 'block';
|
102
|
}
|
103
|
|
104
|
var rect = element.getBoundingClientRect();
|
105
|
|
106
|
if (display !== false) {
|
107
|
element.style.display = display;
|
108
|
}
|
109
|
|
110
|
return {
|
111
|
height: rect.height,
|
112
|
width: rect.width,
|
113
|
top: rect.top + top,
|
114
|
left: rect.left + left,
|
115
|
bottom: rect.bottom + top,
|
116
|
right: rect.right + left,
|
117
|
}
|
118
|
}
|
119
|
|
120
|
export function offsetTop(element) {
|
121
|
element = toNode(element);
|
122
|
return element.getBoundingClientRect().top + getWindow(element).pageYOffset;
|
123
|
}
|
124
|
|
125
|
function getWindow(element) {
|
126
|
return element && element.ownerDocument ? element.ownerDocument.defaultView : window;
|
127
|
}
|
128
|
|
129
|
function moveTo(position, attach, dim, factor) {
|
130
|
each(dirs, function (dir, [prop, align, alignFlip]) {
|
131
|
if (attach[dir] === alignFlip) {
|
132
|
position[align] += dim[prop] * factor;
|
133
|
} else if (attach[dir] === 'center') {
|
134
|
position[align] += dim[prop] * factor / 2;
|
135
|
}
|
136
|
});
|
137
|
}
|
138
|
|
139
|
function getPos(pos) {
|
140
|
|
141
|
var x = /left|center|right/, y = /top|center|bottom/;
|
142
|
|
143
|
pos = (pos || '').split(' ');
|
144
|
|
145
|
if (pos.length === 1) {
|
146
|
pos = x.test(pos[0])
|
147
|
? pos.concat(['center'])
|
148
|
: y.test(pos[0])
|
149
|
? ['center'].concat(pos)
|
150
|
: ['center', 'center'];
|
151
|
}
|
152
|
|
153
|
return {
|
154
|
x: x.test(pos[0]) ? pos[0] : 'center',
|
155
|
y: y.test(pos[1]) ? pos[1] : 'center'
|
156
|
};
|
157
|
}
|
158
|
|
159
|
function getOffsets(offsets, width, height) {
|
160
|
|
161
|
offsets = (offsets || '').split(' ');
|
162
|
|
163
|
return {
|
164
|
x: offsets[0] ? parseFloat(offsets[0]) * (offsets[0][offsets[0].length - 1] === '%' ? width / 100 : 1) : 0,
|
165
|
y: offsets[1] ? parseFloat(offsets[1]) * (offsets[1][offsets[1].length - 1] === '%' ? height / 100 : 1) : 0
|
166
|
};
|
167
|
}
|
168
|
|
169
|
export function flipPosition(pos) {
|
170
|
switch (pos) {
|
171
|
case 'left':
|
172
|
return 'right';
|
173
|
case 'right':
|
174
|
return 'left';
|
175
|
case 'top':
|
176
|
return 'bottom';
|
177
|
case 'bottom':
|
178
|
return 'top';
|
179
|
default:
|
180
|
return pos;
|
181
|
}
|
182
|
}
|