1/**! 2 * @fileOverview Kickass library to create and place poppers near their reference elements. 3 * @version 1.11.0 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
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], html['client' + axis], html['offset' + axis], isIE10$1() ? html['offset' + axis] + computedStyle['margin' + (axis === 'Height' ? 'Top' : 'Left')] + computedStyle['margin' + (axis === 'Height' ? 'Bottom' : 'Right')] : 0); 351} 352 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
vendor: 4,306 bytes, lines 540-682
540); 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; 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} 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}
vendor: 4,716 bytes, lines 719-866
719 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 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 */
vendor: 4,913 bytes, lines 867-1024
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 attributes: {}, 877 flipped: false, 878 offsets: {} 879 }; 880 881 // compute reference element offsets 882 data.offsets.reference = getReferenceOffsets(this.state, this.popper, this.reference); 883 884 // compute auto placement, store placement inside the data object, 885 // modifiers will be able to edit `placement` if needed 886 // and refer to originalPlacement to know the original value 887 data.placement = computeAutoPlacement(this.options.placement, data.offsets.reference, this.popper, this.reference, this.options.modifiers.flip.boundariesElement, this.options.modifiers.flip.padding); 888 889 // store the computed placement inside `originalPlacement` 890 data.originalPlacement = data.placement; 891 892 // compute the popper offsets 893 data.offsets.popper = getPopperOffsets(this.popper, data.offsets.reference, data.placement); 894 data.offsets.popper.position = 'absolute'; 895 896 // run the modifiers 897 data = runModifiers(this.modifiers, data); 898 899 // the first `update` will call `onCreate` callback 900 // the other ones will call `onUpdate` callback 901 if (!this.state.isCreated) { 902 this.state.isCreated = true; 903 this.options.onCreate(data); 904 } else { 905 this.options.onUpdate(data); 906 } 907} 908 909/** 910 * Helper used to know if the given modifier is enabled. 911 * @method 912 * @memberof Popper.Utils 913 * @returns {Boolean} 914 */ 915function isModifierEnabled(modifiers, modifierName) { 916 return modifiers.some(function (_ref) { 917 var name = _ref.name, 918 enabled = _ref.enabled; 919 return enabled && name === modifierName; 920 }); 921} 922 923/** 924 * Get the prefixed supported property name 925 * @method 926 * @memberof Popper.Utils 927 * @argument {String} property (camelCase) 928 * @returns {String} prefixed property (camelCase or PascalCase, depending on the vendor prefix) 929 */ 930function getSupportedPropertyName(property) { 931 var prefixes = [false, 'ms', 'Webkit', 'Moz', 'O']; 932 var upperProp = property.charAt(0).toUpperCase() + property.slice(1); 933 934 for (var i = 0; i < prefixes.length - 1; i++) { 935 var prefix = prefixes[i]; 936 var toCheck = prefix ? '' + prefix + upperProp : property; 937 if (typeof window.document.body.style[toCheck] !== 'undefined') { 938 return toCheck; 939 } 940 } 941 return null; 942} 943 944/** 945 * Destroy the popper 946 * @method 947 * @memberof Popper 948 */ 949function destroy() { 950 this.state.isDestroyed = true; 951 952 // touch DOM only if `applyStyle` modifier is enabled 953 if (isModifierEnabled(this.modifiers, 'applyStyle')) { 954 this.popper.removeAttribute('x-placement'); 955 this.popper.style.left = ''; 956 this.popper.style.position = ''; 957 this.popper.style.top = ''; 958 this.popper.style[getSupportedPropertyName('transform')] = ''; 959 } 960 961 this.disableEventListeners(); 962 963 // remove the popper if user explicity asked for the deletion on destroy 964 // do not use `remove` because IE11 doesn't support it 965 if (this.options.removeOnDestroy) { 966 this.popper.parentNode.removeChild(this.popper); 967 } 968 return this; 969} 970 971function attachToScrollParents(scrollParent, event, callback, scrollParents) { 972 var isBody = scrollParent.nodeName === 'BODY'; 973 var target = isBody ? window : scrollParent; 974 target.addEventListener(event, callback, { passive: true }); 975 976 if (!isBody) { 977 attachToScrollParents(getScrollParent(target.parentNode), event, callback, scrollParents); 978 } 979 scrollParents.push(target); 980} 981 982/** 983 * Setup needed event listeners used to update the popper position 984 * @method 985 * @memberof Popper.Utils 986 * @private 987 */ 988function setupEventListeners(reference, options, state, updateBound) { 989 // Resize event listener on window 990 state.updateBound = updateBound; 991 window.addEventListener('resize', state.updateBound, { passive: true }); 992 993 // Scroll event listener on scroll parents 994 var scrollElement = getScrollParent(reference); 995 attachToScrollParents(scrollElement, 'scroll', state.updateBound, state.scrollParents); 996 state.scrollElement = scrollElement; 997 state.eventsEnabled = true; 998 999 return state; 1000} 1001 1002/** 1003 * It will add resize/scroll events and start recalculating 1004 * position of the popper element when they are triggered. 1005 * @method 1006 * @memberof Popper 1007 */ 1008function enableEventListeners() { 1009 if (!this.state.eventsEnabled) { 1010 this.state = setupEventListeners(this.reference, this.options, this.state, this.scheduleUpdate); 1011 } 1012} 1013 1014/** 1015 * Remove event listeners used to update the popper position 1016 * @method 1017 * @memberof Popper.Utils 1018 * @private 1019 */ 1020function removeEventListeners(reference, state) { 1021 // Remove resize event listener on window 1022 window.removeEventListener('resize', state.updateBound); 1023 1024 // Remove scroll event listener on scroll parents
vendor: 4,378 bytes, lines 1025-1148
1025 state.scrollParents.forEach(function (target) { 1026 target.removeEventListener('scroll', state.updateBound); 1027 }); 1028 1029 // Reset state 1030 state.updateBound = null; 1031 state.scrollParents = []; 1032 state.scrollElement = null; 1033 state.eventsEnabled = false; 1034 return state; 1035} 1036 1037/** 1038 * It will remove resize/scroll events and won't recalculate popper position 1039 * when they are triggered. It also won't trigger onUpdate callback anymore, 1040 * unless you call `update` method manually. 1041 * @method 1042 * @memberof Popper 1043 */ 1044function disableEventListeners() { 1045 if (this.state.eventsEnabled) { 1046 window.cancelAnimationFrame(this.scheduleUpdate); 1047 this.state = removeEventListeners(this.reference, this.state); 1048 } 1049} 1050 1051/** 1052 * Tells if a given input is a number 1053 * @method 1054 * @memberof Popper.Utils 1055 * @param {*} input to check 1056 * @return {Boolean} 1057 */ 1058function isNumeric(n) { 1059 return n !== '' && !isNaN(parseFloat(n)) && isFinite(n); 1060} 1061 1062/** 1063 * Set the style to the given popper 1064 * @method 1065 * @memberof Popper.Utils 1066 * @argument {Element} element - Element to apply the style to 1067 * @argument {Object} styles 1068 * Object with a list of properties and values which will be applied to the element 1069 */ 1070function setStyles(element, styles) { 1071 Object.keys(styles).forEach(function (prop) { 1072 var unit = ''; 1073 // add unit if the value is numeric and is one of the following 1074 if (['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== -1 && isNumeric(styles[prop])) { 1075 unit = 'px'; 1076 } 1077 element.style[prop] = styles[prop] + unit; 1078 }); 1079} 1080 1081/** 1082 * Set the attributes to the given popper 1083 * @method 1084 * @memberof Popper.Utils 1085 * @argument {Element} element - Element to apply the attributes to 1086 * @argument {Object} styles 1087 * Object with a list of properties and values which will be applied to the element 1088 */ 1089function setAttributes(element, attributes) { 1090 Object.keys(attributes).forEach(function (prop) { 1091 var value = attributes[prop]; 1092 if (value !== false) { 1093 element.setAttribute(prop, attributes[prop]); 1094 } else { 1095 element.removeAttribute(prop); 1096 } 1097 }); 1098} 1099 1100/** 1101 * @function 1102 * @memberof Modifiers 1103 * @argument {Object} data - The data object generated by `update` method 1104 * @argument {Object} data.styles - List of style properties - values to apply to popper element 1105 * @argument {Object} data.attributes - List of attribute properties - values to apply to popper element 1106 * @argument {Object} options - Modifiers configuration and options 1107 * @returns {Object} The same data object 1108 */ 1109function applyStyle(data) { 1110 // any property present in `data.styles` will be applied to the popper, 1111 // in this way we can make the 3rd party modifiers add custom styles to it 1112 // Be aware, modifiers could override the properties defined in the previous 1113 // lines of this modifier! 1114 setStyles(data.instance.popper, data.styles); 1115 1116 // any property present in `data.attributes` will be applied to the popper, 1117 // they will be set as HTML attributes of the element 1118 setAttributes(data.instance.popper, data.attributes); 1119 1120 // if the arrow style has been computed, apply the arrow style 1121 if (data.offsets.arrow) { 1122 setStyles(data.arrowElement, data.offsets.arrow); 1123 } 1124 1125 return data; 1126} 1127 1128/** 1129 * Set the x-placement attribute before everything else because it could be used 1130 * to add margins to the popper margins needs to be calculated to get the 1131 * correct popper offsets. 1132 * @method 1133 * @memberof Popper.modifiers 1134 * @param {HTMLElement} reference - The reference element used to position the popper 1135 * @param {HTMLElement} popper - The HTML element used as popper. 1136 * @param {Object} options - Popper.js options 1137 */ 1138function applyStyleOnLoad(reference, popper, options, modifierOptions, state) { 1139 // compute reference element offsets 1140 var referenceOffsets = getReferenceOffsets(state, popper, reference); 1141 1142 // compute auto placement, store placement inside the data object, 1143 // modifiers will be able to edit `placement` if needed 1144 // and refer to originalPlacement to know the original value 1145 var placement = computeAutoPlacement(options.placement, referenceOffsets, popper, reference, options.modifiers.flip.boundariesElement, options.modifiers.flip.padding); 1146 1147 popper.setAttribute('x-placement', placement); 1148
vendor: 4,200 bytes, lines 1149-1265
1149 // Apply `position` to popper before anything else because 1150 // without the position applied we can't guarantee correct computations 1151 setStyles(popper, { position: 'absolute' }); 1152 1153 return options; 1154} 1155 1156/** 1157 * @function 1158 * @memberof Modifiers 1159 * @argument {Object} data - The data object generated by `update` method 1160 * @argument {Object} options - Modifiers configuration and options 1161 * @returns {Object} The data object, properly modified 1162 */ 1163function computeStyle(data, options) { 1164 var x = options.x, 1165 y = options.y; 1166 var popper = data.offsets.popper; 1167 1168 // Remove this legacy support in Popper.js v2 1169 1170 var legacyGpuAccelerationOption = find(data.instance.modifiers, function (modifier) { 1171 return modifier.name === 'applyStyle'; 1172 }).gpuAcceleration; 1173 if (legacyGpuAccelerationOption !== undefined) { 1174 console.warn('WARNING: `gpuAcceleration` option moved to `computeStyle` modifier and will not be supported in future versions of Popper.js!'); 1175 } 1176 var gpuAcceleration = legacyGpuAccelerationOption !== undefined ? legacyGpuAccelerationOption : options.gpuAcceleration; 1177 1178 var offsetParent = getOffsetParent(data.instance.popper); 1179 var offsetParentRect = getBoundingClientRect(offsetParent); 1180 1181 // Styles 1182 var styles = { 1183 position: popper.position 1184 }; 1185 1186 // floor sides to avoid blurry text 1187 var offsets = { 1188 left: Math.floor(popper.left), 1189 top: Math.floor(popper.top), 1190 bottom: Math.floor(popper.bottom), 1191 right: Math.floor(popper.right) 1192 }; 1193 1194 var sideA = x === 'bottom' ? 'top' : 'bottom'; 1195 var sideB = y === 'right' ? 'left' : 'right'; 1196 1197 // if gpuAcceleration is set to `true` and transform is supported, 1198 // we use `translate3d` to apply the position to the popper we 1199 // automatically use the supported prefixed version if needed 1200 var prefixedProperty = getSupportedPropertyName('transform'); 1201 1202 // now, let's make a step back and look at this code closely (wtf?) 1203 // If the content of the popper grows once it's been positioned, it 1204 // may happen that the popper gets misplaced because of the new content 1205 // overflowing its reference element 1206 // To avoid this problem, we provide two options (x and y), which allow 1207 // the consumer to define the offset origin. 1208 // If we position a popper on top of a reference element, we can set 1209 // `x` to `top` to make the popper grow towards its top instead of 1210 // its bottom. 1211 var left = void 0, 1212 top = void 0; 1213 if (sideA === 'bottom') { 1214 top = -offsetParentRect.height + offsets.bottom; 1215 } else { 1216 top = offsets.top; 1217 } 1218 if (sideB === 'right') { 1219 left = -offsetParentRect.width + offsets.right; 1220 } else { 1221 left = offsets.left; 1222 } 1223 if (gpuAcceleration && prefixedProperty) { 1224 styles[prefixedProperty] = 'translate3d(' + left + 'px, ' + top + 'px, 0)'; 1225 styles[sideA] = 0; 1226 styles[sideB] = 0; 1227 styles.willChange = 'transform'; 1228 } else { 1229 // othwerise, we use the standard `top`, `left`, `bottom` and `right` properties 1230 var invertTop = sideA === 'bottom' ? -1 : 1; 1231 var invertLeft = sideB === 'right' ? -1 : 1; 1232 styles[sideA] = top * invertTop; 1233 styles[sideB] = left * invertLeft; 1234 styles.willChange = sideA + ', ' + sideB; 1235 } 1236 1237 // Attributes 1238 var attributes = { 1239 'x-placement': data.placement 1240 }; 1241 1242 // Update attributes and styles of `data` 1243 data.attributes = _extends({}, attributes, data.attributes); 1244 data.styles = _extends({}, styles, data.styles); 1245 1246 return data; 1247} 1248 1249/** 1250 * Helper used to know if the given modifier depends from another one.<br /> 1251 * It checks if the needed modifier is listed and enabled. 1252 * @method 1253 * @memberof Popper.Utils 1254 * @param {Array} modifiers - list of modifiers 1255 * @param {String} requestingName - name of requesting modifier 1256 * @param {String} requestedName - name of requested modifier 1257 * @returns {Boolean} 1258 */ 1259function isModifierRequired(modifiers, requestingName, requestedName) { 1260 var requesting = find(modifiers, function (_ref) { 1261 var name = _ref.name; 1262 return name === requestingName; 1263 }); 1264 1265 var isRequired = !!requesting && modifiers.some(function (modifier) {
vendor: 8,976 bytes, lines 1266-1507
1266 return modifier.name === requestedName && modifier.enabled && modifier.order < requesting.order; 1267 }); 1268 1269 if (!isRequired) { 1270 var _requesting = '`' + requestingName + '`'; 1271 var requested = '`' + requestedName + '`'; 1272 console.warn(requested + ' modifier is required by ' + _requesting + ' modifier in order to work, be sure to include it before ' + _requesting + '!'); 1273 } 1274 return isRequired; 1275} 1276 1277/** 1278 * @function 1279 * @memberof Modifiers 1280 * @argument {Object} data - The data object generated by update method 1281 * @argument {Object} options - Modifiers configuration and options 1282 * @returns {Object} The data object, properly modified 1283 */ 1284function arrow(data, options) { 1285 // arrow depends on keepTogether in order to work 1286 if (!isModifierRequired(data.instance.modifiers, 'arrow', 'keepTogether')) { 1287 return data; 1288 } 1289 1290 var arrowElement = options.element; 1291 1292 // if arrowElement is a string, suppose it's a CSS selector 1293 if (typeof arrowElement === 'string') { 1294 arrowElement = data.instance.popper.querySelector(arrowElement); 1295 1296 // if arrowElement is not found, don't run the modifier 1297 if (!arrowElement) { 1298 return data; 1299 } 1300 } else { 1301 // if the arrowElement isn't a query selector we must check that the 1302 // provided DOM node is child of its popper node 1303 if (!data.instance.popper.contains(arrowElement)) { 1304 console.warn('WARNING: `arrow.element` must be child of its popper element!'); 1305 return data; 1306 } 1307 } 1308 1309 var placement = data.placement.split('-')[0]; 1310 var _data$offsets = data.offsets, 1311 popper = _data$offsets.popper, 1312 reference = _data$offsets.reference; 1313 1314 var isVertical = ['left', 'right'].indexOf(placement) !== -1; 1315 1316 var len = isVertical ? 'height' : 'width'; 1317 var side = isVertical ? 'top' : 'left'; 1318 var altSide = isVertical ? 'left' : 'top'; 1319 var opSide = isVertical ? 'bottom' : 'right'; 1320 var arrowElementSize = getOuterSizes(arrowElement)[len]; 1321 1322 // 1323 // extends keepTogether behavior making sure the popper and its reference have enough pixels in conjuction 1324 // 1325 1326 // top/left side 1327 if (reference[opSide] - arrowElementSize < popper[side]) { 1328 data.offsets.popper[side] -= popper[side] - (reference[opSide] - arrowElementSize); 1329 } 1330 // bottom/right side 1331 if (reference[side] + arrowElementSize > popper[opSide]) { 1332 data.offsets.popper[side] += reference[side] + arrowElementSize - popper[opSide]; 1333 } 1334 1335 // compute center of the popper 1336 var center = reference[side] + reference[len] / 2 - arrowElementSize / 2; 1337 1338 // Compute the sideValue using the updated popper offsets 1339 var sideValue = center - getClientRect(data.offsets.popper)[side]; 1340 1341 // prevent arrowElement from being placed not contiguously to its popper 1342 sideValue = Math.max(Math.min(popper[len] - arrowElementSize, sideValue), 0); 1343 1344 data.arrowElement = arrowElement; 1345 data.offsets.arrow = {}; 1346 data.offsets.arrow[side] = Math.round(sideValue); 1347 data.offsets.arrow[altSide] = ''; // make sure to unset any eventual altSide value from the DOM node 1348 1349 return data; 1350} 1351 1352/** 1353 * Get the opposite placement variation of the given one 1354 * @method 1355 * @memberof Popper.Utils 1356 * @argument {String} placement variation 1357 * @returns {String} flipped placement variation 1358 */ 1359function getOppositeVariation(variation) { 1360 if (variation === 'end') { 1361 return 'start'; 1362 } else if (variation === 'start') { 1363 return 'end'; 1364 } 1365 return variation; 1366} 1367 1368/** 1369 * List of accepted placements to use as values of the `placement` option.<br /> 1370 * Valid placements are: 1371 * - `auto` 1372 * - `top` 1373 * - `right` 1374 * - `bottom` 1375 * - `left` 1376 * 1377 * Each placement can have a variation from this list: 1378 * - `-start` 1379 * - `-end` 1380 * 1381 * Variations are interpreted easily if you think of them as the left to right 1382 * written languages. Horizontally (`top` and `bottom`), `start` is left and `end` 1383 * is right.<br /> 1384 * Vertically (`left` and `right`), `start` is top and `end` is bottom. 1385 * 1386 * Some valid examples are: 1387 * - `top-end` (on top of reference, right aligned) 1388 * - `right-start` (on right of reference, top aligned) 1389 * - `bottom` (on bottom, centered) 1390 * - `auto-right` (on the side with more space available, alignment depends by placement) 1391 * 1392 * @static 1393 * @type {Array} 1394 * @enum {String} 1395 * @readonly 1396 * @method placements 1397 * @memberof Popper 1398 */ 1399var 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']; 1400 1401// Get rid of `auto` `auto-start` and `auto-end` 1402var validPlacements = placements.slice(3); 1403 1404/** 1405 * Given an initial placement, returns all the subsequent placements 1406 * clockwise (or counter-clockwise). 1407 * 1408 * @method 1409 * @memberof Popper.Utils 1410 * @argument {String} placement - A valid placement (it accepts variations) 1411 * @argument {Boolean} counter - Set to true to walk the placements counterclockwise 1412 * @returns {Array} placements including their variations 1413 */ 1414function clockwise(placement) { 1415 var counter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; 1416 1417 var index = validPlacements.indexOf(placement); 1418 var arr = validPlacements.slice(index + 1).concat(validPlacements.slice(0, index)); 1419 return counter ? arr.reverse() : arr; 1420} 1421 1422var BEHAVIORS = { 1423 FLIP: 'flip', 1424 CLOCKWISE: 'clockwise', 1425 COUNTERCLOCKWISE: 'counterclockwise' 1426}; 1427 1428/** 1429 * @function 1430 * @memberof Modifiers 1431 * @argument {Object} data - The data object generated by update method 1432 * @argument {Object} options - Modifiers configuration and options 1433 * @returns {Object} The data object, properly modified 1434 */ 1435function flip(data, options) { 1436 // if `inner` modifier is enabled, we can't use the `flip` modifier 1437 if (isModifierEnabled(data.instance.modifiers, 'inner')) { 1438 return data; 1439 } 1440 1441 if (data.flipped && data.placement === data.originalPlacement) { 1442 // seems like flip is trying to loop, probably there's not enough space on any of the flippable sides 1443 return data; 1444 } 1445 1446 var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, options.boundariesElement); 1447 1448 var placement = data.placement.split('-')[0]; 1449 var placementOpposite = getOppositePlacement(placement); 1450 var variation = data.placement.split('-')[1] || ''; 1451 1452 var flipOrder = []; 1453 1454 switch (options.behavior) { 1455 case BEHAVIORS.FLIP: 1456 flipOrder = [placement, placementOpposite]; 1457 break; 1458 case BEHAVIORS.CLOCKWISE: 1459 flipOrder = clockwise(placement); 1460 break; 1461 case BEHAVIORS.COUNTERCLOCKWISE: 1462 flipOrder = clockwise(placement, true); 1463 break; 1464 default: 1465 flipOrder = options.behavior; 1466 } 1467 1468 flipOrder.forEach(function (step, index) { 1469 if (placement !== step || flipOrder.length === index + 1) { 1470 return data; 1471 } 1472 1473 placement = data.placement.split('-')[0]; 1474 placementOpposite = getOppositePlacement(placement); 1475 1476 var popperOffsets = data.offsets.popper; 1477 var refOffsets = data.offsets.reference; 1478 1479 // using floor because the reference offsets may contain decimals we are not going to consider here 1480 var floor = Math.floor; 1481 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); 1482 1483 var overflowsLeft = floor(popperOffsets.left) < floor(boundaries.left); 1484 var overflowsRight = floor(popperOffsets.right) > floor(boundaries.right); 1485 var overflowsTop = floor(popperOffsets.top) < floor(boundaries.top); 1486 var overflowsBottom = floor(popperOffsets.bottom) > floor(boundaries.bottom); 1487 1488 var overflowsBoundaries = placement === 'left' && overflowsLeft || placement === 'right' && overflowsRight || placement === 'top' && overflowsTop || placement === 'bottom' && overflowsBottom; 1489 1490 // flip the variation if required 1491 var isVertical = ['top', 'bottom'].indexOf(placement) !== -1; 1492 var flippedVariation = !!options.flipVariations && (isVertical && variation === 'start' && overflowsLeft || isVertical && variation === 'end' && overflowsRight || !isVertical && variation === 'start' && overflowsTop || !isVertical && variation === 'end' && overflowsBottom); 1493 1494 if (overlapsRef || overflowsBoundaries || flippedVariation) { 1495 // this boolean to detect any flip loop 1496 data.flipped = true; 1497 1498 if (overlapsRef || overflowsBoundaries) { 1499 placement = flipOrder[index + 1]; 1500 } 1501 1502 if (flippedVariation) { 1503 variation = getOppositeVariation(variation); 1504 } 1505 1506 data.placement = placement + (variation ? '-' + variation : ''); 1507
vendor: 5,717 bytes, lines 1508-1664
1508 // this object contains `position`, we want to preserve it along with 1509 // any additional property we may add in the future 1510 data.offsets.popper = _extends({}, data.offsets.popper, getPopperOffsets(data.instance.popper, data.offsets.reference, data.placement)); 1511 1512 data = runModifiers(data.instance.modifiers, data, 'flip'); 1513 } 1514 }); 1515 return data; 1516} 1517 1518/** 1519 * @function 1520 * @memberof Modifiers 1521 * @argument {Object} data - The data object generated by update method 1522 * @argument {Object} options - Modifiers configuration and options 1523 * @returns {Object} The data object, properly modified 1524 */ 1525function keepTogether(data) { 1526 var _data$offsets = data.offsets, 1527 popper = _data$offsets.popper, 1528 reference = _data$offsets.reference; 1529 1530 var placement = data.placement.split('-')[0]; 1531 var floor = Math.floor; 1532 var isVertical = ['top', 'bottom'].indexOf(placement) !== -1; 1533 var side = isVertical ? 'right' : 'bottom'; 1534 var opSide = isVertical ? 'left' : 'top'; 1535 var measurement = isVertical ? 'width' : 'height'; 1536 1537 if (popper[side] < floor(reference[opSide])) { 1538 data.offsets.popper[opSide] = floor(reference[opSide]) - popper[measurement]; 1539 } 1540 if (popper[opSide] > floor(reference[side])) { 1541 data.offsets.popper[opSide] = floor(reference[side]); 1542 } 1543 1544 return data; 1545} 1546 1547/** 1548 * Converts a string containing value + unit into a px value number 1549 * @function 1550 * @memberof {modifiers~offset} 1551 * @private 1552 * @argument {String} str - Value + unit string 1553 * @argument {String} measurement - `height` or `width` 1554 * @argument {Object} popperOffsets 1555 * @argument {Object} referenceOffsets 1556 * @returns {Number|String} 1557 * Value in pixels, or original string if no values were extracted 1558 */ 1559function toValue(str, measurement, popperOffsets, referenceOffsets) { 1560 // separate value from unit 1561 var split = str.match(/((?:\-|\+)?\d*\.?\d*)(.*)/); 1562 var value = +split[1]; 1563 var unit = split[2]; 1564 1565 // If it's not a number it's an operator, I guess 1566 if (!value) { 1567 return str; 1568 } 1569 1570 if (unit.indexOf('%') === 0) { 1571 var element = void 0; 1572 switch (unit) { 1573 case '%p': 1574 element = popperOffsets; 1575 break; 1576 case '%': 1577 case '%r': 1578 default: 1579 element = referenceOffsets; 1580 } 1581 1582 var rect = getClientRect(element); 1583 return rect[measurement] / 100 * value; 1584 } else if (unit === 'vh' || unit === 'vw') { 1585 // if is a vh or vw, we calculate the size based on the viewport 1586 var size = void 0; 1587 if (unit === 'vh') { 1588 size = Math.max(document.documentElement.clientHeight, window.innerHeight || 0); 1589 } else { 1590 size = Math.max(document.documentElement.clientWidth, window.innerWidth || 0); 1591 } 1592 return size / 100 * value; 1593 } else { 1594 // if is an explicit pixel unit, we get rid of the unit and keep the value 1595 // if is an implicit unit, it's px, and we return just the value 1596 return value; 1597 } 1598} 1599 1600/** 1601 * Parse an `offset` string to extrapolate `x` and `y` numeric offsets. 1602 * @function 1603 * @memberof {modifiers~offset} 1604 * @private 1605 * @argument {String} offset 1606 * @argument {Object} popperOffsets 1607 * @argument {Object} referenceOffsets 1608 * @argument {String} basePlacement 1609 * @returns {Array} a two cells array with x and y offsets in numbers 1610 */ 1611function parseOffset(offset, popperOffsets, referenceOffsets, basePlacement) { 1612 var offsets = [0, 0]; 1613 1614 // Use height if placement is left or right and index is 0 otherwise use width 1615 // in this way the first offset will use an axis and the second one 1616 // will use the other one 1617 var useHeight = ['right', 'left'].indexOf(basePlacement) !== -1; 1618 1619 // Split the offset string to obtain a list of values and operands 1620 // The regex addresses values with the plus or minus sign in front (+10, -20, etc) 1621 var fragments = offset.split(/(\+|\-)/).map(function (frag) { 1622 return frag.trim(); 1623 }); 1624 1625 // Detect if the offset string contains a pair of values or a single one 1626 // they could be separated by comma or space 1627 var divider = fragments.indexOf(find(fragments, function (frag) { 1628 return frag.search(/,|\s/) !== -1; 1629 })); 1630 1631 if (fragments[divider] && fragments[divider].indexOf(',') === -1) { 1632 console.warn('Offsets separated by white space(s) are deprecated, use a comma (,) instead.'); 1633 } 1634 1635 // If divider is found, we divide the list of values and operands to divide 1636 // them by ofset X and Y. 1637 var splitRegex = /\s*,\s*|\s+/; 1638 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]; 1639 1640 // Convert the values with units to absolute pixels to allow our computations 1641 ops = ops.map(function (op, index) { 1642 // Most of the units rely on the orientation of the popper 1643 var measurement = (index === 1 ? !useHeight : useHeight) ? 'height' : 'width'; 1644 var mergeWithPrevious = false; 1645 return op 1646 // This aggregates any `+` or `-` sign that aren't considered operators 1647 // e.g.: 10 + +5 => [10, +, +5] 1648 .reduce(function (a, b) { 1649 if (a[a.length - 1] === '' && ['+', '-'].indexOf(b) !== -1) { 1650 a[a.length - 1] = b; 1651 mergeWithPrevious = true; 1652 return a; 1653 } else if (mergeWithPrevious) { 1654 a[a.length - 1] += b; 1655 mergeWithPrevious = false; 1656 return a; 1657 } else { 1658 return a.concat(b); 1659 } 1660 }, []) 1661 // Here we convert the string values into number values (in px) 1662 .map(function (str) { 1663 return toValue(str, measurement, popperOffsets, referenceOffsets); 1664 });
vendor: 5,101 bytes, lines 1665-1818
1665 }); 1666 1667 // Loop trough the offsets arrays and execute the operations 1668 ops.forEach(function (op, index) { 1669 op.forEach(function (frag, index2) { 1670 if (isNumeric(frag)) { 1671 offsets[index] += frag * (op[index2 - 1] === '-' ? -1 : 1); 1672 } 1673 }); 1674 }); 1675 return offsets; 1676} 1677 1678/** 1679 * @function 1680 * @memberof Modifiers 1681 * @argument {Object} data - The data object generated by update method 1682 * @argument {Object} options - Modifiers configuration and options 1683 * @argument {Number|String} options.offset=0 1684 * The offset value as described in the modifier description 1685 * @returns {Object} The data object, properly modified 1686 */ 1687function offset(data, _ref) { 1688 var offset = _ref.offset; 1689 var placement = data.placement, 1690 _data$offsets = data.offsets, 1691 popper = _data$offsets.popper, 1692 reference = _data$offsets.reference; 1693 1694 var basePlacement = placement.split('-')[0]; 1695 1696 var offsets = void 0; 1697 if (isNumeric(+offset)) { 1698 offsets = [+offset, 0]; 1699 } else { 1700 offsets = parseOffset(offset, popper, reference, basePlacement); 1701 } 1702 1703 if (basePlacement === 'left') { 1704 popper.top += offsets[0]; 1705 popper.left -= offsets[1]; 1706 } else if (basePlacement === 'right') { 1707 popper.top += offsets[0]; 1708 popper.left += offsets[1]; 1709 } else if (basePlacement === 'top') { 1710 popper.left += offsets[0]; 1711 popper.top -= offsets[1]; 1712 } else if (basePlacement === 'bottom') { 1713 popper.left += offsets[0]; 1714 popper.top += offsets[1]; 1715 } 1716 1717 data.popper = popper; 1718 return data; 1719} 1720 1721/** 1722 * @function 1723 * @memberof Modifiers 1724 * @argument {Object} data - The data object generated by `update` method 1725 * @argument {Object} options - Modifiers configuration and options 1726 * @returns {Object} The data object, properly modified 1727 */ 1728function preventOverflow(data, options) { 1729 var boundariesElement = options.boundariesElement || getOffsetParent(data.instance.popper); 1730 1731 // If offsetParent is the reference element, we really want to 1732 // go one step up and use the next offsetParent as reference to 1733 // avoid to make this modifier completely useless and look like broken 1734 if (data.instance.reference === boundariesElement) { 1735 boundariesElement = getOffsetParent(boundariesElement); 1736 } 1737 1738 var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, boundariesElement); 1739 options.boundaries = boundaries; 1740 1741 var order = options.priority; 1742 var popper = data.offsets.popper; 1743 1744 var check = { 1745 primary: function primary(placement) { 1746 var value = popper[placement]; 1747 if (popper[placement] < boundaries[placement] && !options.escapeWithReference) { 1748 value = Math.max(popper[placement], boundaries[placement]); 1749 } 1750 return defineProperty({}, placement, value); 1751 }, 1752 secondary: function secondary(placement) { 1753 var mainSide = placement === 'right' ? 'left' : 'top'; 1754 var value = popper[mainSide]; 1755 if (popper[placement] > boundaries[placement] && !options.escapeWithReference) { 1756 value = Math.min(popper[mainSide], boundaries[placement] - (placement === 'right' ? popper.width : popper.height)); 1757 } 1758 return defineProperty({}, mainSide, value); 1759 } 1760 }; 1761 1762 order.forEach(function (placement) { 1763 var side = ['left', 'top'].indexOf(placement) !== -1 ? 'primary' : 'secondary'; 1764 popper = _extends({}, popper, check[side](placement)); 1765 }); 1766 1767 data.offsets.popper = popper; 1768 1769 return data; 1770} 1771 1772/** 1773 * @function 1774 * @memberof Modifiers 1775 * @argument {Object} data - The data object generated by `update` method 1776 * @argument {Object} options - Modifiers configuration and options 1777 * @returns {Object} The data object, properly modified 1778 */ 1779function shift(data) { 1780 var placement = data.placement; 1781 var basePlacement = placement.split('-')[0]; 1782 var shiftvariation = placement.split('-')[1]; 1783 1784 // if shift shiftvariation is specified, run the modifier 1785 if (shiftvariation) { 1786 var _data$offsets = data.offsets, 1787 reference = _data$offsets.reference, 1788 popper = _data$offsets.popper; 1789 1790 var isVertical = ['bottom', 'top'].indexOf(basePlacement) !== -1; 1791 var side = isVertical ? 'left' : 'top'; 1792 var measurement = isVertical ? 'width' : 'height'; 1793 1794 var shiftOffsets = { 1795 start: defineProperty({}, side, reference[side]), 1796 end: defineProperty({}, side, reference[side] + reference[measurement] - popper[measurement]) 1797 }; 1798 1799 data.offsets.popper = _extends({}, popper, shiftOffsets[shiftvariation]); 1800 } 1801 1802 return data; 1803} 1804 1805/** 1806 * @function 1807 * @memberof Modifiers 1808 * @argument {Object} data - The data object generated by update method 1809 * @argument {Object} options - Modifiers configuration and options 1810 * @returns {Object} The data object, properly modified 1811 */ 1812function hide(data) { 1813 if (!isModifierRequired(data.instance.modifiers, 'hide', 'preventOverflow')) { 1814 return data; 1815 } 1816 1817 var refRect = data.offsets.reference; 1818 var bound = find(data.instance.modifiers, function (modifier) {
vendor: 3,737 bytes, lines 1819-1923
1819 return modifier.name === 'preventOverflow'; 1820 }).boundaries; 1821 1822 if (refRect.bottom < bound.top || refRect.left > bound.right || refRect.top > bound.bottom || refRect.right < bound.left) { 1823 // Avoid unnecessary DOM access if visibility hasn't changed 1824 if (data.hide === true) { 1825 return data; 1826 } 1827 1828 data.hide = true; 1829 data.attributes['x-out-of-boundaries'] = ''; 1830 } else { 1831 // Avoid unnecessary DOM access if visibility hasn't changed 1832 if (data.hide === false) { 1833 return data; 1834 } 1835 1836 data.hide = false; 1837 data.attributes['x-out-of-boundaries'] = false; 1838 } 1839 1840 return data; 1841} 1842 1843/** 1844 * @function 1845 * @memberof Modifiers 1846 * @argument {Object} data - The data object generated by `update` method 1847 * @argument {Object} options - Modifiers configuration and options 1848 * @returns {Object} The data object, properly modified 1849 */ 1850function inner(data) { 1851 var placement = data.placement; 1852 var basePlacement = placement.split('-')[0]; 1853 var _data$offsets = data.offsets, 1854 popper = _data$offsets.popper, 1855 reference = _data$offsets.reference; 1856 1857 var isHoriz = ['left', 'right'].indexOf(basePlacement) !== -1; 1858 1859 var subtractLength = ['top', 'left'].indexOf(basePlacement) === -1; 1860 1861 popper[isHoriz ? 'left' : 'top'] = reference[placement] - (subtractLength ? popper[isHoriz ? 'width' : 'height'] : 0); 1862 1863 data.placement = getOppositePlacement(placement); 1864 data.offsets.popper = getClientRect(popper); 1865 1866 return data; 1867} 1868 1869/** 1870 * Modifier function, each modifier can have a function of this type assigned 1871 * to its `fn` property.<br /> 1872 * These functions will be called on each update, this means that you must 1873 * make sure they are performant enough to avoid performance bottlenecks. 1874 * 1875 * @function ModifierFn 1876 * @argument {dataObject} data - The data object generated by `update` method 1877 * @argument {Object} options - Modifiers configuration and options 1878 * @returns {dataObject} The data object, properly modified 1879 */ 1880 1881/** 1882 * Modifiers are plugins used to alter the behavior of your poppers.<br /> 1883 * Popper.js uses a set of 9 modifiers to provide all the basic functionalities 1884 * needed by the library. 1885 * 1886 * Usually you don't want to override the `order`, `fn` and `onLoad` props. 1887 * All the other properties are configurations that could be tweaked. 1888 * @namespace modifiers 1889 */ 1890var modifiers = { 1891 /** 1892 * Modifier used to shift the popper on the start or end of its reference 1893 * element.<br /> 1894 * It will read the variation of the `placement` property.<br /> 1895 * It can be one either `-end` or `-start`. 1896 * @memberof modifiers 1897 * @inner 1898 */ 1899 shift: { 1900 /** @prop {number} order=100 - Index used to define the order of execution */ 1901 order: 100, 1902 /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ 1903 enabled: true, 1904 /** @prop {ModifierFn} */ 1905 fn: shift 1906 }, 1907 1908 /** 1909 * The `offset` modifier can shift your popper on both its axis. 1910 * 1911 * It accepts the following units: 1912 * - `px` or unitless, interpreted as pixels 1913 * - `%` or `%r`, percentage relative to the length of the reference element 1914 * - `%p`, percentage relative to the length of the popper element 1915 * - `vw`, CSS viewport width unit 1916 * - `vh`, CSS viewport height unit 1917 * 1918 * For length is intended the main axis relative to the placement of the popper.<br /> 1919 * This means that if the placement is `top` or `bottom`, the length will be the 1920 * `width`. In case of `left` or `right`, it will be the height. 1921 * 1922 * You can provide a single value (as `Number` or `String`), or a pair of values 1923 * as `String` divided by a comma or one (or more) white space
1923s.<br /> 1924 * The latter is a deprecated method because it leads to confusion and will be 1925 * removed in v2.<br /> 1926 * Additionally, it accepts additions and subtractions between different units. 1927 * Note that multiplications and divisions aren't supported. 1928 * 1929 * Valid examples are: 1930 * ``` 1931 * 10 1932 * '10%' 1933 * '10, 10' 1934 * '10%, 10' 1935 * '10 + 10%' 1936 * '10 - 5vh + 3%' 1937 * '-10px + 5vh, 5px - 6%' 1938 * ``` 1939 * 1940 * @memberof modifiers 1941 * @inner 1942 */ 1943 offset: { 1944 /** @prop {number} order=200 - Index used to define the order of execution */ 1945 order: 200, 1946 /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ 1947 enabled: true, 1948 /** @prop {ModifierFn} */ 1949 fn: offset, 1950 /** @prop {Number|String} offset=0 1951 * The offset value as described in the modifier description 1952 */ 1953 offset: 0 1954 }, 1955 1956 /** 1957 * Modifier used to prevent the popper from being positioned outside the boundary. 1958 * 1959 * An scenario exists where the reference itself is not within the boundaries.<br /> 1960 * We can say it has "escaped the boundaries" ? or just "escaped".<br /> 1961 * In this case we need to decide whether the popper should either: 1962 * 1963 * - detach from the reference and remain "trapped" in the boundaries, or 1964 * - if it should ignore the boundary and "escape with its reference" 1965 * 1966 * When `escapeWithReference` is set to`true` and reference is completely 1967 * outside its boundaries, the popper will overflow (or completely leave) 1968 * the boundaries in order to remain attached to the edge of the reference. 1969 * 1970 * @memberof modifiers 1971 * @inner 1972 */ 1973 preventOverflow: { 1974 /** @prop {number} order=300 - Index used to define the order of execution */ 1975 order: 300, 1976 /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ 1977 enabled: true, 1978 /** @prop {ModifierFn} */ 1979 fn: preventOverflow, 1980 /** 1981 * @prop {Array} [priority=['left','right','top','bottom']] 1982 * Popper will try to prevent overflow following these priorities by default, 1983 * then, it could overflow on the left and on top of the `boundariesElement` 1984 */ 1985 priority: ['left', 'right', 'top', 'bottom'], 1986 /** 1987 * @prop {number} padding=5 1988 * Amount of pixel used to define a minimum distance between the boundaries 1989 * and the popper this makes sure the popper has always a little padding 1990 * between the edges of its container 1991 */ 1992 padding: 5, 1993 /** 1994 * @prop {String|HTMLElement} boundariesElement='scrollParent' 1995 * Boundaries used by the modifier, can be `scrollParent`, `window`, 1996 * `viewport` or any DOM element. 1997 */ 1998 boundariesElement: 'scrollParent' 1999 }, 2000 2001 /** 2002 * Modifier used to make sure the reference and its popper stay near eachothers 2003 * without leaving any gap between the two. Expecially useful when the arrow is 2004 * enabled and you want to assure it to point to its reference element. 2005 * It cares only about the first axis, you can still have poppers with margin 2006 * between the popper and its reference element. 2007 * @memberof modifiers 2008 * @inner 2009 */ 2010 keepTogether: { 2011 /** @prop {number} order=400 - Index used to define the order of execution */ 2012 order: 400, 2013 /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ 2014 enabled: true, 2015 /** @prop {ModifierFn} */ 2016 fn: keepTogether 2017 }, 2018 2019 /** 2020 * This modifier is used to move the `arrowElement` of the popper to make 2021 * sure it is positioned between the reference element and its popper element. 2022 * It will read the outer size of the `arrowElement` node to detect how many 2023 * pixels of conjuction are needed. 2024 * 2025 * It has no effect if no `arrowElement` is provided. 2026 * @memberof modifiers 2027 * @inner 2028 */ 2029 arrow: { 2030 /** @prop {number} order=500 - Index used to define the order of execution */ 2031 order: 500, 2032 /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ 2033 enabled: true, 2034 /** @prop {ModifierFn} */ 2035 fn: arrow, 2036 /** @prop {String|HTMLElement} element='[x-arrow]' - Selector or node used as arrow */ 2037 element: '[x-arrow]' 2038 }, 2039 2040 /** 2041 * Modifier used to flip the popper's placement when it starts to overlap its 2042 * reference element. 2043 * 2044 * Requires the `preventOverflow` modifier before it in order to work. 2045 * 2046 * **NOTE:** this modifier will interrupt the current update cycle and will 2047 * restart it if it detects the need to flip the placement. 2048 * @memberof modifiers 2049 * @inner 2050 */ 2051 flip: { 2052 /** @prop {number} order=600 - Index used to define the order of execution */ 2053 order: 600, 2054 /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ 2055 enabled: true, 2056 /** @prop {ModifierFn} */ 2057 fn: flip, 2058 /** 2059 * @prop {String|Array} behavior='flip' 2060 * The behavior used to change the popper's placement. It can be one of 2061 * `flip`, `clockwise`, `counterclockwise` or an array with a list of valid 2062 * placements (with optional variations). 2063 */ 2064 behavior: 'flip', 2065 /** 2066 * @prop {number} padding=5 2067 * The popper will flip if it hits the edges of the `boundariesElement` 2068 */ 2069 padding: 5, 2070 /** 2071 * @prop {String|HTMLElement} boundariesElement='viewport' 2072 * The element which will define the boundaries of the popper position, 2073 * the popper will never be placed outside of the defined boundaries 2074 * (except if keepTogether is enabled) 2075 */ 2076 boundariesElement: 'viewport' 2077 }, 2078 2079 /** 2080 * Modifier used to make the popper flow toward the inner of the reference element. 2081 * By default, when this modifier is disabled, the popper will be placed outside 2082 * the reference element. 2083 * @memberof modifiers 2084 * @inner 2085 */ 2086 inner: { 2087 /** @prop {number} order=700 - Index used to define the order of execution */ 2088 order: 700, 2089 /** @prop {Boolean} enabled=false - Whether the modifier is enabled or not */ 2090 enabled: false, 2091 /** @prop {ModifierFn} */ 2092 fn: inner 2093 }, 2094 2095 /** 2096 * Modifier used to hide the popper when its reference element is outside of the 2097 * popper boundaries. It will set a `x-out-of-boundaries` attribute which can 2098 * be used to hide with a CSS selector the popper when its reference is 2099 * out of boundaries. 2100 * 2101 * Requires the `preventOverflow` modifier before it in order to work. 2102 * @memberof modifiers 2103 * @inner 2104 */ 2105 hide: { 2106 /** @prop {number} order=800 - Index used to define the order of execution */ 2107 order: 800, 2108 /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ 2109 enabled: true, 2110 /** @prop {ModifierFn} */ 2111 fn: hide 2112 }, 2113 2114 /** 2115 * Computes the style that will be applied to the popper element to gets 2116 * properly positioned. 2117 * 2118 * Note that this modifier will not touch the DOM, it just prepares the styles 2119 * so that `applyStyle` modifier can apply it. This separation is useful 2120 * in case you need to replace `applyStyle` with a custom implementation. 2121 * 2122 * This modifier has `850` as `order` value to maintain backward compatibility 2123 * with previous versions of Popper.js. Expect the modifiers ordering method 2124 * to change in future major versions of the library. 2125 * 2126 * @memberof modifiers 2127 * @inner 2128 */ 2129 computeStyle: { 2130 /** @prop {number} order=850 - Index used to define the order of execution */ 2131 order: 850, 2132 /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ 2133 enabled: true, 2134 /** @prop {ModifierFn} */ 2135 fn: computeStyle, 2136 /** 2137 * @prop {Boolean} gpuAcceleration=true 2138 * If true, it uses the CSS 3d transformation to position the popper. 2139 * Otherwise, it will use the `top` and `left` properties. 2140 */ 2141 gpuAcceleration: true, 2142 /** 2143 * @prop {string} [x='bottom'] 2144 * Where to anchor the X axis (`bottom` or `top`). AKA X offset origin. 2145 * Change this if your popper should grow in a direction different from `bottom` 2146 */ 2147 x: 'bottom', 2148 /** 2149 * @prop {string} [x='left'] 2150 * Where to anchor the Y axis (`left` or `right`). AKA Y offset origin. 2151 * Change this if your popper should grow in a direction different from `right` 2152 */ 2153 y: 'right' 2154 }, 2155 2156 /** 2157 * Applies the computed styles to the popper element. 2158 * 2159 * All the DOM manipulations are limited to this modifier. This is useful in case 2160 * you want to integrate Popper.js inside a framework or view library and you 2161 * want to delegate all the DOM manipulations to it. 2162 * 2163 * Note that if you disable this modifier, you must make sure the popper element 2164 * has its position set to `absolute` before Popper.js can do its work! 2165 * 2166 * Just disable this modifier and define you own to achieve the desired effect. 2167 * 2168 * @memberof modifiers 2169 * @inner 2170 */ 2171 applyStyle: { 2172 /** @prop {number} order=900 - Index used to define the order of execution */ 2173 order: 900, 2174 /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ 2175 enabled: true, 2176 /** @prop {ModifierFn} */
vendor: 4,612 bytes, lines 2177-2308
2177 fn: applyStyle, 2178 /** @prop {Function} */ 2179 onLoad: applyStyleOnLoad, 2180 /** 2181 * @deprecated since version 1.10.0, the property moved to `computeStyle` modifier 2182 * @prop {Boolean} gpuAcceleration=true 2183 * If true, it uses the CSS 3d transformation to position the popper. 2184 * Otherwise, it will use the `top` and `left` properties. 2185 */ 2186 gpuAcceleration: undefined 2187 } 2188}; 2189 2190/** 2191 * The `dataObject` is an object containing all the informations used by Popper.js 2192 * this object get passed to modifiers and to the `onCreate` and `onUpdate` callbacks. 2193 * @name dataObject 2194 * @property {Object} data.instance The Popper.js instance 2195 * @property {String} data.placement Placement applied to popper 2196 * @property {String} data.originalPlacement Placement originally defined on init 2197 * @property {Boolean} data.flipped True if popper has been flipped by flip modifier 2198 * @property {Boolean} data.hide True if the reference element is out of boundaries, useful to know when to hide the popper. 2199 * @property {HTMLElement} data.arrowElement Node used as arrow by arrow modifier 2200 * @property {Object} data.styles Any CSS property defined here will be applied to the popper, it expects the JavaScript nomenclature (eg. `marginBottom`) 2201 * @property {Object} data.boundaries Offsets of the popper boundaries 2202 * @property {Object} data.offsets The measurements of popper, reference and arrow elements. 2203 * @property {Object} data.offsets.popper `top`, `left`, `width`, `height` values 2204 * @property {Object} data.offsets.reference `top`, `left`, `width`, `height` values 2205 * @property {Object} data.offsets.arrow] `top` and `left` offsets, only one of them will be different from 0 2206 */ 2207 2208/** 2209 * Default options provided to Popper.js constructor.<br /> 2210 * These can be overriden using the `options` argument of Popper.js.<br /> 2211 * To override an option, simply pass as 3rd argument an object with the same 2212 * structure of this object, example: 2213 * ``` 2214 * new Popper(ref, pop, { 2215 * modifiers: { 2216 * preventOverflow: { enabled: false } 2217 * } 2218 * }) 2219 * ``` 2220 * @type {Object} 2221 * @static 2222 * @memberof Popper 2223 */ 2224var Defaults = { 2225 /** 2226 * Popper's placement 2227 * @prop {Popper.placements} placement='bottom' 2228 */ 2229 placement: 'bottom', 2230 2231 /** 2232 * Whether events (resize, scroll) are initially enabled 2233 * @prop {Boolean} eventsEnabled=true 2234 */ 2235 eventsEnabled: true, 2236 2237 /** 2238 * Set to true if you want to automatically remove the popper when 2239 * you call the `destroy` method. 2240 * @prop {Boolean} removeOnDestroy=false 2241 */ 2242 removeOnDestroy: false, 2243 2244 /** 2245 * Callback called when the popper is created.<br /> 2246 * By default, is set to no-op.<br /> 2247 * Access Popper.js instance with `data.instance`. 2248 * @prop {onCreate} 2249 */ 2250 onCreate: function onCreate() {}, 2251 2252 /** 2253 * Callback called when the popper is updated, this callback is not called 2254 * on the initialization/creation of the popper, but only on subsequent 2255 * updates.<br /> 2256 * By default, is set to no-op.<br /> 2257 * Access Popper.js instance with `data.instance`. 2258 * @prop {onUpdate} 2259 */ 2260 onUpdate: function onUpdate() {}, 2261 2262 /** 2263 * List of modifiers used to modify the offsets before they are applied to the popper. 2264 * They provide most of the functionalities of Popper.js 2265 * @prop {modifiers} 2266 */ 2267 modifiers: modifiers 2268}; 2269 2270/** 2271 * @callback onCreate 2272 * @param {dataObject} data 2273 */ 2274 2275/** 2276 * @callback onUpdate 2277 * @param {dataObject} data 2278 */ 2279 2280// Utils 2281// Methods 2282var Popper = function () { 2283 /** 2284 * Create a new Popper.js instance 2285 * @class Popper 2286 * @param {HTMLElement|referenceObject} reference - The reference element used to position the popper 2287 * @param {HTMLElement} popper - The HTML element used as popper. 2288 * @param {Object} options - Your custom options to override the ones defined in [Defaults](#defaults) 2289 * @return {Object} instance - The generated Popper.js instance 2290 */ 2291 function Popper(reference, popper) { 2292 var _this = this; 2293 2294 var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; 2295 classCallCheck(this, Popper); 2296 2297 this.scheduleUpdate = function () { 2298 return requestAnimationFrame(_this.update); 2299 }; 2300 2301 // make update() debounced, so that it only runs at most once-per-tick 2302 this.update = debounce(this.update.bind(this)); 2303 2304 // with {} we create a new object with the options inside it 2305 this.options = _extends({}, Popper.Defaults, options); 2306 2307 // init state 2308 this.state = {
vendor: 4,458 bytes, lines 2309-2438
2309 isDestroyed: false, 2310 isCreated: false, 2311 scrollParents: [] 2312 }; 2313 2314 // get reference and popper elements (allow jQuery wrappers) 2315 this.reference = reference.jquery ? reference[0] : reference; 2316 this.popper = popper.jquery ? popper[0] : popper; 2317 2318 // Deep merge modifiers options 2319 this.options.modifiers = {}; 2320 Object.keys(_extends({}, Popper.Defaults.modifiers, options.modifiers)).forEach(function (name) { 2321 _this.options.modifiers[name] = _extends({}, Popper.Defaults.modifiers[name] || {}, options.modifiers ? options.modifiers[name] : {}); 2322 }); 2323 2324 // Refactoring modifiers' list (Object => Array) 2325 this.modifiers = Object.keys(this.options.modifiers).map(function (name) { 2326 return _extends({ 2327 name: name 2328 }, _this.options.modifiers[name]); 2329 }) 2330 // sort the modifiers by order 2331 .sort(function (a, b) { 2332 return a.order - b.order; 2333 }); 2334 2335 // modifiers have the ability to execute arbitrary code when Popper.js get inited 2336 // such code is executed in the same order of its modifier 2337 // they could add new properties to their options configuration 2338 // BE AWARE: don't add options to `options.modifiers.name` but to `modifierOptions`! 2339 this.modifiers.forEach(function (modifierOptions) { 2340 if (modifierOptions.enabled && isFunction(modifierOptions.onLoad)) { 2341 modifierOptions.onLoad(_this.reference, _this.popper, _this.options, modifierOptions, _this.state); 2342 } 2343 }); 2344 2345 // fire the first update to position the popper in the right place 2346 this.update(); 2347 2348 var eventsEnabled = this.options.eventsEnabled; 2349 if (eventsEnabled) { 2350 // setup event listeners, they will take care of update the position in specific situations 2351 this.enableEventListeners(); 2352 } 2353 2354 this.state.eventsEnabled = eventsEnabled; 2355 } 2356 2357 // We can't use class properties because they don't get listed in the 2358 // class prototype and break stuff like Sinon stubs 2359 2360 2361 createClass(Popper, [{ 2362 key: 'update', 2363 value: function update$$1() { 2364 return update.call(this); 2365 } 2366 }, { 2367 key: 'destroy', 2368 value: function destroy$$1() { 2369 return destroy.call(this); 2370 } 2371 }, { 2372 key: 'enableEventListeners', 2373 value: function enableEventListeners$$1() { 2374 return enableEventListeners.call(this); 2375 } 2376 }, { 2377 key: 'disableEventListeners', 2378 value: function disableEventListeners$$1() { 2379 return disableEventListeners.call(this); 2380 } 2381 2382 /** 2383 * Schedule an update, it will run on the next UI update available 2384 * @method scheduleUpdate 2385 * @memberof Popper 2386 */ 2387 2388 2389 /** 2390 * Collection of utilities useful when writing custom modifiers. 2391 * Starting from version 1.7, this method is available only if you 2392 * include `popper-utils.js` before `popper.js`. 2393 * 2394 * **DEPRECATION**: This way to access PopperUtils is deprecated 2395 * and will be removed in v2! Use the PopperUtils module directly instead. 2396 * Due to the high instability of the methods contained in Utils, we can't 2397 * guarantee them to follow semver. Use them at your own risk! 2398 * @static 2399 * @private 2400 * @type {Object} 2401 * @deprecated since version 1.8 2402 * @member Utils 2403 * @memberof Popper 2404 */ 2405 2406 }]); 2407 return Popper; 2408}(); 2409 2410/** 2411 * The `referenceObject` is an object that provides an interface compatible with Popper.js 2412 * and lets you use it as replacement of a real DOM node.<br /> 2413 * You can use this method to position a popper relatively to a set of coordinates 2414 * in case you don't have a DOM node to use as reference. 2415 * 2416 * ``` 2417 * new Popper(referenceObject, popperNode); 2418 * ``` 2419 * 2420 * NB: This feature isn't supported in Internet Explorer 10 2421 * @name referenceObject 2422 * @property {Function} data.getBoundingClientRect 2423 * A function that returns a set of coordinates compatible with the native `getBoundingClientRect` method. 2424 * @property {number} data.clientWidth 2425 * An ES6 getter that will return the width of the virtual reference element. 2426 * @property {number} data.clientHeight 2427 * An ES6 getter that will return the height of the virtual reference element. 2428 */ 2429 2430 2431Popper.Utils = (typeof window !== 'undefined' ? window : global).PopperUtils; 2432Popper.placements = placements; 2433Popper.Defaults = Defaults; 2434 2435return Popper; 2436 2437}))); 2438//# 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.