bootstrap-twipsy.js 7.15 KiB
/* ==========================================================
 * bootstrap-twipsy.js v2.0.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"
 /* 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}
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
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').html(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( $.support.transition.end, 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 } , tip: function() {
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
return this.$tip = this.$tip || $('<div class="twipsy" />').html(this.options.template) } , 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 } , toggle: function () { this[this.tip().hasClass('in') ? 'hide' : 'show']() } } /* 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 (typeof options == 'string') { twipsy = this.data(name) if (twipsy) twipsy[options]() return this } options = $.extend({}, $.fn[name].defaults, options) if (options.delay && typeof options.delay == 'number') { options.delay = { show: options.delay , hide: options.delay } } function get(ele) { var twipsy = $.data(ele, name) if (!twipsy) {
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
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.delay || !options.delay.show) { twipsy.show() } else { twipsy.fixTitle() setTimeout(function() { if (twipsy.hoverState == 'in') { twipsy.show() } }, options.delay.show) } } function leave() { var twipsy = get(this) twipsy.hoverState = 'out' if (!options.delay || !options.delay.hide) { twipsy.hide() } else { setTimeout(function() { if (twipsy.hoverState == 'out') { twipsy.hide() } }, options.delay.hide) } } 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 , delay: 0 , placement: 'above' , live: false , offset: 0 , trigger: 'hover' , title: 'title' , template: '<div class="twipsy-arrow"></div><div class="twipsy-inner"></div>' } $.fn.twipsy.rejectAttrOptions = [ 'title' ] $.fn.twipsy.elementOptions = function(ele, options) { var data = $(ele).data()
281282283284285286287288289290291
, rejects = $.fn.twipsy.rejectAttrOptions , i = rejects.length while (i--) { delete data[rejects[i]] } return $.extend({}, options, data) } }( window.jQuery || window.ender );