//To make this script work you just need to call the init_balloons function.
//You can call it at any time using any event you want. onLoad for example.

// Some global variables
var object_id;
var old_id;
var balloon;
var timer;
var same;
var closed_manually;

//Core functionality of the balloon script
//This includes the functions that inject our javascript into the page
//as well as functions that control the presentation as well as supporting
//functions


//taken directly from ose.js and modified for my needs
//Looks for all links with the class "balloon_link", attaches an event handler
//Removes href attribute.
function init_balloons() {
    if (!document.getElementsByTagName) return null;
    var info_links = document.getElementsByTagName("a");
    for (c=0;c<info_links.length;c++) {
        var k = info_links[c];
        if (k.className == "balloon_link") {
            k.removeAttribute("href");
            k.onmouseover = delayed_balloon;
            k.onmouseout = stop_timer;
        }
    }
    inflate_balloon(); //for text browsers/screen readers we keep the balloon div blank by default
    document.body.onclick = hide_balloon;
}


function stop_timer(){
    clearTimeout(timer);
}

//The balloon div is hidden by css but if someone hits the site with either a
//scren reader or a text browser or browser that doesn't support css it'll
//still be there. We get around this by having the div empty by default.
//This is the function we run to fill it in
function inflate_balloon(){
    //pretty clever name, isn't it?
    document.getElementById("tooltip_balloon").innerHTML = '<img src="../images/bar_gradient.gif" onMouseDown="dragStart(event,\'tooltip_balloon\');" id="drag_bar" class="drag" /><img src="../images/balloon_close.gif" alt="Close Button" title="Click here to close" onClick="hide_balloon();" /><div id="balloon_loading">&nbsp;</div><div id="balloon_article">&nbsp;</div>';
    document.getElementById("balloon_loading").innerHTML = '<p class="balloon_centered"><img src="../images/loading.gif" alt="Loading..." />Please wait while article is loaded</p>';
}


function delayed_balloon(){
    if (navigator.appName == "Microsoft Internet Explorer"){
        parentid = window.event.srcElement.parentNode.id;
        timer = setTimeout('show_balloon(parentid);', 400);
    }
    else{
        timer = setTimeout(show_balloon, 400, this.id);
    }
    
}


//The show_balloon function below is the main function for the balloon script
//it runs inflate balloon and then hides the balloon. After that we figure out
//which object called this event and identify where within the browser the
//user is scrolled to. Then we define objects for the balloon and source element
//Next we figure out where the source object is on the page and what it's size
//is. We then define the new position for the balloon and add a percentage of
//it's size to the position. Now, for presentation sake we need to insure that
//the balloon doesn't appear outside of the viewport.
//To accomplish this we need our 'working' size which is basically the area
//of the browser the user sees. We need to know the absolute pixels of that.
//So, for example, we find the vertical information by adding the viewport
//height with the vertical scroll position. Now we know where the balloon can be
//allowed to appear. Next we need to figure out how large it is. For the height
//we add the assumed vertical position to the height of the balloon. We now have
//the future absolute position of the balloon. If this number is larger than the
//working area we adjust the position by the difference.
//The rest is basic. We position the balloon, make it visible, make the loading
//message appear, and tell our http object to fetch the article
function show_balloon(ev_id) {
    old_id = object_id;
    
    //Because IE doesn't have a compliant dom like.. EVERY OTHER (modern) BROWSER IN THE WORLD
    if (navigator.appName == "Microsoft Internet Explorer"){
        object_id = ev_id;
        scroll_y = document.documentElement.scrollTop;
        scroll_x = document.documentElement.scrollLeft;
    }
    else{
        object_id = ev_id;
        scroll_y = window.scrollY;
        scroll_x = window.scrollX;
    }
    
    pic = null;
    
    //this fixes a bug (I hope) where the balloon covers the image and then
    //the user mouses over the image again quickly, which then hides our balloon
    if(old_id != object_id){
        //IE chokes on hide_balloon here for some reason, I dont' understand why and I'm sick of dealing with it
        if(navigator.appName == "Microsoft Internet Explorer"){
            document.getElementById("tooltip_balloon").style.visibility="hidden"; //hide the balloon that way we don't see it move
        }
        else{
            hide_balloon();
        }
        same = false;
    }
    else{
        same = true;
    }
    
    if(closed_manually == true){
        same = false;
    }
    
    
    
    //define our objects for quick reference
    balloon = document.getElementById("tooltip_balloon"); // the balloon itself
    pic = document.getElementById(object_id); //the object that was clicked to trigger the event
    
    pic_top = find_top(pic); // top of the object clicked
    pic_left = find_left(pic); //left of the object clicked
    pic_height = pic.offsetHeight; // pi*r^2
    pic_width = pic.offsetWidth; // number of licks it takes to get to the tootsieroll center of a tootsiepop
    
    
    new_balloon_top = pic_top + (pic_height / 1.9);  // these two lines make the balloon position
    new_balloon_left = pic_left + (pic_width / 1.9); // a little more sensible and attractive
    
    //now, we want to insure that the element never causes the page to scroll or appears out of the viewport
    working_height = get_viewport_height() + scroll_y;
    needed_height = new_balloon_top + balloon.offsetHeight;
    
    if(working_height<needed_height){
        height_difference = needed_height - working_height;
        new_balloon_top = new_balloon_top - height_difference - 18; //subtract some because of a scrollbar issue... trust me on this
    }
    
    //working_width = get_viewport_width() + scroll_x;
    working_width = get_viewport_width() + scroll_x;
    needed_width = new_balloon_left + balloon.offsetWidth;
    if (working_width < needed_width){
        width_difference = needed_width - working_width;
        new_balloon_left = new_balloon_left - width_difference - 18; // see above comment for similar line
    }
    
    //delay all the moving and appearing of everything
    if(same == false){
        balloon.style.top = new_balloon_top + "px";
        balloon.style.left = new_balloon_left + "px";
        document.getElementById("balloon_article").style.visibility="hidden";
        balloon.style.visibility="visible";
        document.getElementById("balloon_loading").style.visibility="visible";
        get_article(object_id);
        closed_manually=false;
    }

}


//This function does what the name implies it should. It is slightly complicated
//but not bad. All we do is fetch the source of the event and make sure that
//it wasn't a click in or on the balloon. If it is we don't want to hide it.

function hide_balloon(event){
    //this line intentionally left blank
    if (navigator.appName == "Microsoft Internet Explorer"){
        ev_source = window.event.srcElement;
    }
    else{//firefox was acting stupid here.. so that's why this looks strange.
        if(event){
            ev_source = event.target;
        }
        else{
            ev_source = "undefined";
        }
    }
    //Well, this is a long if statement. Basically we're looking to see if the
    //event source is one of the balloon's divs or an item inside of it.
    //I'm sure the h2 and h3 ifs will have some false positives, but not too many
    if((ev_source.id != "drag_bar") && (ev_source.id != "balloon_article") && (ev_source.className != undefined) && (ev_source.className != "balloon_link") && (ev_source.id != "balloon_loading") && (ev_source.tagName != "H2")  && (ev_source.className != "example") && (ev_source.className != "newwin") && (ev_source.tagName != "H3")){
        document.getElementById("balloon_loading").style.visibility="hidden";
        document.getElementById("balloon_article").style.visibility="hidden";
        document.getElementById("tooltip_balloon").style.visibility="hidden";
        closed_manually = true;
    }
    if(ev_source.alt == "Close Button"){
        document.getElementById("balloon_loading").style.visibility="hidden";
        document.getElementById("balloon_article").style.visibility="hidden";
        document.getElementById("tooltip_balloon").style.visibility="hidden";
        closed_manually = true;
    }
    
}


//This is weldon's http_request function from the notices_and_alerts script.
//It just tries to instantiate an http socket until it succeeds.
function http_request(){
    var http;
    try{
        // Firefox ...
        http = new XMLHttpRequest();
    }
    catch(e){
        // IE
        try{
            http = new ActiveXObject("Msxml2.XMLHTTP");
        }
        catch(e){
            try{
                http = new ActiveXObject("Microsoft.XMLHTTP");
            }
            catch(e){
                return false;
            }
        }
    }
    return http;
}


//This function fetches the article (or error message) from the server.
//When we have the article we hide the loading messaeg and show the article
//We also position the scroll bar at 0
function get_article(article_id){
    http = http_request();
    http.onreadystatechange=function(){
        if(http.readyState == 4){ //when we have a result....
            if (http.status == 200){
                document.getElementById("balloon_article").innerHTML = http.responseText; //put the incoming html into the balloon_article div
            }
            else{
                document.getElementById("balloon_article").innerHTML = "<h2>Error</h2><span class=\"example\"><a href=\"http://uits.iu.edu/page/" + article_id + "/\">http://uits.iu.edu/page/" + article_id + "</a></span><p>Sorry, an error has occurred while retrieving the information you've requested. You can try to go directly to the information source by clicking the link above.</p> <p>For information about server down times or network outages, please visit IU IT Notices.</p><span class=\"example\"><a href=\"http://itnotices.iu.edu/\">http://itnotices.iu.edu/</a></span>";
            }
            document.getElementById("balloon_loading").style.visibility="hidden"; // we don't need to show the loading message anymore
            if (document.getElementById("tooltip_balloon").style.visibility!="hidden"){ //This is a fix for a bug where if you close the balloon before the article loads it still shows up, but without the balloon.
                document.getElementById("balloon_article").style.visibility="visible"; // let's see the article
                initNewWin();
            }
            document.getElementById("balloon_article").scrollTop=0; // when the div is visible again we find that the scroll position is where ever it was before unless we set it to 0
        }
    }
    http.open("GET","../scripts/balloon_article_processor.php?" + article_id, true);
    http.send(null);
}


//The next to functions were originally one function but I wanted to have
//separate ones. They are used in show_balloon() to figure out the position
//of the element that was clicked the names imply what values they return
//Taken from http://www.quirksmode.org/js/findpos.html
function find_left(obj){
    var curleft = 0;
        
    if (obj.offsetParent){
        do{
            curleft += obj.offsetLeft;
        } while (obj = obj.offsetParent);
    }
        
    return curleft;
}

function find_top(obj){
    var curtop = 0;
    
    if (obj.offsetParent){
        do{
            curtop += obj.offsetTop;
        } while (obj = obj.offsetParent);
    }
    
    return curtop;
}

//These functions were originally one function, I think.. either way,
//They do what their names imply they should.
//Next two functions taken from http://andylangton.co.uk/articles/javascript/get-viewport-size-javascript/
function get_viewport_height(){
    var view_height = 0;
    // the more standards compliant browsers (mozilla/netscape/opera/IE7) use window.innerWidth and window.innerHeight
    if (typeof window.innerHeight != 'undefined'){
        view_height = window.innerHeight;
    }
    // IE6 in standards compliant mode (i.e. with a valid doctype as the first line in the document)
    else if (typeof document.documentElement != 'undefined'&& typeof document.documentElement.clientWidth != 'undefined' && document.documentElement.clientWidth != 0){
        view_height = document.documentElement.clientHeight;
    }
    // older versions of IE
    else{
        view_height = document.getElementsByTagName('body')[0].clientHeight;
    }
    return view_height;
}

function get_viewport_width(){
    var view_width = 0;
    // the more standards compliant browsers (mozilla/netscape/opera/IE7) use window.innerWidth and window.innerHeight
    if (typeof window.innerWidth != 'undefined'){
        view_width = window.innerWidth;
    }
    // IE6 in standards compliant mode (i.e. with a valid doctype as the first line in the document)
    else if (typeof document.documentElement != 'undefined'&& typeof document.documentElement.clientWidth != 'undefined' && document.documentElement.clientWidth != 0){
        view_width = document.documentElement.clientWidth;
    }
    // older versions of IE
    else{
        view_width = document.getElementsByTagName('body')[0].clientWidth;
    }
    return view_width;
}


//These next functions are the ones that make the div draggable. None of it is
//my work. I don't think I even modified them much. I added in the bit for opera
//in the browser function.

//*****************************************************************************
// Do not remove this notice.
//
// Copyright 2001 by Mike Hall.
// See http://www.brainjar.com for terms of use.
//*****************************************************************************

// Determine browser and version.

function Browser() {
  var ua, s, i;
  this.isIE    = false;
  this.isNS    = false;
  this.version = null;

  ua = navigator.userAgent;

  s = "MSIE";
  if ((i = ua.indexOf(s)) >= 0) {
    this.isIE = true;
    this.version = parseFloat(ua.substr(i + s.length));
    return;
  }

  s = "Netscape6/";
  if ((i = ua.indexOf(s)) >= 0) {
    this.isNS = true;
    this.version = parseFloat(ua.substr(i + s.length));
    return;
  }

  // Treat any other "Gecko" browser as NS 6.1.

  s = "Gecko";
  if ((i = ua.indexOf(s)) >= 0) {
    this.isNS = true;
    this.version = 6.1;
    return;
  }
  
  //Let's just lie and pretend opera is ie
  s = "Opera";
  if ((i = ua.indexOf(s)) >= 0) {
    this.isIE = true;
    this.version = 6.1;
    return;
  }
}

var browser = new Browser();

// Global object to hold drag information.

var dragObj = new Object();
dragObj.zIndex = 0;

function dragStart(event, id) {

  var el;
  var x, y;

  // If an element id was given, find it. Otherwise use the element being
  // clicked on.

  if (id)
    dragObj.elNode = document.getElementById(id);
  else {
    if (browser.isIE)
      dragObj.elNode = window.event.srcElement;
    if (browser.isNS)
      dragObj.elNode = event.target;

    // If this is a text node, use its parent element.

    if (dragObj.elNode.nodeType == 3)
      dragObj.elNode = dragObj.elNode.parentNode;
  }

  // Get cursor position with respect to the page.

  if (browser.isIE) {
    x = window.event.clientX + document.documentElement.scrollLeft
      + document.body.scrollLeft;
    y = window.event.clientY + document.documentElement.scrollTop
      + document.body.scrollTop;
  }
  if (browser.isNS) {
    x = event.clientX + window.scrollX;
    y = event.clientY + window.scrollY;
  }

  // Save starting positions of cursor and element.

  dragObj.cursorStartX = x;
  dragObj.cursorStartY = y;
  dragObj.elStartLeft  = parseInt(dragObj.elNode.style.left, 10);
  dragObj.elStartTop   = parseInt(dragObj.elNode.style.top,  10);

  if (isNaN(dragObj.elStartLeft)) dragObj.elStartLeft = 0;
  if (isNaN(dragObj.elStartTop))  dragObj.elStartTop  = 0;

  // Update element's z-index.

  dragObj.elNode.style.zIndex = ++dragObj.zIndex;

  // Capture mousemove and mouseup events on the page.

  if (browser.isIE) {
    document.attachEvent("onmousemove", dragGo);
    document.attachEvent("onmouseup",   dragStop);
    window.event.cancelBubble = true;
    window.event.returnValue = false;
  }
  if (browser.isNS) {
    document.addEventListener("mousemove", dragGo,   true);
    document.addEventListener("mouseup",   dragStop, true);
    event.preventDefault();
  }
}

function dragGo(event) {

  var x, y;

  // Get cursor position with respect to the page.

  if (browser.isIE) {
    x = window.event.clientX + document.documentElement.scrollLeft
      + document.body.scrollLeft;
    y = window.event.clientY + document.documentElement.scrollTop
      + document.body.scrollTop;
  }
  if (browser.isNS) {
    x = event.clientX + window.scrollX;
    y = event.clientY + window.scrollY;
  }

  // Move drag element by the same amount the cursor has moved.

  dragObj.elNode.style.left = (dragObj.elStartLeft + x - dragObj.cursorStartX) + "px";
  dragObj.elNode.style.top  = (dragObj.elStartTop  + y - dragObj.cursorStartY) + "px";

  if (browser.isIE) {
    window.event.cancelBubble = true;
    window.event.returnValue = false;
  }
  if (browser.isNS)
    event.preventDefault();
}

function dragStop(event) {

  // Stop capturing mousemove and mouseup events.

  if (browser.isIE) {
    document.detachEvent("onmousemove", dragGo);
    document.detachEvent("onmouseup",   dragStop);
  }
  if (browser.isNS) {
    document.removeEventListener("mousemove", dragGo,   true);
    document.removeEventListener("mouseup",   dragStop, true);
  }
}