tether.js 55 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807
  1. /*! tether 1.3.7 */
  2. (function(root, factory) {
  3. if (typeof define === 'function' && define.amd) {
  4. define(factory);
  5. } else if (typeof exports === 'object') {
  6. module.exports = factory(require, exports, module);
  7. } else {
  8. root.Tether = factory();
  9. }
  10. }(this, function(require, exports, module) {
  11. 'use strict';
  12. var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
  13. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
  14. var TetherBase = undefined;
  15. if (typeof TetherBase === 'undefined') {
  16. TetherBase = { modules: [] };
  17. }
  18. var zeroElement = null;
  19. // Same as native getBoundingClientRect, except it takes into account parent <frame> offsets
  20. // if the element lies within a nested document (<frame> or <iframe>-like).
  21. function getActualBoundingClientRect(node) {
  22. var boundingRect = node.getBoundingClientRect();
  23. // The original object returned by getBoundingClientRect is immutable, so we clone it
  24. // We can't use extend because the properties are not considered part of the object by hasOwnProperty in IE9
  25. var rect = {};
  26. for (var k in boundingRect) {
  27. rect[k] = boundingRect[k];
  28. }
  29. if (node.ownerDocument !== document) {
  30. var _frameElement = node.ownerDocument.defaultView.frameElement;
  31. if (_frameElement) {
  32. var frameRect = getActualBoundingClientRect(_frameElement);
  33. rect.top += frameRect.top;
  34. rect.bottom += frameRect.top;
  35. rect.left += frameRect.left;
  36. rect.right += frameRect.left;
  37. }
  38. }
  39. return rect;
  40. }
  41. function getScrollParents(el) {
  42. // In firefox if the el is inside an iframe with display: none; window.getComputedStyle() will return null;
  43. // https://bugzilla.mozilla.org/show_bug.cgi?id=548397
  44. var computedStyle = getComputedStyle(el) || {};
  45. var position = computedStyle.position;
  46. var parents = [];
  47. if (position === 'fixed') {
  48. return [el];
  49. }
  50. var parent = el;
  51. while ((parent = parent.parentNode) && parent && parent.nodeType === 1) {
  52. var style = undefined;
  53. try {
  54. style = getComputedStyle(parent);
  55. } catch (err) {}
  56. if (typeof style === 'undefined' || style === null) {
  57. parents.push(parent);
  58. return parents;
  59. }
  60. var _style = style;
  61. var overflow = _style.overflow;
  62. var overflowX = _style.overflowX;
  63. var overflowY = _style.overflowY;
  64. if (/(auto|scroll)/.test(overflow + overflowY + overflowX)) {
  65. if (position !== 'absolute' || ['relative', 'absolute', 'fixed'].indexOf(style.position) >= 0) {
  66. parents.push(parent);
  67. }
  68. }
  69. }
  70. parents.push(el.ownerDocument.body);
  71. // If the node is within a frame, account for the parent window scroll
  72. if (el.ownerDocument !== document) {
  73. parents.push(el.ownerDocument.defaultView);
  74. }
  75. return parents;
  76. }
  77. var uniqueId = (function () {
  78. var id = 0;
  79. return function () {
  80. return ++id;
  81. };
  82. })();
  83. var zeroPosCache = {};
  84. var getOrigin = function getOrigin() {
  85. // getBoundingClientRect is unfortunately too accurate. It introduces a pixel or two of
  86. // jitter as the user scrolls that messes with our ability to detect if two positions
  87. // are equivilant or not. We place an element at the top left of the page that will
  88. // get the same jitter, so we can cancel the two out.
  89. var node = zeroElement;
  90. if (!node) {
  91. node = document.createElement('div');
  92. node.setAttribute('data-tether-id', uniqueId());
  93. extend(node.style, {
  94. top: 0,
  95. left: 0,
  96. position: 'absolute'
  97. });
  98. document.body.appendChild(node);
  99. zeroElement = node;
  100. }
  101. var id = node.getAttribute('data-tether-id');
  102. if (typeof zeroPosCache[id] === 'undefined') {
  103. zeroPosCache[id] = getActualBoundingClientRect(node);
  104. // Clear the cache when this position call is done
  105. defer(function () {
  106. delete zeroPosCache[id];
  107. });
  108. }
  109. return zeroPosCache[id];
  110. };
  111. function removeUtilElements() {
  112. if (zeroElement) {
  113. document.body.removeChild(zeroElement);
  114. }
  115. zeroElement = null;
  116. };
  117. function getBounds(el) {
  118. var doc = undefined;
  119. if (el === document) {
  120. doc = document;
  121. el = document.documentElement;
  122. } else {
  123. doc = el.ownerDocument;
  124. }
  125. var docEl = doc.documentElement;
  126. var box = getActualBoundingClientRect(el);
  127. var origin = getOrigin();
  128. box.top -= origin.top;
  129. box.left -= origin.left;
  130. if (typeof box.width === 'undefined') {
  131. box.width = document.body.scrollWidth - box.left - box.right;
  132. }
  133. if (typeof box.height === 'undefined') {
  134. box.height = document.body.scrollHeight - box.top - box.bottom;
  135. }
  136. box.top = box.top - docEl.clientTop;
  137. box.left = box.left - docEl.clientLeft;
  138. box.right = doc.body.clientWidth - box.width - box.left;
  139. box.bottom = doc.body.clientHeight - box.height - box.top;
  140. return box;
  141. }
  142. function getOffsetParent(el) {
  143. return el.offsetParent || document.documentElement;
  144. }
  145. var _scrollBarSize = null;
  146. function getScrollBarSize() {
  147. if (_scrollBarSize) {
  148. return _scrollBarSize;
  149. }
  150. var inner = document.createElement('div');
  151. inner.style.width = '100%';
  152. inner.style.height = '200px';
  153. var outer = document.createElement('div');
  154. extend(outer.style, {
  155. position: 'absolute',
  156. top: 0,
  157. left: 0,
  158. pointerEvents: 'none',
  159. visibility: 'hidden',
  160. width: '200px',
  161. height: '150px',
  162. overflow: 'hidden'
  163. });
  164. outer.appendChild(inner);
  165. document.body.appendChild(outer);
  166. var widthContained = inner.offsetWidth;
  167. outer.style.overflow = 'scroll';
  168. var widthScroll = inner.offsetWidth;
  169. if (widthContained === widthScroll) {
  170. widthScroll = outer.clientWidth;
  171. }
  172. document.body.removeChild(outer);
  173. var width = widthContained - widthScroll;
  174. _scrollBarSize = { width: width, height: width };
  175. return _scrollBarSize;
  176. }
  177. function extend() {
  178. var out = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
  179. var args = [];
  180. Array.prototype.push.apply(args, arguments);
  181. args.slice(1).forEach(function (obj) {
  182. if (obj) {
  183. for (var key in obj) {
  184. if (({}).hasOwnProperty.call(obj, key)) {
  185. out[key] = obj[key];
  186. }
  187. }
  188. }
  189. });
  190. return out;
  191. }
  192. function removeClass(el, name) {
  193. if (typeof el.classList !== 'undefined') {
  194. name.split(' ').forEach(function (cls) {
  195. if (cls.trim()) {
  196. el.classList.remove(cls);
  197. }
  198. });
  199. } else {
  200. var regex = new RegExp('(^| )' + name.split(' ').join('|') + '( |$)', 'gi');
  201. var className = getClassName(el).replace(regex, ' ');
  202. setClassName(el, className);
  203. }
  204. }
  205. function addClass(el, name) {
  206. if (typeof el.classList !== 'undefined') {
  207. name.split(' ').forEach(function (cls) {
  208. if (cls.trim()) {
  209. el.classList.add(cls);
  210. }
  211. });
  212. } else {
  213. removeClass(el, name);
  214. var cls = getClassName(el) + (' ' + name);
  215. setClassName(el, cls);
  216. }
  217. }
  218. function hasClass(el, name) {
  219. if (typeof el.classList !== 'undefined') {
  220. return el.classList.contains(name);
  221. }
  222. var className = getClassName(el);
  223. return new RegExp('(^| )' + name + '( |$)', 'gi').test(className);
  224. }
  225. function getClassName(el) {
  226. // Can't use just SVGAnimatedString here since nodes within a Frame in IE have
  227. // completely separately SVGAnimatedString base classes
  228. if (el.className instanceof el.ownerDocument.defaultView.SVGAnimatedString) {
  229. return el.className.baseVal;
  230. }
  231. return el.className;
  232. }
  233. function setClassName(el, className) {
  234. el.setAttribute('class', className);
  235. }
  236. function updateClasses(el, add, all) {
  237. // Of the set of 'all' classes, we need the 'add' classes, and only the
  238. // 'add' classes to be set.
  239. all.forEach(function (cls) {
  240. if (add.indexOf(cls) === -1 && hasClass(el, cls)) {
  241. removeClass(el, cls);
  242. }
  243. });
  244. add.forEach(function (cls) {
  245. if (!hasClass(el, cls)) {
  246. addClass(el, cls);
  247. }
  248. });
  249. }
  250. var deferred = [];
  251. var defer = function defer(fn) {
  252. deferred.push(fn);
  253. };
  254. var flush = function flush() {
  255. var fn = undefined;
  256. while (fn = deferred.pop()) {
  257. fn();
  258. }
  259. };
  260. var Evented = (function () {
  261. function Evented() {
  262. _classCallCheck(this, Evented);
  263. }
  264. _createClass(Evented, [{
  265. key: 'on',
  266. value: function on(event, handler, ctx) {
  267. var once = arguments.length <= 3 || arguments[3] === undefined ? false : arguments[3];
  268. if (typeof this.bindings === 'undefined') {
  269. this.bindings = {};
  270. }
  271. if (typeof this.bindings[event] === 'undefined') {
  272. this.bindings[event] = [];
  273. }
  274. this.bindings[event].push({ handler: handler, ctx: ctx, once: once });
  275. }
  276. }, {
  277. key: 'once',
  278. value: function once(event, handler, ctx) {
  279. this.on(event, handler, ctx, true);
  280. }
  281. }, {
  282. key: 'off',
  283. value: function off(event, handler) {
  284. if (typeof this.bindings === 'undefined' || typeof this.bindings[event] === 'undefined') {
  285. return;
  286. }
  287. if (typeof handler === 'undefined') {
  288. delete this.bindings[event];
  289. } else {
  290. var i = 0;
  291. while (i < this.bindings[event].length) {
  292. if (this.bindings[event][i].handler === handler) {
  293. this.bindings[event].splice(i, 1);
  294. } else {
  295. ++i;
  296. }
  297. }
  298. }
  299. }
  300. }, {
  301. key: 'trigger',
  302. value: function trigger(event) {
  303. if (typeof this.bindings !== 'undefined' && this.bindings[event]) {
  304. var i = 0;
  305. for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
  306. args[_key - 1] = arguments[_key];
  307. }
  308. while (i < this.bindings[event].length) {
  309. var _bindings$event$i = this.bindings[event][i];
  310. var handler = _bindings$event$i.handler;
  311. var ctx = _bindings$event$i.ctx;
  312. var once = _bindings$event$i.once;
  313. var context = ctx;
  314. if (typeof context === 'undefined') {
  315. context = this;
  316. }
  317. handler.apply(context, args);
  318. if (once) {
  319. this.bindings[event].splice(i, 1);
  320. } else {
  321. ++i;
  322. }
  323. }
  324. }
  325. }
  326. }]);
  327. return Evented;
  328. })();
  329. TetherBase.Utils = {
  330. getActualBoundingClientRect: getActualBoundingClientRect,
  331. getScrollParents: getScrollParents,
  332. getBounds: getBounds,
  333. getOffsetParent: getOffsetParent,
  334. extend: extend,
  335. addClass: addClass,
  336. removeClass: removeClass,
  337. hasClass: hasClass,
  338. updateClasses: updateClasses,
  339. defer: defer,
  340. flush: flush,
  341. uniqueId: uniqueId,
  342. Evented: Evented,
  343. getScrollBarSize: getScrollBarSize,
  344. removeUtilElements: removeUtilElements
  345. };
  346. /* globals TetherBase, performance */
  347. 'use strict';
  348. var _slicedToArray = (function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i['return']) _i['return'](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError('Invalid attempt to destructure non-iterable instance'); } }; })();
  349. var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
  350. var _get = function get(_x6, _x7, _x8) { var _again = true; _function: while (_again) { var object = _x6, property = _x7, receiver = _x8; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x6 = parent; _x7 = property; _x8 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
  351. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
  352. function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
  353. if (typeof TetherBase === 'undefined') {
  354. throw new Error('You must include the utils.js file before tether.js');
  355. }
  356. var _TetherBase$Utils = TetherBase.Utils;
  357. var getScrollParents = _TetherBase$Utils.getScrollParents;
  358. var getBounds = _TetherBase$Utils.getBounds;
  359. var getOffsetParent = _TetherBase$Utils.getOffsetParent;
  360. var extend = _TetherBase$Utils.extend;
  361. var addClass = _TetherBase$Utils.addClass;
  362. var removeClass = _TetherBase$Utils.removeClass;
  363. var updateClasses = _TetherBase$Utils.updateClasses;
  364. var defer = _TetherBase$Utils.defer;
  365. var flush = _TetherBase$Utils.flush;
  366. var getScrollBarSize = _TetherBase$Utils.getScrollBarSize;
  367. var removeUtilElements = _TetherBase$Utils.removeUtilElements;
  368. function within(a, b) {
  369. var diff = arguments.length <= 2 || arguments[2] === undefined ? 1 : arguments[2];
  370. return a + diff >= b && b >= a - diff;
  371. }
  372. var transformKey = (function () {
  373. if (typeof document === 'undefined') {
  374. return '';
  375. }
  376. var el = document.createElement('div');
  377. var transforms = ['transform', 'WebkitTransform', 'OTransform', 'MozTransform', 'msTransform'];
  378. for (var i = 0; i < transforms.length; ++i) {
  379. var key = transforms[i];
  380. if (el.style[key] !== undefined) {
  381. return key;
  382. }
  383. }
  384. })();
  385. var tethers = [];
  386. var position = function position() {
  387. tethers.forEach(function (tether) {
  388. tether.position(false);
  389. });
  390. flush();
  391. };
  392. function now() {
  393. if (typeof performance !== 'undefined' && typeof performance.now !== 'undefined') {
  394. return performance.now();
  395. }
  396. return +new Date();
  397. }
  398. (function () {
  399. var lastCall = null;
  400. var lastDuration = null;
  401. var pendingTimeout = null;
  402. var tick = function tick() {
  403. if (typeof lastDuration !== 'undefined' && lastDuration > 16) {
  404. // We voluntarily throttle ourselves if we can't manage 60fps
  405. lastDuration = Math.min(lastDuration - 16, 250);
  406. // Just in case this is the last event, remember to position just once more
  407. pendingTimeout = setTimeout(tick, 250);
  408. return;
  409. }
  410. if (typeof lastCall !== 'undefined' && now() - lastCall < 10) {
  411. // Some browsers call events a little too frequently, refuse to run more than is reasonable
  412. return;
  413. }
  414. if (pendingTimeout != null) {
  415. clearTimeout(pendingTimeout);
  416. pendingTimeout = null;
  417. }
  418. lastCall = now();
  419. position();
  420. lastDuration = now() - lastCall;
  421. };
  422. if (typeof window !== 'undefined' && typeof window.addEventListener !== 'undefined') {
  423. ['resize', 'scroll', 'touchmove'].forEach(function (event) {
  424. window.addEventListener(event, tick);
  425. });
  426. }
  427. })();
  428. var MIRROR_LR = {
  429. center: 'center',
  430. left: 'right',
  431. right: 'left'
  432. };
  433. var MIRROR_TB = {
  434. middle: 'middle',
  435. top: 'bottom',
  436. bottom: 'top'
  437. };
  438. var OFFSET_MAP = {
  439. top: 0,
  440. left: 0,
  441. middle: '50%',
  442. center: '50%',
  443. bottom: '100%',
  444. right: '100%'
  445. };
  446. var autoToFixedAttachment = function autoToFixedAttachment(attachment, relativeToAttachment) {
  447. var left = attachment.left;
  448. var top = attachment.top;
  449. if (left === 'auto') {
  450. left = MIRROR_LR[relativeToAttachment.left];
  451. }
  452. if (top === 'auto') {
  453. top = MIRROR_TB[relativeToAttachment.top];
  454. }
  455. return { left: left, top: top };
  456. };
  457. var attachmentToOffset = function attachmentToOffset(attachment) {
  458. var left = attachment.left;
  459. var top = attachment.top;
  460. if (typeof OFFSET_MAP[attachment.left] !== 'undefined') {
  461. left = OFFSET_MAP[attachment.left];
  462. }
  463. if (typeof OFFSET_MAP[attachment.top] !== 'undefined') {
  464. top = OFFSET_MAP[attachment.top];
  465. }
  466. return { left: left, top: top };
  467. };
  468. function addOffset() {
  469. var out = { top: 0, left: 0 };
  470. for (var _len = arguments.length, offsets = Array(_len), _key = 0; _key < _len; _key++) {
  471. offsets[_key] = arguments[_key];
  472. }
  473. offsets.forEach(function (_ref) {
  474. var top = _ref.top;
  475. var left = _ref.left;
  476. if (typeof top === 'string') {
  477. top = parseFloat(top, 10);
  478. }
  479. if (typeof left === 'string') {
  480. left = parseFloat(left, 10);
  481. }
  482. out.top += top;
  483. out.left += left;
  484. });
  485. return out;
  486. }
  487. function offsetToPx(offset, size) {
  488. if (typeof offset.left === 'string' && offset.left.indexOf('%') !== -1) {
  489. offset.left = parseFloat(offset.left, 10) / 100 * size.width;
  490. }
  491. if (typeof offset.top === 'string' && offset.top.indexOf('%') !== -1) {
  492. offset.top = parseFloat(offset.top, 10) / 100 * size.height;
  493. }
  494. return offset;
  495. }
  496. var parseOffset = function parseOffset(value) {
  497. var _value$split = value.split(' ');
  498. var _value$split2 = _slicedToArray(_value$split, 2);
  499. var top = _value$split2[0];
  500. var left = _value$split2[1];
  501. return { top: top, left: left };
  502. };
  503. var parseAttachment = parseOffset;
  504. var TetherClass = (function (_Evented) {
  505. _inherits(TetherClass, _Evented);
  506. function TetherClass(options) {
  507. var _this = this;
  508. _classCallCheck(this, TetherClass);
  509. _get(Object.getPrototypeOf(TetherClass.prototype), 'constructor', this).call(this);
  510. this.position = this.position.bind(this);
  511. tethers.push(this);
  512. this.history = [];
  513. this.setOptions(options, false);
  514. TetherBase.modules.forEach(function (module) {
  515. if (typeof module.initialize !== 'undefined') {
  516. module.initialize.call(_this);
  517. }
  518. });
  519. this.position();
  520. }
  521. _createClass(TetherClass, [{
  522. key: 'getClass',
  523. value: function getClass() {
  524. var key = arguments.length <= 0 || arguments[0] === undefined ? '' : arguments[0];
  525. var classes = this.options.classes;
  526. if (typeof classes !== 'undefined' && classes[key]) {
  527. return this.options.classes[key];
  528. } else if (this.options.classPrefix) {
  529. return this.options.classPrefix + '-' + key;
  530. } else {
  531. return key;
  532. }
  533. }
  534. }, {
  535. key: 'setOptions',
  536. value: function setOptions(options) {
  537. var _this2 = this;
  538. var pos = arguments.length <= 1 || arguments[1] === undefined ? true : arguments[1];
  539. var defaults = {
  540. offset: '0 0',
  541. targetOffset: '0 0',
  542. targetAttachment: 'auto auto',
  543. classPrefix: 'tether'
  544. };
  545. this.options = extend(defaults, options);
  546. var _options = this.options;
  547. var element = _options.element;
  548. var target = _options.target;
  549. var targetModifier = _options.targetModifier;
  550. this.element = element;
  551. this.target = target;
  552. this.targetModifier = targetModifier;
  553. if (this.target === 'viewport') {
  554. this.target = document.body;
  555. this.targetModifier = 'visible';
  556. } else if (this.target === 'scroll-handle') {
  557. this.target = document.body;
  558. this.targetModifier = 'scroll-handle';
  559. }
  560. ['element', 'target'].forEach(function (key) {
  561. if (typeof _this2[key] === 'undefined') {
  562. throw new Error('Tether Error: Both element and target must be defined');
  563. }
  564. if (typeof _this2[key].jquery !== 'undefined') {
  565. _this2[key] = _this2[key][0];
  566. } else if (typeof _this2[key] === 'string') {
  567. _this2[key] = document.querySelector(_this2[key]);
  568. }
  569. });
  570. addClass(this.element, this.getClass('element'));
  571. if (!(this.options.addTargetClasses === false)) {
  572. addClass(this.target, this.getClass('target'));
  573. }
  574. if (!this.options.attachment) {
  575. throw new Error('Tether Error: You must provide an attachment');
  576. }
  577. this.targetAttachment = parseAttachment(this.options.targetAttachment);
  578. this.attachment = parseAttachment(this.options.attachment);
  579. this.offset = parseOffset(this.options.offset);
  580. this.targetOffset = parseOffset(this.options.targetOffset);
  581. if (typeof this.scrollParents !== 'undefined') {
  582. this.disable();
  583. }
  584. if (this.targetModifier === 'scroll-handle') {
  585. this.scrollParents = [this.target];
  586. } else {
  587. this.scrollParents = getScrollParents(this.target);
  588. }
  589. if (!(this.options.enabled === false)) {
  590. this.enable(pos);
  591. }
  592. }
  593. }, {
  594. key: 'getTargetBounds',
  595. value: function getTargetBounds() {
  596. if (typeof this.targetModifier !== 'undefined') {
  597. if (this.targetModifier === 'visible') {
  598. if (this.target === document.body) {
  599. return { top: pageYOffset, left: pageXOffset, height: innerHeight, width: innerWidth };
  600. } else {
  601. var bounds = getBounds(this.target);
  602. var out = {
  603. height: bounds.height,
  604. width: bounds.width,
  605. top: bounds.top,
  606. left: bounds.left
  607. };
  608. out.height = Math.min(out.height, bounds.height - (pageYOffset - bounds.top));
  609. out.height = Math.min(out.height, bounds.height - (bounds.top + bounds.height - (pageYOffset + innerHeight)));
  610. out.height = Math.min(innerHeight, out.height);
  611. out.height -= 2;
  612. out.width = Math.min(out.width, bounds.width - (pageXOffset - bounds.left));
  613. out.width = Math.min(out.width, bounds.width - (bounds.left + bounds.width - (pageXOffset + innerWidth)));
  614. out.width = Math.min(innerWidth, out.width);
  615. out.width -= 2;
  616. if (out.top < pageYOffset) {
  617. out.top = pageYOffset;
  618. }
  619. if (out.left < pageXOffset) {
  620. out.left = pageXOffset;
  621. }
  622. return out;
  623. }
  624. } else if (this.targetModifier === 'scroll-handle') {
  625. var bounds = undefined;
  626. var target = this.target;
  627. if (target === document.body) {
  628. target = document.documentElement;
  629. bounds = {
  630. left: pageXOffset,
  631. top: pageYOffset,
  632. height: innerHeight,
  633. width: innerWidth
  634. };
  635. } else {
  636. bounds = getBounds(target);
  637. }
  638. var style = getComputedStyle(target);
  639. var hasBottomScroll = target.scrollWidth > target.clientWidth || [style.overflow, style.overflowX].indexOf('scroll') >= 0 || this.target !== document.body;
  640. var scrollBottom = 0;
  641. if (hasBottomScroll) {
  642. scrollBottom = 15;
  643. }
  644. var height = bounds.height - parseFloat(style.borderTopWidth) - parseFloat(style.borderBottomWidth) - scrollBottom;
  645. var out = {
  646. width: 15,
  647. height: height * 0.975 * (height / target.scrollHeight),
  648. left: bounds.left + bounds.width - parseFloat(style.borderLeftWidth) - 15
  649. };
  650. var fitAdj = 0;
  651. if (height < 408 && this.target === document.body) {
  652. fitAdj = -0.00011 * Math.pow(height, 2) - 0.00727 * height + 22.58;
  653. }
  654. if (this.target !== document.body) {
  655. out.height = Math.max(out.height, 24);
  656. }
  657. var scrollPercentage = this.target.scrollTop / (target.scrollHeight - height);
  658. out.top = scrollPercentage * (height - out.height - fitAdj) + bounds.top + parseFloat(style.borderTopWidth);
  659. if (this.target === document.body) {
  660. out.height = Math.max(out.height, 24);
  661. }
  662. return out;
  663. }
  664. } else {
  665. return getBounds(this.target);
  666. }
  667. }
  668. }, {
  669. key: 'clearCache',
  670. value: function clearCache() {
  671. this._cache = {};
  672. }
  673. }, {
  674. key: 'cache',
  675. value: function cache(k, getter) {
  676. // More than one module will often need the same DOM info, so
  677. // we keep a cache which is cleared on each position call
  678. if (typeof this._cache === 'undefined') {
  679. this._cache = {};
  680. }
  681. if (typeof this._cache[k] === 'undefined') {
  682. this._cache[k] = getter.call(this);
  683. }
  684. return this._cache[k];
  685. }
  686. }, {
  687. key: 'enable',
  688. value: function enable() {
  689. var _this3 = this;
  690. var pos = arguments.length <= 0 || arguments[0] === undefined ? true : arguments[0];
  691. if (!(this.options.addTargetClasses === false)) {
  692. addClass(this.target, this.getClass('enabled'));
  693. }
  694. addClass(this.element, this.getClass('enabled'));
  695. this.enabled = true;
  696. this.scrollParents.forEach(function (parent) {
  697. if (parent !== _this3.target.ownerDocument) {
  698. parent.addEventListener('scroll', _this3.position);
  699. }
  700. });
  701. if (pos) {
  702. this.position();
  703. }
  704. }
  705. }, {
  706. key: 'disable',
  707. value: function disable() {
  708. var _this4 = this;
  709. removeClass(this.target, this.getClass('enabled'));
  710. removeClass(this.element, this.getClass('enabled'));
  711. this.enabled = false;
  712. if (typeof this.scrollParents !== 'undefined') {
  713. this.scrollParents.forEach(function (parent) {
  714. parent.removeEventListener('scroll', _this4.position);
  715. });
  716. }
  717. }
  718. }, {
  719. key: 'destroy',
  720. value: function destroy() {
  721. var _this5 = this;
  722. this.disable();
  723. tethers.forEach(function (tether, i) {
  724. if (tether === _this5) {
  725. tethers.splice(i, 1);
  726. }
  727. });
  728. // Remove any elements we were using for convenience from the DOM
  729. if (tethers.length === 0) {
  730. removeUtilElements();
  731. }
  732. }
  733. }, {
  734. key: 'updateAttachClasses',
  735. value: function updateAttachClasses(elementAttach, targetAttach) {
  736. var _this6 = this;
  737. elementAttach = elementAttach || this.attachment;
  738. targetAttach = targetAttach || this.targetAttachment;
  739. var sides = ['left', 'top', 'bottom', 'right', 'middle', 'center'];
  740. if (typeof this._addAttachClasses !== 'undefined' && this._addAttachClasses.length) {
  741. // updateAttachClasses can be called more than once in a position call, so
  742. // we need to clean up after ourselves such that when the last defer gets
  743. // ran it doesn't add any extra classes from previous calls.
  744. this._addAttachClasses.splice(0, this._addAttachClasses.length);
  745. }
  746. if (typeof this._addAttachClasses === 'undefined') {
  747. this._addAttachClasses = [];
  748. }
  749. var add = this._addAttachClasses;
  750. if (elementAttach.top) {
  751. add.push(this.getClass('element-attached') + '-' + elementAttach.top);
  752. }
  753. if (elementAttach.left) {
  754. add.push(this.getClass('element-attached') + '-' + elementAttach.left);
  755. }
  756. if (targetAttach.top) {
  757. add.push(this.getClass('target-attached') + '-' + targetAttach.top);
  758. }
  759. if (targetAttach.left) {
  760. add.push(this.getClass('target-attached') + '-' + targetAttach.left);
  761. }
  762. var all = [];
  763. sides.forEach(function (side) {
  764. all.push(_this6.getClass('element-attached') + '-' + side);
  765. all.push(_this6.getClass('target-attached') + '-' + side);
  766. });
  767. defer(function () {
  768. if (!(typeof _this6._addAttachClasses !== 'undefined')) {
  769. return;
  770. }
  771. updateClasses(_this6.element, _this6._addAttachClasses, all);
  772. if (!(_this6.options.addTargetClasses === false)) {
  773. updateClasses(_this6.target, _this6._addAttachClasses, all);
  774. }
  775. delete _this6._addAttachClasses;
  776. });
  777. }
  778. }, {
  779. key: 'position',
  780. value: function position() {
  781. var _this7 = this;
  782. var flushChanges = arguments.length <= 0 || arguments[0] === undefined ? true : arguments[0];
  783. // flushChanges commits the changes immediately, leave true unless you are positioning multiple
  784. // tethers (in which case call Tether.Utils.flush yourself when you're done)
  785. if (!this.enabled) {
  786. return;
  787. }
  788. this.clearCache();
  789. // Turn 'auto' attachments into the appropriate corner or edge
  790. var targetAttachment = autoToFixedAttachment(this.targetAttachment, this.attachment);
  791. this.updateAttachClasses(this.attachment, targetAttachment);
  792. var elementPos = this.cache('element-bounds', function () {
  793. return getBounds(_this7.element);
  794. });
  795. var width = elementPos.width;
  796. var height = elementPos.height;
  797. if (width === 0 && height === 0 && typeof this.lastSize !== 'undefined') {
  798. var _lastSize = this.lastSize;
  799. // We cache the height and width to make it possible to position elements that are
  800. // getting hidden.
  801. width = _lastSize.width;
  802. height = _lastSize.height;
  803. } else {
  804. this.lastSize = { width: width, height: height };
  805. }
  806. var targetPos = this.cache('target-bounds', function () {
  807. return _this7.getTargetBounds();
  808. });
  809. var targetSize = targetPos;
  810. // Get an actual px offset from the attachment
  811. var offset = offsetToPx(attachmentToOffset(this.attachment), { width: width, height: height });
  812. var targetOffset = offsetToPx(attachmentToOffset(targetAttachment), targetSize);
  813. var manualOffset = offsetToPx(this.offset, { width: width, height: height });
  814. var manualTargetOffset = offsetToPx(this.targetOffset, targetSize);
  815. // Add the manually provided offset
  816. offset = addOffset(offset, manualOffset);
  817. targetOffset = addOffset(targetOffset, manualTargetOffset);
  818. // It's now our goal to make (element position + offset) == (target position + target offset)
  819. var left = targetPos.left + targetOffset.left - offset.left;
  820. var top = targetPos.top + targetOffset.top - offset.top;
  821. for (var i = 0; i < TetherBase.modules.length; ++i) {
  822. var _module2 = TetherBase.modules[i];
  823. var ret = _module2.position.call(this, {
  824. left: left,
  825. top: top,
  826. targetAttachment: targetAttachment,
  827. targetPos: targetPos,
  828. elementPos: elementPos,
  829. offset: offset,
  830. targetOffset: targetOffset,
  831. manualOffset: manualOffset,
  832. manualTargetOffset: manualTargetOffset,
  833. scrollbarSize: scrollbarSize,
  834. attachment: this.attachment
  835. });
  836. if (ret === false) {
  837. return false;
  838. } else if (typeof ret === 'undefined' || typeof ret !== 'object') {
  839. continue;
  840. } else {
  841. top = ret.top;
  842. left = ret.left;
  843. }
  844. }
  845. // We describe the position three different ways to give the optimizer
  846. // a chance to decide the best possible way to position the element
  847. // with the fewest repaints.
  848. var next = {
  849. // It's position relative to the page (absolute positioning when
  850. // the element is a child of the body)
  851. page: {
  852. top: top,
  853. left: left
  854. },
  855. // It's position relative to the viewport (fixed positioning)
  856. viewport: {
  857. top: top - pageYOffset,
  858. bottom: pageYOffset - top - height + innerHeight,
  859. left: left - pageXOffset,
  860. right: pageXOffset - left - width + innerWidth
  861. }
  862. };
  863. var doc = this.target.ownerDocument;
  864. var win = doc.defaultView;
  865. var scrollbarSize = undefined;
  866. if (win.innerHeight > doc.documentElement.clientHeight) {
  867. scrollbarSize = this.cache('scrollbar-size', getScrollBarSize);
  868. next.viewport.bottom -= scrollbarSize.height;
  869. }
  870. if (win.innerWidth > doc.documentElement.clientWidth) {
  871. scrollbarSize = this.cache('scrollbar-size', getScrollBarSize);
  872. next.viewport.right -= scrollbarSize.width;
  873. }
  874. if (['', 'static'].indexOf(doc.body.style.position) === -1 || ['', 'static'].indexOf(doc.body.parentElement.style.position) === -1) {
  875. // Absolute positioning in the body will be relative to the page, not the 'initial containing block'
  876. next.page.bottom = doc.body.scrollHeight - top - height;
  877. next.page.right = doc.body.scrollWidth - left - width;
  878. }
  879. if (typeof this.options.optimizations !== 'undefined' && this.options.optimizations.moveElement !== false && !(typeof this.targetModifier !== 'undefined')) {
  880. (function () {
  881. var offsetParent = _this7.cache('target-offsetparent', function () {
  882. return getOffsetParent(_this7.target);
  883. });
  884. var offsetPosition = _this7.cache('target-offsetparent-bounds', function () {
  885. return getBounds(offsetParent);
  886. });
  887. var offsetParentStyle = getComputedStyle(offsetParent);
  888. var offsetParentSize = offsetPosition;
  889. var offsetBorder = {};
  890. ['Top', 'Left', 'Bottom', 'Right'].forEach(function (side) {
  891. offsetBorder[side.toLowerCase()] = parseFloat(offsetParentStyle['border' + side + 'Width']);
  892. });
  893. offsetPosition.right = doc.body.scrollWidth - offsetPosition.left - offsetParentSize.width + offsetBorder.right;
  894. offsetPosition.bottom = doc.body.scrollHeight - offsetPosition.top - offsetParentSize.height + offsetBorder.bottom;
  895. if (next.page.top >= offsetPosition.top + offsetBorder.top && next.page.bottom >= offsetPosition.bottom) {
  896. if (next.page.left >= offsetPosition.left + offsetBorder.left && next.page.right >= offsetPosition.right) {
  897. // We're within the visible part of the target's scroll parent
  898. var scrollTop = offsetParent.scrollTop;
  899. var scrollLeft = offsetParent.scrollLeft;
  900. // It's position relative to the target's offset parent (absolute positioning when
  901. // the element is moved to be a child of the target's offset parent).
  902. next.offset = {
  903. top: next.page.top - offsetPosition.top + scrollTop - offsetBorder.top,
  904. left: next.page.left - offsetPosition.left + scrollLeft - offsetBorder.left
  905. };
  906. }
  907. }
  908. })();
  909. }
  910. // We could also travel up the DOM and try each containing context, rather than only
  911. // looking at the body, but we're gonna get diminishing returns.
  912. this.move(next);
  913. this.history.unshift(next);
  914. if (this.history.length > 3) {
  915. this.history.pop();
  916. }
  917. if (flushChanges) {
  918. flush();
  919. }
  920. return true;
  921. }
  922. // THE ISSUE
  923. }, {
  924. key: 'move',
  925. value: function move(pos) {
  926. var _this8 = this;
  927. if (!(typeof this.element.parentNode !== 'undefined')) {
  928. return;
  929. }
  930. var same = {};
  931. for (var type in pos) {
  932. same[type] = {};
  933. for (var key in pos[type]) {
  934. var found = false;
  935. for (var i = 0; i < this.history.length; ++i) {
  936. var point = this.history[i];
  937. if (typeof point[type] !== 'undefined' && !within(point[type][key], pos[type][key])) {
  938. found = true;
  939. break;
  940. }
  941. }
  942. if (!found) {
  943. same[type][key] = true;
  944. }
  945. }
  946. }
  947. var css = { top: '', left: '', right: '', bottom: '' };
  948. var transcribe = function transcribe(_same, _pos) {
  949. var hasOptimizations = typeof _this8.options.optimizations !== 'undefined';
  950. var gpu = hasOptimizations ? _this8.options.optimizations.gpu : null;
  951. if (gpu !== false) {
  952. var yPos = undefined,
  953. xPos = undefined;
  954. if (_same.top) {
  955. css.top = 0;
  956. yPos = _pos.top;
  957. } else {
  958. css.bottom = 0;
  959. yPos = -_pos.bottom;
  960. }
  961. if (_same.left) {
  962. css.left = 0;
  963. xPos = _pos.left;
  964. } else {
  965. css.right = 0;
  966. xPos = -_pos.right;
  967. }
  968. if (window.matchMedia) {
  969. // HubSpot/tether#207
  970. var retina = window.matchMedia('only screen and (min-resolution: 1.3dppx)').matches || window.matchMedia('only screen and (-webkit-min-device-pixel-ratio: 1.3)').matches;
  971. if (!retina) {
  972. xPos = Math.round(xPos);
  973. yPos = Math.round(yPos);
  974. }
  975. }
  976. css[transformKey] = 'translateX(' + xPos + 'px) translateY(' + yPos + 'px)';
  977. if (transformKey !== 'msTransform') {
  978. // The Z transform will keep this in the GPU (faster, and prevents artifacts),
  979. // but IE9 doesn't support 3d transforms and will choke.
  980. css[transformKey] += " translateZ(0)";
  981. }
  982. } else {
  983. if (_same.top) {
  984. css.top = _pos.top + 'px';
  985. } else {
  986. css.bottom = _pos.bottom + 'px';
  987. }
  988. if (_same.left) {
  989. css.left = _pos.left + 'px';
  990. } else {
  991. css.right = _pos.right + 'px';
  992. }
  993. }
  994. };
  995. var moved = false;
  996. if ((same.page.top || same.page.bottom) && (same.page.left || same.page.right)) {
  997. css.position = 'absolute';
  998. transcribe(same.page, pos.page);
  999. } else if ((same.viewport.top || same.viewport.bottom) && (same.viewport.left || same.viewport.right)) {
  1000. css.position = 'fixed';
  1001. transcribe(same.viewport, pos.viewport);
  1002. } else if (typeof same.offset !== 'undefined' && same.offset.top && same.offset.left) {
  1003. (function () {
  1004. css.position = 'absolute';
  1005. var offsetParent = _this8.cache('target-offsetparent', function () {
  1006. return getOffsetParent(_this8.target);
  1007. });
  1008. if (getOffsetParent(_this8.element) !== offsetParent) {
  1009. defer(function () {
  1010. _this8.element.parentNode.removeChild(_this8.element);
  1011. offsetParent.appendChild(_this8.element);
  1012. });
  1013. }
  1014. transcribe(same.offset, pos.offset);
  1015. moved = true;
  1016. })();
  1017. } else {
  1018. css.position = 'absolute';
  1019. transcribe({ top: true, left: true }, pos.page);
  1020. }
  1021. if (!moved) {
  1022. var offsetParentIsBody = true;
  1023. var currentNode = this.element.parentNode;
  1024. while (currentNode && currentNode.nodeType === 1 && currentNode.tagName !== 'BODY') {
  1025. if (getComputedStyle(currentNode).position !== 'static') {
  1026. offsetParentIsBody = false;
  1027. break;
  1028. }
  1029. currentNode = currentNode.parentNode;
  1030. }
  1031. if (!offsetParentIsBody) {
  1032. this.element.parentNode.removeChild(this.element);
  1033. this.element.ownerDocument.body.appendChild(this.element);
  1034. }
  1035. }
  1036. // Any css change will trigger a repaint, so let's avoid one if nothing changed
  1037. var writeCSS = {};
  1038. var write = false;
  1039. for (var key in css) {
  1040. var val = css[key];
  1041. var elVal = this.element.style[key];
  1042. if (elVal !== val) {
  1043. write = true;
  1044. writeCSS[key] = val;
  1045. }
  1046. }
  1047. if (write) {
  1048. defer(function () {
  1049. extend(_this8.element.style, writeCSS);
  1050. _this8.trigger('repositioned');
  1051. });
  1052. }
  1053. }
  1054. }]);
  1055. return TetherClass;
  1056. })(Evented);
  1057. TetherClass.modules = [];
  1058. TetherBase.position = position;
  1059. var Tether = extend(TetherClass, TetherBase);
  1060. /* globals TetherBase */
  1061. 'use strict';
  1062. var _slicedToArray = (function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i['return']) _i['return'](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError('Invalid attempt to destructure non-iterable instance'); } }; })();
  1063. var _TetherBase$Utils = TetherBase.Utils;
  1064. var getBounds = _TetherBase$Utils.getBounds;
  1065. var extend = _TetherBase$Utils.extend;
  1066. var updateClasses = _TetherBase$Utils.updateClasses;
  1067. var defer = _TetherBase$Utils.defer;
  1068. var BOUNDS_FORMAT = ['left', 'top', 'right', 'bottom'];
  1069. function getBoundingRect(tether, to) {
  1070. if (to === 'scrollParent') {
  1071. to = tether.scrollParents[0];
  1072. } else if (to === 'window') {
  1073. to = [pageXOffset, pageYOffset, innerWidth + pageXOffset, innerHeight + pageYOffset];
  1074. }
  1075. if (to === document) {
  1076. to = to.documentElement;
  1077. }
  1078. if (typeof to.nodeType !== 'undefined') {
  1079. (function () {
  1080. var node = to;
  1081. var size = getBounds(to);
  1082. var pos = size;
  1083. var style = getComputedStyle(to);
  1084. to = [pos.left, pos.top, size.width + pos.left, size.height + pos.top];
  1085. // Account any parent Frames scroll offset
  1086. if (node.ownerDocument !== document) {
  1087. var win = node.ownerDocument.defaultView;
  1088. to[0] += win.pageXOffset;
  1089. to[1] += win.pageYOffset;
  1090. to[2] += win.pageXOffset;
  1091. to[3] += win.pageYOffset;
  1092. }
  1093. BOUNDS_FORMAT.forEach(function (side, i) {
  1094. side = side[0].toUpperCase() + side.substr(1);
  1095. if (side === 'Top' || side === 'Left') {
  1096. to[i] += parseFloat(style['border' + side + 'Width']);
  1097. } else {
  1098. to[i] -= parseFloat(style['border' + side + 'Width']);
  1099. }
  1100. });
  1101. })();
  1102. }
  1103. return to;
  1104. }
  1105. TetherBase.modules.push({
  1106. position: function position(_ref) {
  1107. var _this = this;
  1108. var top = _ref.top;
  1109. var left = _ref.left;
  1110. var targetAttachment = _ref.targetAttachment;
  1111. if (!this.options.constraints) {
  1112. return true;
  1113. }
  1114. var _cache = this.cache('element-bounds', function () {
  1115. return getBounds(_this.element);
  1116. });
  1117. var height = _cache.height;
  1118. var width = _cache.width;
  1119. if (width === 0 && height === 0 && typeof this.lastSize !== 'undefined') {
  1120. var _lastSize = this.lastSize;
  1121. // Handle the item getting hidden as a result of our positioning without glitching
  1122. // the classes in and out
  1123. width = _lastSize.width;
  1124. height = _lastSize.height;
  1125. }
  1126. var targetSize = this.cache('target-bounds', function () {
  1127. return _this.getTargetBounds();
  1128. });
  1129. var targetHeight = targetSize.height;
  1130. var targetWidth = targetSize.width;
  1131. var allClasses = [this.getClass('pinned'), this.getClass('out-of-bounds')];
  1132. this.options.constraints.forEach(function (constraint) {
  1133. var outOfBoundsClass = constraint.outOfBoundsClass;
  1134. var pinnedClass = constraint.pinnedClass;
  1135. if (outOfBoundsClass) {
  1136. allClasses.push(outOfBoundsClass);
  1137. }
  1138. if (pinnedClass) {
  1139. allClasses.push(pinnedClass);
  1140. }
  1141. });
  1142. allClasses.forEach(function (cls) {
  1143. ['left', 'top', 'right', 'bottom'].forEach(function (side) {
  1144. allClasses.push(cls + '-' + side);
  1145. });
  1146. });
  1147. var addClasses = [];
  1148. var tAttachment = extend({}, targetAttachment);
  1149. var eAttachment = extend({}, this.attachment);
  1150. this.options.constraints.forEach(function (constraint) {
  1151. var to = constraint.to;
  1152. var attachment = constraint.attachment;
  1153. var pin = constraint.pin;
  1154. if (typeof attachment === 'undefined') {
  1155. attachment = '';
  1156. }
  1157. var changeAttachX = undefined,
  1158. changeAttachY = undefined;
  1159. if (attachment.indexOf(' ') >= 0) {
  1160. var _attachment$split = attachment.split(' ');
  1161. var _attachment$split2 = _slicedToArray(_attachment$split, 2);
  1162. changeAttachY = _attachment$split2[0];
  1163. changeAttachX = _attachment$split2[1];
  1164. } else {
  1165. changeAttachX = changeAttachY = attachment;
  1166. }
  1167. var bounds = getBoundingRect(_this, to);
  1168. if (changeAttachY === 'target' || changeAttachY === 'both') {
  1169. if (top < bounds[1] && tAttachment.top === 'top') {
  1170. top += targetHeight;
  1171. tAttachment.top = 'bottom';
  1172. }
  1173. if (top + height > bounds[3] && tAttachment.top === 'bottom') {
  1174. top -= targetHeight;
  1175. tAttachment.top = 'top';
  1176. }
  1177. }
  1178. if (changeAttachY === 'together') {
  1179. if (tAttachment.top === 'top') {
  1180. if (eAttachment.top === 'bottom' && top < bounds[1]) {
  1181. top += targetHeight;
  1182. tAttachment.top = 'bottom';
  1183. top += height;
  1184. eAttachment.top = 'top';
  1185. } else if (eAttachment.top === 'top' && top + height > bounds[3] && top - (height - targetHeight) >= bounds[1]) {
  1186. top -= height - targetHeight;
  1187. tAttachment.top = 'bottom';
  1188. eAttachment.top = 'bottom';
  1189. }
  1190. }
  1191. if (tAttachment.top === 'bottom') {
  1192. if (eAttachment.top === 'top' && top + height > bounds[3]) {
  1193. top -= targetHeight;
  1194. tAttachment.top = 'top';
  1195. top -= height;
  1196. eAttachment.top = 'bottom';
  1197. } else if (eAttachment.top === 'bottom' && top < bounds[1] && top + (height * 2 - targetHeight) <= bounds[3]) {
  1198. top += height - targetHeight;
  1199. tAttachment.top = 'top';
  1200. eAttachment.top = 'top';
  1201. }
  1202. }
  1203. if (tAttachment.top === 'middle') {
  1204. if (top + height > bounds[3] && eAttachment.top === 'top') {
  1205. top -= height;
  1206. eAttachment.top = 'bottom';
  1207. } else if (top < bounds[1] && eAttachment.top === 'bottom') {
  1208. top += height;
  1209. eAttachment.top = 'top';
  1210. }
  1211. }
  1212. }
  1213. if (changeAttachX === 'target' || changeAttachX === 'both') {
  1214. if (left < bounds[0] && tAttachment.left === 'left') {
  1215. left += targetWidth;
  1216. tAttachment.left = 'right';
  1217. }
  1218. if (left + width > bounds[2] && tAttachment.left === 'right') {
  1219. left -= targetWidth;
  1220. tAttachment.left = 'left';
  1221. }
  1222. }
  1223. if (changeAttachX === 'together') {
  1224. if (left < bounds[0] && tAttachment.left === 'left') {
  1225. if (eAttachment.left === 'right') {
  1226. left += targetWidth;
  1227. tAttachment.left = 'right';
  1228. left += width;
  1229. eAttachment.left = 'left';
  1230. } else if (eAttachment.left === 'left') {
  1231. left += targetWidth;
  1232. tAttachment.left = 'right';
  1233. left -= width;
  1234. eAttachment.left = 'right';
  1235. }
  1236. } else if (left + width > bounds[2] && tAttachment.left === 'right') {
  1237. if (eAttachment.left === 'left') {
  1238. left -= targetWidth;
  1239. tAttachment.left = 'left';
  1240. left -= width;
  1241. eAttachment.left = 'right';
  1242. } else if (eAttachment.left === 'right') {
  1243. left -= targetWidth;
  1244. tAttachment.left = 'left';
  1245. left += width;
  1246. eAttachment.left = 'left';
  1247. }
  1248. } else if (tAttachment.left === 'center') {
  1249. if (left + width > bounds[2] && eAttachment.left === 'left') {
  1250. left -= width;
  1251. eAttachment.left = 'right';
  1252. } else if (left < bounds[0] && eAttachment.left === 'right') {
  1253. left += width;
  1254. eAttachment.left = 'left';
  1255. }
  1256. }
  1257. }
  1258. if (changeAttachY === 'element' || changeAttachY === 'both') {
  1259. if (top < bounds[1] && eAttachment.top === 'bottom') {
  1260. top += height;
  1261. eAttachment.top = 'top';
  1262. }
  1263. if (top + height > bounds[3] && eAttachment.top === 'top') {
  1264. top -= height;
  1265. eAttachment.top = 'bottom';
  1266. }
  1267. }
  1268. if (changeAttachX === 'element' || changeAttachX === 'both') {
  1269. if (left < bounds[0]) {
  1270. if (eAttachment.left === 'right') {
  1271. left += width;
  1272. eAttachment.left = 'left';
  1273. } else if (eAttachment.left === 'center') {
  1274. left += width / 2;
  1275. eAttachment.left = 'left';
  1276. }
  1277. }
  1278. if (left + width > bounds[2]) {
  1279. if (eAttachment.left === 'left') {
  1280. left -= width;
  1281. eAttachment.left = 'right';
  1282. } else if (eAttachment.left === 'center') {
  1283. left -= width / 2;
  1284. eAttachment.left = 'right';
  1285. }
  1286. }
  1287. }
  1288. if (typeof pin === 'string') {
  1289. pin = pin.split(',').map(function (p) {
  1290. return p.trim();
  1291. });
  1292. } else if (pin === true) {
  1293. pin = ['top', 'left', 'right', 'bottom'];
  1294. }
  1295. pin = pin || [];
  1296. var pinned = [];
  1297. var oob = [];
  1298. if (top < bounds[1]) {
  1299. if (pin.indexOf('top') >= 0) {
  1300. top = bounds[1];
  1301. pinned.push('top');
  1302. } else {
  1303. oob.push('top');
  1304. }
  1305. }
  1306. if (top + height > bounds[3]) {
  1307. if (pin.indexOf('bottom') >= 0) {
  1308. top = bounds[3] - height;
  1309. pinned.push('bottom');
  1310. } else {
  1311. oob.push('bottom');
  1312. }
  1313. }
  1314. if (left < bounds[0]) {
  1315. if (pin.indexOf('left') >= 0) {
  1316. left = bounds[0];
  1317. pinned.push('left');
  1318. } else {
  1319. oob.push('left');
  1320. }
  1321. }
  1322. if (left + width > bounds[2]) {
  1323. if (pin.indexOf('right') >= 0) {
  1324. left = bounds[2] - width;
  1325. pinned.push('right');
  1326. } else {
  1327. oob.push('right');
  1328. }
  1329. }
  1330. if (pinned.length) {
  1331. (function () {
  1332. var pinnedClass = undefined;
  1333. if (typeof _this.options.pinnedClass !== 'undefined') {
  1334. pinnedClass = _this.options.pinnedClass;
  1335. } else {
  1336. pinnedClass = _this.getClass('pinned');
  1337. }
  1338. addClasses.push(pinnedClass);
  1339. pinned.forEach(function (side) {
  1340. addClasses.push(pinnedClass + '-' + side);
  1341. });
  1342. })();
  1343. }
  1344. if (oob.length) {
  1345. (function () {
  1346. var oobClass = undefined;
  1347. if (typeof _this.options.outOfBoundsClass !== 'undefined') {
  1348. oobClass = _this.options.outOfBoundsClass;
  1349. } else {
  1350. oobClass = _this.getClass('out-of-bounds');
  1351. }
  1352. addClasses.push(oobClass);
  1353. oob.forEach(function (side) {
  1354. addClasses.push(oobClass + '-' + side);
  1355. });
  1356. })();
  1357. }
  1358. if (pinned.indexOf('left') >= 0 || pinned.indexOf('right') >= 0) {
  1359. eAttachment.left = tAttachment.left = false;
  1360. }
  1361. if (pinned.indexOf('top') >= 0 || pinned.indexOf('bottom') >= 0) {
  1362. eAttachment.top = tAttachment.top = false;
  1363. }
  1364. if (tAttachment.top !== targetAttachment.top || tAttachment.left !== targetAttachment.left || eAttachment.top !== _this.attachment.top || eAttachment.left !== _this.attachment.left) {
  1365. _this.updateAttachClasses(eAttachment, tAttachment);
  1366. _this.trigger('update', {
  1367. attachment: eAttachment,
  1368. targetAttachment: tAttachment
  1369. });
  1370. }
  1371. });
  1372. defer(function () {
  1373. if (!(_this.options.addTargetClasses === false)) {
  1374. updateClasses(_this.target, addClasses, allClasses);
  1375. }
  1376. updateClasses(_this.element, addClasses, allClasses);
  1377. });
  1378. return { top: top, left: left };
  1379. }
  1380. });
  1381. /* globals TetherBase */
  1382. 'use strict';
  1383. var _TetherBase$Utils = TetherBase.Utils;
  1384. var getBounds = _TetherBase$Utils.getBounds;
  1385. var updateClasses = _TetherBase$Utils.updateClasses;
  1386. var defer = _TetherBase$Utils.defer;
  1387. TetherBase.modules.push({
  1388. position: function position(_ref) {
  1389. var _this = this;
  1390. var top = _ref.top;
  1391. var left = _ref.left;
  1392. var _cache = this.cache('element-bounds', function () {
  1393. return getBounds(_this.element);
  1394. });
  1395. var height = _cache.height;
  1396. var width = _cache.width;
  1397. var targetPos = this.getTargetBounds();
  1398. var bottom = top + height;
  1399. var right = left + width;
  1400. var abutted = [];
  1401. if (top <= targetPos.bottom && bottom >= targetPos.top) {
  1402. ['left', 'right'].forEach(function (side) {
  1403. var targetPosSide = targetPos[side];
  1404. if (targetPosSide === left || targetPosSide === right) {
  1405. abutted.push(side);
  1406. }
  1407. });
  1408. }
  1409. if (left <= targetPos.right && right >= targetPos.left) {
  1410. ['top', 'bottom'].forEach(function (side) {
  1411. var targetPosSide = targetPos[side];
  1412. if (targetPosSide === top || targetPosSide === bottom) {
  1413. abutted.push(side);
  1414. }
  1415. });
  1416. }
  1417. var allClasses = [];
  1418. var addClasses = [];
  1419. var sides = ['left', 'top', 'right', 'bottom'];
  1420. allClasses.push(this.getClass('abutted'));
  1421. sides.forEach(function (side) {
  1422. allClasses.push(_this.getClass('abutted') + '-' + side);
  1423. });
  1424. if (abutted.length) {
  1425. addClasses.push(this.getClass('abutted'));
  1426. }
  1427. abutted.forEach(function (side) {
  1428. addClasses.push(_this.getClass('abutted') + '-' + side);
  1429. });
  1430. defer(function () {
  1431. if (!(_this.options.addTargetClasses === false)) {
  1432. updateClasses(_this.target, addClasses, allClasses);
  1433. }
  1434. updateClasses(_this.element, addClasses, allClasses);
  1435. });
  1436. return true;
  1437. }
  1438. });
  1439. /* globals TetherBase */
  1440. 'use strict';
  1441. var _slicedToArray = (function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i['return']) _i['return'](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError('Invalid attempt to destructure non-iterable instance'); } }; })();
  1442. TetherBase.modules.push({
  1443. position: function position(_ref) {
  1444. var top = _ref.top;
  1445. var left = _ref.left;
  1446. if (!this.options.shift) {
  1447. return;
  1448. }
  1449. var shift = this.options.shift;
  1450. if (typeof this.options.shift === 'function') {
  1451. shift = this.options.shift.call(this, { top: top, left: left });
  1452. }
  1453. var shiftTop = undefined,
  1454. shiftLeft = undefined;
  1455. if (typeof shift === 'string') {
  1456. shift = shift.split(' ');
  1457. shift[1] = shift[1] || shift[0];
  1458. var _shift = shift;
  1459. var _shift2 = _slicedToArray(_shift, 2);
  1460. shiftTop = _shift2[0];
  1461. shiftLeft = _shift2[1];
  1462. shiftTop = parseFloat(shiftTop, 10);
  1463. shiftLeft = parseFloat(shiftLeft, 10);
  1464. } else {
  1465. shiftTop = shift.top;
  1466. shiftLeft = shift.left;
  1467. }
  1468. top += shiftTop;
  1469. left += shiftLeft;
  1470. return { top: top, left: left };
  1471. }
  1472. });
  1473. return Tether;
  1474. }));