1 | 'use strict';
|
2 |
|
3 | exports.__esModule = true;
|
4 | exports.default = undefined;
|
5 |
|
6 | var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
|
7 |
|
8 | var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
|
9 |
|
10 | var _typeof2 = require('babel-runtime/helpers/typeof');
|
11 |
|
12 | var _typeof3 = _interopRequireDefault(_typeof2);
|
13 |
|
14 | var _class, _temp, _initialiseProps;
|
15 |
|
16 | var _util = require('../../util');
|
17 |
|
18 | var _findNode = require('./find-node');
|
19 |
|
20 | var _findNode2 = _interopRequireDefault(_findNode);
|
21 |
|
22 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
23 |
|
24 | var VIEWPORT = 'viewport';
|
25 |
|
26 |
|
27 | var getPageX = function getPageX() {
|
28 | return window.pageXOffset || document.documentElement.scrollLeft;
|
29 | };
|
30 | var getPageY = function getPageY() {
|
31 | return window.pageYOffset || document.documentElement.scrollTop;
|
32 | };
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 | function _getSize(element) {
|
40 |
|
41 |
|
42 | if ('offsetWidth' in element && 'offsetHeight' in element) {
|
43 | return {
|
44 | width: element.offsetWidth,
|
45 | height: element.offsetHeight
|
46 | };
|
47 | } else {
|
48 | var _element$getBoundingC = element.getBoundingClientRect(),
|
49 | width = _element$getBoundingC.width,
|
50 | height = _element$getBoundingC.height;
|
51 |
|
52 | return {
|
53 | width: width,
|
54 | height: height
|
55 | };
|
56 | }
|
57 | }
|
58 |
|
59 |
|
60 |
|
61 |
|
62 |
|
63 |
|
64 | function _getElementRect(elem, container) {
|
65 | var offsetTop = 0,
|
66 | offsetLeft = 0,
|
67 | scrollTop = 0,
|
68 | scrollLeft = 0;
|
69 |
|
70 | var _getSize2 = _getSize(elem),
|
71 | width = _getSize2.width,
|
72 | height = _getSize2.height;
|
73 |
|
74 | do {
|
75 | if (!isNaN(elem.offsetTop)) {
|
76 | offsetTop += elem.offsetTop;
|
77 | }
|
78 | if (!isNaN(elem.offsetLeft)) {
|
79 | offsetLeft += elem.offsetLeft;
|
80 | }
|
81 | if (elem && elem.offsetParent) {
|
82 | if (!isNaN(elem.offsetParent.scrollLeft) && elem.offsetParent !== document.body) {
|
83 | scrollLeft += elem.offsetParent.scrollLeft;
|
84 | }
|
85 |
|
86 | if (!isNaN(elem.offsetParent.scrollTop) && elem.offsetParent !== document.body) {
|
87 | scrollTop += elem.offsetParent.scrollTop;
|
88 | }
|
89 | }
|
90 |
|
91 | elem = elem.offsetParent;
|
92 | } while (elem !== null && elem !== container);
|
93 |
|
94 |
|
95 | var treatAsWindow = !container || container === document.body;
|
96 |
|
97 | return {
|
98 | top: offsetTop - scrollTop - (treatAsWindow ? document.documentElement.scrollTop || document.body.scrollTop : 0),
|
99 | left: offsetLeft - scrollLeft - (treatAsWindow ? document.documentElement.scrollLeft || document.body.scrollLeft : 0),
|
100 | width: width,
|
101 | height: height
|
102 | };
|
103 | }
|
104 |
|
105 |
|
106 |
|
107 |
|
108 |
|
109 | function _getViewportSize(container) {
|
110 | if (!container || container === document.body) {
|
111 | return {
|
112 | width: document.documentElement.clientWidth,
|
113 | height: document.documentElement.clientHeight
|
114 | };
|
115 | }
|
116 |
|
117 | var _container$getBoundin = container.getBoundingClientRect(),
|
118 | width = _container$getBoundin.width,
|
119 | height = _container$getBoundin.height;
|
120 |
|
121 | return {
|
122 | width: width,
|
123 | height: height
|
124 | };
|
125 | }
|
126 |
|
127 | var getContainer = function getContainer(_ref) {
|
128 | var container = _ref.container,
|
129 | baseElement = _ref.baseElement;
|
130 |
|
131 |
|
132 | if ((typeof document === 'undefined' ? 'undefined' : (0, _typeof3.default)(document)) === undefined) {
|
133 | return container;
|
134 | }
|
135 |
|
136 | var calcContainer = (0, _findNode2.default)(container, baseElement);
|
137 |
|
138 | if (!calcContainer) {
|
139 | calcContainer = document.body;
|
140 | }
|
141 |
|
142 | while (_util.dom.getStyle(calcContainer, 'position') === 'static') {
|
143 | if (!calcContainer || calcContainer === document.body) {
|
144 | return document.body;
|
145 | }
|
146 | calcContainer = calcContainer.parentNode;
|
147 | }
|
148 |
|
149 | return calcContainer;
|
150 | };
|
151 |
|
152 | var Position = (_temp = _class = function () {
|
153 | function Position(props) {
|
154 | (0, _classCallCheck3.default)(this, Position);
|
155 |
|
156 | _initialiseProps.call(this);
|
157 |
|
158 | this.pinElement = props.pinElement;
|
159 | this.baseElement = props.baseElement;
|
160 | this.pinFollowBaseElementWhenFixed = props.pinFollowBaseElementWhenFixed;
|
161 | this.container = getContainer(props);
|
162 | this.autoFit = props.autoFit || false;
|
163 | this.align = props.align || 'tl tl';
|
164 | this.offset = props.offset || [0, 0];
|
165 | this.needAdjust = props.needAdjust || false;
|
166 | this.isRtl = props.isRtl || false;
|
167 | }
|
168 |
|
169 | |
170 |
|
171 |
|
172 |
|
173 |
|
174 |
|
175 |
|
176 |
|
177 |
|
178 |
|
179 |
|
180 |
|
181 |
|
182 | Position.prototype.setPosition = function setPosition() {
|
183 | var pinElement = this.pinElement;
|
184 | var baseElement = this.baseElement;
|
185 | var pinFollowBaseElementWhenFixed = this.pinFollowBaseElementWhenFixed;
|
186 | var expectedAlign = this._getExpectedAlign();
|
187 | var isPinFixed = void 0,
|
188 | isBaseFixed = void 0,
|
189 | firstPositionResult = void 0;
|
190 | if (pinElement === VIEWPORT) {
|
191 | return;
|
192 | }
|
193 | if (_util.dom.getStyle(pinElement, 'position') !== 'fixed') {
|
194 | _util.dom.setStyle(pinElement, 'position', 'absolute');
|
195 | isPinFixed = false;
|
196 | } else {
|
197 | isPinFixed = true;
|
198 | }
|
199 | if (baseElement === VIEWPORT || _util.dom.getStyle(baseElement, 'position') !== 'fixed') {
|
200 | isBaseFixed = false;
|
201 | } else {
|
202 | isBaseFixed = true;
|
203 | }
|
204 |
|
205 |
|
206 | for (var i = 0; i < expectedAlign.length; i++) {
|
207 | var align = expectedAlign[i];
|
208 | var pinElementPoints = this._normalizePosition(pinElement, align.split(' ')[0], isPinFixed);
|
209 | var baseElementPoints = this._normalizePosition(baseElement, align.split(' ')[1],
|
210 |
|
211 | isPinFixed && !pinFollowBaseElementWhenFixed);
|
212 |
|
213 | var pinElementParentOffset = this._getParentOffset(pinElement);
|
214 | var pinElementParentScrollOffset = this._getParentScrollOffset(pinElement);
|
215 |
|
216 | var baseElementOffset = isPinFixed && isBaseFixed ? this._getLeftTop(baseElement) :
|
217 | baseElementPoints.offset(isPinFixed && pinFollowBaseElementWhenFixed);
|
218 | var top = baseElementOffset.top + baseElementPoints.y - pinElementParentOffset.top - pinElementPoints.y + pinElementParentScrollOffset.top;
|
219 | var left = baseElementOffset.left + baseElementPoints.x - pinElementParentOffset.left - pinElementPoints.x + pinElementParentScrollOffset.left;
|
220 |
|
221 | this._setPinElementPostion(pinElement, { left: left, top: top }, this.offset);
|
222 |
|
223 | if (this._isInViewport(pinElement, align)) {
|
224 | return align;
|
225 | } else if (!firstPositionResult) {
|
226 | if (this.needAdjust && !this.autoFit) {
|
227 | var _getViewportOffset2 = this._getViewportOffset(pinElement, align),
|
228 | right = _getViewportOffset2.right;
|
229 |
|
230 | firstPositionResult = {
|
231 | left: right < 0 ? left + right : left,
|
232 | top: top
|
233 | };
|
234 | } else {
|
235 | firstPositionResult = { left: left, top: top };
|
236 | }
|
237 | }
|
238 | }
|
239 |
|
240 |
|
241 | var inViewportLeft = this._makeElementInViewport(pinElement, firstPositionResult.left, 'Left', isPinFixed);
|
242 | var inViewportTop = this._makeElementInViewport(pinElement, firstPositionResult.top, 'Top', isPinFixed);
|
243 |
|
244 | this._setPinElementPostion(pinElement, { left: inViewportLeft, top: inViewportTop }, this._calPinOffset(expectedAlign[0]));
|
245 |
|
246 | return expectedAlign[0];
|
247 | };
|
248 |
|
249 | Position.prototype._getParentOffset = function _getParentOffset(element) {
|
250 | var parent = element.offsetParent || document.documentElement;
|
251 | var offset = void 0;
|
252 | if (parent === document.body && _util.dom.getStyle(parent, 'position') === 'static') {
|
253 | offset = {
|
254 | top: 0,
|
255 | left: 0
|
256 | };
|
257 | } else {
|
258 | offset = this._getElementOffset(parent);
|
259 | }
|
260 |
|
261 | offset.top += parseFloat(_util.dom.getStyle(parent, 'border-top-width'), 10);
|
262 | offset.left += parseFloat(_util.dom.getStyle(parent, 'border-left-width'), 10);
|
263 | offset.offsetParent = parent;
|
264 | return offset;
|
265 | };
|
266 |
|
267 | Position.prototype._makeElementInViewport = function _makeElementInViewport(pinElement, number, type, isPinFixed) {
|
268 |
|
269 |
|
270 | var result = number;
|
271 | var docElement = document.documentElement;
|
272 | var offsetParent = pinElement.offsetParent || document.documentElement;
|
273 |
|
274 | if (result < 0) {
|
275 | if (isPinFixed) {
|
276 | result = 0;
|
277 | } else if (offsetParent === document.body && _util.dom.getStyle(offsetParent, 'position') === 'static') {
|
278 |
|
279 | result = Math.max(docElement['scroll' + type], document.body['scroll' + type]);
|
280 | }
|
281 | }
|
282 | return result;
|
283 | };
|
284 |
|
285 |
|
286 |
|
287 |
|
288 | Position.prototype._normalizePosition = function _normalizePosition(element, align, ignoreElementOffset) {
|
289 | var points = this._normalizeElement(element, ignoreElementOffset);
|
290 | this._normalizeXY(points, align);
|
291 |
|
292 | return points;
|
293 | };
|
294 |
|
295 | Position.prototype._normalizeXY = function _normalizeXY(points, align) {
|
296 | var x = align.split('')[1];
|
297 | var y = align.split('')[0];
|
298 |
|
299 | points.x = this._xyConverter(x, points, 'width');
|
300 | points.y = this._xyConverter(y, points, 'height');
|
301 |
|
302 | return points;
|
303 | };
|
304 |
|
305 | Position.prototype._xyConverter = function _xyConverter(align, points, type) {
|
306 | var res = align.replace(/t|l/gi, '0%').replace(/c/gi, '50%').replace(/b|r/gi, '100%').replace(/(\d+)%/gi, function (m, d) {
|
307 | return points.size()[type] * (d / 100);
|
308 | });
|
309 |
|
310 | return parseFloat(res, 10) || 0;
|
311 | };
|
312 |
|
313 | Position.prototype._getLeftTop = function _getLeftTop(element) {
|
314 | return {
|
315 | left: parseFloat(_util.dom.getStyle(element, 'left')) || 0,
|
316 | top: parseFloat(_util.dom.getStyle(element, 'top')) || 0
|
317 | };
|
318 | };
|
319 |
|
320 | Position.prototype._normalizeElement = function _normalizeElement(element, ignoreElementOffset) {
|
321 | var _this = this;
|
322 |
|
323 | var result = {
|
324 | element: element,
|
325 | x: 0,
|
326 | y: 0
|
327 | },
|
328 | isViewport = element === VIEWPORT,
|
329 | docElement = document.documentElement;
|
330 |
|
331 | result.offset = function (ignoreScroll) {
|
332 |
|
333 | if (ignoreElementOffset) {
|
334 | return {
|
335 | left: 0,
|
336 | top: 0
|
337 | };
|
338 | } else if (isViewport) {
|
339 | return {
|
340 | left: getPageX(),
|
341 | top: getPageY()
|
342 | };
|
343 | } else {
|
344 | return _this._getElementOffset(element, ignoreScroll);
|
345 | }
|
346 | };
|
347 |
|
348 | result.size = function () {
|
349 | if (isViewport) {
|
350 | return {
|
351 | width: docElement.clientWidth,
|
352 | height: docElement.clientHeight
|
353 | };
|
354 | } else {
|
355 | return _getSize(element);
|
356 | }
|
357 | };
|
358 |
|
359 | return result;
|
360 | };
|
361 |
|
362 |
|
363 |
|
364 |
|
365 |
|
366 | Position.prototype._getElementOffset = function _getElementOffset(element, ignoreScroll) {
|
367 | var rect = element.getBoundingClientRect();
|
368 | var docElement = document.documentElement;
|
369 | var body = document.body;
|
370 | var docClientLeft = docElement.clientLeft || body.clientLeft || 0;
|
371 | var docClientTop = docElement.clientTop || body.clientTop || 0;
|
372 |
|
373 | return {
|
374 | left: rect.left + (ignoreScroll ? 0 : getPageX()) - docClientLeft,
|
375 | top: rect.top + (ignoreScroll ? 0 : getPageY()) - docClientTop
|
376 | };
|
377 | };
|
378 |
|
379 |
|
380 |
|
381 |
|
382 | Position.prototype._getExpectedAlign = function _getExpectedAlign() {
|
383 | var align = this.isRtl ? this._replaceAlignDir(this.align, /l|r/g, { l: 'r', r: 'l' }) : this.align;
|
384 | var expectedAlign = [align];
|
385 | if (this.needAdjust) {
|
386 | if (/t|b/g.test(align)) {
|
387 | expectedAlign.push(this._replaceAlignDir(align, /t|b/g, { t: 'b', b: 't' }));
|
388 | }
|
389 | if (/l|r/g.test(align)) {
|
390 | expectedAlign.push(this._replaceAlignDir(align, /l|r/g, { l: 'r', r: 'l' }));
|
391 | }
|
392 | if (/c/g.test(align)) {
|
393 | expectedAlign.push(this._replaceAlignDir(align, /c(?= |$)/g, { c: 'l' }));
|
394 | expectedAlign.push(this._replaceAlignDir(align, /c(?= |$)/g, { c: 'r' }));
|
395 | }
|
396 | expectedAlign.push(this._replaceAlignDir(align, /l|r|t|b/g, {
|
397 | l: 'r',
|
398 | r: 'l',
|
399 | t: 'b',
|
400 | b: 't'
|
401 | }));
|
402 | }
|
403 | return expectedAlign;
|
404 | };
|
405 |
|
406 |
|
407 |
|
408 |
|
409 | Position.prototype._replaceAlignDir = function _replaceAlignDir(align, regExp, map) {
|
410 | return align.replace(regExp, function (res) {
|
411 | return map[res];
|
412 | });
|
413 | };
|
414 |
|
415 |
|
416 |
|
417 |
|
418 | Position.prototype._isRightAligned = function _isRightAligned(align) {
|
419 | var _align$split = align.split(' '),
|
420 | pinAlign = _align$split[0],
|
421 | baseAlign = _align$split[1];
|
422 |
|
423 | return pinAlign[1] === 'r' && pinAlign[1] === baseAlign[1];
|
424 | };
|
425 |
|
426 |
|
427 |
|
428 |
|
429 | Position.prototype._isBottomAligned = function _isBottomAligned(align) {
|
430 | var _align$split2 = align.split(' '),
|
431 | pinAlign = _align$split2[0],
|
432 | baseAlign = _align$split2[1];
|
433 |
|
434 | return pinAlign[0] === 'b' && pinAlign[0] === baseAlign[0];
|
435 | };
|
436 |
|
437 |
|
438 |
|
439 |
|
440 | Position.prototype._isInViewport = function _isInViewport(element, align) {
|
441 | var viewportSize = _getViewportSize(this.container);
|
442 | var elementRect = _getElementRect(element, this.container);
|
443 | var elementSize = _getSize(element);
|
444 |
|
445 |
|
446 |
|
447 |
|
448 | var viewportWidth = this._isRightAligned(align) ? viewportSize.width : viewportSize.width - 1;
|
449 | var viewportHeight = this._isBottomAligned(align) ? viewportSize.height : viewportSize.height - 1;
|
450 |
|
451 |
|
452 |
|
453 | if (this.autoFit) {
|
454 | return elementRect.top >= 0 && elementRect.top + element.offsetHeight <= viewportHeight;
|
455 | }
|
456 |
|
457 |
|
458 | return elementRect.left >= 0 && elementRect.left + elementSize.width <= viewportWidth && elementRect.top >= 0 && elementRect.top + elementSize.height <= viewportHeight;
|
459 | };
|
460 |
|
461 | Position.prototype._getViewportOffset = function _getViewportOffset(element, align) {
|
462 | var viewportSize = _getViewportSize(this.container);
|
463 | var elementRect = _getElementRect(element, this.container);
|
464 | var elementSize = _getSize(element);
|
465 |
|
466 | var viewportWidth = this._isRightAligned(align) ? viewportSize.width : viewportSize.width - 1;
|
467 | var viewportHeight = this._isBottomAligned(align) ? viewportSize.height : viewportSize.height - 1;
|
468 |
|
469 | return {
|
470 | top: elementRect.top,
|
471 | right: viewportWidth - (elementRect.left + elementSize.width),
|
472 | bottom: viewportHeight - (elementRect.top + elementSize.height),
|
473 | left: elementRect.left
|
474 | };
|
475 | };
|
476 |
|
477 |
|
478 |
|
479 |
|
480 | Position.prototype._setPinElementPostion = function _setPinElementPostion(pinElement, postion) {
|
481 | var offset = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [0, 0];
|
482 | var top = postion.top,
|
483 | left = postion.left;
|
484 |
|
485 | if (!this.isRtl) {
|
486 | _util.dom.setStyle(pinElement, {
|
487 | left: left + offset[0] + 'px',
|
488 | top: top + offset[1] + 'px'
|
489 | });
|
490 | return;
|
491 | }
|
492 |
|
493 |
|
494 | var pinElementParentOffset = this._getParentOffset(pinElement);
|
495 |
|
496 | var _getElementRect2 = _getElementRect(pinElementParentOffset.offsetParent),
|
497 | offsetParentWidth = _getElementRect2.width;
|
498 |
|
499 | var _getElementRect3 = _getElementRect(pinElement),
|
500 | width = _getElementRect3.width;
|
501 |
|
502 | var right = offsetParentWidth - (left + width);
|
503 | _util.dom.setStyle(pinElement, {
|
504 | left: 'auto',
|
505 | right: right + offset[0] + 'px',
|
506 | top: top + offset[1] + 'px'
|
507 | });
|
508 | };
|
509 |
|
510 | return Position;
|
511 | }(), _class.VIEWPORT = VIEWPORT, _class.place = function (props) {
|
512 | return new Position(props).setPosition();
|
513 | }, _initialiseProps = function _initialiseProps() {
|
514 | var _this2 = this;
|
515 |
|
516 | this._calPinOffset = function (align) {
|
517 | var offset = [].concat(_this2.offset);
|
518 |
|
519 | if (_this2.autoFit && align && _this2.container && _this2.container !== document.body) {
|
520 | var baseElementRect = _getElementRect(_this2.baseElement, _this2.container);
|
521 | var pinElementRect = _getElementRect(_this2.pinElement, _this2.container);
|
522 | var viewportSize = _getViewportSize(_this2.container);
|
523 | var pinAlign = align.split(' ')[0];
|
524 | var x = pinAlign.charAt(1);
|
525 | var y = pinAlign.charAt(0);
|
526 |
|
527 | if (pinElementRect.top < 0 || pinElementRect.top + pinElementRect.height > viewportSize.height) {
|
528 | offset[1] = -baseElementRect.top - (y === 't' ? baseElementRect.height : 0);
|
529 | }
|
530 | }
|
531 | return offset;
|
532 | };
|
533 |
|
534 | this._getParentScrollOffset = function (elem) {
|
535 | var top = 0;
|
536 | var left = 0;
|
537 |
|
538 | if (elem && elem.offsetParent && elem.offsetParent !== document.body) {
|
539 | if (!isNaN(elem.offsetParent.scrollTop)) {
|
540 | top += elem.offsetParent.scrollTop;
|
541 | }
|
542 | if (!isNaN(elem.offsetParent.scrollLeft)) {
|
543 | left += elem.offsetParent.scrollLeft;
|
544 | }
|
545 | }
|
546 |
|
547 | return {
|
548 | top: top,
|
549 | left: left
|
550 | };
|
551 | };
|
552 | }, _temp);
|
553 | exports.default = Position;
|
554 | module.exports = exports['default']; |
\ | No newline at end of file |