1/**! 2 * @fileOverview Kickass library to create and place poppers near their reference elements. 3 * @version 1.12.3 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' ? factory(exports) : 27 typeof define === 'function' && define.amd ? define(['exports'], factory) : 28 (factory((global.PopperUtils = global.PopperUtils || {}))); 29}(this, (function (exports) { 'use strict'; 30 31/** 32 * Get CSS computed property of the given element 33 * @method 34 * @memberof Popper.Utils 35 * @argument {Eement} element 36 * @argument {String} property 37 */ 38function getStyleComputedProperty(element, property) { 39 if (element.nodeType !== 1) { 40 return []; 41 } 42 // NOTE: 1 DOM access here 43 var css = window.getComputedStyle(element, null); 44 return property ? css[property] : css; 45} 46 47/** 48 * Returns the parentNode or the host of the element 49 * @method 50 * @memberof Popper.Utils 51 * @argument {Element} element 52 * @returns {Element} parent 53 */ 54function getParentNode(element) { 55 if (element.nodeName === 'HTML') { 56 return element; 57 } 58 return element.parentNode || element.host; 59} 60 61/** 62 * Returns the scrolling parent of the given element 63 * @method 64 * @memberof Popper.Utils 65 * @argument {Element} element 66 * @returns {Element} scroll parent 67 */ 68function getScrollParent(element) { 69 // Return body, `getScroll` will take care to get the correct `scrollTop` from it 70 if (!element || ['HTML', 'BODY', '#document'].indexOf(element.nodeName) !== -1) { 71 return window.document.body; 72 } 73 74 // Firefox want us to check `-x` and `-y` variations as well 75 76 var _getStyleComputedProp = getStyleComputedProperty(element), 77 overflow = _getStyleComputedProp.overflow, 78 overflowX = _getStyleComputedProp.overflowX, 79 overflowY = _getStyleComputedProp.overflowY; 80 81 if (/(auto|scroll)/.test(overflow + overflowY + overflowX)) { 82 return element; 83 } 84 85 return getScrollParent(getParentNode(element)); 86} 87 88/** 89 * Returns the offset parent of the given element 90 * @method 91 * @memberof Popper.Utils 92 * @argument {Element} element 93 * @returns {Element} offset parent 94 */ 95function getOffsetParent(element) { 96 // NOTE: 1 DOM access here 97 var offsetParent = element && element.offsetParent; 98 var nodeName = offsetParent && offsetParent.nodeName; 99 100 if (!nodeName || nodeName === 'BODY' || nodeName === 'HTML') { 101 return window.document.documentElement; 102 } 103 104 // .offsetParent will return the closest TD or TABLE in case 105 // no offsetParent is present, I hate this job... 106 if (['TD', 'TABLE'].indexOf(offsetParent.nodeName) !== -1 && getStyleComputedProperty(offsetParent, 'position') === 'static') { 107 return getOffsetParent(offsetParent); 108 } 109 110 return offsetParent; 111} 112 113function isOffsetContainer(element) { 114 var nodeName = element.nodeName; 115 116 if (nodeName === 'BODY') { 117 return false; 118 } 119 return nodeName === 'HTML' || getOffsetParent(element.firstElementChild) === element; 120} 121 122/** 123 * Finds the root node (document, shadowDOM root) of the given element 124 * @method 125 * @memberof Popper.Utils 126 * @argument {Element} node 127 * @returns {Element} root node 128 */ 129function getRoot(node) { 130 if (node.parentNode !== null) { 131 return getRoot(node.parentNode); 132 } 133 134 return node; 135} 136 137/** 138 * Finds the offset parent common to the two provided nodes 139 * @method 140 * @memberof Popper.Utils 141 * @argument {Element} element1 142 * @argument {Element} element2 143 * @returns {Element} common offset parent 144 */ 145function findCommonOffsetParent(element1, element2) { 146 // This check is needed to avoid errors in case one of the elements isn't defined for any reason 147 if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) { 148 return window.document.documentElement; 149 } 150 151 // Here we make sure to give as "start" the element that comes first in the DOM 152 var order = element1.compareDocumentPosition(element2) & Node.DOCUMENT_POSITION_FOLLOWING; 153 var start = order ? element1 : element2; 154 var end = order ? element2 : element1; 155 156 // Get common ancestor container 157 var range = document.createRange(); 158 range.setStart(start, 0); 159 range.setEnd(end, 0); 160 var commonAncestorContainer = range.commonAncestorContainer; 161
162 // Both nodes are inside #document 163 164 if (element1 !== commonAncestorContainer && element2 !== commonAncestorContainer || start.contains(end)) { 165 if (isOffsetContainer(commonAncestorContainer)) { 166 return commonAncestorContainer; 167 } 168 169 return getOffsetParent(commonAncestorContainer); 170 } 171 172 // one of the nodes is inside shadowDOM, find which one 173 var element1root = getRoot(element1); 174 if (element1root.host) { 175 return findCommonOffsetParent(element1root.host, element2); 176 } else { 177 return findCommonOffsetParent(element1, getRoot(element2).host); 178 } 179} 180 181/** 182 * Gets the scroll value of the given element in the given side (top and left) 183 * @method 184 * @memberof Popper.Utils 185 * @argument {Element} element 186 * @argument {String} side `top` or `left` 187 * @returns {number} amount of scrolled pixels 188 */ 189function getScroll(element) { 190 var side = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'top'; 191 192 var upperSide = side === 'top' ? 'scrollTop' : 'scrollLeft'; 193 var nodeName = element.nodeName; 194 195 if (nodeName === 'BODY' || nodeName === 'HTML') { 196 var html = window.document.documentElement; 197 var scrollingElement = window.document.scrollingElement || html; 198 return scrollingElement[upperSide]; 199 } 200 201 return element[upperSide]; 202} 203 204/* 205 * Sum or subtract the element scroll values (left and top) from a given rect object 206 * @method 207 * @memberof Popper.Utils 208 * @param {Object} rect - Rect object you want to change 209 * @param {HTMLElement} element - The element from the function reads the scroll values 210 * @param {Boolean} subtract - set to true if you want to subtract the scroll values 211 * @return {Object} rect - The modifier rect object 212 */ 213function includeScroll(rect, element) { 214 var subtract = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; 215 216 var scrollTop = getScroll(element, 'top'); 217 var scrollLeft = getScroll(element, 'left'); 218 var modifier = subtract ? -1 : 1; 219 rect.top += scrollTop * modifier; 220 rect.bottom += scrollTop * modifier; 221 rect.left += scrollLeft * modifier; 222 rect.right += scrollLeft * modifier; 223 return rect; 224} 225 226/* 227 * Helper to detect borders of a given element 228 * @method 229 * @memberof Popper.Utils 230 * @param {CSSStyleDeclaration} styles 231 * Result of `getStyleComputedProperty` on the given element 232 * @param {String} axis - `x` or `y` 233 * @return {number} borders - The borders size of the given axis 234 */ 235 236function getBordersSize(styles, axis) { 237 var sideA = axis === 'x' ? 'Left' : 'Top'; 238 var sideB = sideA === 'Left' ? 'Right' : 'Bottom'; 239 240 return +styles['border' + sideA + 'Width'].split('px')[0] + +styles['border' + sideB + 'Width'].split('px')[0]; 241} 242 243/** 244 * Tells if you are running Internet Explorer 10 245 * @method 246 * @memberof Popper.Utils 247 * @returns {Boolean} isIE10 248 */ 249var isIE10 = undefined; 250 251var isIE10$1 = function () { 252 if (isIE10 === undefined) { 253 isIE10 = navigator.appVersion.indexOf('MSIE 10') !== -1; 254 } 255 return isIE10; 256}; 257 258function getSize(axis, body, html, computedStyle) { 259 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); 260} 261 262function getWindowSizes() { 263 var body = window.document.body; 264 var html = window.document.documentElement; 265 var computedStyle = isIE10$1() && window.getComputedStyle(html); 266 267 return { 268 height: getSize('Height', body, html, computedStyle), 269 width: getSize('Width', body, html, computedStyle) 270 }; 271} 272 273var _extends = Object.assign || function (target) { 274 for (var i = 1; i < arguments.length; i++) { 275 var source = arguments[i]; 276 277 for (var key in source) { 278 if (Object.prototype.hasOwnProperty.call(source, key)) { 279 target[key] = source[key]; 280 } 281 } 282 } 283 284 return target; 285}; 286 287/** 288 * Given element offsets, generate an output similar to getBoundingClientRect 289 * @method 290 * @memberof Popper.Utils 291 * @argument {Object} offsets 292 * @returns {Object} ClientRect like output 293 */ 294function getClientRect(offsets) { 295 return _extends({}, offsets, { 296 right: offsets.left + offsets.width, 297 bottom: offsets.top + offsets.height 298 }); 299} 300 301/** 302 * Get bounding client rect of given element 303 * @method 304 * @memberof Popper.Utils 305 * @param {HTMLElement} element 306 * @return {Object} client rect 307 */ 308function getBoundingClientRect(element) { 309 var rect = {}; 310 311 // IE10 10 FIX: Please, don't ask, the element isn't
312 // considered in DOM in some circumstances... 313 // This isn't reproducible in IE10 compatibility mode of IE11 314 if (isIE10$1()) { 315 try { 316 rect = element.getBoundingClientRect(); 317 var scrollTop = getScroll(element, 'top'); 318 var scrollLeft = getScroll(element, 'left'); 319 rect.top += scrollTop; 320 rect.left += scrollLeft; 321 rect.bottom += scrollTop; 322 rect.right += scrollLeft; 323 } catch (err) {} 324 } else { 325 rect = element.getBoundingClientRect(); 326 } 327 328 var result = { 329 left: rect.left, 330 top: rect.top, 331 width: rect.right - rect.left, 332 height: rect.bottom - rect.top 333 }; 334 335 // subtract scrollbar size from sizes 336 var sizes = element.nodeName === 'HTML' ? getWindowSizes() : {}; 337 var width = sizes.width || element.clientWidth || result.right - result.left; 338 var height = sizes.height || element.clientHeight || result.bottom - result.top; 339 340 var horizScrollbar = element.offsetWidth - width; 341 var vertScrollbar = element.offsetHeight - height; 342 343 // if an hypothetical scrollbar is detected, we must be sure it's not a `border` 344 // we make this check conditional for performance reasons 345 if (horizScrollbar || vertScrollbar) { 346 var styles = getStyleComputedProperty(element); 347 horizScrollbar -= getBordersSize(styles, 'x'); 348 vertScrollbar -= getBordersSize(styles, 'y'); 349 350 result.width -= horizScrollbar; 351 result.height -= vertScrollbar; 352 } 353 354 return getClientRect(result); 355} 356 357function getOffsetRectRelativeToArbitraryNode(children, parent) { 358 var isIE10 = isIE10$1(); 359 var isHTML = parent.nodeName === 'HTML'; 360 var childrenRect = getBoundingClientRect(children); 361 var parentRect = getBoundingClientRect(parent); 362 var scrollParent = getScrollParent(children); 363 364 var styles = getStyleComputedProperty(parent); 365 var borderTopWidth = +styles.borderTopWidth.split('px')[0]; 366 var borderLeftWidth = +styles.borderLeftWidth.split('px')[0]; 367 368 var offsets = getClientRect({ 369 top: childrenRect.top - parentRect.top - borderTopWidth, 370 left: childrenRect.left - parentRect.left - borderLeftWidth, 371 width: childrenRect.width, 372 height: childrenRect.height 373 }); 374 offsets.marginTop = 0; 375 offsets.marginLeft = 0; 376 377 // Subtract margins of documentElement in case it's being used as parent 378 // we do this only on HTML because it's the only element that behaves 379 // differently when margins are applied to it. The margins are included in 380 // the box of the documentElement, in the other cases not. 381 if (!isIE10 && isHTML) { 382 var marginTop = +styles.marginTop.split('px')[0]; 383 var marginLeft = +styles.marginLeft.split('px')[0]; 384 385 offsets.top -= borderTopWidth - marginTop; 386 offsets.bottom -= borderTopWidth - marginTop; 387 offsets.left -= borderLeftWidth - marginLeft; 388 offsets.right -= borderLeftWidth - marginLeft; 389 390 // Attach marginTop and marginLeft because in some circumstances we may need them 391 offsets.marginTop = marginTop; 392 offsets.marginLeft = marginLeft; 393 } 394 395 if (isIE10 ? parent.contains(scrollParent) : parent === scrollParent && scrollParent.nodeName !== 'BODY') { 396 offsets = includeScroll(offsets, parent); 397 } 398 399 return offsets; 400} 401 402function getViewportOffsetRectRelativeToArtbitraryNode(element) { 403 var html = window.document.documentElement; 404 var relativeOffset = getOffsetRectRelativeToArbitraryNode(element, html); 405 var width = Math.max(html.clientWidth, window.innerWidth || 0); 406 var height = Math.max(html.clientHeight, window.innerHeight || 0); 407 408 var scrollTop = getScroll(html); 409 var scrollLeft = getScroll(html, 'left'); 410 411 var offset = { 412 top: scrollTop - relativeOffset.top + relativeOffset.marginTop, 413 left: scrollLeft - relativeOffset.left + relativeOffset.marginLeft, 414 width: width, 415 height: height 416 }; 417 418 return getClientRect(offset); 419} 420 421/** 422 * Check if the given element is fixed or is inside a fixed parent 423 * @method 424 * @memberof Popper.Utils 425 * @argument {Element} element 426 * @argument {Element} customContainer 427 * @returns {Boolean} answer to "isFixed?" 428 */ 429function isFixed(element) { 430 var nodeName = element.nodeName; 431 if (nodeName === 'BODY' || nodeName === 'HTML') { 432 return false;
433 } 434 if (getStyleComputedProperty(element, 'position') === 'fixed') { 435 return true; 436 } 437 return isFixed(getParentNode(element)); 438} 439 440/** 441 * Computed the boundaries limits and return them 442 * @method 443 * @memberof Popper.Utils 444 * @param {HTMLElement} popper 445 * @param {HTMLElement} reference 446 * @param {number} padding 447 * @param {HTMLElement} boundariesElement - Element used to define the boundaries 448 * @returns {Object} Coordinates of the boundaries 449 */ 450function getBoundaries(popper, reference, padding, boundariesElement) { 451 // NOTE: 1 DOM access here 452 var boundaries = { top: 0, left: 0 }; 453 var offsetParent = findCommonOffsetParent(popper, reference); 454 455 // Handle viewport case 456 if (boundariesElement === 'viewport') { 457 boundaries = getViewportOffsetRectRelativeToArtbitraryNode(offsetParent); 458 } else { 459 // Handle other cases based on DOM element used as boundaries 460 var boundariesNode = void 0; 461 if (boundariesElement === 'scrollParent') { 462 boundariesNode = getScrollParent(getParentNode(popper)); 463 if (boundariesNode.nodeName === 'BODY') { 464 boundariesNode = window.document.documentElement; 465 } 466 } else if (boundariesElement === 'window') { 467 boundariesNode = window.document.documentElement; 468 } else { 469 boundariesNode = boundariesElement; 470 } 471 472 var offsets = getOffsetRectRelativeToArbitraryNode(boundariesNode, offsetParent); 473 474 // In case of HTML, we need a different computation 475 if (boundariesNode.nodeName === 'HTML' && !isFixed(offsetParent)) { 476 var _getWindowSizes = getWindowSizes(), 477 height = _getWindowSizes.height, 478 width = _getWindowSizes.width; 479 480 boundaries.top += offsets.top - offsets.marginTop; 481 boundaries.bottom = height + offsets.top; 482 boundaries.left += offsets.left - offsets.marginLeft; 483 boundaries.right = width + offsets.left; 484 } else { 485 // for all the other DOM elements, this one is good 486 boundaries = offsets; 487 } 488 } 489 490 // Add paddings 491 boundaries.left += padding; 492 boundaries.top += padding; 493 boundaries.right -= padding; 494 boundaries.bottom -= padding; 495 496 return boundaries; 497} 498 499function getArea(_ref) { 500 var width = _ref.width, 501 height = _ref.height; 502 503 return width * height; 504} 505 506/** 507 * Utility used to transform the `auto` placement to the placement with more 508 * available space. 509 * @method 510 * @memberof Popper.Utils 511 * @argument {Object} data - The data object generated by update method 512 * @argument {Object} options - Modifiers configuration and options 513 * @returns {Object} The data object, properly modified 514 */ 515function computeAutoPlacement(placement, refRect, popper, reference, boundariesElement) { 516 var padding = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0; 517 518 if (placement.indexOf('auto') === -1) { 519 return placement; 520 } 521 522 var boundaries = getBoundaries(popper, reference, padding, boundariesElement); 523 524 var rects = { 525 top: { 526 width: boundaries.width, 527 height: refRect.top - boundaries.top 528 }, 529 right: { 530 width: boundaries.right - refRect.right, 531 height: boundaries.height 532 }, 533 bottom: { 534 width: boundaries.width, 535 height: boundaries.bottom - refRect.bottom 536 }, 537 left: { 538 width: refRect.left - boundaries.left, 539 height: boundaries.height 540 } 541 }; 542 543 var sortedAreas = Object.keys(rects).map(function (key) { 544 return _extends({ 545 key: key 546 }, rects[key], { 547 area: getArea(rects[key]) 548 }); 549 }).sort(function (a, b) { 550 return b.area - a.area; 551 }); 552 553 var filteredAreas = sortedAreas.filter(function (_ref2) { 554 var width = _ref2.width, 555 height = _ref2.height; 556 return width >= popper.clientWidth && height >= popper.clientHeight; 557 }); 558 559 var computedPlacement = filteredAreas.length > 0 ? filteredAreas[0].key : sortedAreas[0].key; 560 561 var variation = placement.split('-')[1]; 562 563 return computedPlacement + (variation ? '-' + variation : ''); 564} 565 566var nativeHints = ['native code', '[object MutationObserverConstructor]']; 567 568/** 569 * Determine if a function is implemented natively (as opposed to a polyfill). 570 * @method 571 * @memberof Popper.Utils 572 * @argument {Function | undefined} fn the function to check 573 * @returns {Boolean} 574 */ 575var isNative = (function (fn) { 576 return nativeHints.some(function (hint) { 577 return (fn || '').toString().indexOf(hint) > -1; 578 }); 579}); 580 581var isBrowser = typeof window !== 'undefined'; 582var longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox']; 583var timeoutDuration = 0; 584for (var i = 0; i < longerTimeoutBrowsers.length; i += 1) { 585 if (isBrowser && navigator.userAgent.indexOf(longerTimeoutBrowsers[i]) >= 0) { 586 timeoutDuration = 1; 587 break; 588 } 589} 590 591function microtaskDebounce(fn) { 592 var scheduled = false;
593 var i = 0; 594 var elem = document.createElement('span'); 595 596 // MutationObserver provides a mechanism for scheduling microtasks, which 597 // are scheduled *before* the next task. This gives us a way to debounce 598 // a function but ensure it's called *before* the next paint. 599 var observer = new MutationObserver(function () { 600 fn(); 601 scheduled = false; 602 }); 603 604 observer.observe(elem, { attributes: true }); 605 606 return function () { 607 if (!scheduled) { 608 scheduled = true; 609 elem.setAttribute('x-index', i); 610 i = i + 1; // don't use compund (+=) because it doesn't get optimized in V8 611 } 612 }; 613} 614 615function taskDebounce(fn) { 616 var scheduled = false; 617 return function () { 618 if (!scheduled) { 619 scheduled = true; 620 setTimeout(function () { 621 scheduled = false; 622 fn(); 623 }, timeoutDuration); 624 } 625 }; 626} 627 628// It's common for MutationObserver polyfills to be seen in the wild, however 629// these rely on Mutation Events which only occur when an element is connected 630// to the DOM. The algorithm used in this module does not use a connected element, 631// and so we must ensure that a *native* MutationObserver is available. 632var supportsNativeMutationObserver = isBrowser && isNative(window.MutationObserver); 633 634/** 635* Create a debounced version of a method, that's asynchronously deferred 636* but called in the minimum time possible. 637* 638* @method 639* @memberof Popper.Utils 640* @argument {Function} fn 641* @returns {Function} 642*/ 643var debounce = supportsNativeMutationObserver ? microtaskDebounce : taskDebounce; 644 645/** 646 * Mimics the `find` method of Array 647 * @method 648 * @memberof Popper.Utils 649 * @argument {Array} arr 650 * @argument prop 651 * @argument value 652 * @returns index or -1 653 */ 654function find(arr, check) { 655 // use native find if supported 656 if (Array.prototype.find) { 657 return arr.find(check); 658 } 659 660 // use `filter` to obtain the same behavior of `find` 661 return arr.filter(check)[0]; 662} 663 664/** 665 * Return the index of the matching object 666 * @method 667 * @memberof Popper.Utils 668 * @argument {Array} arr 669 * @argument prop 670 * @argument value 671 * @returns index or -1 672 */ 673function findIndex(arr, prop, value) { 674 // use native findIndex if supported 675 if (Array.prototype.findIndex) { 676 return arr.findIndex(function (cur) { 677 return cur[prop] === value; 678 }); 679 } 680 681 // use `find` + `indexOf` if `findIndex` isn't supported 682 var match = find(arr, function (obj) { 683 return obj[prop] === value; 684 }); 685 return arr.indexOf(match); 686} 687 688/** 689 * Get the position of the given element, relative to its offset parent 690 * @method 691 * @memberof Popper.Utils 692 * @param {Element} element 693 * @return {Object} position - Coordinates of the element and its `scrollTop` 694 */ 695function getOffsetRect(element) { 696 var elementRect = void 0; 697 if (element.nodeName === 'HTML') { 698 var _getWindowSizes = getWindowSizes(), 699 width = _getWindowSizes.width, 700 height = _getWindowSizes.height; 701 702 elementRect = { 703 width: width, 704 height: height, 705 left: 0, 706 top: 0 707 }; 708 } else { 709 elementRect = { 710 width: element.offsetWidth, 711 height: element.offsetHeight, 712 left: element.offsetLeft, 713 top: element.offsetTop 714 }; 715 } 716 717 // position 718 return getClientRect(elementRect); 719} 720 721/** 722 * Get the outer sizes of the given element (offset size + margins) 723 * @method 724 * @memberof Popper.Utils 725 * @argument {Element} element 726 * @returns {Object}
vendor: 10,305 bytes, lines 726-1039
726 object containing width and height properties 727 */ 728function getOuterSizes(element) { 729 var styles = window.getComputedStyle(element); 730 var x = parseFloat(styles.marginTop) + parseFloat(styles.marginBottom); 731 var y = parseFloat(styles.marginLeft) + parseFloat(styles.marginRight); 732 var result = { 733 width: element.offsetWidth + y, 734 height: element.offsetHeight + x 735 }; 736 return result; 737} 738 739/** 740 * Get the opposite placement of the given one 741 * @method 742 * @memberof Popper.Utils 743 * @argument {String} placement 744 * @returns {String} flipped placement 745 */ 746function getOppositePlacement(placement) { 747 var hash = { left: 'right', right: 'left', bottom: 'top', top: 'bottom' }; 748 return placement.replace(/left|right|bottom|top/g, function (matched) { 749 return hash[matched]; 750 }); 751} 752 753/** 754 * Get offsets to the popper 755 * @method 756 * @memberof Popper.Utils 757 * @param {Object} position - CSS position the Popper will get applied 758 * @param {HTMLElement} popper - the popper element 759 * @param {Object} referenceOffsets - the reference offsets (the popper will be relative to this) 760 * @param {String} placement - one of the valid placement options 761 * @returns {Object} popperOffsets - An object containing the offsets which will be applied to the popper 762 */ 763function getPopperOffsets(popper, referenceOffsets, placement) { 764 placement = placement.split('-')[0]; 765 766 // Get popper node sizes 767 var popperRect = getOuterSizes(popper); 768 769 // Add position, width and height to our offsets object 770 var popperOffsets = { 771 width: popperRect.width, 772 height: popperRect.height 773 }; 774 775 // depending by the popper placement we have to compute its offsets slightly differently 776 var isHoriz = ['right', 'left'].indexOf(placement) !== -1; 777 var mainSide = isHoriz ? 'top' : 'left'; 778 var secondarySide = isHoriz ? 'left' : 'top'; 779 var measurement = isHoriz ? 'height' : 'width'; 780 var secondaryMeasurement = !isHoriz ? 'height' : 'width'; 781 782 popperOffsets[mainSide] = referenceOffsets[mainSide] + referenceOffsets[measurement] / 2 - popperRect[measurement] / 2; 783 if (placement === secondarySide) { 784 popperOffsets[secondarySide] = referenceOffsets[secondarySide] - popperRect[secondaryMeasurement]; 785 } else { 786 popperOffsets[secondarySide] = referenceOffsets[getOppositePlacement(secondarySide)]; 787 } 788 789 return popperOffsets; 790} 791 792/** 793 * Get offsets to the reference element 794 * @method 795 * @memberof Popper.Utils 796 * @param {Object} state 797 * @param {Element} popper - the popper element 798 * @param {Element} reference - the reference element (the popper will be relative to this) 799 * @returns {Object} An object containing the offsets which will be applied to the popper 800 */ 801function getReferenceOffsets(state, popper, reference) { 802 var commonOffsetParent = findCommonOffsetParent(popper, reference); 803 return getOffsetRectRelativeToArbitraryNode(reference, commonOffsetParent); 804} 805 806/** 807 * Get the prefixed supported property name 808 * @method 809 * @memberof Popper.Utils 810 * @argument {String} property (camelCase) 811 * @returns {String} prefixed property (camelCase or PascalCase, depending on the vendor prefix) 812 */ 813function getSupportedPropertyName(property) { 814 var prefixes = [false, 'ms', 'Webkit', 'Moz', 'O']; 815 var upperProp = property.charAt(0).toUpperCase() + property.slice(1); 816 817 for (var i = 0; i < prefixes.length - 1; i++) { 818 var prefix = prefixes[i]; 819 var toCheck = prefix ? '' + prefix + upperProp : property; 820 if (typeof window.document.body.style[toCheck] !== 'undefined') { 821 return toCheck; 822 } 823 } 824 return null; 825} 826 827/** 828 * Check if the given variable is a function 829 * @method 830 * @memberof Popper.Utils 831 * @argument {Any} functionToCheck - variable to check 832 * @returns {Boolean} answer to: is a function? 833 */ 834function isFunction(functionToCheck) { 835 var getType = {}; 836 return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]'; 837} 838 839/** 840 * Helper used to know if the given modifier is enabled. 841 * @method 842 * @memberof Popper.Utils 843 * @returns {Boolean} 844 */ 845function isModifierEnabled(modifiers, modifierName) { 846 return modifiers.some(function (_ref) { 847 var name = _ref.name, 848 enabled = _ref.enabled; 849 return enabled && name === modifierName; 850 }); 851} 852 853/** 854 * Helper used to know if the given modifier depends from another one.<br /> 855 * It checks if the needed modifier is listed and enabled. 856 * @method 857 * @memberof Popper.Utils 858 * @param {Array} modifiers - list of modifiers 859 * @param {String} requestingName - name of requesting modifier 860 * @param {String} requestedName - name of requested modifier 861 * @returns {Boolean} 862 */ 863function isModifierRequired(modifiers, requestingName, requestedName) { 864 var requesting = find(modifiers, function (_ref) { 865 var name = _ref.name; 866 return name === requestingName; 867 }); 868 869 var isRequired = !!requesting && modifiers.some(function (modifier) { 870 return modifier.name === requestedName && modifier.enabled && modifier.order < requesting.order; 871 }); 872 873 if (!isRequired) { 874 var _requesting = '`' + requestingName + '`'; 875 var requested = '`' + requestedName + '`'; 876 console.warn(requested + ' modifier is required by ' + _requesting + ' modifier in order to work, be sure to include it before ' + _requesting + '!'); 877 } 878 return isRequired; 879} 880 881/** 882 * Tells if a given input is a number 883 * @method 884 * @memberof Popper.Utils 885 * @param {*} input to check 886 * @return {Boolean} 887 */ 888function isNumeric(n) { 889 return n !== '' && !isNaN(parseFloat(n)) && isFinite(n); 890} 891 892/** 893 * Remove event listeners used to update the popper position 894 * @method 895 * @memberof Popper.Utils 896 * @private 897 */ 898function removeEventListeners(reference, state) { 899 // Remove resize event listener on window 900 window.removeEventListener('resize', state.updateBound); 901 902 // Remove scroll event listener on scroll parents 903 state.scrollParents.forEach(function (target) { 904 target.removeEventListener('scroll', state.updateBound); 905 }); 906 907 // Reset state 908 state.updateBound = null; 909 state.scrollParents = []; 910 state.scrollElement = null; 911 state.eventsEnabled = false; 912 return state; 913} 914 915/** 916 * Loop trough the list of modifiers and run them in order, 917 * each of them will then edit the data object. 918 * @method 919 * @memberof Popper.Utils 920 * @param {dataObject} data 921 * @param {Array} modifiers 922 * @param {String} ends - Optional modifier name used as stopper 923 * @returns {dataObject} 924 */ 925function runModifiers(modifiers, data, ends) { 926 var modifiersToRun = ends === undefined ? modifiers : modifiers.slice(0, findIndex(modifiers, 'name', ends)); 927 928 modifiersToRun.forEach(function (modifier) { 929 if (modifier.function) { 930 console.warn('`modifier.function` is deprecated, use `modifier.fn`!'); 931 } 932 var fn = modifier.function || modifier.fn; 933 if (modifier.enabled && isFunction(fn)) { 934 // Add properties to offsets to make them a complete clientRect object 935 // we do this before each modifier to make sure the previous one doesn't 936 // mess with these values 937 data.offsets.popper = getClientRect(data.offsets.popper); 938 data.offsets.reference = getClientRect(data.offsets.reference); 939 940 data = fn(data, modifier); 941 } 942 }); 943 944 return data; 945} 946 947/** 948 * Set the attributes to the given popper 949 * @method 950 * @memberof Popper.Utils 951 * @argument {Element} element - Element to apply the attributes to 952 * @argument {Object} styles 953 * Object with a list of properties and values which will be applied to the element 954 */ 955function setAttributes(element, attributes) { 956 Object.keys(attributes).forEach(function (prop) { 957 var value = attributes[prop]; 958 if (value !== false) { 959 element.setAttribute(prop, attributes[prop]); 960 } else { 961 element.removeAttribute(prop); 962 } 963 }); 964} 965 966/** 967 * Set the style to the given popper 968 * @method 969 * @memberof Popper.Utils 970 * @argument {Element} element - Element to apply the style to 971 * @argument {Object} styles 972 * Object with a list of properties and values which will be applied to the element 973 */ 974function setStyles(element, styles) { 975 Object.keys(styles).forEach(function (prop) { 976 var unit = ''; 977 // add unit if the value is numeric and is one of the following 978 if (['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== -1 && isNumeric(styles[prop])) { 979 unit = 'px'; 980 } 981 element.style[prop] = styles[prop] + unit; 982 }); 983} 984 985function attachToScrollParents(scrollParent, event, callback, scrollParents) { 986 var isBody = scrollParent.nodeName === 'BODY'; 987 var target = isBody ? window : scrollParent; 988 target.addEventListener(event, callback, { passive: true }); 989 990 if (!isBody) { 991 attachToScrollParents(getScrollParent(target.parentNode), event, callback, scrollParents); 992 } 993 scrollParents.push(target); 994} 995 996/** 997 * Setup needed event listeners used to update the popper position 998 * @method 999 * @memberof Popper.Utils 1000 * @private 1001 */ 1002function setupEventListeners(reference, options, state, updateBound) { 1003 // Resize event listener on window 1004 state.updateBound = updateBound; 1005 window.addEventListener('resize', state.updateBound, { passive: true }); 1006 1007 // Scroll event listener on scroll parents 1008 var scrollElement = getScrollParent(reference); 1009 attachToScrollParents(scrollElement, 'scroll', state.updateBound, state.scrollParents); 1010 state.scrollElement = scrollElement; 1011 state.eventsEnabled = true; 1012 1013 return state; 1014} 1015 1016// This is here just for backward compatibility with versions lower than v1.10.3 1017// you should import the utilities using named exports, if you want them all use: 1018// ``` 1019// import * as PopperUtils from 'popper-utils'; 1020// ``` 1021// The default export will be removed in the next major version. 1022var index = { 1023 computeAutoPlacement: computeAutoPlacement, 1024 debounce: debounce, 1025 findIndex: findIndex, 1026 getBordersSize: getBordersSize, 1027 getBoundaries: getBoundaries, 1028 getBoundingClientRect: getBoundingClientRect, 1029 getClientRect: getClientRect, 1030 getOffsetParent: getOffsetParent, 1031 getOffsetRect: getOffsetRect, 1032 getOffsetRectRelativeToArbitraryNode: getOffsetRectRelativeToArbitraryNode, 1033 getOuterSizes: getOuterSizes, 1034 getParentNode: getParentNode, 1035 getPopperOffsets: getPopperOffsets, 1036 getReferenceOffsets: getReferenceOffsets, 1037 getScroll: getScroll, 1038 getScrollParent: getScrollParent, 1039 getStyleComputedProperty: getStyleComputedProperty,
1040 getSupportedPropertyName: getSupportedPropertyName, 1041 getWindowSizes: getWindowSizes, 1042 isFixed: isFixed, 1043 isFunction: isFunction, 1044 isModifierEnabled: isModifierEnabled, 1045 isModifierRequired: isModifierRequired, 1046 isNative: isNative, 1047 isNumeric: isNumeric, 1048 removeEventListeners: removeEventListeners, 1049 runModifiers: runModifiers, 1050 setAttributes: setAttributes, 1051 setStyles: setStyles, 1052 setupEventListeners: setupEventListeners 1053}; 1054 1055exports.computeAutoPlacement = computeAutoPlacement; 1056exports.debounce = debounce; 1057exports.findIndex = findIndex; 1058exports.getBordersSize = getBordersSize; 1059exports.getBoundaries = getBoundaries; 1060exports.getBoundingClientRect = getBoundingClientRect; 1061exports.getClientRect = getClientRect; 1062exports.getOffsetParent = getOffsetParent; 1063exports.getOffsetRect = getOffsetRect; 1064exports.getOffsetRectRelativeToArbitraryNode = getOffsetRectRelativeToArbitraryNode; 1065exports.getOuterSizes = getOuterSizes; 1066exports.getParentNode = getParentNode; 1067exports.getPopperOffsets = getPopperOffsets; 1068exports.getReferenceOffsets = getReferenceOffsets; 1069exports.getScroll = getScroll; 1070exports.getScrollParent = getScrollParent; 1071exports.getStyleComputedProperty = getStyleComputedProperty; 1072exports.getSupportedPropertyName = getSupportedPropertyName; 1073exports.getWindowSizes = getWindowSizes; 1074exports.isFixed = isFixed; 1075exports.isFunction = isFunction; 1076exports.isModifierEnabled = isModifierEnabled; 1077exports.isModifierRequired = isModifierRequired; 1078exports.isNative = isNative; 1079exports.isNumeric = isNumeric; 1080exports.removeEventListeners = removeEventListeners; 1081exports.runModifiers = runModifiers; 1082exports.setAttributes = setAttributes; 1083exports.setStyles = setStyles; 1084exports.setupEventListeners = setupEventListeners; 1085exports['default'] = index; 1086 1087Object.defineProperty(exports, '__esModule', { value: true }); 1088 1089}))); 1090//# sourceMappingURL=popper-utils.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.