tooltip-native.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. /* Native Javascript for Bootstrap 4 | Tooltip
  2. ---------------------------------------------*/
  3. // TOOLTIP DEFINITION
  4. // ==================
  5. var Tooltip = function( element,options ) {
  6. // initialization element
  7. element = queryElement(element);
  8. // set options
  9. options = options || {};
  10. // DATA API
  11. var animationData = element[getAttribute](dataAnimation),
  12. placementData = element[getAttribute](dataPlacement),
  13. delayData = element[getAttribute](dataDelay),
  14. containerData = element[getAttribute](dataContainer),
  15. // strings
  16. component = 'tooltip',
  17. classString = 'class',
  18. title = 'title',
  19. fade = 'fade',
  20. div = 'div',
  21. // check container
  22. containerElement = queryElement(options[container]),
  23. containerDataElement = queryElement(containerData),
  24. // maybe the element is inside a modal
  25. modal = getClosest(element,'.modal'),
  26. // maybe the element is inside a fixed navbar
  27. navbarFixedTop = getClosest(element,'.'+fixedTop),
  28. navbarFixedBottom = getClosest(element,'.'+fixedBottom);
  29. // set instance options
  30. this[animation] = options[animation] && options[animation] !== fade ? options[animation] : animationData || fade;
  31. this[placement] = options[placement] ? options[placement] : placementData || top;
  32. this[delay] = parseInt(options[delay] || delayData) || 200;
  33. this[container] = containerElement ? containerElement
  34. : containerDataElement ? containerDataElement
  35. : navbarFixedTop ? navbarFixedTop
  36. : navbarFixedBottom ? navbarFixedBottom
  37. : modal ? modal : DOC[body];
  38. // bind, event targets, title and constants
  39. var self = this, timer = 0, placementSetting = this[placement], tooltip = null,
  40. titleString = element[getAttribute](title) || element[getAttribute](dataTitle) || element[getAttribute](dataOriginalTitle);
  41. if ( !titleString || titleString == "" ) return; // invalidate
  42. // private methods
  43. var removeToolTip = function() {
  44. self[container].removeChild(tooltip);
  45. tooltip = null; timer = null;
  46. },
  47. createToolTip = function() {
  48. titleString = element[getAttribute](title) || element[getAttribute](dataTitle) || element[getAttribute](dataOriginalTitle); // read the title again
  49. if ( titleString && titleString !== "" ) { // invalidate, maybe markup changed
  50. tooltip = DOC[createElement](div);
  51. tooltip[setAttribute]('role',component);
  52. tooltip[style][left] = '0';
  53. tooltip[style][top] = '0';
  54. // tooltip arrow
  55. var tooltipArrow = DOC[createElement](div);
  56. tooltipArrow[setAttribute](classString,'arrow');
  57. tooltip[appendChild](tooltipArrow);
  58. var tooltipInner = DOC[createElement](div);
  59. tooltipInner[setAttribute](classString,component+'-inner');
  60. tooltip[appendChild](tooltipInner);
  61. tooltipInner[innerHTML] = titleString;
  62. self[container][appendChild](tooltip);
  63. tooltip[setAttribute](classString, component + ' bs-' + component+'-'+placementSetting + ' ' + self[animation]);
  64. }
  65. },
  66. updateTooltip = function () {
  67. styleTip(element, tooltip, placementSetting, self[container]);
  68. },
  69. showTooltip = function () {
  70. !hasClass(tooltip,showClass) && ( addClass(tooltip,showClass) );
  71. },
  72. // triggers
  73. showTrigger = function() {
  74. on( globalObject, resizeEvent, self.hide, passiveHandler );
  75. bootstrapCustomEvent.call(element, shownEvent, component);
  76. },
  77. hideTrigger = function() {
  78. off( globalObject, resizeEvent, self.hide, passiveHandler );
  79. removeToolTip();
  80. bootstrapCustomEvent.call(element, hiddenEvent, component);
  81. };
  82. // public methods
  83. this.show = function() {
  84. clearTimeout(timer);
  85. timer = setTimeout( function() {
  86. if (tooltip === null) {
  87. placementSetting = self[placement]; // we reset placement in all cases
  88. // if(createToolTip() == false) return;
  89. if(createToolTip() !== false) {
  90. updateTooltip();
  91. showTooltip();
  92. bootstrapCustomEvent.call(element, showEvent, component);
  93. !!self[animation] ? emulateTransitionEnd(tooltip, showTrigger) : showTrigger();
  94. }
  95. }
  96. }, 20 );
  97. };
  98. this.hide = function() {
  99. clearTimeout(timer);
  100. timer = setTimeout( function() {
  101. if (tooltip && hasClass(tooltip,showClass)) {
  102. bootstrapCustomEvent.call(element, hideEvent, component);
  103. removeClass(tooltip,showClass);
  104. !!self[animation] ? emulateTransitionEnd(tooltip, hideTrigger) : hideTrigger();
  105. }
  106. }, self[delay]);
  107. };
  108. this.toggle = function() {
  109. if (!tooltip) { self.show(); }
  110. else { self.hide(); }
  111. };
  112. // init
  113. if ( !(stringTooltip in element) ) { // prevent adding event handlers twice
  114. element[setAttribute](dataOriginalTitle,titleString);
  115. element.removeAttribute(title);
  116. on(element, mouseHover[0], self.show);
  117. on(element, mouseHover[1], self.hide);
  118. }
  119. element[stringTooltip] = self;
  120. };
  121. // TOOLTIP DATA API
  122. // =================
  123. supports[push]( [ stringTooltip, Tooltip, '['+dataToggle+'="tooltip"]' ] );