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