[ Index ]

PHP Cross Reference of MediaWiki-1.24.0

title

Body

[close]

/resources/src/jquery.tipsy/ -> jquery.tipsy.js (source)

   1  // tipsy, facebook style tooltips for jquery
   2  // version 1.0.0a*
   3  // (c) 2008-2010 jason frame [[email protected]]
   4  // released under the MIT license
   5  
   6  // * This installation of tipsy includes several local modifications to both Javascript and CSS.
   7  //   Please be careful when upgrading.
   8  
   9  (function($) {
  10  
  11      function maybeCall(thing, ctx) {
  12          return (typeof thing == 'function') ? (thing.call(ctx)) : thing;
  13      }
  14  
  15      function Tipsy(element, options) {
  16          this.$element = $(element);
  17          this.options = options;
  18          this.enabled = true;
  19          this.fixTitle();
  20      }
  21  
  22      Tipsy.prototype = {
  23          show: function() {
  24              var title = this.getTitle();
  25              if (title && this.enabled) {
  26                  var $tip = this.tip();
  27  
  28                  $tip.find('.tipsy-inner')[this.options.html ? 'html' : 'text'](title);
  29                  $tip[0].className = 'tipsy'; // reset classname in case of dynamic gravity
  30                  if (this.options.className) {
  31                      $tip.addClass(maybeCall(this.options.className, this.$element[0]));
  32                  }
  33                  $tip.remove().css({top: 0, left: 0, visibility: 'hidden', display: 'block'}).appendTo(document.body);
  34  
  35                  var pos = $.extend({}, this.$element.offset(), {
  36                      width: this.$element[0].offsetWidth,
  37                      height: this.$element[0].offsetHeight
  38                  });
  39  
  40                  var gravity = (typeof this.options.gravity == 'function')
  41                                  ? this.options.gravity.call(this.$element[0])
  42                                  : this.options.gravity;
  43  
  44                  // Attach css classes before checking height/width so they
  45                  // can be applied.
  46                  $tip.addClass('tipsy-' + gravity);
  47                  if (this.options.className) {
  48                      $tip.addClass(maybeCall(this.options.className, this.$element[0]));
  49                  }
  50  
  51                  var actualWidth = $tip[0].offsetWidth, actualHeight = $tip[0].offsetHeight;
  52                  var tp;
  53                  switch (gravity.charAt(0)) {
  54                      case 'n':
  55                          tp = {top: pos.top + pos.height + this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
  56                          break;
  57                      case 's':
  58                          tp = {top: pos.top - actualHeight - this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
  59                          break;
  60                      case 'e':
  61                          tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth - this.options.offset};
  62                          break;
  63                      case 'w':
  64                          tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width + this.options.offset};
  65                          break;
  66                  }
  67  
  68                  if (gravity.length == 2) {
  69                      if (gravity.charAt(1) == 'w') {
  70                          if (this.options.center) {
  71                              tp.left = pos.left + pos.width / 2 - 15;
  72                          } else {
  73                              tp.left = pos.left;
  74                          }
  75                      } else {
  76                          if (this.options.center) {
  77                              tp.left = pos.left + pos.width / 2 - actualWidth + 15;
  78                          } else {
  79                              tp.left = pos.left + pos.width;
  80                          }
  81                      }
  82                  }
  83                  $tip.css(tp);
  84  
  85                  if (this.options.fade) {
  86                      $tip.stop().css({opacity: 0, display: 'block', visibility: 'visible'}).animate({opacity: this.options.opacity}, 100);
  87                  } else {
  88                      $tip.css({visibility: 'visible', opacity: this.options.opacity});
  89                  }
  90              }
  91          },
  92  
  93          hide: function() {
  94              if (this.options.fade) {
  95                  this.tip().stop().fadeOut(100, function() { $(this).remove(); });
  96              } else {
  97                  this.tip().remove();
  98              }
  99          },
 100  
 101  
 102          fixTitle: function() {
 103              var $e = this.$element;
 104              if ($e.attr('title') || typeof($e.attr('original-title')) != 'string') {
 105                  $e.attr('original-title', $e.attr('title') || '').removeAttr('title');
 106              }
 107          },
 108  
 109          getTitle: function() {
 110              var title, $e = this.$element, o = this.options;
 111              this.fixTitle();
 112              if (typeof o.title == 'string') {
 113                  title = $e.attr(o.title == 'title' ? 'original-title' : o.title);
 114              } else if (typeof o.title == 'function') {
 115                  title = o.title.call($e[0]);
 116              }
 117              title = ('' + title).replace(/(^\s*|\s*$)/, "");
 118              return title || o.fallback;
 119          },
 120  
 121          tip: function() {
 122              if (!this.$tip) {
 123                  this.$tip = $('<div class="tipsy"></div>').html('<div class="tipsy-arrow"></div><div class="tipsy-inner"></div>');
 124              }
 125              return this.$tip;
 126          },
 127  
 128          validate: function() {
 129              if (!this.$element[0].parentNode) {
 130                  this.hide();
 131                  this.$element = null;
 132                  this.options = null;
 133              }
 134          },
 135  
 136          enable: function() { this.enabled = true; },
 137          disable: function() { this.enabled = false; },
 138          toggleEnabled: function() { this.enabled = !this.enabled; }
 139      };
 140  
 141      $.fn.tipsy = function(options) {
 142  
 143          if (options === true) {
 144              return this.data('tipsy');
 145          } else if (typeof options == 'string') {
 146              var tipsy = this.data('tipsy');
 147              if (tipsy) tipsy[options]();
 148              return this;
 149          }
 150  
 151          options = $.extend({}, $.fn.tipsy.defaults, options);
 152  
 153          function get(ele) {
 154              var tipsy = $.data(ele, 'tipsy');
 155              if (!tipsy) {
 156                  tipsy = new Tipsy(ele, $.fn.tipsy.elementOptions(ele, options));
 157                  $.data(ele, 'tipsy', tipsy);
 158              }
 159              return tipsy;
 160          }
 161  
 162          function enter() {
 163              var tipsy = get(this);
 164              tipsy.hoverState = 'in';
 165              if (options.delayIn == 0) {
 166                  tipsy.show();
 167              } else {
 168                  tipsy.fixTitle();
 169                  setTimeout(function() { if (tipsy.hoverState == 'in') tipsy.show(); }, options.delayIn);
 170              }
 171          };
 172  
 173          function leave() {
 174              var tipsy = get(this);
 175              tipsy.hoverState = 'out';
 176              if (options.delayOut == 0) {
 177                  tipsy.hide();
 178              } else {
 179                  setTimeout(function() { if (tipsy.hoverState == 'out') tipsy.hide(); }, options.delayOut);
 180              }
 181          };
 182  
 183          if (!options.live) this.each(function() { get(this); });
 184  
 185          if (options.trigger != 'manual') {
 186              var binder   = options.live ? 'live' : 'bind',
 187                  eventIn  = options.trigger == 'hover' ? 'mouseenter' : 'focus',
 188                  eventOut = options.trigger == 'hover' ? 'mouseleave' : 'blur';
 189              this[binder](eventIn, enter)[binder](eventOut, leave);
 190          }
 191  
 192          return this;
 193  
 194      };
 195  
 196      $.fn.tipsy.defaults = {
 197          className: null,
 198          delayIn: 0,
 199          delayOut: 0,
 200          fade: true,
 201          fallback: '',
 202          gravity: 'n',
 203          center: true,
 204          html: false,
 205          live: false,
 206          offset: 0,
 207          opacity: 1.0,
 208          title: 'title',
 209          trigger: 'hover'
 210      };
 211  
 212      // Overwrite this method to provide options on a per-element basis.
 213      // For example, you could store the gravity in a 'tipsy-gravity' attribute:
 214      // return $.extend({}, options, {gravity: $(ele).attr('tipsy-gravity') || 'n' });
 215      // (remember - do not modify 'options' in place!)
 216      $.fn.tipsy.elementOptions = function(ele, options) {
 217          return $.metadata ? $.extend({}, options, $(ele).metadata()) : options;
 218      };
 219  
 220      $.fn.tipsy.autoNS = function() {
 221          return $(this).offset().top > ($(document).scrollTop() + $(window).height() / 2) ? 's' : 'n';
 222      };
 223  
 224      $.fn.tipsy.autoWE = function() {
 225          return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'e' : 'w';
 226      };
 227  
 228      /**
 229       * yields a closure of the supplied parameters, producing a function that takes
 230       * no arguments and is suitable for use as an autogravity function like so:
 231       *
 232       * @param margin (int) - distance from the viewable region edge that an
 233       *        element should be before setting its tooltip's gravity to be away
 234       *        from that edge.
 235       * @param prefer (string, e.g. 'n', 'sw', 'w') - the direction to prefer
 236       *        if there are no viewable region edges effecting the tooltip's
 237       *        gravity. It will try to vary from this minimally, for example,
 238       *        if 'sw' is preferred and an element is near the right viewable 
 239       *        region edge, but not the top edge, it will set the gravity for
 240       *        that element's tooltip to be 'se', preserving the southern
 241       *        component.
 242       */
 243       $.fn.tipsy.autoBounds = function(margin, prefer) {
 244          return function() {
 245              var dir = {ns: prefer[0], ew: (prefer.length > 1 ? prefer[1] : false)},
 246                  boundTop = $(document).scrollTop() + margin,
 247                  boundLeft = $(document).scrollLeft() + margin,
 248                  $this = $(this);
 249  
 250              if ($this.offset().top < boundTop) dir.ns = 'n';
 251              if ($this.offset().left < boundLeft) dir.ew = 'w';
 252              if ($(window).width() + $(document).scrollLeft() - $this.offset().left < margin) dir.ew = 'e';
 253              if ($(window).height() + $(document).scrollTop() - $this.offset().top < margin) dir.ns = 's';
 254  
 255              return dir.ns + (dir.ew ? dir.ew : '');
 256          }
 257      };
 258  
 259  })(jQuery);


Generated: Fri Nov 28 14:03:12 2014 Cross-referenced by PHPXref 0.7.1