tether.js 54 KB

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