1/* =========================================================== 2 * bootstrap-tooltip.js v2.2.2 3 * http://twitter.github.com/bootstrap/javascript.html#tooltips 4 * Inspired by the original jQuery.tipsy by Jason Frame 5 * =========================================================== 6 * Copyright 2012 Twitter, Inc. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 * ========================================================== */ 20!function ($) { 21 22 "use strict"; // jshint ;_; 23 24 25 /* TOOLTIP PUBLIC CLASS DEFINITION 26 * =============================== */ 27 28 var Tooltip = function (element, options) { 29 this.init('tooltip_tip', element, options) 30 } 31 32 Tooltip.prototype = { 33 34 constructor: Tooltip 35 36 , init: function (type, element, options) { 37 var eventIn 38 , eventOut 39 40 this.type = type 41 this.$element = $(element) 42 this.options = this.getOptions(options) 43 this.enabled = true 44 45 if (this.options.trigger == 'click') { 46 this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) 47 } else if (this.options.trigger != 'manual') { 48 eventIn = this.options.trigger == 'hover' ? 'mouseenter' : 'focus' 49 eventOut = this.options.trigger == 'hover' ? 'mouseleave' : 'blur' 50 this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) 51 this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) 52 } 53 54 this.options.selector ? 55 (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : 56 this.fixTitle() 57 } 58 59 , getOptions: function (options) { 60 options = $.extend({}, $.fn[this.type].defaults, options, this.$element.data()) 61 62 if (options.delay && typeof options.delay == 'number') { 63 options.delay = { 64 show: options.delay 65 , hide: options.delay 66 } 67 } 68 69 return options 70 } 71 72 , enter: function (e) { 73 var self = $(e.currentTarget)[this.type](this._options).data(this.type) 74 75 if (!self.options.delay || !self.options.delay.show) return self.show() 76 77 clearTimeout(this.timeout) 78 self.hoverState = 'in' 79 this.timeout = setTimeout(function() { 80 if (self.hoverState == 'in') self.show() 81 }, self.options.delay.show) 82 } 83 84 , leave: function (e) { 85 var self = $(e.currentTarget)[this.type](this._options).data(this.type) 86 87 if (this.timeout) clearTimeout(this.timeout) 88 if (!self.options.delay || !self.options.delay.hide) return self.hide() 89 90 self.hoverState = 'out' 91 this.timeout = setTimeout(function() { 92 if (self.hoverState == 'out') self.hide() 93 }, self.options.delay.hide) 94 } 95 96 , show: function () { 97 var $tip 98 , inside 99 , pos 100 , actualWidth 101 , actualHeight 102 , placement 103 , tp 104 105 if (this.hasContent() && this.enabled) { 106 $tip = this.tip() 107 this.setContent() 108 109 if (this.options.animation) { 110 $tip.addClass('fade') 111 } 112 113 placement = typeof this.options.placement == 'function' ? 114 this.options.placement.call(this, $tip[0], this.$element[0]) : 115 this.options.placement 116 117 inside = /in/.test(placement) 118 119 $tip 120 .detach() 121 .css({ top: 0, left: 0, display: 'block' }) 122 .insertAfter(this.$element) 123 124 pos = this.getPosition(inside) 125 126 actualWidth = $tip[0].offsetWidth 127 actualHeight = $tip[0].offsetHeight 128 129 switch (inside ? placement.split(' ')[1] : placement) { 130 case 'bottom': 131 tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2} 132 break 133 case 'top': 134 tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2} 135 break 136 case 'left': 137 tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth} 138 break 139 case 'right': 140 tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width} 141 break 142 } 143 144 $tip 145 .offset(tp) 146 .addClass(placement) 147 .addClass('in') 148 } 149 } 150 151 , setContent: function () { 152 var $tip = this.tip() 153 , title = this.getTitle() 154 155 $tip.find('.tooltip_tip-inner')[this.options.html ? 'html' : 'text'](title) 156 $tip.removeClass('fade in top bottom left right') 157 } 158 159 , hide: function () { 160 var that = this 161 , $tip = this.tip() 162 163 $tip.removeClass('in') 164 165 function removeWithAnimation() { 166 var timeout = setTimeout(function () {
167 $tip.off($.support.transition.end).detach() 168 }, 500) 169 170 $tip.one($.support.transition.end, function () { 171 clearTimeout(timeout) 172 $tip.detach() 173 }) 174 } 175 176 $.support.transition && this.$tip.hasClass('fade') ? 177 removeWithAnimation() : 178 $tip.detach() 179 180 return this 181 } 182 183 , fixTitle: function () { 184 var $e = this.$element 185 if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') { 186 $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') 187 } 188 } 189 190 , hasContent: function () { 191 return this.getTitle() 192 } 193 194 , getPosition: function (inside) { 195 return $.extend({}, (inside ? {top: 0, left: 0} : this.$element.offset()), { 196 width: this.$element[0].offsetWidth 197 , height: this.$element[0].offsetHeight 198 }) 199 } 200 201 , getTitle: function () { 202 var title 203 , $e = this.$element 204 , o = this.options 205 206 title = $e.attr('data-original-title') 207 || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) 208 209 return title 210 } 211 212 , tip: function () { 213 return this.$tip = this.$tip || $(this.options.template) 214 } 215 216 , validate: function () { 217 if (!this.$element[0].parentNode) { 218 this.hide() 219 this.$element = null 220 this.options = null 221 } 222 } 223 224 , enable: function () { 225 this.enabled = true 226 } 227 228 , disable: function () { 229 this.enabled = false 230 } 231 232 , toggleEnabled: function () { 233 this.enabled = !this.enabled 234 } 235 236 , toggle: function (e) { 237 var self = $(e.currentTarget)[this.type](this._options).data(this.type) 238 self[self.tip().hasClass('in') ? 'hide' : 'show']() 239 } 240 241 , destroy: function () { 242 this.hide().$element.off('.' + this.type).removeData(this.type) 243 } 244 245 } 246 247 248 /* TOOLTIP PLUGIN DEFINITION 249 * ========================= */ 250 251 var old = $.fn.tooltip_tip 252 253 $.fn.tooltip_tip = function ( option ) { 254 return this.each(function () { 255 var $this = $(this) 256 , data = $this.data('tooltip_tip') 257 , options = typeof option == 'object' && option 258 if (!data) $this.data('tooltip_tip', (data = new Tooltip(this, options))) 259 if (typeof option == 'string') data[option]() 260 }) 261 } 262 263 $.fn.tooltip_tip.Constructor = Tooltip 264 265 $.fn.tooltip_tip.defaults = { 266 animation: true 267 , placement: 'top' 268 , selector: false 269 , template: '<div class="tooltip_tip"><div class="tooltip_tip-arrow"></div><div class="tooltip_tip-inner"></div></div>' 270 , trigger: 'hover' 271 , title: '' 272 , delay: 0 273 , html: false 274 } 275 276 277 /* TOOLTIP NO CONFLICT 278 * =================== */ 279 280 $.fn.tooltip_tip.noConflict = function () { 281 $.fn.tooltip_tip = old 282 return this 283 } 284 285}(window.jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.