123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539 |
- /**!
- * @fileOverview Kickass library to create and place poppers near their reference elements.
- * @version 1.1.5
- * @license
- * Copyright (c) 2016 Federico Zivolo and contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
- (function (global, factory) {
- typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('popper.js')) :
- typeof define === 'function' && define.amd ? define(['popper.js'], factory) :
- (global.Tooltip = factory(global.Popper));
- }(this, (function (Popper) { 'use strict';
- Popper = Popper && 'default' in Popper ? Popper['default'] : Popper;
- /**
- * Check if the given variable is a function
- * @method
- * @memberof Popper.Utils
- * @argument {Any} functionToCheck - variable to check
- * @returns {Boolean} answer to: is a function?
- */
- function isFunction(functionToCheck) {
- var getType = {};
- return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
- }
- var classCallCheck = function (instance, Constructor) {
- if (!(instance instanceof Constructor)) {
- throw new TypeError("Cannot call a class as a function");
- }
- };
- var createClass = function () {
- function defineProperties(target, props) {
- for (var i = 0; i < props.length; i++) {
- var descriptor = props[i];
- descriptor.enumerable = descriptor.enumerable || false;
- descriptor.configurable = true;
- if ("value" in descriptor) descriptor.writable = true;
- Object.defineProperty(target, descriptor.key, descriptor);
- }
- }
- return function (Constructor, protoProps, staticProps) {
- if (protoProps) defineProperties(Constructor.prototype, protoProps);
- if (staticProps) defineProperties(Constructor, staticProps);
- return Constructor;
- };
- }();
- var _extends = Object.assign || function (target) {
- for (var i = 1; i < arguments.length; i++) {
- var source = arguments[i];
- for (var key in source) {
- if (Object.prototype.hasOwnProperty.call(source, key)) {
- target[key] = source[key];
- }
- }
- }
- return target;
- };
- var DEFAULT_OPTIONS = {
- container: false,
- delay: 0,
- html: false,
- placement: 'top',
- title: '',
- template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
- trigger: 'hover focus',
- offset: 0
- };
- var Tooltip = function () {
- /**
- * Create a new Tooltip.js instance
- * @class Tooltip
- * @param {HTMLElement} reference - The DOM node used as reference of the tooltip (it can be a jQuery element).
- * @param {Object} options
- * @param {String} options.placement=bottom
- * Placement of the popper accepted values: `top(-start, -end), right(-start, -end), bottom(-start, -end),
- * left(-start, -end)`
- * @param {HTMLElement|String|false} options.container=false - Append the tooltip to a specific element.
- * @param {Number|Object} options.delay=0
- * Delay showing and hiding the tooltip (ms) - does not apply to manual trigger type.
- * If a number is supplied, delay is applied to both hide/show.
- * Object structure is: `{ show: 500, hide: 100 }`
- * @param {Boolean} options.html=false - Insert HTML into the tooltip. If false, the content will inserted with `innerText`.
- * @param {String|PlacementFunction} options.placement='top' - One of the allowed placements, or a function returning one of them.
- * @param {String} [options.template='<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>']
- * Base HTML to used when creating the tooltip.
- * The tooltip's `title` will be injected into the `.tooltip-inner` or `.tooltip__inner`.
- * `.tooltip-arrow` or `.tooltip__arrow` will become the tooltip's arrow.
- * The outermost wrapper element should have the `.tooltip` class.
- * @param {String|HTMLElement|TitleFunction} options.title='' - Default title value if `title` attribute isn't present.
- * @param {String} [options.trigger='hover focus']
- * How tooltip is triggered - click, hover, focus, manual.
- * You may pass multiple triggers; separate them with a space. `manual` cannot be combined with any other trigger.
- * @param {HTMLElement} options.boundariesElement
- * The element used as boundaries for the tooltip. For more information refer to Popper.js'
- * [boundariesElement docs](https://popper.js.org/popper-documentation.html)
- * @param {Number|String} options.offset=0 - Offset of the tooltip relative to its reference. For more information refer to Popper.js'
- * [offset docs](https://popper.js.org/popper-documentation.html)
- * @param {Object} options.popperOptions={} - Popper options, will be passed directly to popper instance. For more information refer to Popper.js'
- * [options docs](https://popper.js.org/popper-documentation.html)
- * @return {Object} instance - The generated tooltip instance
- */
- function Tooltip(reference, options) {
- classCallCheck(this, Tooltip);
- _initialiseProps.call(this);
- // apply user options over default ones
- options = _extends({}, DEFAULT_OPTIONS, options);
- reference.jquery && (reference = reference[0]);
- // cache reference and options
- this.reference = reference;
- this.options = options;
- // get events list
- var events = typeof options.trigger === 'string' ? options.trigger.split(' ').filter(function (trigger) {
- return ['click', 'hover', 'focus'].indexOf(trigger) !== -1;
- }) : [];
- // set initial state
- this._isOpen = false;
- // set event listeners
- this._setEventListeners(reference, events, options);
- }
- //
- // Public methods
- //
- /**
- * Reveals an element's tooltip. This is considered a "manual" triggering of the tooltip.
- * Tooltips with zero-length titles are never displayed.
- * @method Tooltip#show
- * @memberof Tooltip
- */
- /**
- * Hides an element’s tooltip. This is considered a “manual” triggering of the tooltip.
- * @method Tooltip#hide
- * @memberof Tooltip
- */
- /**
- * Hides and destroys an element’s tooltip.
- * @method Tooltip#dispose
- * @memberof Tooltip
- */
- /**
- * Toggles an element’s tooltip. This is considered a “manual” triggering of the tooltip.
- * @method Tooltip#toggle
- * @memberof Tooltip
- */
- //
- // Defaults
- //
- //
- // Private methods
- //
- createClass(Tooltip, [{
- key: '_create',
- /**
- * Creates a new tooltip node
- * @memberof Tooltip
- * @private
- * @param {HTMLElement} reference
- * @param {String} template
- * @param {String|HTMLElement|TitleFunction} title
- * @param {Boolean} allowHtml
- * @return {HTMLelement} tooltipNode
- */
- value: function _create(reference, template, title, allowHtml) {
- // create tooltip element
- var tooltipGenerator = window.document.createElement('div');
- tooltipGenerator.innerHTML = template.trim();
- var tooltipNode = tooltipGenerator.childNodes[0];
- // add unique ID to our tooltip (needed for accessibility reasons)
- tooltipNode.id = 'tooltip_' + Math.random().toString(36).substr(2, 10);
- // set initial `aria-hidden` state to `false` (it's visible!)
- tooltipNode.setAttribute('aria-hidden', 'false');
- // add title to tooltip
- var titleNode = tooltipGenerator.querySelector(this.innerSelector);
- if (title.nodeType === 1) {
- // if title is a node, append it only if allowHtml is true
- allowHtml && titleNode.appendChild(title);
- } else if (isFunction(title)) {
- // if title is a function, call it and set innerText or innerHtml depending by `allowHtml` value
- var titleText = title.call(reference);
- allowHtml ? titleNode.innerHTML = titleText : titleNode.innerText = titleText;
- } else {
- // if it's just a simple text, set innerText or innerHtml depending by `allowHtml` value
- allowHtml ? titleNode.innerHTML = title : titleNode.innerText = title;
- }
- // return the generated tooltip node
- return tooltipNode;
- }
- }, {
- key: '_show',
- value: function _show(reference, options) {
- // don't show if it's already visible
- if (this._isOpen) {
- return this;
- }
- this._isOpen = true;
- // if the tooltipNode already exists, just show it
- if (this._tooltipNode) {
- this._tooltipNode.style.display = '';
- this._tooltipNode.setAttribute('aria-hidden', 'false');
- this.popperInstance.update();
- return this;
- }
- // get title
- var title = reference.getAttribute('title') || options.title;
- // don't show tooltip if no title is defined
- if (!title) {
- return this;
- }
- // create tooltip node
- var tooltipNode = this._create(reference, options.template, title, options.html);
- // Add `aria-describedby` to our reference element for accessibility reasons
- reference.setAttribute('aria-describedby', tooltipNode.id);
- // append tooltip to container
- var container = this._findContainer(options.container, reference);
- this._append(tooltipNode, container);
- var popperOptions = _extends({}, options.popperOptions, {
- placement: options.placement
- });
- popperOptions.modifiers = _extends({}, popperOptions.modifiers, {
- arrow: {
- element: this.arrowSelector
- }
- });
- if (options.boundariesElement) {
- popperOptions.modifiers.preventOverflow = {
- boundariesElement: options.boundariesElement
- };
- }
- this.popperInstance = new Popper(reference, tooltipNode, popperOptions);
- this._tooltipNode = tooltipNode;
- return this;
- }
- }, {
- key: '_hide',
- value: function _hide() /*reference, options*/{
- // don't hide if it's already hidden
- if (!this._isOpen) {
- return this;
- }
- this._isOpen = false;
- // hide tooltipNode
- this._tooltipNode.style.display = 'none';
- this._tooltipNode.setAttribute('aria-hidden', 'true');
- return this;
- }
- }, {
- key: '_dispose',
- value: function _dispose() {
- var _this = this;
- if (this._tooltipNode) {
- this._hide();
- // destroy instance
- this.popperInstance.destroy();
- // remove event listeners
- this._events.forEach(function (_ref) {
- var func = _ref.func,
- event = _ref.event;
- _this.reference.removeEventListener(event, func);
- });
- this._events = [];
- // destroy tooltipNode
- this._tooltipNode.parentNode.removeChild(this._tooltipNode);
- this._tooltipNode = null;
- }
- return this;
- }
- }, {
- key: '_findContainer',
- value: function _findContainer(container, reference) {
- // if container is a query, get the relative element
- if (typeof container === 'string') {
- container = window.document.querySelector(container);
- } else if (container === false) {
- // if container is `false`, set it to reference parent
- container = reference.parentNode;
- }
- return container;
- }
- /**
- * Append tooltip to container
- * @memberof Tooltip
- * @private
- * @param {HTMLElement} tooltip
- * @param {HTMLElement|String|false} container
- */
- }, {
- key: '_append',
- value: function _append(tooltipNode, container) {
- container.appendChild(tooltipNode);
- }
- }, {
- key: '_setEventListeners',
- value: function _setEventListeners(reference, events, options) {
- var _this2 = this;
- var directEvents = [];
- var oppositeEvents = [];
- events.forEach(function (event) {
- switch (event) {
- case 'hover':
- directEvents.push('mouseenter');
- oppositeEvents.push('mouseleave');
- break;
- case 'focus':
- directEvents.push('focus');
- oppositeEvents.push('blur');
- break;
- case 'click':
- directEvents.push('click');
- oppositeEvents.push('click');
- break;
- }
- });
- // schedule show tooltip
- directEvents.forEach(function (event) {
- var func = function func(evt) {
- if (_this2._isOpen === true) {
- return;
- }
- evt.usedByTooltip = true;
- _this2._scheduleShow(reference, options.delay, options, evt);
- };
- _this2._events.push({ event: event, func: func });
- reference.addEventListener(event, func);
- });
- // schedule hide tooltip
- oppositeEvents.forEach(function (event) {
- var func = function func(evt) {
- if (evt.usedByTooltip === true) {
- return;
- }
- _this2._scheduleHide(reference, options.delay, options, evt);
- };
- _this2._events.push({ event: event, func: func });
- reference.addEventListener(event, func);
- });
- }
- }, {
- key: '_scheduleShow',
- value: function _scheduleShow(reference, delay, options /*, evt */) {
- var _this3 = this;
- // defaults to 0
- var computedDelay = delay && delay.show || delay || 0;
- window.setTimeout(function () {
- return _this3._show(reference, options);
- }, computedDelay);
- }
- }, {
- key: '_scheduleHide',
- value: function _scheduleHide(reference, delay, options, evt) {
- var _this4 = this;
- // defaults to 0
- var computedDelay = delay && delay.hide || delay || 0;
- window.setTimeout(function () {
- if (_this4._isOpen === false) {
- return;
- }
- if (!document.body.contains(_this4._tooltipNode)) {
- return;
- }
- // if we are hiding because of a mouseleave, we must check that the new
- // reference isn't the tooltip, because in this case we don't want to hide it
- if (evt.type === 'mouseleave') {
- var isSet = _this4._setTooltipNodeEvent(evt, reference, delay, options);
- // if we set the new event, don't hide the tooltip yet
- // the new event will take care to hide it if necessary
- if (isSet) {
- return;
- }
- }
- _this4._hide(reference, options);
- }, computedDelay);
- }
- }]);
- return Tooltip;
- }();
- /**
- * Placement function, its context is the Tooltip instance.
- * @memberof Tooltip
- * @callback PlacementFunction
- * @param {HTMLElement} tooltip - tooltip DOM node.
- * @param {HTMLElement} reference - reference DOM node.
- * @return {String} placement - One of the allowed placement options.
- */
- /**
- * Title function, its context is the Tooltip instance.
- * @memberof Tooltip
- * @callback TitleFunction
- * @return {String} placement - The desired title.
- */
- var _initialiseProps = function _initialiseProps() {
- var _this5 = this;
- this.show = function () {
- return _this5._show(_this5.reference, _this5.options);
- };
- this.hide = function () {
- return _this5._hide();
- };
- this.dispose = function () {
- return _this5._dispose();
- };
- this.toggle = function () {
- if (_this5._isOpen) {
- return _this5.hide();
- } else {
- return _this5.show();
- }
- };
- this.arrowSelector = '.tooltip-arrow, .tooltip__arrow';
- this.innerSelector = '.tooltip-inner, .tooltip__inner';
- this._events = [];
- this._setTooltipNodeEvent = function (evt, reference, delay, options) {
- var relatedreference = evt.relatedreference || evt.toElement;
- var callback = function callback(evt2) {
- var relatedreference2 = evt2.relatedreference || evt2.toElement;
- // Remove event listener after call
- _this5._tooltipNode.removeEventListener(evt.type, callback);
- // If the new reference is not the reference element
- if (!reference.contains(relatedreference2)) {
- // Schedule to hide tooltip
- _this5._scheduleHide(reference, options.delay, options, evt2);
- }
- };
- if (_this5._tooltipNode.contains(relatedreference)) {
- // listen to mouseleave on the tooltip element to be able to hide the tooltip
- _this5._tooltipNode.addEventListener(evt.type, callback);
- return true;
- }
- return false;
- };
- };
- return Tooltip;
- })));
- //# sourceMappingURL=tooltip.js.map
|