+ * Prefer `scheduleUpdate` over `update` because of performance reasons. + * @method + * @memberof Popper + */ + function update() { + // if popper is destroyed, don't perform any further update + if (this.state.isDestroyed) { + return; + } + + var data = { + instance: this, + styles: {}, + arrowStyles: {}, + attributes: {}, + flipped: false, + offsets: {} + }; + + // compute reference element offsets + data.offsets.reference = getReferenceOffsets(this.state, this.popper, this.reference, this.options.positionFixed); + + // compute auto placement, store placement inside the data object, + // modifiers will be able to edit `placement` if needed + // and refer to originalPlacement to know the original value + data.placement = computeAutoPlacement(this.options.placement, data.offsets.reference, this.popper, this.reference, this.options.modifiers.flip.boundariesElement, this.options.modifiers.flip.padding); + + // store the computed placement inside `originalPlacement` + data.originalPlacement = data.placement; + + data.positionFixed = this.options.positionFixed; + + // compute the popper offsets + data.offsets.popper = getPopperOffsets(this.popper, data.offsets.reference, data.placement); + + data.offsets.popper.position = this.options.positionFixed ? 'fixed' : 'absolute'; + + // run the modifiers + data = runModifiers(this.modifiers, data); + + // the first `update` will call `onCreate` callback + // the other ones will call `onUpdate` callback + if (!this.state.isCreated) { + this.state.isCreated = true; + this.options.onCreate(data); + } else { + this.options.onUpdate(data); + } + } + + /** + * Helper used to know if the given modifier is enabled. + * @method + * @memberof Popper.Utils + * @returns {Boolean} + */ + function isModifierEnabled(modifiers, modifierName) { + return modifiers.some(function (_ref) { + var name = _ref.name, + enabled = _ref.enabled; + return enabled && name === modifierName; + }); + } + + /** + * Get the prefixed supported property name + * @method + * @memberof Popper.Utils + * @argument {String} property (camelCase) + * @returns {String} prefixed property (camelCase or PascalCase, depending on the vendor prefix) + */ + function getSupportedPropertyName(property) { + var prefixes = [false, 'ms', 'Webkit', 'Moz', 'O']; + var upperProp = property.charAt(0).toUpperCase() + property.slice(1); + + for (var i = 0; i < prefixes.length; i++) { + var prefix = prefixes[i]; + var toCheck = prefix ? '' + prefix + upperProp : property; + if (typeof document.body.style[toCheck] !== 'undefined') { + return toCheck; + } + } + return null; + } + + /** + * Destroys the popper. + * @method + * @memberof Popper + */ + function destroy() { + this.state.isDestroyed = true; + + // touch DOM only if `applyStyle` modifier is enabled + if (isModifierEnabled(this.modifiers, 'applyStyle')) { + this.popper.removeAttribute('x-placement'); + this.popper.style.position = ''; + this.popper.style.top = ''; + this.popper.style.left = ''; + this.popper.style.right = ''; + this.popper.style.bottom = ''; + this.popper.style.willChange = ''; + this.popper.style[getSupportedPropertyName('transform')] = ''; + } + + this.disableEventListeners(); + + // remove the popper if user explicity asked for the deletion on destroy + // do not use `remove` because IE11 doesn't support it + if (this.options.removeOnDestroy) { + this.popper.parentNode.removeChild(this.popper); + } + return this; + } + + /** + * Get the window associated with the element + * @argument {Element} element + * @returns {Window} + */ + function getWindow(element) { + var ownerDocument = element.ownerDocument; + return ownerDocument ? ownerDocument.defaultView : window; + } + + function attachToScrollParents(scrollParent, event, callback, scrollParents) { + var isBody = scrollParent.nodeName === 'BODY'; + var target = isBody ? scrollParent.ownerDocument.defaultView : scrollParent; + target.addEventListener(event, callback, { passive: true }); + + if (!isBody) { + attachToScrollParents(getScrollParent(target.parentNode), event, callback, scrollParents); + } + scrollParents.push(target); + } + + /** + * Setup needed event listeners used to update the popper position + * @method + * @memberof Popper.Utils + * @private + */ + function setupEventListeners(reference, options, state, updateBound) { + // Resize event listener on window + state.updateBound = updateBound; + getWindow(reference).addEventListener('resize', state.updateBound, { passive: true }); + + // Scroll event listener on scroll parents + var scrollElement = getScrollParent(reference); + attachToScrollParents(scrollElement, 'scroll', state.updateBound, state.scrollParents); + state.scrollElement = scrollElement; + state.eventsEnabled = true; + + return state; + } + + /** + * It will add resize/scroll events and start recalculating + * position of the popper element when they are triggered. + * @method + * @memberof Popper + */ + function enableEventListeners() { + if (!this.state.eventsEnabled) { + this.state = setupEventListeners(this.reference, this.options, this.state, this.scheduleUpdate); + } + } + + /** + * Remove event listeners used to update the popper position + * @method + * @memberof Popper.Utils + * @private + */ + function removeEventListeners(reference, state) { + // Remove resize event listener on window + getWindow(reference).removeEventListener('resize', state.updateBound); + + // Remove scroll event listener on scroll parents + state.scrollParents.forEach(function (target) { + target.removeEventListener('scroll', state.updateBound); + }); + + // Reset state + state.updateBound = null; + state.scrollParents = []; + state.scrollElement = null; + state.eventsEnabled = false; + return state; + } + + /** + * It will remove resize/scroll events and won't recalculate popper position + * when they are triggered. It also won't trigger `onUpdate` callback anymore, + * unless you call `update` method manually. + * @method + * @memberof Popper + */ + function disableEventListeners() { + if (this.state.eventsEnabled) { + cancelAnimationFrame(this.scheduleUpdate); + this.state = removeEventListeners(this.reference, this.state); + } + } + + /** + * Tells if a given input is a number + * @method + * @memberof Popper.Utils + * @param {*} input to check + * @return {Boolean} + */ + function isNumeric(n) { + return n !== '' && !isNaN(parseFloat(n)) && isFinite(n); + } + + /** + * Set the style to the given popper + * @method + * @memberof Popper.Utils + * @argument {Element} element - Element to apply the style to + * @argument {Object} styles + * Object with a list of properties and values which will be applied to the element + */ + function setStyles(element, styles) { + Object.keys(styles).forEach(function (prop) { + var unit = ''; + // add unit if the value is numeric and is one of the following + if (['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== -1 && isNumeric(styles[prop])) { + unit = 'px'; + } + element.style[prop] = styles[prop] + unit; + }); + } + + /** + * Set the attributes to the given popper + * @method + * @memberof Popper.Utils + * @argument {Element} element - Element to apply the attributes to + * @argument {Object} styles + * Object with a list of properties and values which will be applied to the element + */ + function setAttributes(element, attributes) { + Object.keys(attributes).forEach(function (prop) { + var value = attributes[prop]; + if (value !== false) { + element.setAttribute(prop, attributes[prop]); + } else { + element.removeAttribute(prop); + } + }); + } + + /** + * @function + * @memberof Modifiers + * @argument {Object} data - The data object generated by `update` method + * @argument {Object} data.styles - List of style properties - values to apply to popper element + * @argument {Object} data.attributes - List of attribute properties - values to apply to popper element + * @argument {Object} options - Modifiers configuration and options + * @returns {Object} The same data object + */ + function applyStyle(data) { + // any property present in `data.styles` will be applied to the popper, + // in this way we can make the 3rd party modifiers add custom styles to it + // Be aware, modifiers could override the properties defined in the previous + // lines of this modifier! + setStyles(data.instance.popper, data.styles); + + // any property present in `data.attributes` will be applied to the popper, + // they will be set as HTML attributes of the element + setAttributes(data.instance.popper, data.attributes); + + // if arrowElement is defined and arrowStyles has some properties + if (data.arrowElement && Object.keys(data.arrowStyles).length) { + setStyles(data.arrowElement, data.arrowStyles); + } + + return data; + } + + /** + * Set the x-placement attribute before everything else because it could be used + * to add margins to the popper margins needs to be calculated to get the + * correct popper offsets. + * @method + * @memberof Popper.modifiers + * @param {HTMLElement} reference - The reference element used to position the popper + * @param {HTMLElement} popper - The HTML element used as popper + * @param {Object} options - Popper.js options + */ + function applyStyleOnLoad(reference, popper, options, modifierOptions, state) { + // compute reference element offsets + var referenceOffsets = getReferenceOffsets(state, popper, reference, options.positionFixed); + + // compute auto placement, store placement inside the data object, + // modifiers will be able to edit `placement` if needed + // and refer to originalPlacement to know the original value + var placement = computeAutoPlacement(options.placement, referenceOffsets, popper, reference, options.modifiers.flip.boundariesElement, options.modifiers.flip.padding); + + popper.setAttribute('x-placement', placement); + + // Apply `position` to popper before anything else because + // without the position applied we can't guarantee correct computations + setStyles(popper, { position: options.positionFixed ? 'fixed' : 'absolute' }); + + return options; + } + + /** + * @function + * @memberof Popper.Utils + * @argument {Object} data - The data object generated by `update` method + * @argument {Boolean} shouldRound - If the offsets should be rounded at all + * @returns {Object} The popper's position offsets rounded + * + * The tale of pixel-perfect positioning. It's still not 100% perfect, but as + * good as it can be within reason. + * Discussion here: https://github.com/FezVrasta/popper.js/pull/715 + * + * Low DPI screens cause a popper to be blurry if not using full pixels (Safari + * as well on High DPI screens). + * + * Firefox prefers no rounding for positioning and does not have blurriness on + * high DPI screens. + * + * Only horizontal placement and left/right values need to be considered. + */ + function getRoundedOffsets(data, shouldRound) { + var _data$offsets = data.offsets, + popper = _data$offsets.popper, + reference = _data$offsets.reference; + var round = Math.round, + floor = Math.floor; + + var noRound = function noRound(v) { + return v; + }; + + var referenceWidth = round(reference.width); + var popperWidth = round(popper.width); + + var isVertical = ['left', 'right'].indexOf(data.placement) !== -1; + var isVariation = data.placement.indexOf('-') !== -1; + var sameWidthParity = referenceWidth % 2 === popperWidth % 2; + var bothOddWidth = referenceWidth % 2 === 1 && popperWidth % 2 === 1; + + var horizontalToInteger = !shouldRound ? noRound : isVertical || isVariation || sameWidthParity ? round : floor; + var verticalToInteger = !shouldRound ? noRound : round; + + return { + left: horizontalToInteger(bothOddWidth && !isVariation && shouldRound ? popper.left - 1 : popper.left), + top: verticalToInteger(popper.top), + bottom: verticalToInteger(popper.bottom), + right: horizontalToInteger(popper.right) + }; + } + + var isFirefox = isBrowser && /Firefox/i.test(navigator.userAgent); + + /** + * @function + * @memberof Modifiers + * @argument {Object} data - The data object generated by `update` method + * @argument {Object} options - Modifiers configuration and options + * @returns {Object} The data object, properly modified + */ + function computeStyle(data, options) { + var x = options.x, + y = options.y; + var popper = data.offsets.popper; + + // Remove this legacy support in Popper.js v2 + + var legacyGpuAccelerationOption = find(data.instance.modifiers, function (modifier) { + return modifier.name === 'applyStyle'; + }).gpuAcceleration; + if (legacyGpuAccelerationOption !== undefined) { + console.warn('WARNING: `gpuAcceleration` option moved to `computeStyle` modifier and will not be supported in future versions of Popper.js!'); + } + var gpuAcceleration = legacyGpuAccelerationOption !== undefined ? legacyGpuAccelerationOption : options.gpuAcceleration; + + var offsetParent = getOffsetParent(data.instance.popper); + var offsetParentRect = getBoundingClientRect(offsetParent); + + // Styles + var styles = { + position: popper.position + }; + + var offsets = getRoundedOffsets(data, window.devicePixelRatio < 2 || !isFirefox); + + var sideA = x === 'bottom' ? 'top' : 'bottom'; + var sideB = y === 'right' ? 'left' : 'right'; + + // if gpuAcceleration is set to `true` and transform is supported, + // we use `translate3d` to apply the position to the popper we + // automatically use the supported prefixed version if needed + var prefixedProperty = getSupportedPropertyName('transform'); + + // now, let's make a step back and look at this code closely (wtf?) + // If the content of the popper grows once it's been positioned, it + // may happen that the popper gets misplaced because of the new content + // overflowing its reference element + // To avoid this problem, we provide two options (x and y), which allow + // the consumer to define the offset origin. + // If we position a popper on top of a reference element, we can set + // `x` to `top` to make the popper grow towards its top instead of + // its bottom. + var left = void 0, + top = void 0; + if (sideA === 'bottom') { + // when offsetParent is the positioning is relative to the bottom of the screen (excluding the scrollbar) + // and not the bottom of the html element + if (offsetParent.nodeName === 'HTML') { + top = -offsetParent.clientHeight + offsets.bottom; + } else { + top = -offsetParentRect.height + offsets.bottom; + } + } else { + top = offsets.top; + } + if (sideB === 'right') { + if (offsetParent.nodeName === 'HTML') { + left = -offsetParent.clientWidth + offsets.right; + } else { + left = -offsetParentRect.width + offsets.right; + } + } else { + left = offsets.left; + } + if (gpuAcceleration && prefixedProperty) { + styles[prefixedProperty] = 'translate3d(' + left + 'px, ' + top + 'px, 0)'; + styles[sideA] = 0; + styles[sideB] = 0; + styles.willChange = 'transform'; + } else { + // othwerise, we use the standard `top`, `left`, `bottom` and `right` properties + var invertTop = sideA === 'bottom' ? -1 : 1; + var invertLeft = sideB === 'right' ? -1 : 1; + styles[sideA] = top * invertTop; + styles[sideB] = left * invertLeft; + styles.willChange = sideA + ', ' + sideB; + } + + // Attributes + var attributes = { + 'x-placement': data.placement + }; + + // Update `data` attributes, styles and arrowStyles + data.attributes = _extends({}, attributes, data.attributes); + data.styles = _extends({}, styles, data.styles); + data.arrowStyles = _extends({}, data.offsets.arrow, data.arrowStyles); + + return data; + } + + /** + * Helper used to know if the given modifier depends from another one.
+ * It checks if the needed modifier is listed and enabled. + * @method + * @memberof Popper.Utils + * @param {Array} modifiers - list of modifiers + * @param {String} requestingName - name of requesting modifier + * @param {String} requestedName - name of requested modifier + * @returns {Boolean} + */ + function isModifierRequired(modifiers, requestingName, requestedName) { + var requesting = find(modifiers, function (_ref) { + var name = _ref.name; + return name === requestingName; + }); + + var isRequired = !!requesting && modifiers.some(function (modifier) { + return modifier.name === requestedName && modifier.enabled && modifier.order < requesting.order; + }); + + if (!isRequired) { + var _requesting = '`' + requestingName + '`'; + var requested = '`' + requestedName + '`'; + console.warn(requested + ' modifier is required by ' + _requesting + ' modifier in order to work, be sure to include it before ' + _requesting + '!'); + } + return isRequired; + } + + /** + * @function + * @memberof Modifiers + * @argument {Object} data - The data object generated by update method + * @argument {Object} options - Modifiers configuration and options + * @returns {Object} The data object, properly modified + */ + function arrow(data, options) { + var _data$offsets$arrow; + + // arrow depends on keepTogether in order to work + if (!isModifierRequired(data.instance.modifiers, 'arrow', 'keepTogether')) { + return data; + } + + var arrowElement = options.element; + + // if arrowElement is a string, suppose it's a CSS selector + if (typeof arrowElement === 'string') { + arrowElement = data.instance.popper.querySelector(arrowElement); + + // if arrowElement is not found, don't run the modifier + if (!arrowElement) { + return data; + } + } else { + // if the arrowElement isn't a query selector we must check that the + // provided DOM node is child of its popper node + if (!data.instance.popper.contains(arrowElement)) { + console.warn('WARNING: `arrow.element` must be child of its popper element!'); + return data; + } + } + + var placement = data.placement.split('-')[0]; + var _data$offsets = data.offsets, + popper = _data$offsets.popper, + reference = _data$offsets.reference; + + var isVertical = ['left', 'right'].indexOf(placement) !== -1; + + var len = isVertical ? 'height' : 'width'; + var sideCapitalized = isVertical ? 'Top' : 'Left'; + var side = sideCapitalized.toLowerCase(); + var altSide = isVertical ? 'left' : 'top'; + var opSide = isVertical ? 'bottom' : 'right'; + var arrowElementSize = getOuterSizes(arrowElement)[len]; + + // + // extends keepTogether behavior making sure the popper and its + // reference have enough pixels in conjunction + // + + // top/left side + if (reference[opSide] - arrowElementSize < popper[side]) { + data.offsets.popper[side] -= popper[side] - (reference[opSide] - arrowElementSize); + } + // bottom/right side + if (reference[side] + arrowElementSize > popper[opSide]) { + data.offsets.popper[side] += reference[side] + arrowElementSize - popper[opSide]; + } + data.offsets.popper = getClientRect(data.offsets.popper); + + // compute center of the popper + var center = reference[side] + reference[len] / 2 - arrowElementSize / 2; + + // Compute the sideValue using the updated popper offsets + // take popper margin in account because we don't have this info available + var css = getStyleComputedProperty(data.instance.popper); + var popperMarginSide = parseFloat(css['margin' + sideCapitalized], 10); + var popperBorderSide = parseFloat(css['border' + sideCapitalized + 'Width'], 10); + var sideValue = center - data.offsets.popper[side] - popperMarginSide - popperBorderSide; + + // prevent arrowElement from being placed not contiguously to its popper + sideValue = Math.max(Math.min(popper[len] - arrowElementSize, sideValue), 0); + + data.arrowElement = arrowElement; + data.offsets.arrow = (_data$offsets$arrow = {}, defineProperty(_data$offsets$arrow, side, Math.round(sideValue)), defineProperty(_data$offsets$arrow, altSide, ''), _data$offsets$arrow); + + return data; + } + + /** + * Get the opposite placement variation of the given one + * @method + * @memberof Popper.Utils + * @argument {String} placement variation + * @returns {String} flipped placement variation + */ + function getOppositeVariation(variation) { + if (variation === 'end') { + return 'start'; + } else if (variation === 'start') { + return 'end'; + } + return variation; + } + + /** + * List of accepted placements to use as values of the `placement` option.
+ * Valid placements are: + * - `auto` + * - `top` + * - `right` + * - `bottom` + * - `left` + * + * Each placement can have a variation from this list: + * - `-start` + * - `-end` + * + * Variations are interpreted easily if you think of them as the left to right + * written languages. Horizontally (`top` and `bottom`), `start` is left and `end` + * is right.
+ * Vertically (`left` and `right`), `start` is top and `end` is bottom. + * + * Some valid examples are: + * - `top-end` (on top of reference, right aligned) + * - `right-start` (on right of reference, top aligned) + * - `bottom` (on bottom, centered) + * - `auto-end` (on the side with more space available, alignment depends by placement) + * + * @static + * @type {Array} + * @enum {String} + * @readonly + * @method placements + * @memberof Popper + */ + var placements = ['auto-start', 'auto', 'auto-end', 'top-start', 'top', 'top-end', 'right-start', 'right', 'right-end', 'bottom-end', 'bottom', 'bottom-start', 'left-end', 'left', 'left-start']; + + // Get rid of `auto` `auto-start` and `auto-end` + var validPlacements = placements.slice(3); + + /** + * Given an initial placement, returns all the subsequent placements + * clockwise (or counter-clockwise). + * + * @method + * @memberof Popper.Utils + * @argument {String} placement - A valid placement (it accepts variations) + * @argument {Boolean} counter - Set to true to walk the placements counterclockwise + * @returns {Array} placements including their variations + */ + function clockwise(placement) { + var counter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + + var index = validPlacements.indexOf(placement); + var arr = validPlacements.slice(index + 1).concat(validPlacements.slice(0, index)); + return counter ? arr.reverse() : arr; + } + + var BEHAVIORS = { + FLIP: 'flip', + CLOCKWISE: 'clockwise', + COUNTERCLOCKWISE: 'counterclockwise' }; - function areValidElements() { - for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { - args[_key] = arguments[_key]; + /** + * @function + * @memberof Modifiers + * @argument {Object} data - The data object generated by update method + * @argument {Object} options - Modifiers configuration and options + * @returns {Object} The data object, properly modified + */ + function flip(data, options) { + // if `inner` modifier is enabled, we can't use the `flip` modifier + if (isModifierEnabled(data.instance.modifiers, 'inner')) { + return data; } - return !args.some(function (element) { - return !(element && typeof element.getBoundingClientRect === 'function'); + if (data.flipped && data.placement === data.originalPlacement) { + // seems like flip is trying to loop, probably there's not enough space on any of the flippable sides + return data; + } + + var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, options.boundariesElement, data.positionFixed); + + var placement = data.placement.split('-')[0]; + var placementOpposite = getOppositePlacement(placement); + var variation = data.placement.split('-')[1] || ''; + + var flipOrder = []; + + switch (options.behavior) { + case BEHAVIORS.FLIP: + flipOrder = [placement, placementOpposite]; + break; + case BEHAVIORS.CLOCKWISE: + flipOrder = clockwise(placement); + break; + case BEHAVIORS.COUNTERCLOCKWISE: + flipOrder = clockwise(placement, true); + break; + default: + flipOrder = options.behavior; + } + + flipOrder.forEach(function (step, index) { + if (placement !== step || flipOrder.length === index + 1) { + return data; + } + + placement = data.placement.split('-')[0]; + placementOpposite = getOppositePlacement(placement); + + var popperOffsets = data.offsets.popper; + var refOffsets = data.offsets.reference; + + // using floor because the reference offsets may contain decimals we are not going to consider here + var floor = Math.floor; + var overlapsRef = placement === 'left' && floor(popperOffsets.right) > floor(refOffsets.left) || placement === 'right' && floor(popperOffsets.left) < floor(refOffsets.right) || placement === 'top' && floor(popperOffsets.bottom) > floor(refOffsets.top) || placement === 'bottom' && floor(popperOffsets.top) < floor(refOffsets.bottom); + + var overflowsLeft = floor(popperOffsets.left) < floor(boundaries.left); + var overflowsRight = floor(popperOffsets.right) > floor(boundaries.right); + var overflowsTop = floor(popperOffsets.top) < floor(boundaries.top); + var overflowsBottom = floor(popperOffsets.bottom) > floor(boundaries.bottom); + + var overflowsBoundaries = placement === 'left' && overflowsLeft || placement === 'right' && overflowsRight || placement === 'top' && overflowsTop || placement === 'bottom' && overflowsBottom; + + // flip the variation if required + var isVertical = ['top', 'bottom'].indexOf(placement) !== -1; + var flippedVariation = !!options.flipVariations && (isVertical && variation === 'start' && overflowsLeft || isVertical && variation === 'end' && overflowsRight || !isVertical && variation === 'start' && overflowsTop || !isVertical && variation === 'end' && overflowsBottom); + + if (overlapsRef || overflowsBoundaries || flippedVariation) { + // this boolean to detect any flip loop + data.flipped = true; + + if (overlapsRef || overflowsBoundaries) { + placement = flipOrder[index + 1]; + } + + if (flippedVariation) { + variation = getOppositeVariation(variation); + } + + data.placement = placement + (variation ? '-' + variation : ''); + + // this object contains `position`, we want to preserve it along with + // any additional property we may add in the future + data.offsets.popper = _extends({}, data.offsets.popper, getPopperOffsets(data.instance.popper, data.offsets.reference, data.placement)); + + data = runModifiers(data.instance.modifiers, data, 'flip'); + } }); + return data; } - function popperGenerator(generatorOptions) { - if (generatorOptions === void 0) { - generatorOptions = {}; + /** + * @function + * @memberof Modifiers + * @argument {Object} data - The data object generated by update method + * @argument {Object} options - Modifiers configuration and options + * @returns {Object} The data object, properly modified + */ + function keepTogether(data) { + var _data$offsets = data.offsets, + popper = _data$offsets.popper, + reference = _data$offsets.reference; + + var placement = data.placement.split('-')[0]; + var floor = Math.floor; + var isVertical = ['top', 'bottom'].indexOf(placement) !== -1; + var side = isVertical ? 'right' : 'bottom'; + var opSide = isVertical ? 'left' : 'top'; + var measurement = isVertical ? 'width' : 'height'; + + if (popper[side] < floor(reference[opSide])) { + data.offsets.popper[opSide] = floor(reference[opSide]) - popper[measurement]; + } + if (popper[opSide] > floor(reference[side])) { + data.offsets.popper[opSide] = floor(reference[side]); } - var _generatorOptions = generatorOptions, - _generatorOptions$def = _generatorOptions.defaultModifiers, - defaultModifiers = _generatorOptions$def === void 0 ? [] : _generatorOptions$def, - _generatorOptions$def2 = _generatorOptions.defaultOptions, - defaultOptions = _generatorOptions$def2 === void 0 ? DEFAULT_OPTIONS : _generatorOptions$def2; - return function createPopper(reference, popper, options) { - if (options === void 0) { - options = defaultOptions; - } - - var state = { - placement: 'bottom', - orderedModifiers: [], - options: Object.assign(Object.assign({}, DEFAULT_OPTIONS), defaultOptions), - modifiersData: {}, - elements: { - reference: reference, - popper: popper - }, - attributes: {}, - styles: {} - }; - var effectCleanupFns = []; - var isDestroyed = false; - var instance = { - state: state, - setOptions: function setOptions(options) { - cleanupModifierEffects(); - state.options = Object.assign(Object.assign(Object.assign({}, defaultOptions), state.options), options); - state.scrollParents = { - reference: isElement$1(reference) ? listScrollParents(reference) : reference.contextElement ? listScrollParents(reference.contextElement) : [], - popper: listScrollParents(popper) - }; // Orders the modifiers based on their dependencies and `phase` - // properties - - var orderedModifiers = orderModifiers(mergeByName([].concat(defaultModifiers, state.options.modifiers))); // Strip out disabled modifiers - - state.orderedModifiers = orderedModifiers.filter(function (m) { - return m.enabled; - }); // Validate the provided modifiers so that the consumer will get warned - - runModifierEffects(); - return instance.update(); - }, - // Sync update – it will always be executed, even if not necessary. This - // is useful for low frequency updates where sync behavior simplifies the - // logic. - // For high frequency updates (e.g. `resize` and `scroll` events), always - // prefer the async Popper#update method - forceUpdate: function forceUpdate() { - if (isDestroyed) { - return; - } - - var _state$elements = state.elements, - reference = _state$elements.reference, - popper = _state$elements.popper; // Don't proceed if `reference` or `popper` are not valid elements - // anymore - - if (!areValidElements(reference, popper)) { - - return; - } // Store the reference and popper rects to be read by modifiers - - - state.rects = { - reference: getCompositeRect(reference, getOffsetParent(popper), state.options.strategy === 'fixed'), - popper: getLayoutRect(popper) - }; // Modifiers have the ability to reset the current update cycle. The - // most common use case for this is the `flip` modifier changing the - // placement, which then needs to re-run all the modifiers, because the - // logic was previously ran for the previous placement and is therefore - // stale/incorrect - - state.reset = false; - state.placement = state.options.placement; // On each update cycle, the `modifiersData` property for each modifier - // is filled with the initial data specified by the modifier. This means - // it doesn't persist and is fresh on each update. - // To ensure persistent data, use `${name}#persistent` - - state.orderedModifiers.forEach(function (modifier) { - return state.modifiersData[modifier.name] = Object.assign({}, modifier.data); - }); - - for (var index = 0; index < state.orderedModifiers.length; index++) { - - if (state.reset === true) { - state.reset = false; - index = -1; - continue; - } - - var _state$orderedModifie = state.orderedModifiers[index], - fn = _state$orderedModifie.fn, - _state$orderedModifie2 = _state$orderedModifie.options, - _options = _state$orderedModifie2 === void 0 ? {} : _state$orderedModifie2, - name = _state$orderedModifie.name; - - if (typeof fn === 'function') { - state = fn({ - state: state, - options: _options, - name: name, - instance: instance - }) || state; - } - } - }, - // Async and optimistically optimized update – it will not be executed if - // not necessary (debounced to run at most once-per-tick) - update: debounce(function () { - return new Promise(function (resolve) { - instance.forceUpdate(); - resolve(state); - }); - }), - destroy: function destroy() { - cleanupModifierEffects(); - isDestroyed = true; - } - }; - - if (!areValidElements(reference, popper)) { - - return instance; - } - - instance.setOptions(options).then(function (state) { - if (!isDestroyed && options.onFirstUpdate) { - options.onFirstUpdate(state); - } - }); // Modifiers have the ability to execute arbitrary code before the first - // update cycle runs. They will be executed in the same order as the update - // cycle. This is useful when a modifier adds some persistent data that - // other modifiers need to use, but the modifier is run after the dependent - // one. - - function runModifierEffects() { - state.orderedModifiers.forEach(function (_ref3) { - var name = _ref3.name, - _ref3$options = _ref3.options, - options = _ref3$options === void 0 ? {} : _ref3$options, - effect = _ref3.effect; - - if (typeof effect === 'function') { - var cleanupFn = effect({ - state: state, - name: name, - instance: instance, - options: options - }); - - var noopFn = function noopFn() {}; - - effectCleanupFns.push(cleanupFn || noopFn); - } - }); - } - - function cleanupModifierEffects() { - effectCleanupFns.forEach(function (fn) { - return fn(); - }); - effectCleanupFns = []; - } - - return instance; - }; + return data; } - var createPopper = /*#__PURE__*/popperGenerator(); // eslint-disable-next-line import/no-unused-modules - var defaultModifiers = [eventListeners, popperOffsets$1, computeStyles$1, applyStyles$1]; - var createPopper$1 = /*#__PURE__*/popperGenerator({ - defaultModifiers: defaultModifiers - }); // eslint-disable-next-line import/no-unused-modules + /** + * Converts a string containing value + unit into a px value number + * @function + * @memberof {modifiers~offset} + * @private + * @argument {String} str - Value + unit string + * @argument {String} measurement - `height` or `width` + * @argument {Object} popperOffsets + * @argument {Object} referenceOffsets + * @returns {Number|String} + * Value in pixels, or original string if no values were extracted + */ + function toValue(str, measurement, popperOffsets, referenceOffsets) { + // separate value from unit + var split = str.match(/((?:\-|\+)?\d*\.?\d*)(.*)/); + var value = +split[1]; + var unit = split[2]; - var defaultModifiers$1 = [eventListeners, popperOffsets$1, computeStyles$1, applyStyles$1, offset$1, flip$1, preventOverflow$1, arrow$1, hide$1]; - var createPopper$2 = /*#__PURE__*/popperGenerator({ - defaultModifiers: defaultModifiers$1 - }); // eslint-disable-next-line import/no-unused-modules + // If it's not a number it's an operator, I guess + if (!value) { + return str; + } - var Popper = /*#__PURE__*/Object.freeze({ - __proto__: null, - popperGenerator: popperGenerator, - detectOverflow: detectOverflow, - createPopperBase: createPopper, - createPopper: createPopper$2, - createPopperLite: createPopper$1, - top: top, - bottom: bottom, - right: right, - left: left, - auto: auto, - basePlacements: basePlacements, - start: start, - end: end, - clippingParents: clippingParents, - viewport: viewport, - popper: popper, - reference: reference, - variationPlacements: variationPlacements, - placements: placements, - beforeRead: beforeRead, - read: read, - afterRead: afterRead, - beforeMain: beforeMain, - main: main, - afterMain: afterMain, - beforeWrite: beforeWrite, - write: write, - afterWrite: afterWrite, - modifierPhases: modifierPhases, - applyStyles: applyStyles$1, - arrow: arrow$1, - computeStyles: computeStyles$1, - eventListeners: eventListeners, - flip: flip$1, - hide: hide$1, - offset: offset$1, - popperOffsets: popperOffsets$1, - preventOverflow: preventOverflow$1 - }); + if (unit.indexOf('%') === 0) { + var element = void 0; + switch (unit) { + case '%p': + element = popperOffsets; + break; + case '%': + case '%r': + default: + element = referenceOffsets; + } + + var rect = getClientRect(element); + return rect[measurement] / 100 * value; + } else if (unit === 'vh' || unit === 'vw') { + // if is a vh or vw, we calculate the size based on the viewport + var size = void 0; + if (unit === 'vh') { + size = Math.max(document.documentElement.clientHeight, window.innerHeight || 0); + } else { + size = Math.max(document.documentElement.clientWidth, window.innerWidth || 0); + } + return size / 100 * value; + } else { + // if is an explicit pixel unit, we get rid of the unit and keep the value + // if is an implicit unit, it's px, and we return just the value + return value; + } + } + + /** + * Parse an `offset` string to extrapolate `x` and `y` numeric offsets. + * @function + * @memberof {modifiers~offset} + * @private + * @argument {String} offset + * @argument {Object} popperOffsets + * @argument {Object} referenceOffsets + * @argument {String} basePlacement + * @returns {Array} a two cells array with x and y offsets in numbers + */ + function parseOffset(offset, popperOffsets, referenceOffsets, basePlacement) { + var offsets = [0, 0]; + + // Use height if placement is left or right and index is 0 otherwise use width + // in this way the first offset will use an axis and the second one + // will use the other one + var useHeight = ['right', 'left'].indexOf(basePlacement) !== -1; + + // Split the offset string to obtain a list of values and operands + // The regex addresses values with the plus or minus sign in front (+10, -20, etc) + var fragments = offset.split(/(\+|\-)/).map(function (frag) { + return frag.trim(); + }); + + // Detect if the offset string contains a pair of values or a single one + // they could be separated by comma or space + var divider = fragments.indexOf(find(fragments, function (frag) { + return frag.search(/,|\s/) !== -1; + })); + + if (fragments[divider] && fragments[divider].indexOf(',') === -1) { + console.warn('Offsets separated by white space(s) are deprecated, use a comma (,) instead.'); + } + + // If divider is found, we divide the list of values and operands to divide + // them by ofset X and Y. + var splitRegex = /\s*,\s*|\s+/; + var ops = divider !== -1 ? [fragments.slice(0, divider).concat([fragments[divider].split(splitRegex)[0]]), [fragments[divider].split(splitRegex)[1]].concat(fragments.slice(divider + 1))] : [fragments]; + + // Convert the values with units to absolute pixels to allow our computations + ops = ops.map(function (op, index) { + // Most of the units rely on the orientation of the popper + var measurement = (index === 1 ? !useHeight : useHeight) ? 'height' : 'width'; + var mergeWithPrevious = false; + return op + // This aggregates any `+` or `-` sign that aren't considered operators + // e.g.: 10 + +5 => [10, +, +5] + .reduce(function (a, b) { + if (a[a.length - 1] === '' && ['+', '-'].indexOf(b) !== -1) { + a[a.length - 1] = b; + mergeWithPrevious = true; + return a; + } else if (mergeWithPrevious) { + a[a.length - 1] += b; + mergeWithPrevious = false; + return a; + } else { + return a.concat(b); + } + }, []) + // Here we convert the string values into number values (in px) + .map(function (str) { + return toValue(str, measurement, popperOffsets, referenceOffsets); + }); + }); + + // Loop trough the offsets arrays and execute the operations + ops.forEach(function (op, index) { + op.forEach(function (frag, index2) { + if (isNumeric(frag)) { + offsets[index] += frag * (op[index2 - 1] === '-' ? -1 : 1); + } + }); + }); + return offsets; + } + + /** + * @function + * @memberof Modifiers + * @argument {Object} data - The data object generated by update method + * @argument {Object} options - Modifiers configuration and options + * @argument {Number|String} options.offset=0 + * The offset value as described in the modifier description + * @returns {Object} The data object, properly modified + */ + function offset(data, _ref) { + var offset = _ref.offset; + var placement = data.placement, + _data$offsets = data.offsets, + popper = _data$offsets.popper, + reference = _data$offsets.reference; + + var basePlacement = placement.split('-')[0]; + + var offsets = void 0; + if (isNumeric(+offset)) { + offsets = [+offset, 0]; + } else { + offsets = parseOffset(offset, popper, reference, basePlacement); + } + + if (basePlacement === 'left') { + popper.top += offsets[0]; + popper.left -= offsets[1]; + } else if (basePlacement === 'right') { + popper.top += offsets[0]; + popper.left += offsets[1]; + } else if (basePlacement === 'top') { + popper.left += offsets[0]; + popper.top -= offsets[1]; + } else if (basePlacement === 'bottom') { + popper.left += offsets[0]; + popper.top += offsets[1]; + } + + data.popper = popper; + return data; + } + + /** + * @function + * @memberof Modifiers + * @argument {Object} data - The data object generated by `update` method + * @argument {Object} options - Modifiers configuration and options + * @returns {Object} The data object, properly modified + */ + function preventOverflow(data, options) { + var boundariesElement = options.boundariesElement || getOffsetParent(data.instance.popper); + + // If offsetParent is the reference element, we really want to + // go one step up and use the next offsetParent as reference to + // avoid to make this modifier completely useless and look like broken + if (data.instance.reference === boundariesElement) { + boundariesElement = getOffsetParent(boundariesElement); + } + + // NOTE: DOM access here + // resets the popper's position so that the document size can be calculated excluding + // the size of the popper element itself + var transformProp = getSupportedPropertyName('transform'); + var popperStyles = data.instance.popper.style; // assignment to help minification + var top = popperStyles.top, + left = popperStyles.left, + transform = popperStyles[transformProp]; + + popperStyles.top = ''; + popperStyles.left = ''; + popperStyles[transformProp] = ''; + + var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, boundariesElement, data.positionFixed); + + // NOTE: DOM access here + // restores the original style properties after the offsets have been computed + popperStyles.top = top; + popperStyles.left = left; + popperStyles[transformProp] = transform; + + options.boundaries = boundaries; + + var order = options.priority; + var popper = data.offsets.popper; + + var check = { + primary: function primary(placement) { + var value = popper[placement]; + if (popper[placement] < boundaries[placement] && !options.escapeWithReference) { + value = Math.max(popper[placement], boundaries[placement]); + } + return defineProperty({}, placement, value); + }, + secondary: function secondary(placement) { + var mainSide = placement === 'right' ? 'left' : 'top'; + var value = popper[mainSide]; + if (popper[placement] > boundaries[placement] && !options.escapeWithReference) { + value = Math.min(popper[mainSide], boundaries[placement] - (placement === 'right' ? popper.width : popper.height)); + } + return defineProperty({}, mainSide, value); + } + }; + + order.forEach(function (placement) { + var side = ['left', 'top'].indexOf(placement) !== -1 ? 'primary' : 'secondary'; + popper = _extends({}, popper, check[side](placement)); + }); + + data.offsets.popper = popper; + + return data; + } + + /** + * @function + * @memberof Modifiers + * @argument {Object} data - The data object generated by `update` method + * @argument {Object} options - Modifiers configuration and options + * @returns {Object} The data object, properly modified + */ + function shift(data) { + var placement = data.placement; + var basePlacement = placement.split('-')[0]; + var shiftvariation = placement.split('-')[1]; + + // if shift shiftvariation is specified, run the modifier + if (shiftvariation) { + var _data$offsets = data.offsets, + reference = _data$offsets.reference, + popper = _data$offsets.popper; + + var isVertical = ['bottom', 'top'].indexOf(basePlacement) !== -1; + var side = isVertical ? 'left' : 'top'; + var measurement = isVertical ? 'width' : 'height'; + + var shiftOffsets = { + start: defineProperty({}, side, reference[side]), + end: defineProperty({}, side, reference[side] + reference[measurement] - popper[measurement]) + }; + + data.offsets.popper = _extends({}, popper, shiftOffsets[shiftvariation]); + } + + return data; + } + + /** + * @function + * @memberof Modifiers + * @argument {Object} data - The data object generated by update method + * @argument {Object} options - Modifiers configuration and options + * @returns {Object} The data object, properly modified + */ + function hide(data) { + if (!isModifierRequired(data.instance.modifiers, 'hide', 'preventOverflow')) { + return data; + } + + var refRect = data.offsets.reference; + var bound = find(data.instance.modifiers, function (modifier) { + return modifier.name === 'preventOverflow'; + }).boundaries; + + if (refRect.bottom < bound.top || refRect.left > bound.right || refRect.top > bound.bottom || refRect.right < bound.left) { + // Avoid unnecessary DOM access if visibility hasn't changed + if (data.hide === true) { + return data; + } + + data.hide = true; + data.attributes['x-out-of-boundaries'] = ''; + } else { + // Avoid unnecessary DOM access if visibility hasn't changed + if (data.hide === false) { + return data; + } + + data.hide = false; + data.attributes['x-out-of-boundaries'] = false; + } + + return data; + } + + /** + * @function + * @memberof Modifiers + * @argument {Object} data - The data object generated by `update` method + * @argument {Object} options - Modifiers configuration and options + * @returns {Object} The data object, properly modified + */ + function inner(data) { + var placement = data.placement; + var basePlacement = placement.split('-')[0]; + var _data$offsets = data.offsets, + popper = _data$offsets.popper, + reference = _data$offsets.reference; + + var isHoriz = ['left', 'right'].indexOf(basePlacement) !== -1; + + var subtractLength = ['top', 'left'].indexOf(basePlacement) === -1; + + popper[isHoriz ? 'left' : 'top'] = reference[basePlacement] - (subtractLength ? popper[isHoriz ? 'width' : 'height'] : 0); + + data.placement = getOppositePlacement(placement); + data.offsets.popper = getClientRect(popper); + + return data; + } + + /** + * Modifier function, each modifier can have a function of this type assigned + * to its `fn` property.
+ * These functions will be called on each update, this means that you must + * make sure they are performant enough to avoid performance bottlenecks. + * + * @function ModifierFn + * @argument {dataObject} data - The data object generated by `update` method + * @argument {Object} options - Modifiers configuration and options + * @returns {dataObject} The data object, properly modified + */ + + /** + * Modifiers are plugins used to alter the behavior of your poppers.
+ * Popper.js uses a set of 9 modifiers to provide all the basic functionalities + * needed by the library. + * + * Usually you don't want to override the `order`, `fn` and `onLoad` props. + * All the other properties are configurations that could be tweaked. + * @namespace modifiers + */ + var modifiers = { + /** + * Modifier used to shift the popper on the start or end of its reference + * element.
+ * It will read the variation of the `placement` property.
+ * It can be one either `-end` or `-start`. + * @memberof modifiers + * @inner + */ + shift: { + /** @prop {number} order=100 - Index used to define the order of execution */ + order: 100, + /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ + enabled: true, + /** @prop {ModifierFn} */ + fn: shift + }, + + /** + * The `offset` modifier can shift your popper on both its axis. + * + * It accepts the following units: + * - `px` or unit-less, interpreted as pixels + * - `%` or `%r`, percentage relative to the length of the reference element + * - `%p`, percentage relative to the length of the popper element + * - `vw`, CSS viewport width unit + * - `vh`, CSS viewport height unit + * + * For length is intended the main axis relative to the placement of the popper.
+ * This means that if the placement is `top` or `bottom`, the length will be the + * `width`. In case of `left` or `right`, it will be the `height`. + * + * You can provide a single value (as `Number` or `String`), or a pair of values + * as `String` divided by a comma or one (or more) white spaces.
+ * The latter is a deprecated method because it leads to confusion and will be + * removed in v2.
+ * Additionally, it accepts additions and subtractions between different units. + * Note that multiplications and divisions aren't supported. + * + * Valid examples are: + * ``` + * 10 + * '10%' + * '10, 10' + * '10%, 10' + * '10 + 10%' + * '10 - 5vh + 3%' + * '-10px + 5vh, 5px - 6%' + * ``` + * > **NB**: If you desire to apply offsets to your poppers in a way that may make them overlap + * > with their reference element, unfortunately, you will have to disable the `flip` modifier. + * > You can read more on this at this [issue](https://github.com/FezVrasta/popper.js/issues/373). + * + * @memberof modifiers + * @inner + */ + offset: { + /** @prop {number} order=200 - Index used to define the order of execution */ + order: 200, + /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ + enabled: true, + /** @prop {ModifierFn} */ + fn: offset, + /** @prop {Number|String} offset=0 + * The offset value as described in the modifier description + */ + offset: 0 + }, + + /** + * Modifier used to prevent the popper from being positioned outside the boundary. + * + * A scenario exists where the reference itself is not within the boundaries.
+ * We can say it has "escaped the boundaries" — or just "escaped".
+ * In this case we need to decide whether the popper should either: + * + * - detach from the reference and remain "trapped" in the boundaries, or + * - if it should ignore the boundary and "escape with its reference" + * + * When `escapeWithReference` is set to`true` and reference is completely + * outside its boundaries, the popper will overflow (or completely leave) + * the boundaries in order to remain attached to the edge of the reference. + * + * @memberof modifiers + * @inner + */ + preventOverflow: { + /** @prop {number} order=300 - Index used to define the order of execution */ + order: 300, + /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ + enabled: true, + /** @prop {ModifierFn} */ + fn: preventOverflow, + /** + * @prop {Array} [priority=['left','right','top','bottom']] + * Popper will try to prevent overflow following these priorities by default, + * then, it could overflow on the left and on top of the `boundariesElement` + */ + priority: ['left', 'right', 'top', 'bottom'], + /** + * @prop {number} padding=5 + * Amount of pixel used to define a minimum distance between the boundaries + * and the popper. This makes sure the popper always has a little padding + * between the edges of its container + */ + padding: 5, + /** + * @prop {String|HTMLElement} boundariesElement='scrollParent' + * Boundaries used by the modifier. Can be `scrollParent`, `window`, + * `viewport` or any DOM element. + */ + boundariesElement: 'scrollParent' + }, + + /** + * Modifier used to make sure the reference and its popper stay near each other + * without leaving any gap between the two. Especially useful when the arrow is + * enabled and you want to ensure that it points to its reference element. + * It cares only about the first axis. You can still have poppers with margin + * between the popper and its reference element. + * @memberof modifiers + * @inner + */ + keepTogether: { + /** @prop {number} order=400 - Index used to define the order of execution */ + order: 400, + /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ + enabled: true, + /** @prop {ModifierFn} */ + fn: keepTogether + }, + + /** + * This modifier is used to move the `arrowElement` of the popper to make + * sure it is positioned between the reference element and its popper element. + * It will read the outer size of the `arrowElement` node to detect how many + * pixels of conjunction are needed. + * + * It has no effect if no `arrowElement` is provided. + * @memberof modifiers + * @inner + */ + arrow: { + /** @prop {number} order=500 - Index used to define the order of execution */ + order: 500, + /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ + enabled: true, + /** @prop {ModifierFn} */ + fn: arrow, + /** @prop {String|HTMLElement} element='[x-arrow]' - Selector or node used as arrow */ + element: '[x-arrow]' + }, + + /** + * Modifier used to flip the popper's placement when it starts to overlap its + * reference element. + * + * Requires the `preventOverflow` modifier before it in order to work. + * + * **NOTE:** this modifier will interrupt the current update cycle and will + * restart it if it detects the need to flip the placement. + * @memberof modifiers + * @inner + */ + flip: { + /** @prop {number} order=600 - Index used to define the order of execution */ + order: 600, + /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ + enabled: true, + /** @prop {ModifierFn} */ + fn: flip, + /** + * @prop {String|Array} behavior='flip' + * The behavior used to change the popper's placement. It can be one of + * `flip`, `clockwise`, `counterclockwise` or an array with a list of valid + * placements (with optional variations) + */ + behavior: 'flip', + /** + * @prop {number} padding=5 + * The popper will flip if it hits the edges of the `boundariesElement` + */ + padding: 5, + /** + * @prop {String|HTMLElement} boundariesElement='viewport' + * The element which will define the boundaries of the popper position. + * The popper will never be placed outside of the defined boundaries + * (except if `keepTogether` is enabled) + */ + boundariesElement: 'viewport' + }, + + /** + * Modifier used to make the popper flow toward the inner of the reference element. + * By default, when this modifier is disabled, the popper will be placed outside + * the reference element. + * @memberof modifiers + * @inner + */ + inner: { + /** @prop {number} order=700 - Index used to define the order of execution */ + order: 700, + /** @prop {Boolean} enabled=false - Whether the modifier is enabled or not */ + enabled: false, + /** @prop {ModifierFn} */ + fn: inner + }, + + /** + * Modifier used to hide the popper when its reference element is outside of the + * popper boundaries. It will set a `x-out-of-boundaries` attribute which can + * be used to hide with a CSS selector the popper when its reference is + * out of boundaries. + * + * Requires the `preventOverflow` modifier before it in order to work. + * @memberof modifiers + * @inner + */ + hide: { + /** @prop {number} order=800 - Index used to define the order of execution */ + order: 800, + /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ + enabled: true, + /** @prop {ModifierFn} */ + fn: hide + }, + + /** + * Computes the style that will be applied to the popper element to gets + * properly positioned. + * + * Note that this modifier will not touch the DOM, it just prepares the styles + * so that `applyStyle` modifier can apply it. This separation is useful + * in case you need to replace `applyStyle` with a custom implementation. + * + * This modifier has `850` as `order` value to maintain backward compatibility + * with previous versions of Popper.js. Expect the modifiers ordering method + * to change in future major versions of the library. + * + * @memberof modifiers + * @inner + */ + computeStyle: { + /** @prop {number} order=850 - Index used to define the order of execution */ + order: 850, + /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ + enabled: true, + /** @prop {ModifierFn} */ + fn: computeStyle, + /** + * @prop {Boolean} gpuAcceleration=true + * If true, it uses the CSS 3D transformation to position the popper. + * Otherwise, it will use the `top` and `left` properties + */ + gpuAcceleration: true, + /** + * @prop {string} [x='bottom'] + * Where to anchor the X axis (`bottom` or `top`). AKA X offset origin. + * Change this if your popper should grow in a direction different from `bottom` + */ + x: 'bottom', + /** + * @prop {string} [x='left'] + * Where to anchor the Y axis (`left` or `right`). AKA Y offset origin. + * Change this if your popper should grow in a direction different from `right` + */ + y: 'right' + }, + + /** + * Applies the computed styles to the popper element. + * + * All the DOM manipulations are limited to this modifier. This is useful in case + * you want to integrate Popper.js inside a framework or view library and you + * want to delegate all the DOM manipulations to it. + * + * Note that if you disable this modifier, you must make sure the popper element + * has its position set to `absolute` before Popper.js can do its work! + * + * Just disable this modifier and define your own to achieve the desired effect. + * + * @memberof modifiers + * @inner + */ + applyStyle: { + /** @prop {number} order=900 - Index used to define the order of execution */ + order: 900, + /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ + enabled: true, + /** @prop {ModifierFn} */ + fn: applyStyle, + /** @prop {Function} */ + onLoad: applyStyleOnLoad, + /** + * @deprecated since version 1.10.0, the property moved to `computeStyle` modifier + * @prop {Boolean} gpuAcceleration=true + * If true, it uses the CSS 3D transformation to position the popper. + * Otherwise, it will use the `top` and `left` properties + */ + gpuAcceleration: undefined + } + }; + + /** + * The `dataObject` is an object containing all the information used by Popper.js. + * This object is passed to modifiers and to the `onCreate` and `onUpdate` callbacks. + * @name dataObject + * @property {Object} data.instance The Popper.js instance + * @property {String} data.placement Placement applied to popper + * @property {String} data.originalPlacement Placement originally defined on init + * @property {Boolean} data.flipped True if popper has been flipped by flip modifier + * @property {Boolean} data.hide True if the reference element is out of boundaries, useful to know when to hide the popper + * @property {HTMLElement} data.arrowElement Node used as arrow by arrow modifier + * @property {Object} data.styles Any CSS property defined here will be applied to the popper. It expects the JavaScript nomenclature (eg. `marginBottom`) + * @property {Object} data.arrowStyles Any CSS property defined here will be applied to the popper arrow. It expects the JavaScript nomenclature (eg. `marginBottom`) + * @property {Object} data.boundaries Offsets of the popper boundaries + * @property {Object} data.offsets The measurements of popper, reference and arrow elements + * @property {Object} data.offsets.popper `top`, `left`, `width`, `height` values + * @property {Object} data.offsets.reference `top`, `left`, `width`, `height` values + * @property {Object} data.offsets.arrow] `top` and `left` offsets, only one of them will be different from 0 + */ + + /** + * Default options provided to Popper.js constructor.
+ * These can be overridden using the `options` argument of Popper.js.
+ * To override an option, simply pass an object with the same + * structure of the `options` object, as the 3rd argument. For example: + * ``` + * new Popper(ref, pop, { + * modifiers: { + * preventOverflow: { enabled: false } + * } + * }) + * ``` + * @type {Object} + * @static + * @memberof Popper + */ + var Defaults = { + /** + * Popper's placement. + * @prop {Popper.placements} placement='bottom' + */ + placement: 'bottom', + + /** + * Set this to true if you want popper to position it self in 'fixed' mode + * @prop {Boolean} positionFixed=false + */ + positionFixed: false, + + /** + * Whether events (resize, scroll) are initially enabled. + * @prop {Boolean} eventsEnabled=true + */ + eventsEnabled: true, + + /** + * Set to true if you want to automatically remove the popper when + * you call the `destroy` method. + * @prop {Boolean} removeOnDestroy=false + */ + removeOnDestroy: false, + + /** + * Callback called when the popper is created.
+ * By default, it is set to no-op.
+ * Access Popper.js instance with `data.instance`. + * @prop {onCreate} + */ + onCreate: function onCreate() {}, + + /** + * Callback called when the popper is updated. This callback is not called + * on the initialization/creation of the popper, but only on subsequent + * updates.
+ * By default, it is set to no-op.
+ * Access Popper.js instance with `data.instance`. + * @prop {onUpdate} + */ + onUpdate: function onUpdate() {}, + + /** + * List of modifiers used to modify the offsets before they are applied to the popper. + * They provide most of the functionalities of Popper.js. + * @prop {modifiers} + */ + modifiers: modifiers + }; + + /** + * @callback onCreate + * @param {dataObject} data + */ + + /** + * @callback onUpdate + * @param {dataObject} data + */ + + // Utils + // Methods + var Popper = function () { + /** + * Creates a new Popper.js instance. + * @class Popper + * @param {HTMLElement|referenceObject} reference - The reference element used to position the popper + * @param {HTMLElement} popper - The HTML element used as the popper + * @param {Object} options - Your custom options to override the ones defined in [Defaults](#defaults) + * @return {Object} instance - The generated Popper.js instance + */ + function Popper(reference, popper) { + var _this = this; + + var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + classCallCheck(this, Popper); + + this.scheduleUpdate = function () { + return requestAnimationFrame(_this.update); + }; + + // make update() debounced, so that it only runs at most once-per-tick + this.update = debounce(this.update.bind(this)); + + // with {} we create a new object with the options inside it + this.options = _extends({}, Popper.Defaults, options); + + // init state + this.state = { + isDestroyed: false, + isCreated: false, + scrollParents: [] + }; + + // get reference and popper elements (allow jQuery wrappers) + this.reference = reference && reference.jquery ? reference[0] : reference; + this.popper = popper && popper.jquery ? popper[0] : popper; + + // Deep merge modifiers options + this.options.modifiers = {}; + Object.keys(_extends({}, Popper.Defaults.modifiers, options.modifiers)).forEach(function (name) { + _this.options.modifiers[name] = _extends({}, Popper.Defaults.modifiers[name] || {}, options.modifiers ? options.modifiers[name] : {}); + }); + + // Refactoring modifiers' list (Object => Array) + this.modifiers = Object.keys(this.options.modifiers).map(function (name) { + return _extends({ + name: name + }, _this.options.modifiers[name]); + }) + // sort the modifiers by order + .sort(function (a, b) { + return a.order - b.order; + }); + + // modifiers have the ability to execute arbitrary code when Popper.js get inited + // such code is executed in the same order of its modifier + // they could add new properties to their options configuration + // BE AWARE: don't add options to `options.modifiers.name` but to `modifierOptions`! + this.modifiers.forEach(function (modifierOptions) { + if (modifierOptions.enabled && isFunction(modifierOptions.onLoad)) { + modifierOptions.onLoad(_this.reference, _this.popper, _this.options, modifierOptions, _this.state); + } + }); + + // fire the first update to position the popper in the right place + this.update(); + + var eventsEnabled = this.options.eventsEnabled; + if (eventsEnabled) { + // setup event listeners, they will take care of update the position in specific situations + this.enableEventListeners(); + } + + this.state.eventsEnabled = eventsEnabled; + } + + // We can't use class properties because they don't get listed in the + // class prototype and break stuff like Sinon stubs + + + createClass(Popper, [{ + key: 'update', + value: function update$$1() { + return update.call(this); + } + }, { + key: 'destroy', + value: function destroy$$1() { + return destroy.call(this); + } + }, { + key: 'enableEventListeners', + value: function enableEventListeners$$1() { + return enableEventListeners.call(this); + } + }, { + key: 'disableEventListeners', + value: function disableEventListeners$$1() { + return disableEventListeners.call(this); + } + + /** + * Schedules an update. It will run on the next UI update available. + * @method scheduleUpdate + * @memberof Popper + */ + + + /** + * Collection of utilities useful when writing custom modifiers. + * Starting from version 1.7, this method is available only if you + * include `popper-utils.js` before `popper.js`. + * + * **DEPRECATION**: This way to access PopperUtils is deprecated + * and will be removed in v2! Use the PopperUtils module directly instead. + * Due to the high instability of the methods contained in Utils, we can't + * guarantee them to follow semver. Use them at your own risk! + * @static + * @private + * @type {Object} + * @deprecated since version 1.8 + * @member Utils + * @memberof Popper + */ + + }]); + return Popper; + }(); + + /** + * The `referenceObject` is an object that provides an interface compatible with Popper.js + * and lets you use it as replacement of a real DOM node.
+ * You can use this method to position a popper relatively to a set of coordinates + * in case you don't have a DOM node to use as reference. + * + * ``` + * new Popper(referenceObject, popperNode); + * ``` + * + * NB: This feature isn't supported in Internet Explorer 10. + * @name referenceObject + * @property {Function} data.getBoundingClientRect + * A function that returns a set of coordinates compatible with the native `getBoundingClientRect` method. + * @property {number} data.clientWidth + * An ES6 getter that will return the width of the virtual reference element. + * @property {number} data.clientHeight + * An ES6 getter that will return the height of the virtual reference element. + */ + + + Popper.Utils = (typeof window !== 'undefined' ? window : global).PopperUtils; + Popper.placements = placements; + Popper.Defaults = Defaults; /** * ------------------------------------------------------------------------ @@ -3752,79 +4087,93 @@ */ var NAME$4 = 'dropdown'; + var VERSION$4 = '4.3.1'; var DATA_KEY$4 = 'bs.dropdown'; var EVENT_KEY$4 = "." + DATA_KEY$4; var DATA_API_KEY$4 = '.data-api'; - var ESCAPE_KEY = 'Escape'; - var SPACE_KEY = 'Space'; - var TAB_KEY = 'Tab'; - var ARROW_UP_KEY = 'ArrowUp'; - var ARROW_DOWN_KEY = 'ArrowDown'; - var RIGHT_MOUSE_BUTTON = 2; // MouseEvent.button value for the secondary button, usually the right button + var JQUERY_NO_CONFLICT$4 = $.fn[NAME$4]; + var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key - var REGEXP_KEYDOWN = new RegExp(ARROW_UP_KEY + "|" + ARROW_DOWN_KEY + "|" + ESCAPE_KEY); - var EVENT_HIDE$1 = "hide" + EVENT_KEY$4; - var EVENT_HIDDEN$1 = "hidden" + EVENT_KEY$4; - var EVENT_SHOW$1 = "show" + EVENT_KEY$4; - var EVENT_SHOWN$1 = "shown" + EVENT_KEY$4; - var EVENT_CLICK = "click" + EVENT_KEY$4; - var EVENT_CLICK_DATA_API$4 = "click" + EVENT_KEY$4 + DATA_API_KEY$4; - var EVENT_KEYDOWN_DATA_API = "keydown" + EVENT_KEY$4 + DATA_API_KEY$4; - var EVENT_KEYUP_DATA_API = "keyup" + EVENT_KEY$4 + DATA_API_KEY$4; - var CLASS_NAME_DISABLED = 'disabled'; - var CLASS_NAME_SHOW$1 = 'show'; - var CLASS_NAME_DROPUP = 'dropup'; - var CLASS_NAME_DROPEND = 'dropend'; - var CLASS_NAME_DROPSTART = 'dropstart'; - var CLASS_NAME_NAVBAR = 'navbar'; - var SELECTOR_DATA_TOGGLE$2 = '[data-bs-toggle="dropdown"]'; - var SELECTOR_FORM_CHILD = '.dropdown form'; - var SELECTOR_MENU = '.dropdown-menu'; - var SELECTOR_NAVBAR_NAV = '.navbar-nav'; - var SELECTOR_VISIBLE_ITEMS = '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)'; - var PLACEMENT_TOP = isRTL ? 'top-end' : 'top-start'; - var PLACEMENT_TOPEND = isRTL ? 'top-start' : 'top-end'; - var PLACEMENT_BOTTOM = isRTL ? 'bottom-end' : 'bottom-start'; - var PLACEMENT_BOTTOMEND = isRTL ? 'bottom-start' : 'bottom-end'; - var PLACEMENT_RIGHT = isRTL ? 'left-start' : 'right-start'; - var PLACEMENT_LEFT = isRTL ? 'right-start' : 'left-start'; + var SPACE_KEYCODE = 32; // KeyboardEvent.which value for space key + + var TAB_KEYCODE = 9; // KeyboardEvent.which value for tab key + + var ARROW_UP_KEYCODE = 38; // KeyboardEvent.which value for up arrow key + + var ARROW_DOWN_KEYCODE = 40; // KeyboardEvent.which value for down arrow key + + var RIGHT_MOUSE_BUTTON_WHICH = 3; // MouseEvent.which value for the right button (assuming a right-handed mouse) + + var REGEXP_KEYDOWN = new RegExp(ARROW_UP_KEYCODE + "|" + ARROW_DOWN_KEYCODE + "|" + ESCAPE_KEYCODE); + var Event$4 = { + HIDE: "hide" + EVENT_KEY$4, + HIDDEN: "hidden" + EVENT_KEY$4, + SHOW: "show" + EVENT_KEY$4, + SHOWN: "shown" + EVENT_KEY$4, + CLICK: "click" + EVENT_KEY$4, + CLICK_DATA_API: "click" + EVENT_KEY$4 + DATA_API_KEY$4, + KEYDOWN_DATA_API: "keydown" + EVENT_KEY$4 + DATA_API_KEY$4, + KEYUP_DATA_API: "keyup" + EVENT_KEY$4 + DATA_API_KEY$4 + }; + var ClassName$4 = { + DISABLED: 'disabled', + SHOW: 'show', + DROPUP: 'dropup', + DROPRIGHT: 'dropright', + DROPLEFT: 'dropleft', + MENURIGHT: 'dropdown-menu-right', + MENULEFT: 'dropdown-menu-left', + POSITION_STATIC: 'position-static' + }; + var Selector$4 = { + DATA_TOGGLE: '[data-toggle="dropdown"]', + FORM_CHILD: '.dropdown form', + MENU: '.dropdown-menu', + NAVBAR_NAV: '.navbar-nav', + VISIBLE_ITEMS: '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)' + }; + var AttachmentMap = { + TOP: 'top-start', + TOPEND: 'top-end', + BOTTOM: 'bottom-start', + BOTTOMEND: 'bottom-end', + RIGHT: 'right-start', + RIGHTEND: 'right-end', + LEFT: 'left-start', + LEFTEND: 'left-end' + }; var Default$2 = { offset: 0, flip: true, - boundary: 'clippingParents', + boundary: 'scrollParent', reference: 'toggle', - display: 'dynamic', - popperConfig: null + display: 'dynamic' }; var DefaultType$2 = { offset: '(number|string|function)', flip: 'boolean', boundary: '(string|element)', reference: '(string|element)', - display: 'string', - popperConfig: '(null|object)' + display: 'string' + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + }; - /** - * ------------------------------------------------------------------------ - * Class Definition - * ------------------------------------------------------------------------ - */ - - var Dropdown = /*#__PURE__*/function (_BaseComponent) { - _inheritsLoose(Dropdown, _BaseComponent); + var Dropdown = + /*#__PURE__*/ + function () { function Dropdown(element, config) { - var _this; + this._element = element; + this._popper = null; + this._config = this._getConfig(config); + this._menu = this._getMenuElement(); + this._inNavbar = this._detectNavbar(); - _this = _BaseComponent.call(this, element) || this; - _this._popper = null; - _this._config = _this._getConfig(config); - _this._menu = _this._getMenuElement(); - _this._inNavbar = _this._detectNavbar(); - - _this._addEventListeners(); - - return _this; + this._addEventListeners(); } // Getters @@ -3832,113 +4181,129 @@ // Public _proto.toggle = function toggle() { - if (this._element.disabled || this._element.classList.contains(CLASS_NAME_DISABLED)) { + if (this._element.disabled || $(this._element).hasClass(ClassName$4.DISABLED)) { return; } - var isActive = this._element.classList.contains(CLASS_NAME_SHOW$1); + var parent = Dropdown._getParentFromElement(this._element); - Dropdown.clearMenus(); + var isActive = $(this._menu).hasClass(ClassName$4.SHOW); + + Dropdown._clearMenus(); if (isActive) { return; } - this.show(); - }; - - _proto.show = function show() { - if (this._element.disabled || this._element.classList.contains(CLASS_NAME_DISABLED) || this._menu.classList.contains(CLASS_NAME_SHOW$1)) { - return; - } - - var parent = Dropdown.getParentFromElement(this._element); var relatedTarget = { relatedTarget: this._element }; - var showEvent = EventHandler.trigger(this._element, EVENT_SHOW$1, relatedTarget); + var showEvent = $.Event(Event$4.SHOW, relatedTarget); + $(parent).trigger(showEvent); - if (showEvent.defaultPrevented) { + if (showEvent.isDefaultPrevented()) { return; - } // Totally disable Popper for Dropdowns in Navbar + } // Disable totally Popper.js for Dropdown in Navbar if (!this._inNavbar) { + /** + * Check for Popper dependency + * Popper - https://popper.js.org + */ if (typeof Popper === 'undefined') { - throw new TypeError('Bootstrap\'s dropdowns require Popper (https://popper.js.org)'); + throw new TypeError('Bootstrap\'s dropdowns require Popper.js (https://popper.js.org/)'); } var referenceElement = this._element; if (this._config.reference === 'parent') { referenceElement = parent; - } else if (isElement(this._config.reference)) { + } else if (Util.isElement(this._config.reference)) { referenceElement = this._config.reference; // Check if it's jQuery element if (typeof this._config.reference.jquery !== 'undefined') { referenceElement = this._config.reference[0]; } + } // If boundary is not `scrollParent`, then set position to `static` + // to allow the menu to "escape" the scroll parent's boundaries + // https://github.com/twbs/bootstrap/issues/24251 + + + if (this._config.boundary !== 'scrollParent') { + $(parent).addClass(ClassName$4.POSITION_STATIC); } - this._popper = createPopper$2(referenceElement, this._menu, this._getPopperConfig()); + this._popper = new Popper(referenceElement, this._menu, this._getPopperConfig()); } // If this is a touch-enabled device we add extra // empty mouseover listeners to the body's immediate children; // only needed because of broken event delegation on iOS // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html - if ('ontouchstart' in document.documentElement && !parent.closest(SELECTOR_NAVBAR_NAV)) { - var _ref; - - (_ref = []).concat.apply(_ref, document.body.children).forEach(function (elem) { - return EventHandler.on(elem, 'mouseover', null, noop()); - }); + if ('ontouchstart' in document.documentElement && $(parent).closest(Selector$4.NAVBAR_NAV).length === 0) { + $(document.body).children().on('mouseover', null, $.noop); } this._element.focus(); this._element.setAttribute('aria-expanded', true); - this._menu.classList.toggle(CLASS_NAME_SHOW$1); - - this._element.classList.toggle(CLASS_NAME_SHOW$1); - - EventHandler.trigger(parent, EVENT_SHOWN$1, relatedTarget); + $(this._menu).toggleClass(ClassName$4.SHOW); + $(parent).toggleClass(ClassName$4.SHOW).trigger($.Event(Event$4.SHOWN, relatedTarget)); }; - _proto.hide = function hide() { - if (this._element.disabled || this._element.classList.contains(CLASS_NAME_DISABLED) || !this._menu.classList.contains(CLASS_NAME_SHOW$1)) { + _proto.show = function show() { + if (this._element.disabled || $(this._element).hasClass(ClassName$4.DISABLED) || $(this._menu).hasClass(ClassName$4.SHOW)) { return; } - var parent = Dropdown.getParentFromElement(this._element); var relatedTarget = { relatedTarget: this._element }; - var hideEvent = EventHandler.trigger(parent, EVENT_HIDE$1, relatedTarget); + var showEvent = $.Event(Event$4.SHOW, relatedTarget); - if (hideEvent.defaultPrevented) { + var parent = Dropdown._getParentFromElement(this._element); + + $(parent).trigger(showEvent); + + if (showEvent.isDefaultPrevented()) { return; } - if (this._popper) { - this._popper.destroy(); + $(this._menu).toggleClass(ClassName$4.SHOW); + $(parent).toggleClass(ClassName$4.SHOW).trigger($.Event(Event$4.SHOWN, relatedTarget)); + }; + + _proto.hide = function hide() { + if (this._element.disabled || $(this._element).hasClass(ClassName$4.DISABLED) || !$(this._menu).hasClass(ClassName$4.SHOW)) { + return; } - this._menu.classList.toggle(CLASS_NAME_SHOW$1); + var relatedTarget = { + relatedTarget: this._element + }; + var hideEvent = $.Event(Event$4.HIDE, relatedTarget); - this._element.classList.toggle(CLASS_NAME_SHOW$1); + var parent = Dropdown._getParentFromElement(this._element); - EventHandler.trigger(parent, EVENT_HIDDEN$1, relatedTarget); + $(parent).trigger(hideEvent); + + if (hideEvent.isDefaultPrevented()) { + return; + } + + $(this._menu).toggleClass(ClassName$4.SHOW); + $(parent).toggleClass(ClassName$4.SHOW).trigger($.Event(Event$4.HIDDEN, relatedTarget)); }; _proto.dispose = function dispose() { - _BaseComponent.prototype.dispose.call(this); - - EventHandler.off(this._element, EVENT_KEY$4); + $.removeData(this._element, DATA_KEY$4); + $(this._element).off(EVENT_KEY$4); + this._element = null; this._menu = null; - if (this._popper) { + if (this._popper !== null) { this._popper.destroy(); this._popper = null; @@ -3948,115 +4313,140 @@ _proto.update = function update() { this._inNavbar = this._detectNavbar(); - if (this._popper) { - this._popper.update(); + if (this._popper !== null) { + this._popper.scheduleUpdate(); } } // Private ; _proto._addEventListeners = function _addEventListeners() { - var _this2 = this; + var _this = this; - EventHandler.on(this._element, EVENT_CLICK, function (event) { + $(this._element).on(Event$4.CLICK, function (event) { event.preventDefault(); event.stopPropagation(); - _this2.toggle(); + _this.toggle(); }); }; _proto._getConfig = function _getConfig(config) { - config = _extends({}, this.constructor.Default, Manipulator.getDataAttributes(this._element), config); - typeCheckConfig(NAME$4, config, this.constructor.DefaultType); + config = _objectSpread({}, this.constructor.Default, $(this._element).data(), config); + Util.typeCheckConfig(NAME$4, config, this.constructor.DefaultType); return config; }; _proto._getMenuElement = function _getMenuElement() { - return SelectorEngine.next(this._element, SELECTOR_MENU)[0]; + if (!this._menu) { + var parent = Dropdown._getParentFromElement(this._element); + + if (parent) { + this._menu = parent.querySelector(Selector$4.MENU); + } + } + + return this._menu; }; _proto._getPlacement = function _getPlacement() { - var parentDropdown = this._element.parentNode; + var $parentDropdown = $(this._element.parentNode); + var placement = AttachmentMap.BOTTOM; // Handle dropup - if (parentDropdown.classList.contains(CLASS_NAME_DROPEND)) { - return PLACEMENT_RIGHT; + if ($parentDropdown.hasClass(ClassName$4.DROPUP)) { + placement = AttachmentMap.TOP; + + if ($(this._menu).hasClass(ClassName$4.MENURIGHT)) { + placement = AttachmentMap.TOPEND; + } + } else if ($parentDropdown.hasClass(ClassName$4.DROPRIGHT)) { + placement = AttachmentMap.RIGHT; + } else if ($parentDropdown.hasClass(ClassName$4.DROPLEFT)) { + placement = AttachmentMap.LEFT; + } else if ($(this._menu).hasClass(ClassName$4.MENURIGHT)) { + placement = AttachmentMap.BOTTOMEND; } - if (parentDropdown.classList.contains(CLASS_NAME_DROPSTART)) { - return PLACEMENT_LEFT; - } // We need to trim the value because custom properties can also include spaces - - - var isEnd = getComputedStyle(this._menu).getPropertyValue('--bs-position').trim() === 'end'; - - if (parentDropdown.classList.contains(CLASS_NAME_DROPUP)) { - return isEnd ? PLACEMENT_TOPEND : PLACEMENT_TOP; - } - - return isEnd ? PLACEMENT_BOTTOMEND : PLACEMENT_BOTTOM; + return placement; }; _proto._detectNavbar = function _detectNavbar() { - return this._element.closest("." + CLASS_NAME_NAVBAR) !== null; + return $(this._element).closest('.navbar').length > 0; + }; + + _proto._getOffset = function _getOffset() { + var _this2 = this; + + var offset = {}; + + if (typeof this._config.offset === 'function') { + offset.fn = function (data) { + data.offsets = _objectSpread({}, data.offsets, _this2._config.offset(data.offsets, _this2._element) || {}); + return data; + }; + } else { + offset.offset = this._config.offset; + } + + return offset; }; _proto._getPopperConfig = function _getPopperConfig() { var popperConfig = { placement: this._getPlacement(), - modifiers: [{ - name: 'preventOverflow', - options: { - altBoundary: this._config.flip, - rootBoundary: this._config.boundary + modifiers: { + offset: this._getOffset(), + flip: { + enabled: this._config.flip + }, + preventOverflow: { + boundariesElement: this._config.boundary } - }] - }; // Disable Popper if we have a static display + } // Disable Popper.js if we have a static display + + }; if (this._config.display === 'static') { - popperConfig.modifiers = [{ - name: 'applyStyles', + popperConfig.modifiers.applyStyle = { enabled: false - }]; + }; } - return _extends({}, popperConfig, this._config.popperConfig); + return popperConfig; } // Static ; - Dropdown.dropdownInterface = function dropdownInterface(element, config) { - var data = Data.getData(element, DATA_KEY$4); + Dropdown._jQueryInterface = function _jQueryInterface(config) { + return this.each(function () { + var data = $(this).data(DATA_KEY$4); - var _config = typeof config === 'object' ? config : null; + var _config = typeof config === 'object' ? config : null; - if (!data) { - data = new Dropdown(element, _config); - } - - if (typeof config === 'string') { - if (typeof data[config] === 'undefined') { - throw new TypeError("No method named \"" + config + "\""); + if (!data) { + data = new Dropdown(this, _config); + $(this).data(DATA_KEY$4, data); } - data[config](); - } - }; + if (typeof config === 'string') { + if (typeof data[config] === 'undefined') { + throw new TypeError("No method named \"" + config + "\""); + } - Dropdown.jQueryInterface = function jQueryInterface(config) { - return this.each(function () { - Dropdown.dropdownInterface(this, config); + data[config](); + } }); }; - Dropdown.clearMenus = function clearMenus(event) { - if (event && (event.button === RIGHT_MOUSE_BUTTON || event.type === 'keyup' && event.key !== TAB_KEY)) { + Dropdown._clearMenus = function _clearMenus(event) { + if (event && (event.which === RIGHT_MOUSE_BUTTON_WHICH || event.type === 'keyup' && event.which !== TAB_KEYCODE)) { return; } - var toggles = SelectorEngine.find(SELECTOR_DATA_TOGGLE$2); + var toggles = [].slice.call(document.querySelectorAll(Selector$4.DATA_TOGGLE)); for (var i = 0, len = toggles.length; i < len; i++) { - var parent = Dropdown.getParentFromElement(toggles[i]); - var context = Data.getData(toggles[i], DATA_KEY$4); + var parent = Dropdown._getParentFromElement(toggles[i]); + + var context = $(toggles[i]).data(DATA_KEY$4); var relatedTarget = { relatedTarget: toggles[i] }; @@ -4071,47 +4461,46 @@ var dropdownMenu = context._menu; - if (!toggles[i].classList.contains(CLASS_NAME_SHOW$1)) { + if (!$(parent).hasClass(ClassName$4.SHOW)) { continue; } - if (event && (event.type === 'click' && /input|textarea/i.test(event.target.tagName) || event.type === 'keyup' && event.key === TAB_KEY) && dropdownMenu.contains(event.target)) { + if (event && (event.type === 'click' && /input|textarea/i.test(event.target.tagName) || event.type === 'keyup' && event.which === TAB_KEYCODE) && $.contains(parent, event.target)) { continue; } - var hideEvent = EventHandler.trigger(parent, EVENT_HIDE$1, relatedTarget); + var hideEvent = $.Event(Event$4.HIDE, relatedTarget); + $(parent).trigger(hideEvent); - if (hideEvent.defaultPrevented) { + if (hideEvent.isDefaultPrevented()) { continue; } // If this is a touch-enabled device we remove the extra // empty mouseover listeners we added for iOS support if ('ontouchstart' in document.documentElement) { - var _ref2; - - (_ref2 = []).concat.apply(_ref2, document.body.children).forEach(function (elem) { - return EventHandler.off(elem, 'mouseover', null, noop()); - }); + $(document.body).children().off('mouseover', null, $.noop); } toggles[i].setAttribute('aria-expanded', 'false'); - - if (context._popper) { - context._popper.destroy(); - } - - dropdownMenu.classList.remove(CLASS_NAME_SHOW$1); - toggles[i].classList.remove(CLASS_NAME_SHOW$1); - EventHandler.trigger(parent, EVENT_HIDDEN$1, relatedTarget); + $(dropdownMenu).removeClass(ClassName$4.SHOW); + $(parent).removeClass(ClassName$4.SHOW).trigger($.Event(Event$4.HIDDEN, relatedTarget)); } }; - Dropdown.getParentFromElement = function getParentFromElement(element) { - return getElementFromSelector(element) || element.parentNode; - }; + Dropdown._getParentFromElement = function _getParentFromElement(element) { + var parent; + var selector = Util.getSelectorFromElement(element); - Dropdown.dataApiKeydownHandler = function dataApiKeydownHandler(event) { + if (selector) { + parent = document.querySelector(selector); + } + + return parent || element.parentNode; + } // eslint-disable-next-line complexity + ; + + Dropdown._dataApiKeydownHandler = function _dataApiKeydownHandler(event) { // If not input/textarea: // - And not a key in REGEXP_KEYDOWN => not a dropdown command // If input/textarea: @@ -4119,55 +4508,62 @@ // - If key is other than escape // - If key is not up or down => not a dropdown command // - If trigger inside the menu => not a dropdown command - if (/input|textarea/i.test(event.target.tagName) ? event.key === SPACE_KEY || event.key !== ESCAPE_KEY && (event.key !== ARROW_DOWN_KEY && event.key !== ARROW_UP_KEY || event.target.closest(SELECTOR_MENU)) : !REGEXP_KEYDOWN.test(event.key)) { + if (/input|textarea/i.test(event.target.tagName) ? event.which === SPACE_KEYCODE || event.which !== ESCAPE_KEYCODE && (event.which !== ARROW_DOWN_KEYCODE && event.which !== ARROW_UP_KEYCODE || $(event.target).closest(Selector$4.MENU).length) : !REGEXP_KEYDOWN.test(event.which)) { return; } event.preventDefault(); event.stopPropagation(); - if (this.disabled || this.classList.contains(CLASS_NAME_DISABLED)) { + if (this.disabled || $(this).hasClass(ClassName$4.DISABLED)) { return; } - var parent = Dropdown.getParentFromElement(this); - var isActive = this.classList.contains(CLASS_NAME_SHOW$1); + var parent = Dropdown._getParentFromElement(this); - if (event.key === ESCAPE_KEY) { - var button = this.matches(SELECTOR_DATA_TOGGLE$2) ? this : SelectorEngine.prev(this, SELECTOR_DATA_TOGGLE$2)[0]; - button.focus(); - Dropdown.clearMenus(); + var isActive = $(parent).hasClass(ClassName$4.SHOW); + + if (!isActive || isActive && (event.which === ESCAPE_KEYCODE || event.which === SPACE_KEYCODE)) { + if (event.which === ESCAPE_KEYCODE) { + var toggle = parent.querySelector(Selector$4.DATA_TOGGLE); + $(toggle).trigger('focus'); + } + + $(this).trigger('click'); return; } - if (!isActive || event.key === SPACE_KEY) { - Dropdown.clearMenus(); + var items = [].slice.call(parent.querySelectorAll(Selector$4.VISIBLE_ITEMS)); + + if (items.length === 0) { return; } - var items = SelectorEngine.find(SELECTOR_VISIBLE_ITEMS, parent).filter(isVisible); + var index = items.indexOf(event.target); - if (!items.length) { - return; - } - - var index = items.indexOf(event.target); // Up - - if (event.key === ARROW_UP_KEY && index > 0) { + if (event.which === ARROW_UP_KEYCODE && index > 0) { + // Up index--; - } // Down + } - - if (event.key === ARROW_DOWN_KEY && index < items.length - 1) { + if (event.which === ARROW_DOWN_KEYCODE && index < items.length - 1) { + // Down index++; - } // index is -1 if the first keydown is an ArrowUp + } + if (index < 0) { + index = 0; + } - index = index === -1 ? 0 : index; items[index].focus(); }; _createClass(Dropdown, null, [{ + key: "VERSION", + get: function get() { + return VERSION$4; + } + }, { key: "Default", get: function get() { return Default$2; @@ -4177,15 +4573,10 @@ get: function get() { return DefaultType$2; } - }, { - key: "DATA_KEY", - get: function get() { - return DATA_KEY$4; - } }]); return Dropdown; - }(BaseComponent); + }(); /** * ------------------------------------------------------------------------ * Data Api implementation @@ -4193,40 +4584,27 @@ */ - EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_DATA_TOGGLE$2, Dropdown.dataApiKeydownHandler); - EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_MENU, Dropdown.dataApiKeydownHandler); - EventHandler.on(document, EVENT_CLICK_DATA_API$4, Dropdown.clearMenus); - EventHandler.on(document, EVENT_KEYUP_DATA_API, Dropdown.clearMenus); - EventHandler.on(document, EVENT_CLICK_DATA_API$4, SELECTOR_DATA_TOGGLE$2, function (event) { + $(document).on(Event$4.KEYDOWN_DATA_API, Selector$4.DATA_TOGGLE, Dropdown._dataApiKeydownHandler).on(Event$4.KEYDOWN_DATA_API, Selector$4.MENU, Dropdown._dataApiKeydownHandler).on(Event$4.CLICK_DATA_API + " " + Event$4.KEYUP_DATA_API, Dropdown._clearMenus).on(Event$4.CLICK_DATA_API, Selector$4.DATA_TOGGLE, function (event) { event.preventDefault(); event.stopPropagation(); - Dropdown.dropdownInterface(this, 'toggle'); - }); - EventHandler.on(document, EVENT_CLICK_DATA_API$4, SELECTOR_FORM_CHILD, function (e) { - return e.stopPropagation(); + + Dropdown._jQueryInterface.call($(this), 'toggle'); + }).on(Event$4.CLICK_DATA_API, Selector$4.FORM_CHILD, function (e) { + e.stopPropagation(); }); /** * ------------------------------------------------------------------------ * jQuery * ------------------------------------------------------------------------ - * add .Dropdown to jQuery only if jQuery is present */ - onDOMContentLoaded(function () { - var $ = getjQuery(); - /* istanbul ignore if */ + $.fn[NAME$4] = Dropdown._jQueryInterface; + $.fn[NAME$4].Constructor = Dropdown; - if ($) { - var JQUERY_NO_CONFLICT = $.fn[NAME$4]; - $.fn[NAME$4] = Dropdown.jQueryInterface; - $.fn[NAME$4].Constructor = Dropdown; - - $.fn[NAME$4].noConflict = function () { - $.fn[NAME$4] = JQUERY_NO_CONFLICT; - return Dropdown.jQueryInterface; - }; - } - }); + $.fn[NAME$4].noConflict = function () { + $.fn[NAME$4] = JQUERY_NO_CONFLICT$4; + return Dropdown._jQueryInterface; + }; /** * ------------------------------------------------------------------------ @@ -4235,66 +4613,74 @@ */ var NAME$5 = 'modal'; + var VERSION$5 = '4.3.1'; var DATA_KEY$5 = 'bs.modal'; var EVENT_KEY$5 = "." + DATA_KEY$5; var DATA_API_KEY$5 = '.data-api'; - var ESCAPE_KEY$1 = 'Escape'; + var JQUERY_NO_CONFLICT$5 = $.fn[NAME$5]; + var ESCAPE_KEYCODE$1 = 27; // KeyboardEvent.which value for Escape (Esc) key + var Default$3 = { backdrop: true, keyboard: true, - focus: true + focus: true, + show: true }; var DefaultType$3 = { backdrop: '(boolean|string)', keyboard: 'boolean', - focus: 'boolean' + focus: 'boolean', + show: 'boolean' }; - var EVENT_HIDE$2 = "hide" + EVENT_KEY$5; - var EVENT_HIDE_PREVENTED = "hidePrevented" + EVENT_KEY$5; - var EVENT_HIDDEN$2 = "hidden" + EVENT_KEY$5; - var EVENT_SHOW$2 = "show" + EVENT_KEY$5; - var EVENT_SHOWN$2 = "shown" + EVENT_KEY$5; - var EVENT_FOCUSIN = "focusin" + EVENT_KEY$5; - var EVENT_RESIZE = "resize" + EVENT_KEY$5; - var EVENT_CLICK_DISMISS = "click.dismiss" + EVENT_KEY$5; - var EVENT_KEYDOWN_DISMISS = "keydown.dismiss" + EVENT_KEY$5; - var EVENT_MOUSEUP_DISMISS = "mouseup.dismiss" + EVENT_KEY$5; - var EVENT_MOUSEDOWN_DISMISS = "mousedown.dismiss" + EVENT_KEY$5; - var EVENT_CLICK_DATA_API$5 = "click" + EVENT_KEY$5 + DATA_API_KEY$5; - var CLASS_NAME_SCROLLBAR_MEASURER = 'modal-scrollbar-measure'; - var CLASS_NAME_BACKDROP = 'modal-backdrop'; - var CLASS_NAME_OPEN = 'modal-open'; - var CLASS_NAME_FADE = 'fade'; - var CLASS_NAME_SHOW$2 = 'show'; - var CLASS_NAME_STATIC = 'modal-static'; - var SELECTOR_DIALOG = '.modal-dialog'; - var SELECTOR_MODAL_BODY = '.modal-body'; - var SELECTOR_DATA_TOGGLE$3 = '[data-bs-toggle="modal"]'; - var SELECTOR_DATA_DISMISS = '[data-bs-dismiss="modal"]'; - var SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top'; - var SELECTOR_STICKY_CONTENT = '.sticky-top'; - /** - * ------------------------------------------------------------------------ - * Class Definition - * ------------------------------------------------------------------------ - */ + var Event$5 = { + HIDE: "hide" + EVENT_KEY$5, + HIDDEN: "hidden" + EVENT_KEY$5, + SHOW: "show" + EVENT_KEY$5, + SHOWN: "shown" + EVENT_KEY$5, + FOCUSIN: "focusin" + EVENT_KEY$5, + RESIZE: "resize" + EVENT_KEY$5, + CLICK_DISMISS: "click.dismiss" + EVENT_KEY$5, + KEYDOWN_DISMISS: "keydown.dismiss" + EVENT_KEY$5, + MOUSEUP_DISMISS: "mouseup.dismiss" + EVENT_KEY$5, + MOUSEDOWN_DISMISS: "mousedown.dismiss" + EVENT_KEY$5, + CLICK_DATA_API: "click" + EVENT_KEY$5 + DATA_API_KEY$5 + }; + var ClassName$5 = { + SCROLLABLE: 'modal-dialog-scrollable', + SCROLLBAR_MEASURER: 'modal-scrollbar-measure', + BACKDROP: 'modal-backdrop', + OPEN: 'modal-open', + FADE: 'fade', + SHOW: 'show' + }; + var Selector$5 = { + DIALOG: '.modal-dialog', + MODAL_BODY: '.modal-body', + DATA_TOGGLE: '[data-toggle="modal"]', + DATA_DISMISS: '[data-dismiss="modal"]', + FIXED_CONTENT: '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top', + STICKY_CONTENT: '.sticky-top' + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ - var Modal = /*#__PURE__*/function (_BaseComponent) { - _inheritsLoose(Modal, _BaseComponent); + }; + var Modal = + /*#__PURE__*/ + function () { function Modal(element, config) { - var _this; - - _this = _BaseComponent.call(this, element) || this; - _this._config = _this._getConfig(config); - _this._dialog = SelectorEngine.findOne(SELECTOR_DIALOG, element); - _this._backdrop = null; - _this._isShown = false; - _this._isBodyOverflowing = false; - _this._ignoreBackdropClick = false; - _this._isTransitioning = false; - _this._scrollbarWidth = 0; - return _this; + this._config = this._getConfig(config); + this._element = element; + this._dialog = element.querySelector(Selector$5.DIALOG); + this._backdrop = null; + this._isShown = false; + this._isBodyOverflowing = false; + this._ignoreBackdropClick = false; + this._isTransitioning = false; + this._scrollbarWidth = 0; } // Getters @@ -4306,21 +4692,22 @@ }; _proto.show = function show(relatedTarget) { - var _this2 = this; + var _this = this; if (this._isShown || this._isTransitioning) { return; } - if (this._element.classList.contains(CLASS_NAME_FADE)) { + if ($(this._element).hasClass(ClassName$5.FADE)) { this._isTransitioning = true; } - var showEvent = EventHandler.trigger(this._element, EVENT_SHOW$2, { + var showEvent = $.Event(Event$5.SHOW, { relatedTarget: relatedTarget }); + $(this._element).trigger(showEvent); - if (this._isShown || showEvent.defaultPrevented) { + if (this._isShown || showEvent.isDefaultPrevented()) { return; } @@ -4336,24 +4723,24 @@ this._setResizeEvent(); - EventHandler.on(this._element, EVENT_CLICK_DISMISS, SELECTOR_DATA_DISMISS, function (event) { - return _this2.hide(event); + $(this._element).on(Event$5.CLICK_DISMISS, Selector$5.DATA_DISMISS, function (event) { + return _this.hide(event); }); - EventHandler.on(this._dialog, EVENT_MOUSEDOWN_DISMISS, function () { - EventHandler.one(_this2._element, EVENT_MOUSEUP_DISMISS, function (event) { - if (event.target === _this2._element) { - _this2._ignoreBackdropClick = true; + $(this._dialog).on(Event$5.MOUSEDOWN_DISMISS, function () { + $(_this._element).one(Event$5.MOUSEUP_DISMISS, function (event) { + if ($(event.target).is(_this._element)) { + _this._ignoreBackdropClick = true; } }); }); this._showBackdrop(function () { - return _this2._showElement(relatedTarget); + return _this._showElement(relatedTarget); }); }; _proto.hide = function hide(event) { - var _this3 = this; + var _this2 = this; if (event) { event.preventDefault(); @@ -4363,15 +4750,15 @@ return; } - var hideEvent = EventHandler.trigger(this._element, EVENT_HIDE$2); + var hideEvent = $.Event(Event$5.HIDE); + $(this._element).trigger(hideEvent); - if (hideEvent.defaultPrevented) { + if (!this._isShown || hideEvent.isDefaultPrevented()) { return; } this._isShown = false; - - var transition = this._element.classList.contains(CLASS_NAME_FADE); + var transition = $(this._element).hasClass(ClassName$5.FADE); if (transition) { this._isTransitioning = true; @@ -4381,19 +4768,16 @@ this._setResizeEvent(); - EventHandler.off(document, EVENT_FOCUSIN); - - this._element.classList.remove(CLASS_NAME_SHOW$2); - - EventHandler.off(this._element, EVENT_CLICK_DISMISS); - EventHandler.off(this._dialog, EVENT_MOUSEDOWN_DISMISS); + $(document).off(Event$5.FOCUSIN); + $(this._element).removeClass(ClassName$5.SHOW); + $(this._element).off(Event$5.CLICK_DISMISS); + $(this._dialog).off(Event$5.MOUSEDOWN_DISMISS); if (transition) { - var transitionDuration = getTransitionDurationFromElement(this._element); - EventHandler.one(this._element, TRANSITION_END, function (event) { - return _this3._hideModal(event); - }); - emulateTransitionEnd(this._element, transitionDuration); + var transitionDuration = Util.getTransitionDurationFromElement(this._element); + $(this._element).one(Util.TRANSITION_END, function (event) { + return _this2._hideModal(event); + }).emulateTransitionEnd(transitionDuration); } else { this._hideModal(); } @@ -4401,19 +4785,18 @@ _proto.dispose = function dispose() { [window, this._element, this._dialog].forEach(function (htmlElement) { - return EventHandler.off(htmlElement, EVENT_KEY$5); + return $(htmlElement).off(EVENT_KEY$5); }); - - _BaseComponent.prototype.dispose.call(this); /** - * `document` has 2 events `EVENT_FOCUSIN` and `EVENT_CLICK_DATA_API` + * `document` has 2 events `Event.FOCUSIN` and `Event.CLICK_DATA_API` * Do not move `document` in `htmlElements` array - * It will remove `EVENT_CLICK_DATA_API` event that should remain + * It will remove `Event.CLICK_DATA_API` event that should remain */ - - EventHandler.off(document, EVENT_FOCUSIN); + $(document).off(Event$5.FOCUSIN); + $.removeData(this._element, DATA_KEY$5); this._config = null; + this._element = null; this._dialog = null; this._backdrop = null; this._isShown = null; @@ -4429,17 +4812,15 @@ ; _proto._getConfig = function _getConfig(config) { - config = _extends({}, Default$3, config); - typeCheckConfig(NAME$5, config, DefaultType$3); + config = _objectSpread({}, Default$3, config); + Util.typeCheckConfig(NAME$5, config, DefaultType$3); return config; }; _proto._showElement = function _showElement(relatedTarget) { - var _this4 = this; + var _this3 = this; - var transition = this._element.classList.contains(CLASS_NAME_FADE); - - var modalBody = SelectorEngine.findOne(SELECTOR_MODAL_BODY, this._dialog); + var transition = $(this._element).hasClass(ClassName$5.FADE); if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) { // Don't move modal's DOM position @@ -4452,88 +4833,84 @@ this._element.setAttribute('aria-modal', true); - this._element.setAttribute('role', 'dialog'); - - this._element.scrollTop = 0; - - if (modalBody) { - modalBody.scrollTop = 0; + if ($(this._dialog).hasClass(ClassName$5.SCROLLABLE)) { + this._dialog.querySelector(Selector$5.MODAL_BODY).scrollTop = 0; + } else { + this._element.scrollTop = 0; } if (transition) { - reflow(this._element); + Util.reflow(this._element); } - this._element.classList.add(CLASS_NAME_SHOW$2); + $(this._element).addClass(ClassName$5.SHOW); if (this._config.focus) { this._enforceFocus(); } + var shownEvent = $.Event(Event$5.SHOWN, { + relatedTarget: relatedTarget + }); + var transitionComplete = function transitionComplete() { - if (_this4._config.focus) { - _this4._element.focus(); + if (_this3._config.focus) { + _this3._element.focus(); } - _this4._isTransitioning = false; - EventHandler.trigger(_this4._element, EVENT_SHOWN$2, { - relatedTarget: relatedTarget - }); + _this3._isTransitioning = false; + $(_this3._element).trigger(shownEvent); }; if (transition) { - var transitionDuration = getTransitionDurationFromElement(this._dialog); - EventHandler.one(this._dialog, TRANSITION_END, transitionComplete); - emulateTransitionEnd(this._dialog, transitionDuration); + var transitionDuration = Util.getTransitionDurationFromElement(this._dialog); + $(this._dialog).one(Util.TRANSITION_END, transitionComplete).emulateTransitionEnd(transitionDuration); } else { transitionComplete(); } }; _proto._enforceFocus = function _enforceFocus() { - var _this5 = this; + var _this4 = this; - EventHandler.off(document, EVENT_FOCUSIN); // guard against infinite focus loop - - EventHandler.on(document, EVENT_FOCUSIN, function (event) { - if (document !== event.target && _this5._element !== event.target && !_this5._element.contains(event.target)) { - _this5._element.focus(); + $(document).off(Event$5.FOCUSIN) // Guard against infinite focus loop + .on(Event$5.FOCUSIN, function (event) { + if (document !== event.target && _this4._element !== event.target && $(_this4._element).has(event.target).length === 0) { + _this4._element.focus(); } }); }; _proto._setEscapeEvent = function _setEscapeEvent() { - var _this6 = this; + var _this5 = this; - if (this._isShown) { - EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS, function (event) { - if (_this6._config.keyboard && event.key === ESCAPE_KEY$1) { + if (this._isShown && this._config.keyboard) { + $(this._element).on(Event$5.KEYDOWN_DISMISS, function (event) { + if (event.which === ESCAPE_KEYCODE$1) { event.preventDefault(); - _this6.hide(); - } else if (!_this6._config.keyboard && event.key === ESCAPE_KEY$1) { - _this6._triggerBackdropTransition(); + _this5.hide(); } }); - } else { - EventHandler.off(this._element, EVENT_KEYDOWN_DISMISS); + } else if (!this._isShown) { + $(this._element).off(Event$5.KEYDOWN_DISMISS); } }; _proto._setResizeEvent = function _setResizeEvent() { - var _this7 = this; + var _this6 = this; if (this._isShown) { - EventHandler.on(window, EVENT_RESIZE, function () { - return _this7._adjustDialog(); + $(window).on(Event$5.RESIZE, function (event) { + return _this6.handleUpdate(event); }); } else { - EventHandler.off(window, EVENT_RESIZE); + $(window).off(Event$5.RESIZE); } }; _proto._hideModal = function _hideModal() { - var _this8 = this; + var _this7 = this; this._element.style.display = 'none'; @@ -4541,44 +4918,43 @@ this._element.removeAttribute('aria-modal'); - this._element.removeAttribute('role'); - this._isTransitioning = false; this._showBackdrop(function () { - document.body.classList.remove(CLASS_NAME_OPEN); + $(document.body).removeClass(ClassName$5.OPEN); - _this8._resetAdjustments(); + _this7._resetAdjustments(); - _this8._resetScrollbar(); + _this7._resetScrollbar(); - EventHandler.trigger(_this8._element, EVENT_HIDDEN$2); + $(_this7._element).trigger(Event$5.HIDDEN); }); }; _proto._removeBackdrop = function _removeBackdrop() { - this._backdrop.parentNode.removeChild(this._backdrop); - - this._backdrop = null; + if (this._backdrop) { + $(this._backdrop).remove(); + this._backdrop = null; + } }; _proto._showBackdrop = function _showBackdrop(callback) { - var _this9 = this; + var _this8 = this; - var animate = this._element.classList.contains(CLASS_NAME_FADE) ? CLASS_NAME_FADE : ''; + var animate = $(this._element).hasClass(ClassName$5.FADE) ? ClassName$5.FADE : ''; if (this._isShown && this._config.backdrop) { this._backdrop = document.createElement('div'); - this._backdrop.className = CLASS_NAME_BACKDROP; + this._backdrop.className = ClassName$5.BACKDROP; if (animate) { this._backdrop.classList.add(animate); } - document.body.appendChild(this._backdrop); - EventHandler.on(this._element, EVENT_CLICK_DISMISS, function (event) { - if (_this9._ignoreBackdropClick) { - _this9._ignoreBackdropClick = false; + $(this._backdrop).appendTo(document.body); + $(this._element).on(Event$5.CLICK_DISMISS, function (event) { + if (_this8._ignoreBackdropClick) { + _this8._ignoreBackdropClick = false; return; } @@ -4586,94 +4962,65 @@ return; } - if (_this9._config.backdrop === 'static') { - _this9._triggerBackdropTransition(); + if (_this8._config.backdrop === 'static') { + _this8._element.focus(); } else { - _this9.hide(); + _this8.hide(); } }); if (animate) { - reflow(this._backdrop); + Util.reflow(this._backdrop); } - this._backdrop.classList.add(CLASS_NAME_SHOW$2); + $(this._backdrop).addClass(ClassName$5.SHOW); + + if (!callback) { + return; + } if (!animate) { callback(); return; } - var backdropTransitionDuration = getTransitionDurationFromElement(this._backdrop); - EventHandler.one(this._backdrop, TRANSITION_END, callback); - emulateTransitionEnd(this._backdrop, backdropTransitionDuration); + var backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop); + $(this._backdrop).one(Util.TRANSITION_END, callback).emulateTransitionEnd(backdropTransitionDuration); } else if (!this._isShown && this._backdrop) { - this._backdrop.classList.remove(CLASS_NAME_SHOW$2); + $(this._backdrop).removeClass(ClassName$5.SHOW); var callbackRemove = function callbackRemove() { - _this9._removeBackdrop(); + _this8._removeBackdrop(); - callback(); + if (callback) { + callback(); + } }; - if (this._element.classList.contains(CLASS_NAME_FADE)) { - var _backdropTransitionDuration = getTransitionDurationFromElement(this._backdrop); + if ($(this._element).hasClass(ClassName$5.FADE)) { + var _backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop); - EventHandler.one(this._backdrop, TRANSITION_END, callbackRemove); - emulateTransitionEnd(this._backdrop, _backdropTransitionDuration); + $(this._backdrop).one(Util.TRANSITION_END, callbackRemove).emulateTransitionEnd(_backdropTransitionDuration); } else { callbackRemove(); } - } else { + } else if (callback) { callback(); } - }; - - _proto._triggerBackdropTransition = function _triggerBackdropTransition() { - var _this10 = this; - - var hideEvent = EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED); - - if (hideEvent.defaultPrevented) { - return; - } - - var isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight; - - if (!isModalOverflowing) { - this._element.style.overflowY = 'hidden'; - } - - this._element.classList.add(CLASS_NAME_STATIC); - - var modalTransitionDuration = getTransitionDurationFromElement(this._dialog); - EventHandler.off(this._element, TRANSITION_END); - EventHandler.one(this._element, TRANSITION_END, function () { - _this10._element.classList.remove(CLASS_NAME_STATIC); - - if (!isModalOverflowing) { - EventHandler.one(_this10._element, TRANSITION_END, function () { - _this10._element.style.overflowY = ''; - }); - emulateTransitionEnd(_this10._element, modalTransitionDuration); - } - }); - emulateTransitionEnd(this._element, modalTransitionDuration); - - this._element.focus(); } // ---------------------------------------------------------------------- // the following methods are used to handle overflowing modals + // todo (fat): these should probably be refactored out of modal.js // ---------------------------------------------------------------------- ; _proto._adjustDialog = function _adjustDialog() { var isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight; - if (!this._isBodyOverflowing && isModalOverflowing && !isRTL || this._isBodyOverflowing && !isModalOverflowing && isRTL) { + if (!this._isBodyOverflowing && isModalOverflowing) { this._element.style.paddingLeft = this._scrollbarWidth + "px"; } - if (this._isBodyOverflowing && !isModalOverflowing && !isRTL || !this._isBodyOverflowing && isModalOverflowing && isRTL) { + if (this._isBodyOverflowing && !isModalOverflowing) { this._element.style.paddingRight = this._scrollbarWidth + "px"; } }; @@ -4685,74 +5032,66 @@ _proto._checkScrollbar = function _checkScrollbar() { var rect = document.body.getBoundingClientRect(); - this._isBodyOverflowing = Math.round(rect.left + rect.right) < window.innerWidth; + this._isBodyOverflowing = rect.left + rect.right < window.innerWidth; this._scrollbarWidth = this._getScrollbarWidth(); }; _proto._setScrollbar = function _setScrollbar() { - var _this11 = this; + var _this9 = this; if (this._isBodyOverflowing) { // Note: DOMNode.style.paddingRight returns the actual value or '' if not set // while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set - // Adjust fixed content padding - SelectorEngine.find(SELECTOR_FIXED_CONTENT).forEach(function (element) { + var fixedContent = [].slice.call(document.querySelectorAll(Selector$5.FIXED_CONTENT)); + var stickyContent = [].slice.call(document.querySelectorAll(Selector$5.STICKY_CONTENT)); // Adjust fixed content padding + + $(fixedContent).each(function (index, element) { var actualPadding = element.style.paddingRight; - var calculatedPadding = window.getComputedStyle(element)['padding-right']; - Manipulator.setDataAttribute(element, 'padding-right', actualPadding); - element.style.paddingRight = Number.parseFloat(calculatedPadding) + _this11._scrollbarWidth + "px"; + var calculatedPadding = $(element).css('padding-right'); + $(element).data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + _this9._scrollbarWidth + "px"); }); // Adjust sticky content margin - SelectorEngine.find(SELECTOR_STICKY_CONTENT).forEach(function (element) { + $(stickyContent).each(function (index, element) { var actualMargin = element.style.marginRight; - var calculatedMargin = window.getComputedStyle(element)['margin-right']; - Manipulator.setDataAttribute(element, 'margin-right', actualMargin); - element.style.marginRight = Number.parseFloat(calculatedMargin) - _this11._scrollbarWidth + "px"; + var calculatedMargin = $(element).css('margin-right'); + $(element).data('margin-right', actualMargin).css('margin-right', parseFloat(calculatedMargin) - _this9._scrollbarWidth + "px"); }); // Adjust body padding var actualPadding = document.body.style.paddingRight; - var calculatedPadding = window.getComputedStyle(document.body)['padding-right']; - Manipulator.setDataAttribute(document.body, 'padding-right', actualPadding); - document.body.style.paddingRight = Number.parseFloat(calculatedPadding) + this._scrollbarWidth + "px"; + var calculatedPadding = $(document.body).css('padding-right'); + $(document.body).data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + this._scrollbarWidth + "px"); } - document.body.classList.add(CLASS_NAME_OPEN); + $(document.body).addClass(ClassName$5.OPEN); }; _proto._resetScrollbar = function _resetScrollbar() { // Restore fixed content padding - SelectorEngine.find(SELECTOR_FIXED_CONTENT).forEach(function (element) { - var padding = Manipulator.getDataAttribute(element, 'padding-right'); + var fixedContent = [].slice.call(document.querySelectorAll(Selector$5.FIXED_CONTENT)); + $(fixedContent).each(function (index, element) { + var padding = $(element).data('padding-right'); + $(element).removeData('padding-right'); + element.style.paddingRight = padding ? padding : ''; + }); // Restore sticky content - if (typeof padding !== 'undefined') { - Manipulator.removeDataAttribute(element, 'padding-right'); - element.style.paddingRight = padding; - } - }); // Restore sticky content and navbar-toggler margin - - SelectorEngine.find("" + SELECTOR_STICKY_CONTENT).forEach(function (element) { - var margin = Manipulator.getDataAttribute(element, 'margin-right'); + var elements = [].slice.call(document.querySelectorAll("" + Selector$5.STICKY_CONTENT)); + $(elements).each(function (index, element) { + var margin = $(element).data('margin-right'); if (typeof margin !== 'undefined') { - Manipulator.removeDataAttribute(element, 'margin-right'); - element.style.marginRight = margin; + $(element).css('margin-right', margin).removeData('margin-right'); } }); // Restore body padding - var padding = Manipulator.getDataAttribute(document.body, 'padding-right'); - - if (typeof padding === 'undefined') { - document.body.style.paddingRight = ''; - } else { - Manipulator.removeDataAttribute(document.body, 'padding-right'); - document.body.style.paddingRight = padding; - } + var padding = $(document.body).data('padding-right'); + $(document.body).removeData('padding-right'); + document.body.style.paddingRight = padding ? padding : ''; }; _proto._getScrollbarWidth = function _getScrollbarWidth() { // thx d.walsh var scrollDiv = document.createElement('div'); - scrollDiv.className = CLASS_NAME_SCROLLBAR_MEASURER; + scrollDiv.className = ClassName$5.SCROLLBAR_MEASURER; document.body.appendChild(scrollDiv); var scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth; document.body.removeChild(scrollDiv); @@ -4760,14 +5099,15 @@ } // Static ; - Modal.jQueryInterface = function jQueryInterface(config, relatedTarget) { + Modal._jQueryInterface = function _jQueryInterface(config, relatedTarget) { return this.each(function () { - var data = Data.getData(this, DATA_KEY$5); + var data = $(this).data(DATA_KEY$5); - var _config = _extends({}, Default$3, Manipulator.getDataAttributes(this), typeof config === 'object' && config ? config : {}); + var _config = _objectSpread({}, Default$3, $(this).data(), typeof config === 'object' && config ? config : {}); if (!data) { data = new Modal(this, _config); + $(this).data(DATA_KEY$5, data); } if (typeof config === 'string') { @@ -4776,24 +5116,26 @@ } data[config](relatedTarget); + } else if (_config.show) { + data.show(relatedTarget); } }); }; _createClass(Modal, null, [{ + key: "VERSION", + get: function get() { + return VERSION$5; + } + }, { key: "Default", get: function get() { return Default$3; } - }, { - key: "DATA_KEY", - get: function get() { - return DATA_KEY$5; - } }]); return Modal; - }(BaseComponent); + }(); /** * ------------------------------------------------------------------------ * Data Api implementation @@ -4801,108 +5143,60 @@ */ - EventHandler.on(document, EVENT_CLICK_DATA_API$5, SELECTOR_DATA_TOGGLE$3, function (event) { - var _this12 = this; + $(document).on(Event$5.CLICK_DATA_API, Selector$5.DATA_TOGGLE, function (event) { + var _this10 = this; - var target = getElementFromSelector(this); + var target; + var selector = Util.getSelectorFromElement(this); + + if (selector) { + target = document.querySelector(selector); + } + + var config = $(target).data(DATA_KEY$5) ? 'toggle' : _objectSpread({}, $(target).data(), $(this).data()); if (this.tagName === 'A' || this.tagName === 'AREA') { event.preventDefault(); } - EventHandler.one(target, EVENT_SHOW$2, function (showEvent) { - if (showEvent.defaultPrevented) { - // only register focus restorer if modal will actually get shown + var $target = $(target).one(Event$5.SHOW, function (showEvent) { + if (showEvent.isDefaultPrevented()) { + // Only register focus restorer if modal will actually get shown return; } - EventHandler.one(target, EVENT_HIDDEN$2, function () { - if (isVisible(_this12)) { - _this12.focus(); + $target.one(Event$5.HIDDEN, function () { + if ($(_this10).is(':visible')) { + _this10.focus(); } }); }); - var data = Data.getData(target, DATA_KEY$5); - if (!data) { - var config = _extends({}, Manipulator.getDataAttributes(target), Manipulator.getDataAttributes(this)); - - data = new Modal(target, config); - } - - data.show(this); + Modal._jQueryInterface.call($(target), config, this); }); /** * ------------------------------------------------------------------------ * jQuery * ------------------------------------------------------------------------ - * add .Modal to jQuery only if jQuery is present */ - onDOMContentLoaded(function () { - var $ = getjQuery(); - /* istanbul ignore if */ + $.fn[NAME$5] = Modal._jQueryInterface; + $.fn[NAME$5].Constructor = Modal; - if ($) { - var JQUERY_NO_CONFLICT = $.fn[NAME$5]; - $.fn[NAME$5] = Modal.jQueryInterface; - $.fn[NAME$5].Constructor = Modal; - - $.fn[NAME$5].noConflict = function () { - $.fn[NAME$5] = JQUERY_NO_CONFLICT; - return Modal.jQueryInterface; - }; - } - }); - - /** - * -------------------------------------------------------------------------- - * Bootstrap (v5.0.0-beta1): util/sanitizer.js - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) - * -------------------------------------------------------------------------- - */ - var uriAttrs = new Set(['background', 'cite', 'href', 'itemtype', 'longdesc', 'poster', 'src', 'xlink:href']); - var ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i; - /** - * A pattern that recognizes a commonly useful subset of URLs that are safe. - * - * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts - */ - - var SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^#&/:?]*(?:[#/?]|$))/gi; - /** - * A pattern that matches safe data URLs. Only matches image, video and audio types. - * - * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts - */ - - var DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i; - - var allowedAttribute = function allowedAttribute(attr, allowedAttributeList) { - var attrName = attr.nodeName.toLowerCase(); - - if (allowedAttributeList.includes(attrName)) { - if (uriAttrs.has(attrName)) { - return Boolean(attr.nodeValue.match(SAFE_URL_PATTERN) || attr.nodeValue.match(DATA_URL_PATTERN)); - } - - return true; - } - - var regExp = allowedAttributeList.filter(function (attrRegex) { - return attrRegex instanceof RegExp; - }); // Check if a regular expression validates the attribute. - - for (var i = 0, len = regExp.length; i < len; i++) { - if (attrName.match(regExp[i])) { - return true; - } - } - - return false; + $.fn[NAME$5].noConflict = function () { + $.fn[NAME$5] = JQUERY_NO_CONFLICT$5; + return Modal._jQueryInterface; }; - var DefaultAllowlist = { + /** + * -------------------------------------------------------------------------- + * Bootstrap (v4.3.1): tools/sanitizer.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + var uriAttrs = ['background', 'cite', 'href', 'itemtype', 'longdesc', 'poster', 'src', 'xlink:href']; + var ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i; + var DefaultWhitelist = { // Global attributes allowed on any supplied element below. '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN], a: ['target', 'href', 'title', 'rel'], @@ -4921,7 +5215,7 @@ h5: [], h6: [], i: [], - img: ['src', 'srcset', 'alt', 'title', 'width', 'height'], + img: ['src', 'alt', 'title', 'width', 'height'], li: [], ol: [], p: [], @@ -4934,11 +5228,48 @@ strong: [], u: [], ul: [] - }; - function sanitizeHtml(unsafeHtml, allowList, sanitizeFn) { - var _ref; + /** + * A pattern that recognizes a commonly useful subset of URLs that are safe. + * + * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts + */ - if (!unsafeHtml.length) { + }; + var SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi; + /** + * A pattern that matches safe data URLs. Only matches image, video and audio types. + * + * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts + */ + + var DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+/]+=*$/i; + + function allowedAttribute(attr, allowedAttributeList) { + var attrName = attr.nodeName.toLowerCase(); + + if (allowedAttributeList.indexOf(attrName) !== -1) { + if (uriAttrs.indexOf(attrName) !== -1) { + return Boolean(attr.nodeValue.match(SAFE_URL_PATTERN) || attr.nodeValue.match(DATA_URL_PATTERN)); + } + + return true; + } + + var regExp = allowedAttributeList.filter(function (attrRegex) { + return attrRegex instanceof RegExp; + }); // Check if a regular expression validates the attribute. + + for (var i = 0, l = regExp.length; i < l; i++) { + if (attrName.match(regExp[i])) { + return true; + } + } + + return false; + } + + function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) { + if (unsafeHtml.length === 0) { return unsafeHtml; } @@ -4948,33 +5279,29 @@ var domParser = new window.DOMParser(); var createdDocument = domParser.parseFromString(unsafeHtml, 'text/html'); - var allowlistKeys = Object.keys(allowList); - - var elements = (_ref = []).concat.apply(_ref, createdDocument.body.querySelectorAll('*')); + var whitelistKeys = Object.keys(whiteList); + var elements = [].slice.call(createdDocument.body.querySelectorAll('*')); var _loop = function _loop(i, len) { - var _ref2; - var el = elements[i]; var elName = el.nodeName.toLowerCase(); - if (!allowlistKeys.includes(elName)) { + if (whitelistKeys.indexOf(el.nodeName.toLowerCase()) === -1) { el.parentNode.removeChild(el); return "continue"; } - var attributeList = (_ref2 = []).concat.apply(_ref2, el.attributes); - - var allowedAttributes = [].concat(allowList['*'] || [], allowList[elName] || []); + var attributeList = [].slice.call(el.attributes); + var whitelistedAttributes = [].concat(whiteList['*'] || [], whiteList[elName] || []); attributeList.forEach(function (attr) { - if (!allowedAttribute(attr, allowedAttributes)) { + if (!allowedAttribute(attr, whitelistedAttributes)) { el.removeAttribute(attr.nodeName); } }); }; for (var i = 0, len = elements.length; i < len; i++) { - var _ret = _loop(i); + var _ret = _loop(i, len); if (_ret === "continue") continue; } @@ -4989,11 +5316,13 @@ */ var NAME$6 = 'tooltip'; + var VERSION$6 = '4.3.1'; var DATA_KEY$6 = 'bs.tooltip'; var EVENT_KEY$6 = "." + DATA_KEY$6; + var JQUERY_NO_CONFLICT$6 = $.fn[NAME$6]; var CLASS_PREFIX = 'bs-tooltip'; var BSCLS_PREFIX_REGEX = new RegExp("(^|\\s)" + CLASS_PREFIX + "\\S+", 'g'); - var DISALLOWED_ATTRIBUTES = new Set(['sanitize', 'allowList', 'sanitizeFn']); + var DISALLOWED_ATTRIBUTES = ['sanitize', 'whiteList', 'sanitizeFn']; var DefaultType$4 = { animation: 'boolean', template: 'string', @@ -5003,41 +5332,43 @@ html: 'boolean', selector: '(string|boolean)', placement: '(string|function)', + offset: '(number|string|function)', container: '(string|element|boolean)', - fallbackPlacements: '(null|array)', + fallbackPlacement: '(string|array)', boundary: '(string|element)', - customClass: '(string|function)', sanitize: 'boolean', sanitizeFn: '(null|function)', - allowList: 'object', - popperConfig: '(null|object)' + whiteList: 'object' }; - var AttachmentMap = { + var AttachmentMap$1 = { AUTO: 'auto', TOP: 'top', - RIGHT: isRTL ? 'left' : 'right', + RIGHT: 'right', BOTTOM: 'bottom', - LEFT: isRTL ? 'right' : 'left' + LEFT: 'left' }; var Default$4 = { animation: true, - template: '
- and
+