PageSourceSearch

https://registrationform.jgu.edu.in/js/popper.js

js jgu.edu.in collected 2026-10-01 10:16:11 UTC 69,057 bytes, 1,883 lines download raw bytes

1/**!
2 * @fileOverview Kickass library to create and place poppers near their reference elements.
3 * @version 1.0.4
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/**
32 * Returns the offset parent of the given element
33 * @method
34 * @memberof Popper.Utils
35 * @argument {Element} element
36 * @returns {Element} offset parent
37 */
38function getOffsetParent(element) {
39    // NOTE: 1 DOM access here
40    const offsetParent = element.offsetParent;
41    const nodeName = offsetParent && offsetParent.nodeName;
42
43    if (!nodeName || nodeName === 'BODY' || nodeName === 'HTML') {
44        return window.document.documentElement;
45    }
46
47    return offsetParent;
48}
49
50/**
51 * Get CSS computed property of the given element
52 * @method
53 * @memberof Popper.Utils
54 * @argument {Eement} element
55 * @argument {String} property
56 */
57function getStyleComputedProperty(element, property) {
58    if (element.nodeType !== 1) {
59        return [];
60    }
61    // NOTE: 1 DOM access here
62    const css = window.getComputedStyle(element, null);
63    return property ? css[property] : css;
64}
65
66/**
67 * Returns the parentNode or the host of the element
68 * @method
69 * @memberof Popper.Utils
70 * @argument {Element} element
71 * @returns {Element} parent
72 */
73function getParentNode(element) {
74    if (element.nodeName === 'HTML') {
75        return element;
76    }
77    return element.parentNode || element.host;
78}
79
80/**
81 * Returns the scrolling parent of the given element
82 * @method
83 * @memberof Popper.Utils
84 * @argument {Element} element
85 * @returns {Element} offset parent
86 */
87function getScrollParent(element) {
88    // Return body, `getScroll` will take care to get the correct `scrollTop` from it
89    if (!element || ['HTML', 'BODY', '#document'].indexOf(element.nodeName) !== -1) {
90        return window.document.body;
91    }
92
93    // Firefox want us to check `-x` and `-y` variations as well
94    const { overflow, overflowX, overflowY } = getStyleComputedProperty(element);
95    if (/(auto|scroll)/.test(overflow + overflowY + overflowX)) {
96        return element;
97    }
98
99    return getScrollParent(getParentNode(element));
100}
101
102function getWindowSizes() {
103    const body = window.document.body;
104    const html = window.document.documentElement;
105    return {
106        height: Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight),
107        width: Math.max(body.scrollWidth, body.offsetWidth, html.clientWidth, html.scrollWidth, html.offsetWidth)
108    };
109}
110
111/**
112 * Get the position of the given element, relative to its offset parent
113 * @method
114 * @memberof Popper.Utils
115 * @param {Element} element
116 * @return {Object} position - Coordinates of the element and its `scrollTop`
117 */
118function getOffsetRect(element) {
119    let elementRect;
120    if (element.nodeName === 'HTML') {
121        const { width, height } = getWindowSizes();
122        elementRect = {
123            width,
124            height,
125            left: 0,
126            top: 0
127        };
128    } else {
129        elementRect = {
130            width: element.offsetWidth,
131            height: element.offsetHeight,
132            left: element.offsetLeft,
133            top: element.offsetTop
134        };
135    }
136
137    elementRect.right = elementRect.left + elementRect.width;
138    elementRect.bottom = elementRect.top + elementRect.height;
139
140    // position
141    return elementRect;
142}
143
144/**
145 * Check if the given element is fixed or is inside a fixed parent
146 * @method
147 * @memberof Popper.Utils
148 * @argument {Element} element
149 * @argument {Element} customContainer
150 * @returns {Boolean} answer to "isFixed?"
151 */
152function isFixed(element) {
153    const nodeName = element.nodeName;
154    if (nodeName === 'BODY' || nodeName === 'HTML') {
155        return false;
156    }
157    if (getStyleComputedProperty(element, 'position') === 'fixed') {
158        return true;
159    }
160    return isFixed(getParentNode(element));
161}
162
163/**
164 * Helper used to get the position which will be applied to the popper
165 * @method
166 * @memberof Popper.Utils
167 * @param config {HTMLElement} popper element
168 * @returns {HTMLElement} reference element
169 */
170function getPosition(element) {
171  const container = getOffsetParent(element);
172
173  // Decide if the popper will be fixed
174  // If the reference element is inside a fixed context, the popper will be fixed as well to allow them to scroll together
175  const isParentFixed = isFixed(container);
176  return isParentFixed ? 'fixed' : 'absolute';
177}
178
179/**
180 * Get bounding client rect of given element
181 * @method
182 * @memberof Popper.Utils
183 * @param {HTMLElement} element
184 * @return {Object} client rect
185 */
186function getBoundingClientRect(element) {
187    const isIE10 = navigator.appVersion.indexOf('MSIE 10') !== -1;
188    let rect;
189
190    // IE10 10 FIX: Please, don't ask, the element isn't
191    // considered in DOM in some circumstances...
192    // This isn't reproducible in IE10 compatibility mode of IE11
193    if (isIE10) {
194        try {
195            rect = element.getBoundingClientRect();
196        } catch (err) {
197            rect = {};
198        }
199    } else {
200        rect = element.getBoundingClientRect();
201    }
202
203    const result = {
204        left: rect.left,
205        top: rect.top,
206        right: rect.right,
207        bottom: rect.bottom,
208        width: rect.right - rect.left,
209        height: rect.bottom - rect.top
210    };
211
212    // IE10 FIX: `getBoundingClientRect`, when executed on `documentElement`
213    // will not take in account the `scrollTop` and `scrollLeft`
214    if (element.nodeName === 'HTML' && isIE10) {
215        const { scrollTop, scrollLeft } = window.document.documentElement;
216        result.top -= scrollTop;
217        result.bottom -= scrollTop;
218        result.left -= scrollLeft;
219        result.right -= scrollLeft;
220    }
221
222    // subtract scrollbar size from sizes
223    let horizScrollbar = rect.width - (element.clientWidth || rect.right - rect.left);
224    let vertScrollbar = rect.height - (element.clientHeight || rect.bottom - rect.top);
225
226    // if an hypothetical scrollbar is detected, we must be sure it's not a `border`
227    // we make this check conditional for performance reasons
228    if (horizScrollbar || vertScrollbar) {
229        const styles = getStyleComputedProperty(element);
230        horizScrollbar -= Number(styles.borderLeftWidth.split('px')[0]) + Number(styles.borderRightWidth.split('px')[0]);
231        vertScrollbar -= Number(styles.borderTopWidth.split('px')[0]) + Number(styles.borderBottomWidth.split('px')[0]);
232    }
233
234    result.right -= horizScrollbar;
235    result.width -= horizScrollbar;
236    result.bottom -= vertScrollbar;
237    result.height -= vertScrollbar;
238
239    return result;
240}
241
242function getScroll(element, side = 'top') {
243    const upperSide = side === 'top' ? 'scrollTop' : 'scrollLeft';
244    const nodeName = element.nodeName;
245
246    if (nodeName === 'BODY' || nodeName === 'HTML') {
247        const html = window.document.documentElement;
248        const scrollingElement = window.document.scrollingElement || html;
249        return scrollingElement[upperSide];
250    }
251
252    return element[upperSide];
253}
254
255/**
256 * Given an element and one of its parents, return the offset
257 * @method
258 * @memberof Popper.Utils
259 * @param {HTMLElement} element
260 * @param {HTMLElement} parent
261 * @return {Object} rect
262 */
263function getOffsetRectRelativeToCustomParent(element, parent, fixed = false, transformed = false) {
264    const scrollParent = getScrollParent(parent);
265    const elementRect = getBoundingClientRect(element);
266    const parentRect = getBoundingClientRect(parent);
267
268    const rect = {
269        top: elementRect.top - parentRect.top,
270        left: elementRect.left - parentRect.left,
271        bottom: elementRect.top - parentRect.top + elementRect.height,
272        right: elementRect.left - parentRect.left + elementRect.width,
273        width: elementRect.width,
274        height: elementRect.height
275    };
276
277    if (fixed && !transformed) {
278        const scrollTop = getScroll(scrollParent, 'top');
279        const scrollLeft = getScroll(scrollParent, 'left');
280        rect.top -= scrollTop;
281        rect.bottom -= scrollTop;
282        rect.left -= scrollLeft;
283        rect.right -= scrollLeft;
284    }
285    // When a popper doesn't have any positioned or scrollable parents, `offsetParent.contains(scrollParent)`
286    // will return a "false positive". This is happening because `getOffsetParent` returns `html` node,
287    // and `scrollParent` is the `body` node. Hence the additional check.
288    else if (getOffsetParent(element).contains(scrollParent) && scrollParent.nodeName !== 'BODY') {
289            const scrollTop = getScroll(parent, 'top');
290            const scrollLeft = getScroll(parent, 'left');
291            rect.top += scrollTop;
292            rect.bottom += scrollTop;
293            rect.left += scrollLeft;
294            rect.right += scrollLeft;
295        }
296
297    // subtract borderTopWidth and borderTopWidth from final result
298    const styles = getStyleComputedProperty(parent);
299    const borderTopWidth = Number(styles.borderTopWidth.split('px')[0]);
300    const borderLeftWidth = Number(styles.borderLeftWidth.split('px')[0]);
301
302    rect.top -= borderTopWidth;
303    rect.bottom -= borderTopWidth;
304    rect.left -= borderLeftWidth;
305    rect.right -= borderLeftWidth;
306
307    return rect;
308}
309
310function getTotalScroll(element, side = 'top') {
311    const scrollParent = getScrollParent(element);
312    const scroll = getScroll(scrollParent, side);
313
314    if (['BODY', 'HTML'].indexOf(scrollParent.nodeName) === -1) {
315        return scroll + getTotalScroll(getParentNode(scrollParent), side);
316    }
317    return scroll;
318}
319
320/**
321 * Computed the boundaries limits and return them
322 * @method
323 * @memberof Popper.Utils
324 * @param {Object} data - Object containing the property "offsets" generated by `_getOffsets`
325 * @param {Number} padding - Boundaries padding
326 * @param {Element} boundariesElement - Element used to define the boundaries
327 * @returns {Object} Coordinates of the boundaries
328 */
329function getBoundaries(popper, padding, boundariesElement) {
330    // NOTE: 1 DOM access here
331    let boundaries = { top: 0, left: 0 };
332    const offsetParent = getOffsetParent(popper);
333
334    // Handle viewport case
335    if (boundariesElement === 'viewport') {
336        const { left, top } = getOffsetRect(offsetParent);
337        const { clientWidth: width, clientHeight: height } = window.document.documentElement;
338
339        if (getPosition(popper) === 'fixed') {
340            boundaries.right = width;
341            boundaries.bottom = height;
342        } else {
343            const scrollLeft = getTotalScroll(popper, 'left');
344            const scrollTop = getTotalScroll(popper, 'top');
345
346            boundaries = {
347                top: 0 - top,
348                right: width - left + scrollLeft,
349                bottom: height - top + scrollTop,
350                left: 0 - left
351            };
352        }
353    }
354    // Handle other cases based on DOM element used as boundaries
355    else {
356            let boundariesNode;
357            if (boundariesElement === 'scrollParent') {
358                boundariesNode = getScrollParent(getParentNode(popper));
359            } else if (boundariesElement === 'window') {
360                boundariesNode = window.document.body;
361            } else {
362                boundariesNode = boundariesElement;
363            }
364
365            // In case of BODY, we need a different computation
366            if (boundariesNode.nodeName === 'BODY') {
367                const { height, width } = getWindowSizes();
368                boundaries.right = width;
369                boundaries.bottom = height;
370            }
371            // for all the other DOM elements, this one is good
372            else {
373                    boundaries = getOffsetRectRelativeToCustomParent(boundariesNode, offsetParent, isFixed(popper));
374                }
375        }
376
377    // Add paddings
378    boundaries.left += padding;
379    boundaries.top += padding;
380    boundaries.right -= padding;
381    boundaries.bottom -= padding;
382
383    return boundaries;
384}
385
386/**
387 * Utility used to transform the `auto` placement to the placement with more
388 * available space.
389 * @method
390 * @memberof Popper.Utils
391 * @argument {Object} data - The data object generated by update method
392 * @argument {Object} options - Modifiers configuration and options
393 * @returns {Object} The data object, properly modified
394 */
395function computeAutoPlacement(placement, refRect, popper) {
396    if (placement.indexOf('auto') === -1) {
397        return placement;
398    }
399
400    const boundaries = getBoundaries(popper, 0, 'scrollParent');
401
402    const sides = {
403        top: refRect.top - boundaries.top,
404        right: boundaries.right - refRect.right,
405        bottom: boundaries.bottom - refRect.bottom,
406        left: refRect.left - boundaries.left
407    };
408
409    const computedPlacement = Object.keys(sides).sort((a, b) => sides[b] - sides[a])[0];
410    const variation = placement.split('-')[1];
411
412    return computedPlacement + (variation ? `-${ variation }` : '');
413}
414
415const nativeHints = ['native code', '[object MutationObserverConstructor]' // for mobile safari iOS 9.0
416];
417
418/**
419 * Determine if a function is implemented natively (as opposed to a polyfill).
420 * @argument {Function | undefined} fn the function to check
421 * @returns {boolean}
422 */
423var isNative = (fn => nativeHints.some(hint => (fn || '').toString().indexOf(hint) > -1));
424
425const longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox'];
426let timeoutDuration = 0;
427for (let i = 0; i < longerTimeoutBrowsers.length; i += 1) {
428    if (navigator.userAgent.indexOf(longerTimeoutBrowsers[i]) >= 0) {
429        timeoutDuration = 1;
430        break;
431    }
432}
433
434function microtaskDebounce(fn) {
435    let scheduled = false;
436    let i = 0;
437    let elem = document.createElement('span');
438
439    // MutationObserver provides a mechanism for scheduling microtasks, which
440    // are scheduled *before* the next task. This gives us a way to debounce
441    // a function but ensure it's called *before* the next paint.
442    const observer = new MutationObserver(() => {
443        fn();
444        scheduled = false;
445    });
446
447    observer.observe(elem, { attributes: true });
448
449    return () => {
450        if (!scheduled) {
451            scheduled = true;
452            elem.setAttribute('x-index', i);
453            i = i + 1; // don't use compund (+=) because it doesn't get optimized in V8
454        }
455    };
456}
457
458function taskDebounce(fn) {
459    let scheduled = false;
460    return () => {
461        if (!scheduled) {
462            scheduled = true;
463            setTimeout(() => {
464                scheduled = false;
465                fn();
466            }, timeoutDuration);
467        }
468    };
469}
470
471// It's common for MutationObserver polyfills to be seen in the wild, however
472// these rely on Mutation Events which only occur when an element is connected
473// to the DOM. The algorithm used in this module does not use a connected element,
474// and so we must ensure that a *native* MutationObserver is available.
475const supportsNativeMutationObserver = isNative(window.MutationObserver);
476
477/**
478* Create a debounced version of a method, that's asynchronously deferred
479* but called in the minimum time possible.
480*
481* @method
482* @memberof Popper.Utils
483* @argument {Function} fn
484* @returns {Function}
485*/
486var debounce = supportsNativeMutationObserver ? microtaskDebounce : taskDebounce;
487
488/**
489 * Mimics the `find` method of Array
490 * @method
491 * @memberof Popper.Utils
492 * @argument {Array} arr
493 * @argument prop
494 * @argument value
495 * @returns index or -1
496 */
497function findIndex$1(arr, check) {
498    // use native find if supported
499    if (Array.prototype.find) {
500        return arr.find(check);
501    }
502
503    // use `filter` to obtain the same behavior of `find`
504    return arr.filter(check)[0];
505}
506
507/**
508 * Return the index of the matching object
509 * @method
510 * @memberof Popper.Utils
511 * @argument {Array} arr
512 * @argument prop
513 * @argument value
514 * @returns index or -1
515 */
516function findIndex(arr, prop, value) {
517    // use native findIndex if supported
518    if (Array.prototype.findIndex) {
519        return arr.findIndex(cur => cur[prop] === value);
520    }
521
522    // use `find` + `indexOf` if `findIndex` isn't supported
523    const match = findIndex$1(arr, obj => obj[prop] === value);
524    return arr.indexOf(match);
525}
526
527var _extends = Object.assign || function (target) {
528  for (var i = 1; i < arguments.length; i++) {
529    var source = arguments[i];
530
531    for (var key in source) {
532      if (Object.prototype.hasOwnProperty.call(source, key)) {
533        target[key] = source[key];
534      }
535    }
536  }
537
538  return target;
539};
540
541/**
542 * Given the popper offsets, generate an output similar to getBoundingClientRect
543 * @method
544 * @memberof Popper.Utils
545 * @argument {Object} popperOffsets
546 * @returns {Object} ClientRect like output
547 */
548function getClientRect(popperOffsets) {
549    return _extends({}, popperOffsets, {
550        right: popperOffsets.left + popperOffsets.width,
551        bottom: popperOffsets.top + popperOffsets.height
552    });
553}
554
555/**
556 * Get the outer sizes of the given element (offset size + margins)
557 * @method
558 * @memberof Popper.Utils
559 * @argument {Element} element
560 * @returns {Object}
560 object containing width and height properties
561 */
562function getOuterSizes(element) {
563    const styles = window.getComputedStyle(element);
564    const x = parseFloat(styles.marginTop) + parseFloat(styles.marginBottom);
565    const y = parseFloat(styles.marginLeft) + parseFloat(styles.marginRight);
566    const result = {
567        width: element.offsetWidth + y,
568        height: element.offsetHeight + x
569    };
570    return result;
571}
572
573/**
574 * Get the opposite placement of the given one/
575 * @method
576 * @memberof Popper.Utils
577 * @argument {String} placement
578 * @returns {String} flipped placement
579 */
580function getOppositePlacement(placement) {
581  const hash = { left: 'right', right: 'left', bottom: 'top', top: 'bottom' };
582  return placement.replace(/left|right|bottom|top/g, matched => hash[matched]);
583}
584
585/**
586 * Get offsets to the popper
587 * @method
588 * @memberof Popper.Utils
589 * @param {Element} popper - the popper element
590 * @param {Element} reference - the reference element (the popper will be relative to this)
591 * @returns {Object} An object containing the offsets which will be applied to the popper
592 */
593function getPopperOffsets(state, popper, referenceOffsets, placement) {
594    placement = placement.split('-')[0];
595
596    // Get popper node sizes
597    const popperRect = getOuterSizes(popper);
598
599    // Add position, width and height to our offsets object
600    const popperOffsets = {
601        position: state.position,
602        width: popperRect.width,
603        height: popperRect.height
604    };
605
606    // depending by the popper placement we have to compute its offsets slightly differently
607    const isHoriz = ['right', 'left'].indexOf(placement) !== -1;
608    const mainSide = isHoriz ? 'top' : 'left';
609    const secondarySide = isHoriz ? 'left' : 'top';
610    const measurement = isHoriz ? 'height' : 'width';
611    const secondaryMeasurement = !isHoriz ? 'height' : 'width';
612
613    popperOffsets[mainSide] = referenceOffsets[mainSide] + referenceOffsets[measurement] / 2 - popperRect[measurement] / 2;
614    if (placement === secondarySide) {
615        popperOffsets[secondarySide] = referenceOffsets[secondarySide] - popperRect[secondaryMeasurement];
616    } else {
617        popperOffsets[secondarySide] = referenceOffsets[getOppositePlacement(secondarySide)];
618    }
619
620    return popperOffsets;
621}
622
623/**
624 * Get offsets to the reference element
625 * @method
626 * @memberof Popper.Utils
627 * @param {Object} state
628 * @param {Element} popper - the popper element
629 * @param {Element} reference - the reference element (the popper will be relative to this)
630 * @returns {Object} An object containing the offsets which will be applied to the popper
631 */
632function getReferenceOffsets(state, popper, reference) {
633  const isParentFixed = state.position === 'fixed';
634  const isParentTransformed = state.isParentTransformed;
635  const offsetParent = getOffsetParent(isParentFixed && isParentTransformed ? reference : popper);
636
637  return getOffsetRectRelativeToCustomParent(reference, offsetParent, isParentFixed, isParentTransformed);
638}
639
640/**
641 * Get the prefixed supported property name
642 * @method
643 * @memberof Popper.Utils
644 * @argument {String} property (camelCase)
645 * @returns {String} prefixed property (camelCase)
646 */
647function getSupportedPropertyName(property) {
648    const prefixes = [false, 'ms', 'webkit', 'moz', 'o'];
649    const upperProp = property.charAt(0).toUpperCase() + property.slice(1);
650
651    for (let i = 0; i < prefixes.length - 1; i++) {
652        const prefix = prefixes[i];
653        const toCheck = prefix ? `${ prefix }${ upperProp }` : property;
654        if (typeof window.document.body.style[toCheck] !== 'undefined') {
655            return toCheck;
656        }
657    }
658    return null;
659}
660
661/**
662 * Check if the given variable is a function
663 * @method
664 * @memberof Popper.Utils
665 * @argument {Element} element - Element to check
666 * @returns {Boolean} answer to: is a function?
667 */
668function isFunction(functionToCheck) {
669  const getType = {};
670  return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
671}
672
673/**
674 * Helper used to know if the given modifier is enabled.
675 * @method
676 * @memberof Popper.Utils
677 * @returns {Boolean}
678 */
679function isModifierEnabled(modifiers, modifierName) {
680  return modifiers.some(({ name, enabled }) => enabled && name === modifierName);
681}
682
683/**
684 * Helper used to know if the given modifier depends from another one.
685 * It checks if the needed modifier is listed and enabled.
686 * @method
687 * @memberof Popper.Utils
688 * @returns {Boolean}
689 */
690function isModifierRequired(modifiers, requestingName, requestedName) {
691  const requesting = findIndex$1(modifiers, ({ name }) => name === requestingName);
692
693  return !!requesting && modifiers.some(modifier => {
694    return modifier.name === requestedName && modifier.enabled && modifier.order < requesting.order;
695  });
696}
697
698/**
699 * Tells if a given input is a number
700 * @method
701 * @memberof Popper.Utils
702 * @param {*} input to check
703 * @return {Boolean}
704 */
705function isNumeric(n) {
706  return n !== '' && !isNaN(parseFloat(n)) && isFinite(n);
707}
708
709/**
710 * Check if the given element has transforms applied to itself or a parent
711 * @method
712 * @memberof Popper.Utils
713 * @param  {Element} element
714 * @return {Boolean} answer to "isTransformed?"
715 */
716function isTransformed(element) {
717    if (element.nodeName === 'BODY') {
718        return false;
719    }
720    if (getStyleComputedProperty(element, 'transform') !== 'none') {
721        return true;
722    }
723    return getParentNode(element) ? isTransformed(getParentNode(element)) : element;
724}
725
726/**
727 * Remove event listeners used to update the popper position
728 * @method
729 * @memberof Popper.Utils
730 * @private
731 */
732function removeEventListeners(reference, state) {
733    // NOTE: 1 DOM access here
734    window.removeEventListener('resize', state.updateBound);
735    if (state.scrollElement) {
736        state.scrollElement.removeEventListener('scroll', state.updateBound);
737    }
738    state.updateBound = null;
739    state.scrollElement = null;
740    state.eventsEnabled = false;
741    return state;
742}
743
744/**
745 * Loop trough the list of modifiers and run them in order, each of them will then edit the data object
746 * @method
747 * @memberof Popper.Utils
748 * @param {Object} data
749 * @param {Array} modifiers
750 * @param {Function} ends
751 */
752function runModifiers(modifiers, data, ends) {
753    const modifiersToRun = ends === undefined ? modifiers : modifiers.slice(0, findIndex(modifiers, 'name', ends));
754
755    modifiersToRun.forEach(modifier => {
756        if (modifier.enabled && isFunction(modifier.function)) {
757            data = modifier.function(data, modifier);
758        }
759    });
760
761    return data;
762}
763
764/**
765 * Set the attributes to the given popper
766 * @method
767 * @memberof Popper.Utils
768 * @argument {Element} element - Element to apply the attributes to
769 * @argument {Object} styles - Object with a list of properties and values which will be applied to the element
770 */
771function setAttributes(element, attributes) {
772    Object.keys(attributes).forEach(function (prop) {
773        const value = attributes[prop];
774        if (value !== false) {
775            element.setAttribute(prop, attributes[prop]);
776        } else {
777            element.removeAttribute(prop);
778        }
779    });
780}
781
782/**
783 * Set the style to the given popper
784 * @method
785 * @memberof Popper.Utils
786 * @argument {Element} element - Element to apply the style to
787 * @argument {Object} styles - Object with a list of properties and values which will be applied to the element
788 */
789function setStyles(element, styles) {
790    Object.keys(styles).forEach(prop => {
791        let unit = '';
792        // add unit if the value is numeric and is one of the following
793        if (['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== -1 && isNumeric(styles[prop])) {
794            unit = 'px';
795        }
796        element.style[prop] = styles[prop] + unit;
797    });
798}
799
800/**
801 * Setup needed event listeners used to update the popper position
802 * @method
803 * @memberof Popper.Utils
804 * @private
805 */
806function setupEventListeners(reference, options, state, updateBound) {
807    // NOTE: 1 DOM access here
808    state.updateBound = updateBound;
809    window.addEventListener('resize', state.updateBound, { passive: true });
810    let target = getScrollParent(reference);
811    if (target.nodeName === 'BODY') {
812        target = window;
813    }
814    target.addEventListener('scroll', state.updateBound, { passive: true });
815    state.scrollElement = target;
816    state.eventsEnabled = true;
817
818    return state;
819}
820
821/** @namespace Popper.Utils */
822var Utils = {
823    computeAutoPlacement,
824    debounce,
825    findIndex,
826    getBoundaries,
827    getBoundingClientRect,
828    getClientRect,
829    getOffsetParent,
830    getOffsetRect,
831    getOffsetRectRelativeToCustomParent,
832    getOuterSizes,
833    getParentNode,
834    getPopperOffsets,
835    getPosition,
836    getReferenceOffsets,
837    getScroll,
838    getScrollParent,
839    getStyleComputedProperty,
840    getSupportedPropertyName,
841    getTotalScroll,
842    getWindowSizes,
843    isFixed,
844    isFunction,
845    isModifierEnabled,
846    isModifierRequired,
847    isNative,
848    isNumeric,
849    isTransformed,
850    removeEventListeners,
851    runModifiers,
852    setAttributes,
853    setStyles,
854    setupEventListeners
855};
856
857/**
858 * Apply the computed styles to the popper element
859 * @method
860 * @memberof Modifiers
861 * @argument {Object} data - The data object generated by `update` method
862 * @argument {Object} data.styles - List of style properties - values to apply to popper element
863 * @argument {Object} data.attributes - List of attribute properties - values to apply to popper element
864 * @argument {Object} options - Modifiers configuration and options
865 * @returns {Object} The same data object
866 */
867function applyStyle(data, options) {
868    // apply the final offsets to the popper
869    // NOTE: 1 DOM access here
870    const styles = {
871        position: data.offsets.popper.position
872    };
873
874    const attributes = {
875        'x-placement': data.placement
876    };
877
878    // round top and left to avoid blurry text
879    const left = Math.round(data.offsets.popper.left);
880    const top = Math.round(data.offsets.popper.top);
881
882    // if gpuAcceleration is set to true and transform is supported,
883    //  we use `translate3d` to apply the position to the popper we
884    // automatically use the supported prefixed version if needed
885    const prefixedProperty = getSupportedPropertyName('transform');
886    if (options.gpuAcceleration && prefixedProperty) {
887        styles[prefixedProperty] = 'translate3d(' + left + 'px, ' + top + 'px, 0)';
888        styles.top = 0;
889        styles.left = 0;
890        styles.willChange = 'transform';
891    }
892    // othwerise, we use the standard `left` and `top` properties
893    else {
894            styles.left = left;
895            styles.top = top;
896            styles.willChange = 'top, left';
897        }
898
899    // any property present in `data.styles` will be applied to the popper,
900    // in this way we can make the 3rd party modifiers add custom styles to it
901    // Be aware, modifiers could override the properties defined in the previous
902    // lines of this modifier!
903    setStyles(data.instance.popper, _extends({}, styles, data.styles));
904
905    // any property present in `data.attributes` will be applied to the popper,
906    // they will be set as HTML attributes of the element
907    setAttributes(data.instance.popper, _extends({}, attributes, data.attributes));
908
909    // if the arrow style has been computed, apply the arrow style
910    if (data.offsets.arrow) {
911        setStyles(data.arrowElement, data.offsets.arrow);
912    }
913
914    return data;
915}
916
917/**
918 * Set the x-placement attribute before everything else because it could be used to add margins to the popper
919 * margins needs to be calculated to get the correct popper offsets
920 * @method
921 * @memberof Popper.modifiers
922 * @param {HTMLElement} reference - The reference element used to position the popper
923 * @param {HTMLElement} popper - The HTML element used as popper.
924 * @param {Object} options - Popper.js options
925 */
926function applyStyleOnLoad(reference, popper, options, modifierOptions, state) {
927    // compute reference element offsets
928    const referenceOffsets = getReferenceOffsets(state, popper, reference);
929
930    // compute auto placement, store placement inside the data object,
931    // modifiers will be able to edit `placement` if needed
932    // and refer to originalPlacement to know the original value
933    options.placement = computeAutoPlacement(options.placement, referenceOffsets, popper);
934
935    popper.setAttribute('x-placement', options.placement);
936    return options;
937}
938
939/**
940 * Modifier used to move the arrowElements on the edge of the popper to make sure them are always between the popper and the reference element
941 * It will use the CSS outer size of the arrowElement element to know how many pixels of conjuction are needed
942 * @method
943 * @memberof Modifiers
944 * @argument {Object} data - The data object generated by update method
945 * @argument {Object} options - Modifiers configuration and options
946 * @returns {Object} The data object, properly modified
947 */
948function arrow(data, options) {
949    // arrow depends on keepTogether in order to work
950    if (!isModifierRequired(data.instance.modifiers, 'arrow', 'keepTogether')) {
951        console.warn('WARNING: `keepTogether` modifier is required by arrow modifier in order to work, be sure to include it before `arrow`!');
952        return data;
953    }
954
955    let arrowElement = options.element;
956
957    // if arrowElement is a string, suppose it's a CSS selector
958    if (typeof arrowElement === 'string') {
959        arrowElement = data.instance.popper.querySelector(arrowElement);
960
961        // if arrowElement is not found, don't run the modifier
962        if (!arrowElement) {
963            return data;
964        }
965    } else {
966        // if the arrowElement isn't a query selector we must check that the
967        // provided DOM node is child of its popper node
968        if (!data.instance.popper.contains(arrowElement)) {
969            console.warn('WARNING: `arrow.element` must be child of its popper element!');
970            return data;
971        }
972    }
973
974    const placement = data.placement.split('-')[0];
975    const popper = getClientRect(data.offsets.popper);
976    const reference = data.offsets.reference;
977    const isVertical = ['left', 'right'].indexOf(placement) !== -1;
978
979    const len = isVertical ? 'height' : 'width';
980    const side = isVertical ? 'top' : 'left';
981    const altSide = isVertical ? 'left' : 'top';
982    const opSide = isVertical ? 'bottom' : 'right';
983    const arrowElementSize = getOuterSizes(arrowElement)[len];
984
985    //
986    // extends keepTogether behavior making sure the popper and its reference have enough pixels in conjuction
987    //
988
989    // top/left side
990    if (reference[opSide] - arrowElementSize < popper[side]) {
991        data.offsets.popper[side] -= popper[side] - (reference[opSide] - arrowElementSize);
992    }
993    // bottom/right side
994    if (reference[side] + arrowElementSize > popper[opSide]) {
995        data.offsets.popper[side] += reference[side] + arrowElementSize - popper[opSide];
996    }
997
998    // compute center of the popper
999    const center = reference[side] + reference[len] / 2 - arrowElementSize / 2;
1000
1001    // Compute the sideValue using the updated popper offsets
1002    let sideValue = center - getClientRect(data.offsets.popper)[side];
1003
1004    // prevent arrowElement from being placed not contiguously to its popper
1005    sideValue = Math.max(Math.min(popper[len] - arrowElementSize, sideValue), 0);
1006
1007    data.arrowElement = arrowElement;
1008    data.offsets.arrow = {};
1009    data.offsets.arrow[side] = sideValue;
1010    data.offsets.arrow[altSide] = ''; // make sure to unset any eventual altSide value from the DOM node
1011
1012    return data;
1013}
1014
1015/**
1016 * Get the opposite placement variation of the given one/
1017 * @method
1018 * @memberof Popper.Utils
1019 * @argument {String} placement variation
1020 * @returns {String} flipped placement variation
1021 */
1022function getOppositeVariation(variation) {
1023    if (variation === 'end') {
1024        return 'start';
1025    } else if (variation === 'start') {
1026        return 'end';
1027    }
1028    return variation;
1029}
1030
1031/**
1032 * Modifier used to flip the placement of the popper when the latter is starting overlapping its reference element.
1033 * Requires the `preventOverflow` modifier before it in order to work.
1034 * **NOTE:** data.instance modifier will run all its previous modifiers everytime it tries to flip the popper!
1035 * @method
1036 * @memberof Modifiers
1037 * @argument {Object} data - The data object generated by update method
1038 * @argument {Object} options - Modifiers configuration and options
1039 * @returns {Object} The data object, properly modified
1040 */
1041function flip(data, options) {
1042    // if `inner` modifier is enabled, we can't use the `flip` modifier
1043    if (isModifierEnabled(data.instance.modifiers, 'inner')) {
1044        return data;
1045    }
1046
1047    if (data.flipped && data.placement === data.originalPlacement) {
1048        // seems like flip is trying to loop, probably there's not enough space on any of the flippable sides
1049        return data;
1050    }
1051
1052    const boundaries = getBoundaries(data.instance.popper, options.padding, options.boundariesElement);
1053
1054    let placement = data.placement.split('-')[0];
1055    let placementOpposite = getOppositePlacement(placement);
1056    let variation = data.placement.split('-')[1] || '';
1057
1058    let flipOrder = [];
1059
1060    if (options.behavior === 'flip') {
1061        flipOrder = [placement, placementOpposite];
1062    } else {
1063        flipOrder = options.behavior;
1064    }
1065
1066    flipOrder.forEach((step, index) => {
1067        if (placement !== step || flipOrder.length === index + 1) {
1068            return data;
1069        }
1070
1071        placement = data.placement.split('-')[0];
1072        placementOpposite = getOppositePlacement(placement);
1073
1074        const popperOffsets = getClientRect(data.offsets.popper);
1075        const refOffsets = data.offsets.reference;
1076
1077        // using Math.floor because the reference offsets may contain decimals we are not going to consider here
1078        const overlapsRef = placement === 'left' && Math.floor(popperOffsets.right) > Math.floor(refOffsets.left) || placement === 'right' && Math.floor(popperOffsets.left) < Math.floor(refOffsets.right) || placement === 'top' && Math.floor(popperOffsets.bottom) > Math.floor(refOffsets.top) || placement === 'bottom' && Math.floor(popperOffsets.top) < Math.floor(refOffsets.bottom);
1079
1080        const overflowsBoundaries = placement === 'left' && Math.floor(popperOffsets.left) < Math.floor(boundaries.left) || placement === 'right' && Math.floor(popperOffsets.right) > Math.floor(boundaries.right) || placement === 'top' && Math.floor(popperOffsets.top) < Math.floor(boundaries.top) || placement === 'bottom' && Math.floor(popperOffsets.bottom) > Math.floor(boundaries.bottom);
1081
1082        // flip the variation if required
1083        const isVertical = ['top', 'bottom'].indexOf(placement) !== -1;
1084        const flippedVariation = !!options.flipVariations && (isVertical && variation === 'start' && Math.floor(popperOffsets.left) < Math.floor(boundaries.left) || isVertical && variation === 'end' && Math.floor(popperOffsets.right) > Math.floor(boundaries.right) || !isVertical && variation === 'start' && Math.floor(popperOffsets.top) < Math.floor(boundaries.top) || !isVertical && variation === 'end' && Math.floor(popperOffsets.bottom) > Math.floor(boundaries.bottom));
1085
1086        if (overlapsRef || overflowsBoundaries || flippedVariation) {
1087            // this boolean to detect any flip loop
1088            data.flipped = true;
1089
1090            if (overlapsRef || overflowsBoundaries) {
1091                placement = flipOrder[index + 1];
1092            }
1093
1094            if (flippedVariation) {
1095                variation = getOppositeVariation(variation);
1096            }
1097
1098            data.placement = placement + (variation ? '-' + variation : '');
1099            data.offsets.popper = getPopperOffsets(data.instance.state, data.instance.popper, data.offsets.reference, data.placement);
1100
1101            data = runModifiers(data.instance.modifiers, data, 'flip');
1102        }
1103    });
1104    return data;
1105}
1106
1107/**
1108 * Modifier used to make sure the popper is always near its reference element
1109 * It cares only about the first axis, you can still have poppers with margin
1110 * between the popper and its reference element.
1111 * @method
1112 * @memberof Modifiers
1113 * @argument {Object} data - The data object generated by update method
1114 * @argument {Object} options - Modifiers configuration and options
1115 * @returns {Object} The data object, properly modified
1116 */
1117function keepTogether(data) {
1118    const popper = getClientRect(data.offsets.popper);
1119    const reference = data.offsets.reference;
1120    const placement = data.placement.split('-')[0];
1121    const floor = Math.floor;
1122
1123    if (['top', 'bottom'].indexOf(placement) !== -1) {
1124        if (popper.right < floor(reference.left)) {
1125            data.offsets.popper.left = floor(reference.left) - popper.width;
1126        }
1127        if (popper.left > floor(reference.right)) {
1128            data.offsets.popper.left = floor(reference.right);
1129        }
1130    } else {
1131        if (popper.bottom < floor(reference.top)) {
1132            data.offsets.popper.top = floor(reference.top) - popper.height;
1133        }
1134        if (popper.top > floor(reference.bottom)) {
1135            data.offsets.popper.top = floor(reference.bottom);
1136        }
1137    }
1138
1139    return data;
1140}
1141
1142/**
1143 * Modifier used to add an offset to the popper, useful if you more granularity positioning your popper.
1144 * The offsets will shift the popper on the side of its reference element.
1145 * @method
1146 * @memberof Modifiers
1147 * @argument {Object} data - The data object generated by update method
1148 * @argument {Object} options - Modifiers configuration and options
1149 * @argument {Number|String} options.offset=0
1150 *      Basic usage allows a number used to nudge the popper by the given amount of pixels.
1151 *      You can pass a percentage value as string (eg. `20%`) to nudge by the given percentage (relative to reference element size)
1152 *      Other supported units are `vh` and `vw` (relative to viewport)
1153 *      Additionally, you can pass a pair of values (eg. `10 20` or `2vh 20%`) to nudge the popper
1154 *      on both axis.
1155 *      A note about percentage values, if you want to refer a percentage to the popper size instead of the reference element size,
1156 *      use `%p` instead of `%` (eg: `20%p`). To make it clearer, you can replace `%` with `%r` and use eg.`10%p 25%r`.
1157 *      > **Heads up!** The order of the axis is relative to the popper placement: `bottom` or `top` are `X,Y`, the other are `Y,X`
1158 * @returns {Object} The data object, properly modified
1159 */
1160function offset(data, options) {
1161    const placement = data.placement;
1162    const popper = data.offsets.popper;
1163
1164    let offsets;
1165    if (isNumeric(options.offset)) {
1166        offsets = [options.offset, 0];
1167    } else {
1168        // split the offset in case we are providing a pair of offsets separated
1169        // by a blank space
1170        offsets = options.offset.split(' ');
1171
1172        // itherate through each offset to compute them in case they are percentages
1173        offsets = offsets.map((offset, index) => {
1174            // separate value from unit
1175            const split = offset.match(/(\d*\.?\d*)(.*)/);
1176            const value = +split[1];
1177            const unit = split[2];
1178
1179            // use height if placement is left or right and index is 0 otherwise use width
1180            // in this way the first offset will use an axis and the second one
1181            // will use the other one
1182            let useHeight = placement.indexOf('right') !== -1 || placement.indexOf('left') !== -1;
1183
1184            if (index === 1) {
1185                useHeight = !useHeight;
1186            }
1187
1188            const measurement = useHeight ? 'height' : 'width';
1189
1190            // if is a percentage, we calculate the value of it using as base the
1191            // sizes of the reference element
1192            if (unit === '%' || unit === '%r') {
1193                const referenceRect = getClientRect(data.offsets.reference);
1194                let len = referenceRect[measurement];
1195                return len / 100 * value;
1196            }
1197            // if is a percentage relative to the popper, we calculate the value of it using
1198            // as base the sizes of the popper
1199            else if (unit === '%p') {
1200                    const popperRect = getClientRect(data.offsets.popper);
1201                    let len = popperRect[measurement];
1202                    return len / 100 * value;
1203                }
1204                // if is a vh or vw, we calculate the size based on the viewport
1205                else if (unit === 'vh' || unit === 'vw') {
1206                        let size;
1207                        if (unit === 'vh') {
1208                            size = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
1209                        } else {
1210                            size = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
1211                        }
1212                        return size / 100 * value;
1213                    }
1214                    // if is an explicit pixel unit, we get rid of the unit and keep the value
1215                    else if (unit === 'px') {
1216                            return +value;
1217                        }
1218                        // if is an implicit unit, it's px, and we return just the value
1219                        else {
1220                                return +offset;
1221                            }
1222        });
1223    }
1224
1225    if (data.placement.indexOf('left') !== -1) {
1226        popper.top += offsets[0];
1227        popper.left -= offsets[1] || 0;
1228    } else if (data.placement.indexOf('right') !== -1) {
1229        popper.top += offsets[0];
1230        popper.left += offsets[1] || 0;
1231    } else if (data.placement.indexOf('top') !== -1) {
1232        popper.left += offsets[0];
1233        popper.top -= offsets[1] || 0;
1234    } else if (data.placement.indexOf('bottom') !== -1) {
1235        popper.left += offsets[0];
1236        popper.top += offsets[1] || 0;
1237    }
1238    return data;
1239}
1240
1241/**
1242 * Modifier used to prevent the popper from being positioned outside the boundary.
1243 *
1244 * An scenario exists where the reference itself is not within the boundaries. We can
1245 * say it has "escaped the boundaries" — or just "escaped". In this case we need to
1246 * decide whether the popper should either:
1247 *
1248 * - detach from the reference and remain "trapped" in the boundaries, or
1249 * - if it should be ignore the boundary and "escape with the reference"
1250 *
1251 * When `escapeWithReference` is `true`, and reference is completely outside the
1252 * boundaries, the popper will overflow (or completely leave) the boundaries in order
1253 * to remain attached to the edge of the reference.
1254 *
1255 * @method
1256 * @memberof Modifiers
1257 * @argument {Object} data - The data object generated by `update` method
1258 * @argument {Object} options - Modifiers configuration and options
1259 * @returns {Object} The data object, properly modified
1260 */
1261function preventOverflow(data, options) {
1262    const boundariesElement = options.boundariesElement || getOffsetParent(data.instance.popper);
1263    const boundaries = getBoundaries(data.instance.popper, options.padding, boundariesElement);
1264    options.boundaries = boundaries;
1265
1266    const order = options.priority;
1267    let popper = getClientRect(data.offsets.popper);
1268
1269    const check = {
1270        left() {
1271            let left = popper.left;
1272            if (popper.left < boundaries.left && !shouldOverflowBoundary(data, options, 'left')) {
1273                left = Math.max(popper.left, boundaries.left);
1274            }
1275            return { left };
1276        },
1277        right() {
1278            let left = popper.left;
1279            if (popper.right > boundaries.right && !shouldOverflowBoundary(data, options, 'right')) {
1280                left = Math.min(popper.left, boundaries.right - popper.width);
1281            }
1282            return { left };
1283        },
1284        top() {
1285            let top = popper.top;
1286            if (popper.top < boundaries.top && !shouldOverflowBoundary(data, options, 'top')) {
1287                top = Math.max(popper.top, boundaries.top);
1288            }
1289            return { top };
1290        },
1291        bottom() {
1292            let top = popper.top;
1293            if (popper.bottom >
1293 boundaries.bottom && !shouldOverflowBoundary(data, options, 'bottom')) {
1294                top = Math.min(popper.top, boundaries.bottom - popper.height);
1295            }
1296            return { top };
1297        }
1298    };
1299
1300    order.forEach(direction => {
1301        popper = _extends({}, popper, check[direction]());
1302    });
1303
1304    data.offsets.popper = popper;
1305
1306    return data;
1307}
1308
1309/**
1310 * Determine if the popper should overflow a boundary edge to stay together with the reference.
1311 */
1312function shouldOverflowBoundary(data, options, overflowDirection) {
1313    if (!options.escapeWithReference) {
1314        return false;
1315    }
1316
1317    if (data.flipped && isSameAxis(data.originalPlacement, overflowDirection)) {
1318        return true;
1319    }
1320
1321    if (!isSameAxis(data.originalPlacement, overflowDirection)) {
1322        return true;
1323    }
1324
1325    return true;
1326}
1327
1328/**
1329 * Determine if two placement values are on the same axis.
1330 */
1331function isSameAxis(a, b) {
1332    // placement syntax:
1333    //
1334    //     ( "top" | "right" | "bottom" | "left" ) ( "-start" | "" | "-end" )
1335    //     |------------- Direction -------------|
1336    //
1337    const aDirection = a.split('-')[0];
1338    const bDirection = b.split('-')[0];
1339
1340    return aDirection === bDirection || aDirection === getOppositePlacement(b);
1341}
1342
1343/**
1344 * Modifier used to shift the popper on the start or end of its reference element side
1345 * @method
1346 * @memberof Modifiers
1347 * @argument {Object} data - The data object generated by `update` method
1348 * @argument {Object} options - Modifiers configuration and options
1349 * @returns {Object} The data object, properly modified
1350 */
1351function shift(data) {
1352    const placement = data.placement;
1353    const basePlacement = placement.split('-')[0];
1354    const shiftvariation = placement.split('-')[1];
1355
1356    // if shift shiftvariation is specified, run the modifier
1357    if (shiftvariation) {
1358        const reference = data.offsets.reference;
1359        const popper = getClientRect(data.offsets.popper);
1360
1361        const shiftOffsets = {
1362            y: {
1363                start: { top: reference.top },
1364                end: { top: reference.top + reference.height - popper.height }
1365            },
1366            x: {
1367                start: { left: reference.left },
1368                end: { left: reference.left + reference.width - popper.width }
1369            }
1370        };
1371
1372        const axis = ['bottom', 'top'].indexOf(basePlacement) !== -1 ? 'x' : 'y';
1373
1374        data.offsets.popper = _extends({}, popper, shiftOffsets[axis][shiftvariation]);
1375    }
1376
1377    return data;
1378}
1379
1380/**
1381 * Modifier used to hide the popper when its reference element is outside of the
1382 * popper boundaries. It will set an x-hidden attribute which can be used to hide
1383 * the popper when its reference is out of boundaries.
1384 * @method
1385 * @memberof Modifiers
1386 * @argument {Object} data - The data object generated by update method
1387 * @argument {Object} options - Modifiers configuration and options
1388 * @returns {Object} The data object, properly modified
1389 */
1390function hide(data) {
1391    if (!isModifierRequired(data.instance.modifiers, 'hide', 'preventOverflow')) {
1392        console.warn('WARNING: preventOverflow modifier is required by hide modifier in order to work, be sure to include it before hide!');
1393        return data;
1394    }
1395
1396    const refRect = data.offsets.reference;
1397    const bound = findIndex$1(data.instance.modifiers, modifier => modifier.name === 'preventOverflow').boundaries;
1398
1399    if (refRect.bottom < bound.top || refRect.left > bound.right || refRect.top > bound.bottom || refRect.right < bound.left) {
1400        // Avoid unnecessary DOM access if visibility hasn't changed
1401        if (data.hide === true) {
1402            return data;
1403        }
1404
1405        data.hide = true;
1406        data.attributes['x-out-of-boundaries'] = '';
1407    } else {
1408        // Avoid unnecessary DOM access if visibility hasn't changed
1409        if (data.hide === false) {
1410            return data;
1411        }
1412
1413        data.hide = false;
1414        data.attributes['x-out-of-boundaries'] = false;
1415    }
1416
1417    return data;
1418}
1419
1420/**
1421 * Modifier used to make the popper flow toward the inner of the reference element.
1422 * By default, when this modifier is disabled, the popper will be placed outside
1423 * the reference element.
1424 * @method
1425 * @memberof Modifiers
1426 * @argument {Object} data - The data object generated by `update` method
1427 * @argument {Object} options - Modifiers configuration and options
1428 * @returns {Object} The data object, properly modified
1429 */
1430function inner(data) {
1431    const placement = data.placement;
1432    const basePlacement = placement.split('-')[0];
1433    const popper = getClientRect(data.offsets.popper);
1434    const reference = getClientRect(data.offsets.reference);
1435    const isHoriz = ['left', 'right'].indexOf(basePlacement) !== -1;
1436
1437    const subtractLength = ['top', 'left'].indexOf(basePlacement) === -1;
1438
1439    popper[isHoriz ? 'left' : 'top'] = reference[placement] - (subtractLength ? popper[isHoriz ? 'width' : 'height'] : 0);
1440
1441    data.placement = getOppositePlacement(placement);
1442    data.offsets.popper = getClientRect(popper);
1443
1444    return data;
1445}
1446
1447/**
1448 * Modifiers are plugins used to alter the behavior of your poppers.
1449 * Popper.js uses a set of 7 modifiers to provide all the basic functionalities
1450 * needed by the library.
1451 *
1452 * Each modifier is an object containing several properties listed below.
1453 * @namespace Modifiers
1454 * @param {Object} modifier - Modifier descriptor
1455 * @param {Integer} modifier.order
1456 *      The `order` property defines the execution order of the modifiers.
1457 *      The built-in modifiers have orders with a gap of 100 units in between,
1458 *      this allows you to inject additional modifiers between the existing ones
1459 *      without having to redefine the order of all of them.
1460 *      The modifiers are executed starting from the one with the lowest order.
1461 * @param {Boolean} modifier.enabled - When `true`, the modifier will be used.
1462 * @param {Modifiers~modifier} modifier.function - Modifier function.
1463 * @param {Modifiers~onLoad} modifier.onLoad - Function executed on popper initalization
1464 * @return {Object} data - Each modifier must return the modified `data` object.
1465 */
1466var modifiers = {
1467    shift: {
1468        order: 100,
1469        enabled: true,
1470        function: shift
1471    },
1472    offset: {
1473        order: 200,
1474        enabled: true,
1475        function: offset,
1476        // nudges popper from its origin by the given amount of pixels (can be negative)
1477        offset: 0
1478    },
1479    preventOverflow: {
1480        order: 300,
1481        enabled: true,
1482        function: preventOverflow,
1483        // popper will try to prevent overflow following these priorities
1484        //  by default, then, it could overflow on the left and on top of the boundariesElement
1485        priority: ['left', 'right', 'top', 'bottom'],
1486        // amount of pixel used to define a minimum distance between the boundaries and the popper
1487        // this makes sure the popper has always a little padding between the edges of its container
1488        padding: 5,
1489        boundariesElement: 'scrollParent'
1490    },
1491    keepTogether: {
1492        order: 400,
1493        enabled: true,
1494        function: keepTogether
1495    },
1496    arrow: {
1497        order: 500,
1498        enabled: true,
1499        function: arrow,
1500        // selector or node used as arrow
1501        element: '[x-arrow]'
1502    },
1503    flip: {
1504        order: 600,
1505        enabled: true,
1506        function: flip,
1507        // the behavior used to change the popper's placement
1508        behavior: 'flip',
1509        // the popper will flip if it hits the edges of the boundariesElement - padding
1510        padding: 5,
1511        boundariesElement: 'viewport'
1512    },
1513    inner: {
1514        order: 700,
1515        enabled: false,
1516        function: inner
1517    },
1518    hide: {
1519        order: 800,
1520        enabled: true,
1521        function: hide
1522    },
1523    applyStyle: {
1524        order: 900,
1525        enabled: true,
1526        // if true, it uses the CSS 3d transformation to position the popper
1527        gpuAcceleration: true,
1528        function: applyStyle,
1529        onLoad: applyStyleOnLoad
1530    }
1531};
1532
1533/**
1534 * Modifiers can edit the `data` object to change the beheavior of the popper.
1535 * This object contains all the informations used by Popper.js to compute the
1536 * popper position.
1537 * The modifier can edit the data as needed, and then `return` it as result.
1538 *
1539 * @callback Modifiers~modifier
1540 * @param {dataObject} data
1541 * @return {dataObject} modified data
1542 */
1543
1544/**
1545 * The `dataObject` is an object containing all the informations used by Popper.js
1546 * this object get passed to modifiers and to the `onCreate` and `onUpdate` callbacks.
1547 * @name dataObject
1548 * @property {Object} data.instance The Popper.js instance
1549 * @property {String} data.placement Placement applied to popper
1550 * @property {String} data.originalPlacement Placement originally defined on init
1551 * @property {Boolean} data.flipped True if popper has been flipped by flip modifier
1552 * @property {Boolean} data.hide True if the reference element is out of boundaries, useful to know when to hide the popper.
1553 * @property {HTMLElement} data.arrowElement Node used as arrow by arrow modifier
1554 * @property {Object} data.styles Any CSS property defined here will be applied to the popper, it expects the JavaScript nomenclature (eg. `marginBottom`)
1555 * @property {Object} data.boundaries Offsets of the popper boundaries
1556 * @property {Object} data.offsets The measurements of popper, reference and arrow elements.
1557 * @property {Object} data.offsets.popper `top`, `left`, `width`, `height` values
1558 * @property {Object} data.offsets.reference `top`, `left`, `width`, `height` values
1559 * @property {Object} data.offsets.arro] `top` and `left` offsets, only one of them will be different from 0
1560 */
1561
1562// Utils
1563// Modifiers
1564// default options
1565const DEFAULTS = {
1566    // placement of the popper
1567    placement: 'bottom',
1568
1569    // whether events (resize, scroll) are initially enabled
1570    eventsEnabled: true,
1571
1572    /**
1573     * Callback called when the popper is created.
1574     * By default, is set to no-op.
1575     * Access Popper.js instance with `data.instance`.
1576     * @callback createCallback
1577     * @static
1578     * @param {dataObject} data
1579     */
1580    onCreate: () => {},
1581
1582    /**
1583     * Callback called when the popper is updated, this callback is not called
1584     * on the initialization/creation of the popper, but only on subsequent
1585     * updates.
1586     * By default, is set to no-op.
1587     * Access Popper.js instance with `data.instance`.
1588     * @callback updateCallback
1589     * @static
1590     * @param {dataObject} data
1591     */
1592    onUpdate: () => {},
1593
1594    // list of functions used to modify the offsets before they are applied to the popper
1595    modifiers
1596};
1597
1598/**
1599 * Create a new Popper.js instance
1600 * @class Popper
1601 * @param {HTMLElement} reference - The reference element used to position the popper
1602 * @param {HTMLElement} popper - The HTML element used as popper.
1603 * @param {Object} options
1604 * @param {String} options.placement=bottom
1605 *      Placement of the popper accepted values: `top(-start, -end), right(-start, -end), bottom(-start, -end),
1606 *      left(-start, -end)`
1607 *
1608 * @param {Boolean} options.eventsEnabled=true
1609 *      Whether events (resize, scroll) are initially enabled
1610 * @param {Boolean} options.gpuAcceleration=true
1611 *      When this property is set to true, the popper position will be applied using CSS3 translate3d, allowing the
1612 *      browser to use the GPU to accelerate the rendering.
1613 *      If set to false, the popper will be placed using `top` and `left` properties, not using the GPU.
1614 *
1615 * @param {Boolean} options.removeOnDestroy=false
1616 *      Set to true if you want to automatically remove the popper when you call the `destroy` method.
1617 *
1618 * @param {Object} options.modifiers
1619 *      List of functions used to modify the data before they are applied to the popper (see source code for default values)
1620 *
1621 * @param {Object} options.modifiers.arrow - Arrow modifier configuration
1622 * @param {String|HTMLElement} options.modifiers.arrow.element='[x-arrow]'
1623 *      The DOM Node used as arrow for the popper, or a CSS selector used to get the DOM node. It must be child of
1624 *      its parent Popper. Popper.js will apply to the given element the style required to align the arrow with its
1625 *      reference element.
1626 *      By default, it will look for a child node of the popper with the `x-arrow` attribute.
1627 *
1628 * @param {Object} options.modifiers.offset - Offset modifier configuration
1629 * @param {Number} options.modifiers.offset.offset=0
1630 *      Amount of pixels the popper will be shifted (can be negative).
1631 *
1632 * @param {Object} options.modifiers.preventOverflow - PreventOverflow modifier configuration
1633 * @param {Array} [options.modifiers.preventOverflow.priority=['left', 'right', 'top', 'bottom']]
1634 *      Priority used when Popper.js tries to avoid overflows from the boundaries, they will be checked in order,
1635 *      this means that the last one will never overflow
1636 * @param {String|HTMLElement} options.modifiers.preventOverflow.boundariesElement='scrollParent'
1637 *      Boundaries used by the modifier, can be `scrollParent`, `window`, `viewport` or any DOM element.
1638 * @param {Number} options.modifiers.preventOverflow.padding=5
1639 *      Amount of pixel used to define a minimum distance between the boundaries and the popper
1640 *      this makes sure the popper has always a little padding between the edges of its container.
1641 *
1642 * @param {Object} options.modifiers.flip - Flip modifier configuration
1643 * @param {String|Array} options.modifiers.flip.behavior='flip'
1644 *      The behavior used by the `flip` modifier to change the placement of the popper when the latter is trying to
1645 *      overlap its reference element. Defining `flip` as value, the placement will be flipped on
1646 *      its axis (`right - left`, `top - bottom`).
1647 *      You can even pass an array of placements (eg: `['right', 'left', 'top']` ) to manually specify
1648 *      how alter the placement when a flip is needed. (eg. in the above example, it would first flip from right to left,
1649 *      then, if even in its new placement, the popper is overlapping its reference element, it will be moved to top)
1650 * @param {String|HTMLElement} options.modifiers.flip.boundariesElement='viewport'
1651 *      The element which will define the boundaries of the popper position, the popper will never be placed outside
1652 *      of the defined boundaries (except if `keepTogether` is enabled)
1653 *
1654 * @param {Object} options.modifiers.inner - Inner modifier configuration
1655 * @param {Number} options.modifiers.innner.enabled=false
1656 *      Set to `true` to make the popper flow toward the inner of the reference element.
1657 *
1658 * @param {Number} options.modifiers.flip.padding=5
1659 *      Amount of pixel used to define a minimum distance between the boundaries and the popper
1660 *      this makes sure the popper has always a little padding between the edges of its container.
1661 *
1662 * @param {createCallback} options.onCreate - onCreate callback
1663 *      Function called after the Popper has been instantiated.
1664 *
1665 * @param {updateCallback} options.onUpdate - onUpdate callback
1666 *      Function called on subsequent updates of Popper.
1667 *
1668 * @return {Object} instance - The generated Popper.js instance
1669 */
1670class Popper {
1671    constructor(reference, popper, options = {}) {
1672        this.scheduleUpdate = () => requestAnimationFrame(this.update);
1673
1674        // make update() debounced, so that it only runs at most once-per-tick
1675        this.update = debounce(this.update.bind(this));
1676
1677        // with {} we create a new object with the options inside it
1678        this.options = _extends({}, Popper.Defaults, options);
1679
1680        // init state
1681        this.state = {
1682            isDestroyed: false,
1683            isCreated: false
1684        };
1685
1686        // get reference and popper elements (allow jQuery wrappers)
1687        this.reference = reference.jquery ? reference[0] : reference;
1688        this.popper = popper.jquery ? popper[0] : popper;
1689
1690        // refactoring modifiers' list (Object => Array)
1691        this.modifiers = Object.keys(Popper.Defaults.modifiers).map(name => _extends({ name }, Popper.Defaults.modifiers[name]));
1692
1693        // assign default values to modifiers, making sure to override them with
1694        // the ones defined by user
1695        this.modifiers = this.modifiers.map(defaultConfig => {
1696            const userConfig = options.modifiers && options.modifiers[defaultConfig.name] || {};
1697            return _extends({}, defaultConfig, userConfig);
1698        });
1699
1700        // add custom modifiers to the modifiers list
1701        if (options.modifiers) {
1702            this.options.modifiers = _extends({}, Popper.Defaults.modifiers, options.modifiers);
1703            Object.keys(options.modifiers).forEach(name => {
1704                // take in account only custom modifiers
1705                if (Popper.Defaults.modifiers[name] === undefined) {
1706                    const modifier = options.modifiers[name];
1707                    modifier.name = name;
1708                    this.modifiers.push(modifier);
1709                }
1710            });
1711        }
1712
1713        // get the popper position type
1714        this.state.position = getPosition(this.reference);
1715
1716        // sort the modifiers by order
1717        this.modifiers = this.modifiers.sort((a, b) => a.order - b.order);
1718
1719        // modifiers have the ability to execute arbitrary code when Popper.js get inited
1720        // such code is executed in the same order of its modifier
1721        // they could add new properties to their options configuration
1722        // BE AWARE: don't add options to `options.modifiers.name` but to `modifierOptions`!
1723        this.modifiers.forEach(modifierOptions => {
1724            if (modifierOptions.enabled && isFunction(modifierOptions.onLoad)) {
1725                modifierOptions.onLoad(this.reference, this.popper, this.options, modifierOptions, this.state);
1726            }
1727        });
1728
1729        // determine how we should set the origin of offsets
1730        this.state.isParentTransformed = isTransformed(this.popper.parentNode);
1731
1732        // fire the first update to position the popper in the right place
1733        this.update();
1734
1735        const eventsEnabled = this.options.eventsEnabled;
1736        if (eventsEnabled) {
1737            // setup event listeners, they will take care of update the position in specific situations
1738            this.enableEventListeners();
1739        }
1740
1741        this.state.eventsEnabled = eventsEnabled;
1742    }
1743
1744    //
1745    // Methods
1746    //
1747
1748    /**
1749     * Updates the position of the popper, computing the new offsets and applying the new style
1750     * Prefer `scheduleUpdate` over `update` because of performance reasons
1751     * @method
1752     * @memberof Popper
1753     */
1754    update() {
1755        // if popper is destroyed, don't perform any further update
1756        if (this.state.isDestroyed) {
1757            return;
1758        }
1759
1760        let data = {
1761            instance: this,
1762            styles: {},
1763            attributes: {},
1764            flipped: false,
1765            offsets: {}
1766        };
1767
1768        // make sure to apply the popper position before any computation
1769        this.state.position = getPosition(this.reference);
1770        setStyles(this.popper, { position: this.state.position });
1771
1772        // compute reference element offsets
1773        data.offsets.reference = getReferenceOffsets(this.state, this.popper, this.reference);
1774
1775        // compute auto placement, store placement inside the data object,
1776        // modifiers will be able to edit `placement` if needed
1777        // and refer to originalPlacement to know the original value
1778        data.placement = computeAutoPlacement(this.options.placement, data.offsets.reference, this.popper);
1779
1780        // store the computed placement inside `originalPlacement`
1781        data.originalPlacement = this.options.placement;
1782
1783        // compute the popper offsets
1784        data.offsets.popper = getPopperOffsets(this.state, this.popper, data.offsets.reference, data.placement);
1785
1786        // run the modifiers
1787        data = runModifiers(this.modifiers, data);
1788
1789        // the first `update` will call `onCreate` callback
1790        // the other ones will call `onUpdate` callback
1791        if (!this.state.isCreated) {
1792            this.state.isCreated = true;
1793            this.options.onCreate(data);
1794        } else {
1795            this.options.onUpdate(data);
1796        }
1797    }
1798
1799    /**
1800     * Schedule an update, it will run on the next UI update available
1801     * @method
1802     * @memberof Popper
1803     */
1804
1805
1806    /**
1807     * Destroy the popper
1808     * @method
1809     * @memberof Popper
1810     */
1811    destroy() {
1812        this.state.isDestroyed = true;
1813
1814        // touch DOM only if `applyStyle` modifier is enabled
1815        if (isModifierEnabled(this.modifiers, 'applyStyle')) {
1816            this.popper.removeAttribute('x-placement');
1817            this.popper.style.left = '';
1818            this.popper.style.position = '';
1819            this.popper.style.top = '';
1820            this.popper.style[getSupportedPropertyName('transform')] = '';
1821        }
1822
1823        this.disableEventListeners();
1824
1825        // remove the popper if user explicity asked for the deletion on destroy
1826        // do not use `remove` because IE11 doesn't support it
1827        if (this.options.removeOnDestroy) {
1828            this.popper.parentNode.removeChild(this.popper);
1829        }
1830        return this;
1831    }
1832
1833    /**
1834     * it will add resize/scroll events and start recalculating
1835     * position of the popper element when they are triggered
1836     * @method
1837     * @memberof Popper
1838     */
1839    enableEventListeners() {
1840        if (!this.state.eventsEnabled) {
1841            this.state = setupEventListeners(this.reference, this.options, this.state, this.scheduleUpdate);
1842        }
1843    }
1844
1845    /**
1846     * it will remove resize/scroll events and won't recalculate
1847     * popper position when they are triggered. It also won't trigger onUpdate callback anymore,
1848     * unless you call 'update' method manually.
1849     * @method
1850     * @memberof Popper
1851     */
1852    disableEventListeners() {
1853        if (this.state.eventsEnabled) {
1854            window.cancelAnimationFrame(this.scheduleUpdate);
1855            this.state = removeEventListeners(this.reference, this.state);
1856        }
1857    }
1858
1859    /**
1860     * Collection of utilities useful when writing custom modifiers
1861     * @memberof Popper
1862     */
1863
1864
1865    /**
1866     * List of accepted placements to use as values of the `placement` option
1867     * @memberof Popper
1868     */
1869
1870
1871    /**
1872     * Default Popper.js options
1873     * @memberof Popper
1874     */
1875}
1876Popper.Utils = Utils;
1877Popper.placements = ['auto', 'auto-start', 'auto-end', 'top', 'top-start', 'top-end', 'right', 'right-start', 'right-end', 'bottom', 'bottom-start', 'bottom-end', 'left', 'left-start', 'left-end'];
1878Popper.Defaults = DEFAULTS;
1879
1880return Popper;
1881
1882})));
1883//# sourceMappingURL=popper.js.map

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.