Merge branch 'MDL-81713-main' of https://github.com/junpataleta/moodle
[moodle.git] / lib / amd / src / popper.js
blobecefee60c1499dd634ac484c09514963d2f2ac3b
1 /**!
2  * @fileOverview Kickass library to create and place poppers near their reference elements.
3  * @version 1.12.6
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';
31 var isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';
32 var longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox'];
33 var timeoutDuration = 0;
34 for (var i = 0; i < longerTimeoutBrowsers.length; i += 1) {
35   if (isBrowser && navigator.userAgent.indexOf(longerTimeoutBrowsers[i]) >= 0) {
36     timeoutDuration = 1;
37     break;
38   }
41 function microtaskDebounce(fn) {
42   var called = false;
43   return function () {
44     if (called) {
45       return;
46     }
47     called = true;
48     Promise.resolve().then(function () {
49       called = false;
50       fn();
51     });
52   };
55 function taskDebounce(fn) {
56   var scheduled = false;
57   return function () {
58     if (!scheduled) {
59       scheduled = true;
60       setTimeout(function () {
61         scheduled = false;
62         fn();
63       }, timeoutDuration);
64     }
65   };
68 var supportsMicroTasks = isBrowser && window.Promise;
70 /**
71 * Create a debounced version of a method, that's asynchronously deferred
72 * but called in the minimum time possible.
74 * @method
75 * @memberof Popper.Utils
76 * @argument {Function} fn
77 * @returns {Function}
79 var debounce = supportsMicroTasks ? microtaskDebounce : taskDebounce;
81 /**
82  * Check if the given variable is a function
83  * @method
84  * @memberof Popper.Utils
85  * @argument {Any} functionToCheck - variable to check
86  * @returns {Boolean} answer to: is a function?
87  */
88 function isFunction(functionToCheck) {
89   var getType = {};
90   return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
93 /**
94  * Get CSS computed property of the given element
95  * @method
96  * @memberof Popper.Utils
97  * @argument {Eement} element
98  * @argument {String} property
99  */
100 function getStyleComputedProperty(element, property) {
101   if (element.nodeType !== 1) {
102     return [];
103   }
104   // NOTE: 1 DOM access here
105   var css = window.getComputedStyle(element, null);
106   return property ? css[property] : css;
110  * Returns the parentNode or the host of the element
111  * @method
112  * @memberof Popper.Utils
113  * @argument {Element} element
114  * @returns {Element} parent
115  */
116 function getParentNode(element) {
117   if (element.nodeName === 'HTML') {
118     return element;
119   }
120   return element.parentNode || element.host;
124  * Returns the scrolling parent of the given element
125  * @method
126  * @memberof Popper.Utils
127  * @argument {Element} element
128  * @returns {Element} scroll parent
129  */
130 function getScrollParent(element) {
131   // Return body, `getScroll` will take care to get the correct `scrollTop` from it
132   if (!element) {
133     return window.document.body;
134   }
136   switch (element.nodeName) {
137     case 'HTML':
138     case 'BODY':
139       return element.ownerDocument.body;
140     case '#document':
141       return element.body;
142   }
144   // Firefox want us to check `-x` and `-y` variations as well
146   var _getStyleComputedProp = getStyleComputedProperty(element),
147       overflow = _getStyleComputedProp.overflow,
148       overflowX = _getStyleComputedProp.overflowX,
149       overflowY = _getStyleComputedProp.overflowY;
151   if (/(auto|scroll)/.test(overflow + overflowY + overflowX)) {
152     return element;
153   }
155   return getScrollParent(getParentNode(element));
159  * Returns the offset parent of the given element
160  * @method
161  * @memberof Popper.Utils
162  * @argument {Element} element
163  * @returns {Element} offset parent
164  */
165 function getOffsetParent(element) {
166   // NOTE: 1 DOM access here
167   var offsetParent = element && element.offsetParent;
168   var nodeName = offsetParent && offsetParent.nodeName;
170   if (!nodeName || nodeName === 'BODY' || nodeName === 'HTML') {
171     if (element) {
172       return element.ownerDocument.documentElement;
173     }
175     return window.document.documentElement;
176   }
178   // .offsetParent will return the closest TD or TABLE in case
179   // no offsetParent is present, I hate this job...
180   if (['TD', 'TABLE'].indexOf(offsetParent.nodeName) !== -1 && getStyleComputedProperty(offsetParent, 'position') === 'static') {
181     return getOffsetParent(offsetParent);
182   }
184   return offsetParent;
187 function isOffsetContainer(element) {
188   var nodeName = element.nodeName;
190   if (nodeName === 'BODY') {
191     return false;
192   }
193   return nodeName === 'HTML' || getOffsetParent(element.firstElementChild) === element;
197  * Finds the root node (document, shadowDOM root) of the given element
198  * @method
199  * @memberof Popper.Utils
200  * @argument {Element} node
201  * @returns {Element} root node
202  */
203 function getRoot(node) {
204   if (node.parentNode !== null) {
205     return getRoot(node.parentNode);
206   }
208   return node;
212  * Finds the offset parent common to the two provided nodes
213  * @method
214  * @memberof Popper.Utils
215  * @argument {Element} element1
216  * @argument {Element} element2
217  * @returns {Element} common offset parent
218  */
219 function findCommonOffsetParent(element1, element2) {
220   // This check is needed to avoid errors in case one of the elements isn't defined for any reason
221   if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) {
222     return window.document.documentElement;
223   }
225   // Here we make sure to give as "start" the element that comes first in the DOM
226   var order = element1.compareDocumentPosition(element2) & Node.DOCUMENT_POSITION_FOLLOWING;
227   var start = order ? element1 : element2;
228   var end = order ? element2 : element1;
230   // Get common ancestor container
231   var range = document.createRange();
232   range.setStart(start, 0);
233   range.setEnd(end, 0);
234   var commonAncestorContainer = range.commonAncestorContainer;
236   // Both nodes are inside #document
238   if (element1 !== commonAncestorContainer && element2 !== commonAncestorContainer || start.contains(end)) {
239     if (isOffsetContainer(commonAncestorContainer)) {
240       return commonAncestorContainer;
241     }
243     return getOffsetParent(commonAncestorContainer);
244   }
246   // one of the nodes is inside shadowDOM, find which one
247   var element1root = getRoot(element1);
248   if (element1root.host) {
249     return findCommonOffsetParent(element1root.host, element2);
250   } else {
251     return findCommonOffsetParent(element1, getRoot(element2).host);
252   }
256  * Gets the scroll value of the given element in the given side (top and left)
257  * @method
258  * @memberof Popper.Utils
259  * @argument {Element} element
260  * @argument {String} side `top` or `left`
261  * @returns {number} amount of scrolled pixels
262  */
263 function getScroll(element) {
264   var side = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'top';
266   var upperSide = side === 'top' ? 'scrollTop' : 'scrollLeft';
267   var nodeName = element.nodeName;
269   if (nodeName === 'BODY' || nodeName === 'HTML') {
270     var html = element.ownerDocument.documentElement;
271     var scrollingElement = element.ownerDocument.scrollingElement || html;
272     return scrollingElement[upperSide];
273   }
275   return element[upperSide];
279  * Sum or subtract the element scroll values (left and top) from a given rect object
280  * @method
281  * @memberof Popper.Utils
282  * @param {Object} rect - Rect object you want to change
283  * @param {HTMLElement} element - The element from the function reads the scroll values
284  * @param {Boolean} subtract - set to true if you want to subtract the scroll values
285  * @return {Object} rect - The modifier rect object
286  */
287 function includeScroll(rect, element) {
288   var subtract = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
290   var scrollTop = getScroll(element, 'top');
291   var scrollLeft = getScroll(element, 'left');
292   var modifier = subtract ? -1 : 1;
293   rect.top += scrollTop * modifier;
294   rect.bottom += scrollTop * modifier;
295   rect.left += scrollLeft * modifier;
296   rect.right += scrollLeft * modifier;
297   return rect;
301  * Helper to detect borders of a given element
302  * @method
303  * @memberof Popper.Utils
304  * @param {CSSStyleDeclaration} styles
305  * Result of `getStyleComputedProperty` on the given element
306  * @param {String} axis - `x` or `y`
307  * @return {number} borders - The borders size of the given axis
308  */
310 function getBordersSize(styles, axis) {
311   var sideA = axis === 'x' ? 'Left' : 'Top';
312   var sideB = sideA === 'Left' ? 'Right' : 'Bottom';
314   return +styles['border' + sideA + 'Width'].split('px')[0] + +styles['border' + sideB + 'Width'].split('px')[0];
318  * Tells if you are running Internet Explorer 10
319  * @method
320  * @memberof Popper.Utils
321  * @returns {Boolean} isIE10
322  */
323 var isIE10 = undefined;
325 var isIE10$1 = function () {
326   if (isIE10 === undefined) {
327     isIE10 = navigator.appVersion.indexOf('MSIE 10') !== -1;
328   }
329   return isIE10;
332 function getSize(axis, body, html, computedStyle) {
333   return Math.max(body['offset' + axis], body['scroll' + axis], html['client' + axis], html['offset' + axis], html['scroll' + axis], isIE10$1() ? html['offset' + axis] + computedStyle['margin' + (axis === 'Height' ? 'Top' : 'Left')] + computedStyle['margin' + (axis === 'Height' ? 'Bottom' : 'Right')] : 0);
336 function getWindowSizes() {
337   var body = window.document.body;
338   var html = window.document.documentElement;
339   var computedStyle = isIE10$1() && window.getComputedStyle(html);
341   return {
342     height: getSize('Height', body, html, computedStyle),
343     width: getSize('Width', body, html, computedStyle)
344   };
347 var classCallCheck = function (instance, Constructor) {
348   if (!(instance instanceof Constructor)) {
349     throw new TypeError("Cannot call a class as a function");
350   }
353 var createClass = function () {
354   function defineProperties(target, props) {
355     for (var i = 0; i < props.length; i++) {
356       var descriptor = props[i];
357       descriptor.enumerable = descriptor.enumerable || false;
358       descriptor.configurable = true;
359       if ("value" in descriptor) descriptor.writable = true;
360       Object.defineProperty(target, descriptor.key, descriptor);
361     }
362   }
364   return function (Constructor, protoProps, staticProps) {
365     if (protoProps) defineProperties(Constructor.prototype, protoProps);
366     if (staticProps) defineProperties(Constructor, staticProps);
367     return Constructor;
368   };
369 }();
375 var defineProperty = function (obj, key, value) {
376   if (key in obj) {
377     Object.defineProperty(obj, key, {
378       value: value,
379       enumerable: true,
380       configurable: true,
381       writable: true
382     });
383   } else {
384     obj[key] = value;
385   }
387   return obj;
390 var _extends = Object.assign || function (target) {
391   for (var i = 1; i < arguments.length; i++) {
392     var source = arguments[i];
394     for (var key in source) {
395       if (Object.prototype.hasOwnProperty.call(source, key)) {
396         target[key] = source[key];
397       }
398     }
399   }
401   return target;
405  * Given element offsets, generate an output similar to getBoundingClientRect
406  * @method
407  * @memberof Popper.Utils
408  * @argument {Object} offsets
409  * @returns {Object} ClientRect like output
410  */
411 function getClientRect(offsets) {
412   return _extends({}, offsets, {
413     right: offsets.left + offsets.width,
414     bottom: offsets.top + offsets.height
415   });
419  * Get bounding client rect of given element
420  * @method
421  * @memberof Popper.Utils
422  * @param {HTMLElement} element
423  * @return {Object} client rect
424  */
425 function getBoundingClientRect(element) {
426   var rect = {};
428   // IE10 10 FIX: Please, don't ask, the element isn't
429   // considered in DOM in some circumstances...
430   // This isn't reproducible in IE10 compatibility mode of IE11
431   if (isIE10$1()) {
432     try {
433       rect = element.getBoundingClientRect();
434       var scrollTop = getScroll(element, 'top');
435       var scrollLeft = getScroll(element, 'left');
436       rect.top += scrollTop;
437       rect.left += scrollLeft;
438       rect.bottom += scrollTop;
439       rect.right += scrollLeft;
440     } catch (err) {}
441   } else {
442     rect = element.getBoundingClientRect();
443   }
445   var result = {
446     left: rect.left,
447     top: rect.top,
448     width: rect.right - rect.left,
449     height: rect.bottom - rect.top
450   };
452   // subtract scrollbar size from sizes
453   var sizes = element.nodeName === 'HTML' ? getWindowSizes() : {};
454   var width = sizes.width || element.clientWidth || result.right - result.left;
455   var height = sizes.height || element.clientHeight || result.bottom - result.top;
457   var horizScrollbar = element.offsetWidth - width;
458   var vertScrollbar = element.offsetHeight - height;
460   // if an hypothetical scrollbar is detected, we must be sure it's not a `border`
461   // we make this check conditional for performance reasons
462   if (horizScrollbar || vertScrollbar) {
463     var styles = getStyleComputedProperty(element);
464     horizScrollbar -= getBordersSize(styles, 'x');
465     vertScrollbar -= getBordersSize(styles, 'y');
467     result.width -= horizScrollbar;
468     result.height -= vertScrollbar;
469   }
471   return getClientRect(result);
474 function getOffsetRectRelativeToArbitraryNode(children, parent) {
475   var isIE10 = isIE10$1();
476   var isHTML = parent.nodeName === 'HTML';
477   var childrenRect = getBoundingClientRect(children);
478   var parentRect = getBoundingClientRect(parent);
479   var scrollParent = getScrollParent(children);
481   var styles = getStyleComputedProperty(parent);
482   var borderTopWidth = +styles.borderTopWidth.split('px')[0];
483   var borderLeftWidth = +styles.borderLeftWidth.split('px')[0];
485   var offsets = getClientRect({
486     top: childrenRect.top - parentRect.top - borderTopWidth,
487     left: childrenRect.left - parentRect.left - borderLeftWidth,
488     width: childrenRect.width,
489     height: childrenRect.height
490   });
491   offsets.marginTop = 0;
492   offsets.marginLeft = 0;
494   // Subtract margins of documentElement in case it's being used as parent
495   // we do this only on HTML because it's the only element that behaves
496   // differently when margins are applied to it. The margins are included in
497   // the box of the documentElement, in the other cases not.
498   if (!isIE10 && isHTML) {
499     var marginTop = +styles.marginTop.split('px')[0];
500     var marginLeft = +styles.marginLeft.split('px')[0];
502     offsets.top -= borderTopWidth - marginTop;
503     offsets.bottom -= borderTopWidth - marginTop;
504     offsets.left -= borderLeftWidth - marginLeft;
505     offsets.right -= borderLeftWidth - marginLeft;
507     // Attach marginTop and marginLeft because in some circumstances we may need them
508     offsets.marginTop = marginTop;
509     offsets.marginLeft = marginLeft;
510   }
512   if (isIE10 ? parent.contains(scrollParent) : parent === scrollParent && scrollParent.nodeName !== 'BODY') {
513     offsets = includeScroll(offsets, parent);
514   }
516   return offsets;
519 function getViewportOffsetRectRelativeToArtbitraryNode(element) {
520   var html = element.ownerDocument.documentElement;
521   var relativeOffset = getOffsetRectRelativeToArbitraryNode(element, html);
522   var width = Math.max(html.clientWidth, window.innerWidth || 0);
523   var height = Math.max(html.clientHeight, window.innerHeight || 0);
525   var scrollTop = getScroll(html);
526   var scrollLeft = getScroll(html, 'left');
528   var offset = {
529     top: scrollTop - relativeOffset.top + relativeOffset.marginTop,
530     left: scrollLeft - relativeOffset.left + relativeOffset.marginLeft,
531     width: width,
532     height: height
533   };
535   return getClientRect(offset);
539  * Check if the given element is fixed or is inside a fixed parent
540  * @method
541  * @memberof Popper.Utils
542  * @argument {Element} element
543  * @argument {Element} customContainer
544  * @returns {Boolean} answer to "isFixed?"
545  */
546 function isFixed(element) {
547   var nodeName = element.nodeName;
548   if (nodeName === 'BODY' || nodeName === 'HTML') {
549     return false;
550   }
551   if (getStyleComputedProperty(element, 'position') === 'fixed') {
552     return true;
553   }
554   return isFixed(getParentNode(element));
558  * Computed the boundaries limits and return them
559  * @method
560  * @memberof Popper.Utils
561  * @param {HTMLElement} popper
562  * @param {HTMLElement} reference
563  * @param {number} padding
564  * @param {HTMLElement} boundariesElement - Element used to define the boundaries
565  * @returns {Object} Coordinates of the boundaries
566  */
567 function getBoundaries(popper, reference, padding, boundariesElement) {
568   // NOTE: 1 DOM access here
569   var boundaries = { top: 0, left: 0 };
570   var offsetParent = findCommonOffsetParent(popper, reference);
572   // Handle viewport case
573   if (boundariesElement === 'viewport') {
574     boundaries = getViewportOffsetRectRelativeToArtbitraryNode(offsetParent);
575   } else {
576     // Handle other cases based on DOM element used as boundaries
577     var boundariesNode = void 0;
578     if (boundariesElement === 'scrollParent') {
579       boundariesNode = getScrollParent(getParentNode(popper));
580       if (boundariesNode.nodeName === 'BODY') {
581         boundariesNode = popper.ownerDocument.documentElement;
582       }
583     } else if (boundariesElement === 'window') {
584       boundariesNode = popper.ownerDocument.documentElement;
585     } else {
586       boundariesNode = boundariesElement;
587     }
589     var offsets = getOffsetRectRelativeToArbitraryNode(boundariesNode, offsetParent);
591     // In case of HTML, we need a different computation
592     if (boundariesNode.nodeName === 'HTML' && !isFixed(offsetParent)) {
593       var _getWindowSizes = getWindowSizes(),
594           height = _getWindowSizes.height,
595           width = _getWindowSizes.width;
597       boundaries.top += offsets.top - offsets.marginTop;
598       boundaries.bottom = height + offsets.top;
599       boundaries.left += offsets.left - offsets.marginLeft;
600       boundaries.right = width + offsets.left;
601     } else {
602       // for all the other DOM elements, this one is good
603       boundaries = offsets;
604     }
605   }
607   // Add paddings
608   boundaries.left += padding;
609   boundaries.top += padding;
610   boundaries.right -= padding;
611   boundaries.bottom -= padding;
613   return boundaries;
616 function getArea(_ref) {
617   var width = _ref.width,
618       height = _ref.height;
620   return width * height;
624  * Utility used to transform the `auto` placement to the placement with more
625  * available space.
626  * @method
627  * @memberof Popper.Utils
628  * @argument {Object} data - The data object generated by update method
629  * @argument {Object} options - Modifiers configuration and options
630  * @returns {Object} The data object, properly modified
631  */
632 function computeAutoPlacement(placement, refRect, popper, reference, boundariesElement) {
633   var padding = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0;
635   if (placement.indexOf('auto') === -1) {
636     return placement;
637   }
639   var boundaries = getBoundaries(popper, reference, padding, boundariesElement);
641   var rects = {
642     top: {
643       width: boundaries.width,
644       height: refRect.top - boundaries.top
645     },
646     right: {
647       width: boundaries.right - refRect.right,
648       height: boundaries.height
649     },
650     bottom: {
651       width: boundaries.width,
652       height: boundaries.bottom - refRect.bottom
653     },
654     left: {
655       width: refRect.left - boundaries.left,
656       height: boundaries.height
657     }
658   };
660   var sortedAreas = Object.keys(rects).map(function (key) {
661     return _extends({
662       key: key
663     }, rects[key], {
664       area: getArea(rects[key])
665     });
666   }).sort(function (a, b) {
667     return b.area - a.area;
668   });
670   var filteredAreas = sortedAreas.filter(function (_ref2) {
671     var width = _ref2.width,
672         height = _ref2.height;
673     return width >= popper.clientWidth && height >= popper.clientHeight;
674   });
676   var computedPlacement = filteredAreas.length > 0 ? filteredAreas[0].key : sortedAreas[0].key;
678   var variation = placement.split('-')[1];
680   return computedPlacement + (variation ? '-' + variation : '');
684  * Get offsets to the reference element
685  * @method
686  * @memberof Popper.Utils
687  * @param {Object} state
688  * @param {Element} popper - the popper element
689  * @param {Element} reference - the reference element (the popper will be relative to this)
690  * @returns {Object} An object containing the offsets which will be applied to the popper
691  */
692 function getReferenceOffsets(state, popper, reference) {
693   var commonOffsetParent = findCommonOffsetParent(popper, reference);
694   return getOffsetRectRelativeToArbitraryNode(reference, commonOffsetParent);
698  * Get the outer sizes of the given element (offset size + margins)
699  * @method
700  * @memberof Popper.Utils
701  * @argument {Element} element
702  * @returns {Object} object containing width and height properties
703  */
704 function getOuterSizes(element) {
705   var styles = window.getComputedStyle(element);
706   var x = parseFloat(styles.marginTop) + parseFloat(styles.marginBottom);
707   var y = parseFloat(styles.marginLeft) + parseFloat(styles.marginRight);
708   var result = {
709     width: element.offsetWidth + y,
710     height: element.offsetHeight + x
711   };
712   return result;
716  * Get the opposite placement of the given one
717  * @method
718  * @memberof Popper.Utils
719  * @argument {String} placement
720  * @returns {String} flipped placement
721  */
722 function getOppositePlacement(placement) {
723   var hash = { left: 'right', right: 'left', bottom: 'top', top: 'bottom' };
724   return placement.replace(/left|right|bottom|top/g, function (matched) {
725     return hash[matched];
726   });
730  * Get offsets to the popper
731  * @method
732  * @memberof Popper.Utils
733  * @param {Object} position - CSS position the Popper will get applied
734  * @param {HTMLElement} popper - the popper element
735  * @param {Object} referenceOffsets - the reference offsets (the popper will be relative to this)
736  * @param {String} placement - one of the valid placement options
737  * @returns {Object} popperOffsets - An object containing the offsets which will be applied to the popper
738  */
739 function getPopperOffsets(popper, referenceOffsets, placement) {
740   placement = placement.split('-')[0];
742   // Get popper node sizes
743   var popperRect = getOuterSizes(popper);
745   // Add position, width and height to our offsets object
746   var popperOffsets = {
747     width: popperRect.width,
748     height: popperRect.height
749   };
751   // depending by the popper placement we have to compute its offsets slightly differently
752   var isHoriz = ['right', 'left'].indexOf(placement) !== -1;
753   var mainSide = isHoriz ? 'top' : 'left';
754   var secondarySide = isHoriz ? 'left' : 'top';
755   var measurement = isHoriz ? 'height' : 'width';
756   var secondaryMeasurement = !isHoriz ? 'height' : 'width';
758   popperOffsets[mainSide] = referenceOffsets[mainSide] + referenceOffsets[measurement] / 2 - popperRect[measurement] / 2;
759   if (placement === secondarySide) {
760     popperOffsets[secondarySide] = referenceOffsets[secondarySide] - popperRect[secondaryMeasurement];
761   } else {
762     popperOffsets[secondarySide] = referenceOffsets[getOppositePlacement(secondarySide)];
763   }
765   return popperOffsets;
769  * Mimics the `find` method of Array
770  * @method
771  * @memberof Popper.Utils
772  * @argument {Array} arr
773  * @argument prop
774  * @argument value
775  * @returns index or -1
776  */
777 function find(arr, check) {
778   // use native find if supported
779   if (Array.prototype.find) {
780     return arr.find(check);
781   }
783   // use `filter` to obtain the same behavior of `find`
784   return arr.filter(check)[0];
788  * Return the index of the matching object
789  * @method
790  * @memberof Popper.Utils
791  * @argument {Array} arr
792  * @argument prop
793  * @argument value
794  * @returns index or -1
795  */
796 function findIndex(arr, prop, value) {
797   // use native findIndex if supported
798   if (Array.prototype.findIndex) {
799     return arr.findIndex(function (cur) {
800       return cur[prop] === value;
801     });
802   }
804   // use `find` + `indexOf` if `findIndex` isn't supported
805   var match = find(arr, function (obj) {
806     return obj[prop] === value;
807   });
808   return arr.indexOf(match);
812  * Loop trough the list of modifiers and run them in order,
813  * each of them will then edit the data object.
814  * @method
815  * @memberof Popper.Utils
816  * @param {dataObject} data
817  * @param {Array} modifiers
818  * @param {String} ends - Optional modifier name used as stopper
819  * @returns {dataObject}
820  */
821 function runModifiers(modifiers, data, ends) {
822   var modifiersToRun = ends === undefined ? modifiers : modifiers.slice(0, findIndex(modifiers, 'name', ends));
824   modifiersToRun.forEach(function (modifier) {
825     if (modifier['function']) {
826       // eslint-disable-line dot-notation
827       console.warn('`modifier.function` is deprecated, use `modifier.fn`!');
828     }
829     var fn = modifier['function'] || modifier.fn; // eslint-disable-line dot-notation
830     if (modifier.enabled && isFunction(fn)) {
831       // Add properties to offsets to make them a complete clientRect object
832       // we do this before each modifier to make sure the previous one doesn't
833       // mess with these values
834       data.offsets.popper = getClientRect(data.offsets.popper);
835       data.offsets.reference = getClientRect(data.offsets.reference);
837       data = fn(data, modifier);
838     }
839   });
841   return data;
845  * Updates the position of the popper, computing the new offsets and applying
846  * the new style.<br />
847  * Prefer `scheduleUpdate` over `update` because of performance reasons.
848  * @method
849  * @memberof Popper
850  */
851 function update() {
852   // if popper is destroyed, don't perform any further update
853   if (this.state.isDestroyed) {
854     return;
855   }
857   var data = {
858     instance: this,
859     styles: {},
860     arrowStyles: {},
861     attributes: {},
862     flipped: false,
863     offsets: {}
864   };
866   // compute reference element offsets
867   data.offsets.reference = getReferenceOffsets(this.state, this.popper, this.reference);
869   // compute auto placement, store placement inside the data object,
870   // modifiers will be able to edit `placement` if needed
871   // and refer to originalPlacement to know the original value
872   data.placement = computeAutoPlacement(this.options.placement, data.offsets.reference, this.popper, this.reference, this.options.modifiers.flip.boundariesElement, this.options.modifiers.flip.padding);
874   // store the computed placement inside `originalPlacement`
875   data.originalPlacement = data.placement;
877   // compute the popper offsets
878   data.offsets.popper = getPopperOffsets(this.popper, data.offsets.reference, data.placement);
879   data.offsets.popper.position = 'absolute';
881   // run the modifiers
882   data = runModifiers(this.modifiers, data);
884   // the first `update` will call `onCreate` callback
885   // the other ones will call `onUpdate` callback
886   if (!this.state.isCreated) {
887     this.state.isCreated = true;
888     this.options.onCreate(data);
889   } else {
890     this.options.onUpdate(data);
891   }
895  * Helper used to know if the given modifier is enabled.
896  * @method
897  * @memberof Popper.Utils
898  * @returns {Boolean}
899  */
900 function isModifierEnabled(modifiers, modifierName) {
901   return modifiers.some(function (_ref) {
902     var name = _ref.name,
903         enabled = _ref.enabled;
904     return enabled && name === modifierName;
905   });
909  * Get the prefixed supported property name
910  * @method
911  * @memberof Popper.Utils
912  * @argument {String} property (camelCase)
913  * @returns {String} prefixed property (camelCase or PascalCase, depending on the vendor prefix)
914  */
915 function getSupportedPropertyName(property) {
916   var prefixes = [false, 'ms', 'Webkit', 'Moz', 'O'];
917   var upperProp = property.charAt(0).toUpperCase() + property.slice(1);
919   for (var i = 0; i < prefixes.length - 1; i++) {
920     var prefix = prefixes[i];
921     var toCheck = prefix ? '' + prefix + upperProp : property;
922     if (typeof window.document.body.style[toCheck] !== 'undefined') {
923       return toCheck;
924     }
925   }
926   return null;
930  * Destroy the popper
931  * @method
932  * @memberof Popper
933  */
934 function destroy() {
935   this.state.isDestroyed = true;
937   // touch DOM only if `applyStyle` modifier is enabled
938   if (isModifierEnabled(this.modifiers, 'applyStyle')) {
939     this.popper.removeAttribute('x-placement');
940     this.popper.style.left = '';
941     this.popper.style.position = '';
942     this.popper.style.top = '';
943     this.popper.style[getSupportedPropertyName('transform')] = '';
944   }
946   this.disableEventListeners();
948   // remove the popper if user explicity asked for the deletion on destroy
949   // do not use `remove` because IE11 doesn't support it
950   if (this.options.removeOnDestroy) {
951     this.popper.parentNode.removeChild(this.popper);
952   }
953   return this;
957  * Get the window associated with the element
958  * @argument {Element} element
959  * @returns {Window}
960  */
961 function getWindow(element) {
962   var ownerDocument = element.ownerDocument;
963   return ownerDocument ? ownerDocument.defaultView : window;
966 function attachToScrollParents(scrollParent, event, callback, scrollParents) {
967   var isBody = scrollParent.nodeName === 'BODY';
968   var target = isBody ? scrollParent.ownerDocument.defaultView : scrollParent;
969   target.addEventListener(event, callback, { passive: true });
971   if (!isBody) {
972     attachToScrollParents(getScrollParent(target.parentNode), event, callback, scrollParents);
973   }
974   scrollParents.push(target);
978  * Setup needed event listeners used to update the popper position
979  * @method
980  * @memberof Popper.Utils
981  * @private
982  */
983 function setupEventListeners(reference, options, state, updateBound) {
984   // Resize event listener on window
985   state.updateBound = updateBound;
986   getWindow(reference).addEventListener('resize', state.updateBound, { passive: true });
988   // Scroll event listener on scroll parents
989   var scrollElement = getScrollParent(reference);
990   attachToScrollParents(scrollElement, 'scroll', state.updateBound, state.scrollParents);
991   state.scrollElement = scrollElement;
992   state.eventsEnabled = true;
994   return state;
998  * It will add resize/scroll events and start recalculating
999  * position of the popper element when they are triggered.
1000  * @method
1001  * @memberof Popper
1002  */
1003 function enableEventListeners() {
1004   if (!this.state.eventsEnabled) {
1005     this.state = setupEventListeners(this.reference, this.options, this.state, this.scheduleUpdate);
1006   }
1010  * Remove event listeners used to update the popper position
1011  * @method
1012  * @memberof Popper.Utils
1013  * @private
1014  */
1015 function removeEventListeners(reference, state) {
1016   // Remove resize event listener on window
1017   getWindow(reference).removeEventListener('resize', state.updateBound);
1019   // Remove scroll event listener on scroll parents
1020   state.scrollParents.forEach(function (target) {
1021     target.removeEventListener('scroll', state.updateBound);
1022   });
1024   // Reset state
1025   state.updateBound = null;
1026   state.scrollParents = [];
1027   state.scrollElement = null;
1028   state.eventsEnabled = false;
1029   return state;
1033  * It will remove resize/scroll events and won't recalculate popper position
1034  * when they are triggered. It also won't trigger onUpdate callback anymore,
1035  * unless you call `update` method manually.
1036  * @method
1037  * @memberof Popper
1038  */
1039 function disableEventListeners() {
1040   if (this.state.eventsEnabled) {
1041     window.cancelAnimationFrame(this.scheduleUpdate);
1042     this.state = removeEventListeners(this.reference, this.state);
1043   }
1047  * Tells if a given input is a number
1048  * @method
1049  * @memberof Popper.Utils
1050  * @param {*} input to check
1051  * @return {Boolean}
1052  */
1053 function isNumeric(n) {
1054   return n !== '' && !isNaN(parseFloat(n)) && isFinite(n);
1058  * Set the style to the given popper
1059  * @method
1060  * @memberof Popper.Utils
1061  * @argument {Element} element - Element to apply the style to
1062  * @argument {Object} styles
1063  * Object with a list of properties and values which will be applied to the element
1064  */
1065 function setStyles(element, styles) {
1066   Object.keys(styles).forEach(function (prop) {
1067     var unit = '';
1068     // add unit if the value is numeric and is one of the following
1069     if (['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== -1 && isNumeric(styles[prop])) {
1070       unit = 'px';
1071     }
1072     element.style[prop] = styles[prop] + unit;
1073   });
1077  * Set the attributes to the given popper
1078  * @method
1079  * @memberof Popper.Utils
1080  * @argument {Element} element - Element to apply the attributes to
1081  * @argument {Object} styles
1082  * Object with a list of properties and values which will be applied to the element
1083  */
1084 function setAttributes(element, attributes) {
1085   Object.keys(attributes).forEach(function (prop) {
1086     var value = attributes[prop];
1087     if (value !== false) {
1088       element.setAttribute(prop, attributes[prop]);
1089     } else {
1090       element.removeAttribute(prop);
1091     }
1092   });
1096  * @function
1097  * @memberof Modifiers
1098  * @argument {Object} data - The data object generated by `update` method
1099  * @argument {Object} data.styles - List of style properties - values to apply to popper element
1100  * @argument {Object} data.attributes - List of attribute properties - values to apply to popper element
1101  * @argument {Object} options - Modifiers configuration and options
1102  * @returns {Object} The same data object
1103  */
1104 function applyStyle(data) {
1105   // any property present in `data.styles` will be applied to the popper,
1106   // in this way we can make the 3rd party modifiers add custom styles to it
1107   // Be aware, modifiers could override the properties defined in the previous
1108   // lines of this modifier!
1109   setStyles(data.instance.popper, data.styles);
1111   // any property present in `data.attributes` will be applied to the popper,
1112   // they will be set as HTML attributes of the element
1113   setAttributes(data.instance.popper, data.attributes);
1115   // if arrowElement is defined and arrowStyles has some properties
1116   if (data.arrowElement && Object.keys(data.arrowStyles).length) {
1117     setStyles(data.arrowElement, data.arrowStyles);
1118   }
1120   return data;
1124  * Set the x-placement attribute before everything else because it could be used
1125  * to add margins to the popper margins needs to be calculated to get the
1126  * correct popper offsets.
1127  * @method
1128  * @memberof Popper.modifiers
1129  * @param {HTMLElement} reference - The reference element used to position the popper
1130  * @param {HTMLElement} popper - The HTML element used as popper.
1131  * @param {Object} options - Popper.js options
1132  */
1133 function applyStyleOnLoad(reference, popper, options, modifierOptions, state) {
1134   // compute reference element offsets
1135   var referenceOffsets = getReferenceOffsets(state, popper, reference);
1137   // compute auto placement, store placement inside the data object,
1138   // modifiers will be able to edit `placement` if needed
1139   // and refer to originalPlacement to know the original value
1140   var placement = computeAutoPlacement(options.placement, referenceOffsets, popper, reference, options.modifiers.flip.boundariesElement, options.modifiers.flip.padding);
1142   popper.setAttribute('x-placement', placement);
1144   // Apply `position` to popper before anything else because
1145   // without the position applied we can't guarantee correct computations
1146   setStyles(popper, { position: 'absolute' });
1148   return options;
1152  * @function
1153  * @memberof Modifiers
1154  * @argument {Object} data - The data object generated by `update` method
1155  * @argument {Object} options - Modifiers configuration and options
1156  * @returns {Object} The data object, properly modified
1157  */
1158 function computeStyle(data, options) {
1159   var x = options.x,
1160       y = options.y;
1161   var popper = data.offsets.popper;
1163   // Remove this legacy support in Popper.js v2
1165   var legacyGpuAccelerationOption = find(data.instance.modifiers, function (modifier) {
1166     return modifier.name === 'applyStyle';
1167   }).gpuAcceleration;
1168   if (legacyGpuAccelerationOption !== undefined) {
1169     console.warn('WARNING: `gpuAcceleration` option moved to `computeStyle` modifier and will not be supported in future versions of Popper.js!');
1170   }
1171   var gpuAcceleration = legacyGpuAccelerationOption !== undefined ? legacyGpuAccelerationOption : options.gpuAcceleration;
1173   var offsetParent = getOffsetParent(data.instance.popper);
1174   var offsetParentRect = getBoundingClientRect(offsetParent);
1176   // Styles
1177   var styles = {
1178     position: popper.position
1179   };
1181   // floor sides to avoid blurry text
1182   var offsets = {
1183     left: Math.floor(popper.left),
1184     top: Math.floor(popper.top),
1185     bottom: Math.floor(popper.bottom),
1186     right: Math.floor(popper.right)
1187   };
1189   var sideA = x === 'bottom' ? 'top' : 'bottom';
1190   var sideB = y === 'right' ? 'left' : 'right';
1192   // if gpuAcceleration is set to `true` and transform is supported,
1193   //  we use `translate3d` to apply the position to the popper we
1194   // automatically use the supported prefixed version if needed
1195   var prefixedProperty = getSupportedPropertyName('transform');
1197   // now, let's make a step back and look at this code closely (wtf?)
1198   // If the content of the popper grows once it's been positioned, it
1199   // may happen that the popper gets misplaced because of the new content
1200   // overflowing its reference element
1201   // To avoid this problem, we provide two options (x and y), which allow
1202   // the consumer to define the offset origin.
1203   // If we position a popper on top of a reference element, we can set
1204   // `x` to `top` to make the popper grow towards its top instead of
1205   // its bottom.
1206   var left = void 0,
1207       top = void 0;
1208   if (sideA === 'bottom') {
1209     top = -offsetParentRect.height + offsets.bottom;
1210   } else {
1211     top = offsets.top;
1212   }
1213   if (sideB === 'right') {
1214     left = -offsetParentRect.width + offsets.right;
1215   } else {
1216     left = offsets.left;
1217   }
1218   if (gpuAcceleration && prefixedProperty) {
1219     styles[prefixedProperty] = 'translate3d(' + left + 'px, ' + top + 'px, 0)';
1220     styles[sideA] = 0;
1221     styles[sideB] = 0;
1222     styles.willChange = 'transform';
1223   } else {
1224     // othwerise, we use the standard `top`, `left`, `bottom` and `right` properties
1225     var invertTop = sideA === 'bottom' ? -1 : 1;
1226     var invertLeft = sideB === 'right' ? -1 : 1;
1227     styles[sideA] = top * invertTop;
1228     styles[sideB] = left * invertLeft;
1229     styles.willChange = sideA + ', ' + sideB;
1230   }
1232   // Attributes
1233   var attributes = {
1234     'x-placement': data.placement
1235   };
1237   // Update `data` attributes, styles and arrowStyles
1238   data.attributes = _extends({}, attributes, data.attributes);
1239   data.styles = _extends({}, styles, data.styles);
1240   data.arrowStyles = _extends({}, data.offsets.arrow, data.arrowStyles);
1242   return data;
1246  * Helper used to know if the given modifier depends from another one.<br />
1247  * It checks if the needed modifier is listed and enabled.
1248  * @method
1249  * @memberof Popper.Utils
1250  * @param {Array} modifiers - list of modifiers
1251  * @param {String} requestingName - name of requesting modifier
1252  * @param {String} requestedName - name of requested modifier
1253  * @returns {Boolean}
1254  */
1255 function isModifierRequired(modifiers, requestingName, requestedName) {
1256   var requesting = find(modifiers, function (_ref) {
1257     var name = _ref.name;
1258     return name === requestingName;
1259   });
1261   var isRequired = !!requesting && modifiers.some(function (modifier) {
1262     return modifier.name === requestedName && modifier.enabled && modifier.order < requesting.order;
1263   });
1265   if (!isRequired) {
1266     var _requesting = '`' + requestingName + '`';
1267     var requested = '`' + requestedName + '`';
1268     console.warn(requested + ' modifier is required by ' + _requesting + ' modifier in order to work, be sure to include it before ' + _requesting + '!');
1269   }
1270   return isRequired;
1274  * @function
1275  * @memberof Modifiers
1276  * @argument {Object} data - The data object generated by update method
1277  * @argument {Object} options - Modifiers configuration and options
1278  * @returns {Object} The data object, properly modified
1279  */
1280 function arrow(data, options) {
1281   // arrow depends on keepTogether in order to work
1282   if (!isModifierRequired(data.instance.modifiers, 'arrow', 'keepTogether')) {
1283     return data;
1284   }
1286   var arrowElement = options.element;
1288   // if arrowElement is a string, suppose it's a CSS selector
1289   if (typeof arrowElement === 'string') {
1290     arrowElement = data.instance.popper.querySelector(arrowElement);
1292     // if arrowElement is not found, don't run the modifier
1293     if (!arrowElement) {
1294       return data;
1295     }
1296   } else {
1297     // if the arrowElement isn't a query selector we must check that the
1298     // provided DOM node is child of its popper node
1299     if (!data.instance.popper.contains(arrowElement)) {
1300       console.warn('WARNING: `arrow.element` must be child of its popper element!');
1301       return data;
1302     }
1303   }
1305   var placement = data.placement.split('-')[0];
1306   var _data$offsets = data.offsets,
1307       popper = _data$offsets.popper,
1308       reference = _data$offsets.reference;
1310   var isVertical = ['left', 'right'].indexOf(placement) !== -1;
1312   var len = isVertical ? 'height' : 'width';
1313   var sideCapitalized = isVertical ? 'Top' : 'Left';
1314   var side = sideCapitalized.toLowerCase();
1315   var altSide = isVertical ? 'left' : 'top';
1316   var opSide = isVertical ? 'bottom' : 'right';
1317   var arrowElementSize = getOuterSizes(arrowElement)[len];
1319   //
1320   // extends keepTogether behavior making sure the popper and its
1321   // reference have enough pixels in conjuction
1322   //
1324   // top/left side
1325   if (reference[opSide] - arrowElementSize < popper[side]) {
1326     data.offsets.popper[side] -= popper[side] - (reference[opSide] - arrowElementSize);
1327   }
1328   // bottom/right side
1329   if (reference[side] + arrowElementSize > popper[opSide]) {
1330     data.offsets.popper[side] += reference[side] + arrowElementSize - popper[opSide];
1331   }
1333   // compute center of the popper
1334   var center = reference[side] + reference[len] / 2 - arrowElementSize / 2;
1336   // Compute the sideValue using the updated popper offsets
1337   // take popper margin in account because we don't have this info available
1338   var popperMarginSide = getStyleComputedProperty(data.instance.popper, 'margin' + sideCapitalized).replace('px', '');
1339   var sideValue = center - getClientRect(data.offsets.popper)[side] - popperMarginSide;
1341   // prevent arrowElement from being placed not contiguously to its popper
1342   sideValue = Math.max(Math.min(popper[len] - arrowElementSize, sideValue), 0);
1344   data.arrowElement = arrowElement;
1345   data.offsets.arrow = {};
1346   data.offsets.arrow[side] = Math.round(sideValue);
1347   data.offsets.arrow[altSide] = ''; // make sure to unset any eventual altSide value from the DOM node
1349   return data;
1353  * Get the opposite placement variation of the given one
1354  * @method
1355  * @memberof Popper.Utils
1356  * @argument {String} placement variation
1357  * @returns {String} flipped placement variation
1358  */
1359 function getOppositeVariation(variation) {
1360   if (variation === 'end') {
1361     return 'start';
1362   } else if (variation === 'start') {
1363     return 'end';
1364   }
1365   return variation;
1369  * List of accepted placements to use as values of the `placement` option.<br />
1370  * Valid placements are:
1371  * - `auto`
1372  * - `top`
1373  * - `right`
1374  * - `bottom`
1375  * - `left`
1377  * Each placement can have a variation from this list:
1378  * - `-start`
1379  * - `-end`
1381  * Variations are interpreted easily if you think of them as the left to right
1382  * written languages. Horizontally (`top` and `bottom`), `start` is left and `end`
1383  * is right.<br />
1384  * Vertically (`left` and `right`), `start` is top and `end` is bottom.
1386  * Some valid examples are:
1387  * - `top-end` (on top of reference, right aligned)
1388  * - `right-start` (on right of reference, top aligned)
1389  * - `bottom` (on bottom, centered)
1390  * - `auto-right` (on the side with more space available, alignment depends by placement)
1392  * @static
1393  * @type {Array}
1394  * @enum {String}
1395  * @readonly
1396  * @method placements
1397  * @memberof Popper
1398  */
1399 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'];
1401 // Get rid of `auto` `auto-start` and `auto-end`
1402 var validPlacements = placements.slice(3);
1405  * Given an initial placement, returns all the subsequent placements
1406  * clockwise (or counter-clockwise).
1408  * @method
1409  * @memberof Popper.Utils
1410  * @argument {String} placement - A valid placement (it accepts variations)
1411  * @argument {Boolean} counter - Set to true to walk the placements counterclockwise
1412  * @returns {Array} placements including their variations
1413  */
1414 function clockwise(placement) {
1415   var counter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
1417   var index = validPlacements.indexOf(placement);
1418   var arr = validPlacements.slice(index + 1).concat(validPlacements.slice(0, index));
1419   return counter ? arr.reverse() : arr;
1422 var BEHAVIORS = {
1423   FLIP: 'flip',
1424   CLOCKWISE: 'clockwise',
1425   COUNTERCLOCKWISE: 'counterclockwise'
1429  * @function
1430  * @memberof Modifiers
1431  * @argument {Object} data - The data object generated by update method
1432  * @argument {Object} options - Modifiers configuration and options
1433  * @returns {Object} The data object, properly modified
1434  */
1435 function flip(data, options) {
1436   // if `inner` modifier is enabled, we can't use the `flip` modifier
1437   if (isModifierEnabled(data.instance.modifiers, 'inner')) {
1438     return data;
1439   }
1441   if (data.flipped && data.placement === data.originalPlacement) {
1442     // seems like flip is trying to loop, probably there's not enough space on any of the flippable sides
1443     return data;
1444   }
1446   var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, options.boundariesElement);
1448   var placement = data.placement.split('-')[0];
1449   var placementOpposite = getOppositePlacement(placement);
1450   var variation = data.placement.split('-')[1] || '';
1452   var flipOrder = [];
1454   switch (options.behavior) {
1455     case BEHAVIORS.FLIP:
1456       flipOrder = [placement, placementOpposite];
1457       break;
1458     case BEHAVIORS.CLOCKWISE:
1459       flipOrder = clockwise(placement);
1460       break;
1461     case BEHAVIORS.COUNTERCLOCKWISE:
1462       flipOrder = clockwise(placement, true);
1463       break;
1464     default:
1465       flipOrder = options.behavior;
1466   }
1468   flipOrder.forEach(function (step, index) {
1469     if (placement !== step || flipOrder.length === index + 1) {
1470       return data;
1471     }
1473     placement = data.placement.split('-')[0];
1474     placementOpposite = getOppositePlacement(placement);
1476     var popperOffsets = data.offsets.popper;
1477     var refOffsets = data.offsets.reference;
1479     // using floor because the reference offsets may contain decimals we are not going to consider here
1480     var floor = Math.floor;
1481     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);
1483     var overflowsLeft = floor(popperOffsets.left) < floor(boundaries.left);
1484     var overflowsRight = floor(popperOffsets.right) > floor(boundaries.right);
1485     var overflowsTop = floor(popperOffsets.top) < floor(boundaries.top);
1486     var overflowsBottom = floor(popperOffsets.bottom) > floor(boundaries.bottom);
1488     var overflowsBoundaries = placement === 'left' && overflowsLeft || placement === 'right' && overflowsRight || placement === 'top' && overflowsTop || placement === 'bottom' && overflowsBottom;
1490     // flip the variation if required
1491     var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;
1492     var flippedVariation = !!options.flipVariations && (isVertical && variation === 'start' && overflowsLeft || isVertical && variation === 'end' && overflowsRight || !isVertical && variation === 'start' && overflowsTop || !isVertical && variation === 'end' && overflowsBottom);
1494     if (overlapsRef || overflowsBoundaries || flippedVariation) {
1495       // this boolean to detect any flip loop
1496       data.flipped = true;
1498       if (overlapsRef || overflowsBoundaries) {
1499         placement = flipOrder[index + 1];
1500       }
1502       if (flippedVariation) {
1503         variation = getOppositeVariation(variation);
1504       }
1506       data.placement = placement + (variation ? '-' + variation : '');
1508       // this object contains `position`, we want to preserve it along with
1509       // any additional property we may add in the future
1510       data.offsets.popper = _extends({}, data.offsets.popper, getPopperOffsets(data.instance.popper, data.offsets.reference, data.placement));
1512       data = runModifiers(data.instance.modifiers, data, 'flip');
1513     }
1514   });
1515   return data;
1519  * @function
1520  * @memberof Modifiers
1521  * @argument {Object} data - The data object generated by update method
1522  * @argument {Object} options - Modifiers configuration and options
1523  * @returns {Object} The data object, properly modified
1524  */
1525 function keepTogether(data) {
1526   var _data$offsets = data.offsets,
1527       popper = _data$offsets.popper,
1528       reference = _data$offsets.reference;
1530   var placement = data.placement.split('-')[0];
1531   var floor = Math.floor;
1532   var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;
1533   var side = isVertical ? 'right' : 'bottom';
1534   var opSide = isVertical ? 'left' : 'top';
1535   var measurement = isVertical ? 'width' : 'height';
1537   if (popper[side] < floor(reference[opSide])) {
1538     data.offsets.popper[opSide] = floor(reference[opSide]) - popper[measurement];
1539   }
1540   if (popper[opSide] > floor(reference[side])) {
1541     data.offsets.popper[opSide] = floor(reference[side]);
1542   }
1544   return data;
1548  * Converts a string containing value + unit into a px value number
1549  * @function
1550  * @memberof {modifiers~offset}
1551  * @private
1552  * @argument {String} str - Value + unit string
1553  * @argument {String} measurement - `height` or `width`
1554  * @argument {Object} popperOffsets
1555  * @argument {Object} referenceOffsets
1556  * @returns {Number|String}
1557  * Value in pixels, or original string if no values were extracted
1558  */
1559 function toValue(str, measurement, popperOffsets, referenceOffsets) {
1560   // separate value from unit
1561   var split = str.match(/((?:\-|\+)?\d*\.?\d*)(.*)/);
1562   var value = +split[1];
1563   var unit = split[2];
1565   // If it's not a number it's an operator, I guess
1566   if (!value) {
1567     return str;
1568   }
1570   if (unit.indexOf('%') === 0) {
1571     var element = void 0;
1572     switch (unit) {
1573       case '%p':
1574         element = popperOffsets;
1575         break;
1576       case '%':
1577       case '%r':
1578       default:
1579         element = referenceOffsets;
1580     }
1582     var rect = getClientRect(element);
1583     return rect[measurement] / 100 * value;
1584   } else if (unit === 'vh' || unit === 'vw') {
1585     // if is a vh or vw, we calculate the size based on the viewport
1586     var size = void 0;
1587     if (unit === 'vh') {
1588       size = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
1589     } else {
1590       size = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
1591     }
1592     return size / 100 * value;
1593   } else {
1594     // if is an explicit pixel unit, we get rid of the unit and keep the value
1595     // if is an implicit unit, it's px, and we return just the value
1596     return value;
1597   }
1601  * Parse an `offset` string to extrapolate `x` and `y` numeric offsets.
1602  * @function
1603  * @memberof {modifiers~offset}
1604  * @private
1605  * @argument {String} offset
1606  * @argument {Object} popperOffsets
1607  * @argument {Object} referenceOffsets
1608  * @argument {String} basePlacement
1609  * @returns {Array} a two cells array with x and y offsets in numbers
1610  */
1611 function parseOffset(offset, popperOffsets, referenceOffsets, basePlacement) {
1612   var offsets = [0, 0];
1614   // Use height if placement is left or right and index is 0 otherwise use width
1615   // in this way the first offset will use an axis and the second one
1616   // will use the other one
1617   var useHeight = ['right', 'left'].indexOf(basePlacement) !== -1;
1619   // Split the offset string to obtain a list of values and operands
1620   // The regex addresses values with the plus or minus sign in front (+10, -20, etc)
1621   var fragments = offset.split(/(\+|\-)/).map(function (frag) {
1622     return frag.trim();
1623   });
1625   // Detect if the offset string contains a pair of values or a single one
1626   // they could be separated by comma or space
1627   var divider = fragments.indexOf(find(fragments, function (frag) {
1628     return frag.search(/,|\s/) !== -1;
1629   }));
1631   if (fragments[divider] && fragments[divider].indexOf(',') === -1) {
1632     console.warn('Offsets separated by white space(s) are deprecated, use a comma (,) instead.');
1633   }
1635   // If divider is found, we divide the list of values and operands to divide
1636   // them by ofset X and Y.
1637   var splitRegex = /\s*,\s*|\s+/;
1638   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];
1640   // Convert the values with units to absolute pixels to allow our computations
1641   ops = ops.map(function (op, index) {
1642     // Most of the units rely on the orientation of the popper
1643     var measurement = (index === 1 ? !useHeight : useHeight) ? 'height' : 'width';
1644     var mergeWithPrevious = false;
1645     return op
1646     // This aggregates any `+` or `-` sign that aren't considered operators
1647     // e.g.: 10 + +5 => [10, +, +5]
1648     .reduce(function (a, b) {
1649       if (a[a.length - 1] === '' && ['+', '-'].indexOf(b) !== -1) {
1650         a[a.length - 1] = b;
1651         mergeWithPrevious = true;
1652         return a;
1653       } else if (mergeWithPrevious) {
1654         a[a.length - 1] += b;
1655         mergeWithPrevious = false;
1656         return a;
1657       } else {
1658         return a.concat(b);
1659       }
1660     }, [])
1661     // Here we convert the string values into number values (in px)
1662     .map(function (str) {
1663       return toValue(str, measurement, popperOffsets, referenceOffsets);
1664     });
1665   });
1667   // Loop trough the offsets arrays and execute the operations
1668   ops.forEach(function (op, index) {
1669     op.forEach(function (frag, index2) {
1670       if (isNumeric(frag)) {
1671         offsets[index] += frag * (op[index2 - 1] === '-' ? -1 : 1);
1672       }
1673     });
1674   });
1675   return offsets;
1679  * @function
1680  * @memberof Modifiers
1681  * @argument {Object} data - The data object generated by update method
1682  * @argument {Object} options - Modifiers configuration and options
1683  * @argument {Number|String} options.offset=0
1684  * The offset value as described in the modifier description
1685  * @returns {Object} The data object, properly modified
1686  */
1687 function offset(data, _ref) {
1688   var offset = _ref.offset;
1689   var placement = data.placement,
1690       _data$offsets = data.offsets,
1691       popper = _data$offsets.popper,
1692       reference = _data$offsets.reference;
1694   var basePlacement = placement.split('-')[0];
1696   var offsets = void 0;
1697   if (isNumeric(+offset)) {
1698     offsets = [+offset, 0];
1699   } else {
1700     offsets = parseOffset(offset, popper, reference, basePlacement);
1701   }
1703   if (basePlacement === 'left') {
1704     popper.top += offsets[0];
1705     popper.left -= offsets[1];
1706   } else if (basePlacement === 'right') {
1707     popper.top += offsets[0];
1708     popper.left += offsets[1];
1709   } else if (basePlacement === 'top') {
1710     popper.left += offsets[0];
1711     popper.top -= offsets[1];
1712   } else if (basePlacement === 'bottom') {
1713     popper.left += offsets[0];
1714     popper.top += offsets[1];
1715   }
1717   data.popper = popper;
1718   return data;
1722  * @function
1723  * @memberof Modifiers
1724  * @argument {Object} data - The data object generated by `update` method
1725  * @argument {Object} options - Modifiers configuration and options
1726  * @returns {Object} The data object, properly modified
1727  */
1728 function preventOverflow(data, options) {
1729   var boundariesElement = options.boundariesElement || getOffsetParent(data.instance.popper);
1731   // If offsetParent is the reference element, we really want to
1732   // go one step up and use the next offsetParent as reference to
1733   // avoid to make this modifier completely useless and look like broken
1734   if (data.instance.reference === boundariesElement) {
1735     boundariesElement = getOffsetParent(boundariesElement);
1736   }
1738   var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, boundariesElement);
1739   options.boundaries = boundaries;
1741   var order = options.priority;
1742   var popper = data.offsets.popper;
1744   var check = {
1745     primary: function primary(placement) {
1746       var value = popper[placement];
1747       if (popper[placement] < boundaries[placement] && !options.escapeWithReference) {
1748         value = Math.max(popper[placement], boundaries[placement]);
1749       }
1750       return defineProperty({}, placement, value);
1751     },
1752     secondary: function secondary(placement) {
1753       var mainSide = placement === 'right' ? 'left' : 'top';
1754       var value = popper[mainSide];
1755       if (popper[placement] > boundaries[placement] && !options.escapeWithReference) {
1756         value = Math.min(popper[mainSide], boundaries[placement] - (placement === 'right' ? popper.width : popper.height));
1757       }
1758       return defineProperty({}, mainSide, value);
1759     }
1760   };
1762   order.forEach(function (placement) {
1763     var side = ['left', 'top'].indexOf(placement) !== -1 ? 'primary' : 'secondary';
1764     popper = _extends({}, popper, check[side](placement));
1765   });
1767   data.offsets.popper = popper;
1769   return data;
1773  * @function
1774  * @memberof Modifiers
1775  * @argument {Object} data - The data object generated by `update` method
1776  * @argument {Object} options - Modifiers configuration and options
1777  * @returns {Object} The data object, properly modified
1778  */
1779 function shift(data) {
1780   var placement = data.placement;
1781   var basePlacement = placement.split('-')[0];
1782   var shiftvariation = placement.split('-')[1];
1784   // if shift shiftvariation is specified, run the modifier
1785   if (shiftvariation) {
1786     var _data$offsets = data.offsets,
1787         reference = _data$offsets.reference,
1788         popper = _data$offsets.popper;
1790     var isVertical = ['bottom', 'top'].indexOf(basePlacement) !== -1;
1791     var side = isVertical ? 'left' : 'top';
1792     var measurement = isVertical ? 'width' : 'height';
1794     var shiftOffsets = {
1795       start: defineProperty({}, side, reference[side]),
1796       end: defineProperty({}, side, reference[side] + reference[measurement] - popper[measurement])
1797     };
1799     data.offsets.popper = _extends({}, popper, shiftOffsets[shiftvariation]);
1800   }
1802   return data;
1806  * @function
1807  * @memberof Modifiers
1808  * @argument {Object} data - The data object generated by update method
1809  * @argument {Object} options - Modifiers configuration and options
1810  * @returns {Object} The data object, properly modified
1811  */
1812 function hide(data) {
1813   if (!isModifierRequired(data.instance.modifiers, 'hide', 'preventOverflow')) {
1814     return data;
1815   }
1817   var refRect = data.offsets.reference;
1818   var bound = find(data.instance.modifiers, function (modifier) {
1819     return modifier.name === 'preventOverflow';
1820   }).boundaries;
1822   if (refRect.bottom < bound.top || refRect.left > bound.right || refRect.top > bound.bottom || refRect.right < bound.left) {
1823     // Avoid unnecessary DOM access if visibility hasn't changed
1824     if (data.hide === true) {
1825       return data;
1826     }
1828     data.hide = true;
1829     data.attributes['x-out-of-boundaries'] = '';
1830   } else {
1831     // Avoid unnecessary DOM access if visibility hasn't changed
1832     if (data.hide === false) {
1833       return data;
1834     }
1836     data.hide = false;
1837     data.attributes['x-out-of-boundaries'] = false;
1838   }
1840   return data;
1844  * @function
1845  * @memberof Modifiers
1846  * @argument {Object} data - The data object generated by `update` method
1847  * @argument {Object} options - Modifiers configuration and options
1848  * @returns {Object} The data object, properly modified
1849  */
1850 function inner(data) {
1851   var placement = data.placement;
1852   var basePlacement = placement.split('-')[0];
1853   var _data$offsets = data.offsets,
1854       popper = _data$offsets.popper,
1855       reference = _data$offsets.reference;
1857   var isHoriz = ['left', 'right'].indexOf(basePlacement) !== -1;
1859   var subtractLength = ['top', 'left'].indexOf(basePlacement) === -1;
1861   popper[isHoriz ? 'left' : 'top'] = reference[basePlacement] - (subtractLength ? popper[isHoriz ? 'width' : 'height'] : 0);
1863   data.placement = getOppositePlacement(placement);
1864   data.offsets.popper = getClientRect(popper);
1866   return data;
1870  * Modifier function, each modifier can have a function of this type assigned
1871  * to its `fn` property.<br />
1872  * These functions will be called on each update, this means that you must
1873  * make sure they are performant enough to avoid performance bottlenecks.
1875  * @function ModifierFn
1876  * @argument {dataObject} data - The data object generated by `update` method
1877  * @argument {Object} options - Modifiers configuration and options
1878  * @returns {dataObject} The data object, properly modified
1879  */
1882  * Modifiers are plugins used to alter the behavior of your poppers.<br />
1883  * Popper.js uses a set of 9 modifiers to provide all the basic functionalities
1884  * needed by the library.
1886  * Usually you don't want to override the `order`, `fn` and `onLoad` props.
1887  * All the other properties are configurations that could be tweaked.
1888  * @namespace modifiers
1889  */
1890 var modifiers = {
1891   /**
1892    * Modifier used to shift the popper on the start or end of its reference
1893    * element.<br />
1894    * It will read the variation of the `placement` property.<br />
1895    * It can be one either `-end` or `-start`.
1896    * @memberof modifiers
1897    * @inner
1898    */
1899   shift: {
1900     /** @prop {number} order=100 - Index used to define the order of execution */
1901     order: 100,
1902     /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
1903     enabled: true,
1904     /** @prop {ModifierFn} */
1905     fn: shift
1906   },
1908   /**
1909    * The `offset` modifier can shift your popper on both its axis.
1910    *
1911    * It accepts the following units:
1912    * - `px` or unitless, interpreted as pixels
1913    * - `%` or `%r`, percentage relative to the length of the reference element
1914    * - `%p`, percentage relative to the length of the popper element
1915    * - `vw`, CSS viewport width unit
1916    * - `vh`, CSS viewport height unit
1917    *
1918    * For length is intended the main axis relative to the placement of the popper.<br />
1919    * This means that if the placement is `top` or `bottom`, the length will be the
1920    * `width`. In case of `left` or `right`, it will be the height.
1921    *
1922    * You can provide a single value (as `Number` or `String`), or a pair of values
1923    * as `String` divided by a comma or one (or more) white spaces.<br />
1924    * The latter is a deprecated method because it leads to confusion and will be
1925    * removed in v2.<br />
1926    * Additionally, it accepts additions and subtractions between different units.
1927    * Note that multiplications and divisions aren't supported.
1928    *
1929    * Valid examples are:
1930    * ```
1931    * 10
1932    * '10%'
1933    * '10, 10'
1934    * '10%, 10'
1935    * '10 + 10%'
1936    * '10 - 5vh + 3%'
1937    * '-10px + 5vh, 5px - 6%'
1938    * ```
1939    * > **NB**: If you desire to apply offsets to your poppers in a way that may make them overlap
1940    * > with their reference element, unfortunately, you will have to disable the `flip` modifier.
1941    * > More on this [reading this issue](https://github.com/FezVrasta/popper.js/issues/373)
1942    *
1943    * @memberof modifiers
1944    * @inner
1945    */
1946   offset: {
1947     /** @prop {number} order=200 - Index used to define the order of execution */
1948     order: 200,
1949     /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
1950     enabled: true,
1951     /** @prop {ModifierFn} */
1952     fn: offset,
1953     /** @prop {Number|String} offset=0
1954      * The offset value as described in the modifier description
1955      */
1956     offset: 0
1957   },
1959   /**
1960    * Modifier used to prevent the popper from being positioned outside the boundary.
1961    *
1962    * An scenario exists where the reference itself is not within the boundaries.<br />
1963    * We can say it has "escaped the boundaries" â€” or just "escaped".<br />
1964    * In this case we need to decide whether the popper should either:
1965    *
1966    * - detach from the reference and remain "trapped" in the boundaries, or
1967    * - if it should ignore the boundary and "escape with its reference"
1968    *
1969    * When `escapeWithReference` is set to`true` and reference is completely
1970    * outside its boundaries, the popper will overflow (or completely leave)
1971    * the boundaries in order to remain attached to the edge of the reference.
1972    *
1973    * @memberof modifiers
1974    * @inner
1975    */
1976   preventOverflow: {
1977     /** @prop {number} order=300 - Index used to define the order of execution */
1978     order: 300,
1979     /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
1980     enabled: true,
1981     /** @prop {ModifierFn} */
1982     fn: preventOverflow,
1983     /**
1984      * @prop {Array} [priority=['left','right','top','bottom']]
1985      * Popper will try to prevent overflow following these priorities by default,
1986      * then, it could overflow on the left and on top of the `boundariesElement`
1987      */
1988     priority: ['left', 'right', 'top', 'bottom'],
1989     /**
1990      * @prop {number} padding=5
1991      * Amount of pixel used to define a minimum distance between the boundaries
1992      * and the popper this makes sure the popper has always a little padding
1993      * between the edges of its container
1994      */
1995     padding: 5,
1996     /**
1997      * @prop {String|HTMLElement} boundariesElement='scrollParent'
1998      * Boundaries used by the modifier, can be `scrollParent`, `window`,
1999      * `viewport` or any DOM element.
2000      */
2001     boundariesElement: 'scrollParent'
2002   },
2004   /**
2005    * Modifier used to make sure the reference and its popper stay near eachothers
2006    * without leaving any gap between the two. Expecially useful when the arrow is
2007    * enabled and you want to assure it to point to its reference element.
2008    * It cares only about the first axis, you can still have poppers with margin
2009    * between the popper and its reference element.
2010    * @memberof modifiers
2011    * @inner
2012    */
2013   keepTogether: {
2014     /** @prop {number} order=400 - Index used to define the order of execution */
2015     order: 400,
2016     /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2017     enabled: true,
2018     /** @prop {ModifierFn} */
2019     fn: keepTogether
2020   },
2022   /**
2023    * This modifier is used to move the `arrowElement` of the popper to make
2024    * sure it is positioned between the reference element and its popper element.
2025    * It will read the outer size of the `arrowElement` node to detect how many
2026    * pixels of conjuction are needed.
2027    *
2028    * It has no effect if no `arrowElement` is provided.
2029    * @memberof modifiers
2030    * @inner
2031    */
2032   arrow: {
2033     /** @prop {number} order=500 - Index used to define the order of execution */
2034     order: 500,
2035     /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2036     enabled: true,
2037     /** @prop {ModifierFn} */
2038     fn: arrow,
2039     /** @prop {String|HTMLElement} element='[x-arrow]' - Selector or node used as arrow */
2040     element: '[x-arrow]'
2041   },
2043   /**
2044    * Modifier used to flip the popper's placement when it starts to overlap its
2045    * reference element.
2046    *
2047    * Requires the `preventOverflow` modifier before it in order to work.
2048    *
2049    * **NOTE:** this modifier will interrupt the current update cycle and will
2050    * restart it if it detects the need to flip the placement.
2051    * @memberof modifiers
2052    * @inner
2053    */
2054   flip: {
2055     /** @prop {number} order=600 - Index used to define the order of execution */
2056     order: 600,
2057     /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2058     enabled: true,
2059     /** @prop {ModifierFn} */
2060     fn: flip,
2061     /**
2062      * @prop {String|Array} behavior='flip'
2063      * The behavior used to change the popper's placement. It can be one of
2064      * `flip`, `clockwise`, `counterclockwise` or an array with a list of valid
2065      * placements (with optional variations).
2066      */
2067     behavior: 'flip',
2068     /**
2069      * @prop {number} padding=5
2070      * The popper will flip if it hits the edges of the `boundariesElement`
2071      */
2072     padding: 5,
2073     /**
2074      * @prop {String|HTMLElement} boundariesElement='viewport'
2075      * The element which will define the boundaries of the popper position,
2076      * the popper will never be placed outside of the defined boundaries
2077      * (except if keepTogether is enabled)
2078      */
2079     boundariesElement: 'viewport'
2080   },
2082   /**
2083    * Modifier used to make the popper flow toward the inner of the reference element.
2084    * By default, when this modifier is disabled, the popper will be placed outside
2085    * the reference element.
2086    * @memberof modifiers
2087    * @inner
2088    */
2089   inner: {
2090     /** @prop {number} order=700 - Index used to define the order of execution */
2091     order: 700,
2092     /** @prop {Boolean} enabled=false - Whether the modifier is enabled or not */
2093     enabled: false,
2094     /** @prop {ModifierFn} */
2095     fn: inner
2096   },
2098   /**
2099    * Modifier used to hide the popper when its reference element is outside of the
2100    * popper boundaries. It will set a `x-out-of-boundaries` attribute which can
2101    * be used to hide with a CSS selector the popper when its reference is
2102    * out of boundaries.
2103    *
2104    * Requires the `preventOverflow` modifier before it in order to work.
2105    * @memberof modifiers
2106    * @inner
2107    */
2108   hide: {
2109     /** @prop {number} order=800 - Index used to define the order of execution */
2110     order: 800,
2111     /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2112     enabled: true,
2113     /** @prop {ModifierFn} */
2114     fn: hide
2115   },
2117   /**
2118    * Computes the style that will be applied to the popper element to gets
2119    * properly positioned.
2120    *
2121    * Note that this modifier will not touch the DOM, it just prepares the styles
2122    * so that `applyStyle` modifier can apply it. This separation is useful
2123    * in case you need to replace `applyStyle` with a custom implementation.
2124    *
2125    * This modifier has `850` as `order` value to maintain backward compatibility
2126    * with previous versions of Popper.js. Expect the modifiers ordering method
2127    * to change in future major versions of the library.
2128    *
2129    * @memberof modifiers
2130    * @inner
2131    */
2132   computeStyle: {
2133     /** @prop {number} order=850 - Index used to define the order of execution */
2134     order: 850,
2135     /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2136     enabled: true,
2137     /** @prop {ModifierFn} */
2138     fn: computeStyle,
2139     /**
2140      * @prop {Boolean} gpuAcceleration=true
2141      * If true, it uses the CSS 3d transformation to position the popper.
2142      * Otherwise, it will use the `top` and `left` properties.
2143      */
2144     gpuAcceleration: true,
2145     /**
2146      * @prop {string} [x='bottom']
2147      * Where to anchor the X axis (`bottom` or `top`). AKA X offset origin.
2148      * Change this if your popper should grow in a direction different from `bottom`
2149      */
2150     x: 'bottom',
2151     /**
2152      * @prop {string} [x='left']
2153      * Where to anchor the Y axis (`left` or `right`). AKA Y offset origin.
2154      * Change this if your popper should grow in a direction different from `right`
2155      */
2156     y: 'right'
2157   },
2159   /**
2160    * Applies the computed styles to the popper element.
2161    *
2162    * All the DOM manipulations are limited to this modifier. This is useful in case
2163    * you want to integrate Popper.js inside a framework or view library and you
2164    * want to delegate all the DOM manipulations to it.
2165    *
2166    * Note that if you disable this modifier, you must make sure the popper element
2167    * has its position set to `absolute` before Popper.js can do its work!
2168    *
2169    * Just disable this modifier and define you own to achieve the desired effect.
2170    *
2171    * @memberof modifiers
2172    * @inner
2173    */
2174   applyStyle: {
2175     /** @prop {number} order=900 - Index used to define the order of execution */
2176     order: 900,
2177     /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2178     enabled: true,
2179     /** @prop {ModifierFn} */
2180     fn: applyStyle,
2181     /** @prop {Function} */
2182     onLoad: applyStyleOnLoad,
2183     /**
2184      * @deprecated since version 1.10.0, the property moved to `computeStyle` modifier
2185      * @prop {Boolean} gpuAcceleration=true
2186      * If true, it uses the CSS 3d transformation to position the popper.
2187      * Otherwise, it will use the `top` and `left` properties.
2188      */
2189     gpuAcceleration: undefined
2190   }
2194  * The `dataObject` is an object containing all the informations used by Popper.js
2195  * this object get passed to modifiers and to the `onCreate` and `onUpdate` callbacks.
2196  * @name dataObject
2197  * @property {Object} data.instance The Popper.js instance
2198  * @property {String} data.placement Placement applied to popper
2199  * @property {String} data.originalPlacement Placement originally defined on init
2200  * @property {Boolean} data.flipped True if popper has been flipped by flip modifier
2201  * @property {Boolean} data.hide True if the reference element is out of boundaries, useful to know when to hide the popper.
2202  * @property {HTMLElement} data.arrowElement Node used as arrow by arrow modifier
2203  * @property {Object} data.styles Any CSS property defined here will be applied to the popper, it expects the JavaScript nomenclature (eg. `marginBottom`)
2204  * @property {Object} data.arrowStyles Any CSS property defined here will be applied to the popper arrow, it expects the JavaScript nomenclature (eg. `marginBottom`)
2205  * @property {Object} data.boundaries Offsets of the popper boundaries
2206  * @property {Object} data.offsets The measurements of popper, reference and arrow elements.
2207  * @property {Object} data.offsets.popper `top`, `left`, `width`, `height` values
2208  * @property {Object} data.offsets.reference `top`, `left`, `width`, `height` values
2209  * @property {Object} data.offsets.arrow] `top` and `left` offsets, only one of them will be different from 0
2210  */
2213  * Default options provided to Popper.js constructor.<br />
2214  * These can be overriden using the `options` argument of Popper.js.<br />
2215  * To override an option, simply pass as 3rd argument an object with the same
2216  * structure of this object, example:
2217  * ```
2218  * new Popper(ref, pop, {
2219  *   modifiers: {
2220  *     preventOverflow: { enabled: false }
2221  *   }
2222  * })
2223  * ```
2224  * @type {Object}
2225  * @static
2226  * @memberof Popper
2227  */
2228 var Defaults = {
2229   /**
2230    * Popper's placement
2231    * @prop {Popper.placements} placement='bottom'
2232    */
2233   placement: 'bottom',
2235   /**
2236    * Whether events (resize, scroll) are initially enabled
2237    * @prop {Boolean} eventsEnabled=true
2238    */
2239   eventsEnabled: true,
2241   /**
2242    * Set to true if you want to automatically remove the popper when
2243    * you call the `destroy` method.
2244    * @prop {Boolean} removeOnDestroy=false
2245    */
2246   removeOnDestroy: false,
2248   /**
2249    * Callback called when the popper is created.<br />
2250    * By default, is set to no-op.<br />
2251    * Access Popper.js instance with `data.instance`.
2252    * @prop {onCreate}
2253    */
2254   onCreate: function onCreate() {},
2256   /**
2257    * Callback called when the popper is updated, this callback is not called
2258    * on the initialization/creation of the popper, but only on subsequent
2259    * updates.<br />
2260    * By default, is set to no-op.<br />
2261    * Access Popper.js instance with `data.instance`.
2262    * @prop {onUpdate}
2263    */
2264   onUpdate: function onUpdate() {},
2266   /**
2267    * List of modifiers used to modify the offsets before they are applied to the popper.
2268    * They provide most of the functionalities of Popper.js
2269    * @prop {modifiers}
2270    */
2271   modifiers: modifiers
2275  * @callback onCreate
2276  * @param {dataObject} data
2277  */
2280  * @callback onUpdate
2281  * @param {dataObject} data
2282  */
2284 // Utils
2285 // Methods
2286 var Popper = function () {
2287   /**
2288    * Create a new Popper.js instance
2289    * @class Popper
2290    * @param {HTMLElement|referenceObject} reference - The reference element used to position the popper
2291    * @param {HTMLElement} popper - The HTML element used as popper.
2292    * @param {Object} options - Your custom options to override the ones defined in [Defaults](#defaults)
2293    * @return {Object} instance - The generated Popper.js instance
2294    */
2295   function Popper(reference, popper) {
2296     var _this = this;
2298     var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
2299     classCallCheck(this, Popper);
2301     this.scheduleUpdate = function () {
2302       return requestAnimationFrame(_this.update);
2303     };
2305     // make update() debounced, so that it only runs at most once-per-tick
2306     this.update = debounce(this.update.bind(this));
2308     // with {} we create a new object with the options inside it
2309     this.options = _extends({}, Popper.Defaults, options);
2311     // init state
2312     this.state = {
2313       isDestroyed: false,
2314       isCreated: false,
2315       scrollParents: []
2316     };
2318     // get reference and popper elements (allow jQuery wrappers)
2319     this.reference = reference && reference.jquery ? reference[0] : reference;
2320     this.popper = popper && popper.jquery ? popper[0] : popper;
2322     // Deep merge modifiers options
2323     this.options.modifiers = {};
2324     Object.keys(_extends({}, Popper.Defaults.modifiers, options.modifiers)).forEach(function (name) {
2325       _this.options.modifiers[name] = _extends({}, Popper.Defaults.modifiers[name] || {}, options.modifiers ? options.modifiers[name] : {});
2326     });
2328     // Refactoring modifiers' list (Object => Array)
2329     this.modifiers = Object.keys(this.options.modifiers).map(function (name) {
2330       return _extends({
2331         name: name
2332       }, _this.options.modifiers[name]);
2333     })
2334     // sort the modifiers by order
2335     .sort(function (a, b) {
2336       return a.order - b.order;
2337     });
2339     // modifiers have the ability to execute arbitrary code when Popper.js get inited
2340     // such code is executed in the same order of its modifier
2341     // they could add new properties to their options configuration
2342     // BE AWARE: don't add options to `options.modifiers.name` but to `modifierOptions`!
2343     this.modifiers.forEach(function (modifierOptions) {
2344       if (modifierOptions.enabled && isFunction(modifierOptions.onLoad)) {
2345         modifierOptions.onLoad(_this.reference, _this.popper, _this.options, modifierOptions, _this.state);
2346       }
2347     });
2349     // fire the first update to position the popper in the right place
2350     this.update();
2352     var eventsEnabled = this.options.eventsEnabled;
2353     if (eventsEnabled) {
2354       // setup event listeners, they will take care of update the position in specific situations
2355       this.enableEventListeners();
2356     }
2358     this.state.eventsEnabled = eventsEnabled;
2359   }
2361   // We can't use class properties because they don't get listed in the
2362   // class prototype and break stuff like Sinon stubs
2365   createClass(Popper, [{
2366     key: 'update',
2367     value: function update$$1() {
2368       return update.call(this);
2369     }
2370   }, {
2371     key: 'destroy',
2372     value: function destroy$$1() {
2373       return destroy.call(this);
2374     }
2375   }, {
2376     key: 'enableEventListeners',
2377     value: function enableEventListeners$$1() {
2378       return enableEventListeners.call(this);
2379     }
2380   }, {
2381     key: 'disableEventListeners',
2382     value: function disableEventListeners$$1() {
2383       return disableEventListeners.call(this);
2384     }
2386     /**
2387      * Schedule an update, it will run on the next UI update available
2388      * @method scheduleUpdate
2389      * @memberof Popper
2390      */
2393     /**
2394      * Collection of utilities useful when writing custom modifiers.
2395      * Starting from version 1.7, this method is available only if you
2396      * include `popper-utils.js` before `popper.js`.
2397      *
2398      * **DEPRECATION**: This way to access PopperUtils is deprecated
2399      * and will be removed in v2! Use the PopperUtils module directly instead.
2400      * Due to the high instability of the methods contained in Utils, we can't
2401      * guarantee them to follow semver. Use them at your own risk!
2402      * @static
2403      * @private
2404      * @type {Object}
2405      * @deprecated since version 1.8
2406      * @member Utils
2407      * @memberof Popper
2408      */
2410   }]);
2411   return Popper;
2412 }();
2415  * The `referenceObject` is an object that provides an interface compatible with Popper.js
2416  * and lets you use it as replacement of a real DOM node.<br />
2417  * You can use this method to position a popper relatively to a set of coordinates
2418  * in case you don't have a DOM node to use as reference.
2420  * ```
2421  * new Popper(referenceObject, popperNode);
2422  * ```
2424  * NB: This feature isn't supported in Internet Explorer 10
2425  * @name referenceObject
2426  * @property {Function} data.getBoundingClientRect
2427  * A function that returns a set of coordinates compatible with the native `getBoundingClientRect` method.
2428  * @property {number} data.clientWidth
2429  * An ES6 getter that will return the width of the virtual reference element.
2430  * @property {number} data.clientHeight
2431  * An ES6 getter that will return the height of the virtual reference element.
2432  */
2435 Popper.Utils = (typeof window !== 'undefined' ? window : global).PopperUtils;
2436 Popper.placements = placements;
2437 Popper.Defaults = Defaults;
2439 return Popper;
2441 })));
2442 //# sourceMappingURL=popper.js.map