mirror of
https://github.com/Rushilwiz/spaceout.git
synced 2025-04-21 12:00:15 -04:00
155 lines
5.3 KiB
JavaScript
155 lines
5.3 KiB
JavaScript
// Utils
|
|
import debounce from './utils/debounce';
|
|
import isFunction from './utils/isFunction';
|
|
|
|
// Methods
|
|
import update from './methods/update';
|
|
import destroy from './methods/destroy';
|
|
import enableEventListeners from './methods/enableEventListeners';
|
|
import disableEventListeners from './methods/disableEventListeners';
|
|
import Defaults from './methods/defaults';
|
|
import placements from './methods/placements';
|
|
|
|
export default class Popper {
|
|
/**
|
|
* Creates a new Popper.js instance.
|
|
* @class Popper
|
|
* @param {Element|referenceObject} reference - The reference element used to position the popper
|
|
* @param {Element} popper - The HTML / XML 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
|
|
*/
|
|
constructor(reference, popper, options = {}) {
|
|
// 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 = { ...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({
|
|
...Popper.Defaults.modifiers,
|
|
...options.modifiers,
|
|
}).forEach(name => {
|
|
this.options.modifiers[name] = {
|
|
// If it's a built-in modifier, use it as base
|
|
...(Popper.Defaults.modifiers[name] || {}),
|
|
// If there are custom options, override and merge with default ones
|
|
...(options.modifiers ? options.modifiers[name] : {}),
|
|
};
|
|
});
|
|
|
|
// Refactoring modifiers' list (Object => Array)
|
|
this.modifiers = Object.keys(this.options.modifiers)
|
|
.map(name => ({
|
|
name,
|
|
...this.options.modifiers[name],
|
|
}))
|
|
// sort the modifiers by order
|
|
.sort((a, b) => 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(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();
|
|
|
|
const 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
|
|
update() {
|
|
return update.call(this);
|
|
}
|
|
destroy() {
|
|
return destroy.call(this);
|
|
}
|
|
enableEventListeners() {
|
|
return enableEventListeners.call(this);
|
|
}
|
|
disableEventListeners() {
|
|
return disableEventListeners.call(this);
|
|
}
|
|
|
|
/**
|
|
* Schedules an update. It will run on the next UI update available.
|
|
* @method scheduleUpdate
|
|
* @memberof Popper
|
|
*/
|
|
scheduleUpdate = () => requestAnimationFrame(this.update);
|
|
|
|
/**
|
|
* 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
|
|
*/
|
|
static Utils = (typeof window !== 'undefined' ? window : global).PopperUtils;
|
|
|
|
static placements = placements;
|
|
|
|
static Defaults = Defaults;
|
|
}
|
|
|
|
/**
|
|
* 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.<br />
|
|
* 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.
|
|
*/
|