1/* =========================================================== 2 * bootstrap-tooltip.js v2.0.4 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 21 22!function ($) { 23 24 "use strict"; // jshint ;_; 25 26 27 /* TOOLTIP PUBLIC CLASS DEFINITION 28 * =============================== */ 29 30 var Tooltip = function (element, options) { 31 this.init('tooltip', element, options) 32 } 33 34 Tooltip.prototype = { 35 36 constructor: Tooltip 37 38 , init: function (type, element, options) { 39 var eventIn 40 , eventOut 41 42 this.type = type 43 this.$element = $(element) 44 this.options = this.getOptions(options) 45 this.enabled = true 46 47 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.options.selector, $.proxy(this.enter, this)) 51 this.$element.on(eventOut, 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 .remove() 121 .css({ top: 0, left: 0, display: 'block' }) 122 .appendTo(inside ? this.$element : document.body) 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 .css(tp) 146 .addClass(placement) 147 .addClass('in') 148 } 149 } 150 151 , isHTML: function(text) { 152 // html string detection logic adapted from jQuery 153 return typeof text != 'string' 154 || ( text.charAt(0) === "<" 155 && text.charAt( text.length - 1 ) === ">" 156 && text.length >= 3 157 ) || /^(?:[^<]*<[\w\W]+>[^>]*$)/.exec(text) 158 } 159 160 , setContent: function () { 161 var $tip = this.tip() 162 , title = this.getTitle() 163 164 $tip.find('.tooltip-inner')[this.isHTML(title) ? 'html' : 'text'](title) 165 $tip.removeClass('fade in top bottom left right') 166 } 167 168 , hide: function () { 169 var that = this 170 , $tip = this.tip() 171 172 $tip.removeClass('in') 173 174 function removeWithAnimation() { 175 var timeout = setTimeout(function () {
176 $tip.off($.support.transition.end).remove() 177 }, 500) 178 179 $tip.one($.support.transition.end, function () { 180 clearTimeout(timeout) 181 $tip.remove() 182 }) 183 } 184 185 $.support.transition && this.$tip.hasClass('fade') ? 186 removeWithAnimation() : 187 $tip.remove() 188 } 189 190 , fixTitle: function () { 191 var $e = this.$element 192 if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') { 193 $e.attr('data-original-title', $e.attr('title') || '').removeAttr('title') 194 } 195 } 196 197 , hasContent: function () { 198 return this.getTitle() 199 } 200 201 , getPosition: function (inside) { 202 return $.extend({}, (inside ? {top: 0, left: 0} : this.$element.offset()), { 203 width: this.$element[0].offsetWidth 204 , height: this.$element[0].offsetHeight 205 }) 206 } 207 208 , getTitle: function () { 209 var title 210 , $e = this.$element 211 , o = this.options 212 213 title = $e.attr('data-original-title') 214 || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) 215 216 return title 217 } 218 219 , tip: function () { 220 return this.$tip = this.$tip || $(this.options.template) 221 } 222 223 , validate: function () { 224 if (!this.$element[0].parentNode) { 225 this.hide() 226 this.$element = null 227 this.options = null 228 } 229 } 230 231 , enable: function () { 232 this.enabled = true 233 } 234 235 , disable: function () { 236 this.enabled = false 237 } 238 239 , toggleEnabled: function () { 240 this.enabled = !this.enabled 241 } 242 243 , toggle: function () { 244 this[this.tip().hasClass('in') ? 'hide' : 'show']() 245 } 246 247 } 248 249 250 /* TOOLTIP PLUGIN DEFINITION 251 * ========================= */ 252 253 $.fn.tooltip = function ( option ) { 254 return this.each(function () { 255 var $this = $(this) 256 , data = $this.data('tooltip') 257 , options = typeof option == 'object' && option 258 if (!data) $this.data('tooltip', (data = new Tooltip(this, options))) 259 if (typeof option == 'string') data[option]() 260 }) 261 } 262 263 $.fn.tooltip.Constructor = Tooltip 264 265 $.fn.tooltip.defaults = { 266 animation: true 267 , placement: 'top' 268 , selector: false 269 , template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>' 270 , trigger: 'hover' 271 , title: '' 272 , delay: 0 273 } 274 275}(window.jQuery); 276 277 278 279jQuery(document).ready(function() { 280// tooltip demo 281 $('.tooltips').tooltip({ 282 selector: "a[rel=tooltip]" 283 }) 284 285 $('.tooltip-test').tooltip() 286 $('.popover-test').popover() 287 288 // popover demo 289 $("a[rel=popover]") 290 .popover() 291 .click(function(e) { 292 e.preventDefault() 293 }) 294});
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.