Yahoo Fantasy Smack Tooltip

By Glenn Carr Last update Sep 7, 2007 — Installed 1,463 times.
// ==UserScript==
// @name           Yahoo Fantasy Smack Tooltip
// @namespace      http://glenncarr.com/greasemonkey/yahoofantasy
// @description    Display smack text when hovering over smack image
// @include        *.fantasysports.yahoo.com*
// @author         (c) 2007 Glenn Carr <glenn at glenncarr dot com>
// $LastChangedRevision: 301 $
// $LastChangedDate: 2007-09-06 23:50:24 -0500 (Thu, 06 Sep 2007) $
// ==/UserScript==

/*
 * Most of the credit for this goes to Ryan Grove <ryan@wonko.com> and his excellent Jyte ClaimInfo script:
 *    http://userscripts.org/scripts/show/9216
 *
 * Updates:
 * 22-May-2007 - Added dropshadow image, working image
 * 25-May-2007 - Bail quietly on any exceptions during initialization
 * 06-Sep-2007 - Rename CSS class because of conflict with 'smack' class on football pages
 */

(function() {

var YAHOO, yua, yud, yue, yut;

String.prototype.trim = function () {
  return this.replace(/^\s*(\S*(\s+\S+)*)\s*$/, "$1");
}

String.prototype.stripTags = function() {
  return this.replace(/<\/?[^>]+>/gi,'');
}

var SmackTooltips = function () {
  // -- Private Variables ------------------------------------------------------
  var infoCache    = {},
      descTimeout  = null,
      WORKING_IMG_URL = "data:image/gif,GIF89a%0A%00%0A%00%91%03%00%CC%CC%CC%FFff%FF%00%00%FF%FF%FF!%FF%" +
"0BNETSCAPE2.0%03%01%00%00%00!%F9%04%05%00%00%03%00%2C%00%00%00%00%0A%00%0A%00%00%02%17%9C'r%06%80%1A%" +
"02s'%AE%3Bqk%9A%E2%C3%81%14Gz%D9Q%00%00!%F9%04%05%00%00%03%00%2C%01%00%00%00%08%00%03%00%00%02%0A%9C%" +
"136%22%83%03%00S%10%14%00!%F9%04%05%00%00%03%00%2C%00%00%00%00%06%00%06%00%00%02%0C%9C%070%11%A8%7C%A" +
"2%11%22%D2X%00%00!%F9%04%05%00%00%03%00%2C%00%00%01%00%03%00%08%00%00%02%0A%1C%608%13%C1%BE%96%10c%16" +
"%00!%F9%04%05%00%00%03%00%2C%00%00%04%00%06%00%06%00%00%02%0A%04%86c%C9%1C%E1%A0%10l%16%00!%F9%04%05%" +
"00%00%03%00%2C%01%00%07%00%08%00%03%00%00%02%0A%04%86%23b%13%A1Dz%A9%00%00!%F9%04%05%00%00%03%00%2C%0" +
"4%00%04%00%06%00%06%00%00%02%0C%9C'r%A8%BB%11%06%00%03Jz%0A%00!%F9%04%09%00%00%03%00%2C%07%00%01%00%0" +
"3%00%08%00%00%02%0A%94f%A3%1A1%BD%00%18r%14%00%3B";

  return {
    // -- Public Methods -------------------------------------------------------

    /**
     * Initializes the SmackTooltips module, injecting HTML and CSS into the page
     * and attaching event handlers. This method must be called AFTER the YUI
     * libs are loaded.
     */
    init: function () {
      this.inject();

      // Create custom events.
      this.onSmackReceived = new yut.CustomEvent('smackReceived', this);

      // Attach event handlers.
      var smackLinks = yud.getElementsByClassName( 'blast', 'a' );

      yue.addListener(smackLinks, 'mouseover', this.showDesc, this, true);
      yue.addListener(smackLinks, 'mouseout', this.hideDesc, this, true);

      this.onSmackReceived.subscribe(function (e, args) {
        this.refreshDesc(args[0]);
      }, this, true);
    },

    /**
     * Injects markup and CSS used for the tooltips.
     */
    inject: function () {
      GM_addStyle(
          '.gncSmackTip { font-size: 12px; text-align:left; float:left; margin:10px 0 0 10px !important; margin:10px 0 0 5px; background: url(http://us.i1.yimg.com/us.yimg.com/i/us/sp/fn/default/full/drop_shadow.gif) no-repeat bottom right; }' +
          '.gncSmackTip p:first-child { margin-top: 0; }' +
          '.gncSmackTip p:last-child { margin-bottom: 0; }' +
          '.gncSmackTip div.inner, .gncSmackTip div.loading { display:block; position:relative; background:#eeffff; border:1px solid #333333; margin:0px 4px 4px 0px; padding:4px }' +
          '.gncSmackTip div.loading { font-style: italic; color: #666666; font-size: 80% }'
      );

      var div = document.createElement( 'DIV' );
      div.id = 'smacktip';
      div.style.display = 'none';
      div.setAttribute( 'class', 'gncSmackTip' );
      div.style.zIndex = 99;
      document.body.appendChild( div );
    },

    /**
     * Downloads the team page at the specified URL and caches it for
     * future use.
     *
     * @param {String} team page url
     */
    getSmack: function (url) {
      if (infoCache.hasOwnProperty(url)) {
        this.onSmackReceived.fire(infoCache[url]);
        return;
      }

      GM_xmlhttpRequest({
        method: 'GET',
        url   : url,
        onload: function (response) {
          infoCache[url] = response.responseText;
          SmackTooltips.onSmackReceived.fire(response.responseText);
        }
      });
    },

    /**
     * Hides the smack tooltip.
     */
    hideDesc: function (e) {
      clearTimeout(descTimeout);
      yud.setStyle('smacktip', 'display', 'none');
    },

    /**
     * Loads the YUI Dom, Event, and Animation libraries and calls
     * SmackTooltips.init() when they're finished loading.
     */
    loadYUI: function () {
      var yuiDomEvent = document.createElement('script'),
          yuiAnim     = document.createElement('script');

      try {
        yuiDomEvent.src  = 'http://yui.yahooapis.com/2.2.2/build/yahoo-dom-event/yahoo-dom-event.js';
        yuiAnim.src      = 'http://yui.yahooapis.com/2.2.2/build/animation/animation-min.js';

        document.body.appendChild(yuiDomEvent);
        document.body.appendChild(yuiAnim);
      } catch ( e )
      { return; }

      var loadInterval = setInterval(function () {
        if (!unsafeWindow.YAHOO || !unsafeWindow.YAHOO.util.Anim) {
          return;
        }

        clearInterval(loadInterval);

        YAHOO = unsafeWindow.YAHOO;
        yut   = YAHOO.util;
        yua   = yut.Anim;
        yud   = yut.Dom;
        yue   = yut.Event;

        SmackTooltips.init();
      }, 50);
    },

    /**
     * Refreshes the smack tooltip when team info is received.
     *
     * @param {String} smackContent contents of the team page
     */
    refreshDesc: function (smackContent) {
      var smackTooltip = yud.get('smacktip'),
          match = smackContent.match( /id="smacktext"[^>]+\>([^<]+)\</i );

      if (!match) {
        smackTooltip.innerHTML = 'No description.';
      }
      else {
        var content = match[1].trim();
        smackTooltip.innerHTML = '<div class="inner">' + content + '</div>';
      }
    },

    /**
     * Shows the tooltip after a delay.
     */
    showDesc: function (e) {

      descTimeout = setTimeout(function () {
        var smackTooltip  = yud.get('smacktip'),
            smackLink  = yue.getTarget(e),
            anim       = new yua(smackTooltip, {opacity: {to: 1.0}}, 0.4, YAHOO.util.Easing.easeBoth);

        smackTooltip.innerHTML = '<div class="loading">Loading...<img align="absmiddle" src="' + WORKING_IMG_URL + '"/></div>';

        SmackTooltips.getSmack(smackLink.href);

        yud.setStyle(smackTooltip, 'opacity', 0.0);
        yud.setStyle(smackTooltip, 'display', 'block');

        yud.setXY(smackTooltip, [yud.getX(smackLink),
            yud.getY(smackLink) + smackLink.offsetHeight + 18]);

        anim.animate();
      }, 100);
    }
  };
}();

SmackTooltips.loadYUI();
})();