Built files from Bizgaze WebServer
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

popper-utils.js 36KB

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