tooltip-native.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /* Native Javascript for Bootstrap 3 | 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 == "" ) return false; // invalidate
  50. tooltip = DOC[createElement](div);
  51. tooltip[setAttribute]('role',component);
  52. var tooltipArrow = DOC[createElement](div), tooltipInner = DOC[createElement](div);
  53. tooltipArrow[setAttribute](classString, component+'-arrow'); tooltipInner[setAttribute](classString,component+'-inner');
  54. tooltip[appendChild](tooltipArrow); tooltip[appendChild](tooltipInner);
  55. tooltipInner[innerHTML] = titleString;
  56. self[container][appendChild](tooltip);
  57. tooltip[setAttribute](classString, component + ' ' + placementSetting + ' ' + self[animation]);
  58. },
  59. updateTooltip = function () {
  60. styleTip(element,tooltip,placementSetting,self[container]);
  61. },
  62. showTooltip = function () {
  63. !hasClass(tooltip,inClass) && ( addClass(tooltip,inClass) );
  64. },
  65. // triggers
  66. showTrigger = function() {
  67. bootstrapCustomEvent.call(element, shownEvent, component);
  68. !isIE8 && on( globalObject, resizeEvent, self.hide, passiveHandler );
  69. },
  70. hideTrigger = function() {
  71. !isIE8 && off( globalObject, resizeEvent, self.hide, passiveHandler );
  72. removeToolTip();
  73. bootstrapCustomEvent.call(element, hiddenEvent, component);
  74. };
  75. // public methods
  76. this.show = function() {
  77. clearTimeout(timer);
  78. timer = setTimeout( function() {
  79. if (tooltip === null) {
  80. placementSetting = self[placement]; // we reset placement in all cases
  81. if(createToolTip() == false) return;
  82. updateTooltip();
  83. showTooltip();
  84. bootstrapCustomEvent.call(element, showEvent, component);
  85. !!self[animation] ? emulateTransitionEnd(tooltip, showTrigger) : showTrigger();
  86. }
  87. }, 20 );
  88. };
  89. this.hide = function() {
  90. clearTimeout(timer);
  91. timer = setTimeout( function() {
  92. if (tooltip && hasClass(tooltip,inClass)) {
  93. bootstrapCustomEvent.call(element, hideEvent, component);
  94. removeClass(tooltip,inClass);
  95. !!self[animation] ? emulateTransitionEnd(tooltip, hideTrigger) : hideTrigger();
  96. }
  97. }, self[delay]);
  98. };
  99. this.toggle = function() {
  100. if (!tooltip) { self.show(); }
  101. else { self.hide(); }
  102. };
  103. // init
  104. if ( !(stringTooltip in element) ) { // prevent adding event handlers twice
  105. element[setAttribute](dataOriginalTitle,titleString);
  106. element.removeAttribute(title);
  107. on(element, mouseHover[0], self.show);
  108. on(element, mouseHover[1], self.hide);
  109. }
  110. element[stringTooltip] = self;
  111. };
  112. // TOOLTIP DATA API
  113. // =================
  114. supports[push]( [ stringTooltip, Tooltip, '['+dataToggle+'="tooltip"]' ] );