PluginProbe
UsersWP – Front-end login form, User Registration, User Profile & Members Directory plugin for WP / 1.2.75
UsersWP – Front-end login form, User Registration, User Profile & Members Directory plugin for WP v1.2.75
1.2.76 1.2.75 1.2.74 1.2.73 1.2.72 1.2.71 1.2.70 1.2.69 1.2.68 1.2.67 1.2.66 1.2.65 1.2.64 1.2.63 trunk 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.16 1.0.17 1.0.18 1.0.19 All 176 releases
userswp / vendor / ayecode / wp-ayecode-ui / assets / js / popper.js

popper.js in UsersWP – Front-end login form, User Registration, User Profile & Members Directory plugin for WP 1.2.75, at vendor/ayecode/wp-ayecode-ui/assets/js/popper.js

2,590 lines 85.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**!
2 * @fileOverview Kickass library to create and place poppers near their reference elements.
3 * @version 1.14.7
4 * @license
5 * Copyright (c) 2016 Federico Zivolo and contributors
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in all
15 * copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 */
25 (function (global, factory) {
26 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
27 typeof define === 'function' && define.amd ? define(factory) :
28 (global.Popper = factory());
29 }(this, (function () { 'use strict';
30
31 var isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined';
32
33 var longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox'];
34 var timeoutDuration = 0;
35 for (var i = 0; i < longerTimeoutBrowsers.length; i += 1) {
36 if (isBrowser && navigator.userAgent.indexOf(longerTimeoutBrowsers[i]) >= 0) {
37 timeoutDuration = 1;
38 break;
39 }
40 }
41
42 function microtaskDebounce(fn) {
43 var called = false;
44 return function () {
45 if (called) {
46 return;
47 }
48 called = true;
49 window.Promise.resolve().then(function () {
50 called = false;
51 fn();
52 });
53 };
54 }
55
56 function taskDebounce(fn) {
57 var scheduled = false;
58 return function () {
59 if (!scheduled) {
60 scheduled = true;
61 setTimeout(function () {
62 scheduled = false;
63 fn();
64 }, timeoutDuration);
65 }
66 };
67 }
68
69 var supportsMicroTasks = isBrowser && window.Promise;
70
71 /**
72 * Create a debounced version of a method, that's asynchronously deferred
73 * but called in the minimum time possible.
74 *
75 * @method
76 * @memberof Popper.Utils
77 * @argument {Function} fn
78 * @returns {Function}
79 */
80 var debounce = supportsMicroTasks ? microtaskDebounce : taskDebounce;
81
82 /**
83 * Check if the given variable is a function
84 * @method
85 * @memberof Popper.Utils
86 * @argument {Any} functionToCheck - variable to check
87 * @returns {Boolean} answer to: is a function?
88 */
89 function isFunction(functionToCheck) {
90 var getType = {};
91 return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
92 }
93
94 /**
95 * Get CSS computed property of the given element
96 * @method
97 * @memberof Popper.Utils
98 * @argument {Eement} element
99 * @argument {String} property
100 */
101 function getStyleComputedProperty(element, property) {
102 if (element.nodeType !== 1) {
103 return [];
104 }
105 // NOTE: 1 DOM access here
106 var window = element.ownerDocument.defaultView;
107 var css = window.getComputedStyle(element, null);
108 return property ? css[property] : css;
109 }
110
111 /**
112 * Returns the parentNode or the host of the element
113 * @method
114 * @memberof Popper.Utils
115 * @argument {Element} element
116 * @returns {Element} parent
117 */
118 function getParentNode(element) {
119 if (element.nodeName === 'HTML') {
120 return element;
121 }
122 return element.parentNode || element.host;
123 }
124
125 /**
126 * Returns the scrolling parent of the given element
127 * @method
128 * @memberof Popper.Utils
129 * @argument {Element} element
130 * @returns {Element} scroll parent
131 */
132 function getScrollParent(element) {
133 // Return body, `getScroll` will take care to get the correct `scrollTop` from it
134 if (!element) {
135 return document.body;
136 }
137
138 switch (element.nodeName) {
139 case 'HTML':
140 case 'BODY':
141 return element.ownerDocument.body;
142 case '#document':
143 return element.body;
144 }
145
146 // Firefox want us to check `-x` and `-y` variations as well
147
148 var _getStyleComputedProp = getStyleComputedProperty(element),
149 overflow = _getStyleComputedProp.overflow,
150 overflowX = _getStyleComputedProp.overflowX,
151 overflowY = _getStyleComputedProp.overflowY;
152
153 if (/(auto|scroll|overlay)/.test(overflow + overflowY + overflowX)) {
154 return element;
155 }
156
157 return getScrollParent(getParentNode(element));
158 }
159
160 var isIE11 = isBrowser && !!(window.MSInputMethodContext && document.documentMode);
161 var isIE10 = isBrowser && /MSIE 10/.test(navigator.userAgent);
162
163 /**
164 * Determines if the browser is Internet Explorer
165 * @method
166 * @memberof Popper.Utils
167 * @param {Number} version to check
168 * @returns {Boolean} isIE
169 */
170 function isIE(version) {
171 if (version === 11) {
172 return isIE11;
173 }
174 if (version === 10) {
175 return isIE10;
176 }
177 return isIE11 || isIE10;
178 }
179
180 /**
181 * Returns the offset parent of the given element
182 * @method
183 * @memberof Popper.Utils
184 * @argument {Element} element
185 * @returns {Element} offset parent
186 */
187 function getOffsetParent(element) {
188 if (!element) {
189 return document.documentElement;
190 }
191
192 var noOffsetParent = isIE(10) ? document.body : null;
193
194 // NOTE: 1 DOM access here
195 var offsetParent = element.offsetParent || null;
196 // Skip hidden elements which don't have an offsetParent
197 while (offsetParent === noOffsetParent && element.nextElementSibling) {
198 offsetParent = (element = element.nextElementSibling).offsetParent;
199 }
200
201 var nodeName = offsetParent && offsetParent.nodeName;
202
203 if (!nodeName || nodeName === 'BODY' || nodeName === 'HTML') {
204 return element ? element.ownerDocument.documentElement : document.documentElement;
205 }
206
207 // .offsetParent will return the closest TH, TD or TABLE in case
208 // no offsetParent is present, I hate this job...
209 if (['TH', 'TD', 'TABLE'].indexOf(offsetParent.nodeName) !== -1 && getStyleComputedProperty(offsetParent, 'position') === 'static') {
210 return getOffsetParent(offsetParent);
211 }
212
213 return offsetParent;
214 }
215
216 function isOffsetContainer(element) {
217 var nodeName = element.nodeName;
218
219 if (nodeName === 'BODY') {
220 return false;
221 }
222 return nodeName === 'HTML' || getOffsetParent(element.firstElementChild) === element;
223 }
224
225 /**
226 * Finds the root node (document, shadowDOM root) of the given element
227 * @method
228 * @memberof Popper.Utils
229 * @argument {Element} node
230 * @returns {Element} root node
231 */
232 function getRoot(node) {
233 if (node.parentNode !== null) {
234 return getRoot(node.parentNode);
235 }
236
237 return node;
238 }
239
240 /**
241 * Finds the offset parent common to the two provided nodes
242 * @method
243 * @memberof Popper.Utils
244 * @argument {Element} element1
245 * @argument {Element} element2
246 * @returns {Element} common offset parent
247 */
248 function findCommonOffsetParent(element1, element2) {
249 // This check is needed to avoid errors in case one of the elements isn't defined for any reason
250 if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) {
251 return document.documentElement;
252 }
253
254 // Here we make sure to give as "start" the element that comes first in the DOM
255 var order = element1.compareDocumentPosition(element2) & Node.DOCUMENT_POSITION_FOLLOWING;
256 var start = order ? element1 : element2;
257 var end = order ? element2 : element1;
258
259 // Get common ancestor container
260 var range = document.createRange();
261 range.setStart(start, 0);
262 range.setEnd(end, 0);
263 var commonAncestorContainer = range.commonAncestorContainer;
264
265 // Both nodes are inside #document
266
267 if (element1 !== commonAncestorContainer && element2 !== commonAncestorContainer || start.contains(end)) {
268 if (isOffsetContainer(commonAncestorContainer)) {
269 return commonAncestorContainer;
270 }
271
272 return getOffsetParent(commonAncestorContainer);
273 }
274
275 // one of the nodes is inside shadowDOM, find which one
276 var element1root = getRoot(element1);
277 if (element1root.host) {
278 return findCommonOffsetParent(element1root.host, element2);
279 } else {
280 return findCommonOffsetParent(element1, getRoot(element2).host);
281 }
282 }
283
284 /**
285 * Gets the scroll value of the given element in the given side (top and left)
286 * @method
287 * @memberof Popper.Utils
288 * @argument {Element} element
289 * @argument {String} side `top` or `left`
290 * @returns {number} amount of scrolled pixels
291 */
292 function getScroll(element) {
293 var side = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'top';
294
295 var upperSide = side === 'top' ? 'scrollTop' : 'scrollLeft';
296 var nodeName = element.nodeName;
297
298 if (nodeName === 'BODY' || nodeName === 'HTML') {
299 var html = element.ownerDocument.documentElement;
300 var scrollingElement = element.ownerDocument.scrollingElement || html;
301 return scrollingElement[upperSide];
302 }
303
304 return element[upperSide];
305 }
306
307 /*
308 * Sum or subtract the element scroll values (left and top) from a given rect object
309 * @method
310 * @memberof Popper.Utils
311 * @param {Object} rect - Rect object you want to change
312 * @param {HTMLElement} element - The element from the function reads the scroll values
313 * @param {Boolean} subtract - set to true if you want to subtract the scroll values
314 * @return {Object} rect - The modifier rect object
315 */
316 function includeScroll(rect, element) {
317 var subtract = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
318
319 var scrollTop = getScroll(element, 'top');
320 var scrollLeft = getScroll(element, 'left');
321 var modifier = subtract ? -1 : 1;
322 rect.top += scrollTop * modifier;
323 rect.bottom += scrollTop * modifier;
324 rect.left += scrollLeft * modifier;
325 rect.right += scrollLeft * modifier;
326 return rect;
327 }
328
329 /*
330 * Helper to detect borders of a given element
331 * @method
332 * @memberof Popper.Utils
333 * @param {CSSStyleDeclaration} styles
334 * Result of `getStyleComputedProperty` on the given element
335 * @param {String} axis - `x` or `y`
336 * @return {number} borders - The borders size of the given axis
337 */
338
339 function getBordersSize(styles, axis) {
340 var sideA = axis === 'x' ? 'Left' : 'Top';
341 var sideB = sideA === 'Left' ? 'Right' : 'Bottom';
342
343 return parseFloat(styles['border' + sideA + 'Width'], 10) + parseFloat(styles['border' + sideB + 'Width'], 10);
344 }
345
346 function getSize(axis, body, html, computedStyle) {
347 return Math.max(body['offset' + axis], body['scroll' + axis], html['client' + axis], html['offset' + axis], html['scroll' + axis], isIE(10) ? parseInt(html['offset' + axis]) + parseInt(computedStyle['margin' + (axis === 'Height' ? 'Top' : 'Left')]) + parseInt(computedStyle['margin' + (axis === 'Height' ? 'Bottom' : 'Right')]) : 0);
348 }
349
350 function getWindowSizes(document) {
351 var body = document.body;
352 var html = document.documentElement;
353 var computedStyle = isIE(10) && getComputedStyle(html);
354
355 return {
356 height: getSize('Height', body, html, computedStyle),
357 width: getSize('Width', body, html, computedStyle)
358 };
359 }
360
361 var classCallCheck = function (instance, Constructor) {
362 if (!(instance instanceof Constructor)) {
363 throw new TypeError("Cannot call a class as a function");
364 }
365 };
366
367 var createClass = function () {
368 function defineProperties(target, props) {
369 for (var i = 0; i < props.length; i++) {
370 var descriptor = props[i];
371 descriptor.enumerable = descriptor.enumerable || false;
372 descriptor.configurable = true;
373 if ("value" in descriptor) descriptor.writable = true;
374 Object.defineProperty(target, descriptor.key, descriptor);
375 }
376 }
377
378 return function (Constructor, protoProps, staticProps) {
379 if (protoProps) defineProperties(Constructor.prototype, protoProps);
380 if (staticProps) defineProperties(Constructor, staticProps);
381 return Constructor;
382 };
383 }();
384
385
386
387
388
389 var defineProperty = function (obj, key, value) {
390 if (key in obj) {
391 Object.defineProperty(obj, key, {
392 value: value,
393 enumerable: true,
394 configurable: true,
395 writable: true
396 });
397 } else {
398 obj[key] = value;
399 }
400
401 return obj;
402 };
403
404 var _extends = Object.assign || function (target) {
405 for (var i = 1; i < arguments.length; i++) {
406 var source = arguments[i];
407
408 for (var key in source) {
409 if (Object.prototype.hasOwnProperty.call(source, key)) {
410 target[key] = source[key];
411 }
412 }
413 }
414
415 return target;
416 };
417
418 /**
419 * Given element offsets, generate an output similar to getBoundingClientRect
420 * @method
421 * @memberof Popper.Utils
422 * @argument {Object} offsets
423 * @returns {Object} ClientRect like output
424 */
425 function getClientRect(offsets) {
426 return _extends({}, offsets, {
427 right: offsets.left + offsets.width,
428 bottom: offsets.top + offsets.height
429 });
430 }
431
432 /**
433 * Get bounding client rect of given element
434 * @method
435 * @memberof Popper.Utils
436 * @param {HTMLElement} element
437 * @return {Object} client rect
438 */
439 function getBoundingClientRect(element) {
440 var rect = {};
441
442 // IE10 10 FIX: Please, don't ask, the element isn't
443 // considered in DOM in some circumstances...
444 // This isn't reproducible in IE10 compatibility mode of IE11
445 try {
446 if (isIE(10)) {
447 rect = element.getBoundingClientRect();
448 var scrollTop = getScroll(element, 'top');
449 var scrollLeft = getScroll(element, 'left');
450 rect.top += scrollTop;
451 rect.left += scrollLeft;
452 rect.bottom += scrollTop;
453 rect.right += scrollLeft;
454 } else {
455 rect = element.getBoundingClientRect();
456 }
457 } catch (e) {}
458
459 var result = {
460 left: rect.left,
461 top: rect.top,
462 width: rect.right - rect.left,
463 height: rect.bottom - rect.top
464 };
465
466 // subtract scrollbar size from sizes
467 var sizes = element.nodeName === 'HTML' ? getWindowSizes(element.ownerDocument) : {};
468 var width = sizes.width || element.clientWidth || result.right - result.left;
469 var height = sizes.height || element.clientHeight || result.bottom - result.top;
470
471 var horizScrollbar = element.offsetWidth - width;
472 var vertScrollbar = element.offsetHeight - height;
473
474 // if an hypothetical scrollbar is detected, we must be sure it's not a `border`
475 // we make this check conditional for performance reasons
476 if (horizScrollbar || vertScrollbar) {
477 var styles = getStyleComputedProperty(element);
478 horizScrollbar -= getBordersSize(styles, 'x');
479 vertScrollbar -= getBordersSize(styles, 'y');
480
481 result.width -= horizScrollbar;
482 result.height -= vertScrollbar;
483 }
484
485 return getClientRect(result);
486 }
487
488 function getOffsetRectRelativeToArbitraryNode(children, parent) {
489 var fixedPosition = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
490
491 var isIE10 = isIE(10);
492 var isHTML = parent.nodeName === 'HTML';
493 var childrenRect = getBoundingClientRect(children);
494 var parentRect = getBoundingClientRect(parent);
495 var scrollParent = getScrollParent(children);
496
497 var styles = getStyleComputedProperty(parent);
498 var borderTopWidth = parseFloat(styles.borderTopWidth, 10);
499 var borderLeftWidth = parseFloat(styles.borderLeftWidth, 10);
500
501 // In cases where the parent is fixed, we must ignore negative scroll in offset calc
502 if (fixedPosition && isHTML) {
503 parentRect.top = Math.max(parentRect.top, 0);
504 parentRect.left = Math.max(parentRect.left, 0);
505 }
506 var offsets = getClientRect({
507 top: childrenRect.top - parentRect.top - borderTopWidth,
508 left: childrenRect.left - parentRect.left - borderLeftWidth,
509 width: childrenRect.width,
510 height: childrenRect.height
511 });
512 offsets.marginTop = 0;
513 offsets.marginLeft = 0;
514
515 // Subtract margins of documentElement in case it's being used as parent
516 // we do this only on HTML because it's the only element that behaves
517 // differently when margins are applied to it. The margins are included in
518 // the box of the documentElement, in the other cases not.
519 if (!isIE10 && isHTML) {
520 var marginTop = parseFloat(styles.marginTop, 10);
521 var marginLeft = parseFloat(styles.marginLeft, 10);
522
523 offsets.top -= borderTopWidth - marginTop;
524 offsets.bottom -= borderTopWidth - marginTop;
525 offsets.left -= borderLeftWidth - marginLeft;
526 offsets.right -= borderLeftWidth - marginLeft;
527
528 // Attach marginTop and marginLeft because in some circumstances we may need them
529 offsets.marginTop = marginTop;
530 offsets.marginLeft = marginLeft;
531 }
532
533 if (isIE10 && !fixedPosition ? parent.contains(scrollParent) : parent === scrollParent && scrollParent.nodeName !== 'BODY') {
534 offsets = includeScroll(offsets, parent);
535 }
536
537 return offsets;
538 }
539
540 function getViewportOffsetRectRelativeToArtbitraryNode(element) {
541 var excludeScroll = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
542
543 var html = element.ownerDocument.documentElement;
544 var relativeOffset = getOffsetRectRelativeToArbitraryNode(element, html);
545 var width = Math.max(html.clientWidth, window.innerWidth || 0);
546 var height = Math.max(html.clientHeight, window.innerHeight || 0);
547
548 var scrollTop = !excludeScroll ? getScroll(html) : 0;
549 var scrollLeft = !excludeScroll ? getScroll(html, 'left') : 0;
550
551 var offset = {
552 top: scrollTop - relativeOffset.top + relativeOffset.marginTop,
553 left: scrollLeft - relativeOffset.left + relativeOffset.marginLeft,
554 width: width,
555 height: height
556 };
557
558 return getClientRect(offset);
559 }
560
561 /**
562 * Check if the given element is fixed or is inside a fixed parent
563 * @method
564 * @memberof Popper.Utils
565 * @argument {Element} element
566 * @argument {Element} customContainer
567 * @returns {Boolean} answer to "isFixed?"
568 */
569 function isFixed(element) {
570 var nodeName = element.nodeName;
571 if (nodeName === 'BODY' || nodeName === 'HTML') {
572 return false;
573 }
574 if (getStyleComputedProperty(element, 'position') === 'fixed') {
575 return true;
576 }
577 var parentNode = getParentNode(element);
578 if (!parentNode) {
579 return false;
580 }
581 return isFixed(parentNode);
582 }
583
584 /**
585 * Finds the first parent of an element that has a transformed property defined
586 * @method
587 * @memberof Popper.Utils
588 * @argument {Element} element
589 * @returns {Element} first transformed parent or documentElement
590 */
591
592 function getFixedPositionOffsetParent(element) {
593 // This check is needed to avoid errors in case one of the elements isn't defined for any reason
594 if (!element || !element.parentElement || isIE()) {
595 return document.documentElement;
596 }
597 var el = element.parentElement;
598 while (el && getStyleComputedProperty(el, 'transform') === 'none') {
599 el = el.parentElement;
600 }
601 return el || document.documentElement;
602 }
603
604 /**
605 * Computed the boundaries limits and return them
606 * @method
607 * @memberof Popper.Utils
608 * @param {HTMLElement} popper
609 * @param {HTMLElement} reference
610 * @param {number} padding
611 * @param {HTMLElement} boundariesElement - Element used to define the boundaries
612 * @param {Boolean} fixedPosition - Is in fixed position mode
613 * @returns {Object} Coordinates of the boundaries
614 */
615 function getBoundaries(popper, reference, padding, boundariesElement) {
616 var fixedPosition = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
617
618 // NOTE: 1 DOM access here
619
620 var boundaries = { top: 0, left: 0 };
621 var offsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, reference);
622
623 // Handle viewport case
624 if (boundariesElement === 'viewport') {
625 boundaries = getViewportOffsetRectRelativeToArtbitraryNode(offsetParent, fixedPosition);
626 } else {
627 // Handle other cases based on DOM element used as boundaries
628 var boundariesNode = void 0;
629 if (boundariesElement === 'scrollParent') {
630 boundariesNode = getScrollParent(getParentNode(reference));
631 if (boundariesNode.nodeName === 'BODY') {
632 boundariesNode = popper.ownerDocument.documentElement;
633 }
634 } else if (boundariesElement === 'window') {
635 boundariesNode = popper.ownerDocument.documentElement;
636 } else {
637 boundariesNode = boundariesElement;
638 }
639
640 var offsets = getOffsetRectRelativeToArbitraryNode(boundariesNode, offsetParent, fixedPosition);
641
642 // In case of HTML, we need a different computation
643 if (boundariesNode.nodeName === 'HTML' && !isFixed(offsetParent)) {
644 var _getWindowSizes = getWindowSizes(popper.ownerDocument),
645 height = _getWindowSizes.height,
646 width = _getWindowSizes.width;
647
648 boundaries.top += offsets.top - offsets.marginTop;
649 boundaries.bottom = height + offsets.top;
650 boundaries.left += offsets.left - offsets.marginLeft;
651 boundaries.right = width + offsets.left;
652 } else {
653 // for all the other DOM elements, this one is good
654 boundaries = offsets;
655 }
656 }
657
658 // Add paddings
659 padding = padding || 0;
660 var isPaddingNumber = typeof padding === 'number';
661 boundaries.left += isPaddingNumber ? padding : padding.left || 0;
662 boundaries.top += isPaddingNumber ? padding : padding.top || 0;
663 boundaries.right -= isPaddingNumber ? padding : padding.right || 0;
664 boundaries.bottom -= isPaddingNumber ? padding : padding.bottom || 0;
665
666 return boundaries;
667 }
668
669 function getArea(_ref) {
670 var width = _ref.width,
671 height = _ref.height;
672
673 return width * height;
674 }
675
676 /**
677 * Utility used to transform the `auto` placement to the placement with more
678 * available space.
679 * @method
680 * @memberof Popper.Utils
681 * @argument {Object} data - The data object generated by update method
682 * @argument {Object} options - Modifiers configuration and options
683 * @returns {Object} The data object, properly modified
684 */
685 function computeAutoPlacement(placement, refRect, popper, reference, boundariesElement) {
686 var padding = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0;
687
688 if (placement.indexOf('auto') === -1) {
689 return placement;
690 }
691
692 var boundaries = getBoundaries(popper, reference, padding, boundariesElement);
693
694 var rects = {
695 top: {
696 width: boundaries.width,
697 height: refRect.top - boundaries.top
698 },
699 right: {
700 width: boundaries.right - refRect.right,
701 height: boundaries.height
702 },
703 bottom: {
704 width: boundaries.width,
705 height: boundaries.bottom - refRect.bottom
706 },
707 left: {
708 width: refRect.left - boundaries.left,
709 height: boundaries.height
710 }
711 };
712
713 var sortedAreas = Object.keys(rects).map(function (key) {
714 return _extends({
715 key: key
716 }, rects[key], {
717 area: getArea(rects[key])
718 });
719 }).sort(function (a, b) {
720 return b.area - a.area;
721 });
722
723 var filteredAreas = sortedAreas.filter(function (_ref2) {
724 var width = _ref2.width,
725 height = _ref2.height;
726 return width >= popper.clientWidth && height >= popper.clientHeight;
727 });
728
729 var computedPlacement = filteredAreas.length > 0 ? filteredAreas[0].key : sortedAreas[0].key;
730
731 var variation = placement.split('-')[1];
732
733 return computedPlacement + (variation ? '-' + variation : '');
734 }
735
736 /**
737 * Get offsets to the reference element
738 * @method
739 * @memberof Popper.Utils
740 * @param {Object} state
741 * @param {Element} popper - the popper element
742 * @param {Element} reference - the reference element (the popper will be relative to this)
743 * @param {Element} fixedPosition - is in fixed position mode
744 * @returns {Object} An object containing the offsets which will be applied to the popper
745 */
746 function getReferenceOffsets(state, popper, reference) {
747 var fixedPosition = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
748
749 var commonOffsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, reference);
750 return getOffsetRectRelativeToArbitraryNode(reference, commonOffsetParent, fixedPosition);
751 }
752
753 /**
754 * Get the outer sizes of the given element (offset size + margins)
755 * @method
756 * @memberof Popper.Utils
757 * @argument {Element} element
758 * @returns {Object} object containing width and height properties
759 */
760 function getOuterSizes(element) {
761 var window = element.ownerDocument.defaultView;
762 var styles = window.getComputedStyle(element);
763 var x = parseFloat(styles.marginTop || 0) + parseFloat(styles.marginBottom || 0);
764 var y = parseFloat(styles.marginLeft || 0) + parseFloat(styles.marginRight || 0);
765 var result = {
766 width: element.offsetWidth + y,
767 height: element.offsetHeight + x
768 };
769 return result;
770 }
771
772 /**
773 * Get the opposite placement of the given one
774 * @method
775 * @memberof Popper.Utils
776 * @argument {String} placement
777 * @returns {String} flipped placement
778 */
779 function getOppositePlacement(placement) {
780 var hash = { left: 'right', right: 'left', bottom: 'top', top: 'bottom' };
781 return placement.replace(/left|right|bottom|top/g, function (matched) {
782 return hash[matched];
783 });
784 }
785
786 /**
787 * Get offsets to the popper
788 * @method
789 * @memberof Popper.Utils
790 * @param {Object} position - CSS position the Popper will get applied
791 * @param {HTMLElement} popper - the popper element
792 * @param {Object} referenceOffsets - the reference offsets (the popper will be relative to this)
793 * @param {String} placement - one of the valid placement options
794 * @returns {Object} popperOffsets - An object containing the offsets which will be applied to the popper
795 */
796 function getPopperOffsets(popper, referenceOffsets, placement) {
797 placement = placement.split('-')[0];
798
799 // Get popper node sizes
800 var popperRect = getOuterSizes(popper);
801
802 // Add position, width and height to our offsets object
803 var popperOffsets = {
804 width: popperRect.width,
805 height: popperRect.height
806 };
807
808 // depending by the popper placement we have to compute its offsets slightly differently
809 var isHoriz = ['right', 'left'].indexOf(placement) !== -1;
810 var mainSide = isHoriz ? 'top' : 'left';
811 var secondarySide = isHoriz ? 'left' : 'top';
812 var measurement = isHoriz ? 'height' : 'width';
813 var secondaryMeasurement = !isHoriz ? 'height' : 'width';
814
815 popperOffsets[mainSide] = referenceOffsets[mainSide] + referenceOffsets[measurement] / 2 - popperRect[measurement] / 2;
816 if (placement === secondarySide) {
817 popperOffsets[secondarySide] = referenceOffsets[secondarySide] - popperRect[secondaryMeasurement];
818 } else {
819 popperOffsets[secondarySide] = referenceOffsets[getOppositePlacement(secondarySide)];
820 }
821
822 return popperOffsets;
823 }
824
825 /**
826 * Mimics the `find` method of Array
827 * @method
828 * @memberof Popper.Utils
829 * @argument {Array} arr
830 * @argument prop
831 * @argument value
832 * @returns index or -1
833 */
834 function find(arr, check) {
835 // use native find if supported
836 if (Array.prototype.find) {
837 return arr.find(check);
838 }
839
840 // use `filter` to obtain the same behavior of `find`
841 return arr.filter(check)[0];
842 }
843
844 /**
845 * Return the index of the matching object
846 * @method
847 * @memberof Popper.Utils
848 * @argument {Array} arr
849 * @argument prop
850 * @argument value
851 * @returns index or -1
852 */
853 function findIndex(arr, prop, value) {
854 // use native findIndex if supported
855 if (Array.prototype.findIndex) {
856 return arr.findIndex(function (cur) {
857 return cur[prop] === value;
858 });
859 }
860
861 // use `find` + `indexOf` if `findIndex` isn't supported
862 var match = find(arr, function (obj) {
863 return obj[prop] === value;
864 });
865 return arr.indexOf(match);
866 }
867
868 /**
869 * Loop trough the list of modifiers and run them in order,
870 * each of them will then edit the data object.
871 * @method
872 * @memberof Popper.Utils
873 * @param {dataObject} data
874 * @param {Array} modifiers
875 * @param {String} ends - Optional modifier name used as stopper
876 * @returns {dataObject}
877 */
878 function runModifiers(modifiers, data, ends) {
879 var modifiersToRun = ends === undefined ? modifiers : modifiers.slice(0, findIndex(modifiers, 'name', ends));
880
881 modifiersToRun.forEach(function (modifier) {
882 if (modifier['function']) {
883 // eslint-disable-line dot-notation
884 console.warn('`modifier.function` is deprecated, use `modifier.fn`!');
885 }
886 var fn = modifier['function'] || modifier.fn; // eslint-disable-line dot-notation
887 if (modifier.enabled && isFunction(fn)) {
888 // Add properties to offsets to make them a complete clientRect object
889 // we do this before each modifier to make sure the previous one doesn't
890 // mess with these values
891 data.offsets.popper = getClientRect(data.offsets.popper);
892 data.offsets.reference = getClientRect(data.offsets.reference);
893
894 data = fn(data, modifier);
895 }
896 });
897
898 return data;
899 }
900
901 /**
902 * Updates the position of the popper, computing the new offsets and applying
903 * the new style.<br />
904 * Prefer `scheduleUpdate` over `update` because of performance reasons.
905 * @method
906 * @memberof Popper
907 */
908 function update() {
909 // if popper is destroyed, don't perform any further update
910 if (this.state.isDestroyed) {
911 return;
912 }
913
914 var data = {
915 instance: this,
916 styles: {},
917 arrowStyles: {},
918 attributes: {},
919 flipped: false,
920 offsets: {}
921 };
922
923 // compute reference element offsets
924 data.offsets.reference = getReferenceOffsets(this.state, this.popper, this.reference, this.options.positionFixed);
925
926 // compute auto placement, store placement inside the data object,
927 // modifiers will be able to edit `placement` if needed
928 // and refer to originalPlacement to know the original value
929 data.placement = computeAutoPlacement(this.options.placement, data.offsets.reference, this.popper, this.reference, this.options.modifiers.flip.boundariesElement, this.options.modifiers.flip.padding);
930
931 // store the computed placement inside `originalPlacement`
932 data.originalPlacement = data.placement;
933
934 data.positionFixed = this.options.positionFixed;
935
936 // compute the popper offsets
937 data.offsets.popper = getPopperOffsets(this.popper, data.offsets.reference, data.placement);
938
939 data.offsets.popper.position = this.options.positionFixed ? 'fixed' : 'absolute';
940
941 // run the modifiers
942 data = runModifiers(this.modifiers, data);
943
944 // the first `update` will call `onCreate` callback
945 // the other ones will call `onUpdate` callback
946 if (!this.state.isCreated) {
947 this.state.isCreated = true;
948 this.options.onCreate(data);
949 } else {
950 this.options.onUpdate(data);
951 }
952 }
953
954 /**
955 * Helper used to know if the given modifier is enabled.
956 * @method
957 * @memberof Popper.Utils
958 * @returns {Boolean}
959 */
960 function isModifierEnabled(modifiers, modifierName) {
961 return modifiers.some(function (_ref) {
962 var name = _ref.name,
963 enabled = _ref.enabled;
964 return enabled && name === modifierName;
965 });
966 }
967
968 /**
969 * Get the prefixed supported property name
970 * @method
971 * @memberof Popper.Utils
972 * @argument {String} property (camelCase)
973 * @returns {String} prefixed property (camelCase or PascalCase, depending on the vendor prefix)
974 */
975 function getSupportedPropertyName(property) {
976 var prefixes = [false, 'ms', 'Webkit', 'Moz', 'O'];
977 var upperProp = property.charAt(0).toUpperCase() + property.slice(1);
978
979 for (var i = 0; i < prefixes.length; i++) {
980 var prefix = prefixes[i];
981 var toCheck = prefix ? '' + prefix + upperProp : property;
982 if (typeof document.body.style[toCheck] !== 'undefined') {
983 return toCheck;
984 }
985 }
986 return null;
987 }
988
989 /**
990 * Destroys the popper.
991 * @method
992 * @memberof Popper
993 */
994 function destroy() {
995 this.state.isDestroyed = true;
996
997 // touch DOM only if `applyStyle` modifier is enabled
998 if (isModifierEnabled(this.modifiers, 'applyStyle')) {
999 this.popper.removeAttribute('x-placement');
1000 this.popper.style.position = '';
1001 this.popper.style.top = '';
1002 this.popper.style.left = '';
1003 this.popper.style.right = '';
1004 this.popper.style.bottom = '';
1005 this.popper.style.willChange = '';
1006 this.popper.style[getSupportedPropertyName('transform')] = '';
1007 }
1008
1009 this.disableEventListeners();
1010
1011 // remove the popper if user explicity asked for the deletion on destroy
1012 // do not use `remove` because IE11 doesn't support it
1013 if (this.options.removeOnDestroy) {
1014 this.popper.parentNode.removeChild(this.popper);
1015 }
1016 return this;
1017 }
1018
1019 /**
1020 * Get the window associated with the element
1021 * @argument {Element} element
1022 * @returns {Window}
1023 */
1024 function getWindow(element) {
1025 var ownerDocument = element.ownerDocument;
1026 return ownerDocument ? ownerDocument.defaultView : window;
1027 }
1028
1029 function attachToScrollParents(scrollParent, event, callback, scrollParents) {
1030 var isBody = scrollParent.nodeName === 'BODY';
1031 var target = isBody ? scrollParent.ownerDocument.defaultView : scrollParent;
1032 target.addEventListener(event, callback, { passive: true });
1033
1034 if (!isBody) {
1035 attachToScrollParents(getScrollParent(target.parentNode), event, callback, scrollParents);
1036 }
1037 scrollParents.push(target);
1038 }
1039
1040 /**
1041 * Setup needed event listeners used to update the popper position
1042 * @method
1043 * @memberof Popper.Utils
1044 * @private
1045 */
1046 function setupEventListeners(reference, options, state, updateBound) {
1047 // Resize event listener on window
1048 state.updateBound = updateBound;
1049 getWindow(reference).addEventListener('resize', state.updateBound, { passive: true });
1050
1051 // Scroll event listener on scroll parents
1052 var scrollElement = getScrollParent(reference);
1053 attachToScrollParents(scrollElement, 'scroll', state.updateBound, state.scrollParents);
1054 state.scrollElement = scrollElement;
1055 state.eventsEnabled = true;
1056
1057 return state;
1058 }
1059
1060 /**
1061 * It will add resize/scroll events and start recalculating
1062 * position of the popper element when they are triggered.
1063 * @method
1064 * @memberof Popper
1065 */
1066 function enableEventListeners() {
1067 if (!this.state.eventsEnabled) {
1068 this.state = setupEventListeners(this.reference, this.options, this.state, this.scheduleUpdate);
1069 }
1070 }
1071
1072 /**
1073 * Remove event listeners used to update the popper position
1074 * @method
1075 * @memberof Popper.Utils
1076 * @private
1077 */
1078 function removeEventListeners(reference, state) {
1079 // Remove resize event listener on window
1080 getWindow(reference).removeEventListener('resize', state.updateBound);
1081
1082 // Remove scroll event listener on scroll parents
1083 state.scrollParents.forEach(function (target) {
1084 target.removeEventListener('scroll', state.updateBound);
1085 });
1086
1087 // Reset state
1088 state.updateBound = null;
1089 state.scrollParents = [];
1090 state.scrollElement = null;
1091 state.eventsEnabled = false;
1092 return state;
1093 }
1094
1095 /**
1096 * It will remove resize/scroll events and won't recalculate popper position
1097 * when they are triggered. It also won't trigger `onUpdate` callback anymore,
1098 * unless you call `update` method manually.
1099 * @method
1100 * @memberof Popper
1101 */
1102 function disableEventListeners() {
1103 if (this.state.eventsEnabled) {
1104 cancelAnimationFrame(this.scheduleUpdate);
1105 this.state = removeEventListeners(this.reference, this.state);
1106 }
1107 }
1108
1109 /**
1110 * Tells if a given input is a number
1111 * @method
1112 * @memberof Popper.Utils
1113 * @param {*} input to check
1114 * @return {Boolean}
1115 */
1116 function isNumeric(n) {
1117 return n !== '' && !isNaN(parseFloat(n)) && isFinite(n);
1118 }
1119
1120 /**
1121 * Set the style to the given popper
1122 * @method
1123 * @memberof Popper.Utils
1124 * @argument {Element} element - Element to apply the style to
1125 * @argument {Object} styles
1126 * Object with a list of properties and values which will be applied to the element
1127 */
1128 function setStyles(element, styles) {
1129 Object.keys(styles).forEach(function (prop) {
1130 var unit = '';
1131 // add unit if the value is numeric and is one of the following
1132 if (['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== -1 && isNumeric(styles[prop])) {
1133 unit = 'px';
1134 }
1135 element.style[prop] = styles[prop] + unit;
1136 });
1137 }
1138
1139 /**
1140 * Set the attributes to the given popper
1141 * @method
1142 * @memberof Popper.Utils
1143 * @argument {Element} element - Element to apply the attributes to
1144 * @argument {Object} styles
1145 * Object with a list of properties and values which will be applied to the element
1146 */
1147 function setAttributes(element, attributes) {
1148 Object.keys(attributes).forEach(function (prop) {
1149 var value = attributes[prop];
1150 if (value !== false) {
1151 element.setAttribute(prop, attributes[prop]);
1152 } else {
1153 element.removeAttribute(prop);
1154 }
1155 });
1156 }
1157
1158 /**
1159 * @function
1160 * @memberof Modifiers
1161 * @argument {Object} data - The data object generated by `update` method
1162 * @argument {Object} data.styles - List of style properties - values to apply to popper element
1163 * @argument {Object} data.attributes - List of attribute properties - values to apply to popper element
1164 * @argument {Object} options - Modifiers configuration and options
1165 * @returns {Object} The same data object
1166 */
1167 function applyStyle(data) {
1168 // any property present in `data.styles` will be applied to the popper,
1169 // in this way we can make the 3rd party modifiers add custom styles to it
1170 // Be aware, modifiers could override the properties defined in the previous
1171 // lines of this modifier!
1172 setStyles(data.instance.popper, data.styles);
1173
1174 // any property present in `data.attributes` will be applied to the popper,
1175 // they will be set as HTML attributes of the element
1176 setAttributes(data.instance.popper, data.attributes);
1177
1178 // if arrowElement is defined and arrowStyles has some properties
1179 if (data.arrowElement && Object.keys(data.arrowStyles).length) {
1180 setStyles(data.arrowElement, data.arrowStyles);
1181 }
1182
1183 return data;
1184 }
1185
1186 /**
1187 * Set the x-placement attribute before everything else because it could be used
1188 * to add margins to the popper margins needs to be calculated to get the
1189 * correct popper offsets.
1190 * @method
1191 * @memberof Popper.modifiers
1192 * @param {HTMLElement} reference - The reference element used to position the popper
1193 * @param {HTMLElement} popper - The HTML element used as popper
1194 * @param {Object} options - Popper.js options
1195 */
1196 function applyStyleOnLoad(reference, popper, options, modifierOptions, state) {
1197 // compute reference element offsets
1198 var referenceOffsets = getReferenceOffsets(state, popper, reference, options.positionFixed);
1199
1200 // compute auto placement, store placement inside the data object,
1201 // modifiers will be able to edit `placement` if needed
1202 // and refer to originalPlacement to know the original value
1203 var placement = computeAutoPlacement(options.placement, referenceOffsets, popper, reference, options.modifiers.flip.boundariesElement, options.modifiers.flip.padding);
1204
1205 popper.setAttribute('x-placement', placement);
1206
1207 // Apply `position` to popper before anything else because
1208 // without the position applied we can't guarantee correct computations
1209 setStyles(popper, { position: options.positionFixed ? 'fixed' : 'absolute' });
1210
1211 return options;
1212 }
1213
1214 /**
1215 * @function
1216 * @memberof Popper.Utils
1217 * @argument {Object} data - The data object generated by `update` method
1218 * @argument {Boolean} shouldRound - If the offsets should be rounded at all
1219 * @returns {Object} The popper's position offsets rounded
1220 *
1221 * The tale of pixel-perfect positioning. It's still not 100% perfect, but as
1222 * good as it can be within reason.
1223 * Discussion here: https://github.com/FezVrasta/popper.js/pull/715
1224 *
1225 * Low DPI screens cause a popper to be blurry if not using full pixels (Safari
1226 * as well on High DPI screens).
1227 *
1228 * Firefox prefers no rounding for positioning and does not have blurriness on
1229 * high DPI screens.
1230 *
1231 * Only horizontal placement and left/right values need to be considered.
1232 */
1233 function getRoundedOffsets(data, shouldRound) {
1234 var _data$offsets = data.offsets,
1235 popper = _data$offsets.popper,
1236 reference = _data$offsets.reference;
1237 var round = Math.round,
1238 floor = Math.floor;
1239
1240 var noRound = function noRound(v) {
1241 return v;
1242 };
1243
1244 var referenceWidth = round(reference.width);
1245 var popperWidth = round(popper.width);
1246
1247 var isVertical = ['left', 'right'].indexOf(data.placement) !== -1;
1248 var isVariation = data.placement.indexOf('-') !== -1;
1249 var sameWidthParity = referenceWidth % 2 === popperWidth % 2;
1250 var bothOddWidth = referenceWidth % 2 === 1 && popperWidth % 2 === 1;
1251
1252 var horizontalToInteger = !shouldRound ? noRound : isVertical || isVariation || sameWidthParity ? round : floor;
1253 var verticalToInteger = !shouldRound ? noRound : round;
1254
1255 return {
1256 left: horizontalToInteger(bothOddWidth && !isVariation && shouldRound ? popper.left - 1 : popper.left),
1257 top: verticalToInteger(popper.top),
1258 bottom: verticalToInteger(popper.bottom),
1259 right: horizontalToInteger(popper.right)
1260 };
1261 }
1262
1263 var isFirefox = isBrowser && /Firefox/i.test(navigator.userAgent);
1264
1265 /**
1266 * @function
1267 * @memberof Modifiers
1268 * @argument {Object} data - The data object generated by `update` method
1269 * @argument {Object} options - Modifiers configuration and options
1270 * @returns {Object} The data object, properly modified
1271 */
1272 function computeStyle(data, options) {
1273 var x = options.x,
1274 y = options.y;
1275 var popper = data.offsets.popper;
1276
1277 // Remove this legacy support in Popper.js v2
1278
1279 var legacyGpuAccelerationOption = find(data.instance.modifiers, function (modifier) {
1280 return modifier.name === 'applyStyle';
1281 }).gpuAcceleration;
1282 if (legacyGpuAccelerationOption !== undefined) {
1283 console.warn('WARNING: `gpuAcceleration` option moved to `computeStyle` modifier and will not be supported in future versions of Popper.js!');
1284 }
1285 var gpuAcceleration = legacyGpuAccelerationOption !== undefined ? legacyGpuAccelerationOption : options.gpuAcceleration;
1286
1287 var offsetParent = getOffsetParent(data.instance.popper);
1288 var offsetParentRect = getBoundingClientRect(offsetParent);
1289
1290 // Styles
1291 var styles = {
1292 position: popper.position
1293 };
1294
1295 var offsets = getRoundedOffsets(data, window.devicePixelRatio < 2 || !isFirefox);
1296
1297 var sideA = x === 'bottom' ? 'top' : 'bottom';
1298 var sideB = y === 'right' ? 'left' : 'right';
1299
1300 // if gpuAcceleration is set to `true` and transform is supported,
1301 // we use `translate3d` to apply the position to the popper we
1302 // automatically use the supported prefixed version if needed
1303 var prefixedProperty = getSupportedPropertyName('transform');
1304
1305 // now, let's make a step back and look at this code closely (wtf?)
1306 // If the content of the popper grows once it's been positioned, it
1307 // may happen that the popper gets misplaced because of the new content
1308 // overflowing its reference element
1309 // To avoid this problem, we provide two options (x and y), which allow
1310 // the consumer to define the offset origin.
1311 // If we position a popper on top of a reference element, we can set
1312 // `x` to `top` to make the popper grow towards its top instead of
1313 // its bottom.
1314 var left = void 0,
1315 top = void 0;
1316 if (sideA === 'bottom') {
1317 // when offsetParent is <html> the positioning is relative to the bottom of the screen (excluding the scrollbar)
1318 // and not the bottom of the html element
1319 if (offsetParent.nodeName === 'HTML') {
1320 top = -offsetParent.clientHeight + offsets.bottom;
1321 } else {
1322 top = -offsetParentRect.height + offsets.bottom;
1323 }
1324 } else {
1325 top = offsets.top;
1326 }
1327 if (sideB === 'right') {
1328 if (offsetParent.nodeName === 'HTML') {
1329 left = -offsetParent.clientWidth + offsets.right;
1330 } else {
1331 left = -offsetParentRect.width + offsets.right;
1332 }
1333 } else {
1334 left = offsets.left;
1335 }
1336 if (gpuAcceleration && prefixedProperty) {
1337 styles[prefixedProperty] = 'translate3d(' + left + 'px, ' + top + 'px, 0)';
1338 styles[sideA] = 0;
1339 styles[sideB] = 0;
1340 styles.willChange = 'transform';
1341 } else {
1342 // othwerise, we use the standard `top`, `left`, `bottom` and `right` properties
1343 var invertTop = sideA === 'bottom' ? -1 : 1;
1344 var invertLeft = sideB === 'right' ? -1 : 1;
1345 styles[sideA] = top * invertTop;
1346 styles[sideB] = left * invertLeft;
1347 styles.willChange = sideA + ', ' + sideB;
1348 }
1349
1350 // Attributes
1351 var attributes = {
1352 'x-placement': data.placement
1353 };
1354
1355 // Update `data` attributes, styles and arrowStyles
1356 data.attributes = _extends({}, attributes, data.attributes);
1357 data.styles = _extends({}, styles, data.styles);
1358 data.arrowStyles = _extends({}, data.offsets.arrow, data.arrowStyles);
1359
1360 return data;
1361 }
1362
1363 /**
1364 * Helper used to know if the given modifier depends from another one.<br />
1365 * It checks if the needed modifier is listed and enabled.
1366 * @method
1367 * @memberof Popper.Utils
1368 * @param {Array} modifiers - list of modifiers
1369 * @param {String} requestingName - name of requesting modifier
1370 * @param {String} requestedName - name of requested modifier
1371 * @returns {Boolean}
1372 */
1373 function isModifierRequired(modifiers, requestingName, requestedName) {
1374 var requesting = find(modifiers, function (_ref) {
1375 var name = _ref.name;
1376 return name === requestingName;
1377 });
1378
1379 var isRequired = !!requesting && modifiers.some(function (modifier) {
1380 return modifier.name === requestedName && modifier.enabled && modifier.order < requesting.order;
1381 });
1382
1383 if (!isRequired) {
1384 var _requesting = '`' + requestingName + '`';
1385 var requested = '`' + requestedName + '`';
1386 console.warn(requested + ' modifier is required by ' + _requesting + ' modifier in order to work, be sure to include it before ' + _requesting + '!');
1387 }
1388 return isRequired;
1389 }
1390
1391 /**
1392 * @function
1393 * @memberof Modifiers
1394 * @argument {Object} data - The data object generated by update method
1395 * @argument {Object} options - Modifiers configuration and options
1396 * @returns {Object} The data object, properly modified
1397 */
1398 function arrow(data, options) {
1399 var _data$offsets$arrow;
1400
1401 // arrow depends on keepTogether in order to work
1402 if (!isModifierRequired(data.instance.modifiers, 'arrow', 'keepTogether')) {
1403 return data;
1404 }
1405
1406 var arrowElement = options.element;
1407
1408 // if arrowElement is a string, suppose it's a CSS selector
1409 if (typeof arrowElement === 'string') {
1410 arrowElement = data.instance.popper.querySelector(arrowElement);
1411
1412 // if arrowElement is not found, don't run the modifier
1413 if (!arrowElement) {
1414 return data;
1415 }
1416 } else {
1417 // if the arrowElement isn't a query selector we must check that the
1418 // provided DOM node is child of its popper node
1419 if (!data.instance.popper.contains(arrowElement)) {
1420 console.warn('WARNING: `arrow.element` must be child of its popper element!');
1421 return data;
1422 }
1423 }
1424
1425 var placement = data.placement.split('-')[0];
1426 var _data$offsets = data.offsets,
1427 popper = _data$offsets.popper,
1428 reference = _data$offsets.reference;
1429
1430 var isVertical = ['left', 'right'].indexOf(placement) !== -1;
1431
1432 var len = isVertical ? 'height' : 'width';
1433 var sideCapitalized = isVertical ? 'Top' : 'Left';
1434 var side = sideCapitalized.toLowerCase();
1435 var altSide = isVertical ? 'left' : 'top';
1436 var opSide = isVertical ? 'bottom' : 'right';
1437 var arrowElementSize = getOuterSizes(arrowElement)[len];
1438
1439 //
1440 // extends keepTogether behavior making sure the popper and its
1441 // reference have enough pixels in conjunction
1442 //
1443
1444 // top/left side
1445 if (reference[opSide] - arrowElementSize < popper[side]) {
1446 data.offsets.popper[side] -= popper[side] - (reference[opSide] - arrowElementSize);
1447 }
1448 // bottom/right side
1449 if (reference[side] + arrowElementSize > popper[opSide]) {
1450 data.offsets.popper[side] += reference[side] + arrowElementSize - popper[opSide];
1451 }
1452 data.offsets.popper = getClientRect(data.offsets.popper);
1453
1454 // compute center of the popper
1455 var center = reference[side] + reference[len] / 2 - arrowElementSize / 2;
1456
1457 // Compute the sideValue using the updated popper offsets
1458 // take popper margin in account because we don't have this info available
1459 var css = getStyleComputedProperty(data.instance.popper);
1460 var popperMarginSide = parseFloat(css['margin' + sideCapitalized], 10);
1461 var popperBorderSide = parseFloat(css['border' + sideCapitalized + 'Width'], 10);
1462 var sideValue = center - data.offsets.popper[side] - popperMarginSide - popperBorderSide;
1463
1464 // prevent arrowElement from being placed not contiguously to its popper
1465 sideValue = Math.max(Math.min(popper[len] - arrowElementSize, sideValue), 0);
1466
1467 data.arrowElement = arrowElement;
1468 data.offsets.arrow = (_data$offsets$arrow = {}, defineProperty(_data$offsets$arrow, side, Math.round(sideValue)), defineProperty(_data$offsets$arrow, altSide, ''), _data$offsets$arrow);
1469
1470 return data;
1471 }
1472
1473 /**
1474 * Get the opposite placement variation of the given one
1475 * @method
1476 * @memberof Popper.Utils
1477 * @argument {String} placement variation
1478 * @returns {String} flipped placement variation
1479 */
1480 function getOppositeVariation(variation) {
1481 if (variation === 'end') {
1482 return 'start';
1483 } else if (variation === 'start') {
1484 return 'end';
1485 }
1486 return variation;
1487 }
1488
1489 /**
1490 * List of accepted placements to use as values of the `placement` option.<br />
1491 * Valid placements are:
1492 * - `auto`
1493 * - `top`
1494 * - `right`
1495 * - `bottom`
1496 * - `left`
1497 *
1498 * Each placement can have a variation from this list:
1499 * - `-start`
1500 * - `-end`
1501 *
1502 * Variations are interpreted easily if you think of them as the left to right
1503 * written languages. Horizontally (`top` and `bottom`), `start` is left and `end`
1504 * is right.<br />
1505 * Vertically (`left` and `right`), `start` is top and `end` is bottom.
1506 *
1507 * Some valid examples are:
1508 * - `top-end` (on top of reference, right aligned)
1509 * - `right-start` (on right of reference, top aligned)
1510 * - `bottom` (on bottom, centered)
1511 * - `auto-end` (on the side with more space available, alignment depends by placement)
1512 *
1513 * @static
1514 * @type {Array}
1515 * @enum {String}
1516 * @readonly
1517 * @method placements
1518 * @memberof Popper
1519 */
1520 var placements = ['auto-start', 'auto', 'auto-end', 'top-start', 'top', 'top-end', 'right-start', 'right', 'right-end', 'bottom-end', 'bottom', 'bottom-start', 'left-end', 'left', 'left-start'];
1521
1522 // Get rid of `auto` `auto-start` and `auto-end`
1523 var validPlacements = placements.slice(3);
1524
1525 /**
1526 * Given an initial placement, returns all the subsequent placements
1527 * clockwise (or counter-clockwise).
1528 *
1529 * @method
1530 * @memberof Popper.Utils
1531 * @argument {String} placement - A valid placement (it accepts variations)
1532 * @argument {Boolean} counter - Set to true to walk the placements counterclockwise
1533 * @returns {Array} placements including their variations
1534 */
1535 function clockwise(placement) {
1536 var counter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
1537
1538 var index = validPlacements.indexOf(placement);
1539 var arr = validPlacements.slice(index + 1).concat(validPlacements.slice(0, index));
1540 return counter ? arr.reverse() : arr;
1541 }
1542
1543 var BEHAVIORS = {
1544 FLIP: 'flip',
1545 CLOCKWISE: 'clockwise',
1546 COUNTERCLOCKWISE: 'counterclockwise'
1547 };
1548
1549 /**
1550 * @function
1551 * @memberof Modifiers
1552 * @argument {Object} data - The data object generated by update method
1553 * @argument {Object} options - Modifiers configuration and options
1554 * @returns {Object} The data object, properly modified
1555 */
1556 function flip(data, options) {
1557 // if `inner` modifier is enabled, we can't use the `flip` modifier
1558 if (isModifierEnabled(data.instance.modifiers, 'inner')) {
1559 return data;
1560 }
1561
1562 if (data.flipped && data.placement === data.originalPlacement) {
1563 // seems like flip is trying to loop, probably there's not enough space on any of the flippable sides
1564 return data;
1565 }
1566
1567 var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, options.boundariesElement, data.positionFixed);
1568
1569 var placement = data.placement.split('-')[0];
1570 var placementOpposite = getOppositePlacement(placement);
1571 var variation = data.placement.split('-')[1] || '';
1572
1573 var flipOrder = [];
1574
1575 switch (options.behavior) {
1576 case BEHAVIORS.FLIP:
1577 flipOrder = [placement, placementOpposite];
1578 break;
1579 case BEHAVIORS.CLOCKWISE:
1580 flipOrder = clockwise(placement);
1581 break;
1582 case BEHAVIORS.COUNTERCLOCKWISE:
1583 flipOrder = clockwise(placement, true);
1584 break;
1585 default:
1586 flipOrder = options.behavior;
1587 }
1588
1589 flipOrder.forEach(function (step, index) {
1590 if (placement !== step || flipOrder.length === index + 1) {
1591 return data;
1592 }
1593
1594 placement = data.placement.split('-')[0];
1595 placementOpposite = getOppositePlacement(placement);
1596
1597 var popperOffsets = data.offsets.popper;
1598 var refOffsets = data.offsets.reference;
1599
1600 // using floor because the reference offsets may contain decimals we are not going to consider here
1601 var floor = Math.floor;
1602 var overlapsRef = placement === 'left' && floor(popperOffsets.right) > floor(refOffsets.left) || placement === 'right' && floor(popperOffsets.left) < floor(refOffsets.right) || placement === 'top' && floor(popperOffsets.bottom) > floor(refOffsets.top) || placement === 'bottom' && floor(popperOffsets.top) < floor(refOffsets.bottom);
1603
1604 var overflowsLeft = floor(popperOffsets.left) < floor(boundaries.left);
1605 var overflowsRight = floor(popperOffsets.right) > floor(boundaries.right);
1606 var overflowsTop = floor(popperOffsets.top) < floor(boundaries.top);
1607 var overflowsBottom = floor(popperOffsets.bottom) > floor(boundaries.bottom);
1608
1609 var overflowsBoundaries = placement === 'left' && overflowsLeft || placement === 'right' && overflowsRight || placement === 'top' && overflowsTop || placement === 'bottom' && overflowsBottom;
1610
1611 // flip the variation if required
1612 var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;
1613 var flippedVariation = !!options.flipVariations && (isVertical && variation === 'start' && overflowsLeft || isVertical && variation === 'end' && overflowsRight || !isVertical && variation === 'start' && overflowsTop || !isVertical && variation === 'end' && overflowsBottom);
1614
1615 if (overlapsRef || overflowsBoundaries || flippedVariation) {
1616 // this boolean to detect any flip loop
1617 data.flipped = true;
1618
1619 if (overlapsRef || overflowsBoundaries) {
1620 placement = flipOrder[index + 1];
1621 }
1622
1623 if (flippedVariation) {
1624 variation = getOppositeVariation(variation);
1625 }
1626
1627 data.placement = placement + (variation ? '-' + variation : '');
1628
1629 // this object contains `position`, we want to preserve it along with
1630 // any additional property we may add in the future
1631 data.offsets.popper = _extends({}, data.offsets.popper, getPopperOffsets(data.instance.popper, data.offsets.reference, data.placement));
1632
1633 data = runModifiers(data.instance.modifiers, data, 'flip');
1634 }
1635 });
1636 return data;
1637 }
1638
1639 /**
1640 * @function
1641 * @memberof Modifiers
1642 * @argument {Object} data - The data object generated by update method
1643 * @argument {Object} options - Modifiers configuration and options
1644 * @returns {Object} The data object, properly modified
1645 */
1646 function keepTogether(data) {
1647 var _data$offsets = data.offsets,
1648 popper = _data$offsets.popper,
1649 reference = _data$offsets.reference;
1650
1651 var placement = data.placement.split('-')[0];
1652 var floor = Math.floor;
1653 var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;
1654 var side = isVertical ? 'right' : 'bottom';
1655 var opSide = isVertical ? 'left' : 'top';
1656 var measurement = isVertical ? 'width' : 'height';
1657
1658 if (popper[side] < floor(reference[opSide])) {
1659 data.offsets.popper[opSide] = floor(reference[opSide]) - popper[measurement];
1660 }
1661 if (popper[opSide] > floor(reference[side])) {
1662 data.offsets.popper[opSide] = floor(reference[side]);
1663 }
1664
1665 return data;
1666 }
1667
1668 /**
1669 * Converts a string containing value + unit into a px value number
1670 * @function
1671 * @memberof {modifiers~offset}
1672 * @private
1673 * @argument {String} str - Value + unit string
1674 * @argument {String} measurement - `height` or `width`
1675 * @argument {Object} popperOffsets
1676 * @argument {Object} referenceOffsets
1677 * @returns {Number|String}
1678 * Value in pixels, or original string if no values were extracted
1679 */
1680 function toValue(str, measurement, popperOffsets, referenceOffsets) {
1681 // separate value from unit
1682 var split = str.match(/((?:\-|\+)?\d*\.?\d*)(.*)/);
1683 var value = +split[1];
1684 var unit = split[2];
1685
1686 // If it's not a number it's an operator, I guess
1687 if (!value) {
1688 return str;
1689 }
1690
1691 if (unit.indexOf('%') === 0) {
1692 var element = void 0;
1693 switch (unit) {
1694 case '%p':
1695 element = popperOffsets;
1696 break;
1697 case '%':
1698 case '%r':
1699 default:
1700 element = referenceOffsets;
1701 }
1702
1703 var rect = getClientRect(element);
1704 return rect[measurement] / 100 * value;
1705 } else if (unit === 'vh' || unit === 'vw') {
1706 // if is a vh or vw, we calculate the size based on the viewport
1707 var size = void 0;
1708 if (unit === 'vh') {
1709 size = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
1710 } else {
1711 size = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
1712 }
1713 return size / 100 * value;
1714 } else {
1715 // if is an explicit pixel unit, we get rid of the unit and keep the value
1716 // if is an implicit unit, it's px, and we return just the value
1717 return value;
1718 }
1719 }
1720
1721 /**
1722 * Parse an `offset` string to extrapolate `x` and `y` numeric offsets.
1723 * @function
1724 * @memberof {modifiers~offset}
1725 * @private
1726 * @argument {String} offset
1727 * @argument {Object} popperOffsets
1728 * @argument {Object} referenceOffsets
1729 * @argument {String} basePlacement
1730 * @returns {Array} a two cells array with x and y offsets in numbers
1731 */
1732 function parseOffset(offset, popperOffsets, referenceOffsets, basePlacement) {
1733 var offsets = [0, 0];
1734
1735 // Use height if placement is left or right and index is 0 otherwise use width
1736 // in this way the first offset will use an axis and the second one
1737 // will use the other one
1738 var useHeight = ['right', 'left'].indexOf(basePlacement) !== -1;
1739
1740 // Split the offset string to obtain a list of values and operands
1741 // The regex addresses values with the plus or minus sign in front (+10, -20, etc)
1742 var fragments = offset.split(/(\+|\-)/).map(function (frag) {
1743 return frag.trim();
1744 });
1745
1746 // Detect if the offset string contains a pair of values or a single one
1747 // they could be separated by comma or space
1748 var divider = fragments.indexOf(find(fragments, function (frag) {
1749 return frag.search(/,|\s/) !== -1;
1750 }));
1751
1752 if (fragments[divider] && fragments[divider].indexOf(',') === -1) {
1753 console.warn('Offsets separated by white space(s) are deprecated, use a comma (,) instead.');
1754 }
1755
1756 // If divider is found, we divide the list of values and operands to divide
1757 // them by ofset X and Y.
1758 var splitRegex = /\s*,\s*|\s+/;
1759 var ops = divider !== -1 ? [fragments.slice(0, divider).concat([fragments[divider].split(splitRegex)[0]]), [fragments[divider].split(splitRegex)[1]].concat(fragments.slice(divider + 1))] : [fragments];
1760
1761 // Convert the values with units to absolute pixels to allow our computations
1762 ops = ops.map(function (op, index) {
1763 // Most of the units rely on the orientation of the popper
1764 var measurement = (index === 1 ? !useHeight : useHeight) ? 'height' : 'width';
1765 var mergeWithPrevious = false;
1766 return op
1767 // This aggregates any `+` or `-` sign that aren't considered operators
1768 // e.g.: 10 + +5 => [10, +, +5]
1769 .reduce(function (a, b) {
1770 if (a[a.length - 1] === '' && ['+', '-'].indexOf(b) !== -1) {
1771 a[a.length - 1] = b;
1772 mergeWithPrevious = true;
1773 return a;
1774 } else if (mergeWithPrevious) {
1775 a[a.length - 1] += b;
1776 mergeWithPrevious = false;
1777 return a;
1778 } else {
1779 return a.concat(b);
1780 }
1781 }, [])
1782 // Here we convert the string values into number values (in px)
1783 .map(function (str) {
1784 return toValue(str, measurement, popperOffsets, referenceOffsets);
1785 });
1786 });
1787
1788 // Loop trough the offsets arrays and execute the operations
1789 ops.forEach(function (op, index) {
1790 op.forEach(function (frag, index2) {
1791 if (isNumeric(frag)) {
1792 offsets[index] += frag * (op[index2 - 1] === '-' ? -1 : 1);
1793 }
1794 });
1795 });
1796 return offsets;
1797 }
1798
1799 /**
1800 * @function
1801 * @memberof Modifiers
1802 * @argument {Object} data - The data object generated by update method
1803 * @argument {Object} options - Modifiers configuration and options
1804 * @argument {Number|String} options.offset=0
1805 * The offset value as described in the modifier description
1806 * @returns {Object} The data object, properly modified
1807 */
1808 function offset(data, _ref) {
1809 var offset = _ref.offset;
1810 var placement = data.placement,
1811 _data$offsets = data.offsets,
1812 popper = _data$offsets.popper,
1813 reference = _data$offsets.reference;
1814
1815 var basePlacement = placement.split('-')[0];
1816
1817 var offsets = void 0;
1818 if (isNumeric(+offset)) {
1819 offsets = [+offset, 0];
1820 } else {
1821 offsets = parseOffset(offset, popper, reference, basePlacement);
1822 }
1823
1824 if (basePlacement === 'left') {
1825 popper.top += offsets[0];
1826 popper.left -= offsets[1];
1827 } else if (basePlacement === 'right') {
1828 popper.top += offsets[0];
1829 popper.left += offsets[1];
1830 } else if (basePlacement === 'top') {
1831 popper.left += offsets[0];
1832 popper.top -= offsets[1];
1833 } else if (basePlacement === 'bottom') {
1834 popper.left += offsets[0];
1835 popper.top += offsets[1];
1836 }
1837
1838 data.popper = popper;
1839 return data;
1840 }
1841
1842 /**
1843 * @function
1844 * @memberof Modifiers
1845 * @argument {Object} data - The data object generated by `update` method
1846 * @argument {Object} options - Modifiers configuration and options
1847 * @returns {Object} The data object, properly modified
1848 */
1849 function preventOverflow(data, options) {
1850 var boundariesElement = options.boundariesElement || getOffsetParent(data.instance.popper);
1851
1852 // If offsetParent is the reference element, we really want to
1853 // go one step up and use the next offsetParent as reference to
1854 // avoid to make this modifier completely useless and look like broken
1855 if (data.instance.reference === boundariesElement) {
1856 boundariesElement = getOffsetParent(boundariesElement);
1857 }
1858
1859 // NOTE: DOM access here
1860 // resets the popper's position so that the document size can be calculated excluding
1861 // the size of the popper element itself
1862 var transformProp = getSupportedPropertyName('transform');
1863 var popperStyles = data.instance.popper.style; // assignment to help minification
1864 var top = popperStyles.top,
1865 left = popperStyles.left,
1866 transform = popperStyles[transformProp];
1867
1868 popperStyles.top = '';
1869 popperStyles.left = '';
1870 popperStyles[transformProp] = '';
1871
1872 var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, boundariesElement, data.positionFixed);
1873
1874 // NOTE: DOM access here
1875 // restores the original style properties after the offsets have been computed
1876 popperStyles.top = top;
1877 popperStyles.left = left;
1878 popperStyles[transformProp] = transform;
1879
1880 options.boundaries = boundaries;
1881
1882 var order = options.priority;
1883 var popper = data.offsets.popper;
1884
1885 var check = {
1886 primary: function primary(placement) {
1887 var value = popper[placement];
1888 if (popper[placement] < boundaries[placement] && !options.escapeWithReference) {
1889 value = Math.max(popper[placement], boundaries[placement]);
1890 }
1891 return defineProperty({}, placement, value);
1892 },
1893 secondary: function secondary(placement) {
1894 var mainSide = placement === 'right' ? 'left' : 'top';
1895 var value = popper[mainSide];
1896 if (popper[placement] > boundaries[placement] && !options.escapeWithReference) {
1897 value = Math.min(popper[mainSide], boundaries[placement] - (placement === 'right' ? popper.width : popper.height));
1898 }
1899 return defineProperty({}, mainSide, value);
1900 }
1901 };
1902
1903 order.forEach(function (placement) {
1904 var side = ['left', 'top'].indexOf(placement) !== -1 ? 'primary' : 'secondary';
1905 popper = _extends({}, popper, check[side](placement));
1906 });
1907
1908 data.offsets.popper = popper;
1909
1910 return data;
1911 }
1912
1913 /**
1914 * @function
1915 * @memberof Modifiers
1916 * @argument {Object} data - The data object generated by `update` method
1917 * @argument {Object} options - Modifiers configuration and options
1918 * @returns {Object} The data object, properly modified
1919 */
1920 function shift(data) {
1921 var placement = data.placement;
1922 var basePlacement = placement.split('-')[0];
1923 var shiftvariation = placement.split('-')[1];
1924
1925 // if shift shiftvariation is specified, run the modifier
1926 if (shiftvariation) {
1927 var _data$offsets = data.offsets,
1928 reference = _data$offsets.reference,
1929 popper = _data$offsets.popper;
1930
1931 var isVertical = ['bottom', 'top'].indexOf(basePlacement) !== -1;
1932 var side = isVertical ? 'left' : 'top';
1933 var measurement = isVertical ? 'width' : 'height';
1934
1935 var shiftOffsets = {
1936 start: defineProperty({}, side, reference[side]),
1937 end: defineProperty({}, side, reference[side] + reference[measurement] - popper[measurement])
1938 };
1939
1940 data.offsets.popper = _extends({}, popper, shiftOffsets[shiftvariation]);
1941 }
1942
1943 return data;
1944 }
1945
1946 /**
1947 * @function
1948 * @memberof Modifiers
1949 * @argument {Object} data - The data object generated by update method
1950 * @argument {Object} options - Modifiers configuration and options
1951 * @returns {Object} The data object, properly modified
1952 */
1953 function hide(data) {
1954 if (!isModifierRequired(data.instance.modifiers, 'hide', 'preventOverflow')) {
1955 return data;
1956 }
1957
1958 var refRect = data.offsets.reference;
1959 var bound = find(data.instance.modifiers, function (modifier) {
1960 return modifier.name === 'preventOverflow';
1961 }).boundaries;
1962
1963 if (refRect.bottom < bound.top || refRect.left > bound.right || refRect.top > bound.bottom || refRect.right < bound.left) {
1964 // Avoid unnecessary DOM access if visibility hasn't changed
1965 if (data.hide === true) {
1966 return data;
1967 }
1968
1969 data.hide = true;
1970 data.attributes['x-out-of-boundaries'] = '';
1971 } else {
1972 // Avoid unnecessary DOM access if visibility hasn't changed
1973 if (data.hide === false) {
1974 return data;
1975 }
1976
1977 data.hide = false;
1978 data.attributes['x-out-of-boundaries'] = false;
1979 }
1980
1981 return data;
1982 }
1983
1984 /**
1985 * @function
1986 * @memberof Modifiers
1987 * @argument {Object} data - The data object generated by `update` method
1988 * @argument {Object} options - Modifiers configuration and options
1989 * @returns {Object} The data object, properly modified
1990 */
1991 function inner(data) {
1992 var placement = data.placement;
1993 var basePlacement = placement.split('-')[0];
1994 var _data$offsets = data.offsets,
1995 popper = _data$offsets.popper,
1996 reference = _data$offsets.reference;
1997
1998 var isHoriz = ['left', 'right'].indexOf(basePlacement) !== -1;
1999
2000 var subtractLength = ['top', 'left'].indexOf(basePlacement) === -1;
2001
2002 popper[isHoriz ? 'left' : 'top'] = reference[basePlacement] - (subtractLength ? popper[isHoriz ? 'width' : 'height'] : 0);
2003
2004 data.placement = getOppositePlacement(placement);
2005 data.offsets.popper = getClientRect(popper);
2006
2007 return data;
2008 }
2009
2010 /**
2011 * Modifier function, each modifier can have a function of this type assigned
2012 * to its `fn` property.<br />
2013 * These functions will be called on each update, this means that you must
2014 * make sure they are performant enough to avoid performance bottlenecks.
2015 *
2016 * @function ModifierFn
2017 * @argument {dataObject} data - The data object generated by `update` method
2018 * @argument {Object} options - Modifiers configuration and options
2019 * @returns {dataObject} The data object, properly modified
2020 */
2021
2022 /**
2023 * Modifiers are plugins used to alter the behavior of your poppers.<br />
2024 * Popper.js uses a set of 9 modifiers to provide all the basic functionalities
2025 * needed by the library.
2026 *
2027 * Usually you don't want to override the `order`, `fn` and `onLoad` props.
2028 * All the other properties are configurations that could be tweaked.
2029 * @namespace modifiers
2030 */
2031 var modifiers = {
2032 /**
2033 * Modifier used to shift the popper on the start or end of its reference
2034 * element.<br />
2035 * It will read the variation of the `placement` property.<br />
2036 * It can be one either `-end` or `-start`.
2037 * @memberof modifiers
2038 * @inner
2039 */
2040 shift: {
2041 /** @prop {number} order=100 - Index used to define the order of execution */
2042 order: 100,
2043 /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2044 enabled: true,
2045 /** @prop {ModifierFn} */
2046 fn: shift
2047 },
2048
2049 /**
2050 * The `offset` modifier can shift your popper on both its axis.
2051 *
2052 * It accepts the following units:
2053 * - `px` or unit-less, interpreted as pixels
2054 * - `%` or `%r`, percentage relative to the length of the reference element
2055 * - `%p`, percentage relative to the length of the popper element
2056 * - `vw`, CSS viewport width unit
2057 * - `vh`, CSS viewport height unit
2058 *
2059 * For length is intended the main axis relative to the placement of the popper.<br />
2060 * This means that if the placement is `top` or `bottom`, the length will be the
2061 * `width`. In case of `left` or `right`, it will be the `height`.
2062 *
2063 * You can provide a single value (as `Number` or `String`), or a pair of values
2064 * as `String` divided by a comma or one (or more) white spaces.<br />
2065 * The latter is a deprecated method because it leads to confusion and will be
2066 * removed in v2.<br />
2067 * Additionally, it accepts additions and subtractions between different units.
2068 * Note that multiplications and divisions aren't supported.
2069 *
2070 * Valid examples are:
2071 * ```
2072 * 10
2073 * '10%'
2074 * '10, 10'
2075 * '10%, 10'
2076 * '10 + 10%'
2077 * '10 - 5vh + 3%'
2078 * '-10px + 5vh, 5px - 6%'
2079 * ```
2080 * > **NB**: If you desire to apply offsets to your poppers in a way that may make them overlap
2081 * > with their reference element, unfortunately, you will have to disable the `flip` modifier.
2082 * > You can read more on this at this [issue](https://github.com/FezVrasta/popper.js/issues/373).
2083 *
2084 * @memberof modifiers
2085 * @inner
2086 */
2087 offset: {
2088 /** @prop {number} order=200 - Index used to define the order of execution */
2089 order: 200,
2090 /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2091 enabled: true,
2092 /** @prop {ModifierFn} */
2093 fn: offset,
2094 /** @prop {Number|String} offset=0
2095 * The offset value as described in the modifier description
2096 */
2097 offset: 0
2098 },
2099
2100 /**
2101 * Modifier used to prevent the popper from being positioned outside the boundary.
2102 *
2103 * A scenario exists where the reference itself is not within the boundaries.<br />
2104 * We can say it has "escaped the boundaries" — or just "escaped".<br />
2105 * In this case we need to decide whether the popper should either:
2106 *
2107 * - detach from the reference and remain "trapped" in the boundaries, or
2108 * - if it should ignore the boundary and "escape with its reference"
2109 *
2110 * When `escapeWithReference` is set to`true` and reference is completely
2111 * outside its boundaries, the popper will overflow (or completely leave)
2112 * the boundaries in order to remain attached to the edge of the reference.
2113 *
2114 * @memberof modifiers
2115 * @inner
2116 */
2117 preventOverflow: {
2118 /** @prop {number} order=300 - Index used to define the order of execution */
2119 order: 300,
2120 /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2121 enabled: true,
2122 /** @prop {ModifierFn} */
2123 fn: preventOverflow,
2124 /**
2125 * @prop {Array} [priority=['left','right','top','bottom']]
2126 * Popper will try to prevent overflow following these priorities by default,
2127 * then, it could overflow on the left and on top of the `boundariesElement`
2128 */
2129 priority: ['left', 'right', 'top', 'bottom'],
2130 /**
2131 * @prop {number} padding=5
2132 * Amount of pixel used to define a minimum distance between the boundaries
2133 * and the popper. This makes sure the popper always has a little padding
2134 * between the edges of its container
2135 */
2136 padding: 5,
2137 /**
2138 * @prop {String|HTMLElement} boundariesElement='scrollParent'
2139 * Boundaries used by the modifier. Can be `scrollParent`, `window`,
2140 * `viewport` or any DOM element.
2141 */
2142 boundariesElement: 'scrollParent'
2143 },
2144
2145 /**
2146 * Modifier used to make sure the reference and its popper stay near each other
2147 * without leaving any gap between the two. Especially useful when the arrow is
2148 * enabled and you want to ensure that it points to its reference element.
2149 * It cares only about the first axis. You can still have poppers with margin
2150 * between the popper and its reference element.
2151 * @memberof modifiers
2152 * @inner
2153 */
2154 keepTogether: {
2155 /** @prop {number} order=400 - Index used to define the order of execution */
2156 order: 400,
2157 /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2158 enabled: true,
2159 /** @prop {ModifierFn} */
2160 fn: keepTogether
2161 },
2162
2163 /**
2164 * This modifier is used to move the `arrowElement` of the popper to make
2165 * sure it is positioned between the reference element and its popper element.
2166 * It will read the outer size of the `arrowElement` node to detect how many
2167 * pixels of conjunction are needed.
2168 *
2169 * It has no effect if no `arrowElement` is provided.
2170 * @memberof modifiers
2171 * @inner
2172 */
2173 arrow: {
2174 /** @prop {number} order=500 - Index used to define the order of execution */
2175 order: 500,
2176 /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2177 enabled: true,
2178 /** @prop {ModifierFn} */
2179 fn: arrow,
2180 /** @prop {String|HTMLElement} element='[x-arrow]' - Selector or node used as arrow */
2181 element: '[x-arrow]'
2182 },
2183
2184 /**
2185 * Modifier used to flip the popper's placement when it starts to overlap its
2186 * reference element.
2187 *
2188 * Requires the `preventOverflow` modifier before it in order to work.
2189 *
2190 * **NOTE:** this modifier will interrupt the current update cycle and will
2191 * restart it if it detects the need to flip the placement.
2192 * @memberof modifiers
2193 * @inner
2194 */
2195 flip: {
2196 /** @prop {number} order=600 - Index used to define the order of execution */
2197 order: 600,
2198 /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2199 enabled: true,
2200 /** @prop {ModifierFn} */
2201 fn: flip,
2202 /**
2203 * @prop {String|Array} behavior='flip'
2204 * The behavior used to change the popper's placement. It can be one of
2205 * `flip`, `clockwise`, `counterclockwise` or an array with a list of valid
2206 * placements (with optional variations)
2207 */
2208 behavior: 'flip',
2209 /**
2210 * @prop {number} padding=5
2211 * The popper will flip if it hits the edges of the `boundariesElement`
2212 */
2213 padding: 5,
2214 /**
2215 * @prop {String|HTMLElement} boundariesElement='viewport'
2216 * The element which will define the boundaries of the popper position.
2217 * The popper will never be placed outside of the defined boundaries
2218 * (except if `keepTogether` is enabled)
2219 */
2220 boundariesElement: 'viewport'
2221 },
2222
2223 /**
2224 * Modifier used to make the popper flow toward the inner of the reference element.
2225 * By default, when this modifier is disabled, the popper will be placed outside
2226 * the reference element.
2227 * @memberof modifiers
2228 * @inner
2229 */
2230 inner: {
2231 /** @prop {number} order=700 - Index used to define the order of execution */
2232 order: 700,
2233 /** @prop {Boolean} enabled=false - Whether the modifier is enabled or not */
2234 enabled: false,
2235 /** @prop {ModifierFn} */
2236 fn: inner
2237 },
2238
2239 /**
2240 * Modifier used to hide the popper when its reference element is outside of the
2241 * popper boundaries. It will set a `x-out-of-boundaries` attribute which can
2242 * be used to hide with a CSS selector the popper when its reference is
2243 * out of boundaries.
2244 *
2245 * Requires the `preventOverflow` modifier before it in order to work.
2246 * @memberof modifiers
2247 * @inner
2248 */
2249 hide: {
2250 /** @prop {number} order=800 - Index used to define the order of execution */
2251 order: 800,
2252 /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2253 enabled: true,
2254 /** @prop {ModifierFn} */
2255 fn: hide
2256 },
2257
2258 /**
2259 * Computes the style that will be applied to the popper element to gets
2260 * properly positioned.
2261 *
2262 * Note that this modifier will not touch the DOM, it just prepares the styles
2263 * so that `applyStyle` modifier can apply it. This separation is useful
2264 * in case you need to replace `applyStyle` with a custom implementation.
2265 *
2266 * This modifier has `850` as `order` value to maintain backward compatibility
2267 * with previous versions of Popper.js. Expect the modifiers ordering method
2268 * to change in future major versions of the library.
2269 *
2270 * @memberof modifiers
2271 * @inner
2272 */
2273 computeStyle: {
2274 /** @prop {number} order=850 - Index used to define the order of execution */
2275 order: 850,
2276 /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2277 enabled: true,
2278 /** @prop {ModifierFn} */
2279 fn: computeStyle,
2280 /**
2281 * @prop {Boolean} gpuAcceleration=true
2282 * If true, it uses the CSS 3D transformation to position the popper.
2283 * Otherwise, it will use the `top` and `left` properties
2284 */
2285 gpuAcceleration: true,
2286 /**
2287 * @prop {string} [x='bottom']
2288 * Where to anchor the X axis (`bottom` or `top`). AKA X offset origin.
2289 * Change this if your popper should grow in a direction different from `bottom`
2290 */
2291 x: 'bottom',
2292 /**
2293 * @prop {string} [x='left']
2294 * Where to anchor the Y axis (`left` or `right`). AKA Y offset origin.
2295 * Change this if your popper should grow in a direction different from `right`
2296 */
2297 y: 'right'
2298 },
2299
2300 /**
2301 * Applies the computed styles to the popper element.
2302 *
2303 * All the DOM manipulations are limited to this modifier. This is useful in case
2304 * you want to integrate Popper.js inside a framework or view library and you
2305 * want to delegate all the DOM manipulations to it.
2306 *
2307 * Note that if you disable this modifier, you must make sure the popper element
2308 * has its position set to `absolute` before Popper.js can do its work!
2309 *
2310 * Just disable this modifier and define your own to achieve the desired effect.
2311 *
2312 * @memberof modifiers
2313 * @inner
2314 */
2315 applyStyle: {
2316 /** @prop {number} order=900 - Index used to define the order of execution */
2317 order: 900,
2318 /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2319 enabled: true,
2320 /** @prop {ModifierFn} */
2321 fn: applyStyle,
2322 /** @prop {Function} */
2323 onLoad: applyStyleOnLoad,
2324 /**
2325 * @deprecated since version 1.10.0, the property moved to `computeStyle` modifier
2326 * @prop {Boolean} gpuAcceleration=true
2327 * If true, it uses the CSS 3D transformation to position the popper.
2328 * Otherwise, it will use the `top` and `left` properties
2329 */
2330 gpuAcceleration: undefined
2331 }
2332 };
2333
2334 /**
2335 * The `dataObject` is an object containing all the information used by Popper.js.
2336 * This object is passed to modifiers and to the `onCreate` and `onUpdate` callbacks.
2337 * @name dataObject
2338 * @property {Object} data.instance The Popper.js instance
2339 * @property {String} data.placement Placement applied to popper
2340 * @property {String} data.originalPlacement Placement originally defined on init
2341 * @property {Boolean} data.flipped True if popper has been flipped by flip modifier
2342 * @property {Boolean} data.hide True if the reference element is out of boundaries, useful to know when to hide the popper
2343 * @property {HTMLElement} data.arrowElement Node used as arrow by arrow modifier
2344 * @property {Object} data.styles Any CSS property defined here will be applied to the popper. It expects the JavaScript nomenclature (eg. `marginBottom`)
2345 * @property {Object} data.arrowStyles Any CSS property defined here will be applied to the popper arrow. It expects the JavaScript nomenclature (eg. `marginBottom`)
2346 * @property {Object} data.boundaries Offsets of the popper boundaries
2347 * @property {Object} data.offsets The measurements of popper, reference and arrow elements
2348 * @property {Object} data.offsets.popper `top`, `left`, `width`, `height` values
2349 * @property {Object} data.offsets.reference `top`, `left`, `width`, `height` values
2350 * @property {Object} data.offsets.arrow] `top` and `left` offsets, only one of them will be different from 0
2351 */
2352
2353 /**
2354 * Default options provided to Popper.js constructor.<br />
2355 * These can be overridden using the `options` argument of Popper.js.<br />
2356 * To override an option, simply pass an object with the same
2357 * structure of the `options` object, as the 3rd argument. For example:
2358 * ```
2359 * new Popper(ref, pop, {
2360 * modifiers: {
2361 * preventOverflow: { enabled: false }
2362 * }
2363 * })
2364 * ```
2365 * @type {Object}
2366 * @static
2367 * @memberof Popper
2368 */
2369 var Defaults = {
2370 /**
2371 * Popper's placement.
2372 * @prop {Popper.placements} placement='bottom'
2373 */
2374 placement: 'bottom',
2375
2376 /**
2377 * Set this to true if you want popper to position it self in 'fixed' mode
2378 * @prop {Boolean} positionFixed=false
2379 */
2380 positionFixed: false,
2381
2382 /**
2383 * Whether events (resize, scroll) are initially enabled.
2384 * @prop {Boolean} eventsEnabled=true
2385 */
2386 eventsEnabled: true,
2387
2388 /**
2389 * Set to true if you want to automatically remove the popper when
2390 * you call the `destroy` method.
2391 * @prop {Boolean} removeOnDestroy=false
2392 */
2393 removeOnDestroy: false,
2394
2395 /**
2396 * Callback called when the popper is created.<br />
2397 * By default, it is set to no-op.<br />
2398 * Access Popper.js instance with `data.instance`.
2399 * @prop {onCreate}
2400 */
2401 onCreate: function onCreate() {},
2402
2403 /**
2404 * Callback called when the popper is updated. This callback is not called
2405 * on the initialization/creation of the popper, but only on subsequent
2406 * updates.<br />
2407 * By default, it is set to no-op.<br />
2408 * Access Popper.js instance with `data.instance`.
2409 * @prop {onUpdate}
2410 */
2411 onUpdate: function onUpdate() {},
2412
2413 /**
2414 * List of modifiers used to modify the offsets before they are applied to the popper.
2415 * They provide most of the functionalities of Popper.js.
2416 * @prop {modifiers}
2417 */
2418 modifiers: modifiers
2419 };
2420
2421 /**
2422 * @callback onCreate
2423 * @param {dataObject} data
2424 */
2425
2426 /**
2427 * @callback onUpdate
2428 * @param {dataObject} data
2429 */
2430
2431 // Utils
2432 // Methods
2433 var Popper = function () {
2434 /**
2435 * Creates a new Popper.js instance.
2436 * @class Popper
2437 * @param {HTMLElement|referenceObject} reference - The reference element used to position the popper
2438 * @param {HTMLElement} popper - The HTML element used as the popper
2439 * @param {Object} options - Your custom options to override the ones defined in [Defaults](#defaults)
2440 * @return {Object} instance - The generated Popper.js instance
2441 */
2442 function Popper(reference, popper) {
2443 var _this = this;
2444
2445 var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
2446 classCallCheck(this, Popper);
2447
2448 this.scheduleUpdate = function () {
2449 return requestAnimationFrame(_this.update);
2450 };
2451
2452 // make update() debounced, so that it only runs at most once-per-tick
2453 this.update = debounce(this.update.bind(this));
2454
2455 // with {} we create a new object with the options inside it
2456 this.options = _extends({}, Popper.Defaults, options);
2457
2458 // init state
2459 this.state = {
2460 isDestroyed: false,
2461 isCreated: false,
2462 scrollParents: []
2463 };
2464
2465 // get reference and popper elements (allow jQuery wrappers)
2466 this.reference = reference && reference.jquery ? reference[0] : reference;
2467 this.popper = popper && popper.jquery ? popper[0] : popper;
2468
2469 // Deep merge modifiers options
2470 this.options.modifiers = {};
2471 Object.keys(_extends({}, Popper.Defaults.modifiers, options.modifiers)).forEach(function (name) {
2472 _this.options.modifiers[name] = _extends({}, Popper.Defaults.modifiers[name] || {}, options.modifiers ? options.modifiers[name] : {});
2473 });
2474
2475 // Refactoring modifiers' list (Object => Array)
2476 this.modifiers = Object.keys(this.options.modifiers).map(function (name) {
2477 return _extends({
2478 name: name
2479 }, _this.options.modifiers[name]);
2480 })
2481 // sort the modifiers by order
2482 .sort(function (a, b) {
2483 return a.order - b.order;
2484 });
2485
2486 // modifiers have the ability to execute arbitrary code when Popper.js get inited
2487 // such code is executed in the same order of its modifier
2488 // they could add new properties to their options configuration
2489 // BE AWARE: don't add options to `options.modifiers.name` but to `modifierOptions`!
2490 this.modifiers.forEach(function (modifierOptions) {
2491 if (modifierOptions.enabled && isFunction(modifierOptions.onLoad)) {
2492 modifierOptions.onLoad(_this.reference, _this.popper, _this.options, modifierOptions, _this.state);
2493 }
2494 });
2495
2496 // fire the first update to position the popper in the right place
2497 this.update();
2498
2499 var eventsEnabled = this.options.eventsEnabled;
2500 if (eventsEnabled) {
2501 // setup event listeners, they will take care of update the position in specific situations
2502 this.enableEventListeners();
2503 }
2504
2505 this.state.eventsEnabled = eventsEnabled;
2506 }
2507
2508 // We can't use class properties because they don't get listed in the
2509 // class prototype and break stuff like Sinon stubs
2510
2511
2512 createClass(Popper, [{
2513 key: 'update',
2514 value: function update$$1() {
2515 return update.call(this);
2516 }
2517 }, {
2518 key: 'destroy',
2519 value: function destroy$$1() {
2520 return destroy.call(this);
2521 }
2522 }, {
2523 key: 'enableEventListeners',
2524 value: function enableEventListeners$$1() {
2525 return enableEventListeners.call(this);
2526 }
2527 }, {
2528 key: 'disableEventListeners',
2529 value: function disableEventListeners$$1() {
2530 return disableEventListeners.call(this);
2531 }
2532
2533 /**
2534 * Schedules an update. It will run on the next UI update available.
2535 * @method scheduleUpdate
2536 * @memberof Popper
2537 */
2538
2539
2540 /**
2541 * Collection of utilities useful when writing custom modifiers.
2542 * Starting from version 1.7, this method is available only if you
2543 * include `popper-utils.js` before `popper.js`.
2544 *
2545 * **DEPRECATION**: This way to access PopperUtils is deprecated
2546 * and will be removed in v2! Use the PopperUtils module directly instead.
2547 * Due to the high instability of the methods contained in Utils, we can't
2548 * guarantee them to follow semver. Use them at your own risk!
2549 * @static
2550 * @private
2551 * @type {Object}
2552 * @deprecated since version 1.8
2553 * @member Utils
2554 * @memberof Popper
2555 */
2556
2557 }]);
2558 return Popper;
2559 }();
2560
2561 /**
2562 * The `referenceObject` is an object that provides an interface compatible with Popper.js
2563 * and lets you use it as replacement of a real DOM node.<br />
2564 * You can use this method to position a popper relatively to a set of coordinates
2565 * in case you don't have a DOM node to use as reference.
2566 *
2567 * ```
2568 * new Popper(referenceObject, popperNode);
2569 * ```
2570 *
2571 * NB: This feature isn't supported in Internet Explorer 10.
2572 * @name referenceObject
2573 * @property {Function} data.getBoundingClientRect
2574 * A function that returns a set of coordinates compatible with the native `getBoundingClientRect` method.
2575 * @property {number} data.clientWidth
2576 * An ES6 getter that will return the width of the virtual reference element.
2577 * @property {number} data.clientHeight
2578 * An ES6 getter that will return the height of the virtual reference element.
2579 */
2580
2581
2582 Popper.Utils = (typeof window !== 'undefined' ? window : global).PopperUtils;
2583 Popper.placements = placements;
2584 Popper.Defaults = Defaults;
2585
2586 return Popper;
2587
2588 })));
2589 //# sourceMappingURL=popper.js.map
2590