/**
 i18n string used when an error comes back from the login servlet, used in an alert box
*/
var loginFailureError="Invalid username or password";

/**
 i18n string used for when a successful login occurs and an action is required, but the
 function doesn't know how to deal with that action, it pops up an alert box with this
 string in it, shouldn't really ever happen, unless some code fails
*/
var loginSuccess = "You are now logged in";

/**
 i18n string used to asking the user to login, used in an alert box.
*/
var loginPrompt = "Please log in";

// MyListMenu

/**
 i18n strings for the MyListMenu, text for the add to button
*/
var MyListMenuAddToText = "Add To:";

/**
 i18n strings for the MyListMenu, text for the Create New List button in the meny
*/
var MyListMenuCreateNewListText = "Create New List";

/**
 i18n strings for the MyListMenu, text for the Cancel Button in the menu
*/
var MyListCancelText = "Cancel";

/**
 i18n strings for the MyListMenu, text for the Temporary List label
*/
var tempListName = "Temporary List";

var tempList = 'tempList';

function sessionTimedOut(url){
   window.location = url;
}

/**
sets a timer to refresh the page with the session times out
@param timeOut is in minutes, need to convert to milliseconds
*/
function setSessionTimeout(timeOut,url){
    var to = timeOut*60*1000;
    setTimeout("sessionTimedOut('" + url +"')",to);
}

function createLanguageOptions(allLocales, currentLocale)
{
    var languageSelect = document.languageSelect.languageSelectDropDown;
    var localesArray = splitAllLocales(allLocales);
    for (i in localesArray){
        var optionValue = "?uP_locales=" +getLocaleCode(localesArray[i])+ "&uP_reload_layout=true&uP_tparam=locale&locale=" +getLocaleCode(localesArray[i]);
        optionValue = addRtlParams(localesArray[i], optionValue);
        var option = new Option(getLocaleDisplayName(localesArray[i]), optionValue);
        languageSelect.options[i] = option;
        if (getLocaleCode(localesArray[i]) === currentLocale){
            option.selected = true;
        }
    }
}

function addRtlParams(locale, optionValue)
{
    var localeCode = getLocaleCode(locale);
    var language = localeCode.split("_")[0];
    if (language == null){
        language = localeCode;
    }
    for (x in rtlLanguages)
    {
        var lang = rtlLanguages[x];
        if (language === lang){
            return optionValue + "&uP_tparam=RTL&RTL=true";
        }
        else{
            return optionValue + "&uP_tparam=RTL&RTL=false";
        }
    }
}

var rtlLanguages = new Array("ar", "he");

function splitAllLocales(allLocales){
    return allLocales.split(",");
}

function getLocaleCode(locale){
    return locale.split(":")[0];
}

function getLocaleDisplayName(locale){
    return locale.split(":")[1];
}

function getMyLists(){
    var action = "getMyLists";
    var postData = new PostData();
    postData.append("action",action);
    //var url = "/uPortal/PassThrough/mylist";
    var url = "/liferay/PassThrough/mylist";
    var reqObj = getHttpObject();
    reqObj.open("POST",url,false);
    reqObj.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
    getMyListsCompletionHandler(reqObj.send(postData.get()));
}

function getMyListsCompletionHandler(data){
    var resultObj = null;
    try{
        resultObj = eval('(' + data + ')');
    }
    catch(err){
       resultObj = {"error":true,"result":null};
    }
    if (resultObj["error"] == false){
        error = false;
        try{
            //check to see that myList is initialized
            var x = myList.length;
        }
        catch(err){
            error = true;
        }
        if (error == false){
            var myLists = resultObj["myLists"];
            for (key in myLists){
                myList.add(key, myLists[key]);
            }
        }
    }
}

function promptForLogin(ev,action){
  if (arguments.length <3){
    PromptUser = true;
  }
  else{
      PromptUser = arguments[2];
  }
  if(authenticated == false){
      if(PromptUser == true){
         if (confirm(loginPrompt)){
             Login();
         }
      }
      else{
         Login();
      }

      if (ev) {
         if (ev.stopPropagation){
		    ev.stopPropagation();
		  }
		  else{
		     ev.cancelBubble = true;
		  }
	  }

  }
  else{
    window.location = action;
  }

}

function Login(){
    document.loginForm.submit();
}

/**
Form object
*/
function Form(){}

/**
*/
Form.prototype.init = function(form){
  this.form = form;
  this.extraPostData = new Array();
}

Form.prototype.getPostData = function(form){
  var children = this.form.childNodes;

  var pd = new PostData();

  for(var i=0;i<this.extraPostData.length;i++){
     pd.append(this.extraPostData[i][0],this.extraPostData[i][1]);
  }
  for(var i=0;i<children.length;i++){
    if(children[i].nodeType==1){
       if (children[i].nodeName == "INPUT"){
         switch(children[i].type){
         case "text":
              pd.append(children[i].name,children[i].value);
              break;
         case "password":
              pd.append(children[i].name,children[i].value);
              break;
         }

       }
    }
  }
  return pd.get()
}

Form.prototype.getAction = function(form){
  return this.form.action
}

Form.prototype.getMethod = function(form){
  return this.form.method
}

Form.prototype.appendPostData = function(name,value){
   this.extraPostData.push([name,value]);

}

function $ (id) {
    return findObject(id, false);
}

function $$(id)
{
    return findObject(id, true);
}

/**
 * obj the object to find
 * returnAll return the first record or all records found, else return the first record found.
 * Could add finding of all objects with id and name, and add id to name if returnAll is true.
 * Finds in the order of object, name, id.
 */
function findObject(obj, returnAll)
{
    if(isTypeObject(obj))
    {
        return obj;
    }

    //search for name then id (return all records)
    if(returnAll)
    {
        var retObj=findObjectByName(obj, returnAll);
        if(isTypeObject(retObj))
        {
            return retObj;
        }

        var retObj=findObjectById(obj);
        if(isTypeObject(retObj))
        {
            return retObj;
        }
    }
    //search for id then name (return one record)
    else
    {
        var retObj=findObjectById(obj);
        if(isTypeObject(retObj))
        {
            return retObj;
        }

        var retObj=findObjectByName(obj, returnAll);
        if(isTypeObject(retObj))
        {
            return retObj;
        }
    }

    return undefined;
}

function findObjectById(objectId)
{
    return document.getElementById(objectId);

}

function findObjectByName(objectName, returnAll)
{
    var retObj=document.getElementsByName(objectName);
    if(retObj==null||retObj==undefined)
    {
        return undefined;
    }
    else
    {
        if(returnAll)
        {
            return retObj;
        }
        else
        {
            for(var i=0; i< retObj.length; i++)
            {
                return retObj[i];//return first record found.
            }
        }
    }
}

function isTypeObject(obj)
{
    if(obj!=null&&obj!=undefined && (typeof obj == "object"))
    {
        return true;
    }
    return false;
}

function create (type, id, className) {
	var e = document.createElement(type);
	e.id = id;
	e.className = className;
	return e;
}

function getObject(id, selectAll)
{
    var ee;
    if(selectAll==undefined || selectAll==null  || !selectAll)
    {
        ee=id;
        if(ee==undefined)
        {
            ee = $(id);
        }
    }
    else
    {
        ee=$$(id.id);
    }
    if(ee!=undefined)
    {
        if(ee.length==undefined)
        {
            return new Array(ee);
        }
    }
    return ee;
}


function addClass (id, className) {
    try
    {
        var e=findParent(id, id);
        if (!e.className || e.className.indexOf(className) == -1)
        {
           if (e.className)
           {
               e.className += " " + className;
           }
           else
           {
               e.className = className;
           }
        }
   }
   catch(err){
       //catches and swallows all errors right now
       //alert(err);
   }
}


function removeClass (id, className) {
	try
    {
        var e=findParent(id, id);
        if (e.className)
        {
            e.className = e.className.replace(className, '');
        }
    }
    catch(err)
    {
       //catches and swallows all errors right now
       //alert("error:" + err);
    }
}


function stopPropagation (ev) {
	if (ev) {
		if (ev.stopPropagation) ev.stopPropagation();
		else ev.cancelBubble = true;
	}
}

/**
Takes a string and returns the string without the leading and trailing white spaces
@param sInString a string
@return <string> a string without the leading and trailing white spaces
*/
function trimString(sInString) {
    sInString = sInString.replace( /^\s+/g, "" );// strip leading
    return sInString.replace( /\s+$/g, "" );// strip trailing
}



/**
Hides an element, sets the elements
style attributes visibility=hidden and block=none
@param element refrence to an html element
@return none
*/
function hideElement(element){
    element.style.visibility = "hidden";
    element.style.display = "none";
}

/**
Show an element, sets the elements
style attributes visibility=visible and block=block
@param element refrence to an html element
@return none
*/
function showElement(element){
    element.style.visibility = "visible";
    element.style.display = "block";
}


/* Dynamic Menus */

/**
a global variable that is used to loop through all menus on the page,
all menus are added to this array when the init method of the menu is called
*/
var allMenus = new Array();


/**
creats a js object to hook up to an html element, puts the menus in
the AllMenus array for the page
@param name string, name is used to find other elements like Button or Menu
@param inactiveCSS string, the class to use when the menu is inactive
@param activeCSS string, the class to use when the menu is active
@param focusFeild html element, this is an optional parameter, if set, this will
  be the input field that will get focus when the menu opens
*/
function Menu (name, inactiveCSS, activeCSS, focusField) {
	//if arguments are passed in, call init() now
	if (arguments.length > 0) this.init(name, inactiveCSS, activeCSS, focusField);
}

/**
creates a js object that hooks up to an html element. When the menu is created,
it is put in the AllMenus array for the page
@param name string, name is used to find other elements like Button or Menu
@param inactiveCSS string, the class to use when the menu is inactive
@param activeCSS string, the class to use when the menu is active
@param focusFeild html element, this is an optional parameter, if set, this will
  be the input field that will get focus when the menu opens
*/
Menu.prototype.init = function (name, inactiveCSS, activeCSS, focusField) {
	this.name = name;
	this.buttonDiv = $(name + "Button");
	this.contentDiv = $(name + "Menu");
	this.focusField = focusField;
	this.isOpen = false;
	this.index = allMenus.length;
	this.activeCSS = activeCSS;
	this.inactiveCSS = inactiveCSS;

	this.buttonDiv.onclick = new Function(
		"allMenus[" + this.index + "].toggle();" +
		"stopPropagation(arguments[0] || window.event);"
	);

	this.contentDiv.onclick = new Function(
		"stopPropagation(arguments[0] || window.event);"
	);

	allMenus.push(this);
}






/**
toggles the menu.  If the menu is opened, it will close it, if closed it will open it
*/
Menu.prototype.toggle = function () {
	if (this.isOpen) {
		this.buttonDiv.className = this.buttonDiv.className.replace(this.activeCSS, this.inactiveCSS);
		this.contentDiv.style.display = "none";
		this.isOpen = false;
	}
	else {
		this.buttonDiv.className = this.buttonDiv.className.replace(this.inactiveCSS, this.activeCSS);
		dismissAllMenus();
		this.contentDiv.style.display = "block";
		this.setFocus();
		this.isOpen = true;

	}
}
Menu.prototype.setFocus = function(){
    if (this.focusField){
        var element = null;
      	try{
      	    var element = eval(this.focusField);
      	}
      	catch(err){
      	   element = null;
      	}
      	if (element != null){
            element.focus();
            var v = element.value;
            if (v.length > 0){
                element.select();
            }
      	}
  	}
}

/**
Closes the menu if it is open
*/
Menu.prototype.close = function(){
    if (this.isOpen){
        this.toggle();
    }
}

/**
Opens the menu if it is closed
*/
Menu.prototype.open = function(){
    if (!this.isOpen){
        this.toggle();
    }
}

/**
function used to closed all opened menus that are open
*/
function dismissAllMenus () {
	for (var i=0; i < allMenus.length; i++) {
		if (allMenus[i].isOpen) allMenus[i].toggle();
	}
}


/* Dynamic "folding" sections */
/**
a global array that holds all fold objects on the page, All Fold
objects are added to the array when the init method is called on the Fold
object
*/
var allFolds = new Array();


/**
a js object that is hooked up to an html element, things really happen
in the init, this takes the same arguments for backwards compatibility
@param name string, the name is used to find elements Button and Content
@param html element, an option parameter, if set when the Fold opens
  that element will get focus
*/
function Fold (name, focusField) {
	//if arguments are passed in, call init() now
	if (arguments.length > 0) this.init(name, focusField);
}

/**
creates an js object that is hooked up to an html element
@param name string, the name is used to find elements Button and Content
@param html element, an option parameter, if set when the Fold opens
  that element will get focus
*/
Fold.prototype.init = function (name, focusField) {
	this.name = name;
	this.buttonDiv = $(name + "Button");
	this.contentDiv = $(name + "Content");
	this.focusField = focusField;
	this.isOpen = (this.contentDiv.className.indexOf("hidden") == -1) ? true : false;
	this.index = allFolds.length;
	this.activeCSS = "openFold";
	this.inactiveCSS = "fold";

	if (this.isOpen) {
		this.buttonDiv.innerHTML += " " + clickToHide;
		this.contentDiv.style.display = "block";
	}
	else {
		this.buttonDiv.innerHTML += " " + clickToShow;
		this.contentDiv.style.display = "none";
	}

	this.buttonDiv.onclick = new Function(
		"allFolds[" + this.index + "].toggle();" +
		"stopPropagation(arguments[0] || window.event);"
	);

	this.contentDiv.onclick = new Function(
		"stopPropagation(arguments[0] || window.event);"
	);

	allFolds.push(this);
}

/**
toggles the Fold, if opened will close it, if closed will open it
*/
Fold.prototype.toggle = function () {
	if (this.isOpen) {
		this.buttonDiv.innerHTML = this.buttonDiv.innerHTML.replace(clickToHide, clickToShow);
		this.buttonDiv.className = this.buttonDiv.className.replace(this.activeCSS, this.inactiveCSS);
		this.contentDiv.style.display = "none";
		this.contentDiv.style.visibility = "hidden";
		this.isOpen = false;
	}
	else {
		this.buttonDiv.innerHTML = this.buttonDiv.innerHTML.replace(clickToShow, clickToHide);
		this.buttonDiv.className = this.buttonDiv.className.replace(this.inactiveCSS, this.activeCSS);
		this.contentDiv.style.display = "block";
        this.contentDiv.style.visibility = "visible";
		if (this.focusField) eval(this.focusField + ".focus();" + this.focusField + ".select();");
		this.isOpen = true;
	}
};


/* If Internet Explorer 6, fix PNG images to use alpha transparency correctly */


if (navigator.appVersion.indexOf("MSIE") > -1 && document.all) {
	var appVer = navigator.appVersion;
	var ver = parseFloat(appVer.substring(appVer.indexOf("MSIE") + 5, appVer.indexOf(";", appVer.indexOf("MSIE") + 5)));
	if (ver < 7) window.onload = function () {
	    try{
    		var divs = document.getElementsByTagName("div");
    		var Elements = new Array();

    		var imgs = document.getElementsByTagName("img");
    		for (var i=0;i<imgs.length;i++){
    		   if (imgs[i].src.indexOf(".png") >-1){
    		       Elements.push(imgs[i]);
    		   }
    		}

    		for (var i=0; i < divs.length; i++) {
    			if (divs[i].currentStyle.backgroundImage.indexOf(".png") > -1) {
    				Elements.push(divs[i]);
    			}
    		}
    		fixPNG(Elements);
		}
		catch(err){
            // This just swallows the error
		}
		// After the images are fixed display all the delayed messages
        displayDelayedMessages();
	};
}
else{

  // After the images are fixed display all the delayed messages
  window.onload = function (){displayDelayedMessages();}
}

var delayedMessages = new Array();

function displayDelayedMessages(){
   for(var i=0;i<delayedMessages.length;i++){
      alert(delayedMessages[i]);
   }
   delayedMessages = new Array();
}

function addDelayedMessage(msg){
   delayedMessages.push(msg);
}
/**
Function to fix IE inability to display transparent pngs
@param elements, an array of elements to fix
*/
function fixPNG (Elements) {
	var e, bg, src, parent;

	for (var i=0; i < Elements.length; i++) {
		e = $(Elements[i]);
		img = null;
		bg = e.currentStyle.backgroundImage;

		if (bg == 'none') {
			parent = e.parentNode;
			parent.removeChild(e);
			src = e.src;
			img = e;
			e = parent;
		}
		else {
		    // taking of the url("..")
			src = bg.substring(5, bg.length-2)
		}

		if (src.indexOf('.png') > -1){
		    if(img != null){
			    // IE is wacked, I had to create this image object just to
			    // get the height and width
			    var s = img.src;
			    var img = new Image();
			    img.src = s;
			    e.style.height = img.height + "px";
                e.style.width = img.width + "px";
			}
			e.style.backgroundImage = "none";
			e.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + src + "',sizingMethod='image')";
		}
	}
}

/**
function to valid an email address
@param str, email address
@return boolen, true if it looks like a valid email address, false it does not
look like a valid email address
*/
function validEmail(str) {
    var at="@"
    var dot="."
    var lat=str.indexOf(at)
    var lstr=str.length
    var ldot=str.indexOf(dot)
    var rt = true;

    if (str.indexOf(at)==-1){
          rt= false
    }

    if (str.indexOf(at)==-1 || str.indexOf(at)==0 || str.indexOf(at)==lstr){
          rt = false
    }

    if (str.indexOf(dot)==-1 || str.indexOf(dot)==0 || str.indexOf(dot)==lstr){
          rt= false
    }

    if (str.indexOf(at,(lat+1))!=-1){
        rt= false
    }

    if (str.substring(lat-1,lat)==dot || str.substring(lat+1,lat+2)==dot){
        rt= false
    }

    if (str.indexOf(dot,(lat+2))==-1){
       rt= false
    }

    if (str.indexOf(" ")!=-1){
        rt= false
    }
    return rt
}



/**
 @function getQueryStringArgs
 returns an associative array of the query string arguments if any or  empty object
 @return associative array
 */
function getQueryStringArgs(){
  var args = new Object();
  var query_string = window.location.search.substring(1);
  var pairs = query_string.split("&");
  var name_value = null;
  for(x=0;x<pairs.length;x++){
    if (pairs[x].indexOf('=') != -1){
      name_value = pairs[x].split('=');
      var key = name_value[0];
      var value =decodeURIComponent(name_value[1]);
      if (args[key] == null){
          args[key] = new Array(value);
      }
      else{
      	  args[key].append(value)
      }
    }
  }
  return args;
}


/**
 Ultimate client-side JavaScript client sniff.
 (C) Netscape Communications 1999.  Permission granted to reuse and distribute.
 Revised 17 May 99 to add is.nav5up and is.ie5up (see below).

 Everything you always wanted to know about your JavaScript client
 but were afraid to ask ... "Is" is the constructor function for "is" object,
 which has properties indicating:<br>
 (1) browser vendor:<br>
     is.nav, is.ie, is.opera<br>
 (2) browser version number:<br>
     is.major (integer indicating major version number: 2, 3, 4 ...)<br>
     is.minor (float   indicating full  version number: 2.02, 3.01, 4.04 ...)<br>
 (3) browser vendor AND major version number<br>
     is.nav2, is.nav3, is.nav4, is.nav4up, is.ie3, is.ie4, is.ie4up, is.ie5, is.ie5up<br>
 (4) JavaScript version number:<br>
     is.js (float indicating full JavaScript version number: 1, 1.1, 1.2 ...)<br>
 (5) OS platform and version:<br>
     is.win, is.win16, is.win32, is.win31, is.win95, is.winnt, is.win98<br>
     is.os2<br>
     is.mac, is.mac68k, is.macppc<br>
     is.unix<br>
        is.sun, is.sun4, is.sun5, is.suni86<br>
        is.irix, is.irix5, is.irix6<br>
        is.hpux, is.hpux9, is.hpux10<br>
        is.aix, is.aix1, is.aix2, is.aix3, is.aix4<br>
        is.linux, is.sco, is.unixware, is.mpras, is.reliant<br>
        is.dec, is.sinix, is.freebsd, is.bsd<br>
     is.vms<br>

 See http://www.it97.de/JavaScript/JS_tutorial/bstat/navobj.html and
 http://www.it97.de/JavaScript/JS_tutorial/bstat/Browseraol.html
 for detailed lists of userAgent strings.<br>
<br>
 Note: you don't want your Nav4 or IE4 code to "turn off" or
 stop working when Nav5 and IE5 (or later) are released, so
 in conditional code forks, use is.nav4up ("Nav4 or greater")
 and is.ie4up ("IE4 or greater") instead of is.nav4 or is.ie4
 to check version in code which you want to work on future
 versions.
 */
function Is ()
{   // convert all characters to lowercase to simplify testing
    var agt=navigator.userAgent.toLowerCase();

    // *** BROWSER VERSION ***
    // Note: On IE5, these return 4, so use is.ie5up to detect IE5.
    this.major = parseInt(navigator.appVersion);
    this.minor = parseFloat(navigator.appVersion);

    this.nav  = ((agt.indexOf('mozilla')!=-1) && (agt.indexOf('spoofer')==-1)
                && (agt.indexOf('compatible') == -1) && (agt.indexOf('opera')==-1)
                && (agt.indexOf('webtv')==-1));
    this.nav2 = (this.nav && (this.major == 2));
    this.nav3 = (this.nav && (this.major == 3));
    this.nav4 = (this.nav && (this.major == 4));
    this.nav4up = (this.nav && (this.major >= 4));
    this.navonly      = (this.nav && ((agt.indexOf(";nav") != -1) ||
                          (agt.indexOf("; nav") != -1)) );
    this.nav5 = (this.nav && (this.major == 5));
    this.nav5up = (this.nav && (this.major >= 5));

    this.ie   = (agt.indexOf("msie") != -1);
    this.ie3  = (this.ie && (this.major < 4));
    this.ie4  = (this.ie && (this.major == 4) && (agt.indexOf("msie 5.0")==-1) );
    this.ie4up  = (this.ie  && (this.major >= 4));
    this.ie5  = (this.ie && (this.major == 4) && (agt.indexOf("msie 5.0")!=-1) );
    this.ie5up  = (this.ie  && !this.ie3 && !this.ie4);

    // KNOWN BUG: On AOL4, returns false if IE3 is embedded browser
    // or if this is the first browser window opened.  Thus the
    // properties is.aol, is.aol3, and is.aol4 aren't 100% reliable.
    this.aol   = (agt.indexOf("aol") != -1);
    this.aol3  = (this.aol && this.ie3);
    this.aol4  = (this.aol && this.ie4);

    this.opera = (agt.indexOf("opera") != -1);
    this.webtv = (agt.indexOf("webtv") != -1);

    // *** JAVASCRIPT VERSION CHECK ***
    if (this.nav2 || this.ie3) this.js = 1.0
    else if (this.nav3 || this.opera) this.js = 1.1
    else if ((this.nav4 && (this.minor <= 4.05)) || this.ie4) this.js = 1.2
    else if ((this.nav4 && (this.minor > 4.05)) || this.ie5) this.js = 1.3
    else if (this.nav5) this.js = 1.4
    // NOTE: In the future, update this code when newer versions of JS
    // are released. For now, we try to provide some upward compatibility
    // so that future versions of Nav and IE will show they are at
    // *least* JS 1.x capable. Always check for JS version compatibility
    // with > or >=.
    else if (this.nav && (this.major > 5)) this.js = 1.4
    else if (this.ie && (this.major > 5)) this.js = 1.3
    // HACK: no idea for other browsers; always check for JS version with > or >=
    else this.js = 0.0;

    // *** PLATFORM ***
    this.win   = ( (agt.indexOf("win")!=-1) || (agt.indexOf("16bit")!=-1) );
    // NOTE: On Opera 3.0, the userAgent string includes "Windows 95/NT4" on all
    //        Win32, so you can't distinguish between Win95 and WinNT.
    this.win95 = ((agt.indexOf("win95")!=-1) || (agt.indexOf("windows 95")!=-1));

    // is this a 16 bit compiled version?
    this.win16 = ((agt.indexOf("win16")!=-1) ||
                  (agt.indexOf("16bit")!=-1) || (agt.indexOf("windows 3.1")!=-1) ||
                  (agt.indexOf("windows 16-bit")!=-1) );

    this.win31 = ((agt.indexOf("windows 3.1")!=-1) || (agt.indexOf("win16")!=-1) ||
                  (agt.indexOf("windows 16-bit")!=-1));

    // NOTE: Reliable detection of Win98 may not be possible. It appears that:
    //       - On Nav 4.x and before you'll get plain "Windows" in userAgent.
    //       - On Mercury client, the 32-bit version will return "Win98", but
    //         the 16-bit version running on Win98 will still return "Win95".
    this.win98 = ((agt.indexOf("win98")!=-1) || (agt.indexOf("windows 98")!=-1));
    this.winnt = ((agt.indexOf("winnt")!=-1) || (agt.indexOf("windows nt")!=-1));
    this.win32 = ( this.win95 || this.winnt || this.win98 ||
                   ((this.major >= 4) && (navigator.platform == "Win32")) ||
                   (agt.indexOf("win32")!=-1) || (agt.indexOf("32bit")!=-1) );

    this.os2   = ((agt.indexOf("os/2")!=-1) ||
                  (navigator.appVersion.indexOf("OS/2")!=-1) ||
                  (agt.indexOf("ibm-webexplorer")!=-1));

    this.mac    = (agt.indexOf("mac")!=-1);
    this.mac68k = (this.mac && ((agt.indexOf("68k")!=-1) ||
                               (agt.indexOf("68000")!=-1)));
    this.macppc = (this.mac && ((agt.indexOf("ppc")!=-1) ||
                               (agt.indexOf("powerpc")!=-1)));

    this.sun   = (agt.indexOf("sunos")!=-1);
    this.sun4  = (agt.indexOf("sunos 4")!=-1);
    this.sun5  = (agt.indexOf("sunos 5")!=-1);
    this.suni86= (this.sun && (agt.indexOf("i86")!=-1));
    this.irix  = (agt.indexOf("irix") !=-1);    // SGI
    this.irix5 = (agt.indexOf("irix 5") !=-1);
    this.irix6 = ((agt.indexOf("irix 6") !=-1) || (agt.indexOf("irix6") !=-1));
    this.hpux  = (agt.indexOf("hp-ux")!=-1);
    this.hpux9 = (this.hpux && (agt.indexOf("09.")!=-1));
    this.hpux10= (this.hpux && (agt.indexOf("10.")!=-1));
    this.aix   = (agt.indexOf("aix") !=-1);      // IBM
    this.aix1  = (agt.indexOf("aix 1") !=-1);
    this.aix2  = (agt.indexOf("aix 2") !=-1);
    this.aix3  = (agt.indexOf("aix 3") !=-1);
    this.aix4  = (agt.indexOf("aix 4") !=-1);
    this.linux = (agt.indexOf("inux")!=-1);
    this.sco   = (agt.indexOf("sco")!=-1) || (agt.indexOf("unix_sv")!=-1);
    this.unixware = (agt.indexOf("unix_system_v")!=-1);
    this.mpras    = (agt.indexOf("ncr")!=-1);
    this.reliant  = (agt.indexOf("reliantunix")!=-1);
    this.dec   = ((agt.indexOf("dec")!=-1) || (agt.indexOf("osf1")!=-1) ||
         (agt.indexOf("dec_alpha")!=-1) || (agt.indexOf("alphaserver")!=-1) ||
         (agt.indexOf("ultrix")!=-1) || (agt.indexOf("alphastation")!=-1));
    this.sinix = (agt.indexOf("sinix")!=-1);
    this.freebsd = (agt.indexOf("freebsd")!=-1);
    this.bsd = (agt.indexOf("bsd")!=-1);
    this.unix  = ((agt.indexOf("x11")!=-1) || this.sun || this.irix || this.hpux ||
                 this.sco ||this.unixware || this.mpras || this.reliant ||
                 this.dec || this.sinix || this.aix || this.linux || this.bsd ||
                 this.freebsd);
    this.vms   = ((agt.indexOf("vax")!=-1) || (agt.indexOf("openvms")!=-1));
    this.ce = document.captureEvents && document.releaseEvents;
}


function getXmlHttpPrefix() {

    if (getXmlHttpPrefix.prefix)
        return getXmlHttpPrefix.prefix;
    var prefixes = ["MSXML4.XmlHttp","MSXML3.XmlHttp",
                    "MSXML2.XmlHttp","MSXML.XmlHttp","Microsoft.XmlHttp" ];
    var o;
    for (var i = 0; i < prefixes.length; i++) {
        try {
            // try to create the objects
            o = new ActiveXObject(prefixes[i]);
            return getXmlHttpPrefix.prefix = prefixes[i];
        }
        catch (ex) {
        }
    }
    throw new ENoActiveX("Could not find the Active X control");
}


// Used for testing
function FakeJSHttpRequest(){
   this.readyState = 4;
   this.status = 200;
   this.headers = new Array();

}


FakeJSHttpRequest.prototype.open = function(method,url,async){
   this.method= method;
   this.url = url;
   this.async = async;

}

FakeJSHttpRequest.prototype.setRequestHeader = function(header,value){
   this.headers.push({header:value});

}

FakeJSHttpRequest.prototype.send = function(postData){
   this.onreadystatechange();
}



function FakeHttpRequest(){}

FakeHttpRequest.prototype = new HttpRequest;
FakeHttpRequest.prototype.constructor = FakeHttpRequest;

FakeHttpRequest.prototype.init = function(){

  this.reqObj = new FakeJSHttpRequest();
}

/**
An HttpXMLrequest wrapper class
*/
function HttpRequest(){
   this.reqObj = null;
}

/**
creates the internal request object
*/
HttpRequest.prototype.init = function(){
    var is = new Is();
    this.async = true;
    if (is.ie){
        this.reqObj = new ActiveXObject(getXmlHttpPrefix());
    }
    else{
        this.reqObj = new XMLHttpRequest();
    }
}

/**
  This is the function that gets called when the request is going through
  it's different states.  When readyState == 4 and status ==200 the
  completionHandler is called.  You NEED to set the completion handler
  to a function.
  readyStates:
 0-UNINITIALIZED
     The object has been created, but not initialized (open method has not been called.
 1-LOADING
    The object has been created, but the send method has not been called.
 2-LOADED
    The send method has been called and the status and headers are available,
    but the response is not yet available.
 3-INTERACTIVE
    Some data has been received. You can call responseBody and responseText.
    to get the current partial results.
 4-COMPLETED
   All the data has been received, and the complete data is available in
   responseBody and responseText.
 NOTE: we might be able to tell if the server is down if we never get
 an INTERACTIVE status!  There would have to be some sort of time out
*/
HttpRequest.prototype.readyStateChange = function(){

    if(this.reqObj.readyState == 4){
        if (this.reqObj.status == 200){
            this.completionHandler.call(this,this.reqObj.responseText);
        }
        else if(this.reqObj.status == 500){
            //The handler is expecting a JSON string
            this.completionHandler.call(this,'{"error":true}');
        }
        else{
            this.completionHandler.call(this,'{"error":true}');
        }
    }
}

/**
Opens the Http connection
@param method - POST, GET, etc..
@param url - the url, NOTE: can only go to a URL from the same hostname
@param async - boolean value to indicate async or not (I have NOT tested for non-async yet)
*/
HttpRequest.prototype.open = function(method,url,async){
  this.async = async;
  this.reqObj.open(method,url,async);
}

/**
You can set a request header
@param header - header you would like to set
@param value - the value for that header
*/
HttpRequest.prototype.setRequestHeader = function(header,value){
  this.reqObj.setRequestHeader(header,value);
}

/**
Send out the request
@param postData - string of postdata to send if any
*/
HttpRequest.prototype.send = function(postData){
    var postData = (postData)?postData:"";
    var data = null;
    if (this.async == false){
       this.reqObj.send(postData);
       data = this.reqObj.responseText;
    }
    else{
      this.reqObj.send(postData);
    }
    return data;
}

/**
Set the on onReadyStateChange function, if a function is
not passed in, it used  readyStateChange of this object
*/
HttpRequest.prototype.setOnReadyStateChange = function(func){
   var req = this;
   this.reqObj.onreadystatechange = function(){req.readyStateChange.call(req)};
}

function LoginRequest(){}

LoginRequest.prototype = new HttpRequest;
LoginRequest.prototype.constructor = LoginRequest;


LoginRequest.prototype.init = function(){
  HttpRequest.prototype.init.call(this);

  this.completionHandler = loginCompletionHandler;
}





/**
Returns an HTTP Request Object
@param test - used only in testing, will return an Fake Request Object
@return HttpRequest
*/
function getHttpObject(obj){
    if (arguments.length ==1){
      var req = new obj();
    }
    else{
      var req = new HttpRequest();
    }
    req.init()
    req.setOnReadyStateChange();
    return req
}

/**
Object used to create Post Data
*/
function PostData(){
  this.postData = [];
}

/**
append data to the object
@param name the name to use
@param value the value to use
*/
PostData.prototype.append = function(name,value){
   this.postData.push([name,value]);
}

/**
returns a string of Post Data that has been escaped
@return String
*/
PostData.prototype.get = function(){
   var postData = ""
   for(var i=0;i<this.postData.length;i++){
     if (i == 0){
         postData = escape(this.postData[i][0]) + "=" + escape(this.postData[i][1]);
     }
     else{
        postData = postData + "&" + escape(this.postData[i][0]) + "=" + escape(this.postData[i][1]);
     }
   }
   return postData
}

/**
@class  This js object links a menu on the toolbar
It is used to open, close the menu
@constructor
*/
function ToolbarMenu(){}


/**
The init method links the menu html to this js object
@param name the name of the menu, it is used to get other menu elements
@param activeCSS the class name to set the element to whe the list is active
@param focusField the input element that gets focus when the menu is active
@return null
*/
ToolbarMenu.prototype.init = function (name, activeCSS, focusField){
    this.name = name;
    this.buttonDiv = $(name + "Button");
    this.menuDiv = $(name + "Menu");
    this.menuForm = $(name + "Form");
    this.menuText = $(name + "Text");
    this.activeCSS = activeCSS;
    this.focusField = focusField;
    this.isOpen = false;
    this.index = allMenus.length;
    this.buttonDiv.onclick = new Function(
        "allMenus[" + this.index + "].toggle();" +
        "stopPropagation(arguments[0] || window.event);"
    );
    this.menuDiv.onclick = new Function(
        "stopPropagation(arguments[0] || window.event);"
    );
    allMenus.push(this);
}

/**
Toggle the menu open or closed
@return null
*/
ToolbarMenu.prototype.toggle = function () {

    if (this.isOpen) {
        this.buttonDiv.className = this.buttonDiv.className.replace(this.activeCSS, '');
        this.menuDiv.style.display = "none";
        this.isOpen = false;
    }
    else {
        this.buttonDiv.className += " " + this.activeCSS;
        this.menuDiv.style.display = "block";
        if (this.focusField) eval(this.focusField + ".focus();" + this.focusField + ".select();");
        this.isOpen = true;
    }
}


/**
Closes the menu if it is open
*/
ToolbarMenu.prototype.close = function(){
    if (this.isOpen){
        this.toggle();
    }
}

/**
Opens the menu if it is closed
*/
ToolbarMenu.prototype.open = function(){
    if (!this.isOpen){
        this.toggle();
    }
}

MyListMenu.prototype = new ToolbarMenu;
MyListMenu.prototype.constructor = MyListMenu;


/**
@class This js object is linked to the my list menu on the toolbar.  It is used to add
items to the menu, diplay the menu items
@extends ToolbarMenu
*/
function MyListMenu(){
    /**
    The Add to text, used for internationlization
    */
    this.AddToText = MyListMenuAddToText;

    /**
        Create new list text, used for internationlization
    */
    this.CreateNewListText = MyListMenuCreateNewListText;

    /**
    Cancel button text, used for internationlization
    */
    this.CancelText = MyListCancelText;
}


/**
The init method links the menu html to this js object
@param name the name of the menu, it is used to get other menu elements
@param activeCSS the class name to set the element to whe the list is active
@param focusField the input element that gets focus when the menu is active
@param dataRef reference to the the data objct that will be used for the meny display
@param addToListFunction the add to list function to use
@param addToListFuncParams any parameters to pass to the addToListFunc
@param createListBoolean boolean value to display the create new list link, if not passed in, it
will not display the link
@return null
*/
MyListMenu.prototype.init = function (name, activeCSS, focusField,
                                      dataRef,addToListFunc,addToListFuncParams,
                                      createListBoolean, dialog){
    if (authenticated == false){
        this.createListBoolean = false;
    }
    else{
        this.createListBoolean = (createListBoolean)?true:false;
    }
    this.dataRef = dataRef;
    this.addToListFunc = addToListFunc;
    this.addToListFuncParams = addToListFuncParams;
    this.dialog = dialog;
    ToolbarMenu.prototype.init.call(this,name,activeCSS,focusField);
}

/**
@private
*/
MyListMenu.prototype.setAttribute = function(element,attr,value){
    element.setAttribute("style",value);
}

/**
Clears the my list menu form of all elements
*/
MyListMenu.prototype.clearForm = function(){
    var childrenToRemove = new Array();
    var menuForm = this.menuForm;
    for(var i=0;i<menuForm.childNodes.length;i++){
    childrenToRemove.push(menuForm.childNodes[i]);
    }
    for(var i=0;i<childrenToRemove.length;i++){
        menuForm.removeChild(childrenToRemove[i]);
    }
}


/**
Toggle the menu open or closed, if it is openning it
It calls updateMenu
@return null
*/
MyListMenu.prototype.toggle = function(){

//    if(authenticated == false){
//        if(confirm(loginPrompt)){
//            loginMenu.action = this.toggle;
//            loginMenu.args = [this];
//            loginMenu.open();
//            loginMenu.setFocus();
//        }
//    }
//    else{
        if(!this.isOpen){
            this.updateMenu();
            dismissAllMenus();
        }
        ToolbarMenu.prototype.toggle.call(this);
//    }
 }


/**
@class thie object is used to hold my lists. It is basically a hash table of
List ids and names.
*/
function MyList(){
    this.myList = new Array();
}

/**
@param {int} id the list id
@param {string} name of the list
*/
MyList.prototype.add = function(id,name){
    this.myList.push({"id":id,"name":name});
}

/**
@returns returns the my list object
@type object
*/
MyList.prototype.get = function(){
    return this.myList;
}

/**
Clears the my list object
*/
MyList.prototype.clear = function(){
    this.myList = new Array()
}

/**
@returns the length
*/
MyList.prototype.length = function(){
    return this.myList.length
}


var summary = new Summary();


function Summary (selectAllID,checkBoxName) {
    ///optional parameter for the selectAll input ID
    this.selectAllID = selectAllID ? selectAllID:"selectAll";

}


Summary.prototype.toggleAll = function (box, inputName) {

    var inputs = document.getElementsByTagName("input");
    //HACK for now, if a  third argument is passed in it is the items
    // we want to toggle the items check boxes to, but not do anything else
    try{
        if (arguments.length>2){
            for (var i=0; i < inputs.length; i++) {
                if (inputs[i].type == "checkbox" && inputs[i].name == arguments[2]) {
                   if (box.checked == true){
                      inputs[i].checked = true;
                    }
                    else{
                        inputs[i].checked = false;
                    }
               }
           }
       }
    }
    catch(err){
    // dont do anything jsut eat the error}
    }
    //END HACK !!!
    ///
	var boxes = new Array();
	var toggleOn = false;

    for (var i=0; i < inputs.length; i++) {
		if (inputs[i].type == "checkbox" && inputs[i].name == inputName) {
			boxes[boxes.length] = inputs[i];
			if (box.checked == true){
                inputs[i].checked = true;
            }
            else{
                inputs[i].checked = false;
            }
    		this.toggleRow(inputs[i],box.checked);
            toggleChildItems(inputs[i].value, box.checked);
		}
	}
}

Summary.prototype.allBibsChecked = function (boxName){
    if(boxName!=undefined)
    {
        return this.allChecked(boxName);
    }
    return this.allChecked("bibID");
}

Summary.prototype.allItemsOutChecked = function (boxName){
    if(boxName!=undefined)
    {
        return this.allChecked(boxName);                
    }
    return this.allChecked("renewId");
}

Summary.prototype.allChecked = function (name){
  var inputs = document.getElementsByTagName("input");
  var inputName = name
  var allChecked = true;
  var matchedInputs = new Array();
  for (var i=0; i < inputs.length; i++) {
      if (allChecked == false){
         break;
      }
      if (inputs[i].type == "checkbox" && inputs[i].name == inputName) {
            matchedInputs.push(inputs[i]);
        	if (inputs[i].checked == false){
                allChecked = false;
            }           
		}
	}
   return allChecked
}

Summary.prototype.allItemsChecked = function (){
 return this.allChecked("itemID");
}

function findParentByTagName(elem, tagName)
{
    while(elem!=undefined&&elem!=null)
    {
        if(elem.nodeName==tagName)
        {
            return elem;
        }
        elem=elem.parentNode;
    }
    //if not found, lookup by id.
    return null;
}


function findParent(elem, parentId)
{
    while(elem!=undefined&&elem!=null)
    {
        if(elem.id==parentId)
        {
            return elem;
        }
        elem=elem.parentNode;
    }
    //if not found, lookup by id.
    return $(parentId);
}

Summary.prototype.toggleRow = function (box, selectAll){
    var row=findParentByTagName(box, "TR");
    toggleRowSelection(row, box.checked, selectAll);
    toggleRowHighlighting(row, box.checked, selectAll)
    //Select all Input box
    var selectAllInput = $(this.selectAllID);
    if (selectAllInput != null && selectAllInput != undefined){
        if (box.checked) {
            if (this.checkBoxName == null){
                var allBibsChecked = this.allBibsChecked();
                var allItemsChecked = this.allItemsChecked();
                if(allBibsChecked == true && allItemsChecked == true){
                   selectAllInput.checked = true;
                }
            }
            else{
            	var allInputsChecked = this.allChecked(this.checkBoxName);
            	if (allInputsChecked == true){
            	    selectAllInput.checked = true;
            	}
            	else{
            	    selectAllInput.checked = false;
            	}
            }
        }
        else{
            selectAllInput.checked = false;
        }
    }
}

Summary.prototype.toggleItemsOutRow = function (box){
    var row = $("row_" + box.id);
    toggleRowSelection(row, box.checked, false);
    toggleRowHighlighting(row, box.checked, false)
    if (!box.checked) {
        var selectAll = $(this.selectAllID);
        if (selectAll != null)
        {
            selectAll.checked = false;
        }
    }

    if (box.checked) {
        var allItemsOutChecked = this.allItemsOutChecked();
        if(allItemsOutChecked == true){
            document.getElementById(this.selectAllID).checked = true;
        }
    }
    else{
        document.getElementById(this.selectAllID).checked = false;
    }
}

Summary.prototype.toggleBibRow = function (box, bibId) {
    toggleChildItems(bibId, box.checked);
    this.toggleRow(box, false);
}

Summary.prototype.toggleItemRow = function (box, parentBibId){
    var parentRow = findParentByTagName(box, "TR");
    // Set 'selectedRow' on the parent row. The selectedRow class is used to determine what will be printed.
    if (parentRow != null){
        toggleRowSelection(parentRow, box.checked, false);
    }

    this.toggleRow(box, false);
}

function toggleChildItems(bibId, checked){
    // Hide child checkboxes
    var childItemCheckboxes = getChildElements(bibId, "input");
    var visibility = (checked)?"hidden":"visible";
    for (i=0; i<childItemCheckboxes.length; i++){
        childItemCheckboxes[i].style.visibility = visibility;
        // When child items become visible after being hidden, they should no longer be checked or highlighted
        if (visibility == "visible"){
            childItemCheckboxes[i].checked = false;
        }
    }

    // Set 'selectedRow' class on child items. The selectedRow class is used to determine what will be printed.
    var childItemRows = getChildElements(bibId, "TR");
    for (i=0; i<childItemRows.length; i++){
        toggleRowSelection(childItemRows[i], checked, false);
        toggleRowHighlighting(childItemRows[i], checked, false);
    }
}

function toggleRowSelection(row, checked, selectAll){
    if (checked){
        addClass(row, "selectedRow");
    }
    else{
        removeClass(row, "selectedRow");
    }
}

function toggleRowHighlighting(row, checked, selectAll){
    if (checked){
        addClass(row, "selectedRowColor");
    }
    else{
        removeClass(row, "selectedRowColor");
    }
}

function getChildElements(bibId, tagName){
    var childItemRE = new RegExp("^.*" + bibId);
    var childElements = new Array();
    var allElements = document.getElementsByTagName(tagName);
    for (i=0; i<allElements.length; i++)
    {
        if (childItemRE.exec(allElements[i].getAttribute("name")))
        {
            childElements.push(allElements[i]);
        }
    }
    return childElements;
}

Summary.prototype.highlightBars = function (highlight, boxCells) {

	var barIDs = new Array("summarySelectAllCell", "SummaryLastRowCell");
	var action = (highlight) ? "addClass" : "removeClass";

	for (var i=0; i < boxCells.length; i++) {
		eval(action + "(boxCells[i], 'selectedRowColor')");
	}
	for (var i=0; i < barIDs.length; i++) {
		eval(action + "(barIDs[i], 'selectedRowColor')");
	}
};
