//Copyright 2003-2004 A9.com or its affiliates
//Copyright 2003 - Alexa Internet
// Updated Fri Jul 14 17:06:53 PDT 2006

// this file implements siteInfo popups.  To use it, do the following:
// * Include siteInfo.jsp.  That includes the layout for the siteInfo balloon
// * Create siteInfo links to point to alexa.
// * On those links set siteInfo="true".
// * Call initSiteInfo to initialize rolloves in all those links.
// * If more siteInfo links are dynamicaly created, call initSiteInfo again.

// requires utils.js, prototype.js, behaviour.js

var SI_POPUP_TIMEOUT=100;      // time to pop up after entering site info
var SI_POPDOWN_TIMEOUT=50;     // time to pop down after leaving site info
var SI_MAX_RELATED_LINKS = 3;  // maximum related links to show in the popup
var siPopupTimeout;
var siPopdownTimeout;
var siPopupTarget;

var ALEXA_XML_SOURCE = "/xml/dad";
var ALEXA_IMAGES = "http://client.alexa.com/ds/images/";
var ALEXA_DETAILS_PAGE = "http://www.alexa.com/data/details?url=";
Event.observe(window, 'load', initSiteBubbles);

var a9IsIE = (document.all) ? true : false;

// TODO: rewrite this whole thing using oop

function initSiteBubbles() {
	var siteinfo_selector = "a.siteinfo";
	if(document.getElementsBySelector) {
		siLoadBalloonImages();
		var links = $A(document.getElementsBySelector(siteinfo_selector));
		if( !links ||  !links.length > 0) { return false;}
		links.each( function (element) {
			Event.stopObserving(element, 'mouseover', siMouseOver);
			Event.stopObserving(element, 'mouseout', siMouseOut);
			Event.observe(element, 'mouseover', siMouseOver);
			Event.observe(element, 'mouseout', siMouseOut);
		});
	}
	var balloon = $('balloon');
	Event.stopObserving(balloon, 'mouseover', siMouseOverBalloon);
	Event.stopObserving(balloon, 'mouseout', siMouseOutBalloon);
	Event.observe(balloon, 'mouseover', siMouseOverBalloon);
	Event.observe(balloon, 'mouseout', siMouseOutBalloon);
}


function siGetAncestorWithAttr(node, attr) {
  while (node) {
    if (a9GetAttribute(node, attr)) {
      return node;
    }
    node = node.parentNode;
  }
  return null;
}

// called when the mouse enters the site info link
// Schedule the popup
function siMouseOver(evt) {
	var target = Event.findElement(evt, 'A');
  //target = siGetAncestorWithAttr(target, "popupUrl");
  if (target) {
    siPopupTarget = target;
    if (siPopupTimeout) {
      clearTimeout(siPopupTimeout);
    }
    siPopupTimeout = setTimeout("siPrepPopop()", SI_POPUP_TIMEOUT);
    if (siPopdownTimeout) {
      clearTimeout(siPopdownTimeout);
      siPopdownTimeout = null;
    }
  }
}

// called when the mouse leaves the site info link
// If the popup is scheduled by not yet invoked, unschedule it.
// If it is already popped up, schedule a pop down.
function siMouseOut(evt) {
  if (siPopupTimeout) {
    clearTimeout(siPopupTimeout);
    siPopupTimeout = null;
  }
  siPopupTarget = null;
  var balloon = document.getElementById('balloon');
  if (balloon && balloon.style.display == "") {
    if (siPopdownTimeout) {
      clearTimeout(siPopdownTimeout);
    }
    siPopdownTimeout = setTimeout("siPopdown()", SI_POPDOWN_TIMEOUT);
  }
}

// The mouse is over the balloon.  Unschedule any pending pop down
function siMouseOverBalloon() {
  if (siPopdownTimeout) {
    clearTimeout(siPopdownTimeout);
    siPopdownTimeout = null;
  }
}

// the mouse has left the balloon.  Scheule a pop down.
function siMouseOutBalloon() {
  if (siPopdownTimeout) {
    clearTimeout(siPopdownTimeout);
  }
  siPopdownTimeout = setTimeout("siPopdown()", SI_POPDOWN_TIMEOUT);
}

// We are ready to popup a balloon.  If we already have the data, show the
// balloon.  Otherwise, fetch it from Alexa.
function siPrepPopop() {
  try {
    siPopupTimeout = null;
    if (siPopupTarget) {
      if (siPopupTarget.data) {
        siShowPopup(siPopupTarget.data.request);
      } else {
        var data = new Object;
        siPopupTarget.data = data;
        data.target = siPopupTarget;
        // figure out the URL to send to alexa.  If possible, look for a ?url=
        // argument
        //var url = a9GetAttribute(siPopupTarget, "popupUrl");
        var url = siPopupTarget.href;
        if (!url) return;
        var q = url.indexOf("?");
        if (q != -1) {
          var qu = url.substring(q+1);
          var ui = qu.indexOf("url=");
          if (ui != -1) {
            url = qu.substring(ui+4);
            // if we got here, the url is encoded, so unencode it
            url = a9Decode(url);
          }
        }
				var params = '';
				var options = {method: 'get', parameters: params, onSuccess: siShowPopup};
				new Ajax.Request(ALEXA_XML_SOURCE + url, options);
      }
    }
  } catch (e) {}
}

// fill in and show the popup balloon
function siShowPopup(request) {
	if(!siPopupTarget.data.request) {
		siPopupTarget.data.request = request;
	}
  if (siFillBalloon(request)) {
    siPositionBalloon();
  }
}

// fill in the data into the appropriate fields of the balloon
// Return true if everything succeeded
function siFillBalloon(request) {
  // helper function.  Given a parent node, call getElementsByTagName
  // to return the first descendent node with the given tag.
  // Return null if no such child.
  function getTagNode(el, tag) {
    var a = el.getElementsByTagName(tag);
    if (a && a.length > 0) {
      return a[0];
    }
    return null;
  }

  // helper function.  Looks up a node, and sets its innerHTML to the
  // value.  (If the value is null, set it to the empty string)
  function setValue(nodeName, value) {
    if (value == null) {
      value = "";
    }
    var node = document.getElementById(nodeName);
    if (node) {
      node.innerHTML = value;
    }
  }

  // format a number with commas
  function formatComma(sStr)
  {
    var sInStr = new String(sStr);
    var aThrees = new Array();

    for (var i = sInStr.length; i > 0; i-=3) {
      aThrees[aThrees.length] = sInStr.substring(((i-3 > 0) ? i-3 : 0),i);
    }
    return aThrees.reverse().join(",");
  }
	if(request && request.responseXML) {
    var balloon = document.getElementById('balloon');
		var de = request.responseXML.documentElement;
    if (de) {
			var _alexa = false;
			if(de.nodeName == 'ALEXA') { _alexa = de; }
			else { _alexa = getTagNode(de, "ALEXA"); }
      if (_alexa) {
        var _rls = getTagNode(_alexa, "RLS");
        var _sd = getTagNode(_alexa, "SD");
        var _dmoz = getTagNode(_alexa, "DMOZ");

        // get the url
        var url = _alexa.getAttribute("URL");
        // remove trailing slash
        var stripUrl = url;
        if (stripUrl.lastIndexOf("/") == stripUrl.length-1) {
          stripUrl = stripUrl.substring(0, stripUrl.length - 1);
        }
        setValue("b_siteurl", stripUrl);

        // figure out the ASIN.  It is not displayed directly, but is
        // used in some of the links
        var asin=null;
        if (_sd) {
          var _amzn = getTagNode(_alexa, "AMZN");
          if (_amzn) {
            // the ASIN is only valid if the URL on the ASIN is the same
            // as the start of the overall url
            var amznUrl = _amzn.getAttribute("URL");
            if (url && amznUrl && url.indexOf(amznUrl) == 0) {
              asin = _amzn.getAttribute("ASIN");
            }
          }
        }
				var LINK = ALEXA_DETAILS_PAGE +url;

        var html;
        // get the title.  Several nodes to check.  First check DMOZ/SITE/@TITLE
        var title = null;
        if (_dmoz) {
          var _dmozSite = getTagNode(_dmoz, "SITE");
          if (_dmozSite) {
            title = _dmozSite.getAttribute("TITLE");
          }
        }
        // next check SD/OWNER/@NAME
        if (!title) {
          if (_sd) {
            var _sdOwner = getTagNode(_sd, "OWNER");
            if (_sdOwner) {
              title = _sdOwner.getAttribute("NAME");
            }
          }
        }
        // still no title, take the URL
        if (!title) {
          title = stripUrl;
        }
        setValue("b_sitetitle", title);
        // show the first three related links
        html="";
        var i=0, j=0;
        if (_rls) {
          var _rlList = _rls.getElementsByTagName("RL");
          if (_rlList) {
            for (var i=0, j=0; j<SI_MAX_RELATED_LINKS && i<_rlList.length; i++,j++) {
              var rlHref = _rlList[i].getAttribute("HREF");
              var rlTitle = _rlList[i].getAttribute("TITLE");
              if (rlHref && rlTitle) {
                html += '<li><a style="popup_link" href="http://'+rlHref+'">';
                html += rlTitle.substring(0, 35);
                html += '</a></li>';
              }
            }
          }
        }
        setValue("b_rls", html);
        var b_also = document.getElementById("b_also");
        if (b_also) {
          b_also.style.display=(j==0?"none":"");
        }
        // traffic rank
        var _rank = null;
        if (_sd) {
          var _popularity = getTagNode(_sd, "POPULARITY");
          if (_popularity) {
            _rank = _popularity.getAttribute("TEXT");
          }
        }
				html = "";
        if (_rank) {
          html += "<a href='"+LINK+"'>";
          html += formatComma(_rank);
          html += "</a>";
        } else {
          html += "No Data";
        }
        setValue("b_traffic_rank", html);

        // links to this site
        var _linksIn = null;
        if (_sd) {
          var _linksin = getTagNode(_sd, "LINKSIN");
          if (_linksin) {
            _linksIn = _linksin.getAttribute("NUM");
          }
        }
				html = "";
        if (_linksIn) {
          html="<a href='"+LINK+"'>";
          html += formatComma(_linksIn);
          html += "</a>";
        } else {
          html += "Not Available";
        }
        setValue("b_linksin", html);

        // loading speed
				html = "";
        var _speed = null, _speedPct=null, _speedText=null;
        if (_sd) {
          _speed = getTagNode(_sd, "SPEED");
          if (_speed) {
            _speedPct = _speed.getAttribute("PCT");
            _speedText = _speed.getAttribute("TEXT");
          }
        }
        if (_speedPct && _speedText) {
          var speedSec = (Math.round(_speedText / 100) * 100) / 1000;
          var speedMod="";
          if (_speedPct < 20) {
            speedMod = "Very Slow";
          } else if (_speedPct < 40) {
            speedMod = "Slow";
          } else if (_speedPct < 60) {
            speedMod = "Average";
          } else if (_speedPct < 80) {
            speedMod = "Fast";
          } else if (_speedPct <= 100) {
            speedMod = "Very Fast";
          } else {
            speedMod = "Not Available";
          }
					html += '<a href="' + LINK + '">';
          html += speedMod + ' (' + speedSec + " seconds) ";
					html += '</a>';
        } else {
          html += "Not available";
        }
        setValue("b_speed", html);
        // the date the site first went online
        var _date = null;
        if (_sd) {
          var _created = getTagNode(_sd, "CREATED");
          if (_created) {
            _date = _created.getAttribute("DATE");
          }
        }
        if (_date) {
          html = _date;
        } else {
          html = "Not Available";
        }
        setValue("b_online", html);

        // more info
				$('b_moreinfo').href = LINK;

        return true;
      }
    }
  }
  return false;
}

// position the balloon near the site info, so that it is visible on the page
function siPositionBalloon() {
  var balloon = document.getElementById('balloon');
  var topArrowNode = document.getElementById("toparrow");
  var topArrowRevNode = document.getElementById("toparrowrev");
  var bottomArrowNode = document.getElementById("bottomarrow");
  var bottomArrowRevNode = document.getElementById("bottomarrowrev");
  var topNode = siPopupTarget.offsetParent; 
  var topCoord = siPopupTarget.offsetTop; 
  var leftCoord = siPopupTarget.offsetLeft;

  while (topNode) { 
    topCoord += topNode.offsetTop; 
    leftCoord += topNode.offsetLeft; 
    topNode = topNode.offsetParent; 
  }

  topArrowNode.style.display = "none";
  topArrowRevNode.style.display = "none";
  bottomArrowNode.style.display = "none";
  bottomArrowRevNode.style.display = "";
  // we need to calculate the size of the balloon. The size can
  // only be calculated whtn the balloon is displayed, but we don't
  // want it to actually flash.  Also, we want it positioned at the
  // left, under the fold, so it won't be clipped.
  balloon.style.visibility="hidden";   // so we won't see it
  balloon.style.display ="";           // so we can calculate its size
  balloon.style.left = 0;
  balloon.style.top = document.body.scrollTop;
  var balloonWidth = balloon.offsetWidth;
  var balloonHeight = balloon.offsetHeight;
  bottomArrowRevNode.style.display = "none";

  // default position: above and centered
  var isAbove = true, isCentered=true;
  var top = topCoord - balloonHeight;
  var left = leftCoord - 75;

  // If there is no room above, it needs to be below
  if (top < document.body.scrollTop) {
    isAbove = false;
    top = topCoord + siPopupTarget.offsetHeight;
  }

  // if there is no room to the right, move it left
  if (left + balloonWidth > document.body.clientWidth) {
    isCentered = false;
    left = leftCoord - 235;
  }
  if (left < 0) {
    left = 0;
  }

  if (isAbove) {
    if (isCentered) {
      bottomArrowNode.style.display = "";
    } else {
      bottomArrowRevNode.style.display = "";
    }
  } else {
    if (isCentered) {
      topArrowNode.style.display = "";
    } else {
      topArrowRevNode.style.display = "";
    }
  }
  
  balloon.style.top = top;
  balloon.style.left = left;
  setTimeout("siMakeBalloonVisible()", 0);
}

// if we don't defer resetting the balloon visibility, it flashes
function siMakeBalloonVisible() {
  var balloon = document.getElementById('balloon');
  balloon.style.visibility="";
}

// popdown the balloon.
function siPopdown() {
  if (siPopdownTimeout) {
    clearTimeout(siPopdownTimeout);
  }
  siPopdownTimeout = null;
  var balloon = document.getElementById('balloon');
  if (balloon) {
    balloon.style.display = "none";
  }
}

// For efficiency on initial page load, we don't actually include the balloon
// images in the HTML for the balloon.  Instead we start fetching them after
// page load.
var siBalloonImagesLoaded = false;
function siLoadBalloonImages() {
  try {
    if (!siBalloonImagesLoaded) {
      document.getElementById("blnTopArrow").src = ALEXA_IMAGES+"/top-arrow.gif";
      document.getElementById("blnTopArrowRev").src = ALEXA_IMAGES+"/top-arrow-rev.gif";
      document.getElementById("blnTopLft").src = ALEXA_IMAGES+"/top-lft.gif";
      document.getElementById("blnTopRt").src = ALEXA_IMAGES+"/top-rt.gif";
      document.getElementById("blnBtmLft").src = ALEXA_IMAGES+"/btm-lft.gif";
      document.getElementById("blnBtmRt").src = ALEXA_IMAGES+"/btm-rt.gif";
      document.getElementById("blnBtmArrow").src = ALEXA_IMAGES+"/btm-arrow.gif";
      document.getElementById("blnBtmArrowRev").src = ALEXA_IMAGES+"/btm-arrow-rev.gif";
      document.getElementById("blnTopBdr").style.backgroundImage = "url("+ALEXA_IMAGES+"/top-bdr.gif)";
      document.getElementById("blnLftBdr").style.backgroundImage = "url("+ALEXA_IMAGES+"/lft-bdr.gif)";
      document.getElementById("blnRtBdr").style.backgroundImage = "url("+ALEXA_IMAGES+"/rt-bdr.gif)";
      document.getElementById("blnBtmBdr").style.backgroundImage = "url("+ALEXA_IMAGES+"/btm-bdr.gif)";
      siBalloonImagesLoaded = true;
    }
  } catch (e) {}
}
