bootstrap-twipsy.js 6.90 KiB
/* Adapted from the original jQuery.tipsy by Jason Frame */
(function( $ ) {
 /* CSS TRANSITION SUPPORT (https://gist.github.com/373874)
  * ======================================================= */
  var transitionEnd
  $(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.getTitle() && 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
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
actualWidth = $tip[0].offsetWidth actualHeight = $tip[0].offsetHeight placement = _.maybeCall(this.options.placement, 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') } } , 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*$)/, "")
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
return title || o.fallback } , tip: function() { if (!this.$tip) { this.$tip = $('<div class="twipsy" />').html('<div class="twipsy-arrow"></div><div class="twipsy-inner"></div>') } 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 * ====================== */ var _ = { maybeCall: function ( thing, ctx ) { return (typeof thing == 'function') ? (thing.call(ctx)) : 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)
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
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) } this.bind(name + ':show', enter) this.bind(name + ':hide', leave) return this } $.fn.twipsy.Twipsy = Twipsy $.fn.twipsy.defaults = { animate: true , delayIn: 0 , delayOut: 0 , fallback: '' , placement: 'above' , html: false
281282283284285286287288289290291
, live: false , offset: 0 , title: 'title' , trigger: 'hover' } $.fn.twipsy.elementOptions = function(ele, options) { return $.metadata ? $.extend({}, options, $(ele).metadata()) : options } })( jQuery || ender )