// $Id: tabs.js,v 1.8 2006/12/16 02:42:33 mikeg Exp $


function TabClass()
{
}

var TabClass_prototype_register_tryagain = new Object;

// initially register tabs and call callback() when done registering
TabClass.prototype.register = function (button_id, content_id, callback)
{
  //alert("registering tabs with " + button_id + " and " + content_id + " and callback " + new String(callback));
  // a unique ID of this set of arguments
  var key = button_id+ "_" + content_id;

  this.button_id = button_id;
  this.content_id = content_id;

  this.button_container = el(button_id);
  this.content_container = el(content_id);

  if (!this.button_container || !this.content_container) // these containers don't yet exist...
  {
    // if the key is not in puthtml_tryagain, then add it
    if (!(key in TabClass_prototype_register_tryagain))
    {
      TabClass_prototype_register_tryagain[key] = {counter:5};
    }
    
    if (TabClass_prototype_register_tryagain[key].counter > 0)
    {
      TabClass_prototype_register_tryagain[key].counter-=1;
      //alert("TabClass_prototype_register_tryagain key=" + key + ", " + TabClass_prototype_register_tryagain[key].counter + " times left");
      var call_this = function() { Tab.register(button_id, content_id); }
      setTimeout(call_this, 1000);
    }
    else
    {
      //alert("TabClass failed for key=" + key);
      delete(TabClass_prototype_register_tryagain["key"]);
    }
    return;
  }

  // if the request can finally be satisfied, then clear it from the queue.
  if (key in TabClass_prototype_register_tryagain)
  {
    delete(TabClass_prototype_register_tryagain[key]);
  }

  this.focused = null;  // will be the tab name of the currently focused tab

  this.tab_order = new Array(); // will be the list of tab names in the order they appear on the page
  
  this.tabs = new Object();

  // collect existing buttons
  if (this.button_container)
  {
    for (var i=0; i<this.button_container.childNodes.length; i++)
    {
      // fetch element
      var e = this.button_container.childNodes[i];
      if (e.nodeName=="SPAN" && e.getAttribute && e.getAttribute("name") != null)
      {
        this.tabs[e.getAttribute("name")] = new Object();
        this.tabs[e.getAttribute("name")].button = e;
        this.tab_order.push(e.getAttribute("name"));
      }
    }
  }
    
  // collect corresponding content areas
  if (this.content_container)
  {
    for (var i=0; i<this.content_container.childNodes.length; i++)
    {
      // fetch element
      var e = this.content_container.childNodes[i];
      if (e.nodeName=="DIV" && e.getAttribute && e.getAttribute("name") != null)
      {
        this.tabs[e.getAttribute("name")].content = e;
      }
    }
  }

  if (callback)
  {
    callback();
  }
}

// true or false if tab_name exists
TabClass.prototype.exists = function(tab_name)
{
  if (this.tabs[tab_name]==undefined)
  {
    return false;
  }
  else
  {
    return true;
  }
}


// set the tab's button
TabClass.prototype.set_button = function(tab_name, title_html)
{
  if (tab_name in this.tabs)
  {
    if (title_html != this.tabs[tab_name].button.innerHTML) // this avoids needless flickering
    {
      this.tabs[tab_name].button.innerHTML = title_html + " <img src='/s/images/close.gif' title='Close' onclick=\"Tab.destroy('" + tab_name + "')\" />";
    }
    title_html = title_html.replace(/\<.*?\>/g, "");
    this.tabs[tab_name].button.setAttribute("title", title_html);
  }
}

// focus on a specific tab
TabClass.prototype.focus = function(tab_name)
{
  for (var t in this.tabs)
  {
    this.tabs[t].button.setAttribute("class","tab");
    this.tabs[t].button.setAttribute("className","tab"); // for IE6
    //this.tabs[t].content.style.display="none"; // Why does this not work?
    el(this.tabs[t].content.id).style.display="none";
  }
  if (tab_name in this.tabs)
  {
    this.tabs[tab_name].button.setAttribute("class","tab tab_focus");
    this.tabs[tab_name].button.setAttribute("className","tab tab_focus"); // for IE6
    //this.tabs[tab_name].content.style.display="block"; // Why does this not work?
    el(this.tabs[tab_name].content.id).style.display="block";
  }
  else if (tab_name != null)
  {
    alert("Cannot find " + tab_name);
    return;
  }
  this.focused = tab_name;
}

// append a new tab to the existing ones, focusing on it if a tab is not focused on
TabClass.prototype.append = function(tab_name, button_html, content_html)
{
  if (!content_html) { content_html = "Loading..."; }
  // if this tab doesn't exist yet..
  if (! (tab_name in this.tabs) )
  {
    var newtab = document.createElement("span");
    newtab.setAttribute("name",tab_name);
    newtab.setAttribute("class","tab");
    newtab.setAttribute("className","tab"); // for IE6
    var onclicktext = "Tab.focus('" + tab_name + "');";
    newtab.setAttribute("onclick", onclicktext);
    newtab.onclick = function() { eval(onclicktext); }; // for IE6
    newtab.id = "tab_button_" + tab_name;
    newtab.innerHTML = button_html;
  
    var newcont = document.createElement("div");
    newcont.setAttribute("name",tab_name);
    newcont.setAttribute("class","tab_content");
    newcont.style.display="none";
    newcont.id = "tab_content_" + tab_name;
    newcont.innerHTML = content_html;

    this.button_container.appendChild(newtab);
    this.content_container.appendChild(newcont);

    this.tabs[tab_name] = new Object();
    this.tabs[tab_name].button = el(newtab.id);  // newtab;
    this.tabs[tab_name].content = el(newcont.id); //newcont;

    // alert("0. (this.tabs[${tab_name}].content == el(${id})) is:".process({tab_name:tab_name, id:newcont.id}) + (this.tabs[tab_name].content == el(newcont.id)));

    // alert("1. button parent set: " + (this.button_container == newtab.parentNode));
    // alert("2. button parent set: " + (this.button_container == Tab.tabs[tab_name].button.parentNode));

    // alert("1. content parent set: " + (this.content_container == newcont.parentNode));
    // alert("2. content parent set: " + (this.content_container == Tab.tabs[tab_name].content.parentNode));
 
    this.tab_order.push(tab_name);
 
    // and append this tab name to the session on the server for persistence
    var urls = [];
    urls.push({url:"/api/web/session?what=setvar&type=array&action=append&var=tabs&val="+tab_name});
    url_update(urls);
    
  }

  //if (this.focused == null)
  //{
    this.focus(tab_name);
  //}
}

// destroy a tab 
TabClass.prototype.destroy = function(tab_name)
{
  //alert("destroying tab " + tab_name);
  // find the tab we have to remove
  var tab_position = this.tab_order.indexOf(tab_name);

  // first, focus on another tab if necessary and possible
  if (this.focused == tab_name && this.tab_order.length>0)
  {
    if (this.tab_order.length==1)
    {
      //alert("no tabs to focus on");
      // do nothing, there will be no tab to focus on after this anyways...
      Tab.focus(null);
    }
    else
    {
      if (tab_position == 0) // deleting a tab at the beginning
      {
        //alert("focusing tab at beginning");
        // focus on the tab immediately following the one to be deleted 
        this.focus(this.tab_order[tab_position+1]);
      }
      else if (tab_position>0) // otherwise
      {
        //alert("focusing on tab preceding target");
        // focus on the tab immediately preceding the one to be deleted 
        this.focus(this.tab_order[tab_position-1]);
      }
    }
  }

  // remove the button and content elements from the page
  this.button_container.removeChild(this.tabs[tab_name].button);
  this.content_container.removeChild(this.tabs[tab_name].content);

  // delete the tab from the Tab list..
  delete this.tabs[tab_name]
  this.tab_order.remove(tab_position);

  // and remove this tab name from the session on the server for persistence
  var urls = [];
  urls.push({url:"/api/web/session?what=setvar&type=array&action=remove&var=tabs&val="+tab_name});
  url_update(urls);
}

// return the number of tabs
TabClass.prototype.length = function()
{
  return this.tab_order.length;
}

var Tab = new TabClass();
