popper_js 1.9.9

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