Back to home page

OSCL-LXR

 
 

    


0001 /* ===========================================================
0002  * bootstrap-tooltip.js v2.3.2
0003  * http://getbootstrap.com/2.3.2/javascript.html#tooltips
0004  * Inspired by the original jQuery.tipsy by Jason Frame
0005  * ===========================================================
0006  * Copyright 2013 Twitter, Inc.
0007  *
0008  * Licensed under the Apache License, Version 2.0 (the "License");
0009  * you may not use this file except in compliance with the License.
0010  * You may obtain a copy of the License at
0011  *
0012  * http://www.apache.org/licenses/LICENSE-2.0
0013  *
0014  * Unless required by applicable law or agreed to in writing, software
0015  * distributed under the License is distributed on an "AS IS" BASIS,
0016  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0017  * See the License for the specific language governing permissions and
0018  * limitations under the License.
0019  * ========================================================== */
0020 
0021 
0022 !function ($) {
0023 
0024   "use strict"; // jshint ;_;
0025 
0026 
0027  /* TOOLTIP PUBLIC CLASS DEFINITION
0028   * =============================== */
0029 
0030   var Tooltip = function (element, options) {
0031     this.init('tooltip', element, options)
0032   }
0033 
0034   Tooltip.prototype = {
0035 
0036     constructor: Tooltip
0037 
0038   , init: function (type, element, options) {
0039       var eventIn
0040         , eventOut
0041         , triggers
0042         , trigger
0043         , i
0044 
0045       this.type = type
0046       this.$element = $(element)
0047       this.options = this.getOptions(options)
0048       this.enabled = true
0049 
0050       triggers = this.options.trigger.split(' ')
0051 
0052       for (i = triggers.length; i--;) {
0053         trigger = triggers[i]
0054         if (trigger == 'click') {
0055           this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
0056         } else if (trigger != 'manual') {
0057           eventIn = trigger == 'hover' ? 'mouseenter' : 'focus'
0058           eventOut = trigger == 'hover' ? 'mouseleave' : 'blur'
0059           this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
0060           this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
0061         }
0062       }
0063 
0064       this.options.selector ?
0065         (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
0066         this.fixTitle()
0067     }
0068 
0069   , getOptions: function (options) {
0070       options = $.extend({}, $.fn[this.type].defaults, this.$element.data(), options)
0071 
0072       if (options.delay && typeof options.delay == 'number') {
0073         options.delay = {
0074           show: options.delay
0075         , hide: options.delay
0076         }
0077       }
0078 
0079       return options
0080     }
0081 
0082   , enter: function (e) {
0083       var defaults = $.fn[this.type].defaults
0084         , options = {}
0085         , self
0086 
0087       this._options && $.each(this._options, function (key, value) {
0088         if (defaults[key] != value) options[key] = value
0089       }, this)
0090 
0091       self = $(e.currentTarget)[this.type](options).data(this.type)
0092 
0093       if (!self.options.delay || !self.options.delay.show) return self.show()
0094 
0095       clearTimeout(this.timeout)
0096       self.hoverState = 'in'
0097       this.timeout = setTimeout(function() {
0098         if (self.hoverState == 'in') self.show()
0099       }, self.options.delay.show)
0100     }
0101 
0102   , leave: function (e) {
0103       var self = $(e.currentTarget)[this.type](this._options).data(this.type)
0104 
0105       if (this.timeout) clearTimeout(this.timeout)
0106       if (!self.options.delay || !self.options.delay.hide) return self.hide()
0107 
0108       self.hoverState = 'out'
0109       this.timeout = setTimeout(function() {
0110         if (self.hoverState == 'out') self.hide()
0111       }, self.options.delay.hide)
0112     }
0113 
0114   , show: function () {
0115       var $tip
0116         , pos
0117         , actualWidth
0118         , actualHeight
0119         , placement
0120         , tp
0121         , e = $.Event('show')
0122 
0123       if (this.hasContent() && this.enabled) {
0124         this.$element.trigger(e)
0125         if (e.isDefaultPrevented()) return
0126         $tip = this.tip()
0127         this.setContent()
0128 
0129         if (this.options.animation) {
0130           $tip.addClass('fade')
0131         }
0132 
0133         placement = typeof this.options.placement == 'function' ?
0134           this.options.placement.call(this, $tip[0], this.$element[0]) :
0135           this.options.placement
0136 
0137         $tip
0138           .detach()
0139           .css({ top: 0, left: 0, display: 'block' })
0140 
0141         this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
0142 
0143         pos = this.getPosition()
0144 
0145         actualWidth = $tip[0].offsetWidth
0146         actualHeight = $tip[0].offsetHeight
0147 
0148         switch (placement) {
0149           case 'bottom':
0150             tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2}
0151             break
0152           case 'top':
0153             tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2}
0154             break
0155           case 'left':
0156             tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth}
0157             break
0158           case 'right':
0159             tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}
0160             break
0161         }
0162 
0163         this.applyPlacement(tp, placement)
0164         this.$element.trigger('shown')
0165       }
0166     }
0167 
0168   , applyPlacement: function(offset, placement){
0169       var $tip = this.tip()
0170         , width = $tip[0].offsetWidth
0171         , height = $tip[0].offsetHeight
0172         , actualWidth
0173         , actualHeight
0174         , delta
0175         , replace
0176 
0177       $tip
0178         .offset(offset)
0179         .addClass(placement)
0180         .addClass('in')
0181 
0182       actualWidth = $tip[0].offsetWidth
0183       actualHeight = $tip[0].offsetHeight
0184 
0185       if (placement == 'top' && actualHeight != height) {
0186         offset.top = offset.top + height - actualHeight
0187         replace = true
0188       }
0189 
0190       if (placement == 'bottom' || placement == 'top') {
0191         delta = 0
0192 
0193         if (offset.left < 0){
0194           delta = offset.left * -2
0195           offset.left = 0
0196           $tip.offset(offset)
0197           actualWidth = $tip[0].offsetWidth
0198           actualHeight = $tip[0].offsetHeight
0199         }
0200 
0201         this.replaceArrow(delta - width + actualWidth, actualWidth, 'left')
0202       } else {
0203         this.replaceArrow(actualHeight - height, actualHeight, 'top')
0204       }
0205 
0206       if (replace) $tip.offset(offset)
0207     }
0208 
0209   , replaceArrow: function(delta, dimension, position){
0210       this
0211         .arrow()
0212         .css(position, delta ? (50 * (1 - delta / dimension) + "%") : '')
0213     }
0214 
0215   , setContent: function () {
0216       var $tip = this.tip()
0217         , title = this.getTitle()
0218 
0219       $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
0220       $tip.removeClass('fade in top bottom left right')
0221     }
0222 
0223   , hide: function () {
0224       var that = this
0225         , $tip = this.tip()
0226         , e = $.Event('hide')
0227 
0228       this.$element.trigger(e)
0229       if (e.isDefaultPrevented()) return
0230 
0231       $tip.removeClass('in')
0232 
0233       function removeWithAnimation() {
0234         var timeout = setTimeout(function () {
0235           $tip.off($.support.transition.end).detach()
0236         }, 500)
0237 
0238         $tip.one($.support.transition.end, function () {
0239           clearTimeout(timeout)
0240           $tip.detach()
0241         })
0242       }
0243 
0244       $.support.transition && this.$tip.hasClass('fade') ?
0245         removeWithAnimation() :
0246         $tip.detach()
0247 
0248       this.$element.trigger('hidden')
0249 
0250       return this
0251     }
0252 
0253   , fixTitle: function () {
0254       var $e = this.$element
0255       if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
0256         $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
0257       }
0258     }
0259 
0260   , hasContent: function () {
0261       return this.getTitle()
0262     }
0263 
0264   , getPosition: function () {
0265       var el = this.$element[0]
0266       return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : {
0267         width: el.offsetWidth
0268       , height: el.offsetHeight
0269       }, this.$element.offset())
0270     }
0271 
0272   , getTitle: function () {
0273       var title
0274         , $e = this.$element
0275         , o = this.options
0276 
0277       title = $e.attr('data-original-title')
0278         || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)
0279 
0280       return title
0281     }
0282 
0283   , tip: function () {
0284       return this.$tip = this.$tip || $(this.options.template)
0285     }
0286 
0287   , arrow: function(){
0288       return this.$arrow = this.$arrow || this.tip().find(".tooltip-arrow")
0289     }
0290 
0291   , validate: function () {
0292       if (!this.$element[0].parentNode) {
0293         this.hide()
0294         this.$element = null
0295         this.options = null
0296       }
0297     }
0298 
0299   , enable: function () {
0300       this.enabled = true
0301     }
0302 
0303   , disable: function () {
0304       this.enabled = false
0305     }
0306 
0307   , toggleEnabled: function () {
0308       this.enabled = !this.enabled
0309     }
0310 
0311   , toggle: function (e) {
0312       var self = e ? $(e.currentTarget)[this.type](this._options).data(this.type) : this
0313       self.tip().hasClass('in') ? self.hide() : self.show()
0314     }
0315 
0316   , destroy: function () {
0317       this.hide().$element.off('.' + this.type).removeData(this.type)
0318     }
0319 
0320   }
0321 
0322 
0323  /* TOOLTIP PLUGIN DEFINITION
0324   * ========================= */
0325 
0326   var old = $.fn.tooltip
0327 
0328   $.fn.tooltip = function ( option ) {
0329     return this.each(function () {
0330       var $this = $(this)
0331         , data = $this.data('tooltip')
0332         , options = typeof option == 'object' && option
0333       if (!data) $this.data('tooltip', (data = new Tooltip(this, options)))
0334       if (typeof option == 'string') data[option]()
0335     })
0336   }
0337 
0338   $.fn.tooltip.Constructor = Tooltip
0339 
0340   $.fn.tooltip.defaults = {
0341     animation: true
0342   , placement: 'top'
0343   , selector: false
0344   , template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
0345   , trigger: 'hover focus'
0346   , title: ''
0347   , delay: 0
0348   , html: false
0349   , container: false
0350   }
0351 
0352 
0353  /* TOOLTIP NO CONFLICT
0354   * =================== */
0355 
0356   $.fn.tooltip.noConflict = function () {
0357     $.fn.tooltip = old
0358     return this
0359   }
0360 
0361 }(window.jQuery);