310 行
		
	
	
	
		
			7.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			310 行
		
	
	
	
		
			7.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|  | /* ========================================================== | ||
|  |  * bootstrap-twipsy.js v1.4.0 | ||
|  |  * http://twitter.github.com/bootstrap/javascript.html#twipsy
 | ||
|  |  * Adapted from the original jQuery.tipsy by Jason Frame | ||
|  |  * ========================================================== | ||
|  |  * Copyright 2011 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. | ||
|  |  * ========================================================== */ | ||
|  | 
 | ||
|  | 
 | ||
|  | !function( $ ) { | ||
|  | 
 | ||
|  |   "use strict" | ||
|  | 
 | ||
|  |  /* CSS TRANSITION SUPPORT (https://gist.github.com/373874) | ||
|  |   * ======================================================= */ | ||
|  | 
 | ||
|  |   var transitionEnd | ||
|  | 
 | ||
|  |   $(document).ready(function () { | ||
|  | 
 | ||
|  |     $.support.transition = (function () { | ||
|  |       var thisBody = document.body || document.documentElement | ||
|  |         , thisStyle = thisBody.style | ||
|  |         , support = thisStyle.transition !== undefined || thisStyle.WebkitTransition !== undefined || thisStyle.MozTransition !== undefined || thisStyle.MsTransition !== undefined || thisStyle.OTransition !== undefined | ||
|  |       return support | ||
|  |     })() | ||
|  | 
 | ||
|  |     // set CSS transition event type
 | ||
|  |     if ( $.support.transition ) { | ||
|  |       transitionEnd = "TransitionEnd" | ||
|  |       if ( $.browser.webkit ) { | ||
|  |       	transitionEnd = "webkitTransitionEnd" | ||
|  |       } else if ( $.browser.mozilla ) { | ||
|  |       	transitionEnd = "transitionend" | ||
|  |       } else if ( $.browser.opera ) { | ||
|  |       	transitionEnd = "oTransitionEnd" | ||
|  |       } | ||
|  |     } | ||
|  | 
 | ||
|  |   }) | ||
|  | 
 | ||
|  | 
 | ||
|  |  /* TWIPSY PUBLIC CLASS DEFINITION | ||
|  |   * ============================== */ | ||
|  | 
 | ||
|  |   var Twipsy = function ( element, options ) { | ||
|  |     this.$element = $(element) | ||
|  |     this.options = options | ||
|  |     this.enabled = true | ||
|  |     this.fixTitle() | ||
|  |   } | ||
|  | 
 | ||
|  |   Twipsy.prototype = { | ||
|  | 
 | ||
|  |     show: function() { | ||
|  |       var pos | ||
|  |         , actualWidth | ||
|  |         , actualHeight | ||
|  |         , placement | ||
|  |         , $tip | ||
|  |         , tp | ||
|  | 
 | ||
|  |       if (this.hasContent() && this.enabled) { | ||
|  |         $tip = this.tip() | ||
|  |         this.setContent() | ||
|  | 
 | ||
|  |         if (this.options.animate) { | ||
|  |           $tip.addClass('fade') | ||
|  |         } | ||
|  | 
 | ||
|  |         $tip | ||
|  |           .remove() | ||
|  |           .css({ top: 0, left: 0, display: 'block' }) | ||
|  |           .prependTo(document.body) | ||
|  | 
 | ||
|  |         pos = $.extend({}, this.$element.offset(), { | ||
|  |           width: this.$element[0].offsetWidth | ||
|  |         , height: this.$element[0].offsetHeight | ||
|  |         }) | ||
|  | 
 | ||
|  |         actualWidth = $tip[0].offsetWidth | ||
|  |         actualHeight = $tip[0].offsetHeight | ||
|  | 
 | ||
|  |         placement = maybeCall(this.options.placement, this, [ $tip[0], this.$element[0] ]) | ||
|  | 
 | ||
|  |         switch (placement) { | ||
|  |           case 'below': | ||
|  |             tp = {top: pos.top + pos.height + this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2} | ||
|  |             break | ||
|  |           case 'above': | ||
|  |             tp = {top: pos.top - actualHeight - this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2} | ||
|  |             break | ||
|  |           case 'left': | ||
|  |             tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth - this.options.offset} | ||
|  |             break | ||
|  |           case 'right': | ||
|  |             tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width + this.options.offset} | ||
|  |             break | ||
|  |         } | ||
|  | 
 | ||
|  |         $tip | ||
|  |           .css(tp) | ||
|  |           .addClass(placement) | ||
|  |           .addClass('in') | ||
|  |       } | ||
|  |     } | ||
|  | 
 | ||
|  |   , setContent: function () { | ||
|  |       var $tip = this.tip() | ||
|  |       $tip.find('.twipsy-inner')[this.options.html ? 'html' : 'text'](this.getTitle()) | ||
|  |       $tip[0].className = 'twipsy' | ||
|  |     } | ||
|  | 
 | ||
|  |   , hide: function() { | ||
|  |       var that = this | ||
|  |         , $tip = this.tip() | ||
|  | 
 | ||
|  |       $tip.removeClass('in') | ||
|  | 
 | ||
|  |       function removeElement () { | ||
|  |         $tip.remove() | ||
|  |       } | ||
|  | 
 | ||
|  |       $.support.transition && this.$tip.hasClass('fade') ? | ||
|  |         $tip.bind(transitionEnd, removeElement) : | ||
|  |         removeElement() | ||
|  |     } | ||
|  | 
 | ||
|  |   , 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() | ||
|  |     } | ||
|  | 
 | ||
|  |   , getTitle: function() { | ||
|  |       var title | ||
|  |         , $e = this.$element | ||
|  |         , o = this.options | ||
|  | 
 | ||
|  |         this.fixTitle() | ||
|  | 
 | ||
|  |         if (typeof o.title == 'string') { | ||
|  |           title = $e.attr(o.title == 'title' ? 'data-original-title' : o.title) | ||
|  |         } else if (typeof o.title == 'function') { | ||
|  |           title = o.title.call($e[0]) | ||
|  |         } | ||
|  | 
 | ||
|  |         title = ('' + title).replace(/(^\s*|\s*$)/, "") | ||
|  | 
 | ||
|  |         return title || o.fallback | ||
|  |     } | ||
|  | 
 | ||
|  |   , tip: function() { | ||
|  |       if (!this.$tip) { | ||
|  |         this.$tip = $('<div class="twipsy" />').html(this.options.template) | ||
|  |       } | ||
|  |       return this.$tip | ||
|  |     } | ||
|  | 
 | ||
|  |   , 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 | ||
|  |     } | ||
|  | 
 | ||
|  |   } | ||
|  | 
 | ||
|  | 
 | ||
|  |  /* TWIPSY PRIVATE METHODS | ||
|  |   * ====================== */ | ||
|  | 
 | ||
|  |    function maybeCall ( thing, ctx, args ) { | ||
|  |      return typeof thing == 'function' ? thing.apply(ctx, args) : thing | ||
|  |    } | ||
|  | 
 | ||
|  |  /* TWIPSY PLUGIN DEFINITION | ||
|  |   * ======================== */ | ||
|  | 
 | ||
|  |   $.fn.twipsy = function (options) { | ||
|  |     $.fn.twipsy.initWith.call(this, options, Twipsy, 'twipsy') | ||
|  |     return this | ||
|  |   } | ||
|  | 
 | ||
|  |   $.fn.twipsy.initWith = function (options, Constructor, name) { | ||
|  |     var twipsy | ||
|  |       , binder | ||
|  |       , eventIn | ||
|  |       , eventOut | ||
|  | 
 | ||
|  |     if (options === true) { | ||
|  |       return this.data(name) | ||
|  |     } else if (typeof options == 'string') { | ||
|  |       twipsy = this.data(name) | ||
|  |       if (twipsy) { | ||
|  |         twipsy[options]() | ||
|  |       } | ||
|  |       return this | ||
|  |     } | ||
|  | 
 | ||
|  |     options = $.extend({}, $.fn[name].defaults, options) | ||
|  | 
 | ||
|  |     function get(ele) { | ||
|  |       var twipsy = $.data(ele, name) | ||
|  | 
 | ||
|  |       if (!twipsy) { | ||
|  |         twipsy = new Constructor(ele, $.fn.twipsy.elementOptions(ele, options)) | ||
|  |         $.data(ele, name, twipsy) | ||
|  |       } | ||
|  | 
 | ||
|  |       return twipsy | ||
|  |     } | ||
|  | 
 | ||
|  |     function enter() { | ||
|  |       var twipsy = get(this) | ||
|  |       twipsy.hoverState = 'in' | ||
|  | 
 | ||
|  |       if (options.delayIn == 0) { | ||
|  |         twipsy.show() | ||
|  |       } else { | ||
|  |         twipsy.fixTitle() | ||
|  |         setTimeout(function() { | ||
|  |           if (twipsy.hoverState == 'in') { | ||
|  |             twipsy.show() | ||
|  |           } | ||
|  |         }, options.delayIn) | ||
|  |       } | ||
|  |     } | ||
|  | 
 | ||
|  |     function leave() { | ||
|  |       var twipsy = get(this) | ||
|  |       twipsy.hoverState = 'out' | ||
|  |       if (options.delayOut == 0) { | ||
|  |         twipsy.hide() | ||
|  |       } else { | ||
|  |         setTimeout(function() { | ||
|  |           if (twipsy.hoverState == 'out') { | ||
|  |             twipsy.hide() | ||
|  |           } | ||
|  |         }, options.delayOut) | ||
|  |       } | ||
|  |     } | ||
|  | 
 | ||
|  |     if (!options.live) { | ||
|  |       this.each(function() { | ||
|  |         get(this) | ||
|  |       }) | ||
|  |     } | ||
|  | 
 | ||
|  |     if (options.trigger != 'manual') { | ||
|  |       binder   = options.live ? 'live' : 'bind' | ||
|  |       eventIn  = options.trigger == 'hover' ? 'mouseenter' : 'focus' | ||
|  |       eventOut = options.trigger == 'hover' ? 'mouseleave' : 'blur' | ||
|  |       this[binder](eventIn, enter)[binder](eventOut, leave) | ||
|  |     } | ||
|  | 
 | ||
|  |     return this | ||
|  |   } | ||
|  | 
 | ||
|  |   $.fn.twipsy.Twipsy = Twipsy | ||
|  | 
 | ||
|  |   $.fn.twipsy.defaults = { | ||
|  |     animate: true | ||
|  |   , delayIn: 0 | ||
|  |   , delayOut: 0 | ||
|  |   , fallback: '' | ||
|  |   , placement: 'above' | ||
|  |   , html: false | ||
|  |   , live: false | ||
|  |   , offset: 0 | ||
|  |   , title: 'title' | ||
|  |   , trigger: 'hover' | ||
|  |   , template: '<div class="twipsy-arrow"></div><div class="twipsy-inner"></div>' | ||
|  |   } | ||
|  | 
 | ||
|  |   $.fn.twipsy.elementOptions = function(ele, options) { | ||
|  |     return $.extend({}, options, $(ele).data()) | ||
|  |   } | ||
|  | 
 | ||
|  | }( window.jQuery || window.ender ); |