| /* ========================================================== |
| * 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() { |
| 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 (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.rejectAttrOptions = [ 'title' ] |
| |
| $.fn.twipsy.elementOptions = function(ele, options) { |
| var data = $(ele).data() |
| , rejects = $.fn.twipsy.rejectAttrOptions |
| , i = rejects.length |
| |
| while (i--) { |
| delete data[rejects[i]] |
| } |
| |
| return $.extend({}, options, data) |
| } |
| |
| }( window.jQuery || window.ender ); |