/*! tether 1.2.0 */ (function(root, factory) { if (typeof define === 'function' && define.amd) { define(factory); } else if (typeof exports === 'object') { module.exports = factory(require, exports, module); } else { root.Tether = factory(); } }(this, function(require, exports, module) { 'use strict'; 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; }; })(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var TetherBase = undefined; if (typeof TetherBase === 'undefined') { TetherBase = { modules: [] }; } function getScrollParent(el) { // In firefox if the el is inside an iframe with display: none; window.getComputedStyle() will return null; // https://bugzilla.mozilla.org/show_bug.cgi?id=548397 var computedStyle = getComputedStyle(el) || {}; var position = computedStyle.position; if (position === 'fixed') { return el; } var parent = el; while (parent = parent.parentNode) { var style = undefined; try { style = getComputedStyle(parent); } catch (err) {} if (typeof style === 'undefined' || style === null) { return parent; } var _style = style; var overflow = _style.overflow; var overflowX = _style.overflowX; var overflowY = _style.overflowY; if (/(auto|scroll)/.test(overflow + overflowY + overflowX)) { if (position !== 'absolute' || ['relative', 'absolute', 'fixed'].indexOf(style.position) >= 0) { return parent; } } } return document.body; } var uniqueId = (function () { var id = 0; return function () { return ++id; }; })(); var zeroPosCache = {}; var getOrigin = function getOrigin(doc) { // getBoundingClientRect is unfortunately too accurate. It introduces a pixel or two of // jitter as the user scrolls that messes with our ability to detect if two positions // are equivilant or not. We place an element at the top left of the page that will // get the same jitter, so we can cancel the two out. var node = doc._tetherZeroElement; if (typeof node === 'undefined') { node = doc.createElement('div'); node.setAttribute('data-tether-id', uniqueId()); extend(node.style, { top: 0, left: 0, position: 'absolute' }); doc.body.appendChild(node); doc._tetherZeroElement = node; } var id = node.getAttribute('data-tether-id'); if (typeof zeroPosCache[id] === 'undefined') { zeroPosCache[id] = {}; var rect = node.getBoundingClientRect(); for (var k in rect) { // Can't use extend, as on IE9, elements don't resolve to be hasOwnProperty zeroPosCache[id][k] = rect[k]; } // Clear the cache when this position call is done defer(function () { delete zeroPosCache[id]; }); } return zeroPosCache[id]; }; function getBounds(el) { var doc = undefined; if (el === document) { doc = document; el = document.documentElement; } else { doc = el.ownerDocument; } var docEl = doc.documentElement; var box = {}; // The original object returned by getBoundingClientRect is immutable, so we clone it // We can't use extend because the properties are not considered part of the object by hasOwnProperty in IE9 var rect = el.getBoundingClientRect(); for (var k in rect) { box[k] = rect[k]; } var origin = getOrigin(doc); box.top -= origin.top; box.left -= origin.left; if (typeof box.width === 'undefined') { box.width = document.body.scrollWidth - box.left - box.right; } if (typeof box.height === 'undefined') { box.height = document.body.scrollHeight - box.top - box.bottom; } box.top = box.top - docEl.clientTop; box.left = box.left - docEl.clientLeft; box.right = doc.body.clientWidth - box.width - box.left; box.bottom = doc.body.clientHeight - box.height - box.top; return box; } function getOffsetParent(el) { return el.offsetParent || document.documentElement; } function getScrollBarSize() { var inner = document.createElement('div'); inner.style.width = '100%'; inner.style.height = '200px'; var outer = document.createElement('div'); extend(outer.style, { position: 'absolute', top: 0, left: 0, pointerEvents: 'none', visibility: 'hidden', width: '200px', height: '150px', overflow: 'hidden' }); outer.appendChild(inner); document.body.appendChild(outer); var widthContained = inner.offsetWidth; outer.style.overflow = 'scroll'; var widthScroll = inner.offsetWidth; if (widthContained === widthScroll) { widthScroll = outer.clientWidth; } document.body.removeChild(outer); var width = widthContained - widthScroll; return { width: width, height: width }; } function extend() { var out = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; var args = []; Array.prototype.push.apply(args, arguments); args.slice(1).forEach(function (obj) { if (obj) { for (var key in obj) { if (({}).hasOwnProperty.call(obj, key)) { out[key] = obj[key]; } } } }); return out; } function removeClass(el, name) { if (typeof el.classList !== 'undefined') { name.split(' ').forEach(function (cls) { if (cls.trim()) { el.classList.remove(cls); } }); } else { var regex = new RegExp('(^| )' + name.split(' ').join('|') + '( |$)', 'gi'); var className = getClassName(el).replace(regex, ' '); setClassName(el, className); } } function addClass(el, name) { if (typeof el.classList !== 'undefined') { name.split(' ').forEach(function (cls) { if (cls.trim()) { el.classList.add(cls); } }); } else { removeClass(el, name); var cls = getClassName(el) + (' ' + name); setClassName(el, cls); } } function hasClass(el, name) { if (typeof el.classList !== 'undefined') { return el.classList.contains(name); } var className = getClassName(el); return new RegExp('(^| )' + name + '( |$)', 'gi').test(className); } function getClassName(el) { if (el.className instanceof SVGAnimatedString) { return el.className.baseVal; } return el.className; } function setClassName(el, className) { el.setAttribute('class', className); } function updateClasses(el, add, all) { // Of the set of 'all' classes, we need the 'add' classes, and only the // 'add' classes to be set. all.forEach(function (cls) { if (add.indexOf(cls) === -1 && hasClass(el, cls)) { removeClass(el, cls); } }); add.forEach(function (cls) { if (!hasClass(el, cls)) { addClass(el, cls); } }); } var deferred = []; var defer = function defer(fn) { deferred.push(fn); }; var flush = function flush() { var fn = undefined; while (fn = deferred.pop()) { fn(); } }; var Evented = (function () { function Evented() { _classCallCheck(this, Evented); } _createClass(Evented, [{ key: 'on', value: function on(event, handler, ctx) { var once = arguments.length <= 3 || arguments[3] === undefined ? false : arguments[3]; if (typeof this.bindings === 'undefined') { this.bindings = {}; } if (typeof this.bindings[event] === 'undefined') { this.bindings[event] = []; } this.bindings[event].push({ handler: handler, ctx: ctx, once: once }); } }, { key: 'once', value: function once(event, handler, ctx) { this.on(event, handler, ctx, true); } }, { key: 'off', value: function off(event, handler) { if (typeof this.bindings !== 'undefined' && typeof this.bindings[event] !== 'undefined') { return; } if (typeof handler === 'undefined') { delete this.bindings[event]; } else { var i = 0; while (i < this.bindings[event].length) { if (this.bindings[event][i].handler === handler) { this.bindings[event].splice(i, 1); } else { ++i; } } } } }, { key: 'trigger', value: function trigger(event) { if (typeof this.bindings !== 'undefined' && this.bindings[event]) { var i = 0; for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } while (i < this.bindings[event].length) { var _bindings$event$i = this.bindings[event][i]; var handler = _bindings$event$i.handler; var ctx = _bindings$event$i.ctx; var once = _bindings$event$i.once; var context = ctx; if (typeof context === 'undefined') { context = this; } handler.apply(context, args); if (once) { this.bindings[event].splice(i, 1); } else { ++i; } } } } }]); return Evented; })(); TetherBase.Utils = { getScrollParent: getScrollParent, getBounds: getBounds, getOffsetParent: getOffsetParent, extend: extend, addClass: addClass, removeClass: removeClass, hasClass: hasClass, updateClasses: updateClasses, defer: defer, flush: flush, uniqueId: uniqueId, Evented: Evented, getScrollBarSize: getScrollBarSize }; /* globals TetherBase, performance */ 'use strict'; 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'); } }; })(); 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; }; })(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } if (typeof TetherBase === 'undefined') { throw new Error('You must include the utils.js file before tether.js'); } var _TetherBase$Utils = TetherBase.Utils; var getScrollParent = _TetherBase$Utils.getScrollParent; var getBounds = _TetherBase$Utils.getBounds; var getOffsetParent = _TetherBase$Utils.getOffsetParent; var extend = _TetherBase$Utils.extend; var addClass = _TetherBase$Utils.addClass; var removeClass = _TetherBase$Utils.removeClass; var updateClasses = _TetherBase$Utils.updateClasses; var defer = _TetherBase$Utils.defer; var flush = _TetherBase$Utils.flush; var getScrollBarSize = _TetherBase$Utils.getScrollBarSize; function within(a, b) { var diff = arguments.length <= 2 || arguments[2] === undefined ? 1 : arguments[2]; return a + diff >= b && b >= a - diff; } var transformKey = (function () { if (typeof document === 'undefined') { return ''; } var el = document.createElement('div'); var transforms = ['transform', 'webkitTransform', 'OTransform', 'MozTransform', 'msTransform']; for (var i = 0; i < transforms.length; ++i) { var key = transforms[i]; if (el.style[key] !== undefined) { return key; } } })(); var tethers = []; var position = function position() { tethers.forEach(function (tether) { tether.position(false); }); flush(); }; function now() { if (typeof performance !== 'undefined' && typeof performance.now !== 'undefined') { return performance.now(); } return +new Date(); } (function () { var lastCall = null; var lastDuration = null; var pendingTimeout = null; var tick = function tick() { if (typeof lastDuration !== 'undefined' && lastDuration > 16) { // We voluntarily throttle ourselves if we can't manage 60fps lastDuration = Math.min(lastDuration - 16, 250); // Just in case this is the last event, remember to position just once more pendingTimeout = setTimeout(tick, 250); return; } if (typeof lastCall !== 'undefined' && now() - lastCall < 10) { // Some browsers call events a little too frequently, refuse to run more than is reasonable return; } if (typeof pendingTimeout !== 'undefined') { clearTimeout(pendingTimeout); pendingTimeout = null; } lastCall = now(); position(); lastDuration = now() - lastCall; }; if (typeof window !== 'undefined') { ['resize', 'scroll', 'touchmove'].forEach(function (event) { window.addEventListener(event, tick); }); } })(); var MIRROR_LR = { center: 'center', left: 'right', right: 'left' }; var MIRROR_TB = { middle: 'middle', top: 'bottom', bottom: 'top' }; var OFFSET_MAP = { top: 0, left: 0, middle: '50%', center: '50%', bottom: '100%', right: '100%' }; var autoToFixedAttachment = function autoToFixedAttachment(attachment, relativeToAttachment) { var left = attachment.left; var top = attachment.top; if (left === 'auto') { left = MIRROR_LR[relativeToAttachment.left]; } if (top === 'auto') { top = MIRROR_TB[relativeToAttachment.top]; } return { left: left, top: top }; }; var attachmentToOffset = function attachmentToOffset(attachment) { var left = attachment.left; var top = attachment.top; if (typeof OFFSET_MAP[attachment.left] !== 'undefined') { left = OFFSET_MAP[attachment.left]; } if (typeof OFFSET_MAP[attachment.top] !== 'undefined') { top = OFFSET_MAP[attachment.top]; } return { left: left, top: top }; }; function addOffset() { var out = { top: 0, left: 0 }; for (var _len = arguments.length, offsets = Array(_len), _key = 0; _key < _len; _key++) { offsets[_key] = arguments[_key]; } offsets.forEach(function (_ref) { var top = _ref.top; var left = _ref.left; if (typeof top === 'string') { top = parseFloat(top, 10); } if (typeof left === 'string') { left = parseFloat(left, 10); } out.top += top; out.left += left; }); return out; } function offsetToPx(offset, size) { if (typeof offset.left === 'string' && offset.left.indexOf('%') !== -1) { offset.left = parseFloat(offset.left, 10) / 100 * size.width; } if (typeof offset.top === 'string' && offset.top.indexOf('%') !== -1) { offset.top = parseFloat(offset.top, 10) / 100 * size.height; } return offset; } var parseOffset = function parseOffset(value) { var _value$split = value.split(' '); var _value$split2 = _slicedToArray(_value$split, 2); var top = _value$split2[0]; var left = _value$split2[1]; return { top: top, left: left }; }; var parseAttachment = parseOffset; var TetherClass = (function () { function TetherClass(options) { var _this = this; _classCallCheck(this, TetherClass); this.position = this.position.bind(this); tethers.push(this); this.history = []; this.setOptions(options, false); TetherBase.modules.forEach(function (module) { if (typeof module.initialize !== 'undefined') { module.initialize.call(_this); } }); this.position(); } _createClass(TetherClass, [{ key: 'getClass', value: function getClass() { var key = arguments.length <= 0 || arguments[0] === undefined ? '' : arguments[0]; var classes = this.options.classes; if (typeof classes !== 'undefined' && classes[key]) { return this.options.classes[key]; } else if (this.options.classPrefix) { return this.options.classPrefix + '-' + key; } else { return key; } } }, { key: 'setOptions', value: function setOptions(options) { var _this2 = this; var pos = arguments.length <= 1 || arguments[1] === undefined ? true : arguments[1]; var defaults = { offset: '0 0', targetOffset: '0 0', targetAttachment: 'auto auto', classPrefix: 'tether' }; this.options = extend(defaults, options); var _options = this.options; var element = _options.element; var target = _options.target; var targetModifier = _options.targetModifier; this.element = element; this.target = target; this.targetModifier = targetModifier; if (this.target === 'viewport') { this.target = document.body; this.targetModifier = 'visible'; } else if (this.target === 'scroll-handle') { this.target = document.body; this.targetModifier = 'scroll-handle'; } ['element', 'target'].forEach(function (key) { if (typeof _this2[key] === 'undefined') { throw new Error('Tether Error: Both element and target must be defined'); } if (typeof _this2[key].jquery !== 'undefined') { _this2[key] = _this2[key][0]; } else if (typeof _this2[key] === 'string') { _this2[key] = document.querySelector(_this2[key]); } }); addClass(this.element, this.getClass('element')); if (!(this.options.addTargetClasses === false)) { addClass(this.target, this.getClass('target')); } if (!this.options.attachment) { throw new Error('Tether Error: You must provide an attachment'); } this.targetAttachment = parseAttachment(this.options.targetAttachment); this.attachment = parseAttachment(this.options.attachment); this.offset = parseOffset(this.options.offset); this.targetOffset = parseOffset(this.options.targetOffset); if (typeof this.scrollParent !== 'undefined') { this.disable(); } if (this.targetModifier === 'scroll-handle') { this.scrollParent = this.target; } else { this.scrollParent = getScrollParent(this.target); } if (!(this.options.enabled === false)) { this.enable(pos); } } }, { key: 'getTargetBounds', value: function getTargetBounds() { if (typeof this.targetModifier !== 'undefined') { if (this.targetModifier === 'visible') { if (this.target === document.body) { return { top: pageYOffset, left: pageXOffset, height: innerHeight, width: innerWidth }; } else { var bounds = getBounds(this.target); var out = { height: bounds.height, width: bounds.width, top: bounds.top, left: bounds.left }; out.height = Math.min(out.height, bounds.height - (pageYOffset - bounds.top)); out.height = Math.min(out.height, bounds.height - (bounds.top + bounds.height - (pageYOffset + innerHeight))); out.height = Math.min(innerHeight, out.height); out.height -= 2; out.width = Math.min(out.width, bounds.width - (pageXOffset - bounds.left)); out.width = Math.min(out.width, bounds.width - (bounds.left + bounds.width - (pageXOffset + innerWidth))); out.width = Math.min(innerWidth, out.width); out.width -= 2; if (out.top < pageYOffset) { out.top = pageYOffset; } if (out.left < pageXOffset) { out.left = pageXOffset; } return out; } } else if (this.targetModifier === 'scroll-handle') { var bounds = undefined; var target = this.target; if (target === document.body) { target = document.documentElement; bounds = { left: pageXOffset, top: pageYOffset, height: innerHeight, width: innerWidth }; } else { bounds = getBounds(target); } var style = getComputedStyle(target); var hasBottomScroll = target.scrollWidth > target.clientWidth || [style.overflow, style.overflowX].indexOf('scroll') >= 0 || this.target !== document.body; var scrollBottom = 0; if (hasBottomScroll) { scrollBottom = 15; } var height = bounds.height - parseFloat(style.borderTopWidth) - parseFloat(style.borderBottomWidth) - scrollBottom; var out = { width: 15, height: height * 0.975 * (height / target.scrollHeight), left: bounds.left + bounds.width - parseFloat(style.borderLeftWidth) - 15 }; var fitAdj = 0; if (height < 408 && this.target === document.body) { fitAdj = -0.00011 * Math.pow(height, 2) - 0.00727 * height + 22.58; } if (this.target !== document.body) { out.height = Math.max(out.height, 24); } var scrollPercentage = this.target.scrollTop / (target.scrollHeight - height); out.top = scrollPercentage * (height - out.height - fitAdj) + bounds.top + parseFloat(style.borderTopWidth); if (this.target === document.body) { out.height = Math.max(out.height, 24); } return out; } } else { return getBounds(this.target); } } }, { key: 'clearCache', value: function clearCache() { this._cache = {}; } }, { key: 'cache', value: function cache(k, getter) { // More than one module will often need the same DOM info, so // we keep a cache which is cleared on each position call if (typeof this._cache === 'undefined') { this._cache = {}; } if (typeof this._cache[k] === 'undefined') { this._cache[k] = getter.call(this); } return this._cache[k]; } }, { key: 'enable', value: function enable() { var pos = arguments.length <= 0 || arguments[0] === undefined ? true : arguments[0]; if (!(this.options.addTargetClasses === false)) { addClass(this.target, this.getClass('enabled')); } addClass(this.element, this.getClass('enabled')); this.enabled = true; if (this.scrollParent !== document) { this.scrollParent.addEventListener('scroll', this.position); } if (pos) { this.position(); } } }, { key: 'disable', value: function disable() { removeClass(this.target, this.getClass('enabled')); removeClass(this.element, this.getClass('enabled')); this.enabled = false; if (typeof this.scrollParent !== 'undefined') { this.scrollParent.removeEventListener('scroll', this.position); } } }, { key: 'destroy', value: function destroy() { var _this3 = this; this.disable(); tethers.forEach(function (tether, i) { if (tether === _this3) { tethers.splice(i, 1); return; } }); } }, { key: 'updateAttachClasses', value: function updateAttachClasses(elementAttach, targetAttach) { var _this4 = this; elementAttach = elementAttach || this.attachment; targetAttach = targetAttach || this.targetAttachment; var sides = ['left', 'top', 'bottom', 'right', 'middle', 'center']; if (typeof this._addAttachClasses !== 'undefined' && this._addAttachClasses.length) { // updateAttachClasses can be called more than once in a position call, so // we need to clean up after ourselves such that when the last defer gets // ran it doesn't add any extra classes from previous calls. this._addAttachClasses.splice(0, this._addAttachClasses.length); } if (typeof this._addAttachClasses === 'undefined') { this._addAttachClasses = []; } var add = this._addAttachClasses; if (elementAttach.top) { add.push(this.getClass('element-attached') + '-' + elementAttach.top); } if (elementAttach.left) { add.push(this.getClass('element-attached') + '-' + elementAttach.left); } if (targetAttach.top) { add.push(this.getClass('target-attached') + '-' + targetAttach.top); } if (targetAttach.left) { add.push(this.getClass('target-attached') + '-' + targetAttach.left); } var all = []; sides.forEach(function (side) { all.push(_this4.getClass('element-attached') + '-' + side); all.push(_this4.getClass('target-attached') + '-' + side); }); defer(function () { if (!(typeof _this4._addAttachClasses !== 'undefined')) { return; } updateClasses(_this4.element, _this4._addAttachClasses, all); if (!(_this4.options.addTargetClasses === false)) { updateClasses(_this4.target, _this4._addAttachClasses, all); } delete _this4._addAttachClasses; }); } }, { key: 'position', value: function position() { var _this5 = this; var flushChanges = arguments.length <= 0 || arguments[0] === undefined ? true : arguments[0]; // flushChanges commits the changes immediately, leave true unless you are positioning multiple // tethers (in which case call Tether.Utils.flush yourself when you're done) if (!this.enabled) { return; } this.clearCache(); // Turn 'auto' attachments into the appropriate corner or edge var targetAttachment = autoToFixedAttachment(this.targetAttachment, this.attachment); this.updateAttachClasses(this.attachment, targetAttachment); var elementPos = this.cache('element-bounds', function () { return getBounds(_this5.element); }); var width = elementPos.width; var height = elementPos.height; if (width === 0 && height === 0 && typeof this.lastSize !== 'undefined') { var _lastSize = this.lastSize; // We cache the height and width to make it possible to position elements that are // getting hidden. width = _lastSize.width; height = _lastSize.height; } else { this.lastSize = { width: width, height: height }; } var targetPos = this.cache('target-bounds', function () { return _this5.getTargetBounds(); }); var targetSize = targetPos; // Get an actual px offset from the attachment var offset = offsetToPx(attachmentToOffset(this.attachment), { width: width, height: height }); var targetOffset = offsetToPx(attachmentToOffset(targetAttachment), targetSize); var manualOffset = offsetToPx(this.offset, { width: width, height: height }); var manualTargetOffset = offsetToPx(this.targetOffset, targetSize); // Add the manually provided offset offset = addOffset(offset, manualOffset); targetOffset = addOffset(targetOffset, manualTargetOffset); // It's now our goal to make (element position + offset) == (target position + target offset) var left = targetPos.left + targetOffset.left - offset.left; var top = targetPos.top + targetOffset.top - offset.top; for (var i = 0; i < TetherBase.modules.length; ++i) { var _module2 = TetherBase.modules[i]; var ret = _module2.position.call(this, { left: left, top: top, targetAttachment: targetAttachment, targetPos: targetPos, elementPos: elementPos, offset: offset, targetOffset: targetOffset, manualOffset: manualOffset, manualTargetOffset: manualTargetOffset, scrollbarSize: scrollbarSize, attachment: this.attachment }); if (ret === false) { return false; } else if (typeof ret === 'undefined' || typeof ret !== 'object') { continue; } else { top = ret.top; left = ret.left; } } // We describe the position three different ways to give the optimizer // a chance to decide the best possible way to position the element // with the fewest repaints. var next = { // It's position relative to the page (absolute positioning when // the element is a child of the body) page: { top: top, left: left }, // It's position relative to the viewport (fixed positioning) viewport: { top: top - pageYOffset, bottom: pageYOffset - top - height + innerHeight, left: left - pageXOffset, right: pageXOffset - left - width + innerWidth } }; var scrollbarSize = undefined; if (document.body.scrollWidth > window.innerWidth) { scrollbarSize = this.cache('scrollbar-size', getScrollBarSize); next.viewport.bottom -= scrollbarSize.height; } if (document.body.scrollHeight > window.innerHeight) { scrollbarSize = this.cache('scrollbar-size', getScrollBarSize); next.viewport.right -= scrollbarSize.width; } if (['', 'static'].indexOf(document.body.style.position) === -1 || ['', 'static'].indexOf(document.body.parentElement.style.position) === -1) { // Absolute positioning in the body will be relative to the page, not the 'initial containing block' next.page.bottom = document.body.scrollHeight - top - height; next.page.right = document.body.scrollWidth - left - width; } if (typeof this.options.optimizations !== 'undefined' && this.options.optimizations.moveElement !== false && !(typeof this.targetModifier !== 'undefined')) { (function () { var offsetParent = _this5.cache('target-offsetparent', function () { return getOffsetParent(_this5.target); }); var offsetPosition = _this5.cache('target-offsetparent-bounds', function () { return getBounds(offsetParent); }); var offsetParentStyle = getComputedStyle(offsetParent); var offsetParentSize = offsetPosition; var offsetBorder = {}; ['Top', 'Left', 'Bottom', 'Right'].forEach(function (side) { offsetBorder[side.toLowerCase()] = parseFloat(offsetParentStyle['border' + side + 'Width']); }); offsetPosition.right = document.body.scrollWidth - offsetPosition.left - offsetParentSize.width + offsetBorder.right; offsetPosition.bottom = document.body.scrollHeight - offsetPosition.top - offsetParentSize.height + offsetBorder.bottom; if (next.page.top >= offsetPosition.top + offsetBorder.top && next.page.bottom >= offsetPosition.bottom) { if (next.page.left >= offsetPosition.left + offsetBorder.left && next.page.right >= offsetPosition.right) { // We're within the visible part of the target's scroll parent var scrollTop = offsetParent.scrollTop; var scrollLeft = offsetParent.scrollLeft; // It's position relative to the target's offset parent (absolute positioning when // the element is moved to be a child of the target's offset parent). next.offset = { top: next.page.top - offsetPosition.top + scrollTop - offsetBorder.top, left: next.page.left - offsetPosition.left + scrollLeft - offsetBorder.left }; } } })(); } // We could also travel up the DOM and try each containing context, rather than only // looking at the body, but we're gonna get diminishing returns. this.move(next); this.history.unshift(next); if (this.history.length > 3) { this.history.pop(); } if (flushChanges) { flush(); } return true; } // THE ISSUE }, { key: 'move', value: function move(pos) { var _this6 = this; if (!(typeof this.element.parentNode !== 'undefined')) { return; } var same = {}; for (var type in pos) { same[type] = {}; for (var key in pos[type]) { var found = false; for (var i = 0; i < this.history.length; ++i) { var point = this.history[i]; if (typeof point[type] !== 'undefined' && !within(point[type][key], pos[type][key])) { found = true; break; } } if (!found) { same[type][key] = true; } } } var css = { top: '', left: '', right: '', bottom: '' }; var transcribe = function transcribe(_same, _pos) { var hasOptimizations = typeof _this6.options.optimizations !== 'undefined'; var gpu = hasOptimizations ? _this6.options.optimizations.gpu : null; if (gpu !== false) { var yPos = undefined, xPos = undefined; if (_same.top) { css.top = 0; yPos = _pos.top; } else { css.bottom = 0; yPos = -_pos.bottom; } if (_same.left) { css.left = 0; xPos = _pos.left; } else { css.right = 0; xPos = -_pos.right; } css[transformKey] = 'translateX(' + Math.round(xPos) + 'px) translateY(' + Math.round(yPos) + 'px)'; if (transformKey !== 'msTransform') { // The Z transform will keep this in the GPU (faster, and prevents artifacts), // but IE9 doesn't support 3d transforms and will choke. css[transformKey] += " translateZ(0)"; } } else { if (_same.top) { css.top = _pos.top + 'px'; } else { css.bottom = _pos.bottom + 'px'; } if (_same.left) { css.left = _pos.left + 'px'; } else { css.right = _pos.right + 'px'; } } }; var moved = false; if ((same.page.top || same.page.bottom) && (same.page.left || same.page.right)) { css.position = 'absolute'; transcribe(same.page, pos.page); } else if ((same.viewport.top || same.viewport.bottom) && (same.viewport.left || same.viewport.right)) { css.position = 'fixed'; transcribe(same.viewport, pos.viewport); } else if (typeof same.offset !== 'undefined' && same.offset.top && same.offset.left) { (function () { css.position = 'absolute'; var offsetParent = _this6.cache('target-offsetparent', function () { return getOffsetParent(_this6.target); }); if (getOffsetParent(_this6.element) !== offsetParent) { defer(function () { _this6.element.parentNode.removeChild(_this6.element); offsetParent.appendChild(_this6.element); }); } transcribe(same.offset, pos.offset); moved = true; })(); } else { css.position = 'absolute'; transcribe({ top: true, left: true }, pos.page); } if (!moved) { var offsetParentIsBody = true; var currentNode = this.element.parentNode; while (currentNode && currentNode.tagName !== 'BODY') { if (getComputedStyle(currentNode).position !== 'static') { offsetParentIsBody = false; break; } currentNode = currentNode.parentNode; } if (!offsetParentIsBody) { this.element.parentNode.removeChild(this.element); document.body.appendChild(this.element); } } // Any css change will trigger a repaint, so let's avoid one if nothing changed var writeCSS = {}; var write = false; for (var key in css) { var val = css[key]; var elVal = this.element.style[key]; if (elVal !== '' && val !== '' && ['top', 'left', 'bottom', 'right'].indexOf(key) >= 0) { elVal = parseFloat(elVal); val = parseFloat(val); } if (elVal !== val) { write = true; writeCSS[key] = val; } } if (write) { defer(function () { extend(_this6.element.style, writeCSS); }); } } }]); return TetherClass; })(); TetherClass.modules = []; TetherBase.position = position; var Tether = extend(TetherClass, TetherBase); /* globals TetherBase */ 'use strict'; 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'); } }; })(); var _TetherBase$Utils = TetherBase.Utils; var getBounds = _TetherBase$Utils.getBounds; var extend = _TetherBase$Utils.extend; var updateClasses = _TetherBase$Utils.updateClasses; var defer = _TetherBase$Utils.defer; var BOUNDS_FORMAT = ['left', 'top', 'right', 'bottom']; function getBoundingRect(tether, to) { if (to === 'scrollParent') { to = tether.scrollParent; } else if (to === 'window') { to = [pageXOffset, pageYOffset, innerWidth + pageXOffset, innerHeight + pageYOffset]; } if (to === document) { to = to.documentElement; } if (typeof to.nodeType !== 'undefined') { (function () { var size = getBounds(to); var pos = size; var style = getComputedStyle(to); to = [pos.left, pos.top, size.width + pos.left, size.height + pos.top]; BOUNDS_FORMAT.forEach(function (side, i) { side = side[0].toUpperCase() + side.substr(1); if (side === 'Top' || side === 'Left') { to[i] += parseFloat(style['border' + side + 'Width']); } else { to[i] -= parseFloat(style['border' + side + 'Width']); } }); })(); } return to; } TetherBase.modules.push({ position: function position(_ref) { var _this = this; var top = _ref.top; var left = _ref.left; var targetAttachment = _ref.targetAttachment; if (!this.options.constraints) { return true; } var _cache = this.cache('element-bounds', function () { return getBounds(_this.element); }); var height = _cache.height; var width = _cache.width; if (width === 0 && height === 0 && typeof this.lastSize !== 'undefined') { var _lastSize = this.lastSize; // Handle the item getting hidden as a result of our positioning without glitching // the classes in and out width = _lastSize.width; height = _lastSize.height; } var targetSize = this.cache('target-bounds', function () { return _this.getTargetBounds(); }); var targetHeight = targetSize.height; var targetWidth = targetSize.width; var allClasses = [this.getClass('pinned'), this.getClass('out-of-bounds')]; this.options.constraints.forEach(function (constraint) { var outOfBoundsClass = constraint.outOfBoundsClass; var pinnedClass = constraint.pinnedClass; if (outOfBoundsClass) { allClasses.push(outOfBoundsClass); } if (pinnedClass) { allClasses.push(pinnedClass); } }); allClasses.forEach(function (cls) { ['left', 'top', 'right', 'bottom'].forEach(function (side) { allClasses.push(cls + '-' + side); }); }); var addClasses = []; var tAttachment = extend({}, targetAttachment); var eAttachment = extend({}, this.attachment); this.options.constraints.forEach(function (constraint) { var to = constraint.to; var attachment = constraint.attachment; var pin = constraint.pin; if (typeof attachment === 'undefined') { attachment = ''; } var changeAttachX = undefined, changeAttachY = undefined; if (attachment.indexOf(' ') >= 0) { var _attachment$split = attachment.split(' '); var _attachment$split2 = _slicedToArray(_attachment$split, 2); changeAttachY = _attachment$split2[0]; changeAttachX = _attachment$split2[1]; } else { changeAttachX = changeAttachY = attachment; } var bounds = getBoundingRect(_this, to); if (changeAttachY === 'target' || changeAttachY === 'both') { if (top < bounds[1] && tAttachment.top === 'top') { top += targetHeight; tAttachment.top = 'bottom'; } if (top + height > bounds[3] && tAttachment.top === 'bottom') { top -= targetHeight; tAttachment.top = 'top'; } } if (changeAttachY === 'together') { if (top < bounds[1] && tAttachment.top === 'top') { if (eAttachment.top === 'bottom') { top += targetHeight; tAttachment.top = 'bottom'; top += height; eAttachment.top = 'top'; } else if (eAttachment.top === 'top') { top += targetHeight; tAttachment.top = 'bottom'; top -= height; eAttachment.top = 'bottom'; } } if (top + height > bounds[3] && tAttachment.top === 'bottom') { if (eAttachment.top === 'top') { top -= targetHeight; tAttachment.top = 'top'; top -= height; eAttachment.top = 'bottom'; } else if (eAttachment.top === 'bottom') { top -= targetHeight; tAttachment.top = 'top'; top += height; eAttachment.top = 'top'; } } if (tAttachment.top === 'middle') { if (top + height > bounds[3] && eAttachment.top === 'top') { top -= height; eAttachment.top = 'bottom'; } else if (top < bounds[1] && eAttachment.top === 'bottom') { top += height; eAttachment.top = 'top'; } } } if (changeAttachX === 'target' || changeAttachX === 'both') { if (left < bounds[0] && tAttachment.left === 'left') { left += targetWidth; tAttachment.left = 'right'; } if (left + width > bounds[2] && tAttachment.left === 'right') { left -= targetWidth; tAttachment.left = 'left'; } } if (changeAttachX === 'together') { if (left < bounds[0] && tAttachment.left === 'left') { if (eAttachment.left === 'right') { left += targetWidth; tAttachment.left = 'right'; left += width; eAttachment.left = 'left'; } else if (eAttachment.left === 'left') { left += targetWidth; tAttachment.left = 'right'; left -= width; eAttachment.left = 'right'; } } else if (left + width > bounds[2] && tAttachment.left === 'right') { if (eAttachment.left === 'left') { left -= targetWidth; tAttachment.left = 'left'; left -= width; eAttachment.left = 'right'; } else if (eAttachment.left === 'right') { left -= targetWidth; tAttachment.left = 'left'; left += width; eAttachment.left = 'left'; } } else if (tAttachment.left === 'center') { if (left + width > bounds[2] && eAttachment.left === 'left') { left -= width; eAttachment.left = 'right'; } else if (left < bounds[0] && eAttachment.left === 'right') { left += width; eAttachment.left = 'left'; } } } if (changeAttachY === 'element' || changeAttachY === 'both') { if (top < bounds[1] && eAttachment.top === 'bottom') { top += height; eAttachment.top = 'top'; } if (top + height > bounds[3] && eAttachment.top === 'top') { top -= height; eAttachment.top = 'bottom'; } } if (changeAttachX === 'element' || changeAttachX === 'both') { if (left < bounds[0]) { if (eAttachment.left === 'right') { left += width; eAttachment.left = 'left'; } else if (eAttachment.left === 'center') { left += width / 2; eAttachment.left = 'left'; } } if (left + width > bounds[2]) { if (eAttachment.left === 'left') { left -= width; eAttachment.left = 'right'; } else if (eAttachment.left === 'center') { left -= width / 2; eAttachment.left = 'right'; } } } if (typeof pin === 'string') { pin = pin.split(',').map(function (p) { return p.trim(); }); } else if (pin === true) { pin = ['top', 'left', 'right', 'bottom']; } pin = pin || []; var pinned = []; var oob = []; if (top < bounds[1]) { if (pin.indexOf('top') >= 0) { top = bounds[1]; pinned.push('top'); } else { oob.push('top'); } } if (top + height > bounds[3]) { if (pin.indexOf('bottom') >= 0) { top = bounds[3] - height; pinned.push('bottom'); } else { oob.push('bottom'); } } if (left < bounds[0]) { if (pin.indexOf('left') >= 0) { left = bounds[0]; pinned.push('left'); } else { oob.push('left'); } } if (left + width > bounds[2]) { if (pin.indexOf('right') >= 0) { left = bounds[2] - width; pinned.push('right'); } else { oob.push('right'); } } if (pinned.length) { (function () { var pinnedClass = undefined; if (typeof _this.options.pinnedClass !== 'undefined') { pinnedClass = _this.options.pinnedClass; } else { pinnedClass = _this.getClass('pinned'); } addClasses.push(pinnedClass); pinned.forEach(function (side) { addClasses.push(pinnedClass + '-' + side); }); })(); } if (oob.length) { (function () { var oobClass = undefined; if (typeof _this.options.outOfBoundsClass !== 'undefined') { oobClass = _this.options.outOfBoundsClass; } else { oobClass = _this.getClass('out-of-bounds'); } addClasses.push(oobClass); oob.forEach(function (side) { addClasses.push(oobClass + '-' + side); }); })(); } if (pinned.indexOf('left') >= 0 || pinned.indexOf('right') >= 0) { eAttachment.left = tAttachment.left = false; } if (pinned.indexOf('top') >= 0 || pinned.indexOf('bottom') >= 0) { eAttachment.top = tAttachment.top = false; } if (tAttachment.top !== targetAttachment.top || tAttachment.left !== targetAttachment.left || eAttachment.top !== _this.attachment.top || eAttachment.left !== _this.attachment.left) { _this.updateAttachClasses(eAttachment, tAttachment); } }); defer(function () { if (!(_this.options.addTargetClasses === false)) { updateClasses(_this.target, addClasses, allClasses); } updateClasses(_this.element, addClasses, allClasses); }); return { top: top, left: left }; } }); /* globals TetherBase */ 'use strict'; var _TetherBase$Utils = TetherBase.Utils; var getBounds = _TetherBase$Utils.getBounds; var updateClasses = _TetherBase$Utils.updateClasses; var defer = _TetherBase$Utils.defer; TetherBase.modules.push({ position: function position(_ref) { var _this = this; var top = _ref.top; var left = _ref.left; var _cache = this.cache('element-bounds', function () { return getBounds(_this.element); }); var height = _cache.height; var width = _cache.width; var targetPos = this.getTargetBounds(); var bottom = top + height; var right = left + width; var abutted = []; if (top <= targetPos.bottom && bottom >= targetPos.top) { ['left', 'right'].forEach(function (side) { var targetPosSide = targetPos[side]; if (targetPosSide === left || targetPosSide === right) { abutted.push(side); } }); } if (left <= targetPos.right && right >= targetPos.left) { ['top', 'bottom'].forEach(function (side) { var targetPosSide = targetPos[side]; if (targetPosSide === top || targetPosSide === bottom) { abutted.push(side); } }); } var allClasses = []; var addClasses = []; var sides = ['left', 'top', 'right', 'bottom']; allClasses.push(this.getClass('abutted')); sides.forEach(function (side) { allClasses.push(_this.getClass('abutted') + '-' + side); }); if (abutted.length) { addClasses.push(this.getClass('abutted')); } abutted.forEach(function (side) { addClasses.push(_this.getClass('abutted') + '-' + side); }); defer(function () { if (!(_this.options.addTargetClasses === false)) { updateClasses(_this.target, addClasses, allClasses); } updateClasses(_this.element, addClasses, allClasses); }); return true; } }); /* globals TetherBase */ 'use strict'; 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'); } }; })(); TetherBase.modules.push({ position: function position(_ref) { var top = _ref.top; var left = _ref.left; if (!this.options.shift) { return; } var shift = this.options.shift; if (typeof this.options.shift === 'function') { shift = this.options.shift.call(this, { top: top, left: left }); } var shiftTop = undefined, shiftLeft = undefined; if (typeof shift === 'string') { shift = shift.split(' '); shift[1] = shift[1] || shift[0]; var _shift = shift; var _shift2 = _slicedToArray(_shift, 2); shiftTop = _shift2[0]; shiftLeft = _shift2[1]; shiftTop = parseFloat(shiftTop, 10); shiftLeft = parseFloat(shiftLeft, 10); } else { shiftTop = shift.top; shiftLeft = shift.left; } top += shiftTop; left += shiftLeft; return { top: top, left: left }; } }); return Tether; }));