Issues (141)

resources/bootstrap/js/popper.js (2 issues)

1
/**!
2
 * @fileOverview Kickass library to create and place poppers near their reference elements.
3
 * @version 1.16.1
4
 * @license
5
 * Copyright (c) 2016 Federico Zivolo and contributors
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8
 * of this software and associated documentation files (the "Software"), to deal
9
 * in the Software without restriction, including without limitation the rights
10
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
 * copies of the Software, and to permit persons to whom the Software is
12
 * furnished to do so, subject to the following conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be included in all
15
 * copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
 * SOFTWARE.
24
 */
25
(function (global, factory) {
26
	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
27
	typeof define === 'function' && define.amd ? define(factory) :
28
	(global.Popper = factory());
29
}(this, (function () { 'use strict';
30
31
var isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined' && typeof navigator !== 'undefined';
32
33
var timeoutDuration = function () {
34
  var longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox'];
35
  for (var i = 0; i < longerTimeoutBrowsers.length; i += 1) {
36
    if (isBrowser && navigator.userAgent.indexOf(longerTimeoutBrowsers[i]) >= 0) {
37
      return 1;
38
    }
39
  }
40
  return 0;
41
}();
42
43
function microtaskDebounce(fn) {
44
  var called = false;
45
  return function () {
46
    if (called) {
47
      return;
48
    }
49
    called = true;
50
    window.Promise.resolve().then(function () {
51
      called = false;
52
      fn();
53
    });
54
  };
55
}
56
57
function taskDebounce(fn) {
58
  var scheduled = false;
59
  return function () {
60
    if (!scheduled) {
61
      scheduled = true;
62
      setTimeout(function () {
63
        scheduled = false;
64
        fn();
65
      }, timeoutDuration);
66
    }
67
  };
68
}
69
70
var supportsMicroTasks = isBrowser && window.Promise;
71
72
/**
73
* Create a debounced version of a method, that's asynchronously deferred
74
* but called in the minimum time possible.
75
*
76
* @method
77
* @memberof Popper.Utils
78
* @argument {Function} fn
79
* @returns {Function}
80
*/
81
var debounce = supportsMicroTasks ? microtaskDebounce : taskDebounce;
82
83
/**
84
 * Check if the given variable is a function
85
 * @method
86
 * @memberof Popper.Utils
87
 * @argument {Any} functionToCheck - variable to check
88
 * @returns {Boolean} answer to: is a function?
89
 */
90
function isFunction(functionToCheck) {
91
  var getType = {};
92
  return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
93
}
94
95
/**
96
 * Get CSS computed property of the given element
97
 * @method
98
 * @memberof Popper.Utils
99
 * @argument {Eement} element
100
 * @argument {String} property
101
 */
102
function getStyleComputedProperty(element, property) {
103
  if (element.nodeType !== 1) {
104
    return [];
105
  }
106
  // NOTE: 1 DOM access here
107
  var window = element.ownerDocument.defaultView;
108
  var css = window.getComputedStyle(element, null);
109
  return property ? css[property] : css;
110
}
111
112
/**
113
 * Returns the parentNode or the host of the element
114
 * @method
115
 * @memberof Popper.Utils
116
 * @argument {Element} element
117
 * @returns {Element} parent
118
 */
119
function getParentNode(element) {
120
  if (element.nodeName === 'HTML') {
121
    return element;
122
  }
123
  return element.parentNode || element.host;
124
}
125
126
/**
127
 * Returns the scrolling parent of the given element
128
 * @method
129
 * @memberof Popper.Utils
130
 * @argument {Element} element
131
 * @returns {Element} scroll parent
132
 */
133
function getScrollParent(element) {
134
  // Return body, `getScroll` will take care to get the correct `scrollTop` from it
135
  if (!element) {
136
    return document.body;
137
  }
138
139
  switch (element.nodeName) {
140
    case 'HTML':
141
    case 'BODY':
142
      return element.ownerDocument.body;
143
    case '#document':
144
      return element.body;
145
  }
146
147
  // Firefox want us to check `-x` and `-y` variations as well
148
149
  var _getStyleComputedProp = getStyleComputedProperty(element),
150
      overflow = _getStyleComputedProp.overflow,
151
      overflowX = _getStyleComputedProp.overflowX,
152
      overflowY = _getStyleComputedProp.overflowY;
153
154
  if (/(auto|scroll|overlay)/.test(overflow + overflowY + overflowX)) {
155
    return element;
156
  }
157
158
  return getScrollParent(getParentNode(element));
159
}
160
161
/**
162
 * Returns the reference node of the reference object, or the reference object itself.
163
 * @method
164
 * @memberof Popper.Utils
165
 * @param {Element|Object} reference - the reference element (the popper will be relative to this)
166
 * @returns {Element} parent
167
 */
168
function getReferenceNode(reference) {
169
  return reference && reference.referenceNode ? reference.referenceNode : reference;
170
}
171
172
var isIE11 = isBrowser && !!(window.MSInputMethodContext && document.documentMode);
173
var isIE10 = isBrowser && /MSIE 10/.test(navigator.userAgent);
174
175
/**
176
 * Determines if the browser is Internet Explorer
177
 * @method
178
 * @memberof Popper.Utils
179
 * @param {Number} version to check
180
 * @returns {Boolean} isIE
181
 */
182
function isIE(version) {
183
  if (version === 11) {
184
    return isIE11;
185
  }
186
  if (version === 10) {
187
    return isIE10;
188
  }
189
  return isIE11 || isIE10;
190
}
191
192
/**
193
 * Returns the offset parent of the given element
194
 * @method
195
 * @memberof Popper.Utils
196
 * @argument {Element} element
197
 * @returns {Element} offset parent
198
 */
199
function getOffsetParent(element) {
200
  if (!element) {
201
    return document.documentElement;
202
  }
203
204
  var noOffsetParent = isIE(10) ? document.body : null;
205
206
  // NOTE: 1 DOM access here
207
  var offsetParent = element.offsetParent || null;
208
  // Skip hidden elements which don't have an offsetParent
209
  while (offsetParent === noOffsetParent && element.nextElementSibling) {
210
    offsetParent = (element = element.nextElementSibling).offsetParent;
211
  }
212
213
  var nodeName = offsetParent && offsetParent.nodeName;
214
215
  if (!nodeName || nodeName === 'BODY' || nodeName === 'HTML') {
216
    return element ? element.ownerDocument.documentElement : document.documentElement;
217
  }
218
219
  // .offsetParent will return the closest TH, TD or TABLE in case
220
  // no offsetParent is present, I hate this job...
221
  if (['TH', 'TD', 'TABLE'].indexOf(offsetParent.nodeName) !== -1 && getStyleComputedProperty(offsetParent, 'position') === 'static') {
222
    return getOffsetParent(offsetParent);
223
  }
224
225
  return offsetParent;
226
}
227
228
function isOffsetContainer(element) {
229
  var nodeName = element.nodeName;
230
231
  if (nodeName === 'BODY') {
232
    return false;
233
  }
234
  return nodeName === 'HTML' || getOffsetParent(element.firstElementChild) === element;
235
}
236
237
/**
238
 * Finds the root node (document, shadowDOM root) of the given element
239
 * @method
240
 * @memberof Popper.Utils
241
 * @argument {Element} node
242
 * @returns {Element} root node
243
 */
244
function getRoot(node) {
245
  if (node.parentNode !== null) {
246
    return getRoot(node.parentNode);
247
  }
248
249
  return node;
250
}
251
252
/**
253
 * Finds the offset parent common to the two provided nodes
254
 * @method
255
 * @memberof Popper.Utils
256
 * @argument {Element} element1
257
 * @argument {Element} element2
258
 * @returns {Element} common offset parent
259
 */
260
function findCommonOffsetParent(element1, element2) {
261
  // This check is needed to avoid errors in case one of the elements isn't defined for any reason
262
  if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) {
263
    return document.documentElement;
264
  }
265
266
  // Here we make sure to give as "start" the element that comes first in the DOM
267
  var order = element1.compareDocumentPosition(element2) & Node.DOCUMENT_POSITION_FOLLOWING;
268
  var start = order ? element1 : element2;
269
  var end = order ? element2 : element1;
270
271
  // Get common ancestor container
272
  var range = document.createRange();
273
  range.setStart(start, 0);
274
  range.setEnd(end, 0);
275
  var commonAncestorContainer = range.commonAncestorContainer;
276
277
  // Both nodes are inside #document
278
279
  if (element1 !== commonAncestorContainer && element2 !== commonAncestorContainer || start.contains(end)) {
280
    if (isOffsetContainer(commonAncestorContainer)) {
281
      return commonAncestorContainer;
282
    }
283
284
    return getOffsetParent(commonAncestorContainer);
285
  }
286
287
  // one of the nodes is inside shadowDOM, find which one
288
  var element1root = getRoot(element1);
289
  if (element1root.host) {
290
    return findCommonOffsetParent(element1root.host, element2);
291
  } else {
292
    return findCommonOffsetParent(element1, getRoot(element2).host);
293
  }
294
}
295
296
/**
297
 * Gets the scroll value of the given element in the given side (top and left)
298
 * @method
299
 * @memberof Popper.Utils
300
 * @argument {Element} element
301
 * @argument {String} side `top` or `left`
302
 * @returns {number} amount of scrolled pixels
303
 */
304
function getScroll(element) {
305
  var side = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'top';
306
307
  var upperSide = side === 'top' ? 'scrollTop' : 'scrollLeft';
308
  var nodeName = element.nodeName;
309
310
  if (nodeName === 'BODY' || nodeName === 'HTML') {
311
    var html = element.ownerDocument.documentElement;
312
    var scrollingElement = element.ownerDocument.scrollingElement || html;
313
    return scrollingElement[upperSide];
314
  }
315
316
  return element[upperSide];
317
}
318
319
/*
320
 * Sum or subtract the element scroll values (left and top) from a given rect object
321
 * @method
322
 * @memberof Popper.Utils
323
 * @param {Object} rect - Rect object you want to change
324
 * @param {HTMLElement} element - The element from the function reads the scroll values
325
 * @param {Boolean} subtract - set to true if you want to subtract the scroll values
326
 * @return {Object} rect - The modifier rect object
327
 */
328
function includeScroll(rect, element) {
329
  var subtract = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
330
331
  var scrollTop = getScroll(element, 'top');
332
  var scrollLeft = getScroll(element, 'left');
333
  var modifier = subtract ? -1 : 1;
334
  rect.top += scrollTop * modifier;
335
  rect.bottom += scrollTop * modifier;
336
  rect.left += scrollLeft * modifier;
337
  rect.right += scrollLeft * modifier;
338
  return rect;
339
}
340
341
/*
342
 * Helper to detect borders of a given element
343
 * @method
344
 * @memberof Popper.Utils
345
 * @param {CSSStyleDeclaration} styles
346
 * Result of `getStyleComputedProperty` on the given element
347
 * @param {String} axis - `x` or `y`
348
 * @return {number} borders - The borders size of the given axis
349
 */
350
351
function getBordersSize(styles, axis) {
352
  var sideA = axis === 'x' ? 'Left' : 'Top';
353
  var sideB = sideA === 'Left' ? 'Right' : 'Bottom';
354
355
  return parseFloat(styles['border' + sideA + 'Width']) + parseFloat(styles['border' + sideB + 'Width']);
356
}
357
358
function getSize(axis, body, html, computedStyle) {
359
  return Math.max(body['offset' + axis], body['scroll' + axis], html['client' + axis], html['offset' + axis], html['scroll' + axis], isIE(10) ? parseInt(html['offset' + axis]) + parseInt(computedStyle['margin' + (axis === 'Height' ? 'Top' : 'Left')]) + parseInt(computedStyle['margin' + (axis === 'Height' ? 'Bottom' : 'Right')]) : 0);
360
}
361
362
function getWindowSizes(document) {
363
  var body = document.body;
364
  var html = document.documentElement;
365
  var computedStyle = isIE(10) && getComputedStyle(html);
366
367
  return {
368
    height: getSize('Height', body, html, computedStyle),
369
    width: getSize('Width', body, html, computedStyle)
370
  };
371
}
372
373
var classCallCheck = function (instance, Constructor) {
374
  if (!(instance instanceof Constructor)) {
375
    throw new TypeError("Cannot call a class as a function");
376
  }
377
};
378
379
var createClass = function () {
380
  function defineProperties(target, props) {
381
    for (var i = 0; i < props.length; i++) {
382
      var descriptor = props[i];
383
      descriptor.enumerable = descriptor.enumerable || false;
384
      descriptor.configurable = true;
385
      if ("value" in descriptor) descriptor.writable = true;
386
      Object.defineProperty(target, descriptor.key, descriptor);
387
    }
388
  }
389
390
  return function (Constructor, protoProps, staticProps) {
391
    if (protoProps) defineProperties(Constructor.prototype, protoProps);
392
    if (staticProps) defineProperties(Constructor, staticProps);
393
    return Constructor;
394
  };
395
}();
396
397
398
399
400
401
var defineProperty = function (obj, key, value) {
402
  if (key in obj) {
403
    Object.defineProperty(obj, key, {
404
      value: value,
405
      enumerable: true,
406
      configurable: true,
407
      writable: true
408
    });
409
  } else {
410
    obj[key] = value;
411
  }
412
413
  return obj;
414
};
415
416
var _extends = Object.assign || function (target) {
417
  for (var i = 1; i < arguments.length; i++) {
418
    var source = arguments[i];
419
420
    for (var key in source) {
0 ignored issues
show
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
421
      if (Object.prototype.hasOwnProperty.call(source, key)) {
422
        target[key] = source[key];
423
      }
424
    }
425
  }
426
427
  return target;
428
};
429
430
/**
431
 * Given element offsets, generate an output similar to getBoundingClientRect
432
 * @method
433
 * @memberof Popper.Utils
434
 * @argument {Object} offsets
435
 * @returns {Object} ClientRect like output
436
 */
437
function getClientRect(offsets) {
438
  return _extends({}, offsets, {
439
    right: offsets.left + offsets.width,
440
    bottom: offsets.top + offsets.height
441
  });
442
}
443
444
/**
445
 * Get bounding client rect of given element
446
 * @method
447
 * @memberof Popper.Utils
448
 * @param {HTMLElement} element
449
 * @return {Object} client rect
450
 */
451
function getBoundingClientRect(element) {
452
  var rect = {};
453
454
  // IE10 10 FIX: Please, don't ask, the element isn't
455
  // considered in DOM in some circumstances...
456
  // This isn't reproducible in IE10 compatibility mode of IE11
457
  try {
458
    if (isIE(10)) {
459
      rect = element.getBoundingClientRect();
460
      var scrollTop = getScroll(element, 'top');
461
      var scrollLeft = getScroll(element, 'left');
462
      rect.top += scrollTop;
463
      rect.left += scrollLeft;
464
      rect.bottom += scrollTop;
465
      rect.right += scrollLeft;
466
    } else {
467
      rect = element.getBoundingClientRect();
468
    }
469
  } catch (e) {}
470
471
  var result = {
472
    left: rect.left,
473
    top: rect.top,
474
    width: rect.right - rect.left,
475
    height: rect.bottom - rect.top
476
  };
477
478
  // subtract scrollbar size from sizes
479
  var sizes = element.nodeName === 'HTML' ? getWindowSizes(element.ownerDocument) : {};
480
  var width = sizes.width || element.clientWidth || result.width;
481
  var height = sizes.height || element.clientHeight || result.height;
482
483
  var horizScrollbar = element.offsetWidth - width;
484
  var vertScrollbar = element.offsetHeight - height;
485
486
  // if an hypothetical scrollbar is detected, we must be sure it's not a `border`
487
  // we make this check conditional for performance reasons
488
  if (horizScrollbar || vertScrollbar) {
489
    var styles = getStyleComputedProperty(element);
490
    horizScrollbar -= getBordersSize(styles, 'x');
491
    vertScrollbar -= getBordersSize(styles, 'y');
492
493
    result.width -= horizScrollbar;
494
    result.height -= vertScrollbar;
495
  }
496
497
  return getClientRect(result);
498
}
499
500
function getOffsetRectRelativeToArbitraryNode(children, parent) {
501
  var fixedPosition = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
502
503
  var isIE10 = isIE(10);
504
  var isHTML = parent.nodeName === 'HTML';
505
  var childrenRect = getBoundingClientRect(children);
506
  var parentRect = getBoundingClientRect(parent);
507
  var scrollParent = getScrollParent(children);
508
509
  var styles = getStyleComputedProperty(parent);
510
  var borderTopWidth = parseFloat(styles.borderTopWidth);
511
  var borderLeftWidth = parseFloat(styles.borderLeftWidth);
512
513
  // In cases where the parent is fixed, we must ignore negative scroll in offset calc
514
  if (fixedPosition && isHTML) {
515
    parentRect.top = Math.max(parentRect.top, 0);
516
    parentRect.left = Math.max(parentRect.left, 0);
517
  }
518
  var offsets = getClientRect({
519
    top: childrenRect.top - parentRect.top - borderTopWidth,
520
    left: childrenRect.left - parentRect.left - borderLeftWidth,
521
    width: childrenRect.width,
522
    height: childrenRect.height
523
  });
524
  offsets.marginTop = 0;
525
  offsets.marginLeft = 0;
526
527
  // Subtract margins of documentElement in case it's being used as parent
528
  // we do this only on HTML because it's the only element that behaves
529
  // differently when margins are applied to it. The margins are included in
530
  // the box of the documentElement, in the other cases not.
531
  if (!isIE10 && isHTML) {
532
    var marginTop = parseFloat(styles.marginTop);
533
    var marginLeft = parseFloat(styles.marginLeft);
534
535
    offsets.top -= borderTopWidth - marginTop;
536
    offsets.bottom -= borderTopWidth - marginTop;
537
    offsets.left -= borderLeftWidth - marginLeft;
538
    offsets.right -= borderLeftWidth - marginLeft;
539
540
    // Attach marginTop and marginLeft because in some circumstances we may need them
541
    offsets.marginTop = marginTop;
542
    offsets.marginLeft = marginLeft;
543
  }
544
545
  if (isIE10 && !fixedPosition ? parent.contains(scrollParent) : parent === scrollParent && scrollParent.nodeName !== 'BODY') {
546
    offsets = includeScroll(offsets, parent);
547
  }
548
549
  return offsets;
550
}
551
552
function getViewportOffsetRectRelativeToArtbitraryNode(element) {
553
  var excludeScroll = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
554
555
  var html = element.ownerDocument.documentElement;
556
  var relativeOffset = getOffsetRectRelativeToArbitraryNode(element, html);
557
  var width = Math.max(html.clientWidth, window.innerWidth || 0);
558
  var height = Math.max(html.clientHeight, window.innerHeight || 0);
559
560
  var scrollTop = !excludeScroll ? getScroll(html) : 0;
561
  var scrollLeft = !excludeScroll ? getScroll(html, 'left') : 0;
562
563
  var offset = {
564
    top: scrollTop - relativeOffset.top + relativeOffset.marginTop,
565
    left: scrollLeft - relativeOffset.left + relativeOffset.marginLeft,
566
    width: width,
567
    height: height
568
  };
569
570
  return getClientRect(offset);
571
}
572
573
/**
574
 * Check if the given element is fixed or is inside a fixed parent
575
 * @method
576
 * @memberof Popper.Utils
577
 * @argument {Element} element
578
 * @argument {Element} customContainer
579
 * @returns {Boolean} answer to "isFixed?"
580
 */
581
function isFixed(element) {
582
  var nodeName = element.nodeName;
583
  if (nodeName === 'BODY' || nodeName === 'HTML') {
584
    return false;
585
  }
586
  if (getStyleComputedProperty(element, 'position') === 'fixed') {
587
    return true;
588
  }
589
  var parentNode = getParentNode(element);
590
  if (!parentNode) {
591
    return false;
592
  }
593
  return isFixed(parentNode);
594
}
595
596
/**
597
 * Finds the first parent of an element that has a transformed property defined
598
 * @method
599
 * @memberof Popper.Utils
600
 * @argument {Element} element
601
 * @returns {Element} first transformed parent or documentElement
602
 */
603
604
function getFixedPositionOffsetParent(element) {
605
  // This check is needed to avoid errors in case one of the elements isn't defined for any reason
606
  if (!element || !element.parentElement || isIE()) {
607
    return document.documentElement;
608
  }
609
  var el = element.parentElement;
610
  while (el && getStyleComputedProperty(el, 'transform') === 'none') {
611
    el = el.parentElement;
612
  }
613
  return el || document.documentElement;
614
}
615
616
/**
617
 * Computed the boundaries limits and return them
618
 * @method
619
 * @memberof Popper.Utils
620
 * @param {HTMLElement} popper
621
 * @param {HTMLElement} reference
622
 * @param {number} padding
623
 * @param {HTMLElement} boundariesElement - Element used to define the boundaries
624
 * @param {Boolean} fixedPosition - Is in fixed position mode
625
 * @returns {Object} Coordinates of the boundaries
626
 */
627
function getBoundaries(popper, reference, padding, boundariesElement) {
628
  var fixedPosition = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
629
630
  // NOTE: 1 DOM access here
631
632
  var boundaries = { top: 0, left: 0 };
633
  var offsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, getReferenceNode(reference));
634
635
  // Handle viewport case
636
  if (boundariesElement === 'viewport') {
637
    boundaries = getViewportOffsetRectRelativeToArtbitraryNode(offsetParent, fixedPosition);
638
  } else {
639
    // Handle other cases based on DOM element used as boundaries
640
    var boundariesNode = void 0;
641
    if (boundariesElement === 'scrollParent') {
642
      boundariesNode = getScrollParent(getParentNode(reference));
643
      if (boundariesNode.nodeName === 'BODY') {
644
        boundariesNode = popper.ownerDocument.documentElement;
645
      }
646
    } else if (boundariesElement === 'window') {
647
      boundariesNode = popper.ownerDocument.documentElement;
648
    } else {
649
      boundariesNode = boundariesElement;
650
    }
651
652
    var offsets = getOffsetRectRelativeToArbitraryNode(boundariesNode, offsetParent, fixedPosition);
653
654
    // In case of HTML, we need a different computation
655
    if (boundariesNode.nodeName === 'HTML' && !isFixed(offsetParent)) {
656
      var _getWindowSizes = getWindowSizes(popper.ownerDocument),
657
          height = _getWindowSizes.height,
658
          width = _getWindowSizes.width;
659
660
      boundaries.top += offsets.top - offsets.marginTop;
661
      boundaries.bottom = height + offsets.top;
662
      boundaries.left += offsets.left - offsets.marginLeft;
663
      boundaries.right = width + offsets.left;
664
    } else {
665
      // for all the other DOM elements, this one is good
666
      boundaries = offsets;
667
    }
668
  }
669
670
  // Add paddings
671
  padding = padding || 0;
672
  var isPaddingNumber = typeof padding === 'number';
673
  boundaries.left += isPaddingNumber ? padding : padding.left || 0;
674
  boundaries.top += isPaddingNumber ? padding : padding.top || 0;
675
  boundaries.right -= isPaddingNumber ? padding : padding.right || 0;
676
  boundaries.bottom -= isPaddingNumber ? padding : padding.bottom || 0;
677
678
  return boundaries;
679
}
680
681
function getArea(_ref) {
682
  var width = _ref.width,
683
      height = _ref.height;
684
685
  return width * height;
686
}
687
688
/**
689
 * Utility used to transform the `auto` placement to the placement with more
690
 * available space.
691
 * @method
692
 * @memberof Popper.Utils
693
 * @argument {Object} data - The data object generated by update method
694
 * @argument {Object} options - Modifiers configuration and options
695
 * @returns {Object} The data object, properly modified
696
 */
697
function computeAutoPlacement(placement, refRect, popper, reference, boundariesElement) {
698
  var padding = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0;
699
700
  if (placement.indexOf('auto') === -1) {
701
    return placement;
702
  }
703
704
  var boundaries = getBoundaries(popper, reference, padding, boundariesElement);
705
706
  var rects = {
707
    top: {
708
      width: boundaries.width,
709
      height: refRect.top - boundaries.top
710
    },
711
    right: {
712
      width: boundaries.right - refRect.right,
713
      height: boundaries.height
714
    },
715
    bottom: {
716
      width: boundaries.width,
717
      height: boundaries.bottom - refRect.bottom
718
    },
719
    left: {
720
      width: refRect.left - boundaries.left,
721
      height: boundaries.height
722
    }
723
  };
724
725
  var sortedAreas = Object.keys(rects).map(function (key) {
726
    return _extends({
727
      key: key
728
    }, rects[key], {
729
      area: getArea(rects[key])
730
    });
731
  }).sort(function (a, b) {
732
    return b.area - a.area;
733
  });
734
735
  var filteredAreas = sortedAreas.filter(function (_ref2) {
736
    var width = _ref2.width,
737
        height = _ref2.height;
738
    return width >= popper.clientWidth && height >= popper.clientHeight;
739
  });
740
741
  var computedPlacement = filteredAreas.length > 0 ? filteredAreas[0].key : sortedAreas[0].key;
742
743
  var variation = placement.split('-')[1];
744
745
  return computedPlacement + (variation ? '-' + variation : '');
746
}
747
748
/**
749
 * Get offsets to the reference element
750
 * @method
751
 * @memberof Popper.Utils
752
 * @param {Object} state
753
 * @param {Element} popper - the popper element
754
 * @param {Element} reference - the reference element (the popper will be relative to this)
755
 * @param {Element} fixedPosition - is in fixed position mode
756
 * @returns {Object} An object containing the offsets which will be applied to the popper
757
 */
758
function getReferenceOffsets(state, popper, reference) {
759
  var fixedPosition = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
760
761
  var commonOffsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, getReferenceNode(reference));
762
  return getOffsetRectRelativeToArbitraryNode(reference, commonOffsetParent, fixedPosition);
763
}
764
765
/**
766
 * Get the outer sizes of the given element (offset size + margins)
767
 * @method
768
 * @memberof Popper.Utils
769
 * @argument {Element} element
770
 * @returns {Object} object containing width and height properties
771
 */
772
function getOuterSizes(element) {
773
  var window = element.ownerDocument.defaultView;
774
  var styles = window.getComputedStyle(element);
775
  var x = parseFloat(styles.marginTop || 0) + parseFloat(styles.marginBottom || 0);
776
  var y = parseFloat(styles.marginLeft || 0) + parseFloat(styles.marginRight || 0);
777
  var result = {
778
    width: element.offsetWidth + y,
779
    height: element.offsetHeight + x
780
  };
781
  return result;
782
}
783
784
/**
785
 * Get the opposite placement of the given one
786
 * @method
787
 * @memberof Popper.Utils
788
 * @argument {String} placement
789
 * @returns {String} flipped placement
790
 */
791
function getOppositePlacement(placement) {
792
  var hash = { left: 'right', right: 'left', bottom: 'top', top: 'bottom' };
793
  return placement.replace(/left|right|bottom|top/g, function (matched) {
794
    return hash[matched];
795
  });
796
}
797
798
/**
799
 * Get offsets to the popper
800
 * @method
801
 * @memberof Popper.Utils
802
 * @param {Object} position - CSS position the Popper will get applied
803
 * @param {HTMLElement} popper - the popper element
804
 * @param {Object} referenceOffsets - the reference offsets (the popper will be relative to this)
805
 * @param {String} placement - one of the valid placement options
806
 * @returns {Object} popperOffsets - An object containing the offsets which will be applied to the popper
807
 */
808
function getPopperOffsets(popper, referenceOffsets, placement) {
809
  placement = placement.split('-')[0];
810
811
  // Get popper node sizes
812
  var popperRect = getOuterSizes(popper);
813
814
  // Add position, width and height to our offsets object
815
  var popperOffsets = {
816
    width: popperRect.width,
817
    height: popperRect.height
818
  };
819
820
  // depending by the popper placement we have to compute its offsets slightly differently
821
  var isHoriz = ['right', 'left'].indexOf(placement) !== -1;
822
  var mainSide = isHoriz ? 'top' : 'left';
823
  var secondarySide = isHoriz ? 'left' : 'top';
824
  var measurement = isHoriz ? 'height' : 'width';
825
  var secondaryMeasurement = !isHoriz ? 'height' : 'width';
826
827
  popperOffsets[mainSide] = referenceOffsets[mainSide] + referenceOffsets[measurement] / 2 - popperRect[measurement] / 2;
828
  if (placement === secondarySide) {
829
    popperOffsets[secondarySide] = referenceOffsets[secondarySide] - popperRect[secondaryMeasurement];
830
  } else {
831
    popperOffsets[secondarySide] = referenceOffsets[getOppositePlacement(secondarySide)];
832
  }
833
834
  return popperOffsets;
835
}
836
837
/**
838
 * Mimics the `find` method of Array
839
 * @method
840
 * @memberof Popper.Utils
841
 * @argument {Array} arr
842
 * @argument prop
843
 * @argument value
844
 * @returns index or -1
845
 */
846
function find(arr, check) {
847
  // use native find if supported
848
  if (Array.prototype.find) {
849
    return arr.find(check);
850
  }
851
852
  // use `filter` to obtain the same behavior of `find`
853
  return arr.filter(check)[0];
854
}
855
856
/**
857
 * Return the index of the matching object
858
 * @method
859
 * @memberof Popper.Utils
860
 * @argument {Array} arr
861
 * @argument prop
862
 * @argument value
863
 * @returns index or -1
864
 */
865
function findIndex(arr, prop, value) {
866
  // use native findIndex if supported
867
  if (Array.prototype.findIndex) {
868
    return arr.findIndex(function (cur) {
869
      return cur[prop] === value;
870
    });
871
  }
872
873
  // use `find` + `indexOf` if `findIndex` isn't supported
874
  var match = find(arr, function (obj) {
875
    return obj[prop] === value;
876
  });
877
  return arr.indexOf(match);
878
}
879
880
/**
881
 * Loop trough the list of modifiers and run them in order,
882
 * each of them will then edit the data object.
883
 * @method
884
 * @memberof Popper.Utils
885
 * @param {dataObject} data
886
 * @param {Array} modifiers
887
 * @param {String} ends - Optional modifier name used as stopper
888
 * @returns {dataObject}
889
 */
890
function runModifiers(modifiers, data, ends) {
891
  var modifiersToRun = ends === undefined ? modifiers : modifiers.slice(0, findIndex(modifiers, 'name', ends));
892
893
  modifiersToRun.forEach(function (modifier) {
894
    if (modifier['function']) {
895
      // eslint-disable-line dot-notation
896
      console.warn('`modifier.function` is deprecated, use `modifier.fn`!');
897
    }
898
    var fn = modifier['function'] || modifier.fn; // eslint-disable-line dot-notation
899
    if (modifier.enabled && isFunction(fn)) {
900
      // Add properties to offsets to make them a complete clientRect object
901
      // we do this before each modifier to make sure the previous one doesn't
902
      // mess with these values
903
      data.offsets.popper = getClientRect(data.offsets.popper);
904
      data.offsets.reference = getClientRect(data.offsets.reference);
905
906
      data = fn(data, modifier);
907
    }
908
  });
909
910
  return data;
911
}
912
913
/**
914
 * Updates the position of the popper, computing the new offsets and applying
915
 * the new style.<br />
916
 * Prefer `scheduleUpdate` over `update` because of performance reasons.
917
 * @method
918
 * @memberof Popper
919
 */
920
function update() {
921
  // if popper is destroyed, don't perform any further update
922
  if (this.state.isDestroyed) {
923
    return;
924
  }
925
926
  var data = {
927
    instance: this,
928
    styles: {},
929
    arrowStyles: {},
930
    attributes: {},
931
    flipped: false,
932
    offsets: {}
933
  };
934
935
  // compute reference element offsets
936
  data.offsets.reference = getReferenceOffsets(this.state, this.popper, this.reference, this.options.positionFixed);
937
938
  // compute auto placement, store placement inside the data object,
939
  // modifiers will be able to edit `placement` if needed
940
  // and refer to originalPlacement to know the original value
941
  data.placement = computeAutoPlacement(this.options.placement, data.offsets.reference, this.popper, this.reference, this.options.modifiers.flip.boundariesElement, this.options.modifiers.flip.padding);
942
943
  // store the computed placement inside `originalPlacement`
944
  data.originalPlacement = data.placement;
945
946
  data.positionFixed = this.options.positionFixed;
947
948
  // compute the popper offsets
949
  data.offsets.popper = getPopperOffsets(this.popper, data.offsets.reference, data.placement);
950
951
  data.offsets.popper.position = this.options.positionFixed ? 'fixed' : 'absolute';
952
953
  // run the modifiers
954
  data = runModifiers(this.modifiers, data);
955
956
  // the first `update` will call `onCreate` callback
957
  // the other ones will call `onUpdate` callback
958
  if (!this.state.isCreated) {
959
    this.state.isCreated = true;
960
    this.options.onCreate(data);
961
  } else {
962
    this.options.onUpdate(data);
963
  }
964
}
965
966
/**
967
 * Helper used to know if the given modifier is enabled.
968
 * @method
969
 * @memberof Popper.Utils
970
 * @returns {Boolean}
971
 */
972
function isModifierEnabled(modifiers, modifierName) {
973
  return modifiers.some(function (_ref) {
974
    var name = _ref.name,
975
        enabled = _ref.enabled;
976
    return enabled && name === modifierName;
977
  });
978
}
979
980
/**
981
 * Get the prefixed supported property name
982
 * @method
983
 * @memberof Popper.Utils
984
 * @argument {String} property (camelCase)
985
 * @returns {String} prefixed property (camelCase or PascalCase, depending on the vendor prefix)
986
 */
987
function getSupportedPropertyName(property) {
988
  var prefixes = [false, 'ms', 'Webkit', 'Moz', 'O'];
989
  var upperProp = property.charAt(0).toUpperCase() + property.slice(1);
990
991
  for (var i = 0; i < prefixes.length; i++) {
992
    var prefix = prefixes[i];
993
    var toCheck = prefix ? '' + prefix + upperProp : property;
994
    if (typeof document.body.style[toCheck] !== 'undefined') {
995
      return toCheck;
996
    }
997
  }
998
  return null;
999
}
1000
1001
/**
1002
 * Destroys the popper.
1003
 * @method
1004
 * @memberof Popper
1005
 */
1006
function destroy() {
1007
  this.state.isDestroyed = true;
1008
1009
  // touch DOM only if `applyStyle` modifier is enabled
1010
  if (isModifierEnabled(this.modifiers, 'applyStyle')) {
1011
    this.popper.removeAttribute('x-placement');
1012
    this.popper.style.position = '';
1013
    this.popper.style.top = '';
1014
    this.popper.style.left = '';
1015
    this.popper.style.right = '';
1016
    this.popper.style.bottom = '';
1017
    this.popper.style.willChange = '';
1018
    this.popper.style[getSupportedPropertyName('transform')] = '';
1019
  }
1020
1021
  this.disableEventListeners();
1022
1023
  // remove the popper if user explicitly asked for the deletion on destroy
1024
  // do not use `remove` because IE11 doesn't support it
1025
  if (this.options.removeOnDestroy) {
1026
    this.popper.parentNode.removeChild(this.popper);
1027
  }
1028
  return this;
1029
}
1030
1031
/**
1032
 * Get the window associated with the element
1033
 * @argument {Element} element
1034
 * @returns {Window}
1035
 */
1036
function getWindow(element) {
1037
  var ownerDocument = element.ownerDocument;
1038
  return ownerDocument ? ownerDocument.defaultView : window;
1039
}
1040
1041
function attachToScrollParents(scrollParent, event, callback, scrollParents) {
1042
  var isBody = scrollParent.nodeName === 'BODY';
1043
  var target = isBody ? scrollParent.ownerDocument.defaultView : scrollParent;
1044
  target.addEventListener(event, callback, { passive: true });
1045
1046
  if (!isBody) {
1047
    attachToScrollParents(getScrollParent(target.parentNode), event, callback, scrollParents);
1048
  }
1049
  scrollParents.push(target);
1050
}
1051
1052
/**
1053
 * Setup needed event listeners used to update the popper position
1054
 * @method
1055
 * @memberof Popper.Utils
1056
 * @private
1057
 */
1058
function setupEventListeners(reference, options, state, updateBound) {
1059
  // Resize event listener on window
1060
  state.updateBound = updateBound;
1061
  getWindow(reference).addEventListener('resize', state.updateBound, { passive: true });
1062
1063
  // Scroll event listener on scroll parents
1064
  var scrollElement = getScrollParent(reference);
1065
  attachToScrollParents(scrollElement, 'scroll', state.updateBound, state.scrollParents);
1066
  state.scrollElement = scrollElement;
1067
  state.eventsEnabled = true;
1068
1069
  return state;
1070
}
1071
1072
/**
1073
 * It will add resize/scroll events and start recalculating
1074
 * position of the popper element when they are triggered.
1075
 * @method
1076
 * @memberof Popper
1077
 */
1078
function enableEventListeners() {
1079
  if (!this.state.eventsEnabled) {
1080
    this.state = setupEventListeners(this.reference, this.options, this.state, this.scheduleUpdate);
1081
  }
1082
}
1083
1084
/**
1085
 * Remove event listeners used to update the popper position
1086
 * @method
1087
 * @memberof Popper.Utils
1088
 * @private
1089
 */
1090
function removeEventListeners(reference, state) {
1091
  // Remove resize event listener on window
1092
  getWindow(reference).removeEventListener('resize', state.updateBound);
1093
1094
  // Remove scroll event listener on scroll parents
1095
  state.scrollParents.forEach(function (target) {
1096
    target.removeEventListener('scroll', state.updateBound);
1097
  });
1098
1099
  // Reset state
1100
  state.updateBound = null;
1101
  state.scrollParents = [];
1102
  state.scrollElement = null;
1103
  state.eventsEnabled = false;
1104
  return state;
1105
}
1106
1107
/**
1108
 * It will remove resize/scroll events and won't recalculate popper position
1109
 * when they are triggered. It also won't trigger `onUpdate` callback anymore,
1110
 * unless you call `update` method manually.
1111
 * @method
1112
 * @memberof Popper
1113
 */
1114
function disableEventListeners() {
1115
  if (this.state.eventsEnabled) {
1116
    cancelAnimationFrame(this.scheduleUpdate);
1117
    this.state = removeEventListeners(this.reference, this.state);
1118
  }
1119
}
1120
1121
/**
1122
 * Tells if a given input is a number
1123
 * @method
1124
 * @memberof Popper.Utils
1125
 * @param {*} input to check
1126
 * @return {Boolean}
1127
 */
1128
function isNumeric(n) {
1129
  return n !== '' && !isNaN(parseFloat(n)) && isFinite(n);
1130
}
1131
1132
/**
1133
 * Set the style to the given popper
1134
 * @method
1135
 * @memberof Popper.Utils
1136
 * @argument {Element} element - Element to apply the style to
1137
 * @argument {Object} styles
1138
 * Object with a list of properties and values which will be applied to the element
1139
 */
1140
function setStyles(element, styles) {
1141
  Object.keys(styles).forEach(function (prop) {
1142
    var unit = '';
1143
    // add unit if the value is numeric and is one of the following
1144
    if (['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== -1 && isNumeric(styles[prop])) {
1145
      unit = 'px';
1146
    }
1147
    element.style[prop] = styles[prop] + unit;
1148
  });
1149
}
1150
1151
/**
1152
 * Set the attributes to the given popper
1153
 * @method
1154
 * @memberof Popper.Utils
1155
 * @argument {Element} element - Element to apply the attributes to
1156
 * @argument {Object} styles
1157
 * Object with a list of properties and values which will be applied to the element
1158
 */
1159
function setAttributes(element, attributes) {
1160
  Object.keys(attributes).forEach(function (prop) {
1161
    var value = attributes[prop];
1162
    if (value !== false) {
1163
      element.setAttribute(prop, attributes[prop]);
1164
    } else {
1165
      element.removeAttribute(prop);
1166
    }
1167
  });
1168
}
1169
1170
/**
1171
 * @function
1172
 * @memberof Modifiers
1173
 * @argument {Object} data - The data object generated by `update` method
1174
 * @argument {Object} data.styles - List of style properties - values to apply to popper element
1175
 * @argument {Object} data.attributes - List of attribute properties - values to apply to popper element
1176
 * @argument {Object} options - Modifiers configuration and options
1177
 * @returns {Object} The same data object
1178
 */
1179
function applyStyle(data) {
1180
  // any property present in `data.styles` will be applied to the popper,
1181
  // in this way we can make the 3rd party modifiers add custom styles to it
1182
  // Be aware, modifiers could override the properties defined in the previous
1183
  // lines of this modifier!
1184
  setStyles(data.instance.popper, data.styles);
1185
1186
  // any property present in `data.attributes` will be applied to the popper,
1187
  // they will be set as HTML attributes of the element
1188
  setAttributes(data.instance.popper, data.attributes);
1189
1190
  // if arrowElement is defined and arrowStyles has some properties
1191
  if (data.arrowElement && Object.keys(data.arrowStyles).length) {
1192
    setStyles(data.arrowElement, data.arrowStyles);
1193
  }
1194
1195
  return data;
1196
}
1197
1198
/**
1199
 * Set the x-placement attribute before everything else because it could be used
1200
 * to add margins to the popper margins needs to be calculated to get the
1201
 * correct popper offsets.
1202
 * @method
1203
 * @memberof Popper.modifiers
1204
 * @param {HTMLElement} reference - The reference element used to position the popper
1205
 * @param {HTMLElement} popper - The HTML element used as popper
1206
 * @param {Object} options - Popper.js options
1207
 */
1208
function applyStyleOnLoad(reference, popper, options, modifierOptions, state) {
1209
  // compute reference element offsets
1210
  var referenceOffsets = getReferenceOffsets(state, popper, reference, options.positionFixed);
1211
1212
  // compute auto placement, store placement inside the data object,
1213
  // modifiers will be able to edit `placement` if needed
1214
  // and refer to originalPlacement to know the original value
1215
  var placement = computeAutoPlacement(options.placement, referenceOffsets, popper, reference, options.modifiers.flip.boundariesElement, options.modifiers.flip.padding);
1216
1217
  popper.setAttribute('x-placement', placement);
1218
1219
  // Apply `position` to popper before anything else because
1220
  // without the position applied we can't guarantee correct computations
1221
  setStyles(popper, { position: options.positionFixed ? 'fixed' : 'absolute' });
1222
1223
  return options;
1224
}
1225
1226
/**
1227
 * @function
1228
 * @memberof Popper.Utils
1229
 * @argument {Object} data - The data object generated by `update` method
1230
 * @argument {Boolean} shouldRound - If the offsets should be rounded at all
1231
 * @returns {Object} The popper's position offsets rounded
1232
 *
1233
 * The tale of pixel-perfect positioning. It's still not 100% perfect, but as
1234
 * good as it can be within reason.
1235
 * Discussion here: https://github.com/FezVrasta/popper.js/pull/715
1236
 *
1237
 * Low DPI screens cause a popper to be blurry if not using full pixels (Safari
1238
 * as well on High DPI screens).
1239
 *
1240
 * Firefox prefers no rounding for positioning and does not have blurriness on
1241
 * high DPI screens.
1242
 *
1243
 * Only horizontal placement and left/right values need to be considered.
1244
 */
1245
function getRoundedOffsets(data, shouldRound) {
1246
  var _data$offsets = data.offsets,
1247
      popper = _data$offsets.popper,
1248
      reference = _data$offsets.reference;
1249
  var round = Math.round,
1250
      floor = Math.floor;
1251
1252
  var noRound = function noRound(v) {
1253
    return v;
1254
  };
1255
1256
  var referenceWidth = round(reference.width);
1257
  var popperWidth = round(popper.width);
1258
1259
  var isVertical = ['left', 'right'].indexOf(data.placement) !== -1;
1260
  var isVariation = data.placement.indexOf('-') !== -1;
1261
  var sameWidthParity = referenceWidth % 2 === popperWidth % 2;
1262
  var bothOddWidth = referenceWidth % 2 === 1 && popperWidth % 2 === 1;
1263
1264
  var horizontalToInteger = !shouldRound ? noRound : isVertical || isVariation || sameWidthParity ? round : floor;
1265
  var verticalToInteger = !shouldRound ? noRound : round;
1266
1267
  return {
1268
    left: horizontalToInteger(bothOddWidth && !isVariation && shouldRound ? popper.left - 1 : popper.left),
1269
    top: verticalToInteger(popper.top),
1270
    bottom: verticalToInteger(popper.bottom),
1271
    right: horizontalToInteger(popper.right)
1272
  };
1273
}
1274
1275
var isFirefox = isBrowser && /Firefox/i.test(navigator.userAgent);
1276
1277
/**
1278
 * @function
1279
 * @memberof Modifiers
1280
 * @argument {Object} data - The data object generated by `update` method
1281
 * @argument {Object} options - Modifiers configuration and options
1282
 * @returns {Object} The data object, properly modified
1283
 */
1284
function computeStyle(data, options) {
1285
  var x = options.x,
1286
      y = options.y;
1287
  var popper = data.offsets.popper;
1288
1289
  // Remove this legacy support in Popper.js v2
1290
1291
  var legacyGpuAccelerationOption = find(data.instance.modifiers, function (modifier) {
1292
    return modifier.name === 'applyStyle';
1293
  }).gpuAcceleration;
1294
  if (legacyGpuAccelerationOption !== undefined) {
1295
    console.warn('WARNING: `gpuAcceleration` option moved to `computeStyle` modifier and will not be supported in future versions of Popper.js!');
1296
  }
1297
  var gpuAcceleration = legacyGpuAccelerationOption !== undefined ? legacyGpuAccelerationOption : options.gpuAcceleration;
1298
1299
  var offsetParent = getOffsetParent(data.instance.popper);
1300
  var offsetParentRect = getBoundingClientRect(offsetParent);
1301
1302
  // Styles
1303
  var styles = {
1304
    position: popper.position
1305
  };
1306
1307
  var offsets = getRoundedOffsets(data, window.devicePixelRatio < 2 || !isFirefox);
1308
1309
  var sideA = x === 'bottom' ? 'top' : 'bottom';
1310
  var sideB = y === 'right' ? 'left' : 'right';
1311
1312
  // if gpuAcceleration is set to `true` and transform is supported,
1313
  //  we use `translate3d` to apply the position to the popper we
1314
  // automatically use the supported prefixed version if needed
1315
  var prefixedProperty = getSupportedPropertyName('transform');
1316
1317
  // now, let's make a step back and look at this code closely (wtf?)
1318
  // If the content of the popper grows once it's been positioned, it
1319
  // may happen that the popper gets misplaced because of the new content
1320
  // overflowing its reference element
1321
  // To avoid this problem, we provide two options (x and y), which allow
1322
  // the consumer to define the offset origin.
1323
  // If we position a popper on top of a reference element, we can set
1324
  // `x` to `top` to make the popper grow towards its top instead of
1325
  // its bottom.
1326
  var left = void 0,
1327
      top = void 0;
1328
  if (sideA === 'bottom') {
1329
    // when offsetParent is <html> the positioning is relative to the bottom of the screen (excluding the scrollbar)
1330
    // and not the bottom of the html element
1331
    if (offsetParent.nodeName === 'HTML') {
1332
      top = -offsetParent.clientHeight + offsets.bottom;
1333
    } else {
1334
      top = -offsetParentRect.height + offsets.bottom;
1335
    }
1336
  } else {
1337
    top = offsets.top;
1338
  }
1339
  if (sideB === 'right') {
1340
    if (offsetParent.nodeName === 'HTML') {
1341
      left = -offsetParent.clientWidth + offsets.right;
1342
    } else {
1343
      left = -offsetParentRect.width + offsets.right;
1344
    }
1345
  } else {
1346
    left = offsets.left;
1347
  }
1348
  if (gpuAcceleration && prefixedProperty) {
1349
    styles[prefixedProperty] = 'translate3d(' + left + 'px, ' + top + 'px, 0)';
1350
    styles[sideA] = 0;
1351
    styles[sideB] = 0;
1352
    styles.willChange = 'transform';
1353
  } else {
1354
    // othwerise, we use the standard `top`, `left`, `bottom` and `right` properties
1355
    var invertTop = sideA === 'bottom' ? -1 : 1;
1356
    var invertLeft = sideB === 'right' ? -1 : 1;
1357
    styles[sideA] = top * invertTop;
1358
    styles[sideB] = left * invertLeft;
1359
    styles.willChange = sideA + ', ' + sideB;
1360
  }
1361
1362
  // Attributes
1363
  var attributes = {
1364
    'x-placement': data.placement
1365
  };
1366
1367
  // Update `data` attributes, styles and arrowStyles
1368
  data.attributes = _extends({}, attributes, data.attributes);
1369
  data.styles = _extends({}, styles, data.styles);
1370
  data.arrowStyles = _extends({}, data.offsets.arrow, data.arrowStyles);
1371
1372
  return data;
1373
}
1374
1375
/**
1376
 * Helper used to know if the given modifier depends from another one.<br />
1377
 * It checks if the needed modifier is listed and enabled.
1378
 * @method
1379
 * @memberof Popper.Utils
1380
 * @param {Array} modifiers - list of modifiers
1381
 * @param {String} requestingName - name of requesting modifier
1382
 * @param {String} requestedName - name of requested modifier
1383
 * @returns {Boolean}
1384
 */
1385
function isModifierRequired(modifiers, requestingName, requestedName) {
1386
  var requesting = find(modifiers, function (_ref) {
1387
    var name = _ref.name;
1388
    return name === requestingName;
1389
  });
1390
1391
  var isRequired = !!requesting && modifiers.some(function (modifier) {
1392
    return modifier.name === requestedName && modifier.enabled && modifier.order < requesting.order;
1393
  });
1394
1395
  if (!isRequired) {
1396
    var _requesting = '`' + requestingName + '`';
1397
    var requested = '`' + requestedName + '`';
1398
    console.warn(requested + ' modifier is required by ' + _requesting + ' modifier in order to work, be sure to include it before ' + _requesting + '!');
1399
  }
1400
  return isRequired;
1401
}
1402
1403
/**
1404
 * @function
1405
 * @memberof Modifiers
1406
 * @argument {Object} data - The data object generated by update method
1407
 * @argument {Object} options - Modifiers configuration and options
1408
 * @returns {Object} The data object, properly modified
1409
 */
1410
function arrow(data, options) {
1411
  var _data$offsets$arrow;
1412
1413
  // arrow depends on keepTogether in order to work
1414
  if (!isModifierRequired(data.instance.modifiers, 'arrow', 'keepTogether')) {
1415
    return data;
1416
  }
1417
1418
  var arrowElement = options.element;
1419
1420
  // if arrowElement is a string, suppose it's a CSS selector
1421
  if (typeof arrowElement === 'string') {
1422
    arrowElement = data.instance.popper.querySelector(arrowElement);
1423
1424
    // if arrowElement is not found, don't run the modifier
1425
    if (!arrowElement) {
1426
      return data;
1427
    }
1428
  } else {
1429
    // if the arrowElement isn't a query selector we must check that the
1430
    // provided DOM node is child of its popper node
1431
    if (!data.instance.popper.contains(arrowElement)) {
1432
      console.warn('WARNING: `arrow.element` must be child of its popper element!');
1433
      return data;
1434
    }
1435
  }
1436
1437
  var placement = data.placement.split('-')[0];
1438
  var _data$offsets = data.offsets,
1439
      popper = _data$offsets.popper,
1440
      reference = _data$offsets.reference;
1441
1442
  var isVertical = ['left', 'right'].indexOf(placement) !== -1;
1443
1444
  var len = isVertical ? 'height' : 'width';
1445
  var sideCapitalized = isVertical ? 'Top' : 'Left';
1446
  var side = sideCapitalized.toLowerCase();
1447
  var altSide = isVertical ? 'left' : 'top';
1448
  var opSide = isVertical ? 'bottom' : 'right';
1449
  var arrowElementSize = getOuterSizes(arrowElement)[len];
1450
1451
  //
1452
  // extends keepTogether behavior making sure the popper and its
1453
  // reference have enough pixels in conjunction
1454
  //
1455
1456
  // top/left side
1457
  if (reference[opSide] - arrowElementSize < popper[side]) {
1458
    data.offsets.popper[side] -= popper[side] - (reference[opSide] - arrowElementSize);
1459
  }
1460
  // bottom/right side
1461
  if (reference[side] + arrowElementSize > popper[opSide]) {
1462
    data.offsets.popper[side] += reference[side] + arrowElementSize - popper[opSide];
1463
  }
1464
  data.offsets.popper = getClientRect(data.offsets.popper);
1465
1466
  // compute center of the popper
1467
  var center = reference[side] + reference[len] / 2 - arrowElementSize / 2;
1468
1469
  // Compute the sideValue using the updated popper offsets
1470
  // take popper margin in account because we don't have this info available
1471
  var css = getStyleComputedProperty(data.instance.popper);
1472
  var popperMarginSide = parseFloat(css['margin' + sideCapitalized]);
1473
  var popperBorderSide = parseFloat(css['border' + sideCapitalized + 'Width']);
1474
  var sideValue = center - data.offsets.popper[side] - popperMarginSide - popperBorderSide;
1475
1476
  // prevent arrowElement from being placed not contiguously to its popper
1477
  sideValue = Math.max(Math.min(popper[len] - arrowElementSize, sideValue), 0);
1478
1479
  data.arrowElement = arrowElement;
1480
  data.offsets.arrow = (_data$offsets$arrow = {}, defineProperty(_data$offsets$arrow, side, Math.round(sideValue)), defineProperty(_data$offsets$arrow, altSide, ''), _data$offsets$arrow);
1481
1482
  return data;
1483
}
1484
1485
/**
1486
 * Get the opposite placement variation of the given one
1487
 * @method
1488
 * @memberof Popper.Utils
1489
 * @argument {String} placement variation
1490
 * @returns {String} flipped placement variation
1491
 */
1492
function getOppositeVariation(variation) {
1493
  if (variation === 'end') {
1494
    return 'start';
1495
  } else if (variation === 'start') {
1496
    return 'end';
1497
  }
1498
  return variation;
1499
}
1500
1501
/**
1502
 * List of accepted placements to use as values of the `placement` option.<br />
1503
 * Valid placements are:
1504
 * - `auto`
1505
 * - `top`
1506
 * - `right`
1507
 * - `bottom`
1508
 * - `left`
1509
 *
1510
 * Each placement can have a variation from this list:
1511
 * - `-start`
1512
 * - `-end`
1513
 *
1514
 * Variations are interpreted easily if you think of them as the left to right
1515
 * written languages. Horizontally (`top` and `bottom`), `start` is left and `end`
1516
 * is right.<br />
1517
 * Vertically (`left` and `right`), `start` is top and `end` is bottom.
1518
 *
1519
 * Some valid examples are:
1520
 * - `top-end` (on top of reference, right aligned)
1521
 * - `right-start` (on right of reference, top aligned)
1522
 * - `bottom` (on bottom, centered)
1523
 * - `auto-end` (on the side with more space available, alignment depends by placement)
1524
 *
1525
 * @static
1526
 * @type {Array}
1527
 * @enum {String}
1528
 * @readonly
1529
 * @method placements
1530
 * @memberof Popper
1531
 */
1532
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'];
1533
1534
// Get rid of `auto` `auto-start` and `auto-end`
1535
var validPlacements = placements.slice(3);
1536
1537
/**
1538
 * Given an initial placement, returns all the subsequent placements
1539
 * clockwise (or counter-clockwise).
1540
 *
1541
 * @method
1542
 * @memberof Popper.Utils
1543
 * @argument {String} placement - A valid placement (it accepts variations)
1544
 * @argument {Boolean} counter - Set to true to walk the placements counterclockwise
1545
 * @returns {Array} placements including their variations
1546
 */
1547
function clockwise(placement) {
1548
  var counter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
1549
1550
  var index = validPlacements.indexOf(placement);
1551
  var arr = validPlacements.slice(index + 1).concat(validPlacements.slice(0, index));
1552
  return counter ? arr.reverse() : arr;
1553
}
1554
1555
var BEHAVIORS = {
1556
  FLIP: 'flip',
1557
  CLOCKWISE: 'clockwise',
1558
  COUNTERCLOCKWISE: 'counterclockwise'
1559
};
1560
1561
/**
1562
 * @function
1563
 * @memberof Modifiers
1564
 * @argument {Object} data - The data object generated by update method
1565
 * @argument {Object} options - Modifiers configuration and options
1566
 * @returns {Object} The data object, properly modified
1567
 */
1568
function flip(data, options) {
1569
  // if `inner` modifier is enabled, we can't use the `flip` modifier
1570
  if (isModifierEnabled(data.instance.modifiers, 'inner')) {
1571
    return data;
1572
  }
1573
1574
  if (data.flipped && data.placement === data.originalPlacement) {
1575
    // seems like flip is trying to loop, probably there's not enough space on any of the flippable sides
1576
    return data;
1577
  }
1578
1579
  var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, options.boundariesElement, data.positionFixed);
1580
1581
  var placement = data.placement.split('-')[0];
1582
  var placementOpposite = getOppositePlacement(placement);
1583
  var variation = data.placement.split('-')[1] || '';
1584
1585
  var flipOrder = [];
1586
1587
  switch (options.behavior) {
1588
    case BEHAVIORS.FLIP:
1589
      flipOrder = [placement, placementOpposite];
1590
      break;
1591
    case BEHAVIORS.CLOCKWISE:
1592
      flipOrder = clockwise(placement);
1593
      break;
1594
    case BEHAVIORS.COUNTERCLOCKWISE:
1595
      flipOrder = clockwise(placement, true);
1596
      break;
1597
    default:
1598
      flipOrder = options.behavior;
1599
  }
1600
1601
  flipOrder.forEach(function (step, index) {
1602
    if (placement !== step || flipOrder.length === index + 1) {
1603
      return data;
1604
    }
1605
1606
    placement = data.placement.split('-')[0];
1607
    placementOpposite = getOppositePlacement(placement);
1608
1609
    var popperOffsets = data.offsets.popper;
1610
    var refOffsets = data.offsets.reference;
1611
1612
    // using floor because the reference offsets may contain decimals we are not going to consider here
1613
    var floor = Math.floor;
1614
    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);
1615
1616
    var overflowsLeft = floor(popperOffsets.left) < floor(boundaries.left);
1617
    var overflowsRight = floor(popperOffsets.right) > floor(boundaries.right);
1618
    var overflowsTop = floor(popperOffsets.top) < floor(boundaries.top);
1619
    var overflowsBottom = floor(popperOffsets.bottom) > floor(boundaries.bottom);
1620
1621
    var overflowsBoundaries = placement === 'left' && overflowsLeft || placement === 'right' && overflowsRight || placement === 'top' && overflowsTop || placement === 'bottom' && overflowsBottom;
1622
1623
    // flip the variation if required
1624
    var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;
1625
1626
    // flips variation if reference element overflows boundaries
1627
    var flippedVariationByRef = !!options.flipVariations && (isVertical && variation === 'start' && overflowsLeft || isVertical && variation === 'end' && overflowsRight || !isVertical && variation === 'start' && overflowsTop || !isVertical && variation === 'end' && overflowsBottom);
1628
1629
    // flips variation if popper content overflows boundaries
1630
    var flippedVariationByContent = !!options.flipVariationsByContent && (isVertical && variation === 'start' && overflowsRight || isVertical && variation === 'end' && overflowsLeft || !isVertical && variation === 'start' && overflowsBottom || !isVertical && variation === 'end' && overflowsTop);
1631
1632
    var flippedVariation = flippedVariationByRef || flippedVariationByContent;
1633
1634
    if (overlapsRef || overflowsBoundaries || flippedVariation) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if overlapsRef || overflows...ies || flippedVariation is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
1635
      // this boolean to detect any flip loop
1636
      data.flipped = true;
1637
1638
      if (overlapsRef || overflowsBoundaries) {
1639
        placement = flipOrder[index + 1];
1640
      }
1641
1642
      if (flippedVariation) {
1643
        variation = getOppositeVariation(variation);
1644
      }
1645
1646
      data.placement = placement + (variation ? '-' + variation : '');
1647
1648
      // this object contains `position`, we want to preserve it along with
1649
      // any additional property we may add in the future
1650
      data.offsets.popper = _extends({}, data.offsets.popper, getPopperOffsets(data.instance.popper, data.offsets.reference, data.placement));
1651
1652
      data = runModifiers(data.instance.modifiers, data, 'flip');
1653
    }
1654
  });
1655
  return data;
1656
}
1657
1658
/**
1659
 * @function
1660
 * @memberof Modifiers
1661
 * @argument {Object} data - The data object generated by update method
1662
 * @argument {Object} options - Modifiers configuration and options
1663
 * @returns {Object} The data object, properly modified
1664
 */
1665
function keepTogether(data) {
1666
  var _data$offsets = data.offsets,
1667
      popper = _data$offsets.popper,
1668
      reference = _data$offsets.reference;
1669
1670
  var placement = data.placement.split('-')[0];
1671
  var floor = Math.floor;
1672
  var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;
1673
  var side = isVertical ? 'right' : 'bottom';
1674
  var opSide = isVertical ? 'left' : 'top';
1675
  var measurement = isVertical ? 'width' : 'height';
1676
1677
  if (popper[side] < floor(reference[opSide])) {
1678
    data.offsets.popper[opSide] = floor(reference[opSide]) - popper[measurement];
1679
  }
1680
  if (popper[opSide] > floor(reference[side])) {
1681
    data.offsets.popper[opSide] = floor(reference[side]);
1682
  }
1683
1684
  return data;
1685
}
1686
1687
/**
1688
 * Converts a string containing value + unit into a px value number
1689
 * @function
1690
 * @memberof {modifiers~offset}
1691
 * @private
1692
 * @argument {String} str - Value + unit string
1693
 * @argument {String} measurement - `height` or `width`
1694
 * @argument {Object} popperOffsets
1695
 * @argument {Object} referenceOffsets
1696
 * @returns {Number|String}
1697
 * Value in pixels, or original string if no values were extracted
1698
 */
1699
function toValue(str, measurement, popperOffsets, referenceOffsets) {
1700
  // separate value from unit
1701
  var split = str.match(/((?:\-|\+)?\d*\.?\d*)(.*)/);
1702
  var value = +split[1];
1703
  var unit = split[2];
1704
1705
  // If it's not a number it's an operator, I guess
1706
  if (!value) {
1707
    return str;
1708
  }
1709
1710
  if (unit.indexOf('%') === 0) {
1711
    var element = void 0;
1712
    switch (unit) {
1713
      case '%p':
1714
        element = popperOffsets;
1715
        break;
1716
      case '%':
1717
      case '%r':
1718
      default:
1719
        element = referenceOffsets;
1720
    }
1721
1722
    var rect = getClientRect(element);
1723
    return rect[measurement] / 100 * value;
1724
  } else if (unit === 'vh' || unit === 'vw') {
1725
    // if is a vh or vw, we calculate the size based on the viewport
1726
    var size = void 0;
1727
    if (unit === 'vh') {
1728
      size = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
1729
    } else {
1730
      size = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
1731
    }
1732
    return size / 100 * value;
1733
  } else {
1734
    // if is an explicit pixel unit, we get rid of the unit and keep the value
1735
    // if is an implicit unit, it's px, and we return just the value
1736
    return value;
1737
  }
1738
}
1739
1740
/**
1741
 * Parse an `offset` string to extrapolate `x` and `y` numeric offsets.
1742
 * @function
1743
 * @memberof {modifiers~offset}
1744
 * @private
1745
 * @argument {String} offset
1746
 * @argument {Object} popperOffsets
1747
 * @argument {Object} referenceOffsets
1748
 * @argument {String} basePlacement
1749
 * @returns {Array} a two cells array with x and y offsets in numbers
1750
 */
1751
function parseOffset(offset, popperOffsets, referenceOffsets, basePlacement) {
1752
  var offsets = [0, 0];
1753
1754
  // Use height if placement is left or right and index is 0 otherwise use width
1755
  // in this way the first offset will use an axis and the second one
1756
  // will use the other one
1757
  var useHeight = ['right', 'left'].indexOf(basePlacement) !== -1;
1758
1759
  // Split the offset string to obtain a list of values and operands
1760
  // The regex addresses values with the plus or minus sign in front (+10, -20, etc)
1761
  var fragments = offset.split(/(\+|\-)/).map(function (frag) {
1762
    return frag.trim();
1763
  });
1764
1765
  // Detect if the offset string contains a pair of values or a single one
1766
  // they could be separated by comma or space
1767
  var divider = fragments.indexOf(find(fragments, function (frag) {
1768
    return frag.search(/,|\s/) !== -1;
1769
  }));
1770
1771
  if (fragments[divider] && fragments[divider].indexOf(',') === -1) {
1772
    console.warn('Offsets separated by white space(s) are deprecated, use a comma (,) instead.');
1773
  }
1774
1775
  // If divider is found, we divide the list of values and operands to divide
1776
  // them by ofset X and Y.
1777
  var splitRegex = /\s*,\s*|\s+/;
1778
  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];
1779
1780
  // Convert the values with units to absolute pixels to allow our computations
1781
  ops = ops.map(function (op, index) {
1782
    // Most of the units rely on the orientation of the popper
1783
    var measurement = (index === 1 ? !useHeight : useHeight) ? 'height' : 'width';
1784
    var mergeWithPrevious = false;
1785
    return op
1786
    // This aggregates any `+` or `-` sign that aren't considered operators
1787
    // e.g.: 10 + +5 => [10, +, +5]
1788
    .reduce(function (a, b) {
1789
      if (a[a.length - 1] === '' && ['+', '-'].indexOf(b) !== -1) {
1790
        a[a.length - 1] = b;
1791
        mergeWithPrevious = true;
1792
        return a;
1793
      } else if (mergeWithPrevious) {
1794
        a[a.length - 1] += b;
1795
        mergeWithPrevious = false;
1796
        return a;
1797
      } else {
1798
        return a.concat(b);
1799
      }
1800
    }, [])
1801
    // Here we convert the string values into number values (in px)
1802
    .map(function (str) {
1803
      return toValue(str, measurement, popperOffsets, referenceOffsets);
1804
    });
1805
  });
1806
1807
  // Loop trough the offsets arrays and execute the operations
1808
  ops.forEach(function (op, index) {
1809
    op.forEach(function (frag, index2) {
1810
      if (isNumeric(frag)) {
1811
        offsets[index] += frag * (op[index2 - 1] === '-' ? -1 : 1);
1812
      }
1813
    });
1814
  });
1815
  return offsets;
1816
}
1817
1818
/**
1819
 * @function
1820
 * @memberof Modifiers
1821
 * @argument {Object} data - The data object generated by update method
1822
 * @argument {Object} options - Modifiers configuration and options
1823
 * @argument {Number|String} options.offset=0
1824
 * The offset value as described in the modifier description
1825
 * @returns {Object} The data object, properly modified
1826
 */
1827
function offset(data, _ref) {
1828
  var offset = _ref.offset;
1829
  var placement = data.placement,
1830
      _data$offsets = data.offsets,
1831
      popper = _data$offsets.popper,
1832
      reference = _data$offsets.reference;
1833
1834
  var basePlacement = placement.split('-')[0];
1835
1836
  var offsets = void 0;
1837
  if (isNumeric(+offset)) {
1838
    offsets = [+offset, 0];
1839
  } else {
1840
    offsets = parseOffset(offset, popper, reference, basePlacement);
1841
  }
1842
1843
  if (basePlacement === 'left') {
1844
    popper.top += offsets[0];
1845
    popper.left -= offsets[1];
1846
  } else if (basePlacement === 'right') {
1847
    popper.top += offsets[0];
1848
    popper.left += offsets[1];
1849
  } else if (basePlacement === 'top') {
1850
    popper.left += offsets[0];
1851
    popper.top -= offsets[1];
1852
  } else if (basePlacement === 'bottom') {
1853
    popper.left += offsets[0];
1854
    popper.top += offsets[1];
1855
  }
1856
1857
  data.popper = popper;
1858
  return data;
1859
}
1860
1861
/**
1862
 * @function
1863
 * @memberof Modifiers
1864
 * @argument {Object} data - The data object generated by `update` method
1865
 * @argument {Object} options - Modifiers configuration and options
1866
 * @returns {Object} The data object, properly modified
1867
 */
1868
function preventOverflow(data, options) {
1869
  var boundariesElement = options.boundariesElement || getOffsetParent(data.instance.popper);
1870
1871
  // If offsetParent is the reference element, we really want to
1872
  // go one step up and use the next offsetParent as reference to
1873
  // avoid to make this modifier completely useless and look like broken
1874
  if (data.instance.reference === boundariesElement) {
1875
    boundariesElement = getOffsetParent(boundariesElement);
1876
  }
1877
1878
  // NOTE: DOM access here
1879
  // resets the popper's position so that the document size can be calculated excluding
1880
  // the size of the popper element itself
1881
  var transformProp = getSupportedPropertyName('transform');
1882
  var popperStyles = data.instance.popper.style; // assignment to help minification
1883
  var top = popperStyles.top,
1884
      left = popperStyles.left,
1885
      transform = popperStyles[transformProp];
1886
1887
  popperStyles.top = '';
1888
  popperStyles.left = '';
1889
  popperStyles[transformProp] = '';
1890
1891
  var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, boundariesElement, data.positionFixed);
1892
1893
  // NOTE: DOM access here
1894
  // restores the original style properties after the offsets have been computed
1895
  popperStyles.top = top;
1896
  popperStyles.left = left;
1897
  popperStyles[transformProp] = transform;
1898
1899
  options.boundaries = boundaries;
1900
1901
  var order = options.priority;
1902
  var popper = data.offsets.popper;
1903
1904
  var check = {
1905
    primary: function primary(placement) {
1906
      var value = popper[placement];
1907
      if (popper[placement] < boundaries[placement] && !options.escapeWithReference) {
1908
        value = Math.max(popper[placement], boundaries[placement]);
1909
      }
1910
      return defineProperty({}, placement, value);
1911
    },
1912
    secondary: function secondary(placement) {
1913
      var mainSide = placement === 'right' ? 'left' : 'top';
1914
      var value = popper[mainSide];
1915
      if (popper[placement] > boundaries[placement] && !options.escapeWithReference) {
1916
        value = Math.min(popper[mainSide], boundaries[placement] - (placement === 'right' ? popper.width : popper.height));
1917
      }
1918
      return defineProperty({}, mainSide, value);
1919
    }
1920
  };
1921
1922
  order.forEach(function (placement) {
1923
    var side = ['left', 'top'].indexOf(placement) !== -1 ? 'primary' : 'secondary';
1924
    popper = _extends({}, popper, check[side](placement));
1925
  });
1926
1927
  data.offsets.popper = popper;
1928
1929
  return data;
1930
}
1931
1932
/**
1933
 * @function
1934
 * @memberof Modifiers
1935
 * @argument {Object} data - The data object generated by `update` method
1936
 * @argument {Object} options - Modifiers configuration and options
1937
 * @returns {Object} The data object, properly modified
1938
 */
1939
function shift(data) {
1940
  var placement = data.placement;
1941
  var basePlacement = placement.split('-')[0];
1942
  var shiftvariation = placement.split('-')[1];
1943
1944
  // if shift shiftvariation is specified, run the modifier
1945
  if (shiftvariation) {
1946
    var _data$offsets = data.offsets,
1947
        reference = _data$offsets.reference,
1948
        popper = _data$offsets.popper;
1949
1950
    var isVertical = ['bottom', 'top'].indexOf(basePlacement) !== -1;
1951
    var side = isVertical ? 'left' : 'top';
1952
    var measurement = isVertical ? 'width' : 'height';
1953
1954
    var shiftOffsets = {
1955
      start: defineProperty({}, side, reference[side]),
1956
      end: defineProperty({}, side, reference[side] + reference[measurement] - popper[measurement])
1957
    };
1958
1959
    data.offsets.popper = _extends({}, popper, shiftOffsets[shiftvariation]);
1960
  }
1961
1962
  return data;
1963
}
1964
1965
/**
1966
 * @function
1967
 * @memberof Modifiers
1968
 * @argument {Object} data - The data object generated by update method
1969
 * @argument {Object} options - Modifiers configuration and options
1970
 * @returns {Object} The data object, properly modified
1971
 */
1972
function hide(data) {
1973
  if (!isModifierRequired(data.instance.modifiers, 'hide', 'preventOverflow')) {
1974
    return data;
1975
  }
1976
1977
  var refRect = data.offsets.reference;
1978
  var bound = find(data.instance.modifiers, function (modifier) {
1979
    return modifier.name === 'preventOverflow';
1980
  }).boundaries;
1981
1982
  if (refRect.bottom < bound.top || refRect.left > bound.right || refRect.top > bound.bottom || refRect.right < bound.left) {
1983
    // Avoid unnecessary DOM access if visibility hasn't changed
1984
    if (data.hide === true) {
1985
      return data;
1986
    }
1987
1988
    data.hide = true;
1989
    data.attributes['x-out-of-boundaries'] = '';
1990
  } else {
1991
    // Avoid unnecessary DOM access if visibility hasn't changed
1992
    if (data.hide === false) {
1993
      return data;
1994
    }
1995
1996
    data.hide = false;
1997
    data.attributes['x-out-of-boundaries'] = false;
1998
  }
1999
2000
  return data;
2001
}
2002
2003
/**
2004
 * @function
2005
 * @memberof Modifiers
2006
 * @argument {Object} data - The data object generated by `update` method
2007
 * @argument {Object} options - Modifiers configuration and options
2008
 * @returns {Object} The data object, properly modified
2009
 */
2010
function inner(data) {
2011
  var placement = data.placement;
2012
  var basePlacement = placement.split('-')[0];
2013
  var _data$offsets = data.offsets,
2014
      popper = _data$offsets.popper,
2015
      reference = _data$offsets.reference;
2016
2017
  var isHoriz = ['left', 'right'].indexOf(basePlacement) !== -1;
2018
2019
  var subtractLength = ['top', 'left'].indexOf(basePlacement) === -1;
2020
2021
  popper[isHoriz ? 'left' : 'top'] = reference[basePlacement] - (subtractLength ? popper[isHoriz ? 'width' : 'height'] : 0);
2022
2023
  data.placement = getOppositePlacement(placement);
2024
  data.offsets.popper = getClientRect(popper);
2025
2026
  return data;
2027
}
2028
2029
/**
2030
 * Modifier function, each modifier can have a function of this type assigned
2031
 * to its `fn` property.<br />
2032
 * These functions will be called on each update, this means that you must
2033
 * make sure they are performant enough to avoid performance bottlenecks.
2034
 *
2035
 * @function ModifierFn
2036
 * @argument {dataObject} data - The data object generated by `update` method
2037
 * @argument {Object} options - Modifiers configuration and options
2038
 * @returns {dataObject} The data object, properly modified
2039
 */
2040
2041
/**
2042
 * Modifiers are plugins used to alter the behavior of your poppers.<br />
2043
 * Popper.js uses a set of 9 modifiers to provide all the basic functionalities
2044
 * needed by the library.
2045
 *
2046
 * Usually you don't want to override the `order`, `fn` and `onLoad` props.
2047
 * All the other properties are configurations that could be tweaked.
2048
 * @namespace modifiers
2049
 */
2050
var modifiers = {
2051
  /**
2052
   * Modifier used to shift the popper on the start or end of its reference
2053
   * element.<br />
2054
   * It will read the variation of the `placement` property.<br />
2055
   * It can be one either `-end` or `-start`.
2056
   * @memberof modifiers
2057
   * @inner
2058
   */
2059
  shift: {
2060
    /** @prop {number} order=100 - Index used to define the order of execution */
2061
    order: 100,
2062
    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2063
    enabled: true,
2064
    /** @prop {ModifierFn} */
2065
    fn: shift
2066
  },
2067
2068
  /**
2069
   * The `offset` modifier can shift your popper on both its axis.
2070
   *
2071
   * It accepts the following units:
2072
   * - `px` or unit-less, interpreted as pixels
2073
   * - `%` or `%r`, percentage relative to the length of the reference element
2074
   * - `%p`, percentage relative to the length of the popper element
2075
   * - `vw`, CSS viewport width unit
2076
   * - `vh`, CSS viewport height unit
2077
   *
2078
   * For length is intended the main axis relative to the placement of the popper.<br />
2079
   * This means that if the placement is `top` or `bottom`, the length will be the
2080
   * `width`. In case of `left` or `right`, it will be the `height`.
2081
   *
2082
   * You can provide a single value (as `Number` or `String`), or a pair of values
2083
   * as `String` divided by a comma or one (or more) white spaces.<br />
2084
   * The latter is a deprecated method because it leads to confusion and will be
2085
   * removed in v2.<br />
2086
   * Additionally, it accepts additions and subtractions between different units.
2087
   * Note that multiplications and divisions aren't supported.
2088
   *
2089
   * Valid examples are:
2090
   * ```
2091
   * 10
2092
   * '10%'
2093
   * '10, 10'
2094
   * '10%, 10'
2095
   * '10 + 10%'
2096
   * '10 - 5vh + 3%'
2097
   * '-10px + 5vh, 5px - 6%'
2098
   * ```
2099
   * > **NB**: If you desire to apply offsets to your poppers in a way that may make them overlap
2100
   * > with their reference element, unfortunately, you will have to disable the `flip` modifier.
2101
   * > You can read more on this at this [issue](https://github.com/FezVrasta/popper.js/issues/373).
2102
   *
2103
   * @memberof modifiers
2104
   * @inner
2105
   */
2106
  offset: {
2107
    /** @prop {number} order=200 - Index used to define the order of execution */
2108
    order: 200,
2109
    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2110
    enabled: true,
2111
    /** @prop {ModifierFn} */
2112
    fn: offset,
2113
    /** @prop {Number|String} offset=0
2114
     * The offset value as described in the modifier description
2115
     */
2116
    offset: 0
2117
  },
2118
2119
  /**
2120
   * Modifier used to prevent the popper from being positioned outside the boundary.
2121
   *
2122
   * A scenario exists where the reference itself is not within the boundaries.<br />
2123
   * We can say it has "escaped the boundaries" — or just "escaped".<br />
2124
   * In this case we need to decide whether the popper should either:
2125
   *
2126
   * - detach from the reference and remain "trapped" in the boundaries, or
2127
   * - if it should ignore the boundary and "escape with its reference"
2128
   *
2129
   * When `escapeWithReference` is set to`true` and reference is completely
2130
   * outside its boundaries, the popper will overflow (or completely leave)
2131
   * the boundaries in order to remain attached to the edge of the reference.
2132
   *
2133
   * @memberof modifiers
2134
   * @inner
2135
   */
2136
  preventOverflow: {
2137
    /** @prop {number} order=300 - Index used to define the order of execution */
2138
    order: 300,
2139
    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2140
    enabled: true,
2141
    /** @prop {ModifierFn} */
2142
    fn: preventOverflow,
2143
    /**
2144
     * @prop {Array} [priority=['left','right','top','bottom']]
2145
     * Popper will try to prevent overflow following these priorities by default,
2146
     * then, it could overflow on the left and on top of the `boundariesElement`
2147
     */
2148
    priority: ['left', 'right', 'top', 'bottom'],
2149
    /**
2150
     * @prop {number} padding=5
2151
     * Amount of pixel used to define a minimum distance between the boundaries
2152
     * and the popper. This makes sure the popper always has a little padding
2153
     * between the edges of its container
2154
     */
2155
    padding: 5,
2156
    /**
2157
     * @prop {String|HTMLElement} boundariesElement='scrollParent'
2158
     * Boundaries used by the modifier. Can be `scrollParent`, `window`,
2159
     * `viewport` or any DOM element.
2160
     */
2161
    boundariesElement: 'scrollParent'
2162
  },
2163
2164
  /**
2165
   * Modifier used to make sure the reference and its popper stay near each other
2166
   * without leaving any gap between the two. Especially useful when the arrow is
2167
   * enabled and you want to ensure that it points to its reference element.
2168
   * It cares only about the first axis. You can still have poppers with margin
2169
   * between the popper and its reference element.
2170
   * @memberof modifiers
2171
   * @inner
2172
   */
2173
  keepTogether: {
2174
    /** @prop {number} order=400 - Index used to define the order of execution */
2175
    order: 400,
2176
    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2177
    enabled: true,
2178
    /** @prop {ModifierFn} */
2179
    fn: keepTogether
2180
  },
2181
2182
  /**
2183
   * This modifier is used to move the `arrowElement` of the popper to make
2184
   * sure it is positioned between the reference element and its popper element.
2185
   * It will read the outer size of the `arrowElement` node to detect how many
2186
   * pixels of conjunction are needed.
2187
   *
2188
   * It has no effect if no `arrowElement` is provided.
2189
   * @memberof modifiers
2190
   * @inner
2191
   */
2192
  arrow: {
2193
    /** @prop {number} order=500 - Index used to define the order of execution */
2194
    order: 500,
2195
    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2196
    enabled: true,
2197
    /** @prop {ModifierFn} */
2198
    fn: arrow,
2199
    /** @prop {String|HTMLElement} element='[x-arrow]' - Selector or node used as arrow */
2200
    element: '[x-arrow]'
2201
  },
2202
2203
  /**
2204
   * Modifier used to flip the popper's placement when it starts to overlap its
2205
   * reference element.
2206
   *
2207
   * Requires the `preventOverflow` modifier before it in order to work.
2208
   *
2209
   * **NOTE:** this modifier will interrupt the current update cycle and will
2210
   * restart it if it detects the need to flip the placement.
2211
   * @memberof modifiers
2212
   * @inner
2213
   */
2214
  flip: {
2215
    /** @prop {number} order=600 - Index used to define the order of execution */
2216
    order: 600,
2217
    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2218
    enabled: true,
2219
    /** @prop {ModifierFn} */
2220
    fn: flip,
2221
    /**
2222
     * @prop {String|Array} behavior='flip'
2223
     * The behavior used to change the popper's placement. It can be one of
2224
     * `flip`, `clockwise`, `counterclockwise` or an array with a list of valid
2225
     * placements (with optional variations)
2226
     */
2227
    behavior: 'flip',
2228
    /**
2229
     * @prop {number} padding=5
2230
     * The popper will flip if it hits the edges of the `boundariesElement`
2231
     */
2232
    padding: 5,
2233
    /**
2234
     * @prop {String|HTMLElement} boundariesElement='viewport'
2235
     * The element which will define the boundaries of the popper position.
2236
     * The popper will never be placed outside of the defined boundaries
2237
     * (except if `keepTogether` is enabled)
2238
     */
2239
    boundariesElement: 'viewport',
2240
    /**
2241
     * @prop {Boolean} flipVariations=false
2242
     * The popper will switch placement variation between `-start` and `-end` when
2243
     * the reference element overlaps its boundaries.
2244
     *
2245
     * The original placement should have a set variation.
2246
     */
2247
    flipVariations: false,
2248
    /**
2249
     * @prop {Boolean} flipVariationsByContent=false
2250
     * The popper will switch placement variation between `-start` and `-end` when
2251
     * the popper element overlaps its reference boundaries.
2252
     *
2253
     * The original placement should have a set variation.
2254
     */
2255
    flipVariationsByContent: false
2256
  },
2257
2258
  /**
2259
   * Modifier used to make the popper flow toward the inner of the reference element.
2260
   * By default, when this modifier is disabled, the popper will be placed outside
2261
   * the reference element.
2262
   * @memberof modifiers
2263
   * @inner
2264
   */
2265
  inner: {
2266
    /** @prop {number} order=700 - Index used to define the order of execution */
2267
    order: 700,
2268
    /** @prop {Boolean} enabled=false - Whether the modifier is enabled or not */
2269
    enabled: false,
2270
    /** @prop {ModifierFn} */
2271
    fn: inner
2272
  },
2273
2274
  /**
2275
   * Modifier used to hide the popper when its reference element is outside of the
2276
   * popper boundaries. It will set a `x-out-of-boundaries` attribute which can
2277
   * be used to hide with a CSS selector the popper when its reference is
2278
   * out of boundaries.
2279
   *
2280
   * Requires the `preventOverflow` modifier before it in order to work.
2281
   * @memberof modifiers
2282
   * @inner
2283
   */
2284
  hide: {
2285
    /** @prop {number} order=800 - Index used to define the order of execution */
2286
    order: 800,
2287
    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2288
    enabled: true,
2289
    /** @prop {ModifierFn} */
2290
    fn: hide
2291
  },
2292
2293
  /**
2294
   * Computes the style that will be applied to the popper element to gets
2295
   * properly positioned.
2296
   *
2297
   * Note that this modifier will not touch the DOM, it just prepares the styles
2298
   * so that `applyStyle` modifier can apply it. This separation is useful
2299
   * in case you need to replace `applyStyle` with a custom implementation.
2300
   *
2301
   * This modifier has `850` as `order` value to maintain backward compatibility
2302
   * with previous versions of Popper.js. Expect the modifiers ordering method
2303
   * to change in future major versions of the library.
2304
   *
2305
   * @memberof modifiers
2306
   * @inner
2307
   */
2308
  computeStyle: {
2309
    /** @prop {number} order=850 - Index used to define the order of execution */
2310
    order: 850,
2311
    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2312
    enabled: true,
2313
    /** @prop {ModifierFn} */
2314
    fn: computeStyle,
2315
    /**
2316
     * @prop {Boolean} gpuAcceleration=true
2317
     * If true, it uses the CSS 3D transformation to position the popper.
2318
     * Otherwise, it will use the `top` and `left` properties
2319
     */
2320
    gpuAcceleration: true,
2321
    /**
2322
     * @prop {string} [x='bottom']
2323
     * Where to anchor the X axis (`bottom` or `top`). AKA X offset origin.
2324
     * Change this if your popper should grow in a direction different from `bottom`
2325
     */
2326
    x: 'bottom',
2327
    /**
2328
     * @prop {string} [x='left']
2329
     * Where to anchor the Y axis (`left` or `right`). AKA Y offset origin.
2330
     * Change this if your popper should grow in a direction different from `right`
2331
     */
2332
    y: 'right'
2333
  },
2334
2335
  /**
2336
   * Applies the computed styles to the popper element.
2337
   *
2338
   * All the DOM manipulations are limited to this modifier. This is useful in case
2339
   * you want to integrate Popper.js inside a framework or view library and you
2340
   * want to delegate all the DOM manipulations to it.
2341
   *
2342
   * Note that if you disable this modifier, you must make sure the popper element
2343
   * has its position set to `absolute` before Popper.js can do its work!
2344
   *
2345
   * Just disable this modifier and define your own to achieve the desired effect.
2346
   *
2347
   * @memberof modifiers
2348
   * @inner
2349
   */
2350
  applyStyle: {
2351
    /** @prop {number} order=900 - Index used to define the order of execution */
2352
    order: 900,
2353
    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2354
    enabled: true,
2355
    /** @prop {ModifierFn} */
2356
    fn: applyStyle,
2357
    /** @prop {Function} */
2358
    onLoad: applyStyleOnLoad,
2359
    /**
2360
     * @deprecated since version 1.10.0, the property moved to `computeStyle` modifier
2361
     * @prop {Boolean} gpuAcceleration=true
2362
     * If true, it uses the CSS 3D transformation to position the popper.
2363
     * Otherwise, it will use the `top` and `left` properties
2364
     */
2365
    gpuAcceleration: undefined
2366
  }
2367
};
2368
2369
/**
2370
 * The `dataObject` is an object containing all the information used by Popper.js.
2371
 * This object is passed to modifiers and to the `onCreate` and `onUpdate` callbacks.
2372
 * @name dataObject
2373
 * @property {Object} data.instance The Popper.js instance
2374
 * @property {String} data.placement Placement applied to popper
2375
 * @property {String} data.originalPlacement Placement originally defined on init
2376
 * @property {Boolean} data.flipped True if popper has been flipped by flip modifier
2377
 * @property {Boolean} data.hide True if the reference element is out of boundaries, useful to know when to hide the popper
2378
 * @property {HTMLElement} data.arrowElement Node used as arrow by arrow modifier
2379
 * @property {Object} data.styles Any CSS property defined here will be applied to the popper. It expects the JavaScript nomenclature (eg. `marginBottom`)
2380
 * @property {Object} data.arrowStyles Any CSS property defined here will be applied to the popper arrow. It expects the JavaScript nomenclature (eg. `marginBottom`)
2381
 * @property {Object} data.boundaries Offsets of the popper boundaries
2382
 * @property {Object} data.offsets The measurements of popper, reference and arrow elements
2383
 * @property {Object} data.offsets.popper `top`, `left`, `width`, `height` values
2384
 * @property {Object} data.offsets.reference `top`, `left`, `width`, `height` values
2385
 * @property {Object} data.offsets.arrow] `top` and `left` offsets, only one of them will be different from 0
2386
 */
2387
2388
/**
2389
 * Default options provided to Popper.js constructor.<br />
2390
 * These can be overridden using the `options` argument of Popper.js.<br />
2391
 * To override an option, simply pass an object with the same
2392
 * structure of the `options` object, as the 3rd argument. For example:
2393
 * ```
2394
 * new Popper(ref, pop, {
2395
 *   modifiers: {
2396
 *     preventOverflow: { enabled: false }
2397
 *   }
2398
 * })
2399
 * ```
2400
 * @type {Object}
2401
 * @static
2402
 * @memberof Popper
2403
 */
2404
var Defaults = {
2405
  /**
2406
   * Popper's placement.
2407
   * @prop {Popper.placements} placement='bottom'
2408
   */
2409
  placement: 'bottom',
2410
2411
  /**
2412
   * Set this to true if you want popper to position it self in 'fixed' mode
2413
   * @prop {Boolean} positionFixed=false
2414
   */
2415
  positionFixed: false,
2416
2417
  /**
2418
   * Whether events (resize, scroll) are initially enabled.
2419
   * @prop {Boolean} eventsEnabled=true
2420
   */
2421
  eventsEnabled: true,
2422
2423
  /**
2424
   * Set to true if you want to automatically remove the popper when
2425
   * you call the `destroy` method.
2426
   * @prop {Boolean} removeOnDestroy=false
2427
   */
2428
  removeOnDestroy: false,
2429
2430
  /**
2431
   * Callback called when the popper is created.<br />
2432
   * By default, it is set to no-op.<br />
2433
   * Access Popper.js instance with `data.instance`.
2434
   * @prop {onCreate}
2435
   */
2436
  onCreate: function onCreate() {},
2437
2438
  /**
2439
   * Callback called when the popper is updated. This callback is not called
2440
   * on the initialization/creation of the popper, but only on subsequent
2441
   * updates.<br />
2442
   * By default, it is set to no-op.<br />
2443
   * Access Popper.js instance with `data.instance`.
2444
   * @prop {onUpdate}
2445
   */
2446
  onUpdate: function onUpdate() {},
2447
2448
  /**
2449
   * List of modifiers used to modify the offsets before they are applied to the popper.
2450
   * They provide most of the functionalities of Popper.js.
2451
   * @prop {modifiers}
2452
   */
2453
  modifiers: modifiers
2454
};
2455
2456
/**
2457
 * @callback onCreate
2458
 * @param {dataObject} data
2459
 */
2460
2461
/**
2462
 * @callback onUpdate
2463
 * @param {dataObject} data
2464
 */
2465
2466
// Utils
2467
// Methods
2468
var Popper = function () {
2469
  /**
2470
   * Creates a new Popper.js instance.
2471
   * @class Popper
2472
   * @param {Element|referenceObject} reference - The reference element used to position the popper
2473
   * @param {Element} popper - The HTML / XML element used as the popper
2474
   * @param {Object} options - Your custom options to override the ones defined in [Defaults](#defaults)
2475
   * @return {Object} instance - The generated Popper.js instance
2476
   */
2477
  function Popper(reference, popper) {
2478
    var _this = this;
2479
2480
    var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
2481
    classCallCheck(this, Popper);
2482
2483
    this.scheduleUpdate = function () {
2484
      return requestAnimationFrame(_this.update);
2485
    };
2486
2487
    // make update() debounced, so that it only runs at most once-per-tick
2488
    this.update = debounce(this.update.bind(this));
2489
2490
    // with {} we create a new object with the options inside it
2491
    this.options = _extends({}, Popper.Defaults, options);
2492
2493
    // init state
2494
    this.state = {
2495
      isDestroyed: false,
2496
      isCreated: false,
2497
      scrollParents: []
2498
    };
2499
2500
    // get reference and popper elements (allow jQuery wrappers)
2501
    this.reference = reference && reference.jquery ? reference[0] : reference;
2502
    this.popper = popper && popper.jquery ? popper[0] : popper;
2503
2504
    // Deep merge modifiers options
2505
    this.options.modifiers = {};
2506
    Object.keys(_extends({}, Popper.Defaults.modifiers, options.modifiers)).forEach(function (name) {
2507
      _this.options.modifiers[name] = _extends({}, Popper.Defaults.modifiers[name] || {}, options.modifiers ? options.modifiers[name] : {});
2508
    });
2509
2510
    // Refactoring modifiers' list (Object => Array)
2511
    this.modifiers = Object.keys(this.options.modifiers).map(function (name) {
2512
      return _extends({
2513
        name: name
2514
      }, _this.options.modifiers[name]);
2515
    })
2516
    // sort the modifiers by order
2517
    .sort(function (a, b) {
2518
      return a.order - b.order;
2519
    });
2520
2521
    // modifiers have the ability to execute arbitrary code when Popper.js get inited
2522
    // such code is executed in the same order of its modifier
2523
    // they could add new properties to their options configuration
2524
    // BE AWARE: don't add options to `options.modifiers.name` but to `modifierOptions`!
2525
    this.modifiers.forEach(function (modifierOptions) {
2526
      if (modifierOptions.enabled && isFunction(modifierOptions.onLoad)) {
2527
        modifierOptions.onLoad(_this.reference, _this.popper, _this.options, modifierOptions, _this.state);
2528
      }
2529
    });
2530
2531
    // fire the first update to position the popper in the right place
2532
    this.update();
2533
2534
    var eventsEnabled = this.options.eventsEnabled;
2535
    if (eventsEnabled) {
2536
      // setup event listeners, they will take care of update the position in specific situations
2537
      this.enableEventListeners();
2538
    }
2539
2540
    this.state.eventsEnabled = eventsEnabled;
2541
  }
2542
2543
  // We can't use class properties because they don't get listed in the
2544
  // class prototype and break stuff like Sinon stubs
2545
2546
2547
  createClass(Popper, [{
2548
    key: 'update',
2549
    value: function update$$1() {
2550
      return update.call(this);
2551
    }
2552
  }, {
2553
    key: 'destroy',
2554
    value: function destroy$$1() {
2555
      return destroy.call(this);
2556
    }
2557
  }, {
2558
    key: 'enableEventListeners',
2559
    value: function enableEventListeners$$1() {
2560
      return enableEventListeners.call(this);
2561
    }
2562
  }, {
2563
    key: 'disableEventListeners',
2564
    value: function disableEventListeners$$1() {
2565
      return disableEventListeners.call(this);
2566
    }
2567
2568
    /**
2569
     * Schedules an update. It will run on the next UI update available.
2570
     * @method scheduleUpdate
2571
     * @memberof Popper
2572
     */
2573
2574
2575
    /**
2576
     * Collection of utilities useful when writing custom modifiers.
2577
     * Starting from version 1.7, this method is available only if you
2578
     * include `popper-utils.js` before `popper.js`.
2579
     *
2580
     * **DEPRECATION**: This way to access PopperUtils is deprecated
2581
     * and will be removed in v2! Use the PopperUtils module directly instead.
2582
     * Due to the high instability of the methods contained in Utils, we can't
2583
     * guarantee them to follow semver. Use them at your own risk!
2584
     * @static
2585
     * @private
2586
     * @type {Object}
2587
     * @deprecated since version 1.8
2588
     * @member Utils
2589
     * @memberof Popper
2590
     */
2591
2592
  }]);
2593
  return Popper;
2594
}();
2595
2596
/**
2597
 * The `referenceObject` is an object that provides an interface compatible with Popper.js
2598
 * and lets you use it as replacement of a real DOM node.<br />
2599
 * You can use this method to position a popper relatively to a set of coordinates
2600
 * in case you don't have a DOM node to use as reference.
2601
 *
2602
 * ```
2603
 * new Popper(referenceObject, popperNode);
2604
 * ```
2605
 *
2606
 * NB: This feature isn't supported in Internet Explorer 10.
2607
 * @name referenceObject
2608
 * @property {Function} data.getBoundingClientRect
2609
 * A function that returns a set of coordinates compatible with the native `getBoundingClientRect` method.
2610
 * @property {number} data.clientWidth
2611
 * An ES6 getter that will return the width of the virtual reference element.
2612
 * @property {number} data.clientHeight
2613
 * An ES6 getter that will return the height of the virtual reference element.
2614
 */
2615
2616
2617
Popper.Utils = (typeof window !== 'undefined' ? window : global).PopperUtils;
2618
Popper.placements = placements;
2619
Popper.Defaults = Defaults;
2620
2621
return Popper;
2622
2623
})));
2624
//# sourceMappingURL=popper.js.map
2625