An unfinished system to manage all your paper documentation in an easy way.
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

popper.js 86KB

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