popover.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /**
  2. * --------------------------------------------------------------------------
  3. * Bootstrap (v5.0.2): popover.js
  4. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
  5. * --------------------------------------------------------------------------
  6. */
  7. import { defineJQueryPlugin } from './util/index'
  8. import SelectorEngine from './dom/selector-engine'
  9. import Tooltip from './tooltip'
  10. /**
  11. * ------------------------------------------------------------------------
  12. * Constants
  13. * ------------------------------------------------------------------------
  14. */
  15. const NAME = 'popover'
  16. const DATA_KEY = 'bs.popover'
  17. const EVENT_KEY = `.${DATA_KEY}`
  18. const CLASS_PREFIX = 'bs-popover'
  19. const BSCLS_PREFIX_REGEX = new RegExp(`(^|\\s)${CLASS_PREFIX}\\S+`, 'g')
  20. const Default = {
  21. ...Tooltip.Default,
  22. placement: 'right',
  23. offset: [0, 8],
  24. trigger: 'click',
  25. content: '',
  26. template: '<div class="popover" role="tooltip">' +
  27. '<div class="popover-arrow"></div>' +
  28. '<h3 class="popover-header"></h3>' +
  29. '<div class="popover-body"></div>' +
  30. '</div>'
  31. }
  32. const DefaultType = {
  33. ...Tooltip.DefaultType,
  34. content: '(string|element|function)'
  35. }
  36. const Event = {
  37. HIDE: `hide${EVENT_KEY}`,
  38. HIDDEN: `hidden${EVENT_KEY}`,
  39. SHOW: `show${EVENT_KEY}`,
  40. SHOWN: `shown${EVENT_KEY}`,
  41. INSERTED: `inserted${EVENT_KEY}`,
  42. CLICK: `click${EVENT_KEY}`,
  43. FOCUSIN: `focusin${EVENT_KEY}`,
  44. FOCUSOUT: `focusout${EVENT_KEY}`,
  45. MOUSEENTER: `mouseenter${EVENT_KEY}`,
  46. MOUSELEAVE: `mouseleave${EVENT_KEY}`
  47. }
  48. const CLASS_NAME_FADE = 'fade'
  49. const CLASS_NAME_SHOW = 'show'
  50. const SELECTOR_TITLE = '.popover-header'
  51. const SELECTOR_CONTENT = '.popover-body'
  52. /**
  53. * ------------------------------------------------------------------------
  54. * Class Definition
  55. * ------------------------------------------------------------------------
  56. */
  57. class Popover extends Tooltip {
  58. // Getters
  59. static get Default() {
  60. return Default
  61. }
  62. static get NAME() {
  63. return NAME
  64. }
  65. static get Event() {
  66. return Event
  67. }
  68. static get DefaultType() {
  69. return DefaultType
  70. }
  71. // Overrides
  72. isWithContent() {
  73. return this.getTitle() || this._getContent()
  74. }
  75. getTipElement() {
  76. if (this.tip) {
  77. return this.tip
  78. }
  79. this.tip = super.getTipElement()
  80. if (!this.getTitle()) {
  81. SelectorEngine.findOne(SELECTOR_TITLE, this.tip).remove()
  82. }
  83. if (!this._getContent()) {
  84. SelectorEngine.findOne(SELECTOR_CONTENT, this.tip).remove()
  85. }
  86. return this.tip
  87. }
  88. setContent() {
  89. const tip = this.getTipElement()
  90. // we use append for html objects to maintain js events
  91. this.setElementContent(SelectorEngine.findOne(SELECTOR_TITLE, tip), this.getTitle())
  92. let content = this._getContent()
  93. if (typeof content === 'function') {
  94. content = content.call(this._element)
  95. }
  96. this.setElementContent(SelectorEngine.findOne(SELECTOR_CONTENT, tip), content)
  97. tip.classList.remove(CLASS_NAME_FADE, CLASS_NAME_SHOW)
  98. }
  99. // Private
  100. _addAttachmentClass(attachment) {
  101. this.getTipElement().classList.add(`${CLASS_PREFIX}-${this.updateAttachment(attachment)}`)
  102. }
  103. _getContent() {
  104. return this._element.getAttribute('data-bs-content') || this._config.content
  105. }
  106. _cleanTipClass() {
  107. const tip = this.getTipElement()
  108. const tabClass = tip.getAttribute('class').match(BSCLS_PREFIX_REGEX)
  109. if (tabClass !== null && tabClass.length > 0) {
  110. tabClass.map(token => token.trim())
  111. .forEach(tClass => tip.classList.remove(tClass))
  112. }
  113. }
  114. // Static
  115. static jQueryInterface(config) {
  116. return this.each(function () {
  117. const data = Popover.getOrCreateInstance(this, config)
  118. if (typeof config === 'string') {
  119. if (typeof data[config] === 'undefined') {
  120. throw new TypeError(`No method named "${config}"`)
  121. }
  122. data[config]()
  123. }
  124. })
  125. }
  126. }
  127. /**
  128. * ------------------------------------------------------------------------
  129. * jQuery
  130. * ------------------------------------------------------------------------
  131. * add .Popover to jQuery only if jQuery is present
  132. */
  133. defineJQueryPlugin(Popover)
  134. export default Popover