tooltip.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674
  1. function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
  2. function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
  3. 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); } }
  4. function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
  5. /**
  6. * --------------------------------------------------------------------------
  7. * Bootstrap (v4.1.1): tooltip.js
  8. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  9. * --------------------------------------------------------------------------
  10. */
  11. var Tooltip = function ($) {
  12. /**
  13. * ------------------------------------------------------------------------
  14. * Constants
  15. * ------------------------------------------------------------------------
  16. */
  17. var NAME = 'tooltip';
  18. var VERSION = '4.1.1';
  19. var DATA_KEY = 'bs.tooltip';
  20. var EVENT_KEY = "." + DATA_KEY;
  21. var JQUERY_NO_CONFLICT = $.fn[NAME];
  22. var CLASS_PREFIX = 'bs-tooltip';
  23. var BSCLS_PREFIX_REGEX = new RegExp("(^|\\s)" + CLASS_PREFIX + "\\S+", 'g');
  24. var DefaultType = {
  25. animation: 'boolean',
  26. template: 'string',
  27. title: '(string|element|function)',
  28. trigger: 'string',
  29. delay: '(number|object)',
  30. html: 'boolean',
  31. selector: '(string|boolean)',
  32. placement: '(string|function)',
  33. offset: '(number|string)',
  34. container: '(string|element|boolean)',
  35. fallbackPlacement: '(string|array)',
  36. boundary: '(string|element)'
  37. };
  38. var AttachmentMap = {
  39. AUTO: 'auto',
  40. TOP: 'top',
  41. RIGHT: 'right',
  42. BOTTOM: 'bottom',
  43. LEFT: 'left'
  44. };
  45. var Default = {
  46. animation: true,
  47. template: '<div class="tooltip" role="tooltip">' + '<div class="arrow"></div>' + '<div class="tooltip-inner"></div></div>',
  48. trigger: 'hover focus',
  49. title: '',
  50. delay: 0,
  51. html: false,
  52. selector: false,
  53. placement: 'top',
  54. offset: 0,
  55. container: false,
  56. fallbackPlacement: 'flip',
  57. boundary: 'scrollParent'
  58. };
  59. var HoverState = {
  60. SHOW: 'show',
  61. OUT: 'out'
  62. };
  63. var Event = {
  64. HIDE: "hide" + EVENT_KEY,
  65. HIDDEN: "hidden" + EVENT_KEY,
  66. SHOW: "show" + EVENT_KEY,
  67. SHOWN: "shown" + EVENT_KEY,
  68. INSERTED: "inserted" + EVENT_KEY,
  69. CLICK: "click" + EVENT_KEY,
  70. FOCUSIN: "focusin" + EVENT_KEY,
  71. FOCUSOUT: "focusout" + EVENT_KEY,
  72. MOUSEENTER: "mouseenter" + EVENT_KEY,
  73. MOUSELEAVE: "mouseleave" + EVENT_KEY
  74. };
  75. var ClassName = {
  76. FADE: 'fade',
  77. SHOW: 'show'
  78. };
  79. var Selector = {
  80. TOOLTIP: '.tooltip',
  81. TOOLTIP_INNER: '.tooltip-inner',
  82. ARROW: '.arrow'
  83. };
  84. var Trigger = {
  85. HOVER: 'hover',
  86. FOCUS: 'focus',
  87. CLICK: 'click',
  88. MANUAL: 'manual'
  89. /**
  90. * ------------------------------------------------------------------------
  91. * Class Definition
  92. * ------------------------------------------------------------------------
  93. */
  94. };
  95. var Tooltip =
  96. /*#__PURE__*/
  97. function () {
  98. function Tooltip(element, config) {
  99. /**
  100. * Check for Popper dependency
  101. * Popper - https://popper.js.org
  102. */
  103. if (typeof Popper === 'undefined') {
  104. throw new TypeError('Bootstrap tooltips require Popper.js (https://popper.js.org)');
  105. } // private
  106. this._isEnabled = true;
  107. this._timeout = 0;
  108. this._hoverState = '';
  109. this._activeTrigger = {};
  110. this._popper = null; // Protected
  111. this.element = element;
  112. this.config = this._getConfig(config);
  113. this.tip = null;
  114. this._setListeners();
  115. } // Getters
  116. var _proto = Tooltip.prototype;
  117. // Public
  118. _proto.enable = function enable() {
  119. this._isEnabled = true;
  120. };
  121. _proto.disable = function disable() {
  122. this._isEnabled = false;
  123. };
  124. _proto.toggleEnabled = function toggleEnabled() {
  125. this._isEnabled = !this._isEnabled;
  126. };
  127. _proto.toggle = function toggle(event) {
  128. if (!this._isEnabled) {
  129. return;
  130. }
  131. if (event) {
  132. var dataKey = this.constructor.DATA_KEY;
  133. var context = $(event.currentTarget).data(dataKey);
  134. if (!context) {
  135. context = new this.constructor(event.currentTarget, this._getDelegateConfig());
  136. $(event.currentTarget).data(dataKey, context);
  137. }
  138. context._activeTrigger.click = !context._activeTrigger.click;
  139. if (context._isWithActiveTrigger()) {
  140. context._enter(null, context);
  141. } else {
  142. context._leave(null, context);
  143. }
  144. } else {
  145. if ($(this.getTipElement()).hasClass(ClassName.SHOW)) {
  146. this._leave(null, this);
  147. return;
  148. }
  149. this._enter(null, this);
  150. }
  151. };
  152. _proto.dispose = function dispose() {
  153. clearTimeout(this._timeout);
  154. $.removeData(this.element, this.constructor.DATA_KEY);
  155. $(this.element).off(this.constructor.EVENT_KEY);
  156. $(this.element).closest('.modal').off('hide.bs.modal');
  157. if (this.tip) {
  158. $(this.tip).remove();
  159. }
  160. this._isEnabled = null;
  161. this._timeout = null;
  162. this._hoverState = null;
  163. this._activeTrigger = null;
  164. if (this._popper !== null) {
  165. this._popper.destroy();
  166. }
  167. this._popper = null;
  168. this.element = null;
  169. this.config = null;
  170. this.tip = null;
  171. };
  172. _proto.show = function show() {
  173. var _this = this;
  174. if ($(this.element).css('display') === 'none') {
  175. throw new Error('Please use show on visible elements');
  176. }
  177. var showEvent = $.Event(this.constructor.Event.SHOW);
  178. if (this.isWithContent() && this._isEnabled) {
  179. $(this.element).trigger(showEvent);
  180. var isInTheDom = $.contains(this.element.ownerDocument.documentElement, this.element);
  181. if (showEvent.isDefaultPrevented() || !isInTheDom) {
  182. return;
  183. }
  184. var tip = this.getTipElement();
  185. var tipId = Util.getUID(this.constructor.NAME);
  186. tip.setAttribute('id', tipId);
  187. this.element.setAttribute('aria-describedby', tipId);
  188. this.setContent();
  189. if (this.config.animation) {
  190. $(tip).addClass(ClassName.FADE);
  191. }
  192. var placement = typeof this.config.placement === 'function' ? this.config.placement.call(this, tip, this.element) : this.config.placement;
  193. var attachment = this._getAttachment(placement);
  194. this.addAttachmentClass(attachment);
  195. var container = this.config.container === false ? document.body : $(this.config.container);
  196. $(tip).data(this.constructor.DATA_KEY, this);
  197. if (!$.contains(this.element.ownerDocument.documentElement, this.tip)) {
  198. $(tip).appendTo(container);
  199. }
  200. $(this.element).trigger(this.constructor.Event.INSERTED);
  201. this._popper = new Popper(this.element, tip, {
  202. placement: attachment,
  203. modifiers: {
  204. offset: {
  205. offset: this.config.offset
  206. },
  207. flip: {
  208. behavior: this.config.fallbackPlacement
  209. },
  210. arrow: {
  211. element: Selector.ARROW
  212. },
  213. preventOverflow: {
  214. boundariesElement: this.config.boundary
  215. }
  216. },
  217. onCreate: function onCreate(data) {
  218. if (data.originalPlacement !== data.placement) {
  219. _this._handlePopperPlacementChange(data);
  220. }
  221. },
  222. onUpdate: function onUpdate(data) {
  223. _this._handlePopperPlacementChange(data);
  224. }
  225. });
  226. $(tip).addClass(ClassName.SHOW); // If this is a touch-enabled device we add extra
  227. // empty mouseover listeners to the body's immediate children;
  228. // only needed because of broken event delegation on iOS
  229. // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
  230. if ('ontouchstart' in document.documentElement) {
  231. $(document.body).children().on('mouseover', null, $.noop);
  232. }
  233. var complete = function complete() {
  234. if (_this.config.animation) {
  235. _this._fixTransition();
  236. }
  237. var prevHoverState = _this._hoverState;
  238. _this._hoverState = null;
  239. $(_this.element).trigger(_this.constructor.Event.SHOWN);
  240. if (prevHoverState === HoverState.OUT) {
  241. _this._leave(null, _this);
  242. }
  243. };
  244. if ($(this.tip).hasClass(ClassName.FADE)) {
  245. var transitionDuration = Util.getTransitionDurationFromElement(this.tip);
  246. $(this.tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);
  247. } else {
  248. complete();
  249. }
  250. }
  251. };
  252. _proto.hide = function hide(callback) {
  253. var _this2 = this;
  254. var tip = this.getTipElement();
  255. var hideEvent = $.Event(this.constructor.Event.HIDE);
  256. var complete = function complete() {
  257. if (_this2._hoverState !== HoverState.SHOW && tip.parentNode) {
  258. tip.parentNode.removeChild(tip);
  259. }
  260. _this2._cleanTipClass();
  261. _this2.element.removeAttribute('aria-describedby');
  262. $(_this2.element).trigger(_this2.constructor.Event.HIDDEN);
  263. if (_this2._popper !== null) {
  264. _this2._popper.destroy();
  265. }
  266. if (callback) {
  267. callback();
  268. }
  269. };
  270. $(this.element).trigger(hideEvent);
  271. if (hideEvent.isDefaultPrevented()) {
  272. return;
  273. }
  274. $(tip).removeClass(ClassName.SHOW); // If this is a touch-enabled device we remove the extra
  275. // empty mouseover listeners we added for iOS support
  276. if ('ontouchstart' in document.documentElement) {
  277. $(document.body).children().off('mouseover', null, $.noop);
  278. }
  279. this._activeTrigger[Trigger.CLICK] = false;
  280. this._activeTrigger[Trigger.FOCUS] = false;
  281. this._activeTrigger[Trigger.HOVER] = false;
  282. if ($(this.tip).hasClass(ClassName.FADE)) {
  283. var transitionDuration = Util.getTransitionDurationFromElement(tip);
  284. $(tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);
  285. } else {
  286. complete();
  287. }
  288. this._hoverState = '';
  289. };
  290. _proto.update = function update() {
  291. if (this._popper !== null) {
  292. this._popper.scheduleUpdate();
  293. }
  294. }; // Protected
  295. _proto.isWithContent = function isWithContent() {
  296. return Boolean(this.getTitle());
  297. };
  298. _proto.addAttachmentClass = function addAttachmentClass(attachment) {
  299. $(this.getTipElement()).addClass(CLASS_PREFIX + "-" + attachment);
  300. };
  301. _proto.getTipElement = function getTipElement() {
  302. this.tip = this.tip || $(this.config.template)[0];
  303. return this.tip;
  304. };
  305. _proto.setContent = function setContent() {
  306. var $tip = $(this.getTipElement());
  307. this.setElementContent($tip.find(Selector.TOOLTIP_INNER), this.getTitle());
  308. $tip.removeClass(ClassName.FADE + " " + ClassName.SHOW);
  309. };
  310. _proto.setElementContent = function setElementContent($element, content) {
  311. var html = this.config.html;
  312. if (typeof content === 'object' && (content.nodeType || content.jquery)) {
  313. // Content is a DOM node or a jQuery
  314. if (html) {
  315. if (!$(content).parent().is($element)) {
  316. $element.empty().append(content);
  317. }
  318. } else {
  319. $element.text($(content).text());
  320. }
  321. } else {
  322. $element[html ? 'html' : 'text'](content);
  323. }
  324. };
  325. _proto.getTitle = function getTitle() {
  326. var title = this.element.getAttribute('data-original-title');
  327. if (!title) {
  328. title = typeof this.config.title === 'function' ? this.config.title.call(this.element) : this.config.title;
  329. }
  330. return title;
  331. }; // Private
  332. _proto._getAttachment = function _getAttachment(placement) {
  333. return AttachmentMap[placement.toUpperCase()];
  334. };
  335. _proto._setListeners = function _setListeners() {
  336. var _this3 = this;
  337. var triggers = this.config.trigger.split(' ');
  338. triggers.forEach(function (trigger) {
  339. if (trigger === 'click') {
  340. $(_this3.element).on(_this3.constructor.Event.CLICK, _this3.config.selector, function (event) {
  341. return _this3.toggle(event);
  342. });
  343. } else if (trigger !== Trigger.MANUAL) {
  344. var eventIn = trigger === Trigger.HOVER ? _this3.constructor.Event.MOUSEENTER : _this3.constructor.Event.FOCUSIN;
  345. var eventOut = trigger === Trigger.HOVER ? _this3.constructor.Event.MOUSELEAVE : _this3.constructor.Event.FOCUSOUT;
  346. $(_this3.element).on(eventIn, _this3.config.selector, function (event) {
  347. return _this3._enter(event);
  348. }).on(eventOut, _this3.config.selector, function (event) {
  349. return _this3._leave(event);
  350. });
  351. }
  352. $(_this3.element).closest('.modal').on('hide.bs.modal', function () {
  353. return _this3.hide();
  354. });
  355. });
  356. if (this.config.selector) {
  357. this.config = _objectSpread({}, this.config, {
  358. trigger: 'manual',
  359. selector: ''
  360. });
  361. } else {
  362. this._fixTitle();
  363. }
  364. };
  365. _proto._fixTitle = function _fixTitle() {
  366. var titleType = typeof this.element.getAttribute('data-original-title');
  367. if (this.element.getAttribute('title') || titleType !== 'string') {
  368. this.element.setAttribute('data-original-title', this.element.getAttribute('title') || '');
  369. this.element.setAttribute('title', '');
  370. }
  371. };
  372. _proto._enter = function _enter(event, context) {
  373. var dataKey = this.constructor.DATA_KEY;
  374. context = context || $(event.currentTarget).data(dataKey);
  375. if (!context) {
  376. context = new this.constructor(event.currentTarget, this._getDelegateConfig());
  377. $(event.currentTarget).data(dataKey, context);
  378. }
  379. if (event) {
  380. context._activeTrigger[event.type === 'focusin' ? Trigger.FOCUS : Trigger.HOVER] = true;
  381. }
  382. if ($(context.getTipElement()).hasClass(ClassName.SHOW) || context._hoverState === HoverState.SHOW) {
  383. context._hoverState = HoverState.SHOW;
  384. return;
  385. }
  386. clearTimeout(context._timeout);
  387. context._hoverState = HoverState.SHOW;
  388. if (!context.config.delay || !context.config.delay.show) {
  389. context.show();
  390. return;
  391. }
  392. context._timeout = setTimeout(function () {
  393. if (context._hoverState === HoverState.SHOW) {
  394. context.show();
  395. }
  396. }, context.config.delay.show);
  397. };
  398. _proto._leave = function _leave(event, context) {
  399. var dataKey = this.constructor.DATA_KEY;
  400. context = context || $(event.currentTarget).data(dataKey);
  401. if (!context) {
  402. context = new this.constructor(event.currentTarget, this._getDelegateConfig());
  403. $(event.currentTarget).data(dataKey, context);
  404. }
  405. if (event) {
  406. context._activeTrigger[event.type === 'focusout' ? Trigger.FOCUS : Trigger.HOVER] = false;
  407. }
  408. if (context._isWithActiveTrigger()) {
  409. return;
  410. }
  411. clearTimeout(context._timeout);
  412. context._hoverState = HoverState.OUT;
  413. if (!context.config.delay || !context.config.delay.hide) {
  414. context.hide();
  415. return;
  416. }
  417. context._timeout = setTimeout(function () {
  418. if (context._hoverState === HoverState.OUT) {
  419. context.hide();
  420. }
  421. }, context.config.delay.hide);
  422. };
  423. _proto._isWithActiveTrigger = function _isWithActiveTrigger() {
  424. for (var trigger in this._activeTrigger) {
  425. if (this._activeTrigger[trigger]) {
  426. return true;
  427. }
  428. }
  429. return false;
  430. };
  431. _proto._getConfig = function _getConfig(config) {
  432. config = _objectSpread({}, this.constructor.Default, $(this.element).data(), typeof config === 'object' && config ? config : {});
  433. if (typeof config.delay === 'number') {
  434. config.delay = {
  435. show: config.delay,
  436. hide: config.delay
  437. };
  438. }
  439. if (typeof config.title === 'number') {
  440. config.title = config.title.toString();
  441. }
  442. if (typeof config.content === 'number') {
  443. config.content = config.content.toString();
  444. }
  445. Util.typeCheckConfig(NAME, config, this.constructor.DefaultType);
  446. return config;
  447. };
  448. _proto._getDelegateConfig = function _getDelegateConfig() {
  449. var config = {};
  450. if (this.config) {
  451. for (var key in this.config) {
  452. if (this.constructor.Default[key] !== this.config[key]) {
  453. config[key] = this.config[key];
  454. }
  455. }
  456. }
  457. return config;
  458. };
  459. _proto._cleanTipClass = function _cleanTipClass() {
  460. var $tip = $(this.getTipElement());
  461. var tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX);
  462. if (tabClass !== null && tabClass.length > 0) {
  463. $tip.removeClass(tabClass.join(''));
  464. }
  465. };
  466. _proto._handlePopperPlacementChange = function _handlePopperPlacementChange(data) {
  467. this._cleanTipClass();
  468. this.addAttachmentClass(this._getAttachment(data.placement));
  469. };
  470. _proto._fixTransition = function _fixTransition() {
  471. var tip = this.getTipElement();
  472. var initConfigAnimation = this.config.animation;
  473. if (tip.getAttribute('x-placement') !== null) {
  474. return;
  475. }
  476. $(tip).removeClass(ClassName.FADE);
  477. this.config.animation = false;
  478. this.hide();
  479. this.show();
  480. this.config.animation = initConfigAnimation;
  481. }; // Static
  482. Tooltip._jQueryInterface = function _jQueryInterface(config) {
  483. return this.each(function () {
  484. var data = $(this).data(DATA_KEY);
  485. var _config = typeof config === 'object' && config;
  486. if (!data && /dispose|hide/.test(config)) {
  487. return;
  488. }
  489. if (!data) {
  490. data = new Tooltip(this, _config);
  491. $(this).data(DATA_KEY, data);
  492. }
  493. if (typeof config === 'string') {
  494. if (typeof data[config] === 'undefined') {
  495. throw new TypeError("No method named \"" + config + "\"");
  496. }
  497. data[config]();
  498. }
  499. });
  500. };
  501. _createClass(Tooltip, null, [{
  502. key: "VERSION",
  503. get: function get() {
  504. return VERSION;
  505. }
  506. }, {
  507. key: "Default",
  508. get: function get() {
  509. return Default;
  510. }
  511. }, {
  512. key: "NAME",
  513. get: function get() {
  514. return NAME;
  515. }
  516. }, {
  517. key: "DATA_KEY",
  518. get: function get() {
  519. return DATA_KEY;
  520. }
  521. }, {
  522. key: "Event",
  523. get: function get() {
  524. return Event;
  525. }
  526. }, {
  527. key: "EVENT_KEY",
  528. get: function get() {
  529. return EVENT_KEY;
  530. }
  531. }, {
  532. key: "DefaultType",
  533. get: function get() {
  534. return DefaultType;
  535. }
  536. }]);
  537. return Tooltip;
  538. }();
  539. /**
  540. * ------------------------------------------------------------------------
  541. * jQuery
  542. * ------------------------------------------------------------------------
  543. */
  544. $.fn[NAME] = Tooltip._jQueryInterface;
  545. $.fn[NAME].Constructor = Tooltip;
  546. $.fn[NAME].noConflict = function () {
  547. $.fn[NAME] = JQUERY_NO_CONFLICT;
  548. return Tooltip._jQueryInterface;
  549. };
  550. return Tooltip;
  551. }($, Popper);
  552. //# sourceMappingURL=tooltip.js.map