bootstrap-tooltip.js 7.66 KB
Newer Older
Jacob Thornton's avatar
Jacob Thornton committed
1
/* ===========================================================
Mark Otto's avatar
Mark Otto committed
2
 * bootstrap-tooltip.js v2.2.3
Jacob Thornton's avatar
Jacob Thornton committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 * http://twitter.github.com/bootstrap/javascript.html#tooltips
 * Inspired by the original jQuery.tipsy by Jason Frame
 * ===========================================================
 * Copyright 2012 Twitter, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ========================================================== */

21

22
23
24
!function ($) {

  "use strict"; // jshint ;_;
Jacob Thornton's avatar
Jacob Thornton committed
25
26
27
28
29


 /* TOOLTIP PUBLIC CLASS DEFINITION
  * =============================== */

30
  var Tooltip = function (element, options) {
Jacob Thornton's avatar
Jacob Thornton committed
31
32
33
34
35
36
37
    this.init('tooltip', element, options)
  }

  Tooltip.prototype = {

    constructor: Tooltip

38
  , init: function (type, element, options) {
Jacob Thornton's avatar
Jacob Thornton committed
39
40
41
42
43
44
45
46
      var eventIn
        , eventOut

      this.type = type
      this.$element = $(element)
      this.options = this.getOptions(options)
      this.enabled = true

47
48
49
50
      if (this.options.trigger == 'click') {
        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
      } else if (this.options.trigger != 'manual') {
        eventIn = this.options.trigger == 'hover' ? 'mouseenter' : 'focus'
Jacob Thornton's avatar
Jacob Thornton committed
51
        eventOut = this.options.trigger == 'hover' ? 'mouseleave' : 'blur'
Jacob Thornton's avatar
Jacob Thornton committed
52
53
        this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
Jacob Thornton's avatar
Jacob Thornton committed
54
55
56
57
58
59
60
      }

      this.options.selector ?
        (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
        this.fixTitle()
    }

61
  , getOptions: function (options) {
Jacob Thornton's avatar
Jacob Thornton committed
62
63
64
65
66
67
68
69
70
71
72
73
      options = $.extend({}, $.fn[this.type].defaults, options, this.$element.data())

      if (options.delay && typeof options.delay == 'number') {
        options.delay = {
          show: options.delay
        , hide: options.delay
        }
      }

      return options
    }

74
  , enter: function (e) {
Jacob Thornton's avatar
Jacob Thornton committed
75
76
      var self = $(e.currentTarget)[this.type](this._options).data(this.type)

77
78
79
80
81
82
83
      if (!self.options.delay || !self.options.delay.show) return self.show()

      clearTimeout(this.timeout)
      self.hoverState = 'in'
      this.timeout = setTimeout(function() {
        if (self.hoverState == 'in') self.show()
      }, self.options.delay.show)
Jacob Thornton's avatar
Jacob Thornton committed
84
85
    }

86
  , leave: function (e) {
Jacob Thornton's avatar
Jacob Thornton committed
87
88
      var self = $(e.currentTarget)[this.type](this._options).data(this.type)

Jacob Thornton's avatar
Jacob Thornton committed
89
      if (this.timeout) clearTimeout(this.timeout)
90
91
92
93
94
95
      if (!self.options.delay || !self.options.delay.hide) return self.hide()

      self.hoverState = 'out'
      this.timeout = setTimeout(function() {
        if (self.hoverState == 'out') self.hide()
      }, self.options.delay.hide)
Jacob Thornton's avatar
Jacob Thornton committed
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
    }

  , show: function () {
      var $tip
        , pos
        , actualWidth
        , actualHeight
        , placement
        , tp

      if (this.hasContent() && this.enabled) {
        $tip = this.tip()
        this.setContent()

        if (this.options.animation) {
          $tip.addClass('fade')
        }

        placement = typeof this.options.placement == 'function' ?
          this.options.placement.call(this, $tip[0], this.$element[0]) :
          this.options.placement

        $tip
Jacob Thornton's avatar
rebuild    
Jacob Thornton committed
119
          .detach()
Jacob Thornton's avatar
Jacob Thornton committed
120
          .css({ top: 0, left: 0, display: 'block' })
121
          .insertAfter(this.$element)
Jacob Thornton's avatar
Jacob Thornton committed
122

123
        pos = this.getPosition()
Jacob Thornton's avatar
Jacob Thornton committed
124
125
126
127

        actualWidth = $tip[0].offsetWidth
        actualHeight = $tip[0].offsetHeight

128
        switch (placement) {
Jacob Thornton's avatar
Jacob Thornton committed
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
          case 'bottom':
            tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2}
            break
          case 'top':
            tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2}
            break
          case 'left':
            tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth}
            break
          case 'right':
            tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}
            break
        }

        $tip
144
          .offset(tp)
Jacob Thornton's avatar
Jacob Thornton committed
145
146
147
148
149
150
151
          .addClass(placement)
          .addClass('in')
      }
    }

  , setContent: function () {
      var $tip = this.tip()
152
153
        , title = this.getTitle()

154
      $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
Jacob Thornton's avatar
Jacob Thornton committed
155
156
157
158
159
160
161
162
163
164
165
      $tip.removeClass('fade in top bottom left right')
    }

  , hide: function () {
      var that = this
        , $tip = this.tip()

      $tip.removeClass('in')

      function removeWithAnimation() {
        var timeout = setTimeout(function () {
Jacob Thornton's avatar
rebuild    
Jacob Thornton committed
166
          $tip.off($.support.transition.end).detach()
Jacob Thornton's avatar
Jacob Thornton committed
167
168
169
170
        }, 500)

        $tip.one($.support.transition.end, function () {
          clearTimeout(timeout)
Jacob Thornton's avatar
rebuild    
Jacob Thornton committed
171
          $tip.detach()
Jacob Thornton's avatar
Jacob Thornton committed
172
173
174
175
176
        })
      }

      $.support.transition && this.$tip.hasClass('fade') ?
        removeWithAnimation() :
Jacob Thornton's avatar
rebuild    
Jacob Thornton committed
177
        $tip.detach()
Jacob Thornton's avatar
Jacob Thornton committed
178
179

      return this
Jacob Thornton's avatar
Jacob Thornton committed
180
181
182
183
184
185
186
187
188
189
190
191
192
    }

  , fixTitle: function () {
      var $e = this.$element
      if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
        $e.attr('data-original-title', $e.attr('title') || '').removeAttr('title')
      }
    }

  , hasContent: function () {
      return this.getTitle()
    }

193
194
  , getPosition: function () {
      var el = this.$element[0]
fat's avatar
fat committed
195
      return $.extend({}, el.getBoundingClientRect ? el.getBoundingClientRect() : {
196
197
198
        width: el.offsetWidth
      , height: el.offsetHeight
      }, this.$element.offset())
Jacob Thornton's avatar
Jacob Thornton committed
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
    }

  , getTitle: function () {
      var title
        , $e = this.$element
        , o = this.options

      title = $e.attr('data-original-title')
        || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)

      return title
    }

  , tip: function () {
      return this.$tip = this.$tip || $(this.options.template)
    }

  , validate: function () {
      if (!this.$element[0].parentNode) {
        this.hide()
        this.$element = null
        this.options = null
      }
    }

  , enable: function () {
      this.enabled = true
    }

  , disable: function () {
      this.enabled = false
    }

  , toggleEnabled: function () {
      this.enabled = !this.enabled
    }

Jacob Thornton's avatar
Jacob Thornton committed
236
237
238
  , toggle: function (e) {
      var self = $(e.currentTarget)[this.type](this._options).data(this.type)
      self[self.tip().hasClass('in') ? 'hide' : 'show']()
Jacob Thornton's avatar
Jacob Thornton committed
239
240
    }

Mark Otto's avatar
Mark Otto committed
241
  , destroy: function () {
Jacob Thornton's avatar
Jacob Thornton committed
242
      this.hide().$element.off('.' + this.type).removeData(this.type)
Mark Otto's avatar
Mark Otto committed
243
244
    }

Jacob Thornton's avatar
Jacob Thornton committed
245
246
247
248
249
250
  }


 /* TOOLTIP PLUGIN DEFINITION
  * ========================= */

251
252
  var old = $.fn.tooltip

Jacob Thornton's avatar
Jacob Thornton committed
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
  $.fn.tooltip = function ( option ) {
    return this.each(function () {
      var $this = $(this)
        , data = $this.data('tooltip')
        , options = typeof option == 'object' && option
      if (!data) $this.data('tooltip', (data = new Tooltip(this, options)))
      if (typeof option == 'string') data[option]()
    })
  }

  $.fn.tooltip.Constructor = Tooltip

  $.fn.tooltip.defaults = {
    animation: true
  , placement: 'top'
268
269
  , selector: false
  , template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
Jacob Thornton's avatar
Jacob Thornton committed
270
271
  , trigger: 'hover'
  , title: ''
272
  , delay: 0
273
  , html: false
Jacob Thornton's avatar
Jacob Thornton committed
274
275
  }

276
277
278
279
280
281
282
283
284

 /* TOOLTIP NO CONFLICT
  * =================== */

  $.fn.tooltip.noConflict = function () {
    $.fn.tooltip = old
    return this
  }

285
}(window.jQuery);